Authority freshness: treat a change in authority state as an input to trust freshness - #375
Merged
Conversation
…ss input Add an AuthorityState credential carrying a monotonic authorityEpoch and a status, signed with eddsa-jcs-2022. SessionVouchers and heartbeat requests now record the epoch they were minted under, and the heartbeat validator tracks the highest epoch it has seen per authority. verify_agent_call takes a consequence tier and, for state-freshness tiers, rejects a voucher minted under a stale epoch even when its time-decay trust still passes. The critical tier requires a live M-of-N co-sign read at action time, verified as a standard Ed25519 signature. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0 Co-authored-by: Sudip Chatterjee <263618491+aiconsulting4future@users.noreply.github.com>
…rror to Go Add the canonical AuthorityState build/verify and the epoch-collapse rule to core/vouch-core, and mirror them in the Go sidecar. Both share a new interop vector in test-vectors/authority-state/ generated from Python: a proof built in one language verifies in another, a stale-epoch tamper is rejected everywhere, and every language reaches the same freshness verdict. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
…hared vector Port AuthorityState and the epoch-collapse rule to the TypeScript SDK, verified against the shared interop vector so it agrees byte-for-byte with the Rust core, Go, and Python. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
Add an Authority freshness section to the demos experience: a toggle fires an authority-state transition, and the same time-valid voucher that is accepted for a routine action is rejected for a state-freshness action, with the critical tier falling back to a live M-of-N co-sign. Add the plain-English explainer to docs and the README. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
The unknown-epoch reason code rendered differently in each language because each printed its own null value. Render an absent epoch as "?" everywhere so the string is identical across Python, the Rust core, TypeScript, and Go, and pin both unknown-epoch cases in the shared interop vector so it cannot drift again. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
Add the AuthorityState build, sign, verify, and freshness-evaluation bindings to the WASM core so a browser runs the same operations as the native SDKs. The smoke test reproduces the shared interop vector's proof value in the browser core and matches every freshness case. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
…e example Add sign_authority_state, matching the signer-based one-call form the other credential builders offer, so publishing a state does not need the raw key by hand. Add examples/authority_freshness_demo.py alongside the other demo companions, showing a voucher whose decayed trust still passes being refused once the authority state moves. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
Add tools to publish a signed authority state, verify one, and apply the freshness gate to an action, so an MCP client can use the capability without writing code against the SDK directly. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
Add the capability to the FAQ, the help guides, the home and tools pages, the knowledge base, the Claude skill, the custom GPT, and the Gem, so each one describes it the same way: freshness is time and state and consequence, the epoch comparison is local, and the top tier reads a live quorum co-sign. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
…he design Add the rationale for the epoch to the design doc, the demo copy, and the verify path: a timestamp says when a voucher was minted and never whether authority has changed since, so time alone forces a guess at a safe window, while a new epoch is proof that a real transition happened. The design doc credits the discussion the framing and the treasury scenario came from. Support attesting a design contribution when minting a contributor credential, so someone whose design a change implements can be credited accurately without the credential claiming they wrote the code. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
Name the GitHub account behind the design credit in the specification, the changelog, and the demo section, so the acknowledgement points somewhere. Signed-off-by: Ramprasad Gaddam <groups.rampy1@gmail.com> Vouch-DID: did:vouch:be434c6279c0
Contributor
Vouch Verified Contributor ✨Thank you @aiconsulting4future. The design this pull request implements came from you, and that earns a signed Your certificate (download and share it): https://vouch-protocol.com/c/aiconsulting4future/375 Add the badge to your profile or site (optional): [](https://vouch-protocol.com/c/aiconsulting4future/375)Your Verifiable Credential (eddsa-jcs-2022){
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://vouch-protocol.com/contexts/v1"
],
"id": "urn:uuid:25af0415-4062-4776-88fd-9df9baf04671",
"type": [
"VerifiableCredential",
"VouchCredential"
],
"issuer": "did:web:vouch-protocol.com:contributors",
"validFrom": "2026-08-01T19:45:27Z",
"validUntil": "2126-07-08T19:45:27Z",
"credentialSubject": {
"id": "did:web:vouch-protocol.com:contributors",
"vouchVersion": "1.0",
"intent": {
"action": "attest",
"target": "github:aiconsulting4future",
"resource": "https://github.com/vouch-protocol/vouch/pull/375",
"role": "design-contributor",
"repository": "vouch-protocol/vouch",
"contributionType": "design",
"implementedIn": 375,
"contribution": "Argued that trust freshness must be a function of both elapsed time and authority state change, with the consequence of the action setting the threshold, and supplied the treasury and trading scenario where a credential stays cryptographically valid while no longer representing current authority."
},
"delegationChain": [
{
"issuer": "did:web:vouch-protocol.com",
"subject": "did:web:vouch-protocol.com:contributors",
"intent": {
"action": "attest",
"target": "github:aiconsulting4future",
"resource": "https://github.com/vouch-protocol/vouch/pull/375",
"role": "design-contributor",
"repository": "vouch-protocol/vouch",
"contributionType": "design",
"implementedIn": 375,
"contribution": "Argued that trust freshness must be a function of both elapsed time and authority state change, with the consequence of the action setting the threshold, and supplied the treasury and trading scenario where a credential stays cryptographically valid while no longer representing current authority."
},
"validFrom": "2026-06-19T04:45:43Z",
"validUntil": "2036-06-16T04:45:43Z",
"parentProofValue": "z5g1N4udQdy5asdxnV3qFhApB5cAh28DkMqHjEUSNG6cc8hrDDsxWyVbgn1XXUFR"
}
]
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"created": "2026-08-01T19:45:27Z",
"verificationMethod": "did:web:vouch-protocol.com:contributors#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "z4barz5UTC8s1SEwDLWqLATs4m82M8Rh3yVJkUAksYEkYPKD8nEtb2iwz2p3L3qkbyGQAchyhxsoQ1rftY46mecd5"
}
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Makes a change in authority state a first-class input to trust freshness, alongside elapsed time and the consequence of the action.
An authority publishes a signed
AuthorityStatecredential carrying a monotonicauthorityEpochand a status. SessionVouchers and heartbeat requests record the epoch they were minted under, and for an action that calls for state freshness a verifier refuses a voucher minted under an older epoch, even when its time-decay trust still passes. A timestamp says when a voucher was minted and never whether authority has changed since, so time alone forces a verifier to guess a safe staleness window. A new epoch is proof that a real transition occurred.The epoch comparison is local and needs no network call at action time. The top consequence tier stops trusting cached state entirely and requires a live M-of-N co-sign read at the moment of the action, because a cached epoch cannot cover the gap between the last refresh and this action.
Type of Change
Related Issues
Closes #374
Changes Made
AuthorityStatebuild and verify in the Rust core, mirrored to Python, TypeScript, Go, and WebAssembly, signed witheddsa-jcs-2022.SessionVoucherand heartbeat requests carryauthorityEpoch; the heartbeat validator tracks the highest epoch it has seen per authority.authority_epoch_stale:seen=7,voucher=5that are byte-identical across languages.test-vectors/authority-state/, proving a proof built in one language verifies in the others, that a stale-epoch proof is rejected everywhere, and that all five implementations reach identical freshness verdicts.examples/authority_freshness_demo.pyalongside the other demo companions.Testing
pytest tests/)Python 1339 passed, Rust 168 plus interop, TypeScript 397, Go signer suite, MCP 20, and the WebAssembly smoke test at 20 including reproducing the shared vector's proof value in the browser core. The website static export builds.
Checklist
Credit
The design behind this change did not originate in the repository. It came out of a public discussion with Sudip Chatterjee (@aiconsulting4future), who made two specific contributions: he argued that freshness must be a function of both elapsed time and authority state change, with the consequence of the action setting the threshold, rather than time-decay alone; and he supplied the driving scenario of an autonomous treasury or trading agent whose authority is valid at one moment and, seconds later, is overtaken by a fraud signal, a suspended mandate, or a breached exposure limit, leaving a credential that stays cryptographically valid while no longer representing current authority. He observed that in those cases the acceptable stale window collapses toward zero. That framing is the reason this feature exists. The code here was written in this repository; the design is credited to that discussion, and the feature commit carries a
Co-authored-bytrailer.Once this merges, the Verified Contributor credential for that design contribution is minted by running the
Verified Contributor credentialworkflow with the design inputs, which is the path added in this pull request for crediting someone who did not author the commits: