docs(adr): second review -- the note instead of a refusal, room before spooling, the callable chat model, and the image that was actually built (ADR-035 decision 8)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 17:22:41 +02:00
co-authored by Claude Sonnet 5.5
parent fe6c0fae3a
commit b46a0dd0c9
+21 -8
View File
@@ -1735,17 +1735,30 @@ wording while only `content` is merged.
`network`, `error`), never its text, which can hold a provider's response body, the spool path or `network`, `error`), never its text, which can hold a provider's response body, the spool path or
a word from the transcript (`internal/errkind`). The stored reconcile reason and an engine's a word from the transcript (`internal/errkind`). The stored reconcile reason and an engine's
failure reason are kinds; the page no longer shows provider text. failure reason are kinds; the page no longer shows provider text.
- **Every local engine call has its own deadline** (`TAPIR_TRANSCRIBE_ENGINE_TIMEOUT`, default 25 - **Every local engine call has its own deadline** (`TAPIR_TRANSCRIBE_ENGINE_TIMEOUT`, default 20
minutes), so a wedged engine fails while the job lives and the fallback can run; the job's own minutes: two wedged engines in sequence then leave 20 of the job's 60 minutes for a fallback),
so a wedged engine fails while the job lives and the fallback can run; the job's own
deadline or a cancel still never reaches the cloud. deadline or a cancel still never reaches the cloud.
- **The duration limit is checked against what is converted**, not the file's header: ffmpeg is - **The duration limit is checked against what is converted**, not the file's header: ffmpeg is
capped at the limit plus a minute, a longer result fails the job (`audio_too_long`), and a result capped at the limit plus a minute, a longer result fails the job (`audio_too_long`), and a result
under 80% of the claimed length and more than two minutes short fails it under 80% of the claimed length and more than two minutes short is **transcribed and noted** on
(`audio_incomplete`) instead of returning a partial transcript with no warning. the audio step ("the audio is 20 min long; the file claimed 1 h 19 min"), not refused. The second
- **The queue is bounded**, 20 waiting in total and 3 per user; a full queue is a 429 with a typed adversarial review showed a complete variable-bitrate MP3 whose header over-estimated its length
reason, never a stuck row or a server error. by 4x was wrongly refused by the first version of this check; a note keeps a truncated file
- **Bad input is a 4xx**: a non-UUID id is a 404, a malformed multipart header is a 400 whose text is visible without turning away real recordings.
not logged, and a title or file name with control bytes or invalid UTF-8 is cleaned, not a 500. - **The queue is bounded**, 20 waiting in total and 3 per user, and its room is checked before the
upload is spooled (not after 200 MB and an ffprobe run); a full queue is a 429 with a typed reason,
never a stuck row or a server error.
- **The configured upload chat model is callable.** It is added to the shared chat service's model
list when uploads are on and it is local, because the service re-maps a model it does not offer
(a valid `iguana/gemma4-31b` was being silently swapped for `koala/phi4-mini`).
- **Bad input is a 4xx**: a non-UUID id is a 404, a malformed or cut-off multipart body is a 400
whose text is not logged, and a title with control bytes, bidirectional controls or invalid UTF-8 is
cleaned (emoji joiners, Swedish letters and variation selectors are kept), not a 500.
- **The image was built and inspected** (buildah on koala, 2026-10-02): the first build FAILED
(`tar: xz: Cannot exec`, the golang image has no xz); fixed, rebuilt at 180 MB, ffmpeg and ffprobe
run as `nonroot` in distroless. CI does not build the image on a pull request
(`if: github.event_name != 'pull_request'`), so the first CI build of it is the merge to main.
Not done, filed as follow-ups: a vendored ffmpeg tarball, CSRF cookie review, ffprobe CPU and Not done, filed as follow-ups: a vendored ffmpeg tarball, CSRF cookie review, ffprobe CPU and
stream-count limits, mov external references, `alive_at` clock skew, a hung database blocking the stream-count limits, mov external references, `alive_at` clock skew, a hung database blocking the
tracker, an unbounded gateway response body, a user-facing notice for a recording that is partial but tracker, an unbounded gateway response body, a user-facing notice for a recording that is partial but