# PJ2026-03 PikaOA 企业办公平台总规格

## 修改历史

| 版本 | 对应 commit id | 更新日期 | 变更说明 |
| --- | --- | --- | --- |
| v0.1 | 待本版本提交 | 2026-07-13 | 创建企业办公平台预期终态、模块架构和首批合同与发票能力规格。 |
| v0.2 | 待本版本提交 | 2026-07-14 | 统一平级 REST 资源、UUIDv7 全局标识和仅通过 typed ID 建立对象关联的契约。 |
| v0.3 | 待本版本提交 | 2026-07-14 | 将审计语义校验收敛为非阻塞 warning 和最小安全归一化，避免开发期复杂审计门禁阻塞业务。 |
| v0.4 | 待本版本提交 | 2026-07-14 | 允许 Web 与后端并行开发，最终以同一公开 HTTP API 和 CLI/Web 等价业务流完成集成验收。 |
| v0.5 | 待本版本提交 | 2026-07-14 | 增加不经过 CI/CD 的 YAML-first 专用测试集群临时运行面，并与正式自动交付严格隔离。 |
| v0.6 | 待本版本提交 | 2026-07-15 | 将测试运行面收敛到现有 NC01 k3s 的独立 namespace，复用 PK01 host PostgreSQL 的独立测试库和角色，并增加 hostIP 暴露与测试自动交付契约。 |
| v0.7 | 待本版本提交 | 2026-07-16 | 增加合同与发票 PDF 导入预览、自动字段提取、人工校对、typed ID 附件关联和 YAML 分发的 CLI 管理 token，并将数据库与公网入口收敛到 NC01。 |
| v0.8 | 待本版本提交 | 2026-07-16 | 退役临时测试运行面，将产品 `master` 收敛为 NC01 稳定开发 namespace 的自动交付，并保留 `release` 独立生产交付。 |
| v0.9 | 待本版本提交 | 2026-07-17 | 将后台执行权威收敛到 Temporal，增加共享 application dispatcher、CLI local/`--over-api` 双模式及 API、Worker、Web HMR 独立 native 开发闭环。 |

修改历史只记录规格语义变更，不记录实现进度、阶段基线或一次性证据。

## 正文

## PJ2026-03 PikaOA 企业办公平台总项目需求规格

## 1. 文档控制

| 字段 | 内容 |
| --- | --- |
| 编号 | PJ2026-03 |
| 短名 | PikaOA |
| 层级 | L0 总项目 |
| 规格状态 | 已生效 |
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
| 规格治理索引 | 本文第 9 章 |
| 实现引用版本 | v0.9 |

本文采用 ISO/IEC/IEEE 29148 需求规格模板的项目裁剪版。

本文只定义：

- 企业办公平台的预期终态；
- 稳定业务边界；
- 可扩展模块架构；
- 首批合同与发票能力；
- 可重复执行的验收契约。

当前实现状态、阶段差距、提交、PR、作业、日志和截图进入阶段报告、任务报告或 GitHub issue，不进入本规格正文。

## 2. 目的和范围

### 2.1 项目使命

PikaOA 的使命是为公司提供长期演进的企业办公平台：

- 统一承载员工、组织、业务伙伴、文档、流程、审计和业务模块；
- 让合同、发票等首批模块形成可追溯、可检索、可关联的业务事实；
- 让后续审批、采购、报销、项目、人事、资产和知识管理模块复用同一平台能力；
- 通过稳定模块边界避免每增加一个功能就复制账号、权限、审计、附件和部署逻辑；
- 在 Kubernetes 中以可审计、可重复、自动交付的方式运行。

### 2.2 预期终态

PikaOA 终态必须同时具备：

- 企业平台内核：
  - 统一员工身份、组织成员、角色、权限和会话；
  - 统一业务伙伴、分类、标签、联系人和归档状态；
  - 统一附件、审计、模块注册、搜索和分页契约；
  - 统一 API 错误、字段校验和幂等写入语义；
  - 统一持久化 REST 资源的 UUIDv7 全局标识和 typed ID 关联语义。
- CLI-first 交付：
  - 每个后端业务用例先提供稳定 CLI 入口；
  - 所有已启用模块的管理与业务功能必须通过共享 application dispatcher 提供 CLI 等价入口；
  - CLI 默认在本地组装 dispatcher、repository 和 Temporal client，显式 `--over-api` 才通过公开 HTTP API 调用同一 dispatcher；
  - 受控管理 CLI 优先读取由 owning YAML 分发的 `OA_ADMIN_TOKEN`，不得把 token 写入命令参数、日志或会话文件；
  - CLI local、CLI `--over-api`、Web 与 API 复用同一身份、权限、应用用例和业务语义；
  - Web 与后端可以依据已冻结的资源和 API 契约并行开发；
  - 最终集成验收先以 CLI 证明后端业务语义，再由 Web 通过同一公开 HTTP API 重复等价业务流；
  - 自动化和人工排障不依赖浏览器才能完成核心业务闭环。
- 可扩展业务模块：
  - 每个模块拥有独立领域模型、应用服务、持久化迁移、权限声明、HTTP API 和前端路由；
  - 模块通过稳定端口、领域事件和对象引用协作；
  - 新模块不得复制用户、组织、业务伙伴、审计或附件真相；
  - 成熟模块可以沿既有端口从业务 API 中提取为独立微服务。
- 首批可用能力：
  - 合同管理支持多版本、当前版本、版本历史和关联业务伙伴；
  - 发票管理支持合同关联、合同版本关联、正常与废弃状态以及废弃原因；
  - 员工管理支持管理员和普通员工两类初始角色；
  - 按不同甲方及其分类筛选合同、发票和统计摘要。
- 企业交付能力：
  - Web、业务 API 和异步 Worker 是可独立扩缩和发布的工作负载；
  - Temporal 是后台、可重试和长时执行的唯一编排权威，Worker 只注册 workflow/activity 并消费 owning task queue；
  - PostgreSQL 是业务数据真相；
  - 文件内容通过可替换存储端口管理，元数据与哈希进入业务数据；
  - 配置、Secret、数据库绑定、运行目标和公网暴露均由 owning YAML 管理；
  - 产品 `master` 合并自动交付到 NC01 稳定开发 namespace；
  - 产品 `release` 合并自动交付到独立生产 namespace；
  - development 与 production 分别拥有独立 PostgreSQL database/role、Secret、附件存储、GitOps branch、Argo Application 和公网 HTTPS 入口；
  - 临时测试 namespace、单步测试部署入口和 test 命名控制面不作为长期交付路径。
- 首版可观测能力：
  - Web、CLI、API、Worker 和 CI/CD 统一传播 W3C trace context；
  - Go 服务从第一版接入 OpenTelemetry traces、metrics 和结构化日志关联；
  - Prometheus 从第一版采集服务、HTTP、数据库、领域用例、outbox 和运行时指标；
  - trace、metric 和日志均携带稳定 service、module、operation 和结果属性；
  - 可观测后端不可用时形成显式非阻塞 warning，不阻塞已经成功的用户业务。

### 2.3 范围内

- 员工账户、启停、角色、权限和登录会话。
- 业务伙伴、甲方分类、联系人、标签和归档。
- 合同主记录、多版本、附件、状态、检索和关联。
- 发票主记录、合同/版本关联、附件、废弃标记和检索。
- 合同与发票 PDF 导入预览、可替换文本提取器、可编辑校对草稿和确认后附件关联。
- 审计记录、领域事件、模块注册和模块级导航。
- CLI、Web 工作台、HTTP API、健康接口和异步任务入口。
- Temporal workflow/activity、native API/Worker/Web HMR 生命周期与 local/`--over-api` 等价验证入口。
- OpenTelemetry Collector 接入、Prometheus 指标、结构化日志和 trace/metric 关联。
- PostgreSQL、Kubernetes namespace、Secret、CI/CD、GitOps 和公网 HTTPS。
- 现有 NC01 k3s 中相互隔离的 development 与 production namespace、NC01 host PostgreSQL 独立数据库、YAML-first 自动交付、公网 HTTPS 和可观测性入口。

### 2.4 范围外

- 首期自动签章、电子税务局直连、付款和银行流水对账。
- 对任意扫描版式保证无人工校对的 OCR 准确率；OCR provider 不可用或置信度不足时必须保留可用的人工校对流程。
- 首期通用 BPMN 设计器、复杂会签、组织同步和单点登录。
- 用合同版本覆盖历史版本或物理删除已废弃发票。
- 为每个业务模块部署独立身份系统、独立业务伙伴表或独立审计实现。
- 把运行面 Secret、Pod 环境变量或数据库现状反向保存为配置真相。
- 未经后续规格确认的租约、选主、分布式事务协调器或第二权限体系。

## 3. 术语表

| 术语 | 定义 |
| --- | --- |
| 员工 | 可以登录 PikaOA 并按角色执行操作的公司成员。 |
| 管理员 | 可以管理员工、角色、业务伙伴分类和全部首批业务模块的员工角色。 |
| 普通员工 | 可以使用被授予模块能力但不能管理系统身份与权限的员工角色。 |
| 业务伙伴 | 与公司发生业务关系的外部组织或个人；甲方是业务伙伴的一种业务角色。 |
| 甲方分类 | 用于组织、筛选和汇总甲方的可维护分类。 |
| 合同主记录 | 表示一份合同长期身份、甲方、编号、状态和当前版本 ID 指针的独立业务资源。 |
| 合同版本 | 具有全局唯一 ID 的独立业务资源，通过合同 ID 和前一版本 ID 建立关联，并具有合同内单调递增的版本号。 |
| 当前版本 | 合同主记录明确指向、供默认查询和新关联使用的合同版本。 |
| 发票废弃 | 保留发票记录并记录废弃人、时间和原因，使其不再计入有效业务结果。 |
| Typed ID 关联 | 资源只保存关联对象的资源类型和全局唯一 ID，不复制关联对象私有载荷，也不以嵌套路径或表级从属关系定义资源身份。 |
| 模块 | 具有独立领域边界、权限、迁移、API、事件和前端入口的可插拔业务能力。 |
| 领域事件 | 模块完成业务事务后写入的结构化事实，用于同进程订阅或异步扩展。 |
| 开发运行面 | 与 production namespace 隔离，由产品 `master` 合并自动驱动 PaC、Tekton、GitOps 和 Argo 收敛的长期 API、Worker、Web、附件与数据运行面。 |
| 导入预览 | 对上传 PDF 执行有界文本提取和字段解析后返回的非持久化、可编辑草稿；预览不是合同、合同版本、发票或附件业务事实。 |
| 提取器 | 通过稳定端口读取 PDF 并返回文本、页数、方法和置信度的可替换实现；首选原生文本，OCR 作为可选 provider。 |

## 4. 系统边界和内部模块

### 4.1 外部边界

| 边界项 | 内容 |
| --- | --- |
| 外部使用者 | 管理员、普通员工和经批准的自动化调用方。 |
| 外部输入 | 登录凭据、员工信息、业务伙伴信息、合同版本、发票信息、PDF、附件和筛选条件。 |
| 受控资源 | 员工身份、业务伙伴、合同、发票、附件、审计记录、数据库和运行配置。 |
| 外部输出 | 工作台、列表、详情、版本历史、关联结果、状态、审计和健康摘要。 |
| 用户接口 | CLI、响应式 Web 与版本化 HTTP API。 |
| 系统边界 | PikaOA 管理内部办公业务事实；不替代税务、签章、银行和外部身份平台。 |

### 4.2 L1 能力域

| 编号 | 短名 | 主责边界 | 下游支撑 |
| --- | --- | --- | --- |
| PJ2026-0301 | 组织权限 | 员工、角色、权限、会话和模块授权。 | 全部业务模块。 |
| PJ2026-0302 | 伙伴主数据 | 业务伙伴、甲方角色、分类、联系人和标签。 | 合同、发票及后续业务模块。 |
| PJ2026-0303 | 合同管理 | 合同身份、多版本、当前版本、PDF 导入校对、状态、附件和历史。 | 发票、审批、项目和归档。 |
| PJ2026-0304 | 发票管理 | 发票、PDF 导入校对、合同关联、合同版本关联、废弃和附件。 | 财务、报销、对账和统计。 |
| PJ2026-0305 | 平台内核 | 模块注册、审计、领域事件、附件端口、文档提取器端口、搜索和 API 规范。 | 全部业务模块和自动化。 |
| PJ2026-0306 | 平台交付 | Web/API/Worker 运行、数据库、Secret、CI/CD、GitOps 和公网入口。 | 全部产品能力。 |

### 4.3 模块接入合同

每个业务模块必须声明：

- 唯一模块标识、显示名称和生命周期状态；
- 领域实体、应用用例、数据库迁移和对象引用类型；
- 权限集合及其管理员、普通员工默认授权映射；
- 版本化 HTTP 路由、OpenAPI 描述和稳定错误码；
- 领域事件名称、版本和最小载荷；
- 前端路由、导航项、权限要求和列表/详情入口；
- 审计动作、资源类型和可安全披露的变更摘要；
- 健康、迁移和部署后验证入口。

所有持久化 REST 资源必须遵循统一对象契约：

- 由服务端生成不可变 UUIDv7，业务编号、名称、版本号和外部标识不得充当资源主键；
- 伙伴、合同、合同版本、发票和附件等资源在 REST、领域模型和存储层均保持平级身份；
- 关联只使用 typed ID 字段或显式关联记录，不使用嵌套 REST 路径、级联从属对象或复制载荷形成第二关系真相；
- 删除、归档、废弃或改名不得改变其他资源的 ID，也不得使历史关联失效。

新增模块不得通过修改其他模块私有表完成集成。跨模块读取使用应用端口或稳定对象引用；异步扩展使用事务内写入的领域事件/outbox，不新增第二业务真相。

## 5. 目标架构和数据流

### 5.1 目标架构图

```mermaid
flowchart LR
  U[管理员与员工] --> W[Vue Web 工作台]
  U --> CLI[PikaOA CLI]
  W --> A[Go 业务 API]
  CLI -->|local| D[Application Dispatcher]
  CLI -->|--over-api| A
  A --> D
  D --> I[组织权限模块]
  D --> P[伙伴主数据模块]
  D --> C[合同模块]
  D --> F[发票模块]
  D --> DI[文档导入预览]
  D --> K[平台内核]
  I --> DB[(PostgreSQL)]
  P --> DB
  C --> DB
  F --> DB
  DI --> EX[PDF 文本提取器端口]
  EX --> NT[原生文本提取器]
  EX -. 可选 .-> OCR[OCR provider]
  K --> DB
  D --> S[文件存储端口]
  D --> O[(事务 Outbox)]
  D --> T[Temporal Frontend]
  T --> J[Go Temporal Worker]
  J --> O
  J --> X[后续通知、索引与集成适配器]
  W --> OT[OpenTelemetry Collector]
  CLI --> OT
  A --> OT
  J --> OT
  A --> PM[Prometheus metrics]
  J --> PM
  PM --> PR[Prometheus]
  OT --> TB[Trace backend]
```

部署单元采用三类独立工作负载：

- Web：使用与 HWLAB v0.3 同族的 Vue 3、Vite、TypeScript、Vue Router、Pinia 和 Tailwind 技术栈；
- API：使用成熟 Go HTTP/服务框架、PostgreSQL 驱动、迁移工具、RBAC 库和 OpenAPI 工具；
- Worker：复用 Go 领域与应用层，注册 Temporal workflow/activity，消费 owning task queue 并承载非请求内任务。

CLI 是后端业务的第一用户入口：

- 默认本地模式通过共享 composition root 直接调用 application dispatcher，不依赖 API 进程；
- 显式 `--over-api` 通过与 Web 相同的公开 HTTP API 调用同一 dispatcher；
- local 与 `--over-api` 只能切换 transport，不得复制 repository、领域规则、权限或输出格式；
- 默认输出适合人工扫描的紧凑文本，机器调用显式请求 JSON；
- 长任务使用提交与短轮询，不保持无界阻塞连接；
- 输出包含请求标识和 traceId，但不显示密码、token、完整数据库连接串或附件正文；
- Web 可以与 CLI 和后端并行开发，尚未完成的后端集成差异集中在 API client 适配层并形成非阻塞 warning；
- 对应业务能力只有在 CLI 后端验收通过，且 Web 通过同一公开 HTTP API 完成等价业务流后，才能完成最终验收。

业务 API 在首期采用模块化单体内核：

- 保持单事务、单数据库和低运维复杂度；
- 模块边界与端口从第一版生效；
- Web、API 和 Worker 已是独立工作负载；
- 当容量、团队或故障域需要时，单个模块可以沿既有 API、事件和数据所有权边界提取为独立微服务。

### 5.2 业务数据流

```mermaid
flowchart TD
  R[用户请求] --> G[认证、授权与输入校验]
  G --> AD[Application Dispatcher]
  AD --> M[目标模块应用用例]
  M --> T[领域规则与事务]
  T --> DB[(模块拥有的数据表)]
  T --> A[(统一审计记录)]
  T --> O[(事务 Outbox)]
  DB --> Q[查询投影与分页]
  Q --> V[Web/API 响应]
  O --> C[Temporal Client]
  C --> W[Temporal Workflow]
  W --> A2[Activity]
  A2 --> E[扩展适配器]
```

### 5.3 合同多版本时序

```mermaid
sequenceDiagram
  participant U as 员工
  participant W as Web
  participant A as 合同应用服务
  participant D as PostgreSQL
  U->>W: 新建合同或创建新版本
  W->>A: 提交合同身份、甲方和版本内容
  A->>D: 校验权限、甲方和合同内版本号
  A->>D: 事务写入不可变版本、更新当前版本指针和审计/outbox
  D-->>A: 返回合同与新版本
  A-->>W: 返回当前版本和完整版本摘要
  W-->>U: 展示详情与版本历史
```

### 5.4 发票废弃与合同关联时序

```mermaid
sequenceDiagram
  participant U as 员工
  participant W as Web
  participant A as 发票应用服务
  participant D as PostgreSQL
  U->>W: 登记发票并选择合同/版本
  W->>A: 提交发票与关联标识
  A->>D: 校验合同、版本、甲方一致性并写入发票
  D-->>A: 返回有效发票
  U->>W: 标记发票废弃并填写原因
  W->>A: 提交废弃动作
  A->>D: 原子写入废弃人、时间、原因和审计/outbox
  D-->>A: 返回保留的废弃发票
  A-->>W: 展示废弃标识且默认排除有效统计
```

### 5.5 PDF 导入、校对与附件关联时序

```mermaid
sequenceDiagram
  participant U as 员工
  participant C as CLI 或 Web
  participant I as 导入预览 API
  participant E as 提取器端口
  participant B as 合同或发票 API
  participant A as 附件 API
  U->>C: 选择合同或发票 PDF
  C->>I: multipart PDF 与 documentType
  I->>E: 原生文本提取，必要时尝试 OCR provider
  E-->>I: 文本、页数、方法与置信度
  I-->>C: 可编辑字段、伙伴候选、warning 与 manualReviewRequired
  U->>C: 校对并修改字段
  C->>B: 使用现有 create API 确认业务对象
  B-->>C: 返回合同版本 ID 或发票 ID
  C->>A: 上传原 PDF 并通过 objectType/objectId 关联
  A-->>C: 返回独立 attachmentId 与 referenceId
  C-->>U: 展示业务对象及 PDF 附件
```

导入预览不得持久化 PDF、提取文本或业务字段。只有用户校对确认后，客户端才调用现有业务创建 API；业务对象创建成功后，原 PDF 通过附件 API 生成独立附件资源，并通过 `contract-version` 或 `invoice` typed ID 关联。数字原生 PDF 由原生文本提取器处理；扫描 PDF 在 OCR provider 可用时尝试 OCR，否则返回 `manual_review_required`、`blocking=false`，同时保留空白或部分预填草稿供用户完成校对。

### 5.6 Development 与 production 自动交付数据流

```mermaid
flowchart LR
  M[产品 master 合并] --> DC[Development PaC 与 Tekton]
  DC --> DG[Development GitOps 与 Argo]
  DG --> DN[NC01 PikaOA development namespace]
  DN --> DD[(NC01 host PostgreSQL development database)]
  DN --> DE[oa-dev.hwpod.com]
  R[产品 release 合并] --> PC[Production PaC 与 Tekton]
  PC --> PG[Production GitOps 与 Argo]
  PG --> PN[NC01 PikaOA production namespace]
  PN --> PD[(NC01 host PostgreSQL production database)]
  PN --> PE[oa.hwpod.com]
  DN --> O[OTel 与 Prometheus]
  PN --> O
```

Development 与 production 是职责隔离的两条长期自动交付路径。`master` 只能更新 development consumer、GitOps branch、Argo Application、namespace、数据库、Secret、附件存储和 `oa-dev.hwpod.com`；`release` 只能更新对应 production 对象和 `oa.hwpod.com`。两条路径共享模块架构与通用 renderer，但不共享可变数据或运行对象。临时 test target、手工 PipelineRun、人工 Argo sync 和第二 source authority 不属于目标数据流。

### 5.7 Native-first 开发数据流

```mermaid
flowchart LR
  C[PikaOA CLI] -->|默认 local| D[Application Dispatcher]
  C -->|--over-api| A[Native API]
  A --> D
  D --> P[(NC01 host PostgreSQL)]
  D --> T[Temporal Frontend]
  T --> WK[Native Temporal Worker]
  WK --> P
  V[Vite HMR Web] --> A
  S[Native Smoke] --> C
  S --> V
  M[产品 master PR merge] --> CI[PaC/Tekton/GitOps/Argo]
```

Native 开发必须先于正式交付完成短反馈闭环：

- API、Temporal worker 和 Vite HMR Web 使用独立进程、PID、日志、端口、健康状态和停止入口；
- CLI local 不依赖 API 进程，但使用与 API 相同的 composition root、dispatcher、repository 和授权语义；
- `--over-api` 只替换 transport，不改变命令、输入、输出、错误或业务事务语义；
- native worker 和 API 只连接 owning YAML 选择的真实 PostgreSQL、Temporal 和可观测基础设施，不建立临时数据库或第二编排服务；
- native smoke 依次验证 local CLI、Temporal workflow/activity、独立 API + `--over-api` 和 Web HMR；
- native 验收完成后只合并一次产品 PR，由正常 `master` 自动链完成 development 交付，不用反复 rollout 代替本地迭代。

## 6. 全局原子需求

### 6.1 PIKAOA-L0-REQ-001 模块化平台内核

PikaOA 必须以第 4.3 节的模块接入合同组织业务能力。模块必须拥有清晰数据所有权，复用统一身份、伙伴、附件、审计和事件能力，并能在不改写既有模块私有实现的情况下增加导航、权限、API、迁移和事件订阅。

接受标准包括：

- 模块注册表可以枚举已启用模块及其权限和前端入口；
- 一个示例新增模块可以只通过自身声明与公共端口接入；
- 禁止跨模块直接更新私有表；
- API 与领域事件具有显式版本。

### 6.2 PIKAOA-L0-REQ-002 员工与权限

系统必须支持员工的创建、编辑、启用、停用、角色分配和登录。管理员与普通员工的初始账号由 owning YAML 的 Secret `sourceRef`/`targetKey` 注入，不在 Git、镜像、日志或前端代码中保存密码。

系统还必须支持 owning YAML 分发的 `OA_ADMIN_TOKEN` 作为 CLI 管理凭据：

- API 使用常量时间比较验证 token，并把它映射到现有管理员员工与管理员角色；
- token 不创建第二身份、第二角色或第二权限真相，全部授权继续复用现有 capability；
- token 轮换只由 owning YAML 的 Secret `sourceRef`/`targetKey` 和受控部署完成；
- CLI 只从进程环境读取 `OA_ADMIN_TOKEN`，不提供明文命令行 flag，不把值持久化到 session 文件；
- 未配置 token 时仍可使用现有用户名/密码登录和短期 session，不得生成静默默认 token。

接受标准包括：

- 管理员可以管理员工和角色；
- 普通员工不能管理员工、角色或 Secret；
- 停用员工不能建立新会话；
- 所有业务写入记录实际员工身份。
- `OA_ADMIN_TOKEN` 调用的写入记录被映射管理员员工身份，审计、trace 和 metric 不记录 token 或其摘要。

### 6.3 PIKAOA-L0-REQ-003 业务伙伴和甲方分类

系统必须维护业务伙伴的唯一身份、名称、统一社会信用代码或其他外部标识、角色、分类、标签、联系人、备注和归档状态。合同与发票通过稳定标识关联甲方，不复制甲方名称作为关系真相。

接受标准包括：

- 管理员可以维护甲方分类；
- 员工可以按甲方、分类、标签和归档状态筛选；
- 同一甲方的合同与发票可以从伙伴详情统一查看；
- 甲方改名不破坏历史关联。

### 6.4 PIKAOA-L0-REQ-004 合同多版本

- 每份合同和每个合同版本都是具有独立 UUIDv7 的平级 REST 资源；
- 合同版本通过 `contractId` 关联合同，并通过可选 `previousVersionId` 关联前一版本；
- 合同通过 `currentVersionId` 关联当前版本；
- 合同内版本号单调递增，但版本号不得充当资源主键；
- 创建新版本必须保留旧版本、更新当前版本 ID 指针并记录变更说明、操作者和时间。

每个版本至少包含：

- 版本号和版本说明；
- 合同标题、合同编号和甲方引用；
- 签署日期、生效日期、到期日期和币种；
- 金额、摘要、状态和附件引用；
- 创建人、创建时间和内容哈希。

接受标准包括：

- 详情默认显示当前版本并可查看全部历史版本；
- 任一版本可以通过 `/api/v1/contract-versions/{id}` 独立读取，版本关系只由 ID 字段表达；
- 历史版本不可被当前编辑覆盖；
- 并发创建相同下一版本时只能有一个事务成功；
- 合同可以按甲方、分类、编号、状态和日期筛选。

### 6.5 PIKAOA-L0-REQ-005 发票管理和废弃

- 发票是具有独立 UUIDv7 的平级 REST 资源；
- 发票通过 `partnerId`、可选 `contractId` 和可选 `contractVersionId` 建立关联；
- 发票必须支持号码、类型、开票日期、金额、税额、价税合计和币种；
- 发票不得物理删除；
- 废弃动作必须保留原记录，并记录废弃人、废弃时间和非空原因。

接受标准包括：

- 发票可以关联合同主记录与具体合同版本；
- 关联版本必须属于所选合同；
- 发票甲方与合同甲方不一致时返回明确校验错误；
- 默认有效列表和汇总排除废弃发票；
- 用户可以显式筛选全部、有效或废弃发票。

### 6.6 PIKAOA-L0-REQ-006 附件完整性

- 附件是具有独立 UUIDv7 的平级 REST 资源；
- 合同版本和发票通过显式 typed ID 关联记录引用附件，不把附件作为嵌套从属对象；
- 附件元数据必须记录原文件名、媒体类型、字节数、内容哈希、存储键、上传人和上传时间；
- 存储实现通过端口替换，业务表不保存宿主绝对路径。

接受标准包括：

- 上传、下载和详情读取均执行权限检查；
- 相同对象的附件可独立增删，不改写历史合同版本内容；
- 内容哈希与下载内容一致；
- 文件存储不可用时不生成成功业务引用。

### 6.7 PIKAOA-L0-REQ-007 审计和领域事件

所有身份、伙伴、合同、版本、发票和模块配置写入必须生成不可变审计记录。需要异步扩展的业务事实必须在同一数据库事务中写入 outbox；Worker 只消费已提交事件，不反向成为业务真相。

首期审计校验采用最小、非阻塞语义：

- 缺失可补足字段、格式偏差或安全摘要校验只产生低基数 `warning`，不得单独改变成功业务终态；
- 可安全解释的问题使用稳定 system identity、默认时间或省略摘要完成最小归一化，不建立复杂策略引擎或额外状态；
- 发现疑似 Secret、密码、会话、token 或附件正文时直接删除或替换对应摘要，不允许以 warning 为由披露敏感值；
- PostgreSQL 持久化、事务和 outbox 的真实故障仍按现有一致性契约处理，不把基础设施失败伪装成校验 warning。

接受标准包括：

- 审计记录包含员工、动作、资源类型、资源标识、时间和安全摘要；
- Secret、密码、会话和附件正文不进入审计；
- 业务写入不因审计字段完整性、格式或安全摘要校验 warning 而失败；
- 事务回滚时审计和 outbox 同时回滚；
- Worker 重试不重复改变业务主记录。

### 6.8 PIKAOA-L0-REQ-008 企业工作台

Web 必须是高密度、可持续使用的办公工作台。首屏直接显示导航、筛选、列表、状态和主要动作，不使用营销式落地页。合同、发票、伙伴和员工页面必须具备分页、空态、加载态、错误态、权限态、创建/编辑表单和详情深链。

接受标准包括：

- 桌面与移动视口无控件重叠或不可达操作；
- 列表筛选和详情选择进入 URL 并可刷新恢复；
- 版本历史、废弃标识和甲方分类可直接扫描；
- 图标按钮有可访问名称和工具提示。

### 6.9 PIKAOA-L0-REQ-009 正式自动交付和配置真相

PikaOA 必须运行在独立 Kubernetes namespace。目标、namespace、镜像、数据库引用、Secret、资源、探针、持久卷、公网域名和 CI/CD 参数均由 owning YAML 声明；代码只校验和渲染。

GitHub 目标分支合并必须自动驱动 Gitea 受控镜像、不可变快照、Pipelines-as-Code、Tekton、GitOps、Argo 和运行面收敛。首次 bootstrap 只初始化空镜像仓库和控制面，不得同步业务分支或人工创建 PipelineRun。

接受标准包括：

- Web、API 和 Worker 在同一独立 namespace 内运行；
- API 与 Worker 使用独立 Deployment、Service/健康端点、资源和 rollout；Worker 不提供公网业务入口；
- `master` 与 `release` 分别只更新 development 与 production namespace；
- API 直接连接 YAML 声明的 host PostgreSQL；
- API 与 Worker 通过 YAML 声明的 Temporal serviceRef、logical namespace 和 task queue 协作；
- 运行面 Secret 只显示对象、key、presence 和 fingerprint；
- 健康接口证明进程、数据库和迁移状态；
- 公网 HTTPS 入口通过 YAML 声明的 NC01 edge 暴露。

### 6.10 PIKAOA-L0-REQ-010 OpenTelemetry 与 Prometheus

PikaOA 必须从首版提供 OpenTelemetry 与 Prometheus 可观测性，而不是在业务上线后补接。

OpenTelemetry 必须覆盖：

- Web 和 CLI 发起请求时生成或传播 W3C `traceparent`/`baggage`；
- API HTTP server/client、认证、授权、领域用例、PDF 提取、PostgreSQL、附件存储和 outbox 写入；
- Worker 消费、重试、处理结果和下游适配器；
- Temporal client、workflow、activity、task queue、workflow/run ID、重试和终态；
- CI/CD 从 source、build、artifact、GitOps 到 runtime health 的同一 trace 上下文；
- 结构化日志中的 traceId、spanId、service、module、operation、result 和稳定错误码。

Prometheus 必须覆盖：

- HTTP 请求量、延迟、状态族和在途请求；
- 登录成功/失败、授权拒绝和会话状态摘要；
- 合同创建、版本创建、发票创建、发票废弃、导入预览和提取结果等领域动作计数与延迟；
- PostgreSQL连接池、查询延迟和迁移状态；
- outbox pending、oldest age、processed、retry 和 failed；
- Temporal workflow/activity started、completed、failed、retry、task queue backlog 和处理耗时；
- Go runtime、进程和健康状态。

可观测属性不得包含密码、token、完整合同正文、附件正文、个人敏感字段或无界业务载荷。甲方、合同、发票和员工只在明确需要下钻时使用不可逆或受权限保护的稳定标识，禁止把高基数自由文本作为 metric label。

接受标准包括：

- 一次 CLI 合同版本操作可以从 CLI requestId/traceId 查询到 API、授权、数据库和审计/outbox span；
- 一次 Worker 处理可以通过同一业务 correlation 与来源事件关联；
- Prometheus 可以抓取 API 与 Worker 的 `/metrics` 并显示上述核心指标；
- 健康状态区分应用 ready、数据库 ready、迁移 ready、OTel exporter warning 和 metrics scrape 状态；
- OTel export 超时或 trace backend 暂时不可用只输出 `warning=true`、`blocking=false`，不改变成功业务事务终态。

### 6.11 PIKAOA-L0-REQ-011 CLI-first 集成验收

每个后端业务能力必须通过 `pikaoa` CLI 验收。所有启用模块的管理动作、业务写入和查询必须由共享 application dispatcher 提供 CLI 等价入口。CLI 默认使用 local transport，显式 `--over-api` 使用公开 HTTP API；两者必须复用同一身份、权限、用例、repository 和错误语义。Web 可以依据冻结的资源与 API 契约并行开发，但最终必须通过同一 HTTP adapter 重复等价业务流。

接受标准包括：

- CLI 支持登录、当前身份、员工管理、伙伴/分类管理、合同 CRUD/版本历史、合同与发票 PDF `import-preview`、发票 CRUD/废弃、附件上传、审计查询和健康/metrics 摘要；
- 默认文本输出有界且非空，显式 JSON 输出为单一合法 JSON；
- local 是默认模式且不要求 API 进程；`--over-api` 只能切换 transport，不能启用另一套业务实现；
- 同一命令在 local 与 `--over-api` 下返回同构资源、warning、requestId/traceId 和 typed error；
- `OA_ADMIN_TOKEN` 存在时 CLI 不要求 session 文件并优先使用该环境凭据；不存在时继续使用显式登录建立的短期 session；
- CLI 帮助、错误、JSON、trace、日志和进程参数不得披露 `OA_ADMIN_TOKEN` 值；
- 业务失败返回稳定非零退出码和 typed error，不以 traceback 或空输出代替；
- CLI 业务成功同时返回资源标识、requestId 和 traceId；
- 前后端开发不互设启动门禁；后端 CLI 尚未通过或 API 尚未收敛时，集成差异只能形成非阻塞 warning，不能宣称对应业务能力已经完成最终验收；
- 最终验收必须依次证明 local CLI、Temporal worker、CLI `--over-api` 和 Web HTTP 业务流，并比对结果。

### 6.12 PIKAOA-L0-REQ-012 非阻塞版本告警

Web、API、Worker 和 CI/CD 必须输出结构化日志、健康状态和 trace 上下文。源码版本、镜像版本和 API 版本漂移只能形成非阻塞 warning，不得阻塞可安全解释的用户业务。

### 6.13 PIKAOA-L0-REQ-013 YAML-first 稳定开发运行面

PikaOA 必须在 NC01 k3s 中维护与 production 隔离的稳定 development 运行面。Development 只由产品 `master` 合并驱动自动 CI/CD、GitOps 和 Argo 收敛，不保留临时 test target、单步直写部署或第二 source authority。

Development target 必须由 owning YAML 声明：

- 节点、route、固定 development namespace 和独立附件存储；
- 源码仓库、`master` branch、不可变 source snapshot 和 commit-pinned API、Worker、Web、迁移镜像；
- NC01 host PostgreSQL 中独立 development database、role、Secret export 和受控连接来源；
- 健康探针、OTel endpoint、Prometheus 抓取和 Web 工作负载；
- Temporal serviceRef、logical namespace、task queue、workflow/activity 超时与重试，以及 API/Worker 独立健康探针；
- 独立 GitOps branch、Argo Application、PaC consumer、ServiceAccount 和 Secret；
- `oa-dev.hwpod.com` 公网 HTTPS exposure 及共享 public-edge 引用；
- production namespace、数据库、Secret、GitOps branch、Argo Application 和公网入口保护边界。

接受标准包括：

- 产品 `master` 合并产生唯一正常 webhook、PaC、Tekton、GitOps 和 Argo 自动事件；
- initializer 在 API、Worker 和 Web rollout 前初始化 development database；
- API、Worker、Web、附件 PVC、外部 development PostgreSQL、OTel、Prometheus 和 `oa-dev.hwpod.com` 均可通过受控状态或原入口验收；
- development 运行面不读取或修改 production 数据库凭据、Secret、附件、namespace、GitOps branch、Argo Application或公网入口；
- 旧 test namespace 和控制面对象只在 development 自动链健康后受控退役，旧数据直接丢弃且不迁移；
- 配置一致性、版本漂移和 OTel exporter 失败只产生 `blocking=false` warning，Secret 缺失或 mutation target 不安全仍在写入前失败。

### 6.14 PIKAOA-L0-REQ-014 合同与发票 PDF 导入预览

系统必须为合同和发票提供统一 PDF 导入预览能力：

- `POST /api/v1/import-previews` 只接受有界 `multipart/form-data`，包含 `documentType=contract|invoice` 和 PDF `file`；
- preview 响应包含 `documentType`、文件摘要、`extraction`、可编辑 `fields`、`partyCandidates`、`warnings`、`manualReviewRequired`、`requestId` 和 `traceId`；
- 文件摘要只包含原文件名、媒体类型、字节数、SHA-256 和页数，不回显文件正文；
- `extraction` 至少包含稳定 `method`、提取字符数和 `confidence`，方法必须能区分原生 PDF 文本、OCR provider 和无有效文本；
- `fields` 按文档类型返回现有 create API 可接受的合同版本或发票字段，但不生成 `partnerId`、`contractId`、`contractVersionId` 或其他无法从 PDF 证明的关系；
- `partyCandidates` 可以返回买方、卖方、甲方或乙方的名称与税号候选，客户端由用户选择或校对后再解析为已有伙伴 ID；
- preview 是只读计算结果，不写数据库、不创建附件、不生成业务 UUID，也不进入审计或 outbox；
- 原 PDF 只能在用户确认并获得合同版本 ID 或发票 ID 后，通过现有附件 API 生成独立 UUIDv7，并以 typed ID 关联目标对象；
- 原生文本不足、OCR provider 不可用、字段置信度不足或字段冲突只返回 `blocking=false` warning，并将 `manualReviewRequired` 设为 `true`；
- 文件不是 PDF、超过 YAML 声明的大小上限、PDF 损坏或读取失败返回 typed error，不得伪造空成功预览。

接受标准包括：

- 数字原生发票样例可以预填发票号码、开票日期、买卖双方候选、金额、税额、价税合计和币种；
- 扫描合同样例在没有可用 OCR provider 时明确返回 `manual_review_required`，并允许用户手工完成全部必需字段；
- CLI 默认文本输出有界且非空，显式 JSON 输出为单一合法 JSON，不输出提取全文；
- Web 在同一个导入流程中展示文件、提取方式、warning 和可编辑字段，用户确认后创建业务对象并上传 PDF 附件；
- 合同 PDF 关联新建合同的 `contract-version` ID，发票 PDF 关联 `invoice` ID，任何一方都不成为另一方的隶属对象；
- 导入预览 span 和 metric 只使用低基数文档类型、提取方法、结果和 manual-review 属性，不记录 PDF 正文、企业名称、税号或业务号码。

### 6.15 PIKAOA-L0-REQ-015 Temporal 与 native 敏捷开发

PikaOA 的后台、可重试和长时执行必须由 Temporal workflow/activity 承担。PostgreSQL outbox 保留为事务内领域事件事实，但 ticker、定时轮询器或 API 内 goroutine 不得成为正式执行 authority。Worker 必须独立注册 workflow/activity 并消费 owning YAML 声明的 task queue。

Native 开发必须由仓库正式 CLI 提供非阻塞生命周期入口：

- `native start` 分别启动 API、Worker 或 Web HMR，并立即返回稳定 process ID、PID、端口、日志和 status 命令；
- `native status`、`native logs` 和 `native stop` 对每个组件独立工作，不用一个进程的失败覆盖其他组件事实；
- 端口占用、配置缺失、进程退出和依赖不可用必须返回 typed error 与非空有界输出；
- PID、日志和状态只写入 owning YAML 声明的 state 目录，不扫描或终止不属于当前 PikaOA native 实例的进程；
- Vite HMR 通过 native 配置代理 API，不要求先构建 Web 镜像或部署 Kubernetes；
- native 依赖地址、数据库 configRef、Temporal serviceRef、task queue、端口、日志和 state 目录均来自 owning YAML，不使用隐藏默认或环境 fallback。

接受标准包括：

- native worker 消费一个调用至少一个 activity 的真实 workflow，client 校验精确结果并确认 worker 可停止；
- 默认 CLI 在 API 未启动时完成数据库 CRUD 和 workflow smoke；
- 独立 native API 启动后，同一组 CLI 命令增加 `--over-api` 即可通过；
- 独立 Web HMR 启动后，受控 web-probe custom/local smoke 验证真实 DOM、交互和 API 请求；
- native smoke 通过后，正常产品 PR merge 自动交付独立 API/Worker/Web 工作负载，部署态再次通过同一 CLI 与 Web 验收；
- 任务报告记录 native 迭代次数、native 墙钟时间、正式流水线次数、流水线总耗时、交付墙钟时间和 rollout 次数；缺失资源计量时不得虚构成本或提速比例。

## 7. API、数据与兼容边界

- 外部 HTTP API 使用 `/api/v1` 版本前缀。
- REST adapter 只负责 HTTP envelope、鉴权、状态码和 correlation；业务判断全部委派给共享 application dispatcher。
- Temporal workflow/activity 使用稳定版本名和显式 task queue；workflow 参数只传递有界 typed ID、命令和 correlation，不复制无界附件或 Secret。
- 模块路由使用稳定复数资源名和标准分页参数。
- 写请求返回稳定业务错误码、字段路径和可读消息。
- 所有持久化 REST 资源 ID 使用服务端生成、不可枚举、不可变的 UUIDv7。
- 集合和单资源路径使用平级复数资源名，例如 `/api/v1/contracts/{id}`、`/api/v1/contract-versions/{id}` 和 `/api/v1/invoices/{id}`；嵌套路径只可作为有界查询入口，不得成为资源唯一身份。
- `/api/v1/import-previews` 是非持久化计算资源入口，不返回可长期引用的资源 ID；确认创建和附件上传继续使用已有平级资源 API。
- HTTP Bearer 鉴权接受短期 session token 或 YAML 分发的 `OA_ADMIN_TOKEN`；二者都映射到现有员工与 capability 授权，不创建第二权限体系。
- 时间以 UTC 保存并在用户界面按配置时区显示。
- 金额使用定点十进制语义，不使用二进制浮点保存。
- 数据库迁移单向、版本化、可审计；应用启动不静默修改未知结构。
- 跨模块对象引用包含资源类型和 UUIDv7，只建立 ID 关联，不复制私有载荷或形成对象隶属真相。
- 兼容归一化只处理可安全解释的旧字段；不可解释业务数据返回字段级错误。

## 8. 全局验收契约

### 8.1 功能验收

- 先使用 CLI 管理员账号登录，创建普通员工、甲方分类和甲方。
- 在 development 与 production 运行面通过 YAML 分发 `OA_ADMIN_TOKEN`，使用不含 session 文件的 CLI `whoami` 和管理查询证明管理员身份映射与 capability 生效。
- 通过 CLI 创建合同 v1，再创建 v2，确认 v1 保留且 v2 成为当前版本。
- 通过 CLI 在甲方维度查看合同，并按甲方分类筛选合同。
- 通过 CLI 创建关联合同 v2 的发票，确认合同、版本和甲方关系正确。
- 通过 CLI 对数字原生发票 PDF 执行 `import-preview`，校对预填字段后创建发票并把原 PDF 关联到发票 ID。
- 通过 CLI 对扫描合同 PDF 执行 `import-preview`，确认无有效原生文本时返回非阻塞人工校对 warning，手工补齐后创建合同并把原 PDF 关联到合同版本 ID。
- 通过 CLI 标记发票废弃，确认原因和审计存在，默认有效汇总不包含该发票。
- 使用 CLI 普通员工账号确认允许的业务操作可用、管理员操作不可用。
- Web 与后端可以并行实现；每项功能必须先使用 `OA_ADMIN_TOKEN` 完成 local CLI 和 Temporal worker 验收，再用 `--over-api` 与 Web 重复业务主路径并比对结果。

### 8.2 扩展性验收

- 注册一个不修改首批模块私有实现的示例模块；
- 模块声明权限、路由、导航、迁移、审计动作和事件订阅；
- 示例模块可通过公共伙伴引用和领域事件完成集成；
- 禁用模块后，其导航和新请求入口关闭，但历史业务数据不被删除。

### 8.3 运行验收

- CI/CD 绑定 source commit、PipelineRun、镜像 digest、GitOps revision、Argo 状态和运行面 ready；
- 产品 `master` 的正常合并事件只通过 development consumer 自动更新 development namespace；
- 产品 `release` 的正常合并事件只通过 production consumer 自动更新 production namespace；
- development 与 production 的数据库、Secret、附件 PVC、GitOps branch、Argo Application 和公网入口相互隔离；
- Web、API 和 Worker 运行在 owning YAML 声明的 namespace；
- API 与 Temporal Worker 独立 ready，Worker 不提供公网业务 Service；
- PostgreSQL 连接、迁移、附件存储和健康检查通过；
- Temporal logical namespace、task queue、workflow/activity 与 worker readiness 通过；
- OTel Collector 接收 Web/CLI/API/Worker trace，Prometheus 抓取 API/Worker 指标；
- CLI 主路径均返回可查询的 requestId/traceId，并能关联业务审计；
- `https://oa.hwpod.com` 返回登录页和可用业务工作台；
- `https://oa-dev.hwpod.com` 返回当前 `master` 对应的开发工作台；
- 桌面与移动浏览器完成登录、合同 PDF 导入校对、发票 PDF 导入校对、合同版本和发票废弃主路径；
- 运行和验证输出不披露密码、数据库连接串、token 或附件正文。

## 9. 规格治理

- 本规格是 PikaOA L0 长期真相。
- 稳定需求、模块边界、数据流、接口和验收口径变化先更新本规格或对应 L1 规格。
- 实现进度、当前阻塞、提交、PR、PipelineRun、截图和一次性验证进入 GitHub issue、MDTODO 报告和阶段报告。
- 本项目新增或修改的源码文件必须在文件头部或包级文档中标注 `SPEC: PJ2026-03 PikaOA v0.9`；自动生成文件、第三方代码、纯配置、锁文件和二进制产物例外，但其生成器或 owning 配置必须可追溯。
- L1 规格按第 4.2 节编号建立；优先拆分具有独立生命周期、数据所有权或验收入口的能力域。
