Repository navigation
feat(oid4vc): revoke and reactivate by holder did:key - #41
Merged
Merged
Conversation
Coverage report
Show new covered files 🐣
Show files with reduced coverage 🔻
Test suite run success384 tests passing in 29 suites. Report generated by 🧪jest coverage report action from 23b1749 |
2 tasks done
bwmx
force-pushed
the
feat/revoke-by-did-key
branch
from
September 29, 2026 12:32
0f61987 to
92c3e50
Compare
bwmx
force-pushed
the
feat/revoke-by-did-key
branch
from
October 1, 2026 10:08
c71baf9 to
e0177e7
Compare
bwmx
marked this pull request as ready for review
October 1, 2026 10:31
Revoke and reactivate accept `holderDidKey` as a third way to address credentials, alongside the issuance session's `sessionId` or `credoIssuanceSessionId`. It acts on every issuance session pinned to that wallet did:key, whole-session, exactly as a session id does. Exactly one of the three is accepted; anything else is a 400, and a holder with no sessions is a 404. Sessions are changed one at a time, not atomically; re-sending the request finishes a part-way failure. A holder's unredeemed offers get the status too: the session records a revoked status change with no bits to flip, which allocateForSession already refuses, so the offer cannot issue a valid credential after the holder is revoked. Reactivating the holder, or that offer by its own session id, lifts it. Offer creation writes `sessions/issuance/by-holder/<multibase>/<sessionId>` before the session record, so a failed write leaves at most an index entry that findByHolder skips, never a session that escapes a holder revocation. `GET /credential/issuer/sessions` gains a `?holderDidKey=` filter backed by the same index. The did:key is checked against `did:key:z<base58>` before it becomes a Vault path segment; the key type is not decoded.
bwmx
force-pushed
the
feat/revoke-by-did-key
branch
from
October 1, 2026 12:46
e0177e7 to
14c1c5b
Compare
# Conflicts: # src/oid4vc/REVOCATION_PLAN.md
bwmx
changed the base branch from
feat/credentials-status-and-revoke
to
master
October 2, 2026 12:41
bwmx
marked this pull request as draft
October 2, 2026 15:06
|
Have a fix based on CoPilot recommendations locally but need push access. |
Contributor
Author
Can you create a PR or is that not possible? I don't have relevant permissions RN. If you fork I could even look there in the meantime. We're just finalising this one currently so any fixes are great! |
|
Ran into perhaps the same kind of permissions issue last night, but you can
take a look at:
https://github.com/metacampus-org/intermezzo/tree/master
…On Sun, Oct 4, 2026 at 8:14 PM Blair ***@***.***> wrote:
*bwmx* left a comment (algorandfoundation/intermezzo#41)
<#41 (comment)>
Have a fix based on CoPilot recommendations locally but need push access.
Can you create a PR or is that not possible? I don't have relevant
permissions RN. If you fork I could even look there in the meantime.
We're just finalising this one currently so any fixes are great!
—
Reply to this email directly, view it on GitHub
<#41?email_source=notifications&email_token=ACZSY4ZI3ES2ZV53UBQGMH35SLYW3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKOJYGY2DIMZXGEZ2M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5986443713>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACZSY4ZKKZZTR3CC225EGET5SLYW3AVCNFSNUABFKJSXA33TNF2G64TZHM4TKNJSGM3DQMJZHNEXG43VMU5TKNBXGMZTCOJXGQ42C5QC>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/ACZSY444EXXNPJ2NILGKXHL5SLYW3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKOJYGY2DIMZXGEZ2M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/ACZSY44UTIM2JQDQ67FGQWT5SLYW3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKOJYGY2DIMZXGEZ2M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you commented.Message ID:
***@***.***>
|
Collaborator
|
A couple things to note after looking at this:
We also have a few places that can fixed up that are less critical:
|
Revoking or reactivating by holderDidKey changed one session at a time, so a failure part-way left some sessions changed and the rest untouched. Each holder-wide change is now one transaction, coordinated through a holder record at intermezzo/oid4vc/holders/records/<multibase>: - The holder record is written first. It blocks redemption for every offer the holder has, including offers created later, and records the change so that a re-sent request resumes it. - Each session then records the change and what it replaced. A failure at this step restores everything; no status bit has moved yet. - Commit is a compare-and-set on the holder record, after which each status list flips all of the holder's bits in one write. A failure or crash from there leaves the change pending, still blocking issuance, and re-sending the request finishes it. A committed change is never aborted. Concurrent requests for the same holder drive the same change without undoing or overwriting each other's work, and a request that finds the change already finished undoes any late claims instead of completing them. Holder-wide changes leave changes made by sessionId alone. A credential revoked by sessionId keeps its own reason and time, and stays revoked when the holder is reactivated. An unfinished sessionId change blocks a holder-wide change (409), and a sessionId change waits only while an unfinished, committed holder change owns its session. Sessions created before the holder index existed are indexed once per Vault, by a backfill that starts at boot; holder lookups wait for it. Redemption is now refused before a status entry is allocated when the session or its holder is revoked or changing status, so a blocked redemption no longer uses up an entry. W3C credentials, which carry no status claim, get the same check: it is their only control. createOffer deletes its local writes if saving the session fails.
bwmx
marked this pull request as ready for review
October 26, 2026 14:47
PhearZero
self-requested a review
October 26, 2026 16:53
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.
Adds holder
did:keyas a third way to addressPOST /credential/status/revokeand/reactivate, alongside the parent branch'ssessionIdandcredoIssuanceSessionId.{ "holderDidKey": "did:key:z6Mk...", "reason": "device reported stolen" }It acts on every issuance session pinned to that wallet
did:key, whole-session, the same way a session id does. The body takes exactly one of the three fields: anything else returns 400, and a holder with no sessions returns 404.GET /credential/issuer/sessionsalso gains a?holderDidKey=filter.How
createOfferwritessessions/issuance/by-holder/<multibase>/<sessionId>before the session record. A failed write leaves at most an index entry thatfindByHolderskips, never a session that escapes a holder revocation. Thedid:keymust matchdid:key:z<base58>before it becomes a Vault path segment.allocateForSessionalready refuses issuance from a revoked session, so the open offer cannot issue a valid credential after the holder is revoked. Reactivating the holder, or that offer by its own session id, lifts the fence.Parent-branch behaviour
Unchanged.
sessionId/credoIssuanceSessionIdrequests were run against the parent (625e72a) and this branch with the same 21 bodies (each id alone and with a reason, both, neither,null,'', a number, unknown ids, an over-long reason, reactivate after revoke). Status codes, flipped bits, returned entries and audit fields match.revokeBySessionId/reactivateBySessionId, the entities and the status list repository are untouched. The 400 message now lists all three fields.Validation
Run on the merged tree (
31669b9, master included):test/app.e2e-spec.tsandtest/pq-accounts.e2e-spec.ts, and the capacity check.Known limits
did:keyvalues are checked against the base58 shape only; the key type is not decoded. Decoding (via Credo'sDidKey) is left for a follow-up that also covers the existing check increate-credential-offer.dto.ts.src/oid4vc/README.mdandSEQUENCE.mdare updated to match.