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
|
@@ -11,6 +11,7 @@ import { r as sha256Digest } from "../sha256-C-4WXKIu.js";
|
|
|
11
11
|
import { t as decideSupportSession } from "../support-session-BsmPCbz8.js";
|
|
12
12
|
import { f as scopeList } from "../scopes-0Up_UA2t.js";
|
|
13
13
|
import { o as flattenGrantee } from "../grantee-Dke-9rd1.js";
|
|
14
|
+
import { _ as claimsFirst } from "../instance-snapshot-DuWf1cT3.js";
|
|
14
15
|
import { a as delegatedScopeMap, s as scopesReaching, t as getPermDock } from "../permdock-BvjivVb9.js";
|
|
15
16
|
import { t as anonymousSubject } from "../subject-BGoM5o8B.js";
|
|
16
17
|
import { i as linkPolicyViolation, n as capabilityOf, r as capabilitySubject } from "../capability-BqX94r07.js";
|
|
@@ -18,11 +19,12 @@ import { r as credentialSubject, s as parseCredential } from "../credential-Cyyy
|
|
|
18
19
|
import { t as AccessReviewError } from "../errors-BDUwg2qC.js";
|
|
19
20
|
import { t as policyRowConditionKeys } from "../row-conditions-BAGHOmVq.js";
|
|
20
21
|
import { n as subscribersFor } from "../audience-DTjR8xet.js";
|
|
21
|
-
import { l as sqlIdent, s as quoteSqlLiteral } from "../sql-0WjxIp9g.js";
|
|
22
|
-
import "../sources-
|
|
23
|
-
import { c as subjectFromSupabaseSession, t as callRpc } from "../postgrest-
|
|
24
|
-
import { n as parseSupabaseManifest, t as hasTokenHook } from "../manifest-
|
|
22
|
+
import { i as qualifySqlTable, l as sqlIdent, s as quoteSqlLiteral } from "../sql-0WjxIp9g.js";
|
|
23
|
+
import { o as junctionMembershipSource } from "../sources-C4vkzZJV.js";
|
|
24
|
+
import { c as subjectFromSupabaseSession, t as callRpc } from "../postgrest-DAxFltvO.js";
|
|
25
|
+
import { n as parseSupabaseManifest, t as hasTokenHook } from "../manifest-BXTbHNIV.js";
|
|
25
26
|
import { t as parseCatalog } from "../parse-1_ZheTW5.js";
|
|
27
|
+
import { n as activeTenantMismatch, t as activeOrganizationFrom } from "../active-tenant-DVee32-T.js";
|
|
26
28
|
import { AsyncResult, dbError } from "better-supabase";
|
|
27
29
|
//#region src/better-supabase/access-reviews.ts
|
|
28
30
|
const NOT_MEMBER = "ORGANIZATION_NOT_MEMBER";
|
|
@@ -289,6 +291,17 @@ function isApiKeySession(session) {
|
|
|
289
291
|
const record = Object.fromEntries(Object.entries(session));
|
|
290
292
|
return record["kind"] === "apiKey" && typeof record["keyId"] === "string" && typeof record["name"] === "string" && Array.isArray(record["scopes"]) && record["scopes"].every((scope) => typeof scope === "string");
|
|
291
293
|
}
|
|
294
|
+
function isSessionSnapshot(session) {
|
|
295
|
+
return isRecord(session) && !Object.hasOwn(session, "kind") && typeof session["accessToken"] === "string" && typeof session["userId"] === "string" && isRecord(session["claims"]);
|
|
296
|
+
}
|
|
297
|
+
/** A snapshot as a user session; one whose `sub` is not its `userId` is none. */
|
|
298
|
+
function snapshotSession(snapshot) {
|
|
299
|
+
const { claims } = snapshot;
|
|
300
|
+
return isRecord(claims) && claims["sub"] === snapshot.userId ? {
|
|
301
|
+
kind: "user",
|
|
302
|
+
claims
|
|
303
|
+
} : null;
|
|
304
|
+
}
|
|
292
305
|
function apiKeySubject(session, options) {
|
|
293
306
|
const roles = typeof options.serviceRoles === "function" ? options.serviceRoles(session) : options.serviceRoles ?? manifestServiceRoles(options.manifest);
|
|
294
307
|
const credential = keyCredential({
|
|
@@ -309,14 +322,16 @@ function apiKeySubject(session, options) {
|
|
|
309
322
|
* verified `apiKey` session is the key's credential subject: a personal key
|
|
310
323
|
* acts as its user within the key's scopes, a tenant key as a `service`
|
|
311
324
|
* principal holding `serviceRoles`. Without `apiKeys`, and for `anon`,
|
|
312
|
-
* `service` and `invalid` sessions, the subject is anonymous.
|
|
325
|
+
* `service` and `invalid` sessions, the subject is anonymous. A
|
|
326
|
+
* `SessionSnapshot` maps as the user session of its claims.
|
|
313
327
|
*/
|
|
314
328
|
function subjectFromBetterSupabase(session, options = {}) {
|
|
315
329
|
const { apiKeys, plans = "features", claims, ...rest } = options;
|
|
316
330
|
if (isApiKeySession(session)) return apiKeys === void 0 ? anonymousSubject() : apiKeySubject(session, apiKeys);
|
|
331
|
+
const user = isSessionSnapshot(session) ? snapshotSession(session) : session;
|
|
317
332
|
const claim = typeof plans === "string" ? plans : plans.claim ?? "features";
|
|
318
333
|
const keys = typeof plans === "string" ? void 0 : plans.keys;
|
|
319
|
-
return subjectFromSupabaseSession(keys === void 0 ?
|
|
334
|
+
return subjectFromSupabaseSession(keys === void 0 ? user : decodedFeatures(user, claim, keys), {
|
|
320
335
|
...rest,
|
|
321
336
|
claims: {
|
|
322
337
|
memberships: "memberships",
|
|
@@ -442,8 +457,12 @@ function supportPolicy(options) {
|
|
|
442
457
|
}
|
|
443
458
|
//#endregion
|
|
444
459
|
//#region src/better-supabase/hooks.ts
|
|
445
|
-
/**
|
|
446
|
-
|
|
460
|
+
/**
|
|
461
|
+
* better-supabase's claim that caps a context to the permission keys it lists:
|
|
462
|
+
* `bs_permission_cap` before 0.15, `bsb_permission_cap` from 0.15. A run sets
|
|
463
|
+
* both, so the cap holds on every version in the peer range.
|
|
464
|
+
*/
|
|
465
|
+
const PERMISSION_CAP_CLAIMS = ["bs_permission_cap", "bsb_permission_cap"];
|
|
447
466
|
/**
|
|
448
467
|
* Whether `permdock` is granted `key` with no row; an unknown key and
|
|
449
468
|
* `approval-required` are `false`.
|
|
@@ -522,7 +541,7 @@ function authorizationHooks(options) {
|
|
|
522
541
|
if (!isRecord(claims) || !await holdsAll(claims, ref)) return null;
|
|
523
542
|
return Object.freeze({
|
|
524
543
|
...claims,
|
|
525
|
-
[
|
|
544
|
+
...Object.fromEntries(PERMISSION_CAP_CLAIMS.map((claim) => [claim, [...ref.permissions]]))
|
|
526
545
|
});
|
|
527
546
|
} catch {
|
|
528
547
|
return null;
|
|
@@ -745,7 +764,8 @@ const HOLDERS_OF = "permitted_{scope}_users";
|
|
|
745
764
|
/**
|
|
746
765
|
* better-supabase calls `teamIdsOf` from RLS policies as `authenticated`, so it
|
|
747
766
|
* fills from the caller-bound `member_<scope>_ids_of`, never from the `_for`
|
|
748
|
-
* form only `supabase_auth_admin` may execute.
|
|
767
|
+
* form only `supabase_auth_admin` may execute. Without a team scope, the hook
|
|
768
|
+
* writes `member_team_ids_of` from `supabase.hook.teams`.
|
|
749
769
|
*/
|
|
750
770
|
const TEAM_IDS_OF = "member_{scope}_ids_of";
|
|
751
771
|
/** The scope names better-supabase reads as its teams (doctor BS417). */
|
|
@@ -806,12 +826,25 @@ function membershipOf(source, scope, problems) {
|
|
|
806
826
|
table: source.table,
|
|
807
827
|
userColumn: source.user.column,
|
|
808
828
|
scope: "column" in source.scope ? { column: source.scope.column } : { value: scope },
|
|
809
|
-
idColumn: source.id.column
|
|
829
|
+
idColumn: source.id.column,
|
|
830
|
+
...rolesTableOf(source)
|
|
810
831
|
};
|
|
811
832
|
}
|
|
833
|
+
/**
|
|
834
|
+
* The role set a member's roles come from, one row per scope id, user and role:
|
|
835
|
+
* a role read through a reference over several columns.
|
|
836
|
+
*/
|
|
837
|
+
function rolesTableOf(source) {
|
|
838
|
+
const roles = isRoleList(source.role) ? source.role : [source.role];
|
|
839
|
+
for (const role of roles) if ("through" in role && role.through.on !== void 0) return { rolesTable: role.through.table };
|
|
840
|
+
return {};
|
|
841
|
+
}
|
|
842
|
+
function isRoleList(role) {
|
|
843
|
+
return Array.isArray(role);
|
|
844
|
+
}
|
|
812
845
|
function roleSourceOf(source) {
|
|
813
846
|
const role = source.role;
|
|
814
|
-
if (Array.isArray(role) || !("column" in role) || !("through" in role)) return;
|
|
847
|
+
if (Array.isArray(role) || !("column" in role) || !("through" in role) || role.through.on !== void 0) return;
|
|
815
848
|
return {
|
|
816
849
|
table: source.table,
|
|
817
850
|
role: {
|
|
@@ -846,13 +879,15 @@ function permissionsOf(catalog, scopes) {
|
|
|
846
879
|
};
|
|
847
880
|
});
|
|
848
881
|
}
|
|
849
|
-
function tokenHookOf(manifest) {
|
|
882
|
+
function tokenHookOf(manifest, activeTenant) {
|
|
850
883
|
const owned = manifest.claims.filter((claim) => claim.source === "permdock");
|
|
851
884
|
const registered = manifest.claims.filter((claim) => claim.source !== "permdock");
|
|
852
885
|
const budgeted = manifest.claims.filter((claim) => claim.budget);
|
|
886
|
+
const activeFrom = activeTenant === "resolver" || manifest.hook.activeFrom === void 0 ? void 0 : activeOrganizationFrom(manifest.hook.activeFrom, manifest.tenantClaim);
|
|
853
887
|
return {
|
|
854
888
|
function: `${manifest.hook.schema}.${manifest.hook.function}`,
|
|
855
889
|
tenantClaim: manifest.tenantClaim,
|
|
890
|
+
...activeFrom === void 0 ? {} : { activeOrganizationFrom: activeFrom },
|
|
856
891
|
ownedClaims: owned.map((claim) => claim.name),
|
|
857
892
|
...registered.length > 0 ? { registeredClaims: registered.map((claim) => ({
|
|
858
893
|
name: claim.name,
|
|
@@ -944,13 +979,14 @@ function delegatedScopes(catalog) {
|
|
|
944
979
|
* templates, the membership tables, suspension rows, the token hook and every
|
|
945
980
|
* catalog key with `sqlComplete` set from its `rowConditions`. A `_for`
|
|
946
981
|
* template and `permissionsFor` are set only when the manifest lists their
|
|
947
|
-
* helper, which `rls.mode: 'database'` writes
|
|
948
|
-
* `approvers`
|
|
949
|
-
* `
|
|
950
|
-
* `actorMayWrite` (`permdock_actor_may_write()`) are set
|
|
951
|
-
* lists their helper, and so is `teamIdsOf`
|
|
952
|
-
* for a scope named `team` or `teams`. Throws
|
|
953
|
-
* invalid, or when the tenant scope is
|
|
982
|
+
* helper, which `rls.mode: 'database'` writes. `isApprover` is set with
|
|
983
|
+
* `approvers` or `approver` and `permdock_is_approver`: `approver` fills its
|
|
984
|
+
* `'ai-tool'` entry. `canApprove` is never set. `holdersOf` (`permitted_<tenant
|
|
985
|
+
* scope>_users`) and `actorMayWrite` (`permdock_actor_may_write()`) are set
|
|
986
|
+
* when the manifest lists their helper, and so is `teamIdsOf`
|
|
987
|
+
* (`member_<scope>_ids_of({user})`) for a scope named `team` or `teams`. Throws
|
|
988
|
+
* when the manifest or catalog is invalid, or when the tenant scope is
|
|
989
|
+
* ambiguous.
|
|
954
990
|
*/
|
|
955
991
|
function authorizationProvider(options) {
|
|
956
992
|
const manifest = parseSupabaseManifest(options.manifest);
|
|
@@ -958,6 +994,11 @@ function authorizationProvider(options) {
|
|
|
958
994
|
const rls = manifest.rls;
|
|
959
995
|
const problems = [];
|
|
960
996
|
if (catalog === void 0) problems.push("No catalog: better-supabase cannot check that the permission keys its SQL modules use (ai_chat, workflow, inbox and the rest) exist. Pass `catalog`.");
|
|
997
|
+
const activeFrom = hasTokenHook(manifest) ? manifest.hook.activeFrom : void 0;
|
|
998
|
+
if (options.activeTenant !== void 0 && activeFrom !== void 0) {
|
|
999
|
+
const mismatch = activeTenantMismatch(activeFrom, manifest.tenantClaim, options.activeTenant);
|
|
1000
|
+
if (mismatch !== void 0) problems.push(mismatch);
|
|
1001
|
+
}
|
|
961
1002
|
const tenantScope = tenantScopeOf(manifest, options.scope);
|
|
962
1003
|
const scopeNames = rls.scopes.map((scope) => scope.name);
|
|
963
1004
|
const helpers = new Map(rls.helpers.map((helper) => [helper.name, helper]));
|
|
@@ -1037,7 +1078,7 @@ function authorizationProvider(options) {
|
|
|
1037
1078
|
});
|
|
1038
1079
|
}
|
|
1039
1080
|
let teamIdsOf;
|
|
1040
|
-
const teamHelper = scopeNames.filter((scope) => TEAM_SCOPE.test(scope)).map((scope) => helpers.get(TEAM_IDS_OF.replace("{scope}", scope))).find((helper) => helper !== void 0);
|
|
1081
|
+
const teamHelper = scopeNames.filter((scope) => TEAM_SCOPE.test(scope)).map((scope) => helpers.get(TEAM_IDS_OF.replace("{scope}", scope))).find((helper) => helper !== void 0) ?? helpers.get(TEAM_IDS_OF.replace("{scope}", "team"));
|
|
1041
1082
|
if (teamHelper !== void 0) {
|
|
1042
1083
|
const fn = `${schema}.${sqlIdent(teamHelper.name)}`;
|
|
1043
1084
|
teamIdsOf = `${fn}({user})`;
|
|
@@ -1098,11 +1139,24 @@ function authorizationProvider(options) {
|
|
|
1098
1139
|
...Object.keys(operations).length > 0 ? { operations } : {},
|
|
1099
1140
|
...Object.keys(delegated).length > 0 ? { delegation: { scopes: delegated } } : {},
|
|
1100
1141
|
decidingColumns: manifest.decidingColumns,
|
|
1101
|
-
...hasTokenHook(manifest) ? { tokenHook: tokenHookOf(manifest) } : {},
|
|
1142
|
+
...hasTokenHook(manifest) ? { tokenHook: tokenHookOf(manifest, options.activeTenant) } : {},
|
|
1102
1143
|
...problems.length > 0 ? { problems } : {}
|
|
1103
1144
|
});
|
|
1104
1145
|
}
|
|
1105
1146
|
//#endregion
|
|
1147
|
+
//#region src/better-supabase/report.ts
|
|
1148
|
+
/** `PermDock denied <key>: <first denial reason>.` */
|
|
1149
|
+
function deniedMessage(key, decision) {
|
|
1150
|
+
const why = decision.denials[0]?.reason;
|
|
1151
|
+
return why === void 0 ? `PermDock denied ${key}.` : `PermDock denied ${key}: ${why}.`;
|
|
1152
|
+
}
|
|
1153
|
+
function report(sink, error, context) {
|
|
1154
|
+
if (sink === void 0) return;
|
|
1155
|
+
try {
|
|
1156
|
+
sink(error, context);
|
|
1157
|
+
} catch {}
|
|
1158
|
+
}
|
|
1159
|
+
//#endregion
|
|
1106
1160
|
//#region src/better-supabase/authorizer.ts
|
|
1107
1161
|
const OPERATIONS = /* @__PURE__ */ new Set([
|
|
1108
1162
|
"list",
|
|
@@ -1111,10 +1165,18 @@ const OPERATIONS = /* @__PURE__ */ new Set([
|
|
|
1111
1165
|
"update",
|
|
1112
1166
|
"delete"
|
|
1113
1167
|
]);
|
|
1168
|
+
const READ_ACTIONS = /* @__PURE__ */ new Set([
|
|
1169
|
+
"read",
|
|
1170
|
+
"list",
|
|
1171
|
+
"view"
|
|
1172
|
+
]);
|
|
1114
1173
|
const denied = (reason) => ({
|
|
1115
1174
|
outcome: "denied",
|
|
1116
1175
|
reason
|
|
1117
1176
|
});
|
|
1177
|
+
function isVersionCache(value) {
|
|
1178
|
+
return isRecord(value) && typeof value["maxStaleMs"] === "number" && typeof value["current"] === "function" && typeof value["evict"] === "function";
|
|
1179
|
+
}
|
|
1118
1180
|
function outcomeOf(decision, key) {
|
|
1119
1181
|
switch (decision.outcome) {
|
|
1120
1182
|
case "granted": return { outcome: "granted" };
|
|
@@ -1122,10 +1184,7 @@ function outcomeOf(decision, key) {
|
|
|
1122
1184
|
outcome: "approval-required",
|
|
1123
1185
|
approval: { id: decision.token }
|
|
1124
1186
|
};
|
|
1125
|
-
case "denied":
|
|
1126
|
-
const why = decision.denials[0]?.reason;
|
|
1127
|
-
return denied(why === void 0 ? `PermDock denied ${key}.` : `PermDock denied ${key}: ${why}.`);
|
|
1128
|
-
}
|
|
1187
|
+
case "denied": return denied(deniedMessage(key, decision));
|
|
1129
1188
|
default: return decision;
|
|
1130
1189
|
}
|
|
1131
1190
|
}
|
|
@@ -1144,23 +1203,59 @@ function claimsOf(request) {
|
|
|
1144
1203
|
const claims = subject.properties?.["claims"];
|
|
1145
1204
|
return isRecord(claims) ? claims : void 0;
|
|
1146
1205
|
}
|
|
1206
|
+
const tenantOf = (request) => {
|
|
1207
|
+
const tenant = request.context["tenant"];
|
|
1208
|
+
return typeof tenant === "string" ? tenant : null;
|
|
1209
|
+
};
|
|
1210
|
+
const keyOf = (request) => isPermission(request.action) ? request.action.key : null;
|
|
1147
1211
|
/**
|
|
1148
1212
|
* better-supabase's `authorizer` for PermDock: every resource, action, route
|
|
1149
1213
|
* guard and MCP tool that declares a `permission` is decided with `decide`. The
|
|
1150
1214
|
* subject is mapped from the verified claims with `subjectFromBetterSupabase`;
|
|
1151
1215
|
* the request's `context.tenant` selects the active tenant only among the
|
|
1152
1216
|
* memberships the claims hold. A caller without claims is anonymous, and a
|
|
1153
|
-
* throw denies.
|
|
1217
|
+
* throw denies. With better-supabase 0.15's runtime `memo`, the checks of one
|
|
1218
|
+
* request scope share an instance per claims, tenant and intent.
|
|
1154
1219
|
*/
|
|
1155
1220
|
function authorizer(options) {
|
|
1156
1221
|
const { operations } = options;
|
|
1157
|
-
const
|
|
1222
|
+
const intentOf = (request, batch) => {
|
|
1223
|
+
if (options.intent !== void 0) return options.intent(request);
|
|
1224
|
+
if (batch) return "read";
|
|
1225
|
+
return isPermission(request.action) && READ_ACTIONS.has(request.action.action) ? "read" : "write";
|
|
1226
|
+
};
|
|
1227
|
+
const membershipsFor = (runtime) => {
|
|
1228
|
+
if (options.memberships === void 0) return {};
|
|
1229
|
+
const versions = isVersionCache(runtime?.versions) ? runtime.versions : options.versions;
|
|
1230
|
+
return { memberships: claimsFirst(options.memberships, {
|
|
1231
|
+
onStale: "reread",
|
|
1232
|
+
...options.version === void 0 ? {} : { version: options.version },
|
|
1233
|
+
...versions === void 0 ? {} : { versions }
|
|
1234
|
+
}) };
|
|
1235
|
+
};
|
|
1236
|
+
const instanceFor = async (claims, tenant, intent, runtime) => {
|
|
1158
1237
|
const session = claims === void 0 ? null : {
|
|
1159
1238
|
kind: "user",
|
|
1160
1239
|
claims
|
|
1161
1240
|
};
|
|
1162
|
-
const base = await getPermDock(options.policy, subjectFromBetterSupabase(session, options.subject),
|
|
1163
|
-
|
|
1241
|
+
const base = await getPermDock(options.policy, subjectFromBetterSupabase(session, options.subject), {
|
|
1242
|
+
...options.options,
|
|
1243
|
+
...membershipsFor(runtime),
|
|
1244
|
+
intent
|
|
1245
|
+
});
|
|
1246
|
+
return tenant === null ? base : base.tenant(tenant);
|
|
1247
|
+
};
|
|
1248
|
+
const scoped = (claims, tenant, intent, runtime) => runtime?.memo === void 0 ? instanceFor(claims, tenant, intent, runtime) : runtime.memo.once(`permdock:authorizer:${JSON.stringify([
|
|
1249
|
+
claims ?? null,
|
|
1250
|
+
tenant,
|
|
1251
|
+
intent
|
|
1252
|
+
])}`, () => instanceFor(claims, tenant, intent, runtime));
|
|
1253
|
+
const failed = (error, request) => {
|
|
1254
|
+
report(options.onError, error, {
|
|
1255
|
+
permission: keyOf(request),
|
|
1256
|
+
tenant: tenantOf(request)
|
|
1257
|
+
});
|
|
1258
|
+
return denied("The permission check failed.");
|
|
1164
1259
|
};
|
|
1165
1260
|
return Object.freeze({
|
|
1166
1261
|
apiVersion: 1,
|
|
@@ -1173,39 +1268,98 @@ function authorizer(options) {
|
|
|
1173
1268
|
if (!OPERATIONS.has(operation) || !Object.hasOwn(operations, table)) return void 0;
|
|
1174
1269
|
return operations[table]?.[operation];
|
|
1175
1270
|
} },
|
|
1176
|
-
async evaluate(request) {
|
|
1271
|
+
async evaluate(request, runtime) {
|
|
1177
1272
|
try {
|
|
1178
|
-
return decideWith(await
|
|
1179
|
-
} catch {
|
|
1180
|
-
return
|
|
1273
|
+
return decideWith(await scoped(claimsOf(request), tenantOf(request), intentOf(request, false), runtime), request);
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
return failed(error, request);
|
|
1181
1276
|
}
|
|
1182
1277
|
},
|
|
1183
|
-
evaluations(requests) {
|
|
1278
|
+
evaluations(requests, runtime) {
|
|
1184
1279
|
const cache = /* @__PURE__ */ new Map();
|
|
1185
|
-
const shared = (
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1280
|
+
const shared = (request) => {
|
|
1281
|
+
const claims = claimsOf(request);
|
|
1282
|
+
const tenant = tenantOf(request);
|
|
1283
|
+
const intent = intentOf(request, true);
|
|
1284
|
+
let byKey = cache.get(claims);
|
|
1285
|
+
if (byKey === void 0) {
|
|
1286
|
+
byKey = /* @__PURE__ */ new Map();
|
|
1287
|
+
cache.set(claims, byKey);
|
|
1190
1288
|
}
|
|
1191
|
-
|
|
1289
|
+
const key = JSON.stringify([tenant, intent]);
|
|
1290
|
+
let instance = byKey.get(key);
|
|
1192
1291
|
if (instance === void 0) {
|
|
1193
|
-
instance =
|
|
1194
|
-
|
|
1292
|
+
instance = scoped(claims, tenant, intent, runtime);
|
|
1293
|
+
byKey.set(key, instance);
|
|
1195
1294
|
}
|
|
1196
1295
|
return instance;
|
|
1197
1296
|
};
|
|
1198
1297
|
return Promise.all(requests.map(async (request) => {
|
|
1199
1298
|
try {
|
|
1200
|
-
return decideWith(await shared(
|
|
1201
|
-
} catch {
|
|
1202
|
-
return
|
|
1299
|
+
return decideWith(await shared(request), request);
|
|
1300
|
+
} catch (error) {
|
|
1301
|
+
return failed(error, request);
|
|
1203
1302
|
}
|
|
1204
1303
|
}));
|
|
1205
1304
|
}
|
|
1206
1305
|
});
|
|
1207
1306
|
}
|
|
1208
1307
|
//#endregion
|
|
1308
|
+
//#region src/better-supabase/block-memberships.ts
|
|
1309
|
+
function roleOf(options, columns) {
|
|
1310
|
+
const column = columns.role;
|
|
1311
|
+
if (options.roles !== void 0 && options.roleThrough !== void 0) throw new TypeError("PermDock: blockMembershipSource takes roles or roleThrough, not both; a junction holds role keys");
|
|
1312
|
+
if (options.roles === "many") return {
|
|
1313
|
+
through: `${qualifySqlTable(columns.table).split(".")[0] ?? "better_supabase"}.membership_roles`,
|
|
1314
|
+
on: {
|
|
1315
|
+
[columns.tenant]: columns.tenant,
|
|
1316
|
+
[columns.user]: columns.user
|
|
1317
|
+
},
|
|
1318
|
+
column: "role"
|
|
1319
|
+
};
|
|
1320
|
+
if (options.roles !== void 0) return {
|
|
1321
|
+
through: options.roles.table,
|
|
1322
|
+
on: { [options.roles.id ?? "id"]: options.roles.membership },
|
|
1323
|
+
column: options.roles.role
|
|
1324
|
+
};
|
|
1325
|
+
if (options.roleThrough !== void 0) return {
|
|
1326
|
+
through: options.roleThrough.table,
|
|
1327
|
+
on: { [column]: options.roleThrough.id },
|
|
1328
|
+
column: options.roleThrough.column
|
|
1329
|
+
};
|
|
1330
|
+
return column;
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Memberships from better-supabase's `memberships` block table: one row per
|
|
1334
|
+
* user and organization, its role key in `role`, a custom role's key through
|
|
1335
|
+
* `roleThrough`, or several roles from a `roles` junction or, with `roles:
|
|
1336
|
+
* "many"`, from better-supabase's `membership_roles`. A row with `disabled_at`
|
|
1337
|
+
* set is no membership.
|
|
1338
|
+
*/
|
|
1339
|
+
function blockMembershipSource(options = {}) {
|
|
1340
|
+
const c = options.columns ?? {};
|
|
1341
|
+
const scope = options.scope ?? "organization";
|
|
1342
|
+
const disabledAt = c.disabledAt === null ? void 0 : c.disabledAt ?? "disabled_at";
|
|
1343
|
+
const table = options.table ?? "better_supabase.memberships";
|
|
1344
|
+
const tenant = c.tenant ?? "organization_id";
|
|
1345
|
+
const user = c.user ?? "user_id";
|
|
1346
|
+
return junctionMembershipSource({
|
|
1347
|
+
table,
|
|
1348
|
+
scope,
|
|
1349
|
+
id: tenant,
|
|
1350
|
+
user,
|
|
1351
|
+
roles: roleOf(options, {
|
|
1352
|
+
table,
|
|
1353
|
+
role: c.role ?? "role",
|
|
1354
|
+
tenant,
|
|
1355
|
+
user
|
|
1356
|
+
}),
|
|
1357
|
+
...disabledAt === void 0 ? {} : { disabledAt },
|
|
1358
|
+
...options.query === void 0 ? {} : { query: options.query },
|
|
1359
|
+
...options.suspension === void 0 ? {} : { suspension: options.suspension }
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
//#endregion
|
|
1209
1363
|
//#region src/better-supabase/policies.ts
|
|
1210
1364
|
/**
|
|
1211
1365
|
* PermDock splits a key with row conditions into `key#1`, `key#2`, ... in the
|
|
@@ -1339,7 +1493,8 @@ const refused = (reason) => ({
|
|
|
1339
1493
|
* tools whose `meta` is a PermDock permission. A tool without a permission is
|
|
1340
1494
|
* hidden and refused. `authorize` grants only a `granted` decision: an
|
|
1341
1495
|
* approval-required call is refused, because `createMcp` has no approval flow.
|
|
1342
|
-
* A throw anywhere refuses
|
|
1496
|
+
* A denial's text names the first denial reason. A throw anywhere refuses and
|
|
1497
|
+
* reaches `onError`.
|
|
1343
1498
|
*/
|
|
1344
1499
|
function toolPolicy(options) {
|
|
1345
1500
|
return Object.freeze({
|
|
@@ -1353,10 +1508,14 @@ function toolPolicy(options) {
|
|
|
1353
1508
|
switch (decision.outcome) {
|
|
1354
1509
|
case "granted": return { allowed: true };
|
|
1355
1510
|
case "approval-required": return refused(`${permission.key} needs approval, which this server does not collect.`);
|
|
1356
|
-
case "denied": return refused(
|
|
1511
|
+
case "denied": return refused(deniedMessage(permission.key, decision));
|
|
1357
1512
|
default: return decision;
|
|
1358
1513
|
}
|
|
1359
|
-
} catch {
|
|
1514
|
+
} catch (error) {
|
|
1515
|
+
report(options.onError, error, {
|
|
1516
|
+
permission: permission.key,
|
|
1517
|
+
tenant: null
|
|
1518
|
+
});
|
|
1360
1519
|
return refused("The permission check failed.");
|
|
1361
1520
|
}
|
|
1362
1521
|
},
|
|
@@ -1365,7 +1524,11 @@ function toolPolicy(options) {
|
|
|
1365
1524
|
if (!isPermission(permission)) return false;
|
|
1366
1525
|
try {
|
|
1367
1526
|
return (await options.permdock(ctx)).mayUse(permission);
|
|
1368
|
-
} catch {
|
|
1527
|
+
} catch (error) {
|
|
1528
|
+
report(options.onError, error, {
|
|
1529
|
+
permission: permission.key,
|
|
1530
|
+
tenant: null
|
|
1531
|
+
});
|
|
1369
1532
|
return false;
|
|
1370
1533
|
}
|
|
1371
1534
|
}
|
|
@@ -1585,12 +1748,12 @@ async function subjectFromShareLink(token, options) {
|
|
|
1585
1748
|
//#region src/better-supabase/workflow.ts
|
|
1586
1749
|
/**
|
|
1587
1750
|
* Whether `permdock` is granted the permission `key` (a catalog key or scope)
|
|
1588
|
-
*
|
|
1751
|
+
* on `row`.
|
|
1589
1752
|
*/
|
|
1590
|
-
function grants(permdock, key) {
|
|
1753
|
+
function grants(permdock, key, row) {
|
|
1591
1754
|
try {
|
|
1592
1755
|
const permission = findPermission(permdock.permissions, key);
|
|
1593
|
-
return permission !== void 0 && permdock.decide(permission,
|
|
1756
|
+
return permission !== void 0 && permdock.decide(permission, row).outcome === "granted";
|
|
1594
1757
|
} catch {
|
|
1595
1758
|
return false;
|
|
1596
1759
|
}
|
|
@@ -1598,25 +1761,40 @@ function grants(permdock, key) {
|
|
|
1598
1761
|
/**
|
|
1599
1762
|
* The `can` option of better-supabase's `authorizeHook`, for the caller's
|
|
1600
1763
|
* `permdock`: `true` only when the caller is a member of the hook's tenant and
|
|
1601
|
-
* `decide` grants the permission its `hookMetadata` names there
|
|
1602
|
-
* key, `approval-required` and a throw are
|
|
1764
|
+
* `decide` grants the permission its `hookMetadata` names there, on the row
|
|
1765
|
+
* `options.data` loads. An unknown key, `approval-required` and a throw are
|
|
1766
|
+
* `false`.
|
|
1603
1767
|
*/
|
|
1604
|
-
function hookCan(permdock) {
|
|
1605
|
-
|
|
1768
|
+
function hookCan(permdock, options = {}) {
|
|
1769
|
+
const { data } = options;
|
|
1770
|
+
const decideIn = (tenant, key, row) => {
|
|
1771
|
+
try {
|
|
1772
|
+
return permdock.tenants().includes(tenant) && grants(permdock.tenant(tenant), key, row);
|
|
1773
|
+
} catch {
|
|
1774
|
+
return false;
|
|
1775
|
+
}
|
|
1776
|
+
};
|
|
1777
|
+
if (data === void 0) return (tenant, key) => decideIn(tenant, key);
|
|
1778
|
+
return async (tenant, key) => {
|
|
1779
|
+
let row;
|
|
1606
1780
|
try {
|
|
1607
|
-
|
|
1781
|
+
if (!permdock.tenants().includes(tenant)) return false;
|
|
1782
|
+
row = await data(tenant, key);
|
|
1608
1783
|
} catch {
|
|
1609
1784
|
return false;
|
|
1610
1785
|
}
|
|
1786
|
+
return decideIn(tenant, key, row);
|
|
1611
1787
|
};
|
|
1612
1788
|
}
|
|
1613
1789
|
/**
|
|
1614
1790
|
* The `can` option of better-supabase's `protectWebHandler`: `undefined` (401)
|
|
1615
1791
|
* when the request has no signed-in principal or `getPermDock` throws,
|
|
1616
1792
|
* otherwise whether `decide` grants the permission in the request's active
|
|
1617
|
-
* tenant. An unknown key
|
|
1793
|
+
* tenant, on the row `options.data` loads. An unknown key, `approval-required`
|
|
1794
|
+
* and a throwing `data` are `false` (403).
|
|
1618
1795
|
*/
|
|
1619
|
-
function handlerCan(source) {
|
|
1796
|
+
function handlerCan(source, options = {}) {
|
|
1797
|
+
const { data } = options;
|
|
1620
1798
|
return async (request, key) => {
|
|
1621
1799
|
let permdock;
|
|
1622
1800
|
try {
|
|
@@ -1625,8 +1803,14 @@ function handlerCan(source) {
|
|
|
1625
1803
|
return;
|
|
1626
1804
|
}
|
|
1627
1805
|
if (permdock.subject.principal === null) return;
|
|
1628
|
-
return grants(permdock, key);
|
|
1806
|
+
if (data === void 0) return grants(permdock, key);
|
|
1807
|
+
try {
|
|
1808
|
+
const row = await data(request, key);
|
|
1809
|
+
return grants(permdock, key, row);
|
|
1810
|
+
} catch {
|
|
1811
|
+
return false;
|
|
1812
|
+
}
|
|
1629
1813
|
};
|
|
1630
1814
|
}
|
|
1631
1815
|
//#endregion
|
|
1632
|
-
export { accessReviewApplier, apiKeyClaimOptions, apiKeyVerifier, authorizationHooks, authorizationProvider, authorizer, bucketPolicy, credentialGuard, handlerCan, hookCan, principalFromMemberships, principalSource, roleOrderFromCatalog, subjectFromBetterSupabase, subjectFromShareLink, subscriberPolicy, supportPolicy, toolPolicy, topicPolicy };
|
|
1816
|
+
export { accessReviewApplier, apiKeyClaimOptions, apiKeyVerifier, authorizationHooks, authorizationProvider, authorizer, blockMembershipSource, bucketPolicy, credentialGuard, handlerCan, hookCan, principalFromMemberships, principalSource, roleOrderFromCatalog, subjectFromBetterSupabase, subjectFromShareLink, subscriberPolicy, supportPolicy, toolPolicy, topicPolicy };
|
|
@@ -16,7 +16,7 @@ const casbinImport = defineLeaf({
|
|
|
16
16
|
...outFlag
|
|
17
17
|
},
|
|
18
18
|
async run(ctx, { flags }) {
|
|
19
|
-
const { runCasbinImport } = await import("./casbin-
|
|
19
|
+
const { runCasbinImport } = await import("./casbin-DTi6HSsl.js");
|
|
20
20
|
return runCasbinImport({
|
|
21
21
|
cwd: ctx.cwd,
|
|
22
22
|
model: given(flags.model),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as nonEmptyOr } from "./output-
|
|
1
|
+
import { a as nonEmptyOr } from "./output-CtyBwTNB.js";
|
|
2
2
|
import { t as applyFiles } from "./files-B3AA05f1.js";
|
|
3
3
|
import { n as isIdentifier, t as emitPolicyModule } from "./policy-module-xym9fnSq.js";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
package/dist/cli/bin.js
CHANGED
|
@@ -11,7 +11,7 @@ if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
|
11
11
|
const [{ isCi }, { trapSignals }, { run }, { streamHasColors }] = await Promise.all([
|
|
12
12
|
import("../env-DJZrPjRi.js"),
|
|
13
13
|
import("../signals-B1vHR3fN.js"),
|
|
14
|
-
import("../run-
|
|
14
|
+
import("../run-0vOholnN.js"),
|
|
15
15
|
import("../style-DblOtSga.js")
|
|
16
16
|
]);
|
|
17
17
|
const signals = trapSignals();
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { f as PermissionTree } from "../permission-types-CAY-GU7e.js";
|
|
|
3
3
|
import { o as OperationMap } from "../operations-Ci_rT6Uo.js";
|
|
4
4
|
import { a as CatalogDocument, d as CatalogRole, f as CatalogScope, l as CatalogPermission, m as CatalogUsage, n as CatalogApproval, p as CatalogSupportAccess, r as CatalogBreakGlass, t as CatalogActivation, u as CatalogResource } from "../types-ZzRGoViD.js";
|
|
5
5
|
import { a as pushedPolicy, i as parsePushedPolicy, n as PushedGrant, r as PushedPolicy, t as PUSHED_POLICY_SCHEMA } from "../pushed-policy-CryQheKq.js";
|
|
6
|
-
import { _ as RlsSuspension, a as GenKind, c as RlsActiveRow, d as RlsDialect, f as RlsFunctionMapping, g as RlsSuspendedScope, h as RlsSuspendedMembership, i as GenConfig, l as RlsApiKeys, m as RlsMemberships, n as CliIo, o as PermDockConfig, p as RlsMembershipTable, r as CollectConfig, t as CatalogConfig, u as RlsConfig, v as RlsTarget, y as RunResult } from "../types-
|
|
6
|
+
import { _ as RlsSuspension, a as GenKind, c as RlsActiveRow, d as RlsDialect, f as RlsFunctionMapping, g as RlsSuspendedScope, h as RlsSuspendedMembership, i as GenConfig, l as RlsApiKeys, m as RlsMemberships, n as CliIo, o as PermDockConfig, p as RlsMembershipTable, r as CollectConfig, t as CatalogConfig, u as RlsConfig, v as RlsTarget, y as RunResult } from "../types-Cklw5hJo.js";
|
|
7
7
|
import { o as ResourceNameOf, r as PermissionKeyOf, s as ScopeNameOf, t as ActionNameOf } from "../type-helpers-c7Xo_2Cu.js";
|
|
8
8
|
//#region src/cli/catalog-path.d.ts
|
|
9
9
|
/**
|
|
@@ -76,6 +76,11 @@ type ConfigChecks<C> = [PolicyOf<C>] extends [never] ? unknown : {
|
|
|
76
76
|
readonly powersync?: {
|
|
77
77
|
readonly resources?: readonly ResourceNameOf<PolicyOf<C>>[];
|
|
78
78
|
readonly action?: ActionNameOf<PolicyOf<C>>;
|
|
79
|
+
readonly tables?: Readonly<Record<string, {
|
|
80
|
+
readonly follow?: readonly {
|
|
81
|
+
readonly resource: ResourceNameOf<PolicyOf<C>>;
|
|
82
|
+
}[];
|
|
83
|
+
}>>;
|
|
79
84
|
};
|
|
80
85
|
};
|
|
81
86
|
//#endregion
|
package/dist/cli/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as catalogPath } from "../catalog-path-CnI0XTFK.js";
|
|
2
|
-
import { t as defineConfig } from "../config-
|
|
2
|
+
import { t as defineConfig } from "../config-BR23fL8m.js";
|
|
3
3
|
import { n as parsePushedPolicy, r as pushedPolicy, t as PUSHED_POLICY_SCHEMA } from "../pushed-policy-CDuOL2de.js";
|
|
4
4
|
import { c as parseGrantsMarker, l as parseHookMarker } from "../markers-BeHZ4x9Q.js";
|
|
5
|
-
import { t as run } from "../run-
|
|
5
|
+
import { t as run } from "../run-B5nyNKe8.js";
|
|
6
6
|
//#region src/cli/token-schemas.ts
|
|
7
7
|
const ID = {
|
|
8
8
|
type: "string",
|
|
@@ -85,6 +85,14 @@ const RUN_TICKET_SCHEMA = {
|
|
|
85
85
|
maxItems: 64
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
+
},
|
|
89
|
+
resource: {
|
|
90
|
+
type: "object",
|
|
91
|
+
required: ["type", "id"],
|
|
92
|
+
properties: {
|
|
93
|
+
type: ID,
|
|
94
|
+
id: ID
|
|
95
|
+
}
|
|
88
96
|
}
|
|
89
97
|
},
|
|
90
98
|
anyOf: [{
|
|
@@ -41,7 +41,7 @@ const push = defineLeaf({
|
|
|
41
41
|
},
|
|
42
42
|
async run(ctx, { flags }) {
|
|
43
43
|
const env = await withStdinSecret(ctx, "key", flags["key-stdin"], "PERMDOCK_CLOUD_KEY");
|
|
44
|
-
return (await import("./push-
|
|
44
|
+
return (await import("./push-Dq_ca4-j.js")).runCloud({
|
|
45
45
|
cwd: ctx.cwd,
|
|
46
46
|
config: ctx.config,
|
|
47
47
|
url: given(flags.url),
|
|
@@ -70,7 +70,7 @@ const pull = defineLeaf({
|
|
|
70
70
|
},
|
|
71
71
|
async run(ctx, { flags }) {
|
|
72
72
|
const env = await withStdinSecret(ctx, "token", flags["token-stdin"], "PERMDOCK_CLOUD_TOKEN");
|
|
73
|
-
return (await import("./pull-
|
|
73
|
+
return (await import("./pull-DfJALUbS.js")).runCloudPull({
|
|
74
74
|
cwd: ctx.cwd,
|
|
75
75
|
config: ctx.config,
|
|
76
76
|
url: given(flags.url),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as CliError } from "./errors-Vpu6rKHl.js";
|
|
2
2
|
import { a as rel } from "./files-BSjrtIHw.js";
|
|
3
3
|
import { t as beforeFirst } from "./text-BMFRfBqc.js";
|
|
4
|
-
import { n as ROOT } from "./manifest-
|
|
4
|
+
import { n as ROOT } from "./manifest-Cav1rjNQ.js";
|
|
5
5
|
import { i as renameMessage, n as DEFAULT_CHANGES, r as flagRename, t as COMMAND_MOVES } from "./renames-CGj7YwcQ.js";
|
|
6
6
|
import { i as refuseDirty, t as applyFiles } from "./files-B3AA05f1.js";
|
|
7
7
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
@@ -7,7 +7,7 @@ const codemod = defineLeaf({
|
|
|
7
7
|
description: "The release to migrate to (0.5)",
|
|
8
8
|
required: true,
|
|
9
9
|
async complete() {
|
|
10
|
-
return (await import("./codemod-
|
|
10
|
+
return (await import("./codemod-C1U8_Zu3.js")).codemodVersions();
|
|
11
11
|
}
|
|
12
12
|
}, {
|
|
13
13
|
name: "paths",
|
|
@@ -22,7 +22,7 @@ const codemod = defineLeaf({
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
async run(ctx, { flags, args, rest }) {
|
|
25
|
-
return (await import("./codemod-
|
|
25
|
+
return (await import("./codemod-C1U8_Zu3.js")).runCodemod({
|
|
26
26
|
cwd: ctx.cwd,
|
|
27
27
|
version: args["version"],
|
|
28
28
|
paths: rest,
|