This document explains how admin API tokens are used, how plan-code sessions work, and how the frontend cooperates with both flows.
The backend exposes operations under /api. There are two orthogonal access models:
X-Admin-Token)
ADMIN_API_TOKEN.These models can be used together: an admin can also operate within plan sessions, but admin token is not required for plan-scoped edits.
File: backend/auth.py
@require_admin decorator protects routes that should only be accessible by admins.ADMIN_API_TOKEN from environment and compares it to the X-Admin-Token header.ADMIN_API_TOKEN is not set, behavior is controlled by ADMIN_FAIL_OPEN (default true):
ADMIN_FAIL_OPEN=true, the decorator allows requests through (development convenience).ADMIN_FAIL_OPEN=false in production to enforce the token.Example protected endpoints (subject to change):
/api/plans (create plan)/api/upload/...Frontend usage (file: frontend/src/services/api.js):
X-Admin-Token automatically if it finds a token via Vite env VITE_ADMIN_API_TOKEN or browser localStorage keys (VITE_ADMIN_API_TOKEN, ADMIN_API_TOKEN, adminToken).How to supply a token during development:
frontend/.env.local with VITE_ADMIN_API_TOKEN=yourtokenvalue.localStorage.setItem('VITE_ADMIN_API_TOKEN', 'yourtokenvalue') and reload.File: backend/routes/plans.py
/api/plans/by-code/<PLANCODE>/api/plans/verify-code/<PLANCODE>session['accessed_plan_id'] and session['access_time'].Access checks:
check_plan_access(plan_id) which verifies
session['accessed_plan_id'] == plan_id and that the session has not expired.Rate limiting:
require_plan_access provides basic in-memory rate limiting (max ~10 attempts/hour per client IP) for code verification routes.What plan-code sessions can do:
/api/plans/<id>/api/plans/<id>/progress/api/plans/<id>/degree-audit?format=csv/api/plans/<id>/courses/api/plans/<id>/courses/<plan_course_id>/api/plans/<id>/courses/<plan_course_id>/api/plans/<id>
plan_name, student_email, status, current_program_idWhat plan-code sessions cannot do:
Session utilities:
/api/plans/session/clear clears the session./api/plans/session/status returns { has_access, plan_id, expires_in } when available./api/plans/by-code/<code>, which:
X-Admin-Token.Progress refresh:
/api/plans/<id>/progress to refetch immediately.Modals and focus:
ADMIN_API_TOKEN long and secret. Rotate periodically.ADMIN_FAIL_OPEN=false to enforce admin checks.Environment variables (backend):
ADMIN_API_TOKEN: required for admin routes when ADMIN_FAIL_OPEN=falseADMIN_FAIL_OPEN: true (default) or false; controls whether missing token fails openHeaders (frontend → backend):
X-Admin-Token: included automatically by the frontend service if configuredPlan session lifecycle:
accessed_plan_id and timestamp/api/plans/session/clear