Skip to content

@btravstack/prisma


@btravstack/prisma / rls

rls ​

Classes ​

TenantListingInvalid ​

Defined in: packages/prisma/src/tenant-listing.ts:6

A tenant-listing declaration names an invalid identifier or shares its privileged owner with its caller.

Extends ​

  • TaggedErrorInstance<"TenantListingInvalid", { field: keyof TenantListingOptions; reason: "invalid-identifier" | "shared-role"; }>

Constructors ​

Constructor ​
ts
new TenantListingInvalid(args): TenantListingInvalid;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsobject & object
Returns ​

TenantListingInvalid

Inherited from ​

TaggedError("TenantListingInvalid")<{ readonly field: keyof TenantListingOptions; readonly reason: "invalid-identifier" | "shared-role"; }>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"TenantListingInvalid"TaggedError("TenantListingInvalid")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknownTaggedError("TenantListingInvalid").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
fieldreadonlykeyof TenantListingOptionsTaggedError("TenantListingInvalid").fieldpackages/prisma/src/tenant-listing.ts:7
messagepublicstringTaggedError("TenantListingInvalid").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("TenantListingInvalid").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
reasonreadonly"invalid-identifier" | "shared-role"TaggedError("TenantListingInvalid").reasonpackages/prisma/src/tenant-listing.ts:8
stack?publicstringTaggedError("TenantListingInvalid").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Type Aliases ​

TenantListing ​

ts
type TenantListing = object;

Defined in: packages/prisma/src/tenant-listing.ts:28

A declaration's migration, ready for Prisma 8's rawSql, and its tenant-id-only query.

Properties ​

PropertyModifierTypeDescriptionDefined in
listreadonly(db, after?) => AsyncResult<readonly string[], SqlError>At most 100 IDs in bytewise order. Resume with the last ID; stop on an empty page.packages/prisma/src/tenant-listing.ts:47
migrationreadonlyobject-packages/prisma/src/tenant-listing.ts:29
migration.executereadonlyreadonly Statement[]-packages/prisma/src/tenant-listing.ts:43
migration.idreadonlystring-packages/prisma/src/tenant-listing.ts:30
migration.labelreadonlystring-packages/prisma/src/tenant-listing.ts:31
migration.operationClassreadonly"additive"-packages/prisma/src/tenant-listing.ts:32
migration.postcheckreadonlyreadonly Statement[]-packages/prisma/src/tenant-listing.ts:44
migration.precheckreadonlyreadonly Statement[]-packages/prisma/src/tenant-listing.ts:42
migration.targetreadonlyobject-packages/prisma/src/tenant-listing.ts:33
migration.target.detailsreadonlyobject-packages/prisma/src/tenant-listing.ts:35
migration.target.details.namereadonlystring-packages/prisma/src/tenant-listing.ts:39
migration.target.details.objectTypereadonly"rlsPolicy"-packages/prisma/src/tenant-listing.ts:37
migration.target.details.schemareadonlystring-packages/prisma/src/tenant-listing.ts:36
migration.target.details.tablereadonlystring-packages/prisma/src/tenant-listing.ts:38
migration.target.idreadonly"postgres"-packages/prisma/src/tenant-listing.ts:34

TenantListingOptions ​

ts
type TenantListingOptions = object;

Defined in: packages/prisma/src/tenant-listing.ts:12

Physical database names and existing roles for a narrow tenant-listing capability.

Properties ​

PropertyModifierTypeDescriptionDefined in
namereadonlystringA new paged function in schema; also names its select policy.packages/prisma/src/tenant-listing.ts:18
ownerreadonlystringTrusted function owner with no payload SELECT, superuser or BYPASSRLS; needs schema CREATE.packages/prisma/src/tenant-listing.ts:20
rolereadonlystringApplication role granted execution, with no membership in owner and no schema CREATE privilege.packages/prisma/src/tenant-listing.ts:22
schemareadonlystring-packages/prisma/src/tenant-listing.ts:13
tablereadonlystring-packages/prisma/src/tenant-listing.ts:14
tenantColumn?readonlystringThe physical tenant column. Default tenantId.packages/prisma/src/tenant-listing.ts:16

TenantPinnedOptions ​

ts
type TenantPinnedOptions<S> = QualifyOptions<S> & object;

Defined in: packages/prisma/src/rls.ts:16

Options of tenantPinned: raises, as tryQuery takes it, and the setting the pin writes.

Type Parameters ​

Type ParameterDefault type
S extends stringnever

Type Declaration ​

NameTypeDescriptionDefined in
setting?stringThe PostgreSQL run-time setting the policy reads. Defaults to app.tenant_id, matching current_setting('app.tenant_id', true).packages/prisma/src/rls.ts:21

Functions ​

tenantListing() ​

ts
function tenantListing(options): Result<TenantListing, TenantListingInvalid>;

Defined in: packages/prisma/src/tenant-listing.ts:97

Declare a paged SECURITY DEFINER function returning distinct, non-null tenant IDs as text, and a typed query calling only that function. Each page holds at most 100 IDs in bytewise order; resume after its last ID until empty.

Pass migration to Prisma 8's rawSql inside a reviewed migration. Its transaction installs an owner-only SELECT policy, grants the owner access to the tenant column, fixes the function's search path, revokes PUBLIC execution and grants execution to role. Existing table policies and FORCE ROW LEVEL SECURITY are left intact. No application table privilege is added.

Roles and the table must already exist. The migrator must be able to SET ROLE to the owner; provision that membership for an ordinary migration role. The migration refuses a privileged application or function-owner role, caller membership in the owner, schema CREATE for the caller, owner payload SELECT, or any same-name function overload. Its postcheck verifies the function, policy and execution grants before Prisma records it as applied. Apply the operation transactionally; the function is initially private only once the REVOKE runs. Do not grant the application the owner role afterwards.

Parameters ​

ParameterType
optionsTenantListingOptions

Returns ​

Result<TenantListing, TenantListingInvalid>


tenantPinned() ​

ts
function tenantPinned<Tx, R, S>(
   db, 
   tenant, 
   work, 
   options?
): AsyncResult<R, SqlError | Raised<S>>;

Defined in: packages/prisma/src/rls.ts:86

Runs work in a transaction whose connection is pinned to tenant, so a row-level-security policy reading current_setting('app.tenant_id', true) admits that tenant's rows and no others.

The pin is set_config(setting, tenant, true) — transaction-local, which is the whole reason this opens a transaction rather than issuing the pin and handing back a client. A session-scoped pin followed by a separate query works only while the pool happens to hand back the same connection, and fails the first time it does not; it is the shape a middleware would take, and it is why there is no middleware here.

It answers an AsyncResult, qualified by tryQuery — with raises as it takes it: the pin and the work run on one connection and fail on one channel, so a caller never wraps this in a second combinator. work still hands back a PromiseLike, because that is what Prisma's own transaction callback is.

Type Parameters ​

Type ParameterDefault type
Tx extends Queryable-
R-
S extends stringnever

Parameters ​

ParameterType
dbPinnable<Tx>
tenantstring
work(tx) => PromiseLike<R>
options?TenantPinnedOptions<S>

Returns ​

AsyncResult<R, SqlError | Raised<S>>

Remarks ​

The policy must read the same setting name. A tenantPinned(db, tenant, work, { setting }) whose policy names a different one denies every row and every write, which looks exactly like row security working.

Example ​

ts
const orders = await tenantPinned(db, tenant, (tx) => tx.orm.orders.Order.all());

Released under the MIT License.