feat: /workspace cwd + /home/agentos home + binding facade + all-platform publish#110
Merged
Merged
Conversation
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 20:11
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 20:11
Destroyed
These were absolute symlinks pointing at /home/nathan/secure-exec/... — a local checkout — so they dangle on every other machine and break `pnpm install` (it cannot create a real node_modules over a stale symlink). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The native stack previously compiled only on Linux. This adds macOS (aarch64/x86_64) support, gated entirely behind cfg(target_os) so the Linux paths are untouched. v8-runtime (per-thread CPU accounting): - timeout.rs: pthread_getcpuclockid has no macOS equivalent; the CpuBudgetGuard watchdog now reads the execution thread's CPU time via the Mach thread port (pthread_mach_thread_np + thread_info(THREAD_BASIC_INFO)), readable cross-thread like the Linux clockid. - bridge.rs: RUSAGE_THREAD is Linux-only; process.cpuUsage/resourceUsage get per-thread CPU time from thread_info, the rest best-effort from RUSAGE_SELF. sidecar (host-mount filesystem confinement): - macos_fs.rs: macOS has no openat2(RESOLVE_BENEATH); resolve-beneath path resolution now goes through cap-std (audited userspace walk; openat2 on Linux, fd-relative O_NOFOLLOW walk elsewhere). F_GETPATH replaces readlink on /proc/self/fd; /dev/fd/N replaces /proc/self/fd/N. - host_dir.rs + filesystem.rs: open_beneath / mapped-runtime helpers resolve via cap-std on macOS; O_PATH -> read-only anchor, O_TMPFILE -> empty. All nine mapped-runtime child ops (mkdir/rmdir/unlink/symlink/rename/readlink/lstat/ lutimes) converted from the Linux /proc/self/fd-join idiom to fd-relative *at calls, since /dev/fd/N cannot have children appended. lstat goes through a platform-neutral HostStat translator; rename uses renameat with a real-path EXDEV fallback. Also fixes a latent dangling-fd bug in the mapped utimes path (the resolved handle is now held across the operation on both platforms). - execution.rs: waitid/WNOWAIT is unavailable in nix on macOS; the child-status poll uses waitpid(WNOHANG) there. - Plus latent macOS type-width fixes (mode_t/dev_t/nlink_t). All sidecar lib tests pass on macOS, including every host-mount escape test. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
🚅 Deployed to the secure-exec-pr-110 environment in rivet-frontend
🚅 Deployed to the secure-exec-pr-110 environment in secure-exec
|
…sidecar-client subpath
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 21:24
5e29442 to
c85b45d
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 21:24
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 21:24
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 21:26
c85b45d to
4ec4609
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 21:26
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 21:26
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 21:37
4ec4609 to
e2428fd
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 21:37
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 21:37
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 21:39
e2428fd to
bd51902
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 21:39
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 21:39
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 21:42
bd51902 to
f4f6a8b
Compare
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 21:42
Destroyed
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 21:42
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 21:46
f4f6a8b to
30d5881
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 21:46
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 21:46
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 22, 2026 23:19
30d5881 to
12e8986
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 22, 2026 23:19
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 22, 2026 23:19
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 23, 2026 01:41
12e8986 to
88fbdf2
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 01:41
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 01:41
Destroyed
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 02:13
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 02:13
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 23, 2026 02:15
8575436 to
312c8b3
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 02:15
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 02:15
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 23, 2026 03:47
312c8b3 to
3b83506
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 03:47
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 03:47
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 23, 2026 08:41
3b83506 to
264b49d
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 08:41
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 08:41
Destroyed
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 23, 2026 08:49
264b49d to
8492871
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 08:49
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 08:49
Destroyed
…OS (ABI + env + names) Also fix publish workspace-leak: bumpCargoVersions... bumpPackageJsons only converted workspace:* deps on DISCOVERED packages, so a dep on the CI-excluded @secure-exec/core leaked workspace:* into published tarballs (s3/sandbox/ google-drive), breaking consumers. Now convert any @secure-exec/* workspace dep.
NathanFlurry
force-pushed
the
nathan/workspace-binding-agentos
branch
from
June 23, 2026 09:07
8492871 to
a4e69e3
Compare
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 09:07
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 09:07
Destroyed
… (guest readdir/exec)
The macOS port converted every host-mount child *mutation* to fd-relative
`*at` syscalls but left directory enumeration on `fs::read_dir(proc_path())`,
where `proc_path()` is `/dev/fd/N` on darwin. Unlike Linux's
`/proc/self/fd/N`, a directory fd's `/dev/fd/N` entry is not readdir-able and
returns `ENOTDIR (os error 20)`. That single miss cascaded into both guest
failures:
* guest `readdirSync('/')` -> `ENOTDIR`, and
* guest `exec("/bin/sh")` (ls/tr/node) -> "refused to compile guest
WebAssembly module ... shell-shim script": `discover_command_guest_paths`
reads `/__secure_exec/commands` via the same broken readdir, finds nothing,
so no commands are registered with the CommandDriver and the exec falls
through to the raw `#!/bin/sh` kernel-command stub.
Fix: add `AnchoredFd::readdir_path()` and use it at the three directory-
enumeration sites (host_dir `read_dir`/`read_dir_with_types`, mapped-runtime
`fs.readdir`). On Linux it returns `/proc/self/fd/N` unchanged; on macOS it
recovers the fd's real host path via `fcntl(F_GETPATH)` — the same fd->path
recovery already used for anchored fds elsewhere on darwin. File re-opens keep
using `/dev/fd/N` (inode-pinned, works), and child mutations keep using `*at`.
Strictly `#[cfg(target_os = "macos")]`-gated; Linux paths are byte-identical.
Also wire `macos_fs` into the `filesystem` integration test, which `include!`s
`host_dir.rs` and so needs the module resolvable in the test binary on macOS.
Tests on Apple Silicon: `--test filesystem` 10/10 and `--test posix_compliance`
7/7 pass; reverting only the macOS readdir arm reproduces "command not found
... /bin/ls".
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 10:21
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 10:21
Destroyed
Second darwin fix, surfaced by running the full sidecar suite natively (which the readdir fix made possible). Two parts: 1. Production: `create_vm_shadow_root` used `std::env::temp_dir()` verbatim (`/var/folders/…` on macOS), but `/var` is a symlink to `/private/var` and macOS fd→path recovery (`fcntl(F_GETPATH)`, used by `mapped_runtime_host_path_from_fd`) reports the resolved `/private/var/…` form. The mapped-runtime confinement then did `strip_prefix(host_root)` of an F_GETPATH'd child against the unresolved `/var` root, which failed for every child — so the `fs.readdir` entry-typing loop dropped all entries and guest `readdirSync` of a populated directory returned `[]`. Canonicalize the shadow root up front (macOS-only; host_dir mounts already canonicalize their root for the same reason). Fixes the guest-vs-host-Node divergences in posix_path_repro and builtin_conformance. 2. Test harness: several test targets `include!`/`#[path]`-pull sidecar source (`host_dir.rs`, `filesystem.rs` via service.rs) whose macOS-only `crate::macos_fs::…` references must resolve in the test binary; wire the module in (macOS-only). Also add `crates/sidecar/src/macos_fs.rs` — the macOS resolve-beneath chokepoint — to the architecture_guards `FS_ALLOW` allowlist (sibling to host_dir.rs/filesystem.rs). These let the sidecar test suite compile and run on Apple Silicon at all. Native Apple-Silicon results after this + the readdir fix: 468 passing. The remaining failures are environmental (no network/python in the sandbox) or separate pre-existing macOS-port gaps (host_dir EACCES-vs-EPERM errno mapping, sandbox_agent `/private/var` path unscoping) tracked separately. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…lize mock sandbox-agent root Two remaining darwin parity gaps surfaced by the now-runnable macOS suite: 1. host_dir chmod/chown/utimes on a symlink returned EACCES, not EPERM. The Linux path opens the final component as an `O_PATH | O_NOFOLLOW` anchor and rejects a symlink with EPERM, but macOS has no `O_PATH` and `open(O_NOFOLLOW)` on a symlink fails — the resolve-beneath refusal surfaced as EACCES before the EPERM check could run. Add a macOS branch that `lstat`s the final component through the resolved parent fd (`fstatat(AT_SYMLINK_NOFOLLOW)`) and rejects a symlink with EPERM, matching Linux; non-symlinks open as the anchor as before. 2. test-only: the `MockSandboxAgentServer` strips its temp-dir root prefix from the `realpath` the process helper returns, but on macOS the root is `/var/folders/…` while `realpath` resolves to `/private/var/…`, so stripping failed and the absolute host path leaked back (the plugin's own unscoping is correct). Canonicalize the mock root, same as the production shadow root. Native Apple-Silicon: host_dir 7/7 and sandbox_agent 15/15 now pass. Both changes are `#[cfg(target_os = "macos")]`-gated; Linux is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 11:03
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 11:03
Destroyed
… EINVAL) Review follow-up. The macOS open_metadata_beneath branch routed every path through split_parent, which has no final component for the mount root `/` and returned EINVAL — diverging from Linux, where chmod/chown/utimes on the root succeed (the O_PATH|O_NOFOLLOW open of the root works; root is never a symlink). Special-case the root: open it directly as the anchor before the lstat path. macOS-only; Linux unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
railway-app
Bot
temporarily deployed
to
secure-exec / secure-exec-pr-110
June 23, 2026 11:12
Destroyed
railway-app
Bot
temporarily deployed
to
rivet-frontend / secure-exec-pr-110
June 23, 2026 11:12
Destroyed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the secure-exec side of
SPEC-bindings-workspace.md.user→agentosvia a clean Alpine re-snapshot (uid/gid 1000);$HOME=/home/agentos. Zero/home/userresidue./workspacedefault cwd, decoupled from$HOME: base-fs dir +vm.rsSHADOW_ROOT_BOOTSTRAP_DIRS+ cwd default + kernel defaults + shadow-bootstrap allowlist.@secure-exec/coresidecar-clientfacade restored so consumers (agentOS) keep importingSidecarProcess+ theSidecar*types from it.binding(tool rename) present..exe. (windows/musl flagged for a CI shake-out.)/home/user→/home/agentos(HOME) //workspace(cwd) /agentos(username) across crates, tests, docs, examples.