From 8f16ab671aa4a2c9176a9e29e5d9867d25c85641 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 1 Oct 2026 17:02:11 +0200 Subject: [PATCH] docs(claude): audio upload supersedes the STT deferral for user-supplied audio only The 'no audio-download + STT' bullet is narrowed to YouTube (ADR-007 stands); adds the upload packages, the exact-set isolation test and the pending ffmpeg decision to the build state. Co-Authored-By: Claude Sonnet 5.5 --- CLAUDE.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index cf4a939..02c5454 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -50,8 +50,11 @@ These caused real mistakes that were caught and corrected; the corrections are l - **No global cross-tenant *video* table** — videos stay per-user (data-model). Transcripts ARE shared since ADR-021 (public caption content, keyed by `(provider, provider_video_id)`, non-RLS) so re-analysis never re-fetches; the *videos* half of cross-tenant dedup stays a Future C concern. -- **No audio-download + speech-to-text in the core path** — captions-first (ADR-007). STT is a - deferred, bounded optional component. +- **No YouTube audio-download + speech-to-text in the core path** — captions-first (ADR-007). + That rejection stands. ADR-033 superseded the STT deferral **for user-supplied audio only**: + an authenticated user may upload a recording and get a *private* transcript (own RLS table, + never the shared `transcripts`). It is off by default (`TAPIR_UPLOADS_ENABLED`) and does not + open the door to scraping audio. - **No public SaaS / sign-up / billing / Google OAuth verification at scale** — Future C, deferred behind the Stage 0 gate (ADR-008). @@ -97,7 +100,7 @@ The repo is **green and shipping** — last tag `v0.15.0`. `task check` passes ( - Adapters present under `internal/adapters/`: `youtube` (captions-first `VideoSource`, timedtext/InnerTube acquisition per ADR-010), `summarizer` + `llm` (the copied AI router, now a resilient endpoint chain — local primary → local fallback → external worst-case, - parse-failure-aware, ADR-004 + ADR-022), `store` (Postgres, golang-migrate migrations 001–015), + parse-failure-aware, ADR-004 + ADR-022), `store` (Postgres, golang-migrate migrations 001–017), `secrets` (file-backed `SecretStore`). The brain HTTP sink (ADR-005) is the remaining optional sink. - Stage 1 is open (ADR-012): multi-user with **DB-enforced** isolation — Postgres RLS `FORCE`d @@ -109,6 +112,12 @@ The repo is **green and shipping** — last tag `v0.15.0`. `task check` passes ( (`TestTranscriptsTableIsSharedNotRLS`). The engine reads stored transcripts before any caption fetch (`usecase.resolveTranscript`), so re-analysis — re-summarize, paste-a-URL, onboarding burst — never re-touches YouTube. Per-user summaries/videos stay RLS-scoped. +- Audio upload (ADR-033, migration 017): `internal/uploads` (validation by **probing**, intake, + one-at-a-time in-process worker), `internal/adapters/audio` (ffprobe/ffmpeg), and + `internal/adapters/transcribe` (gateway client + iguana→berget chain). Transcripts are private + in `uploaded_transcripts`; the audio is never retained; chat reuses `chat.Service`. The + isolation test pins the **exact set** of non-RLS tables (`TestRowSecurityOffTablesAreExactlyTheKnownSet`). + The runtime image does not yet contain ffmpeg — that is a pending decision recorded in ADR-033. - `cmd/tapir` subcommands: `list`, `show`, `auth` (interactive host-side OAuth), `run` (batch watch→summarize), `serve` (the HTMX+Templ web reader/writer under `internal/web`, a new transport over the unchanged engine/ports — ADR-003). `tapir env` prints config.