Skip to content

feat(machine): separated agent contexts on Linux nodes, dormant behind assistant:machine-contexts (0.60.0) - #1764

Merged
chronoai-kai merged 11 commits into
mainfrom
feat/machine-contexts
Oct 4, 2026
Merged

chronoai-kai merged 11 commits into
mainfrom
feat/machine-contexts

Conversation

@chronoai-kai

Copy link
Copy Markdown
Contributor

Summary

M1.3 backend/runtime milestone: separated agent contexts on Linux machine nodes, dormant behind assistant:machine-contexts (default off). This mode is never described as "isolated"; full isolation still requires a separate machine container or VM.

  • Opt-in only: a mode change happens only through nyxid__machine_capabilities (selection.mode) with an owner action card. The human Grants PUT refuses mode. Existing assignments stay shared_legacy. Separated authority is issued only to nodes that advertise separated.available, so old nodes never receive it.
  • Per-context identity: UIDs (20000+) are never reused. Each context gets a private 0700 workspace/home/tmp under root-owned, non-writable ancestors. The signed context binding (agent/owner/actor/group) has generation quarantine; saved-login removal, membership loss and mode or login-selection changes bump the generation and quarantine the node profiles.
  • Commands and files: Landlock ABI 6 with a filesystem allowlist plus signal and abstract-socket scoping, applied after the UID/GID switch and NNP, with close_range(CLOEXEC).
  • Browsers: separate secure/dev users, profiles, displays, D-Bus and native sockets, protected by DAC, Chromium's sandbox and Landlock scoping. Saved-login fills are context-bound and fenced on the login row.
  • Legacy roots: on first opt-in they become root:<agent gid> 0770, so context UIDs cannot traverse them. This is fail-closed: only roots owned by the NyxID agent user are touched.
  • Availability: requires euid 0, separate non-root agent/browser/dev users, a managed browser and a live Landlock probe. Otherwise separated.reason explains why, and there is never a silent shared fallback.
  • Documented residuals: shared /dev/shm namespace (distinct UIDs and 0600 protect contents), network not restricted, browsers without a filesystem Landlock ruleset. Details are in docs/MACHINE_AGENT_ISOLATION.md and docs/MACHINE_CONTEXT_SPIKE.md.

Backward compatibility

  • New fields are additive or serde-defaulted: Selection.mode, MachineReceipt.context_mode, MachineProfile.separated. The advertised context::Support accepts unknown fields; node-local journals stay strict.
  • Shared-legacy behaviour is unchanged. Emergency preempt kills the runtime's own UID jobs, which is every job in shared mode. File traversal uses O_PATH for ancestors. The developer-browser user is still resolved lazily at launch.
  • The request_agent_skills schema is byte-identical to main.
  • CLAUDE.md now lists the existing 12419–12422 machine codes; nodes reuse 12419 for separated_context_unavailable and 12421 for context_quarantine_pending.

Follow-up (M1.3b, before owner rollout)

Graphical opt-in, the human desktop API/context selector, and native separate-users VM browser validation.

Validation

  • Implementer, at both default and RUST_MIN_STACK=1572864:
    • host CLI + machine 1,509 passed; Linux arm64 CLI + machine 1,515 passed; Linux privileged checks 7;
    • backend machine 101, saved-login 6, chat-authority 24, assistant-team 14, agent-learning 3;
    • frontend 4,226 tests;
    • Rust 1.98.1 workspace and Linux clippy with -D warnings;
    • native arm64 container e2e under both seccomp profiles, adversarial suite 44 checks per profile.
  • Reviewer: two rounds. Fixed the misplaced mode schema, a stale main merge, a deny_unknown_fields field on the advertised wire type, eager dev-identity resolution, and the error-code documentation.

chrono-kw added 9 commits October 4, 2026 05:06
…olation

# Conflicts:
#	backend/src/routes.rs
…xt users, workspaces and browsers, dormant behind assistant:machine-contexts (M1.3)

Merges origin/main (0.58.0). Owner-card opt-in only; existing assignments stay
shared_legacy and old nodes never receive separated authority. Per-context
never-reused UIDs with private 0700 workspace/home/tmp, signed context
binding with generation quarantine, Landlock ABI 6 for commands and files,
separate secure/dev browser users, profiles and displays, and context-bound
saved-login fills. Never described as isolated: residuals are documented in
docs/MACHINE_AGENT_ISOLATION.md.
# Conflicts:
#	cli/src/wizard/bundle-meta/index.hash
Comment thread cli/src/node/machine/browser.rs Fixed
@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

📊 Code coverage

Component Lines Threshold Status Δ vs base
Backend (nyxid) 87.05% 73% ✅ 🔺 +0.01
CLI (nyxid-cli) 69.23% 64% ✅ 🔻 -0.83
Frontend (vitest) 72.10% 15% ✅ — 0.00

Gate: line coverage must stay at or above the threshold. Ratchet plan (W21): Backend → 55%, CLI → 50%, Frontend → 30% by quarter end.

chrono-kw added 2 commits October 5, 2026 02:33
# Conflicts:
#	Cargo.lock
#	backend/Cargo.toml
#	cli/Cargo.toml
#	cli/src/wizard/bundle-meta/index.hash
#	frontend/package-lock.json
#	frontend/package.json
@chronoai-kai
chronoai-kai merged commit 5277136 into main Oct 4, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants