# 开号与删号

一个人用 Tokenman 要两样东西：**能登录入口**（在「使用者」名单上），和 **机器上有他的一个账号**（他的会话就跑在这个账号里，和别人的文件互相看不到）。开号是把这两样给他，删号是把这两样收回。

## 开号：发一条邀请

最常用的路，一条邀请把两样都办了：他用邀请登录入口，入口把他加进名单，并且马上在一台机器上给他开账号。

**网页**：控制台「使用者」页 → **生成邀请命令**，把打出的那一行发给他。

**命令行**：

```sh
fleet hub invite alice          # 只有 GitHub 用户 alice 本人能用；不写名字则谁拿到都能用一次
fleet hub invite --list         # 所有邀请和状态：未用 · 已用 · 过期 · 作废
fleet hub invite --revoke <id>  # 作废一条还没用过的
```

- 邀请 7 天内有效，只能用一次。
- 他收到的是一行安装命令 `curl -fsSL https://hub.example.com/i/<邀请码> | sh`，照 [成员 · 快速开始](../member/quickstart.md) 走就行。
- 开在哪台机器：设置页「新使用者在哪些服务节点上开登录名」（`fleet.auto_assign`）——`least-busy` 让入口挑最闲的，或写机器名。
- 「每台电脑备好空账号」（`fleet.spares`）打开时，机器上预先备着几个空账号，新人第一次登录就直接拿到一个，不用等；没打开时要等机器建好账号，一般一两分钟。空账号建好或洗净时要先用一个订阅说一句话自检，这一句能用哪些订阅由 `fleet.spare.cred_allow` 决定（默认 `"*"`，只在建号 / 洗号进行中有效，不用给空账号一个个配白名单）；被领走后按这个人自己的规则。建号 / 洗号中途机器上的守护进程重启了，入口会自己重做（至多两次），不会因此停止补备用。
- 「60 秒试用」（`fleet.trial`）打开时，官网的人点「60 秒试用」就能登录、领一个备好的空账号、在浏览器里说第一句话；空账号领完了就排队，页面告诉他前面几个人、大约等多久。一次试用 15 分钟或 20 条消息，先到为准（`fleet.trial.max_secs` / `fleet.trial.max_msgs`）；用完机器自动收回，对话页顶上一直显示还剩多少，旁边就是「申请正式使用」。申请通过后试用直接转正式，对话接着用。关了页面或切走 2 分钟、开着不动 4 分钟（3 分钟时先提示「1 分钟后暂停」）也会把机器放回给排队的人（`fleet.trial.hidden_secs` / `fleet.trial.idle_warn_secs` / `fleet.trial.idle_secs`）；「开着不动」从机器准备好、能打字那一刻才算起；机器 5 分钟还没准备好就放回去、这个人原位重新排队，不算用过试用（`fleet.trial.open_slow_secs`，同时告警 `trial_open_slow`）；放回的机器先洗净、过检查才回预备池。对话单独加密存 24 小时，只有本人能取回：回来按「继续」就换一台干净的机器接着聊。试用者能用哪些订阅由一个设置决定（`fleet.trial.cred_allow`，默认 `"*"`：共享池里它本来就能用的都行；`[]` 则一个都不给，试用页显示「试用暂时没有可用订阅」），不用一个个给试用者配；申请通过时把它写成这个人自己的订阅白名单。试用账号能连到哪由 `fleet.trial.egress` 决定：默认 `off` 不限；`log` 不拦，只把「若收紧会被拦」的连接记进机器的 `egress-deny.log`；`block` 只能连白名单（随版本发的 `conf/trial-egress.allow`，加上入口和 DNS），发信端口 25 / 465 / 587 一律拒。只管试用的人占着的账号，成员和管理员不受影响；每台机器一分钟内跟上，改回 `off` 即撤净。试用者做的网页发到哪由 `fleet.trial.livepage` 决定：默认 `off`，卡片说「这台机器还没连活页」；`on`（部署里还要配好活页的合作方入口 `CCQUOTA_LIVEPAGE_PARTNER_URL` 和它的钥匙 `CCQUOTA_LIVEPAGE_PARTNER_KEY` / `_KEY_FILE`）时，试用者第一次发网页就用他扫码时的微信身份替他开活页账号，钥匙只存在入口、由机器上的凭据代理在转发时换上，会话里拿不到；网页默认只他能看、发好推到他微信；试用结束（到期、用完、转正）一分钟内收回钥匙并告诉活页，删掉这个人时活页账号一起注销。

**别忘了放行订阅**：新使用者默认一个订阅都不能用。他登录后，「使用者」页 → 点他 → 订阅授权，选「全部订阅」或勾几个（[订阅与额度](quota.md)）。

**自托管**：以上全部照做；另外机器上要有空位（[机器](machines.md)）。
**托管**：以上全部照做；机器空位由我们保证。「使用者」页上他那一行写着账号的状态，迟迟开不出来时把这一行发给我们。

### 只让他能登录，不开账号

「使用者」页 → **加使用者**，填 GitHub 用户名；或 `fleet users add alice`。他能登录入口、看控制台，但第一次开会话时会看到「请入口管理员给你分一台」，直到你给他开账号。

### 给已登记的人在指定机器上开账号（自托管）

```sh
fleet hub accounts                                   # 每个人的身份 id（gh:<数字>）和他在各台机器上的账号
fleet hub accounts assign gh:1234567 --host mac-a    # 在 mac-a 上给他开一个
```

一个人可以在几台机器上各有一个账号。托管客户要加第二台机器上的账号，找我们。

## 删号

删号也是两步：**让他登录不了**，和 **收回机器上的账号**。

### 1. 让他登录不了

**网页**：「使用者」页 → 点他 → **移除使用者**。
**命令行**：`fleet users remove alice`。

立刻生效：他的下一个请求就被拒，他的每台客户端（电脑、手机）全部作废。但**他正在跑的会话照跑到关掉为止**——要马上停，做第 2 步。部署配置里写的管理员删不掉（先从配置里拿掉、重新部署）。

### 2. 收回机器上的账号

```sh
fleet hub accounts remove gh:1234567 --host mac-a
```

每台机器各做一次（`fleet hub accounts` 看他在哪几台上有账号）。

> 今天这一步只有命令行，网页上的「移除使用者」不做它。将改为：「使用者」页上直接收回。

收回时机器先停掉他的所有会话和后台服务，然后二选一：

- **回收**（打开了「每台电脑备好空账号」时的默认）：账号洗干净变成一个新的空账号，下一位新人直接拿到。只有检查确认干净、而且凭据隔离到位才会再发出去；不干净的标「坏了」，永远不会给别人。
- **真删**（没打开备用账号，或加 `--delete`）：机器上的系统账号被删掉。

**托管**：命令一样，你直接执行；机器上的事由我们的机器自己完成，不用找我们。

## 删号会留下什么

| 留下的 | 在哪 | 多久 |
|---|---|---|
| 他的家目录打包（代码副本、会话记录、历史） | 那台机器上：Mac 在 `/Users/Shared/offboarded/`，Linux 在 `/home/.attic/` | Linux 30 天后删；Mac 不自动删，要管理员手动清 |
| 他在入口上的身份记录 | 入口 | 一直留着，再邀请回来还是同一个人 |
| 他用过的用量 | 入口 | 一直留着，按人用量里照样算 |
| 审计记录 | 入口 | 审计页显示最近 60 天 |
| 已经推到 GitHub 的分支和 PR | GitHub | 不受影响 |

回收和真删都**先**拿走机器上那份共享订阅的副本，再打包家目录，所以打包里没有订阅凭据。入口这边，他的连接令牌、正在用的认领、没用过的加入码在回收前就作废了。

**自托管**：要彻底销毁打包，在那台机器上删掉对应文件（需要 root）。
**托管**：打包在我们的机器上；要提前销毁，告诉我们是谁。

## 常见情况

- **邀请发错了人**：`fleet hub invite --list` 找到它，`--revoke <id>`。已经用掉的，按上面删号。
- **他换了 GitHub 账号**：`fleet hub accounts rekey <旧 id> <新 id>`，旧身份的账号整个交给新身份，什么都不重开。
- **开号卡住了，名单里有一行开不出来的记录**：`fleet hub accounts forget gh:1234567` 删掉这条从没到过机器的记录，再重新邀请。
- **删号发出去之前机器就没了，那一行一直是 `remove_pending`**：先确认这台机器真的回不来，再 `fleet hub accounts forget gh:1234567 --host <机器> --machine-gone`。它把这一行标成 `removed`，并在记录和审计里写明「家目录未在源机归档」——那台机器上他的家目录没有打包，要留就去旧盘上找。机器还连着时会被拒：那时删除会自己落地。
- **他离职又回来**：重新发邀请；身份还是原来那个，用量历史接得上，机器上是一个新账号。
