agentscope-ai / agentscope-ai/AgentTeams
Design: Skill Center — catalog source of truth, representation, assignment state, and sync
- 主要语言
- Go
- 星标
- 5.6k
- 派生
- 692
- 平均合并
- 5 天 4 小时
- 30 天内合并 PR
- 23
描述
# Design: Skill Center — catalog source of truth, representation, assignment state, and sync
> **Background**: The review of PR #1211 (Skill Center API, 2026-09-03) paused implementation until this design is agreed with the maintainers. This issue takes up the five discussion points raised in that review. The permission-side decisions (who can list / assign / reveal) are tracked in #1220; this issue covers the **catalog architecture** side.
> **Related**: #1211 (implementation: v1 landed on branch 2026-09-11 — builtin + individual layer, L1-only authz, `version`/`requirements`/`updated_at`; team dimension + upload pending) · #1220 (L2 permission & capability model, cross-reference)
> **Proposed by**: @LUOSENGWA (AgentTeams contributor) · 2026-09-03 · EN/ZH below (English is the primary text)
## 1. Question 1 — What is the authoritative public catalog, and which component owns it?
**Proposal: the deployment-level shared skill store (MinIO), read by the controller.**
- The catalog is the shared skill store of the deployment: skill objects uploaded through the upload path (as of 2026-09-11: the controller API, see §8.4), plus the built-in skill templates bundled with the worker image.
- **Owner**: the controller is the only component exposing catalog APIs; writes go through the existing upload path (controller-mediated, stored in MinIO). `Worker.spec` is **not** a source of truth for the catalog — it records per-worker *assignment* only (see Q3).
- Rationale: the MinIO shared store is already the deployment's file truth source (team knowledge bases, shared artifacts). Making the skill catalog an object-level truth in the same store avoids a new storage path and keeps "list on read" simple (Q5).
*(部署级 MinIO 共享 Skill 存储为权威目录,controller 是唯一读出口;写入走既有上传链路。Worker.spec 不是目录的 source of truth,只记 per-worker 分配。理由:MinIO 共享存储已是本部署的文件真相源,Skill 目录复用同一对象级真相,不新增存储路径。)*
## 2. Question 2 — How are built-in, uploaded, marketplace, and remote registry skills represented?
**Proposal: two first-class sources in v1; marketplace / remote registry deferred to P2.**
| source | v1 representation | P2 |
|---|---|---|
| built-in | static template directory bundled in the worker image; listed with `source: builtin`, read-only metadata | — |
| uploaded (deployment-shared) | skill objects in the MinIO shared store; metadata from the stored skill manifest (`source: shared`, version, uploaded_by, uploaded_at) | — |
| marketplace | not in v1 | registry metadata + redacted `source_uri`; credential management via the `external_sources` capability defined in #1220 |
| remote registry | not in v1 | same as marketplace (a remote registry is a marketplace with a different endpoint) |
Each catalog entry carries: `id, name, description, source, version, size, uploaded_by, uploaded_at` — **credentials are never part of catalog metadata** (Q4). *As of 2026-09-11:* "uploaded" covers two scopes — **team layer** (`teams//skills/`, `source: team`) and **individual layer** (`agents/global/skills/`, `source: shared` retained); the `source` value set is `builtin | shared | team` (worker dimension P2). Implemented field set per #1211 v1: `name/description/source/version/requirements/updated_at/agents/runtimes` (§8.2).
*(v1 一等来源:built-in(镜像内置模板目录)+ shared(MinIO 共享存储上传区);marketplace / remote registry 延后 P2,凭据管理挂 #1220 的 external_sources 能力。目录项含 source/version/元数据,永不含凭据。)*
## 3. Question 3 — Boundary between catalog metadata, per-worker assignment state, and the worker's runtime copy
Three distinct layers, three owners:
| layer | answers | owner / storage | API |
|---|---|---|---|
| **catalog metadata** | what skills exist (global, redacted) | MinIO shared store + built-in templates; read by the controller | list / detail (visibility per Q4) |
| **assignment state** | which skills are active on which worker | `Worker.spec.skills` | worker update API (`ActionSkillAssign`, #1220) |
| **runtime copy** | the files the worker process actually loads | worker-local mirror, synced by the worker's own sync loop | not exposed by the controller (out of scope) |
The catalog answers "what exists"; assignment answers "what is on this worker"; the runtime copy is a worker-internal detail. The controller never reads worker-local skill state.
*(三层三主:目录元数据(全局、redacted,controller 读)/ 分配态(Worker.spec.skills,worker 更新 API)/ 运行时副本(worker 本地镜像、自同步,controller 不暴露不读取)。目录答"有什么",分配答"这个 worker 装了什么",运行时副本是 worker 内部细节。)*
## 4. Question 4 — Team visibility, tenant isolation, credential redaction
**Final (2026-09-11; supersedes the original 9/3 global-read proposal): scope is decided by authz, not by request shape.**
| Request | Scope | Access |
|---|---|---|
| `GET /api/v1/skills` (no team param) | builtin + individual layer (`agents/global/skills/`) | **L1 only**; L2 → `400 team scope required` (self-explanatory) |
| `GET /api/v1/skills?team=T` | builtin + `teams/T/skills/` | L1 any / L2 own team; cross-team / unknown → `404` (anti-probing) |
Assignment stays team-scoped per #1220. L3 humans hold no team scope: they get the same 400 on the no-param read (their worker-scoped read path is unchanged).
- **Credential redaction is unconditional**: any `source_uri` with embedded credentials, and any registry auth block, is redacted at the store boundary (on upload) and in every API response. Redaction is a storage invariant, **not** a permission item.
- **Tenant isolation**: v1 is single-tenant (one deployment = one trust domain); per-tenant catalogs (visibility labels or per-tenant store partitions) are P2, to be designed together with the multi-tenant roadmap.
*(定案 2026-09-11,取代 9/3 全局读提案):scope 由 authz 决定,不由请求形态决定——无参 = builtin + 单独层(`agents/global/skills/`),**仅 L1**(L2 → `400 team scope required` 自解释);`?team=T` = builtin + 团队层(`teams/T/skills/`),L1 任意 / L2 本团队 / 跨团队 404 防探测。L3 无团队 scope:无参读同 L2 得 400(其 worker scope 读路径不变)。分配仍按 #1220 team-scoped。凭据 redaction 是无条件存储不变量(上传时 + 每个 API 响应),不是权限项。多租户隔离 = P2,跟多租户路线图一起设计。)*
## 5. Question 5 — How does the catalog update when skills are added, updated, or deleted?
**Proposal: object-level operations + list on read (no cache in v1).**
- **Add** = upload a skill object to the shared store → the next catalog list includes it.
- **Update** = overwrite the object (new version) → the catalog reflects the new metadata.
- **Delete** = remove the object → the catalog drops it; **already-assigned workers keep their runtime copy and their assignment** (no cascade un-assign) — the operator decides whether to un-assign.
- Built-in skills change only with a worker image release.
- No catalog cache in v1: list on read from the store. (P2: TTL cache if listing latency becomes an issue at larger catalog sizes.)
*(对象级操作 + list-on-read(无缓存):新增=上传对象、更新=覆盖、删除=移除对象(已分配 worker 保留运行时副本与分配,不级联解绑——由操作者决定)。built-in 随镜像版本变。P2 视规模加 TTL 缓存。)*
## 6. Effect on #1211 (implementation)
- #1211 v1 is implemented on the branch (2026-09-11, review pending): `GET /api/v1/skills` reads builtin (template scan, per-runtime availability derived from the deployer's own template-selection function so the catalog never drifts) + individual layer (`agents/global/skills/` listing with `updated_at`); builtin entries additionally carry `version`/`requirements` (QwenPaw 2.2.x frontmatter semantics). **Authz: L1 (admin) only** for the no-param read; non-admin callers (L2 humans, team leaders, workers, manager) get `400 team scope required`.
- The team-scoped read (`?team=`) and the upload API (`POST /skills` `scope=team`/`deployment`) ship with the team-skills PR (this issue's §8.4), not with #1211 v1.
- The explicit `ActionList` on the skills resource (no wildcard) stands.
## 7. Open questions for the community
1. Is the MinIO shared store acceptable as the v1 catalog owner (vs. a controller-managed CRD), given it is already the deployment's file truth source?
2. Is the v1 source split right-sized (builtin + shared only; marketplace / remote → P2)?
3. ~~Is global catalog read for all authenticated roles acceptable in v1 (vs. team-filtered)~~ — **Resolved 2026-09-11 (stakeholder): the authz-scope contract** (no-param = L1 only; `?team=` = team scope, L2 own teams — Q4 final table). Open for maintainer comment on the final contract.
4. Is list-on-read acceptable (vs. cache + TTL) at expected catalog sizes?
5. On delete, is "keep runtime copy, keep assignment" the right default (vs. cascade un-assign)?
---
## 8. Follow-ups (2026-09-11, recorded post-#1211-v1)
1. **Update propagation is explicit non-propagation.** "Update" overwrites the catalog object and its metadata only — it does **not** reach already-assigned workers' runtime copies. Assignment is a one-shot copy, not a subscription (the Q5 delete semantics confirm the same boundary). Propagating a new version to assigned workers (materialized-version reporting + an explicit resync action) is a v2 item, building on the per-worker availability endpoint.
2. **Entry metadata as implemented in #1211 (2026-09-11).** Shared entries carry `name` + `updated_at` (the listing timestamp, RFC3339 UTC, omitted when the backend cannot provide one). Builtin entries additionally carry `version` and `requirements` (`require_bins`/`require_envs`/`require_mcps`, QwenPaw 2.2.x frontmatter semantics). Q2's `size` is deferred (MinIO directory entries are virtual 0-byte markers; real sizes need a recursive listing — v2), and `uploaded_by` needs a per-object stat (v2). Shared SKILL.md metadata (description/version/requires) remains a v2 candidate.
3. **Cross-runtime name variants.** `find-skills`, `mcporter`, and `file-sync` ship differing content per runtime template (verified by diff). The name-keyed catalog reports one representative entry (first-scanned template variant — accurate for 4 of the 6 runtimes; hermes/copaw-legacy values are representative). Per-runtime variant metadata is a v2 schema candidate.
4. **Four-layer skill model (final, 2026-09-11 — supersedes the earlier two-layer sketch and "publish = admin only").** Skills (and MCP, as a design principle) live in four layers: **builtin** (code-bundled template directories) · **individual** (`agents/global/skills/` — catalog `source="shared"`, value retained — plus the Manager seed skills in root-level `skills/`/`skills-alpha/`; the Manager/admin's individual assets, **managed by L1 (admin) only**; the Manager agent is the *managed object* of this layer, not a manager of it) · **team** (`teams//skills/` — team-space root, symmetric with `agents//skills/`; the existing worker team STS policy already covers the prefix, zero new authz infrastructure) · **worker** (`agents//skills/` — the materialized copy layer, the only layer that becomes prompt content). **The Manager agent does not participate in any team-skill path** (explicit declaration, to prevent future designs treating the Manager as a team-skill manager). **Publish (humans):** L2 default-uploads into **their own team** (role AND scope — #1220's capability value set unchanged) with a compensation package (upload scan best-effort + **mandatory scan at materialize-at-assign = the real gate** + team scope + audit + `source`/uploader marking + warn-to-admin); L1 additionally gets `scope=deployment` → individual layer. Uploads must go through the controller API (authz + security scan + audit in one chokepoint; L2 humans hold no MinIO STS, so this is their only write path) — the dashboard's direct-MinIO write pattern (`POST /packages`) carries no RBAC and is scheduled for deletion (F5 cutover: new API live → dashboard + plugin switch → route deleted). **External sources (P2):** skills may also be pulled from the **Nacos AI registry** (v3 `GET /nacos/v3/client/ai/skills`, version/label-aware; the dashboard already lists `custom | nacos | builtin` sources) or the **ClawHub** marketplace (`clawhub.ai`, a native QwenPaw hub origin); a controller-side ClawHub fetcher (fetch → security scan → MinIO → catalog metadata) is required for the MinIO-based materialization path. **Security gate:** QwenPaw ships a content scanner (`security/skill_scanner`, 8 signature categories: command injection, data exfiltration, hardcoded secrets, obfuscation, prompt injection, social engineering, supply chain, unauthorized tool use; block/warn/off modes); no other runtime has an equivalent (verified in-tree). The gate design is a **two-layer scan**: upload-time scan (best-effort fast feedback at the controller chokepoint, executed in a QwenPaw runtime container via the existing executor pattern) + **mandatory scan at materialize-at-assign** (block = not copied + reported; covers every write path, including direct MinIO writes by workers/manager that the existing project pattern already permits). Per-runtime enablement gating stays as-is (`require_bins/envs/mcps` honored on QwenPaw 2.2.x; other runtimes have no equivalent gate — unknown = unverified). **Assign (leader agent, not human):** the team's leader agent assigns via the controller worker-update API (`PUT /workers {skills}` — live since #1212, plus the leader's existing write surface, zero new endpoints; the non-sensitive skills/MCP allowlist per #1220 §5, leaders never hold capabilities). Assignment materializes as a controller copy `teams//skills/` → `agents//skills/` (one-shot copy, consistent with Q5's non-propagation semantics) → worker sync loop ≤ 5min. The team layer deliberately sits outside `teams//shared/` (workers actively mirror `shared/` — inside it, skills would materialize to the whole team with no per-skill gate; the controller copy is the only materialization path and the only gate point). **Catalog (#1211):** no-param read = L1 only (builtin + individual layer, L2 → 400); `?team=T` = builtin + team layer (L1 any / L2 own team / cross-team 404); `source` ∈ {builtin, shared, team} (worker dimension P2).
5. **Runtime consumption caveat.** Not every runtime consumes MinIO-seeded or `spec.skills`-assigned skills — `deepseek-harness` preps skills from its in-image plugin manifest (assignment no-ops until it consumes them). Q3's "worker sync loop" assumption holds for the other runtimes.
6. **Visibility cross-reference (updated 2026-09-11, supersedes the 9/5 global-read state).** The API-level read contract is now the authz-scope table in Q4 above (no-param = L1 only, L2 → 400; `?team=` = team scope). The workbench view keeps the team picker: the Worker×skill matrix is filtered to the selected team's workers, and a per-team "skill assets" view aggregates the team workers' `spec.skills`. Tracked in #1220 §13 Q4 (final).
7. **P2 schema constraint (recorded now to avoid rework).** When marketplace/remote registry support lands, remote entries must reuse the same catalog schema (`name/description/source/version/requirements/runtimes` + redacted `source_uri`), inherit the team-scope view filter, and route credentials through the `external_sources` capability.
8. **Trust boundary (final, 2026-09-11 — supersedes "v1 boundary = admin upload surface").** A skill is prompt content injected into worker context. Since L2 can upload to their own team by default (item 4), the boundary is the **two-layer scan gate**: upload scan (best-effort fast feedback) + **mandatory scan at materialize-at-assign** (the only path by which team skills become prompt content; block = not copied + reported). Structure validation (frontmatter lint, name/dir consistency) + audit + uploader marking + warn-to-admin form the compensation package. Multi-tenancy remains P2.
9. **Audit.** Catalog reads are unprivileged (no audit); assignment writes are audited via `ActionSkillAssign` per #1220 §8–9; publishing (team or deployment scope) is audited at the controller chokepoint (v1 = structured log line; the durable MinIO JSONL layer ships with PR-A per #1220 §8).
---
### Q1 权威目录
部署级 MinIO 共享 Skill 存储(对象级,controller 直接读,只读 list + 元数据)= **唯一权威源**;`Worker.spec.skills` / `spec.remoteSkills` 只是**分配状态**,不是目录来源;dashboard 插件不消费分配/副本状态(Q3 脚注)。
9/11 源码补充实查:
- 目录无团队维度(`oss.Client` 的 `ListObjects` 不支持子前缀过滤 → `?team=`/`?worker=` 需扩展接口)
- 技能无安全扫描(上传走 dashboard 自己的私有 OSS 端点,controller 侧无 scanner)
- dashboard `POST /packages` 直写 MinIO `agents/global/skills/` **零 RBAC**(无认证/无校验/无审计 = prompt 注入面)→ 必须改为走 controller API;dashboard `POST /skills` 上传链路同样零 RBAC,F5 一并替换
- MinIO STS 策略只读 list 已确认(无 PutObject)
F1/F2(`GET /packages` 零 RBAC 只读 list;MinIO 无服务端 filter)保持 open。
**F3 团队/worker 技能路径(2026-09-11 定案)**:`teams//skills/`(team 空间根下,与 `agents//skills/` 对称;`agents/teams//skills/` 候选已废——deployer.go:899 用裸 team 名、worker_env.go:43 带 `agents/` 前缀,同前缀会解析碰撞;既有 worker team STS 已覆盖该路径,零新 authz 基建;⚠️ Manager 不参与团队技能任何路径)。
### Q2 表示
`source: builtin | shared` + `version`/`uploaded_by`/`uploaded_at`;**凭据永不进 metadata**(Q4)。
2026-09-11 起:"uploaded" 覆盖两个 scope——**团队层**(`teams//skills/`,`source: team`)与**单独层**(`agents/global/skills/`,`source: shared` 值保留);`source` 值集 `builtin | shared | team`(worker 维度 P2)。#1211 v1 落地字段集:`name/description/source/version/requirements/updated_at/agents/runtimes`(§8.2)。marketplace / remote registry → P2(凭据走 #1220 external_sources 能力)。
### Q3 三层边界
- **目录元数据**(redacted)
- **分配态**(`Worker.spec.skills`,既有 worker 更新 API 管)
- **运行时副本**(worker 内部,controller 不碰)
**分配是单向拷贝**——assign 时从权威源拷进 worker 前缀,之后不自动传播(传播是 P2 的显式功能,不是意外);worker sync loop ≤5min 是同步机制;dashboard 插件不消费分配/副本状态;P2 远程半侧复用同 schema + 团队 scope 过滤 + `external_sources` 溯源。
### Q4 可见性(9/11 定案,取代 9/3 全局读提案)
**scope 由 authz 决定,不由请求形态决定。**
| 请求 | scope | 访问 |
|---|---|---|
| `GET /api/v1/skills`(无 team 参数) | builtin + 单独层(`agents/global/skills/`) | **仅 L1**;L2 → `400 team scope required`(自解释) |
| `GET /api/v1/skills?team=T` | builtin + `teams/T/skills/` | L1 任意 / L2 本团队;跨团队/未知 T → `404`(防探测) |
分配仍按 #1220 team-scoped。L3 无团队 scope:无参读同 L2 得 400(其 worker scope 读路径不变)。凭据 redaction 是无条件存储不变量(上传时 + 每个 API 响应),不是权限项。多租户隔离 = P2,跟多租户路线图一起设计。
### Q5 共享语义
技能 = **不可变版本对象**,**不随团队共享自动传播**;per-worker 副本是运行时事实;"团队共享技能" = 一次 assign 动作 = **一次性拷贝**(不订阅/不自动同步——传播是 P2 的显式功能);v1 = 对象级操作 + list-on-read(无缓存),删除不级联解绑;团队层刻意放在 `teams//shared/` **之外**(worker 主动镜像同步 `shared/`,放里面会无门控物化到全团队;controller 拷贝是唯一物化路径 = 唯一门控点)。
### §6 对 #1211 的影响(实现)
#1211 v1 分支已实现(2026-09-11,待 review):
- `GET /api/v1/skills` 读 **builtin**(模板扫描,per-runtime 可用性取自 deployer 自己的模板选择函数,目录与实际下发的内置技能永不漂移)+ **单独层**(`agents/global/skills/` 列表 + `updated_at`)
- builtin 条目另含 `version`/`requirements`(QwenPaw 2.2.x frontmatter 语义)
- **鉴权:无参读仅 L1(admin)**;非 admin(L2 人类 / 团队 Leader / Worker / Manager)→ `400 team scope required`
- 团队范围读(`?team=`)与上传 API(`POST /skills` `scope=team`/`deployment`)随 team-skills PR(§8.4)交付,不进 #1211 v1
- skills 资源显式 `ActionList`(无 wildcard)维持
### §7 开放问题
1. 凭据脱敏机制(无 token 时的 MinIO 读路径——STS 只读 list 已确认)
2. builtin 模板版本化(catalog `version` 读 SKILL.md frontmatter,模板目录的版本化另议)
3. ~~目录可见性:无参全局读 vs 团队 scope~~ —— **已解决(9/11 干系人定案:authz scope 契约,见 Q4 定案表)**,等 maintainer 对定案契约表态
### §8 Follow-ups(2026-09-11,#1211-v1 落地后记录)
1. **更新 = 显式不传播**:只覆写 catalog 对象与元数据,不到已分配 worker 的运行时副本;assign 是单次拷贝不是订阅;版本传播(物化版本上报 + 显式 resync)= v2,基于 per-worker 可用端点。
2. **#1211 实现的元数据**:shared = `name` + `updated_at`(列表时间戳,RFC3339 UTC,后端不提供则省略);builtin 另含 `version`/`requirements`(QwenPaw 2.2.x frontmatter 语义);`size`(目录条目是虚拟 0 字节标记,真实大小需递归列读)与 `uploaded_by`(需逐对象 stat)延后 v2;shared SKILL.md 元数据仍是 v2 候选。
3. **跨运行时同名变体**:`find-skills`/`mcporter`/`file-sync` 各运行时模板内容不同(diff 实证);name-keyed 目录报一个代表条目(首个扫到的模板变体——对 6 个运行时中的 4 个精确,hermes/copaw-legacy 为代表性值);per-runtime 变体元数据 = v2 schema 候选。
4. **技能四层模型(9/11 定案,取代双层草图与"publish=admin only")**:
- **builtin**——代码捆绑模板目录
- **单独层**——`agents/global/skills/`(目录 `source="shared"` 值保留)+ 根级 `skills/`/`skills-alpha/` Manager 种子;Manager/管理员的单独资产,**仅 L1(admin)管理**(技能 + MCP;MCP 半留在既有 manager 配置面);Manager agent 是*被管理对象*而非管理者
- **团队层**——`teams//skills/`(team 空间根,与 `agents//skills/` 对称;既有 worker team STS 已覆盖前缀,零新 authz 基建;L1 全部 / L2 本团队);**Manager agent 不参与任何团队技能路径**(显式声明,防未来设计把 Manager 当团队技能管理员)
- **worker 层**——`agents//skills/` 物化副本层,唯一变成 prompt 内容的层
- MCP 同理为设计原则
- **发布(人类)**:L2 默认上传**本团队**(role AND scope——#1220 能力值集不变)+ 补偿包(上传扫描 best-effort + **assign 拷贝强制扫描 = 真门** + 团队 scope + 审计 + `source`/uploader 标记 + warn admin);L1 另有 `scope=deployment` → 单独层
- 必须走 controller API(authz + 安全扫描 + 审计三合一 chokepoint;L2 无 MinIO STS,controller API 是其唯一写路径);dashboard 直写 `POST /packages` 零 RBAC = 已定删除(F5 切流:新 API live → dashboard + 插件切换 → 删路由)
- **外部源(P2)**:Nacos AI 注册表(v3 `GET /nacos/v3/client/ai/skills`,version/label-aware;dashboard 已列 `custom | nacos | builtin` 三源)+ ClawHub(clawhub.ai,QwenPaw 原生 hub origin);MinIO 物化路径需 controller fetcher(fetch → 安全扫描 → MinIO → 目录元数据)
- **安全门**:QwenPaw 自带内容扫描器(`security/skill_scanner`,8 类签名:命令注入/数据外泄/硬编码密钥/混淆/prompt 注入/社会工程/供应链/未授权工具使用;block/warn/off 三档);其他运行时均无同等设施(树内实查)。门 = **双层扫描**:上传时扫描(best-effort 快速反馈,controller chokepoint,经既有 executor 模式在 QwenPaw 运行时容器执行)+ **物化-at-assign 强制扫描**(block = 不拷 + 上报;覆盖所有写路径,含既有项目模式已允许的 worker/manager 直写 MinIO)。per-runtime 启用门控维持现状(`require_bins/envs/mcps` 仅 QwenPaw 2.2.x 生效;其他运行时未知 = 未验证)
- **assign(Leader agent,非人类)**:经 controller worker 更新 API(`PUT /workers {skills}`——#1212 已 live + leader 既有写面,零新端点;#1220 §5 非敏感白名单,leader 永不持有能力)物化为 controller 拷贝 `teams//skills/` → `agents//skills/`(一次性拷贝,与 Q5 非传播语义一致)→ worker sync loop ≤5min;团队层刻意在 `teams//shared/` 之外(controller 拷贝 = 唯一物化路径 = 唯一门控点)
- **目录(#1211)**:无参读 = 仅 L1(builtin + 单独层,L2 → 400);`?team=T` = builtin + 团队层(L1 任意 / L2 本团队 / 跨团队 404);`source` ∈ {builtin, shared, team}(worker 维度 P2)
5. **运行时消费注意事项**:并非所有运行时都消费 MinIO 种子或 `spec.skills` 分配的技能——`deepseek-harness` 从镜像内插件清单准备技能(分配 no-op 直到它开始消费);Q3 的"worker sync loop"假设对其余运行时成立。
6. **可见性交叉引用(9/11 更新,取代 9/5 全局读状态)**:API 层读契约 = 上文 Q4 的 authz scope 表(无参 = 仅 L1,L2 → 400;`?team=` = 团队 scope);工作台视图保留团队选择器(Worker×技能矩阵按选中团队过滤;"团队技能资产"视图聚合团队 Worker 的 `spec.skills`)。跟踪于 #1220 §13 Q4(定案)。
7. **P2 schema 约束(现在记录,避免返工)**:marketplace/远程注册表落地时,远程条目必须复用同一目录 schema(`name/description/source/version/requirements/runtimes` + 脱敏 `source_uri`),继承团队 scope 视图过滤,凭据走 `external_sources` 能力。
8. **信任边界(9/11 定案,取代"v1 边界 = admin 上传面")**:技能 = 注入 worker 上下文的 prompt 内容;L2 默认可上传本团队后(第 4 条),边界 = **双层扫描门**:上传扫描(best-effort 快速反馈)+ **物化-at-assign 强制扫描**(团队技能变成 prompt 内容的唯一路径;block = 不拷 + 上报);结构校验(frontmatter lint、name/dir 一致性)+ 审计 + uploader 标记 + warn-to-admin 构成补偿包;多租户仍 P2。
9. **审计**:目录读无特权(免审计);assign 写经 `ActionSkillAssign` 审计(#1220 §8–9);publish(team 或 deployment scope)在 controller chokepoint 审计(v1 = 结构化日志行;持久化 MinIO JSONL 层随 #1220 §8 的 PR-A 交付)。
---
**关联**:#1211(实现:v1 分支已落地——builtin + 单独层、L1-only 鉴权、`version`/`requirements`/`updated_at`;团队维度 + 上传待定)· #1220(L2 权限与能力模型,交叉引用)。权限面在 #1220(ActionSkillAssign / 目录 scope 契约等),本 issue 管架构面。
贡献指南
这个仓库没有索引到贡献指南
评估
这个 Issue 还没有评估数据。