--- 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 adapter:Codex、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 Code+PKCE | | 数据库 | 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` AST+JSON 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 Code+PKCE → 授权服务器 → 飞书 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 | 不能复用、转让或跨 hash;Agent 原生 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 decision+policy evidence | 任一条件失败即 denied;不以工具参数覆盖主体 | | S18 Worker 领取 | `contextd worker` | `FOR UPDATE SKIP LOCKED` claim outbox;idempotency 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_id+release_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/session;OAuth 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_key+open_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` 使用同一 pipeline;confirmed 需要更高权限/确认,但不复制另一套写入逻辑。 - 提交必须引用 `candidate_hash+base_current+confirmation_id+idempotency_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 key;current 已变化返回 `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 小时内返回同一 release;payload 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 completed:p95 ≤ 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-01~03 | 工程、契约、领域、DB | Go module、contracts、migration、sqlc、测试夹具 | 离线 build/test,状态/约束/最小 DB role 通过 | | C1-04~06 | OAuth、绑定、双层授权、MCP、审计 | authorization server 集成、Feishu/Gitea fake、middleware、outbox | 冒充、未绑定、撤权、审计中断用例均 fail closed | | C1-07~08 | current 读取、中文搜索、Local Source Gate、build/validate | 第一/二批 MCP tools、`pg_trgm` benchmark、scanner | 跨项目、历史、越界路径、secret/PII、超限均阻断 | | C1-09~10 | 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-00~C1-03,不连接真实环境、不部署。 若要进入真实实施,必须在 C1 制品通过验收后,再按第 17 节补齐对应参数并单独授权 G0/G1,不能从“文档完成”直接跳到生产部署。