Skip to content

docs(permissions): name declared membershipKeys in the RLS guide's context variables - #26588

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-ervpst
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-ervpst

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Warren · project thread

Fixes #26423

维护者速读

  • 改了什么:RLS 指南「Context variables」表新增 current_user.KEY 一行(链到参考页「Where a membership key comes from」),并重写表后的收尾段:先讲在名册对象上声明 membershipKeys,附一个经类型检查的门户示例,再讲部署侧注册 membership resolver 作为扩展。
  • 为什么改:做门户/合作伙伴访问的作者先读这页指南,旧文只说「部署可注入成员集合」,把他们引向写插件或逐行写策略,而一条 membershipKeys 声明就能解决;参考页与 data 技能早已写明,只缺指南。
  • 风险与回滚:仅改一个手写文档文件,不发布任何包、不动运行时;回滚即 revert 本 PR。
  • 先看:content/docs/permissions/rls.mdx 的 Context variables 一节(新表行与收尾段、示例代码块)。
  • 两分钟验证:grep -c membershipKeys content/docs/permissions/rls.mdx,预期 3;pnpm check:doc-anchors,预期全部片段链接解析通过。
  • 需要你做的:无,席位落地。

What changes

content/docs/permissions/rls.mdx, section ## Context variables only:

  • The table gains a current_user.KEY row: a set a roster object declares under membershipKeys, linked to /docs/references/security/rls#where-a-membership-key-comes-from.
  • The closing paragraph ("Deployments can inject additional membership sets ...") is rewritten to name both sources in the order packages/spec/src/security/rls.zod.ts gives them: a declared key first (userField, valueField, optional filter on the roster object), with one checked example (an account_member roster plus a portal permission set reading account in current_user.portal_account_ids), then a registered membership resolver as the deployment-side extension. It also carries the runtime facts the spec states: read once per request as a system read in the caller's organization, no read on the roster needed, whoever writes roster rows grants the key, a key both sources claim resolves from neither, and an unsupplied key or one over 1,000 values matches no rows.

Shape of truth: MembershipKeySchema / MembershipKeysSchema and the module docblock's "Where a membership key comes from" in packages/spec/src/security/rls.zod.ts, and ObjectSchema.membershipKeys in packages/spec/src/data/object.zod.ts. The example mirrors the one skills/objectstack-data/rules/security.md already type-checks.

Why

The guide is the page an author reads first; it sent them to a deployment-side resolver for what one declared key does. On origin/main 1080f07 the guide had 0 membershipKeys hits while the reference page carried the key.

Tests

Docs-only. The new example carries the os:check marker, so check:skill-examples type-checks it against the built @objectstack/spec declarations.

Acceptance notes

  • Card acceptance: the table carries the current_user.KEY row with the link; grep -c membershipKeys content/docs/permissions/rls.mdx = 3; the anchor resolves (check:doc-anchors green). The docs build is CI's Build Docs job (not run locally).
  • Observed, not fixed (outside the card's surface): the guide's kernel rows list five values, while rls.zod.ts names a sixth the kernel resolves, accessible_org_ids. Noted only.

Verification

All gates run at head c03a2d59 (the only commit; base 1080f074).

Derived gate set: 45 derived, 45 run, all exit 0

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 45 commands from the one-path change set; every one ran with exit 0. check:skill-examples first answered exit 3 (PREREQUISITE NOT MET: packages/client-react/dist unbuilt); after building @objectstack/client-react and its dependencies it answered exit 0 with "266 prose examples type-check across 3 surface(s)". check:doc-anchors: "621 internal #fragment link(s) across 430 source file(s) all resolve to a real heading". check:role-word, check:doc-authoring, check:docs-spec-enumerations, check:nul-bytes: exit 0. Reconciliation (--ran): "45 derived famil(ies) accounted for — 45 run, 0 NOT-MEASURED".

Not measured locally, left to CI: Build Docs, the type-check lanes, Plan Test Core shards.

Clause-②: no
Metadata-protocol: none

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (not touched)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes. (no linted source touched; repo-wide lint is CI's)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (publishes nothing: skip-changeset)
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (not touched)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JQwxbaFpnMwgpCgneKe2qS

…ntext variables

Add the current_user.KEY row to the Context variables table, linked to the
reference page's "Where a membership key comes from", and rewrite the closing
paragraph to name both sources: a membershipKeys declaration on the roster
object first, with one checked example, and a registered membership resolver
as the deployment-side extension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbaFpnMwgpCgneKe2qS
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 27, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Oct 27, 2026
@objectstack-fleet

objectstack-fleet Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor Author

维护者速读

  • 改了什么:RLS 指南 content/docs/permissions/rls.mdx 的「Context variables」一节:表里加 current_user.KEY 一行(链到参考页),表后收尾段重写为两种来源——先在名册对象上声明 membershipKeys(附一个经类型检查的门户示例),再是部署侧注册的 membership resolver。
  • 为什么改:做门户/合作伙伴访问的作者先读这页,旧文只说「部署可注入成员集合」,把人引向写插件;一条 membershipKeys 声明就够。参考页与 data 技能已写明,只缺指南。
  • 风险与回滚:一个手写文档文件,+44/−3,不发包、不动运行时;回滚 = revert 本 PR。
  • 先看:rls.mdx L168 新表行与 L177–218 收尾段。
  • 两分钟验证:grep -c membershipKeys content/docs/permissions/rls.mdx 预期 3;CI Build Docs 与 Lint · docs & code guards 已绿。
  • 需要你做的:无,席位落地。
  • 席位意见:收尾段每条运行时断言都对过源码(见下 ②),示例由 check:skill-examples 类型检查,可落。

席位核对

ACCEPT · domain:devx#1 · session_01JQwxbaFpnMwgpCgneKe2qS · head c03a2d594b · 2026-10-27T09:30Z

  1. Shape: one file, content/docs/permissions/rls.mdx (+44/−3), read via pulls/26588/files; not governed, not a merge=os-regen path, far under 3000 lines. The claim's surface was the table and its closing paragraph; the os:check example sits inside that rewritten passage (dev's declared deviation, accepted).
  2. Premise and claims, measured by the seat on origin/main: 0 membershipKeys hits before (1080f07). Each sentence of the new passage checked against source: userField / valueField / filter = MembershipKeySchema.shape (object-membership-keys.test.ts pins it); "read once per request … as a system read" and "the caller need not read X" = the stageRlsMembership docblock in packages/plugins/plugin-security/src/object-membership-keys.ts and the rls.zod.ts preface; "only when a policy reads the key" = "A key no applicable policy reads is never resolved" (same file); "whoever can write X grants it" = rider 3 there; "a key both sources claim resolves from neither" and "a key neither source supplies … fail closed" = rls.zod.ts "Where a membership key comes from"; 1,000 = MEMBERSHIP_KEY_MAX_VALUES, overflow fails closed.
  3. Gates: head check-runs 48: 32 success, 16 skipped, 0 failing. The skips are path-gated lanes this docs-only diff does not reach (UI lanes, Build Core, Dogfood, opt-in harnesses) plus Check Changeset, skipped by skip-changeset. Not machine-checked by check-expected-skips.mjs (its yaml import is not installed in the seat checkout). Dev's local dispatch-gates --ran: 45 derived, 45 run, 0 not measured.
  4. Accepted deviations: the example's placement (item 1). Clause-②: no holds: no packages/spec/src/** path, docs only.
  5. Out of scope: the guide's kernel rows list five values, but rls.zod.ts names a sixth, accessible_org_ids → Acceptance notes, not filed (a one-row completeness gap on the same page, below the filing gate). Skills-docs: not owed (Metadata-protocol: none).
  6. Landing: not governed, CI green on this head, mergeable clean ⇒ the seat readies it and arms auto-merge through the relay.

Generated by Claude Code

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/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(permissions): the RLS guide's Context variables section never names the declarative membershipKeys / current_user.KEY set

2 participants