Files
suaveplan/openspec/archive/2026-05-19-add-notification-channel/tasks.md
2026-05-27 23:29:53 +01:00

4.0 KiB

Tasks — add @suaveplan/notification-channel

Every checkbox MUST reflect work actually done in this change. No retroactive ticking.

1. Spec authoring

  • 1.1 Read ../suaveplan/enterprise/notification-channel.md end-to-end
  • 1.2 Read upstream ../suaveplan/packages/universal/notification-channel/src/ end-to-end
  • 1.3 Read openspec/AGENTS.md §§ 0a, 2a, 6a, 7, 12a, 13, 14
  • 1.4 Draft proposal.md
  • 1.5 Fill in ## Source mapping
  • 1.6 Draft specs/notification-channel/spec.md
  • 1.7 Every requirement carries a **Verified by:** line

2. Implementation

  • 2.1 package.json, tsconfig.lib.json, vite.config.ts, vitest.config.ts, tests/setup/polyfills.ts
  • 2.2 src/error-codes.ts — defineCodes("NOTIFICATION_CHANNEL", [...]) + typed subclasses
  • 2.3 src/types/notification.types.ts — Notification, channels, status, transitions
  • 2.4 src/schemas/schemas.ts — Zod schemas at every public boundary
  • 2.5 src/hooks/hooks.ts — generic Hooks<TMap> pipeline (local — @suaveplan/events does not export Hooks on genesis)
  • 2.6 src/channels/delivery-channel.ts — DeliveryChannel/DeliveryResult
  • 2.7 src/channels/email-channel.ts
  • 2.8 src/channels/sms-channel.ts
  • 2.9 src/channels/push-channel.ts + push-channel.types.ts (injectable FetchLike)
  • 2.10 src/channels/in-app-channel.ts
  • 2.11 src/channels/webhook-channel.ts (injectable FetchLike)
  • 2.12 src/digest/digest-channel.ts (injectable Clock)
  • 2.13 src/templates/template-engine.ts
  • 2.14 src/rate-limiter/channel-rate-limiter.ts (injectable Clock)
  • 2.15 src/retry/delivery-retry.ts (injectable Clock + sleeper)
  • 2.16 src/scheduler/notification-scheduler.ts (injectable Clock)
  • 2.17 src/preferences/preference-manager.ts (injectable Clock)
  • 2.18 src/router/notification-router.ts (uses genesis EventBus, OTel, hooks)
  • 2.19 src/otel/metrics.ts — counters + histogram + refreshNotificationMeters
  • 2.20 src/fakes/fake-fetch.ts — FetchLike test double
  • 2.21 src/index.ts — explicit named re-exports; side-effect-imports ./error-codes.js

3. Tests

  • 3.1 Unit tests co-located beside each module; cover every public method + every error code at least once
  • 3.2 OTel test using real in-memory MeterProvider
  • 3.3 Tests import only from @suaveplan/testing/runner
  • 3.4 Every it(...) carries { timeout: 5000 } (30000 for async I/O)

4. Documentation

  • 4.1 Sibling .md for every implementation .ts (≥200 words, basic + advanced examples)
  • 4.2 README.md at package root linking every co-located .md under ## Modules

5. Pre-archive verification (the 5-gate triple)

  • 5.1 bun run check — Biome 0 errors / 0 warnings
  • 5.2 bunx turbo lint typecheck test --filter=@suaveplan/notification-channel — green
  • 5.3 bunx turbo test:coverage --filter=@suaveplan/notification-channel — 100/100/100/100
  • 5.4 bun scripts/openspec-conformance.ts @suaveplan/notification-channel — exit 0
  • 5.5 bunx turbo build --filter=@suaveplan/notification-channel — green

6. Pre-archive 7-row checklist (AGENTS.md §13)

  • 6.1 Generics threaded; literal-typed defineCodes union preserved through public surface
  • 6.2 Zod schemas wired at every declared boundary
  • 6.3 Every error code in NOTIFICATION_CHANNEL_CODES thrown by ≥1 production path
  • 6.4 Strict-mode behaviors tested (rate-limit window expiry, dead-letter handler optional, quiet-hours wrap-around)
  • 6.5 OTel instruments emit + asserted with real in-memory MeterProvider
  • 6.6 Lifecycle behaviors tested (cancel after send rejected, scheduler start/stop idempotent)
  • 6.7 No retroactive ticks

7. Archive

  • 7.1 Fold specs/notification-channel/spec.md into openspec/specs/notification-channel/spec.md
  • 7.2 Move openspec/changes/add-notification-channel/ → openspec/archive/2026-05-19-add-notification-channel/