59 lines
3.8 KiB
Markdown
59 lines
3.8 KiB
Markdown
# Capability Spec Delta: api-router — PipelineRouter contract ownership
|
|
|
|
**Package**: `@suaveplan/api-router`
|
|
**Status**: PROPOSED
|
|
|
|
## ADDED Requirements
|
|
|
|
### Requirement: Owns the canonical `PipelineRouter` contract
|
|
|
|
`@suaveplan/api-router` SHALL export the canonical `PipelineRouter` interface and its companion types (`PipelineRoute`, `PipelineRouteOptions`, `PipelineRouteRegistration`) from the `./pipeline` subpath. Every concrete pipeline-router adapter (`api-router-in-memory`, the `HonoRouter` pipeline facet in `api-router-hono`, future Stage-7 engines) targets this contract. `@suaveplan/api-host` MUST consume these types via `@suaveplan/api-router/pipeline` rather than define them locally.
|
|
|
|
#### Scenario: subpath exports the four contract types
|
|
|
|
- **WHEN** `import type { PipelineRoute, PipelineRouteOptions, PipelineRouteRegistration, PipelineRouter } from "@suaveplan/api-router/pipeline"` is used
|
|
- **THEN** all four symbols resolve AND match the prior shapes hosted in `@suaveplan/api-host/request-pipeline`
|
|
|
|
#### Scenario: api-host re-exports preserve back-compat
|
|
|
|
- **WHEN** existing code uses `import { PipelineRouter } from "@suaveplan/api-host/request-pipeline"`
|
|
- **THEN** the symbol resolves to the same type identity as the new canonical location (verified by structural assignment in a type-level test)
|
|
|
|
**Verified by:** `src/pipeline/pipeline.test.ts::"PipelineRouter contract exports the canonical surface"` AND `packages/api-stack/api/api-host/src/request-pipeline/request-pipeline.test.ts::"PipelineRouter re-export matches api-router source-of-truth"`
|
|
|
|
---
|
|
|
|
### Requirement: Ships the canonical `runPipelineRouterConformance` harness
|
|
|
|
`@suaveplan/api-router` SHALL export `runPipelineRouterConformance({ label, build })` from `./testing/pipeline-router-conformance` and re-export it through `./testing` for ergonomic single-subpath consumption. The harness's invariants — route-match, plugin-ownership-preserved-across-reload, status-map propagation, missing-route returns null — MUST be preserved verbatim from the previous `@suaveplan/api-host/testing` location.
|
|
|
|
#### Scenario: harness invariants unchanged from the api-host source location
|
|
|
|
- **WHEN** an adapter that previously passed `runPipelineRouterConformance` from `@suaveplan/api-host/testing` re-targets the harness at `@suaveplan/api-router/testing/pipeline-router-conformance`
|
|
- **THEN** the same scenarios pass with no signature or behaviour change
|
|
|
|
#### Scenario: ergonomic `./testing` re-export
|
|
|
|
- **WHEN** `import { runPipelineRouterConformance } from "@suaveplan/api-router/testing"` is used
|
|
- **THEN** the symbol resolves AND matches the dedicated-subpath export by identity
|
|
|
|
**Verified by:** `src/testing/pipeline-router-conformance/pipeline-router-conformance.test.ts::"invariants match prior api-host location"` AND `src/testing/index.test.ts::"./testing re-exports runPipelineRouterConformance"`
|
|
|
|
---
|
|
|
|
### Requirement: Cycle-free build graph
|
|
|
|
After this change, the workspace build graph MUST NOT contain a cycle between `@suaveplan/api-host` and `@suaveplan/api-router-in-memory`. Turborepo's `bunx turbo run build` MUST complete without emitting `Cyclic dependency detected`.
|
|
|
|
#### Scenario: turbo schedules build with no cycle warning
|
|
|
|
- **WHEN** `bunx turbo run build --filter=@suaveplan/api-host` is run from a clean tree
|
|
- **THEN** stderr contains no `Cyclic dependency detected` line AND the task graph builds successfully
|
|
|
|
#### Scenario: repo-wide test gate runs end-to-end
|
|
|
|
- **WHEN** `bunx turbo test --output-logs=errors-only` is run
|
|
- **THEN** the exit code is 0 AND no package reports a cycle warning
|
|
|
|
**Verified by:** CI assertion in `bun scripts/lint/check-no-cycles.ts` (new; greps `bunx turbo run build --dry=json` for any task whose `dependencies` form a cycle) AND the green-bar evidence captured in the change's archive `tasks.md`
|