mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-28 11:25:00 +00:00
The error message for unsupported version deletion still referenced only DRAFT/REJECTED. Updated both EN and ZH messages to reflect the actual deletable statuses: DRAFT, UPLOADED, REJECTED, SCAN_FAILED. Also updated OSS-02 design doc to mark all blocking items as completed.
663 lines
22 KiB
Markdown
663 lines
22 KiB
Markdown
# OSS-02 Core 语义规则收口
|
||
|
||
## 1. 文档目标
|
||
|
||
本文档固化 SkillHub Core 的运行时语义规则,确保开源版与 SaaS 版对删除、YANKED、同名冲突、package_name 等规则口径一致,避免 AstronClaw 接入后出现状态漂移。本文定义的是可由 SaaS 统一封装并对 AstronClaw 提供的 `Core` 规则基线,不表示 AstronClaw 直接对接这些开源接口。
|
||
|
||
---
|
||
|
||
## 2. 变更概要
|
||
|
||
### 2.1 新增功能
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| UPLOADED 状态 | 新增版本状态,表示"已上传,未提交审核" |
|
||
| PRIVATE skill 自动发布 | PRIVATE skill 发布后进入 UPLOADED 状态,不自动进入审核 |
|
||
| 提交审核接口 | 新增 `POST /{namespace}/{slug}/submit-review`,允许 UPLOADED 状态的版本提交审核 |
|
||
| 撤回审核后进入 UPLOADED | 撤回审核后版本状态变为 UPLOADED,而不是 DRAFT |
|
||
|
||
### 2.2 状态机变更
|
||
|
||
**变更前**:
|
||
```
|
||
DRAFT → SCANNING → PENDING_REVIEW → PUBLISHED
|
||
↓ ↓
|
||
REJECTED YANKED
|
||
```
|
||
|
||
**变更后**:
|
||
```
|
||
DRAFT → SCANNING → UPLOADED → PENDING_REVIEW → PUBLISHED
|
||
↓ ↓ ↓ ↓
|
||
SCAN_FAILED (可删除) REJECTED YANKED
|
||
↓ ↓
|
||
(可删除) (可删除)
|
||
```
|
||
|
||
### 2.3 权限模型变更
|
||
|
||
**核心原则**:权限只和 status 相关,visibility 只影响状态流转。
|
||
|
||
---
|
||
|
||
## 3. 版本状态定义
|
||
|
||
### 3.1 状态枚举
|
||
|
||
```java
|
||
public enum SkillVersionStatus {
|
||
DRAFT, // 草稿,编辑中
|
||
SCANNING, // 安全扫描中
|
||
SCAN_FAILED, // 扫描失败
|
||
UPLOADED, // 已上传,未提交审核(新增)
|
||
PENDING_REVIEW, // 等待审核
|
||
PUBLISHED, // 已发布
|
||
REJECTED, // 审核拒绝
|
||
YANKED // 已撤回
|
||
}
|
||
```
|
||
|
||
### 3.2 状态语义
|
||
|
||
| 状态 | 含义 | 文件状态 | 可下载 | 可编辑 | 有检测报告 |
|
||
|------|------|---------|-------|-------|----------|
|
||
| DRAFT | 草稿,编辑中 | 可能不完整 | 否 | 是 | 否 |
|
||
| SCANNING | 安全扫描中 | 完整 | 否 | 否 | 否 |
|
||
| SCAN_FAILED | 扫描失败 | 完整 | 否 | 是 | 是(失败) |
|
||
| UPLOADED | 已上传,扫描通过 | 完整 | owner | 否 | 是 |
|
||
| PENDING_REVIEW | 审核中 | 完整 | owner | 否 | 是 |
|
||
| PUBLISHED | 已发布 | 完整 | 看 visibility | 否 | 是 |
|
||
| REJECTED | 审核拒绝 | 完整 | 否 | 是 | 是 |
|
||
| YANKED | 已撤回 | 完整 | 否 | 否 | 是 |
|
||
|
||
---
|
||
|
||
## 4. 发布流程设计
|
||
|
||
### 4.1 发布路径
|
||
|
||
| visibility | 发布后初始状态 | 是否创建审核任务 |
|
||
|------------|--------------|----------------|
|
||
| PRIVATE | UPLOADED | 否 |
|
||
| NAMESPACE_ONLY | PENDING_REVIEW | 是 |
|
||
| PUBLIC | PENDING_REVIEW | 是 |
|
||
|
||
### 4.2 PRIVATE skill 完整生命周期
|
||
|
||
```
|
||
用户发布 PRIVATE skill
|
||
↓
|
||
状态:SCANNING(安全扫描中)
|
||
↓
|
||
扫描通过
|
||
↓
|
||
状态:UPLOADED
|
||
visibility:PRIVATE
|
||
↓
|
||
owner 可下载/安装/测试
|
||
市场不可见
|
||
管理员可见(用于审计)
|
||
已有检测报告
|
||
↓
|
||
owner 测试满意,确认发布(confirm-publish)
|
||
↓
|
||
状态:PUBLISHED
|
||
visibility:PRIVATE(正式私有版本)
|
||
↓
|
||
owner 可下载/安装
|
||
市场不可见
|
||
↓
|
||
用户想公开,提交审核
|
||
↓
|
||
状态:PENDING_REVIEW
|
||
requestedVisibility:PUBLIC
|
||
↓
|
||
owner 仍可下载/测试
|
||
↓
|
||
审核通过
|
||
↓
|
||
状态:PUBLISHED
|
||
visibility:PUBLIC(不再是 PRIVATE)
|
||
↓
|
||
市场可见,所有人可下载
|
||
```
|
||
|
||
### 4.3 PUBLIC/NAMESPACE_ONLY skill 生命周期
|
||
|
||
```
|
||
用户发布 PUBLIC/NAMESPACE_ONLY skill
|
||
↓
|
||
状态:PENDING_REVIEW
|
||
↓
|
||
owner 可下载/测试
|
||
↓
|
||
审核通过
|
||
↓
|
||
状态:PUBLISHED
|
||
visibility:PUBLIC 或 NAMESPACE_ONLY
|
||
↓
|
||
市场可见(受 visibility 控制)
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 权限矩阵
|
||
|
||
### 5.1 status 决定下载权限
|
||
|
||
| status | 市场可见 | 可下载 |
|
||
|--------|---------|-------|
|
||
| DRAFT | 否 | 否 |
|
||
| SCANNING | 否 | 否 |
|
||
| SCAN_FAILED | 否 | 否 |
|
||
| UPLOADED | 否 | owner |
|
||
| PENDING_REVIEW | 否 | owner |
|
||
| PUBLISHED | 看 visibility | 看 visibility |
|
||
| REJECTED | 否 | 否 |
|
||
| YANKED | 否 | 否 |
|
||
|
||
### 5.2 PUBLISHED 状态下,visibility 决定可见性
|
||
|
||
| visibility | 市场可见 | 可下载 |
|
||
|------------|---------|-------|
|
||
| PUBLIC | 是 | 所有人 |
|
||
| NAMESPACE_ONLY | 命名空间内 | 命名空间成员 |
|
||
| PRIVATE | 否 | owner |
|
||
|
||
### 5.3 AstronClaw 安装判断规则
|
||
|
||
```
|
||
可安装 =
|
||
skill.status == ACTIVE
|
||
AND skill.hidden == false
|
||
AND 存在至少一个可下载版本
|
||
AND 该版本 bundleReady == true
|
||
|
||
可下载版本判断:
|
||
- UPLOADED/PENDING_REVIEW:仅 owner
|
||
- PUBLISHED:按 visibility 规则
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 状态流转详细设计
|
||
|
||
### 6.1 状态转换表
|
||
|
||
| 当前状态 | 操作 | 目标状态 | 说明 |
|
||
|---------|------|---------|------|
|
||
| DRAFT | 上传包 | SCANNING | 开始安全扫描 |
|
||
| SCANNING | 扫描通过 | UPLOADED 或 PENDING_REVIEW | 看 visibility |
|
||
| SCANNING | 扫描失败 | SCAN_FAILED | - |
|
||
| SCAN_FAILED | 重新上传 | SCANNING | - |
|
||
| UPLOADED | 提交审核 | PENDING_REVIEW | 新增操作 |
|
||
| UPLOADED | 确认发布 | PUBLISHED | PRIVATE skill 正式发布,不触发新扫描 |
|
||
| UPLOADED | 重新上传 | SCANNING | 允许重新上传 |
|
||
| UPLOADED | 删除 | (删除) | 允许删除,未正式发布 |
|
||
| PENDING_REVIEW | 审核通过 | PUBLISHED | - |
|
||
| PENDING_REVIEW | 审核拒绝 | REJECTED | - |
|
||
| PENDING_REVIEW | 撤回审核 | UPLOADED | 变更:原为 DRAFT |
|
||
| PUBLISHED | Yank | YANKED | - |
|
||
| REJECTED | 重新上传 | SCANNING | - |
|
||
|
||
### 6.2 状态机图
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 上传包 │
|
||
└─────────────────────────────────────────┘
|
||
↓
|
||
┌───────────────┐
|
||
│ SCANNING │
|
||
└───────────────┘
|
||
/ \
|
||
扫描通过 / \ 扫描失败
|
||
/ \
|
||
┌────────────────────────┐ ┌───────────────┐
|
||
│ visibility=PRIVATE │ │ SCAN_FAILED │
|
||
│ → UPLOADED │ └───────────────┘
|
||
│ visibility=PUBLIC/ │ │
|
||
│ NAMESPACE_ONLY │ │ 重新上传
|
||
│ → PENDING_REVIEW │ ↓
|
||
└────────────────────────┘ ┌───────────────┐
|
||
│ │ SCANNING │
|
||
↓ └───────────────┘
|
||
┌────────────────────────┐
|
||
│ UPLOADED │◄────────────────────────┐
|
||
│ (PRIVATE skill 专属) │ │
|
||
│ 已有检测报告 │ │
|
||
└────────────────────────┘ │
|
||
/ \ │
|
||
确认发布 / \ 提交审核 │
|
||
(不触发新扫描) / \ │
|
||
/ \ │
|
||
↓ ↓ │
|
||
┌───────────────────┐ ┌───────────────────┐ │
|
||
│ PUBLISHED │ │ PENDING_REVIEW │ │
|
||
│ visibility=PRIVATE│ └───────────────────┘ │
|
||
└───────────────────┘ │ │
|
||
│ │ │
|
||
│ 提交审核 │ 审核通过 │
|
||
↓ ↓ │
|
||
┌───────────────────┐ ┌───────────────────┐ │
|
||
│ PENDING_REVIEW │ │ PUBLISHED │ │
|
||
└───────────────────┘ │ visibility=PUBLIC │ │
|
||
│ │ 或 NAMESPACE_ONLY │ │
|
||
│ └───────────────────┘ │
|
||
│ 撤回审核 │ │
|
||
└──────────────────────┘ │
|
||
(进入 UPLOADED) │
|
||
│
|
||
┌───────────────────┐ │
|
||
│ REJECTED │────────────────────────────────────────┘
|
||
└───────────────────┘ 重新上传
|
||
│
|
||
│ 删除
|
||
↓
|
||
(删除)
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 新增接口设计
|
||
|
||
说明:
|
||
|
||
以下接口属于开源 `Core` 为 SaaS 提供的基础状态机能力。对 `AstronClaw` 而言,后续仍应统一通过 `SkillHub SaaS` 的 `AstronClaw Adapter` 消费这些能力,而不是直接绑定这些开源接口路径。
|
||
|
||
### 7.1 提交审核接口
|
||
|
||
**接口**:`POST /api/v1/skills/{namespace}/{slug}/submit-review`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"version": "1.0.0",
|
||
"targetVisibility": "PUBLIC"
|
||
}
|
||
```
|
||
|
||
**前置条件**:
|
||
- 版本状态为 UPLOADED
|
||
- 操作者为 skill owner 或 namespace ADMIN/OWNER
|
||
|
||
**执行效果**:
|
||
- 版本状态 → PENDING_REVIEW
|
||
- `requestedVisibility` 设为目标可见性
|
||
- 创建审核任务
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"versionId": 100,
|
||
"status": "PENDING_REVIEW",
|
||
"requestedVisibility": "PUBLIC"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.2 确认发布接口(PRIVATE skill)
|
||
|
||
**接口**:`POST /api/v1/skills/{namespace}/{slug}/confirm-publish`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"version": "1.0.0"
|
||
}
|
||
```
|
||
|
||
**前置条件**:
|
||
- 版本状态为 UPLOADED
|
||
- skill.visibility = PRIVATE
|
||
- 操作者为 skill owner
|
||
|
||
**执行效果**:
|
||
- 版本状态 → PUBLISHED
|
||
- visibility 保持 PRIVATE
|
||
- **不触发新的扫描**,复用 UPLOADED 时的扫描结果
|
||
- 未来可扩展:加入"发布扫描"功能
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"skillId": 42,
|
||
"versionId": 100,
|
||
"status": "PUBLISHED",
|
||
"visibility": "PRIVATE"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 删除 / 隐藏 / 归档 / YANKED 语义规则
|
||
|
||
### 8.1 操作语义总表
|
||
|
||
| 操作 | 触发方式 | 可逆 | 市场可见 | 可新装 | 已装保留 | 可卸载 | slug 可复用 |
|
||
|------|---------|------|---------|-------|---------|-------|-----------|
|
||
| **硬删除 skill** | owner 或 SUPER_ADMIN | 否 | 否 | 否 | 是 | 是 | 是 |
|
||
| **归档 skill** | owner / namespace admin | 是 | 否 | 否 | 是 | 是 | 否 |
|
||
| **隐藏 skill** | 管理员 | 是 | 否 | 否 | 是 | 是 | 否 |
|
||
| **Yank 版本** | owner / namespace admin | 否 | 否 | 否 | 是 | 是 | N/A |
|
||
|
||
### 8.2 Yank 版本
|
||
|
||
**定义**:YANK 是"撤回已发布版本"的操作,用于将一个已发布的版本从可用状态移除。
|
||
|
||
**触发条件**:
|
||
- owner 或 namespace ADMIN/OWNER 对 PUBLISHED 状态的版本执行 yank
|
||
|
||
**执行效果**:
|
||
- `version.status` → `YANKED`(不可逆,无 un-yank 操作)
|
||
- `version.downloadReady` → `false`
|
||
- 记录 `yankedAt`、`yankedBy`、`yankReason`
|
||
- 如果该版本是 `skill.latestVersionId` 指向的版本:
|
||
- 自动回退到上一个 PUBLISHED 版本
|
||
- 如果没有其他 PUBLISHED 版本,`latestVersionId` → `null`
|
||
|
||
**对 AstronClaw 的影响**:
|
||
- 已安装实例不受影响
|
||
- 无法新装该版本
|
||
- 升级场景:目标版本被 yank → 升级失败
|
||
|
||
对接原则:
|
||
- 上述语义应由 SaaS Adapter 原样继承并稳定对外提供
|
||
- AstronClaw 通过 Adapter 感知这些状态,不直接绑定开源返回形态
|
||
|
||
**补救方式**:
|
||
- 不能 un-yank
|
||
- 只能发布新版本(rerelease 或重新上传)
|
||
|
||
---
|
||
|
||
## 9. 同名冲突规则
|
||
|
||
### 9.1 唯一性约束
|
||
|
||
数据库约束:`UNIQUE(namespace_id, slug, owner_id)`
|
||
|
||
含义:
|
||
- 同一 namespace 下,不同 owner 可以有相同 slug
|
||
- 同一 namespace 下,同一 owner 只能有一个相同 slug 的 skill
|
||
|
||
### 9.2 冲突规则设计原则
|
||
|
||
**核心原则**:只有 PUBLISHED 状态才会阻塞同名发布,但区分 visibility。
|
||
|
||
| 对方状态 | 我发布同名 PRIVATE | 我发布同名 PUBLIC | 说明 |
|
||
|---------|-------------------|------------------|------|
|
||
| UPLOADED | ✅ 允许 | ✅ 允许 | 多个 UPLOADED 可共存 |
|
||
| PENDING_REVIEW | ✅ 允许 | ✅ 允许 | 还未正式发布 |
|
||
| PRIVATE + PUBLISHED | ❌ 拒绝 | ❌ 拒绝 | 只允许一个正式私有版本 |
|
||
| PUBLIC + PUBLISHED | ❌ 拒绝 | ❌ 拒绝 | 市场已占用 |
|
||
|
||
### 9.3 冲突规则表(详细)
|
||
|
||
| 场景 | 是否允许 | 说明 |
|
||
|------|---------|------|
|
||
| 同 namespace,同 slug,同 owner | 允许(复用) | 新版本挂到已有 skill 下 |
|
||
| 同 namespace,同 slug,不同 owner,对方只有 UPLOADED | 允许 | 多个 UPLOADED 可共存测试 |
|
||
| 同 namespace,同 slug,不同 owner,对方只有 PENDING_REVIEW | 允许 | 还未正式发布 |
|
||
| 同 namespace,同 slug,不同 owner,对方有 PRIVATE + PUBLISHED | 拒绝 | 只允许一个正式私有版本 |
|
||
| 同 namespace,同 slug,不同 owner,对方有 PUBLIC/NAMESPACE_ONLY + PUBLISHED | 拒绝 | 市场已占用 |
|
||
| 不同 namespace,同 slug | 允许 | namespace 隔离 |
|
||
|
||
### 9.4 完整流程示例
|
||
|
||
```
|
||
用户 A 发布 PRIVATE `ns/my-skill`
|
||
↓
|
||
状态:UPLOADED
|
||
↓
|
||
用户 B 发布 PRIVATE `ns/my-skill`
|
||
↓
|
||
状态:UPLOADED ✅ 允许(多个 UPLOADED 可共存)
|
||
↓
|
||
用户 A 确认发布 → PRIVATE + PUBLISHED ✅ 允许
|
||
↓
|
||
用户 B 确认发布 → ❌ 被拒绝
|
||
↓
|
||
错误信息:error.skill.publish.nameConflict.private
|
||
↓
|
||
用户 B 可以:
|
||
1. 改名发布
|
||
2. 等用户 A 删除/归档后再发布
|
||
3. 提交审核变成 PUBLIC(如果 A 是 PRIVATE)
|
||
```
|
||
|
||
### 9.5 代码改动
|
||
|
||
**文件**:`SkillPublishService.java`
|
||
|
||
```java
|
||
// 冲突检查逻辑(第 230-242 行)
|
||
for (Skill existing : existingSkills) {
|
||
if (!existing.getOwnerId().equals(publisherId)) {
|
||
// 检查是否有 PUBLISHED 版本
|
||
boolean hasPublished = !skillVersionRepository
|
||
.findBySkillIdAndStatus(existing.getId(), SkillVersionStatus.PUBLISHED)
|
||
.isEmpty();
|
||
|
||
if (hasPublished) {
|
||
// PUBLISHED 版本存在,无论 visibility 如何都拒绝
|
||
// 因为只允许一个 PRIVATE + PUBLISHED 或 PUBLIC + PUBLISHED
|
||
if (existing.getVisibility() == SkillVisibility.PRIVATE) {
|
||
throw new DomainBadRequestException("error.skill.publish.nameConflict.private", skillSlug);
|
||
} else {
|
||
throw new DomainBadRequestException("error.skill.publish.nameConflict", skillSlug);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.6 错误信息
|
||
|
||
| 错误码 | 说明 |
|
||
|-------|------|
|
||
| `error.skill.publish.nameConflict` | 已有同名 PUBLIC/NAMESPACE_ONLY skill 发布 |
|
||
| `error.skill.publish.nameConflict.private` | 已有同名 PRIVATE skill 正式发布 |
|
||
|
||
---
|
||
|
||
## 10. package_name / runtime 规则
|
||
|
||
### 10.1 当前实现
|
||
|
||
- `package_name` 不是 Core 的结构化字段
|
||
- 存储在 `skill_version.parsedMetadataJson` JSONB 字段中
|
||
- 由 skill 作者在 SKILL.md frontmatter 中定义
|
||
|
||
### 10.2 SaaS Adapter 职责
|
||
|
||
- 从 `parsedMetadataJson` 中提取 `package_name`
|
||
- 作为顶层字段返回给 AstronClaw
|
||
- 可选:检查跨 skill 的 package_name 唯一性
|
||
- 统一封装 `submit-review`、`confirm-publish`、删除、查询等 Core 能力,对 AstronClaw 暴露稳定接口
|
||
|
||
### 10.3 规则建议
|
||
|
||
| 规则 | 建议 |
|
||
|------|------|
|
||
| 格式 | 建议使用 `namespace__slug` 格式,避免冲突 |
|
||
| 跨版本稳定性 | 同一 skill 跨版本应保持 package_name 一致 |
|
||
| 唯一性 | SaaS Adapter 可检查并警告冲突,但不强制阻止 |
|
||
|
||
---
|
||
|
||
## 11. 代码改动清单
|
||
|
||
说明:
|
||
|
||
以下改动属于开源 `Core` 的规则实现,用于给 SaaS 封装层提供稳定能力基线;不等同于直接向 AstronClaw 暴露这些开源接口。
|
||
|
||
### 11.1 枚举新增
|
||
|
||
**文件**:`SkillVersionStatus.java`
|
||
|
||
```java
|
||
public enum SkillVersionStatus {
|
||
DRAFT,
|
||
SCANNING,
|
||
SCAN_FAILED,
|
||
UPLOADED, // 新增
|
||
PENDING_REVIEW,
|
||
PUBLISHED,
|
||
REJECTED,
|
||
YANKED
|
||
}
|
||
```
|
||
|
||
### 11.2 发布逻辑改动
|
||
|
||
**文件**:`SkillPublishService.java`
|
||
|
||
```java
|
||
// 第 279-285 行,改为
|
||
if (visibility == SkillVisibility.PRIVATE) {
|
||
version.setStatus(SkillVersionStatus.UPLOADED);
|
||
version.setPublishedAt(currentTime());
|
||
// 不创建审核任务
|
||
} else if (autoPublish) {
|
||
version.setStatus(SkillVersionStatus.PUBLISHED);
|
||
version.setPublishedAt(currentTime());
|
||
} else {
|
||
version.setStatus(SkillVersionStatus.PENDING_REVIEW);
|
||
// 创建审核任务
|
||
}
|
||
```
|
||
|
||
### 11.3 撤回审核改动
|
||
|
||
**文件**:`SkillGovernanceService.java`
|
||
|
||
```java
|
||
// withdrawPendingVersion 方法,改为
|
||
skillVersion.setStatus(SkillVersionStatus.UPLOADED); // 原为 DRAFT
|
||
```
|
||
|
||
### 11.4 下载权限改动
|
||
|
||
**文件**:`SkillDownloadService.java`、`SkillQueryService.java`
|
||
|
||
```java
|
||
// UPLOADED 和 PENDING_REVIEW 状态允许 owner 下载
|
||
private boolean canDownload(SkillVersion version, Skill skill, String currentUserId) {
|
||
return switch (version.getStatus()) {
|
||
case UPLOADED, PENDING_REVIEW -> skill.getOwnerId().equals(currentUserId);
|
||
case PUBLISHED -> true; // 按 visibility 判断
|
||
default -> false;
|
||
};
|
||
}
|
||
```
|
||
|
||
### 11.5 新增服务
|
||
|
||
**文件**:`SkillReviewSubmitService.java`(新增)
|
||
|
||
- 实现 UPLOADED 版本提交审核逻辑
|
||
|
||
### 11.6 新增控制器
|
||
|
||
**文件**:`SkillReviewSubmitController.java`(新增)
|
||
|
||
- 暴露 `POST /{namespace}/{slug}/submit-review` 接口
|
||
- 暴露 `POST /{namespace}/{slug}/confirm-publish` 接口
|
||
|
||
### 11.7 管理员可见性
|
||
|
||
**文件**:`VisibilityChecker.java`
|
||
|
||
- SUPER_ADMIN 可以看到所有 skill,包括 UPLOADED 状态
|
||
|
||
### 11.8 数据库迁移
|
||
|
||
**文件**:新增迁移脚本
|
||
|
||
- 更新 `skill_version_status` 枚举类型,添加 UPLOADED 值
|
||
|
||
---
|
||
|
||
## 12. 阻塞上线条件
|
||
|
||
| 问题 | 严重程度 | 状态 |
|
||
|------|---------|------|
|
||
| 新增 UPLOADED 状态 | 高 | 已完成 |
|
||
| PRIVATE skill 发布逻辑改动 | 高 | 已完成 |
|
||
| 提交审核接口 | 高 | 已完成 |
|
||
| 撤回审核后进入 UPLOADED | 中 | 已完成 |
|
||
| 同名冲突检查补全 | 中 | 已完成 |
|
||
| 管理员可见 UPLOADED skill | 低 | 已完成 |
|
||
| package_name 唯一性检查 | 低 | 可选(SaaS Adapter 职责) |
|
||
|
||
---
|
||
|
||
## 13. 对老版本的影响
|
||
|
||
### 13.1 数据兼容性
|
||
|
||
| 影响点 | 分析 | 需要处理 |
|
||
|--------|------|---------|
|
||
| 老版本数据 | 不受影响,状态不变 | 否 |
|
||
| 数据库枚举 | 需添加 UPLOADED 值 | 是 |
|
||
| API 兼容性 | 新接口是新增,不影响老接口 | 否 |
|
||
|
||
### 13.2 状态流转影响
|
||
|
||
| 场景 | 老逻辑 | 新逻辑 | 影响 |
|
||
|------|--------|--------|------|
|
||
| 老版本撤回审核 | PENDING_REVIEW → DRAFT | PENDING_REVIEW → UPLOADED | 前端需适配新状态 |
|
||
| 老版本删除 | DRAFT/REJECTED/SCAN_FAILED 可删 | UPLOADED 也可删 | 需更新代码判断 |
|
||
|
||
### 13.3 代码改动点
|
||
|
||
**文件**:`SkillGovernanceService.java`
|
||
|
||
**1. 删除版本逻辑**(第163-166行):
|
||
```java
|
||
// 原代码
|
||
if (version.getStatus() != SkillVersionStatus.DRAFT
|
||
&& version.getStatus() != SkillVersionStatus.REJECTED
|
||
&& version.getStatus() != SkillVersionStatus.SCAN_FAILED) {
|
||
throw new DomainBadRequestException("error.skill.version.delete.unsupported", version.getVersion());
|
||
}
|
||
|
||
// 改为:允许删除 UPLOADED 状态
|
||
if (version.getStatus() != SkillVersionStatus.DRAFT
|
||
&& version.getStatus() != SkillVersionStatus.REJECTED
|
||
&& version.getStatus() != SkillVersionStatus.SCAN_FAILED
|
||
&& version.getStatus() != SkillVersionStatus.UPLOADED) {
|
||
throw new DomainBadRequestException("error.skill.version.delete.unsupported", version.getVersion());
|
||
}
|
||
```
|
||
|
||
**2. 撤回审核逻辑**(第245行):
|
||
```java
|
||
// 原代码
|
||
version.setStatus(SkillVersionStatus.DRAFT);
|
||
|
||
// 改为
|
||
version.setStatus(SkillVersionStatus.UPLOADED);
|
||
```
|
||
|
||
### 13.4 前端适配
|
||
|
||
| 状态 | 前端展示建议 |
|
||
|------|-------------|
|
||
| UPLOADED | "已上传" 或 "待确认" |
|
||
| 可删除状态 | DRAFT、SCAN_FAILED、REJECTED、UPLOADED |
|
||
| 可编辑状态 | DRAFT、SCAN_FAILED、REJECTED |
|
||
|
||
### 13.5 迁移策略
|
||
|
||
1. **数据库迁移**:添加 UPLOADED 枚举值
|
||
2. **代码部署**:先部署后端,再部署前端
|
||
3. **老数据处理**:无需处理,老版本状态保持不变
|
||
4. **回滚方案**:如需回滚,UPLOADED 状态的版本按 DRAFT 处理
|