Agent Handoff Notes
These notes orient future agents working on this repository—especially ongoing multi-tenancy hardening—so changes stay consistent and low-disruption.
Quickstart
- Branch: work (current).
- Tests: run
pytest -qbefore committing; add focused tests for tenancy helpers when changing scoping logic. - App entry:
wsgi.py; Flask app factory inapp/__init__.py. - Maintenance mode: toggle via env flags (see
templates/maintenance.html) to present the downtime page during risky migrations.
Database Migrations - CRITICAL FOR AGENTS
⚠️ ALWAYS follow this workflow when creating migrations to prevent multiple heads errors:
Before Creating ANY Migration
-
ALWAYS sync with the latest code first:
git fetch origin main git merge origin/main -
Verify there is exactly ONE migration head:
flask db heads # MUST show exactly 1 headIf you see multiple heads, STOP and create a merge migration first:
flask db merge heads -m "Merge migration heads" -
Check the current migration revision:
flask db current # Note this revision ID
Creating a Migration
-
Make your model changes in
app/models/ -
Create the migration:
flask db migrate -m "Clear description of change" -
IMMEDIATELY verify the new migration:
- Open the generated file in
migrations/versions/ - Verify
down_revisionmatches whatflask db currentshowed - If it doesn't match, DELETE the migration and restart the workflow
- Open the generated file in
-
Test the migration:
flask db upgrade # Apply it flask db downgrade # Roll it back flask db upgrade # Apply it again -
Verify single head after creation:
flask db heads # MUST still show exactly 1 head # OR use the quick check script: bash scripts/check-migration-heads.sh
Quick Check Script
Before pushing ANY PR that includes migrations, run:
bash scripts/check-migration-heads.sh
This script will immediately tell you if there are multiple heads and provide fix instructions.
Why This Matters
The repository has experienced recurring "multiple heads" errors during deployment because agents created migrations without syncing first. Each time this happens:
- Deployment blocks with errors
- Manual intervention required on production
- Risk of data inconsistencies
The pre-push hook can't catch this when working through the web interface, so agents MUST follow this workflow manually.
Multi-Tenancy Snapshot
- Join codes are the source of truth for class/period isolation. Students pick a join code from their claimed seats, and all student-facing balances/transactions are scoped by that join code (see
get_current_class_contextinapp/routes/student.pyand theTransaction.join_codecomment inapp/models.py). - Teacher ownership lives in the link table. Student access for admins is enforced through the
student_teachersassociation; class-period scope is handled separately throughjoin_codeandclass_memberships(seeget_admin_student_queryinapp/auth.py). - Scoped query helpers like
get_admin_student_queryandget_student_for_adminare centralized inapp/auth.py. Admin routes inapp/routes/admin.pyand system-admin tools inapp/routes/system_admin.pyrely on these—prefer them over directStudent.querycalls. - Student/admin sessions continue to store
admin_idandis_system_adminfor authorization checks; student sessions also persist the selectedcurrent_join_codefor per-class context. - Maintenance page and middleware exist to keep downtime user-friendly during migrations.
High-Priority Follow-Ups
- Database hardening
- Consider enforcing non-null
join_codefor new ledger/attendance records after backfill verification. - Continue reducing legacy teacher-global assumptions in comments, fixtures, and helper signatures.
- Define safe ON DELETE behavior for admins where ownership and class membership rows both exist.
- Consider enforcing non-null
- Code audit
- Replace any residual direct
Student.query.getusage outside helpers. - Remove reliance on teacher-global scoping assumptions in any remaining legacy paths.
- Replace any residual direct
- Testing gaps
- Add shared-student coverage for payroll and attendance flows.
- Add DB-level uniqueness test once constraint exists.
- Operational docs
- Write a runbook for the NOT NULL migration (pre/post checks, maintenance toggle, backfill verification).
PII/Privacy
- Keep PII minimal (current design uses non-PII identifiers and encrypted first names). Avoid adding new PII fields; prefer hashes or initials.
Coding Conventions
- Prefer scoped helpers over ad-hoc filters for tenant access.
- Keep try/except blocks off import statements (per repo guidance).
- Update documentation (
../DEVELOPMENT.md) when milestone status changes.
Checklist Before PR
- Tests pass locally (
pytest -q). - Migrations reviewed for safety (lock impact, backfill steps, maintenance banner plan).
- UI changes include screenshots when visually meaningful (if browser tool available).
- Final summary cites files and commands per system instructions.
PR Template
Please use the following template when creating a PR
<!-- Start of Document -->Description
<!-- Provide a brief description of the changes in this PR -->Type of Change
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- Documentation update
- Refactoring (no functional changes)
- Performance improvement
- Other (please describe):
Testing
<!-- Describe the tests you ran and how to reproduce them -->- Tested locally
- All existing tests pass
- Added new tests for new functionality
Database Migration Checklist
<!-- If this PR includes a database migration, complete the following checklist -->Does this PR include a database migration? [ ] Yes / [ ] No
If Yes, confirm:
- Synced with
mainbranch immediately before runningflask db migrate - Migration file reviewed and verified correct
down_revision - Tested
flask db upgradesuccessfully - Tested
flask db downgradesuccessfully - Confirmed only ONE migration head exists (pre-push hook should verify this)
- Migration has a descriptive message/filename
- Breaking changes or data migrations documented in PR description
Migration file location:
<!-- e.g., migrations/versions/abc123_add_user_email.py -->Checklist
- My code follows the project's style guidelines
- I have performed a self-review of my own code
- I have commented my code where necessary, particularly in hard-to-understand areas
- I have updated the documentation accordingly
- My changes generate no new warnings or errors
- I have read and followed the contributing guidelines
Related Issues
<!-- Link any related issues here -->Closes #