Files
sciagent/docs/audit-log-manager-plan.md
T
Thinh Lam 688fac73e9
CI/CD / backend (push) Failing after 2m8s
CI/CD / frontend (push) Failing after 1m40s
CI/CD / deploy (push) Has been skipped
sciagent code + Gitea Actions CI/CD
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 09:38:30 +07:00

8.1 KiB
Raw Blame History

Audit Log Manager — Admin Planning Document

This plan describes the Audit Log Manager: an admin-only surface for tracing and monitoring per-user activity in the web application, with time as the primary navigation axis. It is derived from and must stay consistent with assets/docs/audit-log-implementation.md (schema, record_audit, role-based logging rules, and Step 6 admin viewer).


1. Goals

Goal Description
Forensic traceability Answer: “What did user U do, and when?” and “What happened to entity E between T₁ and T₂?”
Time-first exploration Default and sort order anchored on occurred_at (UTC stored as TIMESTAMPTZ; display in admins locale or a configured org timezone).
Tamper-aware source Queries read from append-only audit_events (app role: INSERT/SELECT only per implementation guide).
No scope creep v1 is query + view, not anomaly detection, not primary shipping to external log stacks (see implementation guide §9).

2. Relationship to backend data model

The implementation guide defines a unified audit_events table keyed by time:

  • occurred_at — canonical timestamp for all list, filter, and timeline views; indexed with actor_user_id and other dimensions.
  • Actor columnsactor_user_id, actor_email, actor_role (denormalized at event time).
  • Targetaction, entity_type, entity_id, optional before / after JSONB snapshots, metadata, request_id.

Note: The repository may also contain legacy audit_log / trigger-based patterns. The Audit Log Manager should target the new audit_events model from the implementation guide once migrated; until then, scope API field mapping explicitly so the UI contract does not depend on legacy tables.


3. Admin API design

3.1 Endpoint

  • GET /api/v1/admin/audit — admin role check on router and service layer (mirror implementation guide §8).

3.2 Query parameters (time + filters)

Parameter Purpose
from Inclusive lower bound on occurred_at (ISO-8601 / RFC3339, timezone-aware).
to Exclusive or inclusive upper bound (pick one, document in OpenAPI; default: inclusive end-of-day if date-only strings are allowed).
actor_user_id Filter by user UUID (strong identifier for “this users timeline”).
actor_email Partial or exact match per product choice; prefer exact for predictable forensic use.
entity_type, entity_id Narrow to one records history.
action One or many audit_action values (create, read, update, delete, login, logout, login_failed).
request_id Optional: correlate all events from one HTTP request.
page, page_size Paginated results; cap page_size (e.g. 100) for performance.
sort Default occurred_at,desc; optional asc for chronological “playback” within a window.

3.3 Response shape

Each item should expose at minimum:

  • id, occurred_at, actor_user_id, actor_email, actor_role, action, entity_type, entity_id, metadata, request_id, and flags or URLs indicating presence of before / after (full JSON may be omitted from list rows and loaded on detail fetch if payloads are large).

Optional follow-up:

  • GET /api/v1/admin/audit/{id} — full row including before / after for the detail panel.

3.4 Query strategy

  • Always constrain by occurred_at when the admin does not pass from/to — e.g. default last 24 hours or last 7 days to avoid full table scans.
  • Use existing indexes: (actor_user_id, occurred_at DESC), (entity_type, entity_id, occurred_at DESC), (action, occurred_at DESC).

4. Admin UI — Audit Log Manager

4.1 Placement and access

  • Route: /dashboard/admin/audit (or equivalent admin layout path).
  • Wrapped in ProtectedRoute (or equivalent) admin-only; no feature flags that downgrade the check in production.

4.2 Layout

  1. Filter bar — time range, user (email or ID), entity type/id, action multiselect, optional free-text on metadata paths (defer to v2 unless trivial; GIN on metadata supports it later).
  2. Results table — columns: Time (occurred_at), Actor (email + role), Action, Entity (type + id), Summary (one-line from metadata or action), Request (link/filter by request_id if present).
  3. Detail drawer / panel — on row click: show full metadata, before / after side-by-side; diff in the browser with a JSON diff library (per implementation guide — do not compute diff on server).

4.3 Time-centric UX presets

Presets speed up monitoring:

  • Last 24 hours, last 7 days, last 30 days, custom range (date-time pickers with timezone label).
  • “This users activity” deep link: /dashboard/admin/audit?actor_user_id=…&from=…&to=….

4.4 Monitoring-oriented views (v1 vs later)

View v1 Later
Paginated event list with time filters Yes
Sort by occurred_at Yes
Per-user timeline (same data, fixed actor_user_id) Yes Optional density / grouping by day
Per-entity history Yes
Export (CSV/JSON) for compliance Optional Regulated customers often need it
Live / websocket tail No Only if product requires real-time

5. Timestamp semantics

  • Storage: TIMESTAMPTZ in PostgreSQL; all APIs use ISO-8601 with offset or Z.
  • Display: Convert to admin-visible timezone; show UTC in tooltip or secondary row for disputes.
  • Day boundaries: If the UI sends date-only from/to, define explicitly (e.g. start of day / end of day in chosen timezone, then convert to UTC for the query).

6. Privacy, security, and correctness

  • Admin-only on UI and API; verify with automated tests.
  • Do not log secrets in before/after (enforce to_dict() hygiene per implementation guide §5.1 and §8).
  • Failed login events: actor_user_id null, actor_email = attempted address; UI must not imply existence of accounts beyond what policy allows (align with auth UX).
  • Read volume: Applicant read-audit is mostly suppressed by design; admins see all reads they are allowed to see — train admins that “quiet” applicant timelines are expected.

7. Implementation phases (aligned with implementation guide §7)

Phase Deliverable for Audit Log Manager
After Step 1 Stub UI + API returns empty or mock; contract freeze.
After Steps 24 Real data for auth, user admin, initiative writes; filters and table usable for forensic queries.
After Step 5 Read events appear per role rules; admin sees broad read coverage.
Step 6 (shipping target) Full Audit Log Manager as specified here: filters, pagination, detail panel, time presets.
Step 7 Retention/partitioning — Manager may add UI notice “data older than X may be purged per policy.”

8. Acceptance criteria (Audit Log Manager)

  • Admin cannot access /api/v1/admin/audit as non-admin (403).
  • Listing is ordered by occurred_at descending by default; ascending works for a bounded window.
  • Filtering by from / to reduces rows correctly and uses indexed columns.
  • Filtering by actor_user_id or actor_email returns only that actors events.
  • Row detail shows before / after without server-side diff; client-side diff renders correctly for large JSON (smoke test with sample initiative snapshot).
  • Time preset “last 7 days” matches server interpretation (document timezone).
  • No secrets appear in exported or displayed JSON (spot-check against to_dict() tests).

9. References