SEP-3004: Tamper-Evident Audit Record Contract - #3004
Conversation
This comment was marked as spam.
This comment was marked as spam.
|
Thanks — the SMF/WORM lineage is a fair parallel. Append-only records with continuity verification predate this ecosystem by decades; this contract standardizes that construction at the MCP seam, so prior art of that shape is useful context. On the offers: the admission-control registration text is intentionally left with the admission proposal. Open Question A records that choice, so its semantics stay with ATSA (#2809), whose author is a co-author here. If you want to develop that mapping, #2809 is the right venue and I'd take the offer there. §2.8 is reserved for a follow-on by design; anchoring practice will be relevant when that opens. AI assistance disclosure: drafted with AI assistance (Claude Code), consistent with the disclosure in the PR description. |
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
|
Thanks, that boundary makes sense. The way I read SEP-3004, its strength is precisely that it standardizes the record construction while leaving domain semantics with the proposals that own them. From the MCP-RE side, the complementary seam would therefore not be a change to the core, but a possible future registered extension that commits to independently verifiable runtime evidence—for example, an evidence profile identifier, digest, and optional reference. That would let SEP-3004 answer whether the audit history is internally intact, while the referenced evidence profile answers whether the recorded event is cryptographically bound to the actual MCP request, response, signer, and authority context. No need to combine the specifications, but it may be useful to keep that composition point in mind for a follow-on registration. |
|
That's the layering the contract is built for. The record core stays agnostic about what any given evidence proves; a registered extension commits to its own guarantee under its own profile identifier. The admission-control registration in #2809 already registers this way, so a runtime-evidence registration would be the second worked example rather than a new pattern. When MCP-RE is ready for that follow-on, section 2.2 defines the registration surface. Happy to look at a mapping whenever it's useful. |
|
Independent reproduction, since the thread says that half needs no coordination: I Two things fell out that may be worth something to the SEP itself. A three-extension known-answer vector.
One thing the core structurally cannot carry. §2.1 makes @matssun — the decomposition you sketched (evidence profile identifier, digest, optional Caveats, plainly: the acts come from a small self-hosted testnet, not a production network, AI assistance disclosure: built and verified with AI assistance (Claude Code), consistent |
|
Verified on my side as well: 81aea291 recomputes from the printed preimage under the section 2.3 rule, and your delta claim holds, the only change from f733fed9 is the third extension body. An implementation written from the spec text alone landing on the published digests is exactly the property the contract exists to pin. Thank you for running it and for publishing the bytes. The three-extension vector is worth pinning when the vector set next revs. C-REC-6 already claims emitter-neutrality, and a third registered type exercises it rather than restates it, as you say. Your conformance direction is the right one: recomputability, not agreement. That principle is what separates a vector set from an attestation, and I would keep it stated that plainly. On occurred_at, that boundary is deliberate. The core records only what the host can attest at its own trust boundary, and the host cannot attest the caller's clock, so caller-side signed time belongs in an evidence extension. You are right that such an extension earns its place by being able to disagree with the record it rides in. The registration surface in section 2.2 was written for exactly that kind of guarantee, and two independent arrivals at the same profile-id, digest, reference shape says the registration cut is sound. It stays MCP-RE's to land. |
|
Conformance feedback from a small independent deployment (~3 weeks live, four weekly anchor batches, 16 append-only lines). I run an append-only JSONL hash chain with a per-line SHA-256 sidecar, published here:
First commit 2026-07-18; current chain spans ISO weeks W29–W32. Canonicalization boundary. Verification hashes the raw JSONL line bytes (including the trailing newline). Row serialization uses compact JSON ( Append granularity. Weekly batches append multiple records per ISO week (one row per anchored asset). Validators verify line-by-line against the sidecar, not “one digest per calendar week.” Unclear whether verifiers should treat a week as an atomic unit or accept partial-week appends. Digest maintenance cost. Each append rewrites the full sidecar with SHA-256 of every line (currently 16; grows linearly). Cheap at this scale, but the spec does not say whether incremental or Merkle-style updates are expected — that affects how third parties budget verification on long chains. I have not experienced a chain break in production yet, so I have no operational recovery story to offer. Question: for multi-record weekly appends, should conformance tests require verifiers to accept any prefix of a valid chain, or only the latest complete weekly batch? |
|
Another deployment data point, and one structural suggestion on @Tetsurohhori's canonicalization question. We run TTTPS ( On the canonicalization boundary We ended up treating this as two separate layers rather than one choice between raw bytes, canonical JSON and file blobs. The chain hash never touches JSON. It is computed over a fixed-order concatenation of the record's identifying fields, so there is no serializer to disagree about. Key order, whitespace and separators cannot vary because no serializer is involved. Canonical JSON appears only where a document leaves the system and a third party has to verify it independently. There we use JCS (RFC 8785) via the W3C The mismatch described above (compact separators in one artifact, If SEP-3004 pins one rule for both, implementers will keep hitting this. It may be worth saying explicitly that a conformant deployment may use different canonicalization for internal chain linkage and for exported evidence, provided the exported form names its rule. On append granularity Our chain has no notion of a week. Records link to their predecessor individually, and a verifier walks the links. That makes any prefix of the chain verifiable on its own, which seems like the property conformance tests should require. Requiring "only the latest complete weekly batch" would mean a verifier cannot check a chain while a batch is still being written, and calendar boundaries are an odd thing to bake into an integrity property. Batching, in our case, exists at the signing layer instead of the chain layer. That keeps the two concerns independent: how often you sign is an operational choice, and it does not change what a verifier has to do to walk the chain. On digest maintenance cost Rewriting the full sidecar per append is the part that will bite first as the chain grows, and moving the aggregation into the signing layer is what removed it for us. I would rather not go into our specific construction here, but the general point is that if one signature can cover a batch, the per-line sidecar stops being the thing that grows. Where we are The protocol draft is public on the datatracker. Integration packages for LangChain, LiteLLM, LlamaIndex, smolagents and vLLM are on PyPI, and a docs entry for the LangChain one was merged into Happy to answer questions from the operational side if any of this is useful to the SEP. |
|
Thanks — the two-layer split answers the question rather than picking a side, and I think you are right that the mismatch I described is what forcing one rule across both layers produces. The chain hash having no serializer to disagree about is the part I had not considered. Two corrections to my own description, since precision matters more here than looking consistent. On granularity. My wording implied the week is a structural unit. It is not. Verification walks per-record digests, and any prefix verifies on its own — the property you describe. The weekly batching is an operational cadence, i.e. when the export runs, and it does not appear in the verification path at all. I framed a scheduling detail as a chain-layer question. On what I actually run. Calling it a hash chain was imprecise. Records are not linked to each other. It is an append-only log with a per-record digest sidecar, published to a public git repository — so deletion and reordering are caught by git's own commit graph rather than by linkage inside the records. The witness is external. That leads to the structural question I would like the SEP to answer: does conformance require the linkage to live inside the records, or may a deployment externalize the witness to a hash-linked public VCS? The failure modes differ — mine inherits the availability and trust properties of the hosting platform, yours does not — but I do not think either is obviously outside "tamper-evident". One more thing worth pinning, related to your canonicalization point: whichever rule is chosen cannot be applied retroactively. Recomputing digests over existing records to adopt a new rule is, from the outside, indistinguishable from tampering. If the SEP names a rule, it may also need to say that rules are versioned and that a conformant chain verifies across a rule boundary. Question: for a deployment that externalizes the witness, what would you expect conformance tests to check that they would not check for a self-linking chain? |
|
@Tetsurohhori — one deployment data point on the externalized-witness question, because Internal linkage answers "is this sequence internally consistent" and is checkable by What I would expect conformance tests to check for an externalized witness, that they
Concrete existence proof that the composed case verifies end-to-end: our On your last framing — I would resist making the external witness an either/or choice |
|
@navigatorbuilds - That is a better answer than my question. Framing it as either/or was wrong: "internally consistent" and "existed at this point in someone else's history" are different claims, and a deployment can owe both. Your second test lands on mine, so let me be concrete about where it fails. My records carry no signature and no witness reference. The hosting platform's commit graph covers the record file — the blob is hashed by the platform, so inclusion is checkable by anyone with the public repository. But nothing inside the record stream points at the witnessed state. A verifier can recompute the per-record digests with no access to the witness, which satisfies your (a); they only know which witness to check because I said so in this thread, which fails your (b) in the sense you mean. The pointer lives in prose, not in the material. That is the decorative case, and I had not seen it until you separated the two recomputations. The fix has to obey the retroactivity constraint, and your third point already says how: introducing the witness reference is itself a named, versioned event in the record stream, not a silent re-baseline over the existing records. I am not going to recompute the sixteen records I already have — that is the failure mode I raised earlier, and it would be self-inflicted. So the reference enters going forward, the rule change is a record, and a conformant verifier walks across the boundary. I agree the SEP should not force the choice. What is worth pinning is your last point: the exported evidence names what the verifier must trust, and the conformance suite carries at least one vector where witness and records disagree so implementations demonstrate they fail closed. A suite without a disagreement vector cannot distinguish "verified" from "only ever asked one side". I will come back with the versioned witness event once it is in the stream rather than describing it here. |
|
@navigatorbuilds @axcpeter — the versioned witness event is in the stream, so here it is rather than a description. https://raw.githubusercontent.com/aos-standard/catalog/main/ANCHORS.jsonl — line 17: {"event":"witness_ref_introduced","rule_version":"witness-ref-v1","witness":{"kind":"public_vcs","repo":"aos-standard/catalog","commit":"0eb69bf9f26f03b8d4fbce3b3b64ac46e10e1582"},"introduced_at":"2026-08-07"} The boundary behaves as you described: records before the event carry no witness reference, records after it must carry one, and a verifier walks across. I added a disagreement vector to the tests as well — witness present but not matching the referenced state fails closed rather than preferring either side. Where this still fails your second test: the reference is in the material, but the material is not signed. Nothing stops me from appending a second witness_ref_introduced pointing somewhere else, and a verifier holding only the records could not tell which one the deployment actually committed to. So the pointer moved from prose into the stream, which is a real step, but "covered by the deployment's own signature" is not satisfied. I am not going to claim conformance on a partial. That is the next gap and it is a larger change than this one was. A narrow question while I scope it: for the composed case, is a detached signature over the record file at each append sufficient in your view, or does the conformance property require each record to be individually covered — i.e. does a verifier need to authenticate an arbitrary prefix without holding the current head? |
|
@Tetsurohhori — ran line 17 before answering, and through the witness rather than around it:
On the narrow question: the two options converge once you require retention, and retention — not granularity — is the property worth pinning. A detached signature over the file at append k covers that prefix as a unit. If every append's signature is retained as material, any covered prefix authenticates offline; the verifier needs the matching signature, not the current head. If only the latest signature is kept, an exported prefix authenticates only against the live log, and truncation to an old state is indistinguishable from honesty without a freshness source. But notice what retention does: the accumulated signatures are themselves an append-only stream of commitments — records. At that point you have per-record coverage where the record is the batch, and your weekly cadence just sets the batch width. The unattested suffix between signatures is exactly the material presented as "not signed yet" — a cadence choice, not a structure choice. What neither granularity fixes alone is the failure you named — a second So to answer as a conformance property rather than a design pick: (i) any prefix an export claims as covered must authenticate from retained material alone, current head not required; (ii) conflicting continuations under the deployment's key must be attributable from material alone. Per-record signatures satisfy both; so do retained per-append file signatures that bind their predecessor; a latest-signature-only deployment satisfies neither, at any granularity. (Ours runs the per-record end — each record's signature binds bytes, position, predecessor digest, with the head witnessed separately — mostly because exports outlive the log: a single exported record plus its path stays verifiable with no live endpoint. And one thing worth versioning from day one, even at 17 records: audit logs outlive signature schemes. The signature suite is a named parameter of the exported evidence exactly like the canonicalization rule — your |
|
@navigatorbuilds — you checking it through the witness rather than around it is the first time that arrangement has carried any weight. Until someone recomputed the sidecar's prior state from the platform's history, "records 1–16 untouched" was a sentence I wrote about myself. It is now a thing that reproduces without me. That is the whole difference, and I would not have noticed it from the inside. On retention: you are right and my question was mis-framed again. I was asking which granularity to sign at, when the property is whether the signatures are kept as material. Once they are, the accumulated signatures are themselves an append-only stream of commitments, and the cadence only sets the batch width. Stated as your two properties — any prefix an export claims must authenticate from retained material alone, and conflicting continuations under one key must be attributable from material alone — it is testable rather than a matter of taste, which is what a conformance suite needs. A latest-signature-only deployment failing both at every granularity is the kind of statement a suite can be built from. I took the parenthetical seriously, so line 18 is in: {"event":"signature_suite_introduced","rule_version":"signature-suite-v1","signature_suite":"none","introduced_at":"2026-08-08"} To be clear about where that leaves me: neither of your two properties is satisfied. There is no signature, so no prefix authenticates from retained material, and a second witness_ref_introduced under my key would still not be attributable. I have moved the parameter into the stream, not closed the gap. Signing brings key management with it and I am not going to name a date I cannot hold — I would rather say that than promise and be quiet about it later. |
|
@Tetsurohhori — line 18 declared as A deployment that ships with signatures already on has demonstrated one scheme. A deployment that declares That, I think, is what's ready to pin as normative, and it factors cleanly into three parts:
Your |
|
@navigatorbuilds — the ladder framing is better than what I had. I should say plainly that I did not design none as the base of anything; it fell out of refusing to rewrite the sixteen records, and the ordering that produced it was accidental. What you are pointing at is that the accident is the evidence: the mechanism only shows itself at a transition, and a deployment that arrives with the crypto already in place never has to demonstrate one. Part (3) is the part I could act on, so I did rather than describe it. The verifier is published next to the records: curl -sLO https://raw.githubusercontent.com/aos-standard/catalog/main/anchors_verify.py The truncation check rests on the platform's history not having been rewritten. The tool prints that caveat on every run, because it is the assumption a reader would otherwise not know they were inheriting. Two things I noticed from building it, offered as gaps in the normative text rather than objections: (2) needs the boundary event to commit to the prefix it extends. "Named, versioned boundary event" is satisfiable by appending an event that claims an earlier effective point — nothing in the rule as stated prevents a fabricated boundary from being inserted after the fact. You already identified the fix when you noted my witness field naming the prior head was the right binding; I think that has to be normative rather than incidental, or (2) is unenforceable by a verifier holding only the stream. (3)'s vectors should be supplied by the spec, not by the deployment. I wrote my own adversarial cases, which means I wrote cases I happen to fail closed on. That is worth very little compared to a fixture set every implementation must fail identically against. A suite where each deployment brings its own vectors measures self-consistency, not conformance — the same shape as the problem you and I have been circling. |
|
Implementer note — we run per-record chaining alongside an external witness on the same records, so the composed case is the one we operate. One result on test (ii), one on §2.8. I tried to make the witness carry test (ii) at @navigatorbuilds already put the halves where they belong — "Signatures don't prevent that fork; they make it attributable... Deciding which continuation the deployment committed to is the witness's job." The tempting inference is that the witness half is therefore testable today at Two continuations sharing lines 1–16 and differing only at line 17, each with its own sidecar:
So "separate, each fails your case, from opposite sides" holds, and "structurally out of reach until signing lands" is right as stated. What the fork does reach is @Tetsurohhori's point (2): a boundary event must commit to the prefix it extends and to its own inclusion. Naming the prior head is necessary, not sufficient — and that is one adversarial vector a §2.8 reads differently after this week. The text calls an external witness a "distinct, weaker-priority threat — an auditing organization rewriting its own history." The no-re-baseline claim here was settled by exactly that mechanism. When the recording party is also a party to what it records, the recorder rewriting its own history is what decides whether the record is usable against the recorder — which is when audit records get read. Not an argument to un-reserve §2.8, an argument to settle Q-B on what this thread produced rather than on priority. One consequence from having shipped it. If a follow-on defines On @Tetsurohhori's point (3) — vectors should come from the spec, not the deployment — agreed, and it applies to us too. Happy to contribute the fork case and the liveness case to a spec-owned fixture set; ours is public if the shape is useful (tersignhq/evidence-record-conformance, Apache-2.0, every criterion an accepting and a rejecting twin). A vector only counts when the deployment it fails did not write it. AI assistance disclosure: drafted with AI assistance (Claude Code), consistent with the convention already used in this thread; the runs cited were executed, not asserted, and reviewed by a human. — Tersign |
|
@Tetsurohhori @wowlegend — I built the fork on my own machine before replying, because this is a thread about checkable-not-believable and it would be poor form to take the result on your word. Two continuations over the same first sixteen records, differing only at line 17, each with its own recomputed sidecar, both naming Both gaps you found in my three-part text are real, and both tighten it rather than dent it. On (2) — the boundary must commit to its own inclusion, not only to what it extends. You are right that "named, versioned boundary event" as I wrote it is satisfiable by an event appended later that claims an earlier effective point, and that naming the prior head has to be normative rather than incidental or the rule is unenforceable by a verifier holding only the stream. I'll state it as normative: a boundary event binds (a) the digest of the prefix it extends and (b) its own position in that prefix's continuation, both checkable against the witnessed head. wowlegend's fork is the proof that (a) alone is insufficient — both continuations satisfy (a) truthfully. What (b) buys at On (3) — vectors are the spec's, not the deployment's. Fully conceded, and it corrects my own reply-4: a conformance suite in which each deployment brings its own adversarial cases measures self-consistency, which is the exact failure shape all three of us have been circling. The vectors must be a fixture set every implementation fails identically against — records-only truncation, records-and-sidecar-truncated-vs-witness, witness-present-but-disagreeing, fabricated-boundary (your (2), now scorable), and equivocation (gated on signing, marked structurally-out-of-reach for keyless deployments so the gap is visible in the suite rather than argued in threads). On §2.8, wowlegend's point stands. "An auditing organization rewriting its own history" is not a weaker-priority threat when the recording party is itself a party to what it records — that is precisely the condition under which audit records get read, and read against the recorder. The no-re-baseline property in this very thread was settled by that mechanism. That argues for settling Q-B on what the thread produced, not on a priority ordering assigned before the mechanism was shown. So the contract, sharpened by both of you, is:
The |
|
Following the routing discussion in #3202, I tested whether the current From SEP-3004 head I then built a counterfactual vector, A separate, self-describing decision envelope commits to requested, I saw the earlier evidence-profile discussion in this thread and am not Limits: the producer is only AI-assistance disclosure: OpenAI ChatGPT and Codex assisted with implementation, |
|
@wowlegend @navigatorbuilds — I built the fork before reading past your first paragraph, and it is exactly as described: two continuations over the same first sixteen records, differing only at line 17, each with its own sidecar, both naming 0eb69bf truthfully, both VERIFY OK. Four reproductions now. You are right that it is spec-level and not a defect in the tool; the tool faithfully implemented an insufficient rule. Line 19 is in, same mechanism as 17 and 18: {"event":"position_binding_introduced","rule_version":"position-binding-v1","attestation":{"witness":{"kind":"public_vcs","repo":"aos-standard/catalog","commit":"e000814f60f393469479df795114d5b595f7ff49"},"prefix":{"line_count":18,"byte_length":2856,"sha256":"3a0afe1347a9099b51b681b93986120c0aac7302e2440733860de677154968ab"}},"introduced_at":"2026-08-09"} Then I attacked the fix, and it had a downgrade. Strip line 19 and present the forged sixteen-plus-one at eighteen lines: verification fell back to the weaker path and printed VERIFY OK while reporting attested_prefix_lines=0. It knew it had checked nothing and said OK anyway — the same shape as the sentence this thread has been circling, inside my own tool. Unattested is now a third outcome with its own exit code, and its message says so rather than leaving it to be inferred: VERIFY UNATTESTED: no position_binding_introduced attestation (attested_prefix_lines=0); On (3): my vectors do not count and I should not have shipped them as if they did. A fixture set the implementation did not author is the only version of that check worth running, and @wowlegend's offer is the right shape — I would rather be scored against evidence-record-conformance and fail somewhere visible than keep passing cases I wrote. If the fixture set grows a fabricated-boundary and a downgrade-to-unattested vector, I will run against those and report whatever comes back. AI-assistance disclosure: drafted with AI assistance (Claude Code), consistent with the convention in this thread; the runs cited were executed rather than asserted, and reviewed before posting. This applies to my earlier comments in this thread as well, which did not carry the notice. |
|
Shipped rather than offered — the two vectors are in, at @Tetsurohhori — Run them and report whatever comes back, including if they are the wrong shape. A fixture set the deployment it fails did not write is the whole point, and that cuts against us too: if these encode our assumptions rather than the property, the useful outcome is that you say so publicly. One correction, since this thread punishes unchecked claims and I would rather it be mine. @navigatorbuilds attributed to me the line "a suite that only ever recomputes one consistent history cannot distinguish 'verified' from 'only ever asked one side.'" That sentence is his own, from 2026-08-08T09:46Z, where he credited the underlying point to @Tetsurohhori. I did not write it and should not carry it. On the residue: agreed on both limits as stated. What (b) buys at @mohammedmessaoudene-cmd — your Disclosure: drafted with AI assistance, human-reviewed, consistent with the convention already used in this thread. — Tersign |
|
Thanks @wowlegend for the concrete vector invitation. I pinned I then consumed the exact Git blobs for existing vectors p18, n25, and n26 Draft PR: tersignhq/evidence-record-conformance#5 Its GitHub Actions run is currently Scope is structural canonical-object binding only. It does not prove producer AI-assistance disclosure: OpenAI ChatGPT and Codex assisted with implementation, |
|
@wowlegend — ran them. Three of them apply to what I have, and I ran all three.
Both negatives reject as The reason this is not a blanket default-deny: What I did not do. I did not run your harness — Limits, stated rather than implied. No signature suite verification, so signed equivocation is @mohammedmessaoudene-cmd ran the same commit before me against AUEC. Those numbers are his, not On the attribution correction — noted, and thank you for making it against your own interest. Vector bundle SHA256 (ordered file digests): Disclosure: implementation, adapter, execution and drafting were assisted by AI (Claude, Cursor). |
|
Thanks for running only the subset your verifier actually implements, and for stating the non-applicable cases explicitly. I am recording this as a third-party cross-implementation reproduction of the three boundary-binding fixtures at I will not treat this as reproduction of AUEC, its local counts, or the draft p19/n27/n28 vectors. Those remain pending the Tersign CI and review path. I have also recorded the reported bundle digest and the limits you listed, including the unattested tip, absence of signature-level equivocation checks, and force-push dependence. Thank you for the precise scope. AI-assistance disclosure: ChatGPT and Codex assisted with drafting. I reviewed the wording and remain responsible. |
|
@wowlegend — reciprocal, since I ran yours: I put our anchor-stream verifier up to be broken — Two of the three targets exist because our own verifier had those defects. It printed Limits are listed in the issue so nobody spends time rediscovering them. If the targets are the wrong shape, saying so publicly is a useful result and I will record it. Disclosure: the verifier changes, the invitation issue, and this comment were assisted by AI (Claude, Cursor). I ran the commands against the pinned tag myself and remain responsible for what is claimed here. |
|
Follow-up on Workflow Immutable receipt: https://github.com/mohammedmessaoudene-cmd/AUEC/blob/3cabb79e2a9c84db2dd256b64c97134c385d187d/evidence/upstream/tersign/ci-review-merge-receipt.json This closes the external Tersign fixture CI/review/merge gate for this narrow contribution only. It does not choose an MCP field, digest, or canonicalization; establish producer truth; validate the semantic authority reduction; or constitute MCP adoption. AUEC PR #2 remains experimental, draft, and unmerged. AI-assistance disclosure: ChatGPT and Codex assisted with verification and drafting. I reviewed the evidence and remain responsible. |
|
@wowlegend took the invitation I posted here on 8/10 and broke the verifier. Two findings. One of I wrote that the two defects were "now distinct outcomes with distinct exit codes". One of those Both are fixed in Findings and the published construction: @wowlegend. Independent offline reproduction on two Disclosure: the verifier changes, the reproduction runs, and this comment were assisted by AI |
SEP: Tamper-Evident Audit Record Contract (Standards Track)
Specifies an interoperability primitive: a canonical byte form + append-only hash-chain construction that independent implementations produce identically and any third party can verify, with governance context carried in registered extensions, not the core.
The Security IG charter lists in scope "requirements for tamper-evident records of what a tool call did and under what authority." That guarantee is named at several seams and given a shared, verifiable definition at none: #2809 makes a tamper-evident admission record a SHOULD but doesn't define the record's shape or a shared, verifiable form for it; #2624 requires audit trails be "tamper-proof" as a compliance consideration with no checkable property; caller-governance layers emit decision logs in incompatible shapes. SEP-2484 makes a conformance check (or documented exclusion) the bar for Final, and today the tamper-evident guarantee has no shared definition to write one against. Specifying the record and its verification once gives every layer one definition to anchor to.
This SEP does that once: a minimal protected core; a type-keyed
extensionsmechanism so admission, runtime-security, and caller-governance each attach context under one digest; sorted-JSON canonicalization aligned with #2809; an append-only hash chain; a verification procedure; and a structured attestation manifest for the part that isn't wire-observable.Registered:
caller-governance— specified in fullruntime-security— normative text contributed by Maaz (Interlock), cross-ref SEP-2624: Interceptors for the Model Context Protocol #2624admission-control— named, cross-ref SEP-2809: Attested Tool-Server Admission (ATSA) #2809Reproducible. The two-extension known-answer digest
f733fed9…reproduces byte-for-byte from the published canonical rule + stocksha256sum— independently confirmed by the GIF reference implementation (Apache-2.0, github.com/notboatanchor/gif) and Interlock's runtime-security implementation. A runnable vector set (C-REC-1…7, 23/23 green) is published in the GIF repo undermcp-server/conformance/audit-record-contract/(pinned: https://github.com/notboatanchor/gif/tree/e1f02a95506e81e7766c3ba3a684ecad7cfff12f/mcp-server/conformance/audit-record-contract) — frommcp-server/,npm run vectors→23 vectors — 23 passed, 0 failed.Developed in #security-ig. Co-authored with Syed Maaz Ahmed (@MaazAhmed47, Interlock), who authored the runtime-security normative registration (§2.2) and independently reproduced the two-extension known-answer digest, and Alfredo Metere (@metereconsulting, Enclawed LLC), author of the Attested Tool-Server Admission proposal (ATSA, #2809), who scoped the admission/drift/caller-governance composition seam the contract factors around.
Seeking a sponsor from the Security IG. @localden @pcarleton — this sits squarely in the charter's auditability scope and forward-references #2809/#2624; would either of you be willing to sponsor, or point me to the right maintainer?
Refs: #2809, #2624, SEP-2484.
AI assistance disclosure. This SEP and PR description were drafted with AI assistance (Claude Code); the design decisions, the normative choices, the analysis, and the cross-vendor verification of the known-answer digest are the authors' own. AI-assisted comments I post on this PR will be disclosed the same way.