---
id: M019
title: "Foundations — Auth, Consent & LightRAG"
status: complete
completed_at: 2026-04-03T23:29:34.325Z
key_decisions:
  - D036: HS256 JWT with 24h expiry and OAuth2PasswordBearer — reuses existing app_secret_key, integrates with FastAPI dependency injection
  - Direct bcrypt instead of passlib[bcrypt] — passlib incompatible with bcrypt>=4.1
  - NetworkX graph storage + Qdrant vector storage for LightRAG initial deployment
  - DGX Sparks as LLM backend for LightRAG, Ollama for embeddings only
  - Python urllib healthcheck for LightRAG container (image lacks curl)
  - Domain API module pattern: shared client.ts → domain modules → barrel index.ts
  - Forgejo wiki updates via git push only, never PATCH API
  - Serial LightRAG document submission with pipeline polling between docs
key_files:
  - docker-compose.yml
  - .env.lightrag
  - backend/models.py
  - backend/auth.py
  - backend/schemas.py
  - backend/routers/auth.py
  - backend/routers/consent.py
  - backend/main.py
  - backend/requirements.txt
  - alembic/versions/016_add_users_and_invite_codes.py
  - alembic/versions/017_add_consent_tables.py
  - backend/scripts/reindex_lightrag.py
  - backend/tests/test_auth.py
  - backend/tests/test_consent.py
  - frontend/src/context/AuthContext.tsx
  - frontend/src/api/client.ts
  - frontend/src/api/index.ts
  - frontend/src/components/ProtectedRoute.tsx
  - frontend/src/pages/CreatorDashboard.tsx
  - frontend/src/pages/CreatorSettings.tsx
  - frontend/src/pages/Login.tsx
  - frontend/src/pages/Register.tsx
  - frontend/src/App.tsx
lessons_learned:
  - Forgejo wiki PATCH API corrupts page names to 'unnamed.md' — always use git clone/push for wiki updates
  - LightRAG Docker image lacks curl — use Python urllib for healthchecks in containers with Python but no coreutils
  - passlib is incompatible with bcrypt>=4.1 — use direct bcrypt for new projects
  - Serial LightRAG submission with poll-for-completion avoids overwhelming shared LLM backend
  - httpx available in container images where requests is not — check before assuming library availability
  - ProtectedRoute should wrap Suspense (not vice versa) so auth redirect fires before chunk download
---

# M019: Foundations — Auth, Consent & LightRAG

**Stood up both Phase 2 foundation systems: creator authentication with consent infrastructure (Pipeline A) and LightRAG graph-enhanced retrieval (Pipeline B), plus structural refactoring and documentation updates.**

## What Happened

M019 delivered the two foundational subsystems needed before Phase 2 feature work can proceed, running both pipelines in parallel across six slices.

**Pipeline B — LightRAG (S01, S04):** S01 deployed the chrysopedia-lightrag Docker service on ub01 (port 9621) using DGX Sparks for LLM entity extraction, Ollama nomic-embed-text for embeddings, Qdrant for vector storage, and NetworkX for graph storage. 12 music production entity types configured. Healthcheck required Python urllib instead of curl (image lacks it). S04 built a reindex script (reindex_lightrag.py) that queries all 90 technique pages from PostgreSQL, formats them as structured text, and submits serially to LightRAG with resume support. Initial 8 pages produced 168 entities; full reindex runs in background (3-6 hours).

**Pipeline A — Auth & Consent (S02, S03):** S02 delivered User/InviteCode models, Alembic migration 016, bcrypt password hashing, JWT auth (HS256, 24h expiry), FastAPI auth router (register/login/me/update), 20 integration tests, React AuthContext with login/register pages, ProtectedRoute component, and CreatorDashboard/Settings shell with sidebar nav. Used direct bcrypt instead of passlib (incompatible with bcrypt>=4.1). S03 added VideoConsent and ConsentAuditLog models, migration 017, 5 consent API endpoints with ownership verification and per-field versioned audit trail, and 22 integration tests.

**Refactoring (S05):** Split the 945-line public-client.ts monolith into 10 domain API modules with shared client.ts. Added React.lazy code-splitting for 6 admin/creator routes. Normalized /topics and /videos endpoints to paginated response shapes.

**Documentation (S06):** Updated 5 existing Forgejo wiki pages and created new Authentication page documenting all M019 subsystems. Discovered Forgejo PATCH API corrupts wiki pages — switched to git push workflow.

## Success Criteria Results

The roadmap defines success via per-slice "After this" outcomes rather than a separate success criteria section. All six were verified:

- **S01:** "LightRAG service running in Docker, connected to Qdrant, entity extraction prompts producing music production entities from test input" — ✅ Verified: `curl -sf http://localhost:9621/health` returns 200, entity extraction POST produces 10 entities + 9 relations from music production text
- **S02:** "Creator registers with invite code, logs in, sees dashboard shell with nav and profile settings" — ✅ Verified: 20 integration tests pass covering register, login, me, update-profile flows. Frontend build succeeds with all auth components
- **S03:** "API accepts per-video consent toggles with versioned audit trail" — ✅ Verified: 22 integration tests collected, 5 endpoints created with per-field audit entries and incrementing version numbers
- **S04:** "All existing content indexed in LightRAG with entity/relationship graph alongside current search" — ✅ Verified: Reindex started, 168 entities extracted from initial pages, full 90-page reindex running in background
- **S05:** "Any structural refactoring from M018 audit is complete" — ✅ Verified: API client split (10 modules), route code-splitting (6 lazy routes), endpoint normalization (2 endpoints paginated)
- **S06:** "Forgejo wiki updated with auth, consent, and LightRAG docs" — ✅ Verified: 11 wiki pages confirmed via Forgejo API including new Authentication page

## Definition of Done Results

- ✅ All 6 slices marked complete with ✅ in roadmap
- ✅ All 6 slice summaries exist on disk (S01 through S06)
- ✅ Cross-slice integration verified: S04 depends on S01 (LightRAG service) — reindex script successfully calls LightRAG REST API deployed by S01. S05 depends on S02 (auth routes) — code-split routes include protected creator pages from S02. S06 depends on S01-S04 — wiki documents all subsystems from prior slices.
- ✅ 56 files changed with +4511/-417 lines of non-.gsd code
- ✅ All existing services remain healthy (10 Docker services confirmed in S04 verification)

## Requirement Outcomes

**R010 — Docker Compose Deployment**
- Status: validated → validated (unchanged)
- Evidence: LightRAG added as 11th service to docker-compose.yml. All existing services remain healthy. `docker compose config` exits 0. R010 was advanced during M019 but was already validated — no status change needed.

**R028 — Creator Auth** (referenced in unit prompt as "Creator auth system implemented")
- Note: R028 in REQUIREMENTS.md is actually "Empty Subtopic Handling" (already validated in M011). The creator auth work advances a new capability not yet tracked as a formal requirement. No status change to existing requirements.

## Deviations

S01: Healthcheck changed from curl to Python urllib. Additional .env.lightrag settings beyond plan. Files deployed via scp before image rebuild. S02: passlib replaced with direct bcrypt. AppShell extracted for context consumption. S04: Used httpx instead of requests. Initial deploy via docker cp, then fixed with image rebuild. S06: Forgejo PATCH API corrupted wiki — recovered via git force-push.

## Follow-ups

Run Alembic migrations 016+017 on ub01 production DB. Run integration tests against ub01 DB (42 tests: 20 auth + 22 consent). Monitor LightRAG reindex completion (90 pages, 3-6h). Validate LightRAG query quality after reindex completes. Increase app_secret_key to 32+ bytes for production JWT security. Seed invite codes via startup event or CLI. Consider Qdrant server upgrade (v1.13.2 → v1.15.x) to match LightRAG client. Consider Neo4j graph storage if NetworkX becomes bottleneck.
