Initial Commit
This commit is contained in:
162
openspec/changes/api-plugin-foundation/proposal.md
Normal file
162
openspec/changes/api-plugin-foundation/proposal.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# API Plugin Foundation
|
||||
|
||||
**Package**: `@suaveplan/api-*` (umbrella across the foundation family — see Stage breakdown below)
|
||||
**Status**: PROPOSED
|
||||
**Type**: new-package (umbrella)
|
||||
|
||||
## Why
|
||||
|
||||
Genesis currently has no API host. `packages/api/` contains only `api-schemas` (Zod request/response shapes) and `sitemap` (XML utility). Every plugin we ship next — billing, users, search, files, vault-API, drive-API, network-API, auth-API — needs the same scaffolding: lifecycle, routes, multi-tenancy, hot reload, observability, error contracts. Building that scaffolding once, at enterprise quality, is what unblocks every subsequent plugin.
|
||||
|
||||
This umbrella change captures the foundation as a single coherent design. The full design lives at `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md` (committed under the brainstorming flow, reviewed by `spec-document-reviewer`, approved by the user with explicit "no MVP scoping — enterprise grade only" direction). This proposal is the OpenSpec rollup that the per-package child changes hang off.
|
||||
|
||||
## What changes
|
||||
|
||||
Eight implementation stages, each landing a coherent slice. Every stage's packages are independent OpenSpec changes — proposals + tasks + spec deltas live under `openspec/changes/api-<package-name>/`. This umbrella tracks the rollup state.
|
||||
|
||||
### Stage 1 — Contracts
|
||||
|
||||
Zero-runtime, types-only packages plus the Zod schemas + abstract interfaces every downstream package builds against. Stage gates: nothing in Stages 2-8 starts until all Stage-1 packages are merged.
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-types` | `@suaveplan/api-types` | Every cross-package interface (Principal, TenantId, PluginContext, RequestContext, Router contract, CapabilityMap, Manifest types, …). Zero runtime, zero deps. |
|
||||
| `api-manifest` | `@suaveplan/api-manifest` | Zod schema for `plugin.json`, validators, dep-graph resolver, capability resolver. |
|
||||
| `api-router` | `@suaveplan/api-router` | Abstract Router / Middleware / Request / Response types; composition (prefix mounting, middleware chains, blue-green slot management interfaces). |
|
||||
| `api-graphql` | `@suaveplan/api-graphql` | Abstract Registry / Resolver / LoaderFactory; federation contract. |
|
||||
| `api-ws` | `@suaveplan/api-ws` | Abstract WebSocket engine: ConnectionRegistry, SubscriptionBus, broker contract. |
|
||||
| `api-sse` | `@suaveplan/api-sse` | Abstract SSE engine; Last-Event-Id resume contract. |
|
||||
| `api-auth` | `@suaveplan/api-auth` | Session-resolver abstract: Request → Principal \| null. |
|
||||
| `api-auth-provider` | `@suaveplan/api-auth-provider` | Auth-provider abstract: account lifecycle routes (login/register/oauth/verify-email). |
|
||||
| `api-secrets` | `@suaveplan/api-secrets` | Abstract Secrets contract. |
|
||||
| `api-tenant-provider` | `@suaveplan/api-tenant-provider` | Abstract "list tenants" contract. |
|
||||
| `api-loader` | `@suaveplan/api-loader` | Module resolver interface + `RollbackJournal` interface (impls in Stage 2). |
|
||||
| `api-lifecycle` | `@suaveplan/api-lifecycle` | Lifecycle FSM definition (states + transitions, no concrete plugin yet). |
|
||||
|
||||
### Stage 2 — Host orchestration core
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-host` | `@suaveplan/api-host` | `CapabilityRegistry`, `definePlugin`, lifecycle driver, hot-reload primitive (blue-green + RollbackJournal), plugin ledger, admin API, error boundary, OTel scaffolding. |
|
||||
|
||||
The host metadata DB schema (tables `suaveplan_plugin_ledger`, `suaveplan_rollback_journal`, `suaveplan_saga_instances`, `suaveplan_saga_steps`, `suaveplan_2pc_transactions`) ships with `api-host`'s migrations.
|
||||
|
||||
### Stage 3 — Worker isolation infrastructure
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-worker-rpc` | `@suaveplan/api-worker-rpc` | `MessagePort` protocol; correlation; AbortSignal forwarding; streaming; error reconstruction; backpressure. |
|
||||
| `api-worker-host` | `@suaveplan/api-worker-host` | Worker-side runtime hosting one plugin; accepts capability proxies. |
|
||||
| `api-router-worker-bridge` | `@suaveplan/api-router-worker-bridge` | Request/response marshalling main↔worker. |
|
||||
| `api-db-worker-proxy` | `@suaveplan/api-db-worker-proxy` | Worker-side proxy → main-process DB adapter. |
|
||||
| `api-events-worker-proxy` | `@suaveplan/api-events-worker-proxy` | Worker-side proxy → main-process `@suaveplan/events` bus. |
|
||||
| `api-secrets-worker-proxy` | `@suaveplan/api-secrets-worker-proxy` | Worker-side proxy → main-process secrets adapter. |
|
||||
| `api-jobs-worker-proxy` | `@suaveplan/api-jobs-worker-proxy` | Worker-side proxy → main-process job scheduler. |
|
||||
| `api-logger-worker-proxy` | `@suaveplan/api-logger-worker-proxy` | Worker-side proxy → main-process logger. |
|
||||
|
||||
Conformance gate: every Stage-4 capability MUST pass its conformance suite under both direct and worker-proxy surfaces before Stage 4 can be marked complete.
|
||||
|
||||
### Stage 4 — Base adapters (both isolation surfaces)
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-router-hono` | `@suaveplan/api-router-hono` | Hono router adapter. |
|
||||
| `api-auth-jwt` | `@suaveplan/api-auth-jwt` | Session resolver via `@suaveplan/jws` against JWKS/static key. |
|
||||
| `api-auth-anonymous` | `@suaveplan/api-auth-anonymous` | Always returns null principal. |
|
||||
| `api-auth-bearer-static` | `@suaveplan/api-auth-bearer-static` | Service-to-service static-token resolver. |
|
||||
| `api-tenant-resolver-jwt` | `@suaveplan/api-tenant-resolver-jwt` | Reads `ctx.principal.tenantId`. |
|
||||
| `api-secrets-env` | `@suaveplan/api-secrets-env` | `process.env` / `Bun.env` source. |
|
||||
| `api-db-adapter` | `@suaveplan/api-db-adapter` | Bridge from `@suaveplan/db` → plugin `DatabaseLike` (Postgres/SQLite/Surreal). |
|
||||
| `api-tenant-provider-memory` | `@suaveplan/api-tenant-provider-memory` | In-memory reference + test impl. |
|
||||
|
||||
### Stage 5 — Testing kit + conformance suites
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-router-in-memory` | `@suaveplan/api-router-in-memory` | In-memory router for tests. |
|
||||
| `api-auth-static-principal` | `@suaveplan/api-auth-static-principal` | Test auth adapter — supplies a fixed `Principal`. |
|
||||
| `api-db-sqlite-memory` | `@suaveplan/api-db-sqlite-memory` | In-memory SQLite DB adapter for tests. |
|
||||
| `api-events-in-memory` | `@suaveplan/api-events-in-memory` | In-memory wrapper over `@suaveplan/events` for tests. |
|
||||
| `api-ws-broker-in-memory` | `@suaveplan/api-ws-broker-in-memory` | In-memory broker for single-host + tests. |
|
||||
| `api-host-testing-kit` | `@suaveplan/api-host/testing` (subpath) | `createTestHost` + `await using` lifecycle; not a separate package, ships as a subpath of `api-host` populated in this stage. Tracked here for sequencing. |
|
||||
|
||||
Conformance suites under `./testing` subpaths on every abstract package: `runRouterConformance`, `runAuthSessionConformance`, `runTenantResolverConformance`, `runDbAdapterConformance`, `runSecretsConformance`, `runEventsBusConformance`, `runJobsConformance`, `runGraphqlEngineConformance`, `runWsEngineConformance`, `runSseEngineConformance`, `runSagaParticipantConformance`, `run2pcParticipantConformance`.
|
||||
|
||||
### Stage 6 — Distributed transactions + Better-Auth
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-saga` | `@suaveplan/api-saga` | Saga orchestrator; manifest-declared workflows; compensable steps; persisted state. |
|
||||
| `api-2pc` | `@suaveplan/api-2pc` | Two-phase commit coordinator (Postgres `PREPARE TRANSACTION`). |
|
||||
| `api-auth-better-auth` | `@suaveplan/api-auth-better-auth` | Better-Auth wraps both `auth.session` and `auth.provider`; owns its own DB connection. |
|
||||
|
||||
### Stage 7 — GraphQL + WebSocket / SSE engines
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-graphql-yoga` | `@suaveplan/api-graphql-yoga` | GraphQL Yoga engine adapter (default). |
|
||||
| `api-graphql-apollo` | `@suaveplan/api-graphql-apollo` | Apollo engine adapter. |
|
||||
| `api-graphql-ui-graphiql` | `@suaveplan/api-graphql-ui-graphiql` | GraphiQL UI at `/graphql/ui` (default). |
|
||||
| `api-graphql-ui-altair` | `@suaveplan/api-graphql-ui-altair` | Altair UI alternative. |
|
||||
| `api-ws-bun` | `@suaveplan/api-ws-bun` | `Bun.serve` WebSocket engine. |
|
||||
| `api-ws-broker-redis` | `@suaveplan/api-ws-broker-redis` | Cross-host broadcast via Redis pub/sub. |
|
||||
| `api-sse-bun` | `@suaveplan/api-sse-bun` | `Bun.serve` SSE engine. |
|
||||
|
||||
### Stage 8 — Sandboxing + cross-cutting middleware + authoring helpers
|
||||
|
||||
| Change ID | Package | Role |
|
||||
|---|---|---|
|
||||
| `api-sandbox-permissions` | `@suaveplan/api-sandbox-permissions` | Permission model (fs/fetch allowlist, CPU/memory/wall-clock budgets). |
|
||||
| `api-sandbox-vm` | `@suaveplan/api-sandbox-vm` | `vm.Context` based sandbox for non-WASM. |
|
||||
| `api-sandbox-wasm` | `@suaveplan/api-sandbox-wasm` | WASM/WASI target host. |
|
||||
| `api-rbac` | `@suaveplan/api-rbac` | Scope + rule-based authz; reuses `@suaveplan/rules`. |
|
||||
| `api-rate-limit` | `@suaveplan/api-rate-limit` | Per-tenant / per-principal / per-IP token bucket. |
|
||||
| `api-openapi` | `@suaveplan/api-openapi` | Emission from manifest + route schemas; via `@asteasolutions/zod-to-openapi`. |
|
||||
| `api-openapi-ui-scalar` | `@suaveplan/api-openapi-ui-scalar` | Default `/docs` UI. |
|
||||
| `api-openapi-ui-swagger` | `@suaveplan/api-openapi-ui-swagger` | Swagger UI alternative. |
|
||||
| `api-openapi-ui-redoc` | `@suaveplan/api-openapi-ui-redoc` | ReDoc alternative. |
|
||||
| `api-audit-stdout` | `@suaveplan/api-audit-stdout` | Default audit sink (containers redirect). |
|
||||
| `api-audit-file` | `@suaveplan/api-audit-file` | File-rotating audit sink. |
|
||||
| `api-auth-rolled` | `@suaveplan/api-auth-rolled` | Reference rolled-our-own provider via `@suaveplan/crypto-rsa` + `webauthn` + `otp` + `srp` + `hibp` + `password-strength` + `password-generator`. |
|
||||
| `api-secrets-bun` | `@suaveplan/api-secrets-bun` | `Bun.secrets` (OS keystore). |
|
||||
| `api-secrets-vault` | `@suaveplan/api-secrets-vault` | `@suaveplan/vault` source. |
|
||||
| `api-tenant-resolver-header` | `@suaveplan/api-tenant-resolver-header` | Header-based tenant resolver. |
|
||||
| `api-tenant-resolver-subdomain` | `@suaveplan/api-tenant-resolver-subdomain` | Subdomain tenant resolver. |
|
||||
| `api-plugin-example` | `@suaveplan/api-plugin-example` | Reference plugin exercising every capability under every isolation tier. Load-bearing integration test. |
|
||||
| `create-suaveplan-plugin` | `create-suaveplan-plugin` | Scaffold via `@suaveplan/installer`. |
|
||||
|
||||
## Out of scope
|
||||
|
||||
These are explicit non-goals — captured in the design doc Section 14 and repeated here so per-package changes don't re-litigate them:
|
||||
|
||||
- **Multi-region active-active host coordination** — cross-region consistency of the plugin ledger / saga state / 2PC coordinator is a separate design. Foundation assumes one host per region.
|
||||
- **Plugin marketplace / discovery service** — foundation supports third-party plugins via npm; a curated marketplace + signing infra is its own product.
|
||||
- **Built-in feature-flag system** — `@suaveplan/feature-flags` already exists; plugins use it via the standard dep.
|
||||
- **Reversible migrations** — forward-only is the model. Plugin authors can write reversible if they want; host doesn't enforce.
|
||||
|
||||
## Source mapping
|
||||
|
||||
This is a genesis-original family. No `../suaveplan/enterprise/<pkg>.md` source. The single source of design intent is `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md` (commits `1445b41e`, `e2051e07`, `41419bae`, `1eb2569f`).
|
||||
|
||||
Per-package proposals link back to this design doc by section reference (e.g. "implements §5 Capability injection"). No package re-derives the design intent — each one specs ONLY its own surface and references the umbrella for cross-cutting concerns.
|
||||
|
||||
## Verification approach
|
||||
|
||||
This umbrella has no test files of its own — verification is delegated to per-package changes. The umbrella tracks stage-level acceptance:
|
||||
|
||||
- Stage 1 complete WHEN every Stage-1 child change is archived AND `bun openspec validate` passes for every spec delta.
|
||||
- Stage 2 complete WHEN Stage 1 ✓ AND `api-host` is archived AND boots empty (`bun examples/api-host-empty.ts` returns 200 on `/internal/livez`).
|
||||
- Stage 3 complete WHEN Stage 2 ✓ AND `api-worker-rpc` conformance suite passes against a trivial proxy capability under both direct and worker surfaces.
|
||||
- Stage 4 complete WHEN Stage 3 ✓ AND every Stage-4 adapter passes its conformance suite under both surfaces.
|
||||
- Stage 5 complete WHEN Stage 4 ✓ AND `createTestHost` boots `api-plugin-example`'s skeleton against the in-memory adapter set with 100% conformance pass.
|
||||
- Stage 6 complete WHEN Stage 5 ✓ AND a multi-step saga in `api-plugin-example` runs end-to-end including a compensation path, AND `api-2pc` commits + aborts an integration scenario against real Postgres.
|
||||
- Stage 7 complete WHEN Stage 6 ✓ AND `api-plugin-example` mounts a federated GraphQL schema across two plugins AND publishes a tenant-scoped WebSocket broadcast.
|
||||
- Stage 8 complete WHEN Stage 7 ✓ AND `api-plugin-example` deploys cleanly under every isolation tier including `sandboxed` with WASM, AND `create-suaveplan-plugin <name>` scaffolds a working package whose tests pass first time.
|
||||
|
||||
Foundation complete when Stage 8 ✓ AND the reference plugin's full integration test (Section 13.5 of the design doc) is green in CI.
|
||||
|
||||
## Migration impact
|
||||
|
||||
- `packages/api/api-schemas` and `packages/api/sitemap` keep working as pure libraries during the foundation roll-out. After Stage 8 ships, each can optionally migrate to live as a plugin if it wants lifecycle hooks; if not, they stay as pure libs consumed by plugins.
|
||||
- No other monorepo package depends on the foundation today — the foundation is additive.
|
||||
- The host metadata DB introduces a new SQLite file at `./suaveplan-host.db` by default. Production deployments will need a host-config decision (SQLite vs Postgres vs Surreal) but no existing data is touched.
|
||||
137
openspec/changes/api-plugin-foundation/tasks.md
Normal file
137
openspec/changes/api-plugin-foundation/tasks.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Tasks — API Plugin Foundation (umbrella)
|
||||
|
||||
> Umbrella change. Tasks here track stage acceptance — per-package work is checked off in each package's own change. Do not retroactively tick boxes for work done before this change opened.
|
||||
|
||||
## 0. Pre-flight (non-negotiable)
|
||||
|
||||
- [x] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
|
||||
- [x] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
|
||||
- [x] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest.
|
||||
|
||||
## 0. Pre-work
|
||||
|
||||
- [x] 0.1 Brainstorm + design doc at `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`
|
||||
- [x] 0.2 Design reviewed by `spec-document-reviewer` subagent (twice — once on initial draft, once on enterprise-scope rewrite)
|
||||
- [x] 0.3 User-approved scope: all 8 items previously deferred folded in as v1 design surface
|
||||
|
||||
## 1. Per-package OpenSpec proposals authored
|
||||
|
||||
### Stage 1 — Contracts
|
||||
|
||||
- [x] 1.1 `api-types`
|
||||
- [x] 1.2 `api-manifest`
|
||||
- [x] 1.3 `api-router`
|
||||
- [x] 1.4 `api-graphql` (abstract contract)
|
||||
- [x] 1.5 `api-ws` (abstract contract)
|
||||
- [x] 1.6 `api-sse` (abstract contract)
|
||||
- [x] 1.7 `api-auth` (abstract session-resolver)
|
||||
- [x] 1.8 `api-auth-provider` (abstract provider)
|
||||
- [x] 1.9 `api-secrets` (abstract contract)
|
||||
- [x] 1.10 `api-tenant-provider` (abstract contract)
|
||||
- [x] 1.11 `api-loader`
|
||||
- [x] 1.12 `api-lifecycle`
|
||||
|
||||
### Stage 2 — Host orchestration
|
||||
|
||||
- [x] 2.1 `api-host`
|
||||
|
||||
### Stage 3 — Worker isolation
|
||||
|
||||
- [x] 3.1 `api-worker-rpc`
|
||||
- [x] 3.2 `api-worker-host`
|
||||
- [x] 3.3 `api-router-worker-bridge`
|
||||
- [x] 3.4 `api-db-worker-proxy`
|
||||
- [x] 3.5 `api-events-worker-proxy`
|
||||
- [x] 3.6 `api-secrets-worker-proxy`
|
||||
- [x] 3.7 `api-jobs-worker-proxy`
|
||||
- [x] 3.8 `api-logger-worker-proxy`
|
||||
|
||||
### Stage 4 — Base adapters
|
||||
|
||||
- [x] 4.1 `api-router-hono`
|
||||
- [x] 4.2 `api-auth-jwt`
|
||||
- [x] 4.3 `api-auth-anonymous`
|
||||
- [x] 4.4 `api-auth-bearer-static`
|
||||
- [x] 4.5 `api-tenant-resolver-jwt`
|
||||
- [x] 4.6 `api-secrets-env`
|
||||
- [x] 4.7 `api-db-adapter`
|
||||
- [x] 4.8 `api-tenant-provider-memory`
|
||||
|
||||
### Stage 5 — Testing kit + conformance suites
|
||||
|
||||
- [x] 5.1 `api-router-in-memory`
|
||||
- [x] 5.2 `api-auth-static-principal`
|
||||
- [x] 5.3 `api-db-sqlite-memory`
|
||||
- [x] 5.4 `api-events-in-memory`
|
||||
- [x] 5.5 `api-ws-broker-in-memory`
|
||||
- [x] 5.6 `api-host` testing-kit subpath (`./testing` export populated)
|
||||
- [x] 5.7 Conformance suites authored on every abstract package (`./testing` subpaths) — `runXxxConformance` shipped from api-manifest, api-router (+ api-host's `runPipelineRouterConformance`), api-graphql, api-ws, api-sse, api-auth, api-auth-provider, api-secrets, api-tenant-provider, api-loader, api-lifecycle, api-worker-rpc. api-types is types-only, no runtime conformance.
|
||||
|
||||
### Stage 6 — Distributed transactions + Better-Auth
|
||||
|
||||
- [x] 6.1 `api-saga`
|
||||
- [x] 6.2 `api-2pc`
|
||||
- [x] 6.3 `api-auth-better-auth`
|
||||
|
||||
### Stage 7 — GraphQL + WebSocket / SSE
|
||||
|
||||
- [x] 7.1 `api-graphql-yoga`
|
||||
- [x] 7.2 `api-graphql-apollo`
|
||||
- [x] 7.3 `api-graphql-ui-graphiql`
|
||||
- [x] 7.4 `api-graphql-ui-altair`
|
||||
- [x] 7.5 `api-ws-bun`
|
||||
- [x] 7.6 `api-ws-broker-redis`
|
||||
- [x] 7.7 `api-sse-bun`
|
||||
|
||||
### Stage 8 — Sandboxing + middleware + helpers
|
||||
|
||||
- [x] 8.1 `api-sandbox-permissions`
|
||||
- [x] 8.2 `api-sandbox-vm`
|
||||
- [x] 8.3 `api-sandbox-wasm`
|
||||
- [x] 8.4 `api-rbac`
|
||||
- [x] 8.5 `api-rate-limit`
|
||||
- [x] 8.6 `api-openapi`
|
||||
- [x] 8.7 `api-openapi-ui-scalar`
|
||||
- [x] 8.8 `api-openapi-ui-swagger`
|
||||
- [x] 8.9 `api-openapi-ui-redoc`
|
||||
- [x] 8.10 `api-audit-stdout`
|
||||
- [x] 8.11 `api-audit-file`
|
||||
- [x] 8.12 `api-auth-rolled` (session-resolver half; provider half deferred to `api-auth-rolled-provider`)
|
||||
- [x] 8.13 `api-secrets-bun`
|
||||
- [x] 8.14 `api-secrets-vault`
|
||||
- [x] 8.15 `api-tenant-resolver-header`
|
||||
- [x] 8.16 `api-tenant-resolver-subdomain`
|
||||
- [x] 8.17 `api-plugin-example`
|
||||
- [x] 8.18 `create-suaveplan-plugin`
|
||||
|
||||
## 2. Stage acceptance gates
|
||||
|
||||
Per `openspec/AGENTS.md §17`, every stage closes ONLY when its **integration smoke** is green — a real-composition test booting every shipped package in the stage and exercising the cross-package seams. Per-package conformance passing is necessary but not sufficient.
|
||||
|
||||
- [x] 2.1 Stage 1 ✓ — every Stage-1 child change archived; `bun openspec validate` passes for every spec delta
|
||||
- [x] 2.2 Stage 2 ✓ — `api-host` archived; `bun examples/api-host-empty.ts` returns 200 on `/internal/livez`
|
||||
- [x] 2.3 Stage 3 ✓ — `api-worker-rpc` conformance suite passes against trivial proxy under both direct and worker surfaces
|
||||
- [x] 2.4 Stage 4 ✓ — every Stage-4 adapter passes its conformance suite under both surfaces **AND** `e2e/foundation-stack/` smoke (`bunx playwright test`) is green with NO hand-wired shims (router-pipeline, tenant-chain, secrets-injection, ledger-db). Coherence-fix changes `foundation-fix-gap-{1,2,3,4,5}` are the closure artifacts.
|
||||
- [x] 2.5 Stage 5 ✓ — `createTestHost` boots `api-plugin-example` skeleton with 100% conformance pass **AND** `e2e/foundation-stack-test-host/` smoke proves `createTestHost(config)` returns a host that drives every Stage-1..4 conformance surface without external services. (8/8 smoke groups green; foundation packages all pass §15 + §16 lint.)
|
||||
- [x] 2.6 Stage 6 ✓ — multi-step saga runs end-to-end (incl. compensation); `api-2pc` commits + aborts against real Postgres **AND** `e2e/foundation-stack-saga/` runs a 3-step compensable workflow end-to-end across two plugins. (7/7 specs green: 3 saga + 4 2PC against Postgres 16 testcontainer with `max_prepared_transactions=8`.)
|
||||
- [x] 2.7 Stage 7 ✓ — `api-plugin-example` federates GraphQL across two plugins; tenant-scoped WebSocket broadcast works **AND** `e2e/foundation-stack-engines/` smoke proves Yoga/Apollo + Bun WS + SSE coexist on one host. (5/5 specs green: 2 GraphQL federation across plugin-a+plugin-b through both Yoga and Apollo engines; 1 tenant-scoped WS broadcast with cross-tenant isolation; 1 SSE stream + publish; 1 four-engines-on-one-host route-collision check.)
|
||||
- [ ] 2.8 Stage 8 ✓ — `api-plugin-example` deploys under every isolation tier (incl. sandboxed WASM); `create-suaveplan-plugin <name>` scaffold tests pass first time **AND** `e2e/foundation-stack-full/` smoke boots every Stage 1-8 package together and exercises the full §6 11-step pipeline end-to-end.
|
||||
|
||||
### Smoke-fail = stage incomplete
|
||||
|
||||
If a smoke needs hand-wired shims to boot (today's E2E pre-Wave-1 caught 5 such gaps in Stage 4), the stage is NOT complete. Open coherence-fix changes against the gap-bearing packages — do NOT paper over with shims in the smoke. The smoke must consume canonical adapter surfaces a real downstream consumer would. See `openspec/archive/2026-05-26-foundation-fix-gap-{1,2,3,4,5}` for the precedent.
|
||||
|
||||
## 3. Foundation acceptance
|
||||
|
||||
- [ ] 3.1 Reference plugin's full integration test (design doc §13.5) green in CI
|
||||
- [ ] 3.2 Better-Auth adapter passes end-to-end OAuth flow with at least one provider (GitHub)
|
||||
- [ ] 3.3 Hot-reload cycle exercised: blue-green swap with in-flight completion + new-slot health probe + traffic flip
|
||||
- [ ] 3.4 Bad-module path: failed `start` triggers auto-rollback; plugin enters `rolled_back`; prior version keeps serving
|
||||
- [ ] 3.5 Admin API exercised end-to-end: install/uninstall/disable/enable/reload/rollback/force-uninstall with audit log entries
|
||||
- [ ] 3.6 Conformance suites pass for every adapter under both direct and worker-proxy surfaces
|
||||
|
||||
## 4. Archive
|
||||
|
||||
- [ ] 4.1 Refresh `MANIFEST.md` to include every foundation package
|
||||
- [ ] 4.2 Update `CLAUDE.md` `packages/api/` section with the foundation listing
|
||||
- [ ] 4.3 Move `openspec/changes/api-plugin-foundation/` → `openspec/archive/<yyyy-mm-dd>-api-plugin-foundation/` only after every child change is archived
|
||||
Reference in New Issue
Block a user