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,33 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
//#region src/core/validation-error.ts
|
|
3
|
+
/** The base of every Problem Details `type` URI; defined here so a validation error does not pull in the Problem Details builders. */
|
|
4
|
+
const PROBLEM_BASE = "https://permdock.com/problems";
|
|
5
|
+
var PermDockValidationError = class extends Error {
|
|
6
|
+
name = "PermDockValidationError";
|
|
7
|
+
code;
|
|
8
|
+
permission;
|
|
9
|
+
resource;
|
|
10
|
+
issues;
|
|
11
|
+
boundary;
|
|
12
|
+
constructor(input) {
|
|
13
|
+
super(input.message);
|
|
14
|
+
this.code = input.code;
|
|
15
|
+
this.permission = input.permission;
|
|
16
|
+
this.resource = input.resource;
|
|
17
|
+
this.issues = input.issues ?? [];
|
|
18
|
+
this.boundary = input.boundary;
|
|
19
|
+
}
|
|
20
|
+
toProblemDetails(options) {
|
|
21
|
+
return compact({
|
|
22
|
+
type: `${PROBLEM_BASE}/validation`,
|
|
23
|
+
title: "Invalid resource data",
|
|
24
|
+
status: 400,
|
|
25
|
+
detail: this.message,
|
|
26
|
+
instance: options?.instance,
|
|
27
|
+
permission: this.permission,
|
|
28
|
+
issues: this.issues
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PermDockValidationError as n, PROBLEM_BASE as t };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { a as ProblemDetails } from "./errors-DAqevpNk.js";
|
|
2
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
//#region src/core/validation-error.d.ts
|
|
4
|
+
/** The base of every Problem Details `type` URI; defined here so a validation error does not pull in the Problem Details builders. */
|
|
5
|
+
declare const PROBLEM_BASE = "https://permdock.com/problems";
|
|
6
|
+
declare class PermDockValidationError extends Error {
|
|
7
|
+
override readonly name: "PermDockValidationError";
|
|
8
|
+
readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
|
|
9
|
+
readonly permission: string;
|
|
10
|
+
readonly resource: string;
|
|
11
|
+
readonly issues: readonly StandardSchemaV1.Issue[];
|
|
12
|
+
readonly boundary: string;
|
|
13
|
+
constructor(input: {
|
|
14
|
+
readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
|
|
15
|
+
readonly permission: string;
|
|
16
|
+
readonly resource: string;
|
|
17
|
+
readonly issues?: readonly StandardSchemaV1.Issue[];
|
|
18
|
+
readonly boundary: string;
|
|
19
|
+
readonly message: string;
|
|
20
|
+
});
|
|
21
|
+
toProblemDetails(options?: {
|
|
22
|
+
readonly instance?: string;
|
|
23
|
+
}): ProblemDetails;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { PermDockValidationError as n, PROBLEM_BASE as t };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { f as isFieldRelation } from "./permissions-DVoF6dMt.js";
|
|
2
|
+
import { t as expiredAt } from "./expiry-BoBJ8Tvc.js";
|
|
3
|
+
import { n as sameId } from "./ids-DC4V4CFu.js";
|
|
4
|
+
import { c as rootScope, l as scopeChain, m as tenantOf, o as resolveScope, r as findScope, t as activeFor, u as scopeIdOf } from "./scopes-CVdPrWN-.js";
|
|
5
|
+
//#region src/core/tenancy.ts
|
|
6
|
+
function nowSeconds(now) {
|
|
7
|
+
return now ?? Date.now() / 1e3;
|
|
8
|
+
}
|
|
9
|
+
function isMembershipExpired(membership, now) {
|
|
10
|
+
return expiredAt(membership, now ?? nowSeconds());
|
|
11
|
+
}
|
|
12
|
+
/** The instances of the first scope the subject holds a live membership in. */
|
|
13
|
+
function tenantsOf(principal, scopes, now) {
|
|
14
|
+
if (principal === null) return [];
|
|
15
|
+
const tenants = /* @__PURE__ */ new Set();
|
|
16
|
+
for (const membership of principal.memberships ?? []) {
|
|
17
|
+
if (isMembershipExpired(membership, now)) continue;
|
|
18
|
+
const tenant = tenantOf(membership, scopes);
|
|
19
|
+
if (tenant !== void 0) tenants.add(tenant);
|
|
20
|
+
}
|
|
21
|
+
return [...tenants];
|
|
22
|
+
}
|
|
23
|
+
function heldRoleNamesIn(principal, scopes, tenant, now) {
|
|
24
|
+
const names = /* @__PURE__ */ new Set();
|
|
25
|
+
for (const membership of principal?.memberships ?? []) if (!isMembershipExpired(membership, now) && membership.keep === void 0 && tenantOf(membership, scopes) === tenant) for (const name of membership.roles) names.add(name);
|
|
26
|
+
return [...names];
|
|
27
|
+
}
|
|
28
|
+
/** `requested` when a live membership sits in that instance of the first scope; never a default. */
|
|
29
|
+
function resolveActiveTenant(principal, requested, scopes, now) {
|
|
30
|
+
if (requested === void 0) return principal.tenant;
|
|
31
|
+
return (principal.memberships ?? []).some((membership) => !isMembershipExpired(membership, now) && tenantOf(membership, scopes) === requested) ? requested : void 0;
|
|
32
|
+
}
|
|
33
|
+
/** `permdock.team(id)`: only memberships inside that instance of the second scope. */
|
|
34
|
+
function inTeam(membership, scopes, team) {
|
|
35
|
+
if (team === void 0) return true;
|
|
36
|
+
const second = scopes[1]?.name;
|
|
37
|
+
return second !== void 0 && scopeIdOf(membership, second) === team;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether `resource` declares a `memberOf` relation to `scope` on `field`:
|
|
41
|
+
* its rows are partitioned by that scope, so a row without the field matches
|
|
42
|
+
* no membership.
|
|
43
|
+
*/
|
|
44
|
+
function relatesTo(resource, field, scope, scopes) {
|
|
45
|
+
if (resource === void 0) return false;
|
|
46
|
+
return Object.values(resource.relations).some((relation) => isFieldRelation(relation) && relation.field === field && relation.memberOf !== void 0 && resolveScope(scopes, relation.memberOf) === scope);
|
|
47
|
+
}
|
|
48
|
+
/** The fields of `resource`'s `memberOf` relations to `scope`. */
|
|
49
|
+
function memberOfFields(resource, scope, scopes) {
|
|
50
|
+
return [...new Set(Object.values(resource.relations).flatMap((relation) => isFieldRelation(relation) && relation.memberOf !== void 0 && resolveScope(scopes, relation.memberOf) === scope ? [relation.field] : []))];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The field of `resource` that holds `scope`'s instance id: the scope's
|
|
54
|
+
* `key` when one of the resource's `memberOf` relations names it, otherwise
|
|
55
|
+
* the field of its one `memberOf` relation to the scope. A table whose own
|
|
56
|
+
* id is the instance (`organizations.id`) declares
|
|
57
|
+
* `{ self: { field: 'id', memberOf: 'organization' } }`.
|
|
58
|
+
*/
|
|
59
|
+
function scopeField(resource, scope, scopes) {
|
|
60
|
+
const key = findScope(scopes, scope)?.key;
|
|
61
|
+
if (resource === void 0) return key;
|
|
62
|
+
const fields = memberOfFields(resource, scope, scopes);
|
|
63
|
+
if (key !== void 0 && fields.includes(key)) return key;
|
|
64
|
+
return fields.length === 1 ? fields[0] : key;
|
|
65
|
+
}
|
|
66
|
+
/** The scopes that partition `resource`, from its `memberOf` relations. */
|
|
67
|
+
function partitionsOf(resource, scopes) {
|
|
68
|
+
return scopes.filter((scope) => {
|
|
69
|
+
const field = scopeField(resource, scope.name, scopes);
|
|
70
|
+
return field !== void 0 && relatesTo(resource, field, scope.name, scopes);
|
|
71
|
+
}).map((scope) => scope.name);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Whether `row` lies inside a named membership's instance: for the scope and
|
|
75
|
+
* each ancestor, outermost first, a row that carries the scope's key (or whose
|
|
76
|
+
* resource declares it) must hold the membership's id for it. There is no
|
|
77
|
+
* cascade: the membership's own scope is checked, never a scope below it.
|
|
78
|
+
*/
|
|
79
|
+
function rowInScope(membership, scopes, row, partitioned, fieldOf) {
|
|
80
|
+
if (membership.scope === void 0 || row === null || typeof row !== "object") return { ok: true };
|
|
81
|
+
const root = rootScope(scopes);
|
|
82
|
+
const chain = scopeChain(scopes, membership.scope).toReversed();
|
|
83
|
+
for (const name of chain) {
|
|
84
|
+
const key = fieldOf?.(name) ?? findScope(scopes, name)?.key;
|
|
85
|
+
if (key === void 0) continue;
|
|
86
|
+
const value = Object.hasOwn(row, key) ? row[key] : void 0;
|
|
87
|
+
if ((value !== void 0 || partitioned(name, key)) && !sameId(value, scopeIdOf(membership, name))) return {
|
|
88
|
+
ok: false,
|
|
89
|
+
reason: name === root ? "tenant-mismatch" : "scope"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return { ok: true };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Whether a membership answers an instance check for `row`: any membership
|
|
96
|
+
* with a row object, otherwise only the first scope or the instance of the
|
|
97
|
+
* second scope that `team(id)` selected.
|
|
98
|
+
*/
|
|
99
|
+
function nestedAppliesWithoutRow(membership, scopes, row, team) {
|
|
100
|
+
if (row !== null && typeof row === "object") return true;
|
|
101
|
+
return membership.scope === rootScope(scopes) || team !== void 0 && membership.scope === scopes[1]?.name;
|
|
102
|
+
}
|
|
103
|
+
function matchScopedMembership(subject, scope, roleName, row, scopes, resource, resources, now, rolesOf = (membership) => membership.roles, team, walk, instance = false, only) {
|
|
104
|
+
if (scope === "global") return { ok: true };
|
|
105
|
+
if (only !== void 0 && scope !== only) return {
|
|
106
|
+
ok: false,
|
|
107
|
+
reason: "scope"
|
|
108
|
+
};
|
|
109
|
+
const principal = subject.principal;
|
|
110
|
+
if (principal === null) return {
|
|
111
|
+
ok: false,
|
|
112
|
+
reason: "no-membership"
|
|
113
|
+
};
|
|
114
|
+
const memberships = principal.memberships ?? [];
|
|
115
|
+
const root = rootScope(scopes);
|
|
116
|
+
let sawExpired = false;
|
|
117
|
+
let sawWrongScope = false;
|
|
118
|
+
let sawTenantMismatch = false;
|
|
119
|
+
let sawGraph;
|
|
120
|
+
for (const membership of memberships) {
|
|
121
|
+
if (!rolesOf(membership).includes(roleName)) continue;
|
|
122
|
+
if (isMembershipExpired(membership, now)) {
|
|
123
|
+
sawExpired = true;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (typeof scope === "string") {
|
|
127
|
+
if (findScope(scopes, scope) === void 0 || membership.scope !== scope || !inTeam(membership, scopes, team) || !activeFor(membership, scopes, principal.tenant)) continue;
|
|
128
|
+
if (instance && !nestedAppliesWithoutRow(membership, scopes, row, team)) {
|
|
129
|
+
sawWrongScope = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const inside = rowInScope(membership, scopes, row, (name, key) => relatesTo(resource, key, name, scopes), (name) => scopeField(resource, name, scopes));
|
|
133
|
+
if (!inside.ok) {
|
|
134
|
+
if (inside.reason === "tenant-mismatch") sawTenantMismatch = true;
|
|
135
|
+
else sawWrongScope = true;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
ok: true,
|
|
140
|
+
membership
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (membership.on === void 0) continue;
|
|
144
|
+
if (matchResourceMembership(membership, scope.resource, row, resource, resources)) return {
|
|
145
|
+
ok: true,
|
|
146
|
+
membership
|
|
147
|
+
};
|
|
148
|
+
const walked = walk !== void 0 && (membership.on.resource === scope.resource || membershipField(resources.get(scope.resource), membership.on.resource, resources) !== void 0) ? walk(membership, row) : false;
|
|
149
|
+
if (walked === true) return {
|
|
150
|
+
ok: true,
|
|
151
|
+
membership
|
|
152
|
+
};
|
|
153
|
+
if (walked !== false) sawGraph ??= walked;
|
|
154
|
+
sawWrongScope = true;
|
|
155
|
+
}
|
|
156
|
+
if (sawGraph !== void 0) return {
|
|
157
|
+
ok: false,
|
|
158
|
+
reason: sawGraph
|
|
159
|
+
};
|
|
160
|
+
if (scope === root && principal.tenant !== void 0 && !memberships.some((membership) => tenantOf(membership, scopes) === principal.tenant && !isMembershipExpired(membership, now))) return {
|
|
161
|
+
ok: false,
|
|
162
|
+
reason: "no-membership"
|
|
163
|
+
};
|
|
164
|
+
if (sawTenantMismatch) return {
|
|
165
|
+
ok: false,
|
|
166
|
+
reason: "tenant-mismatch"
|
|
167
|
+
};
|
|
168
|
+
if (sawExpired && !sawWrongScope) return {
|
|
169
|
+
ok: false,
|
|
170
|
+
reason: "expired-membership"
|
|
171
|
+
};
|
|
172
|
+
if (sawWrongScope) return {
|
|
173
|
+
ok: false,
|
|
174
|
+
reason: "scope"
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
ok: false,
|
|
178
|
+
reason: "no-membership"
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function matchResourceMembership(membership, roleResource, row, resource, resources) {
|
|
182
|
+
const on = membership.on;
|
|
183
|
+
if (on === void 0)
|
|
184
|
+
/* v8 ignore next */
|
|
185
|
+
return false;
|
|
186
|
+
if (row === null || typeof row !== "object") return false;
|
|
187
|
+
if (on.resource !== roleResource && membershipField(resources.get(roleResource), on.resource, resources) === void 0) return false;
|
|
188
|
+
const field = membershipField(resource, on.resource, resources);
|
|
189
|
+
return field !== void 0 && sameId(row[field], on.id);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The row field that holds the id of a `membershipResource` membership: the
|
|
193
|
+
* row's own id field when the row is of that resource, the declared parent
|
|
194
|
+
* field of the matching ancestor otherwise (the row carries it, never a
|
|
195
|
+
* walk-up query), `undefined` when the resource is not on the row's chain.
|
|
196
|
+
*/
|
|
197
|
+
function membershipField(resource, membershipResource, resources) {
|
|
198
|
+
if (resource === void 0) return;
|
|
199
|
+
if (resource.name === membershipResource) return resource.id ?? "id";
|
|
200
|
+
let current = resource;
|
|
201
|
+
const seen = /* @__PURE__ */ new Set();
|
|
202
|
+
while (current?.parent !== void 0 && !seen.has(current.name)) {
|
|
203
|
+
seen.add(current.name);
|
|
204
|
+
if (current.parent.resource === membershipResource) return current.parent.field;
|
|
205
|
+
current = resources.get(current.parent.resource);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/core/validity.ts
|
|
210
|
+
/**
|
|
211
|
+
* An instant as Unix seconds: a finite number is taken as seconds already, a
|
|
212
|
+
* string must parse as RFC 3339. Anything else is `undefined`, and the caller
|
|
213
|
+
* decides whether that is "absent" or an error.
|
|
214
|
+
*/
|
|
215
|
+
function instantOf(input) {
|
|
216
|
+
if (typeof input === "number") return Number.isFinite(input) ? Math.floor(input) : void 0;
|
|
217
|
+
if (typeof input !== "string" || input.trim() === "") return;
|
|
218
|
+
const millis = Date.parse(input);
|
|
219
|
+
return Number.isFinite(millis) ? Math.floor(millis / 1e3) : void 0;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The normalised validity of a grant, or `undefined` when neither bound is
|
|
223
|
+
* set. Fail-closed at definition time: a bound that does not parse, or a
|
|
224
|
+
* window that ends before it starts, throws so a typo never widens a grant.
|
|
225
|
+
*/
|
|
226
|
+
function normalizeValidity(options, permissionKey) {
|
|
227
|
+
const from = options.validFrom === void 0 ? void 0 : instantOf(options.validFrom);
|
|
228
|
+
const until = options.validUntil === void 0 ? void 0 : instantOf(options.validUntil);
|
|
229
|
+
if (options.validFrom !== void 0 && from === void 0) throw new Error(`PermDock: validFrom on '${permissionKey}' must be an RFC 3339 string or Unix seconds`);
|
|
230
|
+
if (options.validUntil !== void 0 && until === void 0) throw new Error(`PermDock: validUntil on '${permissionKey}' must be an RFC 3339 string or Unix seconds`);
|
|
231
|
+
if (from !== void 0 && until !== void 0 && until <= from) throw new Error(`PermDock: validUntil on '${permissionKey}' must be after validFrom`);
|
|
232
|
+
if (from === void 0 && until === void 0) return;
|
|
233
|
+
return Object.freeze({
|
|
234
|
+
...from === void 0 ? {} : { from },
|
|
235
|
+
...until === void 0 ? {} : { until }
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/** Whether a grant with this validity applies at `now` (Unix seconds); no validity always applies. */
|
|
239
|
+
function isActive(validity, now) {
|
|
240
|
+
if (validity === void 0) return true;
|
|
241
|
+
if (validity.from !== void 0 && now < validity.from) return false;
|
|
242
|
+
return validity.until === void 0 || now < validity.until;
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
export { isMembershipExpired as a, membershipField as c, partitionsOf as d, relatesTo as f, tenantsOf as g, scopeField as h, inTeam as i, nestedAppliesWithoutRow as l, rowInScope as m, normalizeValidity as n, matchScopedMembership as o, resolveActiveTenant as p, heldRoleNamesIn as r, memberOfFields as s, isActive as t, nowSeconds as u };
|