Research: per-user rootless Podman agent containers (Claude Code, Codex, FUSE) #5

Closed
opened 2026-09-24 07:05:42 +00:00 by kayg · 9 comments
Owner

Codex job ai-containers. Task brief lives with the orchestrator; the job comments progress here.

Base: 5f15b1e66a

Codex job `ai-containers`. Task brief lives with the orchestrator; the job comments progress here. Base: 5f15b1e66ac9f1e781add30ed77a2594dda4472e
Author
Owner

Starting research-only investigation on branch main, base SHA 5f15b1e66ac9f1e781add30ed77a2594dda4472e. Workspace remains unchanged. I’m verifying current upstream Podman, FUSE, Claude Code, and Codex guidance and versions against primary sources, then I’ll report the recommendation and exact gate status.

Starting research-only investigation on branch `main`, base SHA `5f15b1e66ac9f1e781add30ed77a2594dda4472e`. Workspace remains unchanged. I’m verifying current upstream Podman, FUSE, Claude Code, and Codex guidance and versions against primary sources, then I’ll report the recommendation and exact gate status.
Author
Owner

Finding — Podman socket is an engine-wide authority boundary. Bollard 0.21.1 exposes connect_with_podman_defaults(), including rootless Podman sockets. Podman's API socket is secured by Unix permissions and grants full Podman API access (including code execution as the service user); Podman documents no API mechanism to limit or audit callers. Rootless --userns=auto creates distinct container UID mappings from subordinate ID ranges, but all containers remain controlled by the same rootless service identity. Therefore a shared service-user engine is practical for a trusted single-tenant boundary, but it is not per-User engine authorization. Keep the socket inaccessible to Agent containers; for stronger cross-User isolation use per-User rootless service identities or a narrow broker that owns the sockets and validates typed requests. Sources: https://docs.rs/bollard/latest/bollard/struct.Docker.html ; https://docs.podman.io/en/latest/markdown/podman-system-service.1.html ; https://docs.podman.io/en/latest/markdown/podman-run.1.html

Finding — Podman socket is an engine-wide authority boundary. Bollard 0.21.1 exposes `connect_with_podman_defaults()`, including rootless Podman sockets. Podman's API socket is secured by Unix permissions and grants full Podman API access (including code execution as the service user); Podman documents no API mechanism to limit or audit callers. Rootless `--userns=auto` creates distinct container UID mappings from subordinate ID ranges, but all containers remain controlled by the same rootless service identity. Therefore a shared service-user engine is practical for a trusted single-tenant boundary, but it is not per-User engine authorization. Keep the socket inaccessible to Agent containers; for stronger cross-User isolation use per-User rootless service identities or a narrow broker that owns the sockets and validates typed requests. Sources: https://docs.rs/bollard/latest/bollard/struct.Docker.html ; https://docs.podman.io/en/latest/markdown/podman-system-service.1.html ; https://docs.podman.io/en/latest/markdown/podman-run.1.html
Author
Owner

Finding — Claude plan authentication has a product-policy constraint. Claude Code docs support browser /login (containers may require copying a code back) and claude setup-token (one-year OAuth token stored by the caller), but Anthropic's current help page says third-party access should use a Claude Console API key or supported cloud provider, and explicitly says developers building a product/tool for others should use that API-key path. A separate June 16 notice says the announced Agent SDK/claude -p subscription changes are paused and those calls still count against subscription usage for now. For calternal's server-managed Agent container, recommend Console/API or supported cloud as default; treat personal-plan OAuth support as an unresolved policy/owner decision, not an assumed entitlement. Sources: https://code.claude.com/docs/en/authentication ; https://support.claude.com/en/articles/13189465-log-in-to-your-claude-account ; https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan

Finding — Claude plan authentication has a product-policy constraint. Claude Code docs support browser `/login` (containers may require copying a code back) and `claude setup-token` (one-year OAuth token stored by the caller), but Anthropic's current help page says third-party access should use a Claude Console API key or supported cloud provider, and explicitly says developers building a product/tool for others should use that API-key path. A separate June 16 notice says the announced Agent SDK/`claude -p` subscription changes are paused and those calls still count against subscription usage for now. For calternal's server-managed Agent container, recommend Console/API or supported cloud as default; treat personal-plan OAuth support as an unresolved policy/owner decision, not an assumed entitlement. Sources: https://code.claude.com/docs/en/authentication ; https://support.claude.com/en/articles/13189465-log-in-to-your-claude-account ; https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan
Author
Owner

Finding — the API-backed FUSE client is implementable in Rust, with a runtime integration gate. The current fuser crate is 0.18.0 (released 2026-07-22), MIT licensed, and implements the userspace side of FUSE; its normal Linux mount/unmount setup can use libfuse but does not require it. The kernel FUSE connection still requires /dev/fuse; non-privileged mounts use the fusermount helper and default to nosuid,nodev. Do not confuse this client mount with fuse-overlayfs, which Podman may use for its own rootless container storage. Keep a container CLI-only fallback until /dev/fuse, mount helper, user namespace, and SELinux/AppArmor behavior are verified together on supported hosts. Sources: https://docs.rs/crate/fuser/0.18.0/source/README.md ; https://docs.rs/crate/fuser/0.18.0/source/LICENSE.md ; https://docs.kernel.org/filesystems/fuse/fuse.html ; https://docs.podman.io/en/stable/markdown/podman.1.html

Finding — the API-backed FUSE client is implementable in Rust, with a runtime integration gate. The current `fuser` crate is 0.18.0 (released 2026-07-22), MIT licensed, and implements the userspace side of FUSE; its normal Linux mount/unmount setup can use libfuse but does not require it. The kernel FUSE connection still requires `/dev/fuse`; non-privileged mounts use the `fusermount` helper and default to `nosuid,nodev`. Do not confuse this client mount with `fuse-overlayfs`, which Podman may use for its own rootless container storage. Keep a container CLI-only fallback until `/dev/fuse`, mount helper, user namespace, and SELinux/AppArmor behavior are verified together on supported hosts. Sources: https://docs.rs/crate/fuser/0.18.0/source/README.md ; https://docs.rs/crate/fuser/0.18.0/source/LICENSE.md ; https://docs.kernel.org/filesystems/fuse/fuse.html ; https://docs.podman.io/en/stable/markdown/podman.1.html
Author
Owner

Finding — prefer the stable Codex CLI event stream for the first integration. OpenAI's current command reference labels codex exec Stable and documents codex exec --json JSONL progress events, while it labels codex app-server Experimental and says it is for local development/debugging and may change without notice. App Server does expose thread/start, turn/start, streamed item/agentMessage/delta, and turn/interrupt, so it is a good later rich integration behind an adapter if calternal accepts an experimental protocol. For v1, spawn codex exec --json -, stream stdout JSONL, and cancel the process/container; do not expose its WebSocket listener. Sources: https://learn.chatgpt.com/docs/developer-commands ; https://learn.chatgpt.com/docs/non-interactive-mode ; https://learn.chatgpt.com/docs/app-server

Codex auth finding — current docs support ChatGPT browser OAuth and beta device-code auth (codex login --device-auth, user/workspace setting must enable it); CODEX_HOME can point to a private per-User persistent volume. File auth is plaintext auth.json and should be handled as a password. OpenAI Terms of Use prohibit sharing account credentials or making an account available to others, so keep each User's own login separate and avoid pooled/shared credentials. API-key login is available for scripted workflows and bills at standard API rates. Sources: https://learn.chatgpt.com/docs/auth ; https://openai.com/policies/row-terms-of-use/

Finding — prefer the stable Codex CLI event stream for the first integration. OpenAI's current command reference labels `codex exec` Stable and documents `codex exec --json` JSONL progress events, while it labels `codex app-server` Experimental and says it is for local development/debugging and may change without notice. App Server does expose `thread/start`, `turn/start`, streamed `item/agentMessage/delta`, and `turn/interrupt`, so it is a good later rich integration behind an adapter if calternal accepts an experimental protocol. For v1, spawn `codex exec --json -`, stream stdout JSONL, and cancel the process/container; do not expose its WebSocket listener. Sources: https://learn.chatgpt.com/docs/developer-commands ; https://learn.chatgpt.com/docs/non-interactive-mode ; https://learn.chatgpt.com/docs/app-server Codex auth finding — current docs support ChatGPT browser OAuth and beta device-code auth (`codex login --device-auth`, user/workspace setting must enable it); `CODEX_HOME` can point to a private per-User persistent volume. File auth is plaintext `auth.json` and should be handled as a password. OpenAI Terms of Use prohibit sharing account credentials or making an account available to others, so keep each User's own login separate and avoid pooled/shared credentials. API-key login is available for scripted workflows and bills at standard API rates. Sources: https://learn.chatgpt.com/docs/auth ; https://openai.com/policies/row-terms-of-use/
Author
Owner

Finding — the required agent image conflicts with the repository's license rule as written. Anthropic's official Claude Code repository has a one-line license notice: “© Anthropic PBC. All rights reserved. Use is subject to Anthropic's Commercial Terms of Service.” The official Codex CLI repository is Apache-2.0. The calternal agent image is supposed to preinstall both, while AGENTS.md says dependencies must be AGPL-compatible and disallows proprietary dependencies. If that rule covers bundled runtime programs, Claude Code cannot be included in the image without an explicit scope exception/owner decision (or a supported alternative). Sources: https://github.com/anthropics/claude-code/blob/main/LICENSE.md ; https://github.com/openai/codex/blob/main/docs/license.md

Finding — the required agent image conflicts with the repository's license rule as written. Anthropic's official Claude Code repository has a one-line license notice: “© Anthropic PBC. All rights reserved. Use is subject to Anthropic's Commercial Terms of Service.” The official Codex CLI repository is Apache-2.0. The calternal agent image is supposed to preinstall both, while AGENTS.md says dependencies must be AGPL-compatible and disallows proprietary dependencies. If that rule covers bundled runtime programs, Claude Code cannot be included in the image without an explicit scope exception/owner decision (or a supported alternative). Sources: https://github.com/anthropics/claude-code/blob/main/LICENSE.md ; https://github.com/openai/codex/blob/main/docs/license.md
Author
Owner

Research finished against the current design (§2 and §10). No repository files were changed. The branch advanced from the recorded start base 5f15b1e66ac9f1e781add30ed77a2594dda4472e to current HEAD bcabc4d444b2be0aaafdde8acf651706402616ed (docs: round 6 decisions); the worktree is clean.

Gate output (not run because this was research-only and no source changed):

  • cargo fmt --check: NOT RUN — research-only
  • cargo clippy --all-targets -- -D warnings: NOT RUN — research-only
  • cargo test: NOT RUN — research-only
  • bun run check: NOT RUN — research-only
  • bun run test: NOT RUN — research-only
  • cargo clean: NOT RUN — no Cargo command/build was run; cleanup would modify build artifacts
Research finished against the current design (§2 and §10). No repository files were changed. The branch advanced from the recorded start base `5f15b1e66ac9f1e781add30ed77a2594dda4472e` to current HEAD `bcabc4d444b2be0aaafdde8acf651706402616ed` (`docs: round 6 decisions`); the worktree is clean. Gate output (not run because this was research-only and no source changed): - `cargo fmt --check`: NOT RUN — research-only - `cargo clippy --all-targets -- -D warnings`: NOT RUN — research-only - `cargo test`: NOT RUN — research-only - `bun run check`: NOT RUN — research-only - `bun run test`: NOT RUN — research-only - `cargo clean`: NOT RUN — no Cargo command/build was run; cleanup would modify build artifacts
Author
Owner

Final head update: another upstream design commit landed while I was closing the research: c6034393564023860ea5f33a6c33e1d1bf904809 (docs: round 7 decisions). It updates notes/glossary decisions only; §§2 and 10 and the AI-container recommendations are unchanged. Worktree is clean.

Gate status remains: cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test, bun run check, bun run test, and cargo clean were not run because this is research-only and no repository files/build artifacts were changed.

Final head update: another upstream design commit landed while I was closing the research: `c6034393564023860ea5f33a6c33e1d1bf904809` (`docs: round 7 decisions`). It updates notes/glossary decisions only; §§2 and 10 and the AI-container recommendations are unchanged. Worktree is clean. Gate status remains: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test`, `bun run check`, `bun run test`, and `cargo clean` were not run because this is research-only and no repository files/build artifacts were changed.
Author
Owner

The research report is complete on this issue. DESIGN §10 records the selected Agent container and server-only data-access model.

The research report is complete on this issue. DESIGN §10 records the selected Agent container and server-only data-access model.
kayg closed this issue 2026-10-03 11:55:02 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#5
No description provided.