feat(hh): real VM unix users + sudo delegation ⛧
Linux-style user permissions inside the sandbox (the original superuser ask): - Backends are now persistent (docker run -d + exec; multipass instance) so the broker can provision accounts and run the shell as a chosen user. - sbx::provision(): create a real unix account per coven member at launch; the OWNER becomes a passwordless superuser (sudo group + /etc/sudoers.d NOPASSWD drop-in on multipass). The shared shell runs as the owner's account. - /sudo <user> and /unsudo <user> (owner-only): real usermod + sudoers.d in the VM — delegate/withdraw superuser. ACL frame carries sudoers; roster shows ⛧ owner · ⚡ sudoer · ◆ driver · • member. Verified live on a real Multipass VM: shell runs as owner@vm with 'sudo -n whoami' == root; '/sudo member' gives member 'NOPASSWD: ALL'; teardown purges the instance. Docker provisions accounts + persistent container (shell as root; sudo pkg absent so drive-grant is the delegation). Tests: 7 cargo tests pass; clean build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+3
-1
@@ -116,10 +116,12 @@ fn draw_roster(f: &mut Frame, area: ratatui::layout::Rect, app: &App, theme: &Th
|
||||
.iter()
|
||||
.map(|u| {
|
||||
let me = u.username == app.me;
|
||||
// ⛧ owner/superuser · ◆ may drive · • member
|
||||
// ⛧ owner · ⚡ sudoer (VM superuser) · ◆ may drive · • member
|
||||
let owner = app.owner.as_deref() == Some(u.username.as_str());
|
||||
let mark = if owner {
|
||||
"⛧"
|
||||
} else if app.sudoers.contains(&u.username) {
|
||||
"⚡"
|
||||
} else if app.drivers.contains(&u.username) {
|
||||
"◆"
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user