diff --git a/cmd/tapir/main.go b/cmd/tapir/main.go index 95de372..4df1cb7 100644 --- a/cmd/tapir/main.go +++ b/cmd/tapir/main.go @@ -207,6 +207,27 @@ func cmdServe(ctx context.Context, log *slog.Logger) error { log.Info("web chat enabled (stored-transcript only)", "models", chatModels(cfg)) } + // Audio upload -> private transcript (ADR-033). Off unless TAPIR_UPLOADS_ENABLED: + // the image must carry ffmpeg first. The worker is IN-PROCESS and one job at a + // time, so it inherits the single-replica assumption below (its queue is + // process-local); it stops with the same ctx as the server. + intake, worker, err := buildUploads(ctx, cfg, st, log) + if err != nil { + return err + } + if intake != nil { + app.Uploads = intake + app.UploadLimits = uploadLimits(cfg) + go worker.Run(ctx) + log.Info("audio upload enabled", "model", cfg.TranscribeModel, "fallback", cfg.TranscribeFallbackModel, + "max_mb", cfg.UploadMaxBytes>>20, "max_minutes", int(cfg.UploadMaxDuration.Minutes())) + log.Warn("audio upload assumes a SINGLE replica: the transcription queue is process-local (ADR-033, ADR-018)") + if cfg.TranscribeFallbackModel != "" { + log.Warn("audio upload fallback is a CLOUD endpoint: if the primary fails, private audio leaves the homelab", + "fallback", cfg.TranscribeFallbackModel) + } + } + // User onboarding is handled by the IdP (Authentik invite flow), not Tapir — // the Dex local-password provisioning path was removed (ADR-019). An // authenticated subject with no Tapir user is routed to /register.