Skip to content

A did:web issuer that cannot be resolved is no longer a bad signature - #78

Merged
ottonomy merged 1 commit into
fix/proof-set-all-proofsfrom
fix/did-web-unresolved
Oct 21, 2026
Merged

ottonomy merged 1 commit into
fix/proof-set-all-proofsfrom
fix/did-web-unresolved

Conversation

@ottonomy

Copy link
Copy Markdown
Contributor

Stacked on #76 — review and merge that first.

Closes #65.

When a did:web issuer's DID document could not be fetched (a 404, or an unreachable host), proof.signature failed with INVALID_SIGNATURE, which is the same verdict a tampered credential gets. The README's error taxonomy already promised DID_WEB_UNRESOLVED for this case, and classifySignatureError already reports it for an HTTPError whose requestUrl is the issuer's DID document. The problem was that the did:web driver verifier-core wires (didWebDriverWithHttpGet) threw plain Errors, so that branch never fired.

What changed

  • didWebDriverWithHttpGet now rejects with a DidDocumentFetchError, named HTTPError and carrying requestUrl (plus status for a non-2xx answer). It does this for a non-2xx status and for anything httpGetService.get throws (transport failure, timeout, size cap, URL-policy refusal). It keeps the fetcher's fixed message and attaches the original error as cause, so no network error text reaches a problem detail.
  • The classifier is unchanged. A failed fetch for a key that is not the issuer's, or for a presentation's own proof, now reports HTTP_ERROR.
did:web DID document fetch before after
non-2xx (e.g. 404) INVALID_SIGNATURE DID_WEB_UNRESOLVED
fetcher throws (host down, timeout, …) INVALID_SIGNATURE DID_WEB_UNRESOLVED
fails for a key that is not the issuer's, or a presentation proof INVALID_SIGNATURE HTTP_ERROR
succeeds, signature broken INVALID_SIGNATURE unchanged

Tests

  • Driver tests with a stubbed fetch: a 404, and a fetch that throws. The second asserts that the fixed message is kept, that no ENOTFOUND text appears, and that the cause chain is preserved.
  • test/did-web-unresolved.spec.ts:
    • classifier cases for an issuer host, a path DID, another host, a did:key issuer, and no credential;
    • offline createVerifier cases with a real Ed25519Signature2020 signature (404 and fetch failure → DID_WEB_UNRESOLVED);
    • a control case: with the DID document served, the honest credential verifies and a tampered one still reports INVALID_SIGNATURE.
  • The acceptance cases fail when the driver change is reverted.

Validation

  • pnpm run build: passes.
  • pnpm run test (lint + vitest): passes, with 1003 tests.
  • tsc -p tsconfig.dev.json: the same 6 pre-existing errors as on the base branch, and none new.
  • Manual check on the live network: vc-test-fixtures verifiableCredentials/v2/ed25519/didWeb/badDidWeb.json verified with createVerifier() defaults now gives DID_WEB_UNRESOLVED ("…could not be retrieved from https://digitalcredentials.github.io/dcc-did-web-bad/did.json").
  • test:browser (Playwright) was not run.

Not in this PR

  • A DID document that loads but has the wrong id, and an allow-list refusal, still report INVALID_SIGNATURE.
  • A status list whose did:web issuer cannot be resolved still reports STATUS_LIST_SIGNATURE_ERROR.

🤖 Generated with Claude Code

…ESOLVED

When a did:web issuer's DID document could not be fetched, a 404 or an
unreachable host, `proof.signature` failed with `INVALID_SIGNATURE`:
the same verdict a tampered credential gets. The classifier already
reports `DID_WEB_UNRESOLVED` for an `HTTPError` whose `requestUrl` is
the issuer's DID document, but the did:web driver verifier-core wires
threw plain `Error`s, so that branch never fired.

- `didWebDriverWithHttpGet` now rejects with a `DidDocumentFetchError`,
  named `HTTPError` and carrying `requestUrl` (and `status` for a
  non-2xx answer), for a non-2xx status and for anything
  `httpGetService.get` throws. The fetcher's fixed message is kept and
  its error becomes `cause`, so no network error text reaches a
  problem detail.
- A fetch failure for a key that is not the issuer's, or for a
  presentation's own proof, now reports `HTTP_ERROR`.
- A DID document with the wrong `id` and an allow-list refusal are
  unchanged.
- Tests: driver cases with a stubbed `fetch`, classifier cases pinning
  the issuer match, and offline acceptance cases through
  `createVerifier` with a real signature, including a tampered
  credential on a resolvable did:web issuer that still reports
  `INVALID_SIGNATURE`.
- CHANGELOG Fixed entry; README `HTTP_ERROR` row says it covers a key
  that is not the issuer's.

Closes #65

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ottonomy
ottonomy added this pull request to stack #77 October 20, 2026 23:06
@ottonomy
ottonomy merged commit e86bb79 into main Oct 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An unreachable did:web is reported as INVALID_SIGNATURE, not DID_WEB_UNRESOLVED

1 participant