Configure subtitles: env secrets and database settings #198

Closed
opened 2026-08-24 21:28:40 +01:00 by naps62-yolo · 1 comment
Owner

Wire subtitle configuration, split the way DESIGN.md §10 already splits it.

Config or environment — secrets and bootstrap only: OpenSubtitles and
Podnapisi credentials, translator API keys and base URLs, the remote-command
template, the alass and ffmpeg binary paths.

Database, editable at runtime — everything that gets tuned: the wanted
language set, which providers are enabled and in what order, the selected
translation engine, per-provider and per-translator daily allowances, and the
per-call timeout for the remote-command backend.

Expose the database half through the API under the existing settings surface,
readable and writable, so #204 can render it. Never expose the secrets through
the API — not even masked. A key that reaches the database ends up in the
sqlite3 .backup on a timer, which §10 does not intend.

A backend whose cargo feature is not compiled in must not be selectable; the
API reports which engines the running binary actually has.

Depends on: #186

Wire subtitle configuration, split the way DESIGN.md §10 already splits it. **Config or environment** — secrets and bootstrap only: OpenSubtitles and Podnapisi credentials, translator API keys and base URLs, the remote-command template, the `alass` and `ffmpeg` binary paths. **Database, editable at runtime** — everything that gets tuned: the wanted language set, which providers are enabled and in what order, the selected translation engine, per-provider and per-translator daily allowances, and the per-call timeout for the remote-command backend. Expose the database half through the API under the existing settings surface, readable and writable, so #204 can render it. Never expose the secrets through the API — not even masked. A key that reaches the database ends up in the `sqlite3 .backup` on a timer, which §10 does not intend. A backend whose cargo feature is not compiled in must not be selectable; the API reports which engines the running binary actually has. Depends on: #186
naps62-yolo added this to the Subtitles milestone 2026-08-24 21:28:40 +01:00
naps62-yolo added the area/apiphase/9-subtitlestype/featuredifficulty/moderate labels 2026-08-24 21:28:40 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:28 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:28 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:28 +01:00
Author
Owner

Implemented the two halves of subtitle configuration DESIGN.md §15/§10 describes.

Bootstrap (config/env, arr-daemon/src/config.rs): OpenSubtitles.com and Podnapisi credentials, the three HTTP translator backends' API keys and base URLs, the remote-command template, and the alass/ffmpeg binary paths. Secrets (all credentials and API keys) are env-only, following the existing deny_unknown_fields pattern — putting one in the TOML file is a parse error. Base URLs, the command template and the binary paths accept file or env, with alass/ffmpeg defaulting to a bare name resolved through PATH.

Database (migration 0025_subtitle_settings.sql + arr-api/src/subtitle_settings.rs): a single-row subtitle_settings table holding the wanted language set, enabled providers in search order, the selected translation engine, per-provider and per-translator daily budgets, and the remote-command timeout. Exposed read/write at GET/PUT /api/settings/subtitles. A translation_engine selection is validated against arr_subs::compiled_engines() — new pub const ENGINES and pub fn compiled_engines() in arr-subs report which of the four translate-* cargo features this binary actually has compiled in, so an uncompiled backend is a 422, not a silent no-op. The response also carries available_engines for #204 to render. Nothing here reaches secrets: the table and its API surface never carry credentials.

Not wired into arr-daemon's reconcile loop or into actual provider/translator construction — those land with the providers themselves (#187, #188, #191–193), which weren't in scope here.

Branch: subtitles/198-subs-config, based on blitz/subtitles.

just ci passed (fmt, clippy, machete, 503 tests, web-check).

Findings

  • Nothing outside this issue's scope surfaced during implementation. arr-subs's translate-* features are all still empty stubs (as intended per its own module docs), so compiled_engines() returns an empty list until #191/#192/#193 land — at that point the settings API will start accepting those engines with no further change needed here.
Implemented the two halves of subtitle configuration DESIGN.md §15/§10 describes. **Bootstrap (config/env, `arr-daemon/src/config.rs`)**: OpenSubtitles.com and Podnapisi credentials, the three HTTP translator backends' API keys and base URLs, the remote-command template, and the `alass`/`ffmpeg` binary paths. Secrets (all credentials and API keys) are env-only, following the existing `deny_unknown_fields` pattern — putting one in the TOML file is a parse error. Base URLs, the command template and the binary paths accept file or env, with `alass`/`ffmpeg` defaulting to a bare name resolved through `PATH`. **Database (migration `0025_subtitle_settings.sql` + `arr-api/src/subtitle_settings.rs`)**: a single-row `subtitle_settings` table holding the wanted language set, enabled providers in search order, the selected translation engine, per-provider and per-translator daily budgets, and the remote-command timeout. Exposed read/write at `GET`/`PUT /api/settings/subtitles`. A `translation_engine` selection is validated against `arr_subs::compiled_engines()` — new `pub const ENGINES` and `pub fn compiled_engines()` in `arr-subs` report which of the four `translate-*` cargo features this binary actually has compiled in, so an uncompiled backend is a 422, not a silent no-op. The response also carries `available_engines` for #204 to render. Nothing here reaches secrets: the table and its API surface never carry credentials. Not wired into `arr-daemon`'s reconcile loop or into actual provider/translator construction — those land with the providers themselves (#187, #188, #191–193), which weren't in scope here. Branch: `subtitles/198-subs-config`, based on `blitz/subtitles`. `just ci` passed (fmt, clippy, machete, 503 tests, web-check). ## Findings - Nothing outside this issue's scope surfaced during implementation. `arr-subs`'s `translate-*` features are all still empty stubs (as intended per its own module docs), so `compiled_engines()` returns an empty list until #191/#192/#193 land — at that point the settings API will start accepting those engines with no further change needed here.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yolo/arr#198