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,369 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
|
|
3
|
+
import { O as readPath, T as isForbiddenKey } from "./permissions-DVoF6dMt.js";
|
|
4
|
+
import { t as ignoreRejection } from "./thenable-okc2xDsj.js";
|
|
5
|
+
import { t as anonymousSubject } from "./subject-C6dLxqHU.js";
|
|
6
|
+
import { t as clientNameOf } from "./clients-DjU5ABMy.js";
|
|
7
|
+
//#region src/jwt/map-claims.ts
|
|
8
|
+
/** OpenID Connect Core section 5.1: profile data the provider owns. */
|
|
9
|
+
const PROFILE_CLAIMS = [
|
|
10
|
+
"name",
|
|
11
|
+
"given_name",
|
|
12
|
+
"family_name",
|
|
13
|
+
"middle_name",
|
|
14
|
+
"nickname",
|
|
15
|
+
"preferred_username",
|
|
16
|
+
"profile",
|
|
17
|
+
"picture",
|
|
18
|
+
"website",
|
|
19
|
+
"email",
|
|
20
|
+
"email_verified",
|
|
21
|
+
"gender",
|
|
22
|
+
"birthdate",
|
|
23
|
+
"zoneinfo",
|
|
24
|
+
"locale",
|
|
25
|
+
"phone_number",
|
|
26
|
+
"phone_number_verified",
|
|
27
|
+
"address",
|
|
28
|
+
"updated_at"
|
|
29
|
+
];
|
|
30
|
+
const DEFAULT_CLAIMS = {
|
|
31
|
+
id: "sub",
|
|
32
|
+
roles: "roles",
|
|
33
|
+
groups: "groups",
|
|
34
|
+
entitlements: "entitlements",
|
|
35
|
+
session: "sid"
|
|
36
|
+
};
|
|
37
|
+
function asStringArray(value) {
|
|
38
|
+
if (typeof value === "string") return value.length === 0 ? [] : value.split(/[,\s]+/u).filter(Boolean);
|
|
39
|
+
if (!Array.isArray(value)) return [];
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const item of value) {
|
|
42
|
+
if (typeof item === "string") {
|
|
43
|
+
out.push(item);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (item !== null && typeof item === "object" && "value" in item && typeof item.value === "string") out.push(item.value);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
function kindOf(claims, paths) {
|
|
51
|
+
const kind = paths?.kind;
|
|
52
|
+
if (kind === "workload" || kind === "user" || kind === "service") return kind;
|
|
53
|
+
if (kind !== void 0) {
|
|
54
|
+
const value = readPath(claims, kind);
|
|
55
|
+
if (value === "workload" || value === "user" || value === "service") return value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function assuranceOf(claims, paths) {
|
|
59
|
+
const configured = paths?.assurance;
|
|
60
|
+
const acrPath = typeof configured === "string" ? configured : configured?.acr ?? "acr";
|
|
61
|
+
const amrPath = typeof configured === "string" ? "amr" : configured?.amr ?? "amr";
|
|
62
|
+
const authTimePath = typeof configured === "string" ? "auth_time" : configured?.authTime ?? "auth_time";
|
|
63
|
+
const verifiedPath = typeof configured === "string" ? "verified_claims" : configured?.verified ?? "verified_claims";
|
|
64
|
+
const acr = readPath(claims, acrPath);
|
|
65
|
+
const amr = readPath(claims, amrPath);
|
|
66
|
+
const authTime = readPath(claims, authTimePath);
|
|
67
|
+
const assurance = compact({
|
|
68
|
+
acr: typeof acr === "string" ? acr : void 0,
|
|
69
|
+
amr: Array.isArray(amr) ? amr.filter((item) => typeof item === "string") : void 0,
|
|
70
|
+
authTime: typeof authTime === "number" ? authTime : void 0,
|
|
71
|
+
verified: verifiedClaimsOf(readPath(claims, verifiedPath))
|
|
72
|
+
});
|
|
73
|
+
return Object.keys(assurance).length === 0 ? void 0 : assurance;
|
|
74
|
+
}
|
|
75
|
+
function isPlainRecord(value) {
|
|
76
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
77
|
+
}
|
|
78
|
+
function hasForbiddenKey(value, depth = 0) {
|
|
79
|
+
if (depth > 16) return true;
|
|
80
|
+
if (Array.isArray(value)) return value.some((item) => hasForbiddenKey(item, depth + 1));
|
|
81
|
+
if (!isPlainRecord(value)) return false;
|
|
82
|
+
return Object.keys(value).some((key) => isForbiddenKey(key) || hasForbiddenKey(value[key], depth + 1));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* `verified_claims` is one object or an array (OIDC4IDA section 5); an entry
|
|
86
|
+
* without `verification.trust_framework` and a `claims` object is dropped.
|
|
87
|
+
*/
|
|
88
|
+
function verifiedClaimsOf(value) {
|
|
89
|
+
const verified = (Array.isArray(value) ? value : [value]).filter((entry) => isPlainRecord(entry) && isPlainRecord(entry["verification"]) && typeof entry["verification"]["trust_framework"] === "string" && isPlainRecord(entry["claims"]) && !hasForbiddenKey(entry));
|
|
90
|
+
return verified.length === 0 ? void 0 : freezeDeep(verified.map((entry) => ({
|
|
91
|
+
verification: entry.verification,
|
|
92
|
+
claims: entry.claims
|
|
93
|
+
})));
|
|
94
|
+
}
|
|
95
|
+
function bindingOf(claims) {
|
|
96
|
+
const cnf = claims["cnf"];
|
|
97
|
+
if (cnf === null || typeof cnf !== "object" || Array.isArray(cnf)) return;
|
|
98
|
+
const record = cnf;
|
|
99
|
+
const binding = compact({
|
|
100
|
+
jkt: typeof record["jkt"] === "string" ? record["jkt"] : void 0,
|
|
101
|
+
"x5t#S256": typeof record["x5t#S256"] === "string" ? record["x5t#S256"] : void 0,
|
|
102
|
+
jwk: record["jwk"] !== null && typeof record["jwk"] === "object" ? record["jwk"] : void 0,
|
|
103
|
+
kid: typeof record["kid"] === "string" ? record["kid"] : void 0
|
|
104
|
+
});
|
|
105
|
+
return Object.keys(binding).length === 0 ? void 0 : binding;
|
|
106
|
+
}
|
|
107
|
+
/** Group roles hold in the active tenant; the group itself is only the `via`. */
|
|
108
|
+
function membershipsFromGroups(groups, groupRoles, tenant) {
|
|
109
|
+
if (tenant === void 0) return [];
|
|
110
|
+
return groups.map((group) => compact({
|
|
111
|
+
tenant,
|
|
112
|
+
roles: groupRoles?.[group] ?? [],
|
|
113
|
+
via: `group:${group}`
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
function stringRecord(value) {
|
|
117
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return;
|
|
118
|
+
const out = {};
|
|
119
|
+
for (const [key, item] of Object.entries(value)) if (typeof item === "string") out[key] = item;
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
function keptKeys(value) {
|
|
123
|
+
if (value === void 0) return;
|
|
124
|
+
if (!Array.isArray(value)) return [];
|
|
125
|
+
const keys = value.filter((key) => typeof key === "string" && key !== "");
|
|
126
|
+
return keys.length === value.length ? keys : [];
|
|
127
|
+
}
|
|
128
|
+
function claimExtras(record) {
|
|
129
|
+
return compact({
|
|
130
|
+
via: typeof record["via"] === "string" ? record["via"] : void 0,
|
|
131
|
+
expiresAt: typeof record["expiresAt"] === "number" ? record["expiresAt"] : void 0,
|
|
132
|
+
keep: keptKeys(record["keep"])
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function membershipsFromClaim(value) {
|
|
136
|
+
if (Array.isArray(value)) return value.flatMap((item) => membershipsFromClaim(item));
|
|
137
|
+
if (value === null || typeof value !== "object") return [];
|
|
138
|
+
const record = value;
|
|
139
|
+
if (typeof record["scope"] === "string" && typeof record["id"] === "string") return [compact({
|
|
140
|
+
scope: record["scope"],
|
|
141
|
+
id: record["id"],
|
|
142
|
+
within: stringRecord(record["within"]),
|
|
143
|
+
roles: asStringArray(record["roles"]),
|
|
144
|
+
...claimExtras(record)
|
|
145
|
+
})];
|
|
146
|
+
if (typeof record["tenant"] === "string" || typeof record["org_id"] === "string") return [compact({
|
|
147
|
+
tenant: typeof record["tenant"] === "string" ? record["tenant"] : String(record["org_id"]),
|
|
148
|
+
roles: asStringArray(record["roles"]),
|
|
149
|
+
team: typeof record["team"] === "string" ? record["team"] : void 0,
|
|
150
|
+
...claimExtras(record)
|
|
151
|
+
})];
|
|
152
|
+
const out = [];
|
|
153
|
+
const byOrganisation = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const [tenant, entry] of Object.entries(record)) {
|
|
155
|
+
if (Array.isArray(entry)) {
|
|
156
|
+
out.push(compact({
|
|
157
|
+
tenant,
|
|
158
|
+
roles: asStringArray(entry)
|
|
159
|
+
}));
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (entry !== null && typeof entry === "object") {
|
|
163
|
+
const nested = entry;
|
|
164
|
+
if (isRoleToOrganisations(nested)) {
|
|
165
|
+
for (const organisation of Object.keys(nested)) {
|
|
166
|
+
const roles = byOrganisation.get(organisation) ?? [];
|
|
167
|
+
roles.push(tenant);
|
|
168
|
+
byOrganisation.set(organisation, roles);
|
|
169
|
+
}
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
out.push(compact({
|
|
173
|
+
tenant,
|
|
174
|
+
roles: asStringArray(nested["roles"] ?? nested)
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const [tenant, roles] of byOrganisation) out.push({
|
|
179
|
+
tenant,
|
|
180
|
+
roles
|
|
181
|
+
});
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
/** Zitadel's `role -> { orgId: orgDomain }` form: string values and no `roles` key. */
|
|
185
|
+
function isRoleToOrganisations(value) {
|
|
186
|
+
const entries = Object.entries(value);
|
|
187
|
+
return entries.length > 0 && !("roles" in value) && entries.every(([key, item]) => typeof item === "string" && !isForbiddenKey(key));
|
|
188
|
+
}
|
|
189
|
+
function isActObject(value) {
|
|
190
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
191
|
+
}
|
|
192
|
+
function actorFromAct(claims, options) {
|
|
193
|
+
const configured = options.actor;
|
|
194
|
+
if (typeof configured === "function") {
|
|
195
|
+
const actor = configured(claims);
|
|
196
|
+
return actor === void 0 ? { status: "absent" } : {
|
|
197
|
+
status: "ok",
|
|
198
|
+
actor,
|
|
199
|
+
chain: claims["act"]
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (!Object.hasOwn(claims, "act") || claims["act"] === void 0) return { status: "absent" };
|
|
203
|
+
const act = claims["act"];
|
|
204
|
+
if (!isActObject(act)) return { status: "invalid" };
|
|
205
|
+
let current = act;
|
|
206
|
+
while (current !== void 0) {
|
|
207
|
+
if (!isActObject(current) || typeof current.sub !== "string" || current.sub.length === 0) return { status: "invalid" };
|
|
208
|
+
current = Object.hasOwn(current, "act") ? current.act : void 0;
|
|
209
|
+
}
|
|
210
|
+
if (typeof act.sub !== "string") return { status: "invalid" };
|
|
211
|
+
return {
|
|
212
|
+
status: "ok",
|
|
213
|
+
actor: compact({
|
|
214
|
+
id: act.sub,
|
|
215
|
+
kind: configured?.kind ?? "oauth-client",
|
|
216
|
+
client: clientNameOf(configured?.clients, act.sub)
|
|
217
|
+
}),
|
|
218
|
+
chain: act
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function delegationOf(claims, options, chain) {
|
|
222
|
+
const paths = options.delegation;
|
|
223
|
+
const scopes = asStringArray(readPath(claims, paths?.scopes ?? "scope"));
|
|
224
|
+
const details = readPath(claims, paths?.authorizationDetails ?? "authorization_details");
|
|
225
|
+
const access = readPath(claims, paths?.access ?? "access");
|
|
226
|
+
const authorizationDetails = Array.isArray(details) ? details : void 0;
|
|
227
|
+
const accessList = Array.isArray(access) ? access : void 0;
|
|
228
|
+
const delegation = compact({
|
|
229
|
+
scopes: scopes.length > 0 ? scopes : void 0,
|
|
230
|
+
authorizationDetails,
|
|
231
|
+
access: accessList,
|
|
232
|
+
chain
|
|
233
|
+
});
|
|
234
|
+
return Object.keys(delegation).length === 0 ? void 0 : delegation;
|
|
235
|
+
}
|
|
236
|
+
function customClaims(claims, reserved) {
|
|
237
|
+
const out = {};
|
|
238
|
+
for (const [key, value] of Object.entries(claims)) {
|
|
239
|
+
if (reserved.includes(key)) continue;
|
|
240
|
+
out[key] = value;
|
|
241
|
+
}
|
|
242
|
+
return out;
|
|
243
|
+
}
|
|
244
|
+
function validateCustomClaims(claims, schema) {
|
|
245
|
+
const result = schema["~standard"].validate(claims);
|
|
246
|
+
if (result instanceof Promise) {
|
|
247
|
+
ignoreRejection(result);
|
|
248
|
+
return { ok: false };
|
|
249
|
+
}
|
|
250
|
+
if ("issues" in result && result.issues !== void 0) return { ok: false };
|
|
251
|
+
return {
|
|
252
|
+
ok: true,
|
|
253
|
+
value: result.value
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function mapClaimsToSubject(claims, options) {
|
|
257
|
+
const paths = options.claims;
|
|
258
|
+
const idPath = paths?.id ?? DEFAULT_CLAIMS.id;
|
|
259
|
+
const id = readPath(claims, idPath);
|
|
260
|
+
if (typeof id !== "string" || id.length === 0) return {
|
|
261
|
+
subject: anonymousSubject(),
|
|
262
|
+
invalidClaims: false,
|
|
263
|
+
invalidChain: false
|
|
264
|
+
};
|
|
265
|
+
const tenantPath = paths?.tenant;
|
|
266
|
+
const tenant = tenantPath === void 0 ? void 0 : readPath(claims, tenantPath);
|
|
267
|
+
const activeTenant = typeof tenant === "string" ? tenant : void 0;
|
|
268
|
+
const roles = asStringArray(readPath(claims, paths?.roles ?? DEFAULT_CLAIMS.roles));
|
|
269
|
+
const plans = asStringArray(readPath(claims, paths?.plans ?? paths?.entitlements ?? DEFAULT_CLAIMS.entitlements));
|
|
270
|
+
const groups = asStringArray(readPath(claims, paths?.groups ?? DEFAULT_CLAIMS.groups));
|
|
271
|
+
const memberships = [...membershipsFromClaim(paths?.memberships === void 0 ? void 0 : readPath(claims, paths.memberships)), ...membershipsFromGroups(groups, options.groupRoles, activeTenant)];
|
|
272
|
+
let extra = customClaims(claims, [
|
|
273
|
+
"iss",
|
|
274
|
+
"sub",
|
|
275
|
+
"aud",
|
|
276
|
+
"exp",
|
|
277
|
+
"nbf",
|
|
278
|
+
"iat",
|
|
279
|
+
"jti",
|
|
280
|
+
"client_id",
|
|
281
|
+
"scope",
|
|
282
|
+
"cnf",
|
|
283
|
+
"act",
|
|
284
|
+
"sid",
|
|
285
|
+
"acr",
|
|
286
|
+
"amr",
|
|
287
|
+
"auth_time",
|
|
288
|
+
"roles",
|
|
289
|
+
"groups",
|
|
290
|
+
"entitlements",
|
|
291
|
+
"authorization_details",
|
|
292
|
+
"access",
|
|
293
|
+
"nonce",
|
|
294
|
+
"azp",
|
|
295
|
+
...PROFILE_CLAIMS
|
|
296
|
+
]);
|
|
297
|
+
let invalidClaims = false;
|
|
298
|
+
if (options.schema !== void 0) {
|
|
299
|
+
const validated = validateCustomClaims(extra, options.schema);
|
|
300
|
+
if (validated.ok) extra = validated.value;
|
|
301
|
+
else {
|
|
302
|
+
extra = {};
|
|
303
|
+
invalidClaims = true;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const binding = bindingOf(claims);
|
|
307
|
+
const act = actorFromAct(claims, options);
|
|
308
|
+
if (act.status === "invalid") return {
|
|
309
|
+
subject: anonymousSubject(),
|
|
310
|
+
invalidClaims: false,
|
|
311
|
+
invalidChain: true
|
|
312
|
+
};
|
|
313
|
+
const principal = freezeDeep(compact({
|
|
314
|
+
id,
|
|
315
|
+
issuer: typeof claims.iss === "string" ? claims.iss : void 0,
|
|
316
|
+
kind: kindOf(claims, paths),
|
|
317
|
+
roles: roles.length > 0 ? roles : void 0,
|
|
318
|
+
plans: plans.length > 0 ? plans : void 0,
|
|
319
|
+
memberships: memberships.length > 0 ? memberships : void 0,
|
|
320
|
+
tenant: activeTenant,
|
|
321
|
+
assurance: assuranceOf(claims, paths),
|
|
322
|
+
binding: act.status === "absent" ? binding : void 0,
|
|
323
|
+
claims: Object.keys(extra).length === 0 ? void 0 : extra
|
|
324
|
+
}));
|
|
325
|
+
const actor = act.status === "absent" ? void 0 : freezeDeep(compact({
|
|
326
|
+
...act.actor,
|
|
327
|
+
binding
|
|
328
|
+
}));
|
|
329
|
+
const sessionPath = paths?.session ?? DEFAULT_CLAIMS.session;
|
|
330
|
+
const sessionValue = readPath(claims, sessionPath);
|
|
331
|
+
const sessionExpiry = claims["session_expiry"];
|
|
332
|
+
const exp = typeof claims.exp === "number" ? claims.exp : void 0;
|
|
333
|
+
const expiresAt = typeof sessionExpiry === "number" && exp !== void 0 ? Math.min(exp, sessionExpiry) : exp;
|
|
334
|
+
return {
|
|
335
|
+
subject: freezeDeep(compact({
|
|
336
|
+
principal,
|
|
337
|
+
actor,
|
|
338
|
+
delegation: options.accept === "id-token" ? void 0 : delegationOf(claims, options, act.status === "ok" ? act.chain : void 0),
|
|
339
|
+
context: {},
|
|
340
|
+
session: typeof sessionValue === "string" ? sessionValue : void 0,
|
|
341
|
+
expiresAt
|
|
342
|
+
})),
|
|
343
|
+
invalidClaims,
|
|
344
|
+
invalidChain: false
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function acceptMismatch(claims, headerTyp, options, audience) {
|
|
348
|
+
const accept = options.accept ?? "access-token";
|
|
349
|
+
const typ = headerTyp?.toLowerCase();
|
|
350
|
+
if (accept === "id-token") {
|
|
351
|
+
if (typ !== void 0 && typ !== "jwt" && typ !== "application/jwt") return true;
|
|
352
|
+
if (typeof claims.iat !== "number") return true;
|
|
353
|
+
const aud = claims.aud;
|
|
354
|
+
const audiences = Array.isArray(aud) ? aud : aud === void 0 ? [] : [aud];
|
|
355
|
+
const clients = audience === void 0 ? [] : typeof audience === "string" ? [audience] : audience;
|
|
356
|
+
const azp = claims["azp"];
|
|
357
|
+
if (azp === void 0) return audiences.length > 1;
|
|
358
|
+
return typeof azp !== "string" || !clients.includes(azp);
|
|
359
|
+
}
|
|
360
|
+
if (options.profile === "fapi2" && typ !== "at+jwt") return true;
|
|
361
|
+
if (typeof claims["nonce"] === "string") return true;
|
|
362
|
+
if (audience !== void 0 && typeof claims.aud === "string") {
|
|
363
|
+
const expected = typeof audience === "string" ? audience : audience[0];
|
|
364
|
+
if (claims.aud !== expected && typ !== "at+jwt") return true;
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
//#endregion
|
|
369
|
+
export { mapClaimsToSubject as n, validateCustomClaims as r, acceptMismatch as t };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { n as PermDockValidationError } from "./validation-error-CnjZ4t92.js";
|
|
3
|
+
import { n as PermDockDeniedError, r as PermDockRevokedError, t as PermDockApprovalRequiredError } from "./errors-Cz5zn0mW.js";
|
|
4
|
+
import { r as decisionResponse, s as problemResponse } from "./problem-B43ztKIm.js";
|
|
5
|
+
import { r as InvalidSignatureError } from "./evaluations-tz6D9A2G.js";
|
|
6
|
+
//#region src/server/map-error.ts
|
|
7
|
+
/**
|
|
8
|
+
* Turns a thrown PermDock error into its Problem Details response, with the
|
|
9
|
+
* status, `WWW-Authenticate` and rate-limit fields `protect` sends for the
|
|
10
|
+
* same decision. Returns `undefined` for anything else so the framework's own
|
|
11
|
+
* error path takes over.
|
|
12
|
+
*/
|
|
13
|
+
function problemFromError(error, options = {}) {
|
|
14
|
+
if (error instanceof InvalidSignatureError) return error.response;
|
|
15
|
+
if (error instanceof PermDockDeniedError || error instanceof PermDockApprovalRequiredError) return decisionResponse(error.toProblemDetails(compact({ instance: options.instance })), error.decision, compact({
|
|
16
|
+
scope: error.scope,
|
|
17
|
+
credentials: options.credentials
|
|
18
|
+
}));
|
|
19
|
+
if (error instanceof PermDockRevokedError) return problemResponse(error.toProblemDetails(), void 0, error.decision);
|
|
20
|
+
if (error instanceof PermDockValidationError) return problemResponse(error.toProblemDetails(compact({ instance: options.instance })));
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { problemFromError as t };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//#region src/cli/markers.ts
|
|
2
|
+
const HOOK_MARKER = "-- permdock:hook v1";
|
|
3
|
+
/** The first line of a `--grants-out` file. */
|
|
4
|
+
const GRANTS_MARKER = "-- permdock:grants v1";
|
|
5
|
+
/** The first line of the `seeds` part: the `role_permissions` rows, a versioned migration. */
|
|
6
|
+
const SEEDS_MARKER = "-- permdock:seeds v1";
|
|
7
|
+
/** The first line of the `indexes` part: the indexes the policies and helpers read through. */
|
|
8
|
+
const INDEXES_MARKER = "-- permdock:indexes v1";
|
|
9
|
+
const HOOK_LINE = /^-- permdock:hook v(?<version>[1-9]\d*)(?: (?<rest>.*))?$/u;
|
|
10
|
+
const GRANTS_LINE = /^-- permdock:grants v(?<version>[1-9]\d*)(?: (?<rest>.*))?$/u;
|
|
11
|
+
function firstLine(sql) {
|
|
12
|
+
return (sql.split("\n", 1)[0] ?? "").replace(/\r$/u, "");
|
|
13
|
+
}
|
|
14
|
+
/** The `key=value` pairs after the marker, in a prototype-less object. */
|
|
15
|
+
function pairs(rest) {
|
|
16
|
+
const fields = Object.create(null);
|
|
17
|
+
for (const pair of (rest ?? "").split(" ")) {
|
|
18
|
+
const eq = pair.indexOf("=");
|
|
19
|
+
if (eq > 0) fields[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
20
|
+
}
|
|
21
|
+
return fields;
|
|
22
|
+
}
|
|
23
|
+
/** The fields of a hook marker line, or undefined when `sql` does not start with one. */
|
|
24
|
+
function hookMarkerFields(sql) {
|
|
25
|
+
const line = firstLine(sql);
|
|
26
|
+
return line.startsWith(`-- permdock:hook v1 `) ? pairs(line.slice(20)) : void 0;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Reads the `-- permdock:hook v<N>` line that starts a generated hook
|
|
30
|
+
* migration. Undefined when the first line is not a hook marker.
|
|
31
|
+
*/
|
|
32
|
+
function parseHookMarker(sql) {
|
|
33
|
+
const match = HOOK_LINE.exec(firstLine(sql));
|
|
34
|
+
if (match?.groups === void 0) return;
|
|
35
|
+
const fields = pairs(match.groups["rest"]);
|
|
36
|
+
const budget = Number(fields["budget"]);
|
|
37
|
+
const claims = fields["claims"];
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
version: Number(match.groups["version"]),
|
|
40
|
+
...fields["schema"] === void 0 ? {} : { schema: fields["schema"] },
|
|
41
|
+
...fields["tenant"] === void 0 ? {} : { tenantClaim: fields["tenant"] },
|
|
42
|
+
...Number.isSafeInteger(budget) && budget > 0 ? { budget } : {},
|
|
43
|
+
claims: Object.freeze(claims === void 0 || claims === "" ? [] : claims.split(",").filter((name) => name !== ""))
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Reads the `-- permdock:grants v<N>` line that starts a `--grants-out`
|
|
48
|
+
* migration. Undefined when the first line is not a grants marker.
|
|
49
|
+
*/
|
|
50
|
+
function parseGrantsMarker(sql) {
|
|
51
|
+
const match = GRANTS_LINE.exec(firstLine(sql));
|
|
52
|
+
if (match?.groups === void 0) return;
|
|
53
|
+
const fields = pairs(match.groups["rest"]);
|
|
54
|
+
return Object.freeze({
|
|
55
|
+
version: Number(match.groups["version"]),
|
|
56
|
+
...fields["schema"] === void 0 ? {} : { schema: fields["schema"] }
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { hookMarkerFields as a, SEEDS_MARKER as i, HOOK_MARKER as n, parseGrantsMarker as o, INDEXES_MARKER as r, parseHookMarker as s, GRANTS_MARKER as t };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { d as scopeList, m as tenantOf, o as resolveScope } from "./scopes-CVdPrWN-.js";
|
|
2
|
+
import { a as isMembershipExpired, t as isActive, u as nowSeconds } from "./validity-uOp8UpYn.js";
|
|
3
|
+
import { t as coveredByDelegation } from "./delegation-D8pUEuce.js";
|
|
4
|
+
//#region src/core/may-use.ts
|
|
5
|
+
function delegationMayCover(permission, delegation, hasActor) {
|
|
6
|
+
return [void 0, ...[...delegation?.access ?? [], ...delegation?.authorizationDetails ?? []].flatMap((entry) => typeof entry === "object" && entry !== null && typeof entry["identifier"] === "string" ? [entry["identifier"]] : [])].some((id) => coveredByDelegation(permission, delegation, id, hasActor) === void 0);
|
|
7
|
+
}
|
|
8
|
+
function blocksEveryRow(grant) {
|
|
9
|
+
return grant.effect === "deny" && grant.where === void 0 && grant.check === void 0 && grant.portable !== false && grant.fields === void 0 && (grant.scope === void 0 || grant.scope === "tenant");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Whether `permission` could be granted to this instance's subject for some
|
|
13
|
+
* row: the grants its snapshot carries for the active tenant, minus an
|
|
14
|
+
* unconditional deny, within its delegation. A listing hint for tools and
|
|
15
|
+
* skills, never a decision; the call itself is decided in full.
|
|
16
|
+
*/
|
|
17
|
+
function mayUse(permdock, permission) {
|
|
18
|
+
try {
|
|
19
|
+
const snapshot = permdock.snapshot();
|
|
20
|
+
if (!("grants" in snapshot)) return false;
|
|
21
|
+
const ceiling = snapshot.delegated;
|
|
22
|
+
if (ceiling !== void 0 && !ceiling.includes(permission.key)) return false;
|
|
23
|
+
if (!delegationMayCover(permission, permdock.subject.delegation, permdock.subject.actor !== void 0 && ceiling === void 0)) return false;
|
|
24
|
+
const tenant = permdock.subject.principal?.tenant;
|
|
25
|
+
const scopes = scopeList(snapshot.scopes);
|
|
26
|
+
const grants = snapshot.grants.filter((grant) => {
|
|
27
|
+
if (grant.permission !== permission.key) return false;
|
|
28
|
+
const owner = grant.membership === void 0 ? void 0 : tenantOf(grant.membership, scopes);
|
|
29
|
+
return owner === void 0 || owner === tenant;
|
|
30
|
+
});
|
|
31
|
+
if (grants.some(blocksEveryRow)) return false;
|
|
32
|
+
return grants.some((grant) => grant.effect === "allow");
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isConditioned(grant) {
|
|
38
|
+
return grant.where !== void 0 || grant.check !== void 0 || grant.validity !== void 0 || grant.portable === false;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The instances of `scope` in which the subject holds `permission`, from its
|
|
42
|
+
* live memberships of exactly that scope, within its delegation: by default
|
|
43
|
+
* those with an allow that carries no row condition (`where`, `check`, a
|
|
44
|
+
* validity window or a non-portable test; a `fields` limit is not a row
|
|
45
|
+
* condition), minus the instances any deny of the permission reaches. The
|
|
46
|
+
* in-process mirror of the SQL `permitted_<scope>_ids_by_permission`. With
|
|
47
|
+
* `conditioned: true` it also lists the instances where a conditioned allow
|
|
48
|
+
* applies, minus only unconditional denies, as
|
|
49
|
+
* `permitted_<scope>_ids_by_permission(p_permission, true)` does. A listing,
|
|
50
|
+
* never a decision: a row's own check still runs `can`.
|
|
51
|
+
*/
|
|
52
|
+
function permittedIds(permdock, permission, scope, options = {}) {
|
|
53
|
+
try {
|
|
54
|
+
const snapshot = permdock.snapshot({ tenants: "all" });
|
|
55
|
+
if (!("grants" in snapshot)) return [];
|
|
56
|
+
const scopes = scopeList(snapshot.scopes);
|
|
57
|
+
const name = resolveScope(scopes, scope);
|
|
58
|
+
const ceiling = snapshot.delegated;
|
|
59
|
+
if (name === void 0 || ceiling !== void 0 && !ceiling.includes(permission.key) || !delegationMayCover(permission, permdock.subject.delegation, permdock.subject.actor !== void 0 && ceiling === void 0)) return [];
|
|
60
|
+
const conditioned = options.conditioned === true;
|
|
61
|
+
const now = nowSeconds();
|
|
62
|
+
const allowed = /* @__PURE__ */ new Set();
|
|
63
|
+
const denied = /* @__PURE__ */ new Set();
|
|
64
|
+
for (const grant of snapshot.grants) {
|
|
65
|
+
const membership = grant.membership;
|
|
66
|
+
if (grant.permission !== permission.key || grant.scope !== name || membership?.scope !== name || membership.id === void 0 || isMembershipExpired(membership, now) || options.within !== void 0 && tenantOf(membership, scopes) !== options.within) continue;
|
|
67
|
+
if (grant.effect === "deny") {
|
|
68
|
+
if (!conditioned || !isConditioned(grant)) denied.add(membership.id);
|
|
69
|
+
} else if ((conditioned || !isConditioned(grant)) && isActive(grant.validity, now)) allowed.add(membership.id);
|
|
70
|
+
}
|
|
71
|
+
return [...allowed].filter((id) => !denied.has(id)).toSorted();
|
|
72
|
+
} catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { permittedIds as n, mayUse as t };
|