Commit graph

553 commits

Author SHA1 Message Date
Daniel
d2a06b0fcf feat: modifying a resource is a job, the same as generating one
Modify held the request open for a library search, a PubMed search, a web
search and a restating model call. That is minutes, and a browser gives up
first — Firefox abandons a non-streaming fetch at five minutes, the same
failure generating was moved off the request to fix in ef574edd. The server
carried on and saved the result while the person watched an error, and closing
the tab killed the work outright.

POST /my-resources/:id/refine now records the request and answers 202 with the
job, exactly as /generate does. The writing moved into refineResource(), which
the job runner dispatches to by kind; the job list, the five-second polling,
the restart recovery and the three-in-flight cap are all the work they already
did, unchanged. Ownership is checked again inside refineResource because the
resource can be deleted while the job waits.

The page follows the job instead of the response. Reporting is unchanged — the
unchanged reply, what was seen and what was searched — it is only said from the
job list now, so it still reaches the person who asked for it after a reload.
2026-09-16 23:28:42 +02:00
Daniel
1a491d7367 feat: a deck up to sixty slides is generated, reviewed and modified
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 8s
Twenty was the review ceiling while the form allowed thirty, so a 21-30 slide
deck was written, stored and then silently never reviewed — and modifying one
above twenty was shown only its first twenty pages while the prompt claimed
one image per slide. The three numbers are the schema's own limit now, so a
deck that can be asked for can also be stored, reviewed and edited: the form's
max, both generation clamps and MAX_SLIDES are all 60.

Measured at that size before this change: 45 pages cost 28,796 prompt tokens
and 2.2s to review, a 46-page deck with a fault on page 24 was found and
re-laid correctly, and a 44-slide deck used ~5,900 output tokens of the
16,000 ceiling.
2026-09-16 17:21:03 +02:00
Daniel
ef574eddcb feat: a resource is generated as a job, and DeepSeek writes it without thinking
Some checks failed
Forgejo Docker Build / Build Docker image (push) Blocked by required conditions
Forgejo Docker Build / End-to-end (browser) (push) Blocked by required conditions
Forgejo Docker Build / Root app tests (push) Has been cancelled
Writing a resource held the request open for as long as it took: a library
search, one or two long model calls, a review, then figures. Measured end to
end that was six minutes on 2026-09-16 (00:40 to 00:46:16, resource 53), and
Firefox abandons a request that has said nothing for five — the browser
reported "NetworkError when attempting to fetch resource" while the server
carried on and saved the deck anyway, so a generation that worked looked
like a failure and left no status line.

The request now records what was asked and answers 202; the work runs on the
server as a job; the page lists what is being written, what landed and what
failed, polls while anything is in flight, and reloads the library when one
lands. Several can run at once, a reload loses nothing, and a boot pass marks
jobs stranded by a restart as failed rather than spinning for ever.

The same generation also ran with DeepSeek's thinking on, which is what made
it take minutes rather than seconds: the 16,000-token write spent the whole
budget reasoning and returned an empty reply (completion_tokens=16000,
reasoning_chars=51573), which fired the automatic retry at four times the
budget, and the 2,000-token reviews of that deck starved the same way four
times over. Thinking is now off for the writing, the review of it and a
revision — DeepSeek's own field, sent by the model wrapper. Other clinical
routes are deliberately untouched and keep the provider default.

The review inherits the writer's rule rather than hard-coding it, so a task
that wants reasoning can still ask. Migration 1781500000000_resource-jobs.js
adds user_resource_jobs; the container entrypoint applies it before the app
starts.
2026-09-16 03:53:57 +02:00
Daniel
ac3e6bf3f0 fix: the assistant page finishes loading for non-admin accounts
The download-transcript button is removed for anyone who is not an admin,
but the event binder still called addEventListener on it unguarded. The
throw stopped the binder before the saved-chat list loaded, before the
click handler for opening old chats was registered, and before the send
box was fully wired, so a non-admin saw no chats until New chat, could not
open old ones, and could not chat. The button is now bound only if present.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 19:59:29 +02:00
Daniel
3c04d662f6 feat: the password door is gone; One Sign In is the only way in
POST /api/auth/login answers 410 for everyone, administrators included. The
sign-in screen never draws an email or a password: it is the provider's
button, or a sentence saying sign-in is not configured. The admin CLI no
longer resets passwords. The e2e harness mints its sessions inside the
container instead of signing in with a password.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 04:14:04 +02:00
Daniel
29ff7e435c feat: One Sign In is the only door; the SSO-only switch is gone
With OIDC on, every password route is shut except /api/auth/login for
administrators — the way back in if the provider is down, reached from an
"Administrator sign-in" link. The disable-local-auth setting, the
registration CLI command and the docs that described them are removed;
accounts, roles and invitations live in authentik.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 03:33:53 +02:00
Daniel
4c699b86ef feat: local registration is closed for good, and its on/off switch is gone
Every account comes through One Sign In; an administrator sends an
invitation link from there. The register route answers 410, the
registration-status route and the admin toggle are removed, and the
setting no longer exists in defaults, lockdown lists or seeds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 03:18:57 +02:00
Daniel
f94c2b9f90 revert: the starter chips are three short labels again
The user, seeing four full questions stacked on the empty page: "the former
way… was better". Labels, three of them, as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-15 01:42:09 +02:00
Daniel
6b9587d09f fix: the assistant's empty state keeps its own heading when the starters arrive
The re-render swapped "Pediatric Clinical Assistant" for a different heading
and line the moment the starter questions loaded. Same words as the page now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 23:55:33 +02:00
Daniel
91a35a4b27 fix: the assistant page keeps its layout whatever the initialiser does, and its starters are whole questions
The page class that hides the app sidebar and gives the chat its full height
was added only after the initialiser returned, so any error there left the
app menu and the chat rail side by side with the panels at half height. The
class goes on first now. The starter chips show the question itself rather
than a two-word label, four of them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 23:42:32 +02:00
Daniel
57ba2a268c fix: the format picker shows the format's name only — the slide count is the one length control
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 1m2s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 7s
The picker labels carried each format's typical length ('15–25 cases, three
or four slides each, 60–90 minutes'), which sat under a slide-count field and
read as a second, contradicting number. The label is the name, the hint says
who the format is for, and the brief tells the model that the slide count
asked for is the length and the parts fit into it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 16:07:05 +02:00
Daniel
50f5036118 feat: the assistant reopens the chat you were in, and DeepSeek answers without thinking when told to
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 11s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
A refresh landed on a new empty chat with the conversation a click away in
the list. The open chat's id is remembered per account and reopened on
load; New chat forgets it; a chat deleted elsewhere is quietly gone.

DeepSeek models think by default: measured on ds-deepseek-v4.1-flash, a
three-sentence clinical answer spent 301 reasoning tokens and 2.9 s before
writing and gave the same answer in 0.9 s with thinking off. The assistant's
reasoning effort now comes from CLINICAL_ASSISTANT_REASONING_EFFORT ('low'
as before; 'none' switches thinking off where a model allows it, sent as
DeepSeek's own thinking field through LiteLLM).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 15:24:48 +02:00
Daniel
7ea6c41941 fix: tables scroll sideways on the phone again instead of breaking words to fit the screen
The morning's change forced every table to the screen width below 640px and
let cells break mid-word, so a four-column table read as columns of broken
syllables. A swipe is the better trade; the hint under the table says so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 14:41:40 +02:00
Daniel
cd00fae460 feat: a deck has a format as well as a theme — the shape of the session, whose parts the model may reuse
A theme is a look and the slide vocabulary is what one slide can be; neither
said what a journal club is (PICO, methods, appraisal, bottom line) or that a
board review runs in case-question-answer cycles, so every deck came out as
the same lecture. assets/deck-formats.json holds ten formats distilled from
how departments run each session — grand rounds, journal club, morning
report, M&M, board review, noon conference, simulation debrief, parent
education, QI project, research abstract — each a sequence of parts naming
the layouts it is usually drawn with and whether it may repeat. The brief is
prose after the layout vocabulary; a part is a unit the model reuses as many
times as the material needs, and every slide stays one of the twelve types.
Chosen beside the theme, 'Free' by default, stored on the deck and carried
through modifications.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016fZGJNyDvERbMgS2Uc2msP
2026-09-14 14:13:22 +02:00
Daniel
055c8d121b fix: the last browser confirm() in the resources library uses the app's confirm modal
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 1m4s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 9s
Deleting a generated image asked with the browser's own confirm(), a bare
dialog that looks nothing like the rest of the app. It now goes through
showConfirm like every other confirmation, with the danger styling and a
Delete button.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015j4L7Eu5Jp8gVMPsXdPaZ2
2026-09-14 10:44:31 +02:00
Daniel
394c543a0a fix: answer and take-home tables wrap to the phone screen instead of scrolling sideways
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 17s
The sideways swipe was not reachable on the phone, so wide tables were cut
off. Below 640px the cells break their words and the table takes the full
width; wide tables get taller, never clipped.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 05:40:42 +02:00
Daniel
012a06c107 fix: lazily loaded components stay invisible until their stylesheet and init are ready
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 48s
Forgejo Docker Build / Build Docker image (push) Successful in 12s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
The fragment's markup was inserted before its own stylesheet resolved, so a
first visit to the assistant tab flashed unstyled content. The pending
marker app.js already sets now also hides the markup; the Loading status
line is all that shows until the tab reports ready.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 05:11:26 +02:00
Daniel
8142dd4ab1 fix: the assistant no longer drags the view to the end while an answer streams
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
The reader can start at the top of a long answer and scroll at their own
pace; the per-token and on-completion jumps to the bottom are gone, which
also stops a finger on the screen fighting the auto-scroll.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-14 04:26:38 +02:00
Daniel
684a8920e9 fix: a deck's illustration stays out of the page (status line only, tile under Images); a streaming table head is held back, never shown as pipes
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 8s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 21:11:36 +02:00
Daniel
4de76dbfd9 feat: a share link pasted into an open tab is handled like a fresh arrival
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 19:04:48 +02:00
Daniel
fa5ed6c2b4 feat: sharing is by link only — the share-with-everyone switch and route are gone
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 57s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 19:00:53 +02:00
Daniel
1beb2d33b0 fix: room between the starter questions and the box; a half-arrived bold run streams as bold, not asterisks
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 53s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:56:41 +02:00
Daniel
bbcc824b65 fix: the share panel stays open (no library redraw behind it); the Nextcloud upload button says what it is
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 54s
Forgejo Docker Build / Build Docker image (push) Successful in 14s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:54:30 +02:00
Daniel
4127e2d101 feat: the starter-prompt pool is built once and regenerated from the admin button only, on gpt-4.1-mini by default; the question box sits two-thirds down before a chat and at the bottom during one
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:38:11 +02:00
Daniel
4119788815 feat: Settings links to the PedsHub account page in a new tab
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 48s
Forgejo Docker Build / Build Docker image (push) Successful in 20s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 18:10:18 +02:00
Daniel
9c86c56968 fix: a failed recording keeps its tab and the retry adds the words after the last word; Settings drops the session list; FAQ says what sign out does
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 8s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:56:32 +02:00
Daniel
cba2a312e1 feat: the preview is a viewer — one page at a time, arrows, keys, swipe, a PDF tab and downloads; the theme leaves the list row
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 51s
Forgejo Docker Build / Build Docker image (push) Successful in 11s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:49:22 +02:00
Daniel
b277ce4b10 fix: the assistant asks for context around each excerpt again — read from the stored chunks, 1400 characters by default
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:41:01 +02:00
Daniel
3e10b6faa7 feat: sign out ends the PedsHub session too (RP-initiated logout); the assistant sends the stored excerpt only
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 11s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:35:35 +02:00
Daniel
a6c2cb1080 perf: context expansion is off by default — the stored excerpt already carries the page, its tables and figure captions
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 55s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:16:28 +02:00
Daniel
cd2ee9192a fix: the silent attempt calls the real start path, /api/auth/oidc
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 58s
Forgejo Docker Build / Build Docker image (push) Successful in 15s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:06:27 +02:00
Daniel
18f7651362 feat: signed in at PedsHub means signed in here — one silent prompt=none attempt before the sign-in page, hash kept
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 51s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 7s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 17:04:25 +02:00
Daniel
e23d35a570 docs: library indexing is scheduled and on request; panel note matches
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 9s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 5s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 16:34:16 +02:00
Daniel
34c495b5d8 fix: the indexer address and token have their own Save; the card's Save & Close keeps its five keys
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 8s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 16:05:46 +02:00
Daniel
93426ac089 feat: the library index reconciles when the admin asks — status and Run indexing now in the Clinical Assistant card
Some checks failed
Forgejo Docker Build / Root app tests (push) Failing after 58s
Forgejo Docker Build / Build Docker image (push) Has been skipped
Forgejo Docker Build / End-to-end (browser) (push) Has been skipped
The clinical-assist indexer no longer polls Nextcloud every five minutes; it
scans once at start and then on POST /api/v1/vector-sync/scan with a bearer
token. The admin panel shows what it reports and carries the button; the
address and token are settings (or the environment). The button stays usable
under lockdown, the fields do not.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 16:02:35 +02:00
Daniel
c7864f763e feat: sharing is by link — follow it, accept, and it is in your resources
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 56s
Forgejo Docker Build / Build Docker image (push) Successful in 10s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 12s
The author presses "Copy a share link" and sends it however they like.
Whoever follows it (app.pedshub.com/#share=<token>) is signed in first if
need be — the token survives the trip through the SSO — then shown what it
is and who from, and adds it with one press. Only the token's hash is
stored; a link lasts 30 days and can be withdrawn; accepting twice is
harmless; the owner following their own link changes nothing. Sharing by
email is gone: nobody is looked up by address. "Everyone signed in" stays
as a switch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 15:20:35 +02:00
Daniel
eb9fdfef35 feat: share a resource with people on this site — by email, or with everyone
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 48s
Forgejo Docker Build / Build Docker image (push) Successful in 6s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 7s
A resource was private with no way out but the author's own Nextcloud.
Share opens reading — open, preview, download — to one person at a time by
exact email (no account is ever listed) or to everyone signed in with one
switch; what others share appears in your library marked "Shared by …".
Writing never travels: modify, re-skin, delete and the share list stay the
author's, every write still filtered on user_id, and the read routes go
through one reader rule. Rows follow the resource and the person.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 15:13:28 +02:00
Daniel
e92b72d406 feat: preview a resource, or a theme's sample deck, as pages — without downloading
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 8s
A PowerPoint or Word file cannot be shown in a browser and a phone has
nowhere to open one. Preview renders the resource the way its download
would be built, turns it into one PNG per page (Gotenberg to PDF, pdftoppm
to pages), and shows the pages in an overlay that scrolls and pinch-zooms
like anything else. Rendered once per version — updated_at and theme are in
the key — and served from disk afterwards. The theme picker's sample deck
has the same Preview beside its download.

Every presentation now shows the theme picker in the library, since
markdown slides take a theme too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 14:48:45 +02:00
Daniel
6e779e61ff fix: citation chips that sit together read in ascending order
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 56s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 6s
[1] early in an answer and then "[2][1]" later showed "2 1". A run of
adjacent chips is now sorted by what it displays — a core rule after inline
parsing — so it reads "1 2". Text between two clusters keeps them apart,
every chip still points at its own source, and the numbering itself is
unchanged: only the order within a run moves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 14:42:51 +02:00
Daniel
d893452d9a feat: the site's Nextcloud is filled in, not typed — the settings page is one button
Some checks failed
Forgejo Docker Build / End-to-end (browser) (push) Blocked by required conditions
Forgejo Docker Build / Root app tests (push) Successful in 55s
Forgejo Docker Build / Build Docker image (push) Has been cancelled
nextcloud.url (or NEXTCLOUD_URL) names the site's Nextcloud. With it set,
the address field is hidden and the page reads "Sign in with Nextcloud",
with the app-password route underneath for whoever needs it; both routes
use the default when no address is given. Without it, nothing changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 14:33:25 +02:00
Daniel
28877ba0c4 feat: My Resources takes Details — what to cover, at length, folded away until needed
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Successful in 17s
Forgejo Docker Build / End-to-end (browser) (push) Successful in 6s
Topic is one line and Instructions say how; neither is the place for a list
of twelve topics or a case to build around. Details is: optional,
collapsed by default, up to 12,000 characters, quoted into the prompt as the
author's own account of what the resource must cover — material, not
commands, in both the deck and the markdown shapes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 14:30:09 +02:00
Daniel
aebb820216 chore: the app is PedsHub Clinical Tools — title, login card, menu, manifest, FAQ, docs
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 1m3s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 7s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 14:23:32 +02:00
Daniel
57ffd80c74 docs: the FAQ says how things work now — SSO sign-in, citations, voices, My Resources
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 55s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 8s
Signing in is a code from the PedsHub sign-in page, not a password; the
citation chips are numbered by first appearance; voices come from every
model the administrator added; the Learning Hub section — a feature that no
longer exists — is replaced by My Resources: decks, themes with sample
downloads, Modify, and the download formats. The two-factor and
change-password entries go with the passwords they described.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 14:03:22 +02:00
Daniel
e306c3ce28 feat: a link into a tab — app.pedshub.com/#resources opens My Resources
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 8s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 10s
The app has no pages and is not getting any. Another site can still send
someone straight to a tab by naming it in the hash: it is read once at
load, stored where sign-in looks for the last tab, and dropped from the
URL, so it survives the round trip through the SSO and does not stick to
the address bar. #resources, #deck and #decks all mean My Resources.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 13:51:36 +02:00
Daniel
f95f9c586d fix: the wait shows its steps and nothing else — the title line repeated the step in progress
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 8s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 06:18:48 +02:00
Daniel
a1842ca919 fix: the scribe keeps its own mark; it is "PedsHub Scribe", as the SSO names it
Some checks failed
Forgejo Docker Build / Build Docker image (push) Blocked by required conditions
Forgejo Docker Build / End-to-end (browser) (push) Blocked by required conditions
Forgejo Docker Build / Root app tests (push) Has been cancelled
Two apps, two logos after all: the stethoscope stays here, the hospital
stays on the quiz. What the last change got right stays too — the login
card without a heading over a single button, the icon as an image in the
card and the menu — and the name now matches the SSO tile.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 06:17:32 +02:00
Daniel
6183509cf8 feat: one PedsHub mark for both apps — login card, menu, favicon, manifest
Some checks failed
Forgejo Docker Build / End-to-end (browser) (push) Blocked by required conditions
Forgejo Docker Build / Root app tests (push) Successful in 50s
Forgejo Docker Build / Build Docker image (push) Has been cancelled
The scribe wore a stethoscope and called itself PedAI while the quiz app
was PedsHub; one product, two identities. Both now use the PedsHub icon.
The login card shows the icon, the name and the tagline and loses the
"Sign In" heading that sat above a single button; the menu bar shows the
icon at 20px beside the name, since the full wordmark did not fit there.
Favicons and the PWA icons are rendered from the same SVG.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 06:15:37 +02:00
Daniel
e58aa1b996 refactor: sign-in codes and registration invitations leave; the SSO has both
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 49s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 6s
Sign-in is email → code at sso.pedshub.com, and new accounts come from an
invitation link minted there, so the app's own code emails and invite codes
recorded a path nobody can take. Gone: the login-code routes and their rate
limiters, the invite admin API and card, the invite field on the register
form, the "email me a code / use my password" choice on the sign-in screen
(an email now leads straight to the password), both utility modules, and
the invite-only setting. A migration drops login_codes and
registration_invites.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 06:11:00 +02:00
Daniel
d94dc0e357 feat: the wait is a list of steps, ticked by the stream's own events
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 56s
Forgejo Docker Build / Build Docker image (push) Successful in 18s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 17s
One line of changing text is now a list the reader can follow: Analyzing
the question → Searching the clinical library → Found 7 sources → Writing
the answer, plus any step the server reports (looking at an image, drawing
one, completing a cut-off reply). Steps are added when the stream says work
began and ticked when it says it ended, so the list is a record of the real
work, not an animation on a timer; nothing delays the answer.

The one hand-off the server cannot signal — retrieval runs before the stream
opens — is done by the stylesheet, not a JS timer, so the autosave debounce
keeps its clock to itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 05:48:14 +02:00
Daniel
fa9970458f fix: the export's last table column wraps again, and citations-off strips every marker form
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 51s
Forgejo Docker Build / Build Docker image (push) Successful in 19s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 11s
The export styles pinned the last column of every table to one unbreakable
line (width:1%; white-space:nowrap) — right for a numbers column, wrong for a
two-column clinical table whose second column is the whole finding: the
table grew to the width of its longest sentence and iOS then inflated the
text in those cells, so the "Finding" column read in a bigger font than the
"Feature" column. The pin goes, and the sheet opts out of text inflation.

With citations switched off the answer is still grounded in the retrieved
sources; only the markers are removed. The stripper now also removes the
escaped \[1, 2\] form and [src] placeholders, which used to survive as text.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-13 05:42:32 +02:00