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 or 4 - Listed in
User.assignedFormsfor thatformId - Listed in
FormSubmission.sharedWithEmails
Assistant Principal is a collaborator, not a second owner. If Preview as AP cannot edit, share the plan from Collaboration. That is expected, not a 403 bug.
School users (canManageTarget)
src/lib/canManageUser.js:
- Nobody manages themselves
- 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).