docs(bus): document email.received + ttp.tagged / ttp.rule.fired.* / ttp.rule.suppressed
Sibling of decnet@e395306 (E.1.2 of the TTP-tagging rollout). The producers don't exist yet — these rows are reserved entries so subscribers can wire patterns now and consume the moment publishers land. PII discipline on email.received is captured inline so it can't get lost in folklore.
@@ -172,6 +172,11 @@ Current topic families:
|
||||
| `canary.{token_id}.triggered` | `decnet canary` worker | `{token_id, decky_id, src_ip, user_agent?, request_path?, dns_qname?, occurred_at, raw_headers?}` — attacker hit the HTTP slug or DNS subdomain; correlator + webhook fanout consume to attribute and forward |
|
||||
| `canary.{token_id}.revoked` | API (`DELETE /tokens/{id}`) | `{token_id, decky_id, revoked_at}` — operator removed a token; subscribers may evict cached lookups by token id |
|
||||
| `system.canary.health` | `decnet canary` worker | standard worker heartbeat |
|
||||
| `smtp.probe.pending` | Ingester | `{decky, attacker_ip, stored_as, mail_from, rcpt_to}` — fired when an smtp_relay decky stores a new inbound message. The realism worker subscribes and forwards the email to the upstream relay if this source IP has not yet reached `probe_limit`. `stored_as` is the quarantine filename (relative to the per-decky smtp dir). `mail_from` / `rcpt_to` are the envelope sender/recipients captured at SMTP time. The worker writes a `probe_relay` bounty row on success or failure so the limit check is DB-backed and survives container restarts. |
|
||||
| `email.received` | _reserved (smtp / smtp-relay services)_ | `{message_uuid, decky_id, session_id, attacker_ip, mail_from, rcpt_count, body_sha256, header_names: [...], attachment_sha256s: [...]}` — fired on full-message receipt, consumed by the TTP `email_lifter`. PII discipline (TTP_TAGGING.md "Hard parts §6"): hashes, counts, header *names*, and rcpt-domain sets only — never rcpt addresses or body bytes. Constant declared with no publisher yet; the SMTP services start emitting it when E.3 (the implementation phase) lands. |
|
||||
| `ttp.tagged` | _reserved (TTP worker)_ | `{tag_uuids: [...], techniques_added: [...], attacker_uuid?, identity_uuid, session_id?}` — published only when `INSERT OR IGNORE` wrote at least one new row. Idempotent re-evaluations that produce zero new tags publish zero events (loop-prevention invariant — a webhook subscriber re-triggering enrichment on `ttp.tagged` could otherwise loop forever). |
|
||||
| `ttp.rule.fired.{technique_id}` | _reserved (TTP worker)_ | `{rule_id, technique_id, sub_technique_id?, tag_uuid, confidence}` — per-technique fan-out for SIEM correlation rules that subscribe to one technique. Topic key is the parent technique; `sub_technique_id` lives in the payload. Use `ttp.rule.fired.>` for fleet-wide subscribers. |
|
||||
| `ttp.rule.suppressed` | _reserved (TTP worker)_ | `{rule_id, technique_id, reason}` where `reason ∈ {"below_floor", "rate_limited", "rule_disabled"}` — observability for tags that *would have* been written but were dropped. Drives the dashboard's per-rule suppression counters. |
|
||||
| `system.log` | _reserved_ | — |
|
||||
| `system.bus.health` | Bus worker heartbeat | `{ts, uptime_s}` |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user