Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
57477e2
feat(avatar): normalize uploaded crop on server
XiaoSeS Oct 12, 2026
6d42bd6
feat(avatar): persist candidate lifecycle
XiaoSeS Oct 12, 2026
b1d5391
feat(namespace): add single-use invitation persistence
XiaoSeS Oct 12, 2026
f7e96bb
feat(avatar): add owner and reviewer workflows
XiaoSeS Oct 12, 2026
9c997f7
feat(namespace): add one-time invitation links
XiaoSeS Oct 12, 2026
0452af0
docs(namespace): clarify invitation lock order
XiaoSeS Oct 12, 2026
2768771
fix(namespace): complete invitation review follow-up
XiaoSeS Oct 12, 2026
7d36d42
test(namespace): cover invitation mutation races
XiaoSeS Oct 12, 2026
08fb846
fix(namespace): keep invitation labels unique and copy promptly
XiaoSeS Oct 12, 2026
ff69136
test(namespace): cover invitation expiry and role boundaries
XiaoSeS Oct 12, 2026
f12019c
fix(invitation): keep login return target on join route
XiaoSeS Oct 12, 2026
6299733
test(invitation): cover invitation permission boundaries
XiaoSeS Oct 12, 2026
44a1623
fix(invitation): align API with issue contract
XiaoSeS Oct 12, 2026
ee17c1e
fix(invitation): enter namespace after member preview
XiaoSeS Oct 12, 2026
e65795d
test(namespace): update command lookup fixtures
XiaoSeS Oct 12, 2026
b67ea7d
feat(avatar): add review and owner interfaces
XiaoSeS Oct 12, 2026
17a18b9
fix(avatar): recover pending reviews and cover moderation flows
XiaoSeS Oct 12, 2026
5f2d479
feat: combine Skill avatars and namespace invitations
XiaoSeS Oct 12, 2026
c48b09d
fix(namespace): expose invitation confirmation errors
XiaoSeS Oct 12, 2026
bc2592c
test(avatar): verify recovery with PostgreSQL transactions
XiaoSeS Oct 12, 2026
3b3e5ed
test(avatar): cover policy and release generation boundaries
XiaoSeS Oct 12, 2026
8c7ea2c
docs: record avatar and invitation acceptance progress
XiaoSeS Oct 12, 2026
1a7ffbe
feat(avatar): stage images before skill publication
XiaoSeS Oct 13, 2026
14cc3f1
fix(auth): declare staged avatar uploads session-only
XiaoSeS Oct 13, 2026
d9c658a
fix(avatar): refresh owner and review caches after mutations
XiaoSeS Oct 13, 2026
c5f8483
fix(publish): refresh content review queue after submission
XiaoSeS Oct 13, 2026
52f694f
docs(avatar): record staged publication acceptance
XiaoSeS Oct 13, 2026
b469b60
fix(avatar): reuse open-source image cropping component
XiaoSeS Oct 13, 2026
4a2a1f7
docs(avatar): record open-source crop acceptance
XiaoSeS Oct 13, 2026
66571f7
fix(avatar): unify update flow and crop in a compact dialog
XiaoSeS Oct 13, 2026
bfb5298
fix(avatar): bound crop dialog and refresh inactive removal caches
XiaoSeS Oct 13, 2026
d275d1e
docs(avatar): record compact dialog acceptance
XiaoSeS Oct 13, 2026
71d0598
feat(review): unify skill avatar approval and space management
XiaoSeS Oct 13, 2026
3de13c0
style(namespace): remove trailing empty line
XiaoSeS Oct 13, 2026
efbb50f
fix(namespace): refresh invitation state before creating link
XiaoSeS Oct 13, 2026
be1529a
fix(review): refresh moderation queue on entry
XiaoSeS Oct 13, 2026
5916771
fix(web): clarify pending avatars and space management
XiaoSeS Oct 14, 2026
a564868
fix(web): expand invitation dialog and clarify its status
XiaoSeS Oct 14, 2026
ccd171e
feat(namespace): retain invitation history and join records
XiaoSeS Oct 14, 2026
b67b955
fix(web): compact invitation history and display names
XiaoSeS Oct 14, 2026
0cfae17
fix(web): reduce invitation dialog control density
XiaoSeS Oct 14, 2026
6f38e40
docs(avatar): clarify machine review outcomes and provider validation
XiaoSeS Oct 14, 2026
8411629
docs(avatar): add user-facing cloud moderation setup guide
XiaoSeS Oct 14, 2026
11ff769
docs(avatar): record review fixes and migration merge order
XiaoSeS Oct 14, 2026
71790bc
merge: sync main after authoring prerequisite
XiaoSeS Oct 14, 2026
57bb09f
test: align namespace guard mock after authoring merge
XiaoSeS Oct 14, 2026
3bfd8a3
fix(review): handle metadata inbox without version context
XiaoSeS Oct 14, 2026
1d7daeb
test(web): align namespace flows with unified space navigation
XiaoSeS Oct 15, 2026
217a222
test(web): require a team fixture for namespace members
XiaoSeS Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions docs/26-skill-avatars.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 技能头像与审核

技能所有者可在新增/更新技能页面选择自定义 PNG/JPEG 头像,网页提供方形裁剪和缩放;不提供预设图标。更新默认保留头像,也可替换或移除。“我的技能”统一从“更新”入口维护,也可只改头像而不发布新版本;详情页仅在标题旁展示当前头像。服务器仍会独立校验:输入不超过 2 MB、边长不超过 1024 像素,并重新编码为 PNG,避免依赖客户端裁剪或保留原图元数据。头像候选存在私有对象存储;审核完成前,公众继续看到旧头像或技能名首字母。所有者在“我的技能”和更新页可查看已提交头像的缩略图及审核状态,待审头像不会替代公开头像;加载失败会提示重试。

## 上传与提交

选择图片后先裁剪并上传到私有存储,上传成功后才允许提交技能或头像修改;未选择头像也可提交新技能。上传失败可重试,但不能把失败或尚未完成的上传随技能提交。上传成功仅表示文件已保存,不表示审核通过。

提交成功后图片才关联到技能并进入对应审核流程。更新时未修改头像会保留原头像;选择移除时先预览首字母。仅改头像时提交成功即恢复兜底;与新技能包一起提交时在同一申请审核通过后移除,驳回保留原头像。失效候选历史保留。取消编辑或提交失败不会改变原头像及已有待审申请。未关联的临时图片保持私有;上传引用 24 小时后过期,过期未关联图片由清理任务定期回收,提交时过期需要重新上传。

技能包与头像同次提交时只有一张技能审核申请:审核员在原技能审核详情同时检查内容与头像,一次批准或驳回,共同生效。机器结果作为同一申请的审批条件,不能提前发布头像。单改头像不创建新技能版本;需要人工决定时仍进入原技能审核队列,标明“头像修改”,不再有独立头像审核队列。

## 审核策略

超级管理员在“系统配置”中分别开关机器审核和人工审核。默认关闭机器审核、开启人工审核。单改头像时,两个开关都关闭直接发布;只开启机器时通过即发布、阻止或未知结果保持私有;只开启人工时进入技能审核队列;两者都开启时先机器后人工。若与技能包同次提交,则不论头像开关如何,仍等待原有技能内容审核共同批准。机器阻止后所有者可申请人工复核;机器服务失败时可重试,不会自动放行。当前云供应商不能提供可证明不可变的模型版本,不跨申请复用机器结果;新申请重新检测。每次调用记录实际服务/API版本和内部审核策略revision,未知模型版本留空,不把SDK或API版本作为模型版本。扩大可见范围时必须重新人工审核。`PRIVATE` 技能头像由所有者直接使用。

人工权限复用技能审核:团队管理员可审本团队,平台技能管理员/超级管理员可审团队和全局;自审限制也沿用原技能审核规则。头像只能由技能所有者提交、替换或删除;管理员可审核和撤下,不可代传。新申请使旧待审申请失效;旧审核决定不能覆盖新头像。被拒绝、替换、删除的候选图片私有保留 30 天后清理,文字审核记录继续保留。头像撤下后显示首字母兜底。

新提交若可见范围扩大,系统在同一技能申请中关联目标范围头像候选,审核完成后共同生效,不能先发布内容再要求另一次人工审核。遗留数据的范围补偿仍保证未经目标范围批准的头像不向新增受众公开。已有相同目标范围的待审申请不会被覆盖;新旧候选使用不同对象键,避免旧文件到期清理影响当前头像。自动建候选失败时旧头像仍保持隐藏;每五分钟分批检查并补建候选。若候选已建但机器读取或审核失败,状态记为 `ERROR`,一小时冷却后自动重试;同一候选自动审核最多调用三次(含首次),到达上限后由所有者在冷却结束后主动重试或重新提交。普通上传在机器调用前宕机留下的 `PENDING` 候选,以及机器处理中宕机留下的 `PROCESSING` 候选,十分钟后也由补偿任务重领。机器调用前后分别使用短事务核验候选指针,外部调用期间不持有数据库锁;过期尝试的迟到结果不会激活头像。当前发布版已驳回的自动申请不会反复入队,历史发布版的驳回不阻止新发布。服务日志仅记录技能或候选 ID 和异常类型,不记录可能包含凭证的供应商请求信息。`PRIVATE` 头像及候选图片只有技能所有者可以读取。

## 部署配置

### 机器结果与人工决定

机器审核结果与申请的最终决定是两个状态。以下针对非 `PRIVATE` 的单改头像;与技能包同时提交时,仍需等待原技能审核共同决定。

| 机器结果 | 开启人工审核 | 未开启人工审核 |
| --- | --- | --- |
| 通过(`PASSED`) | 进入统一技能审核,批准后生效 | 自动生效 |
| 阻止(`BLOCKED`) | 新头像保持私有,申请待审;审核员可拒绝,或填写明确理由后人工改判 | 不生效,不自动变为人工驳回;所有者可申请人工复核 |
| 异常(`ERROR`) | 保持私有,不允许直接批准;先重试得到有效结果 | 保持私有,等待重试 |

文件上传成功不等于机器通过;机器阻止也不等于管理员已经拒绝。人工拒绝后,用户可查看提交图片及拒绝原因,公开头像保持旧图或首字母兜底。机器阻止没有自动驳回整个技能申请,避免把机器判断与人工决定混为一谈。

### 供应商与凭证

在部署密钥配置中指定唯一供应商及其凭证,然后才可从后台开启机器审核。Spring 属性如下;将值映射到部署 Secret/环境变量时请遵循当前部署平台的配置方式,不要写入仓库或后台数据库:

| 供应商 | 属性 |
| --- | --- |
| 通用 | `skillhub.avatar.moderation.provider`:`xfyun` 或 `aliyun` |
| 讯飞 | `skillhub.avatar.moderation.xfyun.app-id`、`skillhub.avatar.moderation.xfyun.access-key-id`、`skillhub.avatar.moderation.xfyun.access-key-secret` |
| 阿里云 | `skillhub.avatar.moderation.aliyun.access-key-id`、`skillhub.avatar.moderation.aliyun.access-key-secret` |

后台只显示两个启停开关,不回显供应商或密钥。阿里云适配器使用上海地域的 `profilePhotoCheck`,通过短期上传令牌把私有候选送到官方 OSS 临时对象,再调用同步审核;不会公开候选 URL。官方返回 `RiskLevel=none/low` 通过,`medium/high` 保持私有并允许人工复核。把 `medium` 归为阻止是本产品策略。响应非 200、空结果或未知值均不放行。机器接口可能按量计费,开启前由部署方确认供应商账号与费用。

阿里云须开通内容安全增强版,测试凭证至少需要 `yundun-greenweb:DescribeUploadToken` 和 `yundun-greenweb:ImageModeration` 权限。当前使用供应商临时上传令牌,无需部署方自建审核用 OSS Bucket 或向该凭证授予自有 OSS 全权限。[官方本地图片接入示例](https://help.aliyun.com/zh/document_detail/467828.html)即使用该流程。阿里云说明上传到其临时存储的本地图片保留 30 分钟;这与 SkillHub 私有候选图片保留 30 天是两个独立生命周期,见[官方接口说明](https://help.aliyun.com/document_detail/467829.html)。

切换部署供应商需要更新服务配置并重启应用。已有候选保留提交时的供应商与机器/人工开关快照,不自动迁移;尚需调用旧供应商的申请在切换后会得到 `ERROR`,不会偷偷改用新供应商。所有者应重新提交以使用新供应商;已经完成的机器结果不会因切换配置被重新检测。

讯飞官方图片审核接口要求把 `accessKeySecret` 放在请求 URL 参数中。应用不会记录完整 URL 或异常原文,但 Java HTTP 客户端调试日志、反向代理、出口代理、链路追踪及第三方日志仍可能记录该 URL。部署方使用讯飞适配器前,必须确认相关组件不采集请求 URL,限制凭证权限并建立轮换机制。若无法满足,先不要开启该适配器。

## 与原 Issue 的差异

原 Issue 提议自动图片审核;本期产品决策改为“上传、裁剪、机器审核可选、人工审核可选”的四种策略。默认使用人工审核,机器审核仅在部署好单一供应商且管理员开启后运行。个人头像不在本期范围。

## 验收要点

分别验证四种开关组合、候选与当前头像隔离、拥有者和审核员权限、审核通过/驳回/复核、相同图片的新申请重新检测及每次策略审计、未知机器结果不放行、连续替换后旧审核无效、删除后首字母兜底、30 天清理以及团队/全局可见范围变化。外部供应商真实计费调用需要部署方测试账号与授权;单元测试使用模拟响应。
1 change: 1 addition & 0 deletions docs/skillhub/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default defineConfig({
text: '核心功能',
items: [
{ text: 'Skill 发布与版本管理', link: '/guide/skill-publish' },
{ text: '技能头像与图片审核接入', link: '/guide/skill-avatars' },
{ text: 'Suite Bundle 批量导入', link: '/guide/suite-bundle' },
{ text: 'Skill 搜索与发现', link: '/guide/skill-discovery' },
{ text: '命名空间与团队管理', link: '/guide/namespace' },
Expand Down
19 changes: 19 additions & 0 deletions docs/skillhub/en/guide/namespace.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ Discover a security issue in the namespace and temporarily freeze all publish op
5. Select a role (Owner / Admin / Member)
6. Confirm to add

**Invite with a link**:

1. An Owner or Admin opens the Members page of an ACTIVE team space and selects "Invite member".
2. Share the copied link securely. It expires after 24 hours and can be redeemed once by one person who is not already a member.
3. The recipient must first pass the usual SkillHub login and account access rules. The page shows the space, current account, and MEMBER permissions. Joining happens only after explicit confirmation.
4. "Revoke invitation" invalidates the link immediately. Creating a new link asks for confirmation before replacing a still usable one; existing members remain members.

Anyone who obtains the link can use it after normal account admission. Do not post it in a public channel. The login return URL does not contain the invitation token; the current browser tab stores it temporarily until joining or terminal invalidation.

**Manage Permissions**:

1. Find the target user in the member list
Expand Down Expand Up @@ -167,6 +176,16 @@ Content-Type: application/json
POST /api/v1/namespaces/{slug}/unfreeze
```

## Invite Members and View History

Team Owners and Admins can create a link from **Members → Invite members**. It expires after 24 hours and permits one new member to join. The recipient must sign in, meet existing admission rules, and confirm joining. Replacing an active link or revoking it requires confirmation and does not remove existing members.

The dialog includes a read-only history (five records per page, up to 240px tall) showing the creator, creation and expiration times, status, and the account that successfully joined. Snapshot names are displayed first; full account IDs are available on hover, with abbreviated IDs used when names are missing. Each generated invitation has its own record. Replacement, revocation, expiration, or a member leaving does not erase history. History cannot restore expired links and does not indicate current membership. Only the space's Owner/Admin can view it; platform roles do not bypass this restriction. Frozen or archived spaces retain a history-only entry.

An upgrade imports only the provable current invitation, marked as a legacy record; earlier links are not reconstructed from incomplete audit data. History remains while the space exists and is deleted when the space is permanently deleted. Existing audit records follow their original retention rules.

The history endpoint requires a browser session: `GET /api/v1/namespaces/{slug}/invitations/history?page=0&size=10`. Page sizes are bounded to 1–50; tokens and hashes are never returned.

## Notes

> **Slug Uniqueness**: Namespace slugs must be globally unique and cannot be changed after creation. Use a short identifier for your team or project.
Expand Down
19 changes: 19 additions & 0 deletions docs/skillhub/guide/namespace.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@
5. 选择角色(Owner / Admin / Member)
6. 确认添加

**通过链接邀请成员**:

1. Owner 或 Admin 在处于 ACTIVE 状态的团队空间「成员」页点击「邀请成员」。
2. 复制链接并安全地发给要加入的人。链接 24 小时内有效,只能由一名尚未加入的用户使用一次。
3. 对方先按现有登录及账号准入规则进入 SkillHub。打开链接后会看到目标空间、当前账号和 MEMBER 权限;点击「确认加入」才会成为成员。
4. 如需提前失效,点击「作废邀请」。重新生成链接时,页面会要求确认旧链接立即失效;已加入的成员不受影响。

邀请链接是持有者可用的加入凭证,不限定邮箱或账号。不要在公开频道分享。登录回跳不会携带邀请 Token;同一浏览器标签页会暂存链接直到确认、已加入或确认失效。

**管理权限**:

1. 在成员列表中找到目标用户
Expand Down Expand Up @@ -167,6 +176,16 @@ Content-Type: application/json
POST /api/v1/namespaces/{slug}/unfreeze
```

## 邀请成员与邀请记录

团队空间的 Owner/Admin 可在“成员 → 邀请成员”生成24小时有效、仅一名新成员可使用的链接。对方须先登录并通过平台准入,再确认加入;仅打开链接不会自动成为成员。替换有效链接和作废须确认,已加入成员不受影响。

弹窗下方直接展示分页邀请记录(网页每页5条,列表最高240px):创建人及时间、到期时间、状态,以及实际加入账号与时间。人员优先显示记录时保存的姓名,完整账号ID放在悬停提示;无姓名时显示短标识。每次生成独立记录,替换、作废、过期和成员离开不会抹掉原历史。历史不能恢复失效链接,也不代表当前成员资格。普通成员和仅有平台角色的账号不能查看,冻结/归档空间的 Owner/Admin 可查看只读历史。

升级只迁入可以准确读取的当前邀请并标记“旧记录”,不推测更早链接的使用情况。空间存在期间保留历史,彻底删除空间时删除邀请业务记录,既有操作审计按原规则保留。

历史查询使用浏览器 Session:`GET /api/v1/namespaces/{slug}/invitations/history?page=0&size=10`,每页1–50条,不返回邀请码或哈希。

## 注意事项

> **Slug 唯一性**:命名空间 slug 在全局范围内必须唯一,且创建后不可修改。建议使用团队或项目的简短标识符。
Expand Down
2 changes: 2 additions & 0 deletions docs/skillhub/guide/review.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ SkillHub 提供了完整的审核工作流,确保发布到注册中心的技
- **推广管理**:将命名空间技能包推���到全局
- **审计日志**:记录所有治理操作

头像变更复用技能审核申请。机器阻止与人工拒绝是不同状态;开关组合、审核操作及云审核接入步骤详见 [技能头像与图片审核接入](/guide/skill-avatars)。

## 使用场景

**场景一:命名空间管理员审核**
Expand Down
Loading
Loading