Files
2026-05-27 23:29:53 +01:00

3.6 KiB

OpenSpec Change: idempotency-spec-conformance

  • Change ID: idempotency-spec-conformance
  • Package: @suaveplan/idempotency
  • Status: PROPOSED
  • Date: 2026-04-26

Summary

Bring @suaveplan/idempotency into spec conformance with openspec/specs/idempotency/spec.md. The implementation already satisfies every MUST clause; this change closes the documentation and parsing gaps so bun scripts/openspec-conformance.ts @suaveplan/idempotency exits 0. No public-API changes.

Current state

@suaveplan/idempotency ships a complete enterprise-grade implementation: structured error hierarchy, eight IDEMPOTENCY.* codes with metadata, eight Zod boundary schemas, injectable Clock, AbortSignal propagation, full OTel meter wiring, MemoryIdempotencyStore / RedisIdempotencyStore / DatabaseIdempotencyStore, MemoryLockProvider / RedisLockProvider, fast-check property tests, and a mitata benchmark suite. The conformance gaps are mechanical:

  • src/error-codes.ts declared the codes inline ({ ... } as const) instead of via defineCodes("IDEMPOTENCY", [...]), so the conformance script could not parse the registry.
  • The folded spec used ### REQ-IDMP-NNN — name headings, which the parser (^[A-Z][A-Z0-9]*-\d+) silently skips, yielding 0 parsed requirements.
  • Schemas were exported but never invoked outside src/schemas/ (every consumer composes the underlying Zod object directly), triggering boundary warnings.
  • 10/10 requirements lacked **Verified by:** lines.
  • Five implicit scenarios were exercised only indirectly: clock injection, AbortSignal mid-flight, OTel no-op + per-instrument labels, structural-adapter acceptance, and benchmark presence.
  • tasks.md of 2026-04-19-enterprise-idempotency/ carries the retroactively ticked marker.

What changes

  1. Refactor src/error-codes.ts to declare IDEMPOTENCY_CODES via defineCodes("IDEMPOTENCY", [...]) from @suaveplan/error. Re-export from src/errors/idempotency-error.ts for backwards compat. No public-API change.
  2. Add // schema: boundary-only marker to src/schemas/idempotency.schemas.ts to suppress the (correct) boundary warning — schemas are consumer-facing only.
  3. Rewrite the requirement headings in openspec/specs/idempotency/spec.md from REQ-IDMP-NNN — name to IDMP-NN — name so the conformance parser picks them up. Add **Verified by:** lines under every requirement.
  4. Add five *.spec-conformance.test.ts files pinning the implicit scenarios:
    • src/errors/idempotency-error.spec-conformance.test.ts — IDMP-01 (hierarchy + namespace + frozen registry).
    • src/schemas/idempotency.schemas.spec-conformance.test.ts — IDMP-02 (every required schema present and round-trippable).
    • src/guard/idempotency-guard.spec-conformance.test.ts — IDMP-03 (clock-driven timestamps & cleanup) + IDMP-04 (pre-aborted and mid-flight signal).
    • src/metrics/idempotency-metrics.spec-conformance.test.ts — IDMP-05 (no-op without meter, all five instruments, correct outcome / operation / result labels, histogram values).
    • tests/structural-adapters.spec-conformance.test.ts — IDMP-08 (plain-object adapter and lock provider).
    • tests/benchmarks-present.spec-conformance.test.ts — IDMP-07 (suite at canonical path covers all four hot paths).
  5. Re-run bun scripts/openspec-conformance.ts @suaveplan/idempotency and confirm exit 0.

Impact

  • Public API unchanged.
  • Error-code registry now uses the canonical defineCodes helper.
  • Six new test files (~350 lines combined).
  • openspec/specs/idempotency/spec.md gains 10 **Verified by:** lines and parseable headings.