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
- Problem type — Visibility gap, not release-driven permission drift. Fix is audit logging + UI surfacing, not investigating deploy migrations.
- 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).
- Log content (minimum) — Actor (admin who saved), timestamp, target user, company, before/after diff (permissions added/removed; role change if applicable).
- Do not block changes in v1 — Audit is read-only visibility; no approval workflow required for this ticket.
Open
- Primary UI surface for v1 — Company 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.)
- Who can view the log —
settings-admin only, anyone with settings-users, super-admin/Attik Admin only, or visible to the affected user?
- Retention — How far back should history show (e.g. 90 days, 1 year, unlimited)?
- Fields logged —
permissions only, or also role, status (active/disabled), and employeeId linkage changes?
- Change source — Should logs distinguish manual checkbox edit vs role/preset/template apply (requires frontend to pass context or infer from diff shape)?
- Preset safety (follow-up?) — Warn when applying a role/preset would remove permissions the user currently has — in v1 or separate ticket?
- 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)