# `pipeline-events-constants` — runtime constants for `PipelineEventsBus` ## Purpose `@suaveplan/api-types` is types-only — adding a runtime export there breaks the byte-size invariant CI enforces. The `PipelineEventsBus` contract still needs runtime constants for the canonical stage order tuple (so consumers can iterate / assert without re-listing the names) and for the per-stage event-name strings (so OTel bridges can name events without re-deriving them). Those constants live here, in `@suaveplan/api-host`, where runtime exports are expected. ## Features - `PIPELINE_STAGE_ORDER` frozen tuple — canonical §6 execution order matching the `PipelineStage` union. - `PIPELINE_EVENT_NAME` literal — log-grep friendly namespace prefix (`api-host.pipeline.stage`). - `PIPELINE_STAGE_EVENT_NAMES` per-stage map — concatenated `${PIPELINE_EVENT_NAME}.` strings for OTel span-event naming. ## Usage: Basic ```ts import { PIPELINE_STAGE_ORDER } from "@suaveplan/api-host"; for (const stage of PIPELINE_STAGE_ORDER) { console.log(stage); // request-id, route-match, tenant, auth, ... } ``` ## Usage: Advanced Build a per-stage histogram dashboard by indexing the per-stage event-name map: ```ts import { PIPELINE_STAGE_EVENT_NAMES } from "@suaveplan/api-host"; import type { PipelineStage } from "@suaveplan/api-types/pipeline-events"; const histograms = new Map(); for (const stage of Object.keys(PIPELINE_STAGE_EVENT_NAMES) as PipelineStage[]) { histograms.set(stage, []); } bus.subscribe((event) => { if (event.outcome === "completed" || event.outcome === "rejected") { histograms.get(event.stage)?.push(event.durationMs ?? 0); } }); ``` ## API Reference ```ts export const PIPELINE_STAGE_ORDER: readonly PipelineStage[]; export const PIPELINE_EVENT_NAME: "api-host.pipeline.stage"; export const PIPELINE_STAGE_EVENT_NAMES: Readonly>; ``` ## Implementation Notes The constants are typed as `readonly PipelineStage[]` (tuple) and `Readonly>` (map). The map's value type is `string` rather than the specific literal because TypeScript widens nested string literals through `Readonly>`. Consumers that need the literal narrowing import the `PIPELINE_STAGE_EVENT_NAMES` constant directly — TypeScript preserves the literal types on the const expression. The tuple MUST stay in lock-step with the `PipelineStage` union in `@suaveplan/api-types/pipeline-events`. A `satisfies` check at the type-test level catches any drift between the two; the conformance harness's order invariant also catches drift at runtime by comparing the actual emit order against this tuple.