Skip to content

Add draft initiative: Runtime Integrity Layers for Agentic Systems#810

Open
narendrakumarnutalapati wants to merge 2 commits into
OWASP:mainfrom
narendrakumarnutalapati:draft/runtime-integrity-layers
Open

Add draft initiative: Runtime Integrity Layers for Agentic Systems#810
narendrakumarnutalapati wants to merge 2 commits into
OWASP:mainfrom
narendrakumarnutalapati:draft/runtime-integrity-layers

Conversation

@narendrakumarnutalapati
Copy link
Copy Markdown

This PR adds a draft initiative for “Runtime Integrity Layers for Agentic Systems”, based on the discussion in #802.

The draft captures a four-layer model:

  • transmission integrity
  • tool integrity
  • authorization-at-execution integrity
  • intent integrity

It also introduces state validity / preconditions as an execution-boundary requirement.

The goal is to provide implementation-oriented guidance:

  • what each layer addresses
  • what artifacts attest to it
  • what enforcement behavior is expected
  • where gaps remain

This is intended as a discussion draft and is very open to feedback.

Signed-off-by: NARENDRA KUMAR NUTALAPATI <narendrakumar.nutalapati@gmail.com>
@desiorac
Copy link
Copy Markdown

The three-checkpoint temporal model from #802 doesn't appear in the current draft. It maps onto the four layers as a complementary axis and might be worth adding:

Pre-decision     → authority and policy validated before the agent acts
Pre-completion   → action in flight, proxy boundary (certifying layer)
Post-completion  → audit trail, non-repudiation, third-party verification

The four layers answer what property is guaranteed. The three checkpoints answer when. A system can satisfy Layer 1 at post-completion (log inspection) while failing to enforce it pre-decision — same layer, different guarantee strength.


On the ArkForge entry

The current description is accurate but underspecified. A more precise mapping:

  • Layer 1 covered: transmission integrity — chain hash over canonical JSON (RFC 8785), Ed25519-signed, submitted to Sigstore Rekor for independent verifiability; includes agent_identity and agent_version fields captured at call time
  • Layer 2 not covered: target URL is caller-supplied and validated only for security constraints (HTTPS, no private IPs); no pre-registered endpoint binding or tool definition hash
  • Layer 3 not covered: scoped to single-boundary deployments — async dispatch and delegated execution are outside this model by design
  • Checkpoint covered: pre-completion (certifying proxy)

The Layer 2 section might also benefit from distinguishing endpoint/method binding (registration-time) from tool definition re-hashing (per-call) as two sub-guarantees with different mitigations — they address different failure modes and neither is implied by the other.

@narendrakumarnutalapati
Copy link
Copy Markdown
Author

This is very helpful — especially the distinction between the layer model (what is guaranteed) and the checkpoint model (when it is enforced).

Agreed that the temporal dimension is missing from the current draft. Adding the three-checkpoint mapping as a complementary axis makes the model more concrete without collapsing the layer separation.

I’ll update the draft to include:

  • an explicit mapping between layers and checkpoints
  • clarification of where guarantees differ by enforcement timing
  • and the ArkForge example refinements you outlined

Let me know if there are specific cases where the mapping would be most useful to illustrate.

Signed-off-by: NARENDRA KUMAR NUTALAPATI <narendrakumar.nutalapati@gmail.com>
@desiorac
Copy link
Copy Markdown

The L1 example from the PR comment is probably the clearest starting point for the document — it's already compact and counterintuitive: a system that logs everything post-completion satisfies L1 on paper but provides no pre-decision protection. That single cell in the matrix does more explanatory work than most full examples.

For a second diagonal, L4 × pre-decision vs. pre-completion is the most practically relevant: at pre-decision you have declared intent, at pre-completion you have the actual pending action — these can diverge if the agent was manipulated mid-execution (ASI01, ASI02). Checking L4 only at pre-decision misses the case where intent drift happened after the initial decision. That's probably the highest-value cell to illustrate for practitioners trying to scope enforcement.

On the ArkForge refinements: the Layer 2 distinction between endpoint binding and tool definition re-hashing is worth keeping separate in the spec — they address different failure modes (substitution vs. drift) and have different implementation points. If you want I can draft the two-line descriptions for each.

@narendrakumarnutalapati
Copy link
Copy Markdown
Author

The enforcement vs attestation split makes sense — especially in clarifying how a system can attest correctly while still allowing incorrect execution without a fail-closed boundary.

For now I’ve kept the draft focused on the layer/checkpoint model and execution-boundary enforcement to keep the scope contained within this PR.

I see this as a natural extension and can incorporate it as an explicit requirement in a follow-up iteration once the base structure settles.

@KeystoneSmartQuotes
Copy link
Copy Markdown

The enforcement/attestation separation the draft is building toward is the right structure, and I wanted to offer a concrete pattern for the execution-boundary enforcement requirement when the next iteration is ready.
The gap the thread isolated in #802 — where a system can satisfy transmission, tool, and authorization-at-execution integrity attestation while still allowing unauthorized execution — maps to a missing control class in the current SP 800-53 catalog. There is no control in the AC or AU families that treats pre-execution authorization for agent actions as a structurally binding event rather than an advisory check.
The pattern that closes this gap: before execution, the agent submits a structured proposed-action descriptor to an external control service. The service evaluates it against a versioned policy snapshot at that exact moment, then issues a signed decision artifact binding the agent identity, policy version, payload hash, and timestamp. Execution is structurally impossible without a valid artifact — and both allows and denials are recorded unconditionally.
This satisfies the enforcement requirement raised in the issue thread: authority valid, policy state matching the evaluated snapshot, and the request reaching the tool identical to what was authorized — all verified at the moment of action, not post-completion.
Happy to contribute this as a reference pattern for the enforcement boundary section in the next iteration.

@narendrakumarnutalapati
Copy link
Copy Markdown
Author

@KeystoneSmartQuotes — the SP 800-53 gap you identified is a strong way to anchor this discussion. The observation that pre-execution authorization is treated as advisory rather than structurally binding is exactly the kind of control gap this model is trying to make explicit.

The pattern you described — proposed action → policy evaluation at execution time → signed decision artifact binding identity, policy state, payload, and time → execution dependent on that artifact — aligns closely with the execution-boundary enforcement concept in the draft.

Agree that this is best captured as a concrete reference pattern for the enforcement boundary section in a follow-up iteration. The NIST framing also strengthens the case for this as a missing control class, not just an implementation detail.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@narendrakumarnutalapati Thanks for the detailed read. Happy to share a technical summary or the NIST SP 800-53 gap analysis if useful for the follow-up iteration.

@desiorac
Copy link
Copy Markdown

The SP 800-53 missing-control-class framing is the right anchor for this.

Building on your denial-recording point, @KeystoneSmartQuotes — that element deserves explicit weight in the reference pattern. A system that only records successful authorizations can't detect probing or incremental boundary-testing; the denial record is forensically as important as the approval. That's the part that maps to a new AU family control rather than an extension of existing ones.

One addition on policy snapshot binding: tying the signed artifact to a policy version number is weaker than binding the policy version hash. Version numbers are mutable labels; the hash guarantees the evaluation is independently reproducible against exactly the snapshot that was applied — you can reconstruct the decision after the fact rather than trusting that the labeled version hasn't changed. Worth being explicit about in the reference pattern.

Happy to contribute language on both points for the enforcement boundary section.

@desiorac
Copy link
Copy Markdown

The "attests correctly while executing incorrectly" failure mode is worth naming precisely: it's a proof-of-execution without a proof-of-authorization. The attestation layer records what happened faithfully, but if the enforcement check is advisory, you end up with a perfect audit trail of a policy violation — which satisfies compliance theater but not actual security posture.

The structural fix the SP 800-53 framing points toward is making the enforcement checkpoint causally upstream of execution, not a parallel recording path. The pattern that works in practice: the agent must receive a signed token from the authorization boundary before the tool call proceeds, and the downstream service validates that token — not the agent's self-report. Attestation then records the token, the call, and the response together, so the proof chain covers authorization and execution as a single atomic unit.

One concrete gap this exposes for the reference pattern: what happens when the authorization service is unavailable? If the default is fail-open (proceed without a token), the enforcement boundary collapses to advisory under degraded conditions. Explicit fail-closed behavior under unavailability probably deserves its own control entry, separate from the steady-state authorization flow.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac These are exactly the right refinements for the reference pattern. On denial recording — agreed it belongs explicitly; probing detection requires the denial record, not just the approval trail. On policy binding — a version hash rather than a version number is the right formulation; the decision needs to be independently reproducible against the exact snapshot evaluated, not a labeled pointer that could drift. On fail-closed under unavailability — this probably warrants its own control entry. If the authorization service is unreachable and the default is fail-open, the enforcement boundary degrades to advisory under the exact conditions where it matters most. Happy to contribute language on all three for the enforcement boundary section.

@desiorac
Copy link
Copy Markdown

@KeystoneSmartQuotes — strong agreement on all three, especially the fail-closed point.

On denial recording: the minimum viable entry is probably {action, policy_version_hash, denial_reason, timestamp, requesting_principal}. Without the requesting principal you lose the ability to distinguish probing from legitimate access attempts that happen to fail — the detection signal is in the pattern across principals, not in individual denials.

On fail-closed as a separate control: yes, and the framing matters. "Fail-closed under unavailability" is really about degradation mode governance — the question isn't just "what happens when the auth service is down" but "who decided what the degradation behavior would be, and is that decision itself auditable." If the fail-open default was set by a deploy config three years ago and nobody reviewed it since, the enforcement boundary was already advisory in practice. The control entry should probably require that degradation mode selection is itself a policy-bound decision with the same versioning discipline as the primary enforcement rules.

On policy binding via content hash: the reproducibility argument is the right one. A labeled version pointer is a level of indirection that introduces a TOCTOU window — the label can be repointed. A content-addressed hash eliminates that class of ambiguity entirely.

Happy to review draft language on any of these when you have it.

@desiorac
Copy link
Copy Markdown

@KeystoneSmartQuotes — the version hash formulation is the right call. A version label is a pointer to a mutable artifact; the hash is the artifact. If the policy store is writable after the decision is recorded, a label-only binding can be satisfied by a snapshot that no longer exists, which makes the audit trail unfalsifiable on paper but unverifiable in practice.

On fail-closed under unavailability deserving its own control: agree, and the control probably needs to distinguish two failure modes. First, enforcement service unreachable: the decision here is binary (deny all vs. degrade to advisory), and anything other than deny-all breaks the causal-upstream guarantee the pattern is trying to establish. Second, policy snapshot unavailable at verification time: here the question is whether you require the evaluating party to hold the snapshot independently or rely on the policy store being available at audit time. These have different threat models: the first is an availability attack on the enforcement path, the second is a retention/integrity attack on the forensic path. Conflating them in a single control risks solutions that address one while leaving the other advisory.

One implementation note on denial recording: storing denials in the same append-only log as approvals, rather than a separate audit stream, is important. It prevents a failure mode where denial logging is disabled under load without affecting approval throughput. Systems that handle this well treat both as the same event class with a transaction_success flag, so the log structure can't be selectively populated. That's probably worth encoding as a structural requirement in the new AU family control rather than leaving it to implementation guidance.

@desiorac
Copy link
Copy Markdown

@KeystoneSmartQuotes — on the fail-closed control, the two failure modes probably need distinct control statements because their mitigations diverge significantly.

Enforcement service unavailable: the correct default is block-and-queue or block-and-reject, with a short (seconds-level) timeout before the fail-closed response. The control text should specify that the enforcement service itself must not be on the critical path for liveness — meaning it can't share failure domains with the action execution surface it governs.

Policy store unavailable (enforcement service reachable but can't load current policy): this is the harder case. Fail-closed is still correct, but the audit requirement changes — the system needs to record which policy snapshot it last successfully loaded, so post-incident analysis can reconstruct the decision boundary at failure time. A stale-snapshot timer (reject decisions older than T minutes without a confirmed policy refresh) is probably the right primitive here, distinct from the availability check.

The two cases collapse into one if you treat "policy store unavailable" as a sub-case of enforcement failure, but the audit semantics differ enough that separate control language is worth the overhead — especially for post-incident reproducibility, which is the real driver for the version hash formulation anyway.

If the follow-up draft is collecting candidate control text, I'd suggest framing these under a new SA or AU extension rather than extending existing AC-3 variants — the causal-upstream enforcement requirement breaks the AC-3 model assumption that authorization is a pre-check, not a gate.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac — the two-failure-mode split is the right structure, and the degradation-mode-as-policy-decision framing from your second point is the sharpest formulation here: it’s not just what the system does under failure, but whether the decision about degradation behavior is itself versioned and auditable. That’s a distinct requirement from the failure response itself. On the SA/AU extension over AC-3 variants — agreed, for exactly the reason you named: the causal-upstream gate breaks the AC-3 pre-check assumption. I’ll draft candidate control text covering all three: denial record structure including requesting principal for cross-principal pattern detection, the two failure modes, and degradation mode governance. What’s the right format to contribute — directly into the PR or as a separate document Narendra can pull from?

@desiorac
Copy link
Copy Markdown

@KeystoneSmartQuotes — the degradation-mode-as-policy-decision framing has a concrete implication for control text scope: the degradation policy artifact needs to be under the same change control process as the primary enforcement policy. If primary policy changes require version hash recording and review, degradation policy changes should too — otherwise you end up with a versioned primary path and an unversioned bypass path, which is structurally the same as a privileged escape hatch.

On the SA/AU framing over AC-3 variants: the reason the causal-upstream gate doesn't fit AC-3 well is that AC-3 scopes to the access decision itself, while what you're describing is a structural requirement on the enforcement component's architecture — closer to SA-17 (developer security architecture and design) applied to the enforcement service as a system component. The AU extension then covers what you'd call "second-order audit events": not just "what action was taken and under what policy" but "when was degradation mode active, for how long, and what triggered it." Those events need the same {principal, policy_version_hash, trigger_condition, timestamp} record structure as primary denial records — degradation-mode activations are as forensically significant as denials, for the same probing-detection reason.

The open question that probably needs its own control statement is whether degradation-mode activations require out-of-band notification to a control plane — you can satisfy the audit requirement with local records, but if the enforcement service is silently degraded, the audit trail only surfaces the gap post-hoc.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac — the out-of-band notification question is the right one to nail down, and I’d argue it’s not optional: silent degradation with a local-only audit trail is a detection gap by design. The control statement should require active notification to a control plane on degradation-mode activation — not as an implementation recommendation but as a structural requirement. A local record that nobody reads until post-incident isn’t a control; it’s a forensic artifact. The notification requirement is what converts the audit trail from retrospective evidence into a live enforcement signal. That probably needs its own control statement distinct from both the primary enforcement flow and the audit record requirement — something closer to an IR (Incident Response) family trigger than a pure AU entry, specifically IR-6 (Incident Reporting) applied to enforcement infrastructure degradation as a reportable event class, since the response to silent degradation isn’t just logging, it’s alerting.

@desiorac
Copy link
Copy Markdown

@KeystoneSmartQuotes — agreed that notification to a control plane is structural, not advisory. But there's a second-order integrity question worth adding to the control text: what are the integrity requirements on the notification itself?

A notification that an attacker who has already compromised the enforcement service can suppress or forge provides weaker guarantees than it appears. That implies the control plane receiving notifications must be on a separate auth and trust boundary from the enforcement service - not just a separate endpoint, but a path where compromise of the enforcement tier doesn't grant write access to the notification channel.

Two additional properties probably belong in the control statement. First, notifications should be sequenced and signed, not just log lines. Signed, sequenced events let the control plane detect suppressed notifications as sequence gaps; silent suppression becomes visible as a missing entry in a verifiable stream. Second, the notification artifact itself should be independently verifiable without trusting the enforcement service's own state. A notification that references the degradation-mode policy version hash (per the earlier point in this thread) satisfies that - the control plane can verify the reported state against the policy store without going back through the degraded enforcement path.

Without those two properties, the notification requirement is satisfied by a UDP syslog message to a logging server, which doesn't meet the spirit of the requirement at all.

@KeystoneSmartQuotes
Copy link
Copy Markdown

KeystoneSmartQuotes commented Mar 28, 2026

@desiorac — The sequenced-and-signed notification requirement plus the separate trust boundary closes the loop on the IR-6 control statement. That framing also answers the format question from earlier: I’ll contribute candidate control text directly into the PR rather than as a separate document.
Here are the three control statements, in the NIST SP 800-53 COSAiS overlay schema format currently used for the Predictive AI overlay:

One thing worth flagging: the notification integrity properties you raised — sequenced, signed, separate trust boundary — may sit more naturally in SA-17 than IR-6. IR-6 covers the reporting obligation; the channel architecture is a design requirement. Happy to adjust the control text if you see it that way too.

@desiorac
Copy link
Copy Markdown

The message was cut off before showing the full control statements — looking forward to seeing the complete text in the PR. The SA-17 anchor is the right choice for the enforcement architecture control: SA-17 covers developer-supplied security architecture requirements, and extending it to mandate explicit documentation of the enforcement service's trust boundary, failure modes, and degradation policy artifacts brings the design-time requirement in line with everything we've established for runtime behavior.

A few things worth anticipating for reviewer feedback on the COSAiS overlay format: the enhancement field will need to clearly differentiate between requirements that apply to the enforcement service itself vs. requirements that apply to the systems that consume enforcement decisions — those are different implementation responsibilities and often end up in different organizational ownership. If the control conflates them, teams will read past the part that applies to them.

On the IR-6 extension — assuming it captures the sequenced-and-signed notification requirement — the tricky editorial question is whether the control text should specify the trust boundary requirement as a structural property or as a set of implementation constraints. Structural is better for longevity (avoids over-specifying an auth mechanism that may change), but then the supplemental guidance section needs to give enough concrete shape that implementors aren't just left with "separate trust boundary" as an undefined term.

Curious what the third control anchors to — CM or AU would both be defensible for the degradation-policy-as-versioned-artifact requirement.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac — GitHub clipped the previous comment. Here are the remaining two control statements, plus a note on the CM question.
Control 2: AU Extension — Unified Agent Action Audit Record
∙ Selected in Moderate Baseline: No (proposed addition)
∙ Applicable AI Lifecycle Phase(s): Model Deployment; Model Operation
∙ Assumptions: Approval and denial events must be forensically inseparable to support probing detection and post-incident reproducibility.
∙ Control Tailoring: The organization shall maintain a unified append-only log treating agent action authorizations and denials as a single event class, structurally preventing selective retention of either path. Denial records shall contain sufficient fields to support cross-principal pattern detection and post-incident decision replay, including the content hash of the evaluated policy snapshot — not a version label — to ensure reproducibility against the exact snapshot applied.
∙ Relevant NIST AI 100-2e2025 Attack ID: NISTAML.024, NISTAML.026
Control 3: IR-6 Extension — Enforcement Infrastructure Degradation Reporting
∙ Selected in Moderate Baseline: No (proposed addition)
∙ Applicable AI Lifecycle Phase(s): Model Deployment; Model Operation
∙ Assumptions: Silent degradation of enforcement infrastructure is a reportable security event, not an operational footnote. Local-only audit records do not constitute a control.
∙ Control Tailoring: The organization shall treat enforcement service degradation-mode activation as a reportable event requiring active notification to a control plane operating on a separate trust boundary from the enforcement tier. Notifications shall be tamper-evident and gap-detectable (i.e., the absence of a notification is itself a detectable condition). The notification shall reference the degradation-mode policy version hash so the control plane can verify reported state against the policy store without traversing the degraded enforcement path. Degradation-mode policy selection shall be subject to the same version control discipline as primary enforcement policy.
∙ Relevant NIST AI 100-2e2025 Attack ID: NISTAML.013, NISTAML.031
On the CM vs AU question for degradation-mode policy governance: CM is the stronger anchor — specifically CM-03 (Configuration Change Control). Degradation mode selection is a configuration decision that determines enforcement behavior under failure. It produces audit events, but it isn’t one. I’ll draft a CM-03 card — the degradation-mode-policy-as-controlled-configuration-item framing maps cleanly to how CM-02 is already structured in the SP 800-53 catalog.
One thing worth flagging from the original truncated comment: the notification integrity properties you raised — sequenced, signed, separate trust boundary — may sit more naturally in SA-17 than IR-6. IR-6 covers the reporting obligation; the channel architecture is a design requirement. Happy to adjust the control text if you see it that way too.

@desiorac
Copy link
Copy Markdown

The "forensically inseparable" requirement implies a specific mandatory field set: the audit record needs to bind the policy artifact version hash at write time, not as optional metadata. Without that field, schema evolution in the AU extension can make historical records ambiguous retroactively - you can have a well-formed record that conforms to the current schema but whose denial condition is unresolvable against the policy version active at decision time. That's a silent precision loss, not a format error, so it won't surface in schema validation.

On the probing detection assumption: the control tailoring should specify minimum granularity at the condition level, not just the outcome level. A record that captures decision: denied satisfies the letter of most AU-12 implementations but gives you almost nothing for IR-6 response - you can detect anomalous denial rates but can't identify which policy surface is being exercised. The condition identifier (or rule ID in an XACML-style policy structure) needs to be a required field, not a recommended one.

For the CM question: if the policy artifact itself is not under the same change control process as the audit schema, you get the asymmetry @KeystoneSmartQuotes flagged earlier in the thread - versioned schema, unversioned content. The straightforward fix is to treat the policy version hash as a foreign key into the CM system, so any audit record points to a specific retrievable artifact. Whether that's a git SHA, a content-addressed store reference, or a signed manifest depends on the implementation, but the control text should specify the requirement, not the mechanism.

Looking forward to seeing the full "The organization shall" clause - the framing so far suggests it will require active binding rather than passive logging, which is the right structural choice.

@KeystoneSmartQuotes
Copy link
Copy Markdown

KeystoneSmartQuotes commented Mar 29, 2026

@desiorac — these refinements are the right ones. Incorporating all three into the updated reference pattern:
On the AU control — three structural updates:
The denial record minimum viable field set you proposed (action, policy_version_hash, denial_reason, timestamp, requesting_principal) is correct. I’d add condition_id — the specific rule or condition within the policy snapshot that produced the denial. Without it, probing detection can observe that a principal is generating denials but cannot distinguish which policy surface is being exercised. The detection signal for incremental boundary-testing lives in that field, not in the denial count alone.
On policy binding: agreed that a version label is a pointer to a mutable artifact. The control text should require that the policy snapshot hash used during evaluation is written to the audit record as a mandatory bound field at write time — not as optional metadata added post-hoc. A record with a missing or null hash should be treated as a structurally incomplete event, not a valid audit entry. This closes the silent-precision-loss failure mode.
On the append-only log structure: agreed that approvals and denials must be the same event class with a decision_outcome flag, stored in the same append-only log. This should be encoded as a structural requirement in the new AU family control — not left to implementation guidance — because a system that separates denial logging into a distinct stream can disable it selectively under load without affecting approval throughput. The control text needs to make that class of selective population architecturally non-compliant.

On SA-17 — enforcement architecture:
The AU control captures the audit requirement. SA-17 is where the causal-upstream enforcement requirement lives, and the control text needs to address it directly.
The structural requirement: before any agentic action is executed, the agent must obtain a signed authorization artifact from an enforcement component that is architecturally separate from the execution surface it governs. The artifact binds: agent identity, action descriptor hash, policy snapshot hash (content-addressed, not labeled), and timestamp. Execution by any downstream service is conditioned on artifact validity — the downstream service validates the artifact independently, not the agent’s self-report.
Two corollaries belong in the control statement, not guidance:
First, the fail-closed requirement under enforcement service unavailability: if the authorization service is unreachable, the required response is block — not degrade to advisory. Any configuration that permits execution without a valid artifact under degraded conditions breaks the causal-upstream guarantee and reduces the enforcement boundary to advisory under the exact conditions where it matters most. The control text should also specify that the authorization service must not share a failure domain with the execution surface it governs.
Second, degradation mode governance as a policy-bound decision: @desiorac’s framing is exactly right — the question is not only “what happens when the auth service is down” but “who decided the degradation behavior, and is that decision itself auditable and versioned.” The degradation mode selection must be treated as a policy artifact subject to the same versioning and hash-binding discipline as the primary enforcement rules. A fail-open default set by a deploy config three years ago with no audit record is an advisory enforcement boundary in practice, regardless of what the primary path does.

The AU and SA-17 cards together close the gap the thread has been building toward: AU records that the authorization event happened and what policy state governed it; SA-17 requires that the enforcement check is causally upstream of execution and structurally binding, not a parallel recording path.

I can contribute formal ‘The organization shall’ language for both — the NIST COSAiS gap framing makes this timely to have in documented form soon.

@desiorac
Copy link
Copy Markdown

condition_id is the right addition. Without it, the denial record tells you that a principal was denied at a specific policy version, but you can't distinguish between "denied because of condition X, which was introduced in this version" and "denied because condition Y, which has been stable across 10 versions." That distinction matters for probing detection: a sequence of denials across different policy versions that all resolve to the same condition_id is a different signal than denials that scatter across conditions, and you lose that correlation entirely if the identifier is version-scoped rather than stable.

That raises the identifier stability question directly: should condition_id be a stable name (persists across policy versions, survives condition rewrites) or a content-addressed identifier (hash of the condition's canonical form at the snapshot version)? Stable names are simpler for correlation queries but can silently drift - a condition named deny_unapproved_tools in v3 may have a materially different predicate than the same name in v7. A content-addressed condition_id (e.g., SHA-256 of the normalized condition expression) ties the identifier to the actual logic, which means condition rewrites produce new identifiers automatically, and probing detection would correctly treat the old and new conditions as distinct - no silent precision loss even across a long policy history.

The practical tradeoff: content-addressed identifiers require the policy artifact to store stable human-readable labels separately from the condition_id used in audit records, otherwise the records become opaque without tooling. Worth specifying in the control text whether the field is required to be human-interpretable or whether a canonical-form hash is acceptable - those are two different auditability requirements with different tooling implications downstream.

@QueBallSharken
Copy link
Copy Markdown

One boundary condition I’d make explicit in the draft language:

A system can have:

  • a valid authorization artifact
  • a faithful execution path
  • and a complete audit record

and still be invalid if the action was not re-evaluated against the live state at commit time.

So alongside proof-of-authorization and proof-of-execution, the reference pattern should also require proof-of-admissibility at the execution boundary.

Otherwise the model can still permit a failure mode where:

  • the token is valid
  • the call is authentic
  • the response is recorded
  • but the resulting state transition was no longer legitimate under current conditions when execution actually occurred

I think that requirement should be stated separately from authorization integrity.

Authorization answers: was this action approved?
Execution integrity answers: was this action faithfully carried out?
Execution-boundary admissibility answers: was this action still allowed to become real under the live state that existed at commit time?

If admissibility cannot be re-derived at that boundary, execution should refuse.

@desiorac
Copy link
Copy Markdown

The admissibility gap is the right thing to make explicit. The failure mode you're pointing at is essentially TOCTOU applied to authorization: the artifact was valid at issuance, the execution path was faithful, but the policy state that would have denied the action at commit time was never consulted. The audit record is internally consistent and still misleading.

This connects directly to the policy_version_hash field we established in the AU extension. Binding the hash at write time handles the forensic question ("what policy was active?") but doesn't enforce re-evaluation — it just makes the staleness detectable after the fact. Proof-of-admissibility as a distinct control property would require that the executing boundary actually gates on the live policy hash, not just records it.

One concrete consequence for the control language: the admissibility check needs to be atomic with the commit. If there's a window between "re-evaluate against live state" and "execute," you can still race a policy update through that window. The requirement probably has to be stated as something like "the action's admissibility shall be determined against the policy snapshot whose hash is recorded in the resulting audit entry, and that evaluation and the action commit shall be treated as a single indivisible operation for the purposes of the AU control."

Your message above got clipped — the failure mode example was cut off. If you can re-post the rest, it would help make sure the control text covers the specific scenario you had in mind.

@desiorac
Copy link
Copy Markdown

The framing is right, and the enforcement consequence follows directly: if admissibility is modeled as a property alongside the commit, the spec can be satisfied by a system that evaluates admissibility, records the result, and then commits regardless of the outcome. The evidence is present; the gate was never closed.

What makes it a genuine precondition rather than a co-located check is causal structure: the commit must be unable to proceed without a successful admissibility evaluation at T_commit. One way to encode this concretely is requiring the admissibility evaluation to produce a short-lived signed token that the commit operation consumes as a mandatory input - the token binds the live state snapshot, the evaluation timestamp, and the allowed transition. No token, no commit; expired token, no commit; token not derived from the actual live state, invalid proof.

The distinction that matters in spec language is between "the system must evaluate admissibility before committing" (behavioral, unenforceable structurally) and "the commit operation takes the admissibility token as an input" (structural, verifiable from the proof). The second form is what prevents compliant proofs for inadmissible commits.

@desiorac
Copy link
Copy Markdown

The "Temporal Execution Integrity" framing nails the key distinction: the admissibility predicate can't be evaluated over a snapshot taken before the commit operation - it has to be co-produced with the commit. The seam between "check" and "execute" is exactly where the TOCTOU failure lives, and recording that the check happened is not the same as proving the check and the commit were causally coupled, not just temporally proximate.

That has a concrete implication for what the admissibility certificate must contain: not just which predicate was applied and what it returned, but the state variables the predicate consumed and their values at evaluation time - enough to reconstruct what the predicate saw. This maps onto compare-and-swap semantics at the action level: the commit succeeds only if the relevant state at execution time matches the state evaluated under the predicate, and the certificate is an output of a successful CAS, not an input to the commit. If it's an input, you have a seam; if it's an output, there's no in-between state where the action executes under a stale predicate.

One thing the draft may need to make explicit: this requires a declared read set per action type. "Relevant state" is defined by the action schema, not the agent - without knowing which state variables are in scope for a given action, you can't define the execution boundary precisely enough for consistent admissibility evaluation. The refusal path belongs in scope here too: a system that silently proceeds on a stale predicate is worse than one that refuses noisily, but a refusal without an auditable record of which admissibility condition failed leaves the same forensic gap from the other direction.

@desiorac
Copy link
Copy Markdown

The three-property structure is clean and I think it works. One tension worth examining: evaluation completeness and reconstruction can conflict when the input surface includes time-varying external state.

If admissibility depends on an ephemeral condition - a rate limit counter, an exclusive lock, a balance at a downstream service - completeness requires capturing that state as input, but reconstruction assumes the canonical inputs produce a stable evaluation result. For state that changes faster than the attestation boundary, you can satisfy completeness (you captured everything relevant) and attestation integrity (the capture was faithful) while still failing reconstruction (re-running the evaluation against the same captured inputs may now yield a different outcome because the semantics of that state have shifted).

This suggests a fourth implicit property worth naming: input stability - the canonical inputs themselves must be snapshotted at a well-defined, coherent point such that re-evaluation against them is meaningful. Without it, reconstruction becomes a weaker guarantee: "the evaluation was reproducible given those inputs at that moment" rather than "the evaluation is reproducible." The difference matters for any auditor or dispute resolution process that needs to re-derive the admissibility result after the fact.

One concrete way to enforce this: require that each input in the admissibility surface carries a content hash and a source timestamp, so reconstruction evidence includes not just the values but the provenance of those values. That shifts the reconstruction burden from "same inputs, same result" to "same inputs at attested times, same result given those versions" - which is a satisfiable property even over volatile state.

@desiorac
Copy link
Copy Markdown

The "operating outside governance" framing is the right one - it sharpens the implementation requirement considerably. If admissibility is non-transferable across time, then the admissibility check and the commit must be atomic: any gap between evaluation and execution creates a window where the predicate can flip without the system detecting it.

This has a direct implication for how attestation must be structured: the admissibility evidence cannot be produced before the commit and carried forward. It must be produced as part of the commit transaction, with its timestamp co-located with the live state snapshot. An admissibility receipt with timestamp T₁ attached to a commit at T₂ is formally invalid under this definition - not because the evaluation was wrong at T₁, but because the conditions that made it true at T₁ are not guaranteed to hold at T₂.

The hardest part to specify precisely is what "exact moment of commit" means in distributed execution. Execution boundaries often aren't atomic events - they span network calls, lock acquisitions, multi-step state transitions. The temporal integrity constraint probably needs to be anchored to a specific visibility point: the moment after which no further world-state mutations are observable by the executing system before commit. Everything evaluated before that point is subject to the non-transferability property and must be treated as provisional.

One consequence worth making explicit in the draft: this means the admissibility evaluator cannot be a separate service that returns a cached token. The evaluation must happen in a context that has exclusive visibility into the relevant state slice at the moment of commit - or the architectural guarantee collapses regardless of how well the evaluation itself is implemented.

@desiorac
Copy link
Copy Markdown

The failure mode is worth naming precisely: execution under an invalidated precondition. The authorization was valid at issuance, the predicate was true at evaluation, but state moved between evaluation and commit. The structural fix maps directly to the invariant databases require for CAS: the comparison and the swap must be atomic, or the guarantee doesn't hold.

That reframes the admissibility certificate as an output of the commit, not an input to it. If it's an input, there's a seam - however narrow - where state can change between predicate evaluation and execution. If it's co-produced at commit, the result is binary: the operation succeeds with a valid certificate, or it fails. There's no path where execution proceeds under a stale predicate.

For the certificate to be independently verifiable against this guarantee, it needs to bind more than "which rules applied at evaluation time": specifically, the state snapshot hash, the evaluation timestamp, and a causal link to the execution event - not just temporal co-location. "50ms before commit" and "at commit" are structurally indistinguishable in a log without that causal coupling. The draft language should probably require those fields explicitly rather than leaving them implied by "re-evaluated at the execution boundary."

One scope question worth raising: the refusal path. A system that refuses on stale admissibility but produces no auditable record of the refusal and the triggering state snapshot has closed the execution gap while leaving a forensic gap - distinct failure modes, but both matter for the integrity model.

@desiorac
Copy link
Copy Markdown

The three-property structure is clean and I think it's the right decomposition. One thing worth pulling on: evaluation completeness is likely the hardest to operationalize, because the canonical input surface is itself ambiguous until explicitly declared. For a state-bound admissibility check, inputs seem bounded (policy artifact + live state snapshot), but in practice they expand: which snapshot version was visible to the read token, whether exclusivity constraints were evaluated against the same consistent slice, whether the execution clock matches the validity window reference. A partially-specified input surface produces attestations that are internally consistent but incomplete - and that may be worse than no attestation, because they pass superficial review.

The practical implication: the canonical input surface probably needs to be declared at design time and bound to the TEI artifact, not inferred at audit time. Otherwise "independently reproducible from canonical inputs" degrades to "we believe these were the inputs," which breaks reconstruction as a property - you can't contest a proof whose input boundary is underspecified.

One open question from this: should the TEI attestation include a commitment to the input surface definition (a schema hash or typed descriptor), so that reconstruction failures are distinguishable from evaluation failures? Those are two very different failure modes - one means the admissibility logic was wrong, the other means the auditor is working from incomplete inputs.

@desiorac
Copy link
Copy Markdown

The structural point is well-taken - these properties share a temporal anchor and a world-state snapshot, so collapsing them under a unified execution boundary concept is architecturally coherent. The tension is that "co-located at the same boundary" doesn't imply "same verifiable predicate." Even if admissibility, temporal binding, and reconstruction are all evaluated at commit time, keeping them as distinct fields in the proof record preserves diagnostic resolution: when a verification fails, you need to know which property was violated, not just that "the execution boundary was unsound."

The request_auth framing handles structural authorization well, but admissibility is a different evaluation domain - it answers whether the conditions that made the transition real still hold, not whether the artifact was structurally valid. Conflating those under one field would mean a stale-resource failure and an expired-authorization failure look identical in the audit record.

A synthesis that might keep the draft coherent: acknowledge that all three share an execution-boundary timestamp (same monotonic anchor, same state snapshot), but treat them as independent predicates that happen to be co-evaluated - similar to how TCP keeps sequence, checksum, and acknowledgement distinct even though they all participate in the same delivery guarantee. The boundary is a single frame, but the predicates within it remain independently falsifiable.

@desiorac
Copy link
Copy Markdown

The structural economy argument is sound - and worth taking seriously before adding dimensions to the model. But there's a reason temporal execution integrity may resist collapsing into request_auth cleanly: the evidence lifecycle is different, not just the evaluation domain.

Authorization evidence is established before execution - it can be generated, cached, validated ahead of time. Admissibility evidence, by your definition, must be generated at the execution boundary and bound to the exact commit time. That's a different temporal relationship with the execution event, not just a different predicate to evaluate. If you fold it under request_auth, you need to clarify that a subset of authorization evidence has this "must be live, must be now" constraint - which is either a sub-type with distinct properties, or effectively a new dimension under a different label.

The reconstruction requirement compounds this: to audit the admissibility claim post-hoc, you need the live state snapshot at commit time to be part of the proof artifact, not derivable from the authorization artifact or the policy version. That evidence doesn't naturally live in request_auth unless you extend that field's semantics significantly.

One path that might preserve structural compactness: define request_auth as covering structural authorization (what transitions are permitted by policy) and add execution_state_binding as a sibling property specifically for the live-world predicate at commit time. That keeps the top-level count low while making the evidence boundary explicit where it matters for auditability.

@desiorac
Copy link
Copy Markdown

That framing is helpful - and I think you're right that collapsing these into the existing execution boundary avoids unnecessary model inflation. The concern I'd flag is whether request_auth as currently scoped is doing too much work if it has to carry both "was this authorization structurally valid at issuance" and "was admissibility re-derived against live state at commit time." Those have different evaluation semantics and different failure signatures.

One way to preserve the boundary cohesion you're describing without overloading request_auth: treat the execution boundary as a single gate with three ordered predicates - authorization validity, admissibility against current state, and temporal binding of the admissibility evaluation itself. All three must hold at the same moment; none promotes to a separate integrity layer. The audit record then captures the gate evaluation as a unit, not three independent checks.

The practical consequence is that the reconstruction guarantee (can an external auditor verify that the gate was evaluated correctly?) applies to the whole gate, not to each predicate separately. That's actually easier to reason about from an audit standpoint: a single signed snapshot of (policy version, world state hash, execution timestamp) at the boundary covers all three, and a missing or inconsistent snapshot is a uniform failure signal regardless of which predicate it would have blocked.

@desiorac
Copy link
Copy Markdown

The gate vs. property distinction has real enforcement consequences that are worth making explicit in the draft. If admissibility is modeled as a property, an audit record can retrospectively note "admissibility was not satisfied" while the transition still committed - which makes it a compliance signal, not an execution constraint. Treating it as a gate means the runtime semantics change: the transition cannot commit without it, full stop.

The implementation-level implication is that the admissibility evaluation must be atomic with the commit decision. A two-phase pattern (evaluate, then commit) reintroduces the TOCTOU gap at a different boundary - the state snapshot used for admissibility may no longer match the state on which the transition acts by the time commit executes.

This also affects what the evidence must capture: not just "admissibility held at some point," but "admissibility was evaluated against the live snapshot at the exact T_commit that was used for the transition." State snapshot hash, predicate result, and execution timestamp need to be co-bound inputs to whatever certifies the boundary crossing - not post-hoc metadata appended alongside it. Without that co-binding, an adversarial or failing system can still produce internally consistent records that misrepresent what actually gated the execution.

@desiorac
Copy link
Copy Markdown

The gate-vs-property distinction you're drawing has direct enforcement consequences that are worth making explicit in the draft. If admissibility is modeled as a property, a spec-compliant implementation can record admissibility_result: failed and still commit - and produce a technically valid evidence bundle. That's not a corner case; it's the default failure mode for any property-based model under adversarial or degraded conditions.

The framing that resolves this: a valid execution receipt is only producible if admissibility held at T_commit. An implementation that proceeds through a failed admissibility gate isn't producing a receipt - it's producing a forgery. The spec should define validity that way, not as a set of fields that must be populated.

The analogy that fits is ACID atomicity: it's not a property of the committed record, it's a constraint on what can enter the committed state. You cannot observe a partially-committed transaction in a well-formed log because the model defines the log in terms of what atomicity permits, not in terms of what it records. Admissibility should sit in the same structural position - not as evidence that accompanies execution, but as the condition under which execution is defined to have occurred at all.

For the draft language, the actionable change is: specify admissibility as a precondition for receipt issuance, not as a field in the receipt. The evidence bundle attests to the state snapshot and timestamp at the boundary; the existence of a valid bundle is the proof admissibility held. A failed admissibility check produces no bundle - it produces a rejection event with a distinct record type.

@KeystoneSmartQuotes
Copy link
Copy Markdown

Based on the thread discussion, posting candidate control language for the three areas we converged on. These are offered as a starting point for the enforcement boundary section — ready for refinement from @desiorac and @QueBallSharken before the next iteration.

The three controls address:
(1) structural isolation of the enforcement component,
(2) governance decision record requirements, and
(3) degradation mode governance as a policy-bound decision.

SA-17(EXT) — Enforcement Architecture Requirement
The organization shall require that the governance authority evaluating proposed agent actions is structurally isolated from the execution system it governs. The governance authority shall have no capability to execute actions, invoke enforcement APIs, or modify the state of governed systems. Any failure of the governance authority shall produce a deny or hold outcome. The system shall never default to permit under any failure condition.

AU(EXT) — Governance Decision Record Requirements
The organization shall require that every governance evaluation — whether the outcome is approval, denial, or hold — is recorded as the same event class in a single append-only log. Each record shall bind: (a) the content-addressed hash of the policy snapshot applied at evaluation time, not a version label; (b) the stable identifier of the specific condition evaluated; (c) the requesting principal; (d) the eligibility outcome; and (e) a precise timestamp. Records shall be cryptographically signed. The log structure shall not permit selective population of approvals without denials.

CM(EXT) — Degradation Mode Governance
The organization shall require that the default behavior of the enforcement boundary under degraded conditions — including governance authority unavailability and policy store unavailability — is itself a versioned, policy-bound decision subject to the same change control process as primary enforcement policy. Degradation mode activations shall be recorded with the same field structure as primary denial records. The system shall distinguish between enforcement service unavailability and policy snapshot unavailability as two separate failure modes with separate audit semantics.
@KeystoneSmartQuotes

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 2, 2026

The three-area framing is a useful scaffold. One concern before @desiorac and @QueBallSharken review: the split between (2) and (3) may obscure the temporal binding requirement that emerged from the earlier thread.

Governance decision records and degradation mode governance both involve policy artifacts - but what the thread converged on is that admissibility at the execution boundary requires more than a valid decision record: it requires evidence that the world state at commit time still satisfied the conditions under which the authorization was issued. That predicate is time-stamped and state-bound, not just policy-bound.

If SA-17(EXT) covers structural isolation of the enforcement component, it may be worth adding a fourth control explicitly for the admissibility evidence requirement - something like: the enforcement component must produce a signed state snapshot at the execution boundary that binds the live resource state, the execution timestamp, and the policy version hash at the moment of commit. This distinguishes between "the decision was valid when made" and "the transition was admissible when executed."

Without that explicit separation, controls (2) and (3) can be satisfied by a system that has a complete governance record but still commits actions against stale admissibility state - which is exactly the TOCTOU failure mode @QueBallSharken was pointing at. The control language should make it impossible to construct a compliant audit trail for an invalid transition.

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 2, 2026

The decision record control has a gap that will matter at implementation time: capturing "which policy applied and what the evaluation result was" doesn't satisfy the temporal execution integrity framing from earlier in this thread, because policy evaluation and execution-boundary admissibility are two separate events. The record needs to co-sign four things at a single commit timestamp: policy artifact hash, live state snapshot hash, admissibility predicate result, and execution time. Without that binding, a gap between "policy evaluated at T1" and "action committed at T2" is undetectable from the record alone.

On degradation mode: the spec probably needs to distinguish between a gate on new admissions and a re-evaluation trigger for in-flight ones. A degradation event that halts new admissions but lets already-admitted actions complete silently can still violate the admissibility invariant if world state changed during that window. Those are two different policy decisions and collapsing them into one control leaves the in-flight case undefined.

For SA-17(EXT), one concrete testable criterion: the enforcement component should be non-bypassable by privileged callers within the same trust domain. Structural isolation that an admin path can override is operationally no isolation at all, and that's the failure mode most production systems actually hit first.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac — these are the right refinements and I want to address each one directly.
On the T1/T2 gap in the AU control: agreed. Capturing which policy applied and what the evaluation result was doesn't satisfy temporal execution integrity because policy evaluation and execution-boundary admissibility are two separate events. The AU(EXT) control text needs to require co-signing of four things at a single commit timestamp — policy artifact hash, live state snapshot hash, admissibility predicate result, and execution time — as a single atomic record. A gap between T1 (policy evaluated) and T2 (action committed) that is undetectable from the record alone is not a compliant audit trail; it's a forensic artifact of a system that may have committed under stale admissibility state. I'll revise the AU(EXT) language to make that co-binding a structural requirement, not a recommended field.

On degradation mode — the in-flight vs. new admission split is the right distinction and the current CM(EXT) language collapses it incorrectly. A degradation event that halts new admissions but permits already-admitted actions to complete silently can still violate the admissibility invariant if world state changed during that window. Those are two separate policy decisions with separate audit semantics: one is an admission gate, the other is a re-evaluation trigger for in-flight actions. I'll split CM(EXT) into two explicit control statements to keep them independently falsifiable.

On SA-17(EXT) — the non-bypassability criterion you named is the right one and belongs in the control text, not the supplemental guidance. The testable form: the enforcement component shall be non-bypassable by privileged callers within the same trust domain. Structural isolation that an administrative path can override is operationally no isolation at all — it is an unversioned bypass path that undermines the causal-upstream guarantee regardless of how well the primary enforcement path performs. I'll add this as an explicit SHALL statement alongside the failure domain separation requirement.

Revised control language — four controls, not three — coming shortly.
@KeystoneSmartQuotes

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac @QueBallSharken — revised control language incorporating all refinements from the thread. Four controls, not three. The fourth is new and addresses the temporal execution integrity gap directly.

Control 1: SA-17(EXT) — Enforcement Architecture Requirement
Selected in Moderate Baseline: No (proposed addition)
Applicable AI Lifecycle Phase(s): Model Deployment; Model Operation
Relevant Attack IDs: NISTAML.013, NISTAML.022, NISTAML.031
The organization shall require that the enforcement component responsible for evaluating proposed agent actions is architecturally and operationally isolated from the execution system it governs. Specifically:
Structural isolation. The enforcement component shall have no capability to execute actions, invoke execution APIs, or modify the state of governed systems directly. Its sole authorized output is an eligibility decision — approve, deny, hold, or escalate — and a corresponding signed record of that decision.
Non-bypassability. The enforcement component shall be non-bypassable by privileged callers within the same trust domain. Structural isolation that an administrative path, elevated credential, or emergency override can circumvent is operationally no isolation at all. Any path that permits execution without a valid enforcement decision — regardless of the caller's privilege level — violates this requirement. This criterion shall be explicitly documented and independently testable.
Failure domain separation. The enforcement component shall not share a failure domain with the execution surface it governs. A failure, compromise, or misconfiguration of the execution surface shall not automatically grant execution authority for unevaluated actions. The default response to any enforcement component failure shall be deny or hold — never permit.
Fail-closed default. If the enforcement component is unreachable, the required system response is block. No configuration shall permit execution to proceed without a valid enforcement decision under any degraded or failure condition. The enforcement component shall not share infrastructure dependencies with the execution surface such that a single failure disables both.

Control 2: AU(EXT) — Unified Governance Decision Record
Selected in Moderate Baseline: No (proposed addition)
Applicable AI Lifecycle Phase(s): Model Deployment; Model Operation; Incident Response
Relevant Attack IDs: NISTAML.013, NISTAML.024, NISTAML.026, NISTAML.041
The organization shall maintain a unified, append-only audit log treating agent action approvals and denials as a single event class. Specifically:
Unified event class. Approvals and denials shall be recorded as the same event type, distinguished only by a decision outcome field. The log structure shall be architecturally incapable of selective population — a system that logs approvals to one stream and denials to a separate stream, or that can disable denial logging independently of approval logging, does not conform to this control.
Mandatory record fields. Every governance decision record — whether the outcome is approve, deny, hold, or escalate — shall bind the following at a single write timestamp: (a) the content-addressed hash of the policy snapshot applied at evaluation time, not a version label or version number; (b) the stable identifier of the specific condition or rule within that policy snapshot that produced the decision; (c) the requesting principal; (d) the decision outcome; (e) a precise timestamp. A record with a missing or null policy snapshot hash shall be treated as a structurally incomplete event, not a valid audit entry.
Temporal co-binding. The record shall co-sign four things at a single commit timestamp: policy artifact hash, live state snapshot hash, admissibility predicate result, and execution time. A gap between T1 (policy evaluated) and T2 (action committed) that is undetectable from the record alone is not a compliant audit trail. This co-binding is a structural requirement, not a recommended field.
Condition-level granularity. The condition identifier (condition_id) shall be a stable, content-addressed reference to the specific policy condition evaluated — not a high-level outcome category. Without condition-level granularity, probing detection can observe that a principal is generating denials but cannot distinguish which policy surface is being exercised. The detection signal for incremental boundary-testing lives in the condition_id field, not in the denial count alone.
Cryptographic integrity. Records shall be cryptographically signed and written to a store that the execution surface cannot modify or delete. Hash-chaining or equivalent append-only integrity protection is required.

Control 3: CM(EXT-1) — Degradation Mode Governance: Admission Gate
Selected in Moderate Baseline: No (proposed addition)
Applicable AI Lifecycle Phase(s): Model Operation; Incident Response
Relevant Attack IDs: NISTAML.013, NISTAML.031
The organization shall treat the enforcement boundary's behavior under degraded conditions as a policy-bound, versioned decision subject to the same change control discipline as primary enforcement policy. This control addresses the admission gate — the handling of new action proposals when the enforcement component is degraded or unavailable:
Degradation policy as a versioned artifact. The default behavior of the enforcement boundary under enforcement component unavailability shall be documented as a formal policy artifact, version-controlled, content-addressed, and subject to the same review and approval process as primary enforcement rules. A fail-open default established by a deployment configuration with no audit record constitutes an unversioned bypass path and does not conform to this requirement.
Admission gate behavior. Under any degraded condition, new agent action proposals shall be held or rejected. No configuration shall permit new actions to proceed to execution without a valid enforcement decision while the enforcement component is in a degraded state.
Degradation event records. Degradation mode activations shall be recorded with the same mandatory field structure as primary denial records, including the content-addressed hash of the degradation policy artifact active at activation time, the triggering condition, and a precise timestamp.
Out-of-band notification. Degradation mode activation shall trigger active notification to a control plane operating on a separate trust and authentication boundary from the enforcement component. Local-only audit records do not satisfy this requirement. Notifications shall be sequenced and signed so that suppressed notifications are detectable as sequence gaps.

Control 4: CM(EXT-2) — Degradation Mode Governance: In-Flight Re-evaluation
Selected in Moderate Baseline: No (proposed addition)
Applicable AI Lifecycle Phase(s): Model Operation; Incident Response
Relevant Attack IDs: NISTAML.022, NISTAML.031
This control addresses a failure mode distinct from admission gate behavior: actions that were validly authorized before a degradation event but have not yet completed execution when world state changes during the degradation window.
In-flight and admission are separate policy decisions. A degradation event that halts new admissions but permits already-admitted actions to complete silently can still violate the enforcement invariant if world state changed during the degradation window. These are two independent policy decisions with independent audit semantics and shall not be collapsed into a single control statement.
Re-evaluation trigger requirement. The organization shall define an explicit policy governing whether in-flight actions are permitted to complete, held for re-evaluation, or cancelled when a degradation event occurs and world state may have changed. This policy shall be documented as a versioned artifact subject to the same change control requirements as the admission gate policy in CM(EXT-1).
In-flight degradation records. For any in-flight action affected by a degradation event, the system shall generate a record identifying the action, the degradation trigger, the policy artifact governing the in-flight disposition decision, and the outcome — whether the action was permitted to complete, held, or cancelled.

Gap note for reviewers: Controls 3 and 4 together close the degradation case that a single CM control cannot address cleanly. The admission gate and the in-flight re-evaluation trigger have different threat models, different policy inputs, and different audit semantics. Collapsing them produces a control that addresses one failure mode while leaving the other undefined.
Happy to contribute a formal cross-reference table mapping all four controls to the layer and checkpoint model in the draft if useful for the next iteration.
Thanks, @KeystoneSmartQuotes

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 2, 2026

The four-control framing is the right structure - splitting temporal execution integrity into its own control prevents it from being absorbed into the authorization or audit controls, which is exactly where it gets lost in practice. A few observations on what would make this land in implementation:

The hardest part of Control 4 (TEI) is the evidence format. Binding "live state at commit time" requires a snapshot with a certified timestamp, not just a hash of the policy artifact. The snapshot must be provably concurrent with the execution event, or you're back to a weaker form of TOCTOU. This means the evidence artifact needs at minimum: state hash, execution timestamp (RFC 3161 or equivalent), and a binding to the specific transition being attempted - all three, not two.

The distinction between SA-17(EXT) (enforcement architecture) and the TEI control matters precisely here: architecture requirements are about what the system must be capable of doing, while TEI is about what must be demonstrated at runtime. Keeping those in separate controls prevents implementers from satisfying the architecture requirement on paper while shipping a system that never actually generates TEI evidence.

One question worth raising for the draft: does Control 4 need to address the case where admissibility re-evaluation itself fails (timeout, unavailable state source)? A strict reading of TEI would say execution must refuse - but that's a significant operational constraint that the control language should call out explicitly rather than leaving to interpretation.

@KeystoneSmartQuotes
Copy link
Copy Markdown

@desiorac — these observations sharpen the control language exactly where it needs it.

On the three-element evidence binding: agreed that two of three isn't sufficient. The state hash alone proves what conditions were evaluated. The certified timestamp alone proves when. But without binding both to the specific transition being attempted, you can't prove that this evaluation governed this commit. All three elements need to be co-signed as a single atomic artifact, not assembled post-hoc. The control language should require exactly that: a single evidence record binding state hash, certified execution timestamp (RFC 3161 or equivalent), and transition identifier, produced as an output of the commit, not an input to it. If it's an input, the seam reappears.

On the SA-17 vs. TEI separation: the distinction you named is the right one and it's load-bearing. Architecture requirements establish structural capability, what the system must be built to do. Runtime evidence requirements establish what must be demonstrated at the moment of execution. A system can satisfy SA-17(EXT) on paper, document the enforcement component, demonstrate failure domain separation, pass an architecture review, while never generating TEI evidence at runtime. Keeping them in separate controls makes that gap detectable. Collapsing them lets it hide.

On the unavailability case: yes, Control 4 needs to address this explicitly rather than leaving it to interpretation. A strict reading of the temporal execution integrity requirement leads to one answer: if admissibility re-evaluation cannot complete- timeout, unavailable state source, inability to produce a valid evidence artifact — execution must refuse. Any other default recreates the advisory-enforcement failure mode the control is designed to prevent. The control language should state this as a MUST NOT: the system must not permit execution to proceed if a valid TEI evidence artifact cannot be produced at the commit boundary. Degraded-conditions behavior needs its own explicit control entry. Which is exactly what CM(EXT-1) and CM(EXT-2) are trying to do, but TEI itself should state the default unambiguously: no artifact, no commit.

@KeystoneSmartQuotes

@narendrakumarnutalapati
Copy link
Copy Markdown
Author

This discussion is converging on something important, and it helps clarify scope.

The current draft is intentionally focused on defining the integrity layers:

– transmission integrity
– tool integrity
– authorization-at-execution integrity
– intent integrity

What the thread is now developing goes deeper into how enforcement actually holds at the execution (mutation) boundary.

The points raised around:

– admissibility as a gate at commit time (not a property)
– atomicity / TOCTOU and causal coupling of evaluation with commit
– mutation authority and non-bypassable enforcement
– co-binding of policy, state snapshot, timestamp, and transition
– distinctions between attestation integrity, evaluation completeness, and reconstruction
– NIST control mappings (SA-17 / AU / CM / IR extensions)

all refine the execution boundary itself rather than introducing additional top-level integrity layers.

To keep the model usable, it helps to separate:

Layers → what property is guaranteed
Execution boundary → how that guarantee is enforced at the point of mutation

At that boundary, the system must enforce (fail-closed):

– authorization binding (request_authorized = request_executed)
– admissibility at T_commit (re-derived against live state and time)

And may provide different evidence levels:

– attested (artifact integrity)
– replayable
– reconstructible (where feasible)

The enforcement-strength differences being discussed (e.g., strong / bounded / detectable-only) are especially relevant for cross-boundary and distributed cases where full atomicity is not always achievable.

Rather than expanding this PR further, I’ll treat these aspects — execution-boundary enforcement, admissibility semantics, and control mappings — as follow-up work so the current draft remains cohesive and reviewable.

This keeps the layer model stable while capturing the direction this discussion is heading.

@QueBallSharken
Copy link
Copy Markdown

What I think this thread has now made clear is that we are very close to a usable finish line, but only if we stop collapsing distinct governance problems back into one generic idea of “integrity.”

My read is that the remaining work is not to add more layers. It is to force the open cases into a small number of explicit boundary requirements and be honest about enforceability when those requirements cannot be met.

The decomposition I think now holds is:

  1. Authorization integrity — what was approved under what declared authority / policy / delegation basis
  2. Execution evidence — what actually ran and what can later be independently verified
  3. Mutation authority — which component actually controls whether the irreversible primitive may occur
  4. Boundary integrity — whether the admissibility predicate both still held and remained authoritative through the validation -> mutation boundary
  5. Session invalidation — whether revocation, prior actions, cumulative exposure, or sequence effects can void future mutation rights before the next side effect
  6. Enforceability class — whether the mutation path is honestly strong, bounded, or detectable-only

For me that is now the smallest complete frame that explains the thread without losing the structural distinctions we spent all this time uncovering.

The key thing I want to press is that the remaining gaps are not all the same kind of gap.

Some are questions of what was decided.
Some are questions of what can be proven afterward.
But the hard governance questions are specifically about whether the component that actually controls the irreversible side effect can still refuse under live state when the moment of mutation arrives.

That is why I keep insisting on making mutation authority explicit.

A system can now prove all of the following:

  • the request was authentic
  • the delegation chain was valid
  • the decision artifact was signed
  • the payload was bound
  • the execution was attested
  • the event was logged
  • the whole thing can be replayed later

and still fail governance if the side effect was able to cross the mutation boundary after the governing admissibility conditions had already changed.

So to me the remaining closure work is this:

  1. Close the admissibility scope

For each irreversible primitive, the draft should require an explicit declaration of the admissibility-relevant authority set.

Not “policy” in the abstract.
Not “trust” in the abstract.
A closed set of live conditions that actually determine whether this transition may still become real.

Depending on the mutation class, that may include:

  • policy state
  • delegation / authority state
  • revocation state
  • tool / capability constraints
  • resource state
  • temporal validity
  • exclusivity / concurrency constraints
  • override validity
  • cumulative session state
  • optionally a behavioral input if the deployment truly makes that load-bearing

If the admissibility scope is not explicit and closed, the architecture can look governed while only enforcing against a partial slice of the real state.

  1. Make mutation authority explicit as a first-class boundary role

The mutating component is not always the policy engine.
Not always the token issuer.
Not always the component that later emits the receipt.

The relevant role is the one that controls the irreversible primitive:

  • write
  • send
  • transfer
  • publish
  • queue irreversible downstream work
  • invoke an external side effect
  • commit a state transition

If that component is not explicitly named as mutation authority, then “authorization at execution” still risks collapsing into an upstream advisory model.

For me the draft should say this plainly:
the component that controls the state-changing primitive is the component that must be able to fail closed.

  1. Distinguish sequencing from atomicity

This thread has now exposed that “revalidate before mutation” is not the same thing as “govern mutation.”

If validation and mutation are separate operations that can be interleaved, the model is still vulnerable to stale-state execution even if the validation itself is correct.

So boundary integrity needs a real continuity requirement.
Implementations should have to show one of the following:

  • a non-interruptible validate -> mutate critical section
  • compare-and-swap / version-checked mutation
  • a single-use state-locked mutation token
  • or some equivalent primitive that makes stale authority unusable at the boundary

Without that, the draft is naming a desired property, not a falsifiable enforcement contract.

  1. Separate local mutation atomicity from cross-boundary mutation atomicity

This is where I think honesty matters most.

If the mutating boundary directly controls the primitive, strong governance may be possible.

If the final effect depends on an external opaque service or third-party API that does not expose a compatible admissibility hook, then the local system may only be able to:

  • strongly govern the outbound request,
  • bound staleness,
  • attest what it sent,
  • detect divergence later,
  • or drive rollback / dispute protocols afterward.

That is not the same thing as strongly governing the external mutation itself.

So I think the draft should require an explicit classification:

  • strong if mutation authority can inline-enforce live admissibility at the true mutation boundary
  • bounded if the system can hold some inputs constant, limit drift, or partially coordinate but not fully control the real effect boundary
  • detectable-only if the system can only explain, attest, or detect after the side effect path has proceeded

That single classification may do more to prevent overclaiming than any additional integrity label.

  1. Keep behavioral trust subordinate to admissibility, not as a new governance layer

I think this is another place where the thread could drift into adding concepts instead of tightening them.

Behavioral trust may matter.
Session drift may matter.
Competence drift may matter.
Relay behavior may matter.

But I do not think they should become a separate governance layer.

If they are load-bearing, they should enter only as declared inputs to the admissibility predicate for specific mutation classes, with:

  • a declared evidence source
  • a freshness bound
  • a threshold rule
  • an invalidation rule
  • and a clear fail mode

Otherwise we are back in vague “trust scoring” territory that sounds important but does not produce a boundary rule.

  1. Make session invalidation explicit

One thing this thread has clarified well is that admissibility is not purely per-action.

Even if a single action is locally valid, prior actions in the session may have changed the conditions for later mutation:

  • revocation may have landed
  • cumulative quota may have been exhausted
  • delegation may have narrowed
  • a prior mutation may have changed the state space
  • a sequence may be admissible action-by-action but invalid in composition

So “session invalidation” is not extra terminology for me.
It is the minimal name for the rule that prior events can void future mutation rights before the next effect occurs.

That seems especially important for multi-step, delegated, or long-running workflows.

  1. Require portable context carryover without pretending it solves governance by itself

For distributed systems, the authorization context often needs to travel.

I agree this likely means some portable artifact:

  • signed decision basis
  • policy / authority version anchor
  • payload or scope binding
  • freshness / validity window
  • per-hop verification semantics

But carrying context forward is not the same thing as governing mutation.
It only prevents loss of the original basis across hops.

The last hop still has to answer:

  • can I strongly enforce this here?
  • can I only partially bound it?
  • or can I only attest after the fact?

So context carryover should support boundary integrity, not replace it.

So if I try to state the finish line as tightly as I can now, it is this:

No irreversible mutation may occur except through an explicit mutation authority that revalidates a closed, still-governing admissibility predicate against authoritative live state under boundary continuity, and refuses otherwise.

And then the rest of the model becomes classificatory:

  • Authorization integrity tells us what was approved
  • Execution evidence tells us what ran
  • Mutation authority tells us who controls the irreversible primitive
  • Boundary integrity tells us whether stale admissibility can survive the validation -> mutation boundary
  • Session invalidation tells us whether earlier events can void later mutation rights
  • Enforceability class tells us how honest the architecture is about what it can really govern inline

That is why I think the thread should resist adding more layers now.

The remaining work is to make the current decomposition normative and testable.

For each mutation-capable path, I think the draft should require something like:

  • identify the irreversible primitive
  • identify the mutation authority
  • declare the admissibility scope
  • declare the continuity / anti-interleaving mechanism
  • declare the invalidation inputs
  • declare the enforceability class

If an implementation cannot answer those six things, then in my view it still has a governance gap even if it has excellent identity, signatures, tokens, receipts, attestations, and replay.

That feels like the cleanest way to close the thread without reopening it into a larger and fuzzier taxonomy.

-Stevil

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 3, 2026

The decomposition holds, and the enforceability question is where it gets honest.

The three properties have different enforcement profiles, and I think that asymmetry matters for the draft language:

  • Authorization integrity is gateable - you can refuse to issue the artifact if preconditions aren't met.
  • Execution integrity is attestable - you can produce cryptographic evidence of the exact path taken, independent of outcome.
  • Admissibility is often only detectable - in any distributed or async system, you cannot atomically lock world state at commit time without either exclusive access or a MVCC-style protocol. Most real systems can only record whether the live state satisfied the admissibility predicate at that moment, not prevent a race that changes state in the gap between check and commit.

That distinction matters for what the spec can actually require vs. what it can only recommend. A requirement to enforce admissibility is only satisfiable in a narrow class of systems. A requirement to bind and record the admissibility evaluation - state snapshot hash, evaluation timestamp, result - is satisfiable broadly and creates a post-hoc falsifiability surface. The audit record can then distinguish "admissibility was evaluated and held" from "admissibility was not evaluated" from "admissibility was evaluated against stale state."

So the draft language probably needs two distinct clauses: one for the systems where enforcement is possible (exclusive commit gates), and one for the majority where temporal binding with a recorded evaluation is the strongest available guarantee. Collapsing those into a single requirement would make the spec either unimplementable or trivially satisfiable depending on how you read it.

@QueBallSharken
Copy link
Copy Markdown

I think that is a fair refinement.

I do not want the draft to collapse inline admissibility enforcement and post-hoc admissibility evaluability into the same requirement.

For me that is exactly why the enforceability class matters.

If mutation authority can refuse before the irreversible step under a still-governing admissibility predicate, that is strong governance.

If the system cannot do that but can still bind the relevant state, timestamps, result, and boundary events tightly enough that admissibility can be falsified afterward, that is still useful — but it is a different class of control.

So I agree the draft likely needs to disclose those separately rather than treating them as one property.

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 3, 2026

The decomposition holds, and the enforceability asymmetry across those three categories is worth making explicit in the draft - because they have different ceilings.

Authorization integrity can be satisfied offline and before execution: bind the artifact cryptographically to a policy version, and that relationship is verifiable forever after. Execution integrity can be satisfied post-hoc: deterministic hashing of the actual request/response at execution time produces a retrospective proof. But temporal admissibility cannot be certified retrospectively. It requires synchronous evaluation against live state at commit time - and in any system with async agent execution, distributed state, or network partitions, that synchronous check either succeeds, fails, or is skipped. You cannot reconstruct it later.

This means the draft should probably distinguish two classes of boundary requirements by certification timing: those that support post-hoc proof (authorization + execution), and those that require contemporaneous evidence (admissibility). For the second class, the system can only record that the check was attempted, with which state snapshot, at which timestamp - not that the check succeeded in the strong sense. That's still meaningful as a refutable record of due diligence, but it's a weaker guarantee, and being explicit about that distinction would prevent the common failure of treating a stored admissibility check as a proven admissibility guarantee.

The practical implication for draft language: admissibility requirements should include a required attestation format (snapshot hash + evaluation timestamp + result + refusal semantics if conditions weren't met), not just a requirement to "re-evaluate at commit time" - because without specifying what that evidence looks like, implementers will conflate the attempt with the guarantee.

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 3, 2026

The four-element co-signing framing is the right shape, but there is an atomicity subtlety worth making explicit: what you need is not just that all four were evaluated at "the same time," but that the commit timestamp provides a monotonic lower bound that post-dates all four evaluations. If they are co-signed independently and bundled under a fresh timestamp afterward, an adversary can assemble valid components from different evaluation moments and still produce a structurally coherent but temporally invalid proof.

The tighter formalization: commit = sign(hash(policy_artifact_hash || state_snapshot_hash || admissibility_result || proposed_action_hash), T_commit) where T_commit is a certified timestamp applied to the concatenated hash, not to any element individually. The binding must happen before the timestamp, not alongside it.

One gap the draft language probably needs to address: the state snapshot has its own acquisition time, which is necessarily earlier than the commit timestamp. Even with a valid certified commit time, a sufficiently stale snapshot could still allow the TOCTOU failure mode you described earlier in the thread. The spec may want an explicit maximum allowed delta between state_snapshot_time and T_commit, or require that the snapshot itself carry a monotonic lower bound (e.g., a block height, a vector clock, or a certified timestamp of its own) so staleness is checkable from the proof alone without external coordination.

@QueBallSharken
Copy link
Copy Markdown

I think the scope line Narendra drew here is fair, and it also helps clarify what the next iteration actually needs to contain.

My read is:

  • the current PR is doing the layer-model work:

    • transmission integrity
    • tool integrity
    • authorization-at-execution integrity
    • intent integrity
  • the thread is now doing the boundary-governance work:

    • admissibility as a gate, not a property
    • mutation authority as a distinct boundary role
    • atomicity / anti-interleaving at the mutation boundary
    • temporal co-binding of policy, state, result, and execution time
    • degradation behavior as a governed configuration, not an operational afterthought
    • honest enforceability distinctions where strong inline control is not actually possible

That separation seems right to me.

What I would not want is for the follow-up to collapse back into generic “integrity” language, because the thread has already shown that several different questions live there and they do not have the same enforcement profile:

  • authorization integrity asks what was approved
  • execution evidence asks what actually ran
  • admissibility asks whether the transition was still allowed to become real under live state at commit time
  • mutation authority asks which component actually had the power to let the irreversible primitive occur

Those are related, but they are not interchangeable.

So if this PR stays focused on the layer/checkpoint model, I think the next iteration should explicitly take on the execution boundary as its own follow-up section and make a small number of things normative and testable.

For each mutation-capable path, I think the minimum useful declaration set is:

  • identify the irreversible primitive
  • identify the mutation authority
  • declare the admissibility scope
  • declare the continuity / anti-interleaving mechanism
  • declare the invalidation inputs
  • declare the enforceability class

That seems to be the smallest frame that incorporates the major refinements people have pushed from different directions in this thread:

  • gate vs property
  • local atomicity vs cross-boundary limitations
  • internal runtime contract vs external boundary artifact
  • action-scoped rather than vague session-scoped authorization
  • behavioral/contextual trust only where explicitly load-bearing
  • separation between inline enforcement and post-hoc falsifiability

I also think the enforceability asymmetry needs to be stated plainly in the follow-up rather than left implicit.

To me the honest split is:

  • strong: the mutation authority can fail closed inline under a still-governing admissibility predicate at the true mutation boundary
  • bounded: the system can hold some inputs constant, constrain drift, or partially coordinate, but not fully control the real effect boundary
  • detectable-only: the strongest available guarantee is tightly bound post-hoc falsifiability after the side-effect path has already proceeded

That is not just editorial cleanup. It is what prevents false equivalence between systems that can actually govern mutation and systems that can only attest or reconstruct after the fact.

So I’m aligned with keeping this PR reviewable, but I do think the thread has now made the follow-up target pretty clear:

No irreversible mutation may occur except through an explicit mutation authority that evaluates a closed, still-governing admissibility predicate against authoritative boundary state under a declared continuity mechanism, emits a verifiable boundary artifact, and refuses otherwise.

Everything else can then be classified relative to that line rather than implied by signatures, tokens, receipts, or replay alone.

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 3, 2026

The layer-model / boundary-governance split is a clean way to frame what the PR and the thread are each doing, and it clarifies why the two conversations kept running in parallel without fully resolving.

The part I'd push on: if admissibility is a gate rather than a property, then the artifact produced at that gate needs to capture the gate decision, not just the evidence that informed it. A property can be attested after the fact ("these conditions held"); a gate decision is only valid at the moment it was made, against the state that existed then. That changes what needs to be recorded - you need a timestamped, state-bound gate verdict, not just a log of which checks ran.

That also clarifies why mutation authority belongs as a distinct boundary role. The entity evaluating authorization and the entity committing the mutation are operating at different points in time against potentially different world state. Conflating those roles is exactly what creates the TOCTOU gap - authorization said "permitted" at T₀, mutation happened at T₁, and nothing re-validated the gate at T₁. Separating mutation authority as a role means you can require that role to hold its own gate-at-commit decision, independently of the earlier authorization chain.

Atomicity then becomes the enforcement mechanism that makes all of this coherent: the gate decision and the mutation have to be one indivisible operation, or the state snapshot the gate evaluated against is no longer guaranteed to match the state the mutation applies to. Without that, you can have a perfectly valid gate record and still commit against stale world state.

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 3, 2026

The state snapshot problem in Control 4 is the part I'd want tightened. Re-deriving admissibility against "live state" only works if the snapshot itself has provenance from outside the agent's trust boundary - producer identity, production timestamp, observation lineage. If the enforcement component controls or influences that snapshot, a privileged agent can satisfy the letter of TEI while feeding it crafted input, and the enforcement component has no basis to detect the substitution. The control language needs a sub-requirement there: the state input to the admissibility predicate must carry its own attestation, bound before the evaluation runs.

Separate point on structure: Control 1 is a prerequisite for Control 4, not a peer. If teams read these as four independent checkboxes, they'll implement the temporal binding while violating the architectural separation that makes it meaningful - an agent with write access to its own enforcement boundary can pass every TEI check and still own the property it's supposed to protect. One explicit sentence on that dependency would close that reading.

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 3, 2026

The co-signing requirement is the right frame. Post-hoc assembly of separately-produced evidence components is the attack surface: each element can be individually valid while the combination is incoherent - state from evaluation E1, timestamp from moment T2, transition from authorization A3, none of which were ever co-present. The atomic artifact constraint closes that gap by making substitution detectable.

One thing worth making explicit in the draft: the atomic co-signature needs to cover the transition identifier as a first-class element alongside state hash and timestamp. Without it, the same (state_hash, timestamp) tuple could plausibly cover multiple candidate transitions evaluated at the same boundary - the artifact doesn't prove this transition was the one that passed admissibility at that moment. Something like a canonical hash of (action_type, target_resource, initiating_agent_id, authorization_artifact_id) should be in the commitment.

This also has implications for the TSA binding @QueBallSharken raised: if the RFC 3161 timestamp is obtained before the state snapshot is taken, the ordering guarantee is wrong. You've timestamped the authorization evaluation, not the admissibility evaluation. The TSA request should be over the full composite (state_hash || transition_hash || policy_version_hash), issued at the execution boundary after admissibility is re-derived. That's where the "temporal" in Temporal Execution Integrity actually lives - in the ordering of the commit, not just the presence of a timestamp.

@KeystoneSmartQuotes
Copy link
Copy Markdown

The thread has now produced something more precise than a control checklist—it has produced a conceptual framework that should govern how the follow-up document is structured. Let me try to consolidate what I feel the thread has established.

On the two-class certification timing distinction (desiorac, comment 63)

This is the most important structural point in the thread and it has not been made explicit enough in the draft language. Authorization integrity and execution integrity support post-hoc proof—you can bind a cryptographic artifact to a policy version or hash a request/response retrospectively and the proof holds. Temporal admissibility is different in kind: it requires synchronous evaluation against live state at commit time and cannot be reconstructed after the fact. A stored admissibility check record is not a proven admissibility guarantee—it is a refutable record of due diligence.

The practical implication desiorac identified is correct: the draft needs a required attestation format for the admissibility class, not just a requirement to "re-evaluate at commit time." Without specifying what that evidence must look like, implementers will conflate the attempt with the guarantee. The minimum attestation format should include: state snapshot hash, evaluation timestamp, admissibility result, and refusal semantics where conditions were not met.

On atomicity and T_commit ordering (desiorac, comment 64)

The tighter formalization is right: commit = sign(hash(policy_artifact_hash || state_snapshot_hash || admissibility_result || proposed_action_hash), T_commit) where T_commit is applied to the concatenated hash, not to any element individually. The attack surface desiorac named—assembling individually valid components from different evaluation moments—is exactly what the co-signature requirement closes. Binding must happen before the timestamp, not alongside it.

The staleness gap needs an explicit requirement: either a maximum allowed delta between state_snapshot_time and T_commit, or a requirement that the snapshot itself carry a monotonic lower bound so staleness is checkable from the proof alone.

On the transition identifier (desiorac, comment 69)

The co-signature over four elements is necessary but not sufficient without a transition identifier. The same (state_hash, timestamp) tuple is ambiguous across multiple candidate transitions evaluated at the same boundary. The artifact must prove this transition passed admissibility at this moment. The canonical hash covering action_type, target_resource, initiating_agent_id, and authorization_artifact_id should be a first-class element in the commitment—not derivable from the other fields.

On TSA ordering (desiorac, comment 69, referencing QueBallSharken)

If the RFC 3161 timestamp is obtained before the state snapshot is acquired, the temporal binding is wrong—you have timestamped the authorization evaluation, not the admissibility evaluation. The TSA request must be over the full composite (state_hash || transition_hash || policy_version_hash), issued at the execution boundary after admissibility is re-derived. The "temporal" in temporal execution integrity lives in the ordering of the commit, not in the presence of a timestamp.

On gate decision vs gate evidence (desiorac, comment 66)

The distinction desiorac drew here should become normative language in the follow-up: the artifact at the gate must capture the gate decision, not merely the evidence that informed it. A property can be attested after the fact. A gate decision is only valid at the moment it was made, against the state that existed then. This distinction changes the minimum record content requirement.

On mutation authority as a distinct boundary role (desiorac, comment 66)

Separating mutation authority from the authorization chain closes the TOCTOU gap structurally. Authorization at T₀ and mutation at T₁ are different events against potentially different world state. The mutation authority must hold its own gate-at-commit decision independently of the earlier authorization chain. This role separation is what gives the atomicity requirement its security meaning—without it, atomicity is a property of a record, not a constraint on execution.

On the Control 1 → Control 4 dependency (desiorac, comment 67)

This must be stated explicitly in the document—one sentence. Control 1 (architectural separation of the enforcement component) is a structural prerequisite for Control 4 (temporal execution integrity), not a peer. An agent with write access to its own enforcement boundary can satisfy every TEI check while controlling the state inputs the enforcement component evaluates. The architectural separation is what gives the temporal binding its security value. Treating the controls as independent checkboxes produces a system that can pass every audit criterion while owning the property it is supposed to protect.

On the layer-model / boundary-governance split (QueBallSharken, comment 65)

The scope framing QueBallSharken proposed is the right structure for the follow-up document. The current PR establishes the layer model. The follow-up should take on the execution boundary as its own section with a small number of normative and testable requirements. The six-point minimum declaration set—irreversible primitive, mutation authority, admissibility scope, continuity mechanism, invalidation inputs, enforceability class—provides the right frame. The three-tier enforceability classification (strong / bounded / detectable-only) should be normative, not descriptive, so implementers are required to declare honestly what their architecture can and cannot guarantee.

@KeystoneSmartQuotes

@desiorac
Copy link
Copy Markdown

desiorac commented Apr 6, 2026

The 6-part frame reads as the right stopping point. One thing worth surfacing explicitly: enforceability class (#6) is not just a label on each control — it determines what evidence obligations are even coherent for that mutation path.

For a strong-enforcement boundary (kernel-mediated, non-bypassable gate), you can require atomic co-binding of policy + state snapshot + timestamp + transition at T_commit, and the NIST SA-17/AU extensions @KeystoneSmartQuotes mapped apply directly.

For a detectable-only boundary (e.g., third-party API where you cannot interpose a gate), the same co-binding requirement becomes aspirational. What you can actually enforce is post-hoc detection with bounded latency — and the evidence obligation shifts from "prove this was authorized at commit time" to "detect within T_detect that it was not." The AU and IR controls still apply, but with a fundamentally different verification model.

This maps cleanly onto @narendrakumarnutalapati's evidence levels (attested / replayable / reconstructible) — each level is the strongest evidence obligation that a given enforceability class can actually sustain. Making that mapping explicit in the draft would prevent implementers from claiming "attested" for a path that is structurally detectable-only.

The remaining editorial question is whether the draft should carry one table that cross-references all three dimensions (6-part frame × NIST controls × enforceability class) or keep them in separate sections with normative cross-references. A single table is more auditable but harder to maintain as the control catalog evolves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants