permdock 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/active-tenant-DVee32-T.js +39 -0
- package/dist/{adoption-scan-Ch07MdxN.js → adoption-scan-DKCOsfcF.js} +1 -1
- package/dist/{arazzo-BpS7LnV0.js → arazzo-BXaEhGHM.js} +1 -1
- package/dist/{arazzo-CmQaGPkM.js → arazzo-CTH5iN--.js} +1 -1
- package/dist/better-supabase/index.d.ts +188 -23
- package/dist/better-supabase/index.js +246 -62
- package/dist/{casbin-B7_yS-oo.js → casbin-BuTZnSPv.js} +1 -1
- package/dist/{casbin-bHyIxTNQ.js → casbin-DTi6HSsl.js} +1 -1
- package/dist/cli/bin.js +1 -1
- package/dist/cli/index.d.ts +6 -1
- package/dist/cli/index.js +10 -2
- package/dist/{cloud-3kWfjnYy.js → cloud-DiAiYFRo.js} +2 -2
- package/dist/{codemod-Bv5i-Mzo.js → codemod-C1U8_Zu3.js} +1 -1
- package/dist/{codemod-D9Aiii1r.js → codemod-_q_ZI01S.js} +2 -2
- package/dist/{collect-B80GYEot.js → collect-D9Tt0Bcx.js} +1 -1
- package/dist/{completion-_bc0OUQ-.js → completion-DLTuCf53.js} +1 -1
- package/dist/{config-BwPBfN0t.js → config-BR23fL8m.js} +2 -2
- package/dist/{config-D5XrLWpk.js → config-CmydKZr2.js} +1 -1
- package/dist/{config-report-BmWIskD7.js → config-report-5AwptLr2.js} +2 -2
- package/dist/{config-shape-ykV0Vm2n.js → config-shape-tsxHx71E.js} +2 -1
- package/dist/{create-BamXmeob.d.ts → create-CDd9c22W.d.ts} +10 -1
- package/dist/{doctor-LPMYjSqO.js → doctor-DxyVeUEE.js} +2 -2
- package/dist/{doctor-ClRVAtXQ.js → doctor-ktitU5Dl.js} +142 -14
- package/dist/{fields-D0vUI6dq.js → fields-DI8s3cPl.js} +1 -1
- package/dist/{gen-BtfFWGbz.js → gen-DuAhghDw.js} +1 -1
- package/dist/{gen-BFfzZSLH.js → gen-DwgCSC6V.js} +1 -1
- package/dist/{import-CST57XLp.js → import-CNBF96hB.js} +2 -2
- package/dist/{import-ACkOrv6g.js → import-t1yqnCyG.js} +1 -1
- package/dist/{index-vYjMrXyK.d.ts → index-Cay5-Kvx.d.ts} +3 -51
- package/dist/index.d.ts +2 -1
- package/dist/{init-txYTuW9u.js → init-CY7THM2v.js} +3 -3
- package/dist/{init-BjuFDYT1.js → init-DFwylmiN.js} +1 -1
- package/dist/{login-CgfCTO3F.js → login-B92-dZMK.js} +1 -1
- package/dist/{login-CfImTJGb.js → login-C5XLYZSF.js} +3 -3
- package/dist/{manifest-CzzWtnAb.d.ts → manifest-B5yF3CIq.d.ts} +19 -0
- package/dist/{manifest-wg8WkkpD.js → manifest-BXTbHNIV.js} +1 -1
- package/dist/{manifest-B2QPh19C.js → manifest-Cav1rjNQ.js} +33 -33
- package/dist/{manifest-schema-2r37XRhD.js → manifest-schema-DQkBK2Mr.js} +28 -1
- package/dist/{migrate-B7oP_sQU.js → migrate-BJHxQqT5.js} +2 -2
- package/dist/{module-values-BJTBdo6y.js → module-values-B1EVTkHP.js} +1 -1
- package/dist/next/index.d.ts +16 -3
- package/dist/next/index.js +1 -1
- package/dist/next/plugin.d.ts +1 -1
- package/dist/next/plugin.js +1 -1
- package/dist/{openapi-BGeuunWC.js → openapi-CuePQL4z.js} +1 -1
- package/dist/{openapi-BIpw3Mb7.js → openapi-gMQQSzNn.js} +2 -2
- package/dist/{output-DV5dwOTs.js → output-CtyBwTNB.js} +1 -1
- package/dist/{ownership-DA5YdYTm.js → ownership-qqBuGJXr.js} +3 -3
- package/dist/{postgrest-5Dr3W64L.js → postgrest-DAxFltvO.js} +1 -1
- package/dist/powersync-6vgKevSi.js +1 -0
- package/dist/{powersync-Bg8u-JcR.js → powersync-CBcsEvdr.js} +2 -2
- package/dist/{powersync-CJrT1DSc.js → powersync-CD8-Ypao.js} +188 -36
- package/dist/{pull-2nJr0qg_.js → pull-CAeaAioC.js} +2 -2
- package/dist/pull-DfJALUbS.js +1 -0
- package/dist/{push-Bn-lMEmI.js → push-Dq_ca4-j.js} +1 -1
- package/dist/{resolve-names-ConCSj1y.js → resolve-names-Y1Cb22cp.js} +4 -4
- package/dist/{rls-Ba9wN0SP.js → rls-BYHN5bcJ.js} +1 -1
- package/dist/{rls-Cx0dtsB7.js → rls-CtRaRrn3.js} +22 -15
- package/dist/run-0vOholnN.js +1 -0
- package/dist/{run-PbRlXTfh.js → run-B5nyNKe8.js} +3 -3
- package/dist/{run-ticket-Dv7aF7Dk.js → run-ticket-DfnZCh-u.js} +19 -6
- package/dist/{run-ticket-B2o2Kxz8.d.ts → run-ticket-ylovhyFQ.d.ts} +16 -1
- package/dist/{scan-CRTj6fke.js → scan-CvFWW_fU.js} +1 -1
- package/dist/{schema-BTsE1WRT.js → schema-CQzIJdEd.js} +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +1 -1
- package/dist/{shared-Afctg7B0.js → shared-DrGLwM3s.js} +1 -1
- package/dist/{skills-C9uKfSF5.js → skills-BZc81VLt.js} +1 -1
- package/dist/{skills-CQQcuGBi.js → skills-Bar7ZqwM.js} +1 -1
- package/dist/{sources-CMAM-2A3.js → sources-C4vkzZJV.js} +12 -7
- package/dist/{types-BMVDHvI0.d.ts → sources-oB1Hg1Fm.d.ts} +316 -2
- package/dist/supabase/index.d.ts +10 -3
- package/dist/supabase/index.js +4 -4
- package/dist/{supabase-SBs3MYUE.js → supabase-CBEK6KEo.js} +2 -2
- package/dist/{supabase-DnMMg5Fn.js → supabase-CC6rIri4.js} +3 -2
- package/dist/supabase-hook-CWvEpdCh.js +1 -0
- package/dist/{supabase-hook-CrgU06WH.js → supabase-hook-CyuD9Wau.js} +110 -47
- package/dist/{supautils-ByezN3b8.js → supautils-C-_jqylY.js} +8 -8
- package/dist/{tables-BqrxBCir.js → tables-DimBcVWY.js} +2 -2
- package/dist/testing/fixtures/index.d.ts +1 -1
- package/dist/testing/fixtures/index.js +26 -28
- package/dist/testing/index.d.ts +4 -3
- package/dist/testing/index.js +3 -2
- package/dist/{types-CzOeVvcC.d.ts → types-Cklw5hJo.d.ts} +23 -2
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +1 -1
- package/dist/usage-CNca1i1W.js +1 -0
- package/dist/{usage-B9EtHWLa.js → usage-Y6xZUfE-.js} +2 -2
- package/dist/{usage-CBzgwfIs.js → usage-heV5KOiU.js} +1 -1
- package/dist/{verify-DlUcTDBz.js → verify-6EauWrkP.js} +6 -6
- package/dist/version-cache-Df11C2Qp.d.ts +51 -0
- package/dist/{watch-BFDKqmUa.js → watch-Bpci3hBY.js} +1 -1
- package/dist/watch-COuvly20.js +1 -0
- package/dist/workflow/index.d.ts +1 -1
- package/dist/workflow/index.js +22 -6
- package/dist/workflow-sdk/index.d.ts +1 -1
- package/package.json +2 -2
- package/schemas/run-v1.json +16 -0
- package/schemas/supabase-manifest-v1.json +28 -0
- package/skills/permdock-agents/references/operations-automations-chat.md +1 -0
- package/skills/permdock-approvals/references/stores-and-resume.md +1 -1
- package/skills/permdock-wire/references/adapters.md +2 -2
- package/dist/powersync-B701tvhE.js +0 -1
- package/dist/pull-C3EEGzSw.js +0 -1
- package/dist/run-Ck22anC2.js +0 -1
- package/dist/sources-CWG32C0G.d.ts +0 -312
- package/dist/supabase-hook-C0FyEACZ.js +0 -1
- package/dist/usage-0hjZPIRX.js +0 -1
- package/dist/watch-ClLuO2TL.js +0 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { i as qualifySqlTable } from "./sql-0WjxIp9g.js";
|
|
2
|
+
//#region src/better-supabase/active-tenant.ts
|
|
3
|
+
function describe(from) {
|
|
4
|
+
return "appMetadata" in from ? `app_metadata.${from.appMetadata}` : `${from.table}.${from.column} (joined on ${from.id})`;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Why PermDock's token hook and better-supabase disagree on the active tenant,
|
|
8
|
+
* or `undefined` when they agree. `"resolver"` takes the tenant from the
|
|
9
|
+
* request, so any hook source agrees with it.
|
|
10
|
+
*/
|
|
11
|
+
function activeTenantMismatch(from, tenantClaim, activeTenant) {
|
|
12
|
+
if (activeTenant === "resolver") return;
|
|
13
|
+
if (activeTenant === "claim") {
|
|
14
|
+
if ("appMetadata" in from && from.appMetadata === tenantClaim) return;
|
|
15
|
+
return `blocks.permissions.activeTenant is "claim", so better-supabase's switch_organization writes app_metadata.${tenantClaim}, but PermDock's token hook reads the active tenant from ${describe(from)}. Set supabase.hook.activeFrom: "app_metadata.${tenantClaim}" and run permdock supabase hook generate.`;
|
|
16
|
+
}
|
|
17
|
+
const dot = activeTenant.profileColumn.lastIndexOf(".");
|
|
18
|
+
if (dot <= 0) return;
|
|
19
|
+
const table = qualifySqlTable(activeTenant.profileColumn.slice(0, dot));
|
|
20
|
+
const column = activeTenant.profileColumn.slice(dot + 1);
|
|
21
|
+
const id = activeTenant.key ?? "id";
|
|
22
|
+
if ("table" in from && qualifySqlTable(from.table) === table && from.column === column && from.id === id) return;
|
|
23
|
+
return `blocks.permissions.activeTenant writes the active tenant to ${table}.${column} (joined on ${id}), but PermDock's token hook reads it from ${describe(from)}. Set supabase.hook.activeFrom: { table: "${table}", column: "${column}", id: "${id}" } and run permdock supabase hook generate.`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Where the token hook reads the active tenant, as better-supabase names it in
|
|
27
|
+
* `tokenHook.activeOrganizationFrom`, or `undefined` when the hook reads an
|
|
28
|
+
* `app_metadata` key other than the tenant claim, which has no better-supabase
|
|
29
|
+
* name.
|
|
30
|
+
*/
|
|
31
|
+
function activeOrganizationFrom(from, tenantClaim) {
|
|
32
|
+
if ("appMetadata" in from) return from.appMetadata === tenantClaim ? "claim" : void 0;
|
|
33
|
+
return {
|
|
34
|
+
profileColumn: `${qualifySqlTable(from.table)}.${from.column}`,
|
|
35
|
+
...from.id === "id" ? {} : { key: from.id }
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { activeTenantMismatch as n, activeOrganizationFrom as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as listSourceFiles } from "./files-BSjrtIHw.js";
|
|
2
|
-
import { t as DOCS_BASE } from "./manifest-
|
|
2
|
+
import { t as DOCS_BASE } from "./manifest-Cav1rjNQ.js";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { relative } from "node:path";
|
|
5
5
|
//#region src/cli/adoption-scan.ts
|
|
@@ -21,7 +21,7 @@ const check = defineLeaf({
|
|
|
21
21
|
...permissionsFlag
|
|
22
22
|
},
|
|
23
23
|
async run(ctx, { flags }) {
|
|
24
|
-
return (await import("./arazzo-
|
|
24
|
+
return (await import("./arazzo-CTH5iN--.js")).runArazzo({
|
|
25
25
|
cwd: ctx.cwd,
|
|
26
26
|
config: ctx.config,
|
|
27
27
|
doc: given(flags.doc),
|
|
@@ -3,7 +3,7 @@ import { c as missingInput } from "./errors-Vpu6rKHl.js";
|
|
|
3
3
|
import { i as readJsonFile } from "./files-BSjrtIHw.js";
|
|
4
4
|
import { t as ARAZZO_REPORT_SCHEMA } from "./version-DMQ0dnN5.js";
|
|
5
5
|
import { a as loadModule, s as pickNamed, t as asPermissionTree } from "./load-DjSU5KXO.js";
|
|
6
|
-
import { t as DOCS_BASE } from "./manifest-
|
|
6
|
+
import { t as DOCS_BASE } from "./manifest-Cav1rjNQ.js";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
8
8
|
import { resolve } from "node:path";
|
|
9
9
|
//#region src/cli/arazzo.ts
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { Cn as ApproverInput, Ot as ApiKeyPrincipal, St as SupportSession, T as Policy, U as CredentialVerifier, Wt as Instant, hr as Subject, pr as Principal, rn as AuthEvent } from "../policy-types-DGIO_gxq.js";
|
|
1
|
+
import { Cn as ApproverInput, Ot as ApiKeyPrincipal, St as SupportSession, T as Policy, U as CredentialVerifier, Wt as Instant, X as Intent, hr as Subject, nt as MembershipSource, pr as Principal, rn as AuthEvent } from "../policy-types-DGIO_gxq.js";
|
|
2
2
|
import { f as PermissionTree, u as Permission } from "../permission-types-CAY-GU7e.js";
|
|
3
3
|
import { _ as PrincipalSource, a as PermDock, h as PrincipalIdentity, o as PermDockOptions } from "../permdock-CprAPN3w.js";
|
|
4
4
|
import { c as AccessReviewStore } from "../types-B2efzoSX.js";
|
|
5
5
|
import { i as SupabaseRpcCaller } from "../postgrest-D5nUGm-c.js";
|
|
6
6
|
import { a as CatalogDocument } from "../types-ZzRGoViD.js";
|
|
7
|
-
import {
|
|
7
|
+
import { A as SupabaseSubjectOptions, C as SupabasePrincipal, N as SupabaseSuspension, O as SupabaseSessionLike, s as SqlMembershipSource } from "../sources-oB1Hg1Fm.js";
|
|
8
|
+
import { n as VersionCache } from "../version-cache-Df11C2Qp.js";
|
|
9
|
+
import { t as SqlQuery } from "../sql-B80DFdpG.js";
|
|
8
10
|
import { c as LinkPolicy, o as CapabilityPrincipal, t as Capability } from "../capability-Di9tiUvi.js";
|
|
9
11
|
import { AuthorizationProvider } from "better-supabase/config";
|
|
10
|
-
import { AuthSession, AuthorizationHooks, Authorizer, SupportAuthorize, SupportAuthorizeInput } from "better-supabase/server";
|
|
12
|
+
import { AuthSession, AuthorizationHooks, AuthorizationRequest, Authorizer, SupportAuthorize, SupportAuthorizeInput } from "better-supabase/server";
|
|
11
13
|
import { EntitlementClaimOptions } from "better-supabase/blocks/entitlements";
|
|
12
14
|
import { ApiKey, ApiKeyClaimsOptions, ApiKeys } from "better-supabase/blocks/api-keys";
|
|
13
15
|
import { AccessTopicPolicy } from "better-supabase/realtime";
|
|
@@ -159,6 +161,18 @@ type ApiKeySessionOptions = {
|
|
|
159
161
|
*/
|
|
160
162
|
readonly serviceRoles?: ServiceRoles<ApiKeySession>;
|
|
161
163
|
};
|
|
164
|
+
/**
|
|
165
|
+
* better-supabase's `SessionSnapshot` (0.15 and later): one verified token,
|
|
166
|
+
* from `bsb.getRequestSession()`, that `'use cache: private'` scopes share. Its
|
|
167
|
+
* `issuedAt` and `authzVersion` come from the `iat` and `authz_ver` claims.
|
|
168
|
+
*/
|
|
169
|
+
type SessionSnapshotLike = {
|
|
170
|
+
readonly accessToken: string;
|
|
171
|
+
readonly userId: string;
|
|
172
|
+
readonly claims: unknown;
|
|
173
|
+
readonly issuedAt?: number | null;
|
|
174
|
+
readonly authzVersion?: number | null;
|
|
175
|
+
};
|
|
162
176
|
/** The claim, and the short code better-supabase writes for each feature key. */
|
|
163
177
|
type FeatureClaim = EntitlementClaimOptions;
|
|
164
178
|
type BetterSupabaseSubjectOptions = Omit<SupabaseSubjectOptions, "claims"> & {
|
|
@@ -184,9 +198,10 @@ type BetterSupabaseSubjectOptions = Omit<SupabaseSubjectOptions, "claims"> & {
|
|
|
184
198
|
* verified `apiKey` session is the key's credential subject: a personal key
|
|
185
199
|
* acts as its user within the key's scopes, a tenant key as a `service`
|
|
186
200
|
* principal holding `serviceRoles`. Without `apiKeys`, and for `anon`,
|
|
187
|
-
* `service` and `invalid` sessions, the subject is anonymous.
|
|
201
|
+
* `service` and `invalid` sessions, the subject is anonymous. A
|
|
202
|
+
* `SessionSnapshot` maps as the user session of its claims.
|
|
188
203
|
*/
|
|
189
|
-
export declare function subjectFromBetterSupabase(session: SupabaseSessionLike | ApiKeySession | null | undefined, options?: BetterSupabaseSubjectOptions): Subject<SupabasePrincipal> | Subject<ApiKeyPrincipal> | Subject;
|
|
204
|
+
export declare function subjectFromBetterSupabase(session: SupabaseSessionLike | ApiKeySession | SessionSnapshotLike | null | undefined, options?: BetterSupabaseSubjectOptions): Subject<SupabasePrincipal> | Subject<ApiKeyPrincipal> | Subject;
|
|
190
205
|
//#endregion
|
|
191
206
|
//#region src/better-supabase/subscribers.d.ts
|
|
192
207
|
/** The fields of better-supabase's `OutboxEvent` the policy reads. */
|
|
@@ -350,6 +365,17 @@ type AuthorizationHooksOptions = {
|
|
|
350
365
|
*/
|
|
351
366
|
export declare function authorizationHooks(options: AuthorizationHooksOptions): AuthorizationHooks;
|
|
352
367
|
//#endregion
|
|
368
|
+
//#region src/better-supabase/active-tenant.d.ts
|
|
369
|
+
/**
|
|
370
|
+
* better-supabase's `blocks.permissions.activeTenant`: where its
|
|
371
|
+
* `switch_organization` writes the active tenant and `current_tenant_id()`
|
|
372
|
+
* reads it.
|
|
373
|
+
*/
|
|
374
|
+
type BetterSupabaseActiveTenant = "claim" | "resolver" | {
|
|
375
|
+
readonly profileColumn: string;
|
|
376
|
+
readonly key?: string;
|
|
377
|
+
};
|
|
378
|
+
//#endregion
|
|
353
379
|
//#region src/better-supabase/provider.d.ts
|
|
354
380
|
type AuthorizationProviderOptions = {
|
|
355
381
|
/**
|
|
@@ -380,6 +406,14 @@ type AuthorizationProviderOptions = {
|
|
|
380
406
|
* `permdock_is_approver` from `rls.approvals`.
|
|
381
407
|
*/
|
|
382
408
|
readonly approvers?: ProviderApprovers;
|
|
409
|
+
/**
|
|
410
|
+
* better-supabase's `blocks.permissions.activeTenant`. When the token hook
|
|
411
|
+
* reads the active tenant from another place than better-supabase writes it,
|
|
412
|
+
* `problems` names the `supabase.hook.activeFrom` to set. With `"resolver"`
|
|
413
|
+
* the tenant comes from the request, so `tokenHook.activeOrganizationFrom`
|
|
414
|
+
* stays unset and doctor BS409 has nothing to compare.
|
|
415
|
+
*/
|
|
416
|
+
readonly activeTenant?: BetterSupabaseActiveTenant;
|
|
383
417
|
};
|
|
384
418
|
/**
|
|
385
419
|
* better-supabase's `authorization` config value, built from PermDock's
|
|
@@ -387,16 +421,31 @@ type AuthorizationProviderOptions = {
|
|
|
387
421
|
* templates, the membership tables, suspension rows, the token hook and every
|
|
388
422
|
* catalog key with `sqlComplete` set from its `rowConditions`. A `_for`
|
|
389
423
|
* template and `permissionsFor` are set only when the manifest lists their
|
|
390
|
-
* helper, which `rls.mode: 'database'` writes
|
|
391
|
-
* `approvers`
|
|
392
|
-
* `
|
|
393
|
-
* `actorMayWrite` (`permdock_actor_may_write()`) are set
|
|
394
|
-
* lists their helper, and so is `teamIdsOf`
|
|
395
|
-
* for a scope named `team` or `teams`. Throws
|
|
396
|
-
* invalid, or when the tenant scope is
|
|
424
|
+
* helper, which `rls.mode: 'database'` writes. `isApprover` is set with
|
|
425
|
+
* `approvers` or `approver` and `permdock_is_approver`: `approver` fills its
|
|
426
|
+
* `'ai-tool'` entry. `canApprove` is never set. `holdersOf` (`permitted_<tenant
|
|
427
|
+
* scope>_users`) and `actorMayWrite` (`permdock_actor_may_write()`) are set
|
|
428
|
+
* when the manifest lists their helper, and so is `teamIdsOf`
|
|
429
|
+
* (`member_<scope>_ids_of({user})`) for a scope named `team` or `teams`. Throws
|
|
430
|
+
* when the manifest or catalog is invalid, or when the tenant scope is
|
|
431
|
+
* ambiguous.
|
|
397
432
|
*/
|
|
398
433
|
export declare function authorizationProvider(options: AuthorizationProviderOptions): AuthorizationProvider;
|
|
399
434
|
//#endregion
|
|
435
|
+
//#region src/better-supabase/report.d.ts
|
|
436
|
+
/** What an `onError` sink receives next to the thrown error. */
|
|
437
|
+
type BetterSupabaseErrorContext = {
|
|
438
|
+
/** The key of the permission being checked, when the request named one. */
|
|
439
|
+
readonly permission: string | null;
|
|
440
|
+
/** The active tenant the check ran in, or `null`. */
|
|
441
|
+
readonly tenant: string | null;
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* Receives an error a permission check threw. The check still denies; a sink
|
|
445
|
+
* that throws is ignored.
|
|
446
|
+
*/
|
|
447
|
+
type BetterSupabaseOnError = (error: unknown, context: BetterSupabaseErrorContext) => void;
|
|
448
|
+
//#endregion
|
|
400
449
|
//#region src/better-supabase/authorizer.d.ts
|
|
401
450
|
/**
|
|
402
451
|
* The table operations better-supabase's `permissions: true` resolves through
|
|
@@ -416,10 +465,36 @@ type AuthorizerOptions = {
|
|
|
416
465
|
*/
|
|
417
466
|
readonly operations?: Readonly<Record<string, Partial<Record<AuthorizerOperation, Permission>>>>;
|
|
418
467
|
/**
|
|
419
|
-
*
|
|
420
|
-
*
|
|
468
|
+
* The membership source a stale or truncated token is re-read from, wrapped
|
|
469
|
+
* in `claimsFirst(source, { onStale: 'reread', versions })`. `versions` is
|
|
470
|
+
* the cache better-supabase passes at runtime (`createNext({ versions })`),
|
|
471
|
+
* else the `versions` option.
|
|
421
472
|
*/
|
|
422
|
-
readonly
|
|
473
|
+
readonly memberships?: MembershipSource | readonly MembershipSource[];
|
|
474
|
+
/**
|
|
475
|
+
* The current authorization version for `memberships`, such as
|
|
476
|
+
* `authzVersion({ query })`; default the source's own `version`.
|
|
477
|
+
*/
|
|
478
|
+
readonly version?: MembershipSource["version"];
|
|
479
|
+
/**
|
|
480
|
+
* The version cache for `memberships` when better-supabase passes none (0.13
|
|
481
|
+
* and 0.14, or a server created without `versions`).
|
|
482
|
+
*/
|
|
483
|
+
readonly versions?: VersionCache;
|
|
484
|
+
/**
|
|
485
|
+
* The intent of one check. By default a batch (`evaluations`, list and row
|
|
486
|
+
* filtering) and an action named `read`, `list` or `view` are `read`, so
|
|
487
|
+
* `claimsFirst` may answer from the version cache; every other check is
|
|
488
|
+
* `write` and reads the version live.
|
|
489
|
+
*/
|
|
490
|
+
readonly intent?: (request: AuthorizationRequest<Permission>) => Intent;
|
|
491
|
+
/** Receives every error a check threw; the check still denies. */
|
|
492
|
+
readonly onError?: BetterSupabaseOnError;
|
|
493
|
+
/**
|
|
494
|
+
* Sources and sinks for each instance. The subject, actor, tenant and intent
|
|
495
|
+
* always come from the verified request.
|
|
496
|
+
*/
|
|
497
|
+
readonly options?: Omit<PermDockOptions, "tenant" | "actor" | "delegation" | "session" | "expiresAt" | "intent">;
|
|
423
498
|
};
|
|
424
499
|
/**
|
|
425
500
|
* better-supabase's `authorizer` for PermDock: every resource, action, route
|
|
@@ -427,10 +502,76 @@ type AuthorizerOptions = {
|
|
|
427
502
|
* subject is mapped from the verified claims with `subjectFromBetterSupabase`;
|
|
428
503
|
* the request's `context.tenant` selects the active tenant only among the
|
|
429
504
|
* memberships the claims hold. A caller without claims is anonymous, and a
|
|
430
|
-
* throw denies.
|
|
505
|
+
* throw denies. With better-supabase 0.15's runtime `memo`, the checks of one
|
|
506
|
+
* request scope share an instance per claims, tenant and intent.
|
|
431
507
|
*/
|
|
432
508
|
export declare function authorizer(options: AuthorizerOptions): Authorizer<Permission>;
|
|
433
509
|
//#endregion
|
|
510
|
+
//#region src/better-supabase/block-memberships.d.ts
|
|
511
|
+
/**
|
|
512
|
+
* A roles table the membership's role column references, in better-supabase's
|
|
513
|
+
* `blocks.memberships.options.roleThrough` shape: the role column holds
|
|
514
|
+
* `table.id`, and `table.column` holds the role key.
|
|
515
|
+
*/
|
|
516
|
+
type BlockRoleThrough = {
|
|
517
|
+
readonly table: string;
|
|
518
|
+
readonly id: string;
|
|
519
|
+
readonly column: string;
|
|
520
|
+
};
|
|
521
|
+
/**
|
|
522
|
+
* A role junction holding several roles per membership: one row per role,
|
|
523
|
+
* `membership` referencing the membership's `id` column and `role` holding the
|
|
524
|
+
* role key.
|
|
525
|
+
*/
|
|
526
|
+
type BlockRoleJunction = {
|
|
527
|
+
readonly table: string;
|
|
528
|
+
/** The junction column referencing the membership. */
|
|
529
|
+
readonly membership: string;
|
|
530
|
+
/** The junction column holding the role key. */
|
|
531
|
+
readonly role: string;
|
|
532
|
+
/** The membership's primary key column. Default `id`. */
|
|
533
|
+
readonly id?: string;
|
|
534
|
+
};
|
|
535
|
+
type BlockMembershipSourceOptions = {
|
|
536
|
+
/** The memberships block's table. Default `better_supabase.memberships`. */
|
|
537
|
+
readonly table?: string;
|
|
538
|
+
/** The declared scope a row is a membership of. Default `organization`. */
|
|
539
|
+
readonly scope?: string;
|
|
540
|
+
/**
|
|
541
|
+
* Physical column names, keyed like better-supabase's
|
|
542
|
+
* `blocks.memberships.columns.memberships`. Defaults `organization_id`,
|
|
543
|
+
* `user_id`, `role` and `disabled_at`.
|
|
544
|
+
*/
|
|
545
|
+
readonly columns?: {
|
|
546
|
+
readonly tenant?: string;
|
|
547
|
+
readonly user?: string;
|
|
548
|
+
readonly role?: string;
|
|
549
|
+
readonly disabledAt?: string | null;
|
|
550
|
+
};
|
|
551
|
+
/**
|
|
552
|
+
* The roles table the role column references, so a custom role's key reads
|
|
553
|
+
* through it. The same value as `blocks.memberships.options.roleThrough`.
|
|
554
|
+
*/
|
|
555
|
+
readonly roleThrough?: BlockRoleThrough;
|
|
556
|
+
/**
|
|
557
|
+
* A role junction read instead of the role column. `"many"` reads
|
|
558
|
+
* `membership_roles` in the table's schema, the role set
|
|
559
|
+
* `blocks.memberships.options.roles.many` keeps, keyed by the tenant and user
|
|
560
|
+
* columns.
|
|
561
|
+
*/
|
|
562
|
+
readonly roles?: BlockRoleJunction | "many";
|
|
563
|
+
readonly query?: SqlQuery;
|
|
564
|
+
readonly suspension?: SupabaseSuspension;
|
|
565
|
+
};
|
|
566
|
+
/**
|
|
567
|
+
* Memberships from better-supabase's `memberships` block table: one row per
|
|
568
|
+
* user and organization, its role key in `role`, a custom role's key through
|
|
569
|
+
* `roleThrough`, or several roles from a `roles` junction or, with `roles:
|
|
570
|
+
* "many"`, from better-supabase's `membership_roles`. A row with `disabled_at`
|
|
571
|
+
* set is no membership.
|
|
572
|
+
*/
|
|
573
|
+
export declare function blockMembershipSource(options?: BlockMembershipSourceOptions): SqlMembershipSource;
|
|
574
|
+
//#endregion
|
|
434
575
|
//#region src/better-supabase/policies.d.ts
|
|
435
576
|
type AccessScope = {
|
|
436
577
|
/**
|
|
@@ -536,6 +677,11 @@ type ToolPolicyOptions<C> = {
|
|
|
536
677
|
* with a row condition denies.
|
|
537
678
|
*/
|
|
538
679
|
readonly data?: (ctx: C, tool: McpToolRef, args: unknown) => unknown;
|
|
680
|
+
/**
|
|
681
|
+
* Receives every error `authorize` or `visible` threw; the tool stays
|
|
682
|
+
* refused.
|
|
683
|
+
*/
|
|
684
|
+
readonly onError?: BetterSupabaseOnError;
|
|
539
685
|
};
|
|
540
686
|
type ToolPolicy<C> = {
|
|
541
687
|
readonly authorize: (ctx: C, tool: McpToolRef, args: unknown) => Promise<McpToolDecision>;
|
|
@@ -546,7 +692,8 @@ type ToolPolicy<C> = {
|
|
|
546
692
|
* tools whose `meta` is a PermDock permission. A tool without a permission is
|
|
547
693
|
* hidden and refused. `authorize` grants only a `granted` decision: an
|
|
548
694
|
* approval-required call is refused, because `createMcp` has no approval flow.
|
|
549
|
-
* A throw anywhere refuses
|
|
695
|
+
* A denial's text names the first denial reason. A throw anywhere refuses and
|
|
696
|
+
* reaches `onError`.
|
|
550
697
|
*/
|
|
551
698
|
export declare function toolPolicy<C>(options: ToolPolicyOptions<C>): ToolPolicy<C>;
|
|
552
699
|
//#endregion
|
|
@@ -729,19 +876,37 @@ export declare function subjectFromShareLink(token: string | undefined | null, o
|
|
|
729
876
|
type HandlerPermDockSource = {
|
|
730
877
|
readonly getPermDock: (request: Request) => PermDock | Promise<PermDock>;
|
|
731
878
|
};
|
|
879
|
+
type HookCanOptions = {
|
|
880
|
+
/**
|
|
881
|
+
* Loads the row the permission `key` is decided on in `tenant`, so a
|
|
882
|
+
* condition on the row applies. Without it there is no row; a throw is
|
|
883
|
+
* `false`.
|
|
884
|
+
*/
|
|
885
|
+
readonly data?: (tenant: string, key: string) => unknown;
|
|
886
|
+
};
|
|
887
|
+
type HandlerCanOptions = {
|
|
888
|
+
/**
|
|
889
|
+
* Loads the row the permission `key` is decided on for `request`, so a
|
|
890
|
+
* condition on the row applies. Without it there is no row; a throw is
|
|
891
|
+
* `false` (403).
|
|
892
|
+
*/
|
|
893
|
+
readonly data?: (request: Request, key: string) => unknown;
|
|
894
|
+
};
|
|
732
895
|
/**
|
|
733
896
|
* The `can` option of better-supabase's `authorizeHook`, for the caller's
|
|
734
897
|
* `permdock`: `true` only when the caller is a member of the hook's tenant and
|
|
735
|
-
* `decide` grants the permission its `hookMetadata` names there
|
|
736
|
-
* key, `approval-required` and a throw are
|
|
898
|
+
* `decide` grants the permission its `hookMetadata` names there, on the row
|
|
899
|
+
* `options.data` loads. An unknown key, `approval-required` and a throw are
|
|
900
|
+
* `false`.
|
|
737
901
|
*/
|
|
738
|
-
export declare function hookCan(permdock: PermDock): NonNullable<AuthorizeHookOptions["can"]>;
|
|
902
|
+
export declare function hookCan(permdock: PermDock, options?: HookCanOptions): NonNullable<AuthorizeHookOptions["can"]>;
|
|
739
903
|
/**
|
|
740
904
|
* The `can` option of better-supabase's `protectWebHandler`: `undefined` (401)
|
|
741
905
|
* when the request has no signed-in principal or `getPermDock` throws,
|
|
742
906
|
* otherwise whether `decide` grants the permission in the request's active
|
|
743
|
-
* tenant. An unknown key
|
|
907
|
+
* tenant, on the row `options.data` loads. An unknown key, `approval-required`
|
|
908
|
+
* and a throwing `data` are `false` (403).
|
|
744
909
|
*/
|
|
745
|
-
export declare function handlerCan(source: HandlerPermDockSource): ProtectWebHandlerOptions["can"];
|
|
910
|
+
export declare function handlerCan(source: HandlerPermDockSource, options?: HandlerCanOptions): ProtectWebHandlerOptions["can"];
|
|
746
911
|
//#endregion
|
|
747
|
-
export type { AccessPolicyOptions, AccessReviewApplierOptions, AccessReviewApplyFailure, AccessReviewApplyResult, ApiKeySession, ApiKeySessionOptions, ApiKeyVerifierOptions, AuthorizationHooksOptions, AuthorizationProviderOptions, AuthorizerOperation, AuthorizerOptions, BetterSupabaseIdentityLink, BetterSupabaseMembershipRow, BetterSupabaseSubjectOptions, BucketAccess, CredentialGuardOptions, HandlerPermDockSource, McpToolDecision, McpToolRef, PendingSupportSession, PrincipalFromMembershipsOptions, PrincipalSourceOptions, ProviderApprovers, RoleOrderOptions, ServiceRoles, ShareLinkResolver, ShareLinkRow, ShareLinkSubjectOptions, ShareLinkTarget, SubscriberPolicyEvent, SubscriberPolicyOptions, SupabasePrincipal, SupportPolicyOptions, ToolPolicy, ToolPolicyOptions, TopicAccess };
|
|
912
|
+
export type { AccessPolicyOptions, AccessReviewApplierOptions, AccessReviewApplyFailure, AccessReviewApplyResult, ApiKeySession, ApiKeySessionOptions, ApiKeyVerifierOptions, AuthorizationHooksOptions, AuthorizationProviderOptions, AuthorizerOperation, AuthorizerOptions, BetterSupabaseActiveTenant, BetterSupabaseErrorContext, BetterSupabaseIdentityLink, BetterSupabaseMembershipRow, BetterSupabaseOnError, BetterSupabaseSubjectOptions, BlockMembershipSourceOptions, BlockRoleJunction, BlockRoleThrough, BucketAccess, CredentialGuardOptions, HandlerCanOptions, HandlerPermDockSource, HookCanOptions, McpToolDecision, McpToolRef, PendingSupportSession, PrincipalFromMembershipsOptions, PrincipalSourceOptions, ProviderApprovers, RoleOrderOptions, ServiceRoles, SessionSnapshotLike, ShareLinkResolver, ShareLinkRow, ShareLinkSubjectOptions, ShareLinkTarget, SubscriberPolicyEvent, SubscriberPolicyOptions, SupabasePrincipal, SupportPolicyOptions, ToolPolicy, ToolPolicyOptions, TopicAccess };
|