Files
2026-05-27 23:29:53 +01:00

5.0 KiB

Capability Spec Delta: webauthn (webauthn)

Package: @suaveplan/webauthn Status: PROPOSED (companion delta of complete-webauthn-mds3)

Every requirement below carries a **Verified by:** line at authoring time. No exceptions.

MODIFIED Requirements

Requirement: Attestation verification dispatch

The package SHALL export verifyAttestation(input: VerifyAttestationInput): Promise<AttestationVerifyResult> from the ./verifier subpath. The function SHALL dispatch on input.attestationObject.fmt to the per-format verifier registered in input.registry, throwing WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED when no verifier is registered. VerifyAttestationInput SHALL accept an optional metadata?: MetadataResolver field and an optional statusFilter?: StatusFilter field (both typed via import type from @suaveplan/webauthn-mds3 — runtime-optional). AttestationVerifyResult SHALL carry an optional metadata?: MetadataLookup field. When input.metadata is undefined the returned AttestationVerifyResult SHALL be byte-identical to the pre-modification contract (strict back-compat). When input.metadata is supplied, after the per-format verifier returns, verifyAttestation SHALL resolve the AAGUID — or, for fmt === "fido-u2f" or an all-zero AAGUID, the SHA-1 SKI of the leaf attestation certificate (FIDO MDS3 §3.1.6) — call lookup / lookupByCertKeyId on the supplied resolver, set result.metadata to the returned MetadataLookup (or omit when undefined), and downgrade result.trusted to false when (input.statusFilter ?? DEFAULT_STATUS_FILTER).accept(lookup.currentStatus) === false.

Scenario: dispatches to registered format verifier

  • WHEN verifyAttestation({ attestationObject: { fmt: "packed", ... }, registry: defaultAttestationRegistry(), ... }) is called
  • THEN the result is produced by the packed verifier and includes trustPath, attestationType, trusted

Scenario: throws WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED on unknown fmt

  • WHEN verifyAttestation({ attestationObject: { fmt: "unknown-fmt", ... }, registry: emptyRegistry }) is called
  • THEN the call rejects with WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED

Scenario: omits metadata field when no resolver injected (back-compat)

  • WHEN verifyAttestation(input) is called with input.metadata === undefined
  • THEN the resolved AttestationVerifyResult has metadata === undefined and is byte-for-byte identical to the legacy (pre-modification) result for the same inputs

Scenario: augments result with metadata when resolver injected

  • GIVEN a MetadataResolver whose lookup returns a MetadataLookup with currentStatus === "FIDO_CERTIFIED_L1"
  • WHEN verifyAttestation({ ..., metadata: resolver }) is called against a packed attestation carrying a known AAGUID
  • THEN result.metadata deep-equals the lookup AND result.trusted is the verifier's original value (unchanged)

Scenario: downgrades trusted=false when default filter rejects status

  • GIVEN a MetadataResolver whose lookup returns currentStatus === "REVOKED" and no caller-supplied statusFilter
  • WHEN verifyAttestation({ ..., metadata: resolver }) is called and the per-format verifier returned trusted: true
  • THEN the merged result.trusted is false AND result.metadata.currentStatus === "REVOKED"

Scenario: caller-supplied statusFilter overrides default

  • GIVEN a MetadataResolver returning currentStatus === "REVOKED" and statusFilter: createStatusFilter({ allow: new Set(["REVOKED"]) })
  • WHEN verifyAttestation({ ..., metadata: resolver, statusFilter }) is called and the verifier returned trusted: true
  • THEN the merged result.trusted is true AND result.metadata.currentStatus === "REVOKED"

Scenario: resolves U2F by attestation-cert SKI

  • GIVEN a MetadataResolver and a fido-u2f attestation whose leaf cert has SKI 0xDEAD…
  • WHEN verifyAttestation({ ..., metadata: resolver }) is called
  • THEN the resolver's lookupByCertKeyId(0xDEAD…) is invoked exactly once AND lookup is never called

Verified by: packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"dispatches to registered format verifier" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"throws WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED on unknown fmt" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"omits metadata field when no resolver injected (back-compat)" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"augments result with metadata when resolver injected" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"downgrades trusted=false when default filter rejects status" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"caller-supplied statusFilter overrides default" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"resolves U2F by attestation-cert SKI"