Files
ai-contract-platform/project-docs/V2-P1-04.8-calendar-oauth-scheduled-sync-dual-key-feedback-quality-dead-letter-alerts-incremental-graph-2026-08-24.md
yuqei 1d85329a6a
Build and Test Quality Gate / Contract Web typecheck and build (pull_request) Successful in 9m12s
Build and Test Quality Gate / Isolated Alibaba and Tencent KMS gateway (pull_request) Failing after 4m53s
Build and Test Quality Gate / Python tests and Contract API migration (pull_request) Failing after 24m55s
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 8m42s
feat: deliver governed contract platform and async AI tasks
2026-08-26 12:53:47 +08:00

194 lines
13 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.
# P1-04.8 企业日历 OAuth、双密钥灰度、反馈质量、死信告警与增量关系图交付报告
日期:2026-08-24
状态:已实现、已迁移、已完成 Chrome 登录态 UAT;自动化与生产构建验证通过
## 1. 阶段结论
P1-04.8 已完成五项能力:
1. Google Calendar、Microsoft 365 日历的服务端 OAuth 授权码 + PKCE、加密令牌、定时同步和增量游标;
2. Webhook 当前/上一版本签名密钥的限时并行灰度、握手验证和显式收口;
3. 根因反馈的租户级质量快照和 issue_code 级质量分解;
4. 影响分析与外部派发死信的滚动窗口、阈值、冷却和告警证据;
5. 关系社区的全量/自动/增量物化、受影响社区重算和未变化成员复用。
本阶段把 P1-04.7 的人工同步、单密钥轮换、反馈计数和全量图物化推进到可持续运营状态。系统仍不静默覆盖合同正文或规则正文;OAuth 状态、同步游标、密钥灰度、质量评估、告警触发和图快照均形成独立证据。
## 2. 产品与业务流程
### 2.1 企业日历 OAuth 与定时增量同步
管理员可创建 `google_calendar` 或 `microsoft_graph` 日历源,填写日历 ID(主日历可填写 `primary`),选择手动或定时同步、15~1440 分钟间隔及是否保存增量游标。
OAuth 流程为:
1. 管理员点击连接;服务端生成一次性 state、PKCE verifier/challenge,state 只保存 SHA-256 摘要,verifier 加密保存并在 10 分钟后失效;
2. 浏览器跳转到固定的 Google 或 Microsoft 官方授权端点;
3. 提供方回调管理页后,前端将 code/state 交给服务端;
4. 服务端校验一次性 state、交换令牌并加密保存 access token、refresh token 和后续增量游标;
5. 治理 Worker 使用数据库租约认领到期日历源,刷新令牌并执行同步;成功后推进 next_sync_at,失败时记录原因、连续失败次数并退避。
Google 使用 `syncToken`;遇到提供方返回 410 时自动清除失效游标并重建全量快照。Microsoft 使用 calendarView delta 返回的 `@odata.deltaLink`。外部请求只允许代码内固定的官方主机,不接受用户提供任意 OAuth/token/API 端点。
本地 UAT 环境没有真实企业 OAuth 客户端凭据,因此 UI 和配置失败边界已验证,但没有伪造外部授权成功。生产接入必须提供客户端 ID/secret、HTTPS 回调和独立令牌加密密钥。
### 2.2 通知双密钥灰度
Webhook 轮换现在支持 1~168 小时宽限期:
- 当前密钥立即升级为新版本;
- 上一版本及有效期被保留,宽限期内请求同时携带当前与上一版本的 HMAC-SHA256 签名;
- 已启用通道可选择在宽限期继续工作,不因轮换造成通知中断;
- 新密钥握手通过后状态变为 `ready_to_finalize`,管理员显式收口后删除上一版本引用;
- 宽限期过期后治理 Worker 自动清理上一版本;
- 新密钥仍只在轮换响应中显示一次,数据库只保存版本而不保存可直接使用的明文派生密钥。
接收方可以通过 `X-Yuqei-Key-Version`、`X-Yuqei-Signature-SHA256` 验证当前密钥;灰度期间额外读取 `X-Yuqei-Previous-Key-Version`、`X-Yuqei-Signature-Previous-SHA256`。
### 2.3 根因反馈质量评估
每次根因反馈新增 1~5 分复核置信度。管理员可生成不可变质量快照,指标包括:
- 反馈数、独立评审人数和评审人多样性;
- 有帮助率、纠正率、评论覆盖率、建议采纳率;
- 平均复核置信度、分类一致率和综合质量分;
- 每个 issue_code 的样本、评审人数、帮助率、纠正率、一致率和质量分。
质量分不等同于“有帮助率”,避免单一正向点击掩盖样本过少、缺少评论、低置信度或评审人单一等问题。快照保留生成者和生成时间,可用于后续比较而不覆盖历史。
### 2.4 死信告警策略
每个租户可独立配置是否启用、影响任务阈值、外部派发阈值、滚动窗口和冷却时间。治理 Worker 汇总窗口内死信,任一维度达到阈值且不在冷却期时:
1. 生成 `playbook_dead_letter_threshold` 治理通知;
2. 记录影响/派发死信数量、触发原因、通知 ID、生成者和时间;
3. 更新 last_alert_at;
4. 冷却期内不重复告警,避免通知风暴。
告警策略默认停用,不会因升级自动向企业外部通道发消息。
### 2.5 万级关系图增量物化
关系社区物化接口增加 `auto/full/incremental` 和 `force`。自动模式在图摘要未变化时直接返回最新快照;图变化时,以最近快照为基线识别变更规则,扩展到受影响的旧社区和当前连通分量,只重算受影响区域,并复用未变化社区成员。
快照记录 build_mode、base_snapshot_id、变化节点/边、复用节点和耗时。成员写入使用批量插入,避免万级节点逐行提交。查询接口公开快照构建模式和变化节点数;前端继续提供物化社区筛选、WebGL 大图及 SVG 降级。
## 3. 技术实现
### 3.1 数据与迁移
Alembic 版本:`20260823_0059`。
新增表:
- `playbook_calendar_remote_events`:外部日历事件的租户/来源级增量物化;
- `playbook_calendar_oauth_states`:短期一次性 OAuth state 与加密 PKCE verifier;
- `playbook_root_cause_feedback_quality_snapshots`:不可变质量快照;
- `playbook_dead_letter_alert_policies`:租户告警策略及版本;
- `playbook_dead_letter_alert_events`:阈值触发证据。
扩展字段:
- `playbook_calendar_sources`:提供方日历 ID、调度、OAuth 加密令牌、加密游标、next_sync_at、失败计数和租约;
- `playbook_calendar_sync_runs`:full/incremental、游标推进、定时触发和 Worker 名称;
- `playbook_notification_channels`:上一密钥版本、有效期和轮换状态;
- `playbook_conflict_root_cause_feedback`:复核置信度;
- `playbook_relationship_community_snapshots`:增量基线、变化/复用计数和耗时。
运行时 schema-check 已覆盖新增表和关键字段。迁移已在 PostgreSQL 正向升级,并在 SQLite 完成 head 升级及跨版本降级测试。0059 downgrade 会先删除本版本创建的列索引,再删除列,兼容 SQLite 对残留索引的严格校验。
### 3.2 接口与前端
新增或扩展的主要接口:
- `POST /governance/calendar-sources/{source_id}/oauth/start`;
- `POST /governance/calendar-oauth/complete`;
- `POST /governance/calendar-sources/{source_id}/oauth/revoke`;
- `POST /governance/calendar-sources/{source_id}/sync` 返回增量与调度证据;
- `POST /governance/notification-channels/{channel_id}/rotate-secret` 接收灰度参数;
- `POST /governance/notification-channels/{channel_id}/finalize-secret-rotation`;
- `GET/PUT /governance/dead-letter-alert-policy`;
- `GET /governance/dead-letter-alert-events`;
- `GET /governance/root-cause-feedback-quality`;
- `POST /governance/root-cause-feedback-quality/evaluate`;
- `POST /relationship-graph/materialize` 接收物化模式和 force。
Contract Web 增加对应的同源代理、OAuth 回调处理、日历调度表单、连接状态、双密钥宽限状态、质量面板、告警策略和增量快照提示。OpenAPI 更新为 103 个路径、156 个 schema,所有 schema 引用可解析。
### 3.3 配置与安全边界
新增运行时变量位于 Contract API `.env.example`:
- `CONTRACT_API_PLAYBOOK_CALENDAR_OAUTH_TOKEN_ENCRYPTION_SECRET` 或 `_FILE`,只能二选一;
- `CONTRACT_API_PLAYBOOK_CALENDAR_OAUTH_REDIRECT_URI`;
- Google/Microsoft 客户端 ID 与 secret;
- Microsoft tenant,默认 `organizations`。
配置检查会拒绝只配置 ID 或只配置 secret、同时配置两种加密密钥来源、提供方存在但没有加密密钥,以及 staging/production 使用非 HTTPS 回调。没有提供方配置时返回 warning,并让 OAuth 发起接口以 409 明确失败,不会降级为明文保存或虚假连接。
## 4. Chrome 超级管理员 UAT
工作空间:Playbook 隔离 UAT
账号:`uat.legal.20260823@example.test`
页面:`http://127.0.0.1:3000/admin/playbook?tab=operations`
### 4.1 可见流程证据
- 页面标题显示 `Enterprise governance · P1-04.8`;
- Google Calendar 表单可切换到 `primary`、定时增量、60 分钟及“保存加密游标并执行增量同步”;
- 生成根因反馈质量快照成功:1 条反馈、1 名评审人、评论覆盖 100%、分类一致 100%、综合质量 82 分;
- 保存死信告警策略成功;UAT 保持策略停用,未制造死信或触发外部通知;
- 生成关系社区快照返回 `playbook-community-cc4774beb595`。当前规则图未变化,因此自动模式复用既有全量快照并显示变化 0、耗时 0ms;专项测试覆盖真实增量分支;
- 关系图和治理配置在 Chrome 可见区域内无控件重叠、文本截断或不可达按钮。
### 4.2 未伪造的外部边界
本地环境没有企业 Google/Microsoft OAuth 凭据,也没有真实 Webhook 接收方。本次没有创建虚假连接、没有对外发送邮件/Webhook,也没有为了演示制造死信。OAuth code 交换、刷新、全量到增量游标推进、定时 Worker 认领、双密钥双签名、握手后收口、阈值告警和增量社区变化由隔离自动化覆盖;上线前仍需在预发布环境完成真实提供方与接收端联调。
## 5. 验证结果
- 当前后端收集 349 项:345 项通过、4 项按环境条件跳过;其中第二轮全量回归 348 项为 344 项通过、4 项跳过,随后新增的双签名网络层测试 1/1 通过;
- P1-04.8 Playbook operations 专项:12/12 通过;
- 迁移失败用例修复后精确复跑:3/3 通过;
- OAuth 专项额外断言 access token、refresh token 和增量 cursor 均未以原始明文持久化;
- 前端现有测试:41/41 通过;
- TypeScript:通过;
- Next.js 生产构建:通过,静态生成/收集 135 个页面;
- OpenAPI YAML:103 个路径、156 个 schema、0 个悬空 schema 引用;
- PostgreSQL Alembic:`20260823_0059 (head)`;
- Contract API `/health`:200,status=ok;
- Contract Web 3000、Contract API 8100、AI API 8101 和治理 Worker 保持运行。
## 6. 市场与架构评估
企业合同治理采购会重点询问企业日历能否自动进入 SLA、令牌与密钥是否可安全轮换、失败是否会主动告警、人工反馈是否可衡量,以及大规模规则库是否需要人工反复全量重算。本阶段直接补齐这些可采购性与可运营性门槛。
当前继续使用 PostgreSQL 事务表和治理 Worker 是合理的:
- OAuth 状态、同步证据、告警证据和图快照需要与租户治理事实一致,事务数据库优先于过早拆分;
- 数据库租约允许多 Worker 安全竞争,达到更高吞吐后可把调度迁移到专用队列而不改变 API;
- 关系社区仍是确定性连通分量,增量物化和批量写入足以支撑当前万级目标,无需现在引入图数据库;
- 反馈质量是可解释统计,不是不可审计的在线模型自训练,符合合同治理的人审边界。
## 7. 发布门槛与下一步
正式开放企业 OAuth 前必须完成:
1. 在 Google Cloud 与 Microsoft Entra 注册生产 HTTPS 回调,采用最小只读日历权限并完成管理员审批;
2. 把 OAuth 令牌加密密钥与 Webhook 主密钥分别托管到 KMS/Vault 或只读 secret file,建立轮换与恢复演练;
3. 用两个预发布租户分别完成授权、初次全量、事件增删、增量同步、游标失效回退、令牌撤销和租户隔离验证;
4. 与真实 Webhook 接收端演练旧密钥、双密钥、新密钥、握手和宽限期到期;
5. 以 10k/50k 节点和高变更率数据压测增量命中率、物化耗时、快照大小和 WebGL 交互延迟;
6. 将日历连续失败、OAuth 失效、同步租约堆积、双密钥即将过期、质量分下降和告警派发失败接入统一可观测平台。
后续可进入 P1-04.9:企业 OAuth 真实预发布接入与管理员同意治理、日历同步 SLO/回放、通知 KMS/Vault 与专用通道、反馈离线基准集、告警升级链路及 50k 图 Worker/LOD 压测。
## 8. 设计依据
- Google Calendar incremental synchronization:<https://developers.google.com/workspace/calendar/api/guides/sync>
- Google OAuth 2.0 web-server applications:<https://developers.google.com/identity/protocols/oauth2/web-server>
- Microsoft identity platform authorization-code flow:<https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow>
- Microsoft Graph calendarView delta:<https://learn.microsoft.com/en-us/graph/api/event-delta?view=graph-rest-1.0>
- Microsoft `offline_access` scope:<https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc>