Skip to content

Commit fc38b08

Browse files
committed
test(auth): hold the ObjectQL double contracts in the agreement pin's fake
Two shrink-only ratchets judged the new fake and were right about both. `check:objectql-double-limit` read the `find` double as limit-blind: it answered every matching row while `bootstrapPlatformAdmin` really does pass a bound (1 for the permission-set probe, 50 for the user and grant reads). The bound is now applied AFTER the filter, by presence, the shape the gate prescribes. `check:engine-double-contract` flagged the double's `update()` as a fake write verb looser than `ObjectQL.update`. The verb is DELETED rather than pinned: its only caller is the `resync` branch, which this pin never asks for, so it was dead surface. Its absence also short-circuits `claimSeedOwnership` at that function's own `typeof ql.update !== 'function'` guard, one step earlier than the registry guard it used to stop at. Neither ratchet's baseline was touched. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0157mMVAq9fjGe2kaSD2aJC8
1 parent fe92c3a commit fc38b08

1 file changed

Lines changed: 15 additions & 7 deletions

File tree

‎packages/plugins/plugin-auth/src/human-user-predicate-agreement.pin.test.ts‎

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,19 @@ import { isHumanUserRow } from './audience-posture.js';
8282
/**
8383
* Minimal in-memory ql: three tables, `where` matched by equality. Enough for
8484
* `bootstrapPlatformAdmin`'s seed step, its existing-admin probe and the
85-
* first-user promotion. `claimSeedOwnership` (best-effort, on the promotion
86-
* path) short-circuits because this object exposes no `registry`.
85+
* first-user promotion.
86+
*
87+
* Two deliberate omissions, both load-bearing:
88+
*
89+
* - **No `update`.** The only caller is the `resync` branch, which this pin
90+
* never asks for. Declaring one anyway would be a fake write verb looser
91+
* than `ObjectQL.update` sitting on a path no assertion covers — so it is
92+
* absent rather than pinned. Its absence also short-circuits
93+
* `claimSeedOwnership` (best-effort on the promotion path) at that
94+
* function's own `typeof ql.update !== 'function'` guard.
95+
* - **`find` honours the caller's `limit`** — applied AFTER the filter, by
96+
* presence, so a bound the caller really passes is not silently ignored by
97+
* a double that answers with more rows than the real engine would.
8798
*/
8899
function makeQl(userRows: unknown[]) {
89100
const tables: Record<string, any[]> = {
@@ -96,21 +107,18 @@ function makeQl(userRows: unknown[]) {
96107
async find(object: string, q: any) {
97108
const rows = tables[object] ?? [];
98109
const where = q?.where ?? {};
99-
return rows.filter((r) =>
110+
const matched = rows.filter((r) =>
100111
Object.entries(where).every(([k, v]) => {
101112
if (k.startsWith('$')) throw new Error(`fake driver: unsupported operator ${k}`);
102113
return (r as any)?.[k] === v;
103114
}),
104115
);
116+
return typeof q?.limit === 'number' ? matched.slice(0, q.limit) : matched;
105117
},
106118
async insert(object: string, data: any) {
107119
(tables[object] ??= []).push({ ...data });
108120
return { id: data.id };
109121
},
110-
async update(object: string, data: any) {
111-
const row = (tables[object] ?? []).find((r) => (r as any)?.id === data?.id);
112-
if (row) Object.assign(row as object, data);
113-
},
114122
};
115123
}
116124

0 commit comments

Comments
 (0)