# Tapir — Stage-0 demo configuration. Copy to .env, fill in, and: # set -a && . ./.env && set +a # No secrets are committed. At demo time, source secret values from op # (e.g. `op run -- ./bin/tapir run`) rather than pasting them here. # # Required-by-command: # tapir auth : TAPIR_YT_CLIENT_ID, TAPIR_YT_CLIENT_SECRET, TAPIR_YT_TOKEN_REF, TAPIR_SECRETS_FILE # tapir run : the above + TAPIR_USER_ID, TAPIR_GATEWAY_URL, TAPIR_SUMMARIZER_MODEL, TAPIR_DB_DSN # --- identity ------------------------------------------------------------- # The Tapir user this run operates as. MUST be a UUID (keys the user_id columns). TAPIR_USER_ID= # --- local AI gateway (LiteLLM) ------------------------------------------- # OpenAI-compatible base URL (".../v1"). Default targets the koala NodePort. TAPIR_GATEWAY_URL=http://koala:30401/v1 # Gateway key — sk-local-123 is STALE (401s); resolve LITELLM_MASTER_KEY from op. TAPIR_GATEWAY_KEY= # Summarization model alias, host/name form. Overridable; pick the final alias # when the gateway is reachable. Thinking models (qwen3/deepseek-r1) are viable — # the llm client now sends max_tokens=8192. TAPIR_SUMMARIZER_MODEL=koala/phi4-mini # Bounds a single completion call (Go duration). Generous for slow thinking models. TAPIR_SUMMARIZER_TIMEOUT=5m # --- Postgres store ------------------------------------------------------- # DSN for the store sink; migrations apply on first connect. At demo time: # kubectl port-forward the postgres18 service, create a tapir db/role, point here. TAPIR_DB_DSN=postgres://tapir:PASSWORD@localhost:5432/tapir?sslmode=disable # --- YouTube OAuth (your registered client) ------------------------------- # From Google Cloud console; YouTube Data API enabled; your account a test user. # The authorized redirect URI must match TAPIR_OAUTH_REDIRECT_ADDR + /callback. TAPIR_YT_CLIENT_ID= TAPIR_YT_CLIENT_SECRET= # Opaque SecretStore reference the refresh token is stored/resolved under. TAPIR_YT_TOKEN_REF=youtube/refresh_token # host:port the `auth` command binds for the local OAuth redirect listener. TAPIR_OAUTH_REDIRECT_ADDR=localhost:8080 # --- secret store (Stage-0 stand-in for op/ESO) --------------------------- # Path to the 0600 file-backed SecretStore. Defaults to # /tapir/secrets.json if unset. TAPIR_SECRETS_FILE= # --- run loop ------------------------------------------------------------- # Empty/0 = single pass. Set (e.g. 15m) to poll on that cadence. TAPIR_POLL_INTERVAL= # How long to wait before re-fetching a transcript that returned HTTP 429 # (rate_limited). Inside the window the video is skipped without hitting the # caption endpoint; after it expires the video is retried. 0 = always retry. # Go duration; default 1h. TAPIR_FETCH_BACKOFF= # Recency bound for AUTO summarization: in automatic mode only videos published # within this window of now are summarized; older ones are discovered + listed # but wait for a manual "Summarize" (so a back-catalogue doesn't self-inflict # 429s). An explicit request bypasses it. Go duration; default 168h (~7d). # 0 = no bound (summarize every unseen video). TAPIR_AUTO_SUMMARIZE_WINDOW= # Minimum interval between outbound caption fetches across the WHOLE process — # the shared per-egress-IP rate gate (ADR-014). Scheduler runners and the web # "Summarize" click-path serialise through it so they cannot collectively trip # 429s. Go duration; default 2s. 0 = unlimited (dev/tests). TAPIR_FETCH_RATE= # --- scheduled discovery (tapir serve, ADR-018) --------------------------- # When > 0, `serve` runs in-process discovery for ALL users on this cadence # (e.g. 2h): one runner pass per user per tick, run-once-on-startup then ticked. # Empty/0 = disabled (dev/tests never auto-fetch). SINGLE-REPLICA assumption — # >1 replica double-runs discovery. Go duration. TAPIR_DISCOVERY_INTERVAL= # --- invitations (tapir invite) ------------------------------------------- # Public base URL used to build the invite link `tapir invite ` prints. # Default https://tapir.d-ma.be; no trailing slash needed. TAPIR_PUBLIC_URL=