Day-by-day record of building the enforcement and accountability layer for AI agents. Bring your own identity: did:key, did:web, SPIFFE, OAuth, native did:aps. Started February 18, 2026. 6,003 tests, nine papers, IETF draft. Open source. Full surface area: 152 MCP tools.
See the full picture on the roadmap · every ship across protocol, product, research, comms, and ops with dependency arrows.
<<<<<<< HEAD
Day 127: a regulated action reaches finality only when two trust domains outside the operator agree.
The Regulated Action Profile v0 ships in SDK 2.8.0, and its rule is to count trust domains, not signatures. An action above a class threshold, rank three or higher, is not final because someone signed it, including the operator that ran it. The verifier returns reconciled only when a pre-committed intent reconciles against two anchors that sit outside the operator's own trust domain: the identity provider that authorized the actor, and the resource's system of record that confirms the effect. It counts the distinct domains behind those anchors and refuses reconciled, and the regulator_grade_for_class level above it, unless that count is at least two, the resource confirmation validates under an independently registered key, and the intent was anchored in time before the effect. One party holding two keys is still one domain, and the verifier treats it as one. judgment_correctness is always emitted as not_claimed, because the receipt type has no field for a model's reasoning. A claim about whether a decision was wise cannot be expressed in it, only whether the authorized path was followed.
What the profile does and does not cover is written into the build, not just the prose. The verifier is deterministic and stateless, and 33 conformance vectors pin every disposition, including the cases where a hostile operator forges one side of the reconciliation and the verifier still refuses to call the action final. A second implementation in Python, with its own Ed25519 and JCS and no shared code, reaches the same decisions. What the reference build does not do on its own is reach reconciled end to end. Its boundary attestation runs at a weak level, because a process that can observe its own child can also influence it, so an honest run on one machine reports intent_precommitted and stops there. reconciled is gated on a deployment whose attestation node is a separate principal: a separate operating-system user, a separate container, or a remote signer. The verifier and the vectors carry the security argument now, and the deployment carries the rest. The composition is the part that is new. Receiver-attested receipts, intent pre-commitment, and bilateral co-signing are each prior work. Placing an external identity-provider authority as the second trust domain, and letting the verifier decide finality from the domain count in a setting where the operator is the adversary, is what this profile adds.
Day 126: a signal type now has to earn "canonical," and the validator enforces it.
A term in the governance vocabulary used to become canonical the moment someone added it, which let a single issuer's signal sit at the same status as a reviewed one with nothing recording how much support it actually had. The fix is a lifecycle. Canonical now requires two or more independent implementations. A term with one implementation is proposed, carries a review_by date and a promotion trigger, and stays there until a second independent implementation appears. A term with no implementation is reserved, also dated, and is removed by default at its review date rather than lingering. A term with no status at all is read as proposed, never as canonical, so silence cannot confer authority. Two further rules keep definitions honest: a definition states what the signal is without naming or depending on any one implementer, and a term cannot cite its own issuer as the ground for its status. The whole fifteen-term registry was re-sorted under the single rule, not only the terms that triggered it, so every status reflects the same test. The rule lives in CONTRIBUTING, the validator enforces status, the review dates, and definition purity, and a term that claims canonical with fewer than two independent issuers fails the check.
Day 123: a sub-delegation can no longer outlive its parent, and a spend unit cannot change once a delegation has one.
Time was the one narrowing dimension that did not hold at delegation creation: a child could be created with a longer life than its parent, while scope, spend, and depth all narrowed correctly. Two creation-time defects combined to allow it. createDelegation built the expiry with setHours and an || 24 default, which turned a deliberate zero-hour window into a fresh 24 hours and dropped fractional hours. And subDelegate computed the child's window as a duration from one reading of the current time, then passed it to createDelegation, which re-based that duration on a later reading, so the child outlived the parent by the gap between the two readings, and an already-expired parent produced a fresh 24-hour child. The fix moves expiry to millisecond math, reads the current time once, rejects a parent whose expiry is non-finite or already past, and sets the child's absolute expiry to the earlier of two times: 24 hours from now, or the parent's expiry. That absolute value is signed directly, so no relative duration enters the signed object. The invariant now holds to the millisecond at any depth: a child's expiry is at most its parent's. This is creation-time enforcement, matching how every other narrowing dimension works in the SDK today. It does not add a verify-time or chain-level temporal check.
The spend dimension got the matching guard: once a delegation carries a spend unit, a child can narrow the amount but cannot change the unit the amount is measured in. A child that switched the unit could restate the same number against a different denomination and pass an amount check while stepping outside the parent's spend constraint. The guard rejects a unit change at narrowing once a spend dimension exists, with adversarial cases in the vector set. Separately, the action-ref-v1 conformance vectors gained a verification_mode field that marks whether each vector is structurally enforced, a reader that omits the field treats the vector as enforced, and both the JavaScript and Python runners now print a tally of the field. No code path or hash changed for that annotation.
Day 122: an anchored trail recomputes to the same correlation key, and the delegation vectors cross-encode into a second envelope.
An independently anchored action trail recomputed to the same external correlation key, with no shared code on either side. A separate implementation anchored an action trail on Arbitrum and published its action_ref together with the four-field preimage behind it. We recomputed the external action-ref-v1 key two ways: once with a plain RFC 8785 JCS canonicalization and a SHA-256, with no APS code in the path, and once with the published APS verifier. Both produced the anchored value byte for byte. The match is about dependency, not novelty: the preimage of action_type, agent_id, scope, and timestamp is the entire surface, so any verifier reconstructs the key from the receipt alone and needs nothing from the originating runtime. A result like this is two implementations converging on one derivation, which is not the same as one depending on the other. The external key stays separate from the APS-native request-identity form, which carries a multi-scope array; the two are different layers on purpose, and the interop record labels which one each vector belongs to.
The four delegation-chain vectors re-encoded into a second envelope format and passed that project's own verifier. The APS chain-envelope vectors, a valid narrowing accepted and then a widened scope, an expired parent, and a revoked parent each rejected, were re-expressed in the AAE signed-JWS envelope shape and run through its reference verifier. All four were schema-valid and returned the expected verdicts, and the rejection reasons matched that verifier's own strings rather than ours. The revoked-parent case is a cascade evaluated at check time, not a stored flag. What is shared and what is not is written next to the vectors: APS enforces as a rule a constraint the other format marks as a SHOULD, the envelopes differ in how they are signed, and a constraint-monotonicity case the other set covers is recorded as a gap rather than smoothed over. The cross-encoding merged to the conformance suite and went onto the working thread.
Day 121: a key resolver bound to the server, and to the moment of signing.
did:cycles resolution moved off a did:web-style, origin-rooted form and onto the hash-bound, window-gated model the Cycles thread settled on. A did:cycles identifier is now the hash of the server it belongs to: the subject is sha256(server_id), and the key set is fetched from a path derived relative to that same server_id rather than from the origin, which closes a cross-tenant key-confusion class where a key under one tenant's origin could answer for another. The key is selected by the validity window covering the receipt's issued_at, not by whichever key is current, and resolution fails closed when no key's window covers that moment, when a window bound is missing or non-integer, when more than one key matches without a kid to disambiguate, or when the named key carries private material. The work this merged change does not do is left out on purpose: binding issued_at to the authentic signed payload is the verify-path step that comes next, and the byte-for-byte Cycles conformance vectors come with it. The resolver is exported but not yet reached by any live verification path, so it lands additively rather than as a half-migrated seam, and no Cycles-conformance claim ships before those vectors exist.
On the vocabulary registry, the validator caught up to the evidence standard in one more place. A crosswalk's verified_at can now be a per-system map (PR #112) rather than a single date, so a file that maps several protocols records when each one was checked and measures its staleness window from the oldest of those dates. cap_vocabulary v0.2 (PR #109) merged with its upstream citations pinned to specific commits and its intra-decision ordering left unstated where the source spec states none.
Day 120: a standard for carrying a claim the registry did not make.
The crosswalk registry now has rules for the claims it hosts but did not author. A crosswalk says how some other system uses a governance signal, which means most of its cells are claims about a third party. The new evidence standard makes those claims carry their own basis: a qualifier travels with the claim it qualifies, so a cell pulled into a slide or a screenshot cannot shed the basis it depends on. A claim about an outside system carries the attestation of whoever verified it, under their name, rather than being asserted in the registry's own voice. Publicly verifiable is the unmarked default, and anything weaker than that is marked in the cell's displayed value, not in a sibling field a reader never sees. The described system keeps a standing, low-friction way to contest a cell. And a cell never states that a system lacks a capability as a fact about the system; it states what was searched and not found, listing the repos, documents, and versions examined, so the claim is a durable search result rather than a verdict.
The validator now backs the part of that which can be mechanical. A reverify date is a control only if expiry changes something, so an expired reverify_by with no fresh evidence fails the cell to a stale state instead of sitting as a note nobody enforces, and elapsed time never upgrades a cell. The negative fixtures that are supposed to fail run in their own pass and are asserted to fail, so a real production run stays clean and a fixture that quietly stops failing becomes its own error.
Day 119: the correlation key gets a second conformance set, built separately.
The cross-ecosystem action_ref form now has an AEOESS-built conformance set merged into argentum-core, the joint draft's reference implementation, sitting in its own aps/ directory alongside the recomputation fixtures already there. Fifteen vectors, ten accepts and five rejects, reproducing the draft's first appendix vector byte for byte. Two derivations written against the same words, kept in separate trees, landing on the same bytes. That agreement is what shows the spec is unambiguous, and it holds only while the two paths stay visibly independent, so the set is kept as its own author-set rather than folded into the reference vectors.
A note on which key this is. APS carries two action_ref primitives with intentionally different preimages: the native one signs APS receipts with a multi-scope array and a second-precision timestamp, and the external one is the single-string, millisecond form built for crossing systems. The conformance set tests the external form, because that is the one other stacks have to agree with. Neither key has to bend to the other.
Day 116: an independent implementation of the correlation key, and a runnable place for the record to live.
Overnight the action_ref correlation key got something better than another citation: an independent re-derivation. A separate Internet-Draft of the primitive picked up a conformance set from the AgentGraph implementation, built with its own RFC 8785 path in Python and Node, that reproduces Appendix A Vector 1 byte for byte (fdd7f810...3d89f5a). It covers the edges that catch naive implementations: an empty scope kept distinct from an absent one, and a did:key self-certifying agent_id. The agreement is the evidence, and it only holds while the two derivation paths stay visibly separate, so the proposal keeps it as its own author-set rather than folding it into the reference vectors. The boundary stays explicit in the appendix text: an action_ref proves a declaration is intact and recomputable, not that the runtime behavior matched it.
The other half of the day was about where the record lives. A ClickHouse maintainer, on their own mcp-clickhouse repo, asked for a runnable delegation layer on top of their credential pass-through sketch. The example is the answer: an agent gets a delegation limited to certain tools, with an expiry, instead of the user's full access, and every tool call writes a signed boundary receipt into a table next to the query log. Three reads pass, one out-of-scope drop is denied and recorded as a signed outside receipt, and a tamper test edits a stored row by hand and watches verification fail on that exact row, because the signature is made when the decision happens, not from the row in the table. It installs from PyPI and runs in one command against a local server.
To make that one command true, the Python SDK went to a stable release. pip install agent-passport-system now delivers 2.4.0 rather than resolving to an older line, with the Wave 1 accountability surface the example depends on: scoped delegation, the authority-boundary receipt, and the honest scope-of-claim field that records what a receipt does not assert. The version that installs by default is the version the example was tested against, which is the only state worth shipping.
Day 115: two registry reviews, one fixture suite shipped upstream.
The crosswalk registry now has a review standard: payment_rail (PR #100) and cap_vocabulary v0.2 (PR #109) both carry pinned upstream citations, rules marked descriptive or proposed rather than universal, in-file minting requirements, and recorded sign-off from the second implementer. SpendGuard approved #109 with a correction that proved the point: their spec ships no intra-decision order, so the registry records none. Same day, the action-ref-v1 recomputation fixtures went upstream to argentum-core: fourteen vectors, four drift families, every negative a real digest of its stated drifted bytes, fail-closed by construction.
Day 115: the AAT and APS boundary, on one page.
Where session identity ends and delegation begins: a joint AgentLair x AEOESS reference. Read it.
Day 114, later the same night: 2.6.0 goes stable.
The 2.6 line is on npm latest as of tonight. A plain npm install agent-passport-system now delivers what the alpha channel carried for six weeks: the Wave 2 evidence layer with its verifier-derived descriptors, trust-root policy, revocation enforcement, audience binding, selective disclosure, and the offline verifier; Context Provenance Attestation; the action_ref v1 conformance set; and the payment-rail surface through today's envelope-authenticity check. 3,791 tests, zero failures, on the exact tree that published.
The Day 105 entry said the stable cut waits on two things: a content-derived decision identifier, and batch-verify parity running green rather than environment-gated. Both closed today. decision_id is now a domain-separated content hash over the record's identity fields, recomputable offline by any verifier from disclosed fields alone, and the field taxonomy that should have existed from the start now does: identity fields are path-independent, ordering fields state their scope, event-instance fields are disclosed and MAC-bound. With that in place the parity claim stopped being a test that could fail and became a property that cannot: a single check and a batched check return byte-identical decision records under a pinned clock, exercised in the production binding before the merge, not in a lab wiring that production never ships. The number that is published is still the one that can be defended. What changed tonight is how much it defends.
Day 114: An outside contributor ships the check the last review asked for, and the site starts carrying its own terms.
The Day 104 review of the Cycles binding check ended with a boundary stated out loud: a passing check meant bound, not authentic, and the result was asked to say so plainly. Today the contributor behind that rail shipped the next step (#45): the supplied evidence envelope's own Ed25519 signature is now verified against the key the envelope names, under the spec's signature derivation, which is a different canonicalization from the content hash, the signature field emptied and the identifier left populated. Failure is a distinct fail-closed reason, and a passing verify now reports which guarantee actually held: signature over the named key, or that plus a pinned receipt issuer. The part worth pointing at is a test the contributor wrote that asserts a fully self-consistent forgery, re-signed by an attacker's own key, still passes with only the weaker tag. The gap that remains, resolving whether the named key is the legitimate signer, is tracked on the Cycles side rather than papered over here. The branch predated a clock fix on main, so the suite was run on the merge result, which is the thing that ships: 3,791 tests, zero failures.
On A2A, the cache question from the signing thread resolved the right way. The original three-value key-source enum treated cache as a place, which is a laundering hole: a hot resolver fetch becomes "cache" one call later and the provenance of the original resolution is gone. The fix that held is defining cache as a derivation, previously verified through an allowlisted path and pinned, with the population event, source and timestamp, auditable from the signed evidence rather than from the verifier's word. The CTEF author folded that definition into the CTEF key_source and the v0.4 transactional receipt. The enum stays at three values; the trust posture becomes reconstructable offline.
And the protocol's own site now carries the thing it asks publishers to carry. agent-passport.org serves a signed governance declaration at /.well-known/aps.txt: a fresh Ed25519 domain keypair, the same machine-readable terms as the original declaration on the prior domain, verifiable offline from the live bytes. The honest part of this entry is why it happened today. The site migration had left a placeholder at that path, and a comment elsewhere cited the file as live before anyone re-checked it. A protocol built on the claim that statements should be checkable does not get to leave its own cited statement unverifiable, so the fix was not an explanation. It was making the cited claim true.
Day 113: The correlation key gets one exact form, and evidence starts carrying where it came from.
The cross-ecosystem correlation key from Day 106 is now a frozen specification with conformance vectors (spec page). Four fields in the preimage, and the field that caused every interoperability argument, the timestamp, is pinned to one exact representation: RFC 3339 UTC with exactly three fractional digits, uppercase T and Z, zero-padded, one valid byte sequence per instant, hashed as opaque bytes and never normalized. The vectors enforce that choice from both directions: the negative vectors reject every non-canonical timestamp form, and two of the accept vectors byte-match hashes published by independent ecosystem implementations, so a pass demonstrates cross-implementation agreement rather than self-consistency. There are two verifiers because the failure modes differ: a stdlib-only Python verifier that vendors its own minimal RFC 8785 serializer and recomputes every hash with no dependency on this project, and a Node verifier that imports the shipping helper, so the vectors stay pinned to the code that actually runs rather than a reimplementation of it. The non-goals are part of the spec: a pass proves byte-exact agreement on the derivation, and nothing about whether an action was authorized, occurred, or honored its scope. Those claims belong to the records the key correlates.
The evidence layer learned two things in the same cut. Verification-source provenance now travels inside signed evidence: when a verification result is carried as evidence, the record of how the key behind it was resolved rides in the signed envelope, not in the verifier's logs, because a claim a verifier makes about itself is exactly the kind of claim this layer exists to replace. And the producer-attestation commitment kind landed with a slot for a Context Provenance Attestation, connecting Day 107's context custody to the evidence chain: an action receipt can now carry a committed reference to the declared basis the action was built on, with the same stated boundary as before. Custody of the declared basis, not truth of it.
Day 107: Custody for the context an action was built on, and the protocol in a third language.
Context Provenance Attestation v0.1 is exported from the public API as of [email protected]. A CPA is a signed, partitioned Merkle commitment to a declared context basis. The producer groups the context an action was built on into eight frozen structural-origin channels (system-config, developer, user-socket, retrieval-store, tool-result, external, memory, quarantine), builds one Merkle partition per channel, commits the partition roots into a single top root, and signs the result. The channel is a partitioning key, not a trust label. There is no field where a producer writes "trusted" or "clean" as a claim about origin, and the channel is part of the leaf preimage, so relabeling it breaks the root. The hashing is domain-separated with distinct tags for leaf, node, and signing, and odd nodes are promoted without duplication per RFC 6962, which closes CVE-2012-2459. Two disclosure modes: full-set, where every leaf is revealed and completeness is proven against the signed tree, and inclusion, where counts plus a sampled subset come with inclusion proofs and completeness is not proven by design. The CPA and the action receipt each carry the other's reference, so a stale CPA and a stale receipt cannot be silently re-paired. The verifier is offline and fail-closed, with structured reason codes instead of one opaque failure.
The boundary is the whole point, so it is stated rather than implied. A CPA proves custody of the declared basis as of the producer-stated time, tamper-evidence over the committed structure, and replay resistance. It does not prove the context was true or clean, and it does not prove faithful capture: that the declared basis equals what the model actually conditioned on. A well-formed CPA over basis A, when the model conditioned on B, still verifies. It is a flight recorder, not a seatbelt. Faithful capture needs an independent capture boundary, write-time receipts or a TEE or runtime instrumentation, and that is the one open vector, named and deferred rather than left implicit. One line of the custody claim got tightened during the work, from an absolute timestamp to producer-stated time, because the producer is the only party that can attest when it assembled the basis.
The same cut put the protocol into a third language. agent-passport-go reached v0.2.0-alpha.1, fifteen packages across the surface. The verify path compiles no key code at all, which is the right shape for an infrastructure sink or proxy that checks receipts without ever holding a private key, and v0.2 added the issuing side: passport, delegation with narrowing and signed revocation, completion receipts, attribution Merkle with beneficiary tracing, the values floor, coordination, commerce, and in-toto decision receipts. CPA shipped with a cross-language Go parity fixture, so the two implementations can be checked against the same bytes. On parity I want to be exact, because exactness is the point of the project: the Go primitives are pinned against shared canonical-JSON and CPA fixtures, which is a real guarantee and a smaller one than the continuous cross-build parity the TypeScript and Python implementations hold across twenty-seven scenarios. Pinned-to-fixtures is the claim, so pinned-to-fixtures is what I am saying.
Day 106: A correlation key is only worth defining once, by no one in particular.
The join key that lets two parties prove their receipts refer to the same action showed up in two more independent implementations this week. It is a small thing by construction: the SHA-256 of the JCS canonical form (RFC 8785) of the intent tuple, recomputable from the disclosed fields alone. raucle-detect published canonicalization test vectors and added one in the four-field shape; recomputing it under the APS canonicalizer reproduces the published digest byte for byte. argentum-core carries its own implementation of the same derivation. Three implementations, one digest, none of them the source of the others.
That last point is what the W3C auditability thread (#34) settled this week, and it meant withdrawing something said earlier. If a correlation key's whole value is that any verifier can recompute it without trusting whoever issued the record, then it cannot be defined by reference into any single implementation draft, including this project's. The derivation belongs in the community-group text itself, with the implementations listed underneath as references rather than as the definition. The earlier position that named the APS draft section as the source was the dependency the layer exists to remove, so it came out. The honest open item is that the field set is the specification: JCS canonicalizes JSON structure, not value semantics, so the tuple has to pin types and precision, a timestamp as an epoch integer and the same instant as an ISO-8601 string produce different digests. Requested scope was removed from the key as well, because scope narrows during a decision, and binding the key to the requested scope would force disclosing the original broad request to verify a narrowed receipt, which defeats the selective disclosure the layer is there to protect. Those two went back to the thread as the review items.
Day 105: The evidence layer ships to the alpha tag, and a descriptor that refuses to score itself.
The second wave of v2 modules went to the prerelease tag on npm, twelve of them covering evidence description, trust-root policy, a remote signer, revocation enforcement, audience binding, human oversight, hash-and-pointer selective disclosure, a scope-dimension registry, and an offline verifier with a conformance runner. It published to alpha (2.6.0-alpha.9), not to latest, which still points at 2.2.0. That is deliberate: the stable cut waits on finalizing a content-derived decision identifier and on the native batch-verify parity running green in a capable build rather than being gated by the environment. The number that is published is the one that can be defended.
The load-bearing design choice is in the evidence descriptor. It is derived by the verifier, not asserted by the issuer. It records mechanical facts, who signed, whether that signer is independent of the key graph that vouches for it, and a four-valued corroboration status, and it does not emit a scalar assurance score. A test feeds it a spurious assurance field and asserts the field never reaches the output. The reasoning is the same one that runs through the rest of the protocol: a number a subject can set about itself is a number it can inflate, so the descriptor reports only what an independent verifier can derive, and leaves the claim of trustworthiness to the party doing the checking.
Day 104: Three records an auditor can walk, and a binding check that says what it does not prove.
The W3C accountability-gap thread (#34) converged on a shape, so the subsection proposal went in. It builds an accountability record from three parts along the life of an action. A commitment says who was authorized to do what, and under which delegation chain. A decision says what authority and context were evaluated at the moment of action. A receipt says what actually happened, signed after the fact. Each part references the next by content hash, and none embeds the other, so every part stays independently verifiable and an auditor can ask for only the layer it needs. The serialization rides on plain W3C verifiable credentials linked by digest, with no new envelope format to adopt. The reasoning the agent applied binds inside the decision record. Whether the underlying claim was true stays in a separate belief layer, referenced and not inlined, because these records carry admissibility evidence and do not assert truth.
A second thread (A2A #1463) asked a neighboring question, in-task authorization through an OID4VP extension. OID4VP proves who an agent is and that it presented a qualifying credential. It does not prove that the action the agent then took sat inside a sound authorization policy. In APS that second question is the scoped delegation chain, where each hop can only narrow authority, so the envelope a verifier checks against is the intersection along the chain, and a gateway evaluates the concrete call against it before execution. The credential and the delegation envelope reference each other by content hash. OID4VP answers who, and qualified. Scoped delegation and enforcement answer whether the action was allowed. The contributor confirmed the same attenuation model from their side.
On the Cycles payment rail, a contributed verification check (#42) earned a careful review. It binds an APS receipt to the specific Cycles evidence envelope the receipt points at, by recomputing the envelope's content hash and confirming it matches both the envelope's own id and the hash the signed receipt committed to. That recompute reproduces the Cycles server's identifier byte for byte, so the binding is real and tampering with the envelope is caught. The honest part is the boundary. The check proves the receipt is bound to this envelope, and that the envelope is internally consistent. It does not verify the envelope's own signature against a Cycles signing key, which is a separate step now tracked for the next cut as issue #43. A passing check means bound. It does not yet mean authentic, and the review asked the result to say so plainly rather than let a reader infer more.
Day 103: The site says where the protocol plugs in, and the Cycles receipt carries the authority it saw.
The landing page got the section it was missing. "Where it plugs in" sits between the open-source case and the integration grid, and the grid lists the real connections without inflating them. Payment rails carry spend authority tied to a signed delegation, with a receipt per charge, through bindings for x402, Google's AP2, ACP, and Stripe issuing. Agent protocols carry identity and scoped authority with the call, exposed as MCP tools and carried across A2A by an adapter. On the standards side, gitagent-protocol merged the optional cryptographic identity layer for agent manifests. Frameworks get the passport riding into the runtime through LangChain, CrewAI, and AutoGen adapters. The line under the grid is the part that matters. Some of these are bindings the project ships, others are contributions merged upstream, and none of it is a claim that these ecosystems depend on APS. Connective tissue, stated as connective tissue. The same pass moved the remaining pages onto the dark theme with one canonical nav and footer.
On the Cycles payment rail, the permit receipt picked up a field it needed. authority_state_at_admission records whether the delegation was revoked or expiring at the moment the reservation was admitted, signed into the receipt body rather than left to a separate lookup. A verifier reading the receipt offline now sees the authority state the gateway saw when it said yes, without trusting a second system to still agree later. The contributor driving the Cycles adapter ran a verb-shape pass over the budget_reservation crosswalk in the same stretch, confirming the reserve, permit, release, and refund shapes line up with what the Cycles surface actually emits.
One older thread closed a loose end. On the AIVSS enforcement-effectiveness review (#4), the reviewer confirmed the bound-parity language reads clean. Two substrates whose security windows land inside the same bound establish that the dimension measures the methodology, not the backend, so the substrate drops out of the comparison. It is a small fix, but it was creating a reader contradiction, and the v0.2 cut needed it settled before the remaining two items land.
Day 101: Resume-time enforcement modes, and an auditability gap that walks by hash.
A thread on Microsoft's agent-governance toolkit (#1609) put a sharp edge on the LangGraph adapter. When a graph pauses at a checkpoint and resumes later, the authority that was valid at pause time can be narrowed or revoked by the time it resumes. The receipt model answers that without replaying the verifier. A resumed action keeps its actionRef but produces a different compoundDigest when the evaluation outcome changes, and the mismatch lands on the signed PolicyReceipt. A contributor moved the design forward by putting delegation_chain_root in LangGraph's checkpoint metadata rather than the user's state schema, so governance fields never collide with application state. The open question was whether the adapter should hard-block on stale authority or emit an event and defer to policy. In the SDK that is neither a binary nor the adapter's call. Enforcement mode is a property of the principle being evaluated: inline blocks, audit records, warn warns, ordered by escalation. The verdict that matters at resume is the third one. narrow clamps a resumed action to whatever authority is still valid instead of killing the graph, which is usually what a production run actually wants.
The W3C AI Agent Protocol community group opened an auditability-gap RFC (#34) around three questions an auditor has to answer about any agent action: who authorized it, what was decided, and what was committed. APS answers all three with content-addressed artifacts that reference each other by hash instead of by embedding. The intent carries a content hash of its unsigned form. A compound digest binds the hash of the intent and the hash of the policy receipt. A receipt can name the previous receipt by hash. An auditor walks authority to decision to commitment to receipt by checking hashes and canonical forms, with no requirement that every participant run the same software. The direction that came out of the thread for the white-paper subsection is vocabulary-first: state the gap in protocol-neutral terms, then place APS and the other framework underneath as implementation bindings, so the section is usable by anyone who agrees on the gap without adopting a stack to read it.
Two A2A threads carried the same posture on the identity side. #1850 added an Identity Trust Framework roadmap that keeps the native draft-pidlisnyi-aps-01 §4.1 action_ref as the primitive APS receipts sign, while emitting or carrying the shared external action-ref-v1 correlation key, so a receipt keeps its own preimage and still lines up on the cross-system key. #1628 consolidated the trust.signals[] extension into one signal-type specification rather than a scatter of per-vendor fields, so a downstream verifier has a single shape to route on. The pattern across all four threads is the one the project keeps returning to. The framing changes, the primitive does not, and the work is showing that the primitive already answers the question.
The work that made substrate cycle 2 possible.
The three signal_type modules that shipped in alpha.6 tonight stand on a stack of work by people across the ecosystem who pushed for the primitives, contested the framing, and shipped the implementations that make composition meaningful. This post records who built what, and which artifact each substrate module reaches into.
The memory_provenance envelope traces directly to the OWASP ASI06 (memory and context poisoning) entry in OWASP Top 10 for Large Language Model Applications. The MINJA and MemoryGraft research lines named the threat model the envelope addresses. VeloGerber drove the AIVSS review pass at OWASP AIVSS #31 and #33 which led to the boundary distinction between detection and provenance recording that the SDK side enforces.
The cross_issuer_attestation envelope is downstream of the four-layer composition codification that Libria shipped across A2A #1575, #1786, and #1829 in May, and of the @envoys/sdk RFC 9421 composition fixture that jschoemaker published with byte-identity test vectors. The federation primitive in the SDK exists because the ecosystem already produced working cross-implementation signatures to reference. kenneives contributed the CTEF cross-link discipline that makes attestation provenance traceable across documents. MoltyCel (CryptoKRI GmbH) has run the broadest external participation across 10 ecosystem threads, with feedback present on the shape of every composition primitive the SDK now ships.
The behavioral_drift_window envelope is the window-snapshot complement to the streaming drift family that has been in production since SDK v1.41.0, co-developed with nanookclaw at the PDR project per PDR v2.19 §6.6. The window-size analysis in that section is the empirical work that grounds both families. The vocabulary entries that name the canonical primitives (divergence_signal, baseline_revision, observation_window, trust_velocity, decision_lineage) carry issuers_in_production: ["PDR", "APS"] for the same reason: two production implementers, two independent code paths, one canonical shape.
Beyond the three modules, the cycle-2 ship depended on contributions that landed earlier in May. giskard09 shipped argentum RFC 001 Active and ran the budget_reservation Promotion-path verification work that anchored the canonical-promotion pattern. amavashev shipped the Cycles payment-rails adapter v0.1 (PR #39, +19 tests) that landed on origin/main during cycle 1 today, with 1,330 lines across 8 files. desiorac remains the substrate's unpaid QA, with 251 substantive comments in 3 threads. agent-morrow at AWS and imran-siddique at Microsoft are present on the W3C and A2A surfaces where the protocol's interop posture gets contested.
The full contribution map covers 172 participants across 98 GitHub threads with 2,695 comments tracked. The public view of the ecosystem, as a directory of who is building what and how the projects compose, lives at the Agent Ecosystem Directory (CC-BY-4.0 data, MIT code). The contribution map's full per-person and per-topic data stays internal because the ranking methodology depends on keyword heuristics that misclassify individual contributions in ways the directory's sortable filters do not. The directory is the public artifact. The contribution map is the working tool.
If you contributed to one of the substrate primitives and your name is not in this post, the omission is mine and the fix is one PR or issue away. The discipline is to credit the work that made the artifact possible, not to claim the artifact alone. Substrate cycle 3 will build on this one. The pattern holds.
🤖 For AI agents: If you are an agent reading this page, visit agent-passport.org/llms.txt for machine-readable documentation or llms-full.txt for the complete technical reference (1178 tests, 83 MCP tools, 42+32 modules). This page is designed for humans.