Skip to content

F2.D — Audit log for admin actions #30

@HXYerror

Description

@HXYerror

Part of #23. Depends on F2.A, F2.B.

Issue added during multi-role review (security S6). Not in original user request but flagged as a hard requirement for any meaningful auth deployment — without it, "who enabled debug on key X at time Y" is unanswerable.

Background

The admin plane introduces mutating actions (key create/revoke, scope edit, debug toggle, config edit, no-auth boot, recovery flow). With multiple operators, an audit trail becomes essential for incident response and compliance.

Goal

An append-only audit log capturing every privileged action with actor, target, before/after, and timestamp.

Tasks

  • Append-only file: ~/.local/share/copilot-api/audit.jsonl, mode 0600
  • One JSON line per event: {ts, actor_key_id, actor_tier, action, target, before?, after?, ip?, user_agent?}
  • Actions to log:
    • key.create, key.revoke, key.scope_change, key.debug_toggle, key.rate_limit_override_change
    • config.edit (with diff summary)
    • auth.bootstrap, auth.recover
    • auth.reject (failed bearer attempt — value never logged, only sha256 prefix)
    • server.start_no_auth (logged once at boot, with bind address)
  • Middleware-enforced: any mutating admin route MUST go through an audit(action, target) helper, otherwise refuse to accept it
  • Rotation: daily by date in filename (audit-YYYY-MM-DD.jsonl), retention configurable (default 365 days — audit logs longer than telemetry)
  • Read endpoint at /admin/audit (admin tier only) with date filter, action filter, pagination
  • Tests: every mutating endpoint produces an audit row; tampering with file mode is detected at startup

Acceptance criteria

  • Every mutating admin action produces exactly one audit row
  • Audit file is append-only (no truncation, no in-place edit)
  • Failed bootstrap/recovery attempts are recorded without exposing key values
  • File mode is 0600

File pointers

  • New: src/services/audit.ts, src/admin/audit/route.ts, tests/audit.test.ts
  • Touch: any admin write handler

Dependencies

Depends on F2.A, F2.B. Should land before F2.E (so the WebUI can audit).

Metadata

Metadata

Assignees

No one assigned

    Labels

    authAuthentication / authorizationsecuritySecurity-sensitivestoragePersistence layer

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions