From 90e1b4dfb0afb2df6411323e37b02117eecfc92b Mon Sep 17 00:00:00 2001 From: zhi Date: Wed, 18 Mar 2026 02:02:08 +0000 Subject: [PATCH] docs(P12.2-P12.3): add state machine overview, permissions overview, and propose flow documentation --- docs/permissions-overview.md | 90 ++++++++++++++++ docs/propose-flow.md | 163 +++++++++++++++++++++++++++++ docs/state-machine-overview.md | 185 +++++++++++++++++++++++++++++++++ 3 files changed, 438 insertions(+) create mode 100644 docs/permissions-overview.md create mode 100644 docs/propose-flow.md create mode 100644 docs/state-machine-overview.md diff --git a/docs/permissions-overview.md b/docs/permissions-overview.md new file mode 100644 index 0000000..4520f48 --- /dev/null +++ b/docs/permissions-overview.md @@ -0,0 +1,90 @@ +# HarborForge — 权限总览 + +> 更新时间:2026-03-18 +> 本文档列出 milestone-propose 功能新增的所有权限,以及默认角色分配。 + +--- + +## 1. 新增权限一览 + +| 权限名 | Category | 含义 | +|--------------------------|------------|-------------------------------| +| `milestone.freeze` | milestone | 将 milestone 从 open 冻结为 freeze | +| `milestone.start` | milestone | 将 milestone 从 freeze 启动为 undergoing | +| `milestone.close` | milestone | 将 milestone 废弃(close) | +| `task.close` | task | 将 task 废弃(close) | +| `task.reopen_closed` | task | 重新打开已废弃的 task | +| `task.reopen_completed` | task | 重新打开已完成的 task | +| `propose.accept` | propose | 接受 propose 并生成 feature task | +| `propose.reject` | propose | 拒绝 propose | +| `propose.reopen` | propose | 重新打开已拒绝的 propose | + +--- + +## 2. 默认角色权限分配 + +### admin(管理员) + +拥有**所有权限**,包括上述 9 个新权限。通过 `init_admin_role()` 自动同步。 + +### mgr(经理) + +| 权限 | 有 | +|-----------------|----| +| milestone.freeze | ✓ | +| milestone.start | ✓ | +| milestone.close | ✓ | +| task.close | ✓ | +| task.reopen_closed | ✓ | +| task.reopen_completed | ✓ | +| propose.accept | ✓ | +| propose.reject | ✓ | +| propose.reopen | ✓ | + +另含:project.read/write/manage_members, task.create/read/write, milestone.create/read/write, monitor.read + +### dev(开发者) + +| 权限 | 有 | +|-----------------|----| +| milestone.freeze | ✗ | +| milestone.start | ✗ | +| milestone.close | ✗ | +| task.close | ✓ | +| task.reopen_closed | ✓ | +| task.reopen_completed | ✓ | +| propose.accept | ✗ | +| propose.reject | ✗ | +| propose.reopen | ✗ | + +另含:project.read, task.create/read/write, milestone.read, monitor.read + +### guest(访客) + +仅 `*.read` 权限,无新增权限。 + +--- + +## 3. 权限设计原则 + +1. **独立不合并**:`reopen_closed` 和 `reopen_completed` 是两个独立权限,允许不同角色分别控制 +2. **增量同步**:角色种子系统只做"加权限",不删除手动配置的额外权限 +3. **操作者校验**:部分动作除权限外还校验操作者身份 + - `open → undergoing`:操作者必须是 assignee + - `undergoing → completed`:操作者必须是 assignee + 需提交 comment + - `completed` 不走 role 权限控制,而是由 assignee 身份决定 + +--- + +## 4. 前端可见性(当前状态) + +> ⚠ 前端按钮当前对所有项目成员可见,尚未根据用户权限做细粒度隐藏。 +> 权限不足时由后端返回 403 阻止操作。 + +后续可通过前端 permission context 实现按钮可见性控制。 + +--- + +## 5. 自定义角色 + +除默认角色外,管理员可通过 Role Editor 页面自由创建角色并分配上述权限。新增的 9 个权限按 `milestone` / `task` / `propose` 三个 category 分组展示。 diff --git a/docs/propose-flow.md b/docs/propose-flow.md new file mode 100644 index 0000000..64ff0a2 --- /dev/null +++ b/docs/propose-flow.md @@ -0,0 +1,163 @@ +# HarborForge — Propose → Feature Story → Milestone 流程 + +> 更新时间:2026-03-18 +> 本文档描述 feature 进入 milestone 的完整流程。 + +--- + +## 1. 流程总览 + +``` +用户创建 Propose 负责人审阅 系统自动生成 + │ │ │ + ▼ ▼ ▼ + Propose (open) ──accept──▶ Propose (accepted) + │ │ + │ ▼ + │ Feature Story Task (pending) + │ 归属选定 milestone + │ + ──reject──▶ Propose (rejected) + │ + ──reopen──▶ Propose (open) ── 重新审阅 ──▶ ... +``` + +--- + +## 2. 详细步骤 + +### Step 1:创建 Propose + +- 用户在 project 下创建 propose +- 填写 title + description +- 系统自动生成 `propose_code`(格式:`{proj_code}:P{i:05x}`) +- 初始状态:`open` + +### Step 2:审阅 + +- 负责人在 Propose 详情页查看内容 +- `open` 状态下可选操作: + - **Accept** — 接受并生成 feature task + - **Reject** — 拒绝(建议填写 reason) +- Propose 创建者在 `open` 状态下可编辑 title/description + +### Step 3a:Accept + +前置条件: +- 操作者拥有 `propose.accept` 权限 +- 选择一个 `open` 状态的目标 milestone(同 project) + +系统执行: +1. Propose status → `accepted` +2. 在目标 milestone 下自动创建 `story/feature` task + - 继承 title、description、created_by + - 默认状态 `pending` +3. 自动回填 `feat_task_id`(只读字段) +4. 写入 activity log + +Accept 后: +- Propose 详情页显示 "View Generated Task" 跳转按钮 +- Propose 主体不可再编辑 + +### Step 3b:Reject + +前置条件: +- 操作者拥有 `propose.reject` 权限 + +系统执行: +1. Propose status → `rejected` +2. 写入 reject reason(activity log) + +Reject 后: +- Propose 详情页显示 "Reopen" 按钮 +- Propose 主体不可编辑 + +### Step 4:Reopen(可选) + +前置条件: +- 操作者拥有 `propose.reopen` 权限 +- Propose 当前状态为 `rejected` + +系统执行: +1. Propose status → `open`(复用原 propose,不创建新记录) +2. 写入 reopen 记录 + +Reopen 后: +- 可再次编辑 title/description +- 可再次 accept 或 reject + +--- + +## 3. Feature Task 生命周期 + +Accept 生成的 feature story task 遵循标准 task 状态机: + +``` +pending → open → undergoing → completed + │ + (触发 milestone auto-complete + 仅当该 task 是 release task 时) +``` + +关键约束: +- Feature story task **不能**通过通用 create task 页面创建 +- Milestone 进入 `freeze` 后,不再接受新的 feature story +- Milestone 非 `open` 时,已有 feature story task 的 body 字段锁定 + +--- + +## 4. Milestone 完整生命周期(含 propose) + +``` +1. 创建 milestone (open) +2. 通过 propose → accept 添加 feature story tasks +3. 创建 release maintenance task(通过 milestone endpoint) +4. Freeze milestone(需有且仅有 1 个 release task) +5. 满足依赖后 Start milestone → undergoing +6. Tasks 开始执行(pending → open → undergoing → completed) +7. Release maintenance task 完成 → milestone 自动 completed +``` + +--- + +## 5. Propose 编码规则 + +- 格式:`{proj_code}:P{i:05x}` +- 示例:`HF:P00001`, `HF:P00002`, `HF:P0000a` +- 每个 project 独立递增 +- 并发安全:数据库 unique 约束保底 + +--- + +## 6. API 端点 + +| 操作 | 方法 | 路径 | +|---------|--------|--------------------------------------------------| +| 创建 | POST | `/projects/{pid}/proposes` | +| 列表 | GET | `/projects/{pid}/proposes` | +| 详情 | GET | `/projects/{pid}/proposes/{id}` | +| 编辑 | PATCH | `/projects/{pid}/proposes/{id}` | +| Accept | POST | `/projects/{pid}/proposes/{id}/actions/accept` | +| Reject | POST | `/projects/{pid}/proposes/{id}/actions/reject` | +| Reopen | POST | `/projects/{pid}/proposes/{id}/actions/reopen` | + +--- + +## 7. CLI 命令 + +```bash +# 列出 proposes +harborforge proposes --project + +# 创建 propose +harborforge propose-create "My Feature Idea" --project + +# Accept(需指定 milestone) +harborforge propose-accept --project --milestone + +# Reject(可选 reason) +harborforge propose-reject --project --reason "Not in scope" + +# Reopen +harborforge propose-reopen --project +``` diff --git a/docs/state-machine-overview.md b/docs/state-machine-overview.md new file mode 100644 index 0000000..30485ae --- /dev/null +++ b/docs/state-machine-overview.md @@ -0,0 +1,185 @@ +# HarborForge — 状态机总览 + +> 更新时间:2026-03-18 +> 本文档描述 milestone、task、propose 三大实体的状态枚举、流转规则及关键约束。 + +--- + +## 1. Milestone 状态机 + +### 1.1 状态枚举 + +| 状态 | 含义 | 终态 | +|-------------|--------------------------|------| +| `open` | 新建,可接纳 feature | ✗ | +| `freeze` | 范围冻结,准备执行 | ✗ | +| `undergoing`| 正在执行 | ✗ | +| `completed` | 正常完成(自动触发) | ✓ | +| `closed` | 废弃 / 取消 | ✓ | + +### 1.2 状态流转 + +``` +open ──freeze──▶ freeze ──start──▶ undergoing ──(auto)──▶ completed + │ │ │ + └──close──▶ closed ◀──close──┘ ◀──close──┘ +``` + +- **open → freeze**:需有且仅有 1 个 `maintenance/release` task +- **freeze → undergoing**:所有前置依赖(milestone + task)必须已 completed;自动记录 `started_at` +- **undergoing → completed**:唯一的 `release maintenance task` 完成时自动触发 +- **open/freeze/undergoing → closed**:需 `milestone.close` 权限 + +### 1.3 编辑限制 + +| 状态 | 基本信息编辑 | 新增 feature story | 新增其他 task | 删除 milestone | +|-------------|-------------|-------------------|--------------|---------------| +| `open` | ✓ | ✓ | ✓ | ✓ | +| `freeze` | 范围字段锁定 | ✗ | ✓ | ✓ | +| `undergoing`| 范围字段锁定 | ✗ | ✗ | ✗ | +| `completed` | ✗ | ✗ | ✗ | ✗ | +| `closed` | ✗ | ✗ | ✗ | ✗ | + +范围字段 = title, description, due_date, planned_release_date, depend_on_milestones, depend_on_tasks + +--- + +## 2. Task 状态机 + +### 2.1 状态枚举 + +| 状态 | 含义 | 终态 | +|-------------|----------------------|------| +| `pending` | 等待(被 milestone 或依赖锁住) | ✗ | +| `open` | 可开始,尚未开工 | ✗ | +| `undergoing`| 正在处理 | ✗ | +| `completed` | 正常完成 | ✓* | +| `closed` | 废弃 / 取消 | ✓* | + +*支持受控 reopen + +### 2.2 状态流转 + +``` +pending ──open──▶ open ──start──▶ undergoing ──finish──▶ completed + │ │ │ │ + └──close──▶ closed ◀──close──┘ ◀──close──┘ │ + │ │ + └◀────────────── reopen ──────────────────────────────┘ + ▲ + └──────────── reopen ──── completed +``` + +### 2.3 流转条件 + +| 流转 | 条件 | +|------------------------|------------------------------------------------| +| pending → open | milestone 为 undergoing + task depend_on 全部 completed | +| open → undergoing | assignee 非空 + 操作者是 assignee | +| undergoing → completed | 操作者是 assignee + 必须提交 completion comment | +| any → closed | 需 `task.close` 权限 | +| closed → open | 需 `task.reopen_closed` 权限;清除 finished_on | +| completed → open | 需 `task.reopen_completed` 权限;清除 finished_on | + +### 2.4 编辑限制 + +| 状态 | 主体编辑 | +|-------------|-------------------------------| +| `pending` | ✓ | +| `open` (无 assignee) | ✓ (任何项目成员) | +| `open` (有 assignee) | 仅 assignee + admin | +| `undergoing`| ✗ | +| `completed` | ✗ | +| `closed` | ✗ | + +Feature story task 在 milestone 非 open 时,body 字段额外锁定。 + +### 2.5 与 Milestone 联动 + +- milestone `open/freeze` → task 只能停留在 `pending` 或 `closed` +- milestone `undergoing` → task 才允许从 `pending` 往后推进 +- milestone `completed/closed` → task 不再继续推进 + +--- + +## 3. Propose 状态机 + +### 3.1 状态枚举 + +| 状态 | 含义 | 终态 | +|-----------|-----------|------| +| `open` | 新建/待审 | ✗ | +| `accepted`| 已接受 | ✓ | +| `rejected`| 已拒绝 | ✓* | + +*支持 reopen + +### 3.2 状态流转 + +``` +open ──accept──▶ accepted + │ + └──reject──▶ rejected ──reopen──▶ open +``` + +### 3.3 流转条件 + +| 流转 | 条件 | +|------------------|----------------------------------------------------------| +| open → accepted | 需 `propose.accept` 权限 + 选择 open 状态的目标 milestone | +| open → rejected | 需 `propose.reject` 权限;建议填写 reason | +| rejected → open | 需 `propose.reopen` 权限;复用原 propose | + +### 3.4 Accept 副作用 + +- 自动创建 `story/feature` task(继承 title/description/created_by) +- 新 task 默认状态 `pending` +- 自动填写 `feat_task_id`(只读) + +### 3.5 编辑限制 + +| 状态 | 主体编辑 | +|-----------|----------------------------| +| `open` | ✓ (creator / admin / mgr) | +| `accepted`| ✗ | +| `rejected`| ✗ | + +--- + +## 4. 创建限制 + +以下 task 类型**不能**通过通用 create task 页面创建: + +| 类型 | 正确创建入口 | +|-----------------|------------------------| +| story/feature | propose → accept | +| maintenance/release | milestone endpoint | + +--- + +## 5. 旧枚举映射(DB 迁移) + +### Milestone + +| 旧值 | 新值 | +|-------------|-------------| +| `open` | `open` | +| `pending` | `open` | +| `deferred` | `closed` | +| `progressing`| `undergoing`| +| `closed` | `closed` | + +### Task + +| 旧值 | 新值 | +|-------------|-------------| +| `open` | `open` | +| `pending` | `pending` | +| `progressing`| `undergoing`| +| `closed` | `closed` | + +### Task Type + +| 旧值 | 新值 | +|--------|--------| +| `task` | `issue`|