From 83db928c41179873c7702f400b28e520003968cd Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 27 Jul 2026 09:22:49 -0700 Subject: [PATCH] feat: export DEVA_AUTH_TAG for in-container account identity - generate_auth_tag() ran only inside the container-name rewrite branch; hoist it and export the result as DEVA_AUTH_TAG on every run - credentials files carry no identity (tokens rotate), so the runner is the only party that knows which account a container talks as - first consumer: claude-code-statusline account chip + per-account cache scoping (the shared ~/.claude/statusline caches bleed across accounts when containers overlay different credentials on one home) - container naming and deva.auth_tag label unchanged Close #496 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 10 ++++++++++ DEV-LOGS.md | 5 +++++ deva.sh | 13 ++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca6916c..687c770 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- `DEVA_AUTH_TAG` container env (#496): the auth tag deva already computes + for container naming (`auth-default` | `auth-file-` | + `api-key-` | `env`) is now exported into every container. + Credentials files carry no identity (tokens rotate), so the tag is the + only stable in-container handle for WHICH account a session runs as. + First consumer: claude-code-statusline — account chip plus per-account + cache scoping, so multi-account `--auth-with` runs stop sharing one + quota/profile cache under the shared `~/.claude`. + ## [0.17.0] - 2026-07-27 ### Added diff --git a/DEV-LOGS.md b/DEV-LOGS.md index ac61666..e013e49 100644 --- a/DEV-LOGS.md +++ b/DEV-LOGS.md @@ -13,6 +13,11 @@ - Minimal markdown markers, no unnecessary formatting, minimal emojis. - Reference issue numbers in the format `#` for easy linking. +# [2026-07-27] Dev Log: DEVA_AUTH_TAG for in-container account identity #496 +- Why: two claude containers on `--auth-with a.credentials.json` / `b.credentials.json` are indistinguishable from inside — /status shows the shared `.claude.json`'s oauthAccount (whoever logged in last), and claude-code-statusline's "account-scoped" caches under the shared `~/.claude/statusline` actively bleed across accounts (B renders A's 5h/7d bars whenever A fetched last; profile.cache sticks to the first account for 24h). Credentials files carry no identity — tokens rotate, no email/uuid — so the runner is the only party that knows which account a container talks as. +- What: hoist generate_auth_tag() out of the container-name rewrite branch (it already produced `auth-default | auth-file- | api-key- | env` for naming and the `deva.auth_tag` label) and export it as `DEVA_AUTH_TAG` on every run. No naming/label change. Verified all three modes via scratch-HOME `--dry-run`. +- Result: in-container tooling gets a stable account handle. Statusline side (chip + per-account cache dirs keyed on the tag) lands in claude-code-statusline. /status stays wrong by design until a per-account `.claude.json` overlay exists — follow-up candidate for `--auth-with`. + # [2026-07-27] Dev Log: cloak release policy + closing the unverified VNC/daemon gap #456 - Why: two loose ends before shipping. (1) The 2026-07-21 entry left "x11vnc serving RFB and a live daemon inside the built image" unverified — that env couldn't apt-install. (2) release.yml made the GitHub Release `needs` the cloak build, so a ~200MB Chromium bake per arch (arm64 under QEMU) sat on the critical path of every release, including patch releases that touch nothing in that layer. - What: diff --git a/deva.sh b/deva.sh index b1333f2..d311964 100755 --- a/deva.sh +++ b/deva.sh @@ -4004,6 +4004,8 @@ _step "agent_prepare" _needs_rewrite=true fi + _auth_tag=$(generate_auth_tag "$ACTIVE_AGENT" "${AUTH_METHOD:-}" "${CUSTOM_CREDENTIALS_FILE:-}" "$_env_auth_override") + if [ "$_needs_rewrite" = true ]; then _rw_slug="$(generate_container_slug)" @@ -4020,10 +4022,9 @@ _step "agent_prepare" _rw_trace_input="" [ "${DEVA_TRACE_ACTIVE:-false}" = true ] && _rw_trace_input="trace" _rw_shape=$(compute_shape_hash "$(docker_image_ref)" "$_rw_vol_input" "${_rw_cfg_input}${_rw_trace_input:+|${_rw_trace_input}}") - _rw_auth_tag=$(generate_auth_tag "$ACTIVE_AGENT" "$AUTH_METHOD" "${CUSTOM_CREDENTIALS_FILE:-}" "$_env_auth_override") _rw_name=$(build_container_name \ - "$DEVA_CONTAINER_PREFIX" "$ACTIVE_AGENT" "$_rw_auth_tag" \ + "$DEVA_CONTAINER_PREFIX" "$ACTIVE_AGENT" "$_auth_tag" \ "$_rw_slug" "$_rw_shape" "$EPHEMERAL_MODE" "$$") for ((i = 0; i < ${#DOCKER_ARGS[@]}; i++)); do @@ -4033,7 +4034,7 @@ _step "agent_prepare" fi done - DOCKER_ARGS+=(--label "deva.auth_tag=${_rw_auth_tag}") + DOCKER_ARGS+=(--label "deva.auth_tag=${_auth_tag}") fi if [ -n "${AUTH_METHOD:-}" ]; then @@ -4041,6 +4042,12 @@ _step "agent_prepare" DOCKER_ARGS+=(-e "DEVA_AUTH_METHOD=${AUTH_METHOD}") [ -n "${AUTH_DETAILS:-}" ] && DOCKER_ARGS+=(-e "DEVA_AUTH_DETAILS=${AUTH_DETAILS}") fi + + # Account identity for in-container tooling (#496). The credentials file + # carries no identity (tokens rotate) — the tag is the only stable handle + # for WHICH account this container runs as. claude-code-statusline keys + # its per-account cache scoping and account chip on it. + DOCKER_ARGS+=(-e "DEVA_AUTH_TAG=${_auth_tag}") } # Determine container name early for env injection