permdock 0.9.0 → 0.10.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-0oFt2RD5.js} +1 -1
- package/dist/{arazzo-BpS7LnV0.js → arazzo-DA9PCXew.js} +1 -1
- package/dist/{arazzo-CmQaGPkM.js → arazzo-DhxDfYt-.js} +1 -1
- package/dist/better-supabase/index.d.ts +188 -23
- package/dist/better-supabase/index.js +246 -62
- package/dist/{casbin-bHyIxTNQ.js → casbin-BJu2liqU.js} +1 -1
- package/dist/{casbin-B7_yS-oo.js → casbin-BkhqGh2z.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-3RIuS4E9.js} +2 -2
- package/dist/{codemod-D9Aiii1r.js → codemod-DLcp-B6v.js} +2 -2
- package/dist/{codemod-Bv5i-Mzo.js → codemod-DRl_w-bY.js} +1 -1
- package/dist/{collect-B80GYEot.js → collect-D9Tt0Bcx.js} +1 -1
- package/dist/{completion-_bc0OUQ-.js → completion-VSWvaaPO.js} +1 -1
- package/dist/{config-BwPBfN0t.js → config-BR23fL8m.js} +2 -2
- package/dist/{config-D5XrLWpk.js → config-kL36AxkE.js} +1 -1
- package/dist/{config-report-BmWIskD7.js → config-report-osnfUNg5.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-B9FY9H0F.js} +2 -2
- package/dist/{doctor-ClRVAtXQ.js → doctor-DfTnMaUt.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-Iuk9mx8A.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-BjuFDYT1.js → init-DeoSvkh2.js} +1 -1
- package/dist/{init-txYTuW9u.js → init-fNF_XmTa.js} +3 -3
- package/dist/{login-CgfCTO3F.js → login-CutVtcmQ.js} +1 -1
- package/dist/{login-CfImTJGb.js → login-DYazeWc9.js} +3 -3
- package/dist/{manifest-B2QPh19C.js → manifest-B4ENCp2I.js} +33 -33
- 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-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-C-ADypaY.js} +1 -1
- package/dist/{openapi-BIpw3Mb7.js → openapi-DFj0cirS.js} +2 -2
- package/dist/{output-DV5dwOTs.js → output-LsbLe41I.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-Bg8u-JcR.js → powersync-B_8uwz7f.js} +2 -2
- package/dist/powersync-CSzDCHRu.js +1 -0
- package/dist/{powersync-CJrT1DSc.js → powersync-DUT-UKgw.js} +188 -36
- package/dist/{pull-2nJr0qg_.js → pull-DQCgvJSC.js} +2 -2
- package/dist/pull-DYbyod1f.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-Cx0dtsB7.js → rls-B57mIeVq.js} +22 -15
- package/dist/{rls-Ba9wN0SP.js → rls-j0YrFPpW.js} +1 -1
- package/dist/run-BATawNVH.js +1 -0
- package/dist/{run-PbRlXTfh.js → run-CLP_fQUF.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-B7xrAvRm.js} +1 -1
- package/dist/{schema-BTsE1WRT.js → schema-3PJ8wAeL.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-BUI8DMqy.js} +1 -1
- package/dist/{skills-CQQcuGBi.js → skills-iwbRxavw.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 +2 -3
- package/dist/supabase/index.js +4 -4
- package/dist/{supabase-DnMMg5Fn.js → supabase-B1EfuD47.js} +2 -2
- package/dist/{supabase-SBs3MYUE.js → supabase-BaizG0n7.js} +2 -2
- package/dist/{supabase-hook-CrgU06WH.js → supabase-hook-BT2P9wah.js} +110 -47
- package/dist/supabase-hook-CbvGAutK.js +1 -0
- package/dist/{supautils-ByezN3b8.js → supautils-DBKOoyjn.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-CBzgwfIs.js → usage-B1ZJOUdr.js} +1 -1
- package/dist/{usage-B9EtHWLa.js → usage-t_nXnwCW.js} +2 -2
- package/dist/usage-weohzv2f.js +1 -0
- package/dist/{verify-DlUcTDBz.js → verify-jHrbmn-E.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-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,51 @@
|
|
|
1
|
+
import { Wt as Instant, yt as VersionQuery } from "./policy-types-DGIO_gxq.js";
|
|
2
|
+
//#region src/core/version-cache.d.ts
|
|
3
|
+
type VersionCacheStats = {
|
|
4
|
+
/** Version reads the cache started. */
|
|
5
|
+
readonly reads: number;
|
|
6
|
+
/** Calls answered by a read already in flight. */
|
|
7
|
+
readonly shared: number;
|
|
8
|
+
/** Calls answered from an entry or a token claim, with no read. */
|
|
9
|
+
readonly hits: number;
|
|
10
|
+
readonly evictions: number;
|
|
11
|
+
readonly size: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Current authorization versions shared by every instance in a process:
|
|
15
|
+
* `claimsFirst(source, { versions })` reads through it.
|
|
16
|
+
*/
|
|
17
|
+
type VersionCache = {
|
|
18
|
+
readonly name?: string;
|
|
19
|
+
/** How old an entry may be when an instance with intent `read` uses it. */
|
|
20
|
+
readonly maxStaleMs: number;
|
|
21
|
+
/**
|
|
22
|
+
* The current version of `principal`. With `live: false`, an entry at most
|
|
23
|
+
* `maxStaleMs` old answers, a read in flight is shared, and a token claim
|
|
24
|
+
* newer than the entry raises it; with `live: true`, `read` runs.
|
|
25
|
+
*/
|
|
26
|
+
current: (principal: VersionQuery, read: () => number | undefined | Promise<number | undefined>, options: {
|
|
27
|
+
readonly live: boolean;
|
|
28
|
+
}) => number | undefined | Promise<number | undefined>;
|
|
29
|
+
/** Drops `principal`'s entry, so the next instance reads the version. */
|
|
30
|
+
evict: (principal: string) => void;
|
|
31
|
+
stats: () => VersionCacheStats;
|
|
32
|
+
};
|
|
33
|
+
type MemoryVersionCacheOptions = {
|
|
34
|
+
/**
|
|
35
|
+
* How stale a read may be, in milliseconds: the entry lifetime and the
|
|
36
|
+
* longest a removed member keeps read access. Clamped to 0 to 60,000.
|
|
37
|
+
*/
|
|
38
|
+
readonly maxStaleMs: number;
|
|
39
|
+
/** Principals kept; the least recently used goes first. Default 10,000. */
|
|
40
|
+
readonly maxEntries?: number;
|
|
41
|
+
/** The clock, read only when an instance asks for a version. */
|
|
42
|
+
readonly now?: () => Instant;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* An in-process `VersionCache`: a bounded LRU keyed by principal id that keeps
|
|
46
|
+
* resolved versions and shares reads in flight. Create it once at module
|
|
47
|
+
* scope.
|
|
48
|
+
*/
|
|
49
|
+
declare function memoryVersionCache(options: MemoryVersionCacheOptions): VersionCache;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { memoryVersionCache as i, VersionCache as n, VersionCacheStats as r, MemoryVersionCacheOptions as t };
|
|
@@ -2,7 +2,7 @@ import { i as dateAt } from "./time-nR1JesoH.js";
|
|
|
2
2
|
import { a as describeError } from "./errors-Vpu6rKHl.js";
|
|
3
3
|
import { t as defaultSrcPath } from "./files-BSjrtIHw.js";
|
|
4
4
|
import { r as runCollect } from "./collect-WCl8cJQV.js";
|
|
5
|
-
import { n as isConfigFile, r as loadConfig } from "./config-
|
|
5
|
+
import { n as isConfigFile, r as loadConfig } from "./config-BR23fL8m.js";
|
|
6
6
|
import { watch } from "node:fs";
|
|
7
7
|
import { basename, dirname, relative, resolve, sep } from "node:path";
|
|
8
8
|
//#region src/cli/watch.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { i as watchCollect } from "./watch-Bpci3hBY.js";
|
package/dist/workflow/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as AutomationSource, i as AutomationRequest, l as memoryAutomationSource, n as AutomationDecision, r as AutomationMode, s as MemoryAutomationSource, t as Automation, u as parseAutomation } from "../automation-C6Jg75xq.js";
|
|
2
2
|
import { i as pollingApprovalWaiter, n as ApprovalWaiter, r as PollingApprovalWaiterOptions, t as ApprovalWaitOptions } from "../waiter-CqUKX6CY.js";
|
|
3
|
-
import { a as WorkflowPermDockOptions, i as WorkflowPermDock, n as AwaitApprovalOptions, o as createPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-
|
|
3
|
+
import { a as WorkflowPermDockOptions, i as WorkflowPermDock, n as AwaitApprovalOptions, o as createPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-CDd9c22W.js";
|
|
4
4
|
import "../index-CaxrMD1A.js";
|
|
5
5
|
export { type ApprovalWaitOptions, type ApprovalWaiter, type Automation, type AutomationDecision, type AutomationMode, type AutomationOptions, type AutomationRequest, type AutomationSource, type AwaitApprovalOptions, type MemoryAutomationSource, type PollingApprovalWaiterOptions, type StartAutomationResult, type WorkflowPermDock, type WorkflowPermDockOptions, createPermDock, memoryAutomationSource, parseAutomation, pollingApprovalWaiter };
|
package/dist/workflow/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { t as compact } from "../compact-CAf557ZB.js";
|
|
2
2
|
import { n as freezeDeep } from "../freeze-jjan0lCv.js";
|
|
3
|
+
import { a as isId } from "../expiry-6XByK0dm.js";
|
|
3
4
|
import { n as findPermission } from "../permission-registry-B8tYxPIt.js";
|
|
4
5
|
import { n as isThenable } from "../thenable-BNSM1U2R.js";
|
|
5
6
|
import { n as memoryAutomationSource, r as parseAutomation } from "../automation-x3KEUusw.js";
|
|
6
7
|
import { l as withApp, t as getPermDock } from "../permdock-BvjivVb9.js";
|
|
7
8
|
import { o as automationEvent } from "../sink-D9_vh372.js";
|
|
8
9
|
import { a as requestApproval, s as resumeDecision } from "../helpers-DJicaG6f.js";
|
|
9
|
-
import { i as subjectFromRunTicket, r as signRunTicket } from "../run-ticket-
|
|
10
|
+
import { i as subjectFromRunTicket, r as signRunTicket } from "../run-ticket-DfnZCh-u.js";
|
|
10
11
|
import { t as pollingApprovalWaiter } from "../waiter-aBLM63_f.js";
|
|
11
12
|
//#region src/workflow/create.ts
|
|
12
13
|
function writeQuietly(sink, event) {
|
|
@@ -121,12 +122,22 @@ function createPermDock(policy, given) {
|
|
|
121
122
|
}]
|
|
122
123
|
});
|
|
123
124
|
}
|
|
125
|
+
const { resource } = startOptions;
|
|
126
|
+
if (resource !== void 0 && !(isId(resource.type) && isId(resource.id))) return deniedStart("validation", { cause: "resource-invalid" });
|
|
124
127
|
const scopes = [];
|
|
128
|
+
const bound = [];
|
|
125
129
|
for (const key of automation.permissions) {
|
|
126
130
|
const leaf = findPermission(policy.permissions, key);
|
|
127
131
|
if (leaf === void 0) return deniedStart("validation", { permission: key });
|
|
128
|
-
|
|
132
|
+
if (resource !== void 0 && leaf.resource === resource.type) bound.push(leaf.action);
|
|
133
|
+
else scopes.push(leaf.scope);
|
|
129
134
|
}
|
|
135
|
+
if (resource !== void 0 && bound.length === 0) return deniedStart("validation", { resource: resource.type });
|
|
136
|
+
const authorizationDetails = resource === void 0 ? void 0 : [{
|
|
137
|
+
type: resource.type,
|
|
138
|
+
identifier: resource.id,
|
|
139
|
+
actions: bound
|
|
140
|
+
}];
|
|
130
141
|
const runId = startOptions.id ?? globalThis.crypto.randomUUID();
|
|
131
142
|
const runAutomation = {
|
|
132
143
|
id: automation.id,
|
|
@@ -139,11 +150,15 @@ function createPermDock(policy, given) {
|
|
|
139
150
|
id: automation.id,
|
|
140
151
|
kind: "automation"
|
|
141
152
|
},
|
|
142
|
-
delegation: {
|
|
153
|
+
delegation: compact({
|
|
154
|
+
scopes,
|
|
155
|
+
authorizationDetails
|
|
156
|
+
}),
|
|
143
157
|
automation: runAutomation,
|
|
144
158
|
tenant: automation.tenant,
|
|
145
159
|
trigger: startOptions.trigger,
|
|
146
160
|
binding: startOptions.binding,
|
|
161
|
+
resource,
|
|
147
162
|
id: runId,
|
|
148
163
|
expiresIn
|
|
149
164
|
}), signer, compact({
|
|
@@ -158,10 +173,11 @@ function createPermDock(policy, given) {
|
|
|
158
173
|
return freezeDeep({
|
|
159
174
|
outcome: "started",
|
|
160
175
|
ticket: signed,
|
|
161
|
-
run: {
|
|
176
|
+
run: compact({
|
|
162
177
|
id: runId,
|
|
163
|
-
automation: runAutomation
|
|
164
|
-
|
|
178
|
+
automation: runAutomation,
|
|
179
|
+
resource
|
|
180
|
+
})
|
|
165
181
|
});
|
|
166
182
|
};
|
|
167
183
|
const opened = async (ticket, permission, data, decideOptions) => {
|
|
@@ -2,7 +2,7 @@ import { Un as Decision } from "../policy-types-DGIO_gxq.js";
|
|
|
2
2
|
import { u as Permission } from "../permission-types-CAY-GU7e.js";
|
|
3
3
|
import { a as PermDock } from "../permdock-CprAPN3w.js";
|
|
4
4
|
import { n as ApprovalWaiter } from "../waiter-CqUKX6CY.js";
|
|
5
|
-
import { i as WorkflowPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-
|
|
5
|
+
import { i as WorkflowPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-CDd9c22W.js";
|
|
6
6
|
//#region src/workflow-sdk/index.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* The part of a Workflow SDK `Hook` the waiter reads: awaiting it suspends the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "permdock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Typed permissions for TypeScript apps, APIs, databases, and AI agents, with the permdock CLI and test runners.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -353,7 +353,7 @@
|
|
|
353
353
|
"ajv": "8.20.0",
|
|
354
354
|
"astro": "7.4.0",
|
|
355
355
|
"babel-plugin-react-compiler": "1.0.0",
|
|
356
|
-
"better-supabase": "0.
|
|
356
|
+
"better-supabase": "0.18.0",
|
|
357
357
|
"better-supabase-floor": "npm:better-supabase@0.13.0",
|
|
358
358
|
"chat": "4.42.0",
|
|
359
359
|
"diff": "9.0.0",
|
package/schemas/run-v1.json
CHANGED
|
@@ -121,6 +121,22 @@
|
|
|
121
121
|
"maxItems": 64
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
+
},
|
|
125
|
+
"resource": {
|
|
126
|
+
"type": "object",
|
|
127
|
+
"required": ["type", "id"],
|
|
128
|
+
"properties": {
|
|
129
|
+
"type": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"minLength": 1,
|
|
132
|
+
"maxLength": 256
|
|
133
|
+
},
|
|
134
|
+
"id": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"minLength": 1,
|
|
137
|
+
"maxLength": 256
|
|
138
|
+
}
|
|
139
|
+
}
|
|
124
140
|
}
|
|
125
141
|
},
|
|
126
142
|
"anyOf": [
|
|
@@ -43,6 +43,27 @@
|
|
|
43
43
|
"type": "string",
|
|
44
44
|
"pattern": "^[A-Za-z_][A-Za-z0-9_]*\\.[A-Za-z_][A-Za-z0-9_]*$"
|
|
45
45
|
}
|
|
46
|
+
},
|
|
47
|
+
"activeFrom": {
|
|
48
|
+
"description": "Where the hook reads the active first-scope id (supabase.hook.activeFrom): an app_metadata key, or a column of a table joined on id. Absent from a manifest written before 0.10.",
|
|
49
|
+
"oneOf": [
|
|
50
|
+
{
|
|
51
|
+
"type": "object",
|
|
52
|
+
"required": ["appMetadata"],
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"properties": { "appMetadata": { "type": "string" } }
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"type": "object",
|
|
58
|
+
"required": ["table", "column", "id"],
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"properties": {
|
|
61
|
+
"table": { "type": "string" },
|
|
62
|
+
"column": { "type": "string" },
|
|
63
|
+
"id": { "type": "string" }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
46
67
|
}
|
|
47
68
|
}
|
|
48
69
|
},
|
|
@@ -562,6 +583,13 @@
|
|
|
562
583
|
},
|
|
563
584
|
"column": {
|
|
564
585
|
"$ref": "#/$defs/identifier"
|
|
586
|
+
},
|
|
587
|
+
"on": {
|
|
588
|
+
"description": "Every referencing column to the column of table it matches, when the reference spans several columns.",
|
|
589
|
+
"type": "object",
|
|
590
|
+
"additionalProperties": {
|
|
591
|
+
"$ref": "#/$defs/identifier"
|
|
592
|
+
}
|
|
565
593
|
}
|
|
566
594
|
}
|
|
567
595
|
}
|
|
@@ -127,6 +127,7 @@ run.can(permissions.invoice.send, invoice);
|
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
- `start(id, { caller, trigger })` reads the live automation, checks the caller's `run` permission and signs a run ticket (`vnd.permdock.run+jwt`, 24 hours by default). Without `caller`, only server code starts it.
|
|
130
|
+
- `start(id, { resource: { type, id } })` binds the run to one record: its permissions on `type` go into an `authorization_details` entry with `identifier: id`, so they hold on that row only; a type none of its permissions is on denies the start.
|
|
130
131
|
- `getPermDock(ticket)` rebuilds the run on every step. A new version, a revoked automation or a publisher who is gone gives an instance that denies everything.
|
|
131
132
|
- `awaitApproval(ticket, permission, row)` decides, parks on the `waiter` while `approval-required`, then decides again with the token against the publisher's rights as of then.
|
|
132
133
|
- `openApproval(ticket, permission, row)` and `resumeApproval(ticket, permission, token, row)` are the two halves, for runners that wait outside the call. A request still pending denies with reason `approval`.
|
|
@@ -501,9 +501,9 @@ const subject = subjectFromSupabase(claims, {
|
|
|
501
501
|
|
|
502
502
|
Write the claims with `permdock supabase hook generate`; `permdock supabase inspect --out` writes the manifest (helper names, tenant claim, budget, claims written) that `authorizationProvider` from `permdock/better-supabase` turns into better-supabase's `authorization` config. No `@supabase/supabase-js` peer. Pair with `permdock rls generate`, or keep SQL as authority and run `permdock rls verify --db-url-stdin` against `sqlFunction` twins ([database-first](https://permdock.com/docs/adapters/rls)); the generic RLS workflow is in the `permdock-data` skill.
|
|
503
503
|
|
|
504
|
-
With better-supabase, set `authorization: authorizationProvider({ manifest, catalog })` in `better-supabase.config.ts` (with `rls.customRoles` its `canAssign` and `canAssignFor` call `permdock_can_assign_any` and its `_for` form, so custom roles are assignable through better-supabase; regenerate the manifest after turning custom roles on), pass `authorizer({ policy })` to the server (`createNext`, `createHono`, `createMcp`) so every `permission` a resource, action, route guard or tool declares is decided by PermDock from the verified claims (`operations` maps tables for `permissions: true`; a missing or anonymous claim denies), build bucket and topic `access` policies with `bucketPolicy` and `topicPolicy`, and map its session with `subjectFromBetterSupabase(session)` (all from `permdock/better-supabase`): the active tenant's `features` become `principal.plans`. Pass `plans: { keys }` when better-supabase's `entitlements.claim.keys` shortens feature keys, and `apiKeys: { permissions, manifest }` so an `apiKey` session maps to the key's credential subject instead of the anonymous one. For `createMcp` tools, put the permission in `meta` and spread `toolPolicy({ permdock })` into the options: tools without one are hidden and refused, and approval-required calls are refused because `createMcp` collects no approvals. Wrap a `CredentialProvider` with `credentialGuard(provider, { permdock, use, revoke? })` so PermDock decides each token use. `authorizationProvider({ ..., approver })` lets holders of that permission approve AI tool calls, never their own. `approvers: { 'ai-tool': holder(p), 'support-session': ..., 'invoice.send': ... }` fills `isApprover` through `permdock_is_approver` (needs `rls.approvals`); only `user()`, `holder()` and `anyOf()` approvers, and a kind it does not name has no approver. `accessReviewApplier({ client, reviews, policy, demoteTo?, email?, permdockFor? })` applies a review's revoked items: `update_member_role` to the `demoteTo` role when that role lacks the permission, else `remove_member`, plus `revoke_invitation` for the member's matching invitations, then `markApplied`; pass the reviewer's client so the blocks' own checks run. better-supabase's `createAgentRuntime({ toolApproval })` takes `toolApproval` from `permdock/ai-sdk` as it is. Validate its claims with `betterSupabase.claims(supabaseClaims().extend(appSchema))` (`supabaseClaims` from `permdock/supabase`, any Standard Schema as `appSchema`) instead of a hand-written copy of the claim shape. A `supabase.hook.claims` function that needs the user's organizations calls `<schema>.member_organization_ids_for(user_id)` (generated by `rls generate`, executable by `supabase_auth_admin` only) instead of querying the membership tables itself. With a scope named `team` or `teams`, `authorizationProvider` fills better-supabase's `teamIdsOf` with `<schema>.member_team_ids_of(user)`, which answers only for the caller, so with `blocks.
|
|
504
|
+
With better-supabase, set `auth.authorization: authorizationProvider({ manifest, catalog })` in `better-supabase.config.ts` (top-level `authorization` before 0.15) (with `rls.customRoles` its `canAssign` and `canAssignFor` call `permdock_can_assign_any` and its `_for` form, so custom roles are assignable through better-supabase; regenerate the manifest after turning custom roles on), pass `authorizer({ policy })` to the server (`createNext`, `createHono`, `createMcp`) so every `permission` a resource, action, route guard or tool declares is decided by PermDock from the verified claims (`operations` maps tables for `permissions: true`; a missing or anonymous claim denies), build bucket and topic `access` policies with `bucketPolicy` and `topicPolicy`, and map its session with `subjectFromBetterSupabase(session)` (all from `permdock/better-supabase`): the active tenant's `features` become `principal.plans`. Pass `plans: { keys }` when better-supabase's `entitlements.claim.keys` shortens feature keys, and `apiKeys: { permissions, manifest }` so an `apiKey` session maps to the key's credential subject instead of the anonymous one. For `createMcp` tools, put the permission in `meta` and spread `toolPolicy({ permdock })` into the options: tools without one are hidden and refused, and approval-required calls are refused because `createMcp` collects no approvals. Wrap a `CredentialProvider` with `credentialGuard(provider, { permdock, use, revoke? })` so PermDock decides each token use. `authorizationProvider({ ..., approver })` lets holders of that permission approve AI tool calls, never their own. `approvers: { 'ai-tool': holder(p), 'support-session': ..., 'invoice.send': ... }` fills `isApprover` through `permdock_is_approver` (needs `rls.approvals`); only `user()`, `holder()` and `anyOf()` approvers, and a kind it does not name has no approver. `accessReviewApplier({ client, reviews, policy, demoteTo?, email?, permdockFor? })` applies a review's revoked items: `update_member_role` to the `demoteTo` role when that role lacks the permission, else `remove_member`, plus `revoke_invitation` for the member's matching invitations, then `markApplied`; pass the reviewer's client so the blocks' own checks run. better-supabase's `createAgentRuntime({ toolApproval })` takes `toolApproval` from `permdock/ai-sdk` as it is. Validate its claims with `betterSupabase.claims(supabaseClaims().extend(appSchema))` (`supabaseClaims` from `permdock/supabase`, any Standard Schema as `appSchema`) instead of a hand-written copy of the claim shape. A `supabase.hook.claims` function that needs the user's organizations calls `<schema>.member_organization_ids_for(user_id)` (generated by `rls generate`, executable by `supabase_auth_admin` only) instead of querying the membership tables itself. With a scope named `team` or `teams`, `authorizationProvider` fills better-supabase's `teamIdsOf` with `<schema>.member_team_ids_of(user)`, which answers only for the caller, so with `blocks.permissions.model: 'provider'` (`blocks.access` before 0.15) better-supabase's `team_ids_of()` and team-sharing policies read PermDock's memberships. A token Supabase's OAuth server issued to a third-party app (`client_id`) becomes an `oauth-client` actor limited to its `scope`; `deny(permission, { to: actor('oauth-client') })` keeps such apps out, in the app and, through `rls generate`, in Postgres. A better-supabase support session (`act.kind: 'support'`) is actor kind `support` with `sessionId` and `readOnly`, and `actingAs` (`act.kind: 'impersonation'`) is kind `impersonation`; neither has a delegation, so they reach nothing until a policy delegation names `actor('support')` or `actor('impersonation')`, and `readOnly: true` (also when `read_only` is absent) narrows that to read-only permissions. Generated RLS reads memberships, not `act`, so a support token sent to the Data API writes as the user: add a restrictive `for update` (and `insert` / `delete`) policy per writable table that requires `act ->> 'read_only' = 'false'` when `act` is a support or session level ([support access](https://permdock.com/docs/guides/support-access)). With `rls.anonymousSignIns: 'deny'`, pass `anonymousSignIns: 'deny'` to the subject mapper too (doctor PD057). Check a deployed database against the generated policies with `permdock rls verify --introspect`.
|
|
505
505
|
|
|
506
|
-
The other better-supabase slots, all from `permdock/better-supabase` ([better-supabase](https://permdock.com/docs/adapters/better-supabase)): `hookCan(permdock)` and `handlerCan({ getPermDock })` are the `can` options of `authorizeHook` and `protectWebHandler` in `better-supabase/workflow-sdk`; they decide with no row,
|
|
506
|
+
The other better-supabase slots, all from `permdock/better-supabase` ([better-supabase](https://permdock.com/docs/adapters/better-supabase)): `hookCan(permdock)` and `handlerCan({ getPermDock })` are the `can` options of `authorizeHook` and `protectWebHandler` in `better-supabase/workflow-sdk`; they decide with no row unless the `data` option loads one (`hookCan(permdock, { data: (tenant, key) => row })`, `handlerCan(source, { data: (request, key) => row })`), so without it a permission with a row condition denies, and `handlerCan` answers `undefined` (401) without a signed-in principal. `supportPolicy({ policy, options?, writable?, approval?, approved? })` is the `authorize` option of `supportSessions`; it decides each start with `decideSupportSession` as the admin, and an `approval-required` start passes only once `approved(input, pending)` returns `{ approvedBy }` for an approver other than the admin. `subscriberPolicy({ policy, principals, events, row?, sender? })` filters outbox, webhook or realtime subscribers to those who may read the event (exact type, then the longest `prefix.*`, then `*`; a type with no entry reaches no one). `principalSource({ claims, identities? })` is a `PrincipalSource` over the claims better-supabase mints, for `decideFor`, `subscribersFor` and delivery; only links the app created through a signed-in flow or a verified address go in `identities`. `authorizationHooks({ policy, claims, service?, principals?, events?, approvers?, support?, tickets? })` is the `authorization` option of `createServer`: it answers automation publish and run-as, delegated OAuth scopes, `approverOf`, identities, delivery audiences, support sessions and run tickets from the claims better-supabase mints now, never from the request.
|
|
507
507
|
|
|
508
508
|
`claims` is whatever Supabase verified: `data.claims` from `supabase.auth.getClaims()` on an `@supabase/ssr` server client, or `jwtClaims` from `@supabase/server` (`ctx.jwtClaims` in `withSupabase` or a `pipeline`, and `c.var.jwtClaims` after a framework bridge such as `toHono([withClaims(), withPermDock()])`). `@supabase/server/adapters/*` and `c.var.supabaseContext` are deprecated and removed on 1 December 2026; do not write new code against them ([Hono, H3, Elysia and NestJS](https://permdock.com/docs/adapters/supabase#hono-h3-elysia-and-nestjs)). Pass `null` for anonymous callers; never `getSession().access_token` (unverified). An API-key auth mode (`secret`, `publishable`) has `jwtClaims: null` and is the anonymous subject, not a user.
|
|
509
509
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { n as runPowerSync } from "./powersync-CJrT1DSc.js";
|
package/dist/pull-C3EEGzSw.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { n as runCloudPull } from "./pull-2nJr0qg_.js";
|
package/dist/run-Ck22anC2.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { t as run } from "./run-PbRlXTfh.js";
|
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
import { nt as MembershipSource } from "./policy-types-DGIO_gxq.js";
|
|
2
|
-
import { n as RoleMap, r as RoleThrough, x as SupabaseSuspension } from "./types-BMVDHvI0.js";
|
|
3
|
-
import { t as SqlQuery } from "./sql-B80DFdpG.js";
|
|
4
|
-
import { c as SupabaseManifestMembership } from "./manifest-CzzWtnAb.js";
|
|
5
|
-
//#region src/supabase/roles.d.ts
|
|
6
|
-
/** A roles table a role column references, by `schema.table`. */
|
|
7
|
-
type RoleKeys = {
|
|
8
|
-
readonly table: string;
|
|
9
|
-
/** The roles table column the reference points at. */
|
|
10
|
-
readonly id: string;
|
|
11
|
-
/** The roles table column holding the role key. */
|
|
12
|
-
readonly key: string;
|
|
13
|
-
/** The referencing table's column. */
|
|
14
|
-
readonly ref: string;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* One role source of a membership row: a key column, or a reference to a roles
|
|
18
|
-
* table.
|
|
19
|
-
*/
|
|
20
|
-
type RoleSource = string | RoleThrough | RoleMap;
|
|
21
|
-
/** A role source, or several the row holds at once. */
|
|
22
|
-
type RoleSpec = RoleSource | readonly RoleSource[];
|
|
23
|
-
/**
|
|
24
|
-
* A roles table whose tenant rows are written by tenants. A role key read
|
|
25
|
-
* through it from a tenant row that is one of `declared` reads as null, so a
|
|
26
|
-
* tenant cannot claim the grants of a declared role by naming a role after it.
|
|
27
|
-
*/
|
|
28
|
-
type RoleGuard = {
|
|
29
|
-
/** `schema.table`, or `public`. */
|
|
30
|
-
readonly table: string;
|
|
31
|
-
/** The tenant column of the roles table. */
|
|
32
|
-
readonly tenant: string;
|
|
33
|
-
/**
|
|
34
|
-
* A tenant row with this column true is the application's own copy of a
|
|
35
|
-
* declared role.
|
|
36
|
-
*/
|
|
37
|
-
readonly skip?: string | undefined;
|
|
38
|
-
readonly declared: readonly string[];
|
|
39
|
-
};
|
|
40
|
-
//#endregion
|
|
41
|
-
//#region src/supabase/sources.d.ts
|
|
42
|
-
type Common = {
|
|
43
|
-
readonly table: string;
|
|
44
|
-
/**
|
|
45
|
-
* Runs the lookups; without it the source only describes SQL (for `permdock
|
|
46
|
-
* supabase hook generate`).
|
|
47
|
-
*/
|
|
48
|
-
readonly query?: SqlQuery;
|
|
49
|
-
/**
|
|
50
|
-
* Drop suspended users and memberships under suspended instances, like
|
|
51
|
-
* `rls.suspension`.
|
|
52
|
-
*/
|
|
53
|
-
readonly suspension?: SupabaseSuspension;
|
|
54
|
-
};
|
|
55
|
-
type MembershipTableOptions = Common & {
|
|
56
|
-
/**
|
|
57
|
-
* Column names; `user`, `scope`, `id` and `role` default to `user_id`,
|
|
58
|
-
* `scope`, `scope_id`, `role`.
|
|
59
|
-
*/
|
|
60
|
-
readonly columns?: {
|
|
61
|
-
/** The user id column, or a reference to a table that holds the user id. */
|
|
62
|
-
readonly user?: string | RoleThrough;
|
|
63
|
-
readonly scope?: string;
|
|
64
|
-
readonly id?: string;
|
|
65
|
-
/** A `jsonb` column of ancestor ids keyed by scope name. */
|
|
66
|
-
readonly within?: string;
|
|
67
|
-
/**
|
|
68
|
-
* The role key column, a reference to a roles table that holds the key, or
|
|
69
|
-
* several of them: the row holds every non-null key.
|
|
70
|
-
*/
|
|
71
|
-
readonly role?: RoleSpec;
|
|
72
|
-
readonly via?: string;
|
|
73
|
-
readonly expiresAt?: string;
|
|
74
|
-
readonly disabledAt?: string;
|
|
75
|
-
/** The principal id that wrote the membership (`grantedBy`). */
|
|
76
|
-
readonly grantedBy?: string;
|
|
77
|
-
/** Free-text justification recorded on the membership (`reason`). */
|
|
78
|
-
readonly reason?: string;
|
|
79
|
-
/** A subgroup column filling `member.group`. */
|
|
80
|
-
readonly group?: string;
|
|
81
|
-
/**
|
|
82
|
-
* A text column; the value `idp` marks the row as owned by the identity
|
|
83
|
-
* provider.
|
|
84
|
-
*/
|
|
85
|
-
readonly managedBy?: string;
|
|
86
|
-
/** A `text[]` column of seats. */
|
|
87
|
-
readonly seats?: string;
|
|
88
|
-
/** A `jsonb` column of app data (`Membership.x`); never written into claims. */
|
|
89
|
-
readonly x?: string;
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
type MembershipJunctionOptions = Common & {
|
|
93
|
-
/** The declared scope every row is a membership of. */
|
|
94
|
-
readonly scope: string;
|
|
95
|
-
/**
|
|
96
|
-
* The user id column (default `user_id`), or a reference to a table that
|
|
97
|
-
* holds the user id.
|
|
98
|
-
*/
|
|
99
|
-
readonly user?: string | RoleThrough;
|
|
100
|
-
/** The column holding the scope instance id. Default `<scope>_id`. */
|
|
101
|
-
readonly id?: string;
|
|
102
|
-
/** Ancestor id columns keyed by scope name. */
|
|
103
|
-
readonly within?: Readonly<Record<string, string>>;
|
|
104
|
-
/**
|
|
105
|
-
* A role column, a reference to a roles table that holds the key, fixed roles
|
|
106
|
-
* every row holds (a contact table with no role column), or `{ sources }`:
|
|
107
|
-
* several role columns whose non-null keys the row holds.
|
|
108
|
-
*/
|
|
109
|
-
readonly roles: string | RoleThrough | RoleMap | readonly string[] | {
|
|
110
|
-
readonly sources: readonly RoleSource[];
|
|
111
|
-
};
|
|
112
|
-
/** The membership kind every row has (`contact`, `staff`, `partner`). */
|
|
113
|
-
readonly via?: string;
|
|
114
|
-
readonly expiresAt?: string;
|
|
115
|
-
readonly disabledAt?: string;
|
|
116
|
-
/** The principal id that wrote the membership (`grantedBy`). */
|
|
117
|
-
readonly grantedBy?: string;
|
|
118
|
-
/** Free-text justification recorded on the membership (`reason`). */
|
|
119
|
-
readonly reason?: string;
|
|
120
|
-
/** A subgroup filling `member.group`: a fixed name every row has, or a column. */
|
|
121
|
-
readonly group?: string | {
|
|
122
|
-
readonly column: string;
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* `idp` when the identity provider owns every row, or a text column holding
|
|
126
|
-
* `idp` per row.
|
|
127
|
-
*/
|
|
128
|
-
readonly managedBy?: "idp" | {
|
|
129
|
-
readonly column: string;
|
|
130
|
-
};
|
|
131
|
-
/** A `text[]` column of seats. */
|
|
132
|
-
readonly seats?: string;
|
|
133
|
-
/** A `jsonb` column of app data (`Membership.x`); never written into claims. */
|
|
134
|
-
readonly x?: string;
|
|
135
|
-
};
|
|
136
|
-
/**
|
|
137
|
-
* What `permdock supabase hook generate` compiles; the same SQL the source
|
|
138
|
-
* runs.
|
|
139
|
-
*/
|
|
140
|
-
type MembershipSql = {
|
|
141
|
-
readonly table: string;
|
|
142
|
-
/**
|
|
143
|
-
* The table's user column: the user id, or with `userThrough` the reference
|
|
144
|
-
* to the row holding it.
|
|
145
|
-
*/
|
|
146
|
-
readonly user: string;
|
|
147
|
-
/**
|
|
148
|
-
* The table that holds the user id when `user` references it; a change of
|
|
149
|
-
* that id bumps the old and the new user.
|
|
150
|
-
*/
|
|
151
|
-
readonly userThrough?: RoleKeys;
|
|
152
|
-
/**
|
|
153
|
-
* `<table>.<user>%type`: the PL/pgSQL type of the user id column, for a
|
|
154
|
-
* variable `select` compares with.
|
|
155
|
-
*/
|
|
156
|
-
readonly userType: string;
|
|
157
|
-
/**
|
|
158
|
-
* The `select` of claim rows for one user, with every filter applied. `user`
|
|
159
|
-
* must have the column's type (a `userType` variable, or an untyped `$1`
|
|
160
|
-
* Postgres infers): the column is compared uncast so its index applies.
|
|
161
|
-
* `keep` adds the `keep` column; it defaults to `keeps`, and a `union` with a
|
|
162
|
-
* source that keeps passes `true`.
|
|
163
|
-
*/
|
|
164
|
-
select: (user: string, keep?: boolean) => string;
|
|
165
|
-
/** The `select` of member rows for one scope instance (`$1` scope, `$2` id). */
|
|
166
|
-
list: (keep?: boolean) => string;
|
|
167
|
-
/**
|
|
168
|
-
* A suspended scope on the source keeps permissions: rows of its suspended
|
|
169
|
-
* instances stay, with a `keep` column.
|
|
170
|
-
*/
|
|
171
|
-
readonly keeps: boolean;
|
|
172
|
-
/**
|
|
173
|
-
* A text column holding `idp` for rows the identity provider owns; `''` when
|
|
174
|
-
* every row is owned.
|
|
175
|
-
*/
|
|
176
|
-
readonly managed?: string;
|
|
177
|
-
/** Other tables the `select` reads (suspension tables). */
|
|
178
|
-
readonly reads: readonly string[];
|
|
179
|
-
/**
|
|
180
|
-
* The roles table the role column references; a key change bumps every
|
|
181
|
-
* holder's authorization version.
|
|
182
|
-
*/
|
|
183
|
-
readonly through?: RoleKeys;
|
|
184
|
-
/** Every roles table the role columns reference, `through` first. */
|
|
185
|
-
readonly throughs: readonly RoleKeys[];
|
|
186
|
-
/**
|
|
187
|
-
* Every column that decides who holds which membership: user, scope, id,
|
|
188
|
-
* `within`, role, `via` and expiry.
|
|
189
|
-
*/
|
|
190
|
-
readonly columns: readonly string[];
|
|
191
|
-
/**
|
|
192
|
-
* For a single-scope source: its scope and the scopes whose ids each row
|
|
193
|
-
* carries.
|
|
194
|
-
*/
|
|
195
|
-
readonly scope?: string;
|
|
196
|
-
readonly holds?: readonly string[];
|
|
197
|
-
/** The source's entry in the hook manifest's `memberships`. */
|
|
198
|
-
readonly manifest: SupabaseManifestMembership;
|
|
199
|
-
/** What the ownership triggers count; absent on a source that is not a table. */
|
|
200
|
-
readonly holders?: MembershipHolders;
|
|
201
|
-
/**
|
|
202
|
-
* The rows as plain columns, for Sync Streams and `powerSyncSource`; a source
|
|
203
|
-
* without it does not sync.
|
|
204
|
-
*/
|
|
205
|
-
readonly stream?: MembershipStream;
|
|
206
|
-
};
|
|
207
|
-
/**
|
|
208
|
-
* One membership source as columns a Sync Streams query can filter on. Tables
|
|
209
|
-
* are `schema.table`; a `through` table is qualified in the source's schema
|
|
210
|
-
* when it names none.
|
|
211
|
-
*/
|
|
212
|
-
type MembershipStream = {
|
|
213
|
-
readonly table: string;
|
|
214
|
-
/** The user id column, or the reference to the table that holds the user id. */
|
|
215
|
-
readonly user: string | RoleThrough;
|
|
216
|
-
/** The scope column, or the scope every row is a membership of. */
|
|
217
|
-
readonly scope: {
|
|
218
|
-
readonly column: string;
|
|
219
|
-
} | {
|
|
220
|
-
readonly value: string;
|
|
221
|
-
};
|
|
222
|
-
readonly id: string;
|
|
223
|
-
/**
|
|
224
|
-
* The role sources (the row holds every non-null key), or the fixed roles
|
|
225
|
-
* every row holds.
|
|
226
|
-
*/
|
|
227
|
-
readonly roles: RoleSpec | {
|
|
228
|
-
readonly value: readonly string[];
|
|
229
|
-
};
|
|
230
|
-
/** The membership kind column, or the kind every row has. */
|
|
231
|
-
readonly via?: {
|
|
232
|
-
readonly column: string;
|
|
233
|
-
} | {
|
|
234
|
-
readonly value: string;
|
|
235
|
-
};
|
|
236
|
-
readonly expiresAt?: string;
|
|
237
|
-
readonly disabledAt?: string;
|
|
238
|
-
/**
|
|
239
|
-
* A row may hold no role key: such a row is no membership, and a reader drops
|
|
240
|
-
* it.
|
|
241
|
-
*/
|
|
242
|
-
readonly nullableRoles: boolean;
|
|
243
|
-
/**
|
|
244
|
-
* The guard the source reads its roles table with: a tenant row named like a
|
|
245
|
-
* declared role is no role.
|
|
246
|
-
*/
|
|
247
|
-
readonly guard?: RoleGuard;
|
|
248
|
-
};
|
|
249
|
-
/**
|
|
250
|
-
* The rows of a membership table, for the holder-count and transfer-only
|
|
251
|
-
* triggers `permdock rls generate` puts on it. No suspension filter: a
|
|
252
|
-
* suspended holder still holds the role.
|
|
253
|
-
*/
|
|
254
|
-
type MembershipHolders = {
|
|
255
|
-
/**
|
|
256
|
-
* `<table>.<id column>%type`: the type of a variable `rows` compares the id
|
|
257
|
-
* column with.
|
|
258
|
-
*/
|
|
259
|
-
readonly idType: string;
|
|
260
|
-
/**
|
|
261
|
-
* The instance id of scope `scope` the PL/pgSQL record `row` holds, as text;
|
|
262
|
-
* null on a row of another scope.
|
|
263
|
-
*/
|
|
264
|
-
id: (scope: string, row: string) => string;
|
|
265
|
-
/**
|
|
266
|
-
* `select id, user_id, role, via, live` over the rows of scope `scope` in
|
|
267
|
-
* `from` (default the table): one row per held role key, `live` false once
|
|
268
|
-
* expired. `id` is an expression of `idType` the id column must equal.
|
|
269
|
-
*/
|
|
270
|
-
rows: (scope: string, options?: {
|
|
271
|
-
readonly id?: string;
|
|
272
|
-
readonly from?: string;
|
|
273
|
-
}) => string;
|
|
274
|
-
};
|
|
275
|
-
type SqlMembershipSource = MembershipSource & {
|
|
276
|
-
readonly sql: MembershipSql;
|
|
277
|
-
/**
|
|
278
|
-
* The same source with the role keys of tenant rows of `guard.table` named
|
|
279
|
-
* like a declared role read as null.
|
|
280
|
-
*/
|
|
281
|
-
readonly guarded?: (guard: RoleGuard) => SqlMembershipSource;
|
|
282
|
-
};
|
|
283
|
-
/** The part of `@supabase/server`'s `PostgresApi` a `SqlQuery` needs. */
|
|
284
|
-
type SupabasePostgres = {
|
|
285
|
-
readonly queryRaw: (text: string, params?: unknown[]) => Promise<readonly Record<string, unknown>[]>;
|
|
286
|
-
};
|
|
287
|
-
declare function supabasePostgresQuery(postgres: SupabasePostgres): SqlQuery;
|
|
288
|
-
/**
|
|
289
|
-
* Memberships from one table holding every scope: a row per user, scope,
|
|
290
|
-
* instance and role (`user_id, scope, scope_id, role`), with optional `within`,
|
|
291
|
-
* `via`, expiry, owner and seat columns. Rows of the same instance merge into
|
|
292
|
-
* one membership.
|
|
293
|
-
*/
|
|
294
|
-
declare function tableMembershipSource(options: MembershipTableOptions): SqlMembershipSource;
|
|
295
|
-
/**
|
|
296
|
-
* Memberships from a table of one scope (`customer_contacts`): every row is a
|
|
297
|
-
* membership of `scope`, with roles from a column or fixed (`['contact']`), a
|
|
298
|
-
* fixed `via`, and ancestor ids from `within` columns.
|
|
299
|
-
*/
|
|
300
|
-
declare function junctionMembershipSource(options: MembershipJunctionOptions): SqlMembershipSource;
|
|
301
|
-
declare const AUTHZ_VERSION_TABLE = "permdock_authz_version";
|
|
302
|
-
/**
|
|
303
|
-
* Reads the authorization version `permdock supabase hook generate` keeps in
|
|
304
|
-
* `<schema>.permdock_authz_version`: pass it to `claimsFirst(sources, { version
|
|
305
|
-
* })`.
|
|
306
|
-
*/
|
|
307
|
-
declare function authzVersion(options: {
|
|
308
|
-
readonly query: SqlQuery;
|
|
309
|
-
readonly schema?: string;
|
|
310
|
-
}): NonNullable<MembershipSource["version"]>;
|
|
311
|
-
//#endregion
|
|
312
|
-
export { MembershipStream as a, SupabasePostgres as c, supabasePostgresQuery as d, tableMembershipSource as f, MembershipSql as i, authzVersion as l, MembershipHolders as n, MembershipTableOptions as o, MembershipJunctionOptions as r, SqlMembershipSource as s, AUTHZ_VERSION_TABLE as t, junctionMembershipSource as u };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { i as runSupabase } from "./supabase-hook-CrgU06WH.js";
|
package/dist/usage-0hjZPIRX.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { t as runUsage } from "./usage-B9EtHWLa.js";
|
package/dist/watch-ClLuO2TL.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { i as watchCollect } from "./watch-BFDKqmUa.js";
|