Skip to main content
Levels are stored on 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

A user may open a form if any of:
  • Super Admin
  • Form owner (userId)
  • principalEmail matches the session email
  • Same schoolName and level 2, 3, or 4 (src/lib/formAccess.js)
  • Listed in User.assignedForms for that formId
  • 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

On User.assignedForms[]:
Empty 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).