Files
suaveplan/openspec/archive/2026-05-18-add-api-plugin-webhook/tasks.md
2026-05-27 23:29:53 +01:00

5.3 KiB

Tasks — add-api-plugin-webhook

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

1. Spec authoring

  • 1.1 Read ../suaveplan/enterprise/api-plugin-webhook.md end-to-end
  • 1.2 Read openspec/AGENTS.md Sections 13 and 14
  • 1.3 Draft proposal.md from openspec/templates/proposal.md
  • 1.4 Fill ## Source mapping — every requirement cites enterprise audit line + justified additions
  • 1.5 Draft specs/api-plugin-webhook/spec.md from openspec/templates/spec-delta.md
  • 1.6 Every requirement carries a **Verified by:** line at authoring time

2. Implementation

  • 2.1 src/error-codes/error-codes.{ts,test.ts,md,index.ts} — 10 WEBHOOK_* codes + WebhookError
  • 2.2 src/types/types.{ts,md,index.ts} — WebhookEndpoint, CreateEndpointInput, UpdateEndpointInput, WebhookPluginOptions, WebhookPluginConfig
  • 2.3 src/schemas/endpoint.{ts,test.ts,md,index.ts} — WebhookEndpointSchema, CreateEndpointInputSchema, UpdateEndpointInputSchema
  • 2.4 src/schemas/options.{ts,test.ts,md,index.ts} — WebhookPluginOptionsSchema
  • 2.5 src/schemas/routes/*.{ts,test.ts,md} + index.ts — per-route schemas (list, create, read, update, delete, test)
  • 2.6 src/otel/instruments.{ts,test.ts,md,index.ts} — counters + histograms, reset for tests
  • 2.7 src/store/endpoint-store.{ts,md,index.ts} — EndpointStore interface
  • 2.8 src/store/memory.{ts,test.ts,md} — MemoryEndpointStore
  • 2.9 src/dead-letter/dead-letter.{ts,md,index.ts} — DeadLetterSink interface + DeadLetterEntry
  • 2.10 src/dead-letter/memory.{ts,test.ts,md} — MemoryDeadLetterSink
  • 2.11 src/services/webhook-service.{ts,test.ts,md,index.ts} — WebhookService impl wrapping @suaveplan/webhook-client
  • 2.12 src/services/registry-augmentation.ts — ServiceRegistry augmentation
  • 2.13 src/routes/build-routes.{ts,test.ts,md,index.ts} — buildWebhookRoutes(service, opts) returning PluginRouteEntry[]
  • 2.14 src/plugin/plugin.{ts,test.ts,md,index.ts} — createWebhookPlugin(options) factory + 5-step onInit lifecycle
  • 2.15 src/api-plugin-webhook.spec-conformance.test.ts — every WEBHOOK_* code thrown from a production path; expectTypeOf on WebhookService, registry augmentation
  • 2.16 src/index.ts — explicit named re-exports only

3. Tests

  • 3.1 Co-located *.test.ts per spec scenario via @suaveplan/testing/runner
  • 3.2 tests/integration/delivery.test.ts — real Hono receiver on random port: register → send → receive; assert HMAC sig + canonical headers + payload
  • 3.3 tests/integration/retry.test.ts — receiver returns 500 twice then 200; delivery succeeds, attempts.length === 3
  • 3.4 tests/integration/dead-letter.test.ts — receiver always returns 500; after maxAttempts send rejects with DELIVERY_EXHAUSTED and dead-letter sink contains the entry
  • 3.5 tests/integration/full-boot.test.ts — real PluginRegistry + real Hono app + real receiver; CRUD via routes then send via service
  • 3.6 tests/dep-graph.test.ts — pins 14 subpath exports + sibling .md per impl file
  • 3.7 All it(...) carry { timeout: 5000 } (30000 for integration)
  • 3.8 Zero vi.mock, zero direct from "vitest" | "bun:test" imports

4. Documentation

  • 4.1 Sibling .md (≥200 words, basic + advanced examples, API reference) per impl file
  • 4.2 README.md — quick-start: defineApp().use(createWebhookPlugin({ ... })); CRUD via routes; service-side send() recipes; EndpointStore / DeadLetterSink extension recipes; OTel + idempotency notes

5. Pre-archive verification (the 5 gates)

  • 5.1 cd /home/paul/web/genesis && bun run check — Biome 0/0/0 across the monorepo
  • 5.2 bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-webhook --force
  • 5.3 bunx turbo test:coverage --filter=@suaveplan/api-plugin-webhook — 100/100/100/100
  • 5.4 bun scripts/openspec-conformance.ts @suaveplan/api-plugin-webhook — exit 0
  • 5.5 bunx turbo build --filter=@suaveplan/api-plugin-webhook --force
  • 5.6 bun scripts/lint/check-test-runner-imports.ts

6. Pre-archive 9-row checklist

  • 6.1 Generics threaded; expectTypeOf assertions on WebhookService / EndpointStore / ContextVariableMap
  • 6.2 Zod schemas wired at every route + factory boundary
  • 6.3 Every WEBHOOK_* error code thrown by at least one production path (asserted by api-plugin-webhook.spec-conformance.test.ts)
  • 6.4 Strict-mode behaviors tested (invalid input rejected; ZodError surfaced as cause)
  • 6.5 OTel counters + histograms emitted from production paths and asserted via real in-memory MeterProvider
  • 6.6 Per-delivery in-flight dedup tested (concurrent send() with same key resolves to one delivery)
  • 6.7 No retroactive tick — every box above reflects work done in this change
  • 6.8 No export * in any feature barrel
  • 6.9 No direct vitest / bun:test imports in src/ or tests/

7. Archive

  • 7.1 Fold spec delta into openspec/specs/api-plugin-webhook/spec.md
  • 7.2 Move openspec/changes/add-api-plugin-webhook/ → openspec/archive/2026-05-18-add-api-plugin-webhook/
  • 7.3 DO NOT touch MANIFEST.md / STATUS.md (per orchestrator instruction)