Signed bundles from Git and dev-to-prod promotion
Objective
Describe how a policy in Git becomes a signed bundle, how Writ promotes it from dev through staging to prod, and how the deploy-action GitHub Action ships it with OIDC and no API keys.
Concept
Git is the source of truth for policy. You write Rego (like the file in this course's lab), review it in a pull request, and merge it. From there Writ turns the committed policy into a signed bundle: a versioned, integrity-protected package the PDP loads. Signing matters because the PDP should only run policy that provably came from your reviewed Git history. If a bundle's signature does not verify, it is not trusted.
Promotion moves that same bundle through environments in order:
Git (merged Rego) -> Writ builds + signs bundle -> dev -> staging -> prod
The bundle is built once and promoted, not rebuilt per environment, so what you tested in staging is byte-for-byte what runs in prod. Each promotion is a governed step Writ records, which is what lets you answer "which bundle version is running in prod, and what commit produced it?"
Two real tools sit around this flow, and it is worth being precise about each:
deploy-actionis a GitHub Action that deploys OPA bundles through the EnforceAuth API. It authenticates with OIDC workload identity (RFC 8693 token exchange), so there are no long-lived API keys in your CI. The workflow requests anid-token: writepermission, GitHub mints a short-lived OIDC token, and a trust policy on the EnforceAuth side exchanges it for deploy access. Rollback is by priorcommit_sha: you redeploy the bundle built from an earlier commit.eactlis the EnforceAuth CLI you use for control-plane operations from a terminal.
Do not confuse the bundle with the decision. The signed bundle is the artifact the PDP loads; the allow-or-deny answer is what OPA or Enterprise OPA computes at request time from that bundle plus the request input. Writ's job ends at getting the right, verified bundle to the right environment.
Note on real tooling: this lesson describes deploy-action and OIDC accurately, but the graded exercise for this course is the OPA policy itself, not a live GitHub deployment. You run opa test locally against the lab. Actually invoking deploy-action requires a configured GitHub repository, an OIDC trust policy, and an EnforceAuth tenant, which is beyond a local lab. The policy you test here is precisely the kind of artifact that flow would sign and promote.
Hands-on lab
Treat ../lab/policy.rego as the merged, reviewed Rego at the top of the promotion flow. Run the suite from the cloned university-labs repo so you know the policy is green before it would ever be signed and promoted:
git clone https://github.com/EnforceAuth/university-labs.git
cd university-labs
opa test courses/getting-started-writ-control-plane -v
A passing opa test is the gate that should precede signing. Now reason about promotion: if this exact file were built into a bundle, the same signed bundle would move dev to staging to prod unchanged. If a later commit introduced a regression, rollback would redeploy the bundle from the prior commit_sha. Nothing about the decision logic changes between environments; only which signed version is live does.
Check for understanding
- Why does Writ build a bundle once and promote it, rather than rebuilding it separately for staging and prod?
- How does
deploy-actionauthenticate to deploy a bundle without storing a long-lived API key, and what GitHub permission does that require? - A bad policy reached prod. Using the flow in this lesson, how do you roll back, and what identifies the version you roll back to?