Skip to content

Commit 16dbdf5

Browse files
committed
test(plugin-approvals): judge the #14946 fake engine's find bound by presence; re-anchor the system-context page; ledger the new pin file
- the fake engine's `find` no longer reads `this` (the objectql-double-limit probe calls it unbound) and applies the caller's bound after the filter, by presence, instead of a default page of 1000 - content/docs/permissions/system-context.mdx: six approval-service.ts line anchors re-aimed by +57, the net insertion of the businessUnitMemberScope docblock above them (check-system-context-census --fix) - engine-double-contract ledger learns business-unit-member-org-screen.test.ts Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
1 parent fe370ce commit 16dbdf5

3 files changed

Lines changed: 18 additions & 5 deletions

File tree

content/docs/permissions/system-context.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ The largest single consumer — **17 of the 106 sites**.
145145
|:--|:---|:---|:---|:---|
146146
| 40 | **Approval record lock released** — a locked record is writable | plugin-approvals | Get: engine self-writes (the status mirror) pass. Lose: the lock that stops edits while an approval is live. Note there is deliberately **no admin exemption** here — only `isSystem` | `lifecycle-hooks.ts:347` |
147147
| 41 | Delegation write guard bypassed | plugin-approvals | Get: service / seed / import may write delegation rows naming another delegator | `lifecycle-hooks.ts:570` |
148-
| 42 | Approval actor / submitter / pending-approver checks bypassed (8 sites) | plugin-approvals | Get: approve, reject, recall, reassign without being a pending approver or the submitter | `plugin-approvals/src/approval-service.ts:963`, `:1072`, `:3248`, `:3396`, `:3564`, `:3635`, `:3824`, `:3864` |
148+
| 42 | Approval actor / submitter / pending-approver checks bypassed (8 sites) | plugin-approvals | Get: approve, reject, recall, reassign without being a pending approver or the submitter | `plugin-approvals/src/approval-service.ts:963`, `:1072`, `:3305`, `:3453`, `:3621`, `:3692`, `:3881`, `:3921` |
149149
| 43 | Saved-report ownership is **assignable**, and an update may reassign it | plugin-reports | Get: `ownerId` from input is honoured. A non-system caller always owns what it creates and can never reassign | `plugin-reports/src/report-service.ts:404`, `:425` |
150150
| 44 | Saved-report access / export / mutation gates bypassed | plugin-reports | Get: read, bulk-export and overwrite any report | `plugin-reports/src/report-service.ts:343`, `:372`, `:447`, `:684` |
151151
| 45 | Attachment access hooks return early (insert + update + delete, and the read AST) | service-storage | Lose: attachment visibility scoping | `attachment-access-hooks.ts:300`, `:349`, `:448`, `:524` |

packages/plugins/plugin-approvals/src/business-unit-member-org-screen.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,17 @@ function makeFakeEngine() {
7676
}
7777
return true;
7878
}
79+
/** Every `find` anyone made, with its options — pins the predicate SHAPE (B5). */
80+
const finds: Array<{ object: string; options: any }> = [];
7981
return {
8082
_tables: tables,
81-
/** Every `find` anyone made, with its options — pins the predicate SHAPE (B5). */
82-
_finds: [] as Array<{ object: string; options: any }>,
83+
_finds: finds,
8384
async find(object: string, options?: any) {
84-
this._finds.push({ object, options });
85+
finds.push({ object, options });
8586
const rows = ensure(object).filter(r => matches(r, options?.filter ?? options?.where));
86-
return rows.slice(0, options?.limit ?? 1000);
87+
// The caller's bound, applied AFTER the filter and by PRESENCE — the
88+
// shape `check:objectql-double-limit` holds every ObjectQL double to.
89+
return typeof options?.limit === 'number' ? rows.slice(0, options.limit) : rows;
8790
},
8891
async insert(object: string, data: any) { ensure(object).push({ ...data }); return { ...data }; },
8992
async update(object: string, data: any, options?: any) {

scripts/engine-double-contract.pinned.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,16 @@
21312131
"verb": "update",
21322132
"pinned": 1
21332133
},
2134+
{
2135+
"file": "packages/plugins/plugin-approvals/src/business-unit-member-org-screen.test.ts",
2136+
"verb": "delete",
2137+
"pinned": 1
2138+
},
2139+
{
2140+
"file": "packages/plugins/plugin-approvals/src/business-unit-member-org-screen.test.ts",
2141+
"verb": "update",
2142+
"pinned": 1
2143+
},
21342144
{
21352145
"file": "packages/plugins/plugin-approvals/src/decision-strand-envelope.test.ts",
21362146
"verb": "delete",

0 commit comments

Comments
 (0)