pdf-quiz-generator/backend/app/services
Daniel 831cb01650 feat: an article follows a topic, rather than copying it once
"Questions filed there later are not added" was the honest description of what
the previous commit built, and it was the wrong thing to build. "The Cardiology
article covers the Cardiology questions" is a standing statement about the
material, not a snapshot of who happened to be filed where on the afternoon
somebody pressed a button — and a copy stops being true the first time a
question is added, silently, with nothing on any screen to say so.

So the claim is now stored, and it is what writes the links:

* `question_article_links` is still the **only** table anything reads. No count,
  no QBank button, no mirror panel on a question, no AI Mode boost learns a
  second question to ask.
* `article_topic_claims` records *why* some of those rows exist, and is the one
  place that makes them — when the claim is staked, when a question is filed
  into the category (single, bulk, or on create), and on a half-hourly sweep
  that catches whatever bypassed both.

A link made this way is an ordinary row and can still be deleted by hand; a
sweep puts it back, which is the honest consequence of a standing claim.
Dropping the claim is how you stop it, and the panel now lists what an article
follows with two ways out — stop following and keep the links, or stop and
remove them.

Migration k1b2c3d4e5f6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-12 19:57:06 +02:00
..
__init__.py Initial commit: PDF Quiz Generator app 2026-03-30 20:04:53 +00:00
ai_mode_service.py fix: a greeting is not a query, so nothing is searched for one 2026-09-12 19:03:30 +02:00
ai_service.py fix: WebP figures, the openai SDK removed, and a voice a site can add to 2026-09-12 17:13:05 +02:00
article_service.py feat: delete an article, and a trash for the ones that were published 2026-09-12 19:31:28 +02:00
article_writer.py feat: search that looks at what an article says 2026-09-12 15:57:42 +02:00
attempt_expiry.py feat: right after a tip is its own slice 2026-09-12 01:51:03 +02:00
captcha.py feat: Cap replaces hCaptcha, self-hosted beside the app 2026-09-12 06:14:14 +02:00
certificate_service.py Add certificate generation, SCORM support, QTI export/import 2026-04-11 01:30:09 +02:00
clinical_library.py feat: short / long / clinical, and stop broad topics retrieving index lines 2026-09-10 18:21:21 +02:00
draft_questions.py refactor: remove per-question sharing 2026-09-12 08:42:51 +02:00
email_service.py feat: sign in with a code sent by email 2026-09-12 17:29:28 +02:00
embedding_service.py feat: a session prepared for you, and a model that can see when the one on the job cannot 2026-09-12 15:46:04 +02:00
exam_blueprint.py feat: study plans built to the board's content outline 2026-09-11 21:40:17 +02:00
extraction_modes.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00
file_intake.py fix: an upload is what its bytes say, not what its name claims 2026-09-12 19:05:12 +02:00
invites.py feat: the player is a box; sharing and sign-up are the administrator's 2026-09-11 19:17:35 +02:00
knowledge_groups.py feat: an organ system is a fact about a topic, not about a keyword 2026-09-12 04:32:25 +02:00
login_codes.py feat: sign in with a code sent by email 2026-09-12 17:29:28 +02:00
pdf_service.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00
prepared_session.py feat: a session prepared for you, and a model that can see when the one on the job cannot 2026-09-12 15:46:04 +02:00
question_figures.py fix: choosing is answering; figures say only what an educator wrote 2026-09-12 00:19:35 +02:00
quiz_builder.py feat: a session prepared for you, and a model that can see when the one on the job cannot 2026-09-12 15:46:04 +02:00
quiz_service.py Junction table for shared questions; verification blocking; semantic bank search; bug fixes 2026-04-01 00:55:13 +02:00
rerank_service.py feat: rerank what a learner is shown, with Cohere through the proxy 2026-09-12 18:23:06 +02:00
search_service.py feat: rerank what a learner is shown, with Cohere through the proxy 2026-09-12 18:23:06 +02:00
site_settings.py fix: WebP figures, the openai SDK removed, and a voice a site can add to 2026-09-12 17:13:05 +02:00
storage_service.py feat: serve uploads through storage, and move all 3,852 files to MinIO 2026-09-10 10:23:34 +02:00
study_plan_context.py feat: an exam that runs out is a result; delete and reset go all the way down 2026-09-11 04:47:11 +02:00
thumbnails.py fix: figures a browser will actually draw, and two requests that could hang 2026-09-12 16:29:45 +02:00
topic_claims.py feat: an article follows a topic, rather than copying it once 2026-09-12 19:57:06 +02:00
vector_service.py fix: gateway-agnostic URL handling for TTS and embeddings, docs cleanup 2026-04-19 02:17:35 +02:00
vision_service.py fix: WebP figures, the openai SDK removed, and a voice a site can add to 2026-09-12 17:13:05 +02:00