|
| 1 | +--- |
| 2 | +title: "Operating governance signals" |
| 3 | +description: "Operator runbook for ack/resolve/dismiss workflow, notification destinations (Slack/email/PagerDuty/webhook), and escalation rules." |
| 4 | +sidebarTitle: "Operating governance signals" |
| 5 | +icon: "list-check" |
| 6 | +--- |
| 7 | + |
| 8 | +# Operating governance signals |
| 9 | + |
| 10 | +[Governance signals](/concepts/governance-signals) are observations operators see and act on. This guide walks through the runbook. |
| 11 | + |
| 12 | +## Daily flow |
| 13 | + |
| 14 | +1. **Triage** the open queue at `app.mnemom.ai/dashboard/teams/{teamId}/governance` (or via `mnemom governance signals list --team <id> --status open`). |
| 15 | +2. **Acknowledge** signals you're investigating. Records `acknowledged_actor_role` per [ADR-046](https://github.com/mnemom/scale/blob/main/decisions/ADR-046-audit-actor-model.md) — captures whether you acted as `org_admin`, `team_admin`, etc. |
| 16 | +3. **Resolve** with a `resolution_status`: |
| 17 | + - `action_taken` — you (or a sovereign agent) made changes (rebalanced team, refreshed cards, …). |
| 18 | + - `wont_fix` — known noise or out of scope. |
| 19 | + - `duplicate` — same root cause as another signal. |
| 20 | + - `false_positive` — detector misfire (file a debt item). |
| 21 | + - `self_resolved` — the underlying condition cleared itself before you acted. |
| 22 | +4. **Dismiss** for noise: the signal is acknowledged but no action is needed and no resolution category applies cleanly. |
| 23 | + |
| 24 | +CLI: |
| 25 | + |
| 26 | +```bash |
| 27 | +mnemom governance signals list --team team-uuid-here --status open |
| 28 | +mnemom governance signals show gs-abc123def456 |
| 29 | +mnemom governance signals ack gs-abc123def456 --action "investigating cluster shape" |
| 30 | +mnemom governance signals resolve gs-abc123def456 \ |
| 31 | + --status action_taken \ |
| 32 | + --action "rebalanced team — moved agent-X to fleet-B" |
| 33 | +``` |
| 34 | + |
| 35 | +## Notification destinations |
| 36 | + |
| 37 | +Configure where signals route off-platform. Each destination is one channel binding for an org. |
| 38 | + |
| 39 | +### Slack |
| 40 | + |
| 41 | +```bash |
| 42 | +mnemom governance destinations add \ |
| 43 | + --org org-id \ |
| 44 | + --channel slack \ |
| 45 | + --name "#sec-alerts" \ |
| 46 | + --config '{"url":"https://hooks.slack.com/services/T.../B.../..."}' |
| 47 | +``` |
| 48 | + |
| 49 | +Block Kit payload with severity-color border, action button "Acknowledge in dashboard." |
| 50 | + |
| 51 | +### Email |
| 52 | + |
| 53 | +```bash |
| 54 | +mnemom governance destinations add \ |
| 55 | + --org org-id \ |
| 56 | + --channel email \ |
| 57 | + --name "Security on-call" \ |
| 58 | + --config '{"to":["security-oncall@yourco.com"],"from":"governance@yourco.com"}' |
| 59 | +``` |
| 60 | + |
| 61 | +Resend-backed HTML + plaintext. |
| 62 | + |
| 63 | +### PagerDuty |
| 64 | + |
| 65 | +```bash |
| 66 | +mnemom governance destinations add \ |
| 67 | + --org org-id \ |
| 68 | + --channel pagerduty \ |
| 69 | + --name "Critical on-call" \ |
| 70 | + --config '{"routing_key":"R1234567890ABCDEF"}' |
| 71 | +``` |
| 72 | + |
| 73 | +Events API v2 with stable `dedup_key` (`governance-signal-{id}`) — coalesced detections don't create duplicate incidents. |
| 74 | + |
| 75 | +### Generic webhook |
| 76 | + |
| 77 | +```bash |
| 78 | +mnemom governance destinations add \ |
| 79 | + --org org-id \ |
| 80 | + --channel webhook \ |
| 81 | + --name "Internal SOC pipeline" \ |
| 82 | + --config '{"url":"https://soc.internal/governance","signing_secret":"<32+ bytes>"}' |
| 83 | +``` |
| 84 | + |
| 85 | +HMAC-SHA256 signed POST. Verify the signature server-side before trusting the payload. |
| 86 | + |
| 87 | +### Test before you trust |
| 88 | + |
| 89 | +Every destination supports a synthetic test signal: |
| 90 | + |
| 91 | +```bash |
| 92 | +mnemom governance destinations test <destination_id> --org <org_id> |
| 93 | +``` |
| 94 | + |
| 95 | +This sends a test signal through the channel only (bypasses rules) and records `last_tested_at` / `last_test_status` on the destination row. The dashboard surfaces the result inline. |
| 96 | + |
| 97 | +## Filter narrowing |
| 98 | + |
| 99 | +Each destination has an optional `filter` that AND-folds with the matching escalation rule's predicate. Useful for "only critical to PagerDuty, everything else to Slack": |
| 100 | + |
| 101 | +```bash |
| 102 | +# PagerDuty: critical only |
| 103 | +mnemom governance destinations add --org org-id --channel pagerduty \ |
| 104 | + --config '...' --filter '{"severities":["critical"]}' |
| 105 | + |
| 106 | +# Slack: warn + high (PagerDuty handles critical separately) |
| 107 | +mnemom governance destinations add --org org-id --channel slack \ |
| 108 | + --config '...' --filter '{"severities":["warn","high"]}' |
| 109 | +``` |
| 110 | + |
| 111 | +Filter keys: `sources`, `severities`, `scopes`, `pattern_types`. Absent key = match-all on that dimension. |
| 112 | + |
| 113 | +## Escalation rules |
| 114 | + |
| 115 | +Rules bind a predicate to a list of destinations. When an inserted signal matches the predicate, the dispatcher routes to the rule's destinations (intersected with each destination's filter). |
| 116 | + |
| 117 | +```bash |
| 118 | +mnemom governance rules add \ |
| 119 | + --org org-id \ |
| 120 | + --name "fleet-critical-pageout" \ |
| 121 | + --predicate '{"source":"sideband.fleet","severity_min":"high"}' \ |
| 122 | + --destinations dest-pagerduty-id,dest-slack-id |
| 123 | +``` |
| 124 | + |
| 125 | +Predicate keys (AND-folded): |
| 126 | + |
| 127 | +- `source` — exact source match. |
| 128 | +- `pattern_type` — exact pattern_type match. |
| 129 | +- `severity_min` / `severity_max` — bound on severity. |
| 130 | +- `scope` — exact scope match. |
| 131 | +- `team_id` — narrow to one team. |
| 132 | +- `threshold_count` + `window_minutes` — **rate-based gating**: fire only if ≥ N matching signals occurred in M minutes. |
| 133 | + |
| 134 | +### Rate-gating example |
| 135 | + |
| 136 | +"Page on-call only if 3+ critical signals fire in 5 minutes": |
| 137 | + |
| 138 | +```bash |
| 139 | +mnemom governance rules add \ |
| 140 | + --org org-id \ |
| 141 | + --name "critical-burst-pageout" \ |
| 142 | + --predicate '{"severity_min":"critical","threshold_count":3,"window_minutes":5}' \ |
| 143 | + --destinations dest-pagerduty-id |
| 144 | +``` |
| 145 | + |
| 146 | +### Dedup across rules |
| 147 | + |
| 148 | +If two rules both route to the same destination, the dispatcher dedups — one Slack message per signal, not two. Each contributing rule's `fire_count` and `last_fired_at` still get bumped. |
| 149 | + |
| 150 | +## Coverage rollup |
| 151 | + |
| 152 | +`GET /v1/orgs/:org_id/governance/coverage?days=30` returns a per-(source, severity) aggregate over the window: |
| 153 | + |
| 154 | +```bash |
| 155 | +curl -H "Authorization: Bearer $TOKEN" \ |
| 156 | + "https://api.mnemom.ai/v1/orgs/org-id/governance/coverage?days=30" | jq |
| 157 | +``` |
| 158 | + |
| 159 | +```json |
| 160 | +{ |
| 161 | + "org_id": "org-id", |
| 162 | + "since": "2026-04-07T00:00:00Z", |
| 163 | + "days": 30, |
| 164 | + "total_signals": 47, |
| 165 | + "by_source_severity": [ |
| 166 | + { "source": "sideband.fleet", "severity": "high", "total": 12, "open": 0 }, |
| 167 | + { "source": "sideband.coherence", "severity": "warn", "total": 8, "open": 2 }, |
| 168 | + { "source": "sideband.drift", "severity": "warn", "total": 27, "open": 4 } |
| 169 | + ] |
| 170 | +} |
| 171 | +``` |
| 172 | + |
| 173 | +Use this for compliance evidence (signals were detected and operators responded), and as input for tuning your escalation rules — sources with high `open` ratios may need ack-process tightening; sources with high volume may want filter narrowing on noisy destinations. |
| 174 | + |
| 175 | +## Auditing |
| 176 | + |
| 177 | +Every state transition records `acknowledged_actor_role` (who acted, in what capacity) per [ADR-046](https://github.com/mnemom/scale/blob/main/decisions/ADR-046-audit-actor-model.md). `resolution_status` + `action_taken` provide the prose audit trail. Combine with [`governance_audit_log`](/specifications/governance-audit-log) for full SOC2-shaped reconstruction. |
| 178 | + |
| 179 | +## Related |
| 180 | + |
| 181 | +- [Governance signals concept](/concepts/governance-signals). |
| 182 | +- [Governance Signals Schema](/specifications/governance-signals-schema). |
| 183 | +- [Sovereign-agent composition](/guides/sovereign-agent-composition) — application-side pattern when you have a sovereign-CTO-shaped agent. |
0 commit comments