Files
test-doc/Gitea知识库/Gitea知识库 v1.1 产品需求文档 PRD.md
2026-08-11 15:40:11 +08:00

436 lines
32 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.
---
title: Gitea知识库 v1.1 产品需求文档 PRD
date: 2026-08-10
type: PRD
status: review-ready
content_status: discussion
owner: Verlit
last_updated_at: 2026-08-10
last_updated_by: Codex
hash: sha256:f2abc96b306a2314d8abf6beef982b56a6bd5dd2147bee1adbc025305d0c9536
hash_scope: Markdown 正文(从一级标题开始至文件末尾)的 UTF-8 SHA-256
belongs_to:
- "[[3-业务线/Gitea知识库/_context|Gitea知识库]]"
depends_knowledge:
- "[[3-业务线/Gitea知识库/公司共享 Context 项目仓库发布方案 v1|公司共享 Context 项目仓库发布方案 v1]]"
- "[[3-业务线/Gitea知识库/公司共享 Context MCP-first 身份与审计方案 v1.1|公司共享 Context MCP-first 身份与审计方案 v1.1]]"
- "[[3-业务线/Gitea知识库/v1.1-技术栈与详细实施设计|v1.1 技术栈与详细实施设计]]"
- "[[3-业务线/Gitea知识库/v1-验收与止损矩阵|v1.1 验收与止损矩阵]]"
---
# Gitea知识库 v1.1 产品需求文档 PRD
## 1. 文档结论
本 PRD 已具备进入 C1 代码开发评审的业务与工程完整度,但不代表已经授权开发、部署或连接真实环境。当前仍处于 `C0 本地工程设计构建`;下一阶段必须由 Verlit 明确宣布后才开始。
方案没有方向性缺陷,也没有偏离原 v1。原 v1 的“一项目一私仓、单向明确发布、发布网关唯一写 `main`、不可变 release、唯一 `main/current`、内容状态与事务状态分离、可恢复和可止损”保持不变;v1.1 只补充 MCP 唯一用户入口、飞书身份、内部权限数据库、Gitea 二次复核、受控本地来源、Agent 无关适配和强制审计。
本轮闭合了三项此前不够明确的实现问题:
1. MCP OAuth 由成熟 OAuth/OIDC Authorization Server 承担协议和令牌生命周期,飞书作为员工身份来源;不在业务服务内从零自研完整授权服务器。
2. 飞书登录不等于 Gitea 授权;v1.1 试点通过受控预配置绑定飞书稳定 ID 与 Gitea 数字用户 ID,未绑定即拒绝。
3. 中文检索首期采用 PostgreSQL `pg_trgm`+元数据过滤,不把面向英文分词的原生 FTS 当成中文主检索。
仍未确定的内容属于环境和治理参数,见第 17 节;它们不要求重写 PRD,但会在对应阶段形成硬门。
## 2. 产品定义
### 2.1 产品一句话
面向全员 Agent 工作方式,以飞书员工身份登录,通过统一远程 MCP 安全读取和发布项目级共享 Context,并由内部授权与 Gitea 仓库权限共同限制访问,所有人、Agent 和服务行为均可追溯。
### 2.2 战略位置
本业务线是“企业内部 AI 系统(先知识库、后 Agent)”的共享 Context 与权限治理底座。当前版本先证明知识库内容可被可靠发布、准确读取、即时撤权、完整审计;Skill Registry、正式审批和更多内容来源只在真实试点证明需要后进入后续版本。
### 2.3 产品入口
- 唯一用户业务入口:Agent Host 中配置的远程 MCP。
- 首批 Agent adapterCodex、Claude Code;其他 Agent 只需满足同一 adapter contract。
- 允许的浏览器页面:飞书/OAuth 授权页及协议回调,不是业务 Web 页面。
- 不建设:独立企业管理后台、权限页面、发布驾驶舱、审计 Web 页面。
## 3. 目标与非目标
### 3.1 v1.1 目标
- 每位员工使用自己的飞书身份完成 MCP OAuth,不使用共享账号。
- 通过 `ProjectGrant ∩ Gitea live permission` 实现双层项目权限。
- Agent 只能读取已授权项目唯一 `current`,不能默认读取 Git 历史、构建区或其他项目。
- 用户可明确选择本地 Markdown/受控附件,经 Local Source Gate、构建、检查、diff 和一次性确认后发布。
- `discussion``confirmed` 复用同一发布链,仅规则和所需权限不同。
- 每次调用自动记录 human、agent、service 三主体以及请求、授权、结果和关联链。
- 发布完成以 Git、release、current、检索索引和 MCP readback 一致为准。
- 支持撤权、失败重试、过期请求、并发冲突和恢复发布。
### 3.2 非目标
- 不建设自定义业务 Web/移动页面。
- 不让 Agent、LLM 或用户参数直接决定身份、角色和权限。
- 不开放任意 SQL、Shell、Git、Gitea Admin、部署、迁移、备份、密钥或审计写删工具。
- 不接入个人全部工作区,不递归扫描未选择目录。
- 不在当前版本建设 Skill Registry、skill 审核表或 skill 发布流程。
- 不做跨项目统一大库、跨项目检索后再由模型过滤。
- 不把向量库、Elasticsearch、Kafka、Redis、Kubernetes 或微服务作为首期前置。
## 4. 角色与责任
| 角色 | 说明 | 允许行为 | 禁止行为 |
|---|---|---|---|
| 普通成员 | 已绑定飞书和 Gitea 的项目成员 | 读取、搜索授权项目;提交允许级别的构建请求 | 直接写 Git、修改权限、读取历史或其他项目 |
| Publisher | 获得项目发布动作的成员 | 在检查和确认后提交 discussion/confirmed 发布 | 绕过网关、force push、修改审计 |
| 治理人员 | 维护用户绑定、ProjectGrant、项目配置和例外 | 受控预配置、撤权、审批配置变更 | 通过普通 MCP 自行扩大权限 |
| 审计人员 | 查看授权范围内的脱敏审计 | 查询、追踪、验证事件链 | 修改或删除审计事件 |
| Agent Host | Codex、Claude Code 或兼容 Agent | 调用标准 MCP、展示确认、传递明确选择的内容 | 自报身份、扫描工作区、持有发布 Git 凭据 |
| `contextd serve` | MCP resource server | 身份、授权、工具路由、读、请求入队、审计 | Gitea 写入、迁移、部署 |
| `contextd worker` | 内部可靠任务执行者 | 构建、Git 写入、export、readback | 面向用户开放、Gitea Admin |
## 5. 系统边界与技术基线
```text
飞书用户
→ Codex / Claude Code / Other Agent
→ Verlit Agent Compatibility Layer
→ OAuth Authorization Server ↔ 飞书 OAuth
→ Reverse Proxy → contextd serve (/mcp)
→ PostgreSQL Identity/AuthZ/Release/Outbox/Audit/Search
→ contextd worker → Gitea 私仓 → immutable release/current
→ MCP readback → Agent
```
| 能力 | 技术基线 |
|---|---|
| 服务端 | Go 1.26.x,官方 Go MCP SDK v1.7.x`net/http` |
| MCP | Streamable HTTP;目标 2026-07-28,兼容 2025-11-25 |
| OAuth | 成熟 OAuth/OIDC Authorization Server+飞书身份联邦;Authorization CodePKCE |
| 数据库 | PostgreSQL 18.x`pgx/v5``sqlc``goose` |
| 可靠任务 | PostgreSQL transactional outbox,独立 `worker` 运行角色 |
| 仓库 | Gitea 1.26.x 支持分支;每项目一私仓;受保护 `main` |
| Git | 系统 Git CLI、临时 worktree、非 force push、CAS/`base_current` |
| 内容 | `goldmark` ASTJSON Schema 2020-12+确定性 builder |
| 中文检索 | PostgreSQL `pg_trgm`+标题/标签/路径/正文元数据过滤 |
| 审计 | PostgreSQL 独立 schema/角色、append-only、hash chain、每日 checkpoint |
| 观测 | OpenTelemetry;正文、token、绝对路径不进入日志或 trace |
| 制品 | OCI 镜像、固定 digest、SBOM;首期不要求 Kubernetes |
## 6. 端到端闭环总览
```mermaid
flowchart LR
G[治理预配置] --> L[飞书 OAuth 登录]
L --> B{绑定与状态有效?}
B -- 否 --> D[拒绝并审计]
B -- 是 --> T[MCP 会话]
T --> A[双层授权]
A --> R[读取 / 搜索 current]
A --> S[本地明确选择]
S --> V[构建 / 校验 / diff]
V --> C[人类一次性确认]
C --> Q[发布请求 + outbox]
Q --> W[worker Git/CAS]
W --> E[immutable release + current + index]
E --> K[MCP readback]
K --> Z[完成回执]
Z --> R
Q -. every step .-> U[三主体审计]
W -- 失败 --> F[failed / retry / recovery release]
F --> Q
X[撤权/停用] --> D
```
闭环定义:一次发布只有在 `release record completed ∩ Gitea commit 可读 ∩ immutable release 校验通过 ∩ current 指向该 release ∩ search index 同版本 ∩ MCP readback hash 一致 ∩ completed 审计已落盘` 时完成。任何一项失败都不得返回成功。
## 7. 每一步调用、功能与输出
下表是 Canvas 的文字真源。`A1` 为普通读,`A2` 为受控构建,`A3` 为 discussion 发布,`A4` 为 confirmed/恢复发布。
| 步骤 | 谁发起 | 调用内容 | 实现功能 | 成功输出 | 失败/审计 |
|---|---|---|---|---|---|
| S00 治理预配置 | 治理人员/运维 | 受控 migration/import`user_identities``feishu_bindings``gitea_bindings``projects``project_grants` | 建立飞书稳定 ID、Gitea 数字 ID、项目和动作授权映射 | 版本化配置记录、导入报告、审计关联 ID | 冲突或重复即整批拒绝;不暴露普通 MCP 写工具 |
| S01 发现资源 | Agent Host | `POST /mcp``/.well-known/oauth-protected-resource` | 发现 MCP resource 与授权服务器 | PRM、授权服务器地址、resource/audience | Origin/Host/protocol 不合法即拒绝并记 `request_denied` |
| S02 飞书 OAuth | Agent adapter | Authorization CodePKCE → 授权服务器 → 飞书 authorize/token/user info | 验证真实飞书员工身份,抵抗 code/token 截获 | 飞书 claims、内部 subject 候选 | state/PKCE/tenant/redirect 不一致即失败;不落飞书明文 token |
| S03 绑定激活 | Identity federation adapter | 查询 `FeishuBinding``GiteaBinding``UserIdentity` | 仅激活唯一预配置的飞书—内部—Gitea 映射 | active internal `user_id` | 未配置进入 `binding_pending`;冲突/停用进入 denied;均审计 |
| S04 MCP 凭据 | Authorization Server | token/refresh/revoke`AgentSession` | 为当前人和 Agent client 创建短期会话 | access token、session、scope、expiry | token 不进入业务日志;会话可即时撤销 |
| S05 身份自查 | 用户/Agent | `get_my_identity``get_my_project_roles` | 展示本人身份、绑定状态和可用角色,不接受参数冒充 | 脱敏 identity/role 摘要 | 只返回 token subject;记录 human/agent/service |
| S06 列出项目 | 用户/Agent | `list_authorized_projects` | 先查 ProjectGrant,再实时查 Gitea permission | 两层均允许的项目列表 | Gitea 不可用、任一层拒绝即 fail closed |
| S07 读取 current | 用户/Agent | `get_current_manifest``read_artifact``verify_release_hash` | 读取唯一 current 的 manifest、正文和校验信息 | project/release/content status/hash/content | 禁止 history/build/private source;每个 project 再鉴权 |
| S08 搜索 current | 用户/Agent | `search_current` → ProjectGrant/Gitea → `pg_trgm` | 仅在已授权项目 current 内进行中文搜索 | 带 project/release/hash 的命中片段 | 先过滤项目再查询;不做跨项目结果后过滤 |
| S09 本地选择 | 用户+adapter | Local Source Gate;允许根、真实路径、类型、大小、secret/PII 预检 | 只读取用户明确选择的本地 Markdown/附件 | 文件数、相对 label、size/hash 预览 | 越界、符号链接、控制文件、秘密/PII 命中即本地阻断 |
| S10 人类确认来源 | 用户+框架确认服务 | 展示选择清单 → 签发 selection confirmation | 确认上传范围,不把 Agent 的自然语言当授权 | 一次性确认、Selection Manifest | 用户取消或 manifest 变化即废弃;不上传未选内容 |
| S11 分块传输 | Agent adapter | `create_selection``append_selection_content` | 将选中内容以固定 chunk 送入隔离临时区 | selection ID、完整度、server-computed hash | 缺块、乱序、超时、hash 不符即废弃整个 selection |
| S12 构建预览 | 用户/Agent | `build_preview` → deterministic builder | 规范化 Markdown、收集附件、改写链接、生成 manifest | candidate artifact、candidate hash、构建报告 | 不由 LLM 决定确定性结果;同输入同版本 hash 相同 |
| S13 完整校验 | 用户/Agent | `validate_release_request` → schema/link/path/secret/PII/policy scanner | 拦截结构、路径、凭据、隐私和规则问题 | validation report、policy version、blocking findings | blocking finding 不得继续;例外必须引用受控记录 |
| S14 差异预览 | 用户/Agent | `preview_release_diff` → current reader | 把 candidate 与 `base_current` 比较 | 文件/章节/附件变化、candidate hash、base_current | current 已变化则标 stale,要求重新构建 |
| S15 发布确认 | 真实用户+框架确认服务 | 固定展示 project/action/hash/base/diff → `confirmation_id` | 给 A3/A4 生成与精确请求 hash 绑定的一次性授权 | 5 分钟内有效的 confirmation ID | 不能复用、转让或跨 hashAgent 原生 prompt 不是最终真源 |
| S16 提交发布 | Publisher/Agent | `submit_discussion_release``submit_confirmed_release` | 创建幂等发布记录并提交 outbox | release ID、queued 状态、correlation ID | 请求、release、outbox、审计同一事务;失败不入队 |
| S17 网关复核 | `contextd serve` | token/user/binding/session/grant/policy/Gitea/confirmation 全链检查 | 在写动作前再次执行双层权限和确认校验 | allowed decisionpolicy evidence | 任一条件失败即 denied;不以工具参数覆盖主体 |
| S18 Worker 领取 | `contextd worker` | `FOR UPDATE SKIP LOCKED` claim outboxidempotency key | 可靠领取一次发布任务,允许安全重试 | processing 状态、attempt、worker identity | 重复事件返回同一 release;审计 worker 主体 |
| S19 Git/CAS 发布 | worker | 临时 worktree、Gitea read/write credential、Git commit/push | 再验 `base_current`,生成完整新 `current/`,单 commit 非 force push | commit SHA、release manifest | non-fast-forward → `STALE_BASE`token 不进命令行/日志 |
| S20 导出与切换 | worker | immutable export、checksum、原子 current pointer | 从 commit 生成不可变 release,并原子切换唯一 current | release path、current version、checksums | 校验失败不切 current;旧 release 保留供恢复 |
| S21 激活检索 | worker | 构建 `pg_trgm` search document/index | 让搜索版本与 current 保持一致 | `project_idrelease_id` index active | 索引失败则发布不 completed;不得搜索旧/半成品索引 |
| S22 MCP 读回 | worker/internal reader | `get_current_manifest``read_artifact` 等同业务读取链 | 用用户将使用的路径验证结果,不只检查磁盘 | readback release/hash/content status | Git/current/MCP 任一不一致即 failed,不能伪成功 |
| S23 完成回执 | serve/worker | 更新 `release_records`、写 completed audit、`get_release_status` | 对用户给出可验证发布结果 | release ID、commit、current/hash、readback、timestamps | completed 审计无法落盘则不返回 completed |
| S24 后续消费 | 用户/Agent | S07/S08 | 后续会话只消费唯一 current,闭合“发布→读取” | 与 S23 相同 release/hash | 若不一致触发完整性告警,停止扩散 |
| S25 审计查询 | 本人/审计人员 | `list_my_actions``trace_release``trace_correlation``verify_audit_event` | 查询脱敏行为、追踪发布全链并验证 hash chain | human/agent/service、decision、result、correlation | 查询也需授权并被审计;无审计写删工具 |
| S26 撤权/离职 | 治理人员/身份事件 | 受控更新 binding/grant/sessionOAuth revoke | 使飞书、Gitea、内部权限或会话任一撤销立即生效 | revoked version、session invalidation、审计 | 下一次调用 fail closed;不等待 access token 自然到期 |
| S27 失败与重试 | 系统/Publisher | `get_release_status`、幂等重试、`cancel_precommit_release` | 区分可重试、需重建、需人工处置的失败 | stable error code、attempt、next action | 已产生 commit 后不可“删除历史式回滚” |
| S28 恢复发布 | Publisher+确认人 | 从已知良好 release 新建 A4 release | 通过新 commit 恢复 current,保留完整历史 | 新 release/commit/current、恢复原因 | 仍需双层权限、完整检查和一次性确认 |
## 8. 功能需求
### FR-01 身份与会话
- 每位用户必须独立 OAuth;同一 Agent Host 上不同用户的 token、session、审计主体不得串用。
- 飞书身份键至少包含 `tenant_keyopen_id`,在权限允许时保留租户内稳定 `user_id`;邮箱、手机号、姓名不作为主键。
- MCP resource server 不直接信任 Feishu token;由授权服务器完成联邦并签发 MCP 资源令牌。
- 未预配置 GiteaBinding 的用户只能看到绑定待处理状态,不可列出项目。
- access token、refresh/session、binding 和 grant 均可撤销;每次调用重新检查权限版本。
### FR-02 双层授权
- 第一层:内部 `ProjectGrant` 决定项目、角色、动作、有效期和 sensitivity policy。
- 第二层:Gitea 当前仓库权限决定该 Gitea 账户是否仍可读取项目。
- 有效权限是两层交集;禁止用并集、兜底角色或 Agent 声明放宽。
- 首期不缓存 Gitea 的 allow 结果;Gitea 超时或错误时 fail closed。
- A3/A4 另需一次性精确确认;确认不替代双层授权。
### FR-03 读取与搜索
- 只允许读取 `main/current` 对应的不可变 release。
- 响应必须带 `project_id``release_id``content_status`、manifest/hash,便于 Agent 判断来源。
- 搜索必须在 SQL 查询前确定授权项目集合,并以 project/release 作为强过滤条件。
- 不返回构建临时区、私人来源、Git 历史、其他分支或未发布 candidate。
### FR-04 Local Source Gate
- 允许根由企业/框架配置,正文和 Agent 无权更改。
- 用户必须明确选择文件或章节;目录选择仅枚举该选择范围,禁止默认扫描整个工作区。
- 解析真实路径后拒绝工作区外路径、符号链接逃逸、`.git`、凭据目录、隐藏控制文件和不允许的二进制。
- 本地先做 secret/PII 预检,服务端收到后再次做完整策略检查;客户端通过不等于服务端放行。
- 只传相对 source label,不传个人绝对路径;正文不进入普通日志、trace 或审计详情。
### FR-05 构建与验证
- builder 输入为 Selection Manifest+内容+固定 builder/policy/schema version。
- 同输入和相同版本必须得到同 candidate hash。
- validation 至少覆盖 schema、Markdown 结构、内部链接、附件引用、路径、凭据、PII、控制文件、大小和内容状态。
- blocking finding 无法通过 Agent 解释绕过;例外必须是受控配置并进入审计。
### FR-06 发布
- `discussion``confirmed` 使用同一 pipelineconfirmed 需要更高权限/确认,但不复制另一套写入逻辑。
- 提交必须引用 `candidate_hashbase_currentconfirmation_ididempotency_key`
- 只有 project-scoped publish gateway credential 可以非 force push 受保护 `main`
- current 必须通过完整目录构建后原子切换,不能在服务目录逐文件修改。
### FR-07 审计
- 每次工具调用产生 `request_received → allowed/denied → completed/failed` 事件链。
- 每个事件至少记录 human、agent、service、session、tool、action、project、request hash、policy、authorization、confirmation、result、correlation。
- `request_received` 无法持久化时拒绝业务调用。
- 普通运行身份无 `audit_events` update/delete;查询只走脱敏 view。
- 事件使用 canonical JSON hash chain,每日生成签名 checkpoint 并纳入备份。
### FR-08 失败、撤权和恢复
- 对外返回稳定错误码和下一步建议,不泄露其他项目、主体或内部路径。
- 可重试错误保持相同 idempotency keycurrent 已变化返回 `STALE_BASE` 并要求重建。
- 已完成 Git commit 不做历史删除式回滚;恢复必须创建新 release。
- 撤权后下一次调用即失败,并可通过 correlation 追溯撤销主体和影响会话。
## 9. MCP 工具清单
| 分组 | 工具 | 风险等级 | 是否需人类确认 |
|---|---|---:|---|
| 身份/读取 | `get_my_identity``list_authorized_projects``get_my_project_roles``get_current_manifest``read_artifact``search_current``verify_release_hash` | A1 | 否;客户端可保留普通 tool prompt |
| 选择/构建 | `create_selection``append_selection_content``build_preview``validate_release_request``preview_release_diff` | A2 | 来源上传前需要明确范围确认;不是发布确认 |
| 发布 | `submit_discussion_release` | A3 | 是,一次性精确确认 |
| 高等级发布/恢复 | `submit_confirmed_release` | A4 | 是,一次性精确确认+更高角色 |
| 状态控制 | `get_release_status``cancel_precommit_release` | A1/A2 | 取消只允许 commit 前;记录审计 |
| 审计查询 | `list_my_actions``get_action_detail``trace_release``trace_correlation``list_project_audit_events``verify_audit_event` | A1/A2 | 按审计角色和项目范围授权 |
以下能力绝不注册为普通 MCP tool:用户/Gitea 绑定写入、ProjectGrant 写入、数据库迁移、部署、备份/恢复、密钥管理、Gitea Admin、通用 Git、Shell/SQL、审计写入/删除、功能动作开关修改。
## 10. 数据与状态
### 10.1 核心数据对象
| 领域 | 对象 |
|---|---|
| 身份 | `UserIdentity``FeishuBinding``GiteaBinding``AgentSession``MCPToken/claims` |
| 授权 | `Project``ProjectGrant``PolicyVersion``Confirmation` |
| 来源与构建 | `Selection``SelectionChunk``Artifact``ValidationReport` |
| 发布 | `ReleaseRecord``CurrentVersion``IdempotencyRecord``OutboxEvent` |
| 搜索 | `CurrentSearchDocument(project_id, release_id, field, normalized_text)` |
| 审计 | `AuditEvent``AuditCheckpoint``Correlation` |
### 10.2 状态机
```text
selection: created → receiving → sealed → consumed | expired | rejected
release: requested → queued → processing → committed → exported → indexed → readback_verified → completed
↘ failed / stale_base / cancelled_before_commit
binding: pending → active → suspended | revoked
session: active → expired | revoked
```
- 不认识的状态一律拒绝,不自动映射为成功。
- `completed` 是最终一致性事实,不等同于“任务已入队”或“Git push 已返回成功”。
- `content_status`discussion/confirmed)与 `release status`queued/completed/failed)保持两个字段。
## 11. 安全默认值
以下值作为 C1 合成环境的可执行默认值;G0 可按安全评审收紧或调整,但不得取消对应控制。
| 参数 | 默认值 |
|---|---|
| MCP access token | 15 分钟;issuer/audience/resource/scope/client 必验 |
| AgentSession/refresh | 8 小时;撤权即时失效 |
| 发布 confirmation | 5 分钟、一次性、绑定 user/session/tool/project/request hash |
| Selection TTL | 30 分钟;完成立即清理,失败最长保留 30 分钟后清理 |
| Markdown 单文件 | 2 MiB |
| 允许附件 | `.png``.jpg``.jpeg``.webp``.pdf`;只作为受控附件,不自动执行 |
| 附件单文件 | 5 MiB |
| Bundle 总量 | 10 MiB、最多 100 个文件 |
| MCP chunk | 256 KiB 原始内容;每块带序号和 hash |
| 路径 | 仅中央配置允许根;拒绝 symlink/junction/reparse point 逃逸 |
| Gitea allow cache | 关闭;每次项目访问实时复核 |
| Idempotency | 同 key 24 小时内返回同一 releasepayload hash 不同则冲突 |
| 普通日志 | 不记录 token、正文、附件、绝对路径、完整 diff |
| 审计试点保留建议 | 在线 365 天;checkpoint/备份 3 年,G0 结合制度确认 |
| 试点恢复建议 | RPO 24 小时、RTO 8 小时;G0 可收紧 |
## 12. 非功能需求
### 12.1 性能与容量试点目标
- `get_my_identity`/项目列表:无外部故障时 p95 ≤ 2 秒。
- current manifest/read:不含大正文传输时 p95 ≤ 2 秒。
- 10 万个 current 文档以内的单项目中文搜索:p95 ≤ 3 秒;以合成和真实试点基准为准。
- 10 MiB 以内发布从 queued 到 readback completedp95 ≤ 60 秒,不以牺牲校验换取速度。
- 单用户同时最多 3 个 receiving selection、1 个 processing release;每项目发布串行化。
### 12.2 可用性与一致性
- 试点目标月可用性 99.5%,不含已公告维护。
- Gitea、数据库、授权服务器或审计写入不可用时,权限与发布 fail closed。
- 读取可在 Git 暂时不可用时继续使用已校验的 current,但必须验证 manifest/hash;任何完整性异常立即停止读取。
- 重启、worker 重复领取、网络超时不得产生两个 current 或重复 commit。
### 12.3 可观测性
- 公开指标:请求量、拒绝原因码、外部依赖延迟、outbox backlog、release 状态耗时、readback mismatch、撤权生效延迟。
- trace 使用 correlation ID 串联 serve、DB、worker、Gitea、export、readback;不包含正文和秘密。
- 审计是合规事实,普通日志和 trace 不能替代审计。
## 13. 异常与恢复矩阵
| 场景 | 系统行为 | 用户下一步 |
|---|---|---|
| 未预配置 Gitea 绑定 | `BINDING_PENDING`,不给项目列表 | 联系治理人员完成受控预配置 |
| ProjectGrant 允许但 Gitea 拒绝 | `PERMISSION_DENIED_SECOND_LAYER` | 检查 Gitea 项目成员关系;不得自动放宽 |
| Gitea 权限 API 超时 | `AUTHZ_DEPENDENCY_UNAVAILABLE`fail closed | 稍后重试;审计保留依赖故障 |
| Local Source Gate 命中 secret/PII | 本地阻断且不传正文 | 移除/脱敏后重新选择 |
| 分块缺失/hash 不符 | selection rejected,全量清理 | 重新创建 selection |
| validation blocking finding | 不生成可发布确认 | 修正文档或走受控例外评审 |
| confirmation 过期/被用过 | `CONFIRMATION_INVALID` | 重新查看 diff 并确认 |
| `base_current` 已变化 | `STALE_BASE` | 重新 build/validate/diff/confirm |
| Git 已提交但 export/index/readback 失败 | release failed,保留 commit,不宣告 completed | 修复依赖后幂等续跑或发恢复 release |
| completed 审计落盘失败 | 不返回 completed | 系统重试,治理人员排查 audit store |
| 撤权/离职 | session/grant/binding version 失效 | 重新授权前任何访问均拒绝 |
| current 完整性异常 | 停止读取和扩散,触发告警 | 从已知良好 release 发起恢复发布 |
## 14. 代码开发与实施拆解
### 14.1 C1 代码开发(需要 Verlit 另行授权)
| 阶段 | 实现内容 | 明细产物 | 退出条件 |
|---|---|---|---|
| C1-00 | Codex/Claude Code adapter contract | MCP 配置样例、fake OAuth、确认和 Local Source Gate 契约测试 | 两个 adapter 使用同一工具 schema;单个失败不降低核心控制 |
| C1-0103 | 工程、契约、领域、DB | Go module、contracts、migration、sqlc、测试夹具 | 离线 build/test,状态/约束/最小 DB role 通过 |
| C1-0406 | OAuth、绑定、双层授权、MCP、审计 | authorization server 集成、Feishu/Gitea fake、middleware、outbox | 冒充、未绑定、撤权、审计中断用例均 fail closed |
| C1-0708 | current 读取、中文搜索、Local Source Gate、build/validate | 第一/二批 MCP tools、`pg_trgm` benchmark、scanner | 跨项目、历史、越界路径、secret/PII、超限均阻断 |
| C1-0910 | release/export/readback、审计查询、OTel | 第三/四批 tools、worker、Git fake、完整性验证 | 并发、幂等、失败续跑、三主体审计通过 |
| C1-11~12 | 安全/恢复测试与制品 | 测试报告、OCI、SBOM、checksum、运行手册 | M01~M10、开发态 T 用例通过;无秘密、无自动部署 |
### 14.2 G0~G5 真实实施(需要单独授权且先确认第 17 节)
1. G0:确认人、项目、OAuth/飞书/Gitea/服务器/审计/备份参数。
2. G1:测试环境基础设施和合成用户/项目,不接真实内容。
3. G2:导入真实绑定和 ProjectGrant,验证双层权限与撤权。
4. G3:按“只读 → 构建 → discussion → confirmed/恢复”逐批开放工具。
5. G4:安全、凭据轮换、备份和空环境恢复。
6. G5:一个低敏感真实项目试点,以真实用户结果和止损矩阵决定是否扩展。
## 15. 验收标准
### 15.1 产品级必须通过
- 两名用户通过各自 OAuth 连接同一 MCP,身份、项目、token、session、审计不串用。
- 未绑定、内部授权拒绝、Gitea 拒绝、Gitea 不可用、撤权五类场景全部 fail closed。
- Agent 无法通过工具参数、prompt、伪造 username 或复用 confirmation 提升权限。
- Local Source Gate 只能上传明确选择内容;越界、符号链接、secret/PII、超限和 hash 错误全部阻断。
- discussion/confirmed 均经过 build、validation、diff、确认、CAS、Git、export、index、readback。
- 并发发布不会产生两个 current;失败不会返回伪成功。
- 发布回执、Gitea commit、immutable release、current、search、MCP readback 的 release/hash 完全一致。
- human、agent、service 三主体链完整;审计事件可验证且普通角色无法修改删除。
- 撤权后下一次调用拒绝;备份可在隔离环境恢复并使旧凭据失效。
### 15.2 止损信号
- 出现共享账号、共享 token、绕过 MCP 的业务写入口。
- 出现内部授权或 Gitea 任一层被忽略。
- Agent 能读取未选择本地内容、未授权项目、历史或构建区。
- 出现两个 current、force push、Git 历史删除或无法恢复的备份。
- 审计可被普通运行身份修改/删除,或关键动作在无 `request_received` 情况下执行。
- 为兼容单个 Agent 而取消 OAuth、确认、Local Source Gate 或审计。
命中任一项即停止新增项目和扩大用户范围,先恢复到只读或 `forced_off`
## 16. PRD 追溯矩阵
| 本 PRD 内容 | 上游依据 | 关系 |
|---|---|---|
| 一项目一私仓、唯一 current、发布状态与内容状态 | 原 v1 | 原样继承 |
| MCP 唯一入口、飞书身份、双层权限、三主体审计 | v1.1 覆盖方案 | 差量补充 |
| Agent adapter、Go/PostgreSQL/Gitea/outbox | 技术栈设计 | 实现选择 |
| 成熟授权服务器 | MCP OAuth 安全边界 | 补齐实现责任,不改业务目标 |
| 飞书—Gitea 预配置绑定 | 双层权限的安全开户流程 | 补齐未绑定/冒充路径 |
| `pg_trgm` 中文检索 | “只搜索授权 current”的实现 | 修正中文检索技术选型 |
| Skill Registry 后置 | 当前版本边界 | 明确不纳入 v1.1 |
## 17. 仍需确认的实施参数
这些不是架构问题,也不需要重新生成设计稿;它们按“开始哪一步、确认哪一项”处理。
| Gate | 最迟时间 | 必须提供/决定 | 没有时的处理 |
|---|---|---|---|
| DG-01 主栈 | C1-01 前 | 团队是否能长期维护 Go | 否则暂停并重新评审 TypeScript 主栈,不双栈混用 |
| DG-02 OAuth AS | C1-04 前 | 可复用的成熟 OAuth/OIDC Authorization Server;若无,批准独立产品及责任人 | 不实现真实 token 签发,只保留 fake auth |
| DG-03 Agent 版本 | C1-00 前 | Codex、Claude Code 支持版本与企业配置分发方式 | 只做通用 contract,不声明该 adapter 可用 |
| DG-04 确认服务 | C1-05 前 | 签名算法、密钥托管、TTL、单次消费存储 | A3/A4 工具不注册 |
| DG-05 Local Source Policy | C1-08 前 | 允许根、类型、大小、secret/PII 规则、临时保留 | 使用第 11 节合成测试默认值,不接真实文件 |
| DG-06 飞书 | G0 前 | 自建 App、管理员、redirect domain、tenant、scope | 不连接飞书 |
| DG-07 Gitea | G0 前 | 新建/复用、版本、管理员、权限 API、项目级服务凭据 | 不连接 Gitea |
| DG-08 人和项目 | G2 前 | 试点项目、成员、Publisher、绑定清单、ProjectGrant、治理/审计责任人 | 不导入真实主体和内容 |
| DG-09 环境 | G1 前 | Linux/容器、域名/TLS、PostgreSQL、反向代理、密钥与监控产品 | 不部署 |
| DG-10 治理 | G1/G4 前 | 审计保留、脱敏、RPO/RTO、备份路径、事故联系人 | 不进入真实试点 |
## 18. 评审与下一步
### 18.1 当前可以确认的结论
- PRD、技术方案和闭环流程可以定稿为“review-ready”。
- 当前没有必要重新改写原 v1,也不需要创建新的业务版本。
- 不需要安装新的绘图或文档能力;本 vault 可直接承载 Markdown PRD 与 Obsidian Canvas。
- 当前不部署、不运行、不连接飞书/Gitea/服务器、不创建代码仓库。
### 18.2 下一条授权应如何表述
若要进入代码阶段,可明确下达:
> 进入 Gitea 知识库 v1.1 的 C1 代码开发,只使用 fake Feishu/Gitea、合成身份和本地临时 PostgreSQL;先执行 C1-00C1-03,不连接真实环境、不部署。
若要进入真实实施,必须在 C1 制品通过验收后,再按第 17 节补齐对应参数并单独授权 G0/G1,不能从“文档完成”直接跳到生产部署。