Files
learning-platform/CLAUDE.md
RaymondVerhoef 3af105bccd feat: Azure (Entra ID) login as user login (#16)
Replaces the client-side PIN login with real authentication against Azure
Entra ID via PocketBase's built-in OAuth2 (OIDC) flow. Every Azure user is
auto-provisioned as a team_member on first login.

- pb_migrations: team_members becomes a PocketBase auth collection (OIDC
  provider configured from env); all collections require @request.auth.id
- pb_hooks: provisioning of role (ENTRA_ADMIN_EMAILS allow-list) and
  enrollment_status, with admin-role re-sync on every login
- frontend: "Sign in with Microsoft" login, pb.authStore-based session,
  TeamManager manages roster/roles (no PIN/manual create)
- infra: Entra env wiring + pb_hooks mount for dev (Labs) and prod
- src/lib/azureAuth.js + tests for the canonical role/allow-list logic
- docs/auth-spec.md

Knowledge base, generated tests and micro-learnings are left untouched.
Existing PIN users are dropped (no migration required, per sign-off).

Closes #16

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:41:08 +02:00

6.3 KiB

CLAUDE.md

What this is

The Respellion Learning Platform — an internal AI-powered learning app that keeps employees current with the company's evolving knowledge base. Employees follow a perpetual 26-week curriculum, each working through weekly learning sessions and tests. An AI assistant called R42 is available on every screen. Admins upload source documents that Claude extracts into a knowledge graph.

This is a single-page React application (Vite) backed by PocketBase. There is no separate backend — all logic runs in the browser and talks directly to PocketBase collections and (via a proxy) the Anthropic API.


Tech stack

Layer Technology
Frontend React 19 + Vite 8, React Router 7
Styling Vanilla CSS (CSS custom properties) + Tailwind v4 utilities mapped to those variables
Animation Framer Motion
Icons Lucide React
Graph viz D3.js (admin knowledge graph only)
Backend / DB / auth PocketBase (self-hosted, SQLite)
AI Anthropic Claude via a reverse-proxy (Caddy in prod, Vite proxy in dev)
Retrieval (RAG) Local TF-IDF over the knowledge graph — no Qdrant, no embeddings API
Validation Zod on all AI tool output
Infra Docker + Caddy; Ansible playbooks under infra/

Claude models (src/lib/llm.js, by tier):

  • fastclaude-haiku-4-5-20251001 (R42 chat, quiz batches, flashcards)
  • standardclaude-sonnet-4-6 (extraction, article/slides/infographic, curriculum)
  • reasoningclaude-opus-4-7

Admins can override any tier's model string from the Settings tab (persisted in localStorage as admin:model:{tier}).


Repository structure

repo/
├── CLAUDE.md              ← you are here
├── AI_AGENT.md            ← detailed architecture/patterns guide — read this
├── README.md              ← quickstart
├── PROTECTED.md           ← files you must not modify
├── docs/                  ← spec files (describe the system as built)
├── src/                   ← THE APPLICATION (React/Vite)
│   ├── pages/             ← route screens (Dashboard, Leren, Testen, Leaderboard, Login, Onboarding, Admin/)
│   ├── components/        ← ui primitives, admin panels, chat (R42), micro_learning
│   ├── lib/               ← services: llm, db, extractionPipeline, learningService,
│   │                        microLearningService, testService, curriculumService, retrieval, pb
│   ├── hooks/             ← React hooks
│   └── store/             ← AppContext (global state)
├── pb_migrations/         ← PocketBase schema migrations (JS, applied by the PB binary)
├── scripts/               ← setup-pb-collections.mjs (local collection bootstrap)
├── public/                ← static assets, fonts
├── infra/                 ← Ansible deploy playbooks (development / production)
├── Caddyfile, Dockerfile, docker-compose.yml  ← deployment (frozen)
└── stylesheet.css         ← authoritative visual reference (frozen)

Note on /app: the top-level app/ directory is abandoned scaffolding from the original Next.js + Qdrant design that was never shipped. It is not wired into package.json, Vite, or Docker. Ignore it. The real app is /src.


Absolute constraints

  1. Never modify any file listed in PROTECTED.md.
  2. Never modify stylesheet.css — it is the authoritative visual reference. Use the CSS variables in src/index.css and the Tailwind classes mapped to them.
  3. Treat the deployment files as frozen unless explicitly asked: Dockerfile, Caddyfile, docker-compose.yml, infra/, .github/workflows/.
  4. Never delete files without explicit confirmation.
  5. Never re-enable PocketBase auto-cancellation — pb.autoCancellation(false) in src/lib/pb.js is deliberate (see AI_AGENT.md §2).
  6. There is no podcast learning type. It was removed. Do not re-add it.
  7. Ask before acting when scope is unclear.

Code conventions

  • All src/lib/db.js functions are async — always await them.
  • All Claude tool output is validated through Zod (src/lib/llmSchemas.js) before use. Never reach /api/anthropic directly — go through callLLM in src/lib/llm.js.
  • No client-side API key. The Anthropic key is injected server-side by the proxy.
  • Reuse the UI primitives in src/components/ui/ (Card, Button, Tag, Input).
  • Mobile-first — the employee app targets 375px width and scales up.
  • No hardcoded hex colors; use the design-system CSS variables / Tailwind tokens.

Running locally

npm install
./pocketbase.exe serve          # or the muchobien/pocketbase Docker image
node scripts/setup-pb-collections.mjs   # first run only — bootstraps collections
npm run dev                     # Vite dev server (proxies /api/anthropic)

Set ANTHROPIC_API_KEY in the environment so the Vite proxy can inject it (vite.config.js). PocketBase migrations in pb_migrations/ apply automatically when the PB binary starts.

Command Purpose
npm run dev Vite dev server
npm run build Production build to dist/
npm test Vitest unit tests
npm run lint ESLint

Documentation map

  • AI_AGENT.md — detailed patterns, gotchas, and subsystem guide. Start here for any real work.
  • docs/architecture.md — system design and data flows
  • docs/data-model.md — every PocketBase collection and field
  • docs/ingestion-spec.md — upload → knowledge-graph extraction
  • docs/generation-spec.md — learning content + micro-learning generation
  • docs/curriculum-spec.md — 26-week per-user curriculum engine
  • docs/r42-spec.md — the R42 chatbot
  • docs/auth-spec.md — Azure (Entra ID) login: OIDC via PocketBase, provisioning, roles
  • docs/frontend-spec.md — screens, routing, onboarding
  • docs/gamification-spec.md — points, badges, leaderboard
  • micro-learning-spec.md — micro-learning learner experience

When you are uncertain

Check the spec files in docs/ and AI_AGENT.md first. If the spec does not cover it, read the actual code in src/ — it is the source of truth. Flag gaps explicitly rather than assuming. Do not treat the abandoned /app scaffolding or legacy-style references in old comments as guidance.