Parent epic
Epic E12: policies, safety, and reliability (P0) — #77
Objective
Build an admin-only audit log view at /admin/audit showing recent platform actions — payments marked paid, tutors approved, sessions rescheduled, tutors reassigned — so the admin has a clear record of all significant changes.
Background
From docs/ARCHITECTURE.md section 5.6 (audit_logs table):
create table public.audit_logs (
id bigint generated by default as identity primary key,
actor_user_id uuid references public.user_profiles(user_id),
action text not null,
entity_type text not null,
entity_id uuid,
details jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
create index on public.audit_logs (created_at desc);
The audit log is written by Server Actions throughout the platform (payment verified, match created, session rescheduled, tutor approved, etc.).
Migration: <ts>_create_audit_logs.sql
Include the audit_logs table if not already created as part of an earlier migration. RLS:
alter table public.audit_logs enable row level security;
-- Admin only reads
create policy "audit_logs_admin_select"
on public.audit_logs for select to authenticated
using (public.is_admin(auth.uid()));
-- Written by security definer functions or admin server actions
create policy "audit_logs_admin_insert"
on public.audit_logs for insert to authenticated
with check (public.is_admin(auth.uid()));
Admin audit log page: app/admin/audit/page.tsx
const { data: logs } = await adminClient
.from('audit_logs')
.select('id, action, entity_type, entity_id, details, created_at, user_profiles!actor_user_id(display_name)')
.order('created_at', { ascending: false })
.limit(200)
Log table
| Timestamp |
Actor |
Action |
Entity |
Details |
| Feb 23, 7:15 PM |
Admin |
payment_marked_paid |
payment |
package_id: xxx... |
| Feb 23, 6:50 PM |
Admin |
tutor_approved |
tutor_profile |
— |
| Feb 22, 8:00 PM |
Ali Hassan |
session_status_updated |
session |
status: done |
| Feb 22, 7:59 PM |
Ahmed Ali |
— |
— |
— |
Action labels
export const AUDIT_ACTION_LABELS: Record<string, string> = {
payment_marked_paid: '💳 Payment marked paid',
payment_rejected: '❌ Payment rejected',
tutor_approved: '✅ Tutor approved',
tutor_approval_revoked: '🚫 Tutor approval revoked',
tutor_assigned: '🎓 Tutor assigned to request',
tutor_reassigned: '🔄 Tutor reassigned',
sessions_generated: '📅 Sessions generated',
session_rescheduled: '📅 Session rescheduled',
session_status_updated: '📝 Session status updated',
meet_link_updated: '🔗 Meet link updated',
}
Acceptance criteria
Definition of done
References
docs/ARCHITECTURE.md — section 5.6 (audit_logs table), section 6.4 (RLS for audit_logs)
docs/OPS.md — section 12 (data hygiene rules — platform is source of truth)
docs/MVP.md — section 11.2 (admin audit log for changes)
Parent epic
Epic E12: policies, safety, and reliability (P0) — #77
Objective
Build an admin-only audit log view at
/admin/auditshowing recent platform actions — payments marked paid, tutors approved, sessions rescheduled, tutors reassigned — so the admin has a clear record of all significant changes.Background
From
docs/ARCHITECTURE.mdsection 5.6 (audit_logs table):The audit log is written by Server Actions throughout the platform (payment verified, match created, session rescheduled, tutor approved, etc.).
Migration:
<ts>_create_audit_logs.sqlInclude the
audit_logstable if not already created as part of an earlier migration. RLS:Admin audit log page:
app/admin/audit/page.tsxLog table
Action labels
Acceptance criteria
audit_logstable migration exists (created as part of E3 or this task)/admin/auditpage exists and is admin-onlyDefinition of done
audit_logstable exists in migrations/admin/audit/page.tsxrenders the log tableapp/admin/layout.tsx)References
docs/ARCHITECTURE.md— section 5.6 (audit_logs table), section 6.4 (RLS for audit_logs)docs/OPS.md— section 12 (data hygiene rules — platform is source of truth)docs/MVP.md— section 11.2 (admin audit log for changes)