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,309 @@
|
|
|
1
|
+
import { _ as listPermissions, a as formerKeys, c as getResource } from "./permissions-DVoF6dMt.js";
|
|
2
|
+
import { t as catalogFingerprint } from "./src-CSbUiozF.js";
|
|
3
|
+
import { S as findRole } from "./grantee-Cv5Sogfv.js";
|
|
4
|
+
import { t as canonicalJson } from "./canonical-json-DemiK4Vp.js";
|
|
5
|
+
import { t as byCodePoint } from "./compare-pfyVnBjE.js";
|
|
6
|
+
import { t as catalogSchema } from "./schema-D3MnDMxa.js";
|
|
7
|
+
import { s as generatorBanner, t as CATALOG_SCHEMA } from "./version-BvacVTZR.js";
|
|
8
|
+
//#region src/cli/catalog-doc.ts
|
|
9
|
+
const ROW_GRANTEES = /* @__PURE__ */ new Set([
|
|
10
|
+
"relation",
|
|
11
|
+
"plan",
|
|
12
|
+
"actor",
|
|
13
|
+
"assurance",
|
|
14
|
+
"inherit"
|
|
15
|
+
]);
|
|
16
|
+
/**
|
|
17
|
+
* Whether a grant depends on more than the role and the scope: a row or body
|
|
18
|
+
* condition, a closure, a field list, a purpose, a break-glass override, a
|
|
19
|
+
* validity window, a `requires`, or a relation, plan, actor or assurance grantee. The SQL helpers
|
|
20
|
+
* (`permdock_has`, `permitted_<scope>_ids`) check only role and scope, so a
|
|
21
|
+
* policy that calls them for such a permission would widen access.
|
|
22
|
+
*/
|
|
23
|
+
function grantHasRowConditions(grant) {
|
|
24
|
+
const grantees = Array.isArray(grant.to) ? grant.to : [grant.to];
|
|
25
|
+
return grant.where !== void 0 || grant.check !== void 0 || grant.closure !== void 0 || !grant.portable || grant.fields !== void 0 || grant.purpose !== void 0 || grant.breakGlass !== void 0 || grant.validity !== void 0 || grant.requires !== void 0 || grantees.some((grantee) => ROW_GRANTEES.has(grantee.kind));
|
|
26
|
+
}
|
|
27
|
+
/** Per permission key, whether any code grant for it has row conditions. */
|
|
28
|
+
function policyRowConditionKeys(policy) {
|
|
29
|
+
const keys = /* @__PURE__ */ new Set();
|
|
30
|
+
for (const grant of [...policy.grants, ...policy.roles.flatMap((binding) => binding.grants)]) if (grant.hosted === void 0 && grantHasRowConditions(grant)) keys.add(grant.permission.key);
|
|
31
|
+
return keys;
|
|
32
|
+
}
|
|
33
|
+
function leafLevels(tree, leaf) {
|
|
34
|
+
if (leaf.kind !== "instance") return;
|
|
35
|
+
const names = Object.keys({ ...getResource(tree, leaf.resource)?.levels });
|
|
36
|
+
return names.length === 0 ? void 0 : names;
|
|
37
|
+
}
|
|
38
|
+
/** With `policy`, permissions carry `hostable` and a known `rowConditions` (without, it is `true`), and roles carry `on`, `assignable` and their ownership rules. */
|
|
39
|
+
function buildCatalog(tree, scan, generatedAt, policy) {
|
|
40
|
+
const hostable = new Set(policy?.hostable ?? []);
|
|
41
|
+
const rowConditions = policy === void 0 ? void 0 : policyRowConditionKeys(policy);
|
|
42
|
+
const resources = {};
|
|
43
|
+
const definedIn = scan.definitionFiles["permissions"];
|
|
44
|
+
for (const leaf of listPermissions(tree)) {
|
|
45
|
+
if (resources[leaf.resource] !== void 0) continue;
|
|
46
|
+
const node = getResource(tree, leaf.resource);
|
|
47
|
+
resources[leaf.resource] = compactResource(definedIn === void 0 ? {
|
|
48
|
+
id: node?.id ?? "id",
|
|
49
|
+
schema: node === void 0 ? null : jsonSchemaOf(node),
|
|
50
|
+
relations: node?.relations,
|
|
51
|
+
version: node?.version,
|
|
52
|
+
restricted: node?.restricted,
|
|
53
|
+
restrictedStops: node?.restrictedStops
|
|
54
|
+
} : {
|
|
55
|
+
id: node?.id ?? "id",
|
|
56
|
+
schema: node === void 0 ? null : jsonSchemaOf(node),
|
|
57
|
+
definedIn,
|
|
58
|
+
relations: node?.relations,
|
|
59
|
+
version: node?.version,
|
|
60
|
+
restricted: node?.restricted,
|
|
61
|
+
restrictedStops: node?.restrictedStops
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const approvals = codeApprovals(policy);
|
|
65
|
+
const breakGlass = codeBreakGlass(policy);
|
|
66
|
+
const body = {
|
|
67
|
+
resources,
|
|
68
|
+
permissions: listPermissions(tree).map((leaf) => withDefined({
|
|
69
|
+
key: leaf.key,
|
|
70
|
+
scope: leaf.scope,
|
|
71
|
+
resource: leaf.resource,
|
|
72
|
+
action: leaf.action,
|
|
73
|
+
arity: leaf.kind,
|
|
74
|
+
meta: metaRecord(leaf.meta),
|
|
75
|
+
usages: scan.usages[leaf.key] ?? [],
|
|
76
|
+
renamedFrom: formerKeys(leaf).length === 0 ? void 0 : formerKeys(leaf),
|
|
77
|
+
levels: leafLevels(tree, leaf),
|
|
78
|
+
hostable: hostable.has(leaf.key) ? true : void 0,
|
|
79
|
+
rowConditions: rowConditions?.has(leaf.key) ?? true,
|
|
80
|
+
approvals: approvals.get(leaf.key),
|
|
81
|
+
breakGlass: breakGlass.get(leaf.key)
|
|
82
|
+
})).toSorted((a, b) => byCodePoint(a.key, b.key)),
|
|
83
|
+
...catalogScopes(policy),
|
|
84
|
+
...catalogRoles(scan.roleNames, policy),
|
|
85
|
+
...scan.planNames.length === 0 ? {} : { plans: scan.planNames.map((key) => ({ key })) },
|
|
86
|
+
...policy === void 0 ? {} : { grants: catalogGrants(policy) },
|
|
87
|
+
...policy?.delegations === void 0 ? {} : { delegations: catalogDelegations(policy) }
|
|
88
|
+
};
|
|
89
|
+
const head = {
|
|
90
|
+
$schema: CATALOG_SCHEMA,
|
|
91
|
+
version: 1,
|
|
92
|
+
generatedAt,
|
|
93
|
+
generator: generatorBanner()
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
...head,
|
|
97
|
+
fingerprint: catalogFingerprint({
|
|
98
|
+
...head,
|
|
99
|
+
...body
|
|
100
|
+
}),
|
|
101
|
+
...body
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function catalogApproval(approval) {
|
|
105
|
+
if (approval === void 0) return;
|
|
106
|
+
return approval === "human" ? "human" : withDefined({
|
|
107
|
+
by: approval.by,
|
|
108
|
+
mode: approval.mode,
|
|
109
|
+
stages: approval.stages,
|
|
110
|
+
distinct: approval.distinct,
|
|
111
|
+
staleOn: approval.staleOn,
|
|
112
|
+
quorum: approval.quorum,
|
|
113
|
+
ttl: approval.ttl,
|
|
114
|
+
escalation: approval.escalation
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Every code grant in canonical order: by permission, allows before denies,
|
|
119
|
+
* then by role (top-level grants last) and finally by canonical JSON, so two
|
|
120
|
+
* catalogs of the same policy list the same grants in the same order
|
|
121
|
+
* whatever the declaration order was.
|
|
122
|
+
*/
|
|
123
|
+
function catalogGrant(grant) {
|
|
124
|
+
const limit = grant.limit === void 0 ? void 0 : withDefined({
|
|
125
|
+
count: grant.limit.count,
|
|
126
|
+
per: grant.limit.per,
|
|
127
|
+
mode: grant.limit.mode
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
permission: grant.permission.key,
|
|
131
|
+
effect: grant.effect,
|
|
132
|
+
role: grant.role,
|
|
133
|
+
to: grant.to,
|
|
134
|
+
scope: grant.scope,
|
|
135
|
+
...withDefined({
|
|
136
|
+
where: grant.portable ? grant.where : void 0,
|
|
137
|
+
check: grant.portable ? grant.check : void 0,
|
|
138
|
+
approval: catalogApproval(grant.approval),
|
|
139
|
+
fields: grant.fields,
|
|
140
|
+
validity: grant.validity,
|
|
141
|
+
name: grant.name,
|
|
142
|
+
purpose: grant.purpose,
|
|
143
|
+
requires: grant.requires?.length === 1 ? grant.requires[0] : grant.requires,
|
|
144
|
+
limit,
|
|
145
|
+
portable: grant.portable ? void 0 : false
|
|
146
|
+
})
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/** The sort key of a catalog grant: permission, allows first, role (top-level last), then the canonical JSON. */
|
|
150
|
+
function catalogGrantKey(grant) {
|
|
151
|
+
return [
|
|
152
|
+
grant.permission,
|
|
153
|
+
grant.effect === "allow" ? "0" : "1",
|
|
154
|
+
grant.role ?? "",
|
|
155
|
+
canonicalJson(grant)
|
|
156
|
+
].join("\0");
|
|
157
|
+
}
|
|
158
|
+
function catalogGrants(policy) {
|
|
159
|
+
const keys = /* @__PURE__ */ new Map();
|
|
160
|
+
const entries = policy.grants.filter((grant) => grant.hosted === void 0).map(catalogGrant);
|
|
161
|
+
for (const entry of entries) keys.set(entry, catalogGrantKey(entry));
|
|
162
|
+
const keyOf = (grant) => keys.get(grant) ?? "";
|
|
163
|
+
return entries.toSorted((a, b) => {
|
|
164
|
+
const left = keyOf(a);
|
|
165
|
+
const right = keyOf(b);
|
|
166
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/** Every policy delegation, sorted by canonical JSON so declaration order does not matter. */
|
|
170
|
+
function catalogDelegations(policy) {
|
|
171
|
+
return (policy.delegations ?? []).map((delegation) => withDefined({
|
|
172
|
+
from: delegation.from,
|
|
173
|
+
to: delegation.to,
|
|
174
|
+
permissions: delegation.permissions,
|
|
175
|
+
validity: delegation.validity
|
|
176
|
+
})).toSorted((a, b) => {
|
|
177
|
+
const left = canonicalJson(a);
|
|
178
|
+
const right = canonicalJson(b);
|
|
179
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/** Per permission key, the distinct approvals the code allows require, in policy order. */
|
|
183
|
+
function codeApprovals(policy) {
|
|
184
|
+
const out = /* @__PURE__ */ new Map();
|
|
185
|
+
const seen = /* @__PURE__ */ new Set();
|
|
186
|
+
for (const grant of policy?.grants ?? []) {
|
|
187
|
+
if (grant.effect !== "allow" || grant.hosted !== void 0 || grant.approval === void 0) continue;
|
|
188
|
+
const approval = catalogApproval(grant.approval);
|
|
189
|
+
if (approval === void 0) continue;
|
|
190
|
+
const id = `${grant.permission.key}\u0000${JSON.stringify(approval)}`;
|
|
191
|
+
if (seen.has(id)) continue;
|
|
192
|
+
seen.add(id);
|
|
193
|
+
out.set(grant.permission.key, [...out.get(grant.permission.key) ?? [], approval]);
|
|
194
|
+
}
|
|
195
|
+
return out;
|
|
196
|
+
}
|
|
197
|
+
/** Per permission key, the break-glass override a `breakGlass` grant declares. */
|
|
198
|
+
function codeBreakGlass(policy) {
|
|
199
|
+
const out = /* @__PURE__ */ new Map();
|
|
200
|
+
for (const grant of policy?.grants ?? []) {
|
|
201
|
+
if (grant.breakGlass === void 0) continue;
|
|
202
|
+
out.set(grant.permission.key, withDefined({
|
|
203
|
+
overrides: grant.breakGlass.overrides,
|
|
204
|
+
purpose: grant.breakGlass.purpose,
|
|
205
|
+
reason: grant.breakGlass.reason,
|
|
206
|
+
maxDuration: grant.breakGlass.maxDuration,
|
|
207
|
+
obligations: grant.breakGlass.obligations
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
function catalogScopes(policy) {
|
|
213
|
+
const scopes = policy?.scopes ?? [];
|
|
214
|
+
return scopes.length === 0 ? {} : { scopes: scopes.map((scope) => withDefined({
|
|
215
|
+
name: scope.name,
|
|
216
|
+
key: scope.key ?? "",
|
|
217
|
+
within: scope.within
|
|
218
|
+
})) };
|
|
219
|
+
}
|
|
220
|
+
function catalogRoles(scanned, policy) {
|
|
221
|
+
if (policy === void 0) return scanned.length === 0 ? {} : { roles: scanned.map((key) => ({ key })) };
|
|
222
|
+
const names = [.../* @__PURE__ */ new Set([...scanned, ...policy.roles.map((role) => role.name)])].toSorted();
|
|
223
|
+
if (names.length === 0) return {};
|
|
224
|
+
return { roles: names.map((key) => {
|
|
225
|
+
const binding = policy.rolesByName.get(key);
|
|
226
|
+
if (binding === void 0) return { key };
|
|
227
|
+
const audience = binding.meta?.audience ?? findRole(policy.vocabulary.roles, key)?.meta.audience;
|
|
228
|
+
return withDefined({
|
|
229
|
+
key,
|
|
230
|
+
on: binding.on === void 0 ? void 0 : typeof binding.on === "string" ? binding.on : "resource",
|
|
231
|
+
assignable: binding.assignable,
|
|
232
|
+
min: binding.min === 0 ? void 0 : binding.min,
|
|
233
|
+
max: binding.max,
|
|
234
|
+
transferOnly: binding.transferOnly === true ? true : void 0,
|
|
235
|
+
assigns: binding.assigns,
|
|
236
|
+
for: binding.for,
|
|
237
|
+
exclusiveWith: binding.exclusiveWith,
|
|
238
|
+
audience,
|
|
239
|
+
activation: binding.activation === void 0 ? void 0 : withDefined({
|
|
240
|
+
maxDuration: binding.activation.maxDuration,
|
|
241
|
+
justification: binding.activation.justification,
|
|
242
|
+
approval: binding.activation.approval === void 0 ? void 0 : true,
|
|
243
|
+
assurance: binding.activation.assurance
|
|
244
|
+
}),
|
|
245
|
+
supportAccess: binding.support === void 0 ? void 0 : {
|
|
246
|
+
actorRequired: binding.support.actorRequired,
|
|
247
|
+
group: binding.support.group,
|
|
248
|
+
durations: binding.support.consent.durations
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}) };
|
|
252
|
+
}
|
|
253
|
+
function withDefined(value) {
|
|
254
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
255
|
+
}
|
|
256
|
+
function compactResource(resource) {
|
|
257
|
+
const relations = resource.relations !== void 0 && Object.keys(resource.relations).length > 0 ? resource.relations : void 0;
|
|
258
|
+
return {
|
|
259
|
+
id: resource.id,
|
|
260
|
+
schema: resource.schema,
|
|
261
|
+
...withDefined({
|
|
262
|
+
definedIn: resource.definedIn,
|
|
263
|
+
relations,
|
|
264
|
+
version: resource.version,
|
|
265
|
+
restricted: resource.restricted,
|
|
266
|
+
restrictedStops: resource.restrictedStops
|
|
267
|
+
})
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function metaRecord(meta) {
|
|
271
|
+
return { ...meta };
|
|
272
|
+
}
|
|
273
|
+
function jsonSchemaOf(node) {
|
|
274
|
+
const output = node.schema?.["~standard"]?.jsonSchema?.output;
|
|
275
|
+
if (typeof output === "function") try {
|
|
276
|
+
return output({ target: "draft-2020-12" });
|
|
277
|
+
} catch {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function formatCatalogJson(doc) {
|
|
283
|
+
return `${JSON.stringify(doc, null, 2)}\n`;
|
|
284
|
+
}
|
|
285
|
+
function catalogForCompare(doc) {
|
|
286
|
+
const { generatedAt: _generatedAt, generator: _generator, ...rest } = doc;
|
|
287
|
+
return `${JSON.stringify(rest, null, 2)}\n`;
|
|
288
|
+
}
|
|
289
|
+
function formatCatalogMarkdown(doc) {
|
|
290
|
+
const lines = ["# Permissions", ""];
|
|
291
|
+
const byResource = /* @__PURE__ */ new Map();
|
|
292
|
+
for (const permission of doc.permissions) {
|
|
293
|
+
const current = byResource.get(permission.resource) ?? [];
|
|
294
|
+
byResource.set(permission.resource, [...current, permission]);
|
|
295
|
+
}
|
|
296
|
+
for (const resource of [...byResource.keys()].toSorted()) {
|
|
297
|
+
lines.push(`## ${resource}`, "");
|
|
298
|
+
lines.push("| Action | Arity | Scope | Usages |");
|
|
299
|
+
lines.push("| --- | --- | --- | --- |");
|
|
300
|
+
for (const permission of byResource.get(resource) ?? []) lines.push(`| \`${permission.action}\` | ${permission.arity} | \`${permission.scope}\` | ${String(permission.usages.length)} |`);
|
|
301
|
+
lines.push("");
|
|
302
|
+
}
|
|
303
|
+
return `${lines.join("\n")}\n`;
|
|
304
|
+
}
|
|
305
|
+
function catalogSchemaDocument() {
|
|
306
|
+
return catalogSchema;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
export { formatCatalogMarkdown as a, formatCatalogJson as i, catalogForCompare as n, jsonSchemaOf as o, catalogSchemaDocument as r, policyRowConditionKeys as s, buildCatalog as t };
|
|
@@ -0,0 +1,48 @@
|
|
|
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/catalog.ts
|
|
4
|
+
function catalog(ctx) {
|
|
5
|
+
return defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "catalog",
|
|
8
|
+
description: COMMAND_DESCRIPTIONS.catalog
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
...globalArgs,
|
|
12
|
+
format: {
|
|
13
|
+
type: "enum",
|
|
14
|
+
options: [
|
|
15
|
+
"json",
|
|
16
|
+
"schema",
|
|
17
|
+
"markdown"
|
|
18
|
+
],
|
|
19
|
+
default: "json",
|
|
20
|
+
description: "Output format"
|
|
21
|
+
},
|
|
22
|
+
from: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Module exporting the permissions, instead of the config",
|
|
25
|
+
valueHint: "module"
|
|
26
|
+
},
|
|
27
|
+
include: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Permission keys or prefixes to keep, repeatable",
|
|
30
|
+
valueHint: "key"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
async run({ args: parsed, rawArgs }) {
|
|
34
|
+
const result = await (await import("./catalog-BjZSovXQ.js")).runCatalog({
|
|
35
|
+
cwd: ctx.cwd,
|
|
36
|
+
config: ctx.config,
|
|
37
|
+
format: parsed.format,
|
|
38
|
+
from: stringArg(parsed.from),
|
|
39
|
+
include: listArg(rawArgs, "include"),
|
|
40
|
+
now: ctx.now,
|
|
41
|
+
io: ctx.io
|
|
42
|
+
});
|
|
43
|
+
ctx.report(result);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { catalog };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
//#region src/cli/catalog-path.ts
|
|
3
|
+
/**
|
|
4
|
+
* The absolute path `permdock collect` writes the catalog to: `collect.out`,
|
|
5
|
+
* then `catalog.out`, then `permissions.catalog.json`, resolved against `cwd`.
|
|
6
|
+
* `out` overrides the config, as `collect --out` does.
|
|
7
|
+
*/
|
|
8
|
+
function catalogPath(config, cwd, out) {
|
|
9
|
+
return resolve(cwd, out ?? config.collect?.out ?? config.catalog?.out ?? "permissions.catalog.json");
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { catalogPath as t };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { a as formatCatalogMarkdown, i as formatCatalogJson, r as catalogSchemaDocument, t as buildCatalog } from "./catalog-doc-Dsc9y7sd.js";
|
|
2
|
+
import { r as listSourceFiles, t as defaultSrcPath } from "./files-DWUN9PzI.js";
|
|
3
|
+
import { a as loadModule, i as loadConfiguredPolicy, o as pickNamed, r as leavesOf, t as asPermissionTree } from "./load-DhWEB9P1.js";
|
|
4
|
+
import { i as scanSources, r as runCollect } from "./collect-DDDv_ESs.js";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
//#region src/cli/catalog.ts
|
|
8
|
+
async function runCatalog(input) {
|
|
9
|
+
if (input.format === "schema") return {
|
|
10
|
+
code: 0,
|
|
11
|
+
output: `${JSON.stringify(catalogSchemaDocument(), null, 2)}\n`
|
|
12
|
+
};
|
|
13
|
+
const from = input.from ?? input.config.permissions;
|
|
14
|
+
let document;
|
|
15
|
+
if (from !== void 0) {
|
|
16
|
+
const abs = resolve(input.cwd, from);
|
|
17
|
+
if (!existsSync(abs)) return {
|
|
18
|
+
code: 2,
|
|
19
|
+
output: `PermDock CLI: module not found: ${from}`
|
|
20
|
+
};
|
|
21
|
+
const tree = asPermissionTree(pickNamed(await loadModule(abs), ["permissions"]));
|
|
22
|
+
const srcPath = input.config.collect?.srcPath ?? defaultSrcPath();
|
|
23
|
+
const files = listSourceFiles(input.cwd, srcPath);
|
|
24
|
+
const scan = scanSources(input.cwd, files, new Set(leavesOf(tree).map((leaf) => leaf.key)));
|
|
25
|
+
document = buildCatalog(tree, scan, input.now.toISOString(), await loadConfiguredPolicy(input.cwd, input.config.policy));
|
|
26
|
+
} else {
|
|
27
|
+
const collected = await runCollect({
|
|
28
|
+
cwd: input.cwd,
|
|
29
|
+
config: input.config,
|
|
30
|
+
collect: input.config.collect ?? {},
|
|
31
|
+
check: false,
|
|
32
|
+
now: input.now,
|
|
33
|
+
io: input.io
|
|
34
|
+
});
|
|
35
|
+
if (collected.document === void 0) return {
|
|
36
|
+
code: collected.code,
|
|
37
|
+
output: collected.message
|
|
38
|
+
};
|
|
39
|
+
document = collected.document;
|
|
40
|
+
}
|
|
41
|
+
const filtered = input.include.length === 0 ? document : {
|
|
42
|
+
...document,
|
|
43
|
+
permissions: document.permissions.filter((permission) => input.include.some((prefix) => permission.key === prefix || permission.key.startsWith(`${prefix}.`) || permission.resource === prefix))
|
|
44
|
+
};
|
|
45
|
+
if (input.format === "markdown") return {
|
|
46
|
+
code: 0,
|
|
47
|
+
output: formatCatalogMarkdown(filtered)
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
code: 0,
|
|
51
|
+
output: formatCatalogJson(filtered)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { runCatalog as t };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { C as Policy, D as PolicyVocabulary, Nr as Principal, kr as Delegation, ln as PermDock } 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
|
+
import { t as ToolMap } from "../types-Bvc4oWT6.js";
|
|
5
|
+
//#region src/claude-agent/create.d.ts
|
|
6
|
+
/** Structural `McpServerProvenance` from `@anthropic-ai/claude-agent-sdk`. */
|
|
7
|
+
type ClaudeMcpServer = {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly source: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* What `subject`, `actor` and `tenant` receive: the `canUseTool` options or
|
|
13
|
+
* the hook input. The subject comes from the app that started the query,
|
|
14
|
+
* never from these fields.
|
|
15
|
+
*/
|
|
16
|
+
type ClaudeAgentContext = {
|
|
17
|
+
readonly toolName: string;
|
|
18
|
+
readonly mcpServer?: ClaudeMcpServer;
|
|
19
|
+
readonly sessionId?: string;
|
|
20
|
+
readonly agentId?: string;
|
|
21
|
+
};
|
|
22
|
+
type ClaudeAgentPermDockOptions<TUser = unknown> = InstanceOptions & {
|
|
23
|
+
readonly subject: (context: ClaudeAgentContext) => TUser | Promise<TUser>;
|
|
24
|
+
readonly actor?: (context: ClaudeAgentContext) => unknown;
|
|
25
|
+
readonly delegation?: (context: ClaudeAgentContext) => Delegation | undefined | Promise<Delegation | undefined>;
|
|
26
|
+
readonly tenant?: string | ((context: ClaudeAgentContext) => string | undefined | Promise<string | undefined>);
|
|
27
|
+
readonly tools: ToolMap;
|
|
28
|
+
/** MCP server sources whose `mcp__*` tools may be decided; default `['sdk']`. */
|
|
29
|
+
readonly mcpSources?: readonly string[];
|
|
30
|
+
readonly store?: ApprovalStore;
|
|
31
|
+
};
|
|
32
|
+
type PermissionResult = {
|
|
33
|
+
readonly behavior: "allow";
|
|
34
|
+
readonly updatedInput: Record<string, unknown>;
|
|
35
|
+
} | {
|
|
36
|
+
readonly behavior: "deny";
|
|
37
|
+
readonly message: string;
|
|
38
|
+
};
|
|
39
|
+
/** Structural `canUseTool` options from `@anthropic-ai/claude-agent-sdk`. */
|
|
40
|
+
type CanUseToolOptions = {
|
|
41
|
+
readonly signal?: AbortSignal;
|
|
42
|
+
readonly mcpServer?: ClaudeMcpServer;
|
|
43
|
+
readonly agentID?: string;
|
|
44
|
+
readonly toolUseID?: string;
|
|
45
|
+
};
|
|
46
|
+
/** Structural `HookInput`; only `PermissionRequest` events are answered. */
|
|
47
|
+
type PermissionRequestHookInput = {
|
|
48
|
+
readonly hook_event_name: string;
|
|
49
|
+
readonly session_id?: string;
|
|
50
|
+
readonly agent_id?: string;
|
|
51
|
+
readonly tool_name?: string;
|
|
52
|
+
readonly tool_input?: unknown;
|
|
53
|
+
readonly mcp_server?: ClaudeMcpServer;
|
|
54
|
+
};
|
|
55
|
+
type PermissionRequestHookOutput = {
|
|
56
|
+
readonly hookSpecificOutput: {
|
|
57
|
+
readonly hookEventName: "PermissionRequest";
|
|
58
|
+
readonly decision: PermissionResult;
|
|
59
|
+
};
|
|
60
|
+
} | Record<string, never>;
|
|
61
|
+
type ClaudeAgentPermDock<V extends PolicyVocabulary = PolicyVocabulary> = {
|
|
62
|
+
/** A `CanUseTool`: pass it as the query's `canUseTool` option. */
|
|
63
|
+
readonly canUseTool: (toolName: string, input: Record<string, unknown>, options?: CanUseToolOptions) => Promise<PermissionResult>;
|
|
64
|
+
/** A `HookCallback` for the `PermissionRequest` event. */
|
|
65
|
+
readonly permissionRequestHook: (input: PermissionRequestHookInput, toolUseID?: string, options?: {
|
|
66
|
+
readonly signal?: AbortSignal;
|
|
67
|
+
}) => Promise<PermissionRequestHookOutput>;
|
|
68
|
+
readonly permdock: (context: ClaudeAgentContext) => Promise<PermDock<V>>;
|
|
69
|
+
};
|
|
70
|
+
export declare function createPermDock<TUser, TPrincipal extends Principal = Principal, V extends PolicyVocabulary = PolicyVocabulary>(policy: Policy<TUser, TPrincipal, V>, options: ClaudeAgentPermDockOptions<TUser>): ClaudeAgentPermDock<V>;
|
|
71
|
+
//#endregion
|
|
72
|
+
export type { CanUseToolOptions, ClaudeAgentContext, ClaudeAgentPermDock, ClaudeAgentPermDockOptions, ClaudeMcpServer, PermissionRequestHookInput, PermissionRequestHookOutput, PermissionResult };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
+
import { t as instanceOptions } from "../instance-options-Dhhcnm3y.js";
|
|
3
|
+
import { n as createAgentKernel } from "../kernel-GSQnMz3O.js";
|
|
4
|
+
//#region src/claude-agent/create.ts
|
|
5
|
+
const MCP_PREFIX = "mcp__";
|
|
6
|
+
function asInput(input) {
|
|
7
|
+
if (input !== null && typeof input === "object" && !Array.isArray(input)) return input;
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
function untrustedServer(context, sources) {
|
|
11
|
+
if (!context.toolName.startsWith(MCP_PREFIX)) return;
|
|
12
|
+
const server = context.mcpServer;
|
|
13
|
+
if (server === void 0) return `Denied: ${context.toolName} has no MCP server provenance.`;
|
|
14
|
+
if (!sources.includes(server.source)) return `Denied: ${context.toolName} comes from an untrusted MCP server source.`;
|
|
15
|
+
if (!context.toolName.startsWith(`${MCP_PREFIX}${server.name}__`)) return `Denied: ${context.toolName} is not served by the MCP server that claims it.`;
|
|
16
|
+
}
|
|
17
|
+
function toResult(verdict, input) {
|
|
18
|
+
if (verdict.outcome === "granted") return {
|
|
19
|
+
behavior: "allow",
|
|
20
|
+
updatedInput: asInput(input)
|
|
21
|
+
};
|
|
22
|
+
if (verdict.outcome === "denied") return {
|
|
23
|
+
behavior: "deny",
|
|
24
|
+
message: verdict.reason
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
behavior: "deny",
|
|
28
|
+
message: `${verdict.summary} Approval ${verdict.token} is pending; retry the call once it is approved.`
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function createPermDock(policy, options) {
|
|
32
|
+
const sources = options.mcpSources ?? ["sdk"];
|
|
33
|
+
const kernel = createAgentKernel(policy, {
|
|
34
|
+
...compact({
|
|
35
|
+
actor: options.actor,
|
|
36
|
+
delegation: options.delegation,
|
|
37
|
+
tenant: options.tenant,
|
|
38
|
+
store: options.store
|
|
39
|
+
}),
|
|
40
|
+
...instanceOptions(options),
|
|
41
|
+
subject: options.subject,
|
|
42
|
+
tools: options.tools,
|
|
43
|
+
adapter: "claude-agent"
|
|
44
|
+
});
|
|
45
|
+
const decide = async (context, input) => {
|
|
46
|
+
const untrusted = untrustedServer(context, sources);
|
|
47
|
+
if (untrusted !== void 0) return {
|
|
48
|
+
behavior: "deny",
|
|
49
|
+
message: untrusted
|
|
50
|
+
};
|
|
51
|
+
return toResult(await kernel.decideTool(context.toolName, input, context), input);
|
|
52
|
+
};
|
|
53
|
+
const canUseTool = (toolName, input, sdkOptions = {}) => decide(compact({
|
|
54
|
+
toolName,
|
|
55
|
+
mcpServer: sdkOptions.mcpServer,
|
|
56
|
+
agentId: sdkOptions.agentID
|
|
57
|
+
}), input);
|
|
58
|
+
const permissionRequestHook = async (input) => {
|
|
59
|
+
if (input.hook_event_name !== "PermissionRequest" || typeof input.tool_name !== "string") return {};
|
|
60
|
+
return { hookSpecificOutput: {
|
|
61
|
+
hookEventName: "PermissionRequest",
|
|
62
|
+
decision: await decide(compact({
|
|
63
|
+
toolName: input.tool_name,
|
|
64
|
+
mcpServer: input.mcp_server,
|
|
65
|
+
sessionId: input.session_id,
|
|
66
|
+
agentId: input.agent_id
|
|
67
|
+
}), input.tool_input)
|
|
68
|
+
} };
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
canUseTool,
|
|
72
|
+
permissionRequestHook,
|
|
73
|
+
permdock: (context) => kernel.instance(context)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { createPermDock };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Nr as Principal, Pr as Subject, xt as RoleSource } from "../policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission } from "../permissions-DttnqqxC.js";
|
|
3
|
+
import { s as RemotePdpCache } from "../types-BVyImy5I.js";
|
|
4
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
5
|
+
//#region src/clerk/types.d.ts
|
|
6
|
+
type ClerkPrincipal = Principal & {
|
|
7
|
+
readonly clerkPermissions?: readonly string[];
|
|
8
|
+
readonly claims?: Readonly<Record<string, unknown>>;
|
|
9
|
+
readonly featureSources?: Readonly<Record<string, "o" | "u">>;
|
|
10
|
+
};
|
|
11
|
+
type ClerkMembershipListItem = {
|
|
12
|
+
readonly organization?: {
|
|
13
|
+
readonly id?: string;
|
|
14
|
+
};
|
|
15
|
+
readonly organizationId?: string;
|
|
16
|
+
readonly role?: string;
|
|
17
|
+
readonly publicUserData?: {
|
|
18
|
+
readonly userId?: string;
|
|
19
|
+
} | null;
|
|
20
|
+
};
|
|
21
|
+
type ClerkBackend = {
|
|
22
|
+
readonly users?: {
|
|
23
|
+
readonly getOrganizationMembershipList?: (args: {
|
|
24
|
+
readonly userId: string;
|
|
25
|
+
readonly limit?: number;
|
|
26
|
+
readonly offset?: number;
|
|
27
|
+
}) => Promise<{
|
|
28
|
+
readonly data?: readonly ClerkMembershipListItem[];
|
|
29
|
+
readonly totalCount?: number;
|
|
30
|
+
} | readonly ClerkMembershipListItem[]>;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
type ClerkGlobalRoles = string | ((claims: Readonly<Record<string, unknown>>) => readonly string[]);
|
|
34
|
+
type ClerkSubjectOptions = {
|
|
35
|
+
readonly memberships?: "active" | "all";
|
|
36
|
+
readonly backend?: ClerkBackend;
|
|
37
|
+
readonly customRoles?: RoleSource;
|
|
38
|
+
readonly permissions?: Readonly<Record<string, Permission>>;
|
|
39
|
+
readonly schema?: StandardSchemaV1;
|
|
40
|
+
readonly globalRoles?: ClerkGlobalRoles;
|
|
41
|
+
readonly features?: Readonly<Record<string, string>>;
|
|
42
|
+
readonly declared?: readonly string[];
|
|
43
|
+
};
|
|
44
|
+
type ClerkAuthObject = {
|
|
45
|
+
readonly userId?: string | null;
|
|
46
|
+
readonly orgId?: string | null;
|
|
47
|
+
readonly orgRole?: string | null;
|
|
48
|
+
readonly orgPermissions?: readonly string[] | null;
|
|
49
|
+
readonly sessionId?: string | null;
|
|
50
|
+
readonly sessionClaims?: Readonly<Record<string, unknown>> | null;
|
|
51
|
+
readonly has?: (...args: never[]) => unknown;
|
|
52
|
+
};
|
|
53
|
+
type ClerkSubjectResolverOptions = ClerkSubjectOptions & {
|
|
54
|
+
readonly cache?: RemotePdpCache;
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/clerk/subject.d.ts
|
|
58
|
+
export declare function subjectFromClerk(authObject: unknown, options?: ClerkSubjectOptions): Promise<Subject<ClerkPrincipal>>;
|
|
59
|
+
/**
|
|
60
|
+
* A resolver that keeps each user's `memberships: 'all'` list for
|
|
61
|
+
* `cache.ttl` (at most 30 seconds), so a removed membership grants until then.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createClerkSubjectResolver(options?: ClerkSubjectResolverOptions): (authObject: unknown) => Promise<Subject<ClerkPrincipal>>;
|
|
64
|
+
//#endregion
|
|
65
|
+
export type { ClerkAuthObject, ClerkBackend, ClerkGlobalRoles, ClerkMembershipListItem, ClerkPrincipal, ClerkSubjectOptions, ClerkSubjectResolverOptions };
|