diff --git a/README.md b/README.md index d33b62b..b560216 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,12 @@ base ("brain") is one optional sink, not the reason Tapir exists. Written in Go. ## Status -Pre-code. The repository currently holds the **guardrail documentation** — vision, decisions, -architecture, data model, and behavior specs — committed before implementation so the design -intent is version-controlled and the build has something to be checked against. +**Stage-0 demo slice built.** The engine, ports, domain, and adapters (`llm`, `summarizer`, +captions-first `youtube`, Postgres `store`) are implemented and green, with the `tapir` +CLI (`auth` / `run` / `list` / `show`) wiring the end-to-end loop for a single user. The +remaining work to *open* the Stage-0 clock is the live run on real subscriptions — see +"Running the Stage-0 demo" below. The guardrail docs (vision, decisions, architecture, data +model, behavior specs) remain the source of intent. ## Read these first (the guardrails) @@ -65,6 +68,67 @@ URI matches `TAPIR_OAUTH_REDIRECT_ADDR`. The summarizer model (`TAPIR_SUMMARIZER_MODEL`, default `koala/phi4-mini`) is overridable; pick the final alias when the gateway is reachable (see `docs/homelab-integration.md`). +### Headless on koala + +koala has no browser and no interactive `op` session, so the two interactive +edges are handled without changing any code: + +**Secrets via an `op` service account** (no `op signin`). Create a 1Password +service account with read on the `HomeLab` vault, export its token, and keep one +op-style env file `tapir.env` — secret values as `op://` refs, the rest as +literals — then prefix every command with `op run`: + +```sh +export OP_SERVICE_ACCOUNT_TOKEN=ops_... # the service-account token + +cat > tapir.env <<'EOF' +TAPIR_USER_ID= +TAPIR_GATEWAY_URL=http://koala:30401/v1 +TAPIR_GATEWAY_KEY=op://HomeLab/LITELLM_MASTER_KEY/password +TAPIR_SUMMARIZER_MODEL=koala/phi4-mini +TAPIR_DB_DSN=op://HomeLab/TAPIR_DB_DSN/password +TAPIR_YT_CLIENT_ID=op://HomeLab/TAPIR_YT_OAUTH/client_id +TAPIR_YT_CLIENT_SECRET=op://HomeLab/TAPIR_YT_OAUTH/client_secret +TAPIR_YT_TOKEN_REF=youtube/refresh_token +TAPIR_SECRETS_FILE=/home/mathias/.config/tapir/secrets.json +TAPIR_OAUTH_REDIRECT_ADDR=localhost:8080 +EOF +chmod 600 tapir.env +``` + +(Create the `TAPIR_DB_DSN` and `TAPIR_YT_OAUTH` items in the `HomeLab` vault +first; `LITELLM_MASTER_KEY` already exists. `sk-local-123` is stale.) + +**`tapir auth` over an SSH tunnel.** The auth command binds a listener on +`localhost:8080` *on koala* and prints the consent URL to stdout — it never +opens a browser. Forward that port to your laptop, run auth, and approve in your +laptop's browser; the redirect returns through the tunnel: + +```sh +# from your laptop: +ssh -L 8080:localhost:8080 koala +# now on koala (one-time): +op run --env-file tapir.env -- ./bin/tapir auth +# → copy the printed URL into your laptop browser, approve; token is stored. +``` + +The Google OAuth client must be a **Desktop/Web** type with authorized redirect +`http://localhost:8080/callback` (matching `TAPIR_OAUTH_REDIRECT_ADDR`), the +YouTube Data API enabled, and your account added as a test user. + +**Everything else is already non-interactive** — once the token is stored, run +headless: + +```sh +op run --env-file tapir.env -- ./bin/tapir run # detect → summarize → deliver +op run --env-file tapir.env -- ./bin/tapir list # read summaries back +op run --env-file tapir.env -- ./bin/tapir show +``` + +Postgres (`postgres18`) is ClusterIP-only; from the koala host reach it with +`kubectl port-forward -n databases svc/postgres18 5432:5432` and point +`TAPIR_DB_DSN` at `localhost:5432` (migrations apply on first connect). + ## Conventions Reuses homelab conventions: Go, Dex for identity, ESO + 1Password for secrets, Postgres for