Files
2026-05-27 23:29:53 +01:00

3.5 KiB

foundation-fix-gap-1-pipeline-router

Summary

Close foundation-coherence Gap #1: @suaveplan/api-router-hono's HonoRouter did not satisfy @suaveplan/api-host's PipelineRouter contract. The two match() shapes diverged (RouteMatch vs PipelineRoute), forcing every host-pipeline consumer to hand-roll a shim — the E2E foundation-stack server's createFixtureRouter() was the canonical example. This change adds a second, additive facet to HonoRouter (registerPipelineRoute / matchPipeline / unregisterPipelinePlugin / listPipelineRoutes) that produces values structurally assignable to the host's PipelineRoute interface, and ships a canonical runPipelineRouterConformance(factory) test harness in @suaveplan/api-host/testing so every concrete adapter has a single contract to pass.

Motivation

Empirically the gap caused two failure modes:

  1. Hand-rolled shims in every consumer — the E2E foundation-stack server's createFixtureRouter() was 80 lines of router logic that should have lived inside api-router-hono. Every new host-pipeline consumer was on track to write the same shim.
  2. No conformance suite — api-router-hono passes runRouterConformance against the abstract Router, but no harness existed for the host's PipelineRouter surface. Adapter drift would only surface during a real E2E run.

The fix is additive — the existing abstract-Router surface is preserved verbatim; the pipeline facet lives next to it as a parallel metadata sidecar. No breaking changes to existing consumers.

Scope

  • @suaveplan/api-router-hono:
    • new src/pipeline/ feature module (PipelineRouteTable, HonoPipelineRoute, HonoPipelineRegistration, HonoPipelineRouteOptions, HonoPipelineHandler).
    • HonoRouter gains registerPipelineRoute, unregisterPipelineRoute, unregisterPipelinePlugin, listPipelineRoutes, matchPipeline.
    • new error code ROUTER_HONO.PIPELINE_ROUTE_COLLISION.
    • new subpath export ./pipeline.
    • dev-dep on @suaveplan/api-host (testing-only).
    • vite config emits index.js per subpath (closes a pre-existing ./adapter resolution bug).
  • @suaveplan/api-host:
    • ./testing subpath populated with runPipelineRouterConformance(factory) + PipelineRouterConformanceFactory / PipelineRouteRegistration types.
    • vite config switched to multi-entry so the dist actually emits testing/testing.js (closes a pre-existing dead-export bug).
  • e2e/foundation-stack:
    • drop hand-rolled createFixtureRouter body; replace with the real HonoRouter pipeline facet.

Verification

  • Unit + integration: bunx turbo lint typecheck test build --filter=@suaveplan/api-router-hono --filter=@suaveplan/api-host → green; 75 unit tests across api-router-hono, 252 across api-host.
  • Coverage: api-router-hono 100/100/100/100 on every touched module (adapter, pipeline, error-codes).
  • E2E: cd e2e/foundation-stack && bunx playwright test — all 10 test groups pass (livez/readyz, plugin routes, tenant resolver, domain error envelope, 404 envelope, secrets, admin plugins/details, admin capabilities, rate-limit, idempotency).

Out of scope

  • Migrating api-router-worker-bridge to the pipeline facet — that adapter will adopt the same harness in a follow-up.
  • Wiring the HonoRouter pipeline facet into the host's LifecycleDriver.mount-routes op — currently consumers register manually; threading through the lifecycle is a follow-up change.