# Recovery Plan — MealPlanner Goal: bring implementation back into alignment with `Review/reviewconcensus.md`. Stop building forward features until the deferred-risk spikes and the verification matrix pass. ## Phase R1 — Stabilize (parallel-safe) - [ ] R1-A: Verification harness. Add `backend/tests/` with pytest config, a `conftest.py` with a transactional DB fixture, and smoke tests covering: app import, `/health`, `/health/db`, every router's GET list endpoint, Alembic `upgrade head` round-trip on a throwaway DB. Add `.github/workflows/ci.yml` running lint + pytest + frontend `npm run build`. - [ ] R1-B: Auth dependencies on existing routers. Implement an `app.security` module with: (1) `require_admin` dep — bearer token compared to `settings.ADMIN_TOKEN`, applied to ALL `/api/admin/*` routes; (2) `require_session` dep — signed-cookie session (itsdangerous, key = `SECRET_KEY`) for profile/pantry/recipes/meals/shopping-list mutations; reads stay open inside the trusted network. Per-voter approval token flow stays as-is. Update `.env.example` with `ADMIN_TOKEN`. Document the model in `docs/SECURITY.md`. - [ ] R1-C: Make `/api/admin/scrape` async. Convert the endpoint to enqueue a background job (FastAPI `BackgroundTasks` for now; APScheduler later). Endpoint returns 202 + `scrape_log_id`; status polled via `/api/admin/logs/{id}`. ScraperService must open its own DB session inside the task (the request-scoped `db` is gone by then). ## Phase R2 — De-risk deferred work (parallel-safe, must run BEFORE further feature work per review §2.4) - [ ] R2-A: Live-scrape spike. Run `LuckyCaliforniaScraper` against `https://luckysupermarkets.com` once, capture the raw HTML/PNG to `backend/tests/fixtures/lucky_ca/`, write a unit test that parses the captured fixture (no live network in CI). Document selector decisions in `.agent/context.md`. If the page can't be parsed, file the schema impact before going further. - [ ] R2-B: Email + approval round-trip spike. Implement minimal SendGrid sender (`app/services/email.py`), an `app/services/approval.py` that issues per-voter signed tokens (TTL, single-use), the GET confirmation page + POST submit handler (the routes already exist as stubs in `meals.py`), and a CLI script `scripts/send_test_approval.py` that creates a fake meal plan, emails one voter, and verifies the click→POST→DB write path end to end against a sandboxed inbox or `MAIL_BACKEND=console`. Goal: prove the schema (family_member, approval_token tables) survives one full round trip BEFORE building Phase 4/5/9. ## Phase R3 — Resume feature work (sequential, only after R1+R2 green) - [ ] R3-A: Phase 4 Recipe Engine — search, tagging, never-suggest filter. - [ ] R3-B: Phase 9 Meal Planner generation algorithm. - [ ] R3-C: Phase 6 SendGrid templated emails (proposal, reminder, confirmation). - [ ] R3-D: Phase 8 Feedback UI. - [ ] R3-E: APScheduler with `--workers 1` for weekly scrape + plan generation + email send. - [ ] R3-F: Phase 10 image strategy. ## Halt conditions - R2 spikes fail → stop, propose schema/spec change, await approval. - Verification matrix in `Review/reviewconcensus.md §6` not green → no R3 work begins.