Skip to content

feat(rest,plugin-security): REST face for the explain engine — GET/POST /api/v1/security/explain (ADR-0090 D6) - #2743

Merged
os-zhuang merged 3 commits into
mainfrom
claude/great-dijkstra-mg1my6
Jul 10, 2026
Merged

feat(rest,plugin-security): REST face for the explain engine — GET/POST /api/v1/security/explain (ADR-0090 D6)#2743
os-zhuang merged 3 commits into
mainfrom
claude/great-dijkstra-mg1my6

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

摘要

ADR-0090 D6(#2696):explain 引擎此前只以进程内 security 服务的形式存在(explain(request, callerContext),security-plugin.ts),没有 REST 路由,任何 UI 都无法调用。本 PR 补上它的 REST 门面,并让鉴权兼容 D12 委托管理:

@objectstack/rest — 新端点 GET/POST /api/v1/security/explain

  • 参数 object / 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;
  • 与 analytics 端点同构:优先解析环境 kernel 自己的 security 服务,单 kernel 部署回落到新增的 securityServiceProvider(由 rest-api-plugin 注入);
  • 在 scoped(/environments/:environmentId)与 unscoped 两个 base path 上都注册。

@objectstack/plugin-security — explain 鉴权兼容委托管理(D12)

  • 解释其他用户此前只认 manage_users;现在也接受一个覆盖目标用户的委托 adminScope(其 BU 子树包含目标用户的业务单元)——能改一个用户授权的管理员,自然可以读"该用户的权限为什么这样解析"。
  • 新增 DelegatedAdminGate.scopesCoverUser(sets, targetUserId),复用网关已有的 resolveHeldScopes / businessUnitsOfUser,解析失败一律 fail-closed。
  • 自解释(不带 userIduserId 为本人)不需要任何能力,保持不变。

测试

  • 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 拒绝 + 自解释放行。
  • 全量:plugin-security 239 通过;rest 226 通过;turbo build(含 d.ts)11 包全绿。

关联

🤖 Generated with Claude Code

https://claude.ai/code/session_01WTubNprerCmJoU1VtUWA93


Generated by Claude Code

…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
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 10, 2026 8:33am

Request Review

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling and removed size/m labels Jul 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/plugin-security, @objectstack/rest.

13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/api/error-catalog.mdx (via @objectstack/rest)
  • content/docs/api/error-handling-server.mdx (via @objectstack/rest)
  • content/docs/api/index.mdx (via @objectstack/rest)
  • content/docs/getting-started/cli.mdx (via @objectstack/plugin-security)
  • content/docs/permissions/access-recipes.mdx (via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx (via packages/plugins/plugin-security, packages/rest)
  • content/docs/permissions/permissions-matrix.mdx (via packages/plugins/plugin-security)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/plugin-security)
  • content/docs/plugins/index.mdx (via @objectstack/plugin-security, @objectstack/rest)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-security, @objectstack/rest)
  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-security, @objectstack/rest)
  • content/docs/ui/dashboards.mdx (via @objectstack/plugin-security)
  • content/docs/ui/role-based-interfaces.mdx (via packages/plugins/plugin-security)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…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
os-zhuang merged commit ac08698 into main Jul 10, 2026
15 of 16 checks passed
@os-zhuang
os-zhuang deleted the claude/great-dijkstra-mg1my6 branch July 10, 2026 08:18
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants