Externalize the canonical expected-event mapping out of TypeScript-only into a BI-readable source that the code loads as its single source of truth. Mirror to Confluence via a generator so a non-developer can answer "what should fire for flow X?". Strictly no behavior change.
No-behavior-change refactor of WHERE the contract lives. Runtime validation behavior remains identical to Phase 3's HEAD. Phase 5's alias map and exact matching will plug into this contract.
data/event-mapping.json.Single JSON object: keys are the 9 EventFunctionNames (page_ready, page_next, page_prev, galleryOpen, gallery_next, gallery_previous, player, articlePart_next, articlePart_previous); values are 3-string tuples [dataLayerName, ga4Name, gemiusName].
Sits in data/ next to the per-domain configs BI analysts already touch. No new npm dependency.
resolveJsonModuletsconfig.json gets resolveJsonModule: true. Types.ts imports eventMappingJson and re-exports as eventMapping. EventFunctionNames = keyof typeof eventMappingJson — derived from JSON, no duplication.
Each value MUST be [string, string, string] of non-empty strings. Malformed JSON throws e.g. Invalid data/event-mapping.json: key "gallery_next" must be a 3-tuple of non-empty strings. Consistent with Phase 1's fail-fast theme.
docs/event-mapping.md.New scripts/generate-event-mapping-doc.ts reads the JSON, writes a clean markdown table per flow with columns Flow / DataLayer / GA4 / Gemius. Includes a generated-file note pointing back to the JSON.
data/event-mapping.json contains the exact same content as the previous TypeScript literal.Types.ts exports eventMapping and EventFunctionNames at the same import surface as before; downstream code unchanged.docs/event-mapping.md regenerated deterministically from the JSON.