Read submitted text and teacher feedback from the homework page

You were right that this data never reaches the browser as an API call.
The legacy front end calls the Feathers API server-side for
submission.comment, submission.grade and submission.gradeComment and
renders them into GET /homework/{taskId}. That Feathers API is not
exposed publicly — /api/v1/* 404s — so the rendered page is the only way
to reach these fields from outside.

core/homework-page.ts parses it, hooked on the data-testid attributes
the project's own e2e tests use rather than incidental markup. The page
authenticates by jwt *cookie*; an Authorization header is ignored and
redirects to the identity provider. Every field is optional and parse
failures return undefined, so a markup change degrades to "not found"
and cannot break get_task. The wording distinguishes the two: absent
feedback is reported as not found, never as none given.

Measured on one course: 4 of 7 graded submissions carry feedback no API
call can return — "vollständig und nachvollziehbar", "Feedback siehe
Zettel", and so on.

This exposed a bug in a shared utility: htmlToText decoded only six
entities, so any named entity passed through raw. German content makes
that routine — "vollständig" would have reached the model verbatim
from boards and task descriptions too, not just here. It now decodes
named, decimal and hex references in one pass, so ä stays
literal instead of decoding twice, and leaves unknown names alone rather
than mangling them.

Also fixes a documented-recovery bug found while restoring the session:
`docker compose restart` does not re-read env_file, so it silently kept
serving the dead token. `up -d` is correct and the docs said the wrong
thing.

78 tests, 38/38 smoke; verified end to end through Claude Code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-13 13:25:35 +02:00
parent ac08e17b48
commit a8badc2fd1
10 changed files with 355 additions and 28 deletions

View File

@@ -129,6 +129,17 @@ not served on this instance (404 across the board), so they are simply
unavailable. Submitted *files* are reachable through files-storage with
`parentType: 'submissions'`.
**Submitted text and written feedback exist only in the rendered web page.**
The legacy front end calls the Feathers API server-side for
`submission.comment`, `submission.grade` and `submission.gradeComment` and
renders them into `GET /homework/{taskId}`. That Feathers API is not exposed
publicly (`/api/v1/*` 404s), so the page is the only way to reach these from
outside. `core/homework-page.ts` parses it, hooked on the `data-testid`
attributes the project's own e2e tests use. Note the page authenticates with the
`jwt` **cookie** — an `Authorization` header is ignored and redirects to the
identity provider. Measured: 4 of 7 graded submissions in one course carried
feedback no API call can return.
**files-storage ignores `parentType` when listing.** Asking for
`.../gradings/{submissionId}` returns the files parented to that id whatever
their type — the records come back saying `parentType: "submissions"`. The path

View File

@@ -70,7 +70,31 @@ boards, cards, files and tasks. **Impossible today at any speed** — the API ha
changed-since filter anywhere. Arguably the most useful item on this list for a
student, and nearly free once the sync job exists.
## 4. Still open
## 4. Remaining gaps, measured
Scanned the instance's 98 GET routes against what the tools cover. Almost
everything student-facing is now covered; what is left, with live checks:
| Area | State on this account |
|---|---|
| `GET /groups/class` | **3 real classes** — the only uncovered endpoint with data |
| `GET /rooms` | empty — the feature is unused here |
| `GET /media-boards/me` | exists, no content |
| `GET /course-info` | 403 — teacher/admin only |
| `GET /alert` | empty |
| `tools`, `oauth2`, `school`, `registrations`, `systems`, `user-login-migrations` | admin/auth plumbing, not student-facing |
Genuinely unavailable, not merely uncovered:
- **Collaborative text editor contents** — the endpoint returns an editor URL,
never the document text.
- **Calendar** — a separate service, absent from the v3 document.
- **Image-only PDFs** — 22 of 255 indexed files are scans with no text layer, so
their contents cannot be searched without OCR.
- **Numeric grades** — the API's `grade` was null on every graded submission
here, so that path stays unverified against real data.
## 5. Still open
- **Video/audio transcription** — this account has 5 MP4s and a WebM that are
currently just "here is a file you cannot read".