Skip to content

feat: add explicit Codex runtime updates with bundled fallback - #110

Merged
eXPerience83 merged 33 commits into
mainfrom
feat/codex-runtime-updates
Aug 8, 2026
Merged

feat: add explicit Codex runtime updates with bundled fallback#110
eXPerience83 merged 33 commits into
mainfrom
feat/codex-runtime-updates

Conversation

@eXPerience83

@eXPerience83 eXPerience83 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Closes #103.

Goal

Add an explicit near-term Codex update path aligned with the Antigravity runtime-admission model, while preserving the immutable image-tested Codex CLI as the fallback.

Unlike Antigravity, OpenAI currently publishes the Codex CLI/package under its own upstream Apache-2.0 license terms and provides complete package archives. Those upstream terms and notices remain applicable to the downloaded Codex package; the Remote Dev project license does not extend to third-party components. This implementation therefore downloads the exact official complete Codex package instead of executing the mutable upstream installer.

Runtime model

  • bundled /usr/local/bin/codex remains immutable and image-tested;
  • optional runtime lives outside CODEX_HOME at /root/.local/share/remote-dev/codex-runtime;
  • that state is mounted and configured only in the Codex service, never the launcher or Antigravity;
  • normal startup/status/resolve/launch performs local integrity checks only and makes no updater network requests;
  • network access requires the explicit menu/CLI install/update action and interactive confirmation before the first request (or administrator-supplied --yes);
  • a newer admitted runtime is labeled official source; Remote Dev review pending;
  • damaged/modified state, resolver failure, missing executable, or an equal/older optional runtime selects the bundled fallback.

review pending is intentionally not described as cryptographically unverified: the official release origin, exact stable tag, architecture, GitHub release SHA-256 metadata, package layout and file identities are verified and bounded compatibility probes run before publication. What remains pending is Remote Dev review and real deployment validation of that exact upstream release.

Admission

The manager accepts only the latest exact stable OpenAI Codex release and the matching official codex-package-<target>.tar.gz. It verifies the bounded canonical package layout, rejects traversal/links/special files, executes changed vendor bytes in a synthetic credential-free home (dropping to a fixed unprivileged identity when root), bounds probe time/output, checks Codex version/launcher flags and the code-mode host listener + /readyz, fingerprints every published file, serializes mutation and atomically switches the active pointer only after all checks pass. The previous active generation is retained while the new one is published so an already-running Codex process cannot lose lazily resolved package resources. Stale .candidate-* staging directories from interrupted earlier publications are reclaimed under the same mutation lock.

The complete package remains outside CODEX_HOME/packages/standalone/releases, so upstream does not classify the Remote Dev-managed copy as its own standalone installation and cannot bypass our explicit manager through the normal standalone self-update path.

UX / persistence

  • remote-dev-codex-runtime status|resolve|install|update|remove;
  • install, update and remove accept --yes only as the explicit non-interactive lifecycle form;
  • Codex menu shows runtime state and explicit update/remove actions;
  • run-codex resolves the optional runtime only after project-owned approval/sandbox policy validation;
  • remote-dev-version and remote-dev-doctor distinguish bundled/runtime/active source;
  • canonical host layout adds state/codex/runtime and preflight/Compose tests keep it Codex-only;
  • recursive state hardening accepts only the canonical Codex runtime target and rejects symlink/non-directory path components before mutation;
  • existing proxy configuration and optional CODEX_CA_CERTIFICATE remain usable by the explicit updater while destination/redirect origin validation remains fixed;
  • EN/ES operational docs are in docs/codex-runtime-updates*.md and the setup READMEs include the new runtime directory/menu actions.

Intentionally unchanged

  • CODEX_HOME=/root/.codex remains the credential/config/session boundary;
  • the outer container remains the supported sandbox boundary and run-codex still owns --sandbox danger-full-access plus approval policy;
  • no system Bubblewrap command is installed;
  • no background updater, silent startup network or auto-update path is added;
  • Antigravity runtime admission remains separate and unchanged.

Validation

Completed on exact head 22504519d3fc097ed32a9eabc6902c8a65f0c460:

  • repository Python/Bash/Compose/data-layout tests;
  • dedicated runtime-manager unit tests including exact stable tag/digest/size rejection, no-network status/resolve with absent and installed runtime, explicit-confirmation-before-network, tamper, resolver fallback, removal, stale-candidate cleanup, filesystem-error normalization and failed-publication preservation;
  • distinct run-codex fixtures proving normal launch uses the resolved runtime and resolver failure uses the bundled executable;
  • image build and full runtime smoke, including rejection of an unsafe Codex runtime-root override;
  • Code Mode companion readiness smoke;
  • canonical mount/environment isolation checks, including launcher/Antigravity exclusion from Codex runtime state;
  • bundled notices, SPDX SBOM, Trivy and no-fixable-critical gate via Build AMD64 #808;
  • optional Antigravity runtime regression workflow #127;
  • latest CodeRabbit review of the final delta reported no actionable comments; all inline review threads are resolved and the exact-head CodeRabbit status is green.

Follow-up research

Remaining before merge:

  • final real TrueNAS candidate validation of the optional Codex runtime path and bundled fallback.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0c1ca5c0-b8e8-411c-a247-2bc2b9bd9e51

📥 Commits

Reviewing files that changed from the base of the PR and between fd406af and 2250451.

📒 Files selected for processing (12)
  • README.es.md
  • README.md
  • docs/codex-runtime-updates.es.md
  • docs/codex-runtime-updates.md
  • images/codex/Dockerfile
  • scripts/remote-dev-codex-runtime.py
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/secure-persistent-state.sh
  • scripts/test-remote-dev-codex-runtime.py
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly to main. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets, SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces, eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update #31 when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.

Files:

  • README.md
  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • images/codex/Dockerfile
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-remote-dev-codex-runtime.py
  • docs/codex-runtime-updates.md
  • README.es.md
  • scripts/remote-dev-codex-runtime.py
  • docs/codex-runtime-updates.es.md
  • scripts/run-codex.sh
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.

Files:

  • README.md
  • docs/codex-runtime-updates.md
  • README.es.md
  • docs/codex-runtime-updates.es.md
**/*.{sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such as CODEX_HOME inside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.

Files:

  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
**/*.{yml,yaml,sh,bash, Dockerfile}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.

Files:

  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
**/*.{yml,yaml,sh,bash,html,js,ts}

📄 CodeRabbit inference engine (AGENTS.md)

The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.

Files:

  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
**/*.{yml,yaml,sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.

Files:

  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
**/*.{sh,bash,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must set AGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.

Files:

  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
scripts/**/*.sh

⚙️ CodeRabbit configuration file

scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.

Files:

  • scripts/remote-dev-menu.sh
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
images/**/Dockerfile

⚙️ CodeRabbit configuration file

images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.

Files:

  • images/codex/Dockerfile
🧠 Learnings (1)
📚 Learning: 2026-08-08T15:58:18.427Z
Learnt from: eXPerience83
Repo: eXPerience83/remote-dev-containers PR: 110
File: README.md:261-276
Timestamp: 2026-08-08T15:58:18.427Z
Learning: In README documentation examples, accurately represent the Codex runtime lifecycle from scripts/remote-dev-version.sh: `Codex CLI: unavailable` indicates a broken immutable bundled CLI or version probe and is treated as invalid by `remote-dev-version --check`; `Codex runtime: not installed` is the normal state when no optional runtime is present; and `Codex runtime: unavailable` means the runtime manager could not obtain optional-runtime status. Healthy edge-output examples should not present these failure states as expected healthy output.

Applied to files:

  • README.md
  • README.es.md
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py

[info] 69-69: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py

[warning] 107-107: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 125-125: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 245-245: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)

🔇 Additional comments (24)
README.md (1)

107-111: LGTM!

docs/codex-runtime-updates.es.md (1)

1-18: LGTM!

Also applies to: 20-38, 40-71, 73-89, 91-111, 113-127

docs/codex-runtime-updates.md (1)

1-18: LGTM!

Also applies to: 20-38, 40-71, 73-89, 91-111, 113-127

README.es.md (1)

26-26: LGTM!

Also applies to: 58-58, 90-97, 123-123, 132-132, 156-156, 175-175, 219-239

scripts/test-remote-dev-codex-runtime.py (5)

107-107: The Ruff PT027 and ast-grep use-jsonify hints do not apply here. The suite is unittest-based and the image runs it with python, not pytest. The use-jsonify rule targets Flask view responses.


62-73: LGTM!

Also applies to: 101-126


234-247: LGTM!


262-273: LGTM!


344-375: LGTM!

scripts/remote-dev-codex-runtime.py (9)

102-110: LGTM!

Also applies to: 143-151


155-177: LGTM!


251-316: LGTM!


319-358: LGTM!


370-414: LGTM!

Also applies to: 417-450


539-608: LGTM!


637-657: LGTM!

Also applies to: 674-749


1010-1023: LGTM!


837-841: 🔒 Security & Privacy

No action needed for real_file symlink handling.

real_file rejects symlinked ROOT/current pointers and treats them as damaged state.

			> Likely an incorrect or invalid review comment.
images/codex/Dockerfile (1)

85-85: LGTM!

Also applies to: 110-111, 123-123, 147-153, 219-225

scripts/secure-persistent-state.sh (1)

45-69: LGTM!

Also applies to: 71-74

scripts/run-codex.sh (1)

176-178: LGTM!

scripts/remote-dev-version.sh (1)

56-68: LGTM!

scripts/remote-dev-doctor.sh (1)

98-98: LGTM!

Also applies to: 127-128

scripts/remote-dev-menu.sh (1)

86-97: LGTM!


Summary by CodeRabbit

  • New Features
    • Added optional Codex runtime status, installation, update, and removal actions.
    • Codex can use validated official runtimes with safe fallback to the bundled version.
    • Added isolated persistent runtime storage for Docker Compose and TrueNAS deployments.
    • Added runtime management options to the Remote Dev menu and diagnostics.
  • Bug Fixes
    • Improved protection against damaged, tampered, or unsafe runtime packages.
    • Updates require explicit confirmation and do not occur during normal startup.
  • Documentation
    • Added English and Spanish guidance covering updates, security, validation, storage, and fallback behavior.

Walkthrough

Adds an explicit Codex runtime manager with secure package admission, isolated persistent storage, bundled fallback resolution, operator controls, diagnostics, tests, image validation, and English and Spanish documentation.

Changes

Codex runtime lifecycle

Layer / File(s) Summary
Runtime admission and lifecycle
scripts/remote-dev-codex-runtime.py, scripts/test-remote-dev-codex-runtime.py, .github/workflows/build-amd64.yml
The manager validates official releases and packages, probes candidates, publishes integrity manifests, reports state, and supports install, update, resolve, and remove. Tests and build validation cover these operations.
Persistent storage and image wiring
images/codex/Dockerfile, compose/docker-compose.yml, compose/truenas.yml, scripts/preflight-data-layout.py, scripts/test_canonical_data_layout.py, scripts/test_preflight_data_layout.py, scripts/secure-persistent-state.sh
The image and services define the isolated runtime root and persistent mounts. Layout, symlink, bind, and permission checks validate the storage contract.
Launch resolution and operator controls
scripts/run-codex.sh, scripts/remote-dev-version.sh, scripts/remote-dev-doctor.sh, scripts/remote-dev-menu.sh, scripts/test-run-codex-policy.sh, scripts/test-remote-dev-menu.sh
Codex launch resolves a valid managed runtime and uses the bundled binary on failure. Diagnostics and menu actions report, update, and remove the managed runtime.
Documentation and repository contract
README.md, README.es.md, docs/architecture.md, docs/security.md, docs/tool-matrix.md, docs/codex-runtime-updates.md, docs/codex-runtime-updates.es.md
Documentation defines explicit updates, trust states, validation, isolation, fallback, persistence, removal, and operator workflows in English and Spanish.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant run-codex.sh
  participant remote-dev-codex-runtime
  participant Codex
  Operator->>run-codex.sh: launch Codex
  run-codex.sh->>remote-dev-codex-runtime: resolve
  remote-dev-codex-runtime-->>run-codex.sh: runtime path or bundled sentinel
  run-codex.sh->>Codex: execute selected path
  Codex-->>Operator: return output and exit status
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: explicit Codex runtime updates with the bundled executable as fallback.
Description check ✅ Passed The description thoroughly covers the change, impact, validation, safety constraints, documentation, and follow-up work.
Linked Issues check ✅ Passed The changes satisfy #103 objectives for explicit updates, validation, fallback, isolation, atomic publication, resolver integration, tests, and documentation.
Out of Scope Changes check ✅ Passed The code, tests, workflows, persistence changes, and documentation are directly related to the Codex runtime update objectives in #103.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/codex-runtime-updates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/codex-runtime-updates.md`:
- Line 5: Scope the licensing statement in docs/codex-runtime-updates.md line 5
to the Remote Dev project code and reference the applicable upstream license
terms for the downloaded Codex package instead of claiming Codex is unqualified
Apache-2.0 software. Apply the same correction to
docs/codex-runtime-updates.es.md line 5, replacing the Spanish Apache-2.0 claim
consistently; do not assert Apache-2.0 coverage for bundled or runtime-installed
components.

In `@scripts/remote-dev-codex-runtime.py`:
- Around line 767-771: Update active_runtime() to recognize ROOT / "current"
when it is either present or a symlink, using the same exists-or-is_symlink
check as remove_runtime. Let dangling symlinks continue into real_file so
state() reports the pointer as damaged or locally modified instead of bundled.
- Around line 438-490: Remove the dead bounded_run function, including its
unfinished stream-capture comments and unreachable AssertionError. Keep
candidate_run as the sole implementation for bounded candidate subprocess
execution and preserve its existing behavior.
- Around line 721-728: Update the release-pruning logic around the publish
pointer switch to preserve the release referenced before the switch, recording
its name in manifest_previous_name before updating the pointer. Exclude both
manifest_previous_name and final_release from the rmtree loop, so only older
generations are removed while an existing Codex process may still use the
previous release.

In `@scripts/test_canonical_data_layout.py`:
- Around line 144-153: Extend the environment assertions in the test loop around
the role handling so the launcher service is explicitly validated, not only
codex and antigravity. Ensure launcher does not contain
REMOTE_DEV_CODEX_RUNTIME_ROOT, while preserving the existing codex runtime-root
assertion and antigravity behavior.

In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 121-168: Add tests covering resolve, remove, and the no-network
guarantee. Verify resolve prints the runtime binary only for kind == "runtime"
and /usr/local/bin/codex for all other states, including damaged; verify remove
deletes optional runtime state without modifying the bundled binary; and patch
remote-dev-codex-runtime.opener to raise while asserting both status and resolve
still succeed without network access.

In `@scripts/test-run-codex-policy.sh`:
- Around line 41-57: The test fixtures currently use the same executable for the
resolved runtime and bundled fallback, allowing launchers that skip resolution
to pass. In the test setup around test_codex and test_runtime_manager, create a
distinct resolved-runtime fixture, make both fixtures record their executable
identity, and assert that normal execution uses the resolved fixture while
resolver failure uses the bundled fixture.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4bd65d03-d987-4caf-8904-e61703c15241

📥 Commits

Reviewing files that changed from the base of the PR and between 1f06bf8 and 879ab15.

📒 Files selected for processing (18)
  • .github/workflows/build-amd64.yml
  • compose/docker-compose.yml
  • compose/truenas.yml
  • docs/codex-runtime-updates.es.md
  • docs/codex-runtime-updates.md
  • images/codex/Dockerfile
  • scripts/preflight-data-layout.py
  • scripts/remote-dev-codex-runtime.py
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/secure-persistent-state.sh
  • scripts/test-remote-dev-codex-runtime.py
  • scripts/test-remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test_canonical_data_layout.py
  • scripts/test_preflight_data_layout.py
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: Build AMD64 / build: feat: add explicit Codex runtime updates with bundled fallback

Conclusion: failure

View job details

enssl.
 `#10` 14.03 (Reading database ...
 (Reading database ... 5%
 (Reading database ... 10%
 (Reading database ... 15%
 (Reading database ... 20%
 (Reading database ... 25%
 (Reading database ... 30%
 (Reading database ... 35%
 (Reading database ... 40%
 (Reading database ... 45%
 (Reading database ... 50%
 (Reading database ... 55%
 (Reading database ... 60%
 (Reading database ... 65%
 (Reading database ... 70%
 (Reading database ... 75%
 (Reading database ... 80%
 (Reading database ... 85%
 (Reading database ... 90%
 (Reading database ... 95%
 (Reading database ... 100%
 (Reading database ... 7816 files and directories currently installed.)
 `#10` 14.04 Preparing to unpack .../000-openssl_3.5.5-1ubuntu3.3_amd64.deb ...
 `#10` 14.04 Unpacking openssl (3.5.5-1ubuntu3.3) ...
 `#10` 14.07 Selecting previously unselected package ca-certificates.
 `#10` 14.07 Preparing to unpack .../001-ca-certificates_20260601~26.04.1_all.deb ...
 `#10` 14.07 Unpacking ca-certificates (20260601~26.04.1) ...
 `#10` 14.10 Selecting previously unselected package less.
 `#10` 14.11 Preparing to unpack .../002-less_668-1build1_amd64.deb ...
 `#10` 14.11 Unpacking less (668-1build1) ...
 `#10` 14.12 Selecting previously unselected package libatomic1:amd64.
 `#10` 14.13 Preparing to unpack .../003-libatomic1_16-20260322-1ubuntu1_amd64.deb ...
 `#10` 14.13 Unpacking libatomic1:amd64 (16-20260322-1ubuntu1) ...
 `#10` 14.14 Selecting previously unselected package libedit2:amd64.
 `#10` 14.14 Preparing to unpack .../004-libedit2_3.1-20251016-1_amd64.deb ...
 `#10` 14.14 Unpacking libedit2:amd64 (3.1-20251016-1) ...
 `#10` 14.16 Selecting previously unselected package libffi8:amd64.
 `#10` 14.16 Preparing to unpack .../005-libffi8_3.5.2-4_amd64.deb ...
 `#10` 14.16 Unpacking libffi8:amd64 (3.5.2-4) ...
 `#10` 14.17 Selecting previously unselected package libnettle8t64:amd64.
 `#10` 14.17 Preparing to unpack .../006-libnettle8t64_3.10.2-1_amd64.deb ...
 `#10` 14.17 Unpacking libnettle8t64:amd64 (3.10.2-1) ...
 `#10` 14.19 Selecting pre...

GitHub Actions: Build AMD64 / 0_build.txt: feat: add explicit Codex runtime updates with bundled fallback

Conclusion: failure

View job details

enssl.
 `#10` 14.03 (Reading database ...
 (Reading database ... 5%
 (Reading database ... 10%
 (Reading database ... 15%
 (Reading database ... 20%
 (Reading database ... 25%
 (Reading database ... 30%
 (Reading database ... 35%
 (Reading database ... 40%
 (Reading database ... 45%
 (Reading database ... 50%
 (Reading database ... 55%
 (Reading database ... 60%
 (Reading database ... 65%
 (Reading database ... 70%
 (Reading database ... 75%
 (Reading database ... 80%
 (Reading database ... 85%
 (Reading database ... 90%
 (Reading database ... 95%
 (Reading database ... 100%
 (Reading database ... 7816 files and directories currently installed.)
 `#10` 14.04 Preparing to unpack .../000-openssl_3.5.5-1ubuntu3.3_amd64.deb ...
 `#10` 14.04 Unpacking openssl (3.5.5-1ubuntu3.3) ...
 `#10` 14.07 Selecting previously unselected package ca-certificates.
 `#10` 14.07 Preparing to unpack .../001-ca-certificates_20260601~26.04.1_all.deb ...
 `#10` 14.07 Unpacking ca-certificates (20260601~26.04.1) ...
 `#10` 14.10 Selecting previously unselected package less.
 `#10` 14.11 Preparing to unpack .../002-less_668-1build1_amd64.deb ...
 `#10` 14.11 Unpacking less (668-1build1) ...
 `#10` 14.12 Selecting previously unselected package libatomic1:amd64.
 `#10` 14.13 Preparing to unpack .../003-libatomic1_16-20260322-1ubuntu1_amd64.deb ...
 `#10` 14.13 Unpacking libatomic1:amd64 (16-20260322-1ubuntu1) ...
 `#10` 14.14 Selecting previously unselected package libedit2:amd64.
 `#10` 14.14 Preparing to unpack .../004-libedit2_3.1-20251016-1_amd64.deb ...
 `#10` 14.14 Unpacking libedit2:amd64 (3.1-20251016-1) ...
 `#10` 14.16 Selecting previously unselected package libffi8:amd64.
 `#10` 14.16 Preparing to unpack .../005-libffi8_3.5.2-4_amd64.deb ...
 `#10` 14.16 Unpacking libffi8:amd64 (3.5.2-4) ...
 `#10` 14.17 Selecting previously unselected package libnettle8t64:amd64.
 `#10` 14.17 Preparing to unpack .../006-libnettle8t64_3.10.2-1_amd64.deb ...
 `#10` 14.17 Unpacking libnettle8t64:amd64 (3.10.2-1) ...
 `#10` 14.19 Selecting pre...
🧰 Additional context used
📓 Path-based instructions (11)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly to main. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets, SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces, eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update #31 when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.

Files:

  • scripts/preflight-data-layout.py
  • compose/truenas.yml
  • compose/docker-compose.yml
  • scripts/secure-persistent-state.sh
  • docs/codex-runtime-updates.md
  • scripts/remote-dev-doctor.sh
  • scripts/test-remote-dev-codex-runtime.py
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test_canonical_data_layout.py
  • images/codex/Dockerfile
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
  • scripts/test_preflight_data_layout.py
  • docs/codex-runtime-updates.es.md
  • scripts/remote-dev-codex-runtime.py
.github/workflows/**

⚙️ CodeRabbit configuration file

.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.

Files:

  • .github/workflows/build-amd64.yml
**/*.{yml,yaml,sh,bash, Dockerfile}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
**/*.{yml,yaml,sh,bash,html,js,ts}

📄 CodeRabbit inference engine (AGENTS.md)

The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
**/*.{yml,yaml,sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
**/*.{sh,bash,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must set AGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
compose/**

⚙️ CodeRabbit configuration file

compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Require launcher and agent services to reference one image while keeping agent state out of the launcher.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
**/*.{sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such as CODEX_HOME inside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.

Files:

  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
scripts/**/*.sh

⚙️ CodeRabbit configuration file

scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.

Files:

  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-doctor.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test-remote-dev-menu.sh
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.

Files:

  • docs/codex-runtime-updates.md
  • docs/codex-runtime-updates.es.md
images/**/Dockerfile

⚙️ CodeRabbit configuration file

images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.

Files:

  • images/codex/Dockerfile
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py

[info] 56-61: use jsonify instead of json.dumps for JSON output
Context: json.dumps({
"layoutVersion": 1, "version": version,
"target": "x86_64-unknown-linux-musl", "variant": "codex",
"entrypoint": "bin/codex", "resourcesDir": "codex-resources",
"pathDir": "codex-path",
})
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 72-72: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 83-83: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 115-115: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

scripts/remote-dev-codex-runtime.py

[error] 171-179: Command coming from incoming request
Context: subprocess.run(
[str(BUNDLED), "--version"],
check=True,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=10,
env={"PATH": "/usr/bin:/bin"},
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 441-450: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 496-505: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 550-559: Command coming from incoming request
Context: subprocess.Popen(
[str(host), "--listen", "ws://127.0.0.1:0"],
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[info] 711-711: use jsonify instead of json.dumps for JSON output
Context: json.dumps(manifest, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[error] 441-450: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 496-505: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)

🪛 LanguageTool
docs/codex-runtime-updates.md

[style] ~87-~87: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ...ume paths continue through run-codex. The launcher first validates the project-owned approval/sa...

(SENT_START_FIRST_PREMIUM)

🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py

[warning] 19-19: Assertion should be broken down into multiple parts

Break down assertion into multiple parts

(PT018)


[warning] 86-86: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 97-97: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 106-106: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 117-118: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


[warning] 118-118: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 157-158: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


[warning] 158-158: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 165-165: Boolean positional value in function call

(FBT003)

scripts/remote-dev-codex-runtime.py

[warning] 29-29: Import from collections.abc instead: Iterator

Import from collections.abc

(UP035)


[warning] 109-109: Boolean-typed positional argument in function definition

(FBT001)


[warning] 109-109: Boolean default positional argument in function definition

(FBT002)


[warning] 170-170: Boolean positional value in function call

(FBT003)


[warning] 172-180: Prefer capture_output over sending stdout and stderr to PIPE

Replace with capture_output keyword argument

(UP022)


[error] 172-172: subprocess call: check for execution of untrusted input

(S603)


[error] 286-288: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.

(S310)


[error] 442-442: subprocess call: check for execution of untrusted input

(S603)


[warning] 450-450: preexec_fn argument is unsafe when using threads

(PLW1509)


[warning] 452-452: Assertion should be broken down into multiple parts

Break down assertion into multiple parts

(PT018)


[error] 497-497: subprocess call: check for execution of untrusted input

(S603)


[warning] 505-505: preexec_fn argument is unsafe when using threads

(PLW1509)


[warning] 507-507: Assertion should be broken down into multiple parts

Break down assertion into multiple parts

(PT018)


[error] 551-551: subprocess call: check for execution of untrusted input

(S603)


[warning] 559-559: preexec_fn argument is unsafe when using threads

(PLW1509)


[warning] 561-561: Assertion should be broken down into multiple parts

Break down assertion into multiple parts

(PT018)


[warning] 734-734: Dynamically typed expressions (typing.Any) are disallowed in manifest

(ANN401)


[warning] 767-767: Too many branches (14 > 12)

(PLR0912)


[warning] 868-868: Boolean-typed positional argument in function definition

(FBT001)


[warning] 909-909: Boolean-typed positional argument in function definition

(FBT001)


[warning] 918-918: Boolean-typed positional argument in function definition

(FBT001)


[warning] 961-961: Boolean-typed positional argument in function definition

(FBT001)


[warning] 1008-1008: Consider moving this statement to an else block

(TRY300)

🔇 Additional comments (28)
scripts/run-codex.sh (1)

4-5: LGTM!

Also applies to: 172-180

scripts/remote-dev-version.sh (1)

6-6: LGTM!

Also applies to: 43-76

scripts/remote-dev-doctor.sh (1)

55-55: LGTM!

Also applies to: 98-98, 125-137, 186-189

scripts/remote-dev-menu.sh (1)

86-94: LGTM!

Also applies to: 177-231

scripts/test-remote-dev-menu.sh (1)

9-13: LGTM!

Also applies to: 78-93, 125-125, 136-174, 185-204, 216-235

scripts/test-run-codex-policy.sh (1)

7-39: LGTM!

Also applies to: 59-106, 207-217, 255-265

scripts/remote-dev-codex-runtime.py (10)

31-145: LGTM!


147-186: LGTM!


189-282: LGTM!


285-315: LGTM!


318-371: LGTM!


374-406: LGTM!


409-436: LGTM!

Also applies to: 493-547


550-647: LGTM!


734-765: LGTM!

Also applies to: 841-907


909-1018: LGTM!

scripts/test-remote-dev-codex-runtime.py (1)

26-64: LGTM!

docs/codex-runtime-updates.es.md (2)

7-16: LGTM!


18-121: LGTM!

docs/codex-runtime-updates.md (1)

7-121: LGTM!

.github/workflows/build-amd64.yml (1)

33-34: LGTM!

Also applies to: 51-51

images/codex/Dockerfile (1)

27-27: LGTM!

Also applies to: 86-86, 111-112, 124-124, 148-153, 219-219

compose/docker-compose.yml (1)

54-54: LGTM!

Also applies to: 103-107

compose/truenas.yml (1)

56-56: LGTM!

Also applies to: 106-110

scripts/preflight-data-layout.py (1)

15-15: LGTM!

scripts/test_canonical_data_layout.py (1)

18-24: LGTM!

Also applies to: 232-233, 242-242

scripts/test_preflight_data_layout.py (1)

18-18: LGTM!

Also applies to: 175-183, 232-232

scripts/secure-persistent-state.sh (1)

14-14: LGTM!

Also applies to: 50-50

Comment thread docs/codex-runtime-updates.md Outdated
Comment thread scripts/remote-dev-codex-runtime.py Outdated
Comment thread scripts/remote-dev-codex-runtime.py
Comment thread scripts/remote-dev-codex-runtime.py Outdated
Comment thread scripts/test_canonical_data_layout.py
Comment thread scripts/test-remote-dev-codex-runtime.py
Comment thread scripts/test-run-codex-policy.sh Outdated

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@eXPerience83
eXPerience83 marked this pull request as ready for review August 8, 2026 06:17

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/codex-runtime-updates.md (1)

18-34: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align the runtime docs with the documented CLI contract.

remote-dev-codex-runtime.py accepts install, update, and remove, with --yes on lifecycle commands and the menu also exposing removal. Update the README and docs so these commands/options are documented consistently and avoid leaving install as an undocumented public alias.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/codex-runtime-updates.md` around lines 18 - 34, Align the runtime
command documentation with the remote-dev-codex-runtime.py CLI contract:
document install, update, and remove, including --yes for lifecycle commands,
and describe removal in the menu while keeping explicit network-access behavior
accurate. Apply these updates in docs/codex-runtime-updates.md (18-34 and
93-104), docs/codex-runtime-updates.es.md (18-34 and 93-105), README.md
(105-112), and README.es.md (90-97); ensure install is presented as a supported
public command rather than an undocumented alias.

Source: Path instructions

scripts/remote-dev-codex-runtime.py (1)

698-708: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Reclaim orphaned .candidate-* staging directories during publish.

The prune loop keeps release_name and previous_name and skips every .candidate- entry. The finally block at Lines 709-711 removes the staging directory of the current run only. If the process is killed between staging.mkdir and that finally block, the partial package directory stays in releases/ forever. Each orphan holds a full Codex package, so the persistent Codex runtime mount grows on every interrupted update.

Remove stale .candidate-* directories inside the same lock. The lock guarantees that no other publish owns them.

♻️ Proposed cleanup of stale staging directories
             keep_names = {release_name}
             if previous_name:
                 keep_names.add(previous_name)
             for old in releases.iterdir():
+                if old.name.startswith(".candidate-") and old != staging:
+                    if old.is_dir() and not old.is_symlink():
+                        shutil.rmtree(old, ignore_errors=True)
+                    continue
                 if (
                     old.name not in keep_names
                     and old.is_dir()
                     and not old.is_symlink()
                     and not old.name.startswith(".candidate-")
                 ):
                     shutil.rmtree(old, ignore_errors=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/remote-dev-codex-runtime.py` around lines 698 - 708, Update the
release-pruning loop around keep_names and releases.iterdir() to delete stale
.candidate-* directories as well as other unkept release directories, while
retaining the current run’s staging directory until its existing finally
cleanup. Perform this cleanup within the same publish lock and preserve the
existing safeguards against deleting symlinks or non-directories.
♻️ Duplicate comments (1)
scripts/test-remote-dev-codex-runtime.py (1)

310-323: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prove the no-network claim with a runtime installed.

self.m.ROOT points at missing-runtime, so state() returns {"kind": "bundled"} at the first check and never reaches active_runtime. The test therefore proves the no-network guarantee only for the "not installed" case. The installed case walks the manifest, the file records and package_metadata, which is the path that a future change could make contact the network.

Publish a synthetic runtime first, then run status and resolve with opener patched to raise.

💚 Proposed extension
     def test_status_and_resolve_never_open_network(self):
         with tempfile.TemporaryDirectory() as text:
-            self.m.ROOT = Path(text) / "missing-runtime"
+            root = Path(text)
+            self.m.ROOT = root / "missing-runtime"
             with mock.patch.object(
                 self.m, "bundled_version", return_value="0.147.0"
             ), mock.patch.object(
                 self.m, "opener", side_effect=AssertionError("network used")
             ):
                 for command in (["status"], ["resolve"]):
                     with self.subTest(command=command[0]):
                         stdout = io.StringIO()
                         with contextlib.redirect_stdout(stdout):
                             self.assertEqual(self.m.main(command), 0)
                         self.assertTrue(stdout.getvalue().strip())
+
+            asset = self.asset()
+            self.m.ROOT = root / "runtime"
+            with mock.patch.object(self.m, "target", return_value=asset["target"]):
+                self.m.publish(self.package(root), asset, asset["url"])
+                with mock.patch.object(
+                    self.m, "bundled_version", return_value="0.147.0"
+                ), mock.patch.object(
+                    self.m, "opener", side_effect=AssertionError("network used")
+                ):
+                    for command in (["status"], ["resolve"]):
+                        with self.subTest(command=command[0], installed=True):
+                            stdout = io.StringIO()
+                            with contextlib.redirect_stdout(stdout):
+                                self.assertEqual(self.m.main(command), 0)
+                            self.assertTrue(stdout.getvalue().strip())
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test-remote-dev-codex-runtime.py` around lines 310 - 323, Update
test_status_and_resolve_never_open_network to publish a synthetic runtime before
invoking status and resolve, so self.m.ROOT represents an installed runtime and
exercises state(), manifest, file-record, and package_metadata handling. Keep
opener patched to raise and retain the assertions that both commands return
successfully with non-empty output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/security.md`:
- Line 59: Update the origin claim in the Codex runtime security documentation
to state that requests use the allowlisted URL origins with TLS verification
against the system CA bundle, including redirects, while a configured HTTP(S)
proxy may act as an intermediary. Also document that CODEX_CA_CERTIFICATE adds
an operator-supplied CA to the same verification; do not claim the updater
connects directly to official origins.

In `@README.es.md`:
- Line 175: Update the Spanish README instruction to replace “realiza los login
de Codex/GitHub” with the natural phrasing “inicia sesión en Codex y GitHub”,
leaving the rest of the sentence unchanged.

In `@scripts/remote-dev-codex-runtime.py`:
- Around line 944-956: Update remove_runtime_entry to catch OSError from both
shutil.rmtree and path.unlink, then route each failure through fail with the
affected path and error details so main reports a standard ManagerError. Ensure
removal failures do not escape as raw exceptions.

In `@scripts/run-codex.sh`:
- Around line 176-177: Update the runtime-manager invocation that assigns
resolved_codex_binary to use a Bash array containing the executable path and
resolve argument, then invoke it with array expansion so the command and
arguments are passed directly without re-evaluation.

In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 219-239: Extend
test_successful_publication_retains_previous_generation with a third publish
using a distinct asset, then assert the first release directory is removed while
the second and third release directories remain. Preserve the existing
assertions that the current generation changes and the immediately previous
generation survives.

In `@scripts/test-run-codex-policy.sh`:
- Around line 183-200: Extend the test setup’s fake-manager modes to simulate
the resolver returning the bundled sentinel and returning a successful but
non-executable path. Add test cases invoking the launcher for each mode,
asserting bundled identity and expected arguments, and verifying the fallback
warning in stderr, alongside the existing resolver-failure case.
- Around line 137-147: Rename the scalar variables in assert_identity from
expected and actual to expected_identity and actual_identity, updating their
assignment, read, comparison, and error message references while leaving the
array variables used by assert_args unchanged.

---

Outside diff comments:
In `@docs/codex-runtime-updates.md`:
- Around line 18-34: Align the runtime command documentation with the
remote-dev-codex-runtime.py CLI contract: document install, update, and remove,
including --yes for lifecycle commands, and describe removal in the menu while
keeping explicit network-access behavior accurate. Apply these updates in
docs/codex-runtime-updates.md (18-34 and 93-104),
docs/codex-runtime-updates.es.md (18-34 and 93-105), README.md (105-112), and
README.es.md (90-97); ensure install is presented as a supported public command
rather than an undocumented alias.

In `@scripts/remote-dev-codex-runtime.py`:
- Around line 698-708: Update the release-pruning loop around keep_names and
releases.iterdir() to delete stale .candidate-* directories as well as other
unkept release directories, while retaining the current run’s staging directory
until its existing finally cleanup. Perform this cleanup within the same publish
lock and preserve the existing safeguards against deleting symlinks or
non-directories.

---

Duplicate comments:
In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 310-323: Update test_status_and_resolve_never_open_network to
publish a synthetic runtime before invoking status and resolve, so self.m.ROOT
represents an installed runtime and exercises state(), manifest, file-record,
and package_metadata handling. Keep opener patched to raise and retain the
assertions that both commands return successfully with non-empty output.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 35333431-0b0d-40d3-b02f-88408d52e44d

📥 Commits

Reviewing files that changed from the base of the PR and between 879ab15 and 411534f.

📒 Files selected for processing (12)
  • README.es.md
  • README.md
  • docs/architecture.md
  • docs/codex-runtime-updates.es.md
  • docs/codex-runtime-updates.md
  • docs/security.md
  • docs/tool-matrix.md
  • scripts/remote-dev-codex-runtime.py
  • scripts/run-codex.sh
  • scripts/test-remote-dev-codex-runtime.py
  • scripts/test-run-codex-policy.sh
  • scripts/test_canonical_data_layout.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly to main. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets, SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces, eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update #31 when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.

Files:

  • docs/security.md
  • docs/tool-matrix.md
  • docs/architecture.md
  • scripts/run-codex.sh
  • scripts/test-remote-dev-codex-runtime.py
  • docs/codex-runtime-updates.md
  • README.md
  • scripts/test_canonical_data_layout.py
  • docs/codex-runtime-updates.es.md
  • README.es.md
  • scripts/test-run-codex-policy.sh
  • scripts/remote-dev-codex-runtime.py
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.

Files:

  • docs/security.md
  • docs/tool-matrix.md
  • docs/architecture.md
  • docs/codex-runtime-updates.md
  • README.md
  • docs/codex-runtime-updates.es.md
  • README.es.md
**/*.{sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such as CODEX_HOME inside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.

Files:

  • scripts/run-codex.sh
  • scripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash, Dockerfile}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.

Files:

  • scripts/run-codex.sh
  • scripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash,html,js,ts}

📄 CodeRabbit inference engine (AGENTS.md)

The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.

Files:

  • scripts/run-codex.sh
  • scripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.

Files:

  • scripts/run-codex.sh
  • scripts/test-run-codex-policy.sh
**/*.{sh,bash,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must set AGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.

Files:

  • scripts/run-codex.sh
  • scripts/test-run-codex-policy.sh
scripts/**/*.sh

⚙️ CodeRabbit configuration file

scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.

Files:

  • scripts/run-codex.sh
  • scripts/test-run-codex-policy.sh
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py

[info] 84-84: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 97-97: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 145-145: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 LanguageTool
README.md

[style] ~288-~288: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...er. - Do not mount the Docker socket. - Do not use privileged mode. - The default ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py

[warning] 21-21: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 149-149: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 213-213: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 326-337: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


[warning] 337-337: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)

scripts/remote-dev-codex-runtime.py

[error] 173-173: subprocess call: check for execution of untrusted input

(S603)

🪛 Shellcheck (0.11.0)
scripts/test-run-codex-policy.sh

[warning] 138-138: Variable was used as an array but is now assigned a string.

(SC2178)


[warning] 140-140: Variable was used as an array but is now assigned a string.

(SC2178)


[warning] 146-146: Expanding an array without an index only gives the first element.

(SC2128)


[warning] 147-147: Expanding an array without an index only gives the first element.

(SC2128)

🔇 Additional comments (25)
README.es.md (1)

26-26: LGTM!

Also applies to: 58-58, 123-123, 132-132, 156-156, 219-239

README.md (1)

21-21: LGTM!

Also applies to: 71-71, 140-140, 149-149, 192-192, 212-215, 261-276, 286-294, 320-321

docs/codex-runtime-updates.es.md (1)

1-16: LGTM!

Also applies to: 36-65, 67-83, 85-91, 106-120

docs/codex-runtime-updates.md (1)

1-16: LGTM!

Also applies to: 36-65, 67-83, 85-91, 106-120

scripts/remote-dev-codex-runtime.py (9)

53-59: LGTM!


98-137: LGTM!


149-167: LGTM!

Also applies to: 170-186


202-238: LGTM!


393-425: LGTM!


457-511: LGTM!


514-583: LGTM!


851-898: LGTM!

Also applies to: 959-1007


806-816: 🚀 Performance & Scalability

Confirm the launch-path cost of full-package hashing.

resolve calls state(), and state() runs active_runtime(), which computes file_sha() for every manifest-record file and walks package.rglob("*") twice for the file-set and symlink checks. scripts/run-codex.sh resolves the runtime on every Codex launch.

Measure the added launch latency on the target hardware. If it is material, bound the full-package hash to a protected state-check path and keep owner, mode, size, and file-set checks on the launch path. Merge the redundant rglob("*") passes to reduce directory traversal.

scripts/test-remote-dev-codex-runtime.py (5)

18-25: LGTM!

Also applies to: 32-87


89-150: LGTM!


152-198: LGTM!


241-309: LGTM!


325-347: LGTM!

scripts/test_canonical_data_layout.py (1)

111-119: LGTM!

Also applies to: 152-161

docs/architecture.md (1)

124-124: LGTM!

Also applies to: 139-139, 165-165

docs/security.md (1)

48-48: LGTM!

docs/tool-matrix.md (1)

39-39: LGTM!

Also applies to: 54-60

scripts/run-codex.sh (2)

4-9: LGTM!

Also applies to: 180-184


185-190: 🔒 Security & Privacy

No change needed. remote-dev-codex-runtime resolve uses state() / active_runtime(), which checks current-pointer regular-file identity, rejects malformed pointers, validates the private manifest and package file set against file paths, sizes, SHA-256, symlinks, permissions, and owner identity, and does not call the update network path.

scripts/test-run-codex-policy.sh (1)

7-13: LGTM!

Also applies to: 30-78, 94-104, 115-115, 152-158, 238-255, 288-304, 335-335

Comment thread docs/security.md Outdated
Comment thread README.es.md Outdated
Comment thread scripts/remote-dev-codex-runtime.py Outdated
Comment thread scripts/run-codex.sh Outdated
Comment thread scripts/test-remote-dev-codex-runtime.py
Comment thread scripts/test-run-codex-policy.sh Outdated
Comment thread scripts/test-run-codex-policy.sh
@eXPerience83
eXPerience83 force-pushed the feat/codex-runtime-updates branch from 962b68b to 0a70d68 Compare August 8, 2026 07:04
@eXPerience83
eXPerience83 force-pushed the feat/codex-runtime-updates branch from 0a70d68 to d818bfe Compare August 8, 2026 07:10
@eXPerience83

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

1 similar comment
@eXPerience83

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/codex-runtime-updates.md`:
- Line 12: Add an explicit statement to docs/codex-runtime-updates.md:12 that
the Remote Dev edge image remains experimental, and link to docs/releases.md or
README.md. Add the equivalent Spanish statement and link at
docs/codex-runtime-updates.es.md:12, ensuring both documents distinguish stable
upstream packages from stable Remote Dev releases.

In `@README.md`:
- Line 149: Update the README runtime-state layout description to include all
managed runtime state: the active pointer at state/codex/runtime/current,
release directories, package files, and integrity manifests such as
remote-dev-runtime.json. Preserve the existing distinctions for CODEX_HOME and
launcher-auth mounts while correcting the claim that runtime contains only a
package and manifest.

In `@scripts/remote-dev-version.sh`:
- Around line 56-62: Update print_codex_runtime_status to capture the
runtime_manager status output and exit code before piping it through sed. If the
status command fails, report the runtime status as unavailable and return
successfully so optional runtime damage cannot abort immutable image identity
reporting; otherwise preserve the existing filtered output.

In `@scripts/secure-persistent-state.sh`:
- Line 14: Move the codex_runtime_root assignment into the existing
Codex-specific branch in scripts/secure-persistent-state.sh, and keep the
hardening call that uses it within that same branch. Ensure non-Codex roles
neither define nor process this Codex-specific path.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8fec6ee9-d8a4-4163-a4e7-7f1461cd2115

📥 Commits

Reviewing files that changed from the base of the PR and between 1f06bf8 and d818bfe.

📒 Files selected for processing (23)
  • .github/workflows/build-amd64.yml
  • README.es.md
  • README.md
  • compose/docker-compose.yml
  • compose/truenas.yml
  • docs/architecture.md
  • docs/codex-runtime-updates.es.md
  • docs/codex-runtime-updates.md
  • docs/security.md
  • docs/tool-matrix.md
  • images/codex/Dockerfile
  • scripts/preflight-data-layout.py
  • scripts/remote-dev-codex-runtime.py
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/secure-persistent-state.sh
  • scripts/test-remote-dev-codex-runtime.py
  • scripts/test-remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test_canonical_data_layout.py
  • scripts/test_preflight_data_layout.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly to main. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets, SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces, eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update #31 when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.

Files:

  • docs/tool-matrix.md
  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • scripts/preflight-data-layout.py
  • scripts/test-remote-dev-codex-runtime.py
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • images/codex/Dockerfile
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
  • docs/security.md
  • docs/architecture.md
  • scripts/test_canonical_data_layout.py
  • scripts/remote-dev-codex-runtime.py
  • docs/codex-runtime-updates.md
  • README.md
  • README.es.md
  • docs/codex-runtime-updates.es.md
  • scripts/test_preflight_data_layout.py
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.

Files:

  • docs/tool-matrix.md
  • docs/security.md
  • docs/architecture.md
  • docs/codex-runtime-updates.md
  • README.md
  • README.es.md
  • docs/codex-runtime-updates.es.md
**/*.{yml,yaml,sh,bash, Dockerfile}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash,html,js,ts}

📄 CodeRabbit inference engine (AGENTS.md)

The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
**/*.{sh,bash,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must set AGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
compose/**

⚙️ CodeRabbit configuration file

compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Require launcher and agent services to reference one image while keeping agent state out of the launcher.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
**/*.{sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such as CODEX_HOME inside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.

Files:

  • scripts/secure-persistent-state.sh
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
scripts/**/*.sh

⚙️ CodeRabbit configuration file

scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.

Files:

  • scripts/secure-persistent-state.sh
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
.github/workflows/**

⚙️ CodeRabbit configuration file

.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.

Files:

  • .github/workflows/build-amd64.yml
images/**/Dockerfile

⚙️ CodeRabbit configuration file

images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.

Files:

  • images/codex/Dockerfile
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py

[info] 84-84: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 97-97: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 107-107: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 145-145: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

scripts/remote-dev-codex-runtime.py

[error] 172-179: Command coming from incoming request
Context: subprocess.run(
[str(BUNDLED), "--version"],
check=True,
text=True,
capture_output=True,
timeout=10,
env={"PATH": "/usr/bin:/bin"},
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 460-469: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 514-523: Command coming from incoming request
Context: subprocess.Popen(
[str(host), "--listen", "ws://127.0.0.1:0"],
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 460-469: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[info] 688-688: use jsonify instead of json.dumps for JSON output
Context: json.dumps(manifest, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 LanguageTool
docs/codex-runtime-updates.md

[style] ~87-~87: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ...ume paths continue through run-codex. The launcher first validates the project-owned approval/sa...

(SENT_START_FIRST_PREMIUM)

README.md

[style] ~288-~288: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...er. - Do not mount the Docker socket. - Do not use privileged mode. - The default ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py

[warning] 21-21: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 110-110: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 121-121: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 130-130: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 149-149: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 213-213: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 326-337: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


[warning] 337-337: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)

scripts/remote-dev-codex-runtime.py

[error] 173-173: subprocess call: check for execution of untrusted input

(S603)


[error] 305-307: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.

(S310)


[error] 461-461: subprocess call: check for execution of untrusted input

(S603)


[warning] 469-469: preexec_fn argument is unsafe when using threads

(PLW1509)


[error] 515-515: subprocess call: check for execution of untrusted input

(S603)


[warning] 523-523: preexec_fn argument is unsafe when using threads

(PLW1509)


[warning] 747-747: Too many branches (15 > 12)

(PLR0912)


[warning] 747-747: Too many statements (52 > 50)

(PLR0915)


[warning] 1004-1004: Consider moving this statement to an else block

(TRY300)

🔇 Additional comments (22)
README.md (1)

21-21: LGTM!

Also applies to: 71-71, 105-112, 140-140, 192-192, 212-215, 261-276, 286-294, 320-321

docs/codex-runtime-updates.es.md (1)

1-11: LGTM!

Also applies to: 13-120

docs/codex-runtime-updates.md (1)

1-11: LGTM!

Also applies to: 13-120

README.es.md (2)

58-58: LGTM!

Also applies to: 90-97, 123-123, 132-132, 156-156, 175-175, 219-219, 228-228, 232-232, 239-239


26-26: 📐 Maintainability & Code Quality

No change needed.

The documented image inventory matches the pinned builds and CI coverage.

scripts/remote-dev-codex-runtime.py (1)

32-71: LGTM!

Also applies to: 110-167, 189-238, 241-334, 337-425, 428-511, 514-583, 612-711, 714-821, 824-889, 892-941, 944-1014

scripts/test-remote-dev-codex-runtime.py (1)

1-352: LGTM!

.github/workflows/build-amd64.yml (1)

33-34: LGTM!

Also applies to: 51-51

scripts/run-codex.sh (1)

4-9: LGTM!

Also applies to: 176-190

scripts/remote-dev-doctor.sh (1)

55-55: LGTM!

Also applies to: 98-98, 125-137, 186-189

scripts/remote-dev-menu.sh (1)

86-95: LGTM!

Also applies to: 176-201, 213-233

scripts/test-run-codex-policy.sh (1)

7-13: LGTM!

Also applies to: 30-78, 94-104, 115-115, 137-158, 185-200, 238-255, 288-304

scripts/test-remote-dev-menu.sh (1)

9-13: LGTM!

Also applies to: 78-93, 125-125, 135-174, 185-204, 216-235

docs/tool-matrix.md (1)

39-39: 📐 Maintainability & Code Quality

No change needed. The optional Antigravity service has its own private runtime mount at /root/.local/share/remote-dev/antigravity, matching the Private entry.

			> Likely an incorrect or invalid review comment.
images/codex/Dockerfile (1)

27-27: LGTM!

Also applies to: 86-86, 111-112, 124-124, 148-153, 219-219

compose/docker-compose.yml (1)

54-54: LGTM!

Also applies to: 103-107

compose/truenas.yml (1)

56-56: LGTM!

Also applies to: 106-110

scripts/preflight-data-layout.py (1)

15-15: LGTM!

scripts/test_preflight_data_layout.py (1)

18-18: LGTM!

Also applies to: 175-183, 232-232

scripts/test_canonical_data_layout.py (1)

18-24: LGTM!

Also applies to: 111-119, 152-161, 236-237, 246-246

docs/architecture.md (1)

124-124: LGTM!

Also applies to: 139-139, 165-165

docs/security.md (1)

48-48: LGTM!

Also applies to: 59-60

Comment thread docs/codex-runtime-updates.md
Comment thread README.md Outdated
Comment thread scripts/remote-dev-version.sh
Comment thread scripts/secure-persistent-state.sh Outdated
@eXPerience83

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/codex/Dockerfile`:
- Line 27: Remove REMOTE_DEV_CODEX_RUNTIME_ROOT from the image-wide ENV
declaration in the Dockerfile, and define it only within the Codex role or Codex
entrypoint. Preserve the helper’s existing internal fallback so direct Codex
invocations continue to work without the environment variable.

In `@README.md`:
- Around line 261-276: The README.md example for remote-dev-version must
document the missing bundled Codex case by including “Codex CLI: unavailable”
alongside the existing bundled-version output. Update README.es.md’s
corresponding description to state that optional runtime version, trust, and
source details are shown only when available; otherwise the command reports
“Codex runtime: unavailable”.

In `@scripts/remote-dev-codex-runtime.py`:
- Around line 662-673: Update publish to catch OSError from the staging and
manifest operations, including copytree, chmod/stat processing, and write_text,
and route the caught exception through fail so it becomes ManagerError with the
standard error message. Keep the existing finally cleanup and successful
publishing behavior unchanged.
- Around line 774-816: Extract the manifest file-record validation and package
integrity checks from active_runtime into a helper such as
verify_package_files(package, manifest), returning expected_paths. Preserve all
existing validation, hash, size, path, symlink, and file-set checks unchanged,
and replace the inline block in active_runtime with a call to the helper so it
retains only pointer, manifest, and version resolution.
- Around line 569-579: Update the readiness poll around the HTTPConnection
request in the remote runtime script to catch both OSError and
http.client.HTTPException, including BadStatusLine, while preserving the
existing retry behavior and connection cleanup so failures reach main’s ERROR
reporting path without an unhandled traceback.

In `@scripts/remote-dev-doctor.sh`:
- Line 98: Update the remote-dev-codex-runtime checks and execution near
check_cmd and status to use the trusted absolute path
/usr/local/bin/remote-dev-codex-runtime instead of PATH resolution. Build the
status invocation as a Bash array and reuse it for execution, while preserving
the existing diagnostic and status behavior.

In `@scripts/run-codex.sh`:
- Line 177: Update the runtime-manager command invocations to use Bash arrays,
preserving executable and argument boundaries: in scripts/run-codex.sh lines
177-177, create runtime_manager_command for "$runtime_manager" resolve and
invoke it via array expansion; in scripts/remote-dev-version.sh lines 62-62,
create an array for "$runtime_manager" status before command substitution; and
in scripts/remote-dev-menu.sh lines 88-88, create an array for
/usr/local/bin/remote-dev-codex-runtime status --menu before command
substitution.

In `@scripts/secure-persistent-state.sh`:
- Around line 47-50: Validate and canonicalize codex_runtime_root before calling
secure_private_tree: require an absolute, non-symlinked directory located within
the dedicated Codex runtime parent, and reject invalid or unsafe
REMOTE_DEV_CODEX_RUNTIME_ROOT values with a clear error. Ensure the validation
path flags the recursive permission mutation before secure_private_tree can run.

In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 89-111: Add negative cases to
test_release_metadata_requires_exact_stable_tag_and_digest covering release
metadata with a digest missing the sha256: prefix, a non-hex digest, and package
sizes of 0 and greater than MAX_PACKAGE. Assert each invalid payload raises
ManagerError, while preserving the existing exact stable tag assertion and test
setup.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cbd0a10b-e0c0-4301-99af-f13445e9190d

📥 Commits

Reviewing files that changed from the base of the PR and between 1f06bf8 and fd406af.

📒 Files selected for processing (23)
  • .github/workflows/build-amd64.yml
  • README.es.md
  • README.md
  • compose/docker-compose.yml
  • compose/truenas.yml
  • docs/architecture.md
  • docs/codex-runtime-updates.es.md
  • docs/codex-runtime-updates.md
  • docs/security.md
  • docs/tool-matrix.md
  • images/codex/Dockerfile
  • scripts/preflight-data-layout.py
  • scripts/remote-dev-codex-runtime.py
  • scripts/remote-dev-doctor.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-version.sh
  • scripts/run-codex.sh
  • scripts/secure-persistent-state.sh
  • scripts/test-remote-dev-codex-runtime.py
  • scripts/test-remote-dev-menu.sh
  • scripts/test-run-codex-policy.sh
  • scripts/test_canonical_data_layout.py
  • scripts/test_preflight_data_layout.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly to main. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets, SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces, eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update #31 when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.

Files:

  • scripts/preflight-data-layout.py
  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • docs/security.md
  • docs/architecture.md
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/test_canonical_data_layout.py
  • scripts/remote-dev-menu.sh
  • docs/tool-matrix.md
  • README.md
  • docs/codex-runtime-updates.md
  • scripts/remote-dev-doctor.sh
  • images/codex/Dockerfile
  • scripts/test-remote-dev-codex-runtime.py
  • docs/codex-runtime-updates.es.md
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
  • scripts/test_preflight_data_layout.py
  • scripts/remote-dev-codex-runtime.py
  • README.es.md
**/*.{yml,yaml,sh,bash, Dockerfile}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
**/*.{yml,yaml,sh,bash,html,js,ts}

📄 CodeRabbit inference engine (AGENTS.md)

The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
**/*.{yml,yaml,sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
**/*.{sh,bash,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must set AGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.

Files:

  • compose/truenas.yml
  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • compose/docker-compose.yml
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
compose/**

⚙️ CodeRabbit configuration file

compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Require launcher and agent services to reference one image while keeping agent state out of the launcher.

Files:

  • compose/truenas.yml
  • compose/docker-compose.yml
**/*.{sh,bash}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such as CODEX_HOME inside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.

Files:

  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
scripts/**/*.sh

⚙️ CodeRabbit configuration file

scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.

Files:

  • scripts/secure-persistent-state.sh
  • scripts/remote-dev-version.sh
  • scripts/test-remote-dev-menu.sh
  • scripts/remote-dev-menu.sh
  • scripts/remote-dev-doctor.sh
  • scripts/test-run-codex-policy.sh
  • scripts/run-codex.sh
.github/workflows/**

⚙️ CodeRabbit configuration file

.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.

Files:

  • .github/workflows/build-amd64.yml
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.

Files:

  • docs/security.md
  • docs/architecture.md
  • docs/tool-matrix.md
  • README.md
  • docs/codex-runtime-updates.md
  • docs/codex-runtime-updates.es.md
  • README.es.md
images/**/Dockerfile

⚙️ CodeRabbit configuration file

images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.

Files:

  • images/codex/Dockerfile
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py

[info] 84-84: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 97-97: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 107-107: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 145-145: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

scripts/remote-dev-codex-runtime.py

[error] 460-469: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 172-179: Command coming from incoming request
Context: subprocess.run(
[str(BUNDLED), "--version"],
check=True,
text=True,
capture_output=True,
timeout=10,
env={"PATH": "/usr/bin:/bin"},
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 460-469: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 514-523: Command coming from incoming request
Context: subprocess.Popen(
[str(host), "--listen", "ws://127.0.0.1:0"],
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[info] 688-688: use jsonify instead of json.dumps for JSON output
Context: json.dumps(manifest, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 LanguageTool
README.md

[style] ~288-~288: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...er. - Do not mount the Docker socket. - Do not use privileged mode. - The default ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

docs/codex-runtime-updates.md

[style] ~89-~89: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ...ume paths continue through run-codex. The launcher first validates the project-owned approval/sa...

(SENT_START_FIRST_PREMIUM)

🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py

[warning] 21-21: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 110-110: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 121-121: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 130-130: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 149-149: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 213-213: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)


[warning] 326-337: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


[warning] 337-337: Use pytest.raises instead of unittest-style assertRaisesRegex

Replace assertRaisesRegex with pytest.raises

(PT027)

scripts/remote-dev-codex-runtime.py

[error] 173-173: subprocess call: check for execution of untrusted input

(S603)


[error] 305-307: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.

(S310)


[error] 461-461: subprocess call: check for execution of untrusted input

(S603)


[warning] 469-469: preexec_fn argument is unsafe when using threads

(PLW1509)


[error] 515-515: subprocess call: check for execution of untrusted input

(S603)


[warning] 523-523: preexec_fn argument is unsafe when using threads

(PLW1509)


[warning] 747-747: Too many branches (15 > 12)

(PLR0912)


[warning] 747-747: Too many statements (52 > 50)

(PLR0915)


[warning] 1004-1004: Consider moving this statement to an else block

(TRY300)

🔇 Additional comments (45)
scripts/run-codex.sh (1)

4-9: LGTM!

Also applies to: 176-176, 178-190

scripts/remote-dev-version.sh (1)

6-6: LGTM!

Also applies to: 43-54, 56-61, 63-81

scripts/remote-dev-doctor.sh (1)

55-55: LGTM!

Also applies to: 186-189

scripts/remote-dev-menu.sh (1)

86-87: LGTM!

Also applies to: 89-95, 177-238

scripts/test-run-codex-policy.sh (1)

7-13: LGTM!

Also applies to: 30-78, 94-104, 115-115, 137-158, 185-200, 238-255, 288-304

scripts/test-remote-dev-menu.sh (1)

9-13: LGTM!

Also applies to: 78-93, 125-125, 135-171, 185-204, 216-235

README.es.md (1)

26-26: LGTM!

Also applies to: 58-58, 90-97, 123-123, 132-132, 156-156, 175-175, 221-239

docs/codex-runtime-updates.md (2)

40-45: 📐 Maintainability & Code Quality

Clarify the supported updater boundary for Arm64/Aarch64.

The runtime-manager, Dockerfile, inventory checks, and release-pin workflow all accept both x86_64-unknown-linux-musl and aarch64-unknown-linux-musl Codex packages, but the published CI and images build/publish only linux/amd64/stable-amd64 and tag edge/edge-amd64. State whether aarch64 packages are official upstream boundaries supported by this repo, or mark them as unsupported/future in both English and Spanish docs.


1-122: LGTM!

images/codex/Dockerfile (1)

86-86: LGTM!

Also applies to: 111-112, 124-124, 148-153, 219-219

compose/docker-compose.yml (1)

54-54: LGTM!

Also applies to: 103-107

compose/truenas.yml (1)

56-56: LGTM!

Also applies to: 106-110

scripts/preflight-data-layout.py (1)

15-15: LGTM!

scripts/test_preflight_data_layout.py (1)

18-18: LGTM!

Also applies to: 175-183, 232-232

scripts/test_canonical_data_layout.py (1)

18-24: LGTM!

Also applies to: 111-119, 152-161, 236-237, 246-246

docs/architecture.md (1)

124-124: LGTM!

Also applies to: 139-139, 165-165

docs/security.md (1)

48-48: LGTM!

Also applies to: 59-60

docs/tool-matrix.md (1)

39-39: LGTM!

Also applies to: 54-60

README.md (1)

21-21: LGTM!

Also applies to: 71-71, 105-112, 140-140, 149-149, 192-192, 212-215, 261-276, 286-294, 320-321

docs/codex-runtime-updates.es.md (1)

1-122: LGTM!

scripts/remote-dev-codex-runtime.py (19)

32-71: LGTM!


82-145: LGTM!


148-168: LGTM!


170-186: LGTM!


189-238: LGTM!


241-301: LGTM!


304-334: LGTM!


337-390: LGTM!


393-425: LGTM!


428-455: LGTM!


457-511: LGTM!


586-609: LGTM!


612-643: LGTM!


714-744: LGTM!


824-848: LGTM!


851-889: LGTM!


892-941: LGTM!


944-972: LGTM!


975-1010: LGTM!

scripts/test-remote-dev-codex-runtime.py (5)

18-30: LGTM!


32-87: LGTM!


152-239: LGTM!


241-323: LGTM!


325-351: LGTM!

.github/workflows/build-amd64.yml (1)

33-34: LGTM!

Also applies to: 51-51

Comment thread images/codex/Dockerfile Outdated
Comment thread README.md
Comment thread scripts/remote-dev-codex-runtime.py
Comment thread scripts/remote-dev-codex-runtime.py
Comment thread scripts/remote-dev-codex-runtime.py
Comment thread scripts/remote-dev-doctor.sh Outdated
Comment thread scripts/run-codex.sh Outdated
Comment thread scripts/secure-persistent-state.sh
Comment thread scripts/test-remote-dev-codex-runtime.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: allow explicit Codex runtime updates with bundled fallback

1 participant