## Selection rationale — why these five first The 2026-04-25 audit (`/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md`, §1) lists ten missing fixtures. This wave picks the five with **direct existing-package consumers in the genesis tree** (per the `CLAUDE.md` package list) so each new fixture immediately unblocks integration testing for shipped code: | Plugin | Direct consumer on genesis | Audit severity | |---|---|---| | `testing-integration-oidc` | `@suaveplan/oauth-client` (Authorization Code + PKCE, Client Credentials, OIDC discovery) | Critical | | `testing-integration-mongodb` | data-tier parity with `@suaveplan/db-sqlite`; future `db-mongodb` | Critical | | `testing-integration-mysql` | data-tier parity with `@suaveplan/db-sqlite`; future `db-mysql` | Critical | | `testing-integration-minio` | AWS-S3 surface parity vs `testing-integration-garage-s3` quirks | High | | `testing-integration-nats` | `@suaveplan/events`; future stream-processing | High | ## Deferred (next waves) - **OpenTelemetry collector** — required to verify exported spans/metrics end-to-end across every package. Held back because it needs a co-designed assertion helper (`assertSpanExported(name, attributes)`) that does not yet exist; spec lands with the OTel-collector change. - **Elasticsearch / OpenSearch** — Typesense covers our search surface today; no shipped consumer. - **Vault** — no shipped secrets consumer; `@suaveplan/env` and `@suaveplan/config` cover env/file layers. - **LocalStack** — overlaps with MinIO + future SQS/SNS work; revisit once an AWS-API consumer ships. - **Caddy / nginx reverse-proxy** — useful for routing tests once `apps/testbed` formalises a reverse-proxy contract. - **Kafka / RabbitMQ** — NATS goes first as the lightest broker; Kafka follows when a Kafka-specific consumer is on deck. ## `dependsOn` interaction Audit §3 flags that `ServiceFixture` lacks declared inter-fixture dependencies. The `testing-integration` core package is expected to gain a `dependsOn?: string[]` field on `ServiceFixture` and topo-sort start order in `TestEnvironment`. That field is specified by `testing-integration` itself — **out of scope** for this change — but every plugin in this wave MUST tolerate its presence: - `testing-integration-oidc` is the canonical upstream: an app fixture that authenticates against the issuer would declare `dependsOn: ['oidc']`. The OIDC fixture itself declares no dependencies. - `testing-integration-mongodb` / `mysql` / `minio` / `nats` likewise declare no dependencies; downstream app fixtures depend on them. Plugins MUST NOT introspect the `dependsOn` field; resolution is `TestEnvironment`'s responsibility. ## Image-pinning policy Mirroring the existing six-plugin precedent: each plugin pins a **minor tag** (`mongo:7.0`, `mysql:8.4`, `nats:2.10-alpine`, `quay.io/keycloak/keycloak:26.0`) AND records a `# TODO: replace with sha256:` comment in the constants file. Digest substitution happens during the implementation chunk, not in the spec — the spec only requires that a digest placeholder exists. ## Env-bridge contract (uniform across all five) When **all** documented env vars for a plugin are present and non-empty, the fixture's `start()` MUST skip container creation entirely and return a `ServiceFixtureHandle` whose config points at the live service. This is the same contract the existing six plugins implement. Each plugin spec below enumerates its env-var set explicitly. ## Injectable fakes — coverage strategy Each fixture exposes a constructor option object with at least: - `containerFactory?: () => GenericContainer` — swap in a fake container for unit tests. - One of: `fetchFn?: typeof fetch` (HTTP-driven seeding — OIDC, MinIO), `execFn?: (cmd: string[]) => Promise<{ stdout, stderr, exitCode }>` (in-container CLI seeding — MongoDB, MySQL, NATS), `tcpPingFn?: (host, port) => Promise` (TCP healthchecks — NATS). This pattern is exactly what `testing-integration-redis` (tcp ping), `testing-integration-postgres` (exec), and `testing-integration-garage-s3` (fetch + exec) already use; consistency lets the same Vitest fake helpers be re-used across plugins. ## Error-code namespacing Each plugin reserves a top-level prefix under `INTEGRATION.*`: `INTEGRATION.OIDC.*`, `INTEGRATION.MONGODB.*`, `INTEGRATION.MYSQL.*`, `INTEGRATION.MINIO.*`, `INTEGRATION.NATS.*`. Codes match `^INTEGRATION\.[A-Z0-9_]+\.[A-Z_]+$` (same regex the existing plugins use).