Skip to content

Commit dad27ef

Browse files
refactor(plugin-security): move what start() registers after the authorization middleware out of security-plugin.ts (#25223 cut 13) (#25599)
<!-- claude-projects-attribution: {"github_login":"os-sales"} --> _Requested by **Sales** · [project thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuMYdF2uchcinMphEKW4sYxd)_ Part of #25223 Clause-②: no Metadata-protocol: none Ruling-ref: 6353073966 Cut 13 of the `security-plugin.ts` split is the third and last part of the `start()` row: R4, what `start()` registers after the authorization middleware. The claim is 6379358210. The seat asked for it in cut 12's landing note (6379109594), as a get/set host pair for `claimTargetAdminUserId` in the #25508 form. This PR moves one run of `start()`'s statements into one new module, unedited: - `packages/plugins/plugin-security/src/security-plugin-start-hooks.ts`: `registerStartHooks`, the 16 statements that close `start()`. Not Tier H: `check-governed-merges --test` on the file list finds 0 of 2 paths in the register, and the size is 999 changed lines (+551 / −448). The landing is the ordinary queue landing after the seat's ACCEPT. **This is the last movable row of `start()`.** After it, `start()` holds R1 (the setup, which assigns 10 of the plugin's members and stays) and the three stub blocks of cuts 11, 12 and 13. (The plan and the claim said R1 writes 11. Measured on the AST, `start()` assigned 11 members, and the 11th, `claimTargetAdminUserId`, was R4's, which this cut moves.) `init()` stays, because ADR-0126:406 `#nav_permission_sets` resolves only on a literal there. So this cut's report on #25223 is also the series' final report. The change is move-only. The branch is `claude/project-thread-3fzya4`, the harness-pinned branch for this session, restarted from `origin/main` at `e073455929` (which contains cut 12's merge `df893f6d76`). The branch name names no issue, so the claim comment is the identity record. ## How the run moves Base line numbers here and below are at `e073455929`, where `security-plugin.ts` is 6,164 lines and `start()` is `:1744`-`:2619` (48 statements). - The run is `start()`'s statements 33 to 48, `:2192`-`:2612`: 421 lines, counted from the first statement's leading comment (`// [ADR-0057 D4 / ADR-0112] …`, `:2192`). It ends `start()`. In order, it registers: - the `sys_user_position` catalog refusal middleware and the grant-holder membership refusal; - the permission-set name hooks, followed by the ADR-0131 D3 note; - the bootstrap once-guards and `runBootstrap`, with its `kernel:ready` registration; - the boot reports on `kernel:bootstrapped`; - the middleware that replays the bootstrap after a qualifying write; - the `sys_member` middleware that reconciles `organization_admin` grants; - `runOrgAdminBackfill`, with its `kernel:ready` registration. - It closes over two of `start()`'s locals and nothing else: `ctx` and `ql`. It uses no `arguments`, `super`, `new.target` or bare `this`, and no `this` inside a non-arrow function. It has no `return`, `await`, `break` or `continue` at its top level that would act on `start()`; the closures' own `return`s and `await`s move with them. All of that was measured on the AST. - The run's eight own locals (`bootstrapRanOnce`, `readSeedSettlement`, `everyoneMutationWired`, `catalogEchoWired`, `catalogEchoBooted`, `managedDeniesApplied`, `runBootstrap`, `runOrgAdminBackfill`) move with it. Nothing after the run read them, because the run ended `start()`. - So the function takes the two locals as parameters, typed as the run saw them there: `PluginContext` and `IObjectQLEngine`. Its body is the run, re-indented one level and otherwise unedited, with every comment above and between its statements. It returns `void`. - In the run's place, `start()` has one BLOCK: the read and write locals, one host literal annotated with the `Pick` of `StartHooksHost`, and `registerStartHooks.call(host, ctx, ql);`. It sits right after the middleware's log line (`:2190`), as the run did, and is now `start()`'s last statement. The comment that closes `start()` (the per-organization seed DATA replay note) stays after it. Every registration is still synchronous and in the same order. ## What moved | code | base lines | host members | |---|---|---| | the registrations after the authorization middleware (16 statements of `start()`) | `:2192`-`:2612` | 3 methods: `declareEveryone`, `deploymentAcceptance`, `deploymentOrgScopingEntitlement`; by value: `bootstrapPermissionSets`; getters: `metadata`, `tenancyPosture`; get/set pair: `claimTargetAdminUserId` | - No module-level declaration moves. The run reads none: everything it names at module level comes from an import. - Import names that only the run reads leave `security-plugin.ts`, 26 in all. The module imports each from the specifier `security-plugin.ts` imports it from, and type imports stay type imports (the proof checks every pair). Thirteen imports leave whole, and five lose names: - `POSITION_ASSIGNMENT_OBJECT` and `createPositionCatalogRefusal`, `registerGrantHolderMembershipRefusal`, `registerGrantPermissionSetNameHooks`, `reportCatalogReferences`, `reportAccessUpgrade` and the type `AccessUpgradeNotifier`, `reportUpgradeImpact`, `SETTINGS_SERVICE` and the type `SettingsManifestReader`, `applyManagedWriteDenies`, `reportPackagedPermissionSetOverlays`, `registerObjectPostureGate`, `registerPackagedPermissionSetLockGate`, `registerSecurityCatalogEcho` and `echoStoredSecurityCatalogOverlays`, `reconcileAudienceBindingSuggestions`, `cleanupPackagePermissions`, `readDeclared`, `readSeedSettlementSnapshot`, `bootstrapPlatformAdmin` and `shouldReplayBootstrapFor`, and `backfillOrgAdminGrants`, `extractMemberPairs` and `reconcileOrgAdminGrant`, each from its `./` module; - the type `SeedSettlementSnapshot` (`@objectstack/spec/contracts`). - Six names stay in `security-plugin.ts`, because code that stays reads them too. The module imports them from the same specifiers: `PluginContext` and `createSecurityCatalogReader` (`@objectstack/core`), `postureEnforcesWall` (`@objectstack/spec/security`), `SHARING_RULES_SERVICE` and the type `DeclaredSharingRuleReader` (`./access-upgrade-report.js`), and `IObjectQLEngine`. - One name stays as a type-only import, and one comment above it is rewritten. Both are disclosed: - `readSeededRecordIds` (cut 11's `./security-plugin-seed-claim.js`) is called only by the run, but the staying docblock of `claimSeedOwnershipOnSettle` links to it (`{@link readSeededRecordIds}`, `:1728`). It stays in that import, type-only, so the link still resolves. A type-only import emits nothing. Cuts 6 (`principalLessDenial`) and 12 (`WriteImageCheckSeam`) are the precedent. - Cut 11's 4-line comment above that import said this file imports "the two `seed-settlement` readers it shares with the promotion-time pass in `start()`". That pass now runs in the new module. So the comment becomes 6 lines that say where the readers are imported now and why `readSeededRecordIds` stays type-only. No other comment in `security-plugin.ts` changes, and every comment in the run moves verbatim. - A scan of every `{@link X}` in `security-plugin.ts` whose head names nothing the file declares or imports gives the same list at base and at head. - The module header says what moved, why it is shaped this way, and how each field is passed. It cites no ADR. ## The shape (#23050 shape B, as cuts 1 to 12 applied it, plus #25508's get/set pair) - `StartHooksHost` is new. It types every member as the class member itself (`SecurityPlugin['m']`). The function types its `this` as the `Pick` of the host over exactly the members the run names, and the stub annotates its literal with the same `Pick`. There is no cast, and no member becomes public or protected. - Methods go in as late-bound closures that call `this.m(...a)` on the plugin at call time. So every hook still reaches the plugin's method on the plugin, and a spy or test double set on the plugin is still the one the hooks reach. - Fields follow the rule cut 1 set, judged on each field's own declaration: - `bootstrapPermissionSets` is declared `readonly`, so it goes by value. It is the same array, whose sets `applyManagedWriteDenies` extends in place, as before. - `metadata` and `tenancyPosture` are not, so they go as getters, read when the hooks run. - `claimTargetAdminUserId` is the one member the run WRITES: `runBootstrap` records the platform admin it found or promoted (`if (report?.adminUserId) this.claimTargetAdminUserId = report.adminUserId;`, `:2281`). It goes as a get/set pair over two locals in the stub, `readClaimTargetAdminUserId` and `writeClaimTargetAdminUserId`, which read and assign `this.claimTargetAdminUserId` on the plugin. This is the form #25224 cut 10 (PR #25508, `7d3c0139fb`) used for `routeOwnership` in `auth-manager-request-routing.ts`. The write lands on the plugin, where cut 11's seed claim reads it through its own getter, so the claim still sees the admin the bootstrap recorded. - The host declares the read-only fields `readonly`, and `claimTargetAdminUserId` without it. The typecheck passes, so the run assigns no other member through the host. - None of these is function-valued, so no receiver changes. - Nothing re-exports the module, so the package entry does not move. ## No reader keys on the moved lines Each was measured on this head, not recalled: - R4 holds no `isSystem` read and no tenant-audit site. `isystem-census` gives 149 sites and `tenant-audit-census` 238 at both ends, with 0 differences and 0 sites in the new module. `check-system-context-census` prints the same summary at both ends, so `content/docs/permissions/system-context.mdx` and the census ledger are untouched. - R4 makes no `canReadObject` call, so the core row-serving pin is untouched. It resolves no delegator, so the #25107 pin is untouched. - The platform checklist's `security-plugin.ts#declareEveryone` (`access-security.json:2032`) resolves on the method, which stays. - No test or script that reads `security-plugin.ts` by path names R4's content. - The suite and every gate run at both ends (below). ## No new anchor entry, and one disclosure about the existing one `scripts/adr-anchors/` is not touched. Paragraph by paragraph, the `security-plugin.ts` entry: - ADR-0055 §1 is the relation reader (`security-plugin-cbp-relation.ts`). ADR-0106 D7 is the readable-field asymmetry (cut 9's module). ADR-0123 D2 is the write tenant wall's refusal (cut 5's module). R4 touches none of them. - ADR-0138 D1 says the seed-ownership claim "this file runs on every `app:seeded` (`claimSeedOwnershipOnSettle`) and at the first promotion" re-owns a NULL-owner row only when the seed reported landing on it (`readSeededRecordIds`). - The first-promotion arm, `runBootstrap`'s `seededRecordIds: readSeededRecordIds(ctx)`, moves into the new module with the run. - The run cites no ADR-0138, so an entry for the new module would need a citation the moved code does not carry, and this cut plants none. Cut 12's ADR-0123 D2 disclosure is the precedent. - The paragraph still holds for `security-plugin.ts`: the claim method and the `readSeededRecordIds` import stay there, and `start()` still registers the first-promotion pass, through the stub. - Cut 11's claim (6373426297) gave three reasons why that entry stays true: the method, the promotion-time pass and the import. The second now lives in the new module. The seed-claim module's own entry is unaffected. A follow-up can add an entry if the seat wants one. ## The published `.d.ts` does not change Measured under the series bar (ruling 6348891160 item 1), on base `e073455929` and on this head. Each was a full `turbo run build` in its own worktree (both exit 0, 77 tasks; `plugin-security` was a cache miss at both ends, so both were really built). - Raw sha256 of `dist/index.d.ts` and `dist/index.d.mts` is the same for all four files, base and head: `7e6a99f7d59debbac137ff8509e7d92fd5d000c655b412ab0f042a27ad35b380` (14,722 lines). The raw diff is 0 lines, so no union order moved either. - Normalised sha256 is the same for all four: `e22a714da70e9efc2849122d87f64bc2f364aa9a5a3fe73965118b5fd272f5a3`. - The normaliser, run from `packages/plugins/plugin-security`, sorts the members of each string-literal union and changes nothing else: ```sh node -e 'const s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join(" | ")))' dist/index.d.ts | sha256sum ``` - Positive control, a real package build rather than an edit of the emitted file. With `private` removed from the `epoch` field in the head source, `pnpm build` in the package gives raw `96fda037…` for both files, different from the real hash. So the comparison does see a visibility change. With the source restored (byte-compared to the committed file), a rebuild gives `7e6a99f7…` again. - `security-plugin.ts` gains no export. `registerStartHooks` and `StartHooksHost` are in no published file, because nothing re-exports the module. - Export tables: the ESM and CJS bundles each export the same 66 names at base and at head. The lists were loaded at runtime, with `require` and `import()` of the built bundles, not parsed. The sorted name list hashes to `df56a808` for all four. - The bundle JS bytes differ, because code moved within them: `index.js` goes from `77bed321` to `72283d9d`, and `index.mjs` from `29e9cece` to `af35c900`. The external specifiers each bundle loads are the same set at both ends: 17 in `index.js` and 20 in `index.mjs`. - Bundle order, disclosed. Thirteen module chunks are emitted later in `index.mjs`, because `security-plugin.ts` no longer imports them first. - Ten are modules whose import leaves `security-plugin.ts` whole: `position-catalog-refusal`, `grant-holder-membership-refusal`, `catalog-reference-report`, `upgrade-impact-report`, `managed-object-write-denies`, `packaged-permission-set-overlay-detection`, `object-posture-gate`, `packaged-permission-set-lock-gate`, `security-catalog-echo` and `cleanup-package-permissions`. The other three are modules those ten import: `federated-phantom-anchors`, `packaged-permission-set-lock` and `objects/sys-user-position.object`. - None of the thirteen imports `security-plugin.ts`. - Their top level only declares: constants, functions, classes, interfaces and types, a `Set`, a `WeakMap`, and `objects/sys-user-position.object.ts`'s `ObjectSchema.create(…)`. That is a validating constructor from `@objectstack/spec`, outside the bundle, and it registers nothing. - Both built bundles load at head (`import()` and `require`), so no top-level read meets an uninitialised binding. No changeset: `skip-changeset`, per ruling 6348891160 item 4. ## Proof of move-only Measured on this head against `e073455929`, with a scratch script that parses both files with the TypeScript compiler API. - **The run, by AST token and by text.** `registerStartHooks`'s body holds 16 statements, with the same TypeScript token sequence as the base run: 1,610 tokens. The body between its braces is the base text from the run's first comment line to its last statement's end, 421 lines, each with two leading spaces removed. That text check is what covers the comments between the statements. - **`start()` outside the run.** The head text of `start()` equals the base text exactly, outside the run, which is now an 18-line stub block ending in the `.call`. Its signature, docblock, the 32 statements before the run and the comment after it are byte-identical. `start()` goes from 876 lines to 473. - **The stub's host literal.** It has 7 members, exactly the `Pick`, in the same order. Each is in the form its own declaration calls for: 3 methods as `this.m(...a)` closures, `bootstrapPermissionSets` by value (declared `readonly`), two getters, each over a `read…` local that reads `this.m`, and `claimTargetAdminUserId` as a `get`/`set` pair over `readClaimTargetAdminUserId` and `writeClaimTargetAdminUserId`. The check also derives the members the base run writes, from the AST, and requires exactly those to be the get/set pairs. - **The host interface.** 7 members, each typed `SecurityPlugin['m']`. The fields the run only reads are `readonly`; the one it writes is not. Its set equals the `Pick`, and the `Pick` equals the set of `this.m` the base run names. - **Class side.** Every other class member is byte-identical to base: 125 named members plus the constructor. The class has 127 members at base and at head. - **Top level of `security-plugin.ts`.** Of the 102 top-level statements at base other than the class, 84 are byte-identical at head. The other 18 are imports: 13 are gone and 5 lose names (the seed-claim one also changes `readSeededRecordIds` to `type readSeededRecordIds`). The one new statement is the module's import. The check asserts the exact list of 27 dropped names and 3 added names (`registerStartHooks`, the type `StartHooksHost`, the type `readSeededRecordIds`). It also asserts that no dropped name is referenced in code, and that `readSeededRecordIds` appears exactly three times: the type import, the import comment and the one `{@link}`. - **Comments above imports.** `security-plugin.ts` loses cut 11's 4-line seed-claim comment and gains its 6-line rewrite plus the 3-line comment over the new import, and no other. The module's imports carry no comment. - **The module's imports.** 33 names, each imported from the specifier `security-plugin.ts` imports it from, with no type import turned into a value import. `./security-plugin.js` gives only the type `SecurityPlugin`. The module's top level is its 21 imports, `StartHooksHost` and `registerStartHooks`, and nothing else. - **Negative controls.** Fourteen mutations of one copy each, and every one fails the check it targets: - in the moved run, `{ object: POSITION_ASSIGNMENT_OBJECT }` changed to a string literal; - in the moved run, one word added to a comment between two statements (`[#22801 → A]`); - in `start()`, the log line before the stub changed; - in the stub, the `set claimTargetAdminUserId` line removed; - in the stub, the write local changed to assign `v ?? undefined`; - in the host interface, `readonly` added to `claimTargetAdminUserId`; - in the host interface, `readonly` dropped from `metadata`; - in the function's `Pick`, `bootstrapPermissionSets` left out; - in `security-plugin.ts`, `bootstrapPlatformAdmin` imported again; - in `security-plugin.ts`, `readSeededRecordIds` imported as a value again; - in `security-plugin.ts`, "the claim's docblock" changed to "its docblock" in the rewritten cut 11 comment; - in `security-plugin.ts`, one space added to `init()`'s signature; - in the module, `readDeclared` imported from another specifier; - in the module, a top-level `const` added. - **git's own view.** This is `git diff --color-moved=plain --color-moved-ws=allow-indentation-change e073455` over the two source files. - Of the 448 deleted lines in `security-plugin.ts`, git sees 439 as moved. The other 9 are cut 11's 4-line comment (rewritten, above) and five specifier lines of multi-line imports that lose a name. - Of the 523 lines of the new module, 446 show as moved. The other 77 are the module's own lines: its header, the regrouped imports, the host interface, and the function's docline, signature and closing brace. - **Size.** 999 changed lines (+551 / −448) over 2 files: `security-plugin.ts` (+28 / −448, from 6,164 to 5,744 lines) and the new module (+523). ## ADR anchors (ruling 6353073966 item 2) - `node scripts/check-adr-symbol-anchors.mjs` exits 0 at base `e073455929`, at this head, at today's `main` (`a57643d3de`) and on this head merged into it: 2,384 anchors over 142 records, 466 symbol anchors, at each. - `pnpm check:adr-anchors` exits 0 at both. Anchored files stay at 84. - **Decision letters on the anchored surface.** On the merge-base `e073455929`: 1888. On this head: 1877. On today's `main`, `a57643d3de`: 1883, because #25589, #25591 and #25592 landed after the merge-base (none touches this package). On this head merged into today's `main` (a clean `git merge-tree`): 1872. So the drop is −11 on either base. That gate counts `ADR-NNNN Dk` citations in each anchored file and in each entry's own invariant text. All −11 are R4's letters leaving `security-plugin.ts`, which holds 185 at base and 174 at head: - ADR-0090 D5 ×3, ADR-0131 D3 ×3; - ×1 each: ADR-0057 D4, ADR-0086 D1, ADR-0090 D11, ADR-0131 D10 and ADR-0131 D4. - Five letters leave `security-plugin.ts` entirely: ADR-0057 D4, ADR-0086 D1, ADR-0090 D11, ADR-0131 D10 and ADR-0131 D4. - The stub, the new import comment, the rewritten cut 11 comment and the module header cite none. No letter is planted and none is invented. - Every moved citation is still in the tree, in the module its code moved to. Citations that resolve tree-wide stay at 52,315, across 6,700 files at base and 6,701 at head (the new file is the module). - The anchor map covers every ADR symbol anchor that names `security-plugin.ts` or the new module, at both ends: 26 citing lines over 17 symbols, measured with `extractAnchors` and `symbolSegmentResolution` from `scripts/symbol-anchors.mjs` (measurement, not a new gate). No anchor changes file or class, and none resolves inside R4. | ADR line | anchor | base | head | |---|---|---|---| | ADR-0049:49 | `#SecurityPlugin` | security-plugin.ts · declaration · `:1206` (class) | security-plugin.ts · declaration · `:1189` (class) | | ADR-0055:123 | `#computeControlledByParentFilter` | security-plugin.ts · declaration · `:5067` (`computeControlledByParentFilter`) | security-plugin.ts · declaration · `:4647` (`computeControlledByParentFilter`) | | ADR-0055:125 | `#assertControlledByParentWrite` | security-plugin.ts · declaration · `:5421` (`assertControlledByParentWrite`) | security-plugin.ts · declaration · `:5001` (`assertControlledByParentWrite`) | | ADR-0055:125 | `#assertMasterRowEditable` | security-plugin.ts · declaration · `:5547` (`assertMasterRowEditable`) | security-plugin.ts · declaration · `:5127` (`assertMasterRowEditable`) | | ADR-0055:135 | `#CBP_MAX_CHAIN_DEPTH` | security-plugin.ts · declaration · `:700` (top-level) | security-plugin.ts · declaration · `:683` (top-level) | | ADR-0055:24 | `#computeRlsFilter` | security-plugin.ts · declaration · `:4441` (`computeRlsFilter`) | security-plugin.ts · declaration · `:4021` (`computeRlsFilter`) | | ADR-0055:5 | `#computeControlledByParentFilter` | security-plugin.ts · declaration · `:5067` (`computeControlledByParentFilter`) | security-plugin.ts · declaration · `:4647` (`computeControlledByParentFilter`) | | ADR-0055:58 | `#assertControlledByParentWrite` | security-plugin.ts · declaration · `:5421` (`assertControlledByParentWrite`) | security-plugin.ts · declaration · `:5001` (`assertControlledByParentWrite`) | | ADR-0066:112 | `#writeCheckPolicies` | security-plugin.ts · declaration · `:1142` (`writeCheckPolicies`) | security-plugin.ts · declaration · `:1125` (`writeCheckPolicies`) | | ADR-0096:181 | `#getReadFilter` | security-plugin.ts · declaration · `:3176` (`getReadFilter`) | security-plugin.ts · declaration · `:2756` (`getReadFilter`) | | ADR-0096:182 | `#getReadFilter` | security-plugin.ts · declaration · `:3176` (`getReadFilter`) | security-plugin.ts · declaration · `:2756` (`getReadFilter`) | | ADR-0096:183 | `#getReadFilter` | security-plugin.ts · declaration · `:3176` (`getReadFilter`) | security-plugin.ts · declaration · `:2756` (`getReadFilter`) | | ADR-0096:199 | `#getReadFilter` | security-plugin.ts · declaration · `:3176` (`getReadFilter`) | security-plugin.ts · declaration · `:2756` (`getReadFilter`) | | ADR-0099:341 | `#hasPlatformAdminPosture` | security-plugin.ts · declaration · `:4468` (`hasPlatformAdminPosture`) | security-plugin.ts · declaration · `:4048` (`hasPlatformAdminPosture`) | | ADR-0099:68 | `#manage_metadata` | security-plugin.ts · literal · `:363` (top-level) | security-plugin.ts · literal · `:346` (top-level) | | ADR-0105:93 | `#collectRLSPolicies` | security-plugin.ts · declaration · `:5601` (`collectRLSPolicies`) | security-plugin.ts · declaration · `:5181` (`collectRLSPolicies`) | | ADR-0123:4 | `#composeWriteTenantWall` | security-plugin.ts · declaration · `:4759` (`composeWriteTenantWall`) | security-plugin.ts · declaration · `:4339` (`composeWriteTenantWall`) | | ADR-0126:406 | `#nav_permission_sets` | security-plugin.ts · literal · `:1634` (`init`) | security-plugin.ts · literal · `:1617` (`init`) | | ADR-0138:152 | `#isPrincipalLessContext` | security-plugin.ts · declaration · `:573` (`isPrincipalLessContext`) | security-plugin.ts · declaration · `:556` (`isPrincipalLessContext`) | | ADR-0138:153 | `#SecurityPlugin.getMetadataReadableFields` | security-plugin.ts · declaration · `:3311` (`getMetadataReadableFields`) | security-plugin.ts · declaration · `:2891` (`getMetadataReadableFields`) | | ADR-0138:248 | `#SecurityPlugin` | security-plugin.ts · declaration · `:1206` (class) | security-plugin.ts · declaration · `:1189` (class) | | ADR-0138:265 | `#SecurityPlugin` | security-plugin.ts · declaration · `:1206` (class) | security-plugin.ts · declaration · `:1189` (class) | | ADR-0138:427 | `#SecurityPlugin.resolvePermissionSetsForContextUnmemoized` | security-plugin.ts · declaration · `:3905` (`resolvePermissionSetsForContextUnmemoized`) | security-plugin.ts · declaration · `:3485` (`resolvePermissionSetsForContextUnmemoized`) | | ADR-0139:222 | `#getReadFilter` | security-plugin.ts · declaration · `:3176` (`getReadFilter`) | security-plugin.ts · declaration · `:2756` (`getReadFilter`) | | ADR-0139:223 | `#computeDelegatedReadFilter` | security-plugin.ts · declaration · `:3230` (`computeDelegatedReadFilter`) | security-plugin.ts · declaration · `:2810` (`computeDelegatedReadFilter`) | | ADR-0139:246 | `#computeControlledByParentFilter` | security-plugin.ts · declaration · `:5067` (`computeControlledByParentFilter`) | security-plugin.ts · declaration · `:4647` (`computeControlledByParentFilter`) | ## Censuses Each census was run at base `e073455929` and at this head, and compared site by site, with the module path mapped back to `security-plugin.ts` and `registerStartHooks` mapped back to `start`. - `isystem-census`: 149 sites at both ends, 0 differences, 0 sites in the new module. Scanned files: 408 at both ends. - `check-system-context-census` exits 0 at both ends with byte-identical output: 149 sites in 22 packages across 77 files, 129 symbols, 142 cited against 142 required, 164 anchors, 21 declared non-read, 20 row references. - `tenant-audit-census`: 238 sites at both ends, 0 differences, 0 sites in the new module, 176 non-engine calls, 87 engine types, 117 declared objects. ## Gates 85 commands, run at base `e073455929` and at this head, each in its own worktree after a full `turbo run build`. They are the 54 families `scripts/pm/dispatch-gates` derives for this file list, the 18-command artifact roster, the hand-picked readers of `security-plugin.ts` (ADR and scripts symbol anchors, `check:adr-anchors`, the platform checklist, the three censuses, query-options erasure), and the package tests. - Head: 85 of 85 exit 0. `dispatch-gates --ran`: 54 derived, 54 run, 0 NOT-MEASURED. - Base: 84 exit 0. The eslint line names the new module, which does not exist there; eslint on `security-plugin.ts` alone exits 0 at base. - Tests: `@objectstack/plugin-security` 222 files, 4,628 passed and 45 skipped at both ends; its typecheck exits 0 at both; the two core pins that read the plugin (`row-serving-door-exposure`, `operation-private-keys`) pass 8 of 8 at both. No test is added, edited or skipped. - Output compared with paths, timings and timestamps masked: 58 identical and 27 different, each read. - 22 differ only by a file count that grows by one, the new module (for example `undeclared-dep-imports` 3,347 → 3,348 files, `isystem-census` corpus 9,692 → 9,693, `tenant-audit-census` sources 755 → 756). - `check-issue-citations` reads no added lines at base; at head it judges the 19 citations the added lines carry, all resolve. - `check:adr-anchors`: the letters above. - `dual-build-cjs-loads` (730 → 728 CommonJS files) and `sourcemap-no-sources-content` (602 → 598 maps): the base worktree's `packages/metadata-protocol/dist` still held six orphan files from an earlier build there (`build-probes-UIM275UL.cjs`, `chunk-PHCN2WJI.cjs` and four maps, referenced by nothing). Otherwise the two trees' `dist` file lists are identical; the head's count is the clean one. - The plugin-security test log differs in interleaving only. - Today's `main`: `origin/main` moved to `a57643d3de` (#25589, #25591, #25592; none touches `plugin-security`, `scripts/adr-anchors` or `docs/adr`). This head merges into it cleanly. On today's `main` and on the merged tree, `check:adr-anchors`, `check-adr-symbol-anchors`, `check-scripts-symbol-anchors`, `check-system-context-census`, `check-tenant-audit-census` and `check-platform-checklist` all exit 0, with the same counts at both apart from the −11 letters. - `check-governed-merges --test` on the final file list at today's `main`: 0 of 2 paths hit the register; 999 changed lines (+551 / −448). Not governed. ## Acceptance notes - Nothing outside this cut is touched: no other section of the class or of `start()`, no behaviour, no anchor entry, no `docs/**` and no `packages/spec/**`. The PR changes two files, both in `packages/plugins/plugin-security/src/`. - Serial check: none of the open PRs touches `security-plugin.ts` or any `security-plugin-*.ts` module (re-listed right before this PR was opened). - After this cut, nothing movable is left in `security-plugin.ts`. The report on #25223 lists every body that stays, with its reason, every cut PR, and the file's line count at the start of the series (11,054) and at the end (5,744). --- _Generated by [Claude Code](https://claude.ai/code/session_017BoLT8Gaa8t9a7AWVH8qZa)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017BoLT8Gaa8t9a7AWVH8qZa Co-authored-by: Claude <noreply@anthropic.com>
1 parent e649c2d commit dad27ef

2 files changed

Lines changed: 551 additions & 448 deletions

File tree

0 commit comments

Comments
 (0)