fix(plugin-sharing, plugin-audit): runtime strings state each decision in words instead of a tracker number (stage 6) - #21533
Conversation
…instead of citing a tracker number Stage 6 of the services lane's share of the runtime-string burn-down: every ledgered tracker-number occurrence in plugin-sharing/src and the one in plugin-audit's audit-writers.ts. Each rewritten string states what the cited card decided, in words, or drops a citation the sentence already explained. Text only: no status, error code, field, route or control flow moves. The doc-authoring prose-id ledger is recomputed with --census-ledger: four file entries leave it, nothing else moves. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
…stage6 The prose-id ledger conflicted: main's copy was taken and regenerated with --census-ledger on the merged tree. Against main it deletes 16 lines and adds none: the plugin-sharing and audit-writers.ts entries go to zero and no other entry moves. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 15 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 e80a5f883ed18501af2fc49ce92de414eb79bd45 && git checkout e80a5f883ed18501af2fc49ce92de414eb79bd45
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ad7c3518983a1bb63fd4601954ac92d055124e42 2f545642d658baf826ccbd7a0f87b52ef7891822 && git checkout -B drift-repro ad7c3518983a1bb63fd4601954ac92d055124e42 && git merge --no-ff 2f545642d658baf826ccbd7a0f87b52ef7891822
node scripts/docs-audit/affected-docs.mjs --json ad7c3518983a1bb63fd4601954ac92d055124e42
|
Part of #20751
Clause-②: no
Stage 6 of the
domain:serviceslane under the maintainer's A / A ruling (5902360492): theplugin-sharingstrings and the oneplugin-auditstring left over from stage 4. The card stays open for the later stages, so this PR carries no closing keyword. Text only: no status, errorcode, field, route, export or control flow moves (the AST skeleton reads SAME for 6 of 6 changed.tsfiles, below).What this does
Eight strings in these two packages sent the reader to a tracker number for the reason behind them. In form D, as stages 1 to 5 applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words.
All 8 ledgered occurrences in this stage's surface (claim
5962584533), re-derived from the ledger onorigin/mainataa463223and read again, the same eight, onad7c3518before merging:plugin-sharing7 (7 pairs, 3 files:share-link-service.ts,sharing-rule-service.ts,sharing-service.ts) andplugin-audit1 (audit-writers.ts, the entry stage 4 left for a later stage). The file excluded at dispatch,plugin-sharing/src/translations/serving-seam.test.ts(PR #21480, since merged), carries no ledger entry and is not touched by this diff.Rewritten in words
Author- and administrator-visible text first, log lines last. Line numbers are at the head.
plugin-auditaudit-writers.ts:972-976, the missing-table fix in the audit write-failure lineos devboot the table exists in that sibling file and not in the primary one; look there before concluding it was never created"os devbootsys_audit_logwas in the siblingdev.telemetry.db(with its rows) and absent fromdev.db, because ADR-0057 section 3.6 routes the audit lifecycle class to the telemetry datasourcesharing-service.ts:312, the reason the record-share orphan sweep prints in its "revoked N rows" linesys_record_sharerow on it, whatever the source, plus a boot sweep by record existence; the card's hazard is a reused record id handing the old record's shares to the new oneshare-link-service.ts:67, the same reason for the share-link sweepsharing-service.ts:735-741, the write-gate failure log line (error)sharing-service.ts:955-961, the authored-row-write probe log line (warn)admitfrom an app-authored, non-floor policy; abstain, a missing method or a throw leaves the refusal byte-for-bytesharing-service.ts:1835-1842, the hierarchy-scope log line (warn)abeb3751f; its REST endpoints answer 404, its timeline reads): it madeorganizationIdthe authoritative, required field and wrote the fail-closed rule intoIHierarchyScopeResolver.resolveOwnerIdsCitation only (the sentence already stated the decision)
sharing-rule-service.ts:424-429, the no-active-organization refusal (8158: "manage_sharing is an ORG-scoped capability ... answering unscoped would expose every tenant's rules. Select an active organization and retry. Platform operators ... and system contexts are unaffected"). ItsPERMISSION_DENIEDprefix is unchanged.sharing-rule-service.ts:529-533, the platform-global delete refusal (7795: "requires platform authority ... Org-scoped manage_sharing does not authorize it, because this rule belongs to no organization and deleting it revokes every tenant's grants under it. It remains listable, readable and evaluable"). ItsPERMISSION_DENIEDprefix is unchanged.Every cited card (8: 5103, 5190, 5226, 5493, 5973, 6428, 7795, 8158) was read through REST, body and every comment, before its string was rewritten. 5973 answers 404 on both the issue and the pull endpoint; its timeline and its merge commit
abeb3751fcarry the decision.The
OrphanSweepSubject.issuememberThe two sweep reasons above are the values of
OrphanSweepSubject.issue, an exported member thatsweepOrphanedRowsByRecordExistenceappends to its "revoked N rows" warning. The member keeps its name and type (a rename is an export change, outside a text-only stage); only its doc comment changes, from "Issue reference appended to ..." to "Why the rows go, appended to ... Runtime text carries no tracker number, so this states the decision in words", so the published declaration no longer asks a caller for a tracker number.Translations
None of these strings has a locale variant: they are refusal and log text, not translation keys.
Ledger (
scripts/doc-authoring-prose-id.baseline.json)The ledger is serial across every lane's stages, so this PR opened only after stage 5's PR #21518 merged (
e3ad4922).origin/mainatad7c3518(which also carries stage 4, PR #21472, and another lane's stage, PR #21521) was then merged in (no rebase). The ledger conflicted; main's copy was taken and regenerated on the merged tree withnode scripts/check-doc-authoring.mjs --census-ledger(exit 0, no growth refusal). Againstmainthe diff deletes 16 lines and adds none: exactly the four file blocks of this stage. A scripted key-by-key comparison of main's copy against the regenerated one reads 4 keys moved, all of them this stage's, each to absent; every other row is unchanged. No other open PR touches the file.ad7c3518)plugin-sharingplugin-audit(audit-writers.ts)service-analytics)pnpm check:doc-authoringat the head: "sibling-package prose ids hold the baseline — 26 pinned site(s) across 6 file(s), 86200 string(s) read in 1252 parsed source(s), no growth, no burn-down unrecorded". No gate is added or loosened;scripts/check-doc-authoring.mjsis untouched.Changeset
.changeset/20751-services-strings-stage6-state-the-decision.md:patchfor@objectstack/plugin-sharingand@objectstack/plugin-audit. Measured after building the merged tree: the new sentences are in each package's built output (dist/index.jsanddist/index.mjsof both). A TypeScript scan of every string literal and template text in the built output finds 0 tracker ids in either package. Control: the same scan reads 34 inservice-analytics' built output, the count its ledger entries carry.Text-only proof
A TypeScript-AST skeleton of each changed
.tsfile, where every string literal and template text is a placeholder, a run of adjacent string operands of a+chain is one string (only its embedded expressions are kept), identifiers and numbers keep their text, and comments are never read.aa463223(where the branch was cut) against the head: 6 of 6 SAME, and the same againstad7c3518(main did not touch any of the six files). Controls on scratch copies ofsharing-service.ts, each mutation's marker counted once on disk first: a one-identifier rename reads DIFF; a text-only change reads SAME; a re-split of one string into two concatenated pieces reads SAME.Pins
sharing-service.test.ts:1616: the write-gate failure log line is found by "an abstention would hand the row to the other write authorities" instead of the id; thefail-closedassertion beside it and thedenyverdict assertions are unchanged. Reverse check, at the committed90db7d4e(the merge did not touch these files), throughscripts/ablation-replace.mjsunder the lock: the new clause put back to the citation form (anchor hit once, blob moved) turned exactly that case red (predicted 1, measured 1 of 131); restored byte-identical toHEADwith an emptygit diff HEAD.Tests
All through
scripts/pm/os-verify-lock.sh, every verdictVERDICT command-exit 0, at the head2f545642(the merged tree;pnpm install --frozen-lockfilefirst):turbo run build --filter=./packages/* --filter=./packages/*/*(71/71).@objectstack/plugin-sharing: 38 files, 954 tests passed;@objectstack/plugin-audit: 38 files, 618 tests passed.typecheckfor both, includingcheck:test-typecheck: OKfor each.90db7d4e, before the merge.Gates
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(no paths) at2f545642(8 paths vs merge basead7c3518, 62 changed lines): 74 commands, run one at a time from the worktree after the full build, each exit code recorded before any pipe; 74 exit 0.--ran: "74 derived famil(ies) accounted for — 74 run, 0 NOT-MEASURED (a DERIVED zero — all 74 recorded an exit code and none of them is 3)". The same 74 also ran green at90db7d4e, before the merge.check-issue-citations: "no issue citations added against ad7c351 (5 file(s) read)";check:i18n: "OK (9 package(s) — all bundles in sync, no undeclared authoring keys)";check:nul-bytes: OK, 9876 files;check:type-check-debt: "none above its recorded number";check:dual-build-cjs-loads: 106 require entry points across 66 packages load;check:dts-closure: 71 built packages, 169/169;check:sourcemap-no-sources-content: 68 packages, 532 maps;check:published-files: 69 publishable packages;check:engine-double-contract: OK.2f545642: the eleven declared wide-population families (check:init-service-contract,check:live-db-isolation,check:meta-type-normalized,check:optional-error-sink,check:resume-authority-declared,check:route-envelope,check:runner-env-posture,check:settings-bind-window,check:startup-registry-verdict,check:verify-stand-in,check:wildcard-fallthrough), pluscheck:durability-log-levelandcheck:error-code-casing(log and refusal text moved; no level or code did).eslint --no-inline-config --format jsonover the 6 changed.tsfiles at2f545642: 6 files linted, 0 errors, 0 warnings.eslint.config.mjsenables no type-aware linting (noparserOptions.project, no typed rules), so this diff cannot move any untouched file's verdict. Repo-widepnpm lintis CI's.origin/mainwas stillad7c3518when this PR opened.Acceptance notes
Noted, not filed:
OrphanSweepSubject.issuenow carries a reason in words; its name still says "issue". Renaming it is an export change and belongs to no text-only stage. Carrier: none.plugin-sharingtest titles and comments still carry ids ([#6428],#5103,#5190, ...); test bodies and comments are outside the ledger. Carrier: none.Generated by Claude Code