Initial Commit
This commit is contained in:
63
openspec/archive/2026-05-26-api-graphql-apollo/proposal.md
Normal file
63
openspec/archive/2026-05-26-api-graphql-apollo/proposal.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# `@suaveplan/api-graphql-apollo` — Apollo Server GraphQL engine adapter
|
||||
|
||||
**Package**: `@suaveplan/api-graphql-apollo`
|
||||
**Status**: PROPOSED
|
||||
**Type**: new-package
|
||||
**Stage**: 7 (GraphQL + WebSocket / SSE engines) — see umbrella `openspec/changes/api-plugin-foundation/`
|
||||
|
||||
## Why
|
||||
|
||||
Per design doc §10.5 the foundation ships GraphQL Yoga as the default engine but offers Apollo Server as an alternative for shops standardised on Apollo's broader feature set — Apollo Studio integration, persisted-query manifest support, the @apollo/federation tooling, and a larger plugin ecosystem (including operation-cost analyzers and request-coalescing). Both engines MUST be host-config swappable, which is only meaningful if both implement the same `api-graphql` contract and pass the same conformance suite.
|
||||
|
||||
Without this adapter the foundation has only one GraphQL engine, undermining the §10.5 "engine choice" guarantee and forcing Apollo-standardised teams to fork the foundation.
|
||||
|
||||
## What changes
|
||||
|
||||
Net-new package depending on `@suaveplan/api-types`, `@suaveplan/api-graphql`, `@suaveplan/api-router`, `@suaveplan/api-ws`, `@suaveplan/error`, `@suaveplan/logger`, `@suaveplan/opentelemetry`, `@apollo/server` (peer), `graphql` (peer), `@apollo/server-plugin-landing-page-disabled` (peer), and `zod`.
|
||||
|
||||
- ADDED: `createApolloGraphqlEngine(opts)` — factory returning the engine implementing `@suaveplan/api-graphql`'s engine contract.
|
||||
- ADDED: `ApolloGraphqlOptions` — Zod-validated config: `endpoint` (default `/graphql`), `sdlEndpoint` (default `/graphql/sdl`), `wsEndpoint` (default `/graphql/ws`), `uiEndpoint` (default `/graphql/ui`), `introspection` (default `false`), `persistedQueriesPath`, `studioReporting`, `maxQueryDepth`, `maxQueryComplexity`, `formatError`.
|
||||
- ADDED: Endpoint mounts (identical to Yoga): `POST /graphql`, `GET /graphql/sdl`, `WS /graphql/ws`, `GET /graphql/ui` (proxied to wired UI plugin).
|
||||
- ADDED: Apollo-specific features behind config flags:
|
||||
- Persisted-query manifest (`persistedQueriesPath`).
|
||||
- Apollo Studio usage reporting (`studioReporting`).
|
||||
- Landing-page disabled by default (no GraphiQL fallback — same rule as Yoga: UI is opt-in via separate package).
|
||||
- ADDED: Subscriptions — same `graphql-ws` over `api-ws` bridge as Yoga.
|
||||
- ADDED: Per-request DataLoader scoping (identical to Yoga).
|
||||
- ADDED: `GRAPHQL_APOLLO_*` error codes: `GRAPHQL_APOLLO_PARSE_FAILED`, `GRAPHQL_APOLLO_VALIDATION_FAILED`, `GRAPHQL_APOLLO_DEPTH_EXCEEDED`, `GRAPHQL_APOLLO_COMPLEXITY_EXCEEDED`, `GRAPHQL_APOLLO_SCHEMA_BUILD_FAILED`, `GRAPHQL_APOLLO_SUBSCRIPTION_TRANSPORT_UNAVAILABLE`, `GRAPHQL_APOLLO_TIMEOUT`, `GRAPHQL_APOLLO_INTROSPECTION_DENIED`, `GRAPHQL_APOLLO_PERSISTED_QUERY_NOT_FOUND`, `GRAPHQL_APOLLO_RESOLVER_THREW`.
|
||||
- ADDED: OTel instruments: same surface as Yoga (`graphql.requests_total`, `graphql.request_duration_ms`, `graphql.resolver_duration_ms`, `graphql.subscriptions_active`, `graphql.schema_rebuilds_total`) — the metric names are deliberately engine-agnostic so dashboards survive an engine swap.
|
||||
- ADDED: `./testing` subpath — re-export of `runGraphqlEngineConformance` bound to `createApolloGraphqlEngine`.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- The abstract `api-graphql` contract.
|
||||
- Apollo Federation (subgraph composition across services) — single-process schema federation across plugins is in scope; cross-service subgraph composition is a separate concern.
|
||||
- The GraphiQL or Altair UI packages.
|
||||
- Yoga-specific concerns.
|
||||
|
||||
## Source mapping
|
||||
|
||||
Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`.
|
||||
|
||||
| Requirement | Design doc section |
|
||||
|---|---|
|
||||
| Alternative engine to Yoga | §10.5 |
|
||||
| Same `api-graphql` contract | §10.5 |
|
||||
| Same conformance suite passes | §10.5 ("Both implement the same `api-graphql` contract; switching is host-config only.") |
|
||||
| Endpoint set identical to Yoga | §10.6 |
|
||||
| Subscriptions over `api-ws` | §10.4 |
|
||||
| Federation across plugins | §10.2 |
|
||||
| Engine-agnostic OTel metric names | §12.3 (host emits for free) + §10.5 (swappable) |
|
||||
|
||||
## Verification approach
|
||||
|
||||
- `src/engine/apollo-engine.test.ts` — schema build, request execution, masked errors, depth/complexity guards.
|
||||
- `src/engine/apollo-engine.spec-conformance.test.ts` — runs `runGraphqlEngineConformance("apollo", createApolloGraphqlEngine)`; MUST pass the exact same invariants as `api-graphql-yoga`.
|
||||
- `src/federation/federation.test.ts` — same federation semantics; collision raises `GRAPHQL.SCHEMA_COLLISION`.
|
||||
- `src/subscriptions/subscriptions.test.ts` (integration, 30000ms) — `graphql-ws` over `api-ws-broker-in-memory`.
|
||||
- `src/persisted-queries/persisted-queries.test.ts` — Apollo-specific: persisted-query manifest lookup; unknown id raises `GRAPHQL_APOLLO_PERSISTED_QUERY_NOT_FOUND`.
|
||||
- `tests/integration/engine-swap.test.ts` (30000ms) — boots the same plugin set under Yoga then under Apollo; asserts identical query results, identical SDL output, identical metric names (operator dashboards survive the swap).
|
||||
|
||||
## Migration impact
|
||||
|
||||
None — additive only.
|
||||
Reference in New Issue
Block a user