Canonical event registry
The events listed here are the events the backend currently accepts on the
product-events channel. The registry mirrors the canonical allow-list in
allow_list.py
on the backend. Any event name not on this page is rejected per event by
the ingest endpoint with rejected_unknown_event and is never silently
dropped.
:::info Drift between this page and the allow-list
This page is hand-maintained and updated in the same PR as the
allow-list (see Adding a new product event).
If you suspect drift — an event accepted at runtime but not listed here,
or vice versa — open the
allow_list.py
source on GitHub and compare. The runtime allow-list is authoritative;
any divergence is a process bug worth reporting.
:::
PII annotations on a property mean that the property's dotted path appears
on the canonical PII paths list (pii_paths.py),
in which case the value is hashed at ingest. The current PII list is
("destination.email",); see the PII policy for the
hashing model. Properties whose dotted paths are not on that list are
stored and forwarded as-is.
project.transfer.requested
The user has asked to transfer ownership of a governance project to a different account (a user or an organization). The transfer has been issued but the backend has not yet confirmed the move. Used by the project-transfer flow to measure the funnel between intent and confirmation.
Owner: @fred (Spine x-004-project-transfer)
Added: 2026-05-13
Emitted from: offline-mutations.ts:1800
| Property | Type | Description | PII |
|---|---|---|---|
project_id | number | Internal id of the governance project being transferred. | — |
destination_kind | string ("organization" | "user") | Kind of destination receiving the project. | — |
destination_id | number | Internal id of the destination organization or user. Never an email address — these emissions carry numeric ids only. | — |
project.transfer.confirmed
The backend has confirmed the transfer from
project.transfer.requested (or a retroactive
detection has determined the transfer succeeded after an earlier transient
error). Emitted once per confirmed transfer; the payload mirrors the
requesting event so funnel queries can join on project_id +
destination_*.
Owner: @fred (Spine x-004-project-transfer)
Added: 2026-05-13
Emitted from: offline-mutations.ts:1831
(success path) and offline-mutations.ts:1857 (retroactive-success path).
| Property | Type | Description | PII |
|---|---|---|---|
project_id | number | Internal id of the governance project that was transferred. | — |
destination_kind | string ("organization" | "user") | Kind of destination that received the project. | — |
destination_id | number | Internal id of the destination organization or user. Never an email address — these emissions carry numeric ids only. | — |
chrome.* — interaction telemetry for the client shell (fe-005)
The client shell redesign in
gnostikon-client#24
(merged 2026-05-15) introduced a new family of events under the
chrome.* namespace. The family is intended as additive — no
existing event from x-005 is renamed and no existing payload is
reshaped — and the emitter helpers live at
src/services/telemetry/chrome-events.ts.
Seven events are emitted by the client today:
chrome.screen_openchrome.sheet_openchrome.sheet_closechrome.command_runchrome.viewport_changechrome.theme_changechrome.legacy_home_used
:::warning Client-emitted, backend-pending — cross-repo follow-up
As of this dx-010 review, none of the seven chrome.* names appear in
the backend allow-list
(allow_list.py).
Per the registry contract above, the ingest endpoint therefore rejects
each chrome.* event with rejected_unknown_event. Until the allow-list
is updated, the family is intent-only — analytics consumers will not
observe any of these events landing in the canonical store.
Tracking: a backend PR is needed to add the seven names to
ALLOWED_EVENT_NAMES. Once merged, this section will be replaced with
full per-event entries (one H3 per event with the Owner / Added / Emitted
from / Property table shape used above).
:::
A note on PII paths that don't fire today
The canonical PII paths list (pii_paths.py)
contains destination.email. Neither of the events above carries a
property at that dotted path — both emit destination_id as a flat
number — so no value is hashed in practice for the seed events. The path
is declared so that any future event that carries destination.email
(for example, a future transfer flow that allows targeting an
unregistered external email) would have that value hashed at ingest
automatically, without the contributor having to remember to update the
PII paths list.
See PII policy for the hashing model.