Skip to content

feat(sandbox): add explicit Docker and Railway user sandbox profiles - #7214

Merged
henrypark133 merged 41 commits into
mainfrom
sandbox/pr1-user-sandbox-railway
Aug 8, 2026
Merged

henrypark133 merged 41 commits into
mainfrom
sandbox/pr1-user-sandbox-railway

Conversation

@henrypark133

@henrypark133 henrypark133 commented Aug 5, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Add explicit Docker and Railway user-sandbox profiles. The Docker profile uses local Docker; the Railway profile uses Railway without probing Docker.
  • Scope workspaces/checkpoints to tenant plus user, and run each command in a fresh non-root Python worker with no caller environment or credentials. Sandbox-enabled profiles explicitly opt into unrestricted direct Docker/provider-NAT egress; ad-hoc transports remain networkless by default.
  • Centralize construction behind composition functions that return a complete typed runtime binding, enforce the matching production process binding, and keep non-sandbox profiles unchanged.
  • Add real-Docker/full-turn tests, Railway transport tests and operator docs, plus CI coverage for production profile selection and the real-Docker lane. Railway shutdown now retries stale checkpoints, attempts provider cleanup, and relies on a five-minute idle timeout as the hard crash/leak backstop.

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

Related #6468, #6469, #6473.

Validation

  • cargo fmt --all -- --check
  • cargo clippy --all --benches --tests --examples --all-features -- -D warnings (affected packages passed scoped --all-targets clippy)
  • cargo build (covered by clippy and test compilation)
  • Relevant tests pass: listed below
  • cargo test --features integration if database-backed or integration behavior changed (Not applicable: no database behavior; the affected Reborn integration target ran directly.)
  • Manual testing: exact-head local Docker persistence/isolation/HTTPS-egress and full-turn container tests pass. A real WebUI/model flow on Colima also passed identity, workspace persistence, non-zero exit handling, and unrestricted egress. Hermetic Railway tests cover direct-network command rendering and worker hardening; rerun the authenticated live Railway canary before production enablement.
  • Local three-lane implementation review ran after merging main. Subsequent review-driven production and test changes were validated by the affected unit suites, architecture ratchet, all-target check/clippy, and exact-head real-Docker/full-turn tests. Two validated Railway-preview limitations are explicitly accepted below: no distributed checkpoint lease and no product-enforced persistent workspace quota.

Test Strategy

User behavior:

An explicit sandbox profile runs Python in its selected provider, maintains a tenant/user workspace, and leaves non-sandbox profiles unchanged. Workers receive no host credentials. Sandbox profiles explicitly grant unrestricted direct outbound network access for PR1; ad-hoc transport construction remains fail-closed with --network none.

Risk areas:

  • Model behavior
  • Browser (Not applicable: no WebUI surface or toggle.)
  • Side effect
  • Persistence
  • Security or permissions
  • External provider
  • Cross-component behavior

Tests added or updated:

  • Unit or contract: ironclaw_sandbox unit suite (218 tests), profile/config and runtime-policy contracts, including fail-closed defaults, explicit direct-network rendering, graceful provider cleanup, and malformed-response checkpoint safety.
  • Reborn integration: a hermetic full scripted turn in a real local container.
  • Recorded fixture: runtime-policy trace fixture for user_sandbox.
  • Browser E2E: Not applicable: deployment-selected profile only.
  • Backend or runtime: hermetic live-Docker persistence/isolation, non-zero exit/status-and-stderr preservation, an explicitly ignored public-HTTPS canary, production local-profile binding, and composition binding tests.
  • Live canary: an earlier operator-run Railway checkpoint canary passed persistence/isolation. The updated direct-egress Railway canary is implemented but still requires an authenticated operator rerun before production enablement.

What the tests prove:

The production local profile selects the Docker-backed user_sandbox binding, the Railway profile selects its remote transport without connecting to Docker, and non-sandbox profiles ignore Railway configuration. Runtime-policy tests reject missing or unexpected sandbox bindings. Real-Docker tests preserve one user's workspace across turns, isolate other users, prove direct HTTPS egress without credential environment variables, return non-zero command exits as ordinary bounded sandbox results with stderr intact, and complete a real Reborn sandbox-shell turn. Hermetic Railway tests cover deterministic checkpoint restoration, credential scrubbing, timeout cleanup, exact-checkpoint provisioning, graceful shutdown cleanup, malformed-response checkpoint safety, and bounded idle-LRU user state that never evicts active entries.

Commands run:

cargo fmt --all -- --check
cargo clippy -p ironclaw_sandbox -p ironclaw_host_api -p ironclaw_runtime_policy -p ironclaw_config -p ironclaw_host_runtime -p ironclaw_composition -p ironclaw --all-targets -- -D warnings
cargo test -p ironclaw_sandbox
cargo test -p ironclaw_sandbox --test user_sandbox_docker_live -- --nocapture
cargo test -p ironclaw_sandbox --test user_sandbox_docker_live sandbox_profile_allows_public_https_egress -- --ignored --nocapture
cargo test -p ironclaw_sandbox sandbox_process::railway::tests
IRONCLAW_REQUIRE_DOCKER_TESTS=1 cargo test -p ironclaw local_sandbox_profile_selects_docker_process_binding_when_required -- --nocapture
cargo test -p ironclaw railway_sandbox_profile_selects_remote_transport_without_connecting_docker -- --nocapture
cargo test -p ironclaw non_sandbox_profile_ignores_railway_sandbox_environment -- --nocapture
IRONCLAW_REQUIRE_DOCKER_TESTS=1 cargo test -p ironclaw_sandbox --test user_sandbox_docker_live -- --nocapture
IRONCLAW_REQUIRE_DOCKER_TESTS=1 cargo test -p ironclaw_integration_tests --test reborn_integration_sandbox_shell_turn -- --nocapture
cargo test -p ironclaw_composition user_sandbox --lib
cargo test -p ironclaw_architecture_tests
cargo clippy -p ironclaw_sandbox -p ironclaw_composition --all-targets --all-features -- -D warnings
cargo clippy -p ironclaw_integration_tests --test reborn_integration_sandbox_shell_turn --all-features -- -D warnings
cargo test -p ironclaw_composition --test libsql_substrate user_sandbox -- --nocapture
cargo test -p ironclaw_architecture_tests --test reborn_composition_boundaries
cargo test -p ironclaw --test smoke
cargo test -p ironclaw_architecture_tests --test reborn_struct_test_support_ratchet
python3 scripts/ci/test_reborn_pr_test_plan.py
python3 scripts/check_no_panics.py --base c51a573c7617e3929cd4826138ec418d64f42a63 --head HEAD

Security Impact

Yes. Shell execution moves only through a sandbox process binding. Workers have no caller environment or credentials, run non-root with a read-only root filesystem, no-new-privileges, and bounded CPU/PIDs/tmp/logs/output. Ad-hoc transports default to --network none; only sandbox-enabled deployment profiles opt into unrestricted direct Docker/provider-NAT egress, surfaced as IRONCLAW_REBORN_NETWORK_MODE=direct. Railway CLI credentials stay host-side. The preview does not yet enforce a per-user persistent workspace disk quota. Custom CLI setup, secret-store mediation, SigV4, and restricted or credential-mediated egress are out of scope.

Reborn Trust-Boundary Checklist

  • Public policy/evidence/trust-bearing types: composition exposes only complete typed runtime process bindings while provider configuration stays private; runtime policy accepts only an opaque user-sandbox binding.
  • Untrusted content enters prompts only through an envelope/escaping primitive. No prompt or ingress path changed.
  • Hashes declare purpose; workspace identity uses length-prefixed tenant/user inputs and claims no authenticity.
  • New/changed status, exit, policy, runtime, or error variants: downstream match sites audited by scoped clippy and runtime-policy/composition tests.
  • Security/durability serde(default) fields fail closed or have migration tests: profile/config parsing rejects incomplete sandbox configuration.
  • Queues/maps/buffers/counters have bounds: output, logs, tmpfs, PIDs, CPU, and timeouts are bounded; Railway user lifecycle state is capped at 4,096 entries with idle-LRU eviction that cannot remove active entries.
  • Driver/operator-visible errors have stable class semantics: missing Docker/Railway configuration is explicit and has no unsandboxed fallback.
  • Sandbox/native/host names accurately describe the trust boundary: user sandbox keys include tenant plus user.

Database Impact

None. No schema or migration change.

Blast Radius

Runtime profile parsing, CLI boot composition, process dispatch, Docker image/CI, and deployment docs. Existing non-sandbox profiles retain their current process backend and ignore Railway settings.

Composition budget rationale: re-seed the absolute composition ratchet from 40,499 to 40,747 (+248 LOC) for provider-neutral profile/deployment mapping, fail-closed capability-policy projection, and the centralized Docker/Railway binding functions. Provider execution remains in ironclaw_sandbox.

Host API ratchet rationale: raise ironclaw_host_api from 18,570 to the measured 18,799 for the UserSandbox wire rename, legacy tenant_sandbox serde alias, canonical reserialization compatibility test, and provider-neutral graceful transport lifecycle hook. This is contract vocabulary and its compatibility proof; sandbox execution and cleanup remain in ironclaw_sandbox.

Rollback Plan

Select a non-sandbox profile or revert this PR. There is no migration; isolated workspaces/checkpoints can be retained or removed operationally.

Review Follow-Through

Railway is preview-only: use exactly one IronClaw replica and avoid deployment overlap because checkpoint coordination is process-local, not a distributed lease. Provider volume limits are the current backstop because PR1 does not enforce a per-user persistent workspace quota. PR1 is Python-only with unrestricted direct egress on sandbox-enabled profiles. Destination filtering, credential mediation, and custom CLI installation are follow-ups.


Review track: C (security/runtime/CI)

Copilot AI lite review requested due to automatic review settings August 5, 2026 07:56
@railway-app

railway-app Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the ironclaw-pr-7214 environment in ironclaw-ci-preview

Service Status Web Updated (UTC)
ironclaw ✅ Success (View Logs) Web Aug 7, 2026 at 10:28 pm

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-7214 August 5, 2026 07:56 Destroyed
@github-actions github-actions Bot added scope: sandbox Docker sandbox scope: ci CI/CD workflows scope: docs Documentation scope: dependencies Dependency updates size: XL 500+ changed lines risk: medium Business logic, config, or moderate-risk modules contributor: core 20+ merged PRs labels Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added local Docker and Railway preview profiles with persistent, per-user sandbox workspaces.
    • Added checkpoint restoration, controlled networking, hardened non-root workers, and sandboxed shell execution.
    • Added configurable Railway worker images, timeouts, authentication, and volume settings.
  • Documentation
    • Added setup guidance and an operator runbook for local Docker and Railway previews.
  • Tests
    • Added coverage for isolation, persistence, security, shell execution, and Railway lifecycle behavior.

Walkthrough

The PR adds user-scoped Docker and Railway sandbox execution, two hosted sandbox profiles, hardened worker configuration, runtime policy wiring, integration tests, and conditional CI execution.

Changes

User sandbox execution

Layer / File(s) Summary
Sandbox contracts and runtime wiring
crates/contracts/..., crates/kernel/..., crates/app/ironclaw_composition/...
Renames tenant sandbox bindings to user sandbox bindings, adds transport shutdown, routes hosted execution through UserSandboxProcessPort, and applies sandbox-specific capability and filesystem policy.
Docker and Railway transports
crates/lanes/ironclaw_sandbox/..., Dockerfile.sandbox-worker
Adds per-user workspace identity, hardened Docker workers, environment restrictions, Railway lifecycle management, checkpoint restoration, cleanup, and output validation.
Hosted sandbox profiles
crates/app/ironclaw_config/..., crates/app/ironclaw_cli/..., crates/app/ironclaw_composition/...
Adds local-Docker and Railway hosted-volume profiles with validation, storage mapping, readiness diagnostics, and profile smoke coverage.
Integration and CI coverage
.github/workflows/..., scripts/ci/..., tests/integration/...
Adds Docker-gated full-turn shell tests, sandbox image setup, dynamic lane selection, and aggregate workflow validation.
Deployment and operator support
Dockerfile, docker/reborn/..., docs/reborn/..., .env.example
Packages the pinned Railway CLI and documents local-Docker and Railway preview deployment operation.
Baselines and supporting contracts
crates/app/ironclaw_architecture_tests/..., scripts/ci/composition-budget.toml, tests/CLAUDE.md
Updates architecture measurements, integration-bin counts, and sandbox test documentation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: benkurrek

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title uses Conventional Commits format and accurately summarizes the Docker and Railway user-sandbox profile changes.
Description check ✅ Passed The description covers all required sections, links related issues, documents validation and security impact, and states rollback and review follow-through.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-7214 August 5, 2026 07:56 Destroyed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds explicit user-sandbox execution profiles (local Docker and Railway preview) and wires builtin.shell through an enforced sandbox process binding, with new real-Docker/full-turn integration coverage, CI lane selection, and updated operator/docs contracts.

Changes:

  • Introduce explicit hosted-single-tenant-volume-sandboxed (local Docker) and ...-sandboxed-railway (Railway Sandboxes) profiles, plus UserSandboxFactory to centralize transport construction.
  • Shift sandbox persistence identity to {tenant_id, user_id} and tighten worker posture (non-root, read-only rootfs, --network none, bounded logs/tmpfs/pids/cpu).
  • Add real Docker contract + full-turn integration test, Railway transport tests/runbook, and a dedicated CI lane triggered by sandbox-surface changes.

Reviewed changes

Copilot reviewed 87 out of 88 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/integration/support/harness/profiles/sandbox_shell.rs Adds a harness profile that builds a real sandboxed shell capability harness.
tests/integration/support/harness/profiles/mod.rs Exposes the new sandbox_shell harness profile module.
tests/integration/support/harness/options.rs Adds a sandboxed_shell option flag to opt into sandbox profile wiring in the harness.
tests/integration/support/harness/mod.rs Builds sandbox-profile services input and binds a Docker-backed UserSandboxFactory when opted in.
tests/integration/support/docker_gate.rs Adds a Docker/worker-image availability gate for local runs and CI fail-closed mode.
tests/integration/support/capability_backend.rs Adds a SandboxShellTools backend selecting the sandboxed shell harness.
tests/integration/support/builder.rs Adds with_sandbox_shell_tools() to route builtin.shell through the real sandbox profile.
tests/integration/reborn_sandbox_shell_turn.rs Adds a full-turn integration test that asserts shell runs in a real Docker worker and persists workspace.
tests/integration/CLAUDE.md Documents the one explicit Docker-required integration test and harness opt-in.
tests/fixtures/llm_traces/runtime_policy/hosted_dev_no_shell.json Updates recorded trace copy to reflect “user sandbox” wording.
tests/e2e_trace_runtime_policy_serde.rs Updates serde round-trip coverage to use ProcessBackendKind::UserSandbox.
tests/CLAUDE.md Updates test-tier docs and counts to include the dedicated sandbox integration test.
scripts/ci/test_reborn_pr_test_plan.py Adds a contract test asserting sandbox-surface diffs select the Docker CI lane.
scripts/ci/reborn_pr_test_plan.py Adds sandbox-surface path mapping and emits run_sandbox_docker in the plan.
docs/reborn/target-architecture/CHECKLIST.md Updates target-architecture checklist wording for UserSandboxProcessPort.
docs/reborn/railway-sandbox-operator.md Adds a Railway sandbox operator runbook (preview-only).
docs/reborn/deploy-reborn-cli-docker.md Updates Docker/Railway deployment guidance and distinguishes sandboxed profiles.
docs/reborn/contracts/runtime-profiles.md Updates hosted-yolo wording to refer to user sandbox boundary.
docs/reborn/contracts/host-runtime.md Updates host-runtime contract text for ProcessBackendKind::UserSandbox and {tenant,user} identity.
docs/reborn-binary.md Updates doc wording to “user-sandbox process binding”.
docs/plans/composition-pubuse.snapshot Updates composition re-exports snapshot for new sandbox factory/config and build-input helpers.
Dockerfile.sandbox-worker Adds a pinned minimal Python worker image for local Docker user-sandbox tests.
Dockerfile Adds a pinned Railway CLI download+checksum step and copies railway into the final image.
docker/reborn/entrypoint.sh Recognizes sandboxed hosted-volume profiles for default config/volume fail-closed checks.
crates/ironclaw_sandbox/tests/user_sandbox_docker_live.rs Adds real-Docker persistence/isolation test for per-user workspace.
crates/ironclaw_sandbox/tests/railway_sandbox_live.rs Adds an ignored, manual Railway canary test for checkpoint persistence/isolation and token scrubbing.
crates/ironclaw_sandbox/src/sandbox_process/worker_spec.rs Centralizes Docker worker security posture + CLI arg renderer and tests.
crates/ironclaw_sandbox/src/sandbox_process/user_key.rs Updates user-key semantics/docs to production per-user identity.
crates/ironclaw_sandbox/src/sandbox_process/railway/tests.rs Adds hermetic Railway CLI transport tests via a fake CLI implementation.
crates/ironclaw_sandbox/src/sandbox_process/network_allowlist.rs Updates docs to refer to UserSandbox.
crates/ironclaw_sandbox/src/sandbox_process/container_identity.rs Enforces non-root container user selection (workspace-owner by default) and adds tests.
crates/ironclaw_sandbox/src/sandbox_process/broker.rs Updates docs to refer to user sandbox commands.
crates/ironclaw_sandbox/src/sandbox_process.rs Switches workspace identity to {tenant,user}, tightens worker host config, blocks caller env injection, and exports Railway transport/config.
crates/ironclaw_sandbox/src/lib.rs Re-exports new Railway preview types and updated sandbox surfaces.
crates/ironclaw_sandbox/CLAUDE.md Updates crate wiring status doc for production builtin.shell execution through sandbox profiles.
crates/ironclaw_sandbox/Cargo.toml Adds tokio sync feature needed by Railway transport/test code.
crates/ironclaw_runtime_policy/src/resolver.rs Resolves hosted profiles to ProcessBackendKind::UserSandbox instead of TenantSandbox.
crates/ironclaw_runtime_policy/src/planner.rs Updates planner docs/tests for UserSandbox backend selection.
crates/ironclaw_reborn_config/tests/profile_contract.rs Adds stable-string and predicate contract coverage for the new profiles.
crates/ironclaw_reborn_config/src/profile.rs Adds profile enum variants, parsing, display order, and storage-subdir mapping for sandboxed profiles.
crates/ironclaw_reborn_composition/tests/service_factory.rs Updates tests to expect UserSandbox process backend and binding errors.
crates/ironclaw_reborn_composition/tests/production_runtime_trigger_poller.rs Updates production harness wiring to use UserSandboxProcessPort.
crates/ironclaw_reborn_composition/tests/production_runtime_project_service.rs Updates production harness wiring to use UserSandboxProcessPort.
crates/ironclaw_reborn_composition/tests/production_runtime_identity.rs Updates production harness wiring to use UserSandboxProcessPort.
crates/ironclaw_reborn_composition/tests/production_runtime_automations.rs Updates production harness wiring to use UserSandboxProcessPort.
crates/ironclaw_reborn_composition/tests/postgres_substrate.rs Updates production policy helper naming and expected UserSandbox backend.
crates/ironclaw_reborn_composition/tests/libsql_substrate.rs Updates production policy helper naming/errors for UserSandbox process binding.
crates/ironclaw_reborn_composition/tests/admin_api_e2e.rs Updates admin harness production policy/backend to UserSandbox.
crates/ironclaw_reborn_composition/src/sandbox.rs Introduces UserSandboxFactory to build local Docker or Railway preview process bindings.
crates/ironclaw_reborn_composition/src/runtime/tests/core.rs Updates production-shaped runtime tests to use UserSandboxProcessPort.
crates/ironclaw_reborn_composition/src/runtime.rs Reuses already-built capability policy from services instead of rebuilding in runtime.
crates/ironclaw_reborn_composition/src/root/profile.rs Adds composition profile variants for the sandboxed hosted-volume profiles.
crates/ironclaw_reborn_composition/src/readiness.rs Adds readiness state/diagnostic reason for sandboxed hosted-volume preview.
crates/ironclaw_reborn_composition/src/production_runtime_policy.rs Renames production policy helper to with_user_sandbox_process_port and updates error mapping.
crates/ironclaw_reborn_composition/src/product_surface.rs Adds operator-status mapping for sandboxed hosted-volume readiness.
crates/ironclaw_reborn_composition/src/memory_binding.rs Treats sandboxed hosted-volume profiles as hosted-single-tenant for memory deployment classification.
crates/ironclaw_reborn_composition/src/lib.rs Adds sandbox module, re-exports UserSandboxFactory and Railway config, updates error variants.
crates/ironclaw_reborn_composition/src/input.rs Renames runtime process binding to UserSandbox and updates validation errors/messages.
crates/ironclaw_reborn_composition/src/factory/runtime_lane_assembly.rs Wires user-sandbox process port into production services when present.
crates/ironclaw_reborn_composition/src/factory/production_backend_assembly.rs Specializes builtin capability policy for the selected process backend (user-sandbox restrictions).
crates/ironclaw_reborn_composition/src/factory/capability_host_tests/approval_gates.rs Removes a now-obsolete standalone tenant-sandbox port test and related test transport.
crates/ironclaw_reborn_composition/src/factory.rs Makes capability_policy available outside test-only builds (used by runtime build).
crates/ironclaw_reborn_composition/src/error.rs Updates RebornBuildError mapping for new user-sandbox binding errors.
crates/ironclaw_reborn_composition/src/deployment.rs Adds sandboxed hosted-volume deployment config and resolved runtime policy helper.
crates/ironclaw_reborn_composition/src/builtin_capability_policy.rs Adds for_process_backend(UserSandbox) projection to strip host fs/network effects from shell grant.
crates/ironclaw_reborn_composition/Cargo.toml Adds ironclaw_sandbox dependency for sandbox process construction.
crates/ironclaw_reborn_cli/src/runtime/mod.rs Wires the new CLI profiles, builds sandbox process bindings, and adds profile-selection contract tests.
crates/ironclaw_host_runtime/tests/support/host_runtime_harness.rs Updates harness runtime policy expected backend to UserSandbox.
crates/ironclaw_host_runtime/tests/runtime_policy_planner_contract.rs Updates planner contract assertions to UserSandbox.
crates/ironclaw_host_runtime/tests/host_runtime_services_contract.rs Updates production wiring validation tests to require UserSandboxProcessPort.
crates/ironclaw_host_runtime/tests/first_party_coding_tools.rs Updates post-edit-check sandbox routing tests to use the user-sandbox port/policy.
crates/ironclaw_host_runtime/tests/first_party_builtin_tools.rs Updates first-party package/handler tests and shell routing tests to UserSandbox.
crates/ironclaw_host_runtime/src/services/production_wiring.rs Renames production wiring component tracking field to user_sandbox_process_port.
crates/ironclaw_host_runtime/src/services/production_services.rs Requires a sandbox process port when runtime policy selects UserSandbox.
crates/ironclaw_host_runtime/src/services/builder.rs Renames builder setters to with_user_sandbox_process_port (+ production variant).
crates/ironclaw_host_runtime/src/services.rs Plumbs user-sandbox process port through services and invocation resolver setup.
crates/ironclaw_host_runtime/src/process_port.rs Renames TenantSandboxProcessPort to UserSandboxProcessPort and updates tests.
crates/ironclaw_host_runtime/src/post_edit_check.rs Updates docs to refer to user sandbox backend.
crates/ironclaw_host_runtime/src/lib.rs Re-exports UserSandboxProcessPort instead of tenant sandbox port.
crates/ironclaw_host_runtime/src/invocation_services/tests.rs Updates resolver tests and error expectations for UserSandbox.
crates/ironclaw_host_runtime/src/invocation_services.rs Renames configured sandbox port slot to user-sandbox and updates selection logic/comments.
crates/ironclaw_host_runtime/src/first_party_tools/mod.rs Restricts builtin.shell effects under UserSandbox and adds helper to remove specific effects.
crates/ironclaw_host_api/src/runtime_policy.rs Renames backend kind to UserSandbox with serde alias and updates docs/tests.
crates/ironclaw_host_api/src/process.rs Updates kernel/runtimes layering docs for UserSandboxProcessPort and user-isolated transport semantics.
Cargo.toml Registers the new integration test binary reborn_integration_sandbox_shell_turn.
Cargo.lock Adds ironclaw_sandbox as a dependency where newly referenced.
.github/workflows/reborn-tests.yml Adds a dedicated “sandbox-docker-tests” job and propagates run_sandbox_docker from the plan.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/lanes/ironclaw_sandbox/src/sandbox_process/railway/tests.rs
Copilot AI review requested due to automatic review settings August 5, 2026 08:00
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-7214 August 5, 2026 08:04 Destroyed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 87 out of 88 changed files in this pull request and generated no new comments.

Suppressed comments (1)

Dockerfile.sandbox-worker:8

  • The worker image sets HOME=/home/sandbox, but the local-Docker transport now defaults to running the container as the numeric owner of the host workspace (often not uid 1000). In that case /home/sandbox is typically owned by uid 1000 and may be non-writable, causing Python tooling that writes to $HOME (pip caches, site config, etc.) to fail unexpectedly. Set HOME to a path that remains writable for the chosen runtime uid (e.g. /workspace or /tmp).
ENV HOME=/home/sandbox

Copilot AI review requested due to automatic review settings August 5, 2026 08:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 87 out of 88 changed files in this pull request and generated no new comments.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48b3b1b25a

ℹ️ 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".

Comment thread crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs
Comment thread scripts/ci/reborn_pr_test_plan.py Outdated
Copilot AI review requested due to automatic review settings August 5, 2026 08:14
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-7214 August 5, 2026 08:14 Destroyed
Copilot AI review requested due to automatic review settings August 7, 2026 06:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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: 1

Caution

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

⚠️ Outside diff range comments (2)
docs/reborn/target-architecture/CHECKLIST.md (2)

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

Reconcile the #7084 status.

The entry says the follow-up is owed after #7084 lands, but it also says #7084 already fixes the issue. Use one status. If #7084 has landed, mark this item complete. Otherwise, change “already fixes” to “will fix”.

🤖 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/reborn/target-architecture/CHECKLIST.md` at line 418, Reconcile the
`#7084` status in the checklist entry: if `#7084` has landed, mark the follow-up
complete; otherwise change “already fixes” to “will fix.” Keep the surrounding
guidance and references unchanged.

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

Use the correct nested CLI path.

The sentence names app/ironclaw_cli, then says the nested path is crates/ironclaw_cli. The correct path is crates/app/ironclaw_cli.

Proposed correction
- makes `crates/ironclaw_cli` the first nested family path
+ makes `crates/app/ironclaw_cli` the first nested family path

As per coding guidelines, the binary entry point is crates/app/ironclaw_cli.

🤖 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/reborn/target-architecture/CHECKLIST.md` at line 428, Correct the CLI
path references in the checklist entry describing the directory move: use
crates/app/ironclaw_cli consistently, including the statement identifying the
first nested family path, while preserving the package name and other rename
details.

Source: Coding guidelines

🤖 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/internal/reborn-binary.md`:
- Around line 510-511: Update the `skills list` supported-profile documentation
and validation to include `hosted-single-tenant-volume-sandboxed` and
`hosted-single-tenant-volume-sandboxed-railway`, matching the profiles listed in
the Reborn profiles section; alternatively, remove those profiles from that
section if they are not intended to be accepted.

---

Outside diff comments:
In `@docs/reborn/target-architecture/CHECKLIST.md`:
- Line 418: Reconcile the `#7084` status in the checklist entry: if `#7084` has
landed, mark the follow-up complete; otherwise change “already fixes” to “will
fix.” Keep the surrounding guidance and references unchanged.
- Line 428: Correct the CLI path references in the checklist entry describing
the directory move: use crates/app/ironclaw_cli consistently, including the
statement identifying the first nested family path, while preserving the package
name and other rename details.
🪄 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: 43a27022-0d1d-47e5-86a4-f75b4a8e68f3

📥 Commits

Reviewing files that changed from the base of the PR and between 24ae804 and 775db43.

📒 Files selected for processing (12)
  • Cargo.toml
  • crates/app/ironclaw_architecture_tests/tests/reborn_dependency_boundaries.rs
  • crates/app/ironclaw_composition/src/lib.rs
  • crates/app/ironclaw_composition/src/product_surface.rs
  • crates/app/ironclaw_composition/src/runtime.rs
  • crates/kernel/ironclaw_host_runtime/src/services/builder.rs
  • crates/kernel/ironclaw_host_runtime/tests/host_runtime_services_contract.rs
  • crates/kernel/ironclaw_host_runtime/tests/support/host_runtime_harness.rs
  • docs/internal/plans/composition-pubuse.snapshot
  • docs/internal/reborn-binary.md
  • docs/reborn/target-architecture/CHECKLIST.md
  • scripts/ci/reborn_pr_test_plan.py

Comment thread docs/internal/reborn-binary.md
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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: 6

Caution

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

⚠️ Outside diff range comments (2)
crates/lanes/ironclaw_sandbox/src/sandbox_process.rs (1)

599-618: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Delete the now-unreachable per-key validation tail.

The early return rejects every non-empty env. Everything after it runs only on a provably empty map, so the into_iter().map(...) closure always yields Vec::new() and its NUL and '=' error strings are unreachable.

Keeping a dead validation path is worse than having none: a future reader will assume caller env is sanitized rather than refused, and may relax the guard on top of validation that never ran.

♻️ Proposed simplification
 fn validate_env(env: HashMap<String, String>) -> Result<Vec<String>, RuntimeProcessError> {
     if !env.is_empty() {
         return Err(RuntimeProcessError::ExecutionFailed(
             "user sandbox commands do not accept caller-provided environment variables".to_string(),
         ));
     }
-    env.into_iter()
-        .map(|(key, value)| {
-            reject_nul("environment variable name", &key)?;
-            reject_nul("environment variable value", &value)?;
-            if key.contains('=') || key.is_empty() {
-                return Err(RuntimeProcessError::ExecutionFailed(
-                    "environment variable names must be non-empty and cannot contain '='"
-                        .to_string(),
-                ));
-            }
-            Ok(format!("{key}={value}"))
-        })
-        .collect()
+    Ok(Vec::new())
 }
🤖 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 `@crates/lanes/ironclaw_sandbox/src/sandbox_process.rs` around lines 599 - 618,
Update validate_env to retain the early rejection for any non-empty environment
and return an empty Vec directly for the empty-map case. Remove the unreachable
into_iter/map closure and its per-key NUL, empty-name, and '=' validation logic.
crates/kernel/ironclaw_host_runtime/src/invocation_services.rs (1)

374-395: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Merge the duplicated mount-scoped arms.

The new TenantWorkspace arm is byte-equivalent to the ScopedVirtual arm: require mounts, wrap self.filesystem in a MountScopedRootFilesystem. Two copies of the same containment decision will drift the moment one side gains a check the other does not.

Collapse them into one arm with a guard so the deployment gate stays explicit and the body stays single-sourced.

♻️ Proposed consolidation
-            FilesystemBackendKind::ScopedVirtual => {
-                let mounts =
-                    mounts.ok_or(InvocationServicesError::UnsupportedFilesystemBackend {
-                        backend: plan.filesystem_backend,
-                    })?;
-                Ok(Arc::new(MountScopedRootFilesystem::new(
-                    Arc::clone(&self.filesystem),
-                    mounts.clone(),
-                )))
-            }
-            FilesystemBackendKind::TenantWorkspace
-                if matches!(plan.deployment, DeploymentMode::HostedMultiTenant) =>
-            {
-                let mounts =
-                    mounts.ok_or(InvocationServicesError::UnsupportedFilesystemBackend {
-                        backend: plan.filesystem_backend,
-                    })?;
-                Ok(Arc::new(MountScopedRootFilesystem::new(
-                    Arc::clone(&self.filesystem),
-                    mounts.clone(),
-                )))
-            }
+            // Both backends resolve to the same mount-scoped view; only the
+            // admissible deployment differs.
+            FilesystemBackendKind::ScopedVirtual
+            | FilesystemBackendKind::TenantWorkspace
+                if matches!(plan.filesystem_backend, FilesystemBackendKind::ScopedVirtual)
+                    || matches!(plan.deployment, DeploymentMode::HostedMultiTenant) =>
+            {
+                let mounts =
+                    mounts.ok_or(InvocationServicesError::UnsupportedFilesystemBackend {
+                        backend: plan.filesystem_backend,
+                    })?;
+                Ok(Arc::new(MountScopedRootFilesystem::new(
+                    Arc::clone(&self.filesystem),
+                    mounts.clone(),
+                )))
+            }
🤖 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 `@crates/kernel/ironclaw_host_runtime/src/invocation_services.rs` around lines
374 - 395, Merge the `FilesystemBackendKind::ScopedVirtual` and hosted
`FilesystemBackendKind::TenantWorkspace` match arms in the filesystem backend
dispatch into one guarded arm. Keep the explicit
`DeploymentMode::HostedMultiTenant` condition for `TenantWorkspace`, require
`mounts`, and retain the single `MountScopedRootFilesystem` construction using
`self.filesystem`.
🤖 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 `@crates/app/ironclaw_composition/src/runtime.rs`:
- Around line 520-521: Update the RuntimeProcessError::UserSandboxShutdown
variant to wrap a RuntimeProcessError rather than a String, preserving the
original sandbox shutdown source error at this boundary while retaining
sanitized messaging at the product boundary.

In `@crates/app/ironclaw_composition/src/sandbox.rs`:
- Around line 22-24: Update both RebornScopedSandboxCommandTransport::connect
construction sites in crates/app/ironclaw_composition/src/sandbox.rs at lines
22-24 and 42-44 to use the runtime-resolved network policy instead of
unconditional with_network_enabled(). Preserve broker proxy configuration for
NetworkMode::Brokered, and pass the resolved allowlist into worker
environment/configuration for NetworkMode::Allowlist, including HostedDev and
HostedYoloTenantScoped, so shell commands cannot bypass egress boundaries.

In `@crates/lanes/ironclaw_sandbox/tests/user_sandbox_docker_live.rs`:
- Around line 15-24: Extend the live sandbox isolation tests around scope() to
cover two tenants: create state as a user in tenant A, then attempt to read it
with the same or another user in tenant B, and assert the state is inaccessible.
Make the tenant an input to scope() while preserving existing user, project, and
thread parameters, and add the required caller-driven two-user cross-tenant
filesystem escape assertion without changing backend or deployment
configuration.

In `@Dockerfile`:
- Around line 22-25: Update the Dockerfile package-install step for
ca-certificates and curl to use exact versions from a reproducible Debian
snapshot, or replace the base/toolchain setup with a pinned toolchain image.
Ensure the bootstrap packages used to fetch the Railway CLI cannot change across
rebuilds.

In `@scripts/ci/reborn_pr_test_plan.py`:
- Around line 159-162: Update SANDBOX_DOCKER_EXACT_PATHS in
reborn_pr_test_plan.py to derive Cargo.toml and src/lib.rs paths from
crate_directory("ironclaw_sandbox", ROOT), so relocated crate roots remain
covered. In scripts/ci/test_reborn_pr_test_plan.py lines 536-556, extend the
inventory-relocation regression with relocated Cargo.toml and src/lib.rs cases.

In `@tests/integration/CLAUDE.md`:
- Around line 80-85: Update the target name in the “Zero setup by default”
section of tests/integration/CLAUDE.md from reborn_sandbox_shell_turn to the
registered reborn_integration_sandbox_shell_turn target, preserving the existing
Docker and CI behavior description.

---

Outside diff comments:
In `@crates/kernel/ironclaw_host_runtime/src/invocation_services.rs`:
- Around line 374-395: Merge the `FilesystemBackendKind::ScopedVirtual` and
hosted `FilesystemBackendKind::TenantWorkspace` match arms in the filesystem
backend dispatch into one guarded arm. Keep the explicit
`DeploymentMode::HostedMultiTenant` condition for `TenantWorkspace`, require
`mounts`, and retain the single `MountScopedRootFilesystem` construction using
`self.filesystem`.

In `@crates/lanes/ironclaw_sandbox/src/sandbox_process.rs`:
- Around line 599-618: Update validate_env to retain the early rejection for any
non-empty environment and return an empty Vec directly for the empty-map case.
Remove the unreachable into_iter/map closure and its per-key NUL, empty-name,
and '=' validation logic.
🪄 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: 3a154b65-bfa5-4a6b-b3a4-5a592aa606f7

📥 Commits

Reviewing files that changed from the base of the PR and between d27dba3 and 561528e.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock, !**/Cargo.lock
  • tests/fixtures/llm_traces/runtime_policy/hosted_dev_no_shell.json is excluded by !tests/fixtures/**
📒 Files selected for processing (96)
  • .env.example
  • .github/workflows/reborn-tests.yml
  • Cargo.toml
  • Dockerfile
  • Dockerfile.sandbox-worker
  • crates/app/ironclaw_architecture_tests/tests/reborn_dependency_boundaries.rs
  • crates/app/ironclaw_architecture_tests/tests/reborn_restructure_baselines.rs
  • crates/app/ironclaw_architecture_tests/tests/reborn_struct_test_support_ratchet.rs
  • crates/app/ironclaw_cli/src/commands/skills.rs
  • crates/app/ironclaw_cli/src/runtime/mod.rs
  • crates/app/ironclaw_cli/tests/smoke.rs
  • crates/app/ironclaw_composition/Cargo.toml
  • crates/app/ironclaw_composition/src/builtin_capability_policy.rs
  • crates/app/ironclaw_composition/src/deployment.rs
  • crates/app/ironclaw_composition/src/error.rs
  • crates/app/ironclaw_composition/src/factory.rs
  • crates/app/ironclaw_composition/src/factory/capability_host_tests/approval_gates.rs
  • crates/app/ironclaw_composition/src/factory/production_backend_assembly.rs
  • crates/app/ironclaw_composition/src/factory/runtime_lane_assembly.rs
  • crates/app/ironclaw_composition/src/factory/tests.rs
  • crates/app/ironclaw_composition/src/input.rs
  • crates/app/ironclaw_composition/src/lib.rs
  • crates/app/ironclaw_composition/src/memory_binding.rs
  • crates/app/ironclaw_composition/src/product_surface.rs
  • crates/app/ironclaw_composition/src/production_runtime_policy.rs
  • crates/app/ironclaw_composition/src/readiness.rs
  • crates/app/ironclaw_composition/src/root/profile.rs
  • crates/app/ironclaw_composition/src/runtime.rs
  • crates/app/ironclaw_composition/src/runtime/capability_host/tests.rs
  • crates/app/ironclaw_composition/src/runtime/tests/core.rs
  • crates/app/ironclaw_composition/src/sandbox.rs
  • crates/app/ironclaw_composition/tests/admin_api_e2e.rs
  • crates/app/ironclaw_composition/tests/libsql_substrate.rs
  • crates/app/ironclaw_composition/tests/postgres_substrate.rs
  • crates/app/ironclaw_composition/tests/production_runtime_automations.rs
  • crates/app/ironclaw_composition/tests/production_runtime_identity.rs
  • crates/app/ironclaw_composition/tests/production_runtime_project_service.rs
  • crates/app/ironclaw_composition/tests/production_runtime_trigger_poller.rs
  • crates/app/ironclaw_composition/tests/service_factory.rs
  • crates/app/ironclaw_config/src/profile.rs
  • crates/app/ironclaw_config/tests/profile_contract.rs
  • crates/contracts/ironclaw_host_api/src/process.rs
  • crates/contracts/ironclaw_host_api/src/runtime_policy.rs
  • crates/kernel/ironclaw_host_runtime/src/first_party_tools/mod.rs
  • crates/kernel/ironclaw_host_runtime/src/invocation_services.rs
  • crates/kernel/ironclaw_host_runtime/src/invocation_services/tests.rs
  • crates/kernel/ironclaw_host_runtime/src/lib.rs
  • crates/kernel/ironclaw_host_runtime/src/post_edit_check.rs
  • crates/kernel/ironclaw_host_runtime/src/process_port.rs
  • crates/kernel/ironclaw_host_runtime/src/services.rs
  • crates/kernel/ironclaw_host_runtime/src/services/builder.rs
  • crates/kernel/ironclaw_host_runtime/src/services/production_services.rs
  • crates/kernel/ironclaw_host_runtime/src/services/production_wiring.rs
  • crates/kernel/ironclaw_host_runtime/tests/first_party_builtin_tools.rs
  • crates/kernel/ironclaw_host_runtime/tests/first_party_coding_tools.rs
  • crates/kernel/ironclaw_host_runtime/tests/host_runtime_services_contract.rs
  • crates/kernel/ironclaw_host_runtime/tests/runtime_policy_planner_contract.rs
  • crates/kernel/ironclaw_host_runtime/tests/support/host_runtime_harness.rs
  • crates/kernel/ironclaw_runtime_policy/src/planner.rs
  • crates/kernel/ironclaw_runtime_policy/src/resolver.rs
  • crates/lanes/ironclaw_sandbox/AGENTS.md
  • crates/lanes/ironclaw_sandbox/Cargo.toml
  • crates/lanes/ironclaw_sandbox/src/lib.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/broker.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/connect.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/container_identity.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/network_allowlist.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/railway/tests.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/user_key.rs
  • crates/lanes/ironclaw_sandbox/src/sandbox_process/worker_spec.rs
  • crates/lanes/ironclaw_sandbox/tests/railway_sandbox_live.rs
  • crates/lanes/ironclaw_sandbox/tests/user_sandbox_docker_live.rs
  • docker/reborn/entrypoint.sh
  • docs/internal/plans/composition-pubuse.snapshot
  • docs/internal/reborn-binary.md
  • docs/reborn/contracts/host-runtime.md
  • docs/reborn/contracts/runtime-profiles.md
  • docs/reborn/deploy-reborn-cli-docker.md
  • docs/reborn/railway-sandbox-operator.md
  • docs/reborn/target-architecture/CHECKLIST.md
  • scripts/ci/composition-budget.toml
  • scripts/ci/reborn_pr_test_plan.py
  • scripts/ci/test_reborn_pr_test_plan.py
  • tests/CLAUDE.md
  • tests/e2e_trace_runtime_policy_serde.rs
  • tests/integration/CLAUDE.md
  • tests/integration/reborn_sandbox_shell_turn.rs
  • tests/integration/support/builder.rs
  • tests/integration/support/capability_backend.rs
  • tests/integration/support/docker_gate.rs
  • tests/integration/support/harness/mod.rs
  • tests/integration/support/harness/options.rs
  • tests/integration/support/harness/profiles/mod.rs
  • tests/integration/support/harness/profiles/sandbox_shell.rs
💤 Files with no reviewable changes (1)
  • crates/app/ironclaw_composition/src/factory/capability_host_tests/approval_gates.rs

Comment thread crates/app/ironclaw_composition/src/runtime.rs Outdated
Comment on lines +22 to +24
let transport = RebornScopedSandboxCommandTransport::connect(
RebornSandboxConfig::new(workspace_root).with_network_enabled(),
)

@coderabbitai coderabbitai Bot Aug 7, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline crates/lanes/ironclaw_sandbox/src/sandbox_process.rs --items all
ast-grep outline crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs --items all

rg -n -C 6 \
  'with_network_enabled|network_enabled|NetworkMode|network_policy|allowlist|allowed_domains' \
  crates/lanes/ironclaw_sandbox \
  crates/app/ironclaw_composition \
  crates/kernel/ironclaw_runtime_policy \
  crates/kernel/ironclaw_host_runtime

rg -n -C 5 \
  'build_(local_docker|railway)_user_sandbox_binding|with_(production_)?user_sandbox_process_port' \
  crates \
  tests

Repository: nearai/ironclaw

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- sandbox.rs ---\n'
cat -n crates/app/ironclaw_composition/src/sandbox.rs

printf '\n--- sandbox_process relevant symbols ---\n'
rg -n -C 8 'enum .*Network|struct .*Config|with_network_enabled|network_enabled|NetworkMode|execute|shell|command|docker|railway' crates/lanes/ironclaw_sandbox/src/sandbox_process.rs crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs

printf '\n--- sandbox_process.rs slice ---\n'
sed -n '1,260p' crates/lanes/ironclaw_sandbox/src/sandbox_process.rs

printf '\n--- railway.rs slice ---\n'
sed -n '1,260p' crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs

Repository: nearai/ironclaw

Length of output: 244


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- sandbox.rs ---'
cat -n crates/app/ironclaw_composition/src/sandbox.rs

printf '%s\n' ''
printf '%s\n' '--- sandbox_process relevant symbols ---'
rg -n -C 8 'enum .*Network|struct .*Config|with_network_enabled|network_enabled|NetworkMode|execute|shell|command|docker|railway' crates/lanes/ironclaw_sandbox/src/sandbox_process.rs crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs

printf '%s\n' ''
printf '%s\n' '--- sandbox_process.rs slice ---'
sed -n '1,260p' crates/lanes/ironclaw_sandbox/src/sandbox_process.rs

printf '%s\n' ''
printf '%s\n' '--- railway.rs slice ---'
sed -n '1,260p' crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs

Repository: nearai/ironclaw

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- allowed domains config functions ---'
rg -n -C 10 'sandbox_allowed_domains|sandbox_network_policy|with_network_enabled|with_network_allowlist|allowed_domains|NetworkPolicy' crates/lanes/ironclaw_sandbox/src/sandbox_process crates/lanes/ironclaw_sandbox/src/sandbox_process -g '*.rs' | sed -n '1,240p'

printf '%s\n' ''
printf '%s\n' '--- Railway config methods and construction ---'
rg -n -C 8 'impl RailwayPreviewSandboxConfig|struct RailwayPreviewSandboxConfig|with_network_enabled|network_enabled|NetworkBroker|allowed_domains|command_env|container_network_mode|execute' crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs crates/lanes/ironclaw_sandbox/src/sandbox_process.rs | sed -n '1,260p'

printf '%s\n' ''
printf '%s\n' '--- tests around DirectAllowlist/networking config ---'
sed -n '1688,1738p' crates/app/ironclaw_composition/src/factory/tests.rs
rg -n -C 8 'DefaultSandboxNetworkEgress|DIRECT|allowlist|WebAccessEgress' crates/lanes/ironclaw_sandbox -g '*.rs'

Repository: nearai/ironclaw

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Railway sandbox argv construction ---'
sed -n '1,140p' crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs
rg -n -C 7 'fn sandbox_exec_argv|fn ephemeral_worker_argv|--exec|--network|direct|allowed_domains|network_mode_env|IRCL|IRONCLAW' crates/lanes/ironclaw_sandbox/src/sandbox_process/railway.rs

printf '%s\n' ''
printf '%s\n' '--- user-sandbox builder call sites in composition ---'
rg -n -C 12 'with_user_sandbox|user_sandbox_network_policy|sandbox_network_policy|user_sandbox_process_backend|ProcessBackendKind::UserSandbox' crates/app/ironclaw_composition crates/kernel/ironclaw_host_runtime crates/app/ironclaw_composition/src -g '*.rs'

printf '%s\n' ''
printf '%s\n' '--- docker worker launch test around network disabled/allowed env ---'
sed -n '880,960p' crates/lanes/ironclaw_sandbox/src/sandbox_process.rs

Repository: nearai/ironclaw

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- local production policy construction ---'
rg -n -C 12 'RebornProductionRuntimePolicy|with_user_sandbox_process_port|LocalSingleUser|Allowlist|DirectAllowlist|HostedDev|HostedYoloTenantScoped|HostedSafe|network_mode' crates/app/ironclaw_composition/src crates/kernel/ironclaw_runtime_policy/src crates/kernel/ironclaw_host_runtime/src/runtime -g '*.rs'

printf '%s\n' ''
printf '%s\n' '--- runtime policy policy construction helpers ---'
rg -n -C 10 'fn .*_user_sandbox|with_user_sandbox|NetworkMode|DefaultSandboxNetworkEgress|ALLOWED|allowed|policy|egress' crates/kernel/ironclaw_runtime_policy/src -g '*.rs'

Repository: nearai/ironclaw

Length of output: 50374


Wire the resolved user-sandbox network policy into with_network_enabled() paths.

crates/app/ironclaw_composition/src/sandbox.rs#L22-L24 and crates/app/ironclaw_composition/src/sandbox.rs#L42-L44 build the Docker/Railway user-sandbox transport with direct egress (with_network_enabled()) but do not pass the policy selected by the runtime profile. For NetworkMode::Brokered, keep the container behind the broker proxy configuration instead of enabling direct networking. For NetworkMode::Allowlist (HostedDev, HostedYoloTenantScoped), pass the resolved allowlist into the worker env/config so shell commands cannot bypass the declared egress boundaries.

📍 Affects 1 file
  • crates/app/ironclaw_composition/src/sandbox.rs#L22-L24 (this comment)
  • crates/app/ironclaw_composition/src/sandbox.rs#L42-L44
🤖 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 `@crates/app/ironclaw_composition/src/sandbox.rs` around lines 22 - 24, Update
both RebornScopedSandboxCommandTransport::connect construction sites in
crates/app/ironclaw_composition/src/sandbox.rs at lines 22-24 and 42-44 to use
the runtime-resolved network policy instead of unconditional
with_network_enabled(). Preserve broker proxy configuration for
NetworkMode::Brokered, and pass the resolved allowlist into worker
environment/configuration for NetworkMode::Allowlist, including HostedDev and
HostedYoloTenantScoped, so shell commands cannot bypass egress boundaries.

Sources: Coding guidelines, Path instructions

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Valid policy/implementation mismatch. PR1 intentionally enables direct egress for this preview (documented and covered by live tests), while the selected policy resolves . The suggested generic factory branching is not safe because Railway/local broker and allowlist enforcement are not implemented here; it would either break the preview or imply enforcement that does not exist. Leaving this open for the explicit contract choice: introduce a direct-egress preview policy or restore deny/brokered egress.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@henrypark133, agreed. The finding is valid, but the generic factory change is not a safe fix.

The current behavior intentionally provides direct egress. The selected runtime policy does not describe that behavior. This conflicts with the repository invariant: “Do not weaken … network … allowlists.”

Keep this finding open until the contract makes one explicit choice:

  1. Add a preview-only direct-egress runtime policy and select it for both sandbox profiles; or
  2. Implement brokered and allowlist enforcement in the Docker and Railway transports, then retain the current policy modes.

Do not add policy branching that claims enforcement before the transports enforce it.


✏️ Learnings added
Learnt from: henrypark133
Repo: nearai/ironclaw PR: 7214
File: crates/app/ironclaw_composition/src/sandbox.rs:22-24
Timestamp: 2026-08-07T21:13:16.351Z
Learning: For the Docker and Railway user-sandbox preview profiles in `crates/app/ironclaw_composition/src/sandbox.rs`, PR `#7214` intentionally enables direct outbound egress. The selected runtime policy currently resolves to a different egress mode, and Docker/Railway brokered or allowlist enforcement is not implemented. Do not add generic policy branching that implies egress enforcement until the transport implements it; resolve the mismatch with an explicit direct-egress preview policy or with real broker/allowlist enforcement.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

Comment thread crates/lanes/ironclaw_sandbox/tests/user_sandbox_docker_live.rs Outdated
Comment thread Dockerfile
Comment thread scripts/ci/reborn_pr_test_plan.py Outdated
Comment thread tests/integration/CLAUDE.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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.

Caution

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

⚠️ Outside diff range comments (1)
scripts/ci/reborn_pr_test_plan.py (1)

728-738: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Extend Docker-lane selectors to ironclaw_composition/src/runtime.rs.

CLAUDE.md/AGENTS.md require integration-first coverage for production-wired Reborn behavior. SANDBOX_DOCKER_EXACT_PATHS does not include crates/app/ironclaw_composition/src/runtime.rs, so a PR touching RebornRuntime::UserSandboxShutdown can skip run_sandbox_docker. Add the exact path to the selector inventory and a regression asserting the non-none plan with run_sandbox_docker enabled.

🤖 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/ci/reborn_pr_test_plan.py` around lines 728 - 738, Update
SANDBOX_DOCKER_EXACT_PATHS in scripts/ci/reborn_pr_test_plan.py to include
crates/app/ironclaw_composition/src/runtime.rs, ensuring changes to
RebornRuntime::UserSandboxShutdown enable run_sandbox_docker. Add a regression
test in scripts/ci/test_reborn_pr_test_plan.py covering that exact path and
asserting a non-none plan with run_sandbox_docker enabled.

Source: Learnings

🤖 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.

Outside diff comments:
In `@scripts/ci/reborn_pr_test_plan.py`:
- Around line 728-738: Update SANDBOX_DOCKER_EXACT_PATHS in
scripts/ci/reborn_pr_test_plan.py to include
crates/app/ironclaw_composition/src/runtime.rs, ensuring changes to
RebornRuntime::UserSandboxShutdown enable run_sandbox_docker. Add a regression
test in scripts/ci/test_reborn_pr_test_plan.py covering that exact path and
asserting a non-none plan with run_sandbox_docker enabled.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: eecdb945-f12e-4a16-b018-2a265f29ad32

📥 Commits

Reviewing files that changed from the base of the PR and between e31192d and 286e799.

📒 Files selected for processing (6)
  • crates/app/ironclaw_composition/src/runtime.rs
  • crates/app/ironclaw_composition/src/runtime/tests/core.rs
  • crates/lanes/ironclaw_sandbox/tests/user_sandbox_docker_live.rs
  • scripts/ci/reborn_pr_test_plan.py
  • scripts/ci/test_reborn_pr_test_plan.py
  • tests/integration/CLAUDE.md

…box-railway

# Conflicts:
#	crates/app/ironclaw_architecture_tests/tests/reborn_dependency_boundaries.rs
#	crates/app/ironclaw_architecture_tests/tests/reborn_restructure_baselines.rs
#	crates/kernel/ironclaw_host_runtime/tests/first_party_builtin_tools.rs
#	scripts/ci/composition-budget.toml
#	tests/CLAUDE.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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.

Caution

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

⚠️ Outside diff range comments (1)
crates/app/ironclaw_composition/src/factory.rs (1)

208-208: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove the crate-private re-export.

LateBoundAgentTurnRuntime is only referenced inside crates/app/ironclaw_composition/src/factory, and factory itself is a private Rust module. This path-preservation shim violates: “Use pub use only for an architecture-mandated contract facade or when exposing a type to downstream consumers; never use it as a path-preservation shim.” Import it from factory::trigger_creation_assembly::LateBoundAgentTurnRuntime instead.

🤖 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 `@crates/app/ironclaw_composition/src/factory.rs` at line 208, Remove the
crate-private re-export of LateBoundAgentTurnRuntime from factory.rs, and update
its internal references to import it directly from
factory::trigger_creation_assembly::LateBoundAgentTurnRuntime.

Sources: Coding guidelines, Path instructions

♻️ Duplicate comments (1)
scripts/ci/reborn_pr_test_plan.py (1)

159-187: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Schedule real-Docker validation for factory.rs sandbox wiring.

crates/app/ironclaw_composition/src/factory.rs changes RebornRuntimeStores.user_sandbox_process_port and production capability-policy availability. It is absent from the Docker selector and its regression matrix. A diff limited to that file can skip the enforced Docker lane.

  • scripts/ci/reborn_pr_test_plan.py#L159-L187: add crates/app/ironclaw_composition/src/factory.rs to SANDBOX_DOCKER_EXACT_PATHS.
  • scripts/ci/test_reborn_pr_test_plan.py#L527-L563: add the same path to test_user_sandbox_worker_change_selects_real_docker_lane.

As per path instructions, “CI and dev tooling” scripts gate merges, so behavior changes need matching workflow updates.

#!/bin/bash
set -euo pipefail

rg -n -C2 \
  'SANDBOX_DOCKER_EXACT_PATHS|crates/app/ironclaw_composition/src/factory\.rs' \
  scripts/ci/reborn_pr_test_plan.py scripts/ci/test_reborn_pr_test_plan.py
🤖 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/ci/reborn_pr_test_plan.py` around lines 159 - 187, Add
crates/app/ironclaw_composition/src/factory.rs to SANDBOX_DOCKER_EXACT_PATHS in
scripts/ci/reborn_pr_test_plan.py and add the same path to
test_user_sandbox_worker_change_selects_real_docker_lane in
scripts/ci/test_reborn_pr_test_plan.py, ensuring factory.rs-only changes select
the real-Docker validation lane.

Source: Path instructions

🤖 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.

Outside diff comments:
In `@crates/app/ironclaw_composition/src/factory.rs`:
- Line 208: Remove the crate-private re-export of LateBoundAgentTurnRuntime from
factory.rs, and update its internal references to import it directly from
factory::trigger_creation_assembly::LateBoundAgentTurnRuntime.

---

Duplicate comments:
In `@scripts/ci/reborn_pr_test_plan.py`:
- Around line 159-187: Add crates/app/ironclaw_composition/src/factory.rs to
SANDBOX_DOCKER_EXACT_PATHS in scripts/ci/reborn_pr_test_plan.py and add the same
path to test_user_sandbox_worker_change_selects_real_docker_lane in
scripts/ci/test_reborn_pr_test_plan.py, ensuring factory.rs-only changes select
the real-Docker validation lane.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 19206401-20a6-4625-abea-d0057f592611

📥 Commits

Reviewing files that changed from the base of the PR and between 286e799 and 063a4cd.

📒 Files selected for processing (19)
  • crates/app/ironclaw_architecture_tests/tests/reborn_dependency_boundaries.rs
  • crates/app/ironclaw_architecture_tests/tests/reborn_restructure_baselines.rs
  • crates/app/ironclaw_composition/src/builtin_capability_policy.rs
  • crates/app/ironclaw_composition/src/factory.rs
  • crates/app/ironclaw_composition/src/factory/production_backend_assembly.rs
  • crates/app/ironclaw_composition/src/factory/tests.rs
  • crates/app/ironclaw_composition/src/product_surface.rs
  • crates/app/ironclaw_composition/src/runtime.rs
  • crates/app/ironclaw_composition/src/runtime/capability_host/tests.rs
  • crates/app/ironclaw_composition/src/runtime/tests/core.rs
  • crates/kernel/ironclaw_host_runtime/src/first_party_tools/mod.rs
  • crates/kernel/ironclaw_host_runtime/src/lib.rs
  • crates/kernel/ironclaw_host_runtime/tests/first_party_builtin_tools.rs
  • scripts/ci/composition-budget.toml
  • scripts/ci/reborn_pr_test_plan.py
  • scripts/ci/test_reborn_pr_test_plan.py
  • tests/CLAUDE.md
  • tests/integration/CLAUDE.md
  • tests/integration/support/harness/mod.rs
💤 Files with no reviewable changes (1)
  • crates/app/ironclaw_composition/src/builtin_capability_policy.rs

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-7214 — 063a4cdc Deployed Aug 7, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: medium Business logic, config, or moderate-risk modules scope: ci CI/CD workflows scope: dependencies Dependency updates scope: docs Documentation scope: sandbox Docker sandbox size: XL 500+ changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants