Repository navigation
refactor(objectql): move the secret and internal-field bodies out of engine.ts into engine-secret-internal-fields.ts (#25522 cut 5) - #26028
Conversation
…engine.ts behind one host (#25522 cut 5) The nine ObjectQL bodies of the "Secret and internal-field handling" area (encryptSecretFields through resolveInternalField) move unedited, one level less indented, into engine-secret-internal-fields.ts. Each method keeps its name, signature, docblock and position and hands its body the members it reads through SecretInternalFieldsHost: _registry, cryptoProvider and txStore as getters, five methods as late-bound closures. stripSearchCompanionFromRead reads no member and is called directly. The three path readers move with them: the federated injected-column ledger key, the records-forms checklist source pointer, and row 27 of the system-context census page. Claude-Session: https://claude.ai/code/session_01FCw8ckDE3VXVavCoqsMQ3u Co-authored-by: Claude <noreply@anthropic.com>
…00 and ADR-0128 The two ADR-0128 D1 citations in the moved encrypt and decrypt bodies left engine.ts's anchored surface with them (decision-letter citations 1,844 at base, 1,842 after the move). This entry anchors the new module, so the letters are verified where the code now lives (1,845 at head). Claude-Session: https://claude.ai/code/session_01FCw8ckDE3VXVavCoqsMQ3u Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 25 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 8 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 19 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 6b6167b0ccd5c68886e9abb5c30a956605f53656 && git checkout 6b6167b0ccd5c68886e9abb5c30a956605f53656
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 39a78b151d691a538856c0f0d57304f8faa69f96 bd40de27336b8976d75e1e9a1995d8c2fe993e89 && git checkout -B drift-repro 39a78b151d691a538856c0f0d57304f8faa69f96 && git merge --no-ff bd40de27336b8976d75e1e9a1995d8c2fe993e89
node scripts/docs-audit/affected-docs.mjs --json 39a78b151d691a538856c0f0d57304f8faa69f96
|
席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」.
Generated by Claude Code |
Requested by Leehom · project thread
Part of #25522
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160
Cut 5 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840). The claim is6412019236, which amends6411795983after the dev report6411990837. The nine bodies of the "Secret and internal-field handling" area move unedited into a new module,packages/objectql/src/engine-secret-internal-fields.ts:encryptSecretFields,refuseEmptyPasswordFields,maskSecretFields,omitInternalFields,stripSearchCompanionFromRead,privilegedReadDriverOptions,resolveSecret,resolveSecretFieldandresolveInternalField. No secret-handling behaviour changes. #25522 stays open for the later cuts.Branch
claude/project-thread-npj50o(the card thread's harness-pinned branch), cut fromorigin/mainatc8cb510a5.mainhas since moved toc16c00f93; nothing in that range touchespackages/objectql/**, the two docs files or the anchor directory entries this PR edits, so the branch is not merged forward and CI builds the merge ref. #25980 (the last commit before the base) changedengine.tsonly in its preamble and trailer; the nine bodies are byte-identical froma4eae0649toc8cb510a5.Why this area (the fresh seam table)
Measured on
origin/maina4eae06499:engine.tsis 23,458 lines, 7,214 of them (30.8%) from the last 30 days (git blame -s --since=2026-09-26T08:45Z), 121 commits in 30 days and 31 in 7. The full 41-section table in #23050's shape, with a per-method screen of every section, is in the dev report6411990837and its project file. The three areas left by cut 4 do not pay a move-only cut without apackages/specedit:buildSummaryIndexis cited frompackages/spec(functional-completeness.ts, ADR-anchored;liveness/field.jsonsummaryOperations, andliveness/ships in the spec tarball);recomputeSummarieshandsthistoaggregateSummaryValueunregisterDriverandclearDatasourceUnavailablearethis.FIELD.delete(sites (U = 3)expandRelatedRecordsreads the private staticMAX_EXPAND_DEPTHand is cited fromliveness/query.jsonandliveness/field.jsonthis.FIELD.delete/insert/update(site, no private-static read (screened by AST), nopackages/specordocs/adrpointerThe shape (#23050 shape B, as cuts 1 to 4 apply it)
.d.ts. Each body is now one host literal plusfn.call(host, …), marked[#25522 cut 5].SecretInternalFieldsHostis new. Each member is typed as the class member (ObjectQL['cryptoProvider'],ObjectQL['getDriver']), and each moved function types itsthisas thePickof exactly the members its body reads; each stub annotates its literal asThisParameterTypeof that function. No cast, and no member changes visibility._registry,cryptoProvider,txStore) go as GETTERS, sosetCryptoProviderbetween calls is seen exactly as before. The five methods the bodies call (getDriver,transactionCoversDriverFor,omitInternalFields,privilegedReadDriverOptions,resolveSecret) go as late-bound closures over the instance, so a double set on the engine still intercepts. Tests do replaceresolveInternalField(4 sites) andresolveSecretField(2) on the instance; those methods stay on the class, so the doubles still take effect.stripSearchCompanionFromReadreads no member and is called directly, as cut 1 callsobjectDisplayLabel.ObjectQLas a TYPE only (no runtime cycle) and nothing re-exports it.engine.tsdrops the names whose last code reader moved:CryptoHandle,collectSecretFields,collectMaskedReadFields,collectMaskedPasswordFields,makeSecretRef,parseSecretRef,isSecretRef,EmptyCredentialWriteError,SECRET_MASKandisSearchCompanionRequested.collectInternalReadFields,collectCredentialFields,stripSearchCompanion,redactPropagatedDriverFaultandICryptoProviderstill have readers there and stay.Net lines (the seat's rule)
engine.ts23,492 → 23,351, net -141. The module is 360 lines: the header and host interface (about 75), nine one-line docblocks, and the 208 moved body lines with their signatures. 667 changed lines over 6 files (+447 / -220), well under the 3,000 human-merge line.The published
.d.tsdoes not change (ruling6348891160)Base:
@objectstack/objectqlbuilt withengine.tsrestored fromc8cb510a5and the new module removed (tree only, restored withgit checkout HEAD --,git statusclean afterwards). Head: built atbd40de2733. The headdist/index.mjscarries the stub'sreadCryptoProvider, which the base build lacks, so each leg built the source it names. All six declaration files are raw byte-identical, so the ruled normaliser has nothing to do:index.d.ts3d0e556fe6cf12c69d3b9516d9f414d235bd7279b3f9cb4bbd10f8fb3f098726index.d.mts9d741b723c1c6697d9b2ccd98cac69075dc5f87328d50936c5d73496c45d4626core.d.tsa024599701ba68ebfa6d0c3781d3c8d755ab1c7c1fc2db5ab89cb30020091a7ecore.d.mts9acb9b18b3220f17a45abc36ef86fb54f53244e634b71400ba45c12895dc5b2butil-CR5tVhqM.d.tsand.d.mts2696708b9ee625ddcdf62709ea19e6d92b39d2d82cdd803652be1b17f625b059Positive control: making line 8014 of the head
util-CR5tVhqM.d.ts(private maskSecretFields;) public gives7f91b0b1062f7356115bd25365df7bc3baaae7678e3d06dc92552ffdb87df35f, so the comparison can fail. Export lists, ESM = CJS at both ends:.182 names (sorted sha256881616cc…0adaa),./core54 (393e8069…90f49), identical at base and head; no moved name is exported.Proof of move-only
A TypeScript-AST leaf-token compare (recursive
getChildren, JSDoc skipped), baseengine.tsagainst the head module:this) + return type + body tokens SAME,asyncthe same, and every body line equals the base line less two leading spaces.encryptSecretFields354 tokens / 73 lines,resolveInternalField324 / 41,resolveSecret197 / 31,resolveSecretField169 / 24,maskSecretFields128 / 17,omitInternalFields96 / 9,refuseEmptyPasswordFields76 / 7,privilegedReadDriverOptions57 / 4,stripSearchCompanionFromRead37 / 2.returnrewritten in the movedresolveInternalFieldormaskSecretFieldsreports DIFFER.Readers of the moved lines, migrated in this PR
docs/qa/platform-checklist/areas/records-forms.json: the secret-field item's source pointer,engine.ts#encryptSecretFields→engine-secret-internal-fields.ts#encryptSecretFields.check:platform-checklistgreen.content/docs/permissions/system-context.mdxrow 27:engine.ts#stripSearchCompanionFromRead→engine-secret-internal-fields.ts#stripSearchCompanionFromRead, theisSystemread's new home.check-system-context-censusgreen: 151 read sites in 22 packages across 79 files, the page cites 144 symbols against 144 required.packages/objectql/src/federated-injected-column-readers.test.ts: the ledger keyengine.ts#encryptSecretFields :: created_at→engine-secret-internal-fields.ts#encryptSecretFields :: created_at(the scan keys by file).buildDriverOptions,enforceTransactionOrigin) and describes no moved body. But the moved encrypt and decrypt bodies carry twoADR-0128 D1citations, and moving them dropped the anchored surface's decision-letter count from 1,844 to 1,842. Cut 4 resolved the same drop with an entry for its new module, so this PR addsscripts/adr-anchors/packages__objectql__src__engine-secret-internal-fields.ts.json(ADR-0100, ADR-0128).check:adr-anchors: base 86 anchored files, 1,844 letter citations; head 87, 1,845.check-tenant-audit-censusgreen (243 write call sites, everyUNTYPED_RECEIVERSrow matched; the movedsecretDriver.create(is a local receiver, not athis.FIELDone).check:logger-receiver-detachgreen (the moved bodies read no logger).check:durability-log-levelgreen over the objectql read seams.Acceptance notes
engine.tsbeside a moved method still resolves by method name, because every method stays on the class. Examples:service-settings'ssettings-crypto-fail-closed.test.tscomment andplugin-security'sinsert-check-post-image.test.tscomments. They are outside this claim's file surface and left as they are.pr_create: 29 PRs are open. One touchesengine.ts: fix(objectql,types,rest)!: a database NOT NULL refusal on a declared field is the record validator's ValidationError at every door #26026 (seat 1's A database NOT NULL refusal answers differently per door: the dispatcher /data twin answers 500 INTERNAL_ERROR, and REST batch/import/form/action rows name the column key (RestServer POST/PATCH /data answer 400 with the label after #24715) #24768, branchclaude/project-thread-otcr21). Its hunks are increateWithAutonumberResync,insertandupdate, andgit merge-treeof the two heads is clean (exit 0). Whichever lands second mergesmain.Verification
At head
bd40de2733:pnpm --filter @objectstack/objectql typecheck(tsc --noEmit+check:test-typecheck, 39 files / 233 errors / 64 pinned signatures held): exit 0.eslint --no-inline-config packages/objectql: exit 0.pnpm --filter @objectstack/objectql exec vitest run --project local: 470 files, 8,742 tests, 8,742 passed, 0 failed, 0 skipped. This includesread-internal-column.test.ts, the secret and password suites, andfederated-injected-column-readers.test.ts..d.tsfiles are byte-identical, so no dependant can see a difference; CI'sTypeScript Type Checkcovers them.dispatch-gates --commandsderived 103 families on the real diff. All were run at head, each exit code recorded before any pipe, and reconciled with--ran(103 accounted for: 102 run, 1 NOT MEASURED).check:skill-examplesexited 3 untilclient-react's closure was built, then 0. NOT MEASURED (CI runs it):check:dual-build-cjs-loadsexit 3, PREREQUISITE NOT MET (it needs every package'sdist/; the export lists above answer it for objectql).check-engine-split-ratio --days 90: 98.1%, exit 0.check-adr-anchors(base and head, above),check-adr-symbol-anchors(2,658 anchors resolve),check-tenant-audit-census,check-nul-bytes,check-platform-checklist --changed-from origin/main(2 anchored files, 14 anchors, 0 lost),check-commit-card-trailers --range origin/main..HEAD.skip-changeset: move-only. The published.d.tsfiles and export lists are byte-identical,liveness/and every other published path are untouched, and the module's runtime is the same code under a different file name.Generated by Claude Code