Network Working Group S. Gilda Internet-Draft 27 October 2026 Intended status: Standards Track Expires: 30 April 2027 An Audit Record Format for AI Agent Authorization Decisions draft-gilda-audit-agent-audit-record-01 Abstract This document defines a record format for AI agent authorization decisions and the effects that followed them. The format is one in- toto predicate type, signed inside a DSSE envelope. A record carries the decision and the observed effect with a derived agreement between them, whether the decision point could evaluate the request and how fresh each input it relied on was, and a canonicalization contract under which a party that trusts neither the agent nor its operator recomputes the record's consistency from its bytes. The document also defines what a party that retains a record keeps beside it, so that the record can later be dated from anchors that party does not control. The format carries the seven minimum audit fields of the WIMSE AI Identity Management System framework, and it is offered as a data model for the audit records the proposed AUDIT working group would specify. It defines no policy. About This Document This note is to be removed before publishing as an RFC. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-gilda-audit-agent-audit- record/. Discussion of this document takes place on the AUDIT Birds of a Feather mailing list (mailto:audit@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/audit/. Subscribe at https://www.ietf.org/mailman/listinfo/audit/. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Gilda Expires 30 April 2027 [Page 1] Internet-Draft Agent Audit Record October 2026 Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 30 April 2027. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 5 3. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 5 4. Audit Record Specification . . . . . . . . . . . . . . . . . 6 4.1. Canonical form . . . . . . . . . . . . . . . . . . . . . 7 4.1.1. JSON profile . . . . . . . . . . . . . . . . . . . . 7 4.1.2. Duplicate members and nesting depth . . . . . . . . . 7 4.2. Subject convention . . . . . . . . . . . . . . . . . . . 7 4.3. Timestamps and correlation . . . . . . . . . . . . . . . 8 4.4. Tamper-evidence . . . . . . . . . . . . . . . . . . . . . 8 4.5. Mapping to the seven minimum fields . . . . . . . . . . . 9 4.6. Verifying a record . . . . . . . . . . . . . . . . . . . 10 4.7. Retained records . . . . . . . . . . . . . . . . . . . . 12 4.7.1. The dating check . . . . . . . . . . . . . . . . . . 14 4.7.2. Anchor validation rules . . . . . . . . . . . . . . . 15 5. Predicate members . . . . . . . . . . . . . . . . . . . . . . 16 5.1. Record identity and hash algorithm . . . . . . . . . . . 19 5.2. Identity, delegation and resource . . . . . . . . . . . . 19 5.3. Decision, effect and agreement . . . . . . . . . . . . . 21 5.4. Evaluation . . . . . . . . . . . . . . . . . . . . . . . 23 5.5. Oversight . . . . . . . . . . . . . . . . . . . . . . . . 26 5.6. Correlation, posture and remediation . . . . . . . . . . 27 5.7. Observation and tier . . . . . . . . . . . . . . . . . . 28 5.8. A worked reading of the example . . . . . . . . . . . . . 29 5.9. Consumption under a cumulative limit . . . . . . . . . . 30 Gilda Expires 30 April 2027 [Page 2] Internet-Draft Agent Audit Record October 2026 5.10. Sequence . . . . . . . . . . . . . . . . . . . . . . . . 33 6. Security Considerations . . . . . . . . . . . . . . . . . . . 33 6.1. The vantage claim is not self-proving . . . . . . . . . . 34 6.2. A producer that observes only itself . . . . . . . . . . 34 6.3. Withheld rows . . . . . . . . . . . . . . . . . . . . . . 34 6.4. Well-formed disagreement . . . . . . . . . . . . . . . . 35 6.5. A decision that was not evaluated . . . . . . . . . . . . 35 6.6. Revocation without a bound . . . . . . . . . . . . . . . 36 6.7. Relationship to other tamper-evidence mechanisms . . . . 36 6.8. Two implementations that both differ from the canonical form . . . . . . . . . . . . . . . . . . . . . . . . . . 36 6.9. Receipt time and late anchoring . . . . . . . . . . . . . 36 7. Privacy Considerations . . . . . . . . . . . . . . . . . . . 37 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 37 9. Conformance . . . . . . . . . . . . . . . . . . . . . . . . . 38 10. Implementation Status . . . . . . . . . . . . . . . . . . . . 39 11. Normative References . . . . . . . . . . . . . . . . . . . . 39 12. Informative References . . . . . . . . . . . . . . . . . . . 40 Appendix A. Design rationale . . . . . . . . . . . . . . . . . . 42 A.1. The canonicalization contract . . . . . . . . . . . . . . 42 A.2. The decision and the observed effect . . . . . . . . . . 43 A.3. Why the tier carries five clauses . . . . . . . . . . . . 44 Appendix B. Conformance vectors . . . . . . . . . . . . . . . . 44 Appendix C. Mapping to the AUDIT problem statement . . . . . . . 57 Document History . . . . . . . . . . . . . . . . . . . . . . . . 60 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 65 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 66 1. Introduction This document defines one record format for an agent's authorization decisions and their effects, and it defines nothing else. It specifies no policy model, no compliance criteria and no retention period, and it does not extend or amend [AIMS]. Two bodies of text ask for such a format. Section 11 of [AIMS] requires audit records for agent authorization decisions and leaves their form open. The proposed charter of the AUDIT working group [AUDIT-CHARTER] asks for data models that represent "interaction records, references to the identities of participating entities, delegation context, authorization state over time, or action provenance", and states that "audit information must be verifiable by a party that trusts neither the agent nor its operator". Appendix C maps each problem the AUDIT BoF request [AUDIT-BOFREQ] and that charter name to the section of this document that addresses it, and names the ones this document leaves to other work. Gilda Expires 30 April 2027 [Page 3] Internet-Draft Agent Audit Record October 2026 This document replaces draft-gilda-wimse-agent-audit-record-02. Sections 1 to 8 and Appendices A and B keep the numbers they had there, so a reference to one of those sections of that revision resolves to the same section here. The goals are: * to make an audit record from one deployment comparable with one from another; * to make "tamper-evident" a property a verifier can test on the bytes it holds; * to carry the authorization decision and the observed effect in one signed record, so a disagreement between them is detectable; * to give the seven minimum fields of Section 11 of [AIMS] one member each. Policy belongs to a deployment, and a record format belongs to everyone who has to read the record. Two implementations that each satisfy Section 11 in their own format produce audit trails that cannot be compared, correlated across a service boundary, or checked by a party that trusts neither producer. Section 11 asks for all three. Comparable has a narrow meaning here. Two records are comparable when a third party holding both can decide, from the bytes alone, whether they describe the same request, whether their decisions agree, and whether either was enforced. The consequence is concrete: two deployments that each hash a request differently cannot join their records on a request digest, so a delegation that crossed between them is reconstructable in neither log. Section 11 of [AIMS] is normative about the existence of agent audit records and silent about their form. It requires that "deployments MUST produce durable audit logs covering authorization decisions and subsequent remediations", that "Audit records MUST be tamper-evident and retained according to the security policy of the deployment", and that audit events record seven minimum fields. Gilda Expires 30 April 2027 [Page 4] Internet-Draft Agent Audit Record October 2026 Section 12 then places the policy model and document format out of scope, stating that they are "not recommended as a target for standardization within this specification". Section 13 places compliance criteria out of scope, and Section 16 records no IANA actions. Appendix A sets out the canonicalization contract and the reason the decision and the observed effect belong in one record. 2. Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. 3. Terminology The following terms are used throughout this document. Two of them, _observer_ and _decision point_, are defined here; the rest are taken from the documents named beside them. Agent, Tool, Service, Resource, LLM: as [AIMS] uses them. Agent identifier: a WIMSE identifier as defined in [WIMSE-ID]. Statement, subject, predicate: as [IN-TOTO] uses them. Observer: the party that produces a record under this document. An observer watches from a layer the agent cannot address. A host- side view of a guest filesystem, a hypervisor-level read of guest state, and kernel-level supervision below the observed process are such layers. An in-process library, a wrapper the agent links, and an importer holding another party's log are not. Decision point: the party that evaluated the authorization request, whatever its architecture. Interval: the period between the before-state and the after-state that one record covers. Retaining party: a party that keeps a record as evidence, whether it produced the record or received it from another party. Anchor: evidence, obtained from a source the retaining party does not control, that a given digest existed no later than a given time: an [RFC3161] time-stamp token, an inclusion proof in an append-only log [RFC9162], or an OpenTimestamps proof. Gilda Expires 30 April 2027 [Page 5] Internet-Draft Agent Audit Record October 2026 Skew tolerance: 300 seconds. Every comparison in this document between times written by two different parties allows it, except a comparison with the time of an opentimestamps anchor, which allows the larger tolerance Section 4.7.2 gives for that kind. A relying party MAY apply a smaller tolerance and MUST NOT apply a larger one. Tier: the degree to which a record's own members corroborate what it claims about how it was observed. A verifier derives the tier under the rule in Section 5.7 and never reads it from the record. Every digest in this document is written as lowercase hexadecimal in the algorithm the record declares in its hashAlgorithm member. 4. Audit Record Specification A record is an in-toto Statement [IN-TOTO] carried in a DSSE envelope [DSSE]. Its predicateType is =========== NOTE: "\" line wrapping per RFC 8792 ============ https://probityai.github.io/agent-evidence-vectors/predicate/v1/\ agent-audit-record Seventeen required predicate members and two optional members are defined in Section 5. Each of the seventeen MUST be present unless a rule in that section makes it conditional, no member has a default, and a verifier MUST NOT supply one for an absent member (vectors F1 and EV3). Two members are conditional on a sibling value, resource.argumentsDigest and correlation.externalAnchor, and each is specified where it is defined. The optional members are oversight (Section 5.5), whose absence says nothing about whether a person acted, and sequence (Section 5.10), whose absence says nothing about how many records the producer issued. A verifier MUST reject a value outside any closed vocabulary this document defines, and MUST NOT ignore the member (vector V1). The closed vocabularies reuse terms registered in [VOCABULARY]. Gilda Expires 30 April 2027 [Page 6] Internet-Draft Agent Audit Record October 2026 A closed vocabulary is extended only by a revision of this document. Once a revision has frozen the predicate type URI (Section 8), a revision that adds a value to any closed vocabulary publishes the extended set under a new predicate type URI and leaves the set under the earlier URI unchanged, so a verifier never meets, under a URI it accepts, a value it is required to refuse. A verifier MUST NOT accept a value outside the set because it is well formed, prefixed, registered elsewhere or accompanied by a description. No closed vocabulary in this document carries a catch-all value such as other, because a catch-all satisfies the vocabulary while saying nothing two records can be compared on. 4.1. Canonical form Two implementations derive the same bytes from the same Statement only if they agree on the serialization and on what makes a Statement malformed. Both are fixed below. 4.1.1. JSON profile Producers and verifiers MUST canonicalize the Statement with [RFC8785], and the signature covers those bytes and no other serialization (vector T2). Producers and verifiers MUST enforce the [RFC7493] I-JSON safe-integer profile: an integer of magnitude at or above 2^53 makes the Statement malformed (vector T5). 4.1.2. Duplicate members and nesting depth A member name repeated at any depth makes the Statement malformed. A verifier MUST reject such a Statement and MUST NOT retain any one occurrence (vector T3). A Statement nested deeper than 128 levels MUST be rejected (vector T4). 4.2. Subject convention A record carries two subject entries. The first is the request, by digest: its name is the correlation identifier and its sha256 digest is the request digest defined in Section 5. The second is the after- state root of the interval the predicate carries, and its name is the first entry's name with the suffix /after. "subject": [ { "name": "urn:example:corr:7f3a", "digest": { "sha256": "9f86d081884c7d659a2feaa0c55ad015..." } }, { "name": "urn:example:corr:7f3a/after", "digest": { "sha256": "60303ae22b998861bce3b28f33eec1be..." } } ] Gilda Expires 30 April 2027 [Page 7] Internet-Draft Agent Audit Record October 2026 A verifier MUST bind on the digest map and MUST NOT bind on either name. A name is a correlation identifier a producer chooses; a digest is a value a verifier recomputes from the bytes it holds. The names exist so that a reader can tell the two entries apart. The second entry MUST be present if and only if the predicate carries an interval (vectors S1 and I1r), and its digest MUST equal the interval's after-state root (vector S2). A decision that was denied, and a permit under which nothing was written, still carry an observed interval. The condition on the interval is what was observed in it, not what was decided: an interval with no writes has equal before-state and after-state roots (vectors A2 and E6), and a write the observer saw in the interval is retained whatever the decision. A write attributed to a denied request yields agreement of disagree under Section 5.3 (vector A3), and a write attributed to another request moves the roots and leaves this record's agreement as it is (vector A7). A consumer therefore reads an absence of effect from the members of a record it holds, and never from a record it does not have. 4.3. Timestamps and correlation Every time value in a record MUST be an [RFC3339] date-time. A producer SHOULD express it in UTC with the "Z" offset, so that two records from different deployments sort together without a conversion step. The correlation identifier is the first subject entry's name, so one identifier binds the request digest, the interval and the record. 4.4. Tamper-evidence A record satisfies the tamper-evidence requirement of Section 11 of [AIMS] when all three of the following hold. The DSSE pre-authentication encoding covers the [RFC8785] canonical bytes of the whole Statement, and every one of the seven minimum fields is inside that pre-image. DSSE PAE = "DSSEv1" SP len("application/vnd.in-toto+json") SP "application/vnd.in-toto+json" SP len(JCS(statement)) SP JCS(statement) The request digest, the ordered write chain of the effect, and both agreement values are recomputable from other members of the same record. A verifier therefore still refuses a record that the key holder altered inconsistently and signed again (vector T1). Gilda Expires 30 April 2027 [Page 8] Internet-Draft Agent Audit Record October 2026 These recomputations detect internally inconsistent alterations even when the altered record is signed again by the key holder. They do not detect a coherent replacement in which the dependent members are changed consistently and signed again. A key holder that keeps authorityDigest, beforeRoot, recordId and witnessNonce, so that the commitment digest still recomputes, and replaces the writes, afterRoot, the second subject entry and every value derived from them, produces a record that every recompute accepts. A coherent replacement is found only by comparison with something the key holder does not control, such as a copy of the original envelope or an anchor over its digest that another party obtained (Section 4.7). The canonical form is fixed as in Section 4.1, so two verifiers derive identical bytes from identical documents. Any one of the three failing is a refusal. The retention half of the Section 11 requirement is a property of a deployment, and a record cannot assert it about itself. A record under this document SHOULD state that in its doesNotAssert member, so that a reader need not infer coverage. Section 4.7 defines what a retaining party keeps beside a record so that the record can still be dated and validated after its keys and algorithms age; how long a deployment keeps it remains the deployment's policy. 4.5. Mapping to the seven minimum fields +====================+=============================================+ | Section 11 field | Members | +====================+=============================================+ | authenticated | agent.id, agent.credentialDigest, | | agent identifier | agent.authentication, agent.signers | +--------------------+---------------------------------------------+ | delegated subject, | delegation.subject, delegation.subjectKind, | | when present | delegation.authorityDigest, and | | | delegation.rootDigest when present | +--------------------+---------------------------------------------+ | resource or tool | resource.kind, resource.id, | | being accessed | resource.binding, resource.argumentsDigest | +--------------------+---------------------------------------------+ | action requested | decision, evaluation and effect, with the | | and authorization | derived agreement, and oversight when | | decision | present | +--------------------+---------------------------------------------+ | timestamp and | correlation and the interval timestamps, | | correlation | and sequence when present | | identifier | | +--------------------+---------------------------------------------+ | posture assessment | posture, carrying both vantages and | Gilda Expires 30 April 2027 [Page 9] Internet-Draft Agent Audit Record October 2026 | or risk state | assessedAt | +--------------------+---------------------------------------------+ | remediation or | remediation | | revocation events | | | and cause | | +--------------------+---------------------------------------------+ Table 1: The seven minimum fields of Section 11 and the members that carry them Each field also carries an evidence partition in fieldEvidence, stating whether the observing substrate covered the value or the producer asserted it. All seven fields can be recorded by an agent about itself. A record that says which ones were is checkable; a record that does not say is not. The fourth field pairs an action with a decision, and this format carries decision, effect and the derived agreement together. A record whose decision and effect disagree is well formed, and the disagreement is visible in signed bytes: "decision": { "action": "write", "reported": "deny" }, "effect": { "observed": "occurred", "writes": [ { "path": "/srv/ledger/settlements.jsonl" } ] }, "agreement": "disagree" A log that carries the decision alone records that case as a clean denial, because it has no other value to disagree with. 4.6. Verifying a record A verifier holds a DSSE envelope and reaches a verdict from the bytes inside it. The checks below are the ones this document has already stated, in the order a verifier can apply them without reading a member twice. The JSON profile comes first, applied while the payload is parsed: the safe-integer bound of [RFC7493], no member name repeated at any depth, and no nesting past 128 levels. Each of the three makes a Statement malformed, so a verifier that finds one of them has nothing further to check. It has to come first because the signature covers [RFC8785] bytes, and a verifier derives those bytes from the parsed Statement: a parser that keeps one occurrence of a repeated name has already done what Section 4.1 forbids before any signature is checked (vector T3). Gilda Expires 30 April 2027 [Page 10] Internet-Draft Agent Audit Record October 2026 The envelope's signature comes second, over the [RFC8785] canonical bytes of the Statement that parse produced. A statement whose signature does not verify over those bytes is malformed, and nothing further is read from it. That includes a statement signed over the bytes it carries, which is what a DSSE verifier that does not derive the canonical form checks (vector T2). Membership comes third. Every one of the seventeen required members is present unless a rule in Section 5 makes it conditional on a sibling value, and every value sits inside the closed vocabulary its member declares. The recomputes come next, and a signature cannot supply them. The three that Section 4.4 requires come first: a verifier derives the request digest from the four members Section 5 names and compares it with the first subject entry, it replays the write chain from the before-state root and compares the result with the second subject entry, and it derives both agreement values from the members they are functions of. A fourth recompute binds the prior commitment rather than the record's content. A verifier recomputes the commitment digest, checks that the commitment precedes the interval, and checks that the commitment key is absent from agent.signers. A fifth derives, from evaluation.inputs, the set of inputs that were stale or never established at decision.reportedAt, and compares it with evaluation.status and unavailableInput (Section 5.4). The tier follows from those results. A verifier reads the five clauses of Section 5.7 against the members it has just checked and assigns authoritative or voluntary itself. A verifier that holds a retained record (Section 4.7) applies one more check, the dating check, after all of the above. It validates each anchor over the envelope digest under the offline rule for its kind, takes the time of the earliest anchor that validates as the time the record is established to have existed, and, for a record received from another party, checks the stated receipt time against the bracket Section 4.7 defines. The dating check produces its own result beside the record's verdict: an envelope that is well formed stays well formed when none of its anchors validates, and it is then simply not dated. For a record that carries delegation.rootDigest, the same verifier also establishes the delegation root. It decodes the delegation-root element, checks that its digest under hashAlgorithm equals delegation.rootDigest, and derives from the material the algorithm the chain's root rested on (vector R13). An element whose digest Gilda Expires 30 April 2027 [Page 11] Internet-Draft Agent Audit Record October 2026 differs makes the entry malformed (vector R15). Where the verifier holds no such element, or the record carries no delegation.rootDigest, it reports the root as not established, and MUST NOT report that as a pass (vector R14). This result too sits beside the record's verdict and does not change it. This document requires no particular order beyond the first two checks, and no particular reporting shape. A verifier that stops at the first failure and a verifier that reports every failure are both conformant. 4.7. Retained records A record's signature says who signed it and nothing about when. A party that keeps a record as evidence therefore keeps a retention entry beside the envelope: a JSON object under the profile of Section 4.1, which the producer did not sign and which this section defines. A retaining party MAY keep the entry in any container. The entry carries no predicate member and changes none, so a record's verdict under Section 4.6 never depends on it. { "envelopeDigest": "...", "received": true, "receivedAt": "2026-09-19T11:04:20Z", "anchorWithin": 300, "anchors": [ { "kind": "rfc3161", "origin": "retainer", "proof": "..." }, { "kind": "transparency-log", "origin": "received", "proof": "..." } ], "validationData": [ { "for": "envelope", "mediaType": "application/pkix-cert", "value": "..." }, { "for": 0, "mediaType": "application/pkix-cert", "value": "..." }, { "for": "delegation-root", "mediaType": "application/jwk-set+json", "value": "..." } ] } envelopeDigest is the digest, under the record's hashAlgorithm, of the [RFC8785] canonical bytes of the DSSE envelope object, so it covers the payload and every signature. Every anchor in the entry is over this value. Gilda Expires 30 April 2027 [Page 12] Internet-Draft Agent Audit Record October 2026 anchors is an array in the order the retaining party obtained its members. A retaining party appends to it and never removes from it or rewrites an element in place. Upgrading a proof, such as completing a pending OpenTimestamps proof once its commitment is in a block, appends the upgraded proof as a new element and keeps the pending one where it was. The pending element never validates and dates nothing (vector R8), and the upgraded element dates the record (vector R12). Rewriting in place would change the order the array records and the index by which validationData names an anchor. Each anchor carries kind, one of the three values of correlation.externalAnchor.kind (Section 5.6); origin, one of retainer and received; and proof, the base64 of the time-stamp token, inclusion proof or OpenTimestamps proof. An anchor of origin retainer is one the retaining party obtained itself, and one of origin received arrived with the record from the party that sent it. The entry carries no time and no algorithm family for an anchor: a verifier derives both from the proof when it validates it (Section 4.7.2), and MUST NOT read either from anywhere else. validationData carries what a verifier needs to validate the envelope's signature and each anchor offline, after the sources it came from may be gone: the certification path or key set of the record's signing key, status information as the retaining party obtained it, and each time-stamping authority's own path and status. It also carries, for a record that names delegation.rootDigest, the certification path or key set of the delegation chain's root key as the chain verifier held it at decision time. Each element names what it is for, one of envelope, the zero-based index of an anchor, and delegation-root, gives a media type, and carries the value in base64. An entry carries at most one delegation-root element, and only for a record that carries delegation.rootDigest; an entry that breaks either rule is malformed. Where status information was already unobtainable when the retaining party first anchored the record, the entry carries no status element for it, and that absence is the record of the fact. Gilda Expires 30 April 2027 [Page 13] Internet-Draft Agent Audit Record October 2026 The member received is true for a record the retaining party received from another party and false for one it produced. The member receivedAt is the time the retaining party states it received the record. It is present if and only if received is true, and an entry that carries it beside received of false, or omits it beside received of true, is malformed (vector R9). The member anchorWithin is the maximum interval, in seconds, that the retaining party commits to between issuance, or receipt for a received record, and its own first anchor. Only an anchor that validates meets it. An OpenTimestamps proof stays pending at a calendar until its commitment is in a block, and a pending proof does not validate offline, so for a retaining party whose anchors of origin retainer are all opentimestamps, anchorWithin covers that confirmation latency and is an interval of hours, not the 300 seconds of the skew tolerance. 4.7.1. The dating check A verifier validates each anchor under Section 4.7.2. The established time of the record is the time of the earliest anchor, of either origin, that validates over envelopeDigest. An anchor that does not validate dates nothing and makes nothing malformed (vector R8). No issuance time a record states establishes when it existed. A retaining party that sets received to true MUST obtain an anchor of origin retainer on receipt, within the anchorWithin it declares, and an entry with received of true and no such anchor is malformed (vector R4). The retention time is the time of the earliest anchor of origin retainer that validates. A verifier MUST reject the entry as malformed when any of these holds: * receivedAt is earlier than the record's issuedAt by more than the skew tolerance (vector R6); * receivedAt is later than the retention time by more than the skew tolerance (vector R3); * the retention time is later than receivedAt, or than issuedAt for a record the retaining party produced, by more than anchorWithin plus the skew tolerance (vector R7). A malformed entry does not change the envelope's verdict. A relying party MUST NOT apply an allowance it grants to received records, such as dating a record from its receipt, on a malformed entry or on an entry in which no anchor of origin retainer validates. This check is a consistency check, not proof of receipt. Its lower edge, issuedAt, is a value the sender signed, and the signature binds the value without saying anything about the sender's clock. Its Gilda Expires 30 April 2027 [Page 14] Internet-Draft Agent Audit Record October 2026 upper edge is an anchor over a digest, which shows only that the retaining party held the digest by that time, and a retaining party can hold the digest before the envelope arrives. A digest anchored before delivery therefore does not establish when the retaining party received the record. A verifier MUST report a receivedAt that passes the check as asserted and consistent with the anchors, and MUST NOT report it as established (vector R5). The check rests on two assumptions, stated so that a relying party can decide whether it holds them: that the sender's clock was correct when it signed, and that the retaining party anchored on delivery and not before. A retaining party also chooses when it anchors. One that anchors late can state a correspondingly late receipt, and nothing in the entry contradicts it, because the bracket's upper edge is an anchor whose time the retaining party chose. The check removes the cheaper case, a receipt time stated with no anchor at all, and what remains is an assumption that the retaining party anchored promptly after the true receipt, within the anchorWithin it declared. That assumption is narrower than trusting the retaining party's statement of receipt, and no function of the entry tests it. An opentimestamps anchor widens the room it leaves: its time can lie up to 7200 seconds after the moment its block existed, so a retaining party whose upper edge is such an anchor can state a receipt up to that much later than a prompt anchor of another kind would allow. 4.7.2. Anchor validation rules Each kind of anchor rests on one of two bases. A hash commitment is validated by recomputation to a value the verifier holds independently, and a signed token is validated by a signature under a path the verifier trusts. A kind names the proof format and not only its basis. A verifier validates an anchor offline from the proof alone, and both the recomputation or signature check and the source of the anchor's time differ by format; a value that named only the basis would tell a verifier neither. The verifier derives the basis from the kind, as stated for each kind below. A Merkle root that commits to envelopeDigest and is published in a Bitcoin transaction is a hash commitment of kind opentimestamps when its proof is carried in the OpenTimestamps serialization, which expresses the path from envelopeDigest through the tree and the transaction to the block header as a sequence of commitment operations (vector R16). A hash commitment published in another public ledger has no kind in this revision, because the bound on its time depends on that ledger's own rules for its timestamps. A revision that adds a kind for such a ledger states that bound, as the opentimestamps rule below states it for Bitcoin. Gilda Expires 30 April 2027 [Page 15] Internet-Draft Agent Audit Record October 2026 rfc3161: a signed token. It validates when its message imprint equals envelopeDigest and its signature verifies under the time- stamping authority's certificate, by a certification path in validationData from that certificate to a trust anchor the verifier holds. Its time is the token's genTime. transparency-log: an inclusion proof that recomputes from envelopeDigest to a tree head. It is a hash commitment when the verifier holds that tree head by a means other than its signature, such as a checkpoint the verifier already witnessed, and a signed token otherwise: it then validates when the tree head's signature verifies under the log's key, by a key or path in validationData that the verifier trusts. Its time is the tree head's timestamp. opentimestamps: a hash commitment. It validates when the proof recomputes from envelopeDigest to the Merkle root in the header of a Bitcoin block that the verifier holds independently, as a block of the chain with the most work. Its time is the timestamp in that block header. A miner sets that value and consensus bounds it only loosely: it must exceed the median timestamp of the eleven blocks before it, and it must be no more than 7200 seconds ahead of the clock of a node that validates it. A header time can therefore lie tens of minutes before or after the moment the block existed. Every comparison in Section 4.7.1 that uses the time of an opentimestamps anchor allows 7200 seconds in place of the skew tolerance (vectors R10 and R11). Where both times compared are times of opentimestamps anchors, as when a verifier finds the earliest anchor, it compares the heights of their blocks and not their timestamps. An anchor rests only on post-quantum assumptions when its validity rests on no quantum-vulnerable algorithm: a hash commitment under a hash with an output of at least 256 bits, or a signed token whose signature and whole path use post-quantum signature algorithms. A verifier derives this from the proof and the path. A retaining party SHOULD hold at least one anchor that rests only on post-quantum assumptions, and SHOULD append a new anchor on a schedule its policy sets, before the algorithms protecting its existing anchors weaken, using the renewal procedures of [RFC4998] or an equivalent. Where a relying party requires post-quantum anchoring from a transition date, as [PQ-AGENT-ID] proposes, this section supplies the anchors, their order and the material to validate each one, and the date is the relying party's. 5. Predicate members Gilda Expires 30 April 2027 [Page 16] Internet-Draft Agent Audit Record October 2026 { "recordId": "...", "tier": "authoritative", "hashAlgorithm": "sha256", "agent": { "id": "spiffe://prod.example.org/ns/payments/sa/reconciler", "credentialDigest": "...", "authentication": "wimse-wpt", "signers": ["..."] }, "delegation": { "subject": "user:alice@example.org", "subjectKind": "user", "authorityDigest": "...", "rootDigest": "..." }, "resource": { "kind": "tool", "id": "mcp://files/write", "binding": "digest-bound", "argumentsDigest": "..." }, "decision": { "action": "write", "requestDigest": "...", "reported": "deny", "decisionPointId": "pdp://prod.example.org/authz-1", "policyDigest": "...", "reportedAt": "2026-09-19T11:04:02Z" }, "evaluation": { "status": "evaluated", "inputs": [ { "input": "policy-source", "lastResult": "2026-09-19T10:00:00Z", "maxAge": 86400 }, { "input": "standing-source", "lastResult": "2026-09-19T11:00:00Z", "maxAge": 3600 } ] }, "effect": { "observed": "occurred", "interval": { "beforeRoot": "...", "afterRoot": "...", "baseResolution": "supplied", "openedAt": "2026-09-19T11:04:01Z", "sealedAt": "2026-09-19T11:04:06Z" }, Gilda Expires 30 April 2027 [Page 17] Internet-Draft Agent Audit Record October 2026 "pathScope": ["/srv/ledger/"], "writes": [ { "path": "/srv/ledger/settlements.jsonl", "preStateDigest": "...", "postStateDigest": "...", "requestDigest": "...", "inScope": true } ] }, "agreement": "disagree", "correlation": { "id": "req:7f3a91c4", "scope": "cross-party", "timeBasis": "beacon-anchored", "externalAnchor": { "kind": "rfc3161", "digest": "..." } }, "posture": { "reported": "sinkhole", "reportedDigest": "...", "observed": "allowlist", "observedDigest": "...", "assessedAt": "2026-09-19T06:00:00Z", "agreement": "disagree" }, "remediation": [ { "cause": "session-revoked", "signalReceivedAt": "2026-09-19T11:04:07Z", "enforcedAt": "2026-09-19T11:04:09Z", "enforcement": "session-terminated", "postEnforcementEffect": "none", "postEnforcementRoot": "..." } ], "observation": { "vantage": "below-observed", "coverage": { "scopeComplete": true, "gaps": [] }, "priorCommitment": { "committedAt": "2026-09-19T11:03:58Z", "witnessNonce": "...", "commitmentDigest": "...", "keyid": "...", "sig": "..." } }, "fieldEvidence": { Gilda Expires 30 April 2027 [Page 18] Internet-Draft Agent Audit Record October 2026 "agent": "producer-asserted", "correlation": "producer-asserted", "decision": "producer-asserted", "delegation": "producer-asserted", "posture": "substrate-covered", "remediation": "substrate-covered", "resource": "substrate-covered" }, "doesNotAssert": ["..."], "issuedAt": "2026-09-19T11:04:11Z" } 5.1. Record identity and hash algorithm recordId is the producer's identifier for this record. It is opaque to a verifier except where the commitment digest is recomputed, which reads it as one of its four inputs. hashAlgorithm names the algorithm every digest in the record is taken under. One value governs the whole record: the subject digests, the credential, authority, policy and posture digests, the interval roots, the write pre-state and post-state digests, and the commitment digest are all taken under it. A record carrying digests in two algorithms is therefore not representable, and that is the point. A verifier comparing two roots has to know they were taken under the same algorithm, and a per- member choice would let a producer choose which comparison a reader could make. issuedAt is the time the producer sealed the record, and it is at or after the interval's sealedAt because the record cannot be issued before the interval it describes has closed. A verifier that does not implement the declared algorithm cannot recompute anything the record binds. It has no verdict to reach on such a record, and reporting that it could not read one is the honest outcome rather than a refusal on the record's content. 5.2. Identity, delegation and resource agent.id carries the WIMSE identifier verbatim, and agent.credentialDigest the digest of the credential the identifier was read from. agent.authentication is the mechanism, over the closed set wimse-wpt, http-message-signature, mtls, oauth-access-token, api- key, none. All but api-key are drawn from Section 9 of [AIMS]. api- key is a bearer secret presented with the request that is not an OAuth access token, such as a key an API issued for the agent or its Gilda Expires 30 April 2027 [Page 19] Internet-Draft Agent Audit Record October 2026 operator (vector A21). none means the request carried no authentication, and a record MUST NOT carry it for a request that presented any credential. For the two bearer mechanisms, oauth- access-token and api-key, agent.credentialDigest is a digest of a bearer secret, against which anyone holding the record can test a guess of that secret; a deployment SHOULD NOT record a bearer secret with less than 128 bits of entropy under this format. agent.signers is the set of key identifiers the agent signs its own records with, as the observer knows them, and it MAY be empty. delegation.subjectKind is one of user, system, none. Field 2 of Section 11 is the only conditional one, so an absent delegated subject is conformant and is spelled subjectKind of none beside a subject of the literal none. A subjectKind of none beside any other subject value is malformed and a verifier MUST NOT prefer either member (vector F2). delegation.authorityDigest MUST be present in every record, and a decision taken under no authority carries the digest of the explicit deny-all document. delegation.rootDigest is optional. When the decision rested on a delegation chain, it is the digest of the certification path or key set of the root key that the chain verifier trusted for that chain at decision time, as the verifier held it, and a record SHOULD carry it. Verification of a chain as Section 6 of [DELEGATION-CHAIN] describes it reaches every token in the chain and stops at the root key, so without this member a later reader cannot reconstruct what the chain rested on. The member records what the verifier held and says nothing about how the verifier came to hold it, so it requires no trust-anchor distribution and no anchor topology, online or offline. The material itself is kept by a retaining party in validationData (Section 4.7), from which a later reader derives the algorithm the chain's root rested on, as it derives the algorithm of the record's own signing key. The digest is taken over the material's bytes as that element carries them. resource.kind is one of path, uri, tool, the three shapes the single category of external endpoints in Section 4 of [AIMS] takes. resource.binding of digest-bound MUST carry argumentsDigest, and not- bindable MUST NOT carry it in any spelling, including null and the empty string (vectors F3, F3b and F3c). Where a decision point can canonicalize the arguments of a call, it SHOULD bind them by digest. A tool call whose arguments it cannot canonicalize has nothing to bind, so that call is representable and it cannot reach the strongest tier. Gilda Expires 30 April 2027 [Page 20] Internet-Draft Agent Audit Record October 2026 5.3. Decision, effect and agreement decision.reported is one of permit, deny, permit-with-conditions. decision.requestDigest MUST equal the first subject entry's sha256 digest and MUST equal the [RFC8785] digest over the members action, argumentsDigest, resourceId and resourceKind (vector F4). The hashed object holds argumentsDigest exactly when resource.binding is digest- bound. Under not-bindable it holds the other three members and no argumentsDigest member at all, so every conforming implementation derives one digest for a given request (vector A6). Altering the action, the resource or the arguments after signing, without replacing the request digest and the first subject entry to match, therefore breaks a recompute even where the signature was applied again. A key holder that replaces all of them consistently has made the coherent replacement of Section 4.4, which no recompute detects. Each write carries requestDigest: the request digest of the request the observer attributes the write to, or the literal unattributed where the observer cannot attribute it. An attribution is an observation, and an observer that cannot tie a write to a request says so rather than guessing. effect.observed describes this record's request, not the whole interval, and it is one of occurred, none, unknown. It MUST be derivable from the write set: occurred when at least one write is attributed to decision.requestDigest; none when no write is attributed to it and no unattributed write lies inside pathScope; and unknown otherwise. A write attributed to a different request belongs to that request's record and does not enter this one's value (vectors A7 and T1). A value of none beside a write attributed to this record's request is malformed (vector E1). The ordered write chain MUST reproduce the after-state root from the before-state root. A verifier replays it with a running root that starts at beforeRoot. Each write in effect.writes, in array order and whatever its requestDigest or inScope, MUST carry a preStateDigest equal to the running root, and its postStateDigest then becomes the running root. The running root after the last write MUST equal afterRoot, so a record with no write carries equal roots. Vector E4 breaks only the start, E2 a link between two writes, E5 only the end, and E6 is the case with no write. A baseResolution of empty-tree MUST carry the empty-tree constant for the declared hash algorithm (vector E3). A member of pathScope MUST NOT contain a glob metacharacter, and a universal scope is the single literal / (vector V2). A write outside pathScope MUST carry inScope of false, which is derived from the path and never a producer opinion (vector V3). Gilda Expires 30 April 2027 [Page 21] Internet-Draft Agent Audit Record October 2026 agreement is one of agree, disagree, not-exercised, indeterminate, one-sided, and it MUST be derivable from decision.reported and effect.observed by the table below (vectors D1, D2 and D3). posture.agreement MUST be derivable from the two carried postures on the same terms: agree when they are equal byte for byte, disagree when both are present and unequal (vector F6). +========================+=================+===============+ | decision.reported | effect.observed | agreement | +========================+=================+===============+ | permit or permit-with- | occurred | agree | | conditions | | | +------------------------+-----------------+---------------+ | deny | none | agree | +------------------------+-----------------+---------------+ | deny | occurred | disagree | +------------------------+-----------------+---------------+ | permit or permit-with- | none | not-exercised | | conditions | | | +------------------------+-----------------+---------------+ | any | unknown | indeterminate | +------------------------+-----------------+---------------+ Table 2: Deriving agreement from the reported decision and the observed effect A permit allows an action and does not require it, so a permitted call that failed or was never made is not-exercised, and a deny that leaked is disagree. The two are different facts and an incident review needs to tell them apart (vector A9). An unattributed write inside pathScope leaves the observer unable to rule the request's effect in or out, so the record says indeterminate rather than choosing (vector A8). The table never produces one-sided. one-sided is in the closed set and this version never produces it, because decision and effect are both required and neither side can be absent. It is reserved so that a version admitting a record with one side missing does not have to change a closed vocabulary, and a record carrying it under this version is malformed (vector D2). A verifier MUST NOT reject a record because either agreement value is disagree, not-exercised or indeterminate (vectors A3, A8 and A9). A disagreement is the record working, and what it means for admission is a consumer policy decision. Gilda Expires 30 April 2027 [Page 22] Internet-Draft Agent Audit Record October 2026 5.4. Evaluation evaluation says whether the decision point evaluated the request, and how fresh each input it relied on was. evaluation.status is one of evaluated, not-evaluated (vector EV11). A decision point records evaluated when its reported decision does not depend on any input it could not obtain, and not-evaluated otherwise. Where delegation paths are judged independently (Section 4.2 of [EVALUATION]), a permit on a fully valid path is evaluated even when an input for another path was unavailable, because no value of that input could change the decision. A deny is not-evaluated whenever a path the decision point could not judge might have been valid. decision.reported always records what the decision point enforced. Under evaluated it is the outcome of evaluating the policy. Under not-evaluated it is the outcome the decision point fell back to, and it is the member that says whether the decision point failed closed (deny) or failed open (permit or permit-with-conditions). A record from a decision point that lost an input and denied therefore carries deny, and beside an effect of none derives agree. Without evaluation that record is byte for byte the record of a correctly enforced denial (vectors A2 and A10), and an incident review cannot tell the two apart. decision.policyDigest names the policy the decision point enforced. Where the policy was the unavailable input, the decision point cannot name that policy's digest, so decision.policyDigest is the digest of the fallback it applied, as delegation.authorityDigest names the deny-all document for a decision taken under no authority (vectors A18 and A20). A decision point that holds the profile a request names and finds that it grants no comparison has evaluated the request, and records evaluated with deny (vector A2); one that does not hold the profile records not-evaluated with policy-source (vector A20). evaluation MUST carry inputs under both statuses (vector EV13). It is an array with one entry for each input the reported decision depended on, each input named at most once (vector FR10). An entry MUST carry each of these three members (vectors FR5 and FR6) and MUST NOT carry any other except the consumption member that Section 5.9 defines (vector FR11): * input, a value from the closed set in the table below (vector FR12); * lastResult, the time at which the source produced the last value of that input the decision point held, or the literal none if it never held one; Gilda Expires 30 April 2027 [Page 23] Internet-Draft Agent Audit Record October 2026 * maxAge, the maximum age in seconds, a non-negative integer, that the decision point applies to that input (vector FR13). The reference time for every entry is decision.reportedAt, the time the decision point reported its decision. An input's age is decision.reportedAt minus lastResult. An input is fresh when its age is at most maxAge, so an age equal to maxAge is fresh (vector FR2); it is stale when its age is greater (vector FR3); and it was never established when lastResult is none (vectors A10 and FR4). A lastResult later than decision.reportedAt by more than the skew tolerance is malformed, because a decision cannot rest on a value produced after it was reported (vector FR9). Where the decision depended on more than one value of one input, as when several delegation paths are judged, the entry's lastResult and maxAge MUST be taken from the same value. If any of those values was never held, lastResult is none and maxAge is the smallest bound among the values never held. Otherwise the entry carries the pair whose lastResult plus maxAge is earliest, and of two such pairs the one with the earlier lastResult (vector FR14). At one reference time every held value is fresh exactly when that time is at most the smallest lastResult plus maxAge among them, so the entry is fresh exactly when every value is, and an age equal to maxAge stays fresh as vector FR2 requires. Taking the oldest lastResult from one value and the smallest maxAge from another can report two fresh values as one stale input (vector FR15). The entry summarizes the freshness of the values and does not enumerate them. A permit on a fully valid path depends only on the values that path used, so its entries carry those values and not the values of the other paths. issuedAt is the time the record was sealed, and it is not a reference time for any input. A held value older than the maximum age the decision point applies to its input is one it could not obtain, as Section 3.5 of [EVALUATION] treats standing that cannot be established within the pinned maximum age. The entries are therefore enough to derive the unavailable inputs, and a verifier derives them: the set of entries that are stale or were never established. Under evaluated that set MUST be empty (vector FR8). Under not-evaluated the member MUST carry unavailableInput, a non-empty array naming each input of that set exactly once and no other (vectors EV1, EV5, EV6, EV7 and FR7), from the closed set in the table below (vector EV4). Under evaluated it MUST NOT carry unavailableInput in any spelling, including null, the empty array and the empty string (vectors EV2, EV8, EV9 and EV10). No member other than status, inputs and unavailableInput is defined, and a verifier MUST reject an evaluation member carrying one (vector EV12). A free-text reason beside the closed set would name an input no other record can be compared with. Gilda Expires 30 April 2027 [Page 24] Internet-Draft Agent Audit Record October 2026 A decision point that receives an input's value from another hop, rather than from its source, copies the source's lastResult into its entry unchanged, so the input's age runs from the source and not from the hop (vectors FR1, FR3 and FR4). It applies its own maxAge in its own record. A hop that later obtains an input an earlier record named as unavailable writes a new record with its own evaluation, and never amends the earlier record, which its producer's signature has sealed. An entry carries what REQ-4 of [EVALUATION-STATE] asks a decision point to record for each input, its as-of time and whether it was accepted, stale or never established, and a forwarded entry carries what REQ-6 asks a hop to preserve: the input name, its evaluation state and its freshness bound. +===================+=======================================+ | input | what it names | +===================+=======================================+ | standing-source | the source issuer standing is | | | established from (Section 3.5 of | | | [EVALUATION]) | +-------------------+---------------------------------------+ | key-source | the source of the issuer or evaluator | | | keys a decision verifies under | | | (Section 3.4 of [EVALUATION]) | +-------------------+---------------------------------------+ | consumption-state | the record of which approvals have | | | been consumed (Section 4.3 of | | | [EVALUATION]) | +-------------------+---------------------------------------+ | policy-source | the policy the decision point | | | evaluates the request against, | | | including a profile the request names | | | that the decision point does not hold | +-------------------+---------------------------------------+ Table 3: The inputs an evaluation entry or unavailableInput names The first three are the inputs Section 5 of [EVALUATION] names as making a refusal transient. A refusal that document classifies as transient is recorded as not-evaluated, naming the inputs that were unavailable. A refusal it classifies as permanent (an unsupported entry type, a signature that does not verify, an expired grant, an issuer whose standing is withdrawn) is recorded as evaluated with deny. The record then carries what Section 5 requires a verifier's own record of a refusal to carry, and what the caller is told is unaffected. Gilda Expires 30 April 2027 [Page 25] Internet-Draft Agent Audit Record October 2026 "decision": { "action": "write", "reported": "deny", "reportedAt": "2026-09-19T11:04:02Z" }, "evaluation": { "status": "not-evaluated", "inputs": [ { "input": "policy-source", "lastResult": "2026-09-19T10:00:00Z", "maxAge": 86400 }, { "input": "standing-source", "lastResult": "2026-09-19T09:30:00Z", "maxAge": 3600 } ], "unavailableInput": ["standing-source"] }, "effect": { "observed": "none", "writes": [] }, "agreement": "agree" The record above is a decision point whose last standing value was 5642 seconds old against a maximum of 3600, and which failed closed. Its agreement is agree, because the deny held, and its evaluation says the deny was not a policy outcome and which input was stale. evaluation is not an input to agreement. "Could not evaluate" is not a decision, so it is not a fourth value of decision.reported, and the agreement table is unchanged: a deny enforced during an outage that leaked anyway is still disagree (vector A19). A verifier MUST NOT reject a record because evaluation.status is not-evaluated, whatever decision.reported and agreement are (vectors A10, A12 to A14, and A18 to A20). A permit recorded as not-evaluated is a decision point failing open, and the format represents it so that it can be found (vector A18). The evidence class of evaluation is the one fieldEvidence declares for decision. 5.5. Oversight oversight is optional. When present it records the kind of act a person took on this request before or at the decision, so that a permit bound to a user confirmation (Section 10.7 of [AIMS]) says whether that person observed the request, checked a stated property of it, chose, or released an action already within authority they held. The four kinds are those of [OVERSIGHT-ACTS], Sections 2.3 to 2.9. Gilda Expires 30 April 2027 [Page 26] Internet-Draft Agent Audit Record October 2026 An oversight member MUST carry oversight.act, which is one of observation, check, decision, release (vector OV1). oversight.recordDigest is optional and, when present, is the digest of the overseer's own signed record, bound as delegation.authorityDigest binds the authority document. No other member is defined, and a verifier MUST reject an oversight member carrying one (vector OV2). The act is producer-asserted: its evidence class is the one fieldEvidence declares for decision, and a verifier does not resolve recordDigest. 5.6. Correlation, posture and remediation correlation.scope is one of producer, cross-party. It MUST be present, because Section 11 asks systems to "correlate events across Agents, Tools, Services, Resources and LLMs", which a producer-scoped identifier cannot do. A record a producer distributes beyond its own deployment SHOULD carry a scope of cross-party. correlation.timeBasis of beacon-anchored MUST carry externalAnchor, and asserted MUST NOT carry it (vector F5). externalAnchor.kind is one of rfc3161, transparency-log, opentimestamps, of which [RFC3161] and [RFC9162] define the first two. externalAnchor.digest is the digest of the anchor's proof and not the proof, so a verifier that holds only the record cannot validate the anchor. Such a verifier reads beacon-anchored as a statement the producer made, accepts the record, and does not date it from the anchor (vector N1). A record is dated from the anchors of a retention entry (Section 4.7), which are over the envelope digest and are validated under the rules in Section 4.7.2. The record's verdict and its dating are two results, and a verifier reports them separately, so vector N1 has one conforming verdict where draft-gilda-wimse-agent-audit-record-02 admitted two. posture.reported and posture.observed are over the closed set no_network, allowlist, sinkhole, unsafe_bypass_egress, each with a digest pinning the posture document. posture.assessedAt carries the time the assessment was made, which Appendix A gives the reason for. A consumer weighing either posture SHOULD read assessedAt beside it. remediation carries one member per event. Its cause is one of session-revoked, risk-elevated, subject-disabled, token-replay- suspected, policy-changed, operator-action. Its enforcement is one of access-attenuated, session-terminated, tokens-discarded, privileges-reduced, reevaluated, not-enforced. In each member enforcedAt MUST be at or after signalReceivedAt (vector F7). Gilda Expires 30 April 2027 [Page 27] Internet-Draft Agent Audit Record October 2026 A verifier MUST NOT reject a record because enforcement is not- enforced (vector A4). A record carries that value when a remediation signal arrived and enforcement did not follow it. postEnforcementEffect and postEnforcementRoot make the Section 11 delay requirement checkable by a third party. A revocation that arrived, was recorded, and was followed by an observed effect is a recorded enforcement failure. This document defines no bound on the delay, because Section 11 carries no unit for "undue", and vector N2 records that case as indeterminate. 5.7. Observation and tier observation.vantage is one of below-observed, peer, self. coverage.scopeComplete is true when the observer read every path inside pathScope throughout the interval, and false otherwise. coverage.gaps is an array of the paths the observer could not read. A gap is inside pathScope when it lies under a member of pathScope, as inScope is derived for a write. A gap inside pathScope contradicts a scopeComplete of true, and a record carrying both is malformed whatever tier it declares (vectors V4 and V5). An observer that could not read part of pathScope SHOULD name that path in coverage.gaps, because a reader learns which ground the record does not cover from the gap list and not from the observer's confidence. The coverage check is a check of the record's own declaration; it does not establish that the observer in fact read every path it did not list. observation.priorCommitment is the observer's commitment, made before the interval opened, to the before-state and to a nonce the observer chose. Its committedAt MUST be strictly before the interval's openedAt (vector C2). Its commitmentDigest MUST recompute as the [RFC8785] digest over authorityDigest, beforeRoot, recordId and witnessNonce (vector C3). Its keyid MUST NOT appear in agent.signers (vector C1), and that disjointness is the one byte-pure discriminator between an observer and a self-observing party. doesNotAssert is the negative-scope member the sections above refer to: an array of explicit statements about what this record does not claim. A record under this version SHOULD carry two entries. The first entry records that it makes no claim about retention. The second records that it makes no claim that the reported decision is the decision the policy engine evaluated. fieldEvidence carries exactly the seven keys named in the mapping table, each one of substrate-covered or producer-asserted. Both terms are reused unchanged from the field-evidence partition Gilda Expires 30 April 2027 [Page 28] Internet-Draft Agent Audit Record October 2026 registered in [VOCABULARY], as the four posture values above are reused from its containment-posture terms. A missing key is malformed (vector FE1), and no key may declare substrate-covered while vantage is self (vector FE2). tier is one of voluntary, authoritative. A verifier MUST recompute it and MUST NOT take the declared value as the tier. Vectors TI1 through TI5 each declare authoritative while failing one clause, so a verifier that reads the declared value passes all five. A record is authoritative if and only if all five of these hold, and voluntary otherwise: vantage is below-observed (vector TI1); priorCommitment is present and complete (vector TI2); pathScope is non-empty (vector TI3); coverage.scopeComplete is true, which by the rule above leaves no gap inside pathScope (vectors TI4 and TI6); and resource.binding is digest-bound (vector TI5). A record declaring authoritative that fails a clause is malformed, and a verifier MUST NOT downgrade it to voluntary (vector TI1). Downgrading would let a producer emit an authoritative-shaped record and rely on the verifier to relabel it. The opposite mismatch is well formed. A record declaring voluntary while meeting all five clauses is not malformed, and a verifier reads it at the tier the recompute gives. Treating the two directions differently is deliberate: a producer that over-claims is relying on somebody else to correct it, and a producer that under-claims is not. A verifier MUST NOT read a voluntary record as evidence that its content corresponds to any independently observed fact (vector A5). 5.8. A worked reading of the example The record at the head of Section 5 reports a write that was denied and happened anyway. Each rule above lands on one of its members. decision.reported is deny, and the single write is attributed to the record's own request, so effect.observed derives as occurred. The third row of the agreement table maps that pair to disagree, which is the value the record carries, so the derivation holds and vector D1 does not apply. posture.reported is sinkhole and posture.observed is allowlist. Both are present and they are unequal, so posture.agreement derives as disagree, which is again the carried value. Gilda Expires 30 April 2027 [Page 29] Internet-Draft Agent Audit Record October 2026 The tier recompute passes all five clauses. vantage is below- observed; priorCommitment carries all five of its own members; pathScope holds one entry; coverage.scopeComplete is true with no gaps; and resource.binding is digest-bound. The declared authoritative is therefore the tier a verifier derives. evaluation.status is evaluated and the member names no unavailable input, so vector EV2 does not apply. Each of its two inputs is fresh at decision.reportedAt, 11:04:02Z: the policy was produced 3842 seconds earlier under a maxAge of 86400, and the standing 242 seconds earlier under a maxAge of 3600, so the recompute gives an empty set of unavailable inputs and vector FR8 does not apply. The record carries no oversight member and claims nothing about a human act. The ordering checks hold on the timestamps as written. Vector C2 tests the first: committedAt at 11:03:58Z falls strictly before openedAt at 11:04:01Z. Vector F7 tests the second: enforcedAt at 11:04:09Z falls two seconds after signalReceivedAt at 11:04:07Z. The single write lies under /srv/ledger/, the one member of pathScope, so its inScope of true is derived from the path and vector V3 does not apply. fieldEvidence carries all seven keys, so vector FE1 does not apply, and vantage is not self, so vector FE2 does not either. What the record says, read whole, is that a write was denied and happened anyway, that the posture the decision point read was not the posture an observer saw, and that a revocation signal was enforced two seconds after it arrived. All three are well formed, and a verifier accepts the record. 5.9. Consumption under a cumulative limit A decision under a cumulative limit, such as a delegated spending limit, depends on the value of consumption-state and not only on its freshness. A permit is correct only when the amount already committed under the limit, plus the amount held for earlier permits that have not settled, plus this request's amount, is within the limit. An as-of time and a maximum age cannot show that, so an entry whose input is consumption-state and whose decision applied a cumulative limit MUST carry a fourth member, consumption, and an entry for any other input MUST NOT carry it (vector CS6). consumption MUST carry each of these members and no other (vector CS9): Gilda Expires 30 April 2027 [Page 30] Internet-Draft Agent Audit Record October 2026 * limitDigest, the digest of the document that sets the limit: the delegated authority delegation.authorityDigest names, or a document that authority names; * unit, the unit amounts are counted in; for money, an ISO 4217 alphabetic code; * limit, consumed, reserved and requested, each a non-negative integer in the smallest subunit of unit (vector CS5): the limit, the amount committed by earlier settled calls under it, the amount held for earlier permits under it that have not settled, and this request's amount; * held, an array with one entry for each unsettled earlier permit, each carrying that permit's requestDigest and amount, whose amounts sum to reserved (vector CS3); * stateRevision, a non-negative integer naming the revision of the consumption state the decision point read. The entry's lastResult is the time that revision was produced. A request whose decision.requestDigest appears in held is the same call as the permit held for it, as when a caller retries after a lost response. Its requested MUST equal the held amount (vector CS4), and it is not counted a second time. A verifier derives withinLimit: true when consumed plus reserved, plus requested unless the request is held, is at most limit. A verifier MUST NOT reject a record because a permit or permit-with-conditions has withinLimit false (vector CS2). A permit beyond the limit is a decision point exceeding its authority, and the format represents it so that it can be found, as it represents a fail-open in Section 5.4. A permit stays in held until a record for the same request settles it. It moves to consumed when that request's record has effect.observed of occurred, and it is released only when that request's record has effect.observed of none. A permit whose response was lost has no such record, so it stays held: a missing reply is not evidence that the call did not execute (vector CS8). Gilda Expires 30 April 2027 [Page 31] Internet-Draft Agent Audit Record October 2026 Two checks need more than one record, and a retaining party that holds the records under one limitDigest runs them. Ordered by stateRevision, every permit MUST appear in the held or the consumed of each later record under that limit until it settles. A permit whose decision read a stateRevision older than a record that already held an unsettled permit, and which omits that permit from its own held, read a state that had not counted it, which is the window in which one limit is spent twice (vector CS7). A release from held with no record of that request showing none is the second (vector CS8). A paid tool call under a delegated limit of 50000 pence, where the effect commits, the response is lost and the caller retries, reads as follows. The first call reads revision 41 with consumed of 30000 and nothing held, requests 12000, and is permitted. Its response is lost, so no record settles it. The retry carries the same request digest, reads revision 42 with consumed of 30000 and that call held for 12000, and is within the limit because the held call is not counted again. A different call for 12000 that reads revision 42 is beyond the limit (30000 plus 12000 plus 12000 is 54000) and is denied. A decision point that permitted that second call after reading revision 41 is found by the check across records (vector CS7). "decision": { "action": "pay", "reported": "permit", "requestDigest": "sha256:r1...", "reportedAt": "2026-10-19T09:00:05Z" }, "evaluation": { "status": "evaluated", "inputs": [ { "input": "consumption-state", "lastResult": "2026-10-19T09:00:04Z", "maxAge": 5, "consumption": { "limitDigest": "sha256:...", "unit": "GBP", "limit": 50000, "consumed": 30000, "reserved": 12000, "requested": 12000, "stateRevision": 42, "held": [ { "requestDigest": "sha256:r1...", "amount": 12000 } ] } } ] } The record above is the retry. Its request is held, so withinLimit is true at 42000 of 50000. Gilda Expires 30 April 2027 [Page 32] Internet-Draft Agent Audit Record October 2026 5.10. Sequence sequence is optional. When present it places the record in a numbered series its producer issues, so that a party holding several records of the series can name one missing from them. It carries exactly two members, and a verifier MUST reject a sequence member carrying any other (vector SQ2): boundary, a string the producer chooses to name one series, and seq, a positive integer (vector SQ3). Two records are in one series when they carry the same boundary and their envelopes verify under the same key, and a producer that changes its signing key starts a new series. A producer MUST give the first record of a series a seq of 1 and each later record of that series a seq one greater than the record before it, and MUST NOT give two records of one series the same seq (vector SQ1). Within a series, seq is also the running count of records issued, so the format carries no separate count member: a count beside a contiguous number that starts at 1 would repeat it and add no check. Two checks need more than one record, and a party holding records of one series runs them. A number below the highest it holds, which it does not hold, names a record that was issued and that it has not received: one withheld, or not yet delivered (vector SQ4). Two records of one series with the same seq and different envelope digests are the producer issuing two different records at one place in the series, and the set fails the check (vector SQ5). Neither check reaches a record above the highest number held: a series whose last records were withheld reads the same as one whose producer stopped issuing, until a later record of it arrives. A consumer that needs that tail bounded SHOULD require a record of the series within an interval its policy sets. sequence is producer-asserted, and its evidence class is the one fieldEvidence declares for correlation. 6. Security Considerations A record is checkable for internal coherence and says nothing about the world outside its own bytes. Where a consumer needs a fact about that world, it has to establish that fact somewhere else. Gilda Expires 30 April 2027 [Page 33] Internet-Draft Agent Audit Record October 2026 6.1. The vantage claim is not self-proving The vantage claim in a record is an assertion about the world, and the record makes it coherent with its own members without making it self-proving. A consumer that requires the vantage to be true MUST anchor the observer's key out of band, exactly as it would anchor any signer. Such a consumer MUST read authoritative as coherence with a claimed observation.vantage, and never as proof of one (vector A5). 6.2. A producer that observes only itself A producer that observes only itself can satisfy every field of this format, and the observation.priorCommitment member raises the cost of doing so. It binds the before-state, the authority and the record identifier under the observer's signature before the interval opens. A forgery therefore has to be decided on before the forger knows what it will be lying about. It does not reduce the cost to zero, and a producer holding two keys satisfies every clause. That residual is detectable by a key inventory outside the record and by no function of the bytes inside it. A consumer that depends on the vantage SHOULD keep such an inventory. 6.3. Withheld rows A record can omit a remediation event, or a claimed access that the observer saw, and no function of a Statement detects a row that was never written. No quantity of extra carried material changes that, because extra material is material a withholding producer also declines to carry. A withheld record and a record never produced are different failures. Where records carry sequence (Section 5.10), a record withheld from a party that holds a later record of the same series is detectable from the records alone, because its number is missing from them. A record never produced leaves no number missing, and neither does a withheld record numbered above the highest one held; no function of the records detects either. The coverage, fieldEvidence and doesNotAssert members exist so that a blind spot travels where the observer is honest about it. An observer that knows of a blind spot SHOULD record it in the doesNotAssert member. None of these members is a defence against a producer that conceals one. Gilda Expires 30 April 2027 [Page 34] Internet-Draft Agent Audit Record October 2026 6.4. Well-formed disagreement A disagreement between the reported decision and the observed effect is well formed, as is a disagreement between the two postures, and as is a remediation event recording that enforcement did not occur. A verifier MUST accept all three (vectors A3 and A4). A format that refused to represent a failed enforcement would mean that no record ever reports one. This clause prevents that. 6.5. A decision that was not evaluated A record whose evaluation.status is not-evaluated is well formed beside any reported decision and any agreement, and a verifier MUST accept it (vectors A10, A12 to A14, and A18 to A20). A deny that was not evaluated is a decision point failing closed, and a permit that was not evaluated is one failing open. Both are facts an audit trail exists to carry. A consumer SHOULD treat a not-evaluated permit as an enforcement failure for policy purposes, and this document leaves that to the consumer. The reason is the one Section 6.4 gives for a disagreement. A format with no way to say that a decision point could not evaluate records every outage as policy: each lost standing source reads as a correctly enforced denial, and each fail-open reads as a permit somebody decided. An incident review that reads such a trail finds no outage, because none was ever written down. Every source a decision point reads is also a way to stop it (Section 5 of [EVALUATION]). An attacker who can make a source unavailable turns fail-closed evaluation into a denial of service, and the not-evaluated records are the evidence of it. A consumer SHOULD read a rate of not-evaluated records naming one input as an availability event, not as a series of policy decisions. evaluation is producer-asserted. A decision point that records evaluated for a decision that depended on an input it did not obtain is withholding, as in Section 6.3, and no function of the record's bytes detects it. The same holds for evaluation.inputs: the recompute catches an entry whose own times contradict the status, and it cannot catch a lastResult written later than the source produced the value, or a hop that wrote the time it received a forwarded value in place of the source's. A consumer that relies on freshness SHOULD read each entry's evidence class as the one fieldEvidence declares for decision. Gilda Expires 30 April 2027 [Page 35] Internet-Draft Agent Audit Record October 2026 6.6. Revocation without a bound Section 11 of [AIMS] requires that revoked or downgraded authorization be enforced "without undue delay" and specifies no bound. This document carries signalReceivedAt and enforcedAt, and defines no bound of its own. A record with an arbitrarily large gap between them is well formed. A consumer SHOULD set a bound on that gap as policy and read a record that exceeds it accordingly. 6.7. Relationship to other tamper-evidence mechanisms A signature over canonical bytes detects an editor who cannot sign. A trusted timestamp [RFC3161] adds an assertion about when the bytes existed, and an append-only log [RFC6962] [RFC9162] adds an assertion that they were published. This document requires neither, and a deployment MAY carry a record under this format in such a log. None of the three detects a producer that signed a false record. The recomputes in Section 4.4 refuse a record whose members contradict one another, whoever signed it. These recomputations check consistency among the represented fields and do not establish the truth of external events. 6.8. Two implementations that both differ from the canonical form Appendix A gives the mechanism by which two implementations can share a serialization that is not [RFC8785]. Neither party can see the failure from inside it. Every signature each of them produces verifies for the other, and the records fail only for a third party that canonicalizes correctly. A consumer therefore derives the canonical bytes itself and does not accept a producer's report of them. Section 4.1 is normative for that reason, and vector T2 is the member that tests it. 6.9. Receipt time and late anchoring A retention entry's receivedAt is asserted by the retaining party, and Section 4.7.1 makes it checkable for consistency, not true. A retaining party that anchors a digest before the envelope arrives, or anchors late and states a correspondingly late receipt, produces an entry that passes the check. A relying party that grants a received record an allowance, such as dating it from its receipt rather than from its issuance, is relying on the two assumptions Section 4.7.1 states, and SHOULD limit the allowance to retaining parties it trusts to anchor on delivery. Gilda Expires 30 April 2027 [Page 36] Internet-Draft Agent Audit Record October 2026 An anchor of origin received was obtained by the party that sent the record. It can date the record's existence, and it says nothing about when the retaining party received it, so it never forms the upper edge of the receipt bracket. 7. Privacy Considerations A record under this document carries an agent identifier, a delegated subject, a resource identifier and a set of paths. The delegated subject in particular may identify a natural person. Deployments SHOULD consider which of these a given consumer needs before distributing a record. The doesNotAssert member is the place to record what a distributed record deliberately omits. The format binds five documents by digest and carries none of them: the credential, the authority document, the policy, and both posture documents. A record that carries delegation.rootDigest binds a sixth, the delegation root's path or key set, which a retaining party keeps beside the record. A consumer that needs their content SHOULD resolve them out of band. That separation is deliberate and is the privacy-preserving default, because it lets a record travel to a party entitled to verify the decision without carrying the material the decision was made from. A consumer entitled to the decision receives the digest and resolves the document only if it needs the content. A retention entry's anchors are over the envelope digest alone, so an anchoring service, a transparency log or a time-stamping authority learns that a record existed and nothing in it. A retaining party that discloses an entry discloses its receipt time and the parties whose validation data it holds, and SHOULD treat the entry with the same care as the record. 8. IANA Considerations This document has no IANA actions. The predicate type is a URI under a namespace the author controls and requires no registration to be used, consistent with the in-toto Attestation Framework's treatment of predicate type identifiers [IN-TOTO]. A registered identifier would be the alternative. It is not proposed here, because a record carries its predicate type inside the bytes its producer signed. A later revision SHOULD NOT move the URI once records carrying it exist, since moving it invalidates every signature over them. Gilda Expires 30 April 2027 [Page 37] Internet-Draft Agent Audit Record October 2026 No revision has yet frozen the URI. Until a revision states in its Document History that it does, the members published in [VECTORS] are test records signed under published test keys, and a revision may change what a record under the URI must carry, as draft-gilda-wimse- agent-audit-record-02 did (vector EV3) and as this revision does (vector EV13). After the freeze, a change to what a record must carry is published under a new URI, as Section 5 requires for an extended vocabulary. 9. Conformance This section states what another document may rely on when it references this one. A conforming producer emits records that meet every MUST of Section 4 and Section 5 that applies to the members it emits. A conforming verifier applies the order of Section 4.6, refuses what Section 5 makes malformed, and, for a retained record, applies Section 4.7. A verifier is not described as conforming to this revision unless it reaches the verdict its manifest declares on every member of the vectors-agent-audit-record family of release 0.26.2 of [VECTORS], and, once a release carries them, on the rows Appendix B marks as next. Passing the corpus is necessary and not sufficient: the three rules Appendix B names as having no member are checked by reading them. A document that references this one normatively SHOULD name the revision it relies on, and MAY name a release of [VECTORS] as its conformance test. The following identifiers are stable across revisions of this document and may be referenced by name: * the predicate type URI of Section 4; * the section anchors canonical, subject, timestamps, tamper, mapping, verifying, retained, dating, anchor-rules, members, evaluation, oversight, consumption, sequence and vectors; * the member identifiers of Appendix B, which keep their row across revisions and are never reused for another row; * the terms this document takes from [VOCABULARY] (the containment_posture values and the field_evidence_partition values substrate-covered and producer-asserted), which are cited at a tagged release of that registry and change only under a new release. Gilda Expires 30 April 2027 [Page 38] Internet-Draft Agent Audit Record October 2026 The predicate type URI is not yet frozen (Section 8). Until it is, a referencing document that needs records to stay valid across revisions names the revision it relies on. 10. Implementation Status Note to the RFC Editor: please remove this section before publication. This section records the status of known implementations at the time of writing, following [RFC7942]. Listing an implementation here does not imply endorsement by the IETF. [VECTORS] is an open conformance corpus for this format, licensed under Apache-2.0. Its vectors-agent-audit-record family publishes each member of Appendix B as a signed DSSE envelope with the verdict a conforming verifier must reach. It ships two verifiers written from the text, one in Python that uses only the standard library and one in Go. Release v0.26.2, published on 26 October 2026, carries 111 members, and anyone can rerun every one of them with a single command: uvx agent-evidence-vectors==0.26.2 \ --corpus vectors-agent-audit-record On release v0.26.2 the run reports 38 members to accept, 72 to reject and 1 indeterminate, each behaving as its manifest declares. Two parties outside the corpus's authorship ran an earlier revision's members themselves and posted their results on the issue tracker of [AIMS]: 47 of 47 members behaved as specified at release 0.14.1, and 47 of 47 at release 0.16.0. The 22 rows Appendix B marks as next (A21, SQ1 to SQ5, R10 to R16 and CS1 to CS9) are added in the release that follows this revision. 11. Normative References [AIMS] Kasselman, P., Lombardo, J., Rosomakho, Y., Campbell, B., Steele, N., and A. Parecki, "AI Identity Management System", Work in Progress, Internet-Draft, draft-ietf- wimse-aims-00, 15 September 2026, . [DSSE] Secure Systems Lab, "Dead Simple Signing Envelope", 2026, . Gilda Expires 30 April 2027 [Page 39] Internet-Draft Agent Audit Record October 2026 [IN-TOTO] in-toto, "in-toto Attestation Framework Specification", 2026, . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, . [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, DOI 10.17487/RFC7493, March 2015, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, DOI 10.17487/RFC8785, June 2020, . [WIMSE-ID] Rosomakho, Y. and J. A. Salowey, "Workload Identifier", Work in Progress, Internet-Draft, draft-ietf-wimse- identifier-03, 6 July 2026, . 12. Informative References [AUDIT-BOFREQ] Kuehlewind, M., "AUDIT - Agent Use of Delegation and Interaction Traceability", 8 October 2026, . [AUDIT-CHARTER] AUDIT BoF proponents, "Agent Use of Delegation and Interaction Traceability (AUDIT) Working Group Charter (proposed)", 2026, . Gilda Expires 30 April 2027 [Page 40] Internet-Draft Agent Audit Record October 2026 [DELEGATION-CHAIN] Asor, R., "Verifiable Attenuated Delegation for AI Agent Chains", Work in Progress, Internet-Draft, draft-asor- wimse-agent-delegation-chain-02, 15 October 2026, . [EVALUATION] Jackson, W., "Verifier-Side Evaluation Semantics for Delegated Authority Chains", Work in Progress, Internet- Draft, draft-jackson-wimse-evaluation-04, 10 October 2026, . [EVALUATION-STATE] Konda, G., "Preserving Evaluation State in Agent Protocol Decisions", Work in Progress, Internet-Draft, draft-konda- agentproto-evaluation-state-01, 10 October 2026, . [OVERSIGHT-ACTS] Ehstand, A., "Terminology for Human Oversight Acts in Automated and Agentic Systems", Work in Progress, Internet-Draft, draft-ehstand-oversight-acts-00, 26 September 2026, . [PQ-AGENT-ID] Uppalapati, V. K., "Post-Quantum Requirements for Software and AI Agent Identity", Work in Progress, Internet-Draft, draft-uppalapati-wimse-pq-agent-identity-00, 28 September 2026, . [RFC3161] Adams, C., Cain, P., Pinkas, D., and R. Zuccherato, "Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)", RFC 3161, DOI 10.17487/RFC3161, August 2001, . [RFC4998] Gondrom, T., Brandner, R., and U. Pordesch, "Evidence Record Syntax (ERS)", RFC 4998, DOI 10.17487/RFC4998, August 2007, . [RFC6962] Laurie, B., Langley, A., and E. Kasper, "Certificate Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013, . Gilda Expires 30 April 2027 [Page 41] Internet-Draft Agent Audit Record October 2026 [RFC7942] Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, July 2016, . [RFC9162] Laurie, B., Messeri, E., and R. Stradling, "Certificate Transparency Version 2.0", RFC 9162, DOI 10.17487/RFC9162, December 2021, . [VECTORS] agent-evidence-vectors contributors, "Agent evidence conformance vectors, release 0.26.2", 26 October 2026, . [VOCABULARY] agent-evidence-vocabulary contributors, "Agent evidence vocabulary, release 0.5.0", 16 October 2026, . Appendix A. Design rationale Two requirements of this document are not derivable from Section 11 of [AIMS] on its own: the canonicalization contract, and carrying the observed effect beside the reported decision. Neither is restated normatively here. A.1. The canonicalization contract The word "tamper-evident" appears once in [AIMS] and is not defined there. Read narrowly it means a record whose alteration is detectable, which a signature provides. Two gaps remain. A signature over a serialization is only as good as the agreement on which bytes were signed, and that agreement is a property of a written contract between two implementations; neither one's code establishes it. Two implementations can agree with each other on a canonical form and both differ from [RFC8785], and no amount of signing or hash-chaining detects that. Each verifies its own records and rejects the other's, or worse, accepts a record whose meaning it has silently changed. A canonicalization contract is therefore part of the tamper-evidence requirement; it is not an implementation detail, and Section 4.1 makes it normative. Gilda Expires 30 April 2027 [Page 42] Internet-Draft Agent Audit Record October 2026 A signature also says nothing about the producer. The party that holds the signing key can alter a record and sign it again, and every signature check still passes. Detecting that requires fields whose values are recomputable from other fields in the same record, so that an internally inconsistent record is refusable regardless of who signed it. A hash chain catches an alteration by a party with no signing key; only a recompute catches the key holder, and Section 4.4 specifies three of them. A recompute catches the key holder only when the alteration leaves the record inconsistent with itself. A coherent replacement, signed again, passes every recompute, and Section 4.4 says what finds it. A.2. The decision and the observed effect The fourth of the seven minimum fields pairs "action requested and authorization decision". A record carrying only the decision is a self-report: it states what an enforcement point concluded, and a deployment that mis-enforces its own conclusion produces a clean audit trail of the decision it failed to apply. Section 11 asks for enough to "reconstruct agent behavior and authorization context after execution", and behaviour is not reconstructable from a decision. This document therefore requires both sides in one record: the decision as reported by the enforcement point, and the effect as observed. It also requires an agreement between them, which a verifier derives from the two values by the table in Section 5.3; it is not a claim the record makes. A decision reported as denied beside an effect observed as having occurred is then a well-formed disagreement in signed bytes, which a verifier accepts and a consumer can find (Section 6.4). In a log that carries the decision alone it is undetectable. The same construction applies to the sixth field. Section 8 of [AIMS] defines posture assessment as an evaluation performed at credential provisioning, while the sixth field asks for the posture "influencing the decision". A conformant record may therefore carry a posture that was accurate at issuance and inaccurate at decision time, with nothing in the record to say which. Carrying posture as the decision point read it, beside the posture as it was observed and its assessedAt, makes that difference visible without constraining either value. Gilda Expires 30 April 2027 [Page 43] Internet-Draft Agent Audit Record October 2026 A.3. Why the tier carries five clauses Each clause of the tier recompute closes one route by which a record could claim an observer's vantage while carrying nothing that distinguishes it from a self-report. vantage of below-observed is the claim itself, and the four clauses under it make the claim cost something. The prior commitment binds the before-state before the interval opens, so a producer cannot decide after the fact what it saw. A non-empty pathScope means the record names the ground it covers. A complete coverage claim, which no listed gap inside that ground may contradict, means the record does not quietly exclude the interesting part. A gap outside that ground does not count against it, because the record claims nothing there. And a digest-bound resource means the arguments of the call are pinned. Dropping any one of them admits a record that carries the authority of the rest while resting on nothing. That is why the corpus in Appendix B carries one reject member per clause. Appendix B. Conformance vectors The table below is the conformance corpus for this format. Each row gives a member identifier, the accept member it derives from, its input, and the verdict a conforming verifier reaches. A reject differs from the accept member in its from column by one mutation, so refusing every input scores nothing on this corpus. An accept member has no parent and its from column reads root. An indeterminate member has more than one conforming verdict and its row gives each. A member whose input is a retained record (R1 to R9) is an envelope with its retention entry, and its row gives the envelope's verdict and the result of the dating check separately. The first in column names the release of the agent-evidence-vectors corpus that first published a member under that identifier, or next for a member no release carries yet. Because evaluation.inputs is required here, every member published under draft-gilda-wimse-agent- audit-record-02 is malformed under this revision (vector EV13), and release v0.26.0 regenerated the whole family under draft-gilda-audit- agent-audit-record-00. Each member kept its identifier and its row, with the entries it needs in evaluation.inputs; vector A10 carries standing-source with a lastResult of none, and vector N1 changes verdict as Section 5.6 states. Release v0.26.2 also carries seven members with no row here, FR13b, FR16, FR17a to FR17c, FR18 and EV14, each testing a rule of Section 5.4. Gilda Expires 30 April 2027 [Page 44] Internet-Draft Agent Audit Record October 2026 Every row names the rule it tests. Three rules this document adds have no member in the table: the binding on the digest map in Section 4.2, the [RFC3339] requirement in Section 4.3, and the single hash algorithm of Section 5.1. An implementation SHOULD be run against every member of the corpus before it is described as conforming to this document, and the three rules above are checked by reading them. The corpus travels with the predicate schema: the revision of this document that freezes the predicate type URI is the revision that publishes these members in [VECTORS], in that repository's manifest layout. +====+====+=============================+================+==========+ |id |from| what it is | expected | first in | +====+====+=============================+================+==========+ |A1 |root| every member present, | valid | v0.18.1 | | | | permit beside occurred, all | | | | | | five tier clauses met | | | +----+----+-----------------------------+----------------+----------+ |A2 |root| deny beside none, equal | valid | v0.18.1 | | | | roots, empty write set | | | +----+----+-----------------------------+----------------+----------+ |A3 |root| A1 with deny beside | valid | v0.18.1 | | | | occurred and agreement of | | | | | | disagree | | | +----+----+-----------------------------+----------------+----------+ |A4 |root| A1 plus a remediation event | valid | v0.18.1 | | | | with enforcement of not- | | | | | | enforced | | | +----+----+-----------------------------+----------------+----------+ |A5 |root| A1 with vantage of self, no | valid | v0.18.1 | | | | prior commitment, tier of | | | | | | voluntary | | | +----+----+-----------------------------+----------------+----------+ |A6 |root| A1 with binding of not- | valid | v0.18.1 | | | | bindable, argumentsDigest | | | | | | absent from the record and | | | | | | from the request-digest | | | | | | preimage, tier of voluntary | | | +----+----+-----------------------------+----------------+----------+ |A7 |root| A2 plus one in-scope write | valid, | v0.18.1 | | | | inside the interval | agreement of | | | | | attributed to a different | agree | | | | | request, roots and chain | | | | | | moved to match | | | +----+----+-----------------------------+----------------+----------+ |A8 |root| A2 plus one in-scope | valid, | v0.18.1 | Gilda Expires 30 April 2027 [Page 45] Internet-Draft Agent Audit Record October 2026 | | | unattributed write inside | agreement of | | | | | the interval, | indeterminate | | | | | effect.observed of unknown | | | +----+----+-----------------------------+----------------+----------+ |A9 |root| A1 with permit beside an | valid, | v0.18.1 | | | | empty write set, equal | agreement of | | | | | roots, effect.observed of | not-exercised | | | | | none | | | +----+----+-----------------------------+----------------+----------+ |A10 |root| A2 with evaluation.status | valid, | v0.18.1 | | | | of not-evaluated and | agreement of | | | | | unavailableInput of | agree | | | | | standing-source | | | +----+----+-----------------------------+----------------+----------+ |A11 |root| A1 plus oversight with act | valid | v0.18.1 | | | | of check and a recordDigest | | | +----+----+-----------------------------+----------------+----------+ |A12 |root| A10 with unavailableInput | valid, | v0.18.1 | | | | of key-source | agreement of | | | | | | agree | | +----+----+-----------------------------+----------------+----------+ |A13 |root| A10 with unavailableInput | valid, | v0.18.1 | | | | of consumption-state | agreement of | | | | | | agree | | +----+----+-----------------------------+----------------+----------+ |A14 |root| A10 with unavailableInput | valid, | v0.18.1 | | | | naming all three inputs of | agreement of | | | | | -02, each once, in neither | agree | | | | | the table order nor sorted | | | | | | order | | | +----+----+-----------------------------+----------------+----------+ |A15 |root| A11 with oversight.act of | valid | v0.18.1 | | | | observation | | | +----+----+-----------------------------+----------------+----------+ |A16 |root| A11 with oversight.act of | valid | v0.18.1 | | | | decision and no | | | | | | recordDigest, which is | | | | | | optional | | | +----+----+-----------------------------+----------------+----------+ |A17 |root| A11 with oversight.act of | valid | v0.18.1 | | | | release | | | +----+----+-----------------------------+----------------+----------+ |A18 |root| A1 with evaluation.status | valid, | v0.26.0 | | | | of not-evaluated, policy- | agreement of | | | | | source never established, | agree | | | | | unavailableInput of policy- | | | | | | source and the allow-all | | | | | | fallback's | | | Gilda Expires 30 April 2027 [Page 46] Internet-Draft Agent Audit Record October 2026 | | | decision.policyDigest | | | +----+----+-----------------------------+----------------+----------+ |A19 |root| A3 with evaluation.status | valid, | v0.26.0 | | | | of not-evaluated, key- | agreement of | | | | | source and consumption- | disagree | | | | | state stale, and | | | | | | unavailableInput naming | | | | | | both | | | +----+----+-----------------------------+----------------+----------+ |A20 |root| A2 with evaluation.status | valid, | v0.26.0 | | | | of not-evaluated, a profile | agreement of | | | | | the request names not held, | agree | | | | | unavailableInput of policy- | | | | | | source and the deny-all | | | | | | fallback's | | | | | | decision.policyDigest | | | +----+----+-----------------------------+----------------+----------+ |A21 |root| A1 with | valid | next | | | | agent.authentication of | | | | | | api-key | | | +----+----+-----------------------------+----------------+----------+ |F1 |A1 | A1 with the whole agent | malformed | v0.18.1 | | | | member removed | | | +----+----+-----------------------------+----------------+----------+ |F2 |A1 | subjectKind of none beside | malformed | v0.18.1 | | | | a named subject | | | +----+----+-----------------------------+----------------+----------+ |F3 |A1 | digest-bound with | malformed | v0.18.1 | | | | argumentsDigest removed | | | +----+----+-----------------------------+----------------+----------+ |F3b |A6 | not-bindable carrying | malformed | v0.18.1 | | | | argumentsDigest of null | | | +----+----+-----------------------------+----------------+----------+ |F3c |A6 | not-bindable carrying | malformed | v0.18.1 | | | | argumentsDigest of the | | | | | | empty string | | | +----+----+-----------------------------+----------------+----------+ |F4 |A1 | action changed, | malformed | v0.18.1 | | | | requestDigest left at its | | | | | | original value | | | +----+----+-----------------------------+----------------+----------+ |F5 |A1 | beacon-anchored with | malformed | v0.18.1 | | | | externalAnchor removed | | | +----+----+-----------------------------+----------------+----------+ |F6 |A1 | two unequal postures | malformed | v0.18.1 | | | | declared as agree | | | +----+----+-----------------------------+----------------+----------+ |F7 |A4 | enforcedAt one second | malformed | v0.18.1 | Gilda Expires 30 April 2027 [Page 47] Internet-Draft Agent Audit Record October 2026 | | | before signalReceivedAt | | | +----+----+-----------------------------+----------------+----------+ |T1 |A1 | effect.observed edited to | malformed | v0.18.1 | | | | none, writes intact, signed | | | | | | again with the real key | | | +----+----+-----------------------------+----------------+----------+ |T2 |A1 | serialized in declaration | malformed | v0.18.1 | | | | order, not [RFC8785] order | | | +----+----+-----------------------------+----------------+----------+ |T3 |A1 | a member name repeated at | malformed | v0.18.1 | | | | depth three | | | +----+----+-----------------------------+----------------+----------+ |T4 |A1 | nesting 129 levels deep | malformed | v0.18.1 | +----+----+-----------------------------+----------------+----------+ |T5 |A1 | an integer of magnitude | malformed | v0.18.1 | | | | exactly 2^53 | | | +----+----+-----------------------------+----------------+----------+ |D1 |A1 | agreement of disagree with | malformed | v0.18.1 | | | | both sides agreeing | | | +----+----+-----------------------------+----------------+----------+ |D2 |A1 | agreement of one-sided with | malformed | v0.18.1 | | | | both values present | | | +----+----+-----------------------------+----------------+----------+ |D3 |A9 | agreement of disagree | malformed | v0.18.1 | | | | beside permit and none | | | +----+----+-----------------------------+----------------+----------+ |S1 |A1 | second subject entry | malformed | v0.18.1 | | | | removed, interval left | | | | | | present | | | +----+----+-----------------------------+----------------+----------+ |S2 |A1 | second subject entry's | malformed | v0.18.1 | | | | digest set to the before- | | | | | | state root | | | +----+----+-----------------------------+----------------+----------+ |I1r |A1 | interval removed, second | malformed | v0.18.1 | | | | subject entry left present | | | +----+----+-----------------------------+----------------+----------+ |TI1 |A1 | authoritative declared with | malformed | v0.18.1 | | | | vantage of self | | | +----+----+-----------------------------+----------------+----------+ |TI2 |A1 | authoritative declared with | malformed | v0.18.1 | | | | no prior commitment | | | +----+----+-----------------------------+----------------+----------+ |TI3 |A1 | authoritative declared with | malformed | v0.18.1 | | | | an empty pathScope | | | +----+----+-----------------------------+----------------+----------+ |TI4 |A1 | authoritative declared with | malformed | v0.18.1 | | | | scopeComplete of false and | | | Gilda Expires 30 April 2027 [Page 48] Internet-Draft Agent Audit Record October 2026 | | | a coverage gap inside | | | | | | pathScope | | | +----+----+-----------------------------+----------------+----------+ |TI5 |A6 | authoritative declared on | malformed | v0.18.1 | | | | A6 | | | +----+----+-----------------------------+----------------+----------+ |TI6 |A1 | authoritative declared with | malformed | v0.26.0 | | | | scopeComplete of false and | | | | | | gaps naming only paths | | | | | | outside pathScope, which | | | | | | draft-gilda-audit-agent- | | | | | | audit-record-00 accepted | | | +----+----+-----------------------------+----------------+----------+ |C1 |A1 | commitment keyid added to | malformed | v0.18.1 | | | | agent.signers | | | +----+----+-----------------------------+----------------+----------+ |C2 |A1 | committedAt one second | malformed | v0.18.1 | | | | after openedAt | | | +----+----+-----------------------------+----------------+----------+ |C3 |A1 | witnessNonce changed, | malformed | v0.18.1 | | | | commitmentDigest left at | | | | | | its original value | | | +----+----+-----------------------------+----------------+----------+ |E1 |A2 | observed of none with a | malformed | v0.18.1 | | | | non-empty write set | | | +----+----+-----------------------------+----------------+----------+ |E2 |A1 | a second write whose pre- | malformed | v0.18.1 | | | | state is not the first | | | | | | write's post-state | | | +----+----+-----------------------------+----------------+----------+ |E3 |A1 | empty-tree under sha256 | malformed | v0.18.1 | | | | carrying the sha1 constant | | | +----+----+-----------------------------+----------------+----------+ |E4 |A1 | the only write's pre-state | malformed | v0.26.0 | | | | is not the before-state | | | | | | root, its post-state is the | | | | | | after-state root | | | +----+----+-----------------------------+----------------+----------+ |E5 |A1 | the only write starts from | malformed | v0.26.0 | | | | the before-state root and | | | | | | its post-state is not the | | | | | | after-state root | | | +----+----+-----------------------------+----------------+----------+ |E6 |A2 | an empty write set beside | malformed | v0.26.0 | | | | an after-state root unequal | | | | | | to the before-state root, | | | | | | second subject moved to | | | | | | match | | | Gilda Expires 30 April 2027 [Page 49] Internet-Draft Agent Audit Record October 2026 +----+----+-----------------------------+----------------+----------+ |V1 |A4 | enforcement of quarantined, | malformed | v0.18.1 | | | | outside the closed set | | | +----+----+-----------------------------+----------------+----------+ |V2 |A1 | a pathScope member carrying | malformed | v0.18.1 | | | | a glob metacharacter | | | +----+----+-----------------------------+----------------+----------+ |V3 |A1 | a write outside pathScope | malformed | v0.18.1 | | | | carrying inScope of true | | | +----+----+-----------------------------+----------------+----------+ |V4 |A1 | scopeComplete of true | malformed | v0.26.0 | | | | beside a gap inside | | | | | | pathScope, all other tier | | | | | | clauses met | | | +----+----+-----------------------------+----------------+----------+ |V5 |A5 | scopeComplete of true | malformed | v0.26.0 | | | | beside a gap inside | | | | | | pathScope, tier of | | | | | | voluntary | | | +----+----+-----------------------------+----------------+----------+ |FE1 |A1 | six of the seven | malformed | v0.18.1 | | | | fieldEvidence keys present | | | +----+----+-----------------------------+----------------+----------+ |FE2 |A5 | substrate-covered declared | malformed | v0.18.1 | | | | beside vantage of self | | | +----+----+-----------------------------+----------------+----------+ |FR1 |root| A1 written by the second of | valid | v0.26.0 | | | | two hops: each input fresh | | | | | | at decision.reportedAt, one | | | | | | carried from the first hop | | | | | | with the source's | | | | | | lastResult unchanged | | | +----+----+-----------------------------+----------------+----------+ |FR2 |root| FR1 with one input's age at | valid, the | v0.26.0 | | | | decision.reportedAt exactly | input fresh | | | | | equal to its maxAge | | | +----+----+-----------------------------+----------------+----------+ |FR3 |root| A10 written by the second | valid, | v0.26.0 | | | | of two hops, the forwarded | agreement of | | | | | standing-source one second | agree | | | | | older than its maxAge | | | +----+----+-----------------------------+----------------+----------+ |FR4 |root| A10 written by the second | valid, | v0.26.0 | | | | of two hops, which received | agreement of | | | | | standing-source as never | agree | | | | | established, lastResult of | | | | | | none | | | +----+----+-----------------------------+----------------+----------+ Gilda Expires 30 April 2027 [Page 50] Internet-Draft Agent Audit Record October 2026 |FR5 |FR1 | an entry with lastResult | malformed | v0.26.0 | | | | removed | | | +----+----+-----------------------------+----------------+----------+ |FR6 |FR1 | an entry with maxAge | malformed | v0.26.0 | | | | removed | | | +----+----+-----------------------------+----------------+----------+ |FR7 |FR3 | unavailableInput naming | malformed | v0.26.0 | | | | key-source, whose entry is | | | | | | fresh, in place of | | | | | | standing-source | | | +----+----+-----------------------------+----------------+----------+ |FR8 |FR1 | evaluated beside an entry | malformed | v0.26.0 | | | | one second older than its | | | | | | maxAge | | | +----+----+-----------------------------+----------------+----------+ |FR9 |FR1 | an entry whose lastResult | malformed | v0.26.0 | | | | is later than | | | | | | decision.reportedAt by more | | | | | | than the skew tolerance | | | +----+----+-----------------------------+----------------+----------+ |FR10|FR1 | one input named in two | malformed | v0.26.0 | | | | entries | | | +----+----+-----------------------------+----------------+----------+ |FR11|FR1 | an entry carrying a fourth | malformed | v0.26.0 | | | | member this document does | | | | | | not define | | | +----+----+-----------------------------+----------------+----------+ |FR12|FR1 | an entry whose input is | malformed | v0.26.0 | | | | network, outside the closed | | | | | | set | | | +----+----+-----------------------------+----------------+----------+ |FR13|FR1 | an entry with a negative | malformed | v0.26.0 | | | | maxAge | | | +----+----+-----------------------------+----------------+----------+ |FR14|root| A2 judging two delegation | valid, | v0.26.0 | | | | paths, two values of | agreement of | | | | | standing-source each fresh | agree | | | | | at decision.reportedAt | | | | | | (ages 30 and 3600 seconds | | | | | | under a maxAge of 60 and of | | | | | | 7200), the entry carrying | | | | | | the first value's pair | | | +----+----+-----------------------------+----------------+----------+ |FR15|FR14| the entry carrying the | malformed | v0.26.0 | | | | second value's lastResult | | | | | | beside the first value's | | | | | | maxAge, under evaluated | | | +----+----+-----------------------------+----------------+----------+ Gilda Expires 30 April 2027 [Page 51] Internet-Draft Agent Audit Record October 2026 |EV1 |A10 | not-evaluated with | malformed | v0.18.1 | | | | unavailableInput removed | | | +----+----+-----------------------------+----------------+----------+ |EV2 |A2 | evaluated carrying | malformed | v0.18.1 | | | | unavailableInput of | | | | | | standing-source | | | +----+----+-----------------------------+----------------+----------+ |EV3 |A1 | the evaluation member | malformed | v0.18.1 | | | | removed, which is the shape | | | | | | of a revision 01 record | | | +----+----+-----------------------------+----------------+----------+ |EV4 |A10 | unavailableInput of | malformed | v0.18.1 | | | | network, outside the closed | | | | | | set | | | +----+----+-----------------------------+----------------+----------+ |EV5 |A10 | not-evaluated with | malformed | v0.18.1 | | | | unavailableInput of the | | | | | | empty array | | | +----+----+-----------------------------+----------------+----------+ |EV6 |A10 | not-evaluated with | malformed | v0.18.1 | | | | standing-source named twice | | | +----+----+-----------------------------+----------------+----------+ |EV7 |A10 | not-evaluated with | malformed | v0.18.1 | | | | unavailableInput of the | | | | | | string standing-source, not | | | | | | an array | | | +----+----+-----------------------------+----------------+----------+ |EV8 |A2 | evaluated carrying | malformed | v0.18.1 | | | | unavailableInput of null | | | +----+----+-----------------------------+----------------+----------+ |EV9 |A2 | evaluated carrying | malformed | v0.18.1 | | | | unavailableInput of the | | | | | | empty array | | | +----+----+-----------------------------+----------------+----------+ |EV10|A2 | evaluated carrying | malformed | v0.18.1 | | | | unavailableInput of the | | | | | | empty string | | | +----+----+-----------------------------+----------------+----------+ |EV11|A10 | evaluation.status of | malformed | v0.26.0 | | | | partially-evaluated, | | | | | | outside the closed set | | | +----+----+-----------------------------+----------------+----------+ |EV12|A10 | evaluation carrying a free- | malformed | v0.26.0 | | | | text reason member this | | | | | | document does not define | | | +----+----+-----------------------------+----------------+----------+ |EV13|A1 | evaluation.inputs removed, | malformed | v0.26.0 | | | | the shape of a record under | | | Gilda Expires 30 April 2027 [Page 52] Internet-Draft Agent Audit Record October 2026 | | | draft-gilda-wimse-agent- | | | | | | audit-record-02 | | | +----+----+-----------------------------+----------------+----------+ |OV1 |A11 | oversight.act of approval, | malformed | v0.18.1 | | | | outside the closed set | | | +----+----+-----------------------------+----------------+----------+ |OV2 |A11 | oversight carrying a member | malformed | v0.18.1 | | | | this document does not | | | | | | define | | | +----+----+-----------------------------+----------------+----------+ |OV3 |A11 | oversight with act removed | malformed | v0.18.1 | | | | and recordDigest kept | | | +----+----+-----------------------------+----------------+----------+ |SQ1 |root| A1 with sequence carrying a | valid | next | | | | boundary and a seq of 1 | | | +----+----+-----------------------------+----------------+----------+ |SQ2 |SQ1 | sequence carrying a count | malformed | next | | | | member this document does | | | | | | not define | | | +----+----+-----------------------------+----------------+----------+ |SQ3 |SQ1 | sequence with a seq of 0 | malformed | next | +----+----+-----------------------------+----------------+----------+ |SQ4 |root| records of one series with | each record | next | | | | seq 1 and 3 held, seq 2 not | valid, the | | | | | held | set names seq | | | | | | 2 as issued | | | | | | and not | | | | | | received | | +----+----+-----------------------------+----------------+----------+ |SQ5 |root| two records of one series | each record | next | | | | with the same seq and | valid, the | | | | | different envelope digests | set fails the | | | | | | check | | +----+----+-----------------------------+----------------+----------+ |N1 |A1 | an anchor token digest | valid, not | v0.18.1, | | | | carried in | dated by the | verdict | | | | correlation.externalAnchor, | anchor | changed | | | | the proof not held | | | +----+----+-----------------------------+----------------+----------+ |N2 |A4 | enforcement forty days | indeterminate | v0.18.1 | | | | after the signal, ordering | | | | | | intact | | | +----+----+-----------------------------+----------------+----------+ |R1 |root| A1 retained by its | record valid, | v0.26.0 | | | | producer: received of false | dated at the | | | | | and one anchor of origin | anchor's time | | | | | retainer inside | | | | | | anchorWithin of issuedAt | | | Gilda Expires 30 April 2027 [Page 53] Internet-Draft Agent Audit Record October 2026 +----+----+-----------------------------+----------------+----------+ |R2 |root| A1 received from another | record valid, | v0.26.0 | | | | party, receivedAt between | receipt time | | | | | issuedAt and the retaining | asserted and | | | | | party's anchor obtained on | consistent | | | | | delivery | | | +----+----+-----------------------------+----------------+----------+ |R3 |R2 | receivedAt later than the | record valid, | v0.26.0 | | | | retaining party's earliest | entry | | | | | anchor by more than the | malformed | | | | | skew tolerance | | | +----+----+-----------------------------+----------------+----------+ |R4 |R2 | received of true and no | record valid, | v0.26.0 | | | | anchor of origin retainer | entry | | | | | | malformed | | +----+----+-----------------------------+----------------+----------+ |R5 |root| R2 with the retaining | record valid, | v0.26.0 | | | | party's anchor obtained | receipt time | | | | | before delivery and | asserted and | | | | | receivedAt inside the | consistent, | | | | | bracket | never | | | | | | established | | +----+----+-----------------------------+----------------+----------+ |R6 |R2 | receivedAt earlier than | record valid, | v0.26.0 | | | | issuedAt by more than the | entry | | | | | skew tolerance | malformed | | +----+----+-----------------------------+----------------+----------+ |R7 |R1 | the retaining party's first | record valid, | v0.26.0 | | | | anchor later than issuedAt | entry | | | | | by more than anchorWithin | malformed | | | | | plus the skew tolerance | | | +----+----+-----------------------------+----------------+----------+ |R8 |R1 | the only anchor's proof is | record valid, | v0.26.0 | | | | over a different envelope | not dated | | | | | digest | | | +----+----+-----------------------------+----------------+----------+ |R9 |R1 | receivedAt carried beside | record valid, | v0.26.0 | | | | received of false | entry | | | | | | malformed | | +----+----+-----------------------------+----------------+----------+ |R10 |R2 | the retaining party's | record valid, | next | | | | anchor is opentimestamps, | receipt time | | | | | its block header time 600 | asserted and | | | | | seconds earlier than | consistent | | | | | receivedAt | | | +----+----+-----------------------------+----------------+----------+ |R11 |R10 | the block header time | record valid, | next | | | | earlier than receivedAt by | entry | | Gilda Expires 30 April 2027 [Page 54] Internet-Draft Agent Audit Record October 2026 | | | more than 7200 seconds | malformed | | +----+----+-----------------------------+----------------+----------+ |R12 |R1 | anchors holding a pending | record valid, | next | | | | OpenTimestamps proof | dated at the | | | | | followed by its upgraded, | upgraded | | | | | complete proof | proof's block | | | | | | time, the | | | | | | pending | | | | | | element | | | | | | dating | | | | | | nothing | | +----+----+-----------------------------+----------------+----------+ |R13 |root| R1 for a record carrying | record valid, | next | | | | delegation.rootDigest, with | delegation | | | | | a delegation-root element | root | | | | | whose digest equals it | established, | | | | | | its algorithm | | | | | | derived from | | | | | | the element | | +----+----+-----------------------------+----------------+----------+ |R14 |R13 | the delegation-root element | record valid, | next | | | | omitted | delegation | | | | | | root not | | | | | | established, | | | | | | never | | | | | | reported as a | | | | | | pass | | +----+----+-----------------------------+----------------+----------+ |R15 |R13 | the delegation-root | record valid, | next | | | | element's digest unequal to | entry | | | | | delegation.rootDigest | malformed | | +----+----+-----------------------------+----------------+----------+ |R16 |R1 | the only anchor an | record valid, | next | | | | opentimestamps proof whose | dated at the | | | | | path runs from | block time | | | | | envelopeDigest through a | | | | | | Merkle tree the retaining | | | | | | party built and a Bitcoin | | | | | | transaction carrying its | | | | | | root to the block header | | | +----+----+-----------------------------+----------------+----------+ |CS1 |root| A1 under a cumulative | valid, | next | | | | limit: a consumption-state | withinLimit | | | | | entry with consumption, the | true | | | | | request within the limit | | | | | | and nothing held | | | +----+----+-----------------------------+----------------+----------+ |CS2 |root| CS1 with permit and | valid, | next | Gilda Expires 30 April 2027 [Page 55] Internet-Draft Agent Audit Record October 2026 | | | consumed plus requested | withinLimit | | | | | beyond limit | false | | +----+----+-----------------------------+----------------+----------+ |CS3 |CS1 | reserved not equal to the | malformed | next | | | | sum of the held amounts | | | +----+----+-----------------------------+----------------+----------+ |CS4 |root| a retry whose | valid, | next | | | | decision.requestDigest is | withinLimit | | | | | in held with an equal | true | | | | | amount, within the limit | | | | | | only because it is not | | | | | | counted twice | | | +----+----+-----------------------------+----------------+----------+ |CS5 |CS1 | a negative requested | malformed | next | +----+----+-----------------------------+----------------+----------+ |CS6 |CS1 | consumption on an entry | malformed | next | | | | whose input is policy- | | | | | | source | | | +----+----+-----------------------------+----------------+----------+ |CS7 |root| two retained records under | each record | next | | | | one limitDigest: the second | valid, the | | | | | permit read a stateRevision | retained set | | | | | older than the record | fails the | | | | | holding the first, | check across | | | | | unsettled permit, and omits | records | | | | | it from held | | | +----+----+-----------------------------+----------------+----------+ |CS8 |root| two retained records under | each record | next | | | | one limitDigest: a permit | valid, the | | | | | released from held with no | retained set | | | | | record of that request | fails the | | | | | showing none | check across | | | | | | records | | +----+----+-----------------------------+----------------+----------+ |CS9 |CS1 | consumption with | malformed | next | | | | stateRevision removed | | | +----+----+-----------------------------+----------------+----------+ Table 4: The conformance corpus, one member for every normative rule this document adds Gilda Expires 30 April 2027 [Page 56] Internet-Draft Agent Audit Record October 2026 Appendix C. Mapping to the AUDIT problem statement The table below takes each problem the AUDIT BoF request [AUDIT-BOFREQ] and the proposed charter [AUDIT-CHARTER] name, quoted or closely paraphrased from those texts, and gives the part of this document that addresses it. Where this document leaves a problem to other work, the row says so. The charter's first deliverable, an architecture, and its third and fourth, protocol extensions and deployment practice, are outside a record format; the rows below fall under its second deliverable, audit data models and semantics, unless a row names another. +======================+=============+============================+ | AUDIT problem | where it is | this document | | | stated | | +======================+=============+============================+ | who initiated an | BoF request | agent.id, | | action | | agent.credentialDigest, | | | | delegation.subject and | | | | delegation.subjectKind, | | | | Section 5 | +----------------------+-------------+----------------------------+ | under which | BoF request | delegation.authorityDigest | | authority it | | and decision.policyDigest, | | occurred | | with evaluation saying | | | | whether the authority was | | | | evaluated, Section 5 and | | | | Section 5.4 | +----------------------+-------------+----------------------------+ | how permissions | BoF request | one record per decision, | | evolved during | | joined by correlation.id; | | execution | | remediation for each | | | | revocation or downgrade | | | | with its enforcement and | | | | the effect after it, | | | | Section 5.6. A record | | | | carries one delegation hop | | | | and no delegation chain | +----------------------+-------------+----------------------------+ | attributing actions | charter, | agent and delegation, with | | to a user, an agent | challenges | the request bound by | | instance or a | | digest to the action, | | delegation context | | resource and arguments, | | | | Section 5 | +----------------------+-------------+----------------------------+ | visibility across | charter, | correlation.id with | | long-running or | challenges | correlation.scope of | | distributed | | cross-party, and the | Gilda Expires 30 April 2027 [Page 57] Internet-Draft Agent Audit Record October 2026 | workflows | | subject convention that | | | | binds one identifier to | | | | the request, the interval | | | | and the record, | | | | Section 4.2 and | | | | Section 5.6 | +----------------------+-------------+----------------------------+ | delegation | charter, | the authorization context | | relationships, | challenges | of each decision, | | dynamic | | including the freshness of | | authorization | | every input it relied on, | | context and identity | | Section 5.4; identity | | transitions | | transitions are left to | | | | the identity work the | | | | charter relies on | +----------------------+-------------+----------------------------+ | interoperable means | charter, | the canonical form, | | to exchange or | challenges | Section 4.1; the | | verify audit | | verification order, | | information across | | Section 4.6; the open | | domains | | conformance corpus, | | | | Appendix B and Section 10 | +----------------------+-------------+----------------------------+ | verifiable by a | charter | the recomputes, which | | party that trusts | | refuse a record its own | | neither the agent | | key holder altered | | nor its operator | | inconsistently, | | | | Section 4.4; the derived | | | | tier, Section 5.7; and | | | | what a record cannot | | | | prove, Section 6 | +----------------------+-------------+----------------------------+ | user intent | BoF | not carried; a record can | | | request, | bind an intent record by | | | charter | digest as it binds the | | | | authority document, and | | | | keeps the user's statement | | | | apart from the decision | +----------------------+-------------+----------------------------+ | invoked or declined | BoF | decision.reported beside | | actions | request, | effect.observed and the | | | charter | derived agreement, so a | | | | declined action that took | | | | effect is visible, | | | | Section 5 | +----------------------+-------------+----------------------------+ | exchanged data | BoF | resource.argumentsDigest | | | request, | binds the arguments by | Gilda Expires 30 April 2027 [Page 58] Internet-Draft Agent Audit Record October 2026 | | charter | digest and carries none of | | | | them, Section 5 and | | | | Section 7 | +----------------------+-------------+----------------------------+ | resulting outcomes | BoF | effect, its write chain | | | request, | and the before-state and | | | charter | after-state roots, | | | | Section 5 | +----------------------+-------------+----------------------------+ | a common identifier | BoF | correlation.id, the first | | linking user intent | request, | subject entry's name, | | to resulting actions | charter | Section 4.2 and | | across boundaries | | Section 4.3 | +----------------------+-------------+----------------------------+ | authorization as a | charter | evaluation.inputs, | | time-evolving state | | posture.assessedAt and | | | | remediation, Section 5.4 | | | | and Section 5.6 | +----------------------+-------------+----------------------------+ | selective disclosure | charter | digests in place of the | | and privacy | | bound documents, and | | | | anchors over a digest | | | | alone, Section 7; no | | | | mechanism for disclosing | | | | part of a record's own | | | | members | +----------------------+-------------+----------------------------+ | collecting, | charter, | what a retaining party | | aggregating, | scope and | keeps, the anchor kinds | | verifying and | deliverable | including a transparency | | transparency-logging | 2 | log, and the dating check, | | records, possibly by | | Section 4.7; no protocol | | an independent | | for collection or | | auditor | | retrieval | +----------------------+-------------+----------------------------+ | a data model for | BoF | this document | | records | request, | | | | new work | | +----------------------+-------------+----------------------------+ | protocols to store | BoF | not defined; Section 4.7 | | and retrieve records | request, | defines what is stored and | | | new work | leaves the protocol open | +----------------------+-------------+----------------------------+ Table 5: AUDIT problems and the parts of this document that address them Gilda Expires 30 April 2027 [Page 59] Internet-Draft Agent Audit Record October 2026 Document History This document replaces draft-gilda-wimse-agent-audit-record. Its target is the AUDIT BoF and the working group it proposes. The revisions listed below as -02, -01 and -00 are revisions of that document. Changes in draft-gilda-audit-agent-audit-record-01: * Section 9 states what a conforming producer and verifier are, ties verifier conformance to release 0.26.2 of [VECTORS], and lists the identifiers a referencing document may rely on. The intended status is Standards Track, so that a working group document can reference this one normatively. * Section 10 and Appendix B name release v0.26.2, which regenerated the corpus under draft-gilda-audit-agent-audit-record-00 and carries 111 members, and the first in column names v0.26.0 for the 36 members that release first published. [VECTORS] and [VOCABULARY] are referenced at tagged releases. * Section 5.9 adds the value a decision under a cumulative limit read. A consumption-state entry carries consumption: the limit's document digest, the unit, the limit, the amounts committed, held and requested, the permits held and the state revision read. A verifier derives withinLimit, a retried request held for a lost response is not counted twice, a held permit is released only by a record of that request showing none, and two checks across retained records find one limit spent twice. Under -00 an entry recorded the freshness of the consumption state and not the amount it showed. * Nine members are added to Appendix B: CS1 to CS9. * Where a decision depended on several values of one input, an entry's lastResult and maxAge are taken from the same value, the one whose lastResult plus maxAge is earliest. Under -00 the entry took the oldest lastResult and the smallest maxAge from different values, which could report two fresh values as one stale input. Vectors FR14 and FR15. * Section 4.2 states the interval condition on what was observed rather than on the decision. Under -00 it said a denied decision carries an empty write set, which contradicted vectors A3 and A7; a write attributed to a denied request is retained and yields disagree. Appendix A describes a deny beside occurred as a well- formed disagreement, not a refusable inconsistency, and refers to the agreement table instead of counting its values. Gilda Expires 30 April 2027 [Page 60] Internet-Draft Agent Audit Record October 2026 * Section 4.4, Section 5.3, Section 6 and Appendix A narrow the claim about a record the key holder signed again. The recomputes refuse an inconsistent alteration; a coherent replacement, in which every dependent member is changed to match and the record is signed again, passes them, and is found only by comparison with a copy or an anchor of the original that the key holder does not control. * Section 5.7 defines coverage.scopeComplete and coverage.gaps. A gap inside pathScope beside a scopeComplete of true is malformed at any tier, and the coverage clause of the tier recompute is scopeComplete of true. Under -00 the clause was a disjunction that passed a record declaring complete coverage beside a listed gap inside its own scope, and one declaring incomplete coverage while naming no gap inside it. Vectors TI6, V4 and V5. * Section 4.7.2 defines the time of an opentimestamps anchor as the timestamp of the Bitcoin block header its proof reaches, and gives comparisons with that time a tolerance of 7200 seconds, the consensus limit on a header time ahead of a validating node's clock, in place of the 300-second skew tolerance. Two such times are ordered by block height. Under -00 the time was unspecified, and an honest retaining party could fail the receipt bracket. Vectors R10 and R11. * Section 4.7 states that only an anchor that validates meets anchorWithin, so for a retaining party that relies on opentimestamps alone, anchorWithin covers the latency before a pending proof is confirmed in a block. * Section 4.7 states that an upgraded proof is appended as a new element beside the pending one it completes, which stays and dates nothing; no element is rewritten in place. Vector R12. * delegation.rootDigest, optional, binds the certification path or key set of the delegation chain's root key that the chain verifier trusted at decision time, and Section 4.7 keeps that material as a delegation-root element of validationData, from which a later reader derives the algorithm the chain rested on. It records what the verifier held and not how it came to hold it, and mandates no anchor topology. A retaining party that holds no such element reports the root as not established. Under -00 the record bound the authority document and not the root key the chain was verified under. Vectors R13 to R15. Gilda Expires 30 April 2027 [Page 61] Internet-Draft Agent Audit Record October 2026 * Section 4.7.2 states why an anchor kind names the proof format and not only its basis, carries a Merkle root published in a Bitcoin transaction as an opentimestamps proof, and states what a revision adding a kind for another ledger has to define. Vector R16. * agent.authentication gains api-key, for a bearer secret that is not an OAuth access token. Under -00 such a request matched no value, and none would have said that no authentication took place; none is now stated to mean exactly that. A digest of a bearer secret is stated to be testable against guesses. Vector A21. * Requirements stated with a lowercase "required" are restated with the BCP 14 keywords: the seventeen members, delegation.authorityDigest, evaluation.inputs and the members of each entry, the members of consumption, oversight.act and correlation.scope. No requirement changes. * Section 5.10 adds an optional sequence member, a series named by boundary and a seq that starts at 1 and rises by one, under the producer's signature. A party holding records of a series names a missing number below the highest it holds, and two records at one number fail the check. Section 6.3 separates a withheld record, which a missing number shows, from a record never produced, which nothing shows. Vectors SQ1 to SQ5. * Section 10 states that the published command checks records under draft-gilda-wimse-agent-audit-record-02 and is not a conformance check for this revision. * Section 5.9 and Section 5.10 follow Section 5.8, so that Sections 5.1 to 5.8 keep the numbers they had in -00 and in draft-gilda- wimse-agent-audit-record-02, as Section 1 states. * The acknowledgments credit the reviewers whose comments led to these changes. Changes in draft-gilda-audit-agent-audit-record-00: * Section 4.7 defines the retention entry a retaining party keeps beside a record: anchors over the envelope digest with their kind and origin, the validation data for the envelope and each anchor, and, for a received record, receivedAt. A verifier derives each anchor's time and algorithm family from its proof. * Section 4.6 gains the dating check. The earliest anchor that validates dates the record, and no issuance time a record states does. A received record must carry an anchor the retaining party obtained on delivery, and a receivedAt outside the bracket from Gilda Expires 30 April 2027 [Page 62] Internet-Draft Agent Audit Record October 2026 issuedAt to that anchor, within the skew tolerance, makes the entry malformed. The check is stated to be a consistency check: it rests on the sender's clock and on the retaining party anchoring on delivery, a digest anchored before delivery does not establish receipt, and the late-anchor limit is stated as an assumption. * Section 4.7.2 gives an offline validation rule for each anchor kind, and says when a transparency-log anchor is a hash commitment and when a signed token. The predicate's own correlation.externalAnchor dates nothing by itself, so vector N1 has one conforming verdict. * Section 5.4 gains evaluation.inputs, required under both statuses: one entry per input the decision depended on, with lastResult and maxAge, both required. Age is measured from lastResult to decision.reportedAt, an age equal to maxAge is fresh, and unavailableInput is derived from the entries and must match them. A forwarded value keeps the source's lastResult. Under draft- gilda-wimse-agent-audit-record-02 freshness could not be recorded for an input that was accepted. * unavailableInput gains policy-source, for a decision point that could not read its policy or does not hold the profile a request names. decision.policyDigest then names the fallback the decision point enforced. * The rule for evaluated is stated: the reported decision does not depend on any input the decision point could not obtain. decision.reported under not-evaluated is stated to be the outcome the decision point fell back to, so a fail-open is a permit and stays findable. * evaluation carries no member other than status, inputs and unavailableInput. Under the earlier revision a free-text reason beside the closed set was not refused. * Each input is mapped to the section of [EVALUATION] that defines it, and a transient refusal under that document is mapped to not- evaluated and a permanent one to evaluated with deny. * The write-chain replay is stated in Section 5: where the running root starts, what each write must match, and where it must end. Under the earlier revision the body required the replay without defining it. Gilda Expires 30 April 2027 [Page 63] Internet-Draft Agent Audit Record October 2026 * Section 4.6 applies the JSON profile before the signature, because deriving the [RFC8785] bytes the signature covers requires a parse the duplicate-member rule constrains. * A closed vocabulary is extended only by a revision, and after the predicate type URI freezes only under a new URI. No vocabulary carries a catch-all value. Section 8 states that no revision has yet frozen the URI. * A skew tolerance of 300 seconds is defined for every comparison between times written by two parties. * Section 10 records the open implementation, and Appendix C maps the problems the AUDIT BoF request and proposed charter name to this document. * A record under the earlier revision is malformed under this one, because it carries no evaluation.inputs (vector EV13). The corpus is regenerated, and 31 members are added to Appendix B: A18 to A20, E4 to E6, EV11 to EV13, FR1 to FR13 and R1 to R9. Changes in draft-gilda-wimse-agent-audit-record-02: * A required evaluation member records whether the decision point evaluated the request, and under not-evaluated names the unavailable inputs from a closed set (Section 5.4). Under -01 a verifier that lost its standing source and denied wrote a record identical to a correctly enforced denial. decision.reported and the agreement table are unchanged. * An optional oversight member records the kind of act a person took behind a decision, and may bind the overseer's own signed record by digest (Section 5.5). * A record conforming to -01 is malformed under -02, because it carries no evaluation member and no member has a default (vector EV3). The predicate type URI does not change: no revision has yet frozen it, and the corpus in [VECTORS] is regenerated against this revision. * Eight members are added to Appendix B: A10, A11, EV1 to EV4, OV1 and OV2. Changes in draft-gilda-wimse-agent-audit-record-01: Gilda Expires 30 April 2027 [Page 64] Internet-Draft Agent Audit Record October 2026 * The request-digest preimage under not-bindable is stated: three members, with no argumentsDigest member in any spelling. Under -00 the text named four members and forbade the fourth, so the preimage was open and three spellings gave three digests. * Each write carries the request digest it is attributed to, or unattributed. effect.observed describes this record's request, and it gains unknown for an unattributed write inside the scope. A write that belongs to another request no longer changes this record's agreement. * agreement gains not-exercised, for a permit beside no effect, and indeterminate, for an effect the observer could not attribute. Under -00 a permitted call that was never made read as disagree, the value a leaked deny also takes. * A statement whose signature fails is malformed, so Section 4.6 and vector T2 report the same verdict. * Six members are added to Appendix B: A7, A8, A9, F3b, F3c and D3. draft-gilda-wimse-agent-audit-record-00 was the first revision. Acknowledgments Cliff Singletary pointed out that an earlier revision could not record a decision point that was unable to evaluate, and proposed the separate member that leaves decision.reported and the agreement table untouched. Girish Konda reviewed that member against Section 5 of [EVALUATION], proposed adding the policy input to its closed set, and asked for the reference time, the boundary case and the freshness of accepted inputs that evaluation.inputs now carries. Wes Jackson proposed reading stale and never-established inputs from the as-of time and the maximum age. Venkata Uppalapati asked whether a receipt time could be bound to anything a later reader can check, which led to the receipt bracket, and named the late-anchor limit it leaves. Iman Schrock pointed out that the bracket is a consistency check and not proof of receipt, and proposed the case of a digest anchored before delivery. Andreas Ehstand asked whether the human act behind a permit belongs in this format and proposed the member that names its kind. Brian Campbell pointed this work to the AUDIT BoF. King Yew Choo asked how the record shows the amount already spent that a decision point read under a cumulative delegated limit, which led to Section 5.9. Mikhail Sergeev found that aggregating freshness across values could report two fresh values as stale and proposed the pairing rule, found that the text on a denied decision contradicted vectors A3 and A7, narrowed the claim about a record signed again, and found that a listed gap inside the scope did not override a Gilda Expires 30 April 2027 [Page 65] Internet-Draft Agent Audit Record October 2026 declaration of complete coverage; the wording of all four follows his. Toshikatsu Oga, from running OpenTimestamps anchors, asked which time an opentimestamps anchor carries and proposed the 7200-second tolerance, the reading of anchorWithin that covers confirmation latency, and appending an upgraded proof. Rafael Asor named the delegation root key a chain verifier trusts as a gap in what is recorded, V.K. Uppalapati separated the recording gap from the gap in how the root key arrives, and Kieran Sweeney warned against closing either by mandating an anchor topology; delegation.rootDigest follows all three. Lars Kersten Kroehl asked whether an anchor kind should name its basis, which value a bearer API key takes, and why a requirement was written in lowercase. Henri Sirkkavaara proposed the sequence member and the distinction between a withheld record and one never produced. Author's Address Sankalp Gilda Email: sankalp.gilda@gmail.com Gilda Expires 30 April 2027 [Page 66]