Commit Graph

160 Commits

Author SHA1 Message Date
RaymondVerhoef
54137122a7 fix: read Entra claims from id_token + UPN e-mail fallback (#24)
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 38s
On Pull Request to Main / publish (pull_request) Successful in 1m10s
On Pull Request to Main / deploy-dev (pull_request) Successful in 3m7s
First Microsoft logins failed with 400 "email: Cannot be blank": Graph's
/oidc/userinfo endpoint omits the email claim for accounts without a
mail attribute, and team_members requires an e-mail (it also drives the
ENTRA_ADMIN_EMAILS role mapping). Reproduced against a mock Entra with
PocketBase v0.30.4; the user-supplied response body matched the
missing-email fingerprint exactly.

- provider config (reconciler + migration fast-path): userInfoURL is now
  empty, so PocketBase reads the claims from the Entra id_token, which
  always carries preferred_username (UPN) and email when available. The
  #18 reconciler flips the already-deployed Labs provider automatically
  on the next boot — no migration needed.
- pb_hooks/entra_oidc.pb.js: onRecordAuthWithOAuth2Request hook falls
  back to the lowercased UPN when the email claim is absent. Guest UPNs
  (ext_user#EXT#@tenant...) are excluded explicitly — "#" is RFC-valid
  in an e-mail local part, so both a naive regex AND PocketBase's own
  validation would accept them (caught by test V5). The hook also logs
  every failed OAuth2 attempt with the underlying error to the container
  log, which PocketBase otherwise only writes to its internal logs db.

Verified with a switchable mock-Entra matrix (8/8): no-email→UPN e-mail
+ allow-list role, email claim wins when present, no duplicate on
re-login, guest UPN yields a clean validation error, anonymous REST
create stays rejected, both log lines present. Regression: issue-22
matrix 9/9 (baseline pinned to 1a1351d now that #23 is merged), DoD
harness 15/15, npm test 112/112.

Closes #24

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 19:26:25 +02:00
RaymondVerhoef
897b46d4a1 fix: allow OAuth2 sign-up on team_members via @request.context rule (#22)
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 39s
On Pull Request to Main / publish (pull_request) Successful in 1m9s
On Pull Request to Main / deploy-dev (pull_request) Successful in 3m9s
Every first Microsoft login failed with 403 "Only superusers can perform
this action": PocketBase applies the collection createRule to the
automatic record creation during OAuth2 sign-up, and team_members was
created with createRule null (superuser-only) on the wrong assumption
that the OAuth2 flow bypasses it. Since the pre-Azure records were
deliberately dropped, every user was a first login and nobody could get
in. Reproduced locally against a mock OIDC provider (PocketBase v0.30.4).

createRule becomes '@request.context = "oauth2"': record creation is
allowed exclusively from within the OAuth2 flow. Anonymous REST creates
(which could otherwise pre-seed rogue admin profiles) remain rejected —
covered by an explicit test.

- pb_migrations/1781000002_allow_oauth2_signup.js: applies the rule on
  already-migrated environments (Labs); idempotent, guarded, with down
- pb_migrations/1781000000_team_members_to_auth.js: same rule for fresh
  environments (filename unchanged — ledger-safe)
- scripts/setup-pb-collections.mjs: fallback entry mirrored
- docs/auth-spec.md: ADR 009 + files table

Verified with a mock-OIDC matrix (9/9): baseline reproduces the 403 on
the old rule; upgrade path heals (first login 200, role/enrollment/name
defaults, second login no duplicate, anonymous create still rejected);
fresh chain + admin allow-list mapping OK. DoD harness regression 15/15,
npm test 112/112.

Closes #22

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 15:15:54 +02:00
RaymondVerhoef
80f738ddcb fix: valid Caddyfile handle_errors + frontend health-gate in deploys (#20)
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 39s
On Pull Request to Main / publish (pull_request) Successful in 1m7s
On Pull Request to Main / deploy-dev (pull_request) Successful in 3m6s
The learning-platform (Caddy) container crash-looped since this morning's
89d3395: `Content-Type application/json` is not a valid subdirective of
`respond` — a Caddyfile parse error aborts Caddy at startup, taking the
whole app offline for authenticated users while every CI run stayed green.
Verified with caddy v2.10.0: "unrecognized subdirective 'Content-Type',
at Caddyfile:53"; the fixed file validates clean.

CI was blind to this twice over: test.yml swaps the real Caddyfile for
Caddyfile.test in the test image, and the deploy health-gate from #18
only covers PocketBase.

- Caddyfile: set Content-Type via a `header @api` directive before the
  `respond`; behaviour of the JSON error response is unchanged
- infra/*/site/deploy-playbook.yml: frontend health-gate (docker exec
  wget --spider on the container) with log dump + abort on failure, and
  an always-on post-deploy smoke report (compose ps, proxy health,
  team_members auth-methods, PocketBase log tail) for visibility behind
  the auth perimeter

Closes #20

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 14:20:15 +02:00
1a1351ddcb Merge pull request 'Fix #18: migratie-ledger-sync + deploy-proof Azure SSO' (#19) from fix/issue-18-migration-ledger-sso into main
All checks were successful
On Push to Main / test (push) Successful in 32s
On Push to Main / publish (push) Successful in 1m8s
On Push to Main / deploy-dev (push) Successful in 3m0s
Reviewed-on: #19
2026-07-11 11:54:37 +00:00
RaymondVerhoef
d79e69aad2 fix: heal migration-ledger mismatch and make Azure SSO deploy-proof (#18)
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 39s
On Pull Request to Main / publish (pull_request) Successful in 1m9s
On Pull Request to Main / deploy-dev (pull_request) Successful in 3m1s
PocketBase on Labs crash-looped since the SSO deploy (PR #17): mounting
--migrationsDir for the first time replayed the entire migration history
against a database that was provisioned out-of-band (empty _migrations
ledger) and died on 1778948471_created_content.js. On top of that the
team_members->auth migration had its own crash paths and trapped OAuth2
config inside a one-shot, env-dependent migration.

- pb_migrations/1000000000_baseline_ledger_sync.js: detects an
  out-of-band provisioned DB (schema exists, ledger empty) and marks the
  79 historical migrations as applied; no-op on fresh or already-synced DBs
- pb_migrations/1781000000_team_members_to_auth.js: idempotency guard,
  relation->text conversion WITH data preservation (PocketBase diffs
  fields by id, so the column is backed up and restored via SQL), unique
  index rebuild, no silent catches, env only as fast-path
- pb_hooks/entra_oidc.pb.js + pb_hooks/utils.js: reconcile the Entra OIDC
  provider from ENTRA_* env on every bootstrap + cron tick
  (compare-before-save, warn-once); heals environments that migrated
  without secrets and supports secret rotation without re-apply
- pb_hooks/team_members.pb.js: require() pattern — JSVM runs callbacks as
  isolated programs, top-level helpers are not in scope (adopts Leroy's
  fix from the fix-sso branch)
- infra/*/site/deploy-playbook.yml: health-gate after compose up — the
  deploy fails loudly with container logs when PocketBase does not become
  healthy (runs #83-#88 were green while PB crash-looped)
- docker-compose.yml: .env.local is optional again
- docs/auth-spec.md + AI_AGENT.md: ledger/reconciler documentation, ADRs
  006-008, never-rename-applied-migrations warning

Verified locally against PocketBase v0.30.4 with a 7-scenario DoD matrix
(fresh DB +/- env, out-of-band DB with data incl. data preservation,
populated-ledger upgrade, late-secrets healing, re-run guard, hook
provisioning): 15/15 pass. npm test 112/112.

Closes #18

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 11:14:09 +02:00
RaymondVerhoef
89d3395a62 feat: enhance OIDC configuration for Azure login and improve error handling in API responses
All checks were successful
On Push to Main / test (push) Successful in 56s
On Push to Main / publish (push) Successful in 1m24s
On Push to Main / deploy-dev (push) Successful in 2m58s
2026-07-11 10:19:54 +02:00
RaymondVerhoef
d5191073f0 feat: migrate team_members to OIDC-based auth collection and update docker-compose environment configuration
All checks were successful
On Push to Main / test (push) Successful in 57s
On Push to Main / publish (push) Successful in 1m16s
On Push to Main / deploy-dev (push) Successful in 3m0s
2026-06-25 18:05:39 +02:00
fab7a12f7b Merge pull request 'fix/issue-16-azure-login' (#17) from fix/issue-16-azure-login into main
All checks were successful
On Push to Main / test (push) Successful in 30s
On Push to Main / publish (push) Successful in 1m15s
On Push to Main / deploy-dev (push) Successful in 2m54s
Reviewed-on: #17
2026-06-24 14:00:40 +00:00
RaymondVerhoef
fe99381cb7 ci: pass Entra (Azure) secrets to deploy playbooks (#16)
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 55s
On Pull Request to Main / publish (pull_request) Successful in 1m16s
On Pull Request to Main / deploy-dev (pull_request) Successful in 3m2s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 15:57:33 +02:00
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
5f34a6f825 Merge pull request 'Bescherm excluded en locked topics tegen AI-deletion/merge' (#15) from fix/protect-excluded-locked-topics into main
All checks were successful
On Push to Main / test (push) Successful in 36s
On Push to Main / publish (push) Successful in 1m19s
On Push to Main / deploy-dev (push) Successful in 1m45s
Reviewed-on: #15
2026-06-04 06:29:33 +00:00
RaymondVerhoef
9395ea11fe fix: bescherm excluded en locked topics tegen AI-deletion/merge
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 46s
On Pull Request to Main / publish (pull_request) Successful in 1m26s
On Pull Request to Main / deploy-dev (pull_request) Successful in 1m49s
Topics met learning_relevance="exclude" of relevance_locked=true werden
door de Full Analysis stilletjes verwijderd: het model zag exclude als
"irrelevant" en stelde ze voor in actions.deletions / actions.merges,
en analyzeGraph paste die zonder filter toe. Het locked-vlaggetje werd
in full-scope payload niet eens meegestuurd, dus zelfs een nieuwe prompt
kon niet helpen.

Defense-in-depth fixes:

1. Pure graphGuard.filterAiActions strips elke deletion/merge waarvan de
   target excluded of locked is, vóór bulkSave. Merges waarin een
   protected topic juist de keepId is (canonical survivor) blijven door.

2. SYSTEM_PROMPTS.full krijgt een expliciete "PROTECTED TOPICS" sectie
   die exclude en locked topics als nooit-te-verwijderen markeert.

3. relevance_locked wordt nu ook in de full-scope compactTopics payload
   meegestuurd, zodat het model de vlag überhaupt ziet.

4. UI-feedback: GraphControls toont een ShieldCheck banner met aantal
   geblokkeerde acties na de analyze, en het excluded-aantal naast de
   "Show Excluded Nodes" toggle (visible/hidden).

5. 13 nieuwe Vitest cases dekken protected detection en alle drop/keep
   paden van filterAiActions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 08:22:12 +02:00
e310b6d85b Merge pull request 'Knowledge graph table view met sort, group en bulk edit' (#11) from fix/issue-10-knowledge-graph-bulk-changes into main
All checks were successful
On Push to Main / test (push) Successful in 44s
On Push to Main / publish (push) Successful in 1m21s
On Push to Main / deploy-dev (push) Successful in 1m46s
Reviewed-on: #11
2026-06-03 20:09:07 +00:00
2b2921f6ed Merge pull request 'fix: stop warning about merged themes in curriculum schedule' (#13) from fix/issue-12-curriculum-merge-warning into main
Some checks failed
On Push to Main / test (push) Has been cancelled
On Push to Main / publish (push) Has been cancelled
On Push to Main / deploy-dev (push) Has been cancelled
Reviewed-on: #13
2026-06-03 20:08:57 +00:00
RaymondVerhoef
2274de4de7 fix: stop warning about merged themes in curriculum schedule
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 44s
On Pull Request to Main / publish (pull_request) Successful in 1m22s
On Pull Request to Main / deploy-dev (pull_request) Successful in 1m40s
When the KB has more than 26 themes the curriculum AI is required to
merge — so theme labels not appearing as week names are expected, not
warnings. The previous validation surfaced this as a console.warn that
read like an error in the learning station console.

- validateSchedule now only flags missing theme labels when themes_kb <= 26
- adds a real coverage check: warns when learning topics are absent from
  every week (the actual signal we care about)
- adds vitest coverage for both behaviours

Closes #12

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 22:05:34 +02:00
RaymondVerhoef
eb08c4ad96 feat: knowledge graph table view met sort, group en bulk edit
All checks were successful
On Pull Request to Main / test (pull_request) Successful in 48s
On Pull Request to Main / publish (pull_request) Successful in 1m20s
On Pull Request to Main / deploy-dev (pull_request) Successful in 1m52s
Voegt een Graph/Table toggle toe aan de admin Knowledge Graph. De tabel
ondersteunt sorteren per kolom, groeperen op type/relevance/theme/difficulty,
filteren op label, multi-select en bulk-wijzigen van type, learning_relevance
en relevance_locked.

Closes #10

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 17:08:51 +02:00
RaymondVerhoef
218f6e7d64 feat: theme-grouped pickers, theme-session content panel, theme/topic naming
All checks were successful
On Push to Main / test (push) Successful in 42s
On Push to Main / publish (push) Successful in 1m17s
On Push to Main / deploy-dev (push) Successful in 1m56s
- Admin Topic Quizzes (was Quizzes): topics are now grouped under
  collapsible theme headers with per-theme counts. Topics without a
  theme fall into a "No theme" bucket rendered last.
- /topic-test picker: eligible topics grouped by theme so learners can
  scan a curriculum theme and drill its topics on demand.
- Fix admin Theme Content panel (was Learning Content): it was empty
  because content moved to the theme_sessions collection in an earlier
  refactor while the panel still queried the legacy per-topic content
  table. Rewrites ContentManager to read db.getAllThemeSessions and
  render the emit_theme_session schema (title, intro, topic sections,
  connections, key takeaways). Adds db.getAllThemeSessions and
  db.deleteThemeSession.
- Disambiguate theme vs topic across the app: the weekly curriculum
  test is now "Theme Test" (nav, page heading, Dashboard card, button,
  explainer); the on-demand bank test stays "Topic Test". Admin nav
  also clarified to "Theme Content" / "Topic Quizzes".

No schema changes. 85/85 tests still pass, build green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 16:37:50 +02:00
RaymondVerhoef
43a71e2110 feat: on-demand topic tests with shared question bank
All checks were successful
On Push to Main / test (push) Successful in 1m1s
On Push to Main / publish (push) Successful in 1m22s
On Push to Main / deploy-dev (push) Successful in 2m18s
Adds a /topic-test route where learners can take a 5-question test on any
eligible topic at any time. Questions come from a shared, admin-curated
question_bank — no LLM calls on the user path. Points feed the existing
leaderboard with a 10pt/topic/week cap (per ISO week) so the bank can't be
farmed, and repeats from a thin bank yield 0 points.

- New PB collections: question_bank, on_demand_attempts (+ migrations and
  setup-pb-collections.mjs entries).
- db.js: un-deprecates getQuizBank/setQuizBank against question_bank so the
  existing admin TestManager panel becomes functional again; adds
  saveOnDemandAttempt, getOnDemandPointsThisWeek, getUserSeenQuestionIds,
  getAllOnDemandAttempts, isoWeekKey.
- testService.js: getEligibleTopicsForOnDemand, startOnDemandTest (unseen-
  first draw), finishOnDemandTest (cap enforcement + leaderboard upsert).
- New TopicTest page, route, and nav entry; weekly test flow untouched.
- Leaderboard folds on-demand 100%s into perfect-score count and merges
  on-demand attempts into the recent activity feed.
- Spec: docs/on-demand-tests-spec.md with ADRs and extension points.
- Tests: 5 new vitest cases covering eligibility, draw fallback, scoring,
  partial cap, and exhausted cap (85/85 total).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 15:06:43 +02:00
RaymondVerhoef
d1a1cc913c Make Dashboard explainer always accessible via help icon
All checks were successful
On Push to Main / test (push) Successful in 44s
On Push to Main / publish (push) Successful in 1m26s
On Push to Main / deploy-dev (push) Successful in 1m54s
Adds a HelpCircle toggle button in the Dashboard header so users can
re-open the platform explainer after dismissing it. The per-user
dismissed state is preserved as the initial-open default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:43:20 +02:00
RaymondVerhoef
8160242be5 feat: update loading message duration and add caching information; increase timeout for theme session generation
All checks were successful
On Push to Main / test (push) Successful in 43s
On Push to Main / publish (push) Successful in 1m25s
On Push to Main / deploy-dev (push) Successful in 1m56s
2026-05-28 12:03:55 +02:00
RaymondVerhoef
d38c75beb1 feat: theme-level weekly sessions and theme-grouped knowledge library
All checks were successful
On Push to Main / test (push) Successful in 46s
On Push to Main / publish (push) Successful in 1m28s
On Push to Main / deploy-dev (push) Successful in 2m9s
- New theme_sessions + theme_session_completions PocketBase collections
- Generate a detailed per-week theme summary covering every topic in the
  week's curriculum slot via EMIT_THEME_SESSION_TOOL; cache per
  (curriculum_version, week_number)
- Replace Leren.jsx "This Week's Topic" card with "This Week's Theme
  Session" that opens the new ThemeSessionView; per-topic micro-learnings
  remain reachable as optional practice from inside the session
- Group the Knowledge Library by topic.theme, pin the current week's
  theme on top, and badge topics already covered by the active session
- Mark week complete when the user finishes reading the theme session

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:44:10 +02:00
RaymondVerhoef
6a1f5556a9 Add dismissible platform explainer to Dashboard
All checks were successful
On Push to Main / test (push) Successful in 39s
On Push to Main / publish (push) Successful in 1m8s
On Push to Main / deploy-dev (push) Successful in 1m38s
Introduces a per-user, dismissible "How Respellion works" card on the
Dashboard so new users understand the learn/test/leaderboard loop and
where to find R42 and the main navigation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:24:44 +02:00
RaymondVerhoef
ad5be01b70 feat: enhance ConceptExplainer to handle content extraction and display; add normalization for PocketBase records
All checks were successful
On Push to Main / test (push) Successful in 39s
On Push to Main / publish (push) Successful in 1m8s
On Push to Main / deploy-dev (push) Successful in 1m34s
2026-05-27 21:18:17 +02:00
RaymondVerhoef
ce276f0296 feat: enhance KnowledgeGraph with edge styles, node navigation, and AI analysis scopes; update GraphControls and NodeDetailPanel for improved relation management 2026-05-27 21:09:05 +02:00
RaymondVerhoef
47a738fde3 feat: migrate graph snapshot handling to localStorage for improved persistence
All checks were successful
On Push to Main / test (push) Successful in 39s
On Push to Main / publish (push) Successful in 1m7s
On Push to Main / deploy-dev (push) Successful in 1m36s
2026-05-27 20:27:16 +02:00
RaymondVerhoef
9fb22b8090 feat: update getQuizResult to handle no records gracefully by using getList 2026-05-27 20:27:08 +02:00
RaymondVerhoef
6309ae716b feat: implement snapshot restore functionality and enhance graph state management
All checks were successful
On Push to Main / test (push) Successful in 40s
On Push to Main / publish (push) Successful in 1m10s
On Push to Main / deploy-dev (push) Successful in 1m35s
2026-05-27 17:43:18 +02:00
RaymondVerhoef
6ea8860b96 feat: refactor KnowledgeGraph component and add NodeDetailPanel for enhanced node management
Some checks failed
On Push to Main / test (push) Successful in 47s
On Push to Main / publish (push) Failing after 31m8s
On Push to Main / deploy-dev (push) Has been cancelled
2026-05-27 15:18:01 +02:00
RaymondVerhoef
7b6a5b4bf0 feat: add GraphControls component and useGraphData hook for knowledge graph management 2026-05-27 15:05:26 +02:00
RaymondVerhoef
3aa32c383e feat: implement quiz results tracking and caching for user tests
All checks were successful
On Push to Main / test (push) Successful in 47s
On Push to Main / publish (push) Successful in 1m27s
On Push to Main / deploy-dev (push) Successful in 2m7s
2026-05-27 10:05:56 +02:00
RaymondVerhoef
07af2783dc Add comprehensive documentation for key organizational aspects
All checks were successful
On Push to Main / test (push) Successful in 1m33s
On Push to Main / publish (push) Successful in 1m31s
On Push to Main / deploy-dev (push) Successful in 2m3s
- Introduced "Pension Scheme & Benefits" detailing secondary employment benefits and pension specifics.
- Created "Roles & Accountabilities" outlining the Holacracy role structure and responsibilities within Respellion.
- Added "Security" section covering GDPR compliance and workplace safety protocols.
- Established "Spending and Contracting" policy detailing expense categories and submission processes.
- Documented "Who We Are" to define Respellion's identity, services, and operational model under Holacracy and ISO 9001.
2026-05-27 08:24:56 +02:00
RaymondVerhoef
7066f881f9 feat: implement onboarding process and enrollment status tracking for users 2026-05-26 21:33:20 +02:00
RaymondVerhoef
febc9dc7f2 Merge branch 'main' of https://git.labs.respellion.tech/rve/learning-platform
All checks were successful
On Push to Main / test (push) Successful in 41s
On Push to Main / publish (push) Successful in 1m12s
On Push to Main / deploy-dev (push) Successful in 1m39s
2026-05-26 14:23:15 +02:00
RaymondVerhoef
46d2735237 Merge branch 'main' of https://git.labs.respellion.tech/rve/learning-platform
Some checks failed
On Push to Main / test (push) Successful in 41s
On Push to Main / deploy-dev (push) Has been cancelled
On Push to Main / publish (push) Has been cancelled
2026-05-26 14:22:08 +02:00
RaymondVerhoef
daec9cf5b5 Add hot update files for layout and webpack with source maps
- Created new hot update JSON and JS files for app layout and webpack.
- Included eval-source-map for development purposes in the layout hot update.
- Added full hash retrieval function in the webpack hot update.
2026-05-26 14:22:01 +02:00
RaymondVerhoef
9b3d7fde8c fix: end micro-learning sessions explicitly and route to test
Every micro-learning format used to call onComplete implicitly — scroll
to the bottom of the explainer, flip the last flashcard, or pick any
scenario option — which yanked users out of the content before they
were done with it.

Replace the implicit triggers with a Finish session button on each
format. The scenario quiz exposes the button only after an option is
chosen so explanations still get read; the flashcard set exposes a
viewed-cards counter next to it.

The topic-reviewed landing screen now offers Back to Station, Try
another format, and Go to test, so finishing a session leads somewhere
useful instead of dead-ending. Drop the unreachable completion box that
the container was rendering underneath the parent's success screen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 14:20:41 +02:00
RaymondVerhoef
84e7468841 feat: drop reflection_prompt type and flag cached micro-learnings
Remove the reflection_prompt micro-learning format end-to-end: type
config, tool definition, container case, selector tile, and the
ReflectionPrompt component file. The format wasn't pulling its weight as
a learning surface.

Add a Beschikbaar badge to selector tiles whose topic already has a
published micro-learning of that type, so users know which formats open
instantly instead of triggering a fresh generation. Cached records are
fetched once per topic via the new getExistingTypesForTopic helper, and
re-fetched after a generation returns so newly-created formats light up
without a manual refresh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 13:41:20 +02:00
RaymondVerhoef
9ea5d5444d fix: generate weekly quiz in a single batch LLM call
The weekly quiz path made up to six sequential LLM calls (one per topic)
with three retries each, blowing past the 30s budget. Worse, the
quiz_banks collection has been dropped, so getQuizBank/setQuizBank are
no-ops and every generated batch was thrown away — the assembled quiz
ended up empty and surfaced as "Could not assemble enough questions."

Replace the per-topic loop with a single batched call on the fast tier
that emits all five questions in one round-trip, using the review topics
as prompt context instead of separate calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 13:22:44 +02:00
RaymondVerhoef
a653812cd8 feat: implement micro-learning generation service and UI components for interactive topic-based learning
All checks were successful
On Push to Main / test (push) Successful in 32s
On Push to Main / publish (push) Successful in 59s
On Push to Main / deploy-dev (push) Successful in 1m33s
2026-05-25 22:17:26 +02:00
RaymondVerhoef
f16438c1bc feat: implement micro learning generation service with cached LLM content delivery and UI components
All checks were successful
On Push to Main / test (push) Successful in 32s
On Push to Main / publish (push) Successful in 1m2s
On Push to Main / deploy-dev (push) Successful in 1m32s
2026-05-25 22:14:00 +02:00
RaymondVerhoef
7164317908 feat: implement quiz generation service with topic selection, LLM integration, and question bank management 2026-05-25 22:08:18 +02:00
RaymondVerhoef
3c04bab1b9 fix
All checks were successful
On Push to Main / test (push) Successful in 31s
On Push to Main / publish (push) Successful in 58s
On Push to Main / deploy-dev (push) Successful in 1m31s
2026-05-25 21:38:53 +02:00
RaymondVerhoef
80532b6d1b fix 2026-05-25 20:51:11 +02:00
RaymondVerhoef
e4030868b4 fix 2026-05-25 19:46:04 +02:00
RaymondVerhoef
7d1fe83f72 fix 2026-05-25 19:41:20 +02:00
RaymondVerhoef
b24ddc5490 fix
All checks were successful
On Push to Main / test (push) Successful in 31s
On Push to Main / publish (push) Successful in 59s
On Push to Main / deploy-dev (push) Successful in 1m31s
2026-05-25 19:35:52 +02:00
RaymondVerhoef
74e18d2638 fix 2026-05-25 19:23:06 +02:00
RaymondVerhoef
9ba9ec94ad fix 2026-05-25 19:18:24 +02:00
RaymondVerhoef
8291a52ba9 fix test 2026-05-25 19:09:17 +02:00
RaymondVerhoef
6968bebbc2 fix
All checks were successful
On Push to Main / test (push) Successful in 30s
On Push to Main / publish (push) Successful in 1m1s
On Push to Main / deploy-dev (push) Successful in 1m31s
2026-05-25 18:50:53 +02:00