54 lines
5.0 KiB
Markdown
54 lines
5.0 KiB
Markdown
## Why
|
|
|
|
Section 2 of the test-suite audit (`/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md` row "No contract tests") lists consumer/provider contract testing as a critical missing tier of the test pyramid: `@suaveplan/oauth-client`, `@suaveplan/webhook-client`, `@suaveplan/schema-registry`, and `@suaveplan/api-schemas` are textbook Pact candidates whose failure modes (provider drifting from consumer expectations, schema breaking changes, OAuth token-endpoint shape mutations, webhook signature drift) are not catchable by today's unit, integration, or E2E tiers.
|
|
|
|
Today the only schema-shaped guard is hand-written Zod validation in each package's tests, which proves the consumer's encoder agrees with itself, not that a real provider's responses still match what the consumer was built against. This change introduces a project-wide Pact-style consumer/provider contract testing capability and wires it into every consumer package whose surface crosses a network boundary.
|
|
|
|
## What Changes
|
|
|
|
### New package — `@suaveplan/testing-contract`
|
|
|
|
- Lives at `packages/testing/testing-contract` and follows the same dependency-graph exception as `@suaveplan/testing-integration`: zero `@suaveplan/*` runtime deps except `@suaveplan/types` (per `CLAUDE.md` rule 8 testing-infrastructure carve-out).
|
|
- Public API:
|
|
- `defineConsumerInteraction({ provider, request, response, state? })` — declarative interaction record.
|
|
- `recordPactInteraction(httpClient)` — wraps a `fetch`-shaped client; while wrapped, every request/response pair is recorded against the matching `defineConsumerInteraction` declarations into a `.pact.json` file.
|
|
- `verifyProviderAgainstPact(pactFile, providerUrl, options)` — replays a pact file's interactions against a running provider and asserts each response matches the recorded shape.
|
|
- `publishPact(brokerUrl, version)` and `pullPactsForVerification(brokerUrl, providerName)` — optional Pact Broker integration; auth via `PACT_BROKER_TOKEN` env.
|
|
- Pact file shape conforms to Pact Specification v3 `interactions[]` (consumer/provider names, request, response, providerStates).
|
|
- Errors prefixed `TESTING_CONTRACT.*`. Coverage gate at 100% (Istanbul, all four metrics).
|
|
|
|
### Cross-cutting requirements on consumer packages
|
|
|
|
Each of the four packages SHALL ship a `*.contract.test.ts` that records interactions against its public API surface using `recordPactInteraction`. The recorded `.pact.json` files are committed to `pacts/<consumer>__<provider>.json` so PR review surfaces wire-format drift. Provider-side specs (where the package itself implements a server / receiver — `webhook-client` receivers, `schema-registry` server) SHALL run `verifyProviderAgainstPact` in CI against the same pact files.
|
|
|
|
### Capability deltas
|
|
|
|
Each consumer package gets an `## ADDED Requirements` block carrying:
|
|
|
|
- A **Consumer-side pact recording** requirement (must produce a pact file in `pacts/`).
|
|
- For server-shaped packages (`webhook-client` receiver, `schema-registry` server), a **Provider-side pact verification** requirement.
|
|
|
|
## Capabilities
|
|
|
|
### New Capabilities
|
|
|
|
- `testing-contract` — Pact-style consumer/provider contract testing primitives (`defineConsumerInteraction`, `recordPactInteraction`, `verifyProviderAgainstPact`, `publishPact`, `pullPactsForVerification`).
|
|
|
|
### Modified Capabilities
|
|
|
|
- `oauth-client` — adds consumer-side pact requirement against the OAuth/OIDC provider's token + discovery endpoints.
|
|
- `webhook-client` — adds consumer-side (signing) and provider-side (receiver) pact requirements.
|
|
- `schema-registry` — adds consumer-side (schema lookup) and provider-side (registry server) pact requirements.
|
|
- `api-schemas` — adds consumer-side pact recording over the `common`/`auth`/`admin`/`events` envelope shapes that consumers send to API plugins.
|
|
|
|
(None of these capabilities have a pre-existing `openspec/specs/<capability>/spec.md` yet; the deltas in this change land them as new files when folded.)
|
|
|
|
## Impact
|
|
|
|
- **Affected code:** new package at `/mnt/s/web/genesis/packages/testing/testing-contract/**`; new `*.contract.test.ts` files inside the four consumer packages; new `pacts/` directories per consumer package.
|
|
- **Affected consumers:** every `@suaveplan/*` package whose surface crosses a network boundary inherits the requirement on its first OpenSpec change after this one lands.
|
|
- **Catalog additions (root `package.json`):** none — `testing-contract` synthesises pact JSON itself rather than depending on `@pact-foundation/pact` (which is Node-only and pulls a Ruby toolchain). The optional broker-publish path uses native `fetch`.
|
|
- **CI:** a new `pact:verify` Turborepo task runs `verifyProviderAgainstPact` on every commit for the provider-shaped packages.
|
|
- **Pre-publish gate:** every package with contract tests must pass `pact:verify` in addition to `lint typecheck test` and 100% coverage.
|
|
- **Cross-cutting:** five new spec files land on archive (`testing-contract`, `oauth-client`, `webhook-client`, `schema-registry`, `api-schemas`).
|