Files
suaveplan/openspec/archive/2026-05-26-api-plugin-example/proposal.md
2026-05-27 23:29:53 +01:00

69 lines
5.0 KiB
Markdown

# `@suaveplan/api-plugin-example` — reference plugin exercising every capability under every isolation tier
**Package**: `@suaveplan/api-plugin-example`
**Status**: PROPOSED
**Type**: new-package
**Stage**: 8 — see umbrella `openspec/changes/api-plugin-foundation/`
## Why
Per design doc §13.5, the reference plugin is a load-bearing integration test, not a tutorial. It exercises every contract surface in the foundation — every capability, every lifecycle hook, every route variant, every distributed-transaction surface, every error code mapping, every migration class. The host's CI runs the example's full integration suite on every host change so any host-side change that breaks the plugin contract fails loudly, in one place, against real Postgres + real Hono router.
The example also doubles as the canonical onboarding doc: when a plugin author asks "how do I use capability X?", the answer is "look at how `api-plugin-example` uses it."
## What changes
- ADDED: A complete `plugin.json` exercising every top-level key (`requiredCapabilities`, `optionalCapabilities`, `isolation`, `trustLevel`, `permissions`, `dependsOn`, `routes`, `graphql`, `websockets`, `sse`, `sagas`, `twoPhaseCommit`, `database`, `jobs`, `events`, `secrets`, `config`, `scopes`, `telemetry`, `openapi`, `errors`, `uninstall`).
- ADDED: `src/index.ts` exporting `definePlugin({ ... })` with:
- REST routes covering every Section 6 step: public, private, validated, streaming, idempotent, rate-limited, RBAC-gated.
- GraphQL types + resolvers + subscriptions (federated alongside a second tiny plugin in the integration test).
- WebSocket endpoint with subscription fan-out (single-host bus AND multi-host bus exercised).
- SSE endpoint with `Last-Event-Id` resume.
- Owned saga (3-step) with compensations + 2PC participation flag.
- Scheduled cron jobs (`reconcile-invoices`, `send-monthly-statements` per-tenant) + queued jobs (`send-receipt`).
- Event publish + subscribe (`example.invoice.created`, subscribes to `users.user.deleted`).
- Custom error codes (`PLUGIN.EXAMPLE.*`) with manifest-mapped statuses + redaction rules.
- Custom metrics declared in manifest (`example.invoices_finalised_total`, `example.stripe.call_duration_ms`, `example.outstanding_invoice_count`).
- Multiple secrets declared.
- ADDED: Migrations across two `schemaVersion` bumps in `migrations/postgres/` (and surrealdb / sqlite mirrors) to exercise upgrade-on-reload AND auto-rollback when the second migration is forced to fail (`tests/integration/migration-rollback.integration.test.ts`).
- ADDED: Integration test (`tests/integration/full-flow.integration.test.ts`) that boots the example against:
1. `isolation: "trusted"`
2. `isolation: "isolated"` (worker thread + worker-rpc)
3. `isolation: "sandboxed"` with vm (`api-sandbox-vm`)
4. `isolation: "sandboxed"` with WASM (`api-sandbox-wasm`)
and exercises the full surface in each tier. Real Postgres via `testing-integration-postgres`, real Hono router.
- ADDED: Intentional schema-violation route (`/_/test/fail-response?failResponse=1`) to integration-test response validation in `enforce` and `warn` modes.
## Out of scope
- Production-grade business logic — the example's routes do the minimum to exercise the surfaces. They are NOT a billing engine.
- Cross-plugin federation specifics beyond the second-plugin pair used for federation tests.
- A web UI for the example — covered by separate frontend work.
## Source mapping
Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`.
| Requirement | Design doc section |
|---|---|
| Reference plugin exercises every capability | §13.5 |
| Routes covering every Section 6 step | §13.5 |
| Migrations across two schema versions | §13.5 |
| Integration test against real Postgres + real Hono | §13.5 |
| Deploys against all three isolation tiers | §15 "What done looks like" |
## Verification approach
The example IS the integration test target. The spec is structured so every documented capability is a separate Requirement whose `Verified by:` cites a concrete integration-test `it(...)`. The integration tests live in this package's `tests/integration/` directory and run as part of host CI.
- `tests/integration/full-flow.integration.test.ts` — runs the full surface against all four isolation modes (parameterised over `["trusted", "isolated", "sandboxed-vm", "sandboxed-wasm"]`).
- `tests/integration/migration-rollback.integration.test.ts` — schema-bump upgrade + forced-failure rollback.
- `tests/integration/response-validation.integration.test.ts` — `?failResponse=1` in `enforce` vs `warn` modes.
- `tests/integration/graphql-federation.integration.test.ts` — federated query across this plugin and a sibling test plugin.
- `tests/integration/ws-broadcast.integration.test.ts` — single-host and multi-host fan-out.
- `tests/integration/saga-2pc.integration.test.ts` — owned saga full happy + compensated paths; 2PC vote/commit/abort cycle.
## Migration impact
None — additive only. The example serves as the canonical integration target for host CI.