Skip to content

docs: multi-user and remote sandbox guides (PR 7d of REORG-PLAN) - #505

Merged
pdettori merged 2 commits into
rossoctl:mainfrom
pdettori:docs/guides-pr7d
Oct 13, 2026
Merged

pdettori merged 2 commits into
rossoctl:mainfrom
pdettori:docs/guides-pr7d

Conversation

@pdettori

Copy link
Copy Markdown
Member

Summary

PR 7d of docs/REORG-PLAN.md: two task guides. Docs only. Based on main after #500.

  • docs/guides/manage-multi-user-sessions.md: onboarding a user on the single-VM path (OAuth app with device flow, starting the control plane, restricting SSH accounts, mocactl login and credentials), verifying isolation (404 for another user's session, session_mismatch, the audit stream), listing and deleting sessions, the admin ?owner= listing, choosing a sandbox tier, revoking access, and what it does not give you.
  • docs/guides/remote-sandbox.md: the worker's settings, choosing the relay token (underscore vs dashed ids), verifying an attach, TLS limits, proving where a command ran, the OpenShift-only microVM host, and what is not supported.
  • Linked from docs/index.md and the README; the plan file records 7d and the demo coverage below.

Commands are taken from the repository's own demos and READMEs. Those demos were run by one person with two GitHub accounts on one laptop; two people on two laptops was not tried, and I did not re-run any of it.

Please check

  • Unrun recipes, marked in the text: the docker run for a container sandbox on an unrelated host against a P6 relay (no doc shows an external host reaching a P6 relay; only in-host containers and the OpenShift microVM host are documented), and the admin curl .../v1/sessions?owner= (the demos never show an admin doing it; mocactl has no --owner option).
  • No user removal exists. No route deletes a subject, and there is no allowlist; the guide says removal means closing the network path.
  • Plaintext attach: the relay's listeners are plaintext gRPC and TLS for a VM or Compose relay is not documented, so the guide warns against exposing the attach port on an untrusted network.
  • The VM demos disagree with the code: they say the worker ignores the workspace key, but each session now gets its own directory (still not a boundary), and 403 single_tenant_deployment is described in docs but absent from the code. I kept to the code.
  • This branch does not link docs/reference/security-model.md (still in docs: security model and hardening checklist (PR 7c of REORG-PLAN) #503); the guides link the multi-user concepts page instead. After docs: security model and hardening checklist (PR 7c of REORG-PLAN) #503 merges, a follow-up can add the security links.

Knative demos: P6 coverage

Knative demo P6 coverage
moca-demo.md None. Scale-to-zero resume and the KEDA fleet do not exist on P6.
remote-sandbox-demo.md Partial. The new remote-sandbox guide covers attach, verification and the planted-marker technique; the BYO docker run placement proof is unrun.
promoted-workflow-demo.md None as a demo; docs/guides/promote-claude-workflow.md covers the commands.

I have not written P6 replacements for the demos. They are deleted with the Knative path at removal; say if you would rather have P6 versions of the last two first.

Verification

scripts/check-doc-links.py reports 0 broken links over 184 files; Prettier run on changed files. Nothing was deployed or re-run. make lint not run locally; CI will.

Assisted-By: Claude (Anthropic AI) noreply@anthropic.com

@ingpaolodettori-dev ingpaolodettori-dev left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs-only PR adding two task guides (multi-user sessions, remote sandbox) plus index/README/plan links. I checked every concrete claim in both guides against main (0e22e39, which is this PR's base): ports, error codes, mocactl output strings, env vars, Redis keys, log lines, setup-vm.sh behaviour, and the token lookup. Nearly all of it is accurate, and the unrun recipes are clearly marked. There is one wrong instruction (token-directory files for dashed sandbox ids) and two misleading statements (the container /workspace called "shared", and admin removal without a restart). None of them blocks the merge.

Author: pdettori (MEMBER — maintainer)
Areas reviewed: Docs (README.md, docs/index.md, docs/REORG-PLAN.md, docs/guides/*)
Agent/IDE config (.claude/.vscode): none
Commits: 1 commit, all signed-off: yes
CI status: all green except deploy-scripts (the Run deploy shell tests step, i.e. make test-deploy). No deploy test reads any file this PR touches, and CI on main at the same base commit is green, so this looks unrelated. Please re-run the job before merging.

Out of the diff: docs/reference/configuration.md:152 on main has the same dashed-id / SH_RELAY_TOKEN_DIR error as the comment on remote-sandbox.md:35. Worth fixing in the same pass.

Comment thread docs/guides/remote-sandbox.md Outdated
Comment on lines +35 to +36
- **Dashed ids** (such as `sh-sandbox-0`) cannot, because systemd drops dashed names; they use the global
`SH_RELAY_TOKEN` or a token-directory file.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: A dashed id can't use a token-directory file. The relay reads $SH_RELAY_TOKEN_DIR/<id> only when the id matches ^[A-Za-z_][A-Za-z0-9_]*$ (packages/sandbox-relay/src/main.ts:325, pinned by test/main-token-dir.test.ts:88-101). Any other id goes straight to the env path. So a dashed id gets SH_RELAY_TOKEN_<id> (verbatim lookup, main.ts:336) or the global SH_RELAY_TOKEN, and an operator who drops a file for sh-sandbox-0 gets every attach refused. The "systemd drops dashed names" reason also holds only where the relay's env comes from an EnvironmentFile= (VM, microVM host). A Compose or container env can carry the dashed name. Suggested wording: "Dashed ids (such as sh-sandbox-0) are never looked up in the token directory; they use SH_RELAY_TOKEN_<id> where the environment can carry a dashed name (not under systemd), otherwise the global SH_RELAY_TOKEN."

## What this does not give you

- **Ownership holds at the API only.** Redis and port 8081 are unauthenticated.
- **Users share the container sandboxes**, their `/workspace`, their Unix user and the process list, until owner

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: This line and line 176 ("a shared /workspace" vs "the microVM tier has … a per-session workspace") conflict with line 206. The container worker advertises workspace-subdir and gives each session its own directory, <root>/<session id> (remote-worker/internal/exec/workspace.go:15-21, cmd/worker/main.go:84-110, harness/src/select-sandbox.ts:381). What users share is the container, the Unix user and the filesystem, so the directories aren't isolated. Suggest "per-session directories under one /workspace, not isolated from each other" here and on line 176, and drop the contrast with the microVM tier's per-session workspace.

| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| One login | `mocactl logout` ends this login on the server and deletes the local file. `mocactl logout --all` ends all of that user's logins |
| A credential | `mocactl credentials delete NAME`. A session on a deleted credential has its next turn refused |
| Admin rights | Remove the subject from `SH_ADMIN_SUBJECTS`; it takes effect within the 15-minute API token lifetime |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: The control plane reads SH_ADMIN_SUBJECTS only at boot (packages/control-plane/src/main.ts:317), so removing a subject does nothing until the control plane is restarted. After the restart, roles reach clients on their next refresh (roles are in the API token, token.ts:33,175, and a refresh recomputes them, identity.ts:38-41), i.e. within 15 minutes. Suggest: "Remove the subject from SH_ADMIN_SUBJECTS and restart the control plane; it takes effect within the 15-minute API token lifetime".

```

5. **Optionally make an admin:** set `SH_ADMIN_SUBJECTS=github:<numeric id>` in `control-plane.env`, restart the
control plane, and have the user log in again. `GET /v1/me` then shows `"roles"`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: roles is always present in GET /v1/me ([] for non-admins, handlers.ts:424), so "shows \"roles\":[\"admin\"]" is the actual check. Logging in again isn't strictly needed either: the next refresh, within 15 minutes, picks the role up.


```bash
mocactl sessions [--json] # every session you own
mocactl sessions delete ID [--json] # also drops the local history; status "deleted", or "accepted" if a turn was in flight

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: deleted/accepted appear only in the --json output. The text output is deleted session ID or deleting session ID; the control plane finishes in the background (packages/mocactl/src/headless.ts:448-460).


The reply must contain `$MARK`. A file that exists nowhere else cannot have come from another sandbox.

2. **Make the answer unambiguous.** With several sandboxes in the tier, either use a tier only that sandbox advertises, or

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: A tier label only narrows placement when the tier is declared in SH_SANDBOX_TIERS on both the supervisor and the control plane and the session picks it (--option sandboxTier=…). With no tiers declared, labels are ignored (harness/src/select-sandbox.ts:648). Worth a link to §4 of the multi-user guide.

manage-multi-user-sessions.md: onboarding a user on the single-VM path,
verifying isolation, listing and deleting sessions, the admin listing,
choosing a tier and revoking access, with what it does not give you.
remote-sandbox.md: the worker's settings, relay tokens, verifying an
attach, TLS limits, proving where a command ran, the OpenShift microVM
host and what is not supported. Commands come from the repository's own
demos and READMEs; unrun recipes are marked. REORG-PLAN records the coverage
of the three Knative demos by P6 demos.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Paolo Dettori <dettori@us.ibm.com>
- Dashed sandbox ids are never looked up in the token directory (also fix
  the configuration reference).
- Container sandboxes have per-session directories under one /workspace,
  not isolated from each other.
- Removing an admin needs a control plane restart; roles refresh within 15
  minutes and /v1/me always lists roles.
- mocactl sessions delete prints text, not deleted/accepted, unless --json.
- A tier label only narrows placement when the tier is declared on both
  sides and the session picks it.
- Link the security model now that it is on main; REORG-PLAN PR numbers.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Paolo Dettori <dettori@us.ibm.com>
@pdettori

Copy link
Copy Markdown
Member Author

Rebased on main (conflicts in docs/index.md and docs/REORG-PLAN.md resolved by keeping both sets of rows) and addressed in c174124. Dashed sandbox ids are never looked up in the token directory (wording fixed here and in docs/reference/configuration.md); container sandboxes have per-session directories under one /workspace, not isolated from each other; removing an admin needs a control plane restart and roles reach clients on their next refresh; the text output of mocactl sessions delete is described, with deleted/accepted only under --json; /v1/me always lists roles and re-login is not required; a tier label only narrows placement when declared on both sides and picked by the session, with a link to the tier section. I also linked the security model, now that it is on main. The deploy-scripts failure the review noted was in make test-deploy, unrelated to the files here; I have not re-run it.

@pdettori
pdettori merged commit a02b9db into rossoctl:main Oct 13, 2026
14 checks passed
@pdettori
pdettori deleted the docs/guides-pr7d branch October 13, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants