Implementation of the Rutgers Degree Planner migration plan with:
- FastAPI backend (
backend/) - Next.js frontend scaffold (
apps/web/) - Prisma schema contract (
prisma/schema.prisma)
- Snapshot lifecycle APIs:
POST /v1/catalog/snapshots:stagePOST /v1/catalog/snapshots:stage-from-csvPOST /v1/catalog/snapshots/{snapshotId}:promoteGET /v1/catalog/snapshots/active
- Course search:
GET /v1/catalog/courses/search
- Plan APIs:
POST /v1/plansPOST /v1/plans/{planId}/items:validatePUT /v1/plans/{planId}/items/{itemId}POST /v1/plans/{planId}/recompute-auditGET /v1/plans/{planId}/audit/latestPOST /v1/plans/{planId}/finalize
- Core rules:
- course canonicalization via regex
\d{2}:\d{3}:\d{3} - snapshot-pinned validation
- offering checks per term instance
- v1 prereq execution supports
courseandall;any/countAtLeastbecome unsupported for validation - summer same-term-above rule requires
completion_status == YES - save-invalid allowed, finalize blocked on invalid/unsupported
- course canonicalization via regex
- Routes:
/catalog/planner/[planId]/degree-tracker/[planId]/progress/[planId]
- Backend wiring through
NEXT_PUBLIC_API_BASE
cd backend python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt
cd backend source .venv/bin/activate scripts/dev_start.sh
Optional override for deterministic local DB target:
cd backend source .venv/bin/activate export DATABASE_URL="sqlite:////ABSOLUTE/PATH/TO/backend/gradpath.db" scripts/dev_start.sh
DATABASE_URL must be set before starting the backend process.
If you change DATABASE_URL, restart the backend process (engine/sessionmaker are cached per process).
Verify the effective DB URL:
cd backend source .venv/bin/activate python -c "from app.db import get_engine; print(get_engine().url)"
Health check:
curl -s http://localhost:8000/health
cd backend source .venv/bin/activate pytest -q
In a second terminal (while API is running):
cd backend source .venv/bin/activate chmod +x scripts/dev_flow.sh scripts/dev_flow.sh
Optional env overrides:
API=http://localhost:8000 DEV_NETID=dev123 DEV_EMAIL=dev123@rutgers.edu scripts/dev_flow.sh
cd apps/web
npm install
NEXT_PUBLIC_API_BASE=http://localhost:8000 npm run devThe WebReg automation adapter targets Rutgers SOC machine APIs under
https://classes.rutgers.edu/soc/api (not browser UI hosts).
If UI endpoints are used (webreg.rutgers.edu, sims.rutgers.edu, dn.rutgers.edu),
the runner will fail closed on redirects.
Run a single unattended SOC ingest job:
cd backend source .venv/bin/activate python scripts/run_soc_ingest.py --campus NB --term-code 2025SU
Optional override:
WEBREG_SOC_URL=https://classes.rutgers.edu/soc/api python scripts/run_soc_ingest.py --campus NB --term-code 2025SU
Run multiple jobs from config:
cd backend source .venv/bin/activate python scripts/run_soc_ingest.py --config scripts/soc_jobs.json --output-jsonl var/soc_ingest_runs.jsonl
run_soc_ingest.py executes jobs sequentially, continues after failures, and exits non-zero if any job fails.
Phase 4 never auto-promotes snapshots; promotion remains manual/policy-gated.
Generate closeout evidence artifacts (example):
cd backend source .venv/bin/activate python scripts/run_soc_ingest.py --campus NB --term-code 2025SU --output-jsonl var/phase4_evidence/run1.jsonl python scripts/run_soc_ingest.py --campus NB --term-code 2025SU --output-jsonl var/phase4_evidence/run2.jsonl
Inspect latest slice status and recent failures from JSONL logs:
cd backend source .venv/bin/activate python scripts/soc_status.py --jsonl var/soc_ingest_runs.jsonl --campus NB --term-code 2025SU --last-n-failures 5
-
POST /v1/plans/{planId}:readyreturns 404:- confirm route is loaded:
curl -s http://localhost:8000/openapi.json | jq -r '.paths | keys[]' | grep ':ready'
- if missing, restart
uvicorn.
- confirm route is loaded:
-
Local DB reset for clean-room testing:
cd backend rm -f gradpath.db source .venv/bin/activate python - <<'PY' from app.db import Base, get_engine Base.metadata.create_all(bind=get_engine()) print("fresh db ready") PY
- Default backend DB is SQLite (
sqlite:///./gradpath.db) for local development. - Relative SQLite URL defaults (
sqlite:///./gradpath.db) are working-directory dependent. - The ingest adapter interface exists (
RegistrarFeedAdapter) with placeholders for:DepartmentCSVAdapterSOCExportAdapterSISAdapter
prisma/schema.prismais included as the canonical relational contract for production PostgreSQL migrations.
These links are design artifacts; implementation authority is defined by each document's status/gate statement.
- Phase 5.2 merge-close note:
docs/phase-5.2-merge-note.md - Phase 5.3 COUNT_MIN decision matrix:
docs/phase-5.3-count-min-decision-matrix.md - Phase 5.3 COUNT_MIN draft spec (gated):
docs/phase-5.3-count-min-spec-draft.md