Repository navigation
Commit dad27ef
<!-- 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
0 commit comments