Platform

Platform overviewArchitectureWorkflow orchestrationGitOps configurationGovernance and AAAAI and MCPKnowledge and contextRuntime and executionEvidence and monitoring

Use cases

All use casesProduction incidentRelease preparationHotfix to productionSecurity scan triage
Why NopsAIIntegrationsSecurity

Resources

All resourcesAI agent governanceMCP governanceMCP securitySelf-hosted platforms
PricingGitHub

Company

How a run worksAboutContactBook a demo

Approvals

A durable human checkpoint in the middle of a run, and the rules that decide who may release it.

ReferenceAutomation authorOperatorSecurity

Key points

  • An approval step pauses the run and releases runner capacity rather than holding it, and it survives a control-plane restart.
  • approval cannot be combined with tasks, goal, script, or include, and an approval step cannot declare outputs.
  • teams names the teams whose members may decide; allow_self_approval decides whether the person who started the run may be one of them.
  • timeout bounds the wait. An expired approval produces a timed_out run, not a failure.
  • Approval failures always fail closed: ignore_failure does not apply to them.

Examples

What this page addsyaml
  - name: production-gate
    depends_on: [package]
    approval:
      type: production-release
      teams:
        - platform/sre
      allow_self_approval: false
      timeout: 24h

  - name: publish
    depends_on: [production-gate]
    script: |
      ./scripts/promote.sh
Pipeline so faryaml
name: release-service
description: Build, verify, and publish the payments service.
container_image: alpine:3.20
working_directory: /workspace
timeout: 45m
display_option: list
variables:
  - RELEASE_CHANNEL
  - platform/shared:ARTIFACT_BUCKET
steps:
  - name: build
    script: |
      make build
      echo "1.0.$(date +%s)" > /nopsai/outputs/BUILD_TAG
    outputs:
      - name: BUILD_TAG

  - name: verify
    image: golang:1.24
    depends_on: [build]
    runtime_pool: ci
    volumes:
      - build-cache:/root/.cache
    script: |
      go vet ./...
      go test ./...

  - name: checks
    depends_on: [verify]
    tasks:
      - name: licenses
        ignore_failure: true
        script: |
          ./scripts/license-check.sh
      - name: sbom
        script: |
          ./scripts/sbom.sh > /workspace/sbom.json
          sha256sum /workspace/sbom.json | cut -d' ' -f1 > /nopsai/outputs/SBOM_DIGEST
        outputs:
          - name: SBOM_DIGEST
      - name: report
        depends_on: [checks.licenses, checks.sbom]
        variables:
          SBOM_DIGEST: $steps.checks.sbom.outputs.SBOM_DIGEST
        script: |
          echo "checks complete"
          echo "sbom $SBOM_DIGEST"

  - name: package
    depends_on: [checks]
    secrets:
      - REGISTRY_TOKEN
      - platform/shared:SIGNING_KEY
    variables:
      BUILD_TAG: $steps.build.outputs.BUILD_TAG
    script: |
      ./scripts/package.sh "$BUILD_TAG"
      echo "channel $RELEASE_CHANNEL, bucket $ARTIFACT_BUCKET"
      ./scripts/mint-token.sh > /nopsai/outputs/PUBLISH_TOKEN
      ./scripts/sign.sh --key "$SIGNING_KEY" --token "$REGISTRY_TOKEN"
    outputs:
      - name: PUBLISH_TOKEN
        sensitive: true

  - name: announce
    depends_on: [package]
    condition: Only run when the release channel is stable.
    ignore_failure: true
    script: |
      ./scripts/announce.sh

  - name: production-gate
    depends_on: [package]
    approval:
      type: production-release
      teams:
        - platform/sre
      allow_self_approval: false
      timeout: 24h

  - name: publish
    depends_on: [production-gate]
    script: |
      ./scripts/promote.sh
Result

The run pauses before publish until a member of platform/sre approves, or 24 hours pass and the run ends timed_out.

Rejected: an approval step that also runs somethingyaml
  - name: production-gate
    approval:
      type: production-release
    script: ./scripts/promote.sh
Result

Rejected: approval cannot be combined with script.

Field reference

steps[].approvalstep modeobjectConditionalNone

Durable human checkpoint that pauses the run and releases runner capacity.

Example

approval:
  type: production-release
  teams:
    - platform/sre

Rules
  • Cannot be combined with tasks, goal, script, or include.
  • Cannot declare outputs.
steps[].approval.typeapprovalstringRequiredNone

Approval kind recorded on the checkpoint and used for audit and notification routing.

Example

type: production-release

Rules
  • Must match ^[a-zA-Z0-9_.-]+$.
Evidence

services/nopsai/pkg/validation/pipeline.go

steps[].approval.teamsapprovalstring[]RequiredNone

Relative team paths allowed to approve or reject the checkpoint.

Example

teams:
  - platform/sre
  - security

Rules
  • At least one team is required.
  • Paths must be relative; absolute paths and ~ are rejected.
  • Segments may not be empty, ., or ...
  • Repeating the same team is rejected (case-insensitive).
Evidence

services/nopsai/pkg/validation/pipeline.go

steps[].approval.allow_self_approvalapprovalbooleanOptionalfalse

Whether the user who started the run may approve this checkpoint.

Example

allow_self_approval: false

Security

Leaving this false preserves four-eyes separation between requester and approver.

steps[].approval.timeoutapprovaldurationOptionalNone

How long the checkpoint waits before the run is marked timed_out.

Example

timeout: 24h

Rules
  • Must parse as a positive Go duration; 0 and negative values are rejected.
Evidence

services/nopsai/pkg/validation/pipeline.go

How it works

The checkpoint is durable because it is a record, not a paused process. That is why capacity is released while it waits, and why a restart does not lose the pending decision.

Put the gate where the risk changes. In this chapter it sits between packaging an artefact and promoting it, so everything reviewable has already happened and nothing irreversible has.

Who may approve is an authorization question, resolved through AAA against the named teams. The directive narrows the set; it does not grant anyone the right to decide.

Implementation evidence

  • services/nopsai/approval_schema.go

    Approval document schema and decision handling.

  • services/nopsai/pkg/validation/pipeline.go

    Rules the validator enforces on this directive set.