fix(plugin-security): explain posture 证据对齐 enforcement 派生(消除标签漂移) - #2949
Merged
Conversation
Security review 低危项。explain-engine 的 derivePosture 之前用松名字匹配作证据 (permissions.includes(ADMIN_FULL_ACCESS) 不校验非作用域 + positions org_owner/org_admin 读 better-auth 角色),比 enforcement(hasPlatformAdminGrant:要求非作用域 admin_full_access user grant;TENANT_ADMIN 用 organization_admin 能力)更松,可能让 explain 面板显示偏高的 posture 标签(作用域 org-admin grant 被误标 PLATFORM/TENANT_ADMIN)。 - 优先直接消费 ctx.posture(principal 经完整 resolveAuthzContext 时逐字返回,结构上不可能漂移)。 - 回退(buildContextForUser 自建 context):复制 enforcement 的非作用域 grant 判定—— buildContextForUser 现按与 hasPlatformAdminGrant 逐字节一致的规则(admin_full_access 且 organization_id==null 的 active user grant)计算并挂出 hasPlatformAdminGrant;derivePosture 以此 + 投影出的 platform_admin 内建岗位判 PLATFORM_ADMIN,以 organization_admin 能力判 TENANT_ADMIN,不再读 org_owner/org_admin 角色岗位(ADR-0095 D3)。 - 保留 explain 特有的 guest→EXTERNAL 底并置于最前。 只改 posture 标签证据,不改 explain verdict、不改 enforcement。#2947 更广缺口不在范围。关联 #2920。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
os-zhuang
marked this pull request as ready for review
July 15, 2026 04:33
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
added a commit
that referenced
this pull request
Jul 15, 2026
…2956) The ADR-0095 D2 posture ladder is derived once by the shared authz resolver from capability grants, but both entry points that build the ExecutionContext (rest-server, runtime resolveExecutionContext) dropped it — so any enforcement-side reader of context.posture always saw undefined (the same drop that forced the explain layer to re-derive it, #2949). - spec: ExecutionContextSchema gains an optional `posture` field (reuses AuthzPostureSchema; no api-surface change — schema tracked as a const). - rest + runtime: plumb authz.posture through when present. - tests: assert PLATFORM_ADMIN / MEMBER are carried and guest stays unset. Additive and behavior-preserving: no enforcement decision consumes posture yet. Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs Co-authored-by: Claude <noreply@anthropic.com>
xuyushun441-sys
pushed a commit
that referenced
this pull request
Jul 17, 2026
…ole coverage The previous revision under-covered the line in three ways, now fixed: 1. 15.0.0 was missing everything outside the ADR-0095 theme from the 14.8.0..15.0.0 range: the strict view/page schema BREAKING change (ADR-0089 D3a, #2943) with its migration, the per-row import automation chain + skipAutomations + runAutomations-default-ON behavior change (#2922), the sys_position/sys_capability system-row write guardrail (#2930), the bidirectional visibility lint (#2931), and the explain posture-label alignment (#2949). 2. 15.0.0 had NO Console section at all, despite bundling the objectui 14.0 major (13.2.0→14.0.0, ~73 commits — first release-page disclosure since much of it rode unversioned in the 14.8.0 pin): the ADR-0057 ChatDock consolidation (including its breaking cleanup #2475), the Gantt batch, lists/forms/auth/Studio/i18n enhancements, two security fixes (#2485/#2410), and the six early-14.1 commits the 15.0.0 pin picked up. 3. The 15.1.0 sections were over-compressed; every domain is now expanded to its full changeset detail, and the Console 14.1 section covers all eight areas of the 94-commit range instead of seven bullets. 465 → ~1000 lines; structure mirrors v14.mdx (per-minor annotations inside one major page, per docs/releases-maintenance.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 17, 2026
…ole coverage (#3082) * docs(releases): expand v15 page to full 14.8→15.0→15.1 backend + Console coverage The previous revision under-covered the line in three ways, now fixed: 1. 15.0.0 was missing everything outside the ADR-0095 theme from the 14.8.0..15.0.0 range: the strict view/page schema BREAKING change (ADR-0089 D3a, #2943) with its migration, the per-row import automation chain + skipAutomations + runAutomations-default-ON behavior change (#2922), the sys_position/sys_capability system-row write guardrail (#2930), the bidirectional visibility lint (#2931), and the explain posture-label alignment (#2949). 2. 15.0.0 had NO Console section at all, despite bundling the objectui 14.0 major (13.2.0→14.0.0, ~73 commits — first release-page disclosure since much of it rode unversioned in the 14.8.0 pin): the ADR-0057 ChatDock consolidation (including its breaking cleanup #2475), the Gantt batch, lists/forms/auth/Studio/i18n enhancements, two security fixes (#2485/#2410), and the six early-14.1 commits the 15.0.0 pin picked up. 3. The 15.1.0 sections were over-compressed; every domain is now expanded to its full changeset detail, and the Console 14.1 section covers all eight areas of the 94-commit range instead of seven bullets. 465 → ~1000 lines; structure mirrors v14.mdx (per-minor annotations inside one major page, per docs/releases-maintenance.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(releases): note post-14.1 fixes carried by the final Console pin (#2615/#2617/#2619/#2620/#2621/#2623) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(releases): add v15 to the releases index; mark v14 line final at 14.8.0 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 17, 2026
…nt path, no explicit deny (#3109) Follow-through on ADR-0095: the derived posture rung is carried on the ExecutionContext since #2956 but no enforcement decision reads it — each tier decision re-derives principal tier from capability bits at its own site, the divergence class behind #2946 Finding 2 (org admin crossed the tenant wall) and #2949 (explain/enforcement posture split). - D1: posture becomes the single tier-adjudication input (Layer 0 exemption, Layer 1 short-circuit tier, explain); capability probe demoted to narrowing fallback; behavior-preserving behind an equivalence gate in the authz matrix. - D2: normative posture → layer action map with six invariants (TENANT_ADMIN never crosses Layer 0; enforcement and explain read the same carried value; posture selects tier, never side; never bypasses system-only write guards). - D3: EXTERNAL rung activation chain (audience:'external' → derivePosture → explicit-shares-only injection), matrix cells land now, implementation demand-gated on an external principal type (portal track). - D4: explicit deny/muting rejected as an adjudication primitive; needs mapped to capability gates / FLS / admission / validity windows; assembly-time muting reserved to a future permission-set-groups ADR. Composes with ADR-0096 (admission vs tiering — orthogonal axes). Number 0099 verified free of open-PR claims before push. Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Jul 18, 2026
Merged
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.
背景(Security review 低危 — posture 标签漂移)
explain-engine 的
derivePosture(context)用松名字匹配作 posture 证据:permissions.includes(ADMIN_FULL_ACCESS)— 纯名字,不校验非作用域;positions.includes('org_owner' / 'org_admin')— 读 better-auth 角色岗位。而 enforcement(
packages/core/src/security/resolve-authz-context.ts)的派生更严:hasPlatformAdminGrant=admin_full_access且非作用域(organization_id == null)的 user grant(sys_user_permission_set);TENANT_ADMIN←organization_admin能力(ctx.permissions.includes(ORGANIZATION_ADMIN)),不读角色岗位(ADR-0095 D3:角色是 provisioning 来源,非裁决输入)。后果:一个作用域
admin_full_accessgrant(或org_owner/org_admin角色)会让 explain 面板给运维显示偏高的 PLATFORM/TENANT_ADMIN 标签。这不改变 explain 的 allow/deny verdict(verdict 来自复用的 enforcement filter),只是 posture 标签漂移。修法(让 explain 的 posture 走与 enforcement 同一份证据)
ctx.posture:principal 经完整resolveAuthzContext时已带 enforcement 派生的 rung,derivePosture逐字返回 → 结构上不可能漂移。buildContextForUser自建 context,不经完整resolveAuthzContext,故无posture):复制 enforcement 的非作用域 grant 判定——buildContextForUser现按与hasPlatformAdminGrant逐字节一致的规则(名字admin_full_access且该 user grant 行organization_id == null且在有效期内)计算并挂出hasPlatformAdminGrant;derivePosture以hasPlatformAdminGrant或投影出的platform_admin内建岗位(该岗位本身只由该 grant 投影而来 — ADR-0068 D2)判PLATFORM_ADMIN;以organization_admin能力判TENANT_ADMIN;不再读org_owner/org_admin角色岗位。guest → EXTERNAL(enforcement floor 是 MEMBER),且置于最前(即便挂了 posture 也先落 EXTERNAL)。范围:只改 explain 的 posture 标签证据 —— 不改 explain 的实际 verdict、不改 enforcement。#2947 已跟踪「posture 未 plumb 进 enforcement context」的更广缺口;本 PR 不做 plumbing,只让 explain 侧派生与 enforcement 派生一致。
测试(实测)
pnpm --filter @objectstack/plugin-security test:423 passed / 18 files(含 authz-matrix-gate、conformance 等)。explain-engine.test.ts33 passed,新增/更新:ctx.posture→ 逐字返回(含"显式 posture 覆盖松回退")。admin_full_access(名字在permissions、无 unscoped grant、无 platform_admin 岗位)→ MEMBER,不再误标 PLATFORM_ADMIN。hasPlatformAdminGrant: true→ PLATFORM_ADMIN;投影platform_admin岗位 → PLATFORM_ADMIN。org_owner/org_admin角色岗位(无 organization_admin 能力)→ MEMBER(漂移移除);organization_admin能力 → TENANT_ADMIN。buildContextForUser:非作用域 admin_full_access user grant →hasPlatformAdminGrant: true;作用域 →false(名字仍进 permissions,但不再赋 platform_admin posture)。tsc 对改动文件无类型错误(仓库既存的
@objectstack/platform-objects/pagesDTS 缺失与本改动无关,位于未触及的security-plugin.ts)。关联 #2920,跟踪 #2947。
🤖 Generated with Claude Code
https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs
Generated by Claude Code