User.level (1–5) and copied onto the JWT. Route handlers should reload User from MongoDB (especially Super Admin mutations) rather than trusting session.user.level alone.
Form authorization
- View
- Edit
- Create / attest / submit
A user may open a form if any of:
- Super Admin
- Form owner (
userId) principalEmailmatches the session email- Same
schoolNameand level 2, 3, or 4 (src/lib/formAccess.js) - Listed in
User.assignedFormsfor thatformId - Listed in
FormSubmission.sharedWithEmails
Assistant Principal is not a second owner: they can edit the school plan but cannot attest or submit. Level 1 still needs an assignment or share. Off-school collaborators always need share/assignment.
School users (canManageTarget)
src/lib/canManageUser.js:
- Nobody manages themselves
- Super Admin (level 5) may list and update every other account, including other Super Admins, and may assign levels 1–5
- Below Super Admin, actor level must be strictly higher than the target
- Principals only see/manage people at their school with level ≤ 3 (list filter is
level: { $lt: 5 }so Super Admins at that school do not appear) - Principals cannot create or promote to level 4 or 5
Collaboration fields
OnUser.assignedForms[]:
assignedSections means all steps. permissions is view | edit | admin.
In-app how-to copy lives in src/lib/roleGuides.js (dashboard How to, /dashboard?view=howto).