Files
git.stella-ops.org/docs/signals/events-24-005.md
StellaOps Bot 108d1c64b3
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
cryptopro-linux-csp / build-and-test (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
sm-remote-ci / build-and-test (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
up
2025-12-09 09:38:09 +02:00

2.9 KiB

signals.fact.updated event contract (SIGNALS-24-005 prep)

Purpose: replace the in-memory logger used during Signals development with a real event bus contract so reachability caches can be invalidated and downstream consumers (Policy Engine, Notifications, Console) can subscribe deterministically.

Topic / channel

  • Primary topic: signals.fact.updated.v1
  • Dead-letter topic: signals.fact.updated.dlq
  • Delivery: at-least-once; consumers must de-duplicate using event_id.

Message envelope

{
  "event_id": "uuid-v4",                // stable across retries; used for idempotency
  "emitted_at": "2025-11-20T00:00:00Z", // UTC, RFC3339
  "tenant": "acme",                     // required; lower-case
  "subject_key": "sbom:sha256:…" ,       // subject of facts (asset, sbom, host). Deterministic model key.
  "fact_kind": "callgraph" | "runtime" | "reachability" | "signal", // enums mapped from Signals domain
  "fact_version": 1,                     // monotonically increasing per subject_key + fact_kind
  "digest": "sha256:…",                 // CAS digest of canonical fact document
  "content_type": "application/json",   // or application/vnd.stellaops.ndjson when chunked
  "producer": "StellaOps.Signals",      // emitting service
  "source": {
    "pipeline": "signals",             // consistent with Observability tags
    "release": "0.4.0-alpha"           // optional
  },
  "trace": {
    "trace_id": "…",                   // pass-through if available
    "span_id": "…"
  }
}

Routing / partitions

  • Partition key: tenant to keep per-tenant ordering.
  • Retry policy: exponential backoff up to 5 minutes; move to DLQ thereafter with dlq_reason header.

Consumer expectations

  • De-duplicate on event_id and digest.
  • Fetch fact body from CAS using digest; avoid embedding large payloads in the message.
  • If consumer cannot resolve CAS, treat as transient and retry later (do not drop).

Security / air-gap posture

  • No PII; tenant id only.
  • Works offline when bus is intra-cluster (e.g., NATS/Redis Streams); external exporters disabled in sealed mode.

Provenance

  • This contract supersedes the temporary log-based publisher referenced in Signals sprint 0143 Execution Log (2025-11-18). Aligns with signals.fact.updated@v1 payload shape already covered by unit tests.
  • Implementation: Signals.Events defaults to Redis Streams (signals.fact.updated.v1 with signals.fact.updated.dlq), emitting envelopes that include event_id, fact_version, and deterministic fact.digest (sha256) generated by the reachability fact hasher.
  • Router transport: set Signals.Events.Driver=router to POST envelopes to the StellaOps Router gateway (BaseUrl + Path, default /router/events/signals.fact.updated) with optional API key/headers. This path should forward to downstream consumers registered in Router; Redis remains mandatory for reachability cache but not for event fan-out when router is enabled.