Repository navigation
refactor(plugin-sharing,spec): retire the ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED provenance waiver with its stamp site - #19668
Conversation
…ON_REQUIRED provenance waiver with its stamp site plugin-sharing recognised the engine's organization refusal through a local re-spelling of the literal (`ENGINE_ORGANIZATION_REFUSAL_CODE`), which is a `check:error-code-provenance` `constdef` stamp site for a code this package only ever matches. The waiver that excused it carried its own expiry: removed together with the stamp site once objectql published a recognizer. objectql now publishes `SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE` and `isSystemWriteOrganizationRequiredError` for exactly this consumer, so the compare is performed without authoring the string here. Both halves ship together because the gate reconciles a waiver in three directions at once and either half alone reddens it. Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1 Co-authored-by: Claude <noreply@anthropic.com>
…ring Both packages' published `files[]` content moves: plugin-sharing's `dist` drops the local constant and gains the engine recognizer call, and spec ships `error-code-ledger.zod.ts` both compiled into `dist` and verbatim through its `src/**/*.zod.ts` entry. Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1 Co-authored-by: Claude <noreply@anthropic.com>
…tire-provenance-waiver
📓 Docs Drift CheckThis PR changes 2 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 33fe159dc9391abe5aa2c23153aaa337be5eee87 && git checkout 33fe159dc9391abe5aa2c23153aaa337be5eee87
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d3a233192d6def825f64c314ce122ce29b890699 17e22cbd1f2070e95f9faa5569e6d032ac3f443e && git checkout -B drift-repro d3a233192d6def825f64c314ce122ce29b890699 && git merge --no-ff 17e22cbd1f2070e95f9faa5569e6d032ac3f443e
node scripts/docs-audit/affected-docs.mjs --json d3a233192d6def825f64c314ce122ce29b890699
|
Contract reviewServed-tier: In-seat at tier. ① Derived judgments⭐ The headline is a correction, and it overturns BOTH the card and triage — verified by this seat in the source, ⛔ not accepted on the dev's word. The card and triage if (err?.code !== ENGINE_ORGANIZATION_REFUSAL_CODE) throw err;
this.logger?.warn?.(
'[sharing-rule] grant refused by the engine organization rule — counted, pass continues',
{ rule, object, record, recipient, code: ENGINE_ORGANIZATION_REFUSAL_CODE },
);
return false;⇒ that Consequence, and it is the one that matters: the waiver's premise 「Matches the code, never emits it」 survives the re-read. It never rested on that site, so the waiver retires on its own stated expiry and ⛔ nothing needs re-adjudicating. The dispatch reserved a 「stop and report」 branch for a real re-emission; there is none, so the site correctly takes the published constant with the other three. Site count and drift, re-read by this seat: 5 occurrences = 1 declaration + 4 references — exactly triage's 「按 4 处算,不是 2 处」. All five had drifted +21 lines since the 2026-09-06 read (137→138, 1631→1652, 1645→1666, 1683→1704, 1691→1712), which is why the dispatch required locating by symbol. The local spelling is gone: The import comment earns its place — it now records why a 「One PR or neither」 is measured, ⛔ not asserted. Two one-legged ablations, each restored with proof: (A) stamp site back, waiver gone ⇒ 「FAIL — 1 stamp site(s) of a registered code with no provenance row」; (B) waiver back, stamp site gone ⇒ 「FAIL — 1 provenance-waiver problem(s): … matches NO stamp site in the scan」. That is exactly the three-way reconciliation the card said would redden on either half alone. ② Semver levelPatch on both
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #16160
Clause-②: no
What this does
Retires the
ERR_SYSTEM_WRITE_ORGANIZATION_REQUIREDprovenance waiver together with its stamp site. Both halves ship here, and neither can ship alone:check:error-code-provenancereconciles a waiver in three directions at once, so removing the stamp site alone reddens it on the stale waiver, and removing the waiver alone reddens it on the orphaned site. That is measured below, not asserted.packages/plugins/plugin-sharing/src/sharing-rule-service.ts— the localENGINE_ORGANIZATION_REFUSAL_CODEconstant is gone. The per-grant catch now asksisSystemWriteOrganizationRequiredError(err), and thewarnthat reports an absorbed refusal namesSYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE. Both come from@objectstack/objectql, whose barrel comment says in so many words that they exist so a consumer performs thecodecompare "without acquiring acheck:error-code-provenancestamp site of its own".packages/spec/src/api/error-code-ledger.zod.ts— the matchingPROVENANCE_WAIVERSentry is deleted. It carried its own expiry: "Removed together with the stamp site when objectql: publish a recognizer forSystemWriteOrganizationRequiredErrorso consumers stop re-spellingERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED—instanceofis measured unsound across the CJS/ESM split #14936 lands and objectql publishes a recognizer."It was four references, exactly as triage counted
Triage's line-by-line read recorded 「删常量会连带四处引用,取卡人排期时按 4 处算,不是 2 处」. Located by symbol, not by line — every number had drifted by +21 since that read:
:137-138:138-139SystemWriteOrganizationRequiredError['code']:1631:1652{@link ENGINE_ORGANIZATION_REFUSAL_CODE}SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE:1645:1666{@link ENGINE_ORGANIZATION_REFUSAL_CODE}:1683:1704if (err?.code !== ENGINE_ORGANIZATION_REFUSAL_CODE) throw err;if (!isSystemWriteOrganizationRequiredError(err)) throw err;:1691:1712code: ENGINE_ORGANIZATION_REFUSAL_CODE,code: SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE,— see the judgement belowFour references plus the declaration. After the edit
git grep ENGINE_ORGANIZATION_REFUSAL_CODEoverpackages/returns nothing.The
:1691judgement, stated rather than carried alongThe card and triage both flagged this site as a separate judgement, on the reading that plugin-sharing emits the code there in its own refusal envelope. On this tree that reading does not hold, and this PR records why.
:1712is not an envelope. It is the second argument ofthis.logger?.warn?.(message, meta)— a structured log field on the refusal the catch has just absorbed. The enclosing method's own contract is explicit that nothing leaves it carrying this code: "Returnstruewhen the grant landed,falsewhen it was refused — never throws for the refusal, and the caller counts what it is told." So plugin-sharing recognises this code and reports what it absorbed; it emits it nowhere.Two consequences, both deliberate:
SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODEis the right value for a log field that must name the code, and an identifier incode:position is not acheck:error-code-provenancestamp site — theobjlitpattern matches a quoted literal only.field-recipient.test.tsasserts the warn payload carriescode: 'ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED', and separately that a grant refused with any other code rethrows. Both stay green, so the swap is proven to have moved neither the reported code nor the width of the catch.Premise re-measured on this tree, against the built artifact
The card's whole basis is that
@objectstack/objectqlpublishes the recognizer. Measured atpackages/objectql/dist/index.d.ts, not at source:plugin-sharing declares
@objectstack/objectqlindependenciesand its tsconfig carries nopathsremap, so the compiler reads that declaration file through the packageexports. A negative control proves the reading is live rather than cached: renaming the imported member to one objectql does not export turns the package typecheck red withand the restore is proven byte-identical (
blob == HEAD,git diff HEADempty).check:error-code-provenance— the load-bearing gate, before and afterBoth readings are from
pnpm --filter @objectstack/spec run check:error-code-provenance, exit code captured before any pipe.Before (exit 0):
After (exit 0):
Sites 339 → 338, waived 17 → 16, waivers 10 → 9, and
listedunmoved at 322 — the drop triage asked to be confirmed, in each of the three counts.--reportbefore the edit named exactly one waived site for the pair,packages/plugins/plugin-sharing/src/sharing-rule-service.ts:138 (constdef); it is absent after."One PR or neither" — measured, in both directions
Two one-legged ablations through
scripts/ablation-replace.mjs, each committed-state, each with its on-disk landing proven and its restore proven (blob == HEAD,git diff HEADempty). Predicted direction before running: red, both.A. The stamp site back, the waiver still gone — the catch re-spelled as a local
*_CODEconstdef:B. The waiver back, the stamp site still gone:
Each half reddens the gate on its own, as the card said. The green above is therefore a reading, not a vacuum. Neither ablation left anything behind: the working tree is clean at the final commit.
Verification
All readings taken at
17e22cbd1(the final commit,origin/mainmerged in at8f30c188a).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackafter the changeset existed, exit codes captured before any pipe, reconciled with--rancarrying each command's code. Two gates first answeredexit 3PREREQUISITE NOT MET rather than a verdict —check:dual-build-cjs-loadsandcheck:i18n; both prerequisites were built and both re-ran green (104 published require entry point(s) across 67 package(s) load;9 package(s) — all bundles in sync).pnpm --filter @objectstack/spec --filter @objectstack/plugin-sharing run typecheck— exit 0, both packages including their script and test layers.pnpm --filter @objectstack/plugin-sharing test—Test Files 37 passed (37),Tests 913 passed (913).pnpm --filter @objectstack/spec test—Test Files 512 passed (512),Tests 14953 passed | 1 todo (14954).pnpm --filter @objectstack/spec check:generated—All 15 generated artifacts are up to date. Nothing to regenerate: no schema, no export and no authorable key moved.pnpm lint(repo-wide, not narrowed) —eslint . --no-inline-config, exit 0, 6996 files linted, 0 errors, 0 warnings, file count read from--format json.scripts/pm/os-verify-lock.shwithOS_VERIFY_LOCK_SLOT=issue-16160; every verdict is itsVERDICT command-exitline, never a bare shell status.Changeset
patchfor both@objectstack/specand@objectstack/plugin-sharing, judged against eachpackage.json'sfiles[]after a build rather than by inspection:@objectstack/plugin-sharingshipsdist. Its builtdist/index.jsanddist/index.mjsnow containisSystemWriteOrganizationRequiredErrorand no longer containENGINE_ORGANIZATION_REFUSAL_CODE(positive control: an unrelated symbol in the same file still matches). Published bytes moved.@objectstack/specships bothdistandsrc/**/*.zod.ts, anderror-code-ledger.zod.tsmatches that second entry — so the edited file ships twice over, compiled and verbatim. The retired waiver'sreasontext is absent fromdistafter the build (positive control: a sibling waiver's reason still matches).So
skip-changesetis not available to this diff on either package.Acceptance notes
sharing-service.tsmentions the literalERR_SYSTEM_WRITE_ORGANIZATION_REQUIREDin two docblocks. Those are comments, the gate masks comments before scanning, and both statements are accurate about the engine's refusal — an observation, not a finding, and deliberately untouched.维护者速读(草稿)
改了什么
删掉了一条「到期债务」:
plugin-sharing过去自己抄了一份引擎错误码的字面量,台账里为此挂了一条豁免记录。现在引擎自己把识别函数发布出来了,plugin-sharing改用它,那条豁免记录随之删除。两处改动必须同一个 PR,分开做任何一半都会让门禁变红。为什么改
那条豁免记录自己写了到期条件——「等 objectql 发布识别器后,与打码点一起删除」——而没有任何门禁会在条件满足时提醒任何人。不删,它就从一条有期限的记录变成永久居留,下一个读台账的人会以为这是个长期决定。本次改动同时消掉一处重复的字符串字面量:抄写的那一份一旦和引擎抛出的不一致,失效形态是一个永远不会触发的 catch,不是一个失败的测试。
风险与代价(含回滚)
风险低。对外错误面零变化:
ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED仍然注册在@objectstack/objectql名下,ERROR_CODE_LEDGER与StandardErrorCode的成员一个没动,本次只动了PROVENANCE_WAIVERS数组里的一个元素。吸收范围也没变宽:两个既有测试分别钉住「吸收这一个码」与「别的码照样抛出」,都是绿的。回滚 = revert 这一个 PR;两处改动在同一次提交里,不存在只回滚一半的形态。席位意见
你要做的
无需动作。这是记账债务的按期兑付,不是行为变更;
Clause-②: no,两个包各一条patchchangeset 已随 PR 提交。Generated by Claude Code