Audit log for membership permission changes

Objective

  • Give company admins and Attik support a permission change history so when someone loses access (e.g. HR tab, Settings → Users), the team can see what changed, when, and who changed it.
  • Record audit events when membership permissions or role are updated — the actual mechanism that gates access today — and surface that history on user-management screens.
  • Replace the current dead end where access changes feel random or tied to releases even though deploys do not auto-rewrite permissions.

Background

  • Catherine (office hours) reported permissions "keep getting changed" — she lost Settings → Users (settings-users) and the HR tab (human) again. Only a small group can edit users, but there was no visibility into changes.
  • Investigation (product triage): Access comes from membership.permissions (and role) merged into session via /auth/web/compile-session. Admins edit via Settings → Users (PATCH /membership/:id); Attik staff can also edit via Attik Admin → Instance Management → User Management. Session cache is invalidated on save — user sees new access on next compile.
  • Releases do not migrate membership permissions on deploy. Losing tabs means those permission strings were removed from the membership document (manual save, role preset, or template apply) — not a silent release regression.
  • Gap today: membership.ts PATCH has no audit trail (no actor, timestamp, or before/after diff).
  • Example permissions: human (HR nav), settings-users (Users settings), settings-admin (broader settings).

Product Decisions

Locked

  1. Problem type — Visibility gap, not release-driven permission drift. Fix is audit logging + UI surfacing, not investigating deploy migrations.
  2. Log at source — Write audit records when membership permissions and/or role change (attik-backend/src/routes/membership.ts PATCH/POST paths that mutate access).
  3. Log content (minimum)Actor (admin who saved), timestamp, target user, company, before/after diff (permissions added/removed; role change if applicable).
  4. Do not block changes in v1 — Audit is read-only visibility; no approval workflow required for this ticket.

Open

  1. Primary UI surface for v1Company Settings → Users (/tools/settings/users/[id]) only, Attik Admin → User Management only, or both? (Catherine's scenario is company-admin edits; Attik Admin is cross-instance support.)
  2. Who can view the logsettings-admin only, anyone with settings-users, super-admin/Attik Admin only, or visible to the affected user?
  3. Retention — How far back should history show (e.g. 90 days, 1 year, unlimited)?
  4. Fields loggedpermissions only, or also role, status (active/disabled), and employeeId linkage changes?
  5. Change source — Should logs distinguish manual checkbox edit vs role/preset/template apply (requires frontend to pass context or infer from diff shape)?
  6. Preset safety (follow-up?) — Warn when applying a role/preset would remove permissions the user currently has — in v1 or separate ticket?
  7. Relationship to ATT-1056 — This ticket is membership permission audit only; link to broader settings audit separately or expand scope later?

Scope

Backend

  • attik-backend/src/routes/membership.ts — on PATCH/POST that changes permissions or role, persist an audit record (new collection or reuse an existing activity/audit pattern if one fits).
  • Capture actor from res.locals.user / membership of the requester and before state from res.locals.item before save.
  • Expose GET endpoint to fetch permission-change history for a membership or user+company (paginated).
  • attik-backend/src/models/membershipSchema.ts — reference; permissions live on membership, not user doc alone.
  • attik-backend/src/util/functions/betterAuth/web/webAuthEndpoints.ts — compile-session reads membership permissions (no change required unless cache invalidation timing matters for display).

Frontend

  • Company path: attik-frontend/src/app/tools/settings/users/[id]/page.tsx and DataForm.tsx — add Permission change history section (list actor, time, diff summary).
  • Attik Admin path (if Open #1 includes it): attik-frontend/src/app/admin/settings/instance-management/user-management/ — same history component when editing a user's membership.
  • Permission gates reference: navButtons.tsx (human → HR), settings/layout.tsx (settings-users → Users).

Out of scope (v1 unless Open decisions expand)

  • Full settings audit across all Settings pages (ATT-1056).
  • Permission template auto-sync (ATT-1721).
  • Preventing admins from making permission changes.
  • Historical backfill before audit ships.

Done when

  • [ ] Saving membership permissions logs actor, timestamp, company, target user, and added/removed permissions.
  • [ ] Admins can view history on the agreed surface(s) from Open #1.
  • [ ] Catherine-style scenario is diagnosable: "who removed human / settings-users and when?"
  • [ ] No change to how permissions are evaluated — logging only.

References

  • Permission catalog: attik-backend/src/util/data/permissionsData.ts
  • Membership CRUD: attik-backend/src/routes/membership.ts
  • Company user edit UI: attik-frontend/src/app/tools/settings/users/[id]/DataForm.tsx
  • Attik Admin users: attik-frontend/src/app/admin/settings/instance-management/user-management/
  • Related: ATT-1056 (broad settings audit), ATT-1721 (template-linked permissions)

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

2 days ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.