2026-05-10-x2-event-taxonomy-expansion
X-2: Event taxonomy expansion (32 new event types)
Date: 2026-05-10 Status: shipped Slug: x2-event-taxonomy Branch: feature/x2-event-taxonomy Strategic plan item: X-2 (XDR pipeline pre-requisite that was deferred behind X-3..X-8)
Summary
Expanded PlatformEventType from 19 → 51 variants by adding 32 security-relevant event types across six categories (identity/auth, authorization, routing, behavioral, data-flow, audit-chain). Added matching PlatformEvent data shapes, OCSF projector cases, and EVENT_MAP entries (40 total — including null-as-suppress for high-volume telemetry events that exist for downstream consumers but should not fan out to webhooks/SIEM by default).
A new completeness-gate test (event-map-coverage.test.ts) fails CI if a future PR adds a PlatformEventType without an EVENT_MAP decision (delivery target or explicit null to suppress). This makes the type union the source of truth and makes "I forgot to map the new event" a compile-time-equivalent error.
Five core emission points are wired now:
cert.issued—src/api/routes/agent-cert.tsaftersignCsrcert.revoked—src/api/routes/agent-cert-revoke.tsafterrevocationStore.revokeagent.bootstrapped—src/api/routes/agent-bootstrap.tson 201 responseauthz.denied—src/api/middleware/rbac.tsonhasPermissionfailureaudit.envelope_signed—src/security/trust-envelope/middleware.tsafter sign
The remaining 27 event types are wired into the type system + projector + EVENT_MAP but their emission points are deferred to follow-up PRs (concentrated in anomaly-detection.ts, pii-scanner.ts, guardrail-chain.ts, model-router-select.ts, audit-signer.ts). Adding the type + projector + map ahead of emission is the right ordering: SIEM destinations can be configured to accept the events before the emission code lands, so there's no event drop at deploy.
Files
Modified
src/infra/notifications/dispatcher.ts(+85 LOC) — 32 new union members + matching data shapes +PLATFORM_EVENT_TYPESexported array for the gate testsrc/infra/notifications/webhook-delivery.ts(+50 LOC) —EVENT_MAPexpanded 8 → 40 entries, madeRecord(wasPartial<>); addedREGISTERED_EVENT_TYPESexportsrc/observability/xdr/ocsf-projector.ts(+200 LOC) — 28 new switch cases (4 are null-returning suppressions)src/api/routes/agent-cert.ts(+15 LOC) —cert.issuedemissionsrc/api/routes/agent-cert-revoke.ts(+15 LOC) —cert.revokedemissionsrc/api/routes/agent-bootstrap.ts(+15 LOC) —agent.bootstrappedemissionsrc/api/middleware/rbac.ts(+15 LOC) —authz.deniedemissionsrc/security/trust-envelope/middleware.ts(+25 LOC) —audit.envelope_signedemission
New
src/infra/notifications/event-map-coverage.test.ts(47 LOC) — runtime completeness gate (2 tests)
Verification
pnpm tsgo— exit 0pnpm test:fast— 7755/0 (+2 from completeness gate)pnpm exec oxfmt --check— cleanpnpm exec oxlint --type-aware— 0 warnings, 0 errors
Lockstep
- TypeScript SDK: no public surface change (no new routes)
- Python SDK: no public surface change
- MCP tools: no public surface change
- routes.json: no new routes;
pnpm buildregenerates as no-op for routes - OpenAPI spec: no surface change
Why "EVENT_MAP value can be null"
Two reasons null beats omission:
- Compile-time-equivalent completeness check: The
Record
type forces every member of the union to be a key. Forgetting one becomes a tsgo error, not a silent runtime drop.
- High-volume events should still be enumerated:
routing.model_selected
fires on every completion. Mapping it to null is a deliberate design decision that documents "we considered this and chose to suppress." A future tenant who wants the firehose can flip the mapping without grepping the codebase to discover whether the event existed.
Why emission points are split between this PR and follow-ups
The plan called for ~600 LOC and emission across 8+ files. Lockstep + reviewer cap suggests a tighter PR. The five emission points wired here cover the highest SIEM-value surfaces (cert lifecycle, agent identity, auth chain). The remaining 27 events are reachable from the type system today and will fire as their emission points land. Importantly: the OCSF projector + EVENTMAP are complete \_now, so a SIEM destination configured this week catches every new emission as it ships without re-configuring.
Stop signals — none
No P0 in computer-eval queue. Strategic plan items remaining: A-8 (counterfactual replay), X-9 (XDR docs), A-10..A-12 (sandbox/test-harness/public spec). Loop continues.