Files
proxy-station/.claude/skills/update-db/SKILL.md
2026-10-03 19:33:03 +08:00

92 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: update-db
description: 对 LA 生产机上的 proxy-station 数据做规范化变更——增删节点、导入分享链接、调整策略组与成员、规则、规则集引用、订阅 token、Surge 设置段落。凡是用户要动线上数据的(「线上加/删个节点」「把这个组改成 url-test」「调一下规则」「建个订阅 token」「删掉那个 token」「改下生产上的设置」),都用这个 Skill,即使没提到「数据库」三个字。它只改数据不碰代码:代码更新与部署归 deploy Skill。
---
# 变更 proxy-station 生产数据
线上数据(节点、策略组、规则、token、设置)住在 la 机的 SQLite(`/opt/proxy-station/data/proxy-station.db`),由常驻的 `proxy-station` 服务直连。本 Skill 的做法是:**走服务自己的管理 API 做变更,变更前用 sqlite3 在线备份做快照**,不直接写库、不重启服务。
## 为什么必须走 API,不能直写 SQLite
API 不是简单转发,直写会绕过它的全部防护:
- zod 校验拦住坏数据(VMess 必有 UUID、WS 必有 path、SS 必有 method)
- 节点名唯一冲突返回 409;规则的 policy 必须指向存在的组或内置策略,否则规则整条失效
- 策略组改名会级联更新引用它的组成员与规则;members 是「整组替换」语义,API 帮你做对
- 订阅 token 由 crypto 随机生成、常量时间比对——手工 INSERT 塞进 null 或坏格式,`/sub` 全部当场 500
生成器每次请求实时读库,**API 改完订阅即刻生效**,不需要重启服务。直接动 SQLite 文件仅限两种只读场景:`api.sh counts` 的行数盘点,以及从备份快照里查旧值。
## 用法
```bash
bash .claude/skills/update-db/scripts/api.sh api GET /api/nodes
bash .claude/skills/update-db/scripts/api.sh api POST /api/nodes '{"name":"…","protocol":"…",…}'
bash .claude/skills/update-db/scripts/api.sh api GET /sub/<token>/clash # 拉订阅做校验(公开端点)
bash .claude/skills/update-db/scripts/api.sh backup <context> # context 用小写连字符 slug,如 add-jp-hy2
bash .claude/skills/update-db/scripts/api.sh counts
bash .claude/skills/update-db/scripts/api.sh health
```
- `api` 经 ssh 在**远端本机回环**调接口:`ADMIN_TOKEN` 只在远端 `/etc/proxy-station/env` 里展开,不经本地 shell、不落对话记录;JSON 走 stdin,无需转义
- 响应末尾带 `__HTTP_STATUS:200__` 一行。**非 2xx 时先读响应体里的错误信息再决定下一步**,不要盲目重试;要管道给 jq 时先剥掉这行:`| sed '$d' | jq …`
- 连不上 la(解析出 198.18.x.x)是本地 fake-IP 劫持了 ssh,与远端无关,等网络恢复再试
- 环境变量可覆盖 `DEPLOY_HOST`/`PS_DATA_DIR`/`PS_ENV_FILE`,默认即生产值
## 标准流程
1. **摸现状**(只读):`api GET /api/groups`、`/api/rules`、`/api/nodes`、`/api/tokens`,把要动的对象当前值拿到手。改组成员、调规则顺序这类「全量替换」操作,不先拿全量必出错。
2. **备份**:`api.sh backup <context>`。一个变更主题一个备份,同主题内的多条变更共用一份。备份落在远端 `data/backups/`(root 属主),不要清理。
3. **执行**:逐条调 API,每条核对 HTTP_STATUS 与返回体。某条失败就停下排查,不要跳过继续。
4. **校验**:
- `counts` 与变更前对比,行数增减要能对上意图
- `api GET` 变更对象,确认落库的是新值
- 涉及下发面的变更(节点/组/规则/token 范围):拉一次 `api GET /sub/<token>/clash` 确认 200;本地装了 mihomo 的话,`mihomo -t -f <文件>` 是最有说服力的端到端验证
- `excluded`/`skippedRules` 只存在于生成器内部、不在 HTTP 响应里;要核对静默排除时,用 `/api/nodes` 列表对比 yaml 里的 `proxies`
5. **汇报**:向用户复述三件事——变更清单、备份文件名、校验结果。三者齐了才算完成。
## 各实体的操作要点
### 节点 `/api/nodes`
- 新节点来自分享链接:先 `POST /api/nodes/import` 带 `{"text":"…","commit":false}` 预览(返回每条的解析结果与自动去重后的名字),确认后再 `commit:true` 真正入库
- 节点名是分流的关键:必须保留出口词尾缀(客户端里没有标签,用户靠名字区分直连/WARP 线路);地区组按名称正则收编,涉及新地区先读 `docs/ADDING-REGIONS.md`
- 临时下线用 `PATCH /:id/enabled {"enabled":false}`,不要删——IR 层会自动剔除停用节点,删了凭据就没了
- 真要删除:先 GET 全量字段向用户展示将消失的内容,确认后 DELETE
### 策略组 `/api/groups`
- `members` 是**整体替换**:GET 全量 → 改数组 → PUT 回去,别只发改动项
- 成员三态:`{kind:"node", nodeId}`/`{kind:"group", refName}`/`{kind:"builtin", refName}`
- `filterRegex` 与 `includeAllNodes` 可共存,**filterRegex 优先**(动态筛选用它,新增同地区节点自动进组)
- 改名后端会级联引用,但已导入客户端的旧组名会失配——改名前先向用户点明
- url-test/fallback 组别忘了 `testUrl`/`interval`/`tolerance`
### 规则 `/api/rules`
- 顺序由 `PUT /api/rules/reorder` 的**全量 ids 数组**决定(GET 拿现有顺序 → 调整 → 全量提交);自定义规则置顶是既有约定
- FINAL 规则永远保留;其策略组失效时 IR 层降级 DIRECT——兜底存在,但别依赖
- 新规则的 policy 必须已存在(内置 DIRECT/REJECT… 或现有组名),后端会校验,报错就先建组
- `POST /api/rules/reset` 会重置回模板初版并**清掉全部自定义规则**——除非用户明说「重置」,否则永远不调用
### 规则集 `/api/rulesets`(只读)
- `GET /api/rulesets` 看清单,`GET /:id/content` 看自托管转换结果
- `ruleset_cache` 是 24h 缓存(etag + 陈旧回落)自动管理,不要手动碰;「改规则集」实际是改引用它的规则
### 订阅 token `/api/tokens`
- 输入 `{name, nodeIds}`:`nodeIds` 空数组 = 下发全部启用节点;非空 = 只下发这些节点(给不同设备发不同范围的入口就在这里配)
- token 值由后端随机生成,创建响应里拿一次;`lastAccessAt`/`accessCount` 可判断是否仍在被使用
- **删除 token 会即刻断供所有用它的订阅 URL**——删除前必须向用户点明后果
### 设置 `/api/settings`
- `surgeSections` 是 Surge 原文段落透传,改错直接毁掉 Surge 配置;动它之前先 GET 存档 + backup,改完拉 `/sub/<token>/surge` 全文核对
## 回滚
- 单条改错:用 API 反向改回。旧值可以从备份快照只读查出:远端 `sqlite3 data/backups/<file>.db 'SELECT …'`
- 整体回滚:`api.sh restore data/backups/<file>.db --confirm`——停服换库再拉起,订阅中断约 10–20 秒,只在用户明确要求时执行
## 边界
- 不改代码、不做部署(那是 deploy Skill 的事);不动 nginx/证书/`ADMIN_TOKEN`/systemd 单元
- 删除类操作与 reset:先列出将删除/重置的完整清单,用户确认后再执行
- 节点凭据是真凭据:汇报里不要粘贴密码/UUID 全文,用节点名指代