Skip to content

feat(spec): C2-α — explain 契约扩展到 record 粒度 (#2920)#2928

Merged
os-zhuang merged 1 commit into
mainfrom
claude/authz-c2-explain-contract
Jul 14, 2026
Merged

feat(spec): C2-α — explain 契约扩展到 record 粒度 (#2920)#2928
os-zhuang merged 1 commit into
mainfrom
claude/authz-c2-explain-contract

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

C2-α — explain 契约扩展到 record 粒度

Contract-first slice of C2「记录级共享 debugger」 (tracking #2920). This PR extends the ADR-0090 D6 access-explanation contract (@objectstack/spec) from object+operation+FLS granularity down to record granularity — schema/types only. No engine (explain-engine.ts untouched) and no UI changes. That is C2-β, which this contract unblocks so framework and objectui can build in parallel.

Contract design

Request side

  • ExplainRequest.recordId (optional) — explain one concrete record at row granularity ("why can user X do OP on record Y?"). Omitted = the pre-C2 object-level question, answered identically. Backward compatible.

Response side — row-level attribution (populated only for record-grained requests)

  • ExplainMatchedRule (new) — one concrete rule that governed the record at a layer: kind ∈ {tenant_filter, owd_baseline, ownership, record_share, sharing_rule, team, territory, rls_policy}, plus grants (SharingLevel), via, predicate, and effect (admits/excludes/neutral).
  • ExplainRecordAttribution (new) — a layer's per-record determination: outcome (admitted/excluded/not_evaluated), effective rowFilter, matchesRecord, matched rules[], detail. Attached as the optional ExplainLayer.record.
  • ExplainDecision.record (new, optional) — the row-level bottom line: recordId, visible, decidedBy (the decisive layer).

Together these carry the β-phase "逐层展开" trace: permission set → 岗位 → 共享 → 行规则 → 有效行过滤 (contributors express set/position; record.rules + rowFilter express share → row rule → effective filter).

Reserved for the ADR-0095 kernel chain (optional/additive; β engine fills)

  • New tenant_isolation layer id — Layer 0, the always-first tenant wall (D1). The layer enum grows to ten ids.
  • ExplainLayer.kernelTier (layer_0_tenant | layer_1_business) — lets a consumer answer "Layer 0 挡的还是业务 RLS 挡的" without hard-coding ids.
  • AuthzPosture enum (PLATFORM_ADMIN > TENANT_ADMIN > MEMBER > EXTERNAL, D2) exposed as optional ExplainDecision.principal.posture.

What β (engine + UI) gets to fill

  • explain-engine.ts: thread recordId through, emit tenant_isolation layer + kernelTier per layer, resolve principal.posture, and populate each layer's record (from the sharing service + RLS compiler outputs already used by enforcement — "explained by construction") and the top-level record verdict.
  • objectui: render the per-record layer-by-layer expansion from ExplainLayer.record.rules / rowFilter and the record.decidedBy summary; posture/kernelTier drive the "tenant wall vs business RLS" and posture-tier framing.

Verification

  • pnpm --filter @objectstack/spec build (typecheck + dts) ✓
  • pnpm --filter @objectstack/spec check:api-surface ✓ (new exports registered)
  • Contract tests extended (round-trip of new fields, backward-compat of object-level requests, enum locks). Full spec suite: 6771/6771 passing.
  • Changeset added (@objectstack/spec minor).

Backward compatibility: every new field is optional or additive; existing object-level requests and reports parse unchanged.

Relates to #2920.

🤖 Generated with Claude Code

https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs


Generated by Claude Code

Extend the ADR-0090 D6 access-explanation contract to record granularity
(schema only; no engine or UI changes). Adds optional recordId on the request;
per-record attribution (ExplainMatchedRule, ExplainRecordAttribution, the
optional ExplainLayer.record, and top-level ExplainDecision.record) on the
response; and reserves the ADR-0095 kernel-chain vocabulary for the β engine:
the tenant_isolation Layer 0 id, ExplainLayer.kernelTier, and the AuthzPosture
ladder on principal. Every new field is optional/additive — object-level
requests parse unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs
@vercel

vercel Bot commented Jul 14, 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 14, 2026 3:54pm

Request Review

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

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

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

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)

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.

@os-zhuang os-zhuang marked this pull request as ready for review July 14, 2026 23:45
@os-zhuang os-zhuang merged commit ed61c9b into main Jul 14, 2026
17 checks passed
@os-zhuang os-zhuang deleted the claude/authz-c2-explain-contract branch July 14, 2026 23:45
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