Skip to content

fix(objectql): elevate ObjectRepository.execute() to REST/MCP's trusted posture - #15051

Merged
hotlong merged 4 commits into
mainfrom
claude/issue-13866-repo-execute-caller-census
Sep 4, 2026
Merged

fix(objectql): elevate ObjectRepository.execute() to REST/MCP's trusted posture#15051
hotlong merged 4 commits into
mainfrom
claude/issue-13866-repo-execute-caller-census

Conversation

@os-musk

@os-musk os-musk commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #13866

The ruling (Director seat, 决裁批 #24, 2026-09-01, maintainer verbatim reply 「同意」)

  1. 普查先行(派发的第一交付物):量出 ObjectRepository.execute()真实调用方人口(仓内 + examples + apps,区分生产/测试),带发火正对照;
  2. 具名可证伪前提:调用方为内部/测试/个位数 ⇒ ——repo.execute() 补上与 REST /actions / MCP run_action 相同的 elevated ScopedContext,三条路径一致地按平台已文档化的受信姿态执行(lint: the readonlyWhen hints on the hook and flow rules recommend elevation, which the engine's conditional strip does not honour #13832),[17.0.0-rc.0] Action body ctx.api is bound to a context-less engine facade — every owner-scoped write dies FORBIDDEN while the audit line claims TRUSTED #3914 的无身份形状消除;
  3. 前提被证伪(普查测出真实应用面依赖「剥」)⇒ ⛔ 停手,带数字回决策箱,⛔ 不硬裁;
  4. 防 AI 棱的关切已结构性承接,入册:A hook cannot elevate, so a hook-written computed column cannot be protected by field-level editable: false — the guard and the writer are the same door #14010(钩子提权改显式 runAs 声明)与 The most common action in any app — set a field on the current record — has no declarative form for a ROW action, while the BULK form is fully declarative #14092(声明式行级写走调用者权限)同日已裁 —— 受信命令式 handler 是文档化逃生口,不是默认编写路径;⛔ 本裁决不重开那两案;
  5. 抬齐落地后 lint: an action body's ctx.api write to a readonly field has no author-time signal — the hook-side gate has no action-side counterpart #13770 的 static-readonly lint 半边前提恢复,该卡的 pm:retriage 由车道收口;
  6. 安全/权限边界类 ⇒ 实施 PR 挂 needs:contract-review(内容肢:未认证外的行为面位移),本席复审。

Census (deliverable one)

Method: chained-accessor grep (.object('<name>').<method>(, same-line AND multiline up to ~120 chars), cross-checked by identifier-categorizing every .execute( hit repo-wide (1115 occurrences), by every ScopedContext/ObjectRepository construction site, and by the sandbox's own method allowlist.

Firing positive control — the identical chained-accessor technique against ObjectRepository's sibling methods, same repo, same day:

method same-line hits multiline (≤120 chars) hits
.insert( 49 29 files
.update( 149
.find( 13
.findOne( 15
.updateById( 16
.count( 20
.execute( 0 0

Production vs test, .object(x).execute(y) (any gap, any package, examples/, apps/): 0 production, 0 test.

Every one of the 1115 .execute( hits resolves, by identifier, to something else entirely: engine.execute( / driver.execute( (raw SQL / flow-engine execute, packages/objectql/src/engine.ts:13358's different execute method), automation.execute( / executor.execute( (workflow dispatch). The handful of literal ObjectRepository.execute() / ScopedRepo.execute() strings in the tree are prose, not invocations — packages/runtime/src/action-execution.ts:459, packages/runtime/src/sandbox/body-runner.ts:896, packages/lint/src/validate-readonly-action-writes.ts:47 all describe this method as "the third executeAction caller" that "supplies neither api nor executionContext" — independently corroborating this PR's own finding, before this PR existed.

Two structural facts explain the zero and rule out an undercount:

  • The sandboxed action/hook-body proxy never exposes executepackages/runtime/src/sandbox/quickjs-runner.ts's READ/WRITE arrays (find/findOne/count/aggregate / insert/update/delete/updateMany/deleteMany/upsert) omit it entirely, so a source: "..." script body (the dominant action-authoring shape — see examples/app-showcase/src/ui/actions/index.ts) cannot call ctx.api.object(x).execute(y) even if authored to.
  • Every native (non-sandboxed) registerAction handler found (examples/app-todo/src/actions/task.handlers.ts, service-sms/service-settings/service-storage/plugin-email's settings.registerAction test actions) uses a slim ActionContext { record, engine, user, params } shape and never reaches ctx.api/.execute() — consistent with them being dispatched through REST /actions / MCP run_action (which build exactly that richer shape) and never through ObjectRepository.execute().

Verdict: premise HOLDS, in its strongest form (population = 0, not merely single-digit).

Implementation

ObjectRepository.execute() (packages/objectql/src/engine.ts) now builds { ...this.context, isSystem: true } — the identical sudo()-shaped elevation buildActionExecutionContext (REST /actions, MCP run_action) and recomputeSummaries's systemCtx already use — and hands the handler executionContext (that envelope) and api (a real ScopedContext bound to it), on top of the existing userId/tenantId/roles. Before: neither key existed, so ctx.api.object(x).execute(y) — the in-process action-composition shape action-execution.ts names this method's own reason to exist — got ctx.api === undefined.

What widens⚠️ corrected post-merge for disclosure completeness, see #15131 and the PR comment below. The paragraph below (as originally written) named only the static-readonly strip; that was true but materially incomplete. ctx.api inside a repo.execute()-dispatched action handler carries isSystem: true, and ObjectQL's registered security middleware reads that as a total, unconditional bypass (plugin-security/src/security-plugin.ts:1614-1616, "System operations bypass security" — return next() ahead of every other gate in that middleware), not only the static readonly strip. Every find/insert/update/delete the handler drives through this ctx.api also skips, in the same stroke: RLS read scoping (:4344) and field-level security (:4495); the CRUD/export permission checks in the same middleware (:1616, canExport at :4573); the ADR-0103 engine-owned/append-only write guard (system-write-guard.ts:96,120, called at :1736); the package-managed / system-row / curated-capability-name / audience-anchor write gates (:1690-1724); the referential-integrity check (engine.ts:5892) and the tenant-audit mute (engine.ts:3773) — in addition to the static readonly/runtime-owned strip on both UPDATE paths (engine.ts:11290, :11473) and the INSERT path (:10025), not the single call site named below. This matches the platform's own documented posture (content/docs/permissions/system-context.mdx: "Elevation is total, and it is not granular") and REST /actions / MCP run_action already carry the identical exposure — so this widens an existing bypass to a third dispatch path, not a new one.

Bounded on two sides: metadata-plane schema masking (metadata-core/object-schema-fls.ts:228) is a separate REST/GraphQL dispatch path this ctx.api surface never reaches; and plugin-sharing/rule-hooks.ts's insert/update materialisation skip was already retired by the maintainer's 2026-08-31 ruling on #13533 (system and user writes materialise sharing grants identically today).

Per the census below, the measured blast radius today is still zero — no shipped write changes behaviour — so the widening is total in kind, empty in practice, today.

Original "what widens" paragraph (superseded by the correction above, kept for the record)

a readonly: true field a handler writes through ctx.api.object(x).update(y), reached via repo.execute(), now lands instead of being silently stripped by the engine's static-readonly strip (!opCtx.context?.isSystem, packages/objectql/src/validation/rule-validator.ts) — matching what the identical write already does through REST /actions and MCP run_action. Per the census above, no shipped write exercises this path today, so nothing that ships changes behaviour; this widens what a future caller of this method is accepted to do.

Ablation (pin: packages/objectql/src/engine-repo-execute-elevation.test.ts, 5 cases)

Predicted in writing before mutating: all 5 cases go RED — each drives a handler through ctx.api.object(x).<op> or reads ctx.executionContext.<field>, both undefined pre-fix, throwing TypeError: Cannot read properties of undefined.

  1. Mutated packages/objectql/src/engine.ts back to the pre-fix 3-line body (verified the exact 12-line replacement matched exactly once before writing — a 0-hit replace would have exited the same way).
  2. Rebuilt (pnpm --filter @objectstack/objectql build, exit 0 — still valid TS) and ran the pin: 5 failed (5), every failure exactly the predicted TypeError, os-verify-lock VERDICT command-exit 1.
  3. Restored via git checkout HEAD -- packages/objectql/src/engine.ts (never bare checkout --). Proved the restore by state: git diff HEAD empty, git status --porcelain empty, and git hash-object on the working-tree file byte-identical to git rev-parse HEAD:<path> (1a476fb09c20ce9e6bcadd570812b337688bf961 both sides).
  4. Rebuilt and reran: 5 passed (5), VERDICT command-exit 0.

Gate verdicts

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (no paths — merge-base derivation), re-derived on the final file list after every commit and again on the final commit. Final derivation: 68 commands (58 path-matched, 7 by change-kind, 5 whole-tree), stable across re-derivations. 61 passed clean throughout.

Two real findings, both in this PR's own new test fixture, both fixed in-branch and re-verified green:

gate first run fix re-run
check:objectql-double-limit ✗ new limit-blind find() double (engine-repo-execute-elevation.test.ts:52) apply the caller's bound after the filter, by presence (the gate's own suggested remedy) ✅ 0 new
check:where-matcher ✗ new silently-wrong WHERE matcher — a $-prefixed combinator read as a field name refuse it loudly (throw), the exact idiom engine-readonly-strip-caller-values.test.ts's own fake driver already uses ✅ 0 new

Five gates read PREREQUISITE NOT MET / an equivalent "build first" refusal — not a pass, not a finding, per this card's own instructions — every one needs a full monorepo build (all ~80 packages) this worktree never ran (only objectql's own dependency closure was built): check:test-completeness (needs a saved turbo run test log), check:pm-half-states (needs GitHub API access this container lacks), check:dual-build-cjs-loads and check:type-check-debt (need every workspace package's dist/), check:skill-examples (needs @objectstack/client-react built — entirely unrelated to this PR's packages/objectql change). All five read as NOT MEASURED locally; CI builds fresh and runs the full farm.

node scripts/pm/check-governed-merges.mjs --test <final files>NOT governed (0 of the 4 paths hit GOVERNED_SURFACES) — ordinary queue landing applies.

Gate re-derivation and the pin-test re-run above were both taken on the final head, 183cd58ec (git rev-parse --short HEAD).

Clause-② (needs:contract-review)

Already applied by ruling clause 6 (content limb: behavioural shift on a surface reachable beyond the unauthenticated boundary) — left on. Independently, against the mechanical floor (any new key on a published payload is always yes): this diff adds two new keys (executionContext, api) to the ctx object an ObjectRepository.execute()-dispatched action handler receives ⇒ yes. Label stays; only the reviewing seat may clear it.

Changeset

.changeset/repo-execute-elevated-context.md@objectstack/objectql: patch. No new exported symbol, no published type moved — runtime behaviour change on an existing, previously-unreachable-in-practice method.


Generated by Claude Code

…ed posture

Director ruling 决裁批 #24 (2026-09-01), clause 2: the census (repo +
examples/ + apps/, production + test) found ZERO real callers of
ObjectRepository.execute() anywhere — every hit was prose describing the
shape, never an invocation — so the premise (callers are internal / test /
single-digit) holds in its strongest form, and the elevation is implemented.

ObjectRepository.execute() now hands the action handler a ScopedContext
bound to { ...callerContext, isSystem: true } (ctx.api) and the same
elevated envelope as ctx.executionContext — the identical sudo()-shaped
formula buildActionExecutionContext (REST /actions, MCP run_action) and
recomputeSummaries's systemCtx already use. Before this, the handler got
neither api nor executionContext: a handler composing a sibling write via
ctx.api.object(x).update(y) got ctx.api === undefined, and the sandbox's
own last-resort fallback ran that write as a non-system caller, so the
engine's static readonly strip applied to this path and not to REST
/actions or MCP run_action.

Fixes #13866

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Pure line rot: content/docs/permissions/system-context.mdx:183 pointed at
engine.ts:14463, which the elevation fix's inserted JSDoc pushed down to
14496 (the ScopedContext.isSystem getter itself is unchanged). Repaired
via `node scripts/check-system-context-census.mjs --fix`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
check:objectql-double-limit flagged the fake driver's find() in
engine-repo-execute-elevation.test.ts as a new limit-blind ObjectQL double.
Apply the caller's bound after the filter, by presence — the gate's own
suggested fix — so the baseline stays at zero new limit-blind doubles.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…binators

check:where-matcher flagged the fake driver's matches() in
engine-repo-execute-elevation.test.ts as a new silently-wrong WHERE matcher
(a $-prefixed combinator key would be read as a literal field name instead
of being rejected). Refuse it loudly instead, matching the exact idiom
engine-readonly-strip-caller-values.test.ts's own fake driver already uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to listnot a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 16 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 0fb944b4f6ec7437ee3abb25fcedbde629466347packageMentionDocs.

Which tree this was computed on

This run read content/docs from 78bf342e86c2043e137e494f986d7cc9dcc9f3c9 — the merge of head 183cd58eceeaac3f820a08f31f85b7f1bf438e80 into base 0fb944b4f6ec7437ee3abb25fcedbde629466347, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 78bf342e86c2043e137e494f986d7cc9dcc9f3c9 && git checkout 78bf342e86c2043e137e494f986d7cc9dcc9f3c9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0fb944b4f6ec7437ee3abb25fcedbde629466347 183cd58eceeaac3f820a08f31f85b7f1bf438e80 && git checkout -B drift-repro 0fb944b4f6ec7437ee3abb25fcedbde629466347 && git merge --no-ff 183cd58eceeaac3f820a08f31f85b7f1bf438e80

node scripts/docs-audit/affected-docs.mjs --json 0fb944b4f6ec7437ee3abb25fcedbde629466347

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@hotlong
hotlong marked this pull request as ready for review September 4, 2026 01:32
@hotlong
hotlong added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit a548550 Sep 4, 2026
43 checks passed
@hotlong
hotlong deleted the claude/issue-13866-repo-execute-caller-census branch September 4, 2026 01:59
os-musk pushed a commit that referenced this pull request Sep 4, 2026
…ass on repo.execute()

PR #15051's "what widens" statement named only the static `readonly` strip
that isSystem: true skips on ctx.api.object(x).update(y). That is true but
materially incomplete: ObjectQL's registered security middleware
(security-plugin.ts:1614-1616) reads isSystem as a TOTAL, unconditional
bypass, so every find/insert/update/delete through this ctx.api also skips
RLS scoping, field-level security, the CRUD/export checks, the ADR-0103
engine-owned write guard, the package-managed/system-row/curated-capability/
audience-anchor write gates, the referential-integrity check and the
tenant-audit mute -- matching REST /actions and MCP run_action exactly, and
documented in full at content/docs/permissions/system-context.mdx.

Bounded on two sides: metadata-plane schema masking (object-schema-fls.ts) is
a separate REST/GraphQL dispatch path this ctx.api surface never reaches, and
plugin-sharing's insert/update materialisation skip was already retired by
the 2026-08-31 ruling on #13533.

Rewrites the changeset paragraph and the execute() docstring to agree; the
PR body itself is corrected via the GitHub API in the same round (a merged
PR's body can still be edited for the historical record). No implementation,
census, ablation, gate, or changeset-level change -- prose only, per the
review finding on #15051.

Part of #13866

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

os-musk commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

os-dev-report

{
  "issue": 13866,
  "status": "done",
  "branch": "claude/issue-13866-disclosure-fix",
  "pr": "https://github.com/objectstack-ai/objectstack/pull/15131",
  "premise_still_valid": false,
  "summary": "Premise mismatch discovered at start: the dispatch described PR #15051 as an open draft carrying needs:contract-review; by the time this round started it was already merged (a54855005, merged by hotlong the maintainer, needs:contract-review no longer on it) and issue #13866 closed. No code change was needed or made -- only the disclosure-completeness fix. Corrected the 'what widens' statement in all three named places: (1) PR #15051's body, updated via the GitHub API for the historical record (a merged PR's body can still be edited) -- read back byte-identical, footer stayed session-URL form (did not downgrade to bare, contrary to the general PATCH-downgrade note); (2) .changeset/repo-execute-elevated-context.md; (3) the execute() docstring in packages/objectql/src/engine.ts. Since the original branch/PR was closed, the changeset+docstring edits landed on a fresh branch off current origin/main and opened as a new draft PR (#15131, not enqueued, not auto-merge-armed) referencing #13866 and #15051. One incidental mechanical fix: the docstring insertion shifted engine.ts line numbers by 26, rotting one system-context.mdx census anchor; repaired with the gate's own --fix (pure line rot, population/classification unchanged: 106 sites/20 packages/45 files).",
  "tests": "Built @objectstack/objectql's dependency closure then the package itself (pnpm --filter '@objectstack/objectql^...' build, then --filter '@objectstack/objectql' build), both exit 0 via os-verify-lock. Re-ran the PR's 5 pins (engine-repo-execute-elevation.test.ts) on final head ba771e706: 'Test Files 1 passed (1) / Tests 5 passed (5)'. Package typecheck (tsc --noEmit + tsconfig.scripts.json + check:test-typecheck): exit 0, 'check:test-typecheck: OK'. node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (no paths, merge-base derivation), re-derived after the anchor-fix commit: 73 commands on the final 3-file diff (.changeset/repo-execute-elevated-context.md, content/docs/permissions/system-context.mdx, packages/objectql/src/engine.ts) plus the 4 roster gates flagged as 'not evidence either way' since a touched path sits under their scan root (check-changeset-fixed.mjs, check:authz-resolver, check:error-code-casing, check:filter-alias-parity) -- all read separately, all pass. Every command's exit code captured before any pipe (redirect-then-capture). Result: all pass except two PREREQUISITE NOT MET (exit 3 / effectively non-pass, not findings, same shape #15051 itself reported): check:dual-build-cjs-loads (needs every workspace package's dist/) and @objectstack/spec check:skill-examples (needs @objectstack/client-react built, unrelated to this diff). node scripts/pm/check-governed-merges.mjs --test on the final 3 files: NOT governed (0/3 hit GOVERNED_SURFACES). No control bytes in either edited file (grep -naP control-byte scan, exit 1 = no matches).",
  "mcp_calls": 10,
  "open_questions": [],
  "out_of_scope_findings": [],
  "isystem_enumeration_reverified_independently": [
    {"row": "Security middleware total short-circuit (the bypass gate itself)", "anchor": "security-plugin.ts:1614-1616", "reviewer_cited": "1614-1616", "confirmed": true, "note": "read directly: comment 'System operations bypass security' + `if (opCtx.context?.isSystem) { return next(); }` ahead of every other check in the middleware"},
    {"row": "RLS read scoping (getReadFilter)", "anchor": "security-plugin.ts:4344", "reviewer_cited": "4344", "confirmed": true},
    {"row": "Field-level security", "anchor": "security-plugin.ts:4495", "reviewer_cited": "4495", "confirmed": true},
    {"row": "CRUD permission checks (same middleware, short-circuited by the same return)", "anchor": "security-plugin.ts:1616", "reviewer_cited": "1616", "confirmed": true},
    {"row": "Export permission (canExport)", "anchor": "security-plugin.ts:4573", "reviewer_cited": "4573", "confirmed": true},
    {"row": "ADR-0103 engine-owned/append-only write guard", "anchor": "system-write-guard.ts:96 (predicate body) and :120 (call site), invoked at security-plugin.ts:1736", "reviewer_cited": "system-write-guard.ts:96,120, called at security-plugin.ts:1736", "confirmed": true, "note": "predicate function starts line 95, its isSystem-reading return statement is line 96; matches reviewer exactly"},
    {"row": "package-managed / system-row / curated-capability-name / audience-anchor write gates", "anchor": "security-plugin.ts:1690, 1704, 1716, 1724 (range 1690-1724)", "reviewer_cited": "1690-1722 (approx)", "confirmed": true, "note": "measured range extends 2 lines past the reviewer's citation (audience-anchor gate call is at :1724) -- same 4 gates, corrected endpoint"},
    {"row": "Static readonly strip -- UPDATE, single row", "anchor": "engine.ts:11290", "reviewer_cited": "11290", "confirmed": true},
    {"row": "Static readonly strip -- UPDATE, bulk/predicate", "anchor": "engine.ts:11473", "reviewer_cited": "11473", "confirmed": true},
    {"row": "Static readonly/runtime-owned strip -- INSERT (stripRuntimeOwnedFields, one call strips BOTH autonumber and static-readonly fields together, reported under reason:'readonly')", "anchor": "engine.ts:10025", "reviewer_cited": "10025 (labeled 'autonumber/runtime-owned strip')", "confirmed": true, "note": "confirmed this single site covers both behaviors -- canonical content/docs/permissions/system-context.mdx independently labels the SAME line 'readonly strip bypassed -- INSERT (engine pass)', reconciling the two framings as the same code"},
    {"row": "Referential-integrity check (assertReferencesResolve)", "anchor": "engine.ts:5892", "reviewer_cited": "5892", "confirmed": true},
    {"row": "Tenant-audit mute", "anchor": "engine.ts:3773", "reviewer_cited": "3773", "confirmed": true},
    {"row": "Hook-session isSystem propagation (carries the flag onward -- not itself a gate)", "anchor": "engine.ts:3543 (buildSession)", "reviewer_cited": "3543", "confirmed": true},
    {"row": "Audit attribution label ('system' vs 'anonymous' -- not itself a gate)", "anchor": "engine.ts:12014", "reviewer_cited": "12014", "confirmed": true}
  ],
  "not_reached_boundaries_reverified_independently": [
    {"claim": "Metadata-plane schema masking (metadata-core/object-schema-fls.ts) is a separate REST/GraphQL schema-serving dispatch path, not the engine write pipeline -- NOT reached via repo.execute()'s ctx.api", "confirmed": true, "method": "read the file header: '@objectstack/metadata-core' depends on {@objectstack/spec, zod} only; its two consumers are @objectstack/rest and @objectstack/runtime's schema-serving exits (GET /meta/object/:name etc.), never the engine's registered middleware chain that ctx.api's find/insert/update/delete/count/aggregate/execute surface drives. Note: isSystem DOES bypass this exemption elsewhere in the platform per content/docs/permissions/system-context.mdx row 7 -- it's simply orthogonal to and unreachable from this PR's specific widening, which is the reviewer's actual (narrower, correct) claim."},
    {"claim": "plugin-sharing/rule-hooks.ts's isSystem materialisation skip (insert/update) was already retired by the 2026-08-31 ruling on #13533 -- system and user writes materialize identically today", "confirmed": true, "method": "read rule-hooks.ts directly: block comment at top states 'RETIRED -- the isSystem materialisation skip ... Maintainer ruling 2026-08-31 (verbatim, untranslated)... 裁定:系统写参与逐记录共享物化'; the surviving isSystem check at line 292 is a DIFFERENT skip (afterDelete-only revocation-timing delegation to record-share-cascade.ts, not a silencer, per the file's own comment) -- confirmed content/docs/permissions/system-context.mdx row 30 independently documents the same distinction in the same words"}
  ],
  "census_zero_callers_reverified_independently": {
    "confirmed": true,
    "method": "grep -rn '\\.execute\\(' across packages/, examples/, apps/, filtered to lines mentioning .object(/ScopedRepo/ObjectRepository -- every hit outside this PR's own new pin test (engine-repo-execute-elevation.test.ts) is prose in a comment describing the shape, never an invocation. Positive control: '.object(x).update(' -> 195 hits, '.object(x).insert(' -> 49 hits, confirming the grep methodology fires when a real caller exists."
  },
  "final_wording_used_in_all_three_places": {
    "pr_15051_body": "Replaced the original 'What widens' paragraph with a corrected version (kept the original nested in a collapsed disclosure block (details/summary tags) for the record) stating the security middleware's total bypass, the full list of skipped behaviours with anchors, the two bounded exclusions, and the still-zero measured blast radius. Verified byte-identical on read-back after the update_pull_request call.",
    "changeset_repo_execute_elevated_context_md": "Rewrote the 'What widens' paragraph to lead with the security-middleware total bypass (citing security-plugin.ts:1614-1616), list every skipped behaviour with anchors, then two new paragraphs for the bounded exclusions (object-schema-fls.ts, rule-hooks.ts) and the census zero-callers close.",
    "engine_ts_execute_docstring": "Added a new '[Disclosure completeness]' paragraph immediately after the existing census paragraph (left the original text intact apart from removing its now-incomplete parenthetical), stating the same total-bypass fact, the full anchor list, and the two bounded exclusions."
  }
}

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/m tests tooling

Projects

None yet

3 participants