Repository navigation
Expiry and revocation no longer halt verification - #75
Merged
Merged
Conversation
`fatal` decided two things at once: a failure made `verified` false, and it halted every later check for the subject. A check can now set `halts: false` to keep the first and drop the second, so a fatal failure that leaves later checks meaningful no longer hides their results. `halts` defaults to `fatal`, so existing checks and caller-added suites behave as before, and their rows keep their shape. A throwing `applies` predicate still halts, since it leaves every check in its suite unknown. More than one suite summary can now carry `fatalFailureAt`; `verified` is false exactly when any does. No built-in check sets `halts` yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… longer halts An expired or not-yet-valid credential failed `proof.signature`, which halts, so its revocation status, its issuer's registration and any caller-added suites came back "Not run". The credential is authentic at that point: @digitalcredentials/vc checks dates only after the proof verifies. - The Data Integrity crypto service reports vc's date failure as a typed CREDENTIAL_EXPIRED / CREDENTIAL_NOT_YET_VALID problem. It does so only for a plain Error, not a VerificationError and with no errors[], whose message matches vc's wording in full, so a date phrase inside a wrapped proof error never counts. - `proof.signature` reads a rejection made only of those problems as a verified signature. - New `proof.validity-period` check, after the signature, judges the dates against the verifier's clock. Fatal, so `verified` stays false, but `halts: false`, so later checks still run. - `status.bitstring` tells an expired status list from a bad one by problem type rather than message text. A tampered and expired credential is still reported as a bad signature; offline tests with real signatures pin this, and fail if a future vc checks dates before the proof. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`status.bitstring` halted the run when it failed, so a revoked or suspended credential, or one whose status list could not be trusted, never reported whether its issuer is registered or who signed the list. A revocation read from a list signed by someone other than the issuer therefore read as a plain revocation. - `status.bitstring` stays fatal but sets `halts: false`. - `status.list-issuer` compares only lists whose proof verified, or was rejected only for its validity dates. It no longer relied on running only after every list verified, which held only while the status check halted. A list whose proof did not verify is skipped, not compared. - Each status list's proof verification is memoised per verification, beside the existing memo of loaded lists, so both checks share one verification per list, judged at one moment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README, the verification-results and architecture docs, and the 2.0.0 CHANGELOG entry said that every fatal failure halts later checks, that at most one suite carries `fatalFailureAt`, and that expiry is part of the signature check. Describe `halts`, `proof.validity-period`, the two built-in fatal checks that do not halt, and what an expired or revoked credential now reports, with an expired-and-revoked example. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Closes #63. Closes #64.
Why
fataldecided two things at once: a failure madeverifiedfalse, and it halted every later check. So:proof.signature. Status, registry and any added suites came back "Not run", even though the credential is authentic:@digitalcredentials/vcchecks dates only after the proof verifies. A revoked-and-expired credential read only "Expired" (Expiry halts verification, so a revoked-and-expired credential reports only expiry #63).status.bitstring, sostatus.list-issuernever ran on a list that marked a credential. A revocation from a list signed by someone else read as a plain revocation (A revocation mark on a list signed by another DID is reported as a revocation, with no sign the list isn't the issuer's #64).What changed
halts?: booleanonVerificationCheck/CheckResult, defaulting tofatal. A fatal check withhalts: falsestill makesverifiedfalse, but the checks after it run. Existing checks and caller suites behave as before, and their rows keep their shape.New
proof.validity-periodcheck (fatal,halts: false), run afterproof.signature. It judgesvalidFrom/validUntil(v2) orissuanceDate/expirationDate(v1) against the verifier'sTimeService, and reportsCREDENTIAL_EXPIRED/CREDENTIAL_NOT_YET_VALID.proof.signaturereads a date-only rejection as a verified signature. The Data Integrity crypto service reports vc's date failure as a typed problem only when all of these hold:Error;VerificationError;errors[];So a date phrase quoted inside a wrapped proof error never counts. The
CryptoServiceTSDoc states the contract.status.bitstringstays fatal but setshalts: false. It now classifies an expired status list by problem type, not by message text.status.list-issuercompares only lists whose proof verified (or was rejected only for its dates), so it now runs, and reports, after a revocation mark. Each list's proof verification is memoised per verification, beside the existing memo of loaded lists, so both checks share one verification per list.Docs: README,
docs/api/verification-results.md,docs/architecture.md, CHANGELOG. More than one suite can now carryfatalFailureAt;verifiedis false exactly when any does.verifieddoes not change for any input.Checked locally
pnpm run build: clean.pnpm run test(lint + vitest): 941 passed, up from 907 onmain.pnpm exec tsc -p tsconfig.dev.json: the same 6 errors asmain.proof.validity-period"Not run". If a future vc checked dates before the proof, these tests fail.VerificationErrorname check, theerrors[]check, the anchored match,proof.signaturepassing any rejection,status.bitstring'shalts: false, andlist-issuertrusting unverified lists.CREDENTIAL_REVOKED+STATUS_LIST_ISSUER_MISMATCH;STATUS_LIST_EXPIRED+ mismatch;list-issuerskipped.test:browser(Playwright).For consumers
Expiry now appears on
cryptographic.proof.validity-period, not oncryptographic.proof.signature. A UI should expect more than one suite withfatalFailureAt, and results for rows that used to be "Not run" after an expiry or revocation.🤖 Generated with Claude Code