Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-<stem>` |
`api-key-<last4>` | `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
Expand Down
5 changes: 5 additions & 0 deletions DEV-LOGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
- Minimal markdown markers, no unnecessary formatting, minimal emojis.
- Reference issue numbers in the format `#<issue-number>` 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-<stem> | api-key-<last4> | 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:
Expand Down
13 changes: 10 additions & 3 deletions deva.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)"

Expand All @@ -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
Expand All @@ -4033,14 +4034,20 @@ _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
DOCKER_ARGS+=(--label "deva.auth=${AUTH_METHOD}")
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}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Pass the auth tag when attaching to existing containers

When a persistent container was created before this version, adding DEVA_AUTH_TAG only to DOCKER_ARGS does not expose it to the launched agent: the attach path skips docker run and invokes docker exec with only the trace override. Upgraded users therefore continue without the tag—and the intended per-account cache isolation—until they manually delete and recreate every persistent container; pass the computed tag as an exec-time environment override as well.

Useful? React with 👍 / 👎.

}

# Determine container name early for env injection
Expand Down
Loading