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>
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
# 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.
|
||||||
Reference in New Issue
Block a user