- Implement lazy MongoDB client initialization in backend/db/mongo_client.py. - Create Gunicorn configuration to ensure MongoDB client is initialized per worker. - Refactor database access layer to support MongoDB with a new MongoLockedTable adapter. - Add migration script to transfer existing TinyDB data to MongoDB, preserving idempotency. - Update tracking event handling to ensure deterministic ordering with a monotonic sequence. - Modify tests to use mongomock for MongoDB integration and ensure existing tests pass. - Add integration test script to run tests against a local MongoDB Docker container. - Document environment variables and migration process in specs/feat-database-migration.md.
5.0 KiB
5.0 KiB
AGENTS.md
Family chore/reward manager. Flask + TinyDB backend (backend/), Vue 3 + TypeScript frontend (frontend/). Real-time updates over SSE.
Commands
Backend (run from backend/)
- Activate venv:
source .venv/bin/activate - Dev server:
python -m flask run --host=0.0.0.0 --port=5000(entry:main.py) - Required env vars:
SECRET_KEY,REFRESH_TOKEN_EXPIRY_DAYS,DIGEST_TOKEN_SECRET,VAPID_PUBLIC_KEY,VAPID_PRIVATE_KEY— Flask raisesRuntimeErroron boot if any are missing - Optional persistence switch:
USE_MONGODB(true|false). Whentrue, setMONGO_URIand optionallyMONGO_DB_NAME. Defaultfalsekeeps TinyDB. - Optional:
DB_ENV/DATA_ENV(prod|test|e2e) — picksdata/vstest_data/dir (seeconfig/paths.py). For MongoDB these also select the default database name (chore_db,chore_db_test,chore_db_e2e) unlessMONGO_DB_NAMEis set. - Tests:
pytest tests/—conftest.pyforcesDB_ENV=test,USE_MONGODB=true,MONGO_URI=mongomock, and sets dummy secrets. Single test:pytest tests/test_routine_api.py::test_name - Python imports assume
backend/is onsys.path(set byconftest.py/flask runcwd). Run pytest frombackend/. - Create admin user:
python scripts/create_admin.py(admin role cannot be set via signup)
Frontend (run from frontend/)
- Dev:
npm run dev(Vite, https://localhost:5173) - Lint:
npm run lint - Type-check:
npm run type-check - Unit tests:
npm run test:unit(Vitest). Single:npx vitest run path/to/file.spec.ts - E2E:
npx playwright test— config auto-starts bothnpm run devand the Flask backend withDB_ENV=e2e DATA_ENV=e2e USE_MONGODB=true MONGO_URI=mongomock. Tests live ine2e/.frontend/.env.testcontains the example MongoDB config. - E2E buckets are Playwright projects (see
playwright.config.ts) targeting directories undere2e/mode_parent/
Architecture
API routing — the /api prefix
- Frontend nginx (and Vite dev proxy) strips
/apibefore forwarding. Backend routes must NOT include/api. Backend defines@app.route('/user'), frontend calls/api/user. auth_apiis the only blueprint registered with a prefix:url_prefix='/auth'inmain.py:67.- API errors return
{ error, code }(codes inbackend/api/error_codes.py). Frontend extracts them viaparseErrorResponse(res)insrc/common/api.ts.
Models — strict 1:1 parity
- Python
@dataclasses inbackend/models/. TypeScript interfaces infrontend/src/common/models.ts. Any model change requires updating both. - Persistence is TinyDB by default, or MongoDB when
USE_MONGODB=true. Both are accessed through theLockedTable/MongoLockedTablewrappers inbackend/db/db.py. Operate on model instances withfrom_dict()/to_dict()— never raw dicts. - MongoDB client initialization is lazy (
backend/db/mongo_client.py).backend/gunicorn.conf.pyprovides thepost_forkhook required for multi-worker Gunicorn deployments;backend/Dockerfileloads it with-c gunicorn.conf.py. - Migration script:
cd backend && python -m scripts/migrate_to_mongodb [--dry-run]. It reads TinyDB JSON files and writes them to MongoDB idempotently, backing up the originals to<db_dir>/backups/<timestamp>/.
SSE event bus — mandatory for every mutation
- Every backend mutation (add/edit/delete/trigger) must call
send_event_for_current_userfromapi/utils.py. Event types inbackend/events/types/are mirrored infrontend/src/common/backendEvents.ts. - Frontend: register listeners in
onMounted, clean up inonUnmounted. SSE endpoint is/events.
Background schedulers (started in main.py at boot)
start_deletion_scheduler— runs hourly, deletes accounts marked for deletion after thresholdstart_digest_scheduler— email digestsstart_state_expiry_scheduler— expires stale statestart_chore_expiry_notification_scheduler— chore expiry notifications
Frontend conventions
- SFC file order:
<template>→<script>→<style scoped>. TypeScript only in<script>. All styles must bescoped. - Colors/spacing: use only
:rootCSS variables fromcolors.css. No hardcoded hex/px for themed properties. - Layout shells:
ParentLayoutfor admin/management,ChildLayoutfor child dashboard/focus. - Images: models carry
image_id; frontend resolves toimage_urlfor rendering.
Testing gotchas
- E2E tests use pre-authenticated sessions via
storageStateinplaywright.config.ts— do not navigate to/auth/login. ImportE2E_EMAIL/E2E_PASSWORDfrome2e/e2e-constants.ts. - E2E buckets that mutate shared state (default tasks, delete-account, create-child) use isolated users. Preserve this pattern when adding new buckets.
- Backend tests:
conftest.pysetsDB_ENV=test+ dummy secrets. Test DB lands intest_data/db/, never touches productiondata/.
Feature specs
Specs live in .github/specs/. If a spec has a checklist, all items must be marked done before the feature is complete.