feat(controller): capability foundation for the L2 permission model (#1220) - #1237
Open
LUOSENGWA wants to merge 3 commits into
Open
feat(controller): capability foundation for the L2 permission model (#1220)#1237LUOSENGWA wants to merge 3 commits into
LUOSENGWA wants to merge 3 commits into
Conversation
…e set and HasCapability helper L2 permission model (agentscope-ai#1220) step 1 of 3 — capability foundation: - Human CR gains spec.capabilities (five-value set per agentscope-ai#1220 §3: full_access, channel_secrets, external_sources, approval_policy, secret_reveal). CRD schemas (controller config + helm) updated; deepcopy regenerated via controller-gen. - internal/auth/capability.go is the single source of truth for the value set (constants + ValidCapabilities + Normalize + ValidCapabilityList); TestValidCapabilitiesMatchesDocumentedValueSet pins the set against the documented five values. - CallerIdentity.Capabilities is populated for L2 humans by the Matrix authenticator (the Human CR is already fetched there — zero new I/O); SA-based identities (admin/manager/leader/worker) never carry capabilities (agentscope-ai#1220 §5). - HasCapability(caller, cap): role baseline first (admin/manager true, worker false, human/team-leader set membership with full_access meta-implication). A capability never implies team scope — callers still enforce TeamMatches. This commit gates no existing operation; the human-update API field and the audit client land in the follow-up commits.
…ate API
PUT /api/v1/humans/{name} accepts capabilities with the same
merge-patch semantics as accessibleTeams (landed in agentscope-ai#1209): absent =
unchanged, explicit list = replaces, [] = clears. Unknown values are
rejected with a 400 listing the closed value set (the set itself is
owned by internal/auth, so there is exactly one source of truth).
Values are stored in canonical form (deduped + sorted).
Access control is unchanged: only admin/manager may update humans —
self-grant was already structurally impossible (the authorizer has no
human-resource case for leader/human/worker roles) and is pinned by the
pre-existing TestAuthorizer_HumanUpdateAdminOnly (agentscope-ai#1209).
HumanResponse now echoes capabilities so grants are observable on GET.
…nt/revoke events internal/audit (agentscope-ai#1220 §8): - layer 1: an immediate structured log line, always (nil storage degrades to log-only); - layer 2: append-only audit/<YYYY-MM-DD>.jsonl (UTC date) written read-modify-write with PutObjectIfMatch ETag-optimistic concurrency and 3 retries (100/200/400ms + jitter); in-process concurrency serialized by a client mutex; durable layer assumes a single controller replica. - Event is a closed schema (no free-text field a secret could hide in), pinned by a secret-hygiene test. UpdateHuman now records one event per changed capability value (capability_grant / capability_revoke) through the same client later consumers (agentscope-ai#1216 OFF gate, external_sources restore, secret contract) will reuse. Audit failures never break the update. Docs: new design/capability-foundation.md (value set, contract table, audit design, known limitations); humans-update-api.md, usage resource-management EN/ZH updated.
LUOSENGWA
marked this pull request as ready for review
September 13, 2026 06:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Capability foundation for the L2 permission model (#1220)
Summary
This PR is step 1 of the #1220 sequencing — the capability model foundation: grantable, queryable, auditable, but gating no existing operation. It adds:
Human.spec.capabilities— the five-value set from Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §3 (full_access,channel_secrets,external_sources,approval_policy,secret_reveal); unknown values are rejected at admission. CRD schemas (controller + helm) updated, deepcopy regenerated.PUT /api/v1/humans/{name}— a new merge-patchcapabilitiesfield mirroring theaccessibleTeamspattern from feat(controller): add human update endpoint (PUT /api/v1/humans/{name}) #1209: absent = unchanged, explicit list = replace,[]= clear, unknown value =400listing the valid set. Stored normalized (deduped + sorted). Admin/manager-only as before — self-grant is structurally impossible (authorizer default-deny, pre-existing pin test).auth.HasCapability(caller, cap)— role baseline first (admin/manager true, worker false, human/team-leader set membership withfull_accessas a meta-implication). A capability never implies team scope; consumers compose the Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §3 check order (role baseline ANDTeamMatchesANDHasCapability). Populated for L2 humans where the Human CR is already fetched (zero new I/O); SA identities never carry it (Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §5 — leaders never hold capabilities).internal/audit— dual-layer audit client (Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §8): an immediate structured log line + append-only dailyaudit/<YYYY-MM-DD>.jsonlwith ETag-optimistic writes (3 retries, 100/200/400 ms + jitter). Closed event schema — never secret values. Wired for capability grant/revoke (one event per changed value).Interface-stability promise for the follow-on PRs: the
Capabilitytype, the five constants, and theHasCapabilitysignature are the consumer contract and will not be renamed.Design
accessibleTeamspattern from #1209 — the human-update API is a single merge-patch endpoint, and a third "set" mode would be inconsistent with it.HasCapability= role baseline first, and never implies team scopeTeamMatchesANDHasCapability; a helper that implied scope would let a consumer skipTeamMatchesand silently widen scope.What this PR does not do
HasCapabilityhas zero production call sites; the audit wiring is grant/revoke events only).secret_revealconsumer (reserved value; the secret contract is a follow-on PR).capabilitiesfield.Tests
400(5 cases)HasCapabilitymatrix — admin / manager / L2±value /full_access/ worker / leader / nil callerPUT /humansgrant×2 + revoke → JSONL event assertionsgofmt/go build ./.../go vet ./.../go test ./...— 22 packages ok, zero failures (baseline + the newinternal/auditpackage). Branch diff scanned: no credential patterns.HasCapability+ authenticator population ② API field + validation + tests ③ audit client + wiring + docs.Related
approval_policyOFF gate for feat(controller): add team-scoped worker tool approval endpoints for L2 humans #1216's already-merged approval endpoints, the mcpServers/remoteSkills restore withexternal_sources, and feat(controller): add worker channel configuration proxy endpoints #1219 (secret contract) withchannel_secrets/secret_reveal.f65d6e1a) — its OFF gate is currently a pure role gate; the error text says "pending the Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 design", i.e. the capability check this PR lands.L2 权限模型的 capability 地基(#1220)
摘要
本 PR 是 #1220 定序的第 1 步——capability 模型地基:可授、可查、可审计,但不门控任何现有操作。新增:
Human.spec.capabilities—— Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §3 五值集(full_access/channel_secrets/external_sources/approval_policy/secret_reveal),未知值准入即拒。CRD schema(controller + helm)已更新,deepcopy 已再生成。PUT /api/v1/humans/{name}—— 新增 merge-patch 语义的capabilities字段,镜像 feat(controller): add human update endpoint (PUT /api/v1/humans/{name}) #1209 的accessibleTeams模式:省略=不变 / 显式列表=替换 /[]=清空 / 未知值=400(错误信息列合法值集)。存储前规范化(去重+排序)。沿用 admin/manager 独占——self-grant 结构上不可能(authorizer 默认拒绝,既有钉测试在位)。auth.HasCapability(caller, cap)—— 角色基线优先(admin/manager 恒真、worker 恒假、human/team-leader 集成员 +full_access元值蕴含)。capability 从不蕴含团队范围;消费侧按 Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §3 顺序组合(角色基线 ANDTeamMatchesANDHasCapability)。L2 human 在 Human CR 已拉取处填充(零新增 I/O);SA 身份永不携带(Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §5——leader 永不持有 capability)。internal/audit—— 双层审计 client(Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 §8):即时结构化日志行 + 每日audit/<YYYY-MM-DD>.jsonl追加写(ETag 乐观并发,3 次重试 100/200/400ms + 抖动)。事件为封闭 schema——永不记 secret 值。已接线 capability grant/revoke(每变更值一条事件)。接口稳定承诺(面向后续 PR):
Capability类型、五个常量、HasCapability签名 = 消费契约,不改名。设计
accessibleTeams模式——human-update API 是单一 merge-patch 端点,再加第三种 "set" 模式不自洽。HasCapability= 角色基线优先,且从不蕴含团队范围TeamMatchesANDHasCapability;若 helper 蕴含 scope,消费侧可能跳过TeamMatches而静默扩大范围。本 PR 不做
HasCapability0 生产调用;审计接线仅 grant/revoke 事件)。secret_reveal消费方(保留值;secret 契约是后续 PR)。capabilities字段。测试
400(5 例)HasCapability矩阵——admin/manager/L2±值/full_access/worker/leader/nil callerPUT /humansgrant×2 + revoke → JSONL 事件断言gofmt/go build ./.../go vet ./.../go test ./...——22 包全 ok、0 失败(基线 + 新internal/audit包)。分支 diff 扫描:无凭据形态。HasCapability+认证填充 ② API 字段+校验+测试 ③ 审计 client+接线+文档。相关
approval_policyOFF 门控、带external_sources的 mcpServers/remoteSkills 恢复、feat(controller): add worker channel configuration proxy endpoints #1219(secret 契约)带channel_secrets/secret_reveal。f65d6e1a)——其 OFF 门控现状 = 纯角色门,错误文案明说 "pending the Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 design" = 本 PR 落地的 capability 检查。