Plugins
actor
Record who created, changed and deleted each row.
import { actor } from "better-supabase/plugins/actor";
const db = defineSupabase(schema)
.use(actor())
.connect(supabase, { actor: { id: user.id, kind: "user" } });- Inserts get
createdByandupdatedBy. - Updates get
updatedBy. WithsoftDelete(), the delete is an update, soupdatedByrecords who deleted the row. - Upserts that may update only get
updatedBy. - Tables with an
impersonated_bycolumn (plugins.actor.impersonatedByin the config renames it) getimpersonatedByon each insert and update made during impersonation: the admin fromactor.impersonator. The user's own writes leave it alone, so the row keeps the last impersonating admin. That is what the SQL modules'track_actor(table, impersonated_by => 'impersonated_by')writes, and it also keepscreated_byon updates. - Anonymous requests set nothing.
createdBy,updatedByandimpersonatedByvalues you pass yourself are refused withinvalid_request, so a caller cannot sign a row as someone else. Pass{ override: true }for imports and backfills.
Server adapters fill actor from the verified JWT. Jobs run as the user who
enqueued them with bs.forContext(job.context) (see
jobs), webhooks and scripts with
bs.actingAs(userId), and work no user owns with bs.admin(), whose actor
is service. Pass resolve(context) to read the id from somewhere else.
For a tamper-proof trail, add the actor and audit SQL module triggers, which
read auth.uid() inside the database.
Last updated on