Pending advisories — wire format and source taxonomy
pending_advisories is the unified cross-turn carryover surface. One table, one read point at the start of each runtime turn (gateway/src/index.ts::injectPendingNudges), multiple sources via a closed source enum spanning runtime + sideband + manual contexts.
This page documents the row shape every consumer can rely on (gateway, observer, dashboard, CLI, webhook subscribers) and the expansion contract for adding new sources.
Row shape
pending → consumed (gateway injected on a turn) or pending → expired (TTL elapsed without injection). No revivals.
Source taxonomy
Closed, hierarchical, append-only enum. Adding a new value requires the expansion recipe (schema amendment + migration + producer + consumer-tolerance).| Context | Producer | Examples |
|---|---|---|
runtime.* | gateway/src/index.ts (same-turn intervention bookkeeping) | runtime.front_door.nudge, runtime.back_door.modification |
manual.* | mnemom-api admin handlers (human-attached) | manual.admin |
Current ratified values (post-cutover)
| Source | Producer | Posture-gated | Webhook event |
|---|---|---|---|
runtime.front_door.nudge | gateway (front-door handler) | No | (none) |
runtime.front_door.enforce | gateway (front-door handler) | No | (none) |
runtime.inside.autonomy.nudge | gateway (CLPI handler) | No | (none) |
runtime.inside.integrity.nudge | gateway (AIP handler) | No | (none) |
runtime.back_door.modification | gateway (back-door handler) | No | (none) |
manual.admin | mnemom-api admin attach handler | No | future manual.advisory_attached |
sideband.drift / sideband.coherence / sideband.fault_line / sideband.fleet previously appeared here. They moved to governance_signals with the 2026-05-07 cutover; the four legacy sideband.*.fired and drift.detected webhook event names continue to fire for D+30 backwards-compat through 2026-06-07.
source_ref shapes
JSONB envelope keyed off source. Conventions:
- Every
runtime.*row carries{checkpoint_id: string, mode_at_fire: "off"|"observe"|"nudge"|"enforce"} - Every
manual.*row carries{actor_user_id: string, attached_at: string, note?: string}
sideband.* source_ref shapes, see governance_signals source_ref; those observations write to the operator-actionable surface, not to this table.
runtime.* — source_ref
checkpoint_id references the integrity_checkpoints row created on the same turn. mode_at_fire is the agent’s effective mode at intervention time (post-cascade, pre-fire).
manual.admin — source_ref
nudge_content format
Every advisory’s text follows a stable wrapper:
[Mnemom: <intervention summary>].
concerns_summary format
Short structured headline (≤80 chars) used for telemetry, dashboard display, and CLI list output. Convention: <axis>: <short outcome>.
| Source | Example |
|---|---|
runtime.* | <checkpoint>: <mode>-fired |
manual.admin | Manual: <one-line note> |
Read endpoints
| Endpoint | Auth | Returns |
|---|---|---|
GET /v1/agents/:id/sideband-advisories | user (org member) | All sideband.* advisories for one agent (default last 50, max 200). |
GET /v1/teams/:id/sideband-advisories | user (org member) | All sideband.* advisories for member agents (default last 100, max 500). |
GET /v1/teams/:id/sideband-coverage | user (org member) | 30-day per-axis sweep summary + raw rows. |
?since=<ISO-8601>— only advisories created after this timestamp?limit=<n>— page size (default 50/100, max 200/500)
X-Service-Key, exposed under an internal namespace that does not appear in the customer OpenAPI):
| Operation | Auth | Purpose |
|---|---|---|
| Active-teams enumeration | X-Service-Key | Observer cron: enumerate teams to sweep |
| Sideband sweep heartbeat | X-Service-Key | Observer heartbeat: UPSERT per-sweep log row |
GET /v1/teams/:id/effective-posture | X-Service-Key (or user) | Observer posture read (customer-facing endpoint) |
Expansion contract
Adding a new source
To add a new value tosource, a single PR train MUST land all of:
- Schema amendment to the source taxonomy adding the value with its producer, consumer responsibilities, and
source_refshape. - Migration (
ALTER TABLE pending_advisories DROP CONSTRAINT … ADD CONSTRAINT … CHECK (source IN (…))) appending the new value. Migration MUST use the post-DDLpg_proc.prosrcASSERT pattern frommnemom-api/database/migrations/158_*.sql. - Producer code that writes rows with the new source — fire-and-forget, never throws on insert failure.
- Consumer-tolerance discipline —
gateway/src/index.ts::injectPendingNudgesMUST already render any unknown source as a generic advisory (the current code does this; it doesn’t filter on source). Future consumers (dashboard filter chips, CLI--source, webhook event types) MUST tolerate the value via either pre-registration or graceful unknown-source fallback. source_refJSONB shape documented per source on this page.- For
sideband.*only — extendPostureBody.sidebandwith the corresponding axis configuration (enabled,cadence_seconds,severity_floororfire_on.*,severity_on_fire). The Posture is the policy surface; new sideband sources without posture-body fields are forbidden.
Removing a source
Forbidden. Removing a source breaks compliance attestation (historical advisories with that source value become un-renderable) and breaks deserialization for any consumer holding archived rows. Deprecation is the only valid path: stop producing the source, document the deprecation, but leave the CHECK constraint accepting the value forever.Webhook events
Each source’s webhook event name follows<source>.fired — with one documented carve-out: sideband.drift keeps its legacy drift.detected name. Subscribers receive the standard webhook envelope:
See also
- Sideband detection — concept overview and the four-source taxonomy
- Trust Posture — the policy surface that drives
sideband.*thresholds - Compliance attestation foundation — how
sideband_sweep_log+ posture-versioned snapshots feed control mappings