feat(server-mode): share one session; scope collaborators' pane tokens (sharing phase 3)

A workspace's owner (or an admin) can share ONE session from its right-click
menu (GET/PUT /api/lanes/:id/sessions/:sid/shares, table session_shares,
audited). The user sees the workspace (access: "session") with only that
session, joins the pane holding it, resumes it on their own account in a
free slot, and uses the workspace's git and Files reads and git writes;
everything else of the workspace answers 403 ESESSIONSHARE (scope.js
sessionShareAllows in scopeGuard). Hook/runtime broadcasts stay with full
collaborators.

A collaborator's pane token (readable by the owner's Linux account) now acts
as them inside that workspace only, and never starts or bills a session
(auth.js paneLaneAllows, 403 EPANESCOPE); a Terminal tab the owner or an
admin opens acts as the owner again. Docs say plainly that under S3 a
session share hands over the owner's account inside the terminal.
This commit is contained in:
2026-11-06 11:25:40 +07:00
parent 1a365a45bd
commit 879a6bb02d
24 changed files with 838 additions and 120 deletions
+17 -1
View File
@@ -2121,7 +2121,23 @@ session hours are billed to them (`session_payers`; a Terminal tab's stay the
owner's). A user disabled since stays on the
list (`disabled: true`) and may be kept or removed; only a new one must be enabled. Users taken off
get the WebSocket message `lane_access` `{laneId, userIds}` (sent to them only). See
`docs/SERVER-MODE.md` → Sharing a workspace.
`docs/SERVER-MODE.md` → Sharing a workspace. A collaborator's pane token
answers only that workspace's reads, the workspace list (filtered to it), its
stage / up / down / hook / feature / mcp-sync writes and `/api/health`
(`403 EPANESCOPE` — never a start or resume).
```http
GET /api/lanes/:id/sessions/:sid/shares → { shares, canManage }
PUT /api/lanes/:id/sessions/:sid/shares {"userIds": [3]} → { shares }
```
One session shared on its own (`session_shares`), same rules as the workspace
list (owner or admin, enabled users, audited `share session <id>`, `404
ENOSESSION` for a session of another workspace). The user gets the workspace
in `GET /api/lanes` with `access: "session"`, only that session in its session
lists, the pane holding it, a resume of it (`start {resumeSessionId}` — no
fork, no new session, no shell), and the workspace's git/Files reads and git
writes; any other call on the workspace answers `403 ESESSIONSHARE`.
#### Workspace context: instructions, folders, context files, memory