shared bwrap sandbox, skip for super admin, extend to pi and terminals

- extract buildSandboxPrefix/buildRunuserSuffix into shared sandbox.ts
- super admin bypasses bwrap for full host access (claude, pi, terminal)
- member pi processes now use bwrap instead of sudo -u
- member terminals now use bwrap instead of sudo -u
- mount /run for systemd-resolved DNS inside sandbox
- pass role through claude spawn params and channel types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 00:06:44 +00:00
co-authored by Claude Opus 4.6
parent c38d5b0ea1
commit 9578110e8b
9 changed files with 386 additions and 180 deletions
+4 -17
View File
@@ -123,7 +123,6 @@ async function handleCommand(ws, msg) {
const cwd = config.cwd ?? process.cwd();
const homeDir = config.homeDir ?? process.cwd();
const userLabel = config.userLabel ?? 'officer';
const username = config.username ?? null;
const cols = config.cols ?? 80;
const rows = config.rows ?? 24;
const isHost = !!config.host;
@@ -136,11 +135,8 @@ async function handleCommand(ws, msg) {
spawnCommand = shell.command;
spawnArgs = shell.args ?? [];
ptyEnv = { ...process.env, TERM: 'xterm-256color', ...(config.env ?? {}) };
} else if (username) {
spawnCommand = 'sudo';
spawnArgs = ['-u', username, '-i', '/bin/zsh'];
ptyEnv = { TERM: 'xterm-256color' };
} else {
// Sandboxed mode: shell config contains the full bwrap command
spawnCommand = shell.command;
spawnArgs = shell.args ?? [];
@@ -150,20 +146,11 @@ async function handleCommand(ws, msg) {
console.error('[pty-sidecar] ensureUserFiles failed:', err);
}
ptyEnv = {
...process.env,
HOME: homeDir,
ZDOTDIR: homeDir,
ZSH: `${homeDir}/.oh-my-zsh`,
SHELL: shell.command,
USER: userLabel,
LOGNAME: userLabel,
OFFICER_TERMINAL_USER: userLabel,
TERM: 'xterm-256color',
};
// bwrap sets env vars internally via --setenv, so use minimal host env
ptyEnv = { TERM: 'xterm-256color' };
}
const ptyCwd = username ? undefined : cwd;
const ptyCwd = isHost ? cwd : undefined;
let term;
try {