Initial Commit
This commit is contained in:
158
openspec/archive/2026-05-10-enterprise-otp/tasks.md
Normal file
158
openspec/archive/2026-05-10-enterprise-otp/tasks.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Tasks — `@suaveplan/otp` (RFC 4226 / 6238 / 6287 + Key URI + recovery codes)
|
||||
|
||||
> Every checkbox MUST reflect work actually done in this change. Do not retroactively tick boxes for work that was already in main when this change opened. Do not tick a box for a test that doesn't exist or doesn't pin the requirement it claims to verify.
|
||||
|
||||
## 1. Spec authoring
|
||||
|
||||
- [ ] 1.1 Read `../suaveplan/enterprise/otp.md` end-to-end
|
||||
- [ ] 1.2 Read `openspec/AGENTS.md` Sections 13, 14, 14a
|
||||
- [ ] 1.3 Read RFC 4226 (HOTP), RFC 6238 (TOTP), RFC 6287 (OCRA), Google Authenticator Key URI Format wiki page
|
||||
- [ ] 1.4 Draft `proposal.md` from `openspec/templates/proposal.md`
|
||||
- [ ] 1.5 Fill in `## Source mapping` table — every requirement cites an RFC clause OR appears in the "no source line" table with justification
|
||||
- [ ] 1.6 Draft `specs/otp/spec.md` from `openspec/templates/spec-delta.md`
|
||||
- [ ] 1.7 Every requirement in the spec delta carries a `**Verified by:**` line naming concrete `it(...)` titles
|
||||
|
||||
## 2. Package scaffold
|
||||
|
||||
- [ ] 2.1 `packages/vault/otp/` directory structure (`src/{hotp,totp,uri,base32,ocra,recovery,drift,errors,observability}/`)
|
||||
- [ ] 2.2 `package.json` — `@suaveplan/otp@0.0.0`, `type: "module"`, `sideEffects: false`, deps via `workspace:^` / `catalog:`
|
||||
- [ ] 2.3 `tsconfig.json` extends `@suaveplan/typescript-config/library.json`
|
||||
- [ ] 2.4 `vite.config.ts` for build, `vitest.config.ts` from `@suaveplan/testing/config`
|
||||
- [ ] 2.5 `README.md` with package description, install snippet, quick-start, `## Modules` table linking every co-located `.md`
|
||||
- [ ] 2.6 Subpath exports map covers `.`, `./uri`, `./base32`, `./ocra`, `./errors`, `./observability`
|
||||
|
||||
## 3. Implementation — HOTP (RFC 4226)
|
||||
|
||||
- [ ] 3.1 `src/hotp/hotp.ts` — `hotp(secret, counter, opts?)` with dynamic truncation per §5.3 step 2
|
||||
- [ ] 3.2 `src/hotp/hotp.types.ts` — `HotpOptions`, `HotpAlgorithm`, `HotpDigits`
|
||||
- [ ] 3.3 `src/hotp/hotp.schema.ts` — `HotpOptionsSchema` Zod boundary
|
||||
- [ ] 3.4 8-byte big-endian counter encoding helper in `src/hotp/encode-counter.ts`
|
||||
- [ ] 3.5 `src/hotp/index.ts` — explicit named re-exports
|
||||
|
||||
## 4. Implementation — TOTP (RFC 6238)
|
||||
|
||||
- [ ] 4.1 `src/totp/totp.ts` — `totp(secret, opts?)` over `T = floor((now − T0) / period)` with injectable `Clock`
|
||||
- [ ] 4.2 `src/totp/verify.ts` — `verify(code, secret, opts?)` with `±window` drift; constant-time loop
|
||||
- [ ] 4.3 `src/totp/verify-many.ts` — `verifyMany(code, secrets[], opts?)` constant-time across the secret list
|
||||
- [ ] 4.4 `src/totp/totp.types.ts` — `TotpOptions`, `TotpVerifyOptions`, `TotpVerifyResult`, `TotpVerifyManyResult`
|
||||
- [ ] 4.5 `src/totp/totp.schema.ts` — `TotpOptionsSchema`, `TotpVerifyOptionsSchema` (`window` ∈ [0,10])
|
||||
- [ ] 4.6 `src/totp/index.ts` — explicit named re-exports
|
||||
|
||||
## 5. Implementation — Key URI Format
|
||||
|
||||
- [ ] 5.1 `src/uri/parse-uri.ts` — `parseUri(uri)` for `otpauth://totp/...` and `hotp` variant
|
||||
- [ ] 5.2 `src/uri/format-uri.ts` — `formatUri(opts)` round-trip with percent-encoding of label and issuer
|
||||
- [ ] 5.3 `src/uri/uri.types.ts` — `OtpUri` discriminated union (`type: "totp" | "hotp"`)
|
||||
- [ ] 5.4 `src/uri/uri.schema.ts` — `OtpUriSchema` Zod boundary
|
||||
- [ ] 5.5 `src/uri/index.ts` — explicit named re-exports
|
||||
|
||||
## 6. Implementation — Base32 (RFC 4648 §6)
|
||||
|
||||
- [ ] 6.1 `src/base32/base32.ts` — `base32Encode(bytes, opts?)` and `base32Decode(input)`; `padding=false` default to match Google Authenticator
|
||||
- [ ] 6.2 `src/base32/index.ts` — explicit named re-exports
|
||||
|
||||
## 7. Implementation — OCRA (RFC 6287)
|
||||
|
||||
- [ ] 7.1 `src/ocra/ocra.ts` — `ocra(suite, key, params)` per §6 computation
|
||||
- [ ] 7.2 `src/ocra/suite.ts` — `parseOcraSuite(suite)` per §6.1 grammar
|
||||
- [ ] 7.3 `src/ocra/verify-ocra.ts` — `verifyOcra(...)` constant-time
|
||||
- [ ] 7.4 `src/ocra/mutual-auth.ts` — `OcraMutualAuthClient`, `OcraMutualAuthServer` per §7.1
|
||||
- [ ] 7.5 `src/ocra/ocra.types.ts` — `OcraSuite`, `OcraParams`, `OcraCryptoFunction`, `OcraDataInput`
|
||||
- [ ] 7.6 `src/ocra/ocra.schema.ts` — `OcraParamsSchema` Zod boundary
|
||||
- [ ] 7.7 `src/ocra/index.ts` — explicit named re-exports
|
||||
|
||||
## 8. Implementation — Recovery codes
|
||||
|
||||
- [ ] 8.1 `src/recovery/generate.ts` — `generateRecoveryCodes(count, opts?)` Crockford-base32 grouping, injectable `Rng`
|
||||
- [ ] 8.2 `src/recovery/hash.ts` — `hashRecoveryCode(code, opts?)` Argon2id via `@suaveplan/crypto-hash`
|
||||
- [ ] 8.3 `src/recovery/verify.ts` — `verifyRecoveryCode(input, hashedCodes[])` constant-time over the full list
|
||||
- [ ] 8.4 `src/recovery/recovery.types.ts` — `RecoveryCodeOptions`, `RecoveryVerifyResult`
|
||||
- [ ] 8.5 `src/recovery/index.ts` — explicit named re-exports
|
||||
|
||||
## 9. Implementation — Clock-drift detector
|
||||
|
||||
- [ ] 9.1 `src/drift/detect.ts` — `detectDrift(code, secret, opts?)` searches `±maxSteps` outside the verify window
|
||||
- [ ] 9.2 `src/drift/drift.types.ts` — `DriftDetectOptions`, `DriftResult`
|
||||
- [ ] 9.3 `src/drift/index.ts` — explicit named re-exports
|
||||
|
||||
## 10. Implementation — Errors and observability
|
||||
|
||||
- [ ] 10.1 `src/errors/codes.ts` — `OTP_CODES` registry via `defineCodes("OTP", [...])`; `OtpError extends SuaveplanError<OtpErrorCode>`
|
||||
- [ ] 10.2 `src/errors/index.ts` — explicit named re-exports
|
||||
- [ ] 10.3 `src/observability/metrics.ts` — histograms and counters wired against `@opentelemetry/api`
|
||||
- [ ] 10.4 `src/observability/index.ts` — explicit named re-exports
|
||||
|
||||
## 11. Root barrel + subpath exports
|
||||
|
||||
- [ ] 11.1 `src/index.ts` — explicit named re-exports of HOTP, TOTP, verify, verifyMany, recovery, drift, errors, observability surfaces (no `export *`)
|
||||
- [ ] 11.2 Verify exports map count matches feature module count (§13 step 8)
|
||||
|
||||
## 12. Documentation
|
||||
|
||||
- [ ] 12.1 Sibling `.md` for every implementation `.ts` (≥200 words; basic + advanced examples; full API reference; implementation notes)
|
||||
- [ ] 12.2 README links every co-located `.md` under `## Modules`
|
||||
|
||||
## 13. Tests (runner-neutral imports — `@suaveplan/testing/runner` only)
|
||||
|
||||
- [ ] 13.1 `src/hotp/hotp.test.ts` — RFC 4226 Appendix D 10 vectors, SHA-256/512 widening, `bigint` past 2^53, digits 6/7/8
|
||||
- [ ] 13.2 `src/totp/totp.test.ts` — RFC 6238 Appendix B 6 vectors across SHA-1/256/512 at digits=8
|
||||
- [ ] 13.3 `src/totp/verify.test.ts` — window 0 / 1 / 10 / >10; `delta` semantics
|
||||
- [ ] 13.4 `src/totp/verify-many.test.ts` — multi-secret happy path + miss path
|
||||
- [ ] 13.5 `src/totp/constant-time.test.ts` — every windowed step and every secret evaluated regardless of early match
|
||||
- [ ] 13.6 `src/uri/parse-uri.test.ts` — every documented parameter; `hotp` variant; malformed paths
|
||||
- [ ] 13.7 `src/uri/format-uri.test.ts` — label / issuer percent-encoding; `:` in label rejected
|
||||
- [ ] 13.8 `src/uri/round-trip.property.test.ts` — fast-check property test
|
||||
- [ ] 13.9 `src/base32/base32.test.ts` — RFC 4648 §6 vectors; padded + unpadded; case-insensitivity; invalid alphabet
|
||||
- [ ] 13.10 `src/ocra/ocra.test.ts` — RFC 6287 Appendix C.1–C.3 vectors
|
||||
- [ ] 13.11 `src/ocra/suite.test.ts` — every §6.1 grammar branch
|
||||
- [ ] 13.12 `src/ocra/mutual-auth.test.ts` — three-message §7.1 round-trip
|
||||
- [ ] 13.13 `src/recovery/generate.test.ts` — Crockford-base32 grouping; deterministic with injected `Rng`
|
||||
- [ ] 13.14 `src/recovery/verify.test.ts` — Argon2id round-trip; constant-time over the full set
|
||||
- [ ] 13.15 `src/drift/detect.test.ts` — drift outside the verify window
|
||||
- [ ] 13.16 `src/errors/codes.spec-conformance.test.ts` — every `OTP_CODES` entry thrown by at least one production path
|
||||
- [ ] 13.17 `src/observability/metrics.spec-conformance.test.ts` — every histogram and counter emitted; assertions against an in-memory `MeterProvider`
|
||||
- [ ] 13.18 `src/index.test.ts` — every documented subpath resolves
|
||||
- [ ] 13.19 Every `it(...)` carries `{ timeout: 5000 }` (or 30000 for genuinely async)
|
||||
- [ ] 13.20 Runner-neutral imports — CLAUDE.md §11 grep clean
|
||||
|
||||
## 14. Pre-archive verification (the 5-gate triple)
|
||||
|
||||
- [ ] 14.1 `bun run check` — Biome 0 errors / 0 warnings / 0 info across the whole monorepo
|
||||
- [ ] 14.2 `bunx turbo lint typecheck test --filter=@suaveplan/otp` — green
|
||||
- [ ] 14.3 `bunx turbo test:coverage --filter=@suaveplan/otp` — 100/100/100/100
|
||||
- [ ] 14.4 `bun scripts/openspec-conformance.ts @suaveplan/otp` — exit 0, no `error` findings
|
||||
- [ ] 14.5 `bunx turbo build --filter=@suaveplan/otp` — green
|
||||
|
||||
## 15. Pre-archive 7-row checklist (AGENTS.md Section 13)
|
||||
|
||||
- [ ] 15.1 Generics threaded; `expectTypeOf` assertions on every literal-type claim (`HotpAlgorithm`, `HotpDigits`, `OtpUri.type`)
|
||||
- [ ] 15.2 Zod schemas wired at every declared boundary (`HotpOptionsSchema`, `TotpOptionsSchema`, `TotpVerifyOptionsSchema`, `OtpUriSchema`, `OcraParamsSchema`)
|
||||
- [ ] 15.3 Every error code in `OTP_CODES` thrown by at least one production path
|
||||
- [ ] 15.4 Strict-mode behaviors tested both on and off (window cap, base32 padding, label `:` rejection)
|
||||
- [ ] 15.5 OTel histograms and counters emitted from production paths and asserted with a real in-memory `MeterProvider`
|
||||
- [ ] 15.6 Lifecycle dedup — N/A (pure functions; no shared mutable state)
|
||||
- [ ] 15.7 No retroactive tick — every box above reflects work done in this change
|
||||
|
||||
## 16. Benchmarks (mitata, `src/__benchmarks__/`)
|
||||
|
||||
- [ ] 16.1 `totp_generate.bench.ts`
|
||||
- [ ] 16.2 `totp_verify_window_1.bench.ts`
|
||||
- [ ] 16.3 `totp_verify_window_10.bench.ts`
|
||||
- [ ] 16.4 `parse_uri.bench.ts`
|
||||
- [ ] 16.5 `format_uri.bench.ts`
|
||||
- [ ] 16.6 Baseline numbers published in README
|
||||
|
||||
## 17. Root-doc refresh + markdownlint (AGENTS.md §13b)
|
||||
|
||||
- [ ] 17.1 `bun scripts/folder-reorg/generate-manifest.ts` — refresh `MANIFEST.md`
|
||||
- [ ] 17.2 `bun scripts/generate-missing.ts` — refresh `MISSING.yml`
|
||||
- [ ] 17.3 `STATUS.md` — move `@suaveplan/otp` from `Pending` to `Completed`
|
||||
- [ ] 17.4 `SUMMARY.md` — add per-package paragraph
|
||||
- [ ] 17.5 `CLAUDE.md` — add package listing under "Vaulted" / vault-orchestration section
|
||||
- [ ] 17.6 `bunx markdownlint-cli2 --fix` — auto-fix; re-stage
|
||||
- [ ] 17.7 `bunx markdownlint-cli2` — second pass exit 0
|
||||
|
||||
## 18. Archive
|
||||
|
||||
- [ ] 18.1 Fold spec delta into `openspec/specs/otp/spec.md` (canonical, status ACTIVE)
|
||||
- [ ] 18.2 Move `openspec/changes/enterprise-otp/` → `openspec/archive/<yyyy-mm-dd>-enterprise-otp/`
|
||||
Reference in New Issue
Block a user