A slimmed-down slice of our mentor↔student matching flow.
When we propose a student to a mentor, the mentor receives an email with Accept and Decline links. Clicking a link records their decision, then we ask a short follow-up (match rating on accept, decline reasons on reject).
Ops has seen proposal records that look accepted but also contain decline reasons. That should never happen.
- Run the project locally.
- Reproduce the inconsistent state.
- Explain what went wrong (briefly).
- Fix it in a way you would be comfortable shipping.
- Add tests that would have caught the issue.
You may change backend and/or frontend. Prefer fitting the existing structure unless a clear refactor improves correctness.
- Backend: Django + Django REST Framework + SQLite
- Frontend: React + Vite
- Auth: none — proposal UUIDs in the URL act as capability tokens (same idea as production signed URLs)
Requires uv.
cd backend
uv sync
uv run python manage.py migrate
uv run python manage.py createsuperuser # optional, for /admin
uv run python manage.py seed_proposal
uv run python manage.py runservercd frontend
npm install
npm run devOpen http://localhost:5173.
| Surface | URL |
|---|---|
| Dev inbox (email stand-in) | http://localhost:5173/ |
Proposals (raw response JSON) |
http://localhost:5173/proposals |
| Django admin | http://localhost:8000/admin/ |
| Accept / decline links | printed by seed_proposal, also in the inbox |
Re-seed anytime:
cd backend && uv run python manage.py seed_proposalcd backend
uv run python manage.py test matchingMentorRequest (student looking for a mentor)
│
└── StudentProposal (sent to one Mentor)
└── response JSON:
value: "accept" | "reject"
reason: { ... } # decline follow-up
match_rating: 0-10 # accept follow-up
recorded_at: ISO datetime
API:
POST /api/review-student/<uuid>/— record accept/rejectPATCH /api/review-student/<uuid>/— record reason / match ratingGET /api/proposal-active/<uuid>/— whether the student is still open + current response valueGET /api/outbox/— fake emails with linksGET /api/proposals/— list proposals for debugging
- Correctness of the state transition
- Clear reasoning about root cause
- Sensible tests
- Changes that match (or thoughtfully improve) the patterns already in the repo
Timebox: aim for a few focused hours, not a rewrite of the whole app.