Skip to main content
This page documents the platform schema for governance signals, the operator-actionable observation surface.

Tables

governance_signals

The single row per open observation. The platform writes via the governance_signal_emit RPC; consumers (REST handlers, dispatcher, UI, CLI) read directly.

Indexes

governance_notification_destinations

governance_escalation_rules

RLS

Service-role bypass model: the API boundary applies authorization in the application layer, and direct database access uses a service role that bypasses row-level security. Row-level security is enabled on all three tables with no user-facing policies — this is fail-closed against accidental exposure (a future direct-database access path can’t leak governance signals across orgs). Future tightening to user-driven row-level UPDATE policies is a follow-up once a shared cross-type user-identity policy helper is in place.

RPCs

governance_signal_emit

SECURITY DEFINER + service-role only. INSERT ... ON CONFLICT DO UPDATE on the open-dedup index — repeated cron emissions of the same condition refresh detected_at, severity, agent_ids, detail, source_ref on the existing open row instead of creating a new one.

governance_signal_acknowledge / _resolve / _dismiss

Operator state transitions. Each captures acknowledged_actor_role and is SECURITY DEFINER so the API can invoke after applying RBAC in TypeScript.

REST endpoints

See api-reference/governance for full schemas. Quick map:

Notification dispatch

Governance signals are not delivered through the account-wide webhook subscription surface (/v1/orgs/:org_id/webhooks, Webhooks). They dispatch only to the channels an org explicitly configures under governance_notification_destinations (webhook, slack, email, or pagerduty — see REST endpoints above). governance.signal.fired is the only event this system dispatches today, sent whenever a new signal is inserted or an existing open signal is coalesced (detected_at/severity/agent_ids/detail refreshed on the open row). Acknowledging, resolving, or dismissing a signal changes its row but does not currently dispatch any notification. An escalation rule only decides which configured destinations a given signal’s governance.signal.fired reaches — matching a rule does not produce a separate event type. The webhook channel signs its POST body HMAC-SHA256 (X-Mnemom-Signature: sha256=<hex>, X-Mnemom-Event: governance.signal.fired, X-Mnemom-Delivery-Id: <uuid>) — subscribers should verify the signature before trusting the payload. This is a distinct signing scheme from the account-wide webhook surface’s X-Webhook-Signature: v1={hex}; do not conflate the two.

Naming convention discipline

source is closed, hierarchical, append-only — mirrors the pending_advisories.source taxonomy. Adding a new value requires:
  1. A schema amendment.
  2. Migration extending the CHECK constraint with ASSERT-after-DDL guard.
  3. Producer code (typically observer).
  4. Consumer-tolerance discipline (gateway / UI / CLI / SDKs).
  5. Posture-gating extension if the source is detector-driven.
Removing a source is forbidden. Deprecation is the only valid path.