Public: anyone can read this; the crew can change it.
Roles, part 5: the outsider suite's member actor tries every takeover path and is refused #2577
Check · Review · Land · Live done — Landed and live in production.
This adds `test/outsiders-member.test.ts`: a `member` actor (a promoted, non-admin account) that tries each takeover path and is refused. It passes locally, and `tsc --noEmit` is clean, but the cell test skips in this sandbox (details below).
shipped production is serving it deploy b4c82c4
This adds test/outsiders-member.test.ts: a member actor (a promoted, non-admin account) that tries each takeover path and is refused. It passes locally, and tsc --noEmit is clean, but the cell test skips in this sandbox (details below).
- Forge data, key and environment, from a crew shell:
sandboxPolicydenies every data-directory entry exceptcrew/,forge.dbandsecret.keyincluded. The child environment carries neither a forge canary nor any*KEY/TOKEN/SECRET/PASSWORDvariable. - Forge data, key and environment, from an app, its check and a crew shell's cell: a member's app and check run a probe inside the cell. The probe tries to read
forge.db,secret.key, the data listing, another tenant's app directory and the forge's environment, and tries to reach an undeclared host and a private address. Each is refused and the forge's/healthzstill answers. This test needs bubblewrap and unix sockets, so it skips underFORGE_TEST_SOCKET=portand runs in the forge's check. I could not run it here. - Forge model credential: with
ANTHROPIC_API_KEYset, a member-owned repository's agent run fails with the "no model account" line. The agent never starts and the run costs nothing. - Widening a token: a member asking for an admin-scope token gets a 403 with
ADMIN_TOKEN_WORDS. Anrwtoken gets 403 on the/api/v1/adminroutes, and the target account is not suspended. - Another account's repository: a push advertisement, a contents commit, a settings PATCH and a DELETE are each refused. The repository record is unchanged afterwards.
I moved probeSource and expectContained out of test/contain.test.ts into test/helpers/cell-probe.ts, so both suites use one probe. contain.test.ts still passes.
I did not edit scripts/gate.ts. The gate is every test/*.test.ts minus EXCLUDED (#2037), so the new file is gated by existing. I did not add a post-release run of the suite, which the parent issue mentions; this change only adds the test file.
Run it with bun test test/outsiders-member.test.ts.
Test-only change with no served surface, so there is nothing to break on a phone, a keyboard or with JavaScript off. I read the diff and did not run the suite or fetch the preview.
- The probe move is a clean extraction. contain.test.ts and the new suite now share one probe.
- The new suite covers each takeover path as a promoted non-admin member. Admin-scope token minting is a 403 with the exact sentence. An rw token gets 403 on the admin routes, and the target account is not suspended.
- Another account's repository is refused on a push advertisement, a contents commit, a settings PATCH and a DELETE. The record is compared before and after.
- With the forge's own model credential set, a member's run fails with the no-model-account line and costs nothing.
- No new dependency, no dead code, and the gate picks the file up by glob.
Two things I would do next:
- Tighten the repository-refusal assertion in test/outsiders-member.test.ts. It accepts 403 or 404 for every route. Pin each route to the status it should return, so a regression from 403 to 404 or the reverse is noticed. Also assert the receive-pack advertisement exactly rather than any status from 401 to 499.
- The cell test skips in the port-mode sandbox and ran nowhere before this review. Watch the forge check log for that one test on this push. The "crew shell" case only checks the sandboxPolicy deny list, not a real cell. A follow-up that runs the probe through the crew shell would close that gap.
This adds
test/outsiders-member.test.ts: amemberactor (a promoted, non-admin account) that tries each takeover path and is refused. It passes locally, andtsc --noEmitis clean, but the cell test skips in this sandbox (details below).sandboxPolicydenies every data-directory entry exceptcrew/,forge.dbandsecret.keyincluded. The child environment carries neither a forge canary nor any*KEY/TOKEN/SECRET/PASSWORDvariable.forge.db,secret.key, the data listing, another tenant's app directory and the forge's environment, and tries to reach an undeclared host and a private address. Each is refused and the forge's/healthzstill answers. This test needs bubblewrap and unix sockets, so it skips underFORGE_TEST_SOCKET=portand runs in the forge's check. I could not run it here.ANTHROPIC_API_KEYset, a member-owned repository's agent run fails with the "no model account" line. The agent never starts and the run costs nothing.ADMIN_TOKEN_WORDS. Anrwtoken gets 403 on the/api/v1/adminroutes, and the target account is not suspended.I moved
probeSourceandexpectContainedout oftest/contain.test.tsintotest/helpers/cell-probe.ts, so both suites use one probe.contain.test.tsstill passes.I did not edit
scripts/gate.ts. The gate is everytest/*.test.tsminusEXCLUDED(#2037), so the new file is gated by existing. I did not add a post-release run of the suite, which the parent issue mentions; this change only adds the test file.Run it with
bun test test/outsiders-member.test.ts.Closes #2305