feat(pool): pin a user to one Claude/Codex pool account

An admin pins a server-mode user to one pool account per tool
(account_pins; PUT /api/accounts/pins with the password step-up and audit,
the Users page's Pin a user, agenthub accounts pin|unpin). The workspace
owner's pin wins over the balancer whenever the pane may use the account;
a pinned login still waits while another pool login holds the home.
This commit is contained in:
2026-10-19 10:05:19 +07:00
parent aa8ac6cad9
commit 9c98638ec0
20 changed files with 776 additions and 39 deletions
+15
View File
@@ -355,6 +355,7 @@ claude setup-token
agenthub accounts add team-1
agenthub accounts list # live panes, $ and tokens in the last 5 h / 7 d, quota, state
agenthub accounts remove team-1
agenthub accounts pin team-1 mia # mia's new sessions always run on team-1 (unpin mia to undo)
```
In server mode an admin can do the same on the **Users** page, in the
@@ -423,6 +424,19 @@ How a new session picks its account (`server/lib/claude-pool.js`):
pane still needs that member's own `/login`.
- A token more than a year old is skipped.
- A resumed session picks an account again, like a new one.
- **Pinning a user to one account.** An admin can skip the ranking for one
user: **Pin a user** in the Account pool card (or
`agenthub accounts pin <account> <user> [--tool codex]`, `unpin <user>` to
undo; their own password again, audited). Every new session in a workspace
that user OWNS then runs on that account, even when it is full — other users
are not affected, and the account is not reserved for them. The pin is a
preference the pool still bounds: an expired account, or a login a host pane
may not take, falls back to the ranking; and since a home holds one
`.credentials.json`, a pinned login waits until that user's panes on another
pool login have ended (a setup-token or API key pin goes in by env and
applies at once). Running sessions keep their account. Removing the account
drops its pins; deleting the user drops theirs. Pins apply in server mode only
(`server/lib/account-pins.js`).
- Quota is read with each account's own token, in the background, at most every
5 minutes. If the usage endpoint refuses a setup-token, the state column shows
`no quota (…)` and ranking uses spend alone.
@@ -447,6 +461,7 @@ CODEX_HOME=$(mktemp -d) codex login
agenthub accounts add team-chatgpt --tool codex --from /tmp/tmp.XXXX
agenthub accounts list --tool codex
agenthub accounts remove team-key --tool codex
agenthub accounts pin team-key mia --tool codex # pins work as for Claude
```
- **API key**: any number of panes at once. The pane gets the key through