Commit graph

3 commits

Author SHA1 Message Date
Daniel
12453ba473 fix: a role is not set here while the provider holds it
Some checks failed
Tests / backend (push) Failing after 4s
Tests / frontend (push) Failing after 28s
Tests / e2e (push) Failing after 34s
Two endpoints still set a role locally — PUT /access/{id}/role and PUT
/admin/users/{id}/role. With OIDC_ROLE_CLAIM configured, my sync applies
the person's groups on every sign-in, so a role set in the app lasts
until they next sign in and is then overwritten. That is the worst kind
of setting: it appears to work, holds for an afternoon, and quietly
undoes itself.

Both now answer 409 naming where the switch actually is. With no mapping
configured they behave exactly as before, which is what a site with no
provider needs.

The two existing tests now patch is_configured explicitly rather than
inheriting whatever the container's .env happens to say — a test that
reads differently on two machines is not a test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-13 14:04:16 +02:00
Daniel
532d613393 feat: question folders, per-section notes, and two feedback paths
Four things that share a spine, so they arrive together.

**Folders.** A hand-picked set of questions, and the fourth thing a grant can
name beside exam, discipline and category. Deliberately not `user_collections`
with a sharing flag: a library is a consequence of access — you save what you
can already see — while a folder is a source of it, and one table holding
thousands of private lists beside a handful that confer permission is one
mistake away from a leak. Built from the question manager, granted on /access.
Membership stays with the owner and moderators so a grantee cannot widen their
own reach, and deleting a folder takes its grants with it.

Two live constraints had to be rewritten to accept it: `ck_grant_has_a_dimension`
and `uq_grant_dimensions` both predate `folder_id`, so a folder-only grant
failed the check and two folder grants collided on the unique index.

**Per-question feedback.** The learner's half already existed. What was wrong
was who could read it: any grant at all let an educator list and delete reports
about the whole bank. Reports are now scoped by `question_scope_predicate`, the
same predicate that decides which questions that educator can see, and a reply
thread makes the report a conversation the learner can follow rather than a
form that swallows what they said.

**Per-section notes and article feedback.** Two tables on purpose:
`article_section_notes` is private to whoever wrote it, `article_feedback` goes
to whoever maintains the article. Both point at the section id inside
`articles.sections` rather than at `article_section_index`, whose rows are
dropped on unpublish — a cascade from there would delete a learner's writing
because an educator took an article down for an afternoon. A rename keeps a
note attached; a deleted section leaves it marked orphaned under the heading it
was written on, for its writer alone to remove.

The header's feedback badge covers both, because questions and reading are the
same job to whoever is doing it.

Migration i9f0a1b2c3d4. 556 backend and 572 frontend tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-12 18:37:43 +02:00
Daniel
994733581e feat: access as one tree — branches, libraries, and an honest "everything"
Access lived in three screens over two tables: category grants in the
question manager, media-library grants in the image bank, and nothing at
all for articles. Nobody could see what one person actually held.

/access is one surface over the same tables. A person on the left,
everything they have on the right. A granted branch shows its children
as covered rather than as separately tickable — a checkbox that changes
nothing is where a permissions screen starts lying — and the count of
categories a grant actually reaches is stated, not implied.

"Everything" is the moderator role, and the page says so instead of
inventing a wildcard grant that would silently mean the same thing and
be impossible to audit. While it is on, the branches below are hidden,
because they no longer apply. Nobody can change their own access.

The gap this closes: an educator granted a branch could edit its
questions but not the articles filed under it — articles were
moderator-or-author only. An article is filed under a category, so a
grant over that branch now covers its reading too. No new table: the
inheritance that category grants already had does the work.

Backend 242/242, frontend 284/284.

Also: the split-view test now focuses the link rather than hovering it.
Hover starts a 350ms timer; focus reveals at once, because the component
does not make a keyboard reader wait. That takes the wall clock out of a
test about the split view. Earlier failures were it losing CPU to the
backend suite running alongside it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-11 12:53:56 +02:00