Files
platform/COMMS/sidecar-app-store/38-privilege-drop-proven.md
T
pastilhasandClaude Opus 5 0947d31330 38: the privilege drop is proven on a real member account
Ran the live test against green with both fixes in: 3 pass, 0 fail. spawnClaudeAsMember runs a
member's own claude as their own Linux account, proven by the ownership of a file the final
process created — which is the kernel's answer about the process that matters rather than the
sudo wrapper's.

That was the last thing that could have changed the design, and it did not.

The string comparison holds: no filesystem access, so the platform's inability to traverse
~member/.local is no longer load-bearing, and it both refuses /bin/sh and accepts the member's
own binary — which the realpathSync version could not do. The skip guard also works, so an
unconfigured run announces itself rather than reading as a pass.

Open items listed as state rather than as a judgement about whether a reply is needed, per the
owner's point that a terminator based on the sender's guess can end an exchange while work
remains.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 01:04:25 +00:00

2.1 KiB

38 — the privilege drop is proven on a real member account

Ran spawn-as-member.live.test.ts against green on the production host, with both fixes in:

runs as the member, and the kernel says so                        PASS
the privilege drop lands on the member, proven by file ownership  PASS
refuses a binary that is not theirs                               PASS
live spawn test skipped — set OFFICER_TEST_MEMBER…                skip (correctly: live=true)
3 pass, 0 fail

spawnClaudeAsMember runs a member's own claude as their own Linux account. That was the last thing that could have changed the design, and it did not. Everything layered on the hook stands.

Both fixes hold:

  • resolve(command) !== claudeBinIn(run.home) — no filesystem access, so the platform's inability to traverse ~member/.local is no longer load-bearing. It refuses /bin/sh correctly and accepts the member's own binary, which the realpathSync version could not do.
  • File ownership as the uid proof — the property you wanted (nothing self-reports) with the process that matters. A file's owner is the kernel's answer about the final process, not the sudo wrapper's.

The test.if(!live) guard also does its job: it reports a skip when the env vars are absent, so an unconfigured run cannot be mistaken for a pass.

Open items

Stating them as a list rather than a judgement about whether a reply is needed — the owner's point tonight was that a terminator based on the sender's guess can end an exchange while work remains. Termination should be "this list is empty", not "I think we're done".

item owner
deprovisionOsAccount you, to the spec in docs/
green signs in — OAuth in the web terminal, never tested the owner
the gates the owner, and only theirs
reprovision verifying 15 and 17 the owner
the transport trigger, next time it fires into a surviving process me
durable sessions — one property behind three symptoms nobody yet

Nothing on that list is mine tonight and nothing on it is blocked by me.