You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2cadb01
Browse filesBrowse the repository at this point in the historyBrowse files
fix(plugin-auth): read the canonical QueryAST in the admin-import protocol
`runImport` now sends `where` / `limit`, and it takes an INJECTED
`ImportProtocolLike`. The wire-alias folding the runner's rewrite relied on
lives in `ObjectStackProtocolImplementation`; a hand-written protocol never
passes through it, so `admin-import-users.ts` read `args.query.$filter` and
got `undefined`.
The failure mode is not a missing filter but an unbounded one: `?? {}` turns
the unread key into an empty filter, the upsert duplicate probe stops
discriminating, and an admin import updates the wrong user. Both halves were
red on this branch (`admin-import-users.test.ts:560` and `:592`).
- The adapter reads `args.query.where` / `args.query.limit`, with no `??`
behind either. One dialect, and an absent `query` is a loud TypeError
rather than a silent match-everything.
- The three `import-runner` test doubles read `where` too. Two were red
(`import-runner-selfref.test.ts`, `import-runner-bulk.test.ts`); the third
was GREEN FOR THE WRONG REASON — its degraded `{}` matched the whole store,
so every no-duplicate assertion held without the probe discriminating.
- `import-runner-idempotency.test.ts` gains the assertion that closes that:
every probe must narrow, and the id recheck is pinned to the
`id: { $in: [...] }` over exactly the pre-assigned ids, bounded by `limit`.
`ImportProtocolLike.findData(args: any)` is deliberately untouched — narrowing
a published extension point is a contract decision and has its own card.
Claude-Session: https://claude.ai/code/session_015QE8qk46e5CHJxyQEUjbf8
Co-authored-by: Claude <noreply@anthropic.com>
`runAdminImportUsers`'s hand-written `ImportProtocolLike` reads the CANONICAL QueryAST (`where` / `limit`) — the payload `@objectstack/rest`'s import runner sends as of this same release — instead of the wire-only `$filter` / `$top`.
6
+
7
+
`POST /api/v1/auth/admin/import-users` reuses the shared import runner but swaps in an identity-specific protocol, because an identity write is `auth.api.createUser` and not an engine insert. That protocol is hand-written, so it never passes through `ObjectStackProtocolImplementation` — the normalizer that folds `$filter` onto `where` and `$top` onto `limit` for a caller arriving off the HTTP door. It has to read the canonical keys itself.
8
+
9
+
-**A mismatch here does not produce a missing filter, it produces an unbounded one.**`const where = args?.query?.$filter ?? {}` turns an unread key into an empty filter, and an empty filter constrains nothing: the upsert duplicate probe stops discriminating, `findExisting` matches rows it was given no key for, and an admin import updates the WRONG user. Both halves are measured in `admin-import-users.test.ts` — the email-match case reported `updated: 2` where one of the two rows was new, and the phone-match case sent a probe carrying no `where` at all.
10
+
-**One dialect, and no default behind it.** The two reads are now `args.query.where` and `args.query.limit`, with no `??`. A default here would not be tolerance for an older caller — this handle is fed by the runner, never off the wire — it is precisely the lenient fallback that converts a spelling mismatch into a silent match-everything. A request that arrives without a `query` now costs a loud `TypeError` instead.
11
+
12
+
⚠️ No published version shipped the mismatch. The runner's rewrite and this adapter land in the same release, and `@objectstack/plugin-auth` depends on `@objectstack/rest` at an exact workspace version, so the two cannot be installed apart. What this entry records is why they move together — and what the same mismatch costs any OTHER hand-written `ImportProtocolLike`, which the `@objectstack/rest` entry calls out for implementors.
0 commit comments