v0.1.75 — 22 May 2026
Bug Fix — Filter extensions on daas_users now correctly block user creation via POST /api/users
Affected endpoint: POST /api/users
Who is affected: Anyone who attached a filter type extension to the
daas_users.items.create event and expected a rejected filter to prevent the
user from being created.
What was wrong
When a filter extension threw an error (e.g. new HookError('Not allowed', 400))
the API returned a 400 response as expected — but the user was still created.
Subsequent GET /api/users calls would show the new user, and their Supabase
Auth entry was fully active.
Root cause
The endpoint called supabase.auth.admin.createUser() before running the
filter. Supabase’s auth API fires a database trigger on success that immediately
inserts the user into daas_users. By the time the filter ran, the creation
was already committed and could not be reversed.
What changed
The handler now runs the filter first — before any write to Auth or the
database. If the filter rejects the operation, nothing is created. Only after
the filter approves the payload does the handler call auth.admin.createUser(),
stamp the returned id onto the record, and persist it.
Before / After
| Scenario | Before this fix | After this fix |
|---|---|---|
Filter throws HookError(400) | ❌ 400 returned but user created | ✅ 400 returned, user not created |
| Filter modifies email / name | ❌ Original values used for auth user | ✅ Filter-modified values used |
| Filter approves payload | ✅ User created | ✅ User created |
Bug Fix — POST /api/utils/import/[collection] now enforces permissions and runs extension filters
Affected endpoint: POST /api/utils/import/{collection}
Who is affected:
- Anyone who attached a
filteroractionextension toitems.createon a collection — those extensions were silently skipped for all imported records. - Anyone who relied on collection-level permission policies to restrict write access — any authenticated user could import data into any collection.
What was wrong
Extensions skipped: The endpoint wrote records directly to the database using a raw upsert, bypassing the entire extension and hook pipeline. Filter extensions, action hooks, and validation rules were never called.
No permission check: The endpoint only verified that the caller was
authenticated. It did not check whether the caller had create permission on
the target collection.
What changed
- All writes now go through
ItemsService, which runs the full filter and hook pipeline. A filter extension that blocksitems.createwill now also block import, and the per-record error is captured in theerrorsarray in the response. - Non-admin users must have
createpermission on the target collection; permission errors return 403. - Scope (
X-Resource-Uri) is respected, consistent with every other write endpoint.
Before / After
| Scenario | Before this fix | After this fix |
|---|---|---|
Filter extension on items.create during import | ❌ Silently skipped | ✅ Executed per record |
Non-admin without create permission imports data | ❌ Allowed (auth check only) | ✅ 403 Forbidden |
| Import by admin | ✅ Worked | ✅ Still works |
| Extension error for one batch | ❌ N/A (bypassed) | ✅ Captured in errors[]; other batches continue |
Behaviour change
If you were importing data as a non-admin user without an explicit create
permission policy on the collection, those imports will now return 403. Add a
create permission entry for the relevant role to restore access.
Additionally, the updated field has been removed from the response body —
the response now contains inserted and total only.