Repository navigation
Commit 77a77e4
<!-- 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 6 of the `security-plugin.ts` split: the rest of step 3.7's Layer 0
tenant write wall, and the engine middleware's context prologue. The
claim is 6358893564, amended by 6359105931 before the push (below). The
bodies of four async methods move unedited out of the class:
- to
`packages/plugins/plugin-security/src/security-plugin-write-tenant-wall.ts`,
beside cut 5's `composeWriteTenantWall`:
- `organizationWallRefusal`, the ADR-0123 D2 scope pre-test. The wall
and `canWriteObject` both ask it.
- `writeWallVerdict`, the wall's per-row verdict for the write preview
(#25062), which the engine asks through `registerWriteWallVerdict`.
- to the new module
`packages/plugins/plugin-security/src/security-plugin-operation-principals.ts`:
- `resolveOperationPrincipals`, the context prologue. It refuses a
context the operation may not run under (ADR-0096 D5 strict mode; on a
walled posture, an on-behalf-of context whose delegator is not a member
of the live organization, ADR-0090 D10 and #25063). It resolves every
other context to the principal's permission sets, and the delegator's on
a delegated context.
- `refuseGuestWithoutOrganization`, the prologue's ADR-0138 D4 refusal
of a guest acting in no organization.
It is move-only, and the card stays open for the later cuts. Branch:
`claude/project-thread-3fzya4`, the harness-pinned branch for this
session, restarted from `origin/main` at `bdf762c9bd`, which carries cut
5's merge `be318db654`. It names no issue, so the claim comment is the
identity record.
**What stays in the class.** Each moved method keeps its name,
signature, docblock and position, less `async`. Three thin adapters of
the wall stay whole: `computeWriteTenantCheckFilter`,
`computeWriteTenantWall` and `raiseWriteWallRefusal`. Each body is
shorter than its stub would be. The middleware, `canWriteObject` and
every other caller still call the methods.
**Module-level declarations.**
- Two move to the wall module, as they stood, docblocks included:
`callerHasOrganizationScope` and `carriesActiveOrganization`. Only the
moved bodies read them: the pre-test reads the first, and the first and
cut 5's body read the second. `carriesActiveOrganization` loses the
`export` cut 5 gave it, so the wall module no longer imports anything
back from `security-plugin.ts` for it.
- Two move to the prologue module: `principalLessDenial`, the ADR-0096
D5 refusal only the prologue throws, docblock included, and the
`@objectstack/core` import of `GuestOrganizationUnresolvedError` and
`resolveGuestOrganization`, comment included, because only the guest
refusal reads it. `principalLessDenial` gains `export` there.
- Three stay and gain `export`. Each module imports what it reads by
value, as cuts 3 and 5 import theirs.
- `isPrincipalLessContext`: ADR-0138:152 anchors it in
`security-plugin.ts`, and the probes and the row scope read it there.
- `isGuestEnvelope`: the middleware's owner-write step and the set
resolution read it.
- `isTenantWallDenial`: `tenant-layer.ts` names it as living in
`security-plugin.ts`.
- `isPrincipalLessContext`'s docblock names the refusal with `{@link
principalLessDenial}`. `security-plugin.ts` imports that name type-only
from the prologue module, so the link still resolves. A type-only import
emits nothing and has no runtime effect; typecheck and lint pass with
it.
- **Why the refusal moves rather than staying exported (the claim
amendment).** The claim had `principalLessDenial` staying in
`security-plugin.ts` with `export`. That was measured on the first head
build: its return type makes the file's declarations import `errors.ts`,
and the published `dist/index.d.ts` then declares
`PermissionDeniedError` and `isPermissionDeniedError` at the top instead
of after the class. That is a raw diff of 102 lines, one 51-line block
moved with its text unchanged, and ruling 6348891160 admits union-order
swaps only. With the refusal moved, the head `.d.ts` is byte-identical
to base.
- Each value import is read only inside a function body, at call time,
never while either module evaluates. `index.ts` still exports only
`SecurityPlugin`, so the published surface does not move (measured
below).
- `WriteTenantWall`, `WriteWallRefusal` and `WriteWallRowVerdict` keep
their one declaration. The method signatures, `raiseWriteWallRefusal`
and `start()` read them. The wall module names all three through the
class's own signatures, as cuts 2 to 5 name theirs.
- The `postureUsesUnionScope` name leaves the
`@objectstack/spec/security` import of `security-plugin.ts`, because no
code left there reads it. The wall module already imports it.
**Two readers outside the moved code follow the bodies.**
- `content/docs/permissions/system-context.mdx`, row 6c. Its anchor is
`security-plugin.ts#writeWallVerdict`, the census site of the body's
`context.isSystem` read. `check-system-context-census` keys each
elevation read by file and enclosing symbol, so with the body moved and
the anchor unchanged the census finds a file with no row. The anchor now
names `security-plugin-write-tenant-wall.ts#writeWallVerdict`. Only the
path changed. The census lists the same sites at base and head, with the
one site's file mapped back (below).
-
`packages/plugins/plugin-security/src/delegated-organization-membership.test.ts`,
the #25107 enumeration pin. It counts, per source file, the delegator
resolutions and the organization-refusal asks, and lists the files that
resolve one. The prologue's one resolution and its one ask now sit in
the new module. The expected list gains
`security-plugin-operation-principals.ts`, and the title says three
files instead of two. The rule it pins, asks equal resolutions in every
file, is unchanged, and it holds at head: the new module counts 1 and 1,
`security-plugin.ts` 7 and 7.
## The published `.d.ts` does not change
Under the series bar (ruling 6348891160 item 1), measured on base
`bdf762c9bd` and on the head (the tree of this PR's commit):
- Raw sha256 of `dist/index.d.ts` and `dist/index.d.mts`, base and head,
all four the same:
`af5dee1bebafa0376a876d1e7b247c878ea42ac35c7336a6d3c12a7953143156`. The
raw diff is 0 lines, so no union order moved either.
- Normalised sha256, all four the same:
`431e7f5097ac1c220bc840188aef02105bc0b16e845e976dd562d02cc79be8bd`.
- The hashes differ from cut 5's report because `origin/main` moved
between cut 5's base and this one. Base and head here are both built
against `bdf762c9bd`'s dependencies, rebuilt on that commit first.
- The first head build of this cut did not meet the bar, and the claim
amendment 6359105931 records why. With `principalLessDenial` kept in
`security-plugin.ts` and exported, the head `.d.ts` declared
`PermissionDeniedError` and `isPermissionDeniedError` at the top instead
of after the class: a raw diff of 102 lines, one 51-line block moved
with its text unchanged. The refusal moved to the prologue module
instead, and the head above is the tree after that change.
- The normaliser, run from `packages/plugins/plugin-security` (it 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 controls on a copy of the head `dist/index.d.ts`, line 1813
(`private organizationWallRefusal;`):
- Made public (`organizationWallRefusal;`): raw
`648873d54d4f3adf15cdbdd199ae7fa25bc46a30230249cebfe5e5bb812c29d1`,
normalised
`847afa0caa5b4756a02a9e7833a0a878783a41187ac45e2e6aea5600a2b35fcf`.
- Renamed (`private organizationWallRefusalRenamed;`): raw
`7a1e24b3874a47fb0a2a54f368917c6db961f2fcde858a11145e55cf7c9e423d`,
normalised
`f76ae5f05b7ca709d90f94a15277906f2862240f3b923c61707dcd703a632bec`.
- Both differ from the real hashes, so the comparison does see a
visibility change and a rename. The first head build above is a third,
unplanned control: the comparison saw one declaration move.
- `writeWallVerdict` is public, so the `.d.ts` carries its full
signature. It is the same line at base and head (line 1874 of both): the
four parameters `object`, `operation`, `context` and `rows`, and the
promise of one verdict per row or `null`.
- Export tables: the ESM and CJS bundles each export the same 66 names
at base and head. The lists were loaded at runtime (`require` and
`import()` of the built bundles), not parsed. The sorted name list
hashes
`83576430f83cf60cecbcc5c0e80214f16c626a8e66f700294fc6a44361423116` on
all four. The count differs from cut 5's 63 because `origin/main` added
exports between the two bases; it is the same at this base and head. The
new exports of `security-plugin.ts` (`isGuestEnvelope`,
`isPrincipalLessContext`, `isTenantWallDenial`) do not reach the entry.
- The bundle JS bytes differ (`index.js` `fe2eebf9` to `77ef1113`,
`index.mjs` `254fc57b` to `f604cc07`), because code moved within them.
No changeset: `skip-changeset`, per ruling 6348891160 item 4.
## What moved
The base line numbers are each method's signature and closing brace at
`bdf762c9bd`. The last column lists the members the body reads, which is
exactly what its host carries.
| method | to | base lines | host members |
|---|---|---|---|
| `organizationWallRefusal` (private, async) | wall | `:8471`-`:8493` |
`computeWriteTenantCheckFilter`, `orgScopingEnabled`, `tenancyPosture` |
| `writeWallVerdict` (public, async) | wall | `:8580`-`:8612` |
`composeWriteTenantWall`, `resolveOperationPrincipals` |
| `resolveOperationPrincipals` (private, async) | prologue |
`:8953`-`:9012` | `logger`, `ql`, `refuseGuestWithoutOrganization`,
`resolvePermissionSetsForContext`, `tenancyPosture` |
| `refuseGuestWithoutOrganization` (private, async) | prologue |
`:9038`-`:9062` | `guestOrganizationRefusalWarned`, `logger`, `ql`,
`tenancyPosture` |
Each stub drops `async` and returns the moved function's promise, as
cuts 1, 3 and 5 did for their async methods. The `.d.ts` emits no
`async`, so this does not reach it. That includes `writeWallVerdict`,
the one public method here, whose full signature the `.d.ts` carries.
## The shape (#23050 shape B, as cuts 1 to 5 applied it)
- The class keeps each method with its name, signature, docblock and
position, because tsup emits members with their JSDoc into the `.d.ts`.
Each body is now one host literal plus `fn.call(host, …)`, marked
`[#25223 cut 6]`.
- `WriteTenantWallHost` gains the members the two new wall bodies read
(`composeWriteTenantWall`, `resolveOperationPrincipals`), and
`OperationPrincipalsHost` is new. Each types every member as the class
member itself (`SecurityPlugin['m']`). Each moved function types its
`this` as the `Pick` of its host over exactly the members its body
reads, 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. A spy or test double set on the plugin is still the
one the body reaches:
- the pre-test still asks the read side's Layer 0 through
`computeWriteTenantCheckFilter`;
- the preview still runs the prologue and the wall through the plugin;
- the prologue still asks the plugin's `refuseGuestWithoutOrganization`
and `resolvePermissionSetsForContext`.
No moved body calls a function-valued field, so no receiver changes.
- Fields follow the rule cut 1 set, on each field's own declaration.
- `guestOrganizationRefusalWarned` is declared `readonly` and goes by
value, so the guest refusal records each reason it warned for in the
plugin's own set, once per reason as before.
- `ql`, `logger` and `tenancyPosture` are not `readonly` (the plugin
assigns each after construction), and `orgScopingEnabled` is the class's
own getter. All four go as getters, so each read happens when the body
makes it.
- The host declares every field `readonly`, so a moved body cannot
assign a member through it; the typecheck passes, so none does.
- Nothing re-exports either module, so the package entry does not move.
## Proof of move-only
- **Bodies, by AST token**: each moved function's body has the same
TypeScript token sequence as the base method body, and each of its 117
lines is the base line with two leading spaces removed. Parameters, the
return type and `async` match. Two negative controls fail the check:
- in the prologue module, the delegation branch's guard on the resolved
set count changed from greater than zero to at least zero;
- in the wall module, `context.isSystem || !context.userId` changed to
`context.isSystem && !context.userId` in the preview's first guard.
- **Cut 5's function**: `composeWriteTenantWall` in the wall module is
byte-identical to base, its pointer docblock included.
- **Class side**: each moved method keeps its docblock and signature,
less `async`. Every other class member, 122 named members plus the
constructor, is byte-identical to base. That includes the three
adapters, `canWriteObject`, `checkControlledByParentWrite`,
`resolvePermissionSetsForContext` and `start()`. The class has 127
members at base and at head.
- **Top level of `security-plugin.ts`**: 96 of the 105 base top-level
statements other than the class are byte-identical to base,
`WriteTenantWall`, `WriteWallRefusal` and `WriteWallRowVerdict`
included. The nine that differ:
- three are the base text with `export ` before `function`:
`isGuestEnvelope`, `isPrincipalLessContext`, `isTenantWallDenial`;
- four moved, with their text checked in the module:
`callerHasOrganizationScope` (identical), `carriesActiveOrganization`
(identical less the `export ` cut 5 added), `principalLessDenial`
(identical plus `export `) and the `@objectstack/core` import
(identical, comment included);
- the `@objectstack/spec/security` import, which loses
`postureUsesUnionScope`;
- cut 5's import of the wall module, which now names cut 6's two
functions too. The one new statement is the import of the prologue
module, with the type-only `principalLessDenial`.
- **git's own view** (`git diff --color-moved=plain
--color-moved-ws=allow-indentation-change bdf762c HEAD` over the
three source files): 183 of 240 deleted lines and 211 of 448 added lines
are detected as moved.
- Deleted, not moved (57). In `security-plugin.ts` (14): cut 5's import
of the wall module with its comment (4 lines), the
`postureUsesUnionScope,` import line, the five declaration lines that
come back changed (`isGuestEnvelope`, `isPrincipalLessContext` and
`isTenantWallDenial` with `export`; `principalLessDenial` with `export`,
in the prologue module; `carriesActiveOrganization` without `export`, in
the wall module) and the four method signature lines, which come back
without `async`. In the wall module (43): cut 5's module docblock and
its import of `carriesActiveOrganization`, rewritten for two cuts, and
two lines of the host docblock, which now speak of several functions.
- Added, not moved: those lines' replacements, the four stubs and the
two import blocks with their comments. In the wall module: the new
docblock and imports, the third type alias and the two new host members.
In the prologue module: the license header, the docblock, the imports,
`OperationPrincipalsHost`, the pointer docblocks and the rewritten
signature heads. The rest are lines git does not pair with a moved
block, such as blanks and closing braces.
- **Size**: 694 changed lines (+451 / -243, 5 files), under the
3000-line human-merge threshold. `security-plugin.ts` goes from 9,992 to
9,863 lines, and the wall module from 437 to 567. The prologue module is
207 lines.
## ADR anchors (ruling 6353073966 item 2)
- `node scripts/check-adr-symbol-anchors.mjs`: exit 0 at base
`bdf762c9bd` and exit 0 at head, both with `2383 anchors across 142
records resolve — 466 symbol (440 declaration, 26 literal), 1889
file-level, 28 cross-repo, 6 exempt, 18 continuation`, the same counts
as cut 5. CI runs this gate (`lint.yml`), but `dispatch-gates
--commands` does not derive it for this change set (#21697), so it is
run by hand here.
- `pnpm check:adr-anchors`: exit 0 at base and at head, 79 anchored
files at both (no entry added or changed). One count moves, and it is
disclosed here rather than answered with a new anchor entry. The
decision-letter citations on the anchored surface go from 2014 to 2010.
Seven `ADR-NNNN Dk` citations move with the prologue's text into the
prologue module, which has no anchor entry: `ADR-0090 D10` four times in
the delegation branch, `ADR-0138 D4` twice (the moved import comment and
the guest refusal's warning) and `ADR-0096 D5` once
(`principalLessDenial`'s docblock). The two new import comments in
`security-plugin.ts` add three. Every citation still resolves as a
citation: the total goes from 52091 to 52100, across 6619 to 6620 files.
Writing an invariant paragraph for the prologue module would be new
prose about the prologue, outside a move-only cut. #25224 cut 5
disclosed the same kind of shift the same way. The wall module is
anchored, so the six citations that move into it (the pre-test's comment
and the two lifted docblocks) stay on the anchored surface.
- `scripts/adr-anchors/` is unchanged. The wall module's entry (cut 5)
carries ADR-0123 and the ADR-0123 D2 paragraph, which describes the
no-active-organization pre-test; `organizationWallRefusal` is that
pre-test, and it now lives in the module the entry names. No paragraph
of the `security-plugin.ts` entry (ADR-0055, ADR-0106, ADR-0123 D2,
ADR-0138 D1) describes the prologue or the guest refusal, so the
prologue module gets no entry, as cut 1's module has none. The
`security-plugin.ts` entry is unchanged. `docs/adr/**` is not touched.
- The anchor map covers every ADR symbol anchor naming
`security-plugin.ts`: 27 anchors, 18 symbols. It was measured with
`extractAnchors` and `symbolSegmentResolution` from
`scripts/symbol-anchors.mjs`, which is measurement, not a new gate. It
was read on `bdf762c9bd` BEFORE the cut, with the four bodies blanked:
no anchor changed class. Every anchor resolves at head in
`security-plugin.ts` with its base class.
The table gives each anchor's class at base and head, the line it
resolves on, and the member that line sits in. Every anchor stays in
`security-plugin.ts`.
| anchor | cited at | base class · line (member) | head class · line |
|---|---|---|---|
| `#CBP_MAX_CHAIN_DEPTH` | ADR-0055:135 | declaration · `:663`
(top-level) | declaration · `:658` |
| `#SecurityPlugin` | ADR-0049:49, ADR-0138:248, ADR-0138:265 |
declaration · `:1340` (class) | declaration · `:1290` |
| `#SecurityPlugin.getMetadataReadableFields` | ADR-0138:153 |
declaration · `:2516` (`start`), `:6135` (method) | declaration ·
`:2466`, `:6085` |
| `#SecurityPlugin.resolvePermissionSetsForContextUnmemoized` |
ADR-0138:427 | declaration · `:7046` (method) | declaration · `:6996` |
| `#assertControlledByParentWrite` | ADR-0055:58, ADR-0055:125 |
declaration · `:9249` (method shell) | declaration · `:9120` |
| `#assertMasterRowEditable` | ADR-0055:125 | declaration · `:9375`
(method shell) | declaration · `:9246` |
| `#collectRLSPolicies` | ADR-0105:93 | declaration · `:9429` (method) |
declaration · `:9300` |
| `#composeWriteTenantWall` | ADR-0123:4 | declaration · `:8513` (method
shell) | declaration · `:8458` (method shell), and `:8533` (see below) |
| `#computeControlledByParentFilter` | ADR-0055:5, ADR-0055:123,
ADR-0139:246 | declaration · `:8841` (method shell) | declaration ·
`:8766` |
| `#computeDelegatedReadFilter` | ADR-0139:223 | declaration · `:6013`
(method) | declaration · `:5963` |
| `#computeRlsFilter` | ADR-0055:24 | declaration · `:5265`
(`explainAccessForCaller`), `:7740` (method) | declaration · `:5215`,
`:7690` |
| `#getReadFilter` | ADR-0096:181, :182, :183, :199, ADR-0139:222 |
declaration · `:2275` (`start`), `:5891` (method) | declaration ·
`:2225`, `:5841` |
| `#hasPlatformAdminPosture` | ADR-0099:317 | declaration · `:7767`
(method) | declaration · `:7717` |
| `#isPrincipalLessContext` | ADR-0138:152 | declaration · `:517`
(top-level) | declaration · `:531` (top-level, now `export function`) |
| `#manage_metadata` | ADR-0099:68 | literal · `:266`
(`PLATFORM_ADMIN_ONLY_CAPABILITIES`) | literal · `:280` |
| `#nav_permission_sets` | ADR-0126:363 | literal · `:1768` (`init`) |
literal · `:1718` |
| `#rlsFilter` | ADR-0055:24 | declaration · `:4342` (local in `start`)
| declaration · `:4292` |
| `#writeCheckPolicies` | ADR-0066:112 | declaration · `:1235`
(top-level) | declaration · `:1185` |
No resolving site moves out of the file. One anchor gains a site, and
its class does not change. ADR-0123:4 `#composeWriteTenantWall` still
resolves on the method declaration, which stays as a shell. At head the
name also starts a line in `writeWallVerdict`'s stub, as its
host-literal key, the closure that calls the method on the plugin
(`:8533`), and appears quoted in that stub's `Pick` (`:8532`). Cut 3's
stub added the same kind of site for `#assertControlledByParentWrite`
(`checkControlledByParentWrite`'s stub, `:8980` here). The anchor is
judged by its class, which is `declaration` at base and at head.
ADR-0138:152 `#isPrincipalLessContext` resolves on the declaration,
which stays and gains `export`.
## Readers
Two readers of the moved lines exist outside the moved code, the census
row and the enumeration pin above, and both are re-pointed in this PR.
No other test, script, gate, baseline or docs anchor reads the moved
lines by path.
- **The system-context census.** `check-system-context-census` exits 0
at base and at head. Both print `148 elevation read sites in 22 packages
… the page cites 140 symbol(s) against 140 required, over 163 anchors`.
The only difference is the file count, 70 to 71, because the one read
site of `writeWallVerdict` now sits in the wall module. `node
scripts/isystem-census.mjs --json` gives the same 148 sites at base and
head, compared without line numbers and with the two new modules mapped
back to `security-plugin.ts`: 0 differences. The role counts are the
same (`read` 153, `declaration` 38, `key` 438, `other` 9), and only the
corpus and scanned file counts move, by one.
- **The tenant-audit census.** The moved bodies hold no engine write:
the prologue reads through `resolveDelegatorContext` and
`resolveGuestOrganization`, which take `ql` as an argument. `node
scripts/tenant-audit-census.mjs --json` gives the same 237 write call
sites at base and head, compared the same way: 0 differences, the same
totals, 0 unresolved, 0 unledgered. Only `scannedSources` moves, 715 to
716, plus the measured-at ref. `check-tenant-audit-census` prints the
same line at both.
- **The #25107 enumeration pin** is described above. It is part of the
plugin-security suite, which passes at head with the same counts as
base.
- **`packages/core/src/security/row-serving-door-exposure.pin.test.ts`**
classifies every caller of the read admission. The moved bodies call no
admission, so the new module needs no row. Run on its own: 3 of 3 pass.
- **The platform checklist.** `check-platform-checklist` exits 0 at base
and head with the same output. No checklist citation names a moved
symbol or a local inside a moved body.
- **Readers by name, not by path.** These were read and none needs a
change:
- `packages/core/src/security/guest-organization.ts` names
`SecurityPlugin.resolveOperationPrincipals`, and `explain-engine.ts` and
`delegated-organization-membership.test.ts` name
`resolveOperationPrincipals`. The method still exists under that name.
- `tenant-layer.ts` names `isTenantWallDenial` in `security-plugin.ts`,
and `explain-engine.ts` names `isTenantWallDenial`. It stays there.
- `write-wall-verdict-equivalence.test.ts` calls
`plugin.writeWallVerdict(…)`, and `packages/objectql` names it in
comments. The public method still exists with the same signature.
- Docblocks in `security-plugin.ts` name `{@link
resolveOperationPrincipals}`, `{@link composeWriteTenantWall}` and
`{@link canWriteObject}`. The methods still exist.
- **Line citations**: no `security-plugin.ts:N` citation in the repo
points into the moved ranges (base `:8471`-`:8493`, `:8580`-`:8612`,
`:8953`-`:9012`, `:9038`-`:9062`) or at the moved module-level
declarations. The citations found are the list cuts 2 to 5 read
(`docs/launch-readiness.md` `:309`, `packages/objectql/src/engine.ts`
`:1614`, `:1690`, `:1736`, spec liveness `:3281` and the rest). Each
already pointed at an unrelated line before cut 2, so this cut does not
make any of them wrong.
- **Docs Drift Check**, re-derived with `node
scripts/docs-audit/affected-docs.mjs --json bdf762c` (advisory): 1
page, `content/docs/permissions/system-context.mdx`, through
`writeWallVerdict`. That is the census row this PR re-points.
- **Census gates, run on base `bdf762c9bd` and head and compared:**
- Identical output: `check-adr-symbol-anchors`,
`check-platform-checklist`, `check-platform-object-tenancy-census`,
`check-registry-log-declared`, `check-rest-log-spy-declared`,
`check-tenant-audit-census`, `check:cross-package-test-inputs`,
`check:driver-memory-census` and `check:query-options-erasure`. The last
reports the same counts at both, and `security-plugin.ts` is not a
baseline key.
- Only scanned counts move:
- `check-system-context-census`: 70 to 71 files, as above.
- `check-undeclared-dep-imports`: 3301 to 3302 files, and 2843 to 2844
specifiers. The prologue module imports `@objectstack/spec/security` and
`@objectstack/core`, and `security-plugin.ts` drops the one
`@objectstack/core` import that moved. Both are declared dependencies.
- `check:org-identifier`: 3643 to 3644 files.
- `check:doc-authoring`: 1420 to 1421 parsed sources. Its clean-file
count goes from 424 to 427 because the head worktree holds three
gitignored generated pages that the base worktree does not
(`content/docs/protocol-upgrade/17.md`, `18.md` and `index.md`). CI's
checkout does not have them.
- `check:logger-receiver-detach`: 3617 to 3619 files: the new module,
and one local build output, as at cuts 2 to 5.
- `check-position-name-fold-loaders`: 12331 to 12335 files, with the
same 8 references (6 test, 2 declared instrument, 0 loader). It walks
the working tree: the new module plus local build outputs that exist
only in the head worktree.
- `check-issue-citations` judges a change set, so it has nothing to read
at base. At head it judged 13 citations across 3 files, and all resolve.
## Acceptance notes
- Nothing outside this cut is touched: no other section of the class, no
behaviour, no `docs/adr/**`, no `scripts/adr-anchors/` entry. The one
file outside the package is the census page, and only its row 6c path
changes.
- Serial check, also in the claim: of the 25 open PRs at claim time,
none touched `security-plugin.ts`, the wall module,
`system-context.mdx`, the delegated-organization test or the
plugin-security anchor entries.
- Since the local runs, `origin/main` gained 15 commits (to
`b22ab8d6fb`). None touches this cut's files. On a scratch merge of this
head onto that main, `check-adr-symbol-anchors`, `check:adr-anchors`,
`check-platform-checklist` and `check-system-context-census` all exit 0.
`check:adr-anchors` there counts 80 anchored files and 2013
decision-letter citations, against 80 and 2017 on that main alone (main
added an anchored file), so the shift this cut makes is the same four.
- What is left of the tenant write wall in `security-plugin.ts` after
this cut: the three adapters (`computeWriteTenantCheckFilter`,
`computeWriteTenantWall`, `raiseWriteWallRefusal`), the four method
shells, the three type declarations and the middleware's step 3.7.
## Gates
All gates ran at the head, the tree of `0177b21a24`, on base
`bdf762c9bd`.
- `pnpm --filter @objectstack/plugin-security test` (`vitest run
--maxWorkers=3`, under the verify lock): Test Files 214 passed (214),
Tests 4465 passed, 45 skipped (4510). Base `bdf762c9bd` gives the same
counts. VERDICT command-exit 0 on both. The first head commit (before
the claim amendment) gave the same counts too.
- `pnpm --filter @objectstack/plugin-security typecheck`: exit 0. It
runs `tsc --noEmit`, the scripts tsconfig, and `check:test-typecheck`.
- `eslint --no-inline-config` over the three touched source files and
the touched test: exit 0.
- `pnpm --filter @objectstack/plugin-security build`: exit 0. It
produced the `.d.ts` and bundles measured above. The package's
dependencies were rebuilt on `bdf762c9bd` first.
- `packages/core/src/security/row-serving-door-exposure.pin.test.ts`: 3
of 3 pass.
- `node scripts/check-adr-symbol-anchors.mjs`, `pnpm check:adr-anchors`,
`pnpm check:platform-checklist` (and its script),
`check-scripts-symbol-anchors` (and `--self-test`), and the two census
`--json` reads. None of these is derived for this change set; each was
run by hand, and each exit is listed below.
- `dispatch-gates --commands`: 88 commands. The census page adds the
docs families, as it did at cut 3. The `--ran` reconciliation shows 88
derived, 88 run, 0 NOT-MEASURED, 0 UNRUN. The zero is derived: all 88
recorded an exit code and none is 3.
Per command (exit code), the 88 derived first and the 8 hand-run after:
- `node scripts/check-ci-filter-parity.mjs` exit 0
- `node scripts/check-closing-keyword-parity.mjs` exit 0
- `node scripts/check-closing-keyword-parity.mjs --self-test` exit 0
- `node scripts/check-comment-mask-adoption.mjs` exit 0
- `node scripts/check-comment-mask-adoption.mjs --self-test` exit 0
- `node scripts/check-comment-mask-corpus.mjs` exit 0
- `node scripts/check-doc-frontmatter.mjs` exit 0
- `node scripts/check-doc-frontmatter.mjs --self-test` exit 0
- `node scripts/check-doc-route-spelling.mjs --advisory` exit 0
- `node scripts/check-doc-route-spelling.mjs --self-test` exit 0
- `node scripts/check-docs-section-name.mjs` exit 0
- `node scripts/check-docs-section-name.mjs --self-test` exit 0
- `node scripts/check-dts-emitted.mjs --self-test` exit 0
- `node scripts/check-issue-citations.mjs` exit 0
- `node scripts/check-keyed-text-bounds.mjs` exit 0
- `node scripts/check-keyed-text-bounds.mjs --self-test` exit 0
- `node scripts/check-platform-object-tenancy-census.mjs` exit 0
- `node scripts/check-platform-object-tenancy-census.mjs --self-test`
exit 0
- `node scripts/check-plugin-teardown-shape.mjs` exit 0
- `node scripts/check-plugin-teardown-shape.mjs --self-test` exit 0
- `node scripts/check-position-name-fold-loaders.mjs` exit 0
- `node scripts/check-position-name-fold-loaders.mjs --self-test` exit 0
- `node scripts/check-registry-log-declared.mjs` exit 0
- `node scripts/check-registry-log-declared.mjs --self-test` exit 0
- `node scripts/check-rest-log-spy-declared.mjs` exit 0
- `node scripts/check-rest-log-spy-declared.mjs --self-test` exit 0
- `node scripts/check-section-landing-index.mjs` exit 0
- `node scripts/check-section-landing-index.mjs --self-test` exit 0
- `node scripts/check-system-context-census.mjs` exit 0
- `node scripts/check-system-context-census.mjs --self-test` exit 0
- `node scripts/check-tenant-audit-census.mjs` exit 0
- `node scripts/check-tenant-audit-census.mjs --self-test` exit 0
- `node scripts/check-undeclared-dep-imports.mjs` exit 0
- `node scripts/check-undeclared-dep-imports.mjs --self-test` exit 0
- `node scripts/docs-audit/check-affected-docs.mjs` exit 0
- `node scripts/docs-audit/check-drift-comment.mjs` exit 0
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions`
exit 0
- `pnpm --filter @objectstack/lint run check:doc-security-posture` exit
0
- `pnpm --filter @objectstack/spec run check:docs` exit 0
- `pnpm --filter @objectstack/spec run check:duration-unit-keys` exit 0
- `pnpm --filter @objectstack/spec run check:empty-state` exit 0
- `pnpm --filter @objectstack/spec run check:liveness` exit 0
- `pnpm --filter @objectstack/spec run check:skill-examples` exit 0
- `pnpm --filter @objectstack/spec run check:strictness-ledger` exit 0
- `pnpm --filter @objectstack/spec run check:variant-docs` exit 0
- `pnpm --filter @objectstack/spec run check:yaml-examples` exit 0
- `pnpm check:closed-ceremony-text` exit 0
- `pnpm check:corpus-claim-drift` exit 0
- `pnpm check:cross-package-test-inputs` exit 0
- `pnpm check:doc-anchors` exit 0
- `pnpm check:doc-authoring` exit 0
- `pnpm check:docs-audit-scope` exit 0
- `pnpm check:docs-redirects` exit 0
- `pnpm check:docs-single-h1` exit 0
- `pnpm check:docs-spec-enumerations` exit 0
- `pnpm check:docs-transcript-drift` exit 0
- `pnpm check:driver-memory-census` exit 0
- `pnpm check:dts-closure` exit 0
- `pnpm check:dual-build-cjs-loads` exit 0
- `pnpm check:engine-double-contract` exit 0
- `pnpm check:error-status-conformance` exit 0
- `pnpm check:gitlink-declared` exit 0
- `pnpm check:i18n` exit 0
- `pnpm check:i18n-stale-fill` exit 0
- `pnpm check:issue-citations` exit 0
- `pnpm check:lean-entry-closure` exit 0
- `pnpm check:logger-receiver-detach` exit 0
- `pnpm check:merge-driver` exit 0
- `pnpm check:nul-bytes` exit 0
- `pnpm check:objectql-double-limit` exit 0
- `pnpm check:org-identifier` exit 0
- `pnpm check:page-declaration-shape` exit 0
- `pnpm check:published-files` exit 0
- `pnpm check:published-readme-links` exit 0
- `pnpm check:query-options-erasure` exit 0
- `pnpm check:react-page-adapter-contract` exit 0
- `pnpm check:refd-timer-probe` exit 0
- `pnpm check:role-word` exit 0
- `pnpm check:skill-identifier-liveness` exit 0
- `pnpm check:slot-lookup` exit 0
- `pnpm check:sourcemap-no-sources-content` exit 0
- `pnpm check:test-source-alias` exit 0
- `pnpm check:tier-file-adoption` exit 0
- `pnpm check:type-check-coverage` exit 0
- `pnpm check:type-check-debt` exit 0
- `pnpm check:vendor-version-stamps` exit 0
- `pnpm check:watch-hint-literal` exit 0
- `pnpm check:where-matcher` exit 0
- `node scripts/check-adr-symbol-anchors.mjs` exit 0
- `node scripts/check-platform-checklist.mjs` exit 0
- `node scripts/check-scripts-symbol-anchors.mjs` exit 0
- `node scripts/check-scripts-symbol-anchors.mjs --self-test` exit 0
- `node scripts/isystem-census.mjs --json` exit 0
- `node scripts/tenant-audit-census.mjs --json` exit 0
- `pnpm check:adr-anchors` exit 0
- `pnpm check:platform-checklist` exit 0
---
_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 3306cad commit 77a77e4
5 files changed
Lines changed: 451 additions & 243 deletions
File tree
- content/docs/permissions
- packages/plugins/plugin-security/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
106 | | - | |
| 106 | + | |
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
685 | 685 | | |
686 | 686 | | |
687 | 687 | | |
688 | | - | |
| 688 | + | |
689 | 689 | | |
690 | 690 | | |
691 | 691 | | |
| |||
694 | 694 | | |
695 | 695 | | |
696 | 696 | | |
697 | | - | |
| 697 | + | |
698 | 698 | | |
699 | 699 | | |
700 | 700 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
0 commit comments