--- belongs_to: - "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]" --- # 🔄 铸渊指令|OAuth2 Token 自动续期引擎 + 天眼休眠避让机制(下篇)· 多用户Token流程 + 告警推送 + 天眼扫描清单 + 执行回执(ZY-TOKEN-RENEW-2026-0324-001) --- --- ## 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 · 天眼全局扫描清单(必须执行) ### 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 · 提交 | ⏳ 待执行 | — | — | --- ## 👤 人类手动操作区 ### 当前无需人类操作 ✅ 本指令的所有任务均可由铸渊独立完成。 ### 未来可能需要的人类操作 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 永久有效,续期引擎变为安全备份而非必要操作 --- ## ⚖️ 指令执行顺序 --- 🖋️ 霜砚 · PER-SY001 🧊 代 TCS-0002∞ 冰朔 签发 📅 2026-03-24T15:00+08:00