Skip to content

docs(adr): repoint three security-plugin.ts symbol anchors to declarations the class keeps - #25316

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-25314-adr-anchor-repoint
Oct 23, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-25314-adr-anchor-repoint

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

Fixes #25314
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6353073966

Tier H (docs/adr/**, AGENTS.md Prime Directive 14): this PR stays a draft and lands only on an APPROVED review by a GOVERNED_APPROVERS account. No seat readies, queues or arms auto-merge on it.

维护者速读(草稿)

改了什么 — 三个 ADR 锚点的拼写,别无其它(无正文改动、无 anchor-exempt 标记、无其它文件)。路径前缀均为 packages/plugins/plugin-security/src/security-plugin.ts:

位置 之前 之后 理由
ADR-0055:26 #sharingModel(读派生 computeControlledByParentFilter 内的局部 const) 文件级锚点(去掉 #symbol) 句子讲的是 #1994 按 id 写前像复读,即 start() 中间件内联的 step 2.7,没有自己的符号;门禁头注对此的处方就是「drop to a file-level path」
ADR-0055:58 #controlled_by_parent(读派生里的三处字符串字面量,literal 级) #assertControlledByParentWrite §3 描述的正是这个 step 2.8 主表编辑闸:解析主表 id、按主表 edit 写过滤复读、null 即拒;本 ADR 第 125 行 "What both halves do now" 的 Write 条已用同一锚点
ADR-0123:4 #refuseNoActiveOrganization(composeWriteTenantWall 内的局部闭包) #composeWriteTenantWall 句子说 D2 的拒绝「从唯一拼写处抛出 … step 3.7」;该方法就是 step 3.7 Layer 0 写租户墙的唯一组合处,闭包住在它里面

为什么改 — #25223 的只搬不改拆分要把这些函数体搬出 security-plugin.ts;旧锚点只靠函数体内的 token 碰巧拼写相同才解析,一搬就 unresolved-symbol(在撤回的五体切头 94ef3e320f 上已复现)。新目标是拆分各切都保留在类上的方法声明(或文件本身),之后任何搬动都不会再悄悄弄断它们。

风险与代价(含回滚) — 零运行时影响,只动 3 行文档。回滚即 revert 本 PR。

席位意见 —

你要做的 — 审阅三处新指向是否对得上句子;同意即 APPROVE。若不同意其中某处,点名改法即可(候选见裁决 6353073966 第 3 条)。

Why each target (one line each)

  • ADR-0055:26 → file-level. The sentence describes the pre-existing fix(security)[P0]: enforce RLS on by-id writes — close member-edits-others'-records hole (#1985) #1994 by-id pre-image re-read (2.7. Row-level WRITE authorization (pre-image check)., inline in the start() middleware) — no symbol of its own exists, and the ruling's other candidate #checkControlledByParentWrite re-reads the MASTER, not "the target row under the write-op RLS filter", so the gate header's file-level remedy is the honest pointer.
  • ADR-0055:58 → #assertControlledByParentWrite (not the ruling's first candidate #checkControlledByParentWrite). §3's sentence is the master-edit write gate for update/delete/create: resolve the master id, re-read the master under its edit write filter, deny on null. That is assertControlledByParentWrite (step 2.8, :9654), which the middleware calls directly. checkControlledByParentWrite (:9492) is the served ISecurityService member that wraps it for one by-id update and returns an outcome instead of throwing. ADR-0055:125 already anchors the write half to #assertControlledByParentWrite, and ruling 6353073966 lists it among the method shells the class keeps across every cut. If the maintainer prefers the ruling's candidate, it is a one-token amend.
  • ADR-0123:4 → #composeWriteTenantWall. Step 3.7's Layer 0 tenant write wall, "the ONE spelling of the wall's judgement of a row" by its own docblock; the refuseNoActiveOrganization closure lives inside it.

Anchor readings

Measured with extractAnchors / symbolSegmentResolution / symbolResolutionClass from scripts/symbol-anchors.mjs (comments stripped as the gate strips them), on origin/main 258f4e6aa (base) and this head 0dafb657eb; security-plugin.ts is byte-identical in both.

anchor before: class · line(s) after: class · line(s)
ADR-0055:26 #sharingModel · declaration · :9208 (local const in computeControlledByParentFilter) file-level (path only, still checked)
ADR-0055:58 #controlled_by_parent · literal · :9035, :9209, :9275 #assertControlledByParentWrite · declaration · :9654
ADR-0123:4 #refuseNoActiveOrganization · declaration · :8499 (local closure in composeWriteTenantWall) #composeWriteTenantWall · declaration · :8432

node scripts/check-adr-symbol-anchors.mjs (under os-verify-lock):

  • base 258f4e6aa: exit 0 — 2383 anchors across 142 records resolve — 467 symbol (440 declaration, 27 literal), 1888 file-level.
  • head 0dafb657eb: exit 0 — 2383 anchors across 142 records resolve — 466 symbol (440 declaration, 26 literal), 1889 file-level.

The declaration count is flat, not +1: ADR-0055:58 moves literal → declaration (+1) and ADR-0055:26 moves declaration → file-level (−1). The literal count drops by one.

Tests and gates

Docs-only diff; no package touched, so no build closure, no package tests, no ablation.

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 0dafb657eb derived 20 families for the two changed paths; each ran under scripts/pm/os-verify-lock.sh, all exit 0: check-adr-links (+ --self-test), check-adr-symbol-anchors (+ --self-test), check-ci-filter-parity, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus, @objectstack/lint check:doc-formula-expressions (first run exit 3 PREREQUISITE NOT MET; re-run exit 0 after the prescribed turbo run build --filter=@objectstack/formula --filter=@objectstack/lint), check:adr-anchors, check:closed-ceremony-text, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:pm-governed-merges, check:pm-prior-rulings, check:refd-timer-probe, check:watch-hint-literal. --ran reconciliation: 20 derived, 20 run, 0 NOT-MEASURED (a derived zero, every line carrying its exit code).

Changeset

None: docs/adr/** publishes nothing from any released package, so this PR carries skip-changeset.

Acceptance notes

  • #checkControlledByParentWrite resolves as declaration on three lines, not one: the method at :9492 and two object-literal service members at :2442 and :5346. It is not used by this PR; noted for whoever amends ADR-0055:58 to it.
  • ADR-0055:58's sentence says "In the pre-image block"; the master-edit gate is step 2.8, the block right after the step 2.7 pre-image check, and it covers six operations (insert/update/delete/transfer/restore/purge) where the sentence names three. The sentence reads narrower than the code, not false; no prose was changed here (gate header: "Do not repair prose to clear this gate"). Carrier: none.
  • A file-level anchor is not judged by symbol, so a later cut that moves the step 2.7 middleware out of security-plugin.ts (the cut-9+ plan) will not red on ADR-0055:26; that cut's own anchor map (ruling 6353073966 item 2) is what covers it.

🤖 Generated with Claude Code

https://claude.ai/code/session_016g7nYP9wdNx1GDa5XDr7Uy

…kens

ADR-0055 Context item 3 drops to a file-level anchor (the #1994 by-id
pre-image check is inline step 2.7 and has no symbol of its own); ADR-0055
section 3 points at assertControlledByParentWrite, the master-edit write
gate it describes; ADR-0123's amendment points at composeWriteTenantWall,
the step 3.7 wall that spells the refusal. Anchor spellings only, no prose.

Claude-Session: https://claude.ai/code/session_016g7nYP9wdNx1GDa5XDr7Uy
Co-authored-by: Claude <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/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants