BLOG/BY COMPANY SIZE
THEME
BY COMPANY SIZE

OrchStep for regulated industries

In regulated shops the deploy isn't the hard part — proving who approved it and what shipped is. Here's how to make the change record a byproduct of running the change.

Mar 31, 2026 OrchStep Team 7 minROLE: Compliance EngineerSCALE: Enterprise

If you work where SOX, HIPAA, PCI, or an internal change-advisory board sets the rules, the technical deploy is the easy 10%. The other 90% is evidence: who approved this change, what artifact actually shipped, was the production gate enforced or just supposed to be, and can you produce all of that nine months later when an auditor asks. Most teams answer with screenshots, a ticket pasted into Slack, and a deploy script that has no idea any of this exists.

The problem with that split is drift. The runbook says "requires VP approval." The script doesn't check. One Friday it ships anyway. Now the control is a sentence in a doc instead of a thing the system enforces. OrchStep closes that gap by making the control a step — an assertion that fails the run if the approver isn't named, an audit line that's written whether the change succeeds or rolls back.

What automation looks like in a regulated shop

You're not optimizing for speed. You're optimizing for defensibility. That means:

  • Controls that are enforced by the run, not documented next to it.
  • An audit trail that's a byproduct of executing the change, not a manual second step someone forgets.
  • A preview an approver or auditor can read before anything touches production.
  • Separation between staging and production that the workflow guarantees, not convention.

Where OrchStep fits

OrchStep runs your existing deploy commands, but wraps them in assert gates, if: branches, and finally: blocks that always run. The approval check isn't a comment — it's a step that fails the workflow. The audit log isn't a follow-up task — it's a finally: that fires on success and on rollback alike.

Here's a controlled-change workflow where the compliance controls are part of the run:

orchstep.yml
name: controlled-change
defaults:
  change_id: CHG-0001
  tier: staging
  approver: unset

tasks:
  # orchstep run change --var change_id=CHG-2048 --var tier=production --var approver=jdoe
  change:
    steps:
      - name: record
        func: shell
        do: echo "opening change {{ vars.change_id }} for {{ vars.tier }}"
        outputs:
          ticket: "{{ vars.change_id }}"
      - name: require-approval
        func: assert
        args:
          condition: '{{ ne vars.approver "unset" }}'
          message: "production change needs a named approver"
      - name: evidence
        func: shell
        do: echo "collecting build provenance for {{ steps.record.ticket }}"
      - name: apply
        func: shell
        do: echo "applying {{ steps.record.ticket }} to {{ vars.tier }}"
        catch:
          - name: revert
            func: shell
            do: echo "reverting {{ steps.record.ticket }} on {{ vars.tier }}"
        finally:
          - name: audit
            func: shell
            do: echo "audit log sealed for {{ steps.record.ticket }} by {{ vars.approver }}"
      - name: gate
        if: '{{ eq vars.tier "production" }}'
        then:
          - name: attest
            func: shell
            do: echo "attestation filed for {{ steps.record.ticket }}"
        else:
          - name: stage-note
            func: shell
            do: echo "staged {{ steps.record.ticket }}, no attestation required"

Run it without an approver and the require-approval assert stops the workflow before anything is applied — the control is enforced, not advisory. The audit step is in finally:, so the trail is written whether the change applies cleanly or reverts. The production attest step only runs on the production tier, and the workflow guarantees it.

Three workflows worth stealing

1. The approval gate that actually gates. The assert step turns "production changes require a named approver" from policy text into an enforced precondition. No approver, no run. Pair it with your CI's required-reviewers so the named approver in the run matches the one who clicked approve. See The assert function and the Compliance-gated change use case.

2. The audit trail as a byproduct. Everything the auditor wants — change ID, tier, approver, outcome — is emitted by steps and sealed in a finally: block that runs on success and on rollback. The evidence is produced by running the change, so there's no second manual step to skip. See Error Handling.

3. The pre-change preview. Before a CAB meeting, orchstep run change --var change_id=CHG-2048 --var tier=production --dry-run resolves every variable and prints the exact plan — which branch runs, what gets applied — without executing. The board reviews the real plan, not a description of it. See Previewing with Dry Run.

What you gained

ConcernScript + ticket + screenshotsOrchStep
Approval enforcementa sentence in the runbookassert that fails the run
Audit trailmanual, easy to forgetfinally: step, always runs
Prod vs staging controlsconventionif: gate the workflow guarantees
Rollback evidence"we think we reverted"catch: + sealed audit line
Pre-change reviewa description--dry-run of the real plan
Change recordassembled after the facta byproduct of the run

OrchStep is not a GRC platform and doesn't replace your system of record — it makes the deploy produce clean evidence for whatever system you already use. If your controls are fully handled by an existing change-management tool with enforced gates, lean on it. Where the gap is "the script doesn't know about the policy," a workflow that encodes the control is what closes it. For sensitive values, keep them out of the workflow file entirely with the secrets conduit.

Where to go next

Spend more time proving the change than making it? Make the change record fall out of running the change.

#COMPLIANCE#AUDIT#APPROVALS#CHANGE-MANAGEMENT
Try it in two minutes — one binary, no signup.
curl -fsSL https://orchstep.dev/install.sh | sh

RELATED — BY COMPANY SIZE