shuangyan-notebook/第五域 · Fifth Domain/⚒️ 铸渊·协作指令|GitHub ↔ Notion 桥接协议/🔄 铸渊指令|OAuth2 Token 自动续期引擎 + 天眼休眠避让机制(下篇)· 多用户Toke 4c4928ee96764b308ec38d573a255696.md
Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

394 lines
14 KiB
Markdown
Raw Permalink 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.

---
belongs_to:
- "[[INDEX · 铸渊·协作指令GitHub ↔ Notion 桥接协议]]"
---
# 🔄 铸渊指令OAuth2 Token 自动续期引擎 + 天眼休眠避让机制(下篇)· 多用户Token流程 + 告警推送 + 天眼扫描清单 + 执行回执ZY-TOKEN-RENEW-2026-0324-001
---
<aside>
🚨
**指令编号ZY-TOKEN-RENEW-2026-0324-001下篇**
**上篇:** [🔄 铸渊指令OAuth2 Token 自动续期引擎 + 天眼休眠避让机制(上篇)· 6天自动刷新 + 休眠窗口智能避让 + 多用户Token管理架构ZY-TOKEN-RENEW-2026-0324-001](%F0%9F%94%84%20%E9%93%B8%E6%B8%8A%E6%8C%87%E4%BB%A4%EF%BD%9COAuth2%20Token%20%E8%87%AA%E5%8A%A8%E7%BB%AD%E6%9C%9F%E5%BC%95%E6%93%8E%20+%20%E5%A4%A9%E7%9C%BC%E4%BC%91%E7%9C%A0%E9%81%BF%E8%AE%A9%E6%9C%BA%E5%88%B6%EF%BC%88%E4%B8%8A%E7%AF%87%EF%BC%89%C2%B7%206%E5%A4%A9%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0%20%20bee3531f4e1a4e52a597922626c9d317.md)
**前置指令:** [🔑 铸渊指令Google Drive OAuth2 代理人重构 · Service Account→OAuth2 全量替换 + 天眼全局扫描验收ZY-OAUTH2-REBUILD-2026-0324-001](%F0%9F%94%91%20%E9%93%B8%E6%B8%8A%E6%8C%87%E4%BB%A4%EF%BD%9CGoogle%20Drive%20OAuth2%20%E4%BB%A3%E7%90%86%E4%BA%BA%E9%87%8D%E6%9E%84%20%C2%B7%20Service%20Account%20ea304b59af9f473fbadfe1df1faee61e.md)
**关联仓库:** [https://github.com/qinfendebingshuo/guanghulab](https://github.com/qinfendebingshuo/guanghulab)
**版权锚点:** 国作登字-2026-A-00037559 · TCS-0002∞ 冰朔
</aside>
---
## Phase F · 多用户 Token 流程
### 新用户接入流程
当新开发者需要接入 Drive 权限时,流程如下:
```mermaid
sequenceDiagram
participant Dev as 新开发者
participant Human as 冰朔(人类管理员)
participant ZY as 铸渊(自动化)
participant GH as GitHub Secrets
participant GG as Google OAuth2
Dev->>Human: 申请 Drive 权限
Human->>GG: 在 Google Cloud 加入测试用户白名单
Human->>GG: 用新用户 Gmail 完成 OAuth 授权
Human->>GH: 注入 GDRIVE_REFRESH_TOKEN_DEVxxx
Human->>ZY: 通知铸渊更新注册表
ZY->>ZY: 在 gdrive-tokens.json 添加新条目
ZY->>ZY: 提交注册表更新
Note over ZY: 下次 CRON 触发时自动纳入续期管理
```
### 新用户注册表条目模板
铸渊收到新用户接入通知后,在 `config/gdrive-tokens.json``tokens` 数组中添加:
```json
{
"user_id": "DEV-001",
"user_name": "开发者名称",
"role": "developer",
"github_secret_name": "GDRIVE_REFRESH_TOKEN_DEV001",
"last_renewed": "2026-XX-XXTXX:XX:XX+08:00",
"expires_at": "2026-XX-XXTXX:XX:XX+08:00",
"status": "active",
"renew_count": 0,
"notes": "开发者描述"
}
```
### GitHub Secret 命名规范
| **角色** | **Secret 命名** | **示例** |
| --- | --- | --- |
| 主控(冰朔) | `GDRIVE_REFRESH_TOKEN` | 已存在 |
| 开发者 1 | `GDRIVE_REFRESH_TOKEN_DEV001` | 未来添加 |
| 开发者 2 | `GDRIVE_REFRESH_TOKEN_DEV002` | 未来添加 |
| CI/CD 测试 | `GDRIVE_REFRESH_TOKEN_CI` | 可选 |
### Workflow 如何读取多用户 Token
`renew-tokens.js` 已设计为遍历注册表,根据每个条目的 `github_secret_name` 从环境变量读取对应 Token。
但 Workflow 中需要显式将 Secret 注入环境变量。铸渊在添加新用户时,同时更新 Workflow YAML
```yaml
# 在 renew-gdrive-tokens.yml 和 check-token-health.yml 的 env 中添加:
env:
GDRIVE_CLIENT_ID: $ secrets.GDRIVE_CLIENT_ID
GDRIVE_CLIENT_SECRET: $ secrets.GDRIVE_CLIENT_SECRET
GDRIVE_REFRESH_TOKEN: $ secrets.GDRIVE_REFRESH_TOKEN
# 新增开发者 Token每次加人时追加
# GDRIVE_REFRESH_TOKEN_DEV001: $ secrets.GDRIVE_REFRESH_TOKEN_DEV001
# GDRIVE_REFRESH_TOKEN_DEV002: $ secrets.GDRIVE_REFRESH_TOKEN_DEV002
GITHUB_TOKEN: $ secrets.GITHUB_TOKEN
```
---
## Phase G · 告警推送系统
### 告警级别
| **级别** | **触发条件** | **推送渠道** | **行动** |
| --- | --- | --- | --- |
| 🟢 INFO | Token 刷新成功 | 回执日志(注册表 renew_log | 无需操作 |
| 🟡 WARN | Token 剩余 < 72小时但刷新成功 | 回执日志 + grid-db/logs/ | 关注但无需操作 |
| 🟠 ALERT | Token 剩余 < 48小时且刷新失败 | token-alert.json + 主控台 + 公告板 | 要求人类 24 小时内介入 |
| 🔴 CRITICAL | Token 已过期 / 全部刷新失败 | token-alert.json + 主控台 + 公告板 + Workflow 失败标记 | **紧急:人类立即介入重新授权** |
### 告警输出文件:`grid-db/logs/token-alert.json`
刷新脚本在有失败时自动生成此文件天眼系统可读取它来决定是否推送告警
```json
{
"alert_type": "TOKEN_RENEWAL_FAILURE",
"severity": "CRITICAL",
"time": "2026-03-30T10:00:00Z",
"failed_users": ["TCS-0002"],
"message": "1 个 Token 刷新失败,需要人类介入",
"action_required": "HUMAN_REAUTH",
"instructions": [
"1. 登录 Google Cloud Console",
"2. 访问授权链接获取新 code",
"3. 运行换 token 脚本获取新 refresh_token",
"4. 更新 GitHub Secret: GDRIVE_REFRESH_TOKEN",
"5. 手动触发 renew-gdrive-tokens workflow 验证"
]
}
```
### 天眼告警读取脚本:`scripts/gdrive/push-token-alerts.js`
```jsx
/**
* push-token-alerts.js
*
* 天眼系统调用此脚本读取 token-alert.json
* 并将告警信息写入主控台 + 公告板
*
* 输出:
* - grid-db/notifications/token-alert-{timestamp}.md → 主控台通知
* - grid-db/bulletin/token-alert-{timestamp}.md → 公告板通知
*/
const fs = require('fs');
const path = require('path');
function pushAlerts() {
const alertPath = path.join(__dirname, '../../grid-db/logs/token-alert.json');
if (!fs.existsSync(alertPath)) {
console.log('✅ 无告警。');
return;
}
const alert = JSON.parse(fs.readFileSync(alertPath, 'utf8'));
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
// 生成主控台通知
const dashboardContent = [
`# ⚠️ Token 续期告警`,
``,
`**时间:** ${alert.time}`,
`**严重级:** ${alert.severity || 'ALERT'}`,
`**影响用户:** ${alert.failed_users.join(', ')}`,
``,
`## 描述`,
alert.message,
``,
`## 需要人类操作`,
...(alert.instructions || []).map((s, i) => s),
``,
`---`,
`*此告警由 Token 续期引擎自动生成*`
].join('\n');
// 写入主控台
const notifDir = path.join(__dirname, '../../grid-db/notifications');
if (!fs.existsSync(notifDir)) fs.mkdirSync(notifDir, { recursive: true });
fs.writeFileSync(path.join(notifDir, `token-alert-${timestamp}.md`), dashboardContent);
// 写入公告板
const bulletinDir = path.join(__dirname, '../../grid-db/bulletin');
if (!fs.existsSync(bulletinDir)) fs.mkdirSync(bulletinDir, { recursive: true });
fs.writeFileSync(path.join(bulletinDir, `token-alert-${timestamp}.md`), dashboardContent);
// 清除已处理的告警文件
fs.unlinkSync(alertPath);
console.log(`⚠️ 告警已推送到主控台 + 公告板: token-alert-${timestamp}.md`);
}
pushAlerts();
```
---
## Phase H · 天眼全局扫描清单(必须执行)
<aside>
🦅
**所有代码写完后,必须运行天眼系统进行全局扫描!**
天眼扫描通过后才能提交。
</aside>
### 1. 文件完整性扫描
| **检查项** | **预期** | **状态** |
| --- | --- | --- |
| `config/gdrive-tokens.json` 存在 | ✅ 存在且 JSON 格式有效 | ⏳ |
| `scripts/gdrive/renew-tokens.js` 存在 | ✅ 存在且可执行 | ⏳ |
| `scripts/gdrive/check-hibernation.js` 存在 | ✅ 存在且可导入 | ⏳ |
| `scripts/gdrive/push-token-alerts.js` 存在 | ✅ 存在且可执行 | ⏳ |
| `.github/workflows/renew-gdrive-tokens.yml` 存在 | ✅ 存在且 YAML 格式有效 | ⏳ |
| `.github/workflows/check-token-health.yml` 存在 | ✅ 存在且 YAML 格式有效 | ⏳ |
| `grid-db/logs/` 目录存在 | ✅ 存在(可为空) | ⏳ |
| `grid-db/notifications/` 目录存在 | ✅ 存在(可为空) | ⏳ |
| `grid-db/bulletin/` 目录存在 | ✅ 存在(可为空) | ⏳ |
### 2. 注册表数据完整性扫描
-`schema_version` 字段存在
-`oauth_app.token_ttl_days` = 7
-`oauth_app.renew_interval_days` = 6
-`tokens` 数组至少包含主控 TCS-0002
- ✅ 主控条目的 `github_secret_name` = `GDRIVE_REFRESH_TOKEN`
- ✅ 主控条目的 `status` = `active`
- ✅ 主控条目的 `expires_at` 在未来(未过期)
- ✅ 每个条目的 `github_secret_name` 唯一且对应一个实际存在的 GitHub Secret
### 3. CRON 与休眠冲突扫描
| **检查项** | **预期** | **状态** |
| --- | --- | --- |
| 主刷新 A CRON 时间不在周六 20:00-00:00 CST | ✅ 周一 10:00 CST 安全 | ⏳ |
| 主刷新 B CRON 时间不在周六 20:00-00:00 CST | ✅ 周四 10:00 CST 安全 | ⏳ |
| 安全网 CRON 时间不在日休眠 04:00-04:10 CST | ✅ 12:15 CST 安全 | ⏳ |
| 主刷新 A + B 间隔 ≤ 6 天 | ✅ 周一→周四 = 3天周四→下周一 = 4天 | ⏳ |
| 最坏情况:周一失败+周四失败,安全网能在 48h 内发现 | ✅ 每天检查,最晚 1 天内发现 | ⏳ |
| 最极端场景:连续 3 次刷新都失败→告警输出 | ✅ token-alert.json + 非零退出码 | ⏳ |
### 4. 天眼生命线任务集成扫描
-`skyeye-config.json`(或等价)中包含 `TOKEN-RENEW``TOKEN-HEALTH` 生命线任务
- ✅ 两个任务均标记 `hibernate_exempt: true`
- ✅ 休眠决策引擎已加入生命线豁免逻辑
- ✅ 天眼休眠期内触发 Token 刷新,确认能正常执行(不被休眠拦截)
### 5. 安全扫描
-`renew-tokens.js` 中无硬编码凭据
- ❌ 日志输出中不包含 Token 实体grep 检查 `console.log` 中是否输出 `refresh_token`
-`gdrive-tokens.json` 中不包含 Token 实体(只有元数据)
- ✅ 所有凭据仅通过 `process.env` 读取
- ✅ GitHub Secret 更新用 `tweetsodium` 加密(不明文传输)
### 6. Workflow 完整性扫描
-`renew-gdrive-tokens.yml` 包含 `[skip ci]` 防循环触发
-`check-token-health.yml` 包含 `[skip ci]` 防循环触发
- ✅ 两个 Workflow 均支持 `workflow_dispatch` 手动触发
- ✅ 失败时有告警输出(非零退出码 + alert 文件)
-`tweetsodium` 依赖在 workflow 中安装(不依赖本地 node_modules
### 7. 端到端流程验证
- ✅ 手动触发 `renew-gdrive-tokens` Workflow确认能正常完成
- ✅ 检查注册表 `renew_log` 中是否写入了成功记录
- ✅ 检查 `expires_at` 是否已更新为新的 7 天后
- ✅ 检查 GitHub Secret `GDRIVE_REFRESH_TOKEN` 是否被更新(看 secret 的 "Updated" 时间戳)
- ✅ 手动触发 `check-token-health` Workflow确认显示 “All tokens healthy”
---
## Phase I · 提交
天眼扫描全部通过后:
```bash
git add -A
git commit -m "feat: OAuth2 Token 自动续期引擎 + 天眼生命线任务豁免 + 多用户Token管理 · ZY-TOKEN-RENEW-2026-0324-001 [skip ci]"
git push
```
提交后,手动触发一次 `renew-gdrive-tokens` Workflow确认全绿。
---
## 📈 生命周期时序图
以下是一个典型周期的时序图,展示刷新、休眠、检查的协作关系:
```mermaid
gantt
title Token 续期生命周期(一周示例)
dateFormat HH:mm
axisFormat %H:%M
section 周一
主刷新 A :done, 10:00, 10:10
安全网检查 :done, 12:15, 12:20
section 周二
安全网检查 :done, 12:15, 12:20
section 周三
安全网检查 :done, 12:15, 12:20
section 周四
主刷新 B :done, 10:00, 10:10
安全网检查 :done, 12:15, 12:20
section 周五
安全网检查 :done, 12:15, 12:20
section 周六
安全网检查 :done, 12:15, 12:20
天眼休眠 :crit, 20:00, 24:00
section 周日
安全网检查 :done, 12:15, 12:20
```
---
## 📝 执行回执区
铸渊完成每个 Phase 后,在此处追加回执:
| **Phase** | **状态** | **完成时间** | **备注 / Commit SHA** |
| --- | --- | --- | --- |
| A · Token 注册表 | ⏳ 待执行 | — | — |
| B · Token 自动刷新脚本 | ⏳ 待执行 | — | — |
| C · 天眼休眠避让机制 | ⏳ 待执行 | — | — |
| D · GitHub Action Workflow | ⏳ 待执行 | — | — |
| E · 天眼生命线任务注册 | ⏳ 待执行 | — | — |
| F · 多用户 Token 流程 | ⏳ 待执行 | — | — |
| G · 告警推送系统 | ⏳ 待执行 | — | — |
| H · 天眼全局扫描 | ⏳ 待执行 | — | — |
| I · 提交 | ⏳ 待执行 | — | — |
---
## 👤 人类手动操作区
<aside>
👤
**以下操作需要冰朔(人类)手动完成,铸渊无法代为执行:**
</aside>
### 当前无需人类操作 ✅
本指令的所有任务均可由铸渊独立完成。
### 未来可能需要的人类操作
1.**添加新开发者时**
- 在 Google Cloud Console 加入测试用户白名单
- 用新用户 Gmail 完成 OAuth 授权
- 在 GitHub 添加对应的 `GDRIVE_REFRESH_TOKEN_DEVxxx` Secret
- 通知铸渊更新注册表
2.**Token 刷新失败时(告警触发)**
- 重新访问授权链接 → 拿新 code → 换新 token → 更新 GitHub Secret
- 手动触发 `renew-gdrive-tokens` Workflow 验证
3.**发布 OAuth 应用(彻底解决过期问题)**
- 路径Google Cloud Console → API和服务 → OAuth 权限请求页面 → 点「发布应用」
- 发布后 Refresh Token 永久有效,续期引擎变为安全备份而非必要操作
---
## ⚖️ 指令执行顺序
<aside>
🚦
**上篇 Phase A→E + 下篇 Phase F→I严格顺序执行。**
Phase H 天眼扫描未通过前,禁止执行 Phase I 提交。
每个 Phase 完成后在回执区写状态。
</aside>
---
🖋️ 霜砚 · PER-SY001
🧊 代 TCS-0002∞ 冰朔 签发
📅 2026-03-24T15:00+08:00