Skip to content

Define machine-verifiable approval-to-execution scope binding for SAFE evidence #13

Open

Description

@lumirosh

Spun out of #5 at the author's request, where the transport mapping was in scope but these semantics were not.

Problem

SAFE's Evidence Preservation list requires members to retain human approval and intervention events. Preserving the event is not the same as preserving what it authorized.

Two of the RFC's reportable conditions depend on that difference: a system acting on a third-party system without authorization, and a system continuing to probe after detection. Both require a reader to distinguish four outcomes that today would be reported identically:

  1. No valid authority existed.
  2. Valid authority existed and execution stayed inside it.
  3. Valid authority existed and execution left its scope.
  4. Evidence is insufficient to determine which of the above occurred.

These are different control failures with different remediation. A member can satisfy every item on the Evidence Preservation list and still leave a reader unable to tell them apart.

Why this is not an upstream transport question

otel-genai#368 (draft) adds gen_ai.agent.governance.ref as a deliberately opaque, producer-scoped reference, with the referenced record's format, schema, lifecycle and validation explicitly out of scope. That looks like the right decision for a transport convention.

It also means the pointer exists and its contents are undefined. This issue proposes requirements for what a SAFE-conformant record behind that reference should establish. It does not ask OTel to parse it, and it does not propose a new transport.

otel-genai#159 (gen_ai.agent.paused / .resumed, with pause.reason: human_input) is the natural carrier for the approval moment itself.

Proposed requirements

Requirements, not a schema. Vocabularies can start small.

R1. Both operands preserved. What was approved, and what actually executed, must both be retained in a form that survives export to another party.

R2. Structured, not prose. The approved action should be expressed against a structured action vocabulary, for example a tool-call schema, rather than free text. The approved resource should use a stable identifier, for example the workload identifiers already proposed in the #5 mapping, rather than a human-readable name.

R3. Recomputable verdict. Any conformance result must be recomputable by an independent party. A recorded verdict must reference the comparison method and its version, alongside the normalized inputs and the evidence references used. A verdict without a stated method is an assertion, not evidence, and inherits exactly the problem this proposal exists to solve. This constraint was raised by @meshailabs in #5 and is adopted here.

R4. Authority validity is a separate question. Whether authority was valid, time-bound and not self-extended is the subject of #1. This issue assumes that question is answered elsewhere, and addresses only whether execution remained inside the scope that authority granted.

R5. Insufficient evidence is a reportable state. Absence of a determination must be distinguishable from a negative determination.

Relationship to existing work

Prior art, with its limits stated

I maintain Open Decision Receipt, Apache-2.0, vendor-neutral: https://github.com/lumirosh/open-decision-receipt

Cited as prior art and as a worked example of the failure above, not as a solved standard and not for adoption. It records both operands, approval_scope on the authority block and actual_action on the execution block, and both are free-text strings. It therefore cannot mechanically compare them, and neither can anyone reading its output. R2 and R3 are what that implementation is missing.

Runnable lifecycle example: https://github.com/lumirosh/open-decision-receipt/tree/main/examples/end-to-end-artifact-bundle

Activity

  1. Rambi-2020 commented on Aug 18, 2026

    @Rambi-2020

    A related evidence requirement may be worth making explicit here: authority lineage, execution-time authority revalidation, and post-action authorization reconciliation.

    R4 appropriately separates authority validity from the question addressed by this issue: whether execution remained inside the scope granted.

    There appears to be an additional evidentiary gap between approval and execution.

    An action may have been validly approved and still no longer be authorized when the agent actually acts.

    For consequential agent actions, the evidence record should therefore establish not only that approval occurred, but that the supporting authority remained valid at the point of execution.

    Conceptually:

    source authority → delegation → human approval → execution-time authority revalidation → action → post-action reconciliation

    Immediately before consequential execution, the system should be able to establish that:

    • the approving human or organization still possesses the required authority;
    • the authorization has not expired, been revoked, superseded, transferred, or otherwise invalidated;
    • the authority lineage remains intact;
    • the scope originally approved still matches the action about to occur;
    • no material factual condition underlying the approval has changed;
    • no superseding instruction from equal or superior authority conflicts with the approval; and
    • the action actually queued for execution remains within the previously authorized parameters.

    If those conditions cannot be established, the prior approval should not automatically authorize execution. The action should return to the appropriate human authority for determination.

    This addresses a time-of-authorization versus time-of-action problem.

    A system may truthfully possess evidence that:

    “This action was authorized.”

    while being unable to establish:

    “This action is still authorized now.”

    Those are materially different propositions.

    This resembles the familiar time-of-check/time-of-use problem in computer systems, but applied to human and organizational authority.

    The post-action record should then reconcile the executed action against the authority that was valid at the actual execution point: Who had authority, where did it originate, what did it permit, was that authority still valid when execution occurred, who or what exercised it, and did the resulting action match it?

    This permits an incident review to distinguish at least:

    1. valid authority lineage / valid at execution / action within scope;
    2. valid lineage / valid at execution / action outside scope;
    3. authority valid at approval but no longer valid at execution;
    4. invalid or broken authority lineage;
    5. unauthorized substitution or usurpation of authority;
    6. required human authority bypassed or functionally abdicated; and
    7. insufficient evidence to establish execution-time authority validity.

    This concept comes from Silicon Sherlock, an independently developed probable-cause and AI-governance framework. I am offering the evidentiary control concept for consideration, not proposing adoption of any proprietary implementation.

  2. meshailabs commented on Aug 19, 2026

    @meshailabs

    The time-of-approval versus time-of-action gap is real, and worth a requirement. Two edits would keep it implementable.

    First, split the revalidation conditions by whether a producer can attest them. Expiry, revocation, and scope-match against the queued action are machine-verifiable at execution time, and records for them already exist: otel-genai#445 carries approval resolution as approved/refused/expired with expiry requiring a configured deadline, and a decision record emitted only when the evaluation is consulted before the action is the execution-time revalidation record by construction. "No material factual condition has changed" and "no superseding instruction conflicts" are not attestable by any producer. A conformance item no member can implement weakens the list around it.

    Second, the seven outcomes fold back into the four in the issue body: 3 through 6 are refinements of outcome 1, useful in an incident narrative, but the evidence record only needs to support the four-way distinction. Keeping the taxonomy minimal is what keeps requirement R4 testable.

  3. Rambi-2020 commented on Aug 19, 2026

    @Rambi-2020

    Agreed on both edits.

    For this issue, the conformance requirement should be limited to producer-attestable execution-time evidence: expiry or revocation status against declared authoritative sources, structured scope-match against the queued action, and a decision evaluation consulted before execution. The record should state what the producer actually evaluated and should not infer anything from silence.

    “No material factual condition has changed” and “no superseding instruction conflicts” cannot be universal producer attestations. A producer may record checks against declared inputs, but those conditions otherwise remain human or organizational reauthorization predicates outside the machine-conformance requirement. They are not eliminated; they belong at a different control layer.

    Agreed also that the four outcomes in the issue body should remain the testable evidence taxonomy. The seven-item list is better retained as incident-analysis subtypes—particularly refinements of “no valid authority existed”—rather than additional R4 outcomes.

    That keeps the requirement minimal and implementable while preserving the approval-to-action distinction.

  4. elang2 commented on Aug 20, 2026

    @elang2

    The gap between "we recorded the decision" and "a verifier can confirm what that decision actually evaluated" is the one I keep hitting too. Open Decision Receipt surfaces the same tension. Both operands are preserved, but the comparison between them isn't mechanically reproducible from the record alone.

    I've been working on a mechanism that addresses the verification half of R3. I'm calling it decisionContextDigest. SHA-256 of a canonicalized input frame captured at policy evaluation time, covering the resolved principal, tool name, namespace, upstream server, matched rule (or null), and the effect. Ordered key-value pairs, JSON-serialized, hashed. A verifier holding the expected inputs recomputes independently and confirms a match.

    The point isn't that some policy ran. It's what data the policy was looking at when it decided. Given trust in the intermediary that captured the frame, the digest lets you confirm the evaluation inputs without re-running the policy logic itself. That's not the full R3 (you'd still need the policy code for a complete replay), but it closes the part where today you have no way to know if the inputs were genuine or caller-supplied.

    This also touches R2, incidentally. The canonical form is a structured vocabulary, not prose. Tool identity uses the namespace/name/upstream triple from the protocol layer, and the matched rule is the serialized policy object. So the operands are mechanically comparable by construction.

    For backward compat: the digest field is conditionally included in canonicalization only when present. Old records verify unchanged.

    CycloneDX/specification#1016 reached the same conclusion from the supply-chain side, and E006 (https://github.com/Silentpartnercoding/agent-trust-benchmark/blob/main/docs/E006.md) demonstrated experimentally that a policy can pass every correctness check while evaluating attacker-supplied data. Same shape showing up in three independent efforts, for what that's worth.

    Working implementation: https://github.com/elang2/mcp-audit-gateway (PR #1 adds the digest).

  5. lumirosh commented on Aug 20, 2026

    @lumirosh
    Author

    Agreed on the narrowing proposed by @meshailabs and accepted by @Rambi-2020.

    For this issue, execution-time conformance should be limited to producer-attestable evidence: expiry or revocation status against declared authoritative sources, structured comparison of the queued action against the approved scope, and evidence that the relevant decision evaluation was consulted before execution.

    The producer should record what it actually evaluated and should not infer truth from missing evidence. “No material factual condition has changed” and “no superseding instruction conflicts” remain important, but they are human or organizational reauthorization questions rather than universal producer attestations.

    The four outcomes in the issue body remain the testable taxonomy. The seven outcomes are useful incident-analysis subtypes, not additional conformance states.

    An update to the ODR prior-art note is also warranted.

    At v0.2.0-rc.3, ODR now carries structured request.canonical_action and execution.canonical_action objects and binds them through a SHA-256 action_hash. The approval carries that commitment, and sealing is refused when the execution action hash differs.

    That is progress, but it does not close this issue. approval_scope and actual_action remain free-text fields, and the implementation performs exact object equality rather than semantic containment. It does not yet record a named comparison method and version or a separate match | mismatch | insufficient_evidence determination. In other words, ODR now demonstrates action integrity across the lifecycle, but not the complete R2, R3, and R5 requirements proposed here.

    @elang2, I think decisionContextDigest is a useful contribution to the integrity precondition for R3. It commits the record to the evaluation frame captured by the intermediary, addressing the gap between “a policy was consulted” and “this is the context the policy evaluated.”

    I would keep it adjacent to R3 rather than treat it as satisfying R3.

    There are three distinct questions:

    1. Integrity: is this the same recorded object or evaluation frame?
    2. Containment: did the executed action remain inside the approved scope?
    3. Recomputation: can an independent party derive the recorded determination from normalized inputs and a stated method?

    A digest addresses the first. It does not perform semantic containment, and without the evaluation method it does not independently reproduce the verdict.

    For example, “transfer up to 50,000” and “transfer 30,000” should produce different action commitments, while the second action may still be contained within the first authorization. Hash equality cannot decide that relationship.

    I would therefore keep R3 implementation-neutral:

    A recomputable verdict must reference the complete normalized inputs consumed by the comparison or evaluation, the authoritative references or provenance available for those inputs, the comparison or evaluation method and its version, and the resulting determination, in a form that allows an independent party to recompute and compare that determination.

    decisionContextDigest can implement the input-integrity part of that requirement.

    Two interoperability details should remain explicit:

    • Evaluation inputs must be separable from the resulting verdict. The current digest includes effect, which provides tamper-evidence over the pair but does not by itself make the verdict derivable.
    • Any digest intended for cross-implementation recomputation needs a named and versioned canonicalization contract. This applies to ODR’s current canonical action hashing as well.

    The requirement should stay above any single implementation, including mine.

  6. CSOAI-ORG commented on Sep 20, 2026

    @CSOAI-ORG

    Acceptance examples for R1/R3/R5: distinguish a released call from its external effect

    Building on this issue's existing four-way taxonomy, CSOAI suggests a small additional evidence distinction: an in-scope, authorized request can have an unconfirmed external outcome. This does not require another authority model or another conformance verdict.

    The authorization decision, scope comparison, invocation attempt, provider acknowledgement, and evidence of the external effect answer different questions. A timeout is not proof that an action did not happen; a successful acknowledgement is not always proof of delivery. Scope conformance can be known while the outcome remains unknown.

    Suggested supplementary record semantics:

    • Bind each attempt and each effect observation to the same stable logical action_id. Keep attempt identifiers distinct; a retry is not automatically a second completed action.
    • Record external_effect_status independently of the scope determination. Suggested illustrative values: confirmed, unconfirmed, conflicting, and not_applicable. They are not official SAFE vocabulary.
    • Name the effect being checked, the evidence source, method/version and observation time. An acknowledgement can confirm receipt by a service while leaving downstream delivery unconfirmed. Do not promote one claim into the other.
    • Preserve event time separately from collector receipt time and disclose uncertainty. Later evidence should append a superseding determination, not silently rewrite what was known earlier.
    • Keep references to credential scope and validity, not reusable tokens, private keys or session cookies. Access-controlled evidence can remain unavailable to a particular reviewer without becoming a successful verification.

    Proposed synthetic acceptance cases, not reported execution results:

    Fixture Expected interpretation
    Valid authorization, matching attempted request, no effect evidence Scope may be consistent; external effect remains unconfirmed. Do not label delivery completed.
    Provider acknowledges queueing but no destination receipt exists Queue acceptance is confirmed; destination delivery is not.
    Timeout followed by a matching destination receipt Preserve the timeout; append confirmed effect with its evidence and time. Do not infer that timeout meant non-execution.
    Retried request produces two observations of the same provider operation ID Preserve both observations; do not count two completed effects solely from two receipts.
    A valid signature accompanies an inaccessible effect-evidence reference Record signature integrity separately; the external-effect claim remains unverified for that reviewer.
    Two observations conflict about the same effect Retain both and report conflict, not whichever looks more favourable.

    One deliberately minimal example, not an official schema or an incident record:

    {
      "example_only": true,
      "action_id": "synthetic:notification-01",
      "attempt_id": "synthetic:attempt-01",
      "scope_determination": "match",
      "scope_method": "synthetic:exact-action-comparison/v1",
      "acknowledged_effect": "accepted_for_processing",
      "external_effect_under_review": "delivered_to_destination",
      "external_effect_status": "unconfirmed",
      "external_effect_evidence_ref": null,
      "unresolved_questions": ["Was the notification delivered?"]
    }

    This complements #29's delegation lineage and #34's coverage disclosure. It also makes our discriminating-control concern in #32 concrete: consumers should be tested against an authorized-but-unconfirmed case, not only completed happy-path examples.

    Would this distinction fit best as linked evidence-profile guidance for R1/R3/R5? The intent is to preserve your existing four outcomes for authority/scope while preventing a separate unsupported completion claim.

    Nicholas Templeman, CSOAI

    Methodological feedback with synthetic examples only; no private incident data, membership claim or certification claim. No endorsement or adoption is implied.

  7. dleighsystem commented on Oct 2, 2026

    @dleighsystem

    Adding one data point to R1, R3 and R5, and to the execution-time
    revalidation narrowing agreed above, because we have a running instance of
    this taxonomy rather than a schema for it.

    Setup. An agent in an NVIDIA OpenShell 0.1.2 sandbox makes MCP tool calls
    through OpenShell's supervisor-middleware hook. The middleware is a small
    gateway (ours; the record format and checker are what we would contribute,
    the gateway itself is proprietary) that, before OpenShell injects
    credentials, signs four kinds of record into a hash-chained ledger: the
    scope it will judge against (allowed tenant and resource, declared by a
    principal before the run, never derived from the agent's history), the
    grant (the approved arguments of a single-use human approval, consumed
    atomically at this call), the intent (a hash over the executed arguments)
    and the decision (a digest of the canonical input frame at evaluation
    time, close to the decisionContextDigest described above). Denials are
    signed with the same scope they were judged against.

    Independent verdict. A separate checker, holding only the export and the
    producer's Ed25519 public key, recomputes the chain, verifies the signed head
    over exactly those records, and
    evaluates two policies per call: matching unexpired approval, and allowed
    tenant/resource. Each predicate is true, false or unknown; one false is a
    violation, all true is no violation, anything else is INSUFFICIENT_EVIDENCE
    with the missing fields named. The checker writes its own source hashes and
    rule version next to every verdict, so a third party recomputes rather than
    trusts (R3).

    Result on a real run, four calls, forty records, no out-of-band
    declarations:

    Call Approval policy Tenant policy
    unapproved, own tenant violation no violation
    unapproved, other tenant violation violation
    approved no violation no violation
    tool OpenShell's own rule forbids never reached the middleware

    The four outcomes in the issue body fall out directly: outcome 1 is a false
    approval predicate, 2 is all-true, 3 is a true approval with a false scope
    predicate, 4 is INSUFFICIENT_EVIDENCE. We hit outcome 4 for real in an
    earlier run: the policy's tool schema did not pin a single resource, so the
    tenant predicate was unknown for a same-tenant denial. It resolved only after
    the operator declared the resource and the producer signed that declaration
    into the scope record, which is the point @Habirua makes on #47.

    The same records on a production gateway. The format is not demo-only.
    On 1 October a model-driven agent ran six cases through a zero-traffic
    revision of our production gateway: approved, missing, expired and forged
    approvals, a wrong tenant, and an injected target. Every decision, including
    the three that dispatched nothing, was signed into the ledger before any
    dispatch; the two authorized calls produced two receipts; the checker
    resolved 12 of 12 findings from signed records with no declared bindings.
    Since 2 October production exports carry the Ed25519 head; a real 29-record
    export verified with the public key alone, and a copy with one record altered
    was rejected.

    Two correlation lessons from those runs bear on #41's point about stable
    event identity. The same call attempted twice, once denied and once approved,
    produced two decision records with one digest; the producer now writes the
    decision record on the call's own action. Three byte-identical rule-generated
    non-call decisions did the same across three actions; the controller now pins
    the record by the entry hash the producer returned when it signed. Both are
    cases where "what was decided" is not enough to identify "which decision".

    Limitation we should name ourselves. The export head is a producer
    signature over a chain prefix (first link, last hash, record count), not an
    inclusion proof: there is no public transparency log behind it, which is
    where #37 goes further and where we would follow the thread. Our production
    ledger is additionally anchored to external storage per record; the demo
    exports are not. Per-record HMAC signatures remain for the tenant.

    If useful, we can contribute the run's export with its signed head, the
    producer's public key, and the checker's expected outputs as a conformance
    vector in whatever shape #39's harness settles on. Nothing secret is needed
    to reproduce the verdicts.

  8. Gary-Gayle commented on Oct 7, 2026

    @Gary-Gayle

    @dleighsystem Yes, that bundle would be useful. The repeated-call example is particularly relevant to #39: matching decision content does not establish which action attempt the record belongs to.

    Could you link a shareable export, signed head and public key, together with the checker revision, run command and separately recorded expected outputs? The denied-then-approved pair would make a focused starting case.

    We could then map the records to #39’s lifecycle bindings and identify which properties your checker actually evaluates. The current #39 harness checks structure and fixture consistency; your checker’s cryptographic and policy results would remain separately identified.

    That gives us a concrete interoperability exercise using the record format and checker you’ve offered, without requiring disclosure of the proprietary gateway.

  9. CSOAI-ORG commented on Oct 7, 2026

    @CSOAI-ORG

    7 October implementation update — scoped approval → invocation → effect

    Offering this as reference implementation evidence, not as a proposal that SAFE adopt a CSOAI schema.

    We have now split out the portable record that our earlier comment was missing: CSOAI source PR CSOAI-ORG/councilof-ai#2911 adds a vendor-neutral HITL authority-to-effect profile. It binds the exact request/resource/proposal digest; an explicit human or authorized-principal decision, authority epoch, scope digest and expiry; the invocation state/executor/digest; the separately observed effect/digest; and a separately identified verification method/evidence set.

    The negative controls reject DENY/REVOKE with EXECUTED, an observed effect without an effect digest, and a completed verification without evidence. Local schema acceptance is 7/7.

    The important boundary for this issue is that the profile does not require GSPC or any particular engine. GSPC may consume the record later as measurement/claim-maintenance evidence; OpenShell may be an executor; neither grants the approval. The record therefore keeps approval != invocation != effect != verification.

    This also gives a concrete place for the execution-time revalidation discussion above: the decision has an authority epoch, scoped digest and expiry that can be rechecked immediately before execution. A digest establishes integrity of the evaluated frame; semantic scope containment and independent recomputation still remain separate questions where the comparison method is not present.

    Status: source PR / candidate profile only; not SAFE adoption, vendor endorsement, or a deployed Alliance component.

  10. CSOAI-ORG commented on Oct 7, 2026

    @CSOAI-ORG

    CSOAI implementation note — 7 October 2026

    Separately from the export/checker request above, we have now put the approval-to-effect binding into a source-only candidate:

    CSOAI-ORG/councilof-ai#2911

    The candidate keeps proposal, approval or denial, invocation, observed external effect, independent verification and maintained claim as separate states. It is runtime-neutral: GSPC is optional as verifier/claim-maintenance consumer, OpenShell is optional as executor, and measurement never grants execution authority.

    Current acceptance at the candidate head: PASS 10/10 composition controls. The negative controls reject inconsistent authority/effect combinations and verified outcomes that have no retained evidence; a denied/rejected path validates separately.

    This is implementation evidence for the R1/R3/R5 shape, not a proposal that SAFE adopt the CSOAI schema or any named engine. The source PR is not production-deployment evidence and does not claim Alliance or vendor endorsement.

  11. meshailabs commented on Oct 10, 2026

    @meshailabs

    Small update to my earlier comment: open-telemetry/semantic-conventions-genai#445 no longer carries approval resolution. pause.resolution and expired were dropped in review since no instrumentation produces them yet, so expiry and revocation evidence has to come from the SAFE record itself. Also, open-telemetry/semantic-conventions-genai#368 now adds gen_ai.external_ref rather than gen_ai.agent.governance.ref.

  12. meshailabs commented on Oct 17, 2026

    @meshailabs

    Quick follow-up: open-telemetry/semantic-conventions-genai#368 has since been closed. Maintainers want refs to point at specific things that are also recorded as their own attributes, not arbitrary records (see open-telemetry/semantic-conventions#4102). So for now there is no OTel attribute that points at the SAFE record.

  13. CSOAI-ORG commented on Oct 29, 2026

    @CSOAI-ORG

    The measurement-capsule profile we posted on 27 October describes the evidence type this issue is asking for: a receipt-shaped record that carries the check identifier and version, the configuration digest, the expected and observed outcome, and an evidence reference — and, equally, what to record when a check could not be run.

    The part that bears on the question is that the scope of an action and the evidence that the action was in scope are recorded separately, so a reader can tell an authorisation that was granted from an authorisation that was shown to have applied.

    It is a profile, not a proposal: it names no requirement for SAFE and asks for no text to change. We are pointing at it because it already describes the evidence type, and a reader who wants to specify that type in SAFE should not have to invent it from scratch.

    CSOAI Ltd is an Open Secure AI Alliance General Member and runs Council of AI (councilof.ai), an AI measurement service with free and paid tools. We publish measurements; we do not grade them.

  14. SiCar10mw commented on Oct 30, 2026

    @SiCar10mw

    From #3 (design-time control lineage: design_coverage / design_references). Related, different layer — flagging, not merging.

    R1's "approved action" shouldn't stop at the point-in-time approval event. For agents whose authorization actually traces to a spec-time decision, the approved-action record needs to be able to point back to the design-time artifact that authorized the behavior class — otherwise R3's "recomputable verdict" has nothing stable to recompute against once the approver is reasoning from a spec that predates the execution by months.

    Keep #13 and #3 separate, same split you made with #43: this is approval→execution binding, #3 is pre-ship specification/acceptance. But the two reference chains need to compose, not duplicate fields.

  15. pavancharak commented on Nov 5, 2026

    @pavancharak

    We implement part of the approval-to-execution binding this issue describes. Here is where it stands against R1–R5, based on the code.

    What the code does

    Every policy is validated when it loads. A rule that approves an action must require a signed human approval, whether the action is a read or a write.
    A signed approval must come from a trusted issuer, carry a valid Ed25519 signature, and be unexpired and unrevoked. Trusted issuers are a code list plus approvers added through maker checker. Revocation takes effect on the next request. The approval is bound to the action, the resource, and, where declared, a value taken from the Intent rather than from the caller’s declared facts. Each approval is used once.
    The release is performed by ExecutionGateway. It re-checks the approval at release without consuming it. This runs when the authorization carries a signals hash, which the runtime always sets, and when the signal verifier is bound, which production does.
    If no signal verifier is configured, the runtime refuses approve decisions instead of trusting the approval.
    Declared signals must have their declared types, or the request is refused before any rule runs.
    Per-agent authority grants are checked at release. A grant that is revoked, replaced, or expired refuses execution, and so does a deployment with no grant registry.
    Trust records can be verified offline against keys pinned in a trust file, with no network calls. Verification cannot show that a key belongs to Parmana.

    Against R1–R5

    R1 (both operands): the gateway checks the release against the signed approval, not only against the request.
    R2 (structured): approvals reference structured action and resource identifiers, and the value is a number taken from the Intent.
    R3 (recomputable verdict): the policy decision records the matched rule and the full evaluation trace, but not a comparison method or version next to the verdict. That is a gap.
    R4: agree that authority validity belongs in #1. The expiry, revocation, and single-use checks above are the producer-side part.
    R5 (insufficient evidence): the policy has only APPROVE and REJECT. A missing signal makes its condition false, so missing evidence and a real refusal produce the same REJECT outcome, with different reasons. We agree R5 needs a distinct state. Authorizations signed before the release-time check existed carry no signals hash, so the gateway skips the signal and approval re-checks for them at release, and a skipped check counts as a pass. We would close that gap.

    Refusals

    A refusal is final, and nothing is approved automatically. If an operator has configured an approval webhook or email, the approver is notified when an approval would cure the refusal. Notification is best effort.

    We agree that integrity and containment are separate questions. A digest proves the first, not the second.

  16. lumirosh commented on Nov 7, 2026

    @lumirosh
    Author

    Thank you, Pavan. This is a useful implementation-level assessment, particularly the explicit R3 and R5 gaps.

    I would separate the release decision from the evidentiary determination. A runtime can refuse execution while recording insufficient evidence, rather than treating missing evidence as an established scope violation. R5 need not require a third enforcement decision.

    The legacy authorization path is worth isolating: a required revalidation check that did not run should remain distinguishable from one that passed.

    Could you share a minimal reproducible fixture for an authorization without signals_hash, with the implementation revision, run command and expected outputs showing both the release outcome and which checks ran?

    That would give this thread a concrete negative case without assuming your reported behavior has been independently reproduced. For R3, the comparison method/version and normalized inputs should remain available alongside the determination.

  17. pavancharak commented on Nov 7, 2026

    @pavancharak

    A case for the authorization without a signal hash, plus a check-level record shape for R3 and R5. It can be checked against any implementation without running anything.

    Case

    • Variant A (no verifier): Authorization has no signalsHash. The case assumes the request signals have drifted from decision-time state. Without a hash, the implementation cannot detect drift. No verifier is configured. verify returns valid: true. Release proceeds (read from code, not separately tested). The signal-freshness field is omitted from the result.
    • Variant B (verifier configured): Authorization has no signalsHash. The same drift premise applies. A verifier is configured but is not consulted, because the missing hash refuses first. verify returns valid: false. Release is refused. The signal-freshness field is false. The failure message names it (read from code; no test asserts the message text).

    As JSON:

    {
      "case": "authorization_without_signal_hash",
      "authorization": { "signed": true, "signalsHash": null },
      "request": { "signals": { "declared_signal_name": "drifted_value" } },
      "variants": {
        "A_no_verifier": {
          "verifier_configured": false,
          "expected": { "valid": true, "release": "proceeds", "signalsStillCurrent": "absent" }
        },
        "B_verifier_configured": {
          "verifier_configured": true,
          "verifier_result": "not_consulted",
          "expected": { "valid": false, "release": "refused", "signalsStillCurrent": false }
        }
      }
    }

    In variant A, the signal check leaves no trace in the verification result. A failure message lists only checks that are false, so a reader cannot tell "check did not run" from "check passed." The stored execution result does not carry the check values, as far as the part of its interface I read. This is the R5 gap.

    Proposed check-level record (a shape to discuss, not a schema; none of these fields exist in the current code)

    {
      "check": "signal_freshness",
      "status": "passed | failed | not_run",
      "method": "exact_hash_compare + verifier",
      "method_version": "1",
      "inputs_ref": "normalized_inputs_ref",
      "determination_separate_from_release": true
    }

    The release decision and the evidentiary determination would be kept separate, so a refusal can still carry an insufficient-evidence determination. method and method_version address R3.

    These outcomes come from one implementation's unit tests. They describe that implementation's behavior, not a reference result.

    Generated by Claude Code

  18. lumirosh commented on Nov 7, 2026

    @lumirosh
    Author

    Thanks, Pavan. The A/B split makes the distinction clearer. In B, the missing decision-time hash prevents a freshness determination; the refusal does not establish that drift was detected.

    Could you link the implementation revision and relevant tests/run command, including whether A reaches ExecutionGateway through the supported runtime path? Your earlier note says the runtime refuses approvals without a verifier.

    I’d keep the code-read release prediction separate from an exercised release result. That would make this a reproducible implementation example without treating it as a normative SAFE result.

  19. lumirosh commented on Nov 7, 2026

    @lumirosh
    Author

    @SiCar10mw, agreed on keeping #3 and #13 separate while making their reference chains composable. Where approval relies on a design-time decision, the record should identify the artifact/version and its relationship to the approved scope.

    That reference does not itself establish current authority or scope conformance. R3 still needs the inputs and method used for the determination. I’d prefer linked references over duplicating #3’s design-context fields here.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions