Skip to content

Add persisted Event audit-stream foundation (read path)

Placeholder ppxd requested to merge feat/event-audit-foundation into main

Summary

First step toward Octopus-parity deployment history: a persisted, append-only Event audit stream to replace today's client-synthesized history (which can only derive release-created / deployment-started / deployment-completed from existing fields, with no provenance/snapshot). Read foundation only — no emission wiring yet (additive; nothing changes for users until later PRs).

  • Event entity — append-only (deliberately NOT IAuditable), lean: smallint-backed Category + EstablishedWith enums, jsonb structured References (the UI renders + linkifies the category template against these, so English text isn't duplicated per row), and first-class indexed document columns (project/release/deployment/environment/machine/server_task) for the known history access paths — faster + smaller than a jsonb relation blob, matching ServerTaskLog's existing index pattern.
  • EventCategoryRegistry — the 12 categories (3 document-audit + 9 deployment-lifecycle), each with display name + message template; drift-pinned by tests.
  • DbUp migration — lean event table + partial composite indexes (keyset-paginated by id) + an occurred index for time-based retention; plus a lazy event_document_snapshot side table (snapshots stay out of the hot feed).
  • IEventService — RecordAsync (provenance from ICurrentUser) + GetEventsAsync (per-document filter, newest-first keyset pagination, clamped page size). Thin GetEventsRequest handler → service (Rule 16/17).
  • Distinct from existing logs (no conflict): ServerTaskLog = raw output, ActivityLog = execution tree, DeploymentInterruption/Completion = detail. Event is a thin audit pointer.

Deferred to planned follow-ups

PR-2 deployment-lifecycle emission · PR-3 document-audit interceptor + snapshot writes · PR-4 established-with/user-agent provenance polish · PR-5 frontend reads the real feed (+ diff) · RANGE partitioning (table is partition-ready — occurred is the future key; event has zero data so the conversion is clean before emission lands).

Test plan

  • Unit (8): EventCategoryRegistry drift guard (every category has a descriptor) + display names + persisted enum-value pins
  • Integration on real Postgres (3): RecordAsync persists + jsonb References round-trip; keyset pagination newest-first across pages; space + document isolation
  • Squid.Api (Core + Message + Api), unit, and integration projects all build clean; purely additive (no existing files edited)
  • CI: full unit + integration suites green

Merge request reports

Loading