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,404 @@
|
|
|
1
|
+
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
+
import { n as freezeDeep } from "../freeze-CrU8nQeX.js";
|
|
3
|
+
import { T as isForbiddenKey } from "../permissions-DVoF6dMt.js";
|
|
4
|
+
import { i as parsePolicyDocument } from "../hosted-DJQw46hn.js";
|
|
5
|
+
import { t as CLOUD_EVENT_TYPES } from "../sink-Bd9PSyfq.js";
|
|
6
|
+
import { r as isApprovalErrorCode, t as ApprovalError } from "../errors-DRnGZHzF.js";
|
|
7
|
+
import { t as joseTokenVerifier } from "../verifier-BxBo6I44.js";
|
|
8
|
+
import { t as timeoutSignal } from "../timeout-D51niuQP.js";
|
|
9
|
+
//#region src/cloud/create.ts
|
|
10
|
+
/** Milliseconds a PermDock Cloud request may take; a slower one fails like an unreachable Cloud. */
|
|
11
|
+
const CLOUD_TIMEOUT_MS = 1e4;
|
|
12
|
+
function readEnv(name) {
|
|
13
|
+
const value = globalThis.process?.env?.[name];
|
|
14
|
+
return typeof value === "string" ? value : "";
|
|
15
|
+
}
|
|
16
|
+
function firstNonEmpty(...values) {
|
|
17
|
+
for (const value of values) if (value !== void 0 && value !== "") return value;
|
|
18
|
+
return "";
|
|
19
|
+
}
|
|
20
|
+
function trimSlash(value) {
|
|
21
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
22
|
+
}
|
|
23
|
+
function isRecord$1(value) {
|
|
24
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function asApproval(value) {
|
|
27
|
+
if (!isRecord$1(value) || value["v"] !== 1 || typeof value["token"] !== "string") return null;
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
function isCompactJws$1(value) {
|
|
31
|
+
return !value.startsWith("{") && value.split(".").length === 3;
|
|
32
|
+
}
|
|
33
|
+
/** The refusal PermDock Cloud names in its body, else the one its status implies. */
|
|
34
|
+
async function approvalErrorFrom(response) {
|
|
35
|
+
let body;
|
|
36
|
+
try {
|
|
37
|
+
body = await response.json();
|
|
38
|
+
} catch {
|
|
39
|
+
return approvalErrorFromStatus(response.status);
|
|
40
|
+
}
|
|
41
|
+
if (body === null || typeof body !== "object" || !("code" in body)) return approvalErrorFromStatus(response.status);
|
|
42
|
+
const code = body.code;
|
|
43
|
+
if (!isApprovalErrorCode(code)) return approvalErrorFromStatus(response.status);
|
|
44
|
+
const detail = "detail" in body ? body.detail : void 0;
|
|
45
|
+
return new ApprovalError(code, typeof detail === "string" && detail.length > 0 ? detail : code);
|
|
46
|
+
}
|
|
47
|
+
function approvalErrorFromStatus(status) {
|
|
48
|
+
if (status === 409) return new ApprovalError("approval-not-pending", "approval is not pending");
|
|
49
|
+
if (status === 410) return new ApprovalError("approval-expired", "approval has expired");
|
|
50
|
+
return new ApprovalError("approval-not-found", "approval was not found");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The environment URL and JWK Set URL `cloud()` uses, resolved with the same
|
|
54
|
+
* fallbacks (`PERMDOCK_CLOUD_URL`; `PERMDOCK_CLOUD_ENV`, `VERCEL_ENV`, `production`).
|
|
55
|
+
*/
|
|
56
|
+
function cloudEndpoints(options = {}) {
|
|
57
|
+
const url = trimSlash(firstNonEmpty(options.url, readEnv("PERMDOCK_CLOUD_URL")));
|
|
58
|
+
if (url === "") throw new Error("PermDock: cloud() requires url and key.");
|
|
59
|
+
const environment = firstNonEmpty(options.environment, readEnv("PERMDOCK_CLOUD_ENV"), readEnv("VERCEL_ENV"), "production");
|
|
60
|
+
const issuer = `${url}/v1/environments/${encodeURIComponent(environment)}`;
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
issuer,
|
|
63
|
+
jwks: `${issuer}/.well-known/jwks.json`
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function cloud(options = {}) {
|
|
67
|
+
const key = firstNonEmpty(options.key, readEnv("PERMDOCK_CLOUD_KEY"));
|
|
68
|
+
if (key === "") throw new Error("PermDock: cloud() requires url and key.");
|
|
69
|
+
const { issuer: root, jwks } = cloudEndpoints(options);
|
|
70
|
+
const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
71
|
+
const flushAt = options.flushAt ?? 32;
|
|
72
|
+
const waitUntil = options.waitUntil;
|
|
73
|
+
const headers = () => {
|
|
74
|
+
const next = new Headers();
|
|
75
|
+
next.set("authorization", `Bearer ${key}`);
|
|
76
|
+
next.set("content-type", "application/json");
|
|
77
|
+
return next;
|
|
78
|
+
};
|
|
79
|
+
const request = (path, init = {}, accept) => {
|
|
80
|
+
const next = headers();
|
|
81
|
+
if (accept !== void 0) next.set("accept", accept);
|
|
82
|
+
return fetchFn(`${root}${path}`, {
|
|
83
|
+
...init,
|
|
84
|
+
headers: next,
|
|
85
|
+
signal: timeoutSignal(CLOUD_TIMEOUT_MS, init.signal)
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const approvals = {
|
|
89
|
+
async create(record) {
|
|
90
|
+
if (!(await request("/approvals", {
|
|
91
|
+
method: "POST",
|
|
92
|
+
body: JSON.stringify(record)
|
|
93
|
+
})).ok) throw new Error("PermDock Cloud rejected the approval create");
|
|
94
|
+
},
|
|
95
|
+
async get(token) {
|
|
96
|
+
try {
|
|
97
|
+
const response = await request(`/approvals/${encodeURIComponent(token)}`);
|
|
98
|
+
if (!response.ok) return null;
|
|
99
|
+
return asApproval(await response.json());
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
async resolve(token, verdict) {
|
|
105
|
+
const response = await request(`/approvals/${encodeURIComponent(token)}/resolve`, {
|
|
106
|
+
method: "POST",
|
|
107
|
+
body: JSON.stringify(verdict)
|
|
108
|
+
});
|
|
109
|
+
if (!response.ok) throw await approvalErrorFrom(response);
|
|
110
|
+
const parsed = asApproval(await response.json());
|
|
111
|
+
if (parsed === null) throw new ApprovalError("approval-not-found", "PermDock Cloud returned an unknown approval shape");
|
|
112
|
+
return parsed;
|
|
113
|
+
},
|
|
114
|
+
async consume(token, now) {
|
|
115
|
+
try {
|
|
116
|
+
const response = await request(`/approvals/${encodeURIComponent(token)}/consume`, {
|
|
117
|
+
method: "POST",
|
|
118
|
+
body: JSON.stringify(compact({ now: now === void 0 ? void 0 : now.toISOString() }))
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok) return null;
|
|
121
|
+
return asApproval(await response.json());
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
async list(query) {
|
|
127
|
+
const params = new URLSearchParams(compact({
|
|
128
|
+
status: query.status,
|
|
129
|
+
principalId: query.principalId,
|
|
130
|
+
actorId: query.actorId,
|
|
131
|
+
tenant: query.tenant,
|
|
132
|
+
session: query.session,
|
|
133
|
+
limit: query.limit === void 0 ? void 0 : String(query.limit),
|
|
134
|
+
cursor: query.cursor
|
|
135
|
+
}));
|
|
136
|
+
const suffix = params.size === 0 ? "" : `?${params.toString()}`;
|
|
137
|
+
try {
|
|
138
|
+
const response = await request(`/approvals${suffix}`);
|
|
139
|
+
if (!response.ok) return { items: [] };
|
|
140
|
+
const body = await response.json();
|
|
141
|
+
if (!isRecord$1(body) || !Array.isArray(body["items"])) return { items: [] };
|
|
142
|
+
const items = body["items"].flatMap((item) => {
|
|
143
|
+
const parsed = asApproval(item);
|
|
144
|
+
return parsed === null ? [] : [parsed];
|
|
145
|
+
});
|
|
146
|
+
return typeof body["next"] === "string" && body["next"] !== "" ? {
|
|
147
|
+
items,
|
|
148
|
+
next: body["next"]
|
|
149
|
+
} : { items };
|
|
150
|
+
} catch {
|
|
151
|
+
return { items: [] };
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
async cancel(filter, meta) {
|
|
155
|
+
const response = await request("/approvals/cancel", {
|
|
156
|
+
method: "POST",
|
|
157
|
+
body: JSON.stringify(compact({
|
|
158
|
+
filter,
|
|
159
|
+
by: meta.by,
|
|
160
|
+
note: meta.note
|
|
161
|
+
}))
|
|
162
|
+
});
|
|
163
|
+
if (!response.ok) throw new Error("PermDock Cloud rejected the approval cancel");
|
|
164
|
+
const body = await response.json();
|
|
165
|
+
if (!isRecord$1(body) || typeof body["cancelled"] !== "number") throw new Error("PermDock Cloud returned an unknown cancel shape");
|
|
166
|
+
return body["cancelled"];
|
|
167
|
+
},
|
|
168
|
+
async expire(now) {
|
|
169
|
+
try {
|
|
170
|
+
const response = await request("/approvals/expire", {
|
|
171
|
+
method: "POST",
|
|
172
|
+
body: JSON.stringify(compact({ now: now === void 0 ? void 0 : now.toISOString() }))
|
|
173
|
+
});
|
|
174
|
+
if (!response.ok) return 0;
|
|
175
|
+
const body = await response.json();
|
|
176
|
+
if (!isRecord$1(body) || typeof body["expired"] !== "number") return 0;
|
|
177
|
+
return body["expired"];
|
|
178
|
+
} catch {
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const capacity = options.capacity ?? 1e4;
|
|
184
|
+
const pending = [];
|
|
185
|
+
const bound = () => {
|
|
186
|
+
if (pending.length > capacity) pending.splice(0, pending.length - capacity);
|
|
187
|
+
};
|
|
188
|
+
const flush = async () => {
|
|
189
|
+
if (pending.length === 0) return;
|
|
190
|
+
const events = pending.splice(0);
|
|
191
|
+
try {
|
|
192
|
+
if (!(await request("/decisions", {
|
|
193
|
+
method: "POST",
|
|
194
|
+
body: JSON.stringify({ events })
|
|
195
|
+
})).ok) pending.unshift(...events);
|
|
196
|
+
} catch {
|
|
197
|
+
pending.unshift(...events);
|
|
198
|
+
}
|
|
199
|
+
bound();
|
|
200
|
+
};
|
|
201
|
+
const sink = {
|
|
202
|
+
write(events) {
|
|
203
|
+
pending.push(...events);
|
|
204
|
+
bound();
|
|
205
|
+
if (pending.length >= flushAt) return flush();
|
|
206
|
+
if (waitUntil !== void 0 && pending.length > 0) waitUntil(flush());
|
|
207
|
+
},
|
|
208
|
+
flush
|
|
209
|
+
};
|
|
210
|
+
const snapshots = { async get() {
|
|
211
|
+
const response = await request("/snapshot", {}, "application/jwt");
|
|
212
|
+
if (!response.ok) throw new Error("PermDock Cloud snapshot request failed");
|
|
213
|
+
const text = (await response.text()).trim();
|
|
214
|
+
if (!isCompactJws$1(text)) throw new Error("PermDock Cloud served an unsigned snapshot");
|
|
215
|
+
return text;
|
|
216
|
+
} };
|
|
217
|
+
let document = null;
|
|
218
|
+
return freezeDeep({
|
|
219
|
+
approvals,
|
|
220
|
+
sink,
|
|
221
|
+
snapshots,
|
|
222
|
+
policies: {
|
|
223
|
+
current() {
|
|
224
|
+
return document;
|
|
225
|
+
},
|
|
226
|
+
async refresh() {
|
|
227
|
+
const verifier = options.verifier;
|
|
228
|
+
if (verifier === void 0) return;
|
|
229
|
+
let response;
|
|
230
|
+
try {
|
|
231
|
+
response = await request("/policy");
|
|
232
|
+
} catch {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (response.status === 404) {
|
|
236
|
+
document = null;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!response.ok) return;
|
|
240
|
+
const token = (await response.text()).trim();
|
|
241
|
+
if (!isCompactJws$1(token)) return;
|
|
242
|
+
const verified = await verifier.verify(token, {
|
|
243
|
+
typ: "permdock-policy+jwt",
|
|
244
|
+
issuer: root,
|
|
245
|
+
audience: root
|
|
246
|
+
});
|
|
247
|
+
if (!verified.ok) return;
|
|
248
|
+
let next;
|
|
249
|
+
try {
|
|
250
|
+
next = parsePolicyDocument(verified.claims["policy"]);
|
|
251
|
+
} catch {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
document = next;
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
issuer: root,
|
|
258
|
+
jwks
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/cloud/webhook.ts
|
|
263
|
+
const TYPES = new Set(Object.values(CLOUD_EVENT_TYPES));
|
|
264
|
+
function isRecord(value) {
|
|
265
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
266
|
+
}
|
|
267
|
+
function hasUnsafeKey(value) {
|
|
268
|
+
if (Array.isArray(value)) return value.some(hasUnsafeKey);
|
|
269
|
+
if (!isRecord(value)) return false;
|
|
270
|
+
return Object.keys(value).some((key) => isForbiddenKey(key) || hasUnsafeKey(value[key]));
|
|
271
|
+
}
|
|
272
|
+
const FINDING_CODES = /* @__PURE__ */ new Set([
|
|
273
|
+
"permission-removed",
|
|
274
|
+
"not-hostable",
|
|
275
|
+
"grantee-removed",
|
|
276
|
+
"approval-tightened"
|
|
277
|
+
]);
|
|
278
|
+
function isFinding(value) {
|
|
279
|
+
return isRecord(value) && FINDING_CODES.has(value["code"]) && typeof value["permission"] === "string" && (value["grant"] === void 0 || typeof value["grant"] === "string");
|
|
280
|
+
}
|
|
281
|
+
function validData(type, data) {
|
|
282
|
+
switch (type) {
|
|
283
|
+
case "dev.permdock.decision": return data["type"] === "decision" && typeof data["permission"] === "string";
|
|
284
|
+
case "dev.permdock.approval": return data["type"] === "decision" && (data["phase"] === "requested" || data["phase"] === "resolved");
|
|
285
|
+
case "dev.permdock.directory": return data["type"] === "directory" && typeof data["tenant"] === "string";
|
|
286
|
+
case "dev.permdock.membership": return data["type"] === "membership" && isRecord(data["principal"]);
|
|
287
|
+
case "dev.permdock.credential": return data["type"] === "credential" && isRecord(data["credential"]) && typeof data["credential"]["id"] === "string" && (data["credential"]["kind"] === "user" || data["credential"]["kind"] === "service") && isRecord(data["principal"]) && (data["operation"] === "created" || data["operation"] === "used" || data["operation"] === "rotated" || data["operation"] === "revoked");
|
|
288
|
+
case "dev.permdock.catalog": return (data["kind"] === "publish" || data["kind"] === "drift") && typeof data["fingerprint"] === "string" && (data["previous"] === void 0 || typeof data["previous"] === "string") && (data["findings"] === void 0 || Array.isArray(data["findings"]) && data["findings"].every(isFinding));
|
|
289
|
+
case "dev.permdock.access.started":
|
|
290
|
+
case "dev.permdock.access.ended":
|
|
291
|
+
case "dev.permdock.access.revoked": return data["type"] === "access" && typeof data["tenant"] === "string" && isRecord(data["principal"]) && typeof data["principal"]["id"] === "string";
|
|
292
|
+
default: return type;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Validates one CloudEvent against the closed type list and its data shape;
|
|
297
|
+
* returns `null` for anything else, never throws.
|
|
298
|
+
*/
|
|
299
|
+
function parseCloudEvent(value) {
|
|
300
|
+
if (!isRecord(value) || hasUnsafeKey(value) || value["specversion"] !== "1.0" || typeof value["type"] !== "string" || !TYPES.has(value["type"]) || typeof value["source"] !== "string" || typeof value["id"] !== "string" || typeof value["time"] !== "string" || value["subject"] !== void 0 && typeof value["subject"] !== "string" || !isRecord(value["data"]) || !validData(value["type"], value["data"])) return null;
|
|
301
|
+
return freezeDeep(JSON.parse(JSON.stringify(value)));
|
|
302
|
+
}
|
|
303
|
+
function verifierFor(options) {
|
|
304
|
+
if (options.verifier !== void 0) return options.verifier;
|
|
305
|
+
if (options.jwks === void 0) return;
|
|
306
|
+
try {
|
|
307
|
+
return joseTokenVerifier({
|
|
308
|
+
jwks: typeof options.jwks === "string" ? new URL(options.jwks) : options.jwks,
|
|
309
|
+
algorithms: ["Ed25519", "ES256"]
|
|
310
|
+
});
|
|
311
|
+
} catch {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function isCompactJws(value) {
|
|
316
|
+
return /^[\w-]+\.[\w-]+\.[\w-]+$/u.test(value);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Verifies a PermDock Cloud webhook delivery: a compact JWS with
|
|
320
|
+
* `typ: permdock-decisions+jwt` whose `events` claim holds CloudEvents.
|
|
321
|
+
* There is no unsigned mode, and it never throws.
|
|
322
|
+
*/
|
|
323
|
+
async function verifyWebhook(request, options) {
|
|
324
|
+
let body;
|
|
325
|
+
try {
|
|
326
|
+
body = (await request.text()).trim();
|
|
327
|
+
} catch {
|
|
328
|
+
return {
|
|
329
|
+
ok: false,
|
|
330
|
+
reason: "unsigned"
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
if (!isCompactJws(body)) return {
|
|
334
|
+
ok: false,
|
|
335
|
+
reason: "unsigned"
|
|
336
|
+
};
|
|
337
|
+
const verifier = verifierFor(options);
|
|
338
|
+
if (verifier === void 0) return {
|
|
339
|
+
ok: false,
|
|
340
|
+
reason: "invalid-token",
|
|
341
|
+
cause: "jwks-unavailable"
|
|
342
|
+
};
|
|
343
|
+
let verified;
|
|
344
|
+
try {
|
|
345
|
+
verified = await verifier.verify(body, {
|
|
346
|
+
typ: "permdock-decisions+jwt",
|
|
347
|
+
audience: options.audience
|
|
348
|
+
});
|
|
349
|
+
} catch {
|
|
350
|
+
return {
|
|
351
|
+
ok: false,
|
|
352
|
+
reason: "invalid-token",
|
|
353
|
+
cause: "malformed"
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
if (!verified.ok) return {
|
|
357
|
+
ok: false,
|
|
358
|
+
reason: "invalid-token",
|
|
359
|
+
cause: verified.cause
|
|
360
|
+
};
|
|
361
|
+
const jti = verified.claims["jti"];
|
|
362
|
+
const raw = verified.claims["events"];
|
|
363
|
+
if (typeof jti !== "string" || !Array.isArray(raw)) return {
|
|
364
|
+
ok: false,
|
|
365
|
+
reason: "invalid-events"
|
|
366
|
+
};
|
|
367
|
+
const events = [];
|
|
368
|
+
for (const item of raw) {
|
|
369
|
+
const parsed = parseCloudEvent(item);
|
|
370
|
+
if (parsed === null) return {
|
|
371
|
+
ok: false,
|
|
372
|
+
reason: "invalid-events"
|
|
373
|
+
};
|
|
374
|
+
events.push(parsed);
|
|
375
|
+
}
|
|
376
|
+
if (options.replay !== void 0) {
|
|
377
|
+
const key = `permdock-webhook:${jti}`;
|
|
378
|
+
const expiresAt = typeof verified.claims.exp === "number" ? verified.claims.exp : void 0;
|
|
379
|
+
try {
|
|
380
|
+
if (options.replay.claim === void 0) {
|
|
381
|
+
if (await options.replay.seen(key)) return {
|
|
382
|
+
ok: false,
|
|
383
|
+
reason: "replayed"
|
|
384
|
+
};
|
|
385
|
+
await options.replay.remember(key, expiresAt);
|
|
386
|
+
} else if (!await options.replay.claim(key, expiresAt)) return {
|
|
387
|
+
ok: false,
|
|
388
|
+
reason: "replayed"
|
|
389
|
+
};
|
|
390
|
+
} catch {
|
|
391
|
+
return {
|
|
392
|
+
ok: false,
|
|
393
|
+
reason: "replayed"
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return freezeDeep({
|
|
398
|
+
ok: true,
|
|
399
|
+
id: jti,
|
|
400
|
+
events
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
//#endregion
|
|
404
|
+
export { cloud, cloudEndpoints, parseCloudEvent, verifyWebhook };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { i as globalArgs, s as stringArg, t as COMMAND_DESCRIPTIONS } from "./commands-DWOrSQic.js";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
//#region src/cli/commands/cloud.ts
|
|
4
|
+
function cloud(ctx) {
|
|
5
|
+
return defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "cloud",
|
|
8
|
+
description: COMMAND_DESCRIPTIONS.cloud
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
...globalArgs,
|
|
12
|
+
action: {
|
|
13
|
+
type: "positional",
|
|
14
|
+
required: false,
|
|
15
|
+
description: "push"
|
|
16
|
+
},
|
|
17
|
+
"dry-run": {
|
|
18
|
+
type: "boolean",
|
|
19
|
+
description: "Print the payload; send nothing"
|
|
20
|
+
},
|
|
21
|
+
url: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Cloud API base URL",
|
|
24
|
+
valueHint: "url"
|
|
25
|
+
},
|
|
26
|
+
environment: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Target environment",
|
|
29
|
+
valueHint: "env"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
async run({ args: parsed }) {
|
|
33
|
+
const result = await (await import("./cloud-Bo3e9Ak3.js")).runCloud({
|
|
34
|
+
cwd: ctx.cwd,
|
|
35
|
+
config: ctx.config,
|
|
36
|
+
rest: parsed._,
|
|
37
|
+
url: stringArg(parsed.url),
|
|
38
|
+
environment: stringArg(parsed.environment),
|
|
39
|
+
dryRun: parsed["dry-run"] === true,
|
|
40
|
+
json: ctx.json,
|
|
41
|
+
env: ctx.io.env ?? process.env,
|
|
42
|
+
now: ctx.now,
|
|
43
|
+
io: ctx.io
|
|
44
|
+
});
|
|
45
|
+
ctx.report(result);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { cloud };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { t as catalogFingerprint } from "./src-CSbUiozF.js";
|
|
2
|
+
import { s as snapshotScopes } from "./permdock-CzqXjCpU.js";
|
|
3
|
+
import { i as describeError } from "./errors-CWfoNg9N.js";
|
|
4
|
+
import { i as loadConfiguredPolicy } from "./load-DhWEB9P1.js";
|
|
5
|
+
import { t as parseCatalog } from "./parse-BuyjxhZV.js";
|
|
6
|
+
import { t as runCatalog } from "./catalog-z8q6bi_r.js";
|
|
7
|
+
//#region src/cli/cloud.ts
|
|
8
|
+
function firstNonEmpty(...values) {
|
|
9
|
+
for (const value of values) if (value !== void 0 && value !== "") return value;
|
|
10
|
+
return "";
|
|
11
|
+
}
|
|
12
|
+
function pushedGrant(grant) {
|
|
13
|
+
const entry = {
|
|
14
|
+
permission: grant.permission.key,
|
|
15
|
+
effect: grant.effect,
|
|
16
|
+
role: grant.role,
|
|
17
|
+
to: grant.to,
|
|
18
|
+
where: grant.portable ? grant.where : void 0,
|
|
19
|
+
check: grant.portable ? grant.check : void 0,
|
|
20
|
+
approval: grant.approval,
|
|
21
|
+
scope: grant.scope === "global" ? void 0 : typeof grant.scope === "string" ? grant.scope : { resource: grant.scope.resource },
|
|
22
|
+
portable: grant.portable ? void 0 : false,
|
|
23
|
+
fields: grant.fields,
|
|
24
|
+
limit: grant.limit
|
|
25
|
+
};
|
|
26
|
+
return Object.fromEntries(Object.entries(entry).filter(([, value]) => value !== void 0));
|
|
27
|
+
}
|
|
28
|
+
/** The code policy as the hosted AuthZEN endpoint evaluates it; closures travel as `portable: false` and deny there. */
|
|
29
|
+
function pushedPolicy(policy) {
|
|
30
|
+
const scopes = snapshotScopes(policy);
|
|
31
|
+
return {
|
|
32
|
+
fingerprint: policy.fingerprint,
|
|
33
|
+
...scopes === void 0 ? {} : { scopes },
|
|
34
|
+
grants: policy.grants.filter((grant) => grant.hosted === void 0).map(pushedGrant)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function runCloud(input) {
|
|
38
|
+
if (input.rest[0] !== "push") return {
|
|
39
|
+
code: 2,
|
|
40
|
+
output: `usage: permdock cloud push [--dry-run] [--url <url>] [--environment <env>]`
|
|
41
|
+
};
|
|
42
|
+
const built = await runCatalog({
|
|
43
|
+
cwd: input.cwd,
|
|
44
|
+
config: input.config,
|
|
45
|
+
format: "json",
|
|
46
|
+
from: void 0,
|
|
47
|
+
include: [],
|
|
48
|
+
now: input.now,
|
|
49
|
+
io: input.io
|
|
50
|
+
});
|
|
51
|
+
if (built.code !== 0) return {
|
|
52
|
+
code: built.code,
|
|
53
|
+
output: built.output
|
|
54
|
+
};
|
|
55
|
+
const catalog = parseCatalog(built.output);
|
|
56
|
+
const fingerprint = catalogFingerprint(catalog);
|
|
57
|
+
const loaded = await loadConfiguredPolicy(input.cwd, input.config.policy);
|
|
58
|
+
const policy = loaded === void 0 ? void 0 : pushedPolicy(loaded);
|
|
59
|
+
const hostable = catalog.permissions.filter((permission) => permission.hostable === true).map((permission) => permission.key);
|
|
60
|
+
const summary = {
|
|
61
|
+
fingerprint,
|
|
62
|
+
permissions: catalog.permissions.length,
|
|
63
|
+
hostable,
|
|
64
|
+
roles: (catalog.roles ?? []).length,
|
|
65
|
+
plans: (catalog.plans ?? []).length,
|
|
66
|
+
grants: policy?.grants.length ?? 0
|
|
67
|
+
};
|
|
68
|
+
const url = firstNonEmpty(input.url, input.env["PERMDOCK_CLOUD_URL"]).replace(/\/$/u, "");
|
|
69
|
+
const environment = firstNonEmpty(input.environment, input.env["PERMDOCK_CLOUD_ENV"], input.env["VERCEL_ENV"], "production");
|
|
70
|
+
const describe = (verb) => input.json ? JSON.stringify({
|
|
71
|
+
...summary,
|
|
72
|
+
environment,
|
|
73
|
+
status: verb
|
|
74
|
+
}) : `${verb} catalog ${fingerprint} (${String(summary.permissions)} permissions, ${String(hostable.length)} hostable) to ${environment}`;
|
|
75
|
+
if (input.dryRun) return {
|
|
76
|
+
code: 0,
|
|
77
|
+
output: describe("would push")
|
|
78
|
+
};
|
|
79
|
+
const key = input.env["PERMDOCK_CLOUD_KEY"] ?? "";
|
|
80
|
+
if (url === "" || key === "") return {
|
|
81
|
+
code: 2,
|
|
82
|
+
output: "permdock cloud push needs PERMDOCK_CLOUD_URL (or --url) and PERMDOCK_CLOUD_KEY in the environment"
|
|
83
|
+
};
|
|
84
|
+
const fetchFn = input.io.fetch ?? globalThis.fetch.bind(globalThis);
|
|
85
|
+
let response;
|
|
86
|
+
try {
|
|
87
|
+
response = await fetchFn(`${url}/v1/environments/${encodeURIComponent(environment)}/catalog`, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
authorization: `Bearer ${key}`,
|
|
91
|
+
"content-type": "application/json"
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify(policy === void 0 ? {
|
|
94
|
+
fingerprint,
|
|
95
|
+
catalog
|
|
96
|
+
} : {
|
|
97
|
+
fingerprint,
|
|
98
|
+
catalog,
|
|
99
|
+
policy
|
|
100
|
+
})
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
return {
|
|
104
|
+
code: 1,
|
|
105
|
+
output: `PermDock Cloud unreachable: ${describeError(error)}`
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (!response.ok) return {
|
|
109
|
+
code: 1,
|
|
110
|
+
output: `PermDock Cloud rejected the catalog: HTTP ${String(response.status)}`
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
code: 0,
|
|
114
|
+
output: describe("pushed")
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { runCloud };
|