# Tasks — `add-webauthn-mds3` ## 1. Package scaffolding - [ ] 1.1 Create `packages/auth/webauthn-mds3/` per genesis package layout. - [ ] 1.2 `package.json` at `version: 0.0.0`, `sideEffects: false`, `workspace:^` for internal deps, `catalog:*` for external. - [ ] 1.3 `tsconfig.json` extending `@suaveplan/typescript-config` universal preset. - [ ] 1.4 `vitest.config.ts` using `createTestConfig()` from `@suaveplan/testing/config`; coverage thresholds 100 / 100 / 100 / 100; `provider: 'istanbul'`. - [ ] 1.5 Subpath exports map in `package.json`: `.`, `./fetch`, `./verify`, `./cache`, `./refresher`, `./errors`. - [ ] 1.6 Root `README.md` with one-paragraph description, install, quick-start, Modules section linking to every co-located `.md`. ## 2. Constants + FIDO root pinning - [ ] 2.1 `src/constants/fido-root.ts` + `.md` — pin the FIDO Alliance MDS3 root CA DER bytes + SHA-256 fingerprint; export `FIDO_MDS3_DEFAULT_URL`, `DEFAULT_REFRESH_INTERVAL_MS`, `DEFAULT_REVOCATION_STATUSES`. ## 3. Error codes - [ ] 3.1 `src/errors/error-codes.ts` + `.md` — `defineCodes("WEBAUTHN_MDS3", [...])` with every code from the spec delta; export `WebAuthnMds3Error`. - [ ] 3.2 `src/errors/errors.test.ts` — assert every code is reachable from a production path (call-site grep harness). ## 4. Schemas - [ ] 4.1 `src/schemas/metadata-blob.schemas.ts` + `.md` — `MetadataBlobPayloadSchema`, `MetadataStatementSchema`, `AuthenticatorStatusSchema`, `StatusReportSchema`, `BiometricStatusReportSchema`, `EcdaaTrustAnchorSchema`, `MetadataBlobEntrySchema` tracking FIDO MDS3 §3.1. ## 5. Fetch - [ ] 5.1 `src/fetch/fetch-blob.ts` + `.md` — `fetchMetadataBlob({ fetch, url?, signal? })`; maps non-2xx → `BLOB_FETCH_FAILED`; honors `AbortSignal`. - [ ] 5.2 `src/fetch/fetch-blob.test.ts` — happy path; non-2xx; abort. ## 6. Verify - [ ] 6.1 `src/verify/verify-blob.ts` + `.md` — verify compact JWS via `@suaveplan/jws`; pin alg allow-list (RS256, ES256, ES384); validate `x5c` chain to FIDO root via `@suaveplan/x509`; check `nextUpdate`; decode + Zod-validate payload. - [ ] 6.2 `src/verify/verify-blob.test.ts` — happy, signature-flipped, chain-broken, expired, alg-disallowed, schema-mismatch (use sample-blob fixture). ## 7. Cache - [ ] 7.1 `src/cache/metadata-cache.ts` + `.md` — wraps injected `StorageLike` with key namespace `webauthn-mds3:blob:v1`; surfaces `CACHE_READ_FAILED` / `CACHE_WRITE_FAILED`. - [ ] 7.2 `src/cache/metadata-cache.test.ts` — round-trip; injected storage failure mapping. ## 8. Refresher - [ ] 8.1 `src/refresher/metadata-refresher.ts` + `.md` — `createMetadataRefresher({ fetch, storage, clock, logger, intervalMs?, signal? })`; reentrancy guard; OTel counter; jittered scheduling at `nextUpdate - jitter`. - [ ] 8.2 `src/refresher/metadata-refresher.test.ts` — schedule, reentrancy guard, abort, OTel counter, fallback to `intervalMs`. ## 9. Resolver - [ ] 9.1 `src/resolver/types.ts` + `.md` — `MetadataResolver`, `MetadataLookup` interfaces (no name collisions per AGENTS.md §10 — folder is `resolver/`, files use feature names not `*-resolver.ts`). - [ ] 9.2 `src/resolver/memory.ts` + `.md` + `memory.test.ts` — `createMemoryResolver` for verified payloads. - [ ] 9.3 `src/resolver/cached.ts` + `.md` + `cached.test.ts` — `createCachedResolver` reading the cache + optional refresher drive. ## 10. Observability - [ ] 10.1 `src/observability/metrics.ts` + `.md` — `webauthn_mds3.refresh_total{outcome}`, `webauthn_mds3.lookup_total{outcome}` counters; `webauthn_mds3.blob_age_ms` histogram. No-op when no exporter. - [ ] 10.2 `src/observability/metrics.test.ts` — every metric records on its production path against an in-memory `MeterProvider`. ## 11. Fixtures - [ ] 11.1 `src/__fixtures__/mds3-sample-blob.jwt` — captured FIDO Alliance MDS3 conformance-suite sample blob. - [ ] 11.2 `src/__fixtures__/mds3-corrupted-blob.jwt` — signature-flipped variant for negative tests. - [ ] 11.3 `src/__fixtures__/index.ts` — typed fixture exports. ## 12. Benchmarks - [ ] 12.1 `src/__benchmarks__/verify-blob.bench.ts` — JWS verify throughput on the sample blob. - [ ] 12.2 `src/__benchmarks__/resolve-aaguid.bench.ts` — AAGUID lookup throughput. ## 13. Integration into `@suaveplan/webauthn` - [ ] 13.1 Extend `VerifyAttestationInput` with optional `metadata?: MetadataResolver` field (typed via `import type` from `@suaveplan/webauthn-mds3` — no runtime dep). - [ ] 13.2 Extend `AttestationVerifyResult` with optional `metadata?: MetadataLookup` field. - [ ] 13.3 Wire post-verifier resolution: AAGUID for non-U2F formats, attestation-cert SKI for `fido-u2f`; downgrade `trusted=false` on revoked statuses; configurable revocation set with default from `DEFAULT_REVOCATION_STATUSES`. - [ ] 13.4 Update `packages/auth/webauthn/src/verifier/verify-attestation.test.ts` — three new tests: resolver injected augments result; revoked status downgrades trust; no resolver = byte-identical legacy behaviour. - [ ] 13.5 Refresh `packages/auth/webauthn/src/verifier/verify-attestation.md` and the three attestation doc anchors (`packed.md`, `fido-u2f.md`, `none.md`) so the "caller wires MDS3" language now mentions `MetadataResolver` as the canonical seam. - [ ] 13.6 Add `@suaveplan/webauthn-mds3` to `packages/auth/webauthn/README.md` Modules section as the recommended MDS3 sidecar. ## 14. Pre-publish gate - [ ] 14.1 `bunx turbo lint typecheck test --filter=@suaveplan/webauthn-mds3` green. - [ ] 14.2 `bunx turbo test:coverage --filter=@suaveplan/webauthn-mds3` 100 / 100 / 100 / 100. - [ ] 14.3 `bunx turbo lint typecheck test --filter=@suaveplan/webauthn` green (dependent sweep — §13 step 10). - [ ] 14.4 Banned-pattern scan: zero matches per §13 step 4. - [ ] 14.5 Barrel-shape scan (§13 step 4a): zero matches. - [ ] 14.6 Test-runner import scan (§13 step 4b): zero matches. - [ ] 14.7 Missing-`.md` scan: zero misses. - [ ] 14.8 `bunx markdownlint-cli2 --fix` then second pass with no `--fix` exits 0. ## 15. Repo-root manifest refresh (§13b) - [ ] 15.1 `bun scripts/folder-reorg/generate-manifest.ts` → `MANIFEST.md` refreshed. - [ ] 15.2 `bun scripts/generate-missing.ts` → `MISSING.yml` refreshed. - [ ] 15.3 `STATUS.md` updated: add `@suaveplan/webauthn-mds3` row. - [ ] 15.4 `SUMMARY.md` paragraph for `webauthn-mds3` added. ## 16. Fold + archive - [ ] 16.1 Fold `specs/webauthn-mds3/spec.md` into `openspec/specs/webauthn-mds3/spec.md`. - [ ] 16.2 Fold `specs/webauthn/spec.md` `## MODIFIED Requirements` into the canonical `openspec/specs/webauthn/spec.md`. - [ ] 16.3 Move `openspec/changes/add-webauthn-mds3/` → `openspec/archive/-add-webauthn-mds3/`.