feat(server-s3): a member's tmux follows tmux upgrades — tmux-member + Users → Members' tmux
A member's tmux server keeps the version it started with until their last pane closes, but the dashboard asked it with TMUX_BIN, the newest tmux: a 3.8 client on a 3.6 server spun it at 100% CPU (three members needed a manual kill on 2026-10-15). - /opt/agenthub/libexec/tmux-member (install-system, in sudoers): runs a member's tmux call with the binary of THEIR running server (/proc/<pid>/exe, found from the socket in /proc/net/unix), else TMUX_BIN. It runs as the member and execs only a process they own. sudoArgv uses it once installed (linux-accounts readConf), TMUX_BIN until then. - Users → Members' tmux (GET /api/users/tmux): each member server's version beside the installed one, sessions, agents working. An admin restarts one (POST /api/users/:id/tmux-restart) or every idle outdated one (POST /api/users/tmux-restart-idle), with their password again, audited per member; a server that will not stop answers 409 ETMUXSTUCK naming its pid for root. - server-s3-system.test.js: `delete` is a provision action since Delete user, so the "unknown action" case now uses `purge`. Operators: run `sudo agenthub server install-system` once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
* - GET/PUT/DELETE /api/me/avatar (Auth) — the account's own picture
|
||||
* - GET/PATCH /api/users/{id} (Auth) — the Users page's Edit user form
|
||||
* - GET /api/users/{id}/avatar (Auth) — one account's picture (admin/analyst)
|
||||
* - GET /api/users/tmux, POST /api/users/{id}/tmux-restart, POST /api/users/tmux-restart-idle
|
||||
* (Auth) — each member's own tmux server and an admin's restart of it (S3)
|
||||
* Exports `{ tags, schemas, paths }`, combined into the spec by
|
||||
* server/openapi-extra.js. See docs/SERVER-MODE.md.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
@@ -409,6 +411,77 @@ const paths = {
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/users/tmux": {
|
||||
get: {
|
||||
tags: ["Auth"],
|
||||
operationId: "listMemberTmux",
|
||||
summary:
|
||||
"Each member's own tmux server (one Linux user per account): its version beside the installed one, sessions, agents working (admin/analyst)",
|
||||
responses: {
|
||||
200: {
|
||||
description:
|
||||
"{available, installed, matched, users: [{id, username, running, stuck?, version, pid, startedAt, sessions, busy, outdated}]} — available false without S3",
|
||||
},
|
||||
403: err("EADMIN — a developer"),
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/users/{id}/tmux-restart": {
|
||||
post: {
|
||||
tags: ["Auth"],
|
||||
operationId: "restartMemberTmux",
|
||||
summary:
|
||||
"End one member's tmux server — every pane of theirs closes; the next start runs the installed tmux (admin, own password again, audited)",
|
||||
parameters: [idParam],
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
required: ["currentPassword"],
|
||||
properties: { currentPassword: { type: "string" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: { description: "{user}" },
|
||||
403: err("EREAUTH (own password wrong) / EADMIN / ELOCALMODE"),
|
||||
404: err("ENOUSER"),
|
||||
409: err(
|
||||
"ETMUXSTUCK — the server did not stop (the message names the pid for root) / ENOS3"
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/users/tmux-restart-idle": {
|
||||
post: {
|
||||
tags: ["Auth"],
|
||||
operationId: "restartIdleMemberTmux",
|
||||
summary:
|
||||
"Restart every member server older than the installed tmux while no agent of theirs works (admin, own password again, audited per member)",
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
required: ["currentPassword"],
|
||||
properties: { currentPassword: { type: "string" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description:
|
||||
"{restarted: [username], skipped: [username — an agent working], failed: [{username, message}]}",
|
||||
},
|
||||
403: err("EREAUTH / EADMIN / ELOCALMODE"),
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/users/{id}/avatar": {
|
||||
get: {
|
||||
tags: ["Auth"],
|
||||
|
||||
Reference in New Issue
Block a user