feat: add the isolated single-stack launcher - #64
Conversation
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (10)
Summary by CodeRabbit
WalkthroughThe PR adds an authenticated Remote Dev launcher beside the Codex terminal. Both services use one image with separate credentials and state. Runtime roles, health checks, Compose topology, security controls, documentation, and automated validation are updated. ChangesRemote Dev launcher stack
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant Browser
participant RemoteDevLauncher
participant CodexTTYD
Browser->>RemoteDevLauncher: Authenticate and request launcher page
RemoteDevLauncher-->>Browser: Return validated Codex endpoint link
Browser->>CodexTTYD: Authenticate and open terminal
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
|
@codex review Please review the exact head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f25e9133cc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review Please review the updated exact head |
There was a problem hiding this comment.
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 @.env.example:
- Around line 26-29: Rename the documented environment variables in the
`.env.example` block from REMOTE_DEV_CODEX_PUBLIC_HOST and
REMOTE_DEV_CODEX_PUBLIC_SCHEME to REMOTE_DEV_LAUNCHER_CODEX_HOST and
REMOTE_DEV_LAUNCHER_CODEX_SCHEME, preserving their existing comments and empty
defaults.
In `@compose/docker-compose.yml`:
- Line 21: Update the launcher service’s ALLOW_INSECURE_WEB configuration to use
a LAUNCHER_-prefixed environment variable, separating it from the Codex
service’s override while preserving the existing default value and
launcher-specific setting pattern.
- Line 8: Update the launcher service definition in docker-compose.yml to run
with an explicit non-root user instead of user "0:0"; choose a service-specific
unprivileged UID/GID compatible with the image and preserve the launcher’s
access to its secret and Python HTTP server.
In `@compose/truenas.yml`:
- Line 37: Rename the host-side secret source in the TrueNAS compose mount from
web_password.txt to launcher_password.txt, while preserving the
/run/secrets/launcher_password destination and read-only mode. Update all
English and Spanish deployment documentation references to use the new
launcher_password.txt path.
In `@docs/architecture.md`:
- Around line 146-156: The TrueNAS launcher secret filename differs from the
compose-mounted secret and local configuration. Align the launcher secret path
in the architecture documentation with the filename used by the compose mount
and local config, while preserving the existing Codex secret path.
In `@docs/security.md`:
- Line 24: Update the `/healthz` descriptions to use accurate network-scope
wording: in docs/security.md lines 24-24, describe it as an unauthenticated,
secret-free health endpoint; in docs/architecture.md lines 107-107, remove
“local” from the healthcheck description.
In `@scripts/test_single_stack_compose.py`:
- Around line 135-153: Update the credential validation around the top-level
secrets and bind-mount checks to require exactly one launcher credential source
and exactly one Codex credential source. Ensure each service has either its
corresponding top-level secret or password bind mount, reject missing sources
and multiple sources, and retain the existing checks that the launcher and Codex
sources are independent.
- Around line 18-31: Update FORBIDDEN_LAUNCHER_TEXT to also reject the socket
path without the /var prefix and Podman socket mount paths, ensuring all valid
Docker/Podman socket spellings are covered; you may use a broader docker.sock
entry if preferred.
- Around line 34-37: Update compose_config so docker compose config receives a
minimal, explicitly constructed environment rather than os.environ.copy(), while
preserving only the variables required for Compose invocation and committed
defaults. Ensure exported values such as LAUNCHER_BASE_PATH, LAUNCHER_USERNAME,
and WEB_BASE_PATH cannot alter rendering, so the existing topology assertions
deterministically validate image references, roles, launcher isolation, Docker
access restrictions, and Codex compatibility.
🪄 Autofix (Beta)
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: 07b497b2-ab76-4541-9bee-32910227d379
📒 Files selected for processing (25)
.coderabbit.yaml.env.example.github/workflows/build-amd64.ymlAGENTS.mdCHANGELOG.mdMakefilePROJECT_STATUS.mdREADME.es.mdREADME.mdcompose/docker-compose.ymlcompose/truenas.ymldocs/architecture.mddocs/releases.mddocs/security.mdimages/codex/Dockerfilescripts/lib/remote-dev-runtime.shscripts/remote-dev-doctor.shscripts/remote-dev-healthcheck.shscripts/remote-dev-launcher.pyscripts/runtime-smoke-test.shscripts/start-remote-dev-web.shscripts/test-compose-image-compat.shscripts/test-remote-dev-launcher.shscripts/test-role-neutral-runtime.shscripts/test_single_stack_compose.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (7)
.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
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Before changing runtime architecture or support claims, read the current GitHub issues listed as sources of truth; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly tomain. Keep one focused objective per PR and obtain approval before adding a subsystem or changing the agreed PR boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; prefer explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for Antigravity or Claude Code. 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 documented and reviewed removal point.
A PR is merge-ready only when the exact final head has the requiredbuildcheck green, review findings are evaluated and fixed, conversations are resolved, and the branch is up to date withmain; use squash merge.
Never use privileged containers, Docker or Podman sockets,SYS_ADMIN, host-root mounts, or broad/root,/home,/opt,/usr/local, or parent data-root persistence.
Do not share writable agent credentials, GitHub CLI state, Git configuration, SSH state, caches, histories, or workspaces between role services.
Do not give the launcher access to agent credentials or workspaces.
Never expose secret values in diagnostics, logs, tests, issues, or pull-request descriptions.
Treat the supported TrueNAS isolation boundary as the outer container. Approval prompts are not a sandbox or isolation boundary, and Bubblewrap, Landlock, or another inner sandbox must not be claimed active without a positive runtime test proving it.
Keep product-specific variables such asCODEX_HOMEinside the C...
Files:
scripts/start-remote-dev-web.shscripts/remote-dev-healthcheck.shscripts/test-role-neutral-runtime.shscripts/test-compose-image-compat.shMakefilescripts/runtime-smoke-test.shdocs/security.mdcompose/truenas.ymlAGENTS.mdcompose/docker-compose.ymlscripts/lib/remote-dev-runtime.shscripts/remote-dev-doctor.shimages/codex/Dockerfilescripts/test_single_stack_compose.pyscripts/test-remote-dev-launcher.shdocs/releases.mdCHANGELOG.mdREADME.es.mdREADME.mdPROJECT_STATUS.mdscripts/remote-dev-launcher.pydocs/architecture.md
**/*.{sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash}: Never useeval, sourced editable state, or user-controlled shell fragments for role, mode, installer, routing, or command dispatch.
Use fixed, validated enums for roles and start modes; reject unknown values with a deterministic non-zero exit status and a clear message.
Build command invocations with Bash arrays, preserve arguments without re-evaluating them, and preserve command exit status.
Files:
scripts/start-remote-dev-web.shscripts/remote-dev-healthcheck.shscripts/test-role-neutral-runtime.shscripts/test-compose-image-compat.shscripts/runtime-smoke-test.shscripts/lib/remote-dev-runtime.shscripts/remote-dev-doctor.shscripts/test-remote-dev-launcher.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/start-remote-dev-web.shscripts/remote-dev-healthcheck.shscripts/test-role-neutral-runtime.shscripts/test-compose-image-compat.shscripts/runtime-smoke-test.shscripts/lib/remote-dev-runtime.shscripts/remote-dev-doctor.shscripts/test-remote-dev-launcher.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/security.mdAGENTS.mddocs/releases.mdCHANGELOG.mdREADME.es.mdREADME.mdPROJECT_STATUS.mddocs/architecture.md
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.
Files:
compose/truenas.ymlcompose/docker-compose.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/runtime-smoke-test.sh
[warning] 8-8: A credential-bearing variable (e.g. PASSWORD, PASSWD, SECRET, TOKEN, API_KEY) is assigned a hardcoded string literal. Secrets committed to a script are exposed in source control, process listings, and shell history, and cannot be rotated without a code change. Read the value from a secrets manager or an injected environment variable at runtime instead (e.g. PASSWORD="${DB_PASSWORD:?must be set}"), and never commit the literal.
Context: launcher_secret='synthetic-launcher-secret'
Note: [CWE-798] Use of Hard-coded Credentials.
(hardcoded-password-assignment-bash)
scripts/test_single_stack_compose.py
[error] 37-55: Command coming from incoming request
Context: subprocess.run(
[
"docker",
"compose",
"--env-file",
str(env_file),
"-f",
str(path),
"config",
"--format",
"json",
],
cwd=ROOT,
env=env,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[info] 127-127: use jsonify instead of json.dumps for JSON output
Context: json.dumps(launcher, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
scripts/test-remote-dev-launcher.sh
[warning] 15-15: A credential-bearing variable (e.g. PASSWORD, PASSWD, SECRET, TOKEN, API_KEY) is assigned a hardcoded string literal. Secrets committed to a script are exposed in source control, process listings, and shell history, and cannot be rotated without a code change. Read the value from a secrets manager or an injected environment variable at runtime instead (e.g. PASSWORD="${DB_PASSWORD:?must be set}"), and never commit the literal.
Context: secret='synthetic-launcher-secret'
Note: [CWE-798] Use of Hard-coded Credentials.
(hardcoded-password-assignment-bash)
scripts/remote-dev-launcher.py
[info] 167-175: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
{
"host": config.codex_host,
"port": config.codex_port,
"scheme": config.codex_scheme,
"path": config.codex_path,
},
separators=(",", ":"),
)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 Betterleaks (1.7.0)
scripts/test-remote-dev-launcher.sh
[high] 65-66: Discovered a potential basic authorization token provided in a curl command, which could compromise the curl accessed resource.
(curl-auth-user)
🪛 dotenv-linter (4.0.0)
.env.example
[warning] 5-5: [UnorderedKey] The LAUNCHER_PASSWORD_PATH key should go before the REMOTE_DEV_IMAGE key
(UnorderedKey)
[warning] 11-11: [UnorderedKey] The LAUNCHER_BASE_PATH key should go before the LAUNCHER_PUBLISH_IP key
(UnorderedKey)
[warning] 13-13: [UnorderedKey] The LAUNCHER_CHECK_ORIGIN key should go before the LAUNCHER_PUBLISH_IP key
(UnorderedKey)
🪛 LanguageTool
docs/security.md
[style] ~48-~48: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...- Never mount /var/run/docker.sock. - Never use privileged: true, host PID, or ho...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
CHANGELOG.md
[style] ~68-~68: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...gacy package tags without rebuilding. - Changed the normal TrueNAS x-portal entry from ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~69-~69: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...enticated Codex port and data layout. - Changed the image healthcheck from Codex-specif...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
README.md
[style] ~224-~224: 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.0)
scripts/test_single_stack_compose.py
[warning] 38-56: Prefer capture_output over sending stdout and stderr to PIPE
Replace with capture_output keyword argument
(UP022)
[error] 38-38: subprocess call: check for execution of untrusted input
(S603)
[error] 39-49: Starting a process with a partial executable path
(S607)
[warning] 58-60: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 64-64: Boolean-typed positional argument in function definition
(FBT001)
scripts/remote-dev-launcher.py
[warning] 25-25: Boolean-typed positional argument in function definition
(FBT001)
[warning] 33-33: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 41-41: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 43-43: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 49-51: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 61-61: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 63-63: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 69-69: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 81-81: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 86-86: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 89-89: Boolean positional value in function call
(FBT003)
[warning] 92-94: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 136-136: Avoid specifying long messages outside the exception class
(TRY003)
[error] 139-139: Possible binding to all interfaces
(S104)
[warning] 144-144: Boolean positional value in function call
(FBT003)
[warning] 229-230: Use format specifiers instead of percent format
Replace with format specifiers
(UP031)
[warning] 390-393: Use contextlib.suppress(KeyboardInterrupt) instead of try-except-pass
Replace try-except-pass with with contextlib.suppress(KeyboardInterrupt): ...
(SIM105)
🪛 Shellcheck (0.11.0)
scripts/test-role-neutral-runtime.sh
[info] 51-51: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 52-52: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 53-53: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 54-54: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 56-56: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 57-57: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 58-58: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 59-59: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 60-60: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 61-61: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 62-62: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 63-63: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 64-64: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[info] 65-65: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
🔇 Additional comments (29)
AGENTS.md (1)
15-15: LGTM!Also applies to: 42-42, 57-65, 66-88, 104-104
CHANGELOG.md (1)
22-38: LGTM!Also applies to: 68-69, 71-92
PROJECT_STATUS.md (2)
9-9: LGTM!Also applies to: 22-26, 34-43, 49-49
65-65: 📐 Maintainability & Code QualityNo change needed.
The updater dispatches
build-amd64.ymlfor the updated automation branch; that workflow runsscripts/build-local.sh, which executes the launcher/Codex smoke tests andscripts/runtime-smoke-test.sh, and then runs the Trivy scans plus the enforcer.README.es.md (1)
6-63: LGTM!Also applies to: 73-128, 141-166
README.md (1)
6-28: LGTM!Also applies to: 30-58, 60-80, 102-102, 126-139, 146-168, 200-200, 218-236
docs/architecture.md (2)
5-17: LGTM!Also applies to: 31-85, 89-106, 108-129, 131-145, 157-158, 169-186, 190-205, 209-227, 231-252, 256-265
18-30: 📐 Maintainability & Code QualityNo changes needed.
The referenced issues state that
#24is closed,#25and#31are open work items,#36is closed, and#46remains under separate approval-mode work.docs/releases.md (1)
25-45: LGTM!Also applies to: 69-87, 91-91
docs/security.md (1)
7-23: LGTM!Also applies to: 25-55, 82-84
.coderabbit.yaml (2)
35-46: LGTM!
58-58: LGTM!compose/docker-compose.yml (1)
1-1: LGTM!Also applies to: 10-20, 22-40, 42-50, 105-106
compose/truenas.yml (1)
1-36: LGTM!Also applies to: 38-52, 85-85, 104-106
scripts/test_single_stack_compose.py (1)
64-133: LGTM!Also applies to: 155-193
scripts/test-compose-image-compat.sh (2)
19-22: LGTM!Also applies to: 29-62
23-28: 📐 Maintainability & Code QualityNo change needed.
scripts/test-compose-image-compat.shalready enablesset -euo pipefail, so thedocker compose ... | sort -upipeline preserves the left-hand exit status..github/workflows/build-amd64.yml (1)
32-33: LGTM!Also applies to: 55-57
Makefile (1)
14-18: LGTM!.env.example (1)
5-15: LGTM!images/codex/Dockerfile (1)
60-65: LGTM!Also applies to: 74-95, 133-141
scripts/remote-dev-launcher.py (1)
1-399: LGTM!scripts/start-remote-dev-web.sh (1)
13-16: LGTM!scripts/remote-dev-healthcheck.sh (1)
1-37: LGTM!scripts/test-remote-dev-launcher.sh (1)
1-131: LGTM!scripts/runtime-smoke-test.sh (1)
4-12: LGTM!Also applies to: 68-68, 116-179, 180-184
scripts/lib/remote-dev-runtime.sh (1)
16-24: LGTM!Also applies to: 56-59, 74-77
scripts/remote-dev-doctor.sh (1)
29-72: LGTM!Also applies to: 89-97, 123-147
scripts/test-role-neutral-runtime.sh (1)
51-69: LGTM!Also applies to: 83-88, 109-109
|
Review follow-up on the exact current branch:
The |
|
@codex review Please review the exact current head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e144a3e58f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review Please verify the exact current head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f4cc5ebb5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| curl --fail --silent --show-error \ | ||
| --connect-timeout 2 --max-time 4 \ | ||
| "http://127.0.0.1:${WEB_PORT:-7680}${health_path}" >/dev/null |
There was a problem hiding this comment.
Preserve accepted dot segments in health requests
When LAUNCHER_BASE_PATH produces a WEB_BASE_PATH containing a dot segment such as /a/../b/, the launcher validator accepts it and serves the literal /a/../b/healthz, but this curl invocation normalizes the request to /b/healthz, so Docker marks the running launcher unhealthy. Checked curl 8.5.0's --help all, which describes --path-as-is as “Do not squash .. sequences in URL path”; either reject dot segments in the shared path validation or add that option so the probe preserves every accepted path.
AGENTS.md reference: AGENTS.md:L88-L88
Useful? React with 👍 / 👎.
What changed
REMOTE_DEV_ROLE=launcherrole in the canonical runtime;7680;7681;REMOTE_DEV_IMAGEreference in generic and TrueNAS Compose;CODEX_DATA_ROOTand persistent paths;Launcher security boundary
The launcher:
65532before binding or serving;Originagainst the request host;The second browser authentication challenge at the Codex endpoint is intentional. This PR does not introduce a trusted terminal proxy.
Validation
launcherandcodex;Deliberately out of scope
No reverse proxy, one-origin transport,
CODEX_DATA_ROOTmigration, neutral persistent-data layout, Antigravity, Claude Code, Context7, outer-container hardening or cross-service canaries.Part of #25. Real TrueNAS browser navigation and exact-digest evidence remain manual gates before this slice is considered validated in the target environment.