Policy as Code

Policy as code is the practice of expressing rules as executable checks โ€” versioned, reviewed, and evaluated by a system โ€” rather than as prose that people are expected to follow. The rule stops depending on whether someone read the document and remembered it at the right moment.

Open Policy Agent separates policy decisions from their enforcement. An application sends structured input, and OPA evaluates it against policies and data, using Rego to express the rules. The calling system must enforce the resulting decision on the relevant operation. That separation lets the policy and the enforcement integration be reviewed and tested for their different responsibilities.

Why the decoupling matters

A shared policy source lets several enforcement points use the same reviewed rules without maintaining independent definitions. Runtime instances still load deployed copies or bundles. Track their versions and distribution status so a common source is not mistaken for simultaneous rollout everywhere.

It also changes what a rule change costs. A policy in a document is changed by editing the document and hoping; a policy in code is changed through review, is distributed from one source, and leaves a record of what changed and when.

One source is not the same as in force everywhere at the same instant, and the difference matters during a change. Enforcement points load policy โ€” a sidecar fetches a bundle, an admission controller syncs, an agent polls โ€” so between publishing a version and every point running it there is a window in which two versions are being enforced. Open Policy Agent’s bundle mechanism is explicit that distribution is eventually consistent, which is the honest general description.

Treat a policy change as a deployment: observe the version active at each enforcement point and verify the transition. Assess the allowed-request sets under old, new, and mixed configurations. Adding an allow rule can widen access when rules combine by union; it is not a generally safe precursor to tightening. A compatibility expansion and an urgent permission withdrawal need different rollout decisions. Set the permitted propagation delay and failure behavior, test intermediate states, and confirm that required restrictions reached every applicable path.

What can be checked automatically

Can be checkedCannot be checked
Structure โ€” required fields, types, naming conventions, whether a dataset has an owner and a classificationWhether the classification is honest, or whether the recorded owner knows they own it
Placement โ€” whether a resource was created in a permitted region, whether a copy crossed a boundaryWhether the data in it is the data the policy was written about
Process โ€” whether a contract exists before publication, whether a change went through reviewWhether the review was meaningful
Values against rules โ€” nulls where forbidden, ranges, referential checks; and, once a meaning has been agreed, whether the calculation implements itWhich meaning to adopt: cents or dollars, whether active excludes trials, whether a total should include refunds

The right-hand column is not a gap to be closed by better tooling; it is the part that stays human. A meaning decision belongs in a written metric definition, not in a check.

But the boundary sits in a specific place, and drawing it too early gives away checks you could have had. Choosing the meaning is human; verifying that the code follows the meaning already chosen is ordinary testing. Once someone has decided that revenue is net of refunds and expressed in minor units, each of those becomes checkable:

  • A fixture with a known answer. A small fixed input โ€” three orders, one refunded โ€” and the expected output computed by hand. The test fails if a later change starts including refunds, which no amount of column-type checking would catch.
  • Unit and scale assertions. If the agreed unit is cents, a check that the column is an integer type and that amounts fall in the expected range flags some conversion errors, not all of them: 10,000 cents turned into 100 dollars is still an integer and still above most lower bounds, and a bound tight enough to catch it rejects genuine small transactions. A conclusive check uses a fixture โ€” a known source amount, its stated unit, and the expected converted value โ€” or a reconciliation against the source.
  • Population assertions. If trials are excluded, assert that no trial account appears in the metric’s input โ€” the definition’s exclusion rendered as a query.

So the honest division is not human judgment on one side and automation on the other. Deciding the meaning is human, writing it down is documentation, and testing that the implementation still matches what was written is automated. Skipping that last part is the common failure, and it is what produces a definition everyone agrees on and a calculation that stopped following it four releases ago.

What has to be true for a policy to bind

  • It must sit where every access path crosses. A rule enforced in one interface binds only the people who arrive through it, and analytical platforms usually offer several routes to the same bytes โ€” a SQL endpoint, a direct file read, an import into a reporting model, a share with another account. List the paths and say which mechanism enforces the rule on each.
  • Each rule needs a stated severity. Blocking and warning are different promises: one refuses to publish the candidate version when a check fails, the other publishes it and records the failure where it will be seen, with someone named to follow up. Whether consumers keep seeing the previous good version after a block is not something the severity provides. It depends on the publishing design โ€” validating in isolation before an atomic switch, or an equivalent transactional guarantee โ€” and a check that runs after the public table has already been updated finds the failure with the data already changed, while partition-by-partition publishing can leave it half new. Deciding that per rule is what keeps a policy set from becoming either a wall nobody can ship past or a dashboard nobody reads.

Treat the policies themselves as code in every sense: review changes, version them, test them against examples that should pass and examples that should fail, and keep them where the people bound by them can read them. A policy engine with rules nobody can inspect has moved the opacity rather than removed it.

federated computational governance combines scoped domain authority with shared rules and automated enforcement where appropriate. This does not exclude individual review, sampling, or specialist judgment for high-risk cases. Keep decision-making, policy evaluation, enforcement, and verification distinct, with owners for exceptions and uncovered paths. Who Decides What compares authority arrangements; the presence of human review alone does not make a federation centralized.

References


Discover more from Insightful Data Lab

Subscribe to get the latest posts sent to your email.

Similar Posts

Questions, corrections, or additional insights?

This site uses Akismet to reduce spam. Learn how your comment data is processed.