feat(rest,plugin-security): REST face for the explain engine — GET/POST /api/v1/security/explain (ADR-0090 D6) - #2743
Merged
Merged
Conversation
…ST /api/v1/security/explain (ADR-0090 D6, #2696) The D6 explain engine shipped service-only ('security'.explain); no UI could reach it. Add the admin-facing REST endpoint and the D12 authority it needs: - @objectstack/rest: GET/POST {base}/security/explain (object/operation/ userId validated against ExplainRequestSchema) delegating to the security service's explain(request, callerContext). Authenticated-only (401 even on requireAuth=false), 501 without a security service, PermissionDeniedError → 403. Env-kernel service preferred; new securityServiceProvider host fallback wired by the REST plugin. - @objectstack/plugin-security: explainAccessForCaller honors delegated administration (D12) — explaining another user is authorized by manage_users OR a delegated adminScope whose BU subtree covers the target user (new DelegatedAdminGate.scopesCoverUser, fail-closed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WTubNprerCmJoU1VtUWA93
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…12 explain authorization Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WTubNprerCmJoU1VtUWA93
Both sides added a securityServiceProvider (mine for /security/explain, main's for /security/suggested-bindings): kept one shared provider, kept main's registerSecurityEndpoints (suggested-bindings) and renamed the explain registrar to registerSecurityExplainEndpoints. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WTubNprerCmJoU1VtUWA93
os-zhuang
added a commit
that referenced
this pull request
Jul 10, 2026
Ships the ADR-0090 v2 UI surface into the vendored console: spec-13 adoption + position relabel + external OWD dial + matrix OWD badges (objectui#2369), the D5 suggested-audience-binding install prompt + Access-pillar banner (objectui#2376, pairs with #2746), and the D6 'why can this user access?' explain panel (objectui#2375, pairs with #2743). Console rebuilt and bundle canary verified at this sha. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
13 tasks
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.
摘要
ADR-0090 D6(#2696):explain 引擎此前只以进程内
security服务的形式存在(explain(request, callerContext),security-plugin.ts),没有 REST 路由,任何 UI 都无法调用。本 PR 补上它的 REST 门面,并让鉴权兼容 D12 委托管理:@objectstack/rest— 新端点GET/POST /api/v1/security/explainobject/operation/userId?(GET 走 query,POST 走 body),用 spec 的ExplainRequestSchema校验(400);security服务的explain(request, callerContext)(即SecurityPlugin.explainAccessForCaller)——与强制执行中间件同一条代码路径,"explained by construction";requireAuth=false也返回 401);服务抛出的PermissionDeniedError映射为 403;没有挂载 plugin-security 时返回 501;security服务,单 kernel 部署回落到新增的securityServiceProvider(由rest-api-plugin注入);/environments/:environmentId)与 unscoped 两个 base path 上都注册。@objectstack/plugin-security— explain 鉴权兼容委托管理(D12)manage_users;现在也接受一个覆盖目标用户的委托adminScope(其 BU 子树包含目标用户的业务单元)——能改一个用户授权的管理员,自然可以读"该用户的权限为什么这样解析"。DelegatedAdminGate.scopesCoverUser(sets, targetUserId),复用网关已有的resolveHeldScopes/businessUnitsOfUser,解析失败一律 fail-closed。userId或userId为本人)不需要任何能力,保持不变。测试
packages/rest/src/security-routes.test.ts(新):路由注册、POST/GET 委托与参数解析、401(匿名)、400(缺 object / 非法 operation)、403(权限拒绝映射)、501(无服务)、500(异常)——8 个用例。packages/plugins/plugin-security/src/security-plugin.test.ts:新增explainAccessForCaller (ADR-0090 D6/D12)块 —— 委托管理员可解释子树内用户、子树外拒绝、manage_users路径回归、无能力且无 scope 拒绝 + 自解释放行。turbo build(含 d.ts)11 包全绿。关联
docs/adr/0090-permission-model-v2-concept-convergence.md(D6、D12)🤖 Generated with Claude Code
https://claude.ai/code/session_01WTubNprerCmJoU1VtUWA93
Generated by Claude Code