Roles, gates, and an audit trail
Switch between counsellor, admin, parent, and reviewer roles to see how the system would gate data visibility. Every action — including this role switch — appends to the audit log below.
Counsellor (Dr. Priya Menon)
Current demo role · stored in a session cookie · in production, this is determined by SSO + DB-side row-level security.
audit_log row.
Production behaviour: the role would gate which students, reports, and dashboards each user sees, enforced by Postgres row-level security policies.
50 of 81 entries
| When | User | Role | Action | Entity | Details |
|---|---|---|---|---|---|
| today | Nandini Iyer | parent | delete_session_denied | session#1 | {"denied":true,"reason":"viewer attempted destructive write","required_role":"admin"} |
| today | Ramesh Shenoy | counselor | view | student#20 | {"path":"/students/20"} |
| today | Ashwin Rao | counselor | role_switch | — | {"from":"counselor","to":"admin"} |
| today | Aditi Krishnan | reviewer | export | dashboard | {"format":"csv","rows":47} |
| yesterday | Sundar Krishnan | parent | search | — | {"query":"RIASEC artistic","results":13} |
| yesterday | Dr. Priya Menon | counselor | view | student#7 | {"path":"/students/7"} |
| yesterday | Dr. Priya Menon | counselor | export | dashboard | {"format":"csv","rows":47} |
| yesterday | Nitya Balakrishnan | counselor | export | dashboard | {"format":"csv","rows":47} |
| 3d ago | Dr. Priya Menon | counselor | role_switch | — | {"from":"counselor","to":"admin"} |
| 3d ago | Ashwin Rao | counselor | login | — | {"ip":"192.168.1.42"} |
| 3d ago | Sundar Krishnan | parent | edit | student#8 | {"path":"/students/8"} |
| 4d ago | Sandeep Kumar | admin | search | — | {"query":"RIASEC artistic","results":11} |
| 4d ago | Nandini Iyer | parent | login | — | {"ip":"192.168.1.42"} |
| 5d ago | Vikram Suresh | reviewer | export | dashboard | {"format":"csv","rows":47} |
| 5d ago | Sandeep Kumar | admin | export | dashboard | {"format":"csv","rows":47} |
| 6d ago | Kavita Iyer | counselor | login | — | {"ip":"192.168.1.42"} |
| 6d ago | Aditi Krishnan | reviewer | edit | student#24 | {"path":"/students/24"} |
| 1w ago | Sandeep Kumar | admin | search | — | {"query":"RIASEC artistic","results":5} |
| 1w ago | Vikram Suresh | reviewer | export | dashboard | {"format":"csv","rows":47} |
| 1w ago | Nitya Balakrishnan | counselor | view | student#27 | {"path":"/students/27"} |
| 1w ago | Aditi Krishnan | reviewer | edit | student#10 | {"path":"/students/10"} |
| 1w ago | Nandini Iyer | parent | view | student#17 | {"path":"/students/17"} |
| 1w ago | Ashwin Rao | counselor | login | — | {"ip":"192.168.1.42"} |
| 1w ago | Sundar Krishnan | parent | role_switch | — | {"from":"counselor","to":"admin"} |
| 1w ago | Vikram Suresh | reviewer | login | — | {"ip":"192.168.1.42"} |
| 1w ago | Ramesh Shenoy | counselor | view | student#32 | {"path":"/students/32"} |
| 1w ago | Sandeep Kumar | admin | login | — | {"ip":"192.168.1.42"} |
| 1w ago | Ashwin Rao | counselor | export | dashboard | {"format":"csv","rows":47} |
| 1w ago | Aditi Krishnan | reviewer | export | dashboard | {"format":"csv","rows":47} |
| 1w ago | Sundar Krishnan | parent | edit | student#36 | {"path":"/students/36"} |
| 1w ago | Dr. Priya Menon | counselor | role_switch | — | {"from":"counselor","to":"admin"} |
| 1w ago | Nandini Iyer | parent | search | — | {"query":"RIASEC artistic","results":5} |
| 1w ago | Nandini Iyer | parent | view | student#21 | {"path":"/students/21"} |
| 1w ago | Dr. Priya Menon | counselor | role_switch | — | {"from":"counselor","to":"admin"} |
| 1w ago | Ashwin Rao | counselor | search | — | {"query":"RIASEC artistic","results":5} |
| 1w ago | Sundar Krishnan | parent | edit | student#37 | {"path":"/students/37"} |
| 2w ago | Vikram Suresh | reviewer | view | student#29 | {"path":"/students/29"} |
| 2w ago | Ashwin Rao | counselor | login | — | {"ip":"192.168.1.42"} |
| 2w ago | Kavita Iyer | counselor | login | — | {"ip":"192.168.1.42"} |
| 2w ago | Kavita Iyer | counselor | search | — | {"query":"RIASEC artistic","results":4} |
| 2w ago | Ashwin Rao | counselor | edit | student#41 | {"path":"/students/41"} |
| 2w ago | Dr. Priya Menon | counselor | login | — | {"ip":"192.168.1.42"} |
| 2w ago | Aditi Krishnan | reviewer | login | — | {"ip":"192.168.1.42"} |
| 2w ago | Sandeep Kumar | admin | export | dashboard | {"format":"csv","rows":47} |
| 2w ago | Dr. Priya Menon | counselor | role_switch | — | {"from":"counselor","to":"admin"} |
| 2w ago | Nandini Iyer | parent | edit | student#22 | {"path":"/students/22"} |
| 2w ago | Sandeep Kumar | admin | search | — | {"query":"RIASEC artistic","results":12} |
| 2w ago | Ashwin Rao | counselor | view | student#8 | {"path":"/students/8"} |
| 2w ago | Aditi Krishnan | reviewer | edit | student#50 | {"path":"/students/50"} |
| 2w ago | Dr. Priya Menon | counselor | edit | student#4 | {"path":"/students/4"} |
- Real authentication — SSO for school admins, magic-link for parents, JWT-based sessions
- Postgres row-level security policies that enforce role gates at the DB layer (not the app layer)
- Per-tenant isolation — schools become tenants, queries auto-scoped via
tenant_id - Audit retention policy — currently append-forever; prod would archive entries older than 90 days to cold storage
- Right-to-be-forgotten flow for student records under DPDP / GDPR compliance
Cookie-based role toggle, audit-everything
Role lives in a signed cookie (demo_role). The button POSTs to /security/role; server sets SET-COOKIE + redirects. No session table needed for the demo.
Every write handler reads the cookie. Viewer attempting a write returns 403 with the audit_log row — never a silent redirect. The denial is itself an audit event.
Every read of student PII, every write, every role flip writes a row into audit_log: actor, action, target, ts, ip. Append-only, never updated.
The viewer below renders the last 100 audit rows. In prod this becomes a tenant-scoped, filterable, exportable trail with retention.