UPDATED IN SEPTEMBER 2026

Policy-as-code

Policy-as-code means expressing compliance rules as executable code that runs in the pipeline rather than as documents people are asked to read - now extending to enterprise managed settings for agent clients, an org-wide default model admins can actually enforce, and repository-supplied agent config placed on a mandatory-diff path because it executes the moment a folder is opened.

L3 · SYSTEMATICWhat this level takes
MUSTNot met, not at this level
  • Minimum viable audit trail is captured per AI-assisted change: model identifier, timestamp, context description, human approver
  • Policy-as-code enforces compliance rules in CI (OPA or equivalent)
  • Compliance gates run on every PR to in-scope repositories
SHOULDExpected in practice, not required
  • Audit trail fields are validated by CI (missing fields fail the build)
  • Policy exceptions are logged and require follow-up within 48 hours
EVIDENCEHow you would check
  • Sample commit or PR metadata showing model, timestamp, context, approver fields
  • OPA policy configuration in CI pipeline
  • Compliance gate pass/fail logs
DEPENDS ON
  • Delivery L2 (Governance & Compliance) - official AI tool policy must exist before codifying it
  • Delivery L2 (CI/CD Pipeline) - CI must be fast enough for compliance gates to not block development

What It Is

Policy-as-code means expressing compliance rules as executable code that runs automatically in the CI/CD pipeline, rather than as documents that developers are expected to read and follow manually. Instead of a policy document that says "all AI-generated code must have a human reviewer," a policy-as-code implementation is a CI check that fails if the PR lacks a human approval record from a non-author account. The policy is enforced, not hoped for.

The technical foundation for policy-as-code in most organizations is Open Policy Agent (OPA), a general-purpose policy engine that evaluates structured inputs (JSON representing commit metadata, PR attributes, security scan results) against Rego policy rules and returns a decision: allow or deny. OPA integrates with CI systems (GitHub Actions, GitLab CI, Jenkins), Kubernetes admission controllers, API gateways, and infrastructure provisioning tools. A single OPA policy can enforce the same rule across all of these integration points simultaneously.

At L3 (Systematic), policy-as-code applies to the delivery pipeline specifically: CI checks that enforce AI disclosure requirements, block merges that lack required audit trail fields, verify that AI-generated code in high-risk repositories was reviewed by a human with specific permissions, and confirm that model versions used are on the approved list. The policy lives in the repository alongside the code it governs, goes through code review when it changes, and its enforcement decisions are logged and auditable.

Two additions in 2026 changed what policy-as-code has to cover. The first is that the agent clients themselves became a policy surface: enterprise managed settings now govern which plugins and marketplaces are permitted and whether developers can bypass approval prompts, and as of 2026-08-26 GitHub's global model policy went generally available, letting Business and Enterprise administrators enforce a default model across the organisation. "Which model is this code being written by" moved from a preference to an enforceable setting, which means it is now something your policy can actually assert rather than merely request.

The second is more urgent. Repository-supplied agent configuration is executable code, and August proved it at scale. In the ChainDrop compromise of the keyv npm ecosystem on 2026-08-04, a maintainer account takeover pushed a credential stealer to main and the project's own Actions pipeline built and published it - 444 packages and 2,212 versions in under four hours, across a dependency surface with roughly 2 billion monthly downloads. The detail that matters for this guide is where persistence was planted: .vscode/tasks.json with runOn: folderOpen, and .claude/settings.json with a SessionStart hook. Opening the repository, or starting an agent session in it, executed the payload. No npm install required. Two weeks later, on 2026-08-20, three crates.io packages were compromised through a maintainer account that added a dependency on a typosquatted proc-macro1, whose build.rs fetched and ran a payload at compile time - the same class of attack in a different ecosystem. And on 2026-08-03 Open VSX removed 77 "evil twin" extensions impersonating major vendors, 19 of which harvested CI/CD environment variables, from the marketplace that Cursor, Windsurf and VSCodium use by default.

The practical consequence is a short, specific list of paths that must never merge without a human reading the diff: .claude/, .vscode/, .cursor/, .gemini/, and build.rs. Put them in CODEOWNERS, enforce them in policy, and disable auto-run hooks entirely for workspaces you did not author.

The shift from document-based policy to policy-as-code has a profound effect on compliance reliability. Document-based policies have adoption rates that peak at launch and decay over time - developers skip steps under deadline pressure, new developers don't find the policy document, policy updates don't reach developers who were already past onboarding. Policy-as-code has adoption rates that are mechanically enforced: every merge request, every deployment, every time. The compliance evidence is the CI run log, not a survey about whether people read the policy.

Why It Matters

  • Compliance is mechanically enforced, not behaviorally dependent - policy-as-code eliminates the failure mode where developers know the policy but don't follow it under pressure; the pipeline either passes or fails, regardless of deadline urgency
  • Policy changes go through code review - when a compliance rule changes, the change to the policy code goes through the same review process as application code, creating an auditable history of what was required when
  • Audit evidence is the CI log - instead of collecting attestations from developers or doing periodic audits, the compliance evidence is the automated check results that run on every merge; this is a much stronger evidence base for SOC2 and ISO 27001
  • Scales automatically with team growth - adding a new team or repository to the policy scope requires adding it to the OPA policy config, not training new developers on a document they may not find
  • Enables proactive policy testing - policy rules can be unit-tested like application code; you can verify that a rule correctly rejects a non-compliant commit before it ever runs in production CI
  • Covers agent config files, now a live attack surface - in May 2026 agent configuration became something attackers write to, so policy-as-code must lint, normalize, and review these files like code; the Mini Shai-Hulud worm (CVE-2026-45321, CVSS 9.6) planted persistence by writing Claude Code hooks into ~/.claude/settings.json, and the TrapDoor campaign hid zero-width-Unicode prompt injection inside CLAUDE.md and .cursorrules across 34 poisoned packages
  • Vendor platforms now ship the enforcement surface natively - GitHub's enterprise managed-settings.json went generally available July 1, 2026, and on July 27 enterprise managed settings were extended to the GitHub Copilot app and the Copilot cloud agent: enterprise owners define allowed plugins and marketplaces and whether developers can bypass approval prompts. GitHub's own framing is the policy-as-code thesis verbatim: "Any client outside the policy is a gap... Governance is only as strong as its least-covered surface." On July 23 GitHub also added agent automation controls to Issues (rationale, confidence, approvals), giving policies a place to hook into agent-triggered work
  • Repository config executes before any install step - ChainDrop planted persistence in .vscode/tasks.json (runOn: folderOpen) and .claude/settings.json (SessionStart), so cloning and opening was enough; build.rs did the equivalent at compile time in the crates.io compromise. These paths need a mandatory human diff, not a scanner
  • The default model is now an enforceable setting - GitHub's global model policy reached general availability on 2026-08-26, so Business and Enterprise administrators can set an org-wide default model rather than publishing a recommendation. Policy-as-code should assert the setting, not the intention
  • Vendor defaults move, so pin them in policy rather than inheriting them - Claude Code's default permission mode went to Manual in July and then to auto mode on 2026-08-14 for Pro, Max and Team accounts, while remaining opt-in on Claude Enterprise, the Claude API, Bedrock, Google Cloud and Microsoft Foundry. Organisation-managed defaults do not move at all, which is the whole argument for setting them: a policy that relies on the shipped default is a policy that changes when a vendor ships a release note
  • Encodes vendor sovereignty as a hard control - June 2026 made model availability a governance risk, not just a procurement detail. Anthropic disabled Fable 5 and Mythos 5 worldwide on June 12 to comply with a US export-control order, and Fable 5 on Bedrock was found to route inference data back to Anthropic, breaking Bedrock's data-residency guarantee. Policy-as-code should now enforce model and vendor portability (no pipeline pinned to a single un-substitutable model), data-residency routing (inference confined to approved Bedrock/Vertex/Foundry EU regions), and a self-hostable fallback so a model that disappears overnight does not halt delivery

Getting Started

  1. Install OPA and write your first policy - start with the simplest possible policy: a CI check that reads the commit message and verifies it contains an AI-Model: trailer if the PR author has the "AI-user" team label. Write the Rego rule, test it against sample inputs (compliant commit, non-compliant commit), and add it as a GitHub Actions step. The first policy takes a day to build; every subsequent policy takes an afternoon.
  2. Create a policy repository - store your OPA policies in a dedicated repository (or a policy/ directory in your platform monorepo) with a test suite and a CI pipeline that validates policies before deployment. This creates the same code quality guarantees for policy code that you apply to application code.
  3. Start with non-blocking advisory mode - before making policies blocking, run them in advisory mode for two weeks: the CI check runs, logs its result, but doesn't fail the build. Use this period to see how many PRs would fail, fix any false positives in the policy logic, and communicate the change to developers before it takes effect.
  4. Define the policy input schema - OPA policies evaluate structured JSON input. Define the input schema for your CI context: what fields are available (commit author, PR reviewers, commit message content, changed files, labels, security scan results, AI disclosure fields). This schema is the contract between your CI system and your policies.
  5. Build the policy test suite - for each policy rule, write test cases: a compliant example that should pass, multiple non-compliant examples that should fail, and any edge cases (first PR from a new developer, emergency bypass process). The test suite runs in CI and prevents policy regressions.
  6. Put agent config paths on a mandatory-diff path - .claude/, .vscode/, .cursor/, .gemini/ and build.rs in CODEOWNERS, a policy rule that refuses to auto-merge any PR touching them, and a rule that no agent may modify them without human approval. This is the single highest-value policy rule to add this quarter, and it is an afternoon of work.
  7. Disable auto-run hooks for untrusted workspaces - folderOpen tasks and SessionStart hooks should not fire in a repository your organisation did not author. Set this centrally through enterprise managed settings rather than asking each developer to configure it, and treat a third-party repository opened on a developer machine as an untrusted workspace by default.
  8. Assert the enterprise settings you rely on, including the default model - with the global model policy generally available since 2026-08-26, the org-wide default model belongs in your enforced configuration alongside allowed plugins, permitted marketplaces and whether prompt bypass is available. Check the enforced values in CI rather than trusting that they were set once.
  9. Document the exception process in the policy code - every policy should have a documented exception path: an emergency bypass label (compliance/exception-approved) that allows a merge to proceed with override, requiring a follow-up ticket within 48 hours. The exception is captured in the CI log; the follow-up is tracked in the issue tracker. No dark paths around policy.
TIP

Start with OPA Playground (play.openpolicyagent.org) to write and test Rego policies before deploying them. The playground lets you paste a policy and input JSON, run the policy, and see the decision. It's much faster than deploying to CI for iteration.

Common Pitfalls

Writing policies that are too strict too fast. A policy that fails half of existing PRs on day one will be overridden, complained about, and disabled. Start with policies that reflect current best practice (not aspirational practice) and tighten them over time as teams improve. The first policy should have a 95% pass rate on existing PRs; only then start using it to drive behavioral change.

Not providing actionable failure messages. When an OPA check fails, the developer should know exactly what to do to fix it. "Policy violation: missing AI audit fields" is not actionable. "This commit appears to be AI-assisted but is missing required audit fields. Add AI-Model: <model-id>, AI-Timestamp: <ISO timestamp>, AI-Context: <description>, AI-Approver: <email> to your commit message. See docs/ai-audit-trail.md for details." is actionable.

Treating policy code as exempt from review. Policy changes have compliance implications - a policy that accidentally allows a prohibited pattern or blocks a legitimate use case has real consequences. Policy code should go through the same review process as security-sensitive application code, with at minimum two reviewers including someone from security or compliance.

No exception process. A policy with no exception process will either be routinely overridden (if developers can bypass it) or will create genuine blockers (if they can't). The exception process must be documented, fast (same-day or next-day approval), and auditable. The exception itself is compliance evidence - an organization that has a well-used, well-documented exception process is demonstrating mature governance.

Relying on scanning where you should be pinning and reviewing. The August evidence runs consistently against scanning as a primary control: the ChainDrop tarballs carried valid npm provenance attestations, the crates.io exposure windows were 86 to 107 minutes, and the Open VSX evil twins sat in the default marketplace for several days. Provenance was correct and the source was malware. Policy should therefore pin versions, restrict marketplaces to an allowlist, and require a human diff on executable configuration - not wait for a scanner to have an opinion.

Assuming a vendor default is a control. Defaults change on the vendor's release schedule, not yours. Claude Code's permission default moved twice in two months. Where a setting matters to your compliance story, set it through organisation-managed configuration, where it does not move at all, and assert it in policy.

Forgetting that policies need updating. When AI tools evolve (new model versions, new agent capabilities, new use cases), policies that were written for an earlier state of AI tooling will generate false positives and false negatives. Build a quarterly policy review into your governance calendar, triggered by either the calendar date or by a significant change in the AI tool stack.

How Different Roles See It

BobHEAD OF ENGINEERING

Bob has been managing AI governance through policy documents and PR template fields for six months. The compliance rate on PR disclosures is 75% - good, but not auditable at the level his SOC2 auditors expect. They want evidence that the policy is enforced, not just documented. Bob needs to close the gap between "we have a policy" and "we enforce our policy."

What Bob should do: Bob should scope a one-sprint policy-as-code implementation for the highest-priority compliance requirement: AI disclosure in PRs to SOC2-scope repositories. The implementation steps are: (1) an OPA policy that checks for required AI disclosure fields in PR descriptions, (2) a GitHub Actions integration that runs the check on every PR targeting main, (3) two weeks of advisory mode with 100% of failures logged and reported, (4) one week of remediation (fixing the 25% non-compliant PRs, adjusting the policy logic if needed), (5) enforcement mode. This moves the compliance rate from 75% behavioral compliance to 100% enforced compliance for the in-scope repositories, and gives Bob concrete CI run logs as audit evidence.

SarahPRODUCTIVITY LEAD

Sarah has been manually reviewing PR disclosure data every month to check compliance rates. The process takes two hours per review cycle and the data is often incomplete because some PRs lack disclosures and she has to chase down the developers who submitted them.

What Sarah should do: Sarah should champion the policy-as-code implementation as a productivity tool for her own work. Once policy enforcement runs automatically in CI, the compliance data is collected automatically in the CI run log - no manual review needed. Sarah should work with the platform team to build a simple analytics pipeline that reads the CI policy check results, computes weekly compliance rates by team and repository, and populates her productivity dashboard automatically. The policy-as-code implementation eliminates her manual compliance review work and improves data quality simultaneously. Sarah should frame this as: "policy-as-code gives me better compliance data with less work - it's a win for governance and a win for developer experience."

VictorSTAFF ENGINEER - AI CHAMPION

Victor has been informally advocating for policy-as-code for months and has already written prototype OPA rules for the AI audit trail requirements. He wants to get the organization to adopt them but has been waiting for the right moment.

What Victor should do: Victor should present his prototypes with concrete data from a dry run. He should run his OPA policies against the last 90 days of commit history in the most important repository and produce a report: X% of AI-assisted commits would have passed, Y% would have failed, and here is the breakdown of failure reasons. This moves the conversation from "should we do policy-as-code?" to "here's what policy-as-code would have caught." Victor should also address the rollout path explicitly: advisory mode for 30 days, then enforcement with an exception process that he's already designed. Having a complete proposal with working code, dry-run data, and a rollout plan is far more likely to get approval than an abstract recommendation. There is also one rule Victor should ship immediately rather than bundling into the proposal: a block on auto-merging any PR that touches .claude/, .vscode/, .cursor/, .gemini/ or build.rs. After ChainDrop, that rule needs no dry run and no business case.

How This Guide Changed

What each edition changed in this guide, newest first.

  1. V1.6September 2026LATEST

    August turned "agent configuration is an attack surface" from a reasonable precaution into a documented incident class, and the item and guide changed accordingly. ChainDrop planted its persistence in .vscode/tasks.json with runOn: folderOpen and .claude/settings.json with a SessionStart hook, so opening the repository or starting a session was execution - no install step involved - and the crates.io compromise did the same thing through build.rs at compile time. The guide now names five paths that belong on a mandatory-diff path and argues for pinning and allowlisting over scanning, since the malicious npm tarballs carried valid provenance attestations. On the enforcement side, GitHub's global model policy reached general availability on 2026-08-26, so the org-wide default model became something policy can assert; the guide's note about Claude Code's July default was updated too, since that default moved again on 2026-08-14, which is itself the argument for setting organisation-managed values rather than inheriting vendor ones.

  2. V1.5August 2026

    Recorded vendor platforms shipping the enforcement surface natively. GitHub's enterprise managed-settings.json went generally available July 1 and was extended to the Copilot app and cloud agent on July 27, letting enterprise owners define allowed plugins and marketplaces and whether developers can bypass approval prompts. GitHub's own framing states the policy-as-code thesis verbatim: governance is only as strong as its least-covered surface. Claude Code also flipped its default permission mode from Auto to Manual on July 3, so a policy requiring explicit approval now matches the tool's default instead of fighting it.

  3. V1.4July 2026

    Encoded vendor sovereignty as a hard control after June made model availability a governance risk rather than a procurement detail. Anthropic disabled Fable 5 and Mythos 5 worldwide on June 12 under a US export-control order, and Fable 5 on Bedrock was found to route inference data back to Anthropic, breaking Bedrock's residency guarantee. Policy-as-code gained three requirements: model and vendor portability, data-residency routing, and a self-hostable fallback so a model that disappears overnight does not halt delivery.

  4. V1.3June 2026

    Added agent configuration files as a live attack surface that policy-as-code must lint, normalize and review like code. The Mini Shai-Hulud worm (CVE-2026-45321, CVSS 9.6) planted persistence by writing Claude Code hooks into ~/.claude/settings.json, and the TrapDoor campaign hid zero-width-Unicode prompt injection inside CLAUDE.md and .cursorrules across 34 poisoned packages.

  5. V1.0March 2026

    The launch edition's argument for executable compliance. Instead of a document stating that AI-generated code must have a human reviewer, a check that fails the build when the approval record is missing, with Open Policy Agent as the engine and the policy living in the repository it governs so that changing it goes through review like anything else.

Where does your team actually sit on this?

This guide describes one level of one area. Run the assessment to place your team across all 16 areas, see which gates you have passed, and get a report you can take to your stakeholders.

Start the assessment