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

5.0 KiB

@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.