System diagrams

These diagrams complement the architecture overview. Names match OpenAPI operations and Redis stream/event names.

Worker processing and realtime delivery

flowchart LR
  A[auth] -->|email.send| MJ[(mail.jobs)]
  S[any API service] -->|audit.entry| AJ[(audit.events)]
  S -->|webhook.deliver| WH[(webhook.jobs)]
  U[users/auth] -->|force-logout publish| P[(Redis pub/sub)]
  W[worker consumer groups] -->|XREADGROUP| MJ
  W -->|XREADGROUP| AJ
  W -->|XREADGROUP| WH
  W --> D[(dedup marker / audit msg_id)]
  W --> M[mailer/webhook provider]
  W -->|after max attempts| DLQ[(stream:dlq)]
  P --> R[realtime]
  R --> H[room hub]
  H --> WS[authorized WebSocket clients]

Workers acknowledge only after side effects and dedup evidence succeed. XAUTOCLAIM recovers abandoned messages; replay requires the offline DLQ administrator credential. Realtime serializes writes per connection and uses Redis only for cross-instance control messages.

Login and authorization

sequenceDiagram
  participant B as Browser
  participant G as Gateway
  participant A as Auth
  participant R as RBAC
  B->>G: POST /auth/login + device ID
  G->>A: validated request
  A->>A: rate/lockout + password + MFA
  A->>R: resolve roles, permissions, version
  R-->>A: claims
  A-->>G: access token + HttpOnly refresh cookie
  G-->>B: envelope
  B->>G: authorized API request
  G->>G: verify JWT and current claims version
  G->>G: enforce route permission
  G-->>B: response

Registration and projection materialization

sequenceDiagram
  participant B as Browser
  participant G as Gateway
  participant A as Auth/Postgres
  participant X as users.events
  participant U as Users consumer
  participant R as RBAC consumer
  B->>G: POST /auth/register
  G->>A: validated registration
  A->>A: commit identity and event outbox
  A-->>G: 201 access + refresh session
  G-->>B: registered
  A->>X: user.created v1
  par projections
    X->>U: materialize profile (upsert)
  and default access
    X->>R: assign default user role (idempotent)
  end

The response does not wait for projections. Consumers start at stream position 0, and stable IDs/upserts make replay safe.

Refresh-token rotation and reuse detection

sequenceDiagram
  participant B as Browser
  participant G as Gateway
  participant A as Auth
  participant D as Session store
  B->>G: POST /auth/refresh + HttpOnly cookie + device ID
  G->>A: refresh request
  A->>D: consume current token atomically
  alt current token
    D-->>A: active session family
    A->>D: store rotated token and short grace predecessor
    A-->>B: new access token + rotated cookie
  else grace replay from same device
    D-->>A: already rotated response
    A-->>B: current replacement
  else reuse or device mismatch
    A->>D: revoke entire family
    A-->>B: uniform 401 + clear cookie
  end

Session lifecycle

stateDiagram-v2
  [*] --> Active: login/register
  Active --> Rotated: refresh
  Rotated --> Active: replacement becomes current
  Active --> Revoked: logout/admin revoke/password reset
  Rotated --> Revoked: reuse detection
  Active --> Expired: absolute expiry
  Rotated --> Expired: absolute expiry
  Revoked --> [*]
  Expired --> [*]

Revoked and expired sessions never return to active. Account lock/inactivation also makes active sessions unusable through current-state checks.

Stream data flow

flowchart TB
  subgraph Producers
    AUTH[auth]
    USERS[users]
    API[all API services]
    SCHED[scheduler leader]
  end
  subgraph Redis Streams
    UE[(users.events)]
    MAIL[(mail.jobs)]
    AUDIT[(audit.events)]
    WEBHOOK[(webhook.jobs)]
    DOMAIN[(configured domain streams)]
  end
  AUTH -->|user.created / user.deleted| UE
  AUTH -->|email.send| MAIL
  USERS -->|user.deleted| UE
  API -->|audit.entry| AUDIT
  API -->|webhook.deliver| WEBHOOK
  SCHED --> DOMAIN
  UE --> USERSC[users projection group]
  UE --> RBACC[RBAC default-role group]
  MAIL --> WORKER[worker mail group]
  AUDIT --> WORKER
  WEBHOOK --> WORKER
  DOMAIN --> HANDLERS[registered worker handlers]

Trust boundaries

flowchart LR
  Internet((Internet)) -->|TLS| Edge[nginx / gateway]
  Edge -->|verified identity + internal secret| Services[private Go services]
  Services -->|scoped credentials| PG[(PostgreSQL schemas)]
  Services -->|ACL users + signed events| Redis[(Redis)]
  Services -->|OTLP/logs/metrics| Obs[observability network]
  Services -->|egress allowlist| Providers[SMTP / HIBP / webhooks]
  CI[GitHub/Jenkins] -->|signed images and deploy identity| Registry[registry]
  Registry --> Cluster[Kubernetes / Compose host]

Every arrow crosses an authentication, network, or data-ownership boundary. Detailed threats and residual risks are in THREAT_MODEL.md.