Tenlayers,oneeventlog.

Traffic enters at L0 and never touches production. Everything after that is observation, and one irreversible decision at L4. Each layer writes to the same ordered event store, which is what makes the console a view of the system rather than a reconstruction of it.

Every layer, and what it is responsible for

Status is how far each layer has actually been taken. The architecture is complete, the implementation is not, and those are not the same claim.

Event-first, or none of the rest works.

The schema was frozen before the console existed. Every layer emits the same record shape into one ordered log, so live monitoring, investigation and replay are three views of one stream rather than three integrations.

The conversion record
{
  "type": "DECEPTION_CONVERSION",
  "phase": "DECEPTION",
  "risk_before": 97.5,
  "risk_after": 97.5,
  "reached_by": "threshold",
  "trigger": "T1003.008 · /etc/shadow read",
  "network_before": [
    "mgmt_net",
    "backend_net"
  ],
  "network_after": [
    "mgmt_net",
    "deception_net"
  ],
  "secrets_unmounted": true,
  "egress_policy": "default-deny"
}

The record every layer writes. risk_before, risk_delta and risk_after are carried on the event itself, so the curve in the console is read from the log rather than recomputed from it.

The live path
  1. Every layerwrites one record shape
  2. Redis Streamsordered, in memory
  3. Postgresdurable, replayable
  4. WebSocket / SSEpushed to the console
  5. Reacttimeline · risk · replay · environment
Why it is frozen

One Pydantic definition for every inter-layer message, settled before the console existed. Without it each component invents its own event format and the timeline has to be reassembled from logs afterwards, which is exactly the reconstruction this design refuses to do.