Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
d90f4c1
feat(sandbox): package the macOS native plugin exec entry
vanedaltro Oct 29, 2026
6b34933
feat(sandbox): package Linux native plugin startup boundary
vanedaltro Oct 29, 2026
afdf44f
test(sandbox): grant fixture null-device reads and exercise argument …
vanedaltro Oct 29, 2026
95848c1
test(sandbox): exercise packaged helper across native runtime matrix
vanedaltro Oct 29, 2026
758b86f
test(sandbox): distinguish Deno descriptor control and collect runtim…
vanedaltro Oct 29, 2026
bc85090
docs(sandbox): record native Linux packaged runtime acceptance
vanedaltro Oct 29, 2026
3a5fa82
feat(sandbox): serialize generation revocation with final launch commit
vanedaltro Oct 29, 2026
a4e97c1
fix(plugins): isolate host bootstrap environment from tool overlays
vanedaltro Oct 29, 2026
c812102
fix(ci): build sandbox helper before plugin bootstrap acceptance
vanedaltro Oct 29, 2026
9e802ec
fix(plugins): select package runtime startup configuration
vanedaltro Oct 29, 2026
ef19583
feat(sandbox): inventory private plugin roots without content IO
vanedaltro Oct 29, 2026
729546f
feat(sandbox): compose bounded native macOS plugin policies
vanedaltro Oct 29, 2026
de2c91e
test(sandbox): avoid timestamp precision assumptions in alias checks
vanedaltro Oct 29, 2026
94e1ada
Merge private inventory test correction
vanedaltro Oct 29, 2026
483066c
fix(ci): allow Intel bootstrap acceptance to finish compiling
vanedaltro Oct 29, 2026
dadfe18
Merge bootstrap acceptance build budget correction
vanedaltro Oct 29, 2026
7261e88
Merge bootstrap acceptance build budget correction
vanedaltro Oct 29, 2026
0cf48fc
test(sandbox): prove Linux protected mount ancestry and file masks
vanedaltro Oct 29, 2026
ee7268c
test(sandbox): record kernel and mount runtime versions
vanedaltro Oct 29, 2026
d4fcf3e
test(sandbox): retain observed Linux device mask denials
vanedaltro Oct 29, 2026
2548fde
docs(sandbox): record Linux protected mount primitive receipts
vanedaltro Oct 29, 2026
27f1a90
feat(sandbox): compose native Linux plugin mounts and Landlock policy
vanedaltro Oct 29, 2026
b4822f2
test(sandbox): scope unavailable policy assertions to non-Linux hosts
vanedaltro Oct 29, 2026
546641f
test(sandbox): distinguish private file masks from directory masks
vanedaltro Oct 29, 2026
856a70f
docs(plugins): retain Linux policy native evidence
vanedaltro Oct 29, 2026
505537f
test(plugins): probe native Linux host socket reachability
vanedaltro Oct 29, 2026
18791fb
docs(plugins): record native UNIX socket counterexample
vanedaltro Oct 29, 2026
ccde59d
test(plugins): evaluate Linux socket-family confinement
vanedaltro Oct 29, 2026
15e1ef8
test(plugins): reject pair rebinding in IPC candidate
vanedaltro Oct 29, 2026
35dfec0
Merge remote-tracking branch 'origin/main' into feat/plugin-linux-ipc…
vanedaltro Oct 29, 2026
3c2cf7e
docs: constrain goal delivery to one active PR
vanedaltro Oct 29, 2026
2f3b3c2
test(plugins): evaluate path-scoped UNIX socket confinement
vanedaltro Oct 29, 2026
0855777
test(plugins): record unavailable UNIX policy kernel support
vanedaltro Oct 29, 2026
19cf223
fix(plugins): exclude project paths from runtime lookup
vanedaltro Oct 29, 2026
f3e761b
fix(plugins): retain host group identity until child cleanup
vanedaltro Oct 29, 2026
228ac01
fix(plugins): retain host resources through cancelled cleanup
vanedaltro Oct 30, 2026
7936cb6
test(plugins): probe thread-specific socket descriptor pinning
vanedaltro Oct 30, 2026
c0feb88
docs: prioritize active goal PR readiness
vanedaltro Oct 30, 2026
91568c7
test: bound feedback chain waits by progress
vanedaltro Oct 30, 2026
7fbf892
docs: retain native descriptor pinning receipts
vanedaltro Oct 30, 2026
321e607
test(plugins): separate fixture startup from cleanup deadlines
vanedaltro Oct 30, 2026
f84c394
test(plugins): prototype descriptor-pinned socket mediation
vanedaltro Oct 30, 2026
fb5a5a1
docs: retain source-bound socket broker results
vanedaltro Oct 30, 2026
9de3bf7
test(plugins): exercise broker thread-local descriptor tables
vanedaltro Oct 30, 2026
9d0e205
test(hooks): hold only the callback exercised by shutdown
vanedaltro Oct 30, 2026
51bf555
docs: retain broker thread-selection evidence
vanedaltro Oct 30, 2026
7a8ed4e
test(plugins): prove cancellation settles owned socket workers
vanedaltro Oct 30, 2026
204866e
docs: retain socket-worker cancellation receipts
vanedaltro Oct 30, 2026
d47cfe2
test(plugins): exercise socket and address mutation
vanedaltro Oct 30, 2026
7ca8058
docs: retain socket mutation proof receipts
vanedaltro Oct 30, 2026
71d0199
test(plugins): exercise escaped descendant namespace lifetime
vanedaltro Oct 30, 2026
4760de7
docs: retain escaped descendant settlement evidence
vanedaltro Oct 30, 2026
ceecb47
test(plugins): exercise socket worker capacity and recovery
vanedaltro Oct 30, 2026
e6fd3d2
fix(plugins): retain unconfirmed package worker ownership
vanedaltro Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ binary_id(cyber-account)
| binary_id(cyber-sandbox::bridge)
| binary_id(cyber-sandbox::git_inspection)
| binary_id(cyber-sandbox::plugin_copy)
| binary_id(cyber-sandbox::native_exec)
| binary_id(cyber-sandbox::proxy_shutdown)
| binary_id(cyber-sandbox::windows_confine)
| binary_id(cyber-sandbox::windows_job)
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
branches: [main]
pull_request:

concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
# Commits that only touch root Markdown, docs/ or openspec/ skip the build and test
# jobs; OpenSpec validation still runs for them.
Expand Down
292 changes: 292 additions & 0 deletions .github/workflows/plugin-bootstrap-environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
name: Plugin bootstrap environment

on:
workflow_dispatch:
pull_request:
paths:
- crates/cyber-tools/src/plugin_host/**
- crates/cyber-app/tests/plugins.rs
- crates/cyber-sandbox/**
- .github/workflows/plugin-bootstrap-environment.yml
- Cargo.lock
push:
branches: [main]
paths:
- crates/cyber-tools/src/plugin_host/**
- crates/cyber-app/tests/plugins.rs
- crates/cyber-sandbox/**
- .github/workflows/plugin-bootstrap-environment.yml
- Cargo.lock

permissions:
contents: read

concurrency:
group: plugin-bootstrap-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
bootstrap:
name: Host bootstrap (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm, macos-15, macos-15-intel, windows-latest]
env:
CARGO_INCREMENTAL: 0
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.4.4'
- uses: denoland/setup-deno@v2
with:
deno-version: 'v2.9.8'
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Linux sandbox prerequisites
if: runner.os == 'Linux'
shell: bash
run: |
set -euo pipefail
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.*
sudo apt-get update
sudo apt-get install -y bubblewrap
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
- name: Build distributed sandbox helper
shell: bash
run: cargo build --locked -p cyber-sandbox --bin cyber-sandbox-exec
- name: Verify explicit environment construction
shell: bash
run: cargo test --locked -p cyber-tools --lib plugin_host::environment
- name: Verify runtime search exclusions
shell: bash
run: cargo test --locked -p cyber-tools --lib plugin_host::runtime_search
- name: Verify missing runtime search guards are detected
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
source=crates/cyber-tools/src/plugin_host/runtime_search.rs
cp "$source" "$RUNNER_TEMP/runtime-search-positive.rs"
trap 'cp "$RUNNER_TEMP/runtime-search-positive.rs" "$source"' EXIT
python3 - "$source" <<'PY'
from pathlib import Path
import sys
path = Path(sys.argv[1])
text = path.read_text()
for before in ['excluded.iter().any(|root| directory.starts_with(root))',
'excluded.iter().any(|root| candidate.starts_with(root))']:
assert text.count(before) == 1
text = text.replace(before, 'false')
path.write_text(text)
PY
name=project_and_package_path_entries_cannot_shadow_the_owner_runtime
if cargo test --locked -p cyber-tools --lib "plugin_host::runtime_search::tests::$name" -- --exact > "$RUNNER_TEMP/runtime-search-control.log" 2>&1; then
echo 'Missing runtime search guards unexpectedly passed' >&2
exit 1
fi
python3 - "$RUNNER_TEMP/runtime-search-control.log" "$name" <<'PY'
from pathlib import Path
import sys
text = Path(sys.argv[1]).read_text()
assert f'{sys.argv[2]} ... FAILED' in text, text
assert 'runtime selection receipt' in text, text
PY
cp "$RUNNER_TEMP/runtime-search-positive.rs" "$source"
cargo test --locked -p cyber-tools --lib plugin_host::runtime_search
- name: Verify same-group plugin child lifetime
if: runner.os != 'Windows'
shell: bash
run: cargo test --locked -p cyber-tools --lib plugin_host::settlement_tests
- name: Verify host resource lifetime controls
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
source=crates/cyber-tools/src/plugin_host/lifetime.rs
cp "$source" "$RUNNER_TEMP/plugin-lifetime-positive.rs"
trap 'cp "$RUNNER_TEMP/plugin-lifetime-positive.rs" "$source"' EXIT
for control in tree early-resources unknown-resources; do
cp "$RUNNER_TEMP/plugin-lifetime-positive.rs" "$source"
python3 - "$source" "$control" <<'PYCONTROL'
from pathlib import Path
import sys
path = Path(sys.argv[1]); text = path.read_text()
if sys.argv[2] == 'tree':
before, after = '.wait_tree()', '.wait()'
elif sys.argv[2] == 'early-resources':
before = 'if let Some(held) = self.held.take() {\n let _reply = schedule(held);'
after = 'if let Some(mut held) = self.held.take() {\n held.resources.take();\n let _reply = schedule(held);'
else:
before, after = 'std::mem::forget(resources);', 'drop(resources);'
assert text.count(before) == 1
path.write_text(text.replace(before, after))
PYCONTROL
query=same_group_child
if [[ "$control" == early-resources ]]; then query=plugin_host::settlement_tests::abandoned_initialization_keeps_scratch_until_cleanup_waits; fi
if [[ "$control" == unknown-resources ]]; then query=plugin_host::settlement_tests::unconfirmed_wait_retains_resources_without_signalling_cached_group; fi
if cargo test --locked -p cyber-tools --lib "$query" > "$RUNNER_TEMP/plugin-lifetime-$control-control.log" 2>&1; then
echo "Missing $control lifetime guard unexpectedly passed" >&2
exit 1
fi
python3 - "$RUNNER_TEMP/plugin-lifetime-$control-control.log" "$control" <<'PYCONTROL'
from pathlib import Path
import re, sys
text = re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]', '', Path(sys.argv[1]).read_text())
cases = {
'tree': (['crashed_host_stops_its_same_group_child_and_releases_scratch',
'acknowledged_shutdown_stops_a_same_group_child_after_leader_exit'],
'plugin descendant retained stdout after host settlement'),
'early-resources': (['abandoned_initialization_keeps_scratch_until_cleanup_waits'],
'scratch removed before cleanup waiter ran'),
'unknown-resources': (['unconfirmed_wait_retains_resources_without_signalling_cached_group'],
'unconfirmed wait deleted host scratch'),
}
names, reason = cases[sys.argv[2]]
for name in names: assert name + ' ... FAILED' in text, text
assert reason in text, text
PYCONTROL
done
cp "$RUNNER_TEMP/plugin-lifetime-positive.rs" "$source"
cargo test --locked -p cyber-tools --lib plugin_host::settlement_tests
- name: Verify non-consuming proxy revocation
shell: bash
run: cargo test --locked -p cyber-sandbox --lib proxy::tests
- name: Verify bundled runtime startup receipts
shell: bash
run: |
set -euo pipefail
bun --version
deno --version
cargo test --locked -p cyber-tools --lib plugin_host::launch -- --include-ignored
- name: Verify missing runtime startup filters are detected
shell: bash
run: |
set -euo pipefail
source=crates/cyber-tools/src/plugin_host/launch.rs
cp "$source" "$RUNNER_TEMP/runtime-startup-positive.rs"
trap 'cp "$RUNNER_TEMP/runtime-startup-positive.rs" "$source"' EXIT
for runtime in bun deno; do
cp "$RUNNER_TEMP/runtime-startup-positive.rs" "$source"
python3 - "$runtime" <<'PY'
import sys
from pathlib import Path
path = Path('crates/cyber-tools/src/plugin_host/launch.rs')
text = path.read_text()
start = text.index('fn bun_arguments(' if sys.argv[1] == 'bun' else 'fn deno_arguments(')
end = text.index('\nfn deno_arguments(' if sys.argv[1] == 'bun' else '\nfn runtime_config(', start)
body = text[start:end]
flag, replacement = ('"--no-env-file".into(),', '') if sys.argv[1] == 'bun' else ('vec!["--no-config".into()]', 'Vec::new()')
assert body.count(flag) == 1
body = body.replace(flag, replacement)
path.write_text(text[:start] + body + text[end:])
PY
if [[ "$runtime" == bun ]]; then
name=bun_starts_bundled_rpc_without_project_preloads_or_dotenv
else
name=deno_starts_bundled_rpc_without_project_configuration_or_lock_changes
fi
if cargo test --locked -p cyber-tools --lib "plugin_host::launch::startup_tests::$name" -- --ignored --exact > "$RUNNER_TEMP/runtime-$runtime-control.log" 2>&1; then
cat "$RUNNER_TEMP/runtime-$runtime-control.log"
echo "Missing $runtime startup filter unexpectedly passed" >&2
exit 1
fi
cat "$RUNNER_TEMP/runtime-$runtime-control.log"
python3 - "$RUNNER_TEMP/runtime-$runtime-control.log" "$name" <<'PY'
import re, sys
from pathlib import Path
text = re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]', '', Path(sys.argv[1]).read_text())
assert f'{sys.argv[2]} ... FAILED' in text
assert 'project startup code ran before the approved entry' in text or 'runtime startup failed' in text
PY
done
cp "$RUNNER_TEMP/runtime-startup-positive.rs" "$source"
cargo test --locked -p cyber-tools --lib plugin_host::launch -- --include-ignored
- name: Verify prepared workspace boundary is required
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
source=crates/cyber-sandbox/src/plugin_image.rs
cp "$source" "$RUNNER_TEMP/workspace-boundary-positive.rs"
trap 'cp "$RUNNER_TEMP/workspace-boundary-positive.rs" "$source"' EXIT
python3 - <<'PYCONTROL'
from pathlib import Path
path = Path('crates/cyber-sandbox/src/plugin_image.rs')
text = path.read_text()
original = 'const NAME: &str = "package.json";'
assert text.count(original) == 1
path.write_text(text.replace(original, 'const NAME: &str = "without-boundary.json";'))
PYCONTROL
name=deno_starts_bundled_rpc_without_project_configuration_or_lock_changes
if cargo test --locked -p cyber-tools --lib "plugin_host::launch::startup_tests::$name" -- --ignored --exact > "$RUNNER_TEMP/workspace-boundary-control.log" 2>&1; then
cat "$RUNNER_TEMP/workspace-boundary-control.log"
echo 'Missing-workspace-boundary control unexpectedly passed' >&2
exit 1
fi
cat "$RUNNER_TEMP/workspace-boundary-control.log"
python3 - "$RUNNER_TEMP/workspace-boundary-control.log" <<'PYCONTROL'
from pathlib import Path
import re, sys
text = re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]', '', Path(sys.argv[1]).read_text())
assert 'deno_starts_bundled_rpc_without_project_configuration_or_lock_changes ... FAILED' in text
assert 'runtime startup failed' in text
PYCONTROL
cp "$RUNNER_TEMP/workspace-boundary-positive.rs" "$source"
cargo test --locked -p cyber-tools --lib plugin_host::launch -- --include-ignored
- name: Verify real production plugin hosts
if: runner.os != 'Windows'
shell: bash
run: cargo test --locked -p cyber-app --test plugins
- name: Verify unsafe tool overlays fail the production regression
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
source=crates/cyber-tools/src/plugin_host/launch.rs
cp "$source" "$RUNNER_TEMP/plugin-launch-positive.rs"
trap 'cp "$RUNNER_TEMP/plugin-launch-positive.rs" "$source"' EXIT
python3 - <<'PY'
from pathlib import Path
path = Path('crates/cyber-tools/src/plugin_host/launch.rs')
text = path.read_text()
original = ' let environment =\n super::environment::build(plugin.name, plugin.root, &scratch.path, &wrapped.env);'
assert text.count(original) == 1
replacement = original.replace('let environment =', 'let mut environment =') + '\n environment.extend(launch.config.env.set.clone());'
path.write_text(text.replace(original, replacement))
PY
if cargo test --locked -p cyber-app --test plugins plugin_bootstrap_environment_ignores_tool_overlays_and_owns_home -- --exact > "$RUNNER_TEMP/plugin-overlay-control.log" 2>&1; then
cat "$RUNNER_TEMP/plugin-overlay-control.log"
echo 'Unsafe-overlay control unexpectedly passed' >&2
exit 1
fi
cat "$RUNNER_TEMP/plugin-overlay-control.log"
python3 - "$RUNNER_TEMP/plugin-overlay-control.log" <<'PY'
import re, sys
from pathlib import Path
text = re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]', '', Path(sys.argv[1]).read_text())
assert 'plugin_bootstrap_environment_ignores_tool_overlays_and_owns_home ... FAILED' in text
assert 'inspect_bootstrap was not advertised' in text or 'assertion `left == right` failed' in text
PY
cp "$RUNNER_TEMP/plugin-launch-positive.rs" "$source"
cargo test --locked -p cyber-app --test plugins plugin_bootstrap_environment_ignores_tool_overlays_and_owns_home -- --exact
- name: Retain unsafe-overlay counterexample
if: always()
uses: actions/upload-artifact@v4
with:
name: plugin-overlay-control-${{ matrix.os }}
path: |
${{ runner.temp }}/plugin-overlay-control.log
${{ runner.temp }}/runtime-bun-control.log
${{ runner.temp }}/runtime-deno-control.log
${{ runner.temp }}/workspace-boundary-control.log
${{ runner.temp }}/runtime-search-control.log
${{ runner.temp }}/plugin-lifetime-*-control.log
if-no-files-found: warn
retention-days: 14
Loading
Loading