govulncheck reported GO-2026-5970 as called via golang.org/x/text v0.31.0
(reached through the DB driver). Bump to v0.39.0; x/sync moves to v0.21.0
as its required minimum. govulncheck ./...: 0 vulnerabilities.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A 503 from the issuer's discovery endpoint made `serve` exit and the pod
restart. New now retries discovery 5 times (2+4+8+16 s back-off, ~30 s)
before failing as before; a cancelled ctx ends the back-off at once.
WithDiscoveryRetry lets tests shrink the schedule.
Closes#59
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Low findings of the PR #62 re-review: the WithTimeout test's comment claimed cancellation
travels on the context but only the language was asserted (the WithoutCancel mutant survived),
and PlanFor('') and PlanFor(unknown) were untested.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The label moves from the done fragment to the page header, so queued, transcribing and
failed recordings show it too. The scenario no longer implies a general engine exists. Found
by the PR #62 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
PlanFor(lang) on the Ensemble and a LanguagePlanner the worker prefers: the page lists
the other engine (and the fallback if configured), not the base engine, the comparison and
the decisions as coming. Found by the PR #62 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found by the PR #62 review: the message could be replaced with 'x' and the test stayed green.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The wrapper sits in front of both local engines; a fresh context there would send an auto
upload as language=sv and un-cancel the job, and no test noticed. Found by the PR #62 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The read is capped at 17 bytes and no valid language is longer than 4, so the parse
refuses anything the length check would; the mutant that removed it survived.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Form field (Swedish preselected, Other = auto) read before the file part and refused
before anything is spooled if outside the closed set; stored on the row (migration 021,
CHECK constraint, default sv for history); carried on the Job and the worker's context;
shown on the status page. Feature scenarios and the coverage map are updated, and
ADR-033/034 amended.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The other engine transcribes alone, then the cloud fallback if it fails and the job is
still live. A cancelled job never reaches the fallback (mutation-checked).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The request used to hard-code language=sv for every upload, so a recording in another
language was decoded as Swedish. The language now comes from the context; no language in
the context is still sv.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
sv and auto; an empty form value is sv, anything else is refused. LanguageFrom defaults to
sv so a caller that sets nothing behaves as before.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Skipping 'by', 'reconciled' and '+' as words everywhere let an alias with one of those
names pass as local. The two-engine shape is now split on its own separators and each alias
judged whole; a reconciler that is not local is pinned too. Hardening suggested by the third
PR #58 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The previous version kept only words containing '/' and dropped the rest, so a bare
TAPIR_TRANSCRIBE_MODEL alias in the composite produced a false 'all local' result. Found
by the PR #58 re-review; red tests for a bare alias, an alias with a space and a split
'berget / x' first.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The tracker comment said 'never a stalled job'; each transition can wait up to the timeout.
The delete refusal is judged at the moment of the attempt. Found by the PR #58 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The earlier entry posted to an app without uploads, where the route does not exist, and
stayed green with the route removed. This one seeds a finished row and goes red without the
gate. Found by the PR #58 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Only the 8-byte override was exercised; >= vs >, a huge default and a non-positive option
all stayed green. Also says why the error-body read ignores its error. Found by the PR #58
review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The worker fake ignored the heartbeat time, so the store-boundary half of the app-clock
fix had no assertion. Found by the PR #58 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Every earlier test passed WithSaveTimeout; the worker passes nothing, so the 5 s default
was the only production value and a flip to 0, 1ms or 1h stayed green. Found by the PR #58
review; each flip is now red.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The two-engine path writes '<base> + <alt>, reconciled by <model>'. IsLocalModel is a
single-alias match, so the composite was 'not local' and the note claimed the audio left
the homelab, naming a local host as the provider. Found by the PR #58 review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>