Recheck current policy authority before protected bytes leave
Our protected-release path checks authority twice. In the executable example, the first check succeeds, the second reports revocation, and the caller receives no protected bytes.
That behavior is the reason I keep a signed policy revision separate from current authorization. The signature lets me identify and verify the decision material. A live authority check tells me whether this principal may still use that exact revision now. Both properties matter when a model or transformation can run long enough for the world to change around it.
I built the policy leaf around that distinction. Compilation produces an immutable revision with a pin. Evaluation checks its constraints against current authority. Protection executes the configured stages, revalidates the final representation and checks authority again before returning bytes. The archive preserves revisions without choosing which revision is active.
The resulting architecture has several boundaries worth keeping explicit: exact signed content, trusted issuer administration, active policy selection, current principal rights, format validation and the final protected sink. A confident green result becomes dangerous when a receiver forgets which of those boundaries produced it.
The interval that a signature cannot close
Consider a buffered response under revision three of an engineering policy. At admission, the principal has the required capability, the destination has acceptable region and retention evidence, and the policy has not expired. The request pins that revision and starts work.
While the response is being prepared, an administrator revokes the issuer, removes the principal's capability or disables the active revision. The original bytes and signature remain exactly as they were. Re-verifying those bytes can still establish their cryptographic integrity. It cannot establish that the organization still authorizes their use.
That is why I ask two different questions. What exact policy did this operation use? Is using that policy still permitted at this transition? The first wants stable identity. The second wants a current authoritative observation. Replacing one with the other either loses reproducibility or carries stale permission forward.
Our pin contains tenant, policy identifier, revision and digest. CurrentAuthority receives that pin, the principal, the capability list and the evaluation time. The provider must check the active revision, current principal rights and issuer or key revocation. The request's capability list supplies a subject to check; it does not authenticate itself.
An archive lookup cannot implement that contract merely because it returns a valid signed document. A cache also needs an explicit consistency and revocation contract before its response can stand in for current authority. Naming the interface does not solve the freshness requirement for whoever supplies it.
What I put inside the signature
I sign a domain-separated envelope together with the exact document bytes. The binding includes tenant, policy identity, issuer, principal, revision, issue and expiry times, required capabilities, organization denies and pinned grammar digests.
The signing message uses an explicit domain:
return json.Marshal(struct {
Domain string
Binding Binding
Document []byte
}{"optinrouter.enterprise.policy.v1", b, doc})
The document is a byte slice. In this encoding it is represented as bytes rather than being parsed and reconstructed as an equivalent JSON object. Changing whitespace in the document changes the signing message. Resigning that changed document produces a different policy digest even if its parsed meaning looks equivalent.
That is deliberate. I want the archived subject to be recoverable without guessing which normalization a different component applied. Semantic equivalence can be useful for another comparison, but it should not silently replace the identity of the approved artifact.
The digest is over the entire signing message. A revision number alone would not distinguish two conflicting envelopes that claim the same human-readable version. A content digest alone would omit which tenant, principal or grammar constraints belong to those bytes.
Compilation requires an explicit verifier. There is no permissive default. Our fixture uses real Ed25519 signatures and a test issuer. A production verifier must additionally establish trusted issuer identity, accepted algorithm and key, tenant administration rights and verification of the entire message. A mathematically valid signature from an unauthorized signer is still the wrong authority.
Compilation copies the document, signature, capability lists and grammar map into the revision. That prevents the caller from editing its original slices or map after verification and changing what the retained revision means. The test exercise changes the caller-owned data after compilation and confirms the compiled pin and evaluation remain stable.
Give evaluation a precise meaning
Evaluate starts from a blocking result. It rejects a canceled context, foreign tenant or principal, missing capability and stale binding before it can return allow. It requires a current-authority provider and checks cancellation again around that call.
Organization denies take precedence over preferences. Processing permission is separate from capture and sale; this enterprise leaf refuses capture and sale. Destination checks use explicit model, region, placement and retention facts. A provider's headquarters cannot substitute for verified execution-region evidence.
The accepted retention value is no_content, but even that is only one condition. The input must say retention evidence is verified, region evidence must be verified, the model and region must be allowed, and processing must be explicitly enabled. A privacy label does not grant the rest of the operation's rights.
Limits are also checked against the policy document: requested deadline, parallel-action count and repair attempts. The implemented leaf supports buffered delivery and zero repair attempts. A schema-valid document can describe a mode whose execution is still unavailable. Accepting a document is a different transition from supporting every behavior it can express.
This is useful product discipline. I can preserve a versioned configuration language while refusing a runtime feature until its owner supplies the missing guarantee. Silently downgrading delivery or choosing a different placement would change the policy the request was admitted under.
Evaluate does not run redaction, semantic filtering or grammar stages. It produces a policy decision. Calling Evaluate and then releasing raw output would skip the composition that Protect exists to enforce.
Protect the final representation
Protect creates a bounded context, evaluates authority and runs the ordered stages for one buffered unit. Request and tool-argument targets use input stages. Responses use output stages. Unknown targets refuse. Each unit and each transformation result is bounded at one mebibyte.
Grammar stages resolve by reference, then check their digest and target against the signed binding. A reference name that happens to resolve to a newer grammar is insufficient. The policy admitted a particular grammar identity for a particular target.
Non-grammar stages call a trusted Controls executor. That interface can redact or filter the private bytes; it must respect cancellation and perform no external consequential effects. The bytes must stay out of telemetry. The policy library does not provide a default classifier or detector with imagined accuracy.
Every configured stage needs an available implementation. The required field does not create a quiet bypass when an executor is missing. A missing control or failed transformation yields unavailable with no protected output. A deployment that wants different optional-stage behavior needs a separately specified policy contract.
The important ordering detail comes after the stage loop. A transformation can invalidate a format that an earlier stage validated. Redaction might replace a number with a string, remove a required field, exceed a length limit or produce malformed JSON. Running a grammar check once at the start does not protect the final bytes.
Our source repeats grammar validation over the final transformed representation:
for _, s := range stages {
if s.Kind == "grammar" {
g := grammars[s.Ref]
if g.Validate(target, data) != nil {
d.State = Block
if g.Metadata().OnInvalid == "hold" {
d.State = Hold
}
d.Reason = GrammarInvalid
return d, nil
}
}
}
In the exercise, a valid review object passes its grammar stage. A later control replaces it with invalid bytes. The final grammar check blocks and returns no data. Removing that final loop in an isolated negative-control copy makes the exercise fail on the protected property.
Grammar validity still has a limited meaning. A well-formed object with approved:true is not evidence that its recommendation is correct or authorized. The grammar constrains representation. The policy checks a different set of permissions. Funding, tool admission and the business meaning of the proposed action remain separate owners.
Ask again at release
After transformations and final grammar validation, Protect evaluates the same pinned revision against current authority and a fresh clock observation:
end := r.Evaluate(ctx, a, in, clock())
if end.State != Allow {
return end, nil
}
return d, data
The fixture authority can revoke on its second call. That gives a precise observation: start check allowed, release check refused, zero protected bytes returned. The expiry case advances the clock to the exact expiry time between checks; release refuses there too. We do not need to wait an hour to test an hour-long validity interval.
Returning nil data alongside refusal matters. A downstream caller should not need to remember that a buffer is sensitive while ignoring an attractive payload attached to a denied result. The API makes the safe data-flow path explicit.
I also test cancellation during a control. Client cancellation does not forcibly stop synchronous Go code, but the release path can observe it and refuse to return protected data. The context deadline is installed before the initial authority call, so even that first dependency receives the request's bounded context.
The distinction matters operationally: a deadline is a cooperative contract. An executor that ignores cancellation can occupy a goroutine beyond the requested interval. This library cannot kill it by setting a timer. Hard resource isolation, bounded worker admission or process supervision belongs to the component running that executor.
The source caps the requested Protect deadline at 120,000 milliseconds. That is an upper bound on accepted configuration, not a promise that arbitrary third-party synchronous code can be terminated in 120 seconds. The release check protects the output decision; resource enforcement needs its own mechanism.
The final sink still owns a race
An in-process authority check occurs before an effect. Another actor can revoke permission after that check but before the protected sink commits. Returning a successful decision does not make those operations atomic across a process or service boundary.
Our integration contract assigns authority epoch or fencing and transactional coupling to the caller that owns the sink. For a database mutation, that could mean checking an active authority version inside the same transaction that admits the mutation. For a remote service, it can require a receiver-enforced capability or fence the remote service understands.
Those are architectural options, not claims that this leaf implemented every sink. The owner must choose a mechanism compatible with the target's consistency model. A fresh check immediately before release narrows the interval; a receiver that validates the relevant fence closes a different class of race.
The same reasoning applies to streaming. This implementation admits complete buffered units. It refuses validated_stream_units as unavailable. Once a prefix has left a transport, a later refusal cannot retrieve it. A streaming design needs an explicit unit boundary and must finish its checks before each protected unit crosses that boundary.
For an operator, this is where a diagram has to become a route inventory. Which function returns bytes? Which component writes them to a socket? Which component commits a tool action? Can any alias bypass the protected path? Who verifies the final authorization token? Each answer changes the enforcement claim.
Archive, activation and key lifecycle
The persistence API uses caller-owned authenticated tenant transactions. It does not begin or commit them. The caller authorizes organization-admin writes, establishes tenant scope and commits. Row-level security provides another boundary under the intended runtime privileges.
The archive identity is tenant, policy, revision and the exact signing message. An identical retry is idempotent; a conflicting message at the same revision returns conflict. A different valid signature is not a new policy identity. The original archived signature is retained and must still verify when loaded.
That has a consequence for key rotation. If the original signature can no longer be verified under the accepted key set, a fresh signature submitted as a retry does not silently replace the historical artifact. The owner may need a new revision. Revocation, archival readability and active-use permission need explicit lifecycle decisions.
The integration notes keep the database archive separate from active policy and revocation authority. They also say Gate E stays disabled until parent integration. I treat that as a concrete readiness boundary: callable compilation and protection functions exist; production activation requires the shared contracts, trusted producers and actual route wiring.
There is another boundary beneath row-level security. An application role that can forge the transaction's tenant setting cannot be protected from itself merely by reading that setting in a policy. Trusted server identity and the transaction wrapper remain load-bearing. The database rule is valuable within that threat model; it cannot manufacture a trustworthy principal from an application-controlled string.
The operator decision
For one agent workflow, write down the immutable subject, the source of current authority and the protected sink. Put every transformation between the initial check and final representation on the same page. Then name what can change while those transformations run.
Exercise revocation at release, exact expiry, missing controls, changed grammar pins and a later transformation that breaks valid output. Deliberately remove each final check and confirm the test fails for the intended reason. Keep format success, policy permission, spending authority and tool permission as separate decisions.
Finally, ask the sink owner how admission couples to current authority. A check can be implemented correctly while the transport or commit path never invokes it. The useful engineering outcome is a complete enforced route with a recoverable decision subject, not another broadly named validator.
Version the behavior you are prepared to invalidate
A policy pin also gives recovery a stable question. If a worker restarts halfway through preparation, it can recover which revision admitted the operation instead of silently switching to whatever is newest. Recovery still has to ask whether that revision remains usable now. Keeping the subject stable does not grant it an extended lifetime.
The same principle applies to evidence reuse. A grammar result belongs to particular bytes, a particular grammar digest and a target. Changing the bytes after that result invalidates its representation claim. Changing current authority invalidates a different claim. A receipt should preserve which observation became stale so the next owner repeats the right work.
I want that distinction in operational telemetry without capturing content. Policy pin, stage identity, typed refusal, timing and transition identity can support diagnosis. Copying the raw private unit into a debug log would create a new disclosure path outside the release architecture. Observability needs its own data contract, especially when an agent is tempted to print the payload to explain a refusal.
How this was verified
Twelve immutable source snapshots cover policy, grammar, owning unit tests, integration notes and public examples. Exact pure source files run in a reduced standalone Go1.22 module; the production module's database dependencies and PostgreSQL suite are excluded. The retained owning suites produced 50 policy and 45 grammar pass events, including parent tests and subtests, rather than 95 separately counted assertions. The original 23-case exercise uses real Ed25519 with fixture-only issuer trust and scripted authority/control providers. Two author negative controls remove final authority and final grammar validation; both make the exercise fail. These results establish offline composition behavior. Trusted production authority, database fencing, route activation, detector accuracy and live disclosure outcomes require separate evidence.
The independent source-blind review caught 16 of 42 compile-checked broken variants with the original exercise. I retained that result and expanded the exercise from 23 to 51 cases. An author replay of the same set catches 42 of 42; this is a same-set follow-up, not a fresh independent score. The original exercise and results are preserved alongside the new receipt.
