Story: Audit trail and system account
Table of Contents
This page documents a story in Sprint 12. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Get the audit trail honest. Standardise terminology. Add a non-login
system account for initial population. Make protocol messages stop
trusting client-supplied modified_by. Decompose the generation
context so generators can read audit fields from environment.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 12 |
| Now | Completed 2026-02-17. |
| Waiting on | None. |
| Next | None. |
| Last touched | 2026-02-17 |
Acceptance
- modified_by + performed_by have soft FK to accounts.
- performed_by visible in UI.
- System account exists; used for initial population only.
- Protocol rejects client-supplied modified_by.
- generation_engine + generation_environment + generation_context in place; ~36 generators migrated.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Fix audit trail metadata for recorded_by and modified_by | DONE | 2026-05-19 | 2026-02-16 | modified_by + performed_by soft FK to accounts; super-admin no longer 'modified by bootstrap'; tenant admin no longer 'recorded by onboarding'; performed_by visible in UI; terminology standardised. |
| Investigate how performed by is being set | DONE | 2026-05-19 | 2026-02-16 | Audit the source of performed_by; should be the database account. |
| Add system account | DONE | 2026-05-19 | 2026-02-16 | Non-login system account used for all initial population; publication uses the new admin account, not the system account. |
| Add-entity messages should not set modified_by | DONE | 2026-05-19 | 2026-02-16 | modified_by must come from the session (logged-in user); reject any client-supplied modified_by in protocol messages. |
| Add generation context with KVP for audit trail fields | DONE | 2026-05-19 | 2026-02-17 | generation_context decomposed into generation_engine + generation_environment + composing context; ~36 generators migrated to accept generation_context&; modified_by lookup via environment; strict ores_iam_validate_account_username_fn re-enabled; make_generation_context() factory in ores.testing. |
Decisions
- modified_by = DB user, performed_by = app actor
- split is real; was previously inconsistent.
- System account for bootstrap, admin account for publication
- separates initial-state-only writes from operational ones.
- Environment + parent-chain lookup
- clean way to plumb tenant_id + modified_by into generators without explicit parameters.
Out of scope
- Audit-trail UI surface (separate story).
- Field-level audit (we audit at the row level only).
See also
- Service accounts and audit (sprint 11) — predecessor work establishing the performed_by field.