Files
suaveplan/openspec/changes/_superseded-narrow-deferrals-2026-05-17/add-storage-mux/tasks.md
2026-05-27 23:29:53 +01:00

93 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks — storage-mux
> Every checkbox MUST reflect work actually done in this change.
## 1. Spec authoring
- [ ] 1.1 Read `openspec/specs/storage/spec.md` and confirm `AbstractStorage` surface
- [ ] 1.2 Read `openspec/AGENTS.md` §0c, §13, §14
- [ ] 1.3 Read archived `openspec/archive/2026-05-16-add-storage-cdn/` for the deferral and family conventions
- [ ] 1.4 Read `packages/flow/retry/src/retry/retry.ts` to confirm `runWithRetry` + `RetryStrategy` surface
- [ ] 1.5 Draft `proposal.md`, `design.md`, `specs/storage-mux/spec.md`, `tasks.md`
- [ ] 1.6 Numbered Requirement/Scenario checklist per §0c step 6
## 2. Scaffolding
- [ ] 2.1 Create `packages/storage/storage-mux/` mirroring `packages/storage/storage-cdn/` conventions
- [ ] 2.2 `package.json` v0.0.0, `"sideEffects": false`, subpath exports per feature
- [ ] 2.3 Deps: `@suaveplan/error`, `@suaveplan/events`, `@suaveplan/retry`, `@suaveplan/storage`, `@suaveplan/types`, `@opentelemetry/api`, `zod`, `tslib`
- [ ] 2.4 DevDeps: `@suaveplan/testing`, `@vitest/coverage-istanbul`, `fast-check`, `mitata`, `typescript`, `vite`, `vite-plugin-dts`, `vitest`
- [ ] 2.5 `tsconfig`, `vite.config.ts`, `vitest.config.ts` via `createTestConfig`
- [ ] 2.6 `README.md` root with Modules section linking every `.md`
## 3. Error registry
- [ ] 3.1 `src/error-codes.ts` — `defineCodes("STORAGE_MUX", [...])` with 8 codes (`ALL_BACKENDS_DOWN`, `NO_BACKENDS_CONFIGURED`, `HEALTHCHECK_FAILED`, `BACKEND_TIMEOUT`, `INVALID_POLICY`, `INVALID_WEIGHT`, `WRITE_FANOUT_PARTIAL`, `BACKEND_ABORTED`)
- [ ] 3.2 `src/error-codes.ts` — `StorageMuxError extends SuaveplanError<StorageMuxErrorCode>` with `backendName`, `attemptIndex`, `attemptCount` discriminants
## 4. Types & schemas
- [ ] 4.1 `src/types/backend-entry.types.ts` — `BackendEntry` interface (`name`, `storage`, `weight?`, `healthcheck?`)
- [ ] 4.2 `src/types/mux-options.types.ts` — `MuxPolicy` discriminated string union, `StorageMuxOptions`
- [ ] 4.3 `src/types/mux-options.schemas.ts` — Zod schemas validating non-empty backends, policy whitelist, weight ≥ 0
## 5. Selectors / policies
- [ ] 5.1 `src/policies/selector.types.ts` — `BackendSelector` interface (`select(op, key?, healthy): BackendEntry`)
- [ ] 5.2 `src/policies/classify.ts` + `.md` + `.test.ts` — pure error classification per design §4 table
- [ ] 5.3 `src/policies/failover/failover.ts` + `.md` + `.test.ts` — fall-through + retry composition
- [ ] 5.4 `src/policies/round-robin/round-robin.ts` + `.md` + `.test.ts` — atomic counter, skip down
- [ ] 5.5 `src/policies/sticky-by-key/sticky-by-key.ts` + `.md` + `.test.ts` — FNV-1a hash, deterministic
- [ ] 5.6 `src/policies/shield/shield.ts` + `.md` + `.test.ts` — read cascade, write fan-out, partial signal
## 6. Health
- [ ] 6.1 `src/health/health.ts` + `.md` + `.test.ts` — `BackendHealth` tracker, exponential cooldown, recovery probe, active healthcheck via injected `Clock`
## 7. Mux core
- [ ] 7.1 `src/mux/mux.ts` + `.md` — `StorageMux extends AbstractStorage`, per-op routing through `BackendSelector` + `runWithRetry`, per-backend timeout race, AbortSignal linking
- [ ] 7.2 `src/mux/mux.test.ts` — construction validation, policy dispatch, abort surfacing
- [ ] 7.3 `src/mux/mux.spec-conformance.test.ts` — `runStorageConformance` × 4 policies × 3 `MemoryStorage` backends
## 8. Observability
- [ ] 8.1 `src/observability/events.ts` + `.md` + `.test.ts` — event topic constants (`storage-mux.backend.down`, `.recovered`, `.failover`, `.fanout-partial`), `emit*` helpers consuming `EventBusLike`
- [ ] 8.2 `src/observability/otel.ts` + `.md` + `.test.ts` — span attribute helpers (`mux.backend.name`, `mux.attempt.index`, `mux.policy`)
## 9. Barrel + exports
- [ ] 9.1 `src/index.ts` — explicit named re-exports per §6a (NO `export *`)
- [ ] 9.2 `package.json` subpath exports match every feature directory
## 10. Tests
- [ ] 10.1 `src/error-codes/error-codes.test.ts` — every `STORAGE_MUX_*` code reachable from a real call site
- [ ] 10.2 All test imports via `@suaveplan/testing/runner` (§7)
- [ ] 10.3 Every `it(...)` carries `{ timeout: 5000 }` (or 30000 for async health)
- [ ] 10.4 Backend isolation test: hung-promise primary does NOT block fallback within `backendTimeoutMs`
## 11. Documentation
- [ ] 11.1 Sibling `.md` for every implementation `.ts` (≥ 200 words, all required sections)
- [ ] 11.2 `README.md` documents each policy with a usage example
## 12. Gates
- [ ] 12.1 `bun run check`
- [ ] 12.2 `bunx turbo lint typecheck test --filter=@suaveplan/storage-mux`
- [ ] 12.3 `bunx turbo test:coverage --filter=@suaveplan/storage-mux` (100/100/100/100)
- [ ] 12.4 `bun scripts/lint/check-test-runner-imports.ts`
- [ ] 12.5 Tier-purity grep `grep -rnE "from ['\"](node:|bun:)" packages/storage/storage-mux/src/` returns empty
- [ ] 12.6 Banned-pattern scan returns empty
- [ ] 12.7 `bun scripts/openspec-conformance.ts @suaveplan/storage-mux`
## 13. Manifest & archival
- [ ] 13.1 `bun scripts/folder-reorg/generate-manifest.ts`
- [ ] 13.2 `bun scripts/generate-missing.ts`
- [ ] 13.3 Update `STATUS.md` and `SUMMARY.md`
- [ ] 13.4 `bunx markdownlint-cli2 --fix`
- [ ] 13.5 Fold `specs/storage-mux/spec.md` → `openspec/specs/storage-mux/spec.md`
- [ ] 13.6 Move change folder → `openspec/archive/<yyyy-mm-dd>-add-storage-mux/`