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,224 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { t as PROBLEM_BASE } from "./validation-error-CnjZ4t92.js";
|
|
3
|
+
import { s as rootMembershipId } from "./scopes-CVdPrWN-.js";
|
|
4
|
+
import { n as isApprovalError } from "./errors-DRnGZHzF.js";
|
|
5
|
+
import { n as hasCredentials } from "./http-SO7qGttf.js";
|
|
6
|
+
import { l as unauthenticatedProblem } from "./problem-B43ztKIm.js";
|
|
7
|
+
import { n as assertApprover } from "./store-DMAWwAJV.js";
|
|
8
|
+
import { m as approverRelations, p as heldPermissions } from "./helpers-H_KARDVC.js";
|
|
9
|
+
//#region src/approvals/handler.ts
|
|
10
|
+
function problem(status, title, detail, slug) {
|
|
11
|
+
const body = {
|
|
12
|
+
type: `${PROBLEM_BASE}/${slug}`,
|
|
13
|
+
title,
|
|
14
|
+
status,
|
|
15
|
+
detail
|
|
16
|
+
};
|
|
17
|
+
return new Response(JSON.stringify(body), {
|
|
18
|
+
status,
|
|
19
|
+
headers: { "content-type": "application/problem+json" }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function json(status, body) {
|
|
23
|
+
return new Response(JSON.stringify(body), {
|
|
24
|
+
status,
|
|
25
|
+
headers: { "content-type": "application/json" }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function parseRoute(url, method) {
|
|
29
|
+
const parts = url.pathname.replace(/\/+$/u, "").split("/").filter(Boolean);
|
|
30
|
+
const last = parts.at(-1);
|
|
31
|
+
const prev = parts.at(-2);
|
|
32
|
+
if (last === void 0) return;
|
|
33
|
+
if (method === "GET" && last === "pending") return { kind: "pending" };
|
|
34
|
+
if (method === "GET" && last === "mine") return { kind: "mine" };
|
|
35
|
+
if (method === "POST" && last === "approve" && prev !== void 0) return {
|
|
36
|
+
kind: "approve",
|
|
37
|
+
token: decodeURIComponent(prev)
|
|
38
|
+
};
|
|
39
|
+
if (method === "POST" && last === "reject" && prev !== void 0) return {
|
|
40
|
+
kind: "reject",
|
|
41
|
+
token: decodeURIComponent(prev)
|
|
42
|
+
};
|
|
43
|
+
if (method === "GET" && last !== "pending" && last !== "mine") return {
|
|
44
|
+
kind: "get",
|
|
45
|
+
token: decodeURIComponent(last)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function resolveSubject(request, resolve) {
|
|
49
|
+
try {
|
|
50
|
+
const subject = await resolve(request);
|
|
51
|
+
if (subject === null || subject === void 0) return null;
|
|
52
|
+
return subject;
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function membershipTenants(subject) {
|
|
58
|
+
const principal = subject.principal;
|
|
59
|
+
if (principal === null) return [];
|
|
60
|
+
const tenants = /* @__PURE__ */ new Set();
|
|
61
|
+
if (principal.tenant !== void 0) tenants.add(principal.tenant);
|
|
62
|
+
for (const membership of principal.memberships ?? []) {
|
|
63
|
+
const tenant = rootMembershipId(membership);
|
|
64
|
+
if (tenant !== void 0) tenants.add(tenant);
|
|
65
|
+
}
|
|
66
|
+
return [...tenants];
|
|
67
|
+
}
|
|
68
|
+
function belongsToTenant(subject, tenant) {
|
|
69
|
+
return membershipTenants(subject).includes(tenant);
|
|
70
|
+
}
|
|
71
|
+
async function mayResolve(request, subject, requireDistinct, options) {
|
|
72
|
+
try {
|
|
73
|
+
const relations = await approverRelations(request, subject, options);
|
|
74
|
+
const permissions = await heldPermissions(request, subject, options.permdockFor);
|
|
75
|
+
assertApprover(request, subject, requireDistinct, /* @__PURE__ */ new Date(), relations, permissions);
|
|
76
|
+
return true;
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function canView(request, subject) {
|
|
82
|
+
const principal = subject.principal;
|
|
83
|
+
if (principal === null) return false;
|
|
84
|
+
if (request.subject.principal?.id === principal.id) return true;
|
|
85
|
+
const tenant = request.subject.principal?.tenant;
|
|
86
|
+
if (tenant !== void 0) return belongsToTenant(subject, tenant);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The tenants whose pending requests the approver may list: the requested one,
|
|
91
|
+
* else the active one, else every membership tenant. Requests without a tenant
|
|
92
|
+
* are listed only when no tenant was requested or active.
|
|
93
|
+
*/
|
|
94
|
+
function pageQuery(url) {
|
|
95
|
+
const limit = url.searchParams.get("limit");
|
|
96
|
+
const cursor = url.searchParams.get("cursor");
|
|
97
|
+
return compact({
|
|
98
|
+
limit: limit === null ? void 0 : Number(limit),
|
|
99
|
+
cursor: cursor ?? void 0
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function inboxScope(url, subject) {
|
|
103
|
+
const requested = url.searchParams.get("tenant");
|
|
104
|
+
if (requested !== null && requested !== "") {
|
|
105
|
+
if (!belongsToTenant(subject, requested)) return { ok: false };
|
|
106
|
+
return {
|
|
107
|
+
ok: true,
|
|
108
|
+
tenants: [requested],
|
|
109
|
+
tenantless: false
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const active = subject.principal?.tenant;
|
|
113
|
+
if (active !== void 0) return {
|
|
114
|
+
ok: true,
|
|
115
|
+
tenants: [active],
|
|
116
|
+
tenantless: false
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
ok: true,
|
|
120
|
+
tenants: membershipTenants(subject),
|
|
121
|
+
tenantless: true
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function signedApproval(request, signer, audience) {
|
|
125
|
+
if (signer === void 0 || request.status !== "approved") return Promise.resolve(void 0);
|
|
126
|
+
const payload = { approval: {
|
|
127
|
+
token: request.token,
|
|
128
|
+
permission: request.permission,
|
|
129
|
+
resource: request.resource,
|
|
130
|
+
status: request.status
|
|
131
|
+
} };
|
|
132
|
+
if (request.subject.principal !== null) payload["sub"] = request.subject.principal.id;
|
|
133
|
+
return signer.sign(payload, compact({
|
|
134
|
+
typ: "permdock-approval+jwt",
|
|
135
|
+
audience,
|
|
136
|
+
expiresAt: Math.floor(Date.parse(request.expiresAt) / 1e3)
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
async function readNote(request) {
|
|
140
|
+
const contentType = request.headers.get("content-type") ?? "";
|
|
141
|
+
if (request.method !== "POST" || contentType === "") return;
|
|
142
|
+
if (!contentType.includes("application/json")) return;
|
|
143
|
+
try {
|
|
144
|
+
const body = await request.json();
|
|
145
|
+
if (body !== null && typeof body === "object" && "note" in body && typeof body.note === "string") return body.note;
|
|
146
|
+
} catch {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function mapError(error, credentials) {
|
|
151
|
+
if (!isApprovalError(error)) return problem(500, "Internal error", "approval store failed", "internal");
|
|
152
|
+
if (error.code === "approval-not-found") return problem(404, "Not found", error.message, "not-found");
|
|
153
|
+
if (error.code === "approval-not-pending" || error.code === "approval-expired" || error.code === "approver-repeated") return problem(409, "Conflict", error.message, "conflict");
|
|
154
|
+
if (error.code === "approver-unauthenticated") return unauthenticatedProblem(credentials);
|
|
155
|
+
return problem(403, "Permission denied", error.message, "denied");
|
|
156
|
+
}
|
|
157
|
+
function approvalsHandler(store, options) {
|
|
158
|
+
const requireDistinct = options.requireDistinctApprover === true;
|
|
159
|
+
return async (request) => {
|
|
160
|
+
const url = new URL(request.url);
|
|
161
|
+
const route = parseRoute(url, request.method);
|
|
162
|
+
if (route === void 0) return problem(405, "Method not allowed", "unknown approvals route", "method-not-allowed");
|
|
163
|
+
await store.expire();
|
|
164
|
+
const subject = await resolveSubject(request, options.subject);
|
|
165
|
+
const principal = subject?.principal ?? null;
|
|
166
|
+
if (subject === null || principal === null) return unauthenticatedProblem(hasCredentials(request));
|
|
167
|
+
try {
|
|
168
|
+
if (route.kind === "pending") {
|
|
169
|
+
const scoped = inboxScope(url, subject);
|
|
170
|
+
if (!scoped.ok) return problem(403, "Permission denied", "approver does not belong to that tenant", "denied");
|
|
171
|
+
const page = await store.list({
|
|
172
|
+
...pageQuery(url),
|
|
173
|
+
status: "pending"
|
|
174
|
+
});
|
|
175
|
+
const tenants = new Set(scoped.tenants);
|
|
176
|
+
const eligible = await Promise.all(page.items.map(async (item) => {
|
|
177
|
+
const tenant = item.subject.principal?.tenant;
|
|
178
|
+
return (tenant === void 0 ? scoped.tenantless : tenants.has(tenant)) && await mayResolve(item, subject, requireDistinct, options);
|
|
179
|
+
}));
|
|
180
|
+
return json(200, compact({
|
|
181
|
+
items: page.items.filter((_, index) => eligible[index] === true),
|
|
182
|
+
next: page.next
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
if (route.kind === "mine") {
|
|
186
|
+
const page = await store.list({
|
|
187
|
+
...pageQuery(url),
|
|
188
|
+
principalId: principal.id
|
|
189
|
+
});
|
|
190
|
+
return json(200, compact({
|
|
191
|
+
items: page.items,
|
|
192
|
+
next: page.next
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
if (route.kind === "get") {
|
|
196
|
+
const current = await store.get(route.token);
|
|
197
|
+
if (current === null || !canView(current, subject)) return problem(404, "Not found", "approval was not found", "not-found");
|
|
198
|
+
return json(200, current);
|
|
199
|
+
}
|
|
200
|
+
const current = await store.get(route.token);
|
|
201
|
+
if (current === null) return problem(404, "Not found", "approval was not found", "not-found");
|
|
202
|
+
const relations = await approverRelations(current, subject, options);
|
|
203
|
+
const permissions = await heldPermissions(current, subject, options.permdockFor);
|
|
204
|
+
assertApprover(current, subject, requireDistinct, /* @__PURE__ */ new Date(), relations, permissions);
|
|
205
|
+
const note = await readNote(request);
|
|
206
|
+
const resolved = await store.resolve(route.token, compact({
|
|
207
|
+
status: route.kind === "approve" ? "approved" : "rejected",
|
|
208
|
+
by: subject,
|
|
209
|
+
note,
|
|
210
|
+
relations,
|
|
211
|
+
permissions
|
|
212
|
+
}));
|
|
213
|
+
const signed = await signedApproval(resolved, options.signer, options.audience);
|
|
214
|
+
return json(200, compact({
|
|
215
|
+
...resolved,
|
|
216
|
+
signed
|
|
217
|
+
}));
|
|
218
|
+
} catch (error) {
|
|
219
|
+
return mapError(error, hasCredentials(request));
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
//#endregion
|
|
224
|
+
export { approvalsHandler as t };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { n as isReadonlyArray } from "./compact-y6vfu2_f.js";
|
|
2
|
+
//#region src/core/approvers.ts
|
|
3
|
+
/** Approves when the approver holds `permission` in the request's tenant (any role, custom roles included). */
|
|
4
|
+
function holder(permission) {
|
|
5
|
+
const key = permission?.key;
|
|
6
|
+
if (typeof key !== "string" || key === "") throw new Error("PermDock: holder() needs a permission");
|
|
7
|
+
return Object.freeze({
|
|
8
|
+
kind: "permission",
|
|
9
|
+
permission: key
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/** Approves when the approver matches any one of `items`. */
|
|
13
|
+
function anyOf(...items) {
|
|
14
|
+
if (items.length === 0) throw new Error("PermDock: anyOf() needs at least one approver");
|
|
15
|
+
return Object.freeze({
|
|
16
|
+
kind: "any-of",
|
|
17
|
+
of: Object.freeze([...items])
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** Approves when the approver matches every one of `items`; the same as a list. */
|
|
21
|
+
function allOf(...items) {
|
|
22
|
+
if (items.length === 0) throw new Error("PermDock: allOf() needs at least one approver");
|
|
23
|
+
return Object.freeze([...items]);
|
|
24
|
+
}
|
|
25
|
+
/** A named approver for `approval.by`, matched on the approver's principal id. */
|
|
26
|
+
function user(id) {
|
|
27
|
+
if (typeof id !== "string" || id === "") throw new Error("PermDock: user() needs a non-empty principal id");
|
|
28
|
+
return Object.freeze({
|
|
29
|
+
kind: "user",
|
|
30
|
+
id
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function isUserApprover(value) {
|
|
34
|
+
return value !== null && typeof value === "object" && "kind" in value && value.kind === "user";
|
|
35
|
+
}
|
|
36
|
+
function flattenApprovers(input) {
|
|
37
|
+
if (input === void 0) return [];
|
|
38
|
+
if (isReadonlyArray(input)) return input;
|
|
39
|
+
return [input];
|
|
40
|
+
}
|
|
41
|
+
/** Every approver `input` names, inside `anyOf` groups too, for reading facts and labels. */
|
|
42
|
+
function approverLeaves(input) {
|
|
43
|
+
return flattenApprovers(input).flatMap((item) => item.kind === "any-of" ? item.of.flatMap((entry) => approverLeaves(entry)) : [item]);
|
|
44
|
+
}
|
|
45
|
+
function isPermissionApprover(value) {
|
|
46
|
+
return value !== null && typeof value === "object" && "kind" in value && value.kind === "permission";
|
|
47
|
+
}
|
|
48
|
+
function isAnyOfInput(value) {
|
|
49
|
+
return value !== null && typeof value === "object" && "kind" in value && value.kind === "any-of";
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { holder as a, isUserApprover as c, flattenApprovers as i, user as l, anyOf as n, isAnyOfInput as o, approverLeaves as r, isPermissionApprover as s, allOf as t };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { u as arazzoFindings } from "./snapshot-Enxd0n-s.js";
|
|
2
|
+
import { a as loadModule, o as pickNamed, t as asPermissionTree } from "./load-DhWEB9P1.js";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
//#region src/cli/arazzo.ts
|
|
6
|
+
async function runArazzo(input) {
|
|
7
|
+
if (input.rest[0] !== "check") return {
|
|
8
|
+
code: 2,
|
|
9
|
+
output: "permdock arazzo check --doc <arazzo> --openapi <doc>"
|
|
10
|
+
};
|
|
11
|
+
const docPath = input.doc;
|
|
12
|
+
const openapiPath = input.openapi;
|
|
13
|
+
if (docPath === void 0 || openapiPath === void 0) return {
|
|
14
|
+
code: 2,
|
|
15
|
+
output: "arazzo check requires --doc and --openapi"
|
|
16
|
+
};
|
|
17
|
+
const arazzoFile = resolve(input.cwd, docPath);
|
|
18
|
+
const openapiFile = resolve(input.cwd, openapiPath);
|
|
19
|
+
if (!existsSync(arazzoFile) || !existsSync(openapiFile)) return {
|
|
20
|
+
code: 2,
|
|
21
|
+
output: "arazzo check: document not found"
|
|
22
|
+
};
|
|
23
|
+
let arazzo;
|
|
24
|
+
let openapi;
|
|
25
|
+
try {
|
|
26
|
+
arazzo = JSON.parse(readFileSync(arazzoFile, "utf8"));
|
|
27
|
+
openapi = JSON.parse(readFileSync(openapiFile, "utf8"));
|
|
28
|
+
} catch {
|
|
29
|
+
return {
|
|
30
|
+
code: 2,
|
|
31
|
+
output: "arazzo check: unreadable JSON"
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const from = input.from ?? input.config.permissions;
|
|
35
|
+
let tree;
|
|
36
|
+
if (from !== void 0) {
|
|
37
|
+
const abs = resolve(input.cwd, from);
|
|
38
|
+
if (!existsSync(abs)) return {
|
|
39
|
+
code: 2,
|
|
40
|
+
output: `arazzo check: permissions not found: ${from}`
|
|
41
|
+
};
|
|
42
|
+
const mod = await loadModule(abs);
|
|
43
|
+
tree = asPermissionTree(pickNamed(mod, ["permissions"]));
|
|
44
|
+
}
|
|
45
|
+
const findings = arazzoFindings(input.workflow === void 0 ? {
|
|
46
|
+
arazzo,
|
|
47
|
+
openapi
|
|
48
|
+
} : {
|
|
49
|
+
arazzo,
|
|
50
|
+
openapi,
|
|
51
|
+
workflowId: input.workflow
|
|
52
|
+
}, tree);
|
|
53
|
+
if (input.json) return {
|
|
54
|
+
code: findings.length === 0 ? 0 : 1,
|
|
55
|
+
output: JSON.stringify({
|
|
56
|
+
$schema: "permdock-arazzo-check",
|
|
57
|
+
findings
|
|
58
|
+
})
|
|
59
|
+
};
|
|
60
|
+
if (findings.length === 0) return {
|
|
61
|
+
code: 0,
|
|
62
|
+
output: "arazzo check: all steps documented"
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
code: 1,
|
|
66
|
+
output: findings.map((finding) => `${finding.workflowId} ${finding.stepId}: ${finding.reason} (${finding.detail})`).join("\n")
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { runArazzo };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { a as listArg, i as globalArgs, s as stringArg, t as COMMAND_DESCRIPTIONS } from "./commands-DWOrSQic.js";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
//#region src/cli/commands/arazzo.ts
|
|
4
|
+
function arazzo(ctx) {
|
|
5
|
+
return defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "arazzo",
|
|
8
|
+
description: COMMAND_DESCRIPTIONS.arazzo
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
...globalArgs,
|
|
12
|
+
action: {
|
|
13
|
+
type: "positional",
|
|
14
|
+
required: false,
|
|
15
|
+
description: "check"
|
|
16
|
+
},
|
|
17
|
+
doc: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Arazzo document",
|
|
20
|
+
valueHint: "arazzo.json"
|
|
21
|
+
},
|
|
22
|
+
openapi: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "OpenAPI document the workflows call",
|
|
25
|
+
valueHint: "doc.json"
|
|
26
|
+
},
|
|
27
|
+
workflow: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Check one workflow",
|
|
30
|
+
valueHint: "id"
|
|
31
|
+
},
|
|
32
|
+
from: {
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "Module exporting the policy, instead of the config",
|
|
35
|
+
valueHint: "module"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
async run({ args: parsed, rawArgs }) {
|
|
39
|
+
const result = await (await import("./arazzo-BAgw9ap6.js")).runArazzo({
|
|
40
|
+
cwd: ctx.cwd,
|
|
41
|
+
config: ctx.config,
|
|
42
|
+
rest: parsed._,
|
|
43
|
+
doc: listArg(rawArgs, "doc")[0],
|
|
44
|
+
openapi: stringArg(parsed.openapi),
|
|
45
|
+
workflow: stringArg(parsed.workflow),
|
|
46
|
+
from: stringArg(parsed.from),
|
|
47
|
+
json: ctx.json
|
|
48
|
+
});
|
|
49
|
+
ctx.report(result);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { arazzo };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { C as Policy, Nr as Principal } from "../policy-CFZAr_Al.js";
|
|
2
|
+
import { f as ApprovalStore } from "../types-vKyAMtcX.js";
|
|
3
|
+
import { t as InstanceOptions } from "../instance-options-BK_rNOSC.js";
|
|
4
|
+
//#region src/authzen/types.d.ts
|
|
5
|
+
type AuthzenResourceAdapter = {
|
|
6
|
+
readonly load?: (id: string) => unknown;
|
|
7
|
+
readonly list?: (query: {
|
|
8
|
+
readonly where?: unknown;
|
|
9
|
+
}) => readonly unknown[] | Promise<readonly unknown[]>;
|
|
10
|
+
};
|
|
11
|
+
type AuthzenSubjectRecord = {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly [key: string]: unknown;
|
|
14
|
+
};
|
|
15
|
+
type AuthzenPermDockOptions<TUser = unknown> = InstanceOptions & {
|
|
16
|
+
readonly subject: (request: Request) => TUser | Promise<TUser>;
|
|
17
|
+
readonly anonymous?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Allow-list over the authenticated PEP. Only a PEP it returns `true` for
|
|
20
|
+
* may evaluate the body's `subject`, `actor` and `delegation`; every other
|
|
21
|
+
* caller is evaluated as itself. Off by default.
|
|
22
|
+
*/
|
|
23
|
+
readonly trustedPep?: (pep: unknown) => boolean;
|
|
24
|
+
readonly resources?: Readonly<Record<string, AuthzenResourceAdapter>>;
|
|
25
|
+
readonly subjects?: {
|
|
26
|
+
readonly list?: () => readonly AuthzenSubjectRecord[] | Promise<readonly AuthzenSubjectRecord[]>;
|
|
27
|
+
};
|
|
28
|
+
readonly store?: ApprovalStore;
|
|
29
|
+
readonly maxEvaluations?: number;
|
|
30
|
+
};
|
|
31
|
+
type AuthzenPermDock = {
|
|
32
|
+
readonly permdockHandler: (request: Request) => Promise<Response>;
|
|
33
|
+
};
|
|
34
|
+
type AuthzenFactory = <TUser, TPrincipal extends Principal = Principal>(policy: Policy<TUser, TPrincipal>, options: AuthzenPermDockOptions<TUser>) => AuthzenPermDock;
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/authzen/create.d.ts
|
|
37
|
+
export declare const createPermDock: AuthzenFactory;
|
|
38
|
+
//#endregion
|
|
39
|
+
export type { AuthzenFactory, AuthzenPermDock, AuthzenPermDockOptions, AuthzenResourceAdapter, AuthzenSubjectRecord };
|