# MUSE-AUTH-CLI Decision Record Status: **Draft** — taken over in this checkout 2026-10-07 per user choice. Only explicit user acceptance moves this document (or any decision) to Final. Handoff note: a prior grill session settled D1–D11 and U1 and reportedly marked its own record Final, but that file lives in another checkout (absent here; this repo has no MUSE-AUTH-CLI.md, PI-AGENT-AUTH.md, OPERATORS.md, or agy-auth-switch). D1–D11 details below are CARRIED, not verified — their full text needs a paste or peer handoff before this record can go Final. ## Goal Define the `muse-auth` CLI: per-profile credential switcher (`~/.config/muse/accounts//auth.json`), tailnet push/pull of profiles between nodes, and a session spend logger — without stranding live sessions (the 2026-10-07 fleet-wide 400 outage was a mid-stream credential swap). ## Non-goals (proposed) - Implementation of `muse-auth` (needs a separate explicit request). - `agy-auth-switch` validation (Track B, separate lane; PI-AGENT-AUTH.md is Final). - OPERATORS.md amendment for agent-invokable keys (U2 follow-on, own delta). ## Settled (from prior-session transcript, unverified here) ### U1. Allowance reset period — SETTLED (calendar month) Profile token allowances reset on the 1st of each month UTC, matching standard billing cycles (not a rolling 30-day window). ### D10/D11. Agent-invokable key handling — SETTLED in principle, amendment pending Decisions exist; codification as an OPERATORS.md amendment delta is the U2 follow-on and is UNRESOLVED. ### D1–D11 (remaining detail) — CARRIED, text unavailable Full decision text was settled in the prior session but is not present in this checkout. CARRIED as-is; paste or peer handoff required to verify. This record cannot go Final until they are quoted or re-settled here. ## Scope contract (ACCEPTED 2026-10-07; user chose "accept the scope as written") - Artifact boundary: IN — this decision record only. OUT — runtime code, tests, OPERATORS.md amendment, Track B validation. - Done means: (1) push/pull file-set decision settled; (2) live-session guard decision settled; (3) D1–D11 text verified or re-settled; (4) user explicitly accepts this record as Final. - Later stages (implementation, U2 amendment) each return for their own interview; accepting this record never approves them. - "Go"/"do it all" authorize only the boundary above. ## Settled Decisions (New) ### P1. Push/pull transfer file set — SETTLED (Credentials + Metadata) Transfer `auth.json` (cookies, tokens, session identity) and `metadata.json` (plan tier, spend watermarks, profile label). Ephemeral caches, runtime logs, and local locks are omitted from transfer. (`profile.json` in the earlier grill options was shorthand for this file and is superseded; confirmed 2026-10-07.) ### P2. Live-session switch guard — SETTLED (Block with Force Override) Refuse to switch credentials if active `muse-bin` or worker processes are detected holding the old profile identity. Operators must either terminate active processes first or explicitly pass `--force` to override, preventing mid-stream 400 outages caused by stale in-memory tokens. (Confirmed in this interview 2026-10-07.) ## Pending None. (All pending architectural decisions P1 and P2 are settled). ## Session credential isolation (P3 — BUILT 2026-10-07, user-ordered) Each muse session runs with an isolated config dir `/tmp/muse-session-/muse`: symlinks to `~/.config/muse/*` except `auth.json`, which is replaced with the bound profile's credentials; refreshed tokens sync back to the profile on session exit/save. Implications (unresolved): this largely obsoletes P2's block (switching stops disturbing live sessions; the guard becomes a backstop for legacy non-isolated sessions). Open risks: token sync-back races when two sessions share a profile (solved: newest-wins by mtime), sessions killed -9 never syncing (solved: reap-by-scan, no exit hook), symlink fragility (accepted: rebuilt per launch). Implementation: bin/muse_session_bind.py (`launch` builds the dir and execs with XDG_CONFIG_HOME; `save`/`reap` sync back; `status` lists). Key integration choice: exec, not supervise, so panes keep their muse-bin identity and watcher coverage is untouched. Tests: tests/test_muse_session_bind.py (13). Follow-ups for the owning lanes: wire `box runtime launch` / resume-pool `resume` through the binder, and arm a reap timer once the profile store (P1) exists.