docs(P12.2-P12.3): add state machine overview, permissions overview, and propose flow documentation
This commit is contained in:
90
docs/permissions-overview.md
Normal file
90
docs/permissions-overview.md
Normal file
@@ -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 分组展示。
|
||||
163
docs/propose-flow.md
Normal file
163
docs/propose-flow.md
Normal file
@@ -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 <project_id>
|
||||
|
||||
# 创建 propose
|
||||
harborforge propose-create "My Feature Idea" --project <project_id>
|
||||
|
||||
# Accept(需指定 milestone)
|
||||
harborforge propose-accept <propose_id> --project <project_id> --milestone <milestone_id>
|
||||
|
||||
# Reject(可选 reason)
|
||||
harborforge propose-reject <propose_id> --project <project_id> --reason "Not in scope"
|
||||
|
||||
# Reopen
|
||||
harborforge propose-reopen <propose_id> --project <project_id>
|
||||
```
|
||||
185
docs/state-machine-overview.md
Normal file
185
docs/state-machine-overview.md
Normal file
@@ -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`|
|
||||
Reference in New Issue
Block a user