permdock 0.0.0 → 0.2.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/README.md +327 -1
- package/dist/a2a/index.d.ts +169 -0
- package/dist/a2a/index.js +232 -0
- package/dist/adapter-context-mlWsVGGg.js +23 -0
- package/dist/ai-sdk/index.d.ts +95 -0
- package/dist/ai-sdk/index.js +154 -0
- package/dist/approval-required-TzNB9oQA.js +6 -0
- package/dist/approvals/index.d.ts +3 -0
- package/dist/approvals/index.js +5 -0
- package/dist/approvals-DbYAuNkG.js +224 -0
- package/dist/approvers-DT4AVyIg.js +52 -0
- package/dist/arazzo-BAgw9ap6.js +70 -0
- package/dist/arazzo-cmvX2jDe.js +54 -0
- package/dist/authzen/index.d.ts +39 -0
- package/dist/authzen/index.js +302 -0
- package/dist/better-auth/index.d.ts +109 -0
- package/dist/better-auth/index.js +344 -0
- package/dist/better-supabase/index.d.ts +206 -0
- package/dist/better-supabase/index.js +620 -0
- package/dist/bind-CVy3Espv.d.ts +25 -0
- package/dist/bind-VnYn2HKq.js +97 -0
- package/dist/boundary-BM8a_P6E.js +13 -0
- package/dist/boundary-BmHxVH1J.d.ts +15 -0
- package/dist/budget-JqcRqyhK.d.ts +11 -0
- package/dist/budget-NbEtbJC_.js +11 -0
- package/dist/canonical-json-DemiK4Vp.js +26 -0
- package/dist/capability-4qPdO9gk.js +173 -0
- package/dist/capability-Dq43tT1u.d.ts +99 -0
- package/dist/catalog/index.d.ts +12 -0
- package/dist/catalog/index.js +2 -0
- package/dist/catalog-BjZSovXQ.js +2 -0
- package/dist/catalog-doc-Dsc9y7sd.js +309 -0
- package/dist/catalog-h2tlKFkq.js +48 -0
- package/dist/catalog-path-CnI0XTFK.js +12 -0
- package/dist/catalog-z8q6bi_r.js +55 -0
- package/dist/claude-agent/index.d.ts +72 -0
- package/dist/claude-agent/index.js +77 -0
- package/dist/clerk/index.d.ts +65 -0
- package/dist/clerk/index.js +301 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +20 -0
- package/dist/cli/index.d.ts +46 -0
- package/dist/cli/index.js +5 -0
- package/dist/clients-C7zLFuWT.d.ts +12 -0
- package/dist/clients-DjU5ABMy.js +23 -0
- package/dist/cloud/index.d.ts +90 -0
- package/dist/cloud/index.js +404 -0
- package/dist/cloud-BGhHS-lY.js +50 -0
- package/dist/cloud-Bo3e9Ak3.js +118 -0
- package/dist/collect-DDDv_ESs.js +502 -0
- package/dist/collect-DLlujdHC.js +83 -0
- package/dist/collect-rG2IQ3t0.js +2 -0
- package/dist/commands-DWOrSQic.js +97 -0
- package/dist/compact-y6vfu2_f.js +19 -0
- package/dist/compare-pfyVnBjE.js +12 -0
- package/dist/compile/index.d.ts +3 -0
- package/dist/compile/index.js +2 -0
- package/dist/compile-Ba4blROR.js +613 -0
- package/dist/compile-CNnl6uIt.d.ts +94 -0
- package/dist/config-BJiM-xAm.js +157 -0
- package/dist/config-Bn00Z3ks.js +36 -0
- package/dist/config-report-Dw_JcUqT.js +44 -0
- package/dist/connection-CU8MQxRi.js +194 -0
- package/dist/context-Ttp0ekMT.js +82 -0
- package/dist/convex/index.d.ts +45 -0
- package/dist/convex/index.js +65 -0
- package/dist/create-BWyx3jua.d.ts +245 -0
- package/dist/create-CPhDL6qx.js +253 -0
- package/dist/credential-8P81ff4u.js +306 -0
- package/dist/delegation-D8pUEuce.js +103 -0
- package/dist/describe-B_gVZEVi.js +94 -0
- package/dist/describe-PdoqESvg.d.ts +36 -0
- package/dist/diff-B8Tunc3o.js +451 -0
- package/dist/diff-CzqLxZ77.js +48 -0
- package/dist/digest-B3kc_PgQ.d.ts +19 -0
- package/dist/digest-BI-6aa6d.js +27 -0
- package/dist/doctor-WpvG6p4k.js +1194 -0
- package/dist/doctor-collect-ByfYlNv1.js +664 -0
- package/dist/doctor-rOr-4ZfS.js +53 -0
- package/dist/drizzle/index.d.ts +73 -0
- package/dist/drizzle/index.js +160 -0
- package/dist/duration-xK2jGFVc.js +25 -0
- package/dist/elysia/index.d.ts +49 -0
- package/dist/elysia/index.js +59 -0
- package/dist/errors-CWfoNg9N.js +47 -0
- package/dist/errors-Cz5zn0mW.js +123 -0
- package/dist/errors-DAqevpNk.d.ts +125 -0
- package/dist/errors-DRnGZHzF.js +30 -0
- package/dist/evaluation-items-CfCCejQd.js +40 -0
- package/dist/evaluations-tz6D9A2G.js +461 -0
- package/dist/eve/index.d.ts +86 -0
- package/dist/eve/index.js +176 -0
- package/dist/expiry-BoBJ8Tvc.js +7 -0
- package/dist/express/index.d.ts +23 -0
- package/dist/express/index.js +78 -0
- package/dist/fastify/index.d.ts +33 -0
- package/dist/fastify/index.js +92 -0
- package/dist/fields-BMl1RxoX.js +26 -0
- package/dist/files-DWUN9PzI.js +125 -0
- package/dist/fixtures-ht28Cplr.js +67 -0
- package/dist/freeze-CrU8nQeX.js +60 -0
- package/dist/from-snapshot-C3sHpZNS.js +569 -0
- package/dist/generate-CH7ThJ14.js +173 -0
- package/dist/grantee-Cv5Sogfv.js +602 -0
- package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
- package/dist/headers-BZSDieNT.js +6 -0
- package/dist/headers-Cf-zWvsO.d.ts +6 -0
- package/dist/helpers-H_KARDVC.js +421 -0
- package/dist/hono/index.d.ts +48 -0
- package/dist/hono/index.js +99 -0
- package/dist/hosted-DJQw46hn.js +266 -0
- package/dist/http-BIhmLfCc.js +95 -0
- package/dist/http-DPuDaChb.d.ts +13 -0
- package/dist/http-SO7qGttf.js +44 -0
- package/dist/ids-DC4V4CFu.js +18 -0
- package/dist/index-A0YNL8jZ.d.ts +177 -0
- package/dist/index-CtE07CBF.d.ts +6 -0
- package/dist/index-D3vbkoSI.d.ts +483 -0
- package/dist/index-D6_cSa1z.d.ts +201 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +26 -0
- package/dist/instance-options-BK_rNOSC.d.ts +11 -0
- package/dist/instance-options-Dhhcnm3y.js +22 -0
- package/dist/json-schema-BsAflUGW.js +106 -0
- package/dist/jwt/index.d.ts +91 -0
- package/dist/jwt/index.js +590 -0
- package/dist/kernel-GSQnMz3O.js +208 -0
- package/dist/kysely/index.d.ts +78 -0
- package/dist/kysely/index.js +129 -0
- package/dist/live-options-H2eG8dfJ.js +60 -0
- package/dist/load-DhWEB9P1.js +75 -0
- package/dist/load-DwJUafYN.js +2 -0
- package/dist/load-jose-BL6LH4bL.js +11 -0
- package/dist/lru-8q4WZjBV.js +28 -0
- package/dist/manifest-iaoBXHKc.js +783 -0
- package/dist/manifest-uDS9y5de.d.ts +206 -0
- package/dist/map-AcxK9o_D.js +147 -0
- package/dist/map-claims-Z4QZOiFF.js +369 -0
- package/dist/map-error-pgUWNNtG.js +23 -0
- package/dist/markers-B0hYLvMD.js +60 -0
- package/dist/may-use-DndQ5tQ-.js +77 -0
- package/dist/mcp/index.d.ts +159 -0
- package/dist/mcp/index.js +603 -0
- package/dist/nest/index.d.ts +75 -0
- package/dist/nest/index.js +261 -0
- package/dist/next/client.d.ts +23 -0
- package/dist/next/client.js +33 -0
- package/dist/next/index.d.ts +93 -0
- package/dist/next/index.js +180 -0
- package/dist/next/plugin.d.ts +14 -0
- package/dist/next/plugin.js +33 -0
- package/dist/node/index.d.ts +24 -0
- package/dist/node/index.js +34 -0
- package/dist/openai/index.d.ts +62 -0
- package/dist/openai/index.js +92 -0
- package/dist/openapi/index.d.ts +176 -0
- package/dist/openapi/index.js +3 -0
- package/dist/openapi-Bbg4wGVL.js +164 -0
- package/dist/openapi-BqRBvAng.js +538 -0
- package/dist/openapi-CqqEbHsL.js +250 -0
- package/dist/openapi-import-cmwetbzw.js +5959 -0
- package/dist/openapi-schema--ARjyfQr.js +6902 -0
- package/dist/orpc/index.d.ts +51 -0
- package/dist/orpc/index.js +145 -0
- package/dist/otel/index.d.ts +13 -0
- package/dist/otel/index.js +202 -0
- package/dist/package-root-zGkxO3oN.js +30 -0
- package/dist/parse-BuyjxhZV.js +53 -0
- package/dist/parse-local-manifest-BkGQNzAh.d.ts +10 -0
- package/dist/parse-local-manifest-BrMozJCo.js +36 -0
- package/dist/pdp/index.d.ts +22 -0
- package/dist/pdp/index.js +682 -0
- package/dist/peer-BOr_kJE1.js +31 -0
- package/dist/permdock-CzqXjCpU.js +3471 -0
- package/dist/permissions-CDgvKG5L.d.ts +52 -0
- package/dist/permissions-CpZrivYv.js +142 -0
- package/dist/permissions-DVoF6dMt.js +662 -0
- package/dist/permissions-DttnqqxC.d.ts +214 -0
- package/dist/pins-8ILTftC9.js +12 -0
- package/dist/policy-CFZAr_Al.d.ts +2252 -0
- package/dist/policy-D8UFyERw.d.ts +20 -0
- package/dist/policy-xyWg7QdR.js +1122 -0
- package/dist/powersync-A8x_Yyvh.js +2 -0
- package/dist/powersync-C7kLglqX.js +540 -0
- package/dist/powersync-yW1UUFzp.js +62 -0
- package/dist/prisma/index.d.ts +136 -0
- package/dist/prisma/index.js +455 -0
- package/dist/problem-B43ztKIm.js +191 -0
- package/dist/problem-details-CkL50EEf.d.ts +7 -0
- package/dist/problem-details-_AMOYz-w.js +144 -0
- package/dist/prompt-CXYhLfsS.js +32 -0
- package/dist/protected-CNsMzrVd.d.ts +27 -0
- package/dist/protected-Cs6kTaHo.js +100 -0
- package/dist/protected-bZs6rbT1.d.ts +40 -0
- package/dist/provider-Cjr62YMV.d.ts +6 -0
- package/dist/provider-DLzpb2Xz.js +52 -0
- package/dist/provider-store-DNyC1y48.js +43 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.js +7 -0
- package/dist/react/provider-client.d.ts +2 -0
- package/dist/react/provider-client.js +3 -0
- package/dist/react-native/index.d.ts +198 -0
- package/dist/react-native/index.js +696 -0
- package/dist/refs-KYb4ntaz.js +91 -0
- package/dist/relations-cjOL01hZ.js +505 -0
- package/dist/replay-BsOyTrdV.js +28 -0
- package/dist/replay-sqBGMnNs.d.ts +5 -0
- package/dist/resource-ref-CaS9yVPi.js +20 -0
- package/dist/revocations-Bhr0aMIC.js +27 -0
- package/dist/revocations-Cy06JNx2.d.ts +21 -0
- package/dist/rls-BMNydpHk.js +2521 -0
- package/dist/rls-CEvs64Kj.js +238 -0
- package/dist/rls-fields-BMasREhR.js +3502 -0
- package/dist/rls-graph-pc9fuXYm.js +435 -0
- package/dist/rls-import-D8F7j35Q.js +943 -0
- package/dist/rls-migrate-7wikfrVI.js +367 -0
- package/dist/rls-ownership-B5Lkq62W.js +843 -0
- package/dist/rls-shared-aOQ4hGTO.js +493 -0
- package/dist/rls-verify-D8B7dOTh.js +745 -0
- package/dist/row-check-Dt35czLy.d.ts +40 -0
- package/dist/rpc-DOK54_CS.js +89 -0
- package/dist/run-YXCJDNYk.js +174 -0
- package/dist/runtime-CB8gQFvS.js +11 -0
- package/dist/saas-Bj_FFkjN.js +1203 -0
- package/dist/schema-D3MnDMxa.js +300 -0
- package/dist/scim/index.d.ts +2 -0
- package/dist/scim/index.js +2 -0
- package/dist/scim-BFGBBAqR.js +1445 -0
- package/dist/scopes-CVdPrWN-.js +239 -0
- package/dist/server/index.d.ts +134 -0
- package/dist/server/index.js +11 -0
- package/dist/server-DlZ28Oz5.js +268 -0
- package/dist/sha256-BO0swRXL.js +150 -0
- package/dist/shared-DRu8VFVM.js +123 -0
- package/dist/sink-Bd9PSyfq.js +141 -0
- package/dist/sink-Gs6TTVa-.d.ts +104 -0
- package/dist/skills-Biq5uup3.js +192 -0
- package/dist/skills-JaymNCdK.js +56 -0
- package/dist/snapshot-Enxd0n-s.js +975 -0
- package/dist/snapshot-cache-D6jLelln.js +44 -0
- package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
- package/dist/solid/index.d.ts +93 -0
- package/dist/solid/index.js +188 -0
- package/dist/sources-B0UvrJ21.js +534 -0
- package/dist/sources-BcJgw0lt.d.ts +192 -0
- package/dist/sql-xdg5f4Fi.js +27 -0
- package/dist/src-CSbUiozF.js +568 -0
- package/dist/ssf/index.d.ts +4 -0
- package/dist/ssf/index.js +596 -0
- package/dist/store-DMAWwAJV.js +371 -0
- package/dist/store-D_pjn91-.d.ts +36 -0
- package/dist/store-options-yO0V6gRn.js +716 -0
- package/dist/stores-4_sqiOA1.js +87 -0
- package/dist/stores-DVR5NHLE.d.ts +52 -0
- package/dist/stream-DDpvynSB.js +66 -0
- package/dist/stream-DlvG2hs-.d.ts +12 -0
- package/dist/style-CTm1AXDT.js +22 -0
- package/dist/subject-C6dLxqHU.js +24 -0
- package/dist/subject-settings-BwBmCdTR.js +128 -0
- package/dist/supabase/index.d.ts +183 -0
- package/dist/supabase/index.js +5 -0
- package/dist/supabase/middleware.d.ts +82 -0
- package/dist/supabase/middleware.js +102 -0
- package/dist/supabase-CwafwxxF.js +83 -0
- package/dist/supabase-DTBaC20O.js +774 -0
- package/dist/supabase-config-Bs44dare.js +472 -0
- package/dist/supabase-hook-BuxLQLpU.js +1814 -0
- package/dist/supabase-hook-D5qVd_D8.js +2 -0
- package/dist/supautils-DYZnzRWV.js +91 -0
- package/dist/svelte/PermissionBoundary.svelte +37 -0
- package/dist/svelte/Protected.svelte +40 -0
- package/dist/svelte/index.d.ts +13 -0
- package/dist/svelte/index.js +107 -0
- package/dist/svelte/runtime.d.ts +7 -0
- package/dist/svelte/runtime.js +4 -0
- package/dist/svelte/source.d.ts +13 -0
- package/dist/svelte/source.js +11 -0
- package/dist/terminal/index.d.ts +163 -0
- package/dist/terminal/index.js +833 -0
- package/dist/testing/index.d.ts +745 -0
- package/dist/testing/index.js +3672 -0
- package/dist/testing/saas/index.d.ts +194 -0
- package/dist/testing/saas/index.js +3 -0
- package/dist/testing/saas/permissions.d.ts +2 -0
- package/dist/testing/saas/permissions.js +2 -0
- package/dist/text-diff-BdkkYSbi.js +15 -0
- package/dist/thenable-okc2xDsj.js +10 -0
- package/dist/timeout-D51niuQP.js +8 -0
- package/dist/token-CIWxJOCh.js +50 -0
- package/dist/trpc/index.d.ts +61 -0
- package/dist/trpc/index.js +122 -0
- package/dist/types-9AWO9EGt.d.ts +197 -0
- package/dist/types-BPxgszlT.d.ts +550 -0
- package/dist/types-BVyImy5I.d.ts +120 -0
- package/dist/types-Bvc4oWT6.d.ts +9 -0
- package/dist/types-C3s9xVJG.d.ts +48 -0
- package/dist/types-Dnemwd77.d.ts +183 -0
- package/dist/types-kxznc7cn.d.ts +52 -0
- package/dist/types-vKyAMtcX.d.ts +157 -0
- package/dist/types-vNSDF7Dq.d.ts +66 -0
- package/dist/types-yF5LmQVD.d.ts +306 -0
- package/dist/unplugin/index.d.ts +7 -0
- package/dist/unplugin/index.js +31 -0
- package/dist/usage-D07N9QJ3.js +42 -0
- package/dist/usage-D82l1CwK.js +2 -0
- package/dist/usage-DG1oeCca.js +693 -0
- package/dist/validation-error-CnjZ4t92.js +33 -0
- package/dist/validation-error-CtF23SrC.d.ts +26 -0
- package/dist/validity-uOp8UpYn.js +245 -0
- package/dist/verifier-BxBo6I44.js +466 -0
- package/dist/version-BvacVTZR.js +17 -0
- package/dist/views-Soe7bGSC.js +95 -0
- package/dist/vocabulary-DA8a8zif.d.ts +56 -0
- package/dist/vue/index.d.ts +79 -0
- package/dist/vue/index.js +196 -0
- package/dist/watch-Etoa_Mvr.js +2 -0
- package/dist/watch-UihESpsJ.js +128 -0
- package/dist/webmcp/index.d.ts +75 -0
- package/dist/webmcp/index.js +307 -0
- package/package.json +450 -5
- package/rulesets/permdock.yaml +29 -0
- package/schemas/approval-request-v1.json +175 -0
- package/schemas/catalog-v1.json +535 -0
- package/schemas/openapi/oas-3.1.json +1298 -0
- package/schemas/openapi/oas-3.2.json +1516 -0
- package/schemas/openapi/overlay-1.1.json +79 -0
- package/schemas/supabase-claims-v1.json +144 -0
- package/schemas/supabase-manifest-v1.json +361 -0
- package/skills/permdock/SKILL.md +66 -0
- package/skills/permdock-agents/SKILL.md +77 -0
- package/skills/permdock-agents/references/runtimes.md +213 -0
- package/skills/permdock-approvals/SKILL.md +80 -0
- package/skills/permdock-approvals/references/stores-and-resume.md +94 -0
- package/skills/permdock-audit/SKILL.md +67 -0
- package/skills/permdock-credentials/SKILL.md +55 -0
- package/skills/permdock-credentials/references/tokens-keys-links.md +132 -0
- package/skills/permdock-data/SKILL.md +57 -0
- package/skills/permdock-data/references/queries-and-rls.md +62 -0
- package/skills/permdock-data/references/relationships.md +67 -0
- package/skills/permdock-tenancy/SKILL.md +80 -0
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +89 -0
- package/skills/permdock-wire/SKILL.md +116 -0
- package/skills/permdock-wire/references/adapters.md +492 -0
- package/skills/permdock-wire/references/policy-options.md +45 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { n as isReadonlyArray, t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
+
import { n as freezeDeep } from "../freeze-CrU8nQeX.js";
|
|
3
|
+
import { _ as listPermissions } from "../permissions-DVoF6dMt.js";
|
|
4
|
+
import { m as role, t as allow } from "../policy-xyWg7QdR.js";
|
|
5
|
+
import { t as ignoreRejection } from "../thenable-okc2xDsj.js";
|
|
6
|
+
import { t as anonymousSubject } from "../subject-C6dLxqHU.js";
|
|
7
|
+
import { i as membershipEvent } from "../sink-Bd9PSyfq.js";
|
|
8
|
+
//#region src/better-auth/parse.ts
|
|
9
|
+
function isRecord(value) {
|
|
10
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
function asRoles(value) {
|
|
13
|
+
if (typeof value === "string") return value === "" ? [] : value.split(",").map((item) => item.trim()).filter((item) => item !== "");
|
|
14
|
+
if (!Array.isArray(value)) return [];
|
|
15
|
+
return value.filter((item) => typeof item === "string");
|
|
16
|
+
}
|
|
17
|
+
function asStatements(value) {
|
|
18
|
+
if (!isRecord(value)) return {};
|
|
19
|
+
const out = {};
|
|
20
|
+
for (const [resource, actions] of Object.entries(value)) {
|
|
21
|
+
if (!Array.isArray(actions)) continue;
|
|
22
|
+
out[resource] = actions.filter((action) => typeof action === "string");
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
function expiresAtSeconds(value) {
|
|
27
|
+
if (typeof value === "number" && Number.isFinite(value)) return value > 0xe8d4a51000 ? Math.floor(value / 1e3) : Math.floor(value);
|
|
28
|
+
if (value instanceof Date) {
|
|
29
|
+
const ms = value.getTime();
|
|
30
|
+
return Number.isFinite(ms) ? Math.floor(ms / 1e3) : void 0;
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
const parsed = Date.parse(value);
|
|
34
|
+
return Number.isNaN(parsed) ? void 0 : Math.floor(parsed / 1e3);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function unwrapList(value) {
|
|
38
|
+
if (Array.isArray(value)) return value;
|
|
39
|
+
if (!isRecord(value)) return [];
|
|
40
|
+
for (const key of [
|
|
41
|
+
"members",
|
|
42
|
+
"teams",
|
|
43
|
+
"organizations",
|
|
44
|
+
"roles",
|
|
45
|
+
"data",
|
|
46
|
+
"items"
|
|
47
|
+
]) {
|
|
48
|
+
const inner = value[key];
|
|
49
|
+
if (Array.isArray(inner)) return inner;
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Member rows for `userId` only. `listMembers` returns every member of an
|
|
55
|
+
* organization, so a row without the caller's `userId` is never theirs.
|
|
56
|
+
*/
|
|
57
|
+
function parseMemberRows(value, userId, requireUserId = true) {
|
|
58
|
+
const out = [];
|
|
59
|
+
const rows = isRecord(value) && typeof value["organizationId"] === "string" ? [value] : unwrapList(value);
|
|
60
|
+
for (const item of rows) {
|
|
61
|
+
if (!isRecord(item)) continue;
|
|
62
|
+
const owner = typeof item["userId"] === "string" ? item["userId"] : void 0;
|
|
63
|
+
if (owner === void 0 ? requireUserId : owner !== userId) continue;
|
|
64
|
+
const tenant = typeof item["organizationId"] === "string" ? item["organizationId"] : void 0;
|
|
65
|
+
const roles = asRoles(item["role"] ?? item["roles"]);
|
|
66
|
+
if (tenant === void 0 || roles.length === 0) continue;
|
|
67
|
+
out.push(compact({
|
|
68
|
+
tenant,
|
|
69
|
+
roles
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
function parseTeamRows(value, userId) {
|
|
75
|
+
const out = [];
|
|
76
|
+
for (const item of unwrapList(value)) {
|
|
77
|
+
if (!isRecord(item)) continue;
|
|
78
|
+
if (typeof item["userId"] === "string" && item["userId"] !== userId) continue;
|
|
79
|
+
const teamRecord = isRecord(item["team"]) ? item["team"] : void 0;
|
|
80
|
+
const team = typeof item["teamId"] === "string" ? item["teamId"] : typeof teamRecord?.["id"] === "string" ? teamRecord["id"] : void 0;
|
|
81
|
+
const tenant = typeof item["organizationId"] === "string" ? item["organizationId"] : typeof teamRecord?.["organizationId"] === "string" ? teamRecord["organizationId"] : void 0;
|
|
82
|
+
const roles = asRoles(item["role"] ?? item["roles"]);
|
|
83
|
+
if (team === void 0 || roles.length === 0) continue;
|
|
84
|
+
out.push(compact({
|
|
85
|
+
tenant,
|
|
86
|
+
team,
|
|
87
|
+
roles,
|
|
88
|
+
via: `team:${team}`
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function parseOrganizationRoles(value) {
|
|
94
|
+
const out = [];
|
|
95
|
+
for (const item of unwrapList(value)) {
|
|
96
|
+
if (!isRecord(item)) continue;
|
|
97
|
+
const name = typeof item["role"] === "string" ? item["role"] : typeof item["name"] === "string" ? item["name"] : void 0;
|
|
98
|
+
if (name === void 0 || name === "") continue;
|
|
99
|
+
out.push({
|
|
100
|
+
name,
|
|
101
|
+
statements: asStatements(item["permission"] ?? item["permissions"] ?? item["statements"])
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
function statementsCover(candidate, required) {
|
|
107
|
+
for (const [resource, actions] of Object.entries(required)) {
|
|
108
|
+
const held = candidate[resource];
|
|
109
|
+
if (held === void 0) return false;
|
|
110
|
+
const set = new Set(held);
|
|
111
|
+
for (const action of actions) if (!set.has(action)) return false;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/better-auth/roles.ts
|
|
117
|
+
function statementsOf(accessRole) {
|
|
118
|
+
return asStatements(accessRole.statements ?? accessRole.permissions);
|
|
119
|
+
}
|
|
120
|
+
function rolesFromAccessControl(access, permissions, options = {}) {
|
|
121
|
+
const leaves = listPermissions(permissions);
|
|
122
|
+
const unmatched = [];
|
|
123
|
+
const roles = [];
|
|
124
|
+
for (const [name, accessRole] of Object.entries(access.roles)) {
|
|
125
|
+
const statements = statementsOf(accessRole);
|
|
126
|
+
const grants = [];
|
|
127
|
+
for (const [resource, actions] of Object.entries(statements)) for (const action of actions) {
|
|
128
|
+
const leaf = leaves.find((item) => item.resource === resource && item.action === action);
|
|
129
|
+
if (leaf === void 0) {
|
|
130
|
+
unmatched.push({
|
|
131
|
+
role: name,
|
|
132
|
+
resource,
|
|
133
|
+
action
|
|
134
|
+
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
grants.push(allow(leaf));
|
|
138
|
+
}
|
|
139
|
+
roles.push(options.on === "tenant" ? role(name, grants, { on: "tenant" }) : role(name, grants));
|
|
140
|
+
}
|
|
141
|
+
return Object.assign(roles, { unmatched });
|
|
142
|
+
}
|
|
143
|
+
function betterAuthRoleSource(auth, options = {}) {
|
|
144
|
+
const assignableRoles = options.assignable ?? [];
|
|
145
|
+
return {
|
|
146
|
+
async rolesFor(tenant) {
|
|
147
|
+
try {
|
|
148
|
+
return parseOrganizationRoles(await auth.api?.listOrganizationRoles?.({
|
|
149
|
+
query: { organizationId: tenant },
|
|
150
|
+
headers: options.headers
|
|
151
|
+
})).map((item) => freezeDeep(compact({
|
|
152
|
+
tenant,
|
|
153
|
+
name: item.name,
|
|
154
|
+
includes: assignableRoles.filter((declared) => statementsCover(item.statements, declared.statements)).map((declared) => declared.name)
|
|
155
|
+
})));
|
|
156
|
+
} catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
assignable() {
|
|
161
|
+
return assignableRoles.map((item) => item.name);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/** A team role sits in the second scope inside its organization; an organization role in the first. */
|
|
166
|
+
function scopeOfChange(event) {
|
|
167
|
+
const tenant = event.organizationId;
|
|
168
|
+
if (tenant === void 0) return {};
|
|
169
|
+
return event.teamId === void 0 ? {
|
|
170
|
+
scope: "tenant",
|
|
171
|
+
id: tenant
|
|
172
|
+
} : {
|
|
173
|
+
scope: "team",
|
|
174
|
+
id: event.teamId,
|
|
175
|
+
within: { tenant }
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function onRoleChange(refresh, options = {}) {
|
|
179
|
+
return async (event) => {
|
|
180
|
+
await refresh(event);
|
|
181
|
+
const sink = options.sink;
|
|
182
|
+
if (sink === void 0 || event.userId === void 0) return;
|
|
183
|
+
const added = event.role !== void 0 && event.role !== event.previousRole ? [event.role] : [];
|
|
184
|
+
const removed = event.previousRole !== void 0 && event.previousRole !== event.role ? [event.previousRole] : [];
|
|
185
|
+
const operation = event.previousRole === void 0 ? "added" : event.role === void 0 ? "removed" : "changed";
|
|
186
|
+
try {
|
|
187
|
+
await sink.write([membershipEvent(compact({
|
|
188
|
+
source: "better-auth",
|
|
189
|
+
operation,
|
|
190
|
+
principal: { id: event.userId },
|
|
191
|
+
...scopeOfChange(event),
|
|
192
|
+
roles: {
|
|
193
|
+
added,
|
|
194
|
+
removed
|
|
195
|
+
},
|
|
196
|
+
by: event.by
|
|
197
|
+
}))]);
|
|
198
|
+
} catch {}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/better-auth/subject.ts
|
|
203
|
+
const PROFILE_FIELDS = /* @__PURE__ */ new Set([
|
|
204
|
+
"name",
|
|
205
|
+
"image",
|
|
206
|
+
"displayName"
|
|
207
|
+
]);
|
|
208
|
+
function validateClaims(extra, schema) {
|
|
209
|
+
const result = schema["~standard"].validate(extra);
|
|
210
|
+
if (result instanceof Promise) {
|
|
211
|
+
ignoreRejection(result);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if ("issues" in result && result.issues !== void 0) return;
|
|
215
|
+
const value = result.value;
|
|
216
|
+
return isRecord(value) ? value : void 0;
|
|
217
|
+
}
|
|
218
|
+
function extraFields(user) {
|
|
219
|
+
const reserved = /* @__PURE__ */ new Set([
|
|
220
|
+
"id",
|
|
221
|
+
"role",
|
|
222
|
+
"roles",
|
|
223
|
+
"email",
|
|
224
|
+
"emailVerified",
|
|
225
|
+
"createdAt",
|
|
226
|
+
"updatedAt",
|
|
227
|
+
"banned",
|
|
228
|
+
"banReason",
|
|
229
|
+
"banExpires"
|
|
230
|
+
]);
|
|
231
|
+
const extra = {};
|
|
232
|
+
for (const [key, value] of Object.entries(user)) {
|
|
233
|
+
if (reserved.has(key) || PROFILE_FIELDS.has(key)) continue;
|
|
234
|
+
extra[key] = value;
|
|
235
|
+
}
|
|
236
|
+
return extra;
|
|
237
|
+
}
|
|
238
|
+
function isTrustedSession(session) {
|
|
239
|
+
if (!isRecord(session)) return false;
|
|
240
|
+
return isRecord(session["user"]) || isRecord(session["session"]);
|
|
241
|
+
}
|
|
242
|
+
async function settle(load, fallback) {
|
|
243
|
+
try {
|
|
244
|
+
return await load();
|
|
245
|
+
} catch {
|
|
246
|
+
return fallback;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function organizationIds(auth, tenant, options) {
|
|
250
|
+
const list = auth.api?.listOrganizations;
|
|
251
|
+
if (options.memberships === "active" || list === void 0) return tenant === void 0 ? [] : [tenant];
|
|
252
|
+
const ids = (await settle(async () => {
|
|
253
|
+
const value = await list({ headers: options.headers });
|
|
254
|
+
return isReadonlyArray(value) ? value : [];
|
|
255
|
+
}, [])).map((row) => isRecord(row) && typeof row["id"] === "string" ? row["id"] : void 0).filter((id) => id !== void 0 && id !== "");
|
|
256
|
+
return [...new Set(ids)];
|
|
257
|
+
}
|
|
258
|
+
const MEMBER_LIMIT = 5e3;
|
|
259
|
+
/** Every member row of the user in one adapter query, or `undefined` without an adapter. */
|
|
260
|
+
async function memberRows(auth, userId) {
|
|
261
|
+
try {
|
|
262
|
+
const findMany = (await auth.$context)?.adapter?.findMany;
|
|
263
|
+
if (findMany === void 0) return;
|
|
264
|
+
return parseMemberRows(await findMany({
|
|
265
|
+
model: "member",
|
|
266
|
+
where: [{
|
|
267
|
+
field: "userId",
|
|
268
|
+
value: userId
|
|
269
|
+
}],
|
|
270
|
+
limit: MEMBER_LIMIT
|
|
271
|
+
}), userId);
|
|
272
|
+
} catch {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function memberIn(auth, userId, organizationId, tenant, headers) {
|
|
277
|
+
const active = auth.api?.getActiveMember;
|
|
278
|
+
if (organizationId === tenant && active !== void 0) return settle(async () => parseMemberRows(await active({ headers }), userId), []);
|
|
279
|
+
const list = auth.api?.listMembers;
|
|
280
|
+
if (list === void 0) return Promise.resolve([]);
|
|
281
|
+
return settle(async () => parseMemberRows(await list({
|
|
282
|
+
query: {
|
|
283
|
+
organizationId,
|
|
284
|
+
filterField: "userId",
|
|
285
|
+
filterOperator: "eq",
|
|
286
|
+
filterValue: userId
|
|
287
|
+
},
|
|
288
|
+
headers
|
|
289
|
+
}), userId).filter((item) => item.tenant === organizationId), []);
|
|
290
|
+
}
|
|
291
|
+
async function loadMemberships(auth, session, user, userId, tenant, options) {
|
|
292
|
+
let members = parseMemberRows(session["members"] ?? session["member"] ?? user["members"], userId, false);
|
|
293
|
+
let teams = parseTeamRows(session["teamMembers"] ?? session["teams"] ?? user["teamMembers"], userId);
|
|
294
|
+
const headers = options.headers;
|
|
295
|
+
if (members.length === 0) {
|
|
296
|
+
const rows = options.memberships === "active" ? void 0 : await memberRows(auth, userId);
|
|
297
|
+
if (rows === void 0) {
|
|
298
|
+
const ids = await organizationIds(auth, tenant, options);
|
|
299
|
+
members = (await Promise.all(ids.map((id) => memberIn(auth, userId, id, tenant, headers)))).flat();
|
|
300
|
+
} else members = rows;
|
|
301
|
+
}
|
|
302
|
+
const listUserTeams = auth.api?.listUserTeams;
|
|
303
|
+
if (teams.length === 0 && listUserTeams !== void 0) teams = await settle(async () => parseTeamRows(await listUserTeams({ headers }), userId), []);
|
|
304
|
+
if (options.memberships === "active" && tenant !== void 0) {
|
|
305
|
+
members = members.filter((item) => item.tenant === tenant);
|
|
306
|
+
teams = teams.filter((item) => item.tenant === tenant);
|
|
307
|
+
}
|
|
308
|
+
return [...members, ...teams];
|
|
309
|
+
}
|
|
310
|
+
async function subjectFromBetterAuth(auth, session, options = {}) {
|
|
311
|
+
try {
|
|
312
|
+
if (session === null || session === void 0 || !isTrustedSession(session)) return anonymousSubject();
|
|
313
|
+
if (!isRecord(session["user"])) return anonymousSubject();
|
|
314
|
+
const user = session["user"];
|
|
315
|
+
const record = isRecord(session["session"]) ? session["session"] : void 0;
|
|
316
|
+
const id = typeof user["id"] === "string" ? user["id"] : void 0;
|
|
317
|
+
if (id === void 0 || id === "") return anonymousSubject();
|
|
318
|
+
const tenant = typeof record?.["activeOrganizationId"] === "string" ? record["activeOrganizationId"] : void 0;
|
|
319
|
+
const roles = asRoles(user["role"] ?? user["roles"]);
|
|
320
|
+
const declared = options.declared;
|
|
321
|
+
const globalRoles = declared === void 0 ? roles : roles.filter((role) => declared.includes(role));
|
|
322
|
+
const extra = options.schema === void 0 ? {} : validateClaims(extraFields(user), options.schema) ?? {};
|
|
323
|
+
const memberships = await loadMemberships(auth, session, user, id, tenant, options);
|
|
324
|
+
const principal = compact({
|
|
325
|
+
id,
|
|
326
|
+
kind: "user",
|
|
327
|
+
roles: globalRoles,
|
|
328
|
+
tenant,
|
|
329
|
+
memberships,
|
|
330
|
+
email: typeof user["email"] === "string" ? user["email"] : void 0,
|
|
331
|
+
claims: Object.keys(extra).length === 0 ? void 0 : extra
|
|
332
|
+
});
|
|
333
|
+
return freezeDeep(compact({
|
|
334
|
+
principal,
|
|
335
|
+
context: {},
|
|
336
|
+
session: typeof record?.["id"] === "string" ? record["id"] : void 0,
|
|
337
|
+
expiresAt: expiresAtSeconds(record?.["expiresAt"])
|
|
338
|
+
}));
|
|
339
|
+
} catch {
|
|
340
|
+
return anonymousSubject();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
344
|
+
export { betterAuthRoleSource, onRoleChange, rolesFromAccessControl, subjectFromBetterAuth };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { $t as CredentialPrincipal, Pr as Subject, ln as PermDock, nt as CredentialVerifier } from "../policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission, m as PermissionTree } from "../permissions-DttnqqxC.js";
|
|
3
|
+
import { g as SupabaseSubjectOptions, m as SupabaseSessionLike, u as SupabasePrincipal } from "../types-yF5LmQVD.js";
|
|
4
|
+
import { AuthorizationProvider } from "better-supabase/config";
|
|
5
|
+
import { AccessTopicPolicy } from "better-supabase/realtime";
|
|
6
|
+
import { AccessBucketPolicy } from "better-supabase/storage";
|
|
7
|
+
import { ApiKey, ApiKeyClaimsOptions, ApiKeys } from "better-supabase/blocks/api-keys";
|
|
8
|
+
import { CredentialProvider } from "better-supabase/credentials";
|
|
9
|
+
import { ToolDecision, ToolRef } from "better-supabase/mcp";
|
|
10
|
+
import { EntitlementClaimOptions } from "better-supabase/blocks/entitlements";
|
|
11
|
+
import { AuthSession } from "better-supabase/server";
|
|
12
|
+
//#region src/better-supabase/provider.d.ts
|
|
13
|
+
type AuthorizationProviderOptions = {
|
|
14
|
+
/** `permdock.manifest.json`, parsed or as JSON text, from `permdock supabase inspect --out`. */
|
|
15
|
+
readonly manifest: unknown;
|
|
16
|
+
/**
|
|
17
|
+
* `permissions.catalog.json` from `permdock catalog`. Without it the
|
|
18
|
+
* provider lists no permissions, so better-supabase refuses every key in
|
|
19
|
+
* a bucket, topic or module check.
|
|
20
|
+
*/
|
|
21
|
+
readonly catalog?: unknown;
|
|
22
|
+
/** The scope tenants are; defaults to the manifest's one root scope. */
|
|
23
|
+
readonly scope?: string;
|
|
24
|
+
/**
|
|
25
|
+
* The permission that lets a user decide a tool call waiting for approval
|
|
26
|
+
* in a tenant, for better-supabase's `canApprove`. The approver is never
|
|
27
|
+
* the user who asked (`approvals.distinctApprover`). Without it the chat's
|
|
28
|
+
* owner decides.
|
|
29
|
+
*/
|
|
30
|
+
readonly approver?: Permission;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* better-supabase's `authorization` config value, built from PermDock's
|
|
34
|
+
* manifest and catalog: the scopes, the `rls generate` helpers as SQL
|
|
35
|
+
* templates, the membership tables, suspension rows, the token hook and
|
|
36
|
+
* every catalog key with `sqlComplete` set from its `rowConditions`. A
|
|
37
|
+
* `_for` template and `permissionsFor` are set only when the manifest lists
|
|
38
|
+
* their helper, which `rls.mode: 'database'` writes; `canApprove` only with
|
|
39
|
+
* `approver`. Throws when the manifest or catalog is invalid, or when the
|
|
40
|
+
* tenant scope is ambiguous.
|
|
41
|
+
*/
|
|
42
|
+
export declare function authorizationProvider(options: AuthorizationProviderOptions): AuthorizationProvider;
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/better-supabase/policies.d.ts
|
|
45
|
+
type AccessPolicyOptions = {
|
|
46
|
+
/** `permdock.manifest.json`, parsed or as JSON text: it names the helpers' schema and the scopes. */
|
|
47
|
+
readonly manifest: unknown;
|
|
48
|
+
/** `permissions.catalog.json`: only keys it marks `rowConditions: false` are accepted. */
|
|
49
|
+
readonly catalog: unknown;
|
|
50
|
+
/** A scope in the manifest's `rls.scopes`, or `platform` for permissions granted globally. */
|
|
51
|
+
readonly scope: string;
|
|
52
|
+
/** 1-based path or topic segment holding the scope id; better-supabase's default is the `{organizationId}` segment. */
|
|
53
|
+
readonly segment?: number;
|
|
54
|
+
};
|
|
55
|
+
type BucketAccess = {
|
|
56
|
+
/** Downloads, signed URLs, renders and metadata reads. */
|
|
57
|
+
readonly read: Permission;
|
|
58
|
+
/** Listing; without it `read` covers listing too. */
|
|
59
|
+
readonly list?: Permission;
|
|
60
|
+
/** Uploads, updates and moves; also deletes unless `delete` is set. */
|
|
61
|
+
readonly write: Permission;
|
|
62
|
+
readonly delete?: Permission;
|
|
63
|
+
};
|
|
64
|
+
type TopicAccess = {
|
|
65
|
+
readonly receive: Permission;
|
|
66
|
+
/** Lets clients send on the topic. */
|
|
67
|
+
readonly send?: Permission;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* A better-supabase bucket `policy` that checks PermDock permissions with
|
|
71
|
+
* the `rls generate` helpers at `scope`. The helpers check role and scope
|
|
72
|
+
* only, so a permission the catalog doesn't mark `rowConditions: false`, or
|
|
73
|
+
* doesn't grant at `scope`, throws.
|
|
74
|
+
*/
|
|
75
|
+
export declare function bucketPolicy(access: BucketAccess, options: AccessPolicyOptions): AccessBucketPolicy;
|
|
76
|
+
/** As {@link bucketPolicy}, for a better-supabase Realtime topic. */
|
|
77
|
+
export declare function topicPolicy(access: TopicAccess, options: AccessPolicyOptions): AccessTopicPolicy;
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/better-supabase/api-keys.d.ts
|
|
80
|
+
/** The roles a tenant key holds in its tenant: a list, or one per key. */
|
|
81
|
+
type ServiceRoles<K> = readonly string[] | ((key: K) => readonly string[]);
|
|
82
|
+
type ApiKeyVerifierOptions = {
|
|
83
|
+
/** `createApiKeys()` over a service transport. */
|
|
84
|
+
readonly keys: Pick<ApiKeys, "verify">;
|
|
85
|
+
/**
|
|
86
|
+
* `permdock.manifest.json`, whose `rls.apiKeys.serviceRoles` is the
|
|
87
|
+
* default for `serviceRoles`.
|
|
88
|
+
*/
|
|
89
|
+
readonly manifest?: unknown;
|
|
90
|
+
/**
|
|
91
|
+
* The roles a tenant key holds in its tenant, as a `service` principal.
|
|
92
|
+
* Without it or a manifest with `rls.apiKeys`, a tenant key verifies to
|
|
93
|
+
* `null`.
|
|
94
|
+
*/
|
|
95
|
+
readonly serviceRoles?: ServiceRoles<ApiKey>;
|
|
96
|
+
/** The permissions `*` stands for. Without it, a key with `*` verifies to `null`. */
|
|
97
|
+
readonly allPermissions?: readonly Permission[];
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* better-supabase's API keys as a `CredentialVerifier`, for
|
|
101
|
+
* `subjectFromApiKey` from `permdock/server`, which reads PermDock's
|
|
102
|
+
* `pdk_<id>_<secret>` format: create the keys with `prefix: "pdk"`. The
|
|
103
|
+
* credential id is the key's `publicId`, the id in the token. A personal key
|
|
104
|
+
* is a `user` credential acting as its user (inside its tenant when the key
|
|
105
|
+
* is limited to one), a tenant key a `service` credential holding
|
|
106
|
+
* `serviceRoles` in its tenant, and the key's scopes are the credential's
|
|
107
|
+
* permissions. better-supabase records the use when it verifies, so there is
|
|
108
|
+
* no `touch`. A rotated key in its grace period verifies, and its credential
|
|
109
|
+
* expires when the grace period ends. An invalid, revoked, expired or
|
|
110
|
+
* rate-limited key, and a failed lookup, are `null`. `permdock/server` exports a different
|
|
111
|
+
* `apiKeyVerifier`, over the application's own key records.
|
|
112
|
+
*/
|
|
113
|
+
export declare function apiKeyVerifier(options: ApiKeyVerifierOptions): CredentialVerifier;
|
|
114
|
+
/**
|
|
115
|
+
* The `claim` and `tenantClaim` options of better-supabase's
|
|
116
|
+
* `apiKeyClaims()`, from the manifest's `rls.apiKeys`, so a key's token
|
|
117
|
+
* carries the scopes ceiling, tenant and roles the `rls generate` helpers
|
|
118
|
+
* read. Throws when the manifest has no `rls.apiKeys`.
|
|
119
|
+
*/
|
|
120
|
+
export declare function apiKeyClaimOptions(manifest: unknown): Pick<ApiKeyClaimsOptions, "claim" | "tenantClaim">;
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/better-supabase/credentials.d.ts
|
|
123
|
+
type CredentialGuardOptions = {
|
|
124
|
+
/** The request's PermDock instance. */
|
|
125
|
+
readonly permdock: () => PermDock | Promise<PermDock>;
|
|
126
|
+
/** The permission that resolves a token or connects an account; decided on the ref. */
|
|
127
|
+
readonly use: Permission;
|
|
128
|
+
/** The permission that revokes a stored credential; defaults to `use`. */
|
|
129
|
+
readonly revoke?: Permission;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* `provider` with every `getToken`, `startAuthorization`,
|
|
133
|
+
* `completeAuthorization` and `revoke` decided by PermDock first, on the
|
|
134
|
+
* `CredentialRef` as the row. Anything but `granted` is a `forbidden`
|
|
135
|
+
* error with hint `PERMDOCK_DENIED`, and a failed check is one too.
|
|
136
|
+
* `capabilities` and `verifyInbound` (a third party's request, with no
|
|
137
|
+
* user) pass through. Build it per request, with that request's PermDock.
|
|
138
|
+
*/
|
|
139
|
+
export declare function credentialGuard(provider: CredentialProvider, options: CredentialGuardOptions): CredentialProvider;
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/better-supabase/mcp.d.ts
|
|
142
|
+
/** What better-supabase's `createMcp` hooks see of a tool. */
|
|
143
|
+
type McpToolRef = Pick<ToolRef, "meta">;
|
|
144
|
+
/** The outcome of better-supabase's `createMcp` `authorize` hook. */
|
|
145
|
+
type McpToolDecision = ToolDecision;
|
|
146
|
+
type ToolPolicyOptions<C> = {
|
|
147
|
+
/** The request's PermDock instance, from the hook's context. */
|
|
148
|
+
readonly permdock: (ctx: C) => PermDock | Promise<PermDock>;
|
|
149
|
+
/**
|
|
150
|
+
* The row an instance permission is decided on, from the validated
|
|
151
|
+
* arguments. Without it the call is decided without a row, which an
|
|
152
|
+
* instance permission with a row condition denies.
|
|
153
|
+
*/
|
|
154
|
+
readonly data?: (ctx: C, tool: McpToolRef, args: unknown) => unknown;
|
|
155
|
+
};
|
|
156
|
+
type ToolPolicy<C> = {
|
|
157
|
+
readonly authorize: (ctx: C, tool: McpToolRef, args: unknown) => Promise<McpToolDecision>;
|
|
158
|
+
readonly visible: (ctx: C, tool: McpToolRef) => Promise<boolean>;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* The `authorize` and `visible` hooks of better-supabase's `createMcp`, for
|
|
162
|
+
* tools whose `meta` is a PermDock permission. A tool without a permission
|
|
163
|
+
* is hidden and refused. `authorize` grants only a `granted` decision: an
|
|
164
|
+
* approval-required call is refused, because `createMcp`
|
|
165
|
+
* has no approval flow. A throw anywhere refuses.
|
|
166
|
+
*/
|
|
167
|
+
export declare function toolPolicy<C>(options: ToolPolicyOptions<C>): ToolPolicy<C>;
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/better-supabase/subject.d.ts
|
|
170
|
+
/** An `AuthSession` of kind `apiKey`, from better-supabase's api-keys middleware. */
|
|
171
|
+
type ApiKeySession = Extract<AuthSession, {
|
|
172
|
+
readonly kind: "apiKey";
|
|
173
|
+
}>;
|
|
174
|
+
type ApiKeySessionOptions = {
|
|
175
|
+
/** The definitions: the key's scopes become the subject's delegation, and `*` stands for all of them. */
|
|
176
|
+
readonly permissions: PermissionTree;
|
|
177
|
+
/** `permdock.manifest.json`, whose `rls.apiKeys.serviceRoles` is the default for `serviceRoles`. */
|
|
178
|
+
readonly manifest?: unknown;
|
|
179
|
+
/** The roles a tenant key holds in its tenant. Without it or a manifest with `rls.apiKeys`, a tenant key is anonymous. */
|
|
180
|
+
readonly serviceRoles?: ServiceRoles<ApiKeySession>;
|
|
181
|
+
};
|
|
182
|
+
/** The claim, and the short code better-supabase writes for each feature key. */
|
|
183
|
+
type FeatureClaim = EntitlementClaimOptions;
|
|
184
|
+
type BetterSupabaseSubjectOptions = Omit<SupabaseSubjectOptions, "plans"> & {
|
|
185
|
+
/** How `kind: 'apiKey'` sessions map. Without it they are anonymous. */
|
|
186
|
+
readonly apiKeys?: ApiKeySessionOptions;
|
|
187
|
+
/**
|
|
188
|
+
* The claim `principal.plans` reads: its name (default `features`), or
|
|
189
|
+
* `{ claim, keys }` with the same `entitlements.claim.keys` better-supabase
|
|
190
|
+
* writes short codes with, so `plans` holds the feature keys. A code
|
|
191
|
+
* without a key is dropped.
|
|
192
|
+
*/
|
|
193
|
+
readonly plans?: string | FeatureClaim;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* `subjectFromSupabaseSession` for better-supabase's `AuthSession`, reading
|
|
197
|
+
* `memberships` for the memberships and the entitlements module's `features`
|
|
198
|
+
* claim for `principal.plans` (`plans` names another claim). With `apiKeys`,
|
|
199
|
+
* a verified `apiKey` session is the key's credential subject: a personal key
|
|
200
|
+
* acts as its user within the key's scopes, a tenant key as a `service`
|
|
201
|
+
* principal holding `serviceRoles`. Without `apiKeys`, and for `anon`,
|
|
202
|
+
* `service` and `invalid` sessions, the subject is anonymous.
|
|
203
|
+
*/
|
|
204
|
+
export declare function subjectFromBetterSupabase(session: SupabaseSessionLike | ApiKeySession | null | undefined, options?: BetterSupabaseSubjectOptions): Subject<SupabasePrincipal> | Subject<CredentialPrincipal> | Subject;
|
|
205
|
+
//#endregion
|
|
206
|
+
export type { AccessPolicyOptions, ApiKeySession, ApiKeySessionOptions, ApiKeyVerifierOptions, AuthorizationProviderOptions, BetterSupabaseSubjectOptions, BucketAccess, CredentialGuardOptions, McpToolDecision, McpToolRef, ServiceRoles, SupabasePrincipal, ToolPolicy, ToolPolicyOptions, TopicAccess };
|