TenantAtlas/specs/134-audit-log-foundation/data-model.md
ahmido 28cfe38ba4 feat: lay audit log foundation (#163)
## Summary
- turn the Monitoring audit log placeholder into a real workspace-scoped audit review surface
- introduce a shared audit recorder, richer audit value objects, and additive audit log schema evolution
- add audit outcome and actor badges, permission-aware related navigation, and durable audit retention coverage

## Included
- canonical `/admin/audit-log` list and detail inspection UI
- audit model helpers, taxonomy expansion, actor/target snapshots, and recorder/builder services
- operation terminal audit writes and purge command retention changes
- spec 134 design artifacts and focused Pest coverage for audit foundation behavior

## Validation
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact tests/Unit/Audit tests/Unit/Badges/AuditBadgesTest.php tests/Feature/Filament/AuditLogPageTest.php tests/Feature/Filament/AuditLogDetailInspectionTest.php tests/Feature/Filament/AuditLogAuthorizationTest.php tests/Feature/Monitoring/AuditCoverageGovernanceTest.php tests/Feature/Monitoring/AuditCoverageOperationsTest.php tests/Feature/Console/TenantpilotPurgeNonPersistentDataTest.php`

## Notes
- Livewire v4.0+ compliance is preserved within the existing Filament v5 application.
- No provider registration changes were needed; panel provider registration remains in `bootstrap/providers.php`.
- No new globally searchable resource was introduced.
- The audit page remains read-only; no destructive actions were added.
- No new asset pipeline changes were introduced; existing deploy-time `php artisan filament:assets` behavior remains unchanged.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #163
2026-03-11 09:39:37 +00:00

11 KiB

Data Model: Audit Log Foundation

Feature: 134-audit-log-foundation | Date: 2026-03-11

Overview

This feature extends an existing persisted entity rather than introducing a second audit-history store. The design adds a first-class event model, normalized actor and target snapshots, and a canonical read model for the Monitoring audit page.

The main model layers are:

  1. AuditLog as the durable event record,
  2. normalized event taxonomy and outcome semantics,
  3. actor and target snapshots captured at write time,
  4. structured context payloads with redaction,
  5. a workspace-scoped audit list and detail read model.

Existing Persistent Entity to Evolve

AuditLog

Current persisted shape already includes:

Attribute Type Notes
id int Existing primary key
tenant_id int nullable Existing tenant scope field
workspace_id int nullable Added later for workspace-scoped events
actor_id int nullable Existing actor identifier
actor_email string nullable Existing actor display fallback
actor_name string nullable Existing actor display fallback
action string Existing event key
resource_type string nullable Existing target-type precursor
resource_id string nullable Existing target-id precursor
status string Existing outcome precursor
metadata json nullable Existing structured payload precursor
recorded_at timestamp Existing event time

Planned first-class audit semantics to add or formalize:

Target Semantic Likely Storage Shape Purpose
event_type or normalized action existing action reused or renamed semantically Stable taxonomy key
summary new string/text column Human-readable list/detail summary
outcome new column or normalized use of status Explicit success/failure/partial/info/blocked state
actor_type new string column Human/system/scheduled/integration distinction
actor_label derived from existing name/email or new snapshot field Stable readable actor label
target_type existing resource_type reused or normalized Stable target taxonomy key
target_id existing resource_id reused or normalized Structured target identity
target_label new string column Stable readable target label
operation_run_id optional relation shortcut Operational cross-linking
context existing metadata reused or renamed semantically Structured supporting metadata
occurred_at existing recorded_at reused or normalized Canonical event timestamp

Core rules:

  • Every row is append-only in normal product flows.
  • Every row must remain understandable even when the source object is deleted or renamed later.
  • Every row must be scoped at least to a workspace; tenant scope remains nullable for workspace-only events.

Supporting Domain Concepts

AuditEventType

Field Type Description
key string Stable registry key such as baseline_capture.completed
family string Domain grouping such as baseline, finding, backup, restore, workspace_membership
verb string Normalized operator-facing action verb
supports_target_link bool Whether target drill-down is meaningful

Rules:

  • Must come from a shared canonical registry.
  • Must cover both legacy migrated keys and new first-wave keys.

AuditOutcome

Value Meaning
success Action completed successfully
failed Action failed
partial Action completed partially
info Informational/non-mutating event
blocked Action was intentionally prevented

Rules:

  • Badge rendering is centralized.
  • Existing historical values like success and failure need compatibility mapping where required.

AuditActorSnapshot

Field Type Description
actor_type string enum human, system, scheduled, integration, platform if compatibility requires
actor_id string or int nullable Stable identifier when available
actor_label string nullable Display label captured at event time
actor_email string nullable Secondary identity where useful

Rules:

  • Human and non-human actors must be distinguishable in storage and UI.
  • Historical readability must not depend on the actor record continuing to exist.

AuditTargetSnapshot

Field Type Description
target_type string nullable Canonical target kind such as finding, baseline_profile, backup_set
target_id string nullable Stable identity
target_label string nullable Display label captured at write time
workspace_id int Scope guard
tenant_id int nullable Tenant guard for tenant-owned targets

Rules:

  • Target label should be snapped at write time whenever practical.
  • Related links remain optional and permission-aware.

AuditContext

Field Type Description
context JSON-like object Structured metadata for interpretation

Expected content patterns:

Pattern Example
before/after lifecycle change before_status, after_status
related run identity operation_run_id
workflow rationale reason, reason_code
ownership reassignment from_assignee_user_id, to_assignee_user_id
summary counts items_succeeded, items_failed

Rules:

  • Context must remain intentionally shaped.
  • AuditContextSanitizer or equivalent must redact secrets, tokens, and sensitive fields.
  • Raw policy payloads and oversized blobs are not first-class audit context.

Read Models for the Monitoring Page

AuditLogListRow

Field Type Description
id int Event identity
occurred_at datetime Default sort field
summary string Primary row text
event_type string Secondary technical key
outcome string Badge-rendered state
actor_label string Who or what caused the event
actor_type string Actor-kind indicator
target_label string nullable Affected object
target_type string nullable Secondary target hint
tenant_label string nullable Only when safe to show
workspace_id int Scope
has_related_link bool Whether drill-down is available to this viewer

Rules:

  • Summary-first ordering is mandatory.
  • Rows remain understandable without opening the detail view.

AuditLogFilterState

Field Type Description
search string nullable High-signal summary search
tenant_id string nullable Defaulted from active tenant when entitled
event_type string nullable Taxonomy filter
outcome string nullable Outcome filter
actor string nullable Actor-label or actor-kind filter
target_type string nullable Target kind filter
date_from date nullable Range lower bound
date_until date nullable Range upper bound

Rules:

  • Filter options must come only from the active workspace and authorized tenant subset.
  • Empty results are valid and intentional.

AuditLogDetailViewModel

Field Type Description
summary string Primary heading
occurred_at datetime Event timestamp
actor AuditActorSnapshot Who/what caused the event
target AuditTargetSnapshot nullable Affected object
outcome string Result state
context_items list Readable context facts
technical_metadata list Secondary raw identifiers or event key
related_link object nullable Canonical target destination when permitted

Rules:

  • Readable context facts come before raw JSON.
  • The event must stay intelligible if related_link is absent.

Existing Domain Relations Important for Coverage

Finding

Relevant persisted fields already include status, severity, assignee and owner users, due dates, and closed or resolved timestamps.

Audit significance:

  • status changes
  • assignee or owner changes
  • risk acceptance via STATUS_RISK_ACCEPTED
  • reopen, resolve, close transitions

BaselineProfile

Relevant persisted fields already include workspace ownership, status, capture mode, active snapshot, and creator.

Audit significance:

  • create or update or archive actions
  • capture and compare lifecycle events through related jobs and operation context

BackupSet

Relevant persisted fields already include tenant ownership, metadata, completion time, and restore-run relation.

Audit significance:

  • create or update or archive events
  • restore initiation linkages and backup-scope summaries

RestoreRun

Relevant persisted fields already include status, preview, results, group mapping, completion timestamps, and operation-run relation.

Audit significance:

  • restore started, completed, failed, partial outcomes
  • assignment outcome summaries and preview/execute distinctions when meaningful

OperationRun

Remains the canonical operational record for long-running workflows.

Audit significance:

  • high-value completion/failure/retry evidence
  • optional operation_run_id shortcut from AuditLog

State and Transition Notes

AuditLog lifecycle

Created
  -> persisted as historical fact
  -> never user-edited or user-deleted in normal flows
  -> may be superseded or corrected only by later audit events

Workflow-to-audit relationship

User/system action occurs
  -> domain service or job performs authorization and mutation
  -> shared audit recorder writes one meaningful event with actor/target/context
  -> canonical Monitoring page surfaces the event in reverse chronological order

Validation Rules

Rule Result
Every audit row has workspace scope Required
Tenant-scoped events must belong to the same workspace Required
Actor kind is explicit for new rows Required
Summary is human-readable and non-empty for new rows Required
Context is sanitized and shaped Required
No user-facing edit/delete path exists Required
Related links are permission-aware and optional Required

Schema Impact

Schema changes are expected. The preferred migration strategy is additive evolution of audit_logs with compatibility-safe backfills and indexes for:

  • occurred-at or recorded-at descending review,
  • workspace + occurred-at,
  • tenant + occurred-at,
  • event type,
  • outcome,
  • actor lookup,
  • target lookup,
  • optional operation-run shortcuts.