feat(pool): an admin's switch moves a user's Claude login at once

PUT /api/accounts/pins (and agenthub accounts pin) now writes a pinned
Claude login into the user's home right away (claude-pool.switchHome):
every home's newer pair is copied back first, the member's own login is
never written over, and no pane is restarted — running sessions take the
new pair at their next credentials read. A live home stays on the login it
holds, so unpinning does not flip it back. The Users page calls it
"Switch a user's account" and says what happened.
This commit is contained in:
2026-10-19 10:23:44 +07:00
parent 9c98638ec0
commit 776ad6466f
16 changed files with 208 additions and 89 deletions
+14 -4
View File
@@ -17,8 +17,9 @@
* Keychain item's JSON); or `token` — a `claude setup-token` token. A Codex
* one is an OpenAI API key or the text of an `auth.json` (`token`).
* `PUT /pins` (`{tool, userId, account}`, `account: null` unpins) pins one
* user's new sessions of a tool to one pool account (account-pins.js); `GET /`
* lists the pins under `pins`.
* user's sessions of a tool to one pool account (account-pins.js) — a Claude
* login goes into their home at once, so running panes move without a
* restart (`switched`); `GET /` lists the pins under `pins`.
* `GET /profiles` lists the saved profiles that can be moved in (identity only). Like every Users-page change
* they need the admin's own password again (`currentPassword`), are audited
* (the account NAME only), and refuse in local mode. The secret only goes IN:
@@ -213,10 +214,19 @@ router.post(
router.put(
"/pins",
poolChange((_req, body) => {
poolChange(async (_req, body) => {
const pin = pins.setPin(Number(body.userId), body.tool, body.account ?? null);
let switched = null;
if (pin.account) {
try {
switched = await pins.applyPin(pin.userId, body.tool);
} catch (e) {
console.warn(`[accounts] switch ${pin.username} → ${pin.account}: ${e.message}`);
switched = "next-session";
}
}
return {
json: { pin },
json: { pin, switched },
target: pin.userId,
action: pin.account
? `pool: pin ${pin.username} to ${body.tool} account ${pin.account}`