feat(server-mode): pane presence and typing audit (sharing phase 4)
A pane's tab shows the other people who have it open (pane-presence.js, in memory, fed by the /ws-pty attach; GET /api/lanes/:id/presence and the pane_presence broadcast to the owner and full collaborators) and says "Billed to <name>" for a pane a collaborator opened (startedBy on the run). The first real keystroke of each attach into a shared workspace's pane by anyone but its owner is audited as `type into <run id>` (mouse, focus and terminal replies to tmux do not count). The pty socket now pings, so a vanished browser is ended at the next re-check and leaves the presence list.
This commit is contained in:
+11
@@ -2126,6 +2126,17 @@ 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/presence → { panes: { "<run id>": [{id, name}] } }
|
||||
```
|
||||
|
||||
Who has which pane open (server mode; local mode `{panes: {}}`), in memory;
|
||||
changes come as the WebSocket message `pane_presence` `{laneId, runId, users}`
|
||||
to the workspace's owner and full collaborators. A run handle
|
||||
(`GET /api/run`) carries `startedBy: {id, name}` when a collaborator opened
|
||||
it — they pay for it. The first keystroke of a terminal attach into a shared
|
||||
workspace's pane by anyone but its owner is audited (`type into <run id>`).
|
||||
|
||||
```http
|
||||
GET /api/lanes/:id/sessions/:sid/shares → { shares, canManage }
|
||||
PUT /api/lanes/:id/sessions/:sid/shares {"userIds": [3]} → { shares }
|
||||
|
||||
@@ -311,6 +311,17 @@ resume or any other call that could bill them. The CLI's workspace commands
|
||||
work from their pane; the MCP server and the statusline's spend line do not.
|
||||
A pane the owner or an admin opens still acts as the owner.
|
||||
|
||||
**Who is here, and who pays.** A pane's tab shows the other people who have
|
||||
it open (`pane_presence`, `GET /api/lanes/:id/presence`, in memory — never
|
||||
the viewer themself), and its tooltip says "Billed to <name>" for a pane a
|
||||
collaborator opened (`startedBy` on the run). The first keystroke of each
|
||||
terminal attach into a SHARED workspace's pane (whole or one session of it)
|
||||
by anyone but its owner is written to the audit log as `type into <run id>` —
|
||||
who typed where, never what (mouse, focus and the terminal's own answers to
|
||||
tmux do not count); the Chat composer types through the same attach, so its
|
||||
prompts are covered too. A terminal that stops answering pings (a sleeping
|
||||
laptop) is ended at the next re-check, and its presence with it.
|
||||
|
||||
#### Sharing one session
|
||||
|
||||
The owner (or an admin) can also share ONE session: right-click it in the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Workspace & session sharing — plan
|
||||
|
||||
Status: **phases 1–3 built 2026-11-06** (workspace sharing; collaborators run on their own account, billed per payer by hour — `session_payers`; one session can be shared — `session_shares`; R1 decided as option **(a)** — accept and warn hard). Phase 4 not built.
|
||||
Status: **phases 1–4 built 2026-11-06** (workspace sharing; collaborators run on their own account, billed per payer by hour — `session_payers`; one session can be shared — `session_shares`; pane presence + typing audit; R1 decided as option **(a)** — accept and warn hard).
|
||||
An independent review of phase 1 found and got fixed: a collaborator's Terminal
|
||||
tab acted as the owner through its pane token (now `dashboard_runs.started_by`),
|
||||
`POST /api/run {shell:true}` bypassed `ECOLLABSTART`, a disabled collaborator
|
||||
|
||||
Reference in New Issue
Block a user