permdock 0.1.0 → 0.3.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 +106 -47
- package/dist/a2a/index.d.ts +7 -16
- package/dist/a2a/index.js +59 -98
- package/dist/adapter-context-mlWsVGGg.js +23 -0
- package/dist/ai-sdk/index.d.ts +37 -16
- package/dist/ai-sdk/index.js +30 -13
- package/dist/approvals/index.d.ts +3 -3
- package/dist/approvals/index.js +5 -4
- package/dist/{approvals-DaxY-Bdg.js → approvals-DbYAuNkG.js} +17 -11
- package/dist/approvers-DT4AVyIg.js +52 -0
- package/dist/{arazzo-CTeVuXr5.js → arazzo-BAgw9ap6.js} +2 -2
- package/dist/{arazzo-aoTkqYsJ.js → arazzo-CKwwqFWz.js} +2 -2
- package/dist/authzen/index.d.ts +4 -13
- package/dist/authzen/index.js +16 -50
- package/dist/better-auth/index.d.ts +20 -3
- package/dist/better-auth/index.js +27 -7
- package/dist/better-supabase/index.d.ts +223 -0
- package/dist/better-supabase/index.js +648 -0
- package/dist/bind-C_ob3LKa.d.ts +25 -0
- package/dist/bind-CuzGytRf.js +97 -0
- package/dist/boundary-BM8a_P6E.js +13 -0
- package/dist/boundary-BmHxVH1J.d.ts +15 -0
- package/dist/canonical-json-DemiK4Vp.js +26 -0
- package/dist/{capability-BDG_nkxt.d.ts → capability-2kYTMWDv.d.ts} +2 -2
- package/dist/{capability-B68OFnZx.js → capability-4qPdO9gk.js} +7 -5
- package/dist/catalog/index.d.ts +1 -1
- package/dist/catalog/index.js +1 -1
- package/dist/catalog-CRW5Mx_B.js +2 -0
- package/dist/{catalog-H-vFGwWK.js → catalog-DWF5cYqB.js} +4 -4
- package/dist/{catalog-B0E6bggc.js → catalog-dFZdWCGN.js} +2 -2
- package/dist/{catalog-doc-BSo_Q_-6.js → catalog-doc-DdGm82XT.js} +20 -32
- package/dist/claude-agent/index.d.ts +5 -14
- package/dist/claude-agent/index.js +4 -10
- package/dist/clerk/index.d.ts +12 -3
- package/dist/clerk/index.js +26 -5
- package/dist/cli/bin.js +1 -1
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +2 -2
- package/dist/clients-C7zLFuWT.d.ts +12 -0
- package/dist/clients-DjU5ABMy.js +23 -0
- package/dist/cloud/index.d.ts +4 -5
- package/dist/cloud/index.js +20 -6
- package/dist/{cloud-BNQTrmrr.js → cloud-CB_ELYuX.js} +2 -2
- package/dist/{cloud-Cuxr6Czw.js → cloud-DWLXO2af.js} +7 -6
- package/dist/collect-DClJsheJ.js +83 -0
- package/dist/{collect-O-tOtbnk.js → collect-DSTE3ml9.js} +194 -42
- package/dist/collect-DSWOk19R.js +2 -0
- package/dist/{commands-BMh_Etm2.js → commands-DSxCqG9A.js} +16 -12
- package/dist/compile/index.d.ts +3 -0
- package/dist/compile/index.js +2 -0
- package/dist/{compile-D22iwvuV.js → compile-Ba4blROR.js} +85 -30
- package/dist/compile-BkRyBDBw.d.ts +94 -0
- package/dist/config-BJiM-xAm.js +157 -0
- package/dist/config-Dnszbv-6.js +36 -0
- package/dist/config-report-DMvWKUxL.js +44 -0
- package/dist/{connection-JvqwHODC.js → connection-CU8MQxRi.js} +1 -1
- package/dist/{context-CKEAabd7.js → context-Bcy85rGi.js} +36 -27
- package/dist/convex/index.d.ts +9 -4
- package/dist/convex/index.js +14 -4
- package/dist/create-B1d519XK.d.ts +245 -0
- package/dist/create-CMwIl-w2.js +253 -0
- package/dist/{credential-B_rkUNlY.js → credential-8P81ff4u.js} +26 -46
- package/dist/delegation-D8pUEuce.js +103 -0
- package/dist/{describe-Bt1YD5uS.js → describe-B_gVZEVi.js} +10 -15
- package/dist/{describe-DernyItf.d.ts → describe-DMYiCjJV.d.ts} +9 -10
- package/dist/{diff-x5Il8LVa.js → diff-2VaeChzX.js} +44 -11
- package/dist/{diff-BUzf5Poi.js → diff-DBIhz_f2.js} +2 -2
- package/dist/{doctor-Bqo6FwUa.js → doctor-BwCAMLx_.js} +2 -2
- package/dist/doctor-collect-CHk6XWOA.js +665 -0
- package/dist/doctor-igIiM_Hl.js +1194 -0
- package/dist/drizzle/index.d.ts +4 -3
- package/dist/drizzle/index.js +3 -3
- package/dist/elysia/index.d.ts +6 -28
- package/dist/elysia/index.js +16 -60
- package/dist/{errors-DSMnAVNa.js → errors-CWfoNg9N.js} +8 -4
- package/dist/{errors-Iy71s7Oj.js → errors-Cz5zn0mW.js} +17 -71
- package/dist/{errors-DbZ1YOnb.d.ts → errors-DPdqI50v.d.ts} +8 -21
- package/dist/{errors-m3u9TmDu.js → errors-DRnGZHzF.js} +4 -1
- package/dist/evaluation-items-CfCCejQd.js +40 -0
- package/dist/{evaluations-DsAU9ppl.js → evaluations-tz6D9A2G.js} +28 -46
- package/dist/eve/index.d.ts +6 -15
- package/dist/eve/index.js +7 -12
- package/dist/expiry-BoBJ8Tvc.js +7 -0
- package/dist/express/index.d.ts +6 -29
- package/dist/express/index.js +28 -58
- package/dist/fastify/index.d.ts +6 -29
- package/dist/fastify/index.js +16 -65
- package/dist/fields-BMl1RxoX.js +26 -0
- package/dist/{files-B_wAGYmt.js → files-DWUN9PzI.js} +5 -1
- package/dist/{fixtures-Cvaw0gDG.js → fixtures-ht28Cplr.js} +5 -2
- package/dist/{freeze-y1_jQL4v.js → freeze-CrU8nQeX.js} +31 -2
- package/dist/{from-snapshot-BMGnhmgv.js → from-snapshot-CTLijvdm.js} +66 -48
- package/dist/{grantee-Bv04_Vzf.js → grantee-Cv5Sogfv.js} +88 -7
- package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
- package/dist/{headers-B5RRv3Xm.js → headers-BZSDieNT.js} +1 -1
- package/dist/{headers-C8SHQccD.d.ts → headers-Cf-zWvsO.d.ts} +1 -1
- package/dist/helpers-H_KARDVC.js +421 -0
- package/dist/hono/index.d.ts +6 -28
- package/dist/hono/index.js +11 -43
- package/dist/{hosted-BwKQ1BTA.js → hosted-DJQw46hn.js} +6 -5
- package/dist/{http-GgVApX1k.js → http-BIhmLfCc.js} +4 -20
- package/dist/http-SO7qGttf.js +44 -0
- package/dist/ids-DC4V4CFu.js +18 -0
- package/dist/index-0nNqHspG.d.ts +6 -0
- package/dist/{index-xIxJLwOQ.d.ts → index-BNc7Wer_.d.ts} +75 -7
- package/dist/{index-CltcQ4Bf.d.ts → index-C7Tw7MaW.d.ts} +68 -5
- package/dist/{index-LF_hS-yn.d.ts → index-C8z4RjQV.d.ts} +1 -1
- package/dist/index.d.ts +14 -9
- package/dist/index.js +22 -17
- package/dist/instance-options-Dhhcnm3y.js +22 -0
- package/dist/instance-options-jARdwfPN.d.ts +11 -0
- package/dist/{parse-DPfIvFMU.js → json-schema-BsAflUGW.js} +28 -57
- package/dist/jwt/index.d.ts +10 -6
- package/dist/jwt/index.js +32 -13
- package/dist/kernel-_RRHmnMY.js +208 -0
- package/dist/kysely/index.d.ts +4 -3
- package/dist/kysely/index.js +3 -3
- package/dist/live-options-H2eG8dfJ.js +60 -0
- package/dist/{load-BZ24CpZP.js → load-DhWEB9P1.js} +16 -10
- package/dist/load-DwJUafYN.js +2 -0
- package/dist/manifest-iaoBXHKc.js +783 -0
- package/dist/manifest-uDS9y5de.d.ts +206 -0
- package/dist/{map-DowSO96j.js → map-AcxK9o_D.js} +4 -15
- package/dist/{map-claims-B_6I1Rn-.js → map-claims-Z4QZOiFF.js} +13 -4
- package/dist/map-error-pgUWNNtG.js +23 -0
- package/dist/may-use-DndQ5tQ-.js +77 -0
- package/dist/mcp/index.d.ts +54 -22
- package/dist/mcp/index.js +218 -178
- package/dist/nest/index.d.ts +26 -31
- package/dist/nest/index.js +75 -84
- package/dist/next/client.d.ts +7 -8
- package/dist/next/client.js +11 -9
- package/dist/next/index.d.ts +30 -47
- package/dist/next/index.js +45 -60
- package/dist/next/plugin.d.ts +1 -1
- package/dist/next/plugin.js +32 -1
- package/dist/node/index.d.ts +9 -28
- package/dist/node/index.js +11 -43
- package/dist/openai/index.d.ts +6 -15
- package/dist/openai/index.js +7 -20
- package/dist/openapi/index.d.ts +87 -4
- package/dist/openapi/index.js +3 -3
- package/dist/{openapi-DcqM8nU7.js → openapi-BqRBvAng.js} +237 -5
- package/dist/{openapi-DWD0Uc_4.js → openapi-CqqEbHsL.js} +5 -5
- package/dist/{openapi-import-BWRUNNeW.js → openapi-import-cmwetbzw.js} +1 -1
- package/dist/{openapi-CwePaF7C.js → openapi-l0xYHkcv.js} +3 -3
- package/dist/{openapi-schema-D8j_T9tO.js → openapi-schema--ARjyfQr.js} +2 -2
- package/dist/orpc/index.d.ts +15 -28
- package/dist/orpc/index.js +74 -117
- package/dist/otel/index.d.ts +2 -2
- package/dist/parse-BuyjxhZV.js +53 -0
- package/dist/parse-local-manifest-BrMozJCo.js +36 -0
- package/dist/parse-local-manifest-JLnaBH0S.d.ts +10 -0
- package/dist/pdp/index.d.ts +2 -2
- package/dist/pdp/index.js +14 -127
- package/dist/{permdock-yoZ7EjxX.js → permdock-CbgvLnuo.js} +672 -149
- package/dist/{permissions-B8vCg_bI.d.ts → permissions-CDgvKG5L.d.ts} +2 -2
- package/dist/{permissions-DC7GROPA.js → permissions-DVoF6dMt.js} +77 -15
- package/dist/{permissions-B4apnahQ.d.ts → permissions-DttnqqxC.d.ts} +34 -5
- package/dist/{permissions-CofRqesP.js → permissions-RJrovw98.js} +3 -3
- package/dist/{pins-CqE1jZuF.js → pins-8ILTftC9.js} +2 -2
- package/dist/{policy-Cq2fB8Q5.d.ts → policy-D2W7uv19.d.ts} +2 -2
- package/dist/{policy-CInmNGkM.d.ts → policy-IB6yxpC3.d.ts} +351 -42
- package/dist/{policy-ANp36PnI.js → policy-xyWg7QdR.js} +173 -22
- package/dist/powersync-BylawD_U.js +540 -0
- package/dist/powersync-DliZK_-y.js +62 -0
- package/dist/powersync-e_AZrKbg.js +2 -0
- package/dist/prisma/index.d.ts +3 -2
- package/dist/prisma/index.js +45 -20
- package/dist/{problem-Cgp9-KZA.js → problem-B43ztKIm.js} +74 -109
- package/dist/problem-details-DX075l9V.d.ts +7 -0
- package/dist/problem-details-_AMOYz-w.js +144 -0
- package/dist/{protected-BuPAycJT.d.ts → protected-BdnIEFkY.d.ts} +5 -4
- package/dist/protected-utU-SLuy.js +100 -0
- package/dist/protected-xAr24FEC.d.ts +40 -0
- package/dist/provider-CSQd7m92.js +52 -0
- package/dist/{provider-wTAUda2v.d.ts → provider-DZY281jO.d.ts} +1 -1
- package/dist/provider-store-Cfbvo4DE.js +43 -0
- package/dist/react/index.d.ts +7 -5
- package/dist/react/index.js +5 -4
- package/dist/react/provider-client.d.ts +1 -1
- package/dist/react/provider-client.js +1 -1
- package/dist/react-native/index.d.ts +166 -10
- package/dist/react-native/index.js +607 -85
- package/dist/{refs-ChLSxbST.js → refs-KYb4ntaz.js} +4 -3
- package/dist/{relations-r4soIFZB.js → relations-cjOL01hZ.js} +110 -31
- package/dist/replay-BsOyTrdV.js +28 -0
- package/dist/replay-CYyiLiwO.d.ts +5 -0
- package/dist/resource-ref-CaS9yVPi.js +20 -0
- package/dist/revocations-Bhr0aMIC.js +27 -0
- package/dist/{rls-BOFU3chG.js → rls-B4ur8nKQ.js} +8 -3
- package/dist/rls-DQtdgTHB.js +2521 -0
- package/dist/rls-fields-74oZPXWL.js +3582 -0
- package/dist/{rls-graph-DxQ39PJj.js → rls-graph-CHwx0V8q.js} +100 -36
- package/dist/{rls-import-CXV6LBlS.js → rls-import-BTFVk3jH.js} +7 -6
- package/dist/{rls-migrate-DrFPbf8p.js → rls-migrate-CN4TlJTO.js} +6 -5
- package/dist/rls-ownership-RuFqaqGz.js +843 -0
- package/dist/rls-shared-Cewd_-zI.js +495 -0
- package/dist/rls-verify-CVQTHTh5.js +746 -0
- package/dist/{row-check-BajTgQZ-.d.ts → row-check-Dt35czLy.d.ts} +12 -15
- package/dist/row-conditions-h2HythXQ.js +27 -0
- package/dist/rpc-DL9Sqvb1.js +89 -0
- package/dist/{run-CJ6UvS3a.js → run-DKDbM4Du.js} +31 -12
- package/dist/runtime-CB8gQFvS.js +11 -0
- package/dist/{saas-BRrZzJkM.js → saas-DhpJjnBA.js} +17 -7
- package/dist/{schema-P8yoma__.js → schema-D3MnDMxa.js} +8 -4
- package/dist/scim/index.d.ts +1 -1
- package/dist/scim/index.js +1 -1
- package/dist/{scim-9NFa0XVZ.js → scim-BFGBBAqR.js} +1 -1
- package/dist/{scopes-cKVp_WTw.js → scopes-CVdPrWN-.js} +35 -8
- package/dist/server/index.d.ts +22 -11
- package/dist/server/index.js +11 -8
- package/dist/{credentials-BgRX3WEg.js → server-DlZ28Oz5.js} +1 -1
- package/dist/shared-DRu8VFVM.js +123 -0
- package/dist/{sink-Cfr9-7YC.d.ts → sink-B1fZzIMf.d.ts} +1 -1
- package/dist/skills-Biq5uup3.js +192 -0
- package/dist/{skills-C_lpV4Jx.js → skills-Bx-U0irG.js} +10 -4
- package/dist/{snapshot-DE8dE_hz.js → snapshot-Enxd0n-s.js} +138 -214
- package/dist/snapshot-cache-B-LxUahj.d.ts +45 -0
- package/dist/snapshot-cache-D6jLelln.js +44 -0
- package/dist/solid/index.d.ts +39 -9
- package/dist/solid/index.js +76 -85
- package/dist/sources-4p0-4xQm.js +545 -0
- package/dist/sources-BdOYLw9j.d.ts +192 -0
- package/dist/{sql-Bll1d7y0.js → sql-xdg5f4Fi.js} +6 -1
- package/dist/{src-CTNT-PBW.js → src-BDwEZWrZ.js} +149 -11
- package/dist/ssf/index.d.ts +3 -2
- package/dist/ssf/index.js +3 -29
- package/dist/store-DMAWwAJV.js +371 -0
- package/dist/{store-Bq90395i.d.ts → store-jOBYpiXC.d.ts} +13 -4
- package/dist/store-options-ByhZq1jV.js +716 -0
- package/dist/{stores-CkG2HrSg.js → stores-BT2pSCub.js} +10 -63
- package/dist/{stores-CvOnu_2T.d.ts → stores-C0IMQrGI.d.ts} +20 -9
- package/dist/{stream-BhMfZOwr.d.ts → stream-D1RXubw2.d.ts} +2 -2
- package/dist/{stream-Q_xlB6Ko.js → stream-DDpvynSB.js} +16 -2
- package/dist/subject-settings-BwBmCdTR.js +128 -0
- package/dist/supabase/index.d.ts +133 -6
- package/dist/supabase/index.js +4 -3
- package/dist/supabase/middleware.d.ts +32 -27
- package/dist/supabase/middleware.js +56 -22
- package/dist/{supabase-D8UlBA7Z.js → supabase-Boqb9a_Y.js} +3 -3
- package/dist/{supabase-DTxGtYdi.js → supabase-C0qESOa-.js} +347 -367
- package/dist/supabase-config-BpPXt3x1.js +472 -0
- package/dist/supabase-hook-6sYLXg_u.js +2 -0
- package/dist/{supabase-hook-D_OqGb_V.js → supabase-hook-CSLQ4zJ3.js} +1037 -705
- package/dist/supautils-Cn4R4cJ4.js +91 -0
- package/dist/svelte/PermissionBoundary.svelte +37 -0
- package/dist/svelte/Protected.svelte +8 -2
- package/dist/svelte/index.d.ts +9 -6
- package/dist/svelte/index.js +61 -7
- package/dist/svelte/runtime.d.ts +4 -3
- package/dist/svelte/runtime.js +4 -3
- package/dist/svelte/source.d.ts +9 -6
- package/dist/svelte/source.js +7 -4
- package/dist/terminal/index.d.ts +6 -14
- package/dist/terminal/index.js +44 -32
- package/dist/testing/index.d.ts +105 -16
- package/dist/testing/index.js +504 -40
- package/dist/testing/saas/index.d.ts +4 -4
- package/dist/testing/saas/index.js +2 -2
- package/dist/testing/saas/permissions.d.ts +1 -1
- package/dist/testing/saas/permissions.js +1 -1
- package/dist/token-CIWxJOCh.js +50 -0
- package/dist/trpc/index.d.ts +7 -26
- package/dist/trpc/index.js +17 -100
- package/dist/types-BnIEz1sU.d.ts +48 -0
- package/dist/{types-CxquUByI.d.ts → types-Bvc4oWT6.d.ts} +1 -1
- package/dist/{sources-DOpW5Ila.d.ts → types-C97IskBw.d.ts} +86 -127
- package/dist/types-CKNSyIf_.d.ts +52 -0
- package/dist/types-Cq_H8N_X.d.ts +197 -0
- package/dist/{types-D6Z6-rKJ.d.ts → types-DbjRN55U.d.ts} +273 -22
- package/dist/{types-BBK-exvJ.d.ts → types-Dnemwd77.d.ts} +7 -1
- package/dist/{types-BvBk1wgn.d.ts → types-DxiCGmmd.d.ts} +5 -3
- package/dist/{types-B9dmiiab.d.ts → types-QCuYJh4q.d.ts} +1 -1
- package/dist/{types-B8w5PFtS.d.ts → types-aqOHTHcp.d.ts} +17 -1
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +10 -9
- package/dist/usage-DorAJiU_.js +2 -0
- package/dist/{usage-1ozMubLY.js → usage-GTixvDDU.js} +2 -2
- package/dist/{usage-CUnK6Ou9.js → usage-ItS7nLcl.js} +225 -62
- package/dist/validation-error-Ba264OaJ.d.ts +26 -0
- package/dist/validation-error-CnjZ4t92.js +33 -0
- package/dist/{validity-D0uRmJKJ.js → validity-uOp8UpYn.js} +57 -36
- package/dist/{verifier-B90agnhl.js → verifier-BxBo6I44.js} +10 -5
- package/dist/version-BvacVTZR.js +17 -0
- package/dist/views-Soe7bGSC.js +95 -0
- package/dist/{vocabulary-Dk0fs-Jk.d.ts → vocabulary-DA8a8zif.d.ts} +1 -1
- package/dist/vue/index.d.ts +35 -13
- package/dist/vue/index.js +86 -93
- package/dist/watch-BwxLTYMZ.js +2 -0
- package/dist/watch-DVBJ9cBq.js +128 -0
- package/dist/webmcp/index.d.ts +2 -2
- package/dist/webmcp/index.js +7 -13
- package/package.json +62 -36
- package/schemas/approval-request-v1.json +175 -0
- package/schemas/catalog-v1.json +29 -1
- package/schemas/supabase-claims-v1.json +6 -1
- package/schemas/supabase-manifest-v1.json +150 -6
- package/skills/permdock/SKILL.md +7 -7
- package/skills/permdock-agents/SKILL.md +5 -5
- package/skills/permdock-agents/references/runtimes.md +12 -10
- package/skills/permdock-approvals/SKILL.md +4 -4
- package/skills/permdock-approvals/references/stores-and-resume.md +15 -4
- package/skills/permdock-audit/SKILL.md +3 -3
- package/skills/permdock-credentials/SKILL.md +4 -4
- package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
- package/skills/permdock-data/SKILL.md +4 -4
- package/skills/permdock-data/references/queries-and-rls.md +14 -6
- package/skills/permdock-data/references/relationships.md +5 -3
- package/skills/permdock-tenancy/SKILL.md +9 -6
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +14 -8
- package/skills/permdock-wire/SKILL.md +4 -4
- package/skills/permdock-wire/references/adapters.md +42 -30
- package/skills/permdock-wire/references/policy-options.md +5 -3
- package/dist/approvers-aH0PJkmf.js +0 -20
- package/dist/catalog-idsHc0vo.js +0 -2
- package/dist/collect-B7_TIfmg.js +0 -49
- package/dist/collect-fRPAQIWb.js +0 -2
- package/dist/compile-CQbvyIBr.d.ts +0 -30
- package/dist/config-BPYmjTOp.js +0 -26
- package/dist/context-gtAwAILx.js +0 -6
- package/dist/create-BKF3dgFk.d.ts +0 -162
- package/dist/create-CSkhDU9T.js +0 -222
- package/dist/doctor-BGle8Gqi.js +0 -1314
- package/dist/helpers-DnSOrhB9.js +0 -682
- package/dist/index-fG6NSXlc.d.ts +0 -9
- package/dist/kernel-YOGCWNLf.js +0 -211
- package/dist/load-QOOm1z70.js +0 -2
- package/dist/manifest-DDQbC6K0.d.ts +0 -118
- package/dist/map-error-RJ3ZsUyA.js +0 -16
- package/dist/may-use-CnFEjVEp.js +0 -37
- package/dist/pg-4GJWDUxG.js +0 -953
- package/dist/plugin-4gr7IxFJ.js +0 -65
- package/dist/protected-B4K3BKoX.js +0 -138
- package/dist/protected-wY7nXhY9.d.ts +0 -23
- package/dist/provider-_wx46HpB.js +0 -48
- package/dist/rls-CJVja9Ww.js +0 -2119
- package/dist/rls-helpers-BxRuif0l.js +0 -1346
- package/dist/runtime-DP9ttFh1.js +0 -27
- package/dist/skills-Dx3QLnMY.js +0 -110
- package/dist/source-DoBBYJi2.js +0 -6
- package/dist/sources-DVHM3Mwq.js +0 -284
- package/dist/store-C6hFW6ta.js +0 -508
- package/dist/subject-settings-xt7V845g.js +0 -82
- package/dist/supabase-hook-DW-xP4hU.js +0 -2
- package/dist/types-DbWdEfcm.d.ts +0 -87
- package/dist/types-bva3i4Gf.d.ts +0 -98
- package/dist/types-i4BAOvdb.d.ts +0 -97
- package/dist/usage-PyEor6GA.js +0 -2
- package/dist/version-CnSh33Fj.js +0 -16
package/dist/mcp/index.js
CHANGED
|
@@ -1,20 +1,71 @@
|
|
|
1
1
|
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
-
import { n as freezeDeep } from "../freeze-
|
|
3
|
-
import { t as annotationsFor } from "../permissions-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { n as freezeDeep } from "../freeze-CrU8nQeX.js";
|
|
3
|
+
import { t as annotationsFor } from "../permissions-DVoF6dMt.js";
|
|
4
|
+
import { a as wireDenials, i as stepUpOf } from "../problem-details-_AMOYz-w.js";
|
|
5
|
+
import { t as describe } from "../describe-B_gVZEVi.js";
|
|
6
|
+
import { i as scopesReaching, r as challengeScope } from "../permdock-CbgvLnuo.js";
|
|
7
|
+
import { n as resourceRef } from "../resource-ref-CaS9yVPi.js";
|
|
7
8
|
import { t as anonymousSubject } from "../subject-C6dLxqHU.js";
|
|
8
|
-
import { t as mayUse } from "../may-use-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { t as mayUse } from "../may-use-DndQ5tQ-.js";
|
|
10
|
+
import { c as protectedResourceMetadataUrl, n as bearerChallenge } from "../problem-B43ztKIm.js";
|
|
11
|
+
import { t as clientNameOf } from "../clients-DjU5ABMy.js";
|
|
12
|
+
import { n as mapClaimsToSubject } from "../map-claims-Z4QZOiFF.js";
|
|
13
|
+
import { t as instanceOptions } from "../instance-options-Dhhcnm3y.js";
|
|
14
|
+
import { n as createAgentKernel } from "../kernel-_RRHmnMY.js";
|
|
12
15
|
import { t as boundedMap } from "../lru-8q4WZjBV.js";
|
|
16
|
+
//#region src/mcp/subject.ts
|
|
17
|
+
const DEFAULT_MCP_ACTOR_KIND = "mcp-client";
|
|
18
|
+
/** `kind`, or the default when absent; `undefined` for a kind that is not a non-empty string. */
|
|
19
|
+
function mcpActorKind(kind) {
|
|
20
|
+
if (kind === void 0) return DEFAULT_MCP_ACTOR_KIND;
|
|
21
|
+
return typeof kind === "string" && kind !== "" ? kind : void 0;
|
|
22
|
+
}
|
|
23
|
+
function isRecord$1(value) {
|
|
24
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Maps the `AuthInfo` the MCP SDK's bearer verification produced to a
|
|
28
|
+
* `Subject`: the principal from the verified claims in `extra`, the client
|
|
29
|
+
* as an actor of kind `actorKind` (`mcp-client` by default), the granted
|
|
30
|
+
* scopes as the delegation. Never verifies and never throws; anything
|
|
31
|
+
* unusable, including an `actorKind` that is not a non-empty string, is
|
|
32
|
+
* the anonymous subject.
|
|
33
|
+
*/
|
|
34
|
+
function subjectFromMcp(authInfo, options = {}) {
|
|
35
|
+
try {
|
|
36
|
+
const kind = mcpActorKind(options.actorKind);
|
|
37
|
+
if (authInfo === void 0 || !isRecord$1(authInfo.extra) || kind === void 0) return anonymousSubject();
|
|
38
|
+
const claims = compact({
|
|
39
|
+
...authInfo.extra,
|
|
40
|
+
authorization_details: authInfo.extra["authorizationDetails"] ?? authInfo.extra["authorization_details"],
|
|
41
|
+
scope: authInfo.scopes?.join(" "),
|
|
42
|
+
client_id: authInfo.clientId,
|
|
43
|
+
exp: authInfo.expiresAt
|
|
44
|
+
});
|
|
45
|
+
const mapped = mapClaimsToSubject(claims, options);
|
|
46
|
+
if (mapped.invalidClaims || mapped.invalidChain || mapped.subject.principal === null) return anonymousSubject();
|
|
47
|
+
const clientId = authInfo.clientId;
|
|
48
|
+
return freezeDeep(compact({
|
|
49
|
+
...mapped.subject,
|
|
50
|
+
actor: typeof clientId === "string" && clientId !== "" ? compact({
|
|
51
|
+
id: clientId,
|
|
52
|
+
kind,
|
|
53
|
+
client: clientNameOf(options.clients, clientId)
|
|
54
|
+
}) : mapped.subject.actor
|
|
55
|
+
}));
|
|
56
|
+
} catch {
|
|
57
|
+
return anonymousSubject();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
13
61
|
//#region src/mcp/create.ts
|
|
14
62
|
/** `_meta` key on `tools/call`, `resources/read` and `prompts/get` carrying an approval token. */
|
|
15
63
|
const APPROVAL_META_KEY = "dev.permdock/approval";
|
|
16
64
|
const SESSIONS_PER_SERVER = 1e3;
|
|
17
65
|
const CLIENT_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
|
|
66
|
+
const PROTOCOL_VERSION = "io.modelcontextprotocol/protocolVersion";
|
|
67
|
+
/** The first protocol revision whose list results define `ttlMs` and `cacheScope`. */
|
|
68
|
+
const CACHEABLE_LISTS_SINCE = "2026-07-28";
|
|
18
69
|
/** What a completion re-check still accepts after the handler ran. */
|
|
19
70
|
function stillAllowed(decision, approved) {
|
|
20
71
|
switch (decision.outcome) {
|
|
@@ -24,11 +75,11 @@ function stillAllowed(decision, approved) {
|
|
|
24
75
|
default: return decision;
|
|
25
76
|
}
|
|
26
77
|
}
|
|
27
|
-
function isRecord
|
|
78
|
+
function isRecord(value) {
|
|
28
79
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
29
80
|
}
|
|
30
81
|
function contextOf(value) {
|
|
31
|
-
return isRecord
|
|
82
|
+
return isRecord(value) ? value : {};
|
|
32
83
|
}
|
|
33
84
|
function approvalTokenOf(context) {
|
|
34
85
|
let fromState;
|
|
@@ -53,8 +104,8 @@ function delegationOf(authInfo) {
|
|
|
53
104
|
authorizationDetails: authorizationDetailsOf(authInfo)
|
|
54
105
|
});
|
|
55
106
|
}
|
|
56
|
-
function hasScope(authInfo,
|
|
57
|
-
return (authInfo.scopes ?? []).includes(scope);
|
|
107
|
+
function hasScope(authInfo, scopes) {
|
|
108
|
+
return scopes.some((scope) => (authInfo.scopes ?? []).includes(scope));
|
|
58
109
|
}
|
|
59
110
|
function resourceMetadataOf(authInfo) {
|
|
60
111
|
if (authInfo.resourceMetadataUrl !== void 0) return authInfo.resourceMetadataUrl;
|
|
@@ -69,11 +120,20 @@ function sameResource(expected, actual) {
|
|
|
69
120
|
return false;
|
|
70
121
|
}
|
|
71
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Whether the request was sent under a revision that defines `cacheScope` on
|
|
125
|
+
* list results. Only those requests carry the per-request envelope; a
|
|
126
|
+
* 2025-era request has none and gets no cache fields.
|
|
127
|
+
*/
|
|
128
|
+
function definesCacheScope(context) {
|
|
129
|
+
const version = context.mcpReq?.envelope?.[PROTOCOL_VERSION];
|
|
130
|
+
return typeof version === "string" && version >= CACHEABLE_LISTS_SINCE;
|
|
131
|
+
}
|
|
72
132
|
function acceptsUrlElicitation(context, fallback) {
|
|
73
133
|
const fromEnvelope = context.mcpReq?.envelope?.[CLIENT_CAPABILITIES];
|
|
74
|
-
const capabilities = isRecord
|
|
75
|
-
if (!isRecord
|
|
76
|
-
return isRecord
|
|
134
|
+
const capabilities = isRecord(fromEnvelope) ? fromEnvelope : fallback?.();
|
|
135
|
+
if (!isRecord(capabilities) || !isRecord(capabilities["elicitation"])) return false;
|
|
136
|
+
return isRecord(capabilities["elicitation"]["url"]);
|
|
77
137
|
}
|
|
78
138
|
function withParams(at, params) {
|
|
79
139
|
let url;
|
|
@@ -99,16 +159,6 @@ function urlElicitation(key, message, url, requestState) {
|
|
|
99
159
|
requestState
|
|
100
160
|
});
|
|
101
161
|
}
|
|
102
|
-
function resourceRef(permission, data) {
|
|
103
|
-
if (isRecord$1(data)) {
|
|
104
|
-
const id = data["id"];
|
|
105
|
-
if (typeof id === "string" || typeof id === "number") return {
|
|
106
|
-
type: permission.resource,
|
|
107
|
-
id: String(id)
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
return { type: permission.resource };
|
|
111
|
-
}
|
|
112
162
|
function deniedRefusal(decision, permission, data) {
|
|
113
163
|
const alternatives = decision.alternatives.map((leaf) => leaf.key);
|
|
114
164
|
const resource = resourceRef(permission, data);
|
|
@@ -147,6 +197,24 @@ function plainRefusal(permission, text, extra) {
|
|
|
147
197
|
}
|
|
148
198
|
};
|
|
149
199
|
}
|
|
200
|
+
function tenantOf(tenant) {
|
|
201
|
+
if (typeof tenant !== "function") return tenant;
|
|
202
|
+
return (call) => tenant(call.authInfo ?? {});
|
|
203
|
+
}
|
|
204
|
+
function failedRefusal(permission, failure) {
|
|
205
|
+
switch (failure) {
|
|
206
|
+
case "load-failed": return plainRefusal(permission, `Denied: ${permission.key} failed closed.`, { denials: [{
|
|
207
|
+
role: null,
|
|
208
|
+
reason: "validation"
|
|
209
|
+
}] });
|
|
210
|
+
case "no-data": return plainRefusal(permission, `Denied: ${permission.key} found nothing to decide on.`, { denials: [{
|
|
211
|
+
role: null,
|
|
212
|
+
reason: "validation"
|
|
213
|
+
}] });
|
|
214
|
+
case "failed": return plainRefusal(permission, `Denied: ${permission.key} failed closed.`, {});
|
|
215
|
+
default: return failure;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
150
218
|
function toolRefusal(refusal) {
|
|
151
219
|
if (refusal.inputRequired !== void 0) return refusal.inputRequired;
|
|
152
220
|
return {
|
|
@@ -159,8 +227,8 @@ function toolRefusal(refusal) {
|
|
|
159
227
|
};
|
|
160
228
|
}
|
|
161
229
|
function requirePermission(kind, name, config) {
|
|
162
|
-
const permission = isRecord
|
|
163
|
-
if (!isRecord
|
|
230
|
+
const permission = isRecord(config) ? config["permission"] : void 0;
|
|
231
|
+
if (!isRecord(permission) || typeof permission["key"] !== "string") throw new TypeError(`permdock/mcp: ${kind} ${name} has no permission; every guarded registration needs one.`);
|
|
164
232
|
return permission;
|
|
165
233
|
}
|
|
166
234
|
function sessionKey(context) {
|
|
@@ -170,13 +238,21 @@ function throwRefusal(refusal) {
|
|
|
170
238
|
if (refusal.inputRequired !== void 0) return refusal.inputRequired;
|
|
171
239
|
throw new Error(refusal.text);
|
|
172
240
|
}
|
|
173
|
-
function
|
|
241
|
+
function declaredScopes(name, value) {
|
|
242
|
+
if (value === void 0) return;
|
|
243
|
+
const scopes = Array.isArray(value) ? value : [];
|
|
244
|
+
const names = scopes.filter((scope) => typeof scope === "string" && scope !== "");
|
|
245
|
+
const [first, ...rest] = names;
|
|
246
|
+
if (first === void 0 || names.length !== scopes.length) throw new TypeError(`permdock/mcp: tool ${name} sets oauthScopes, which must be a non-empty list of scope names.`);
|
|
247
|
+
return Object.freeze([first, ...rest]);
|
|
248
|
+
}
|
|
249
|
+
function challengeFor(own, reaching, challenged) {
|
|
174
250
|
return async (context) => {
|
|
175
251
|
const first = await own?.(context);
|
|
176
252
|
if (first !== void 0) return first;
|
|
177
253
|
const authInfo = context.authInfo;
|
|
178
|
-
if (authInfo === void 0 || hasScope(authInfo,
|
|
179
|
-
return { scopes: [
|
|
254
|
+
if (authInfo === void 0 || hasScope(authInfo, reaching)) return;
|
|
255
|
+
return { scopes: [challenged] };
|
|
180
256
|
};
|
|
181
257
|
}
|
|
182
258
|
function guardUpdates(registered, wrap, rename, currentName) {
|
|
@@ -192,40 +268,35 @@ function guardUpdates(registered, wrap, rename, currentName) {
|
|
|
192
268
|
};
|
|
193
269
|
}
|
|
194
270
|
function createPermDock(policy, options) {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
let tenant;
|
|
204
|
-
try {
|
|
205
|
-
tenant = typeof options.tenant === "function" ? await options.tenant(material) : options.tenant;
|
|
206
|
-
} catch {
|
|
207
|
-
tenant = void 0;
|
|
208
|
-
}
|
|
209
|
-
const clientId = authInfo?.clientId;
|
|
210
|
-
const built = await createPermDock$1(policy, user, compact({
|
|
211
|
-
tenant,
|
|
212
|
-
actor: typeof clientId === "string" && clientId !== "" ? {
|
|
271
|
+
const actorKind = mcpActorKind(options.actorKind);
|
|
272
|
+
if (actorKind === void 0) throw new TypeError("permdock/mcp: actorKind must be a non-empty string");
|
|
273
|
+
const kernel = createAgentKernel(policy, compact({
|
|
274
|
+
subject: (call) => options.subject(call.authInfo ?? {}),
|
|
275
|
+
actor: (call) => {
|
|
276
|
+
const clientId = call.authInfo?.clientId;
|
|
277
|
+
return typeof clientId === "string" && clientId !== "" ? compact({
|
|
213
278
|
id: clientId,
|
|
214
|
-
kind:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
};
|
|
279
|
+
kind: actorKind,
|
|
280
|
+
client: clientNameOf(options.clients, clientId)
|
|
281
|
+
}) : void 0;
|
|
282
|
+
},
|
|
283
|
+
delegation: (call) => call.authInfo === void 0 ? void 0 : delegationOf(call.authInfo),
|
|
284
|
+
tenant: tenantOf(options.tenant),
|
|
285
|
+
store: options.store,
|
|
286
|
+
adapter: "mcp",
|
|
287
|
+
boundary: "mcp-args",
|
|
288
|
+
wrap: options.otel,
|
|
289
|
+
...instanceOptions(options)
|
|
290
|
+
}));
|
|
227
291
|
const forThisServer = (authInfo) => options.resource === void 0 || sameResource(options.resource, authInfo.resource);
|
|
228
|
-
const
|
|
292
|
+
const reachOf = (permission, declared) => declared === void 0 ? {
|
|
293
|
+
scopes: scopesReaching(policy, permission),
|
|
294
|
+
challenge: challengeScope(policy, permission)
|
|
295
|
+
} : {
|
|
296
|
+
scopes: declared,
|
|
297
|
+
challenge: declared[0]
|
|
298
|
+
};
|
|
299
|
+
const reachable = (authInfo, reach) => authInfo === void 0 ? options.requireAuthInfo !== true : forThisServer(authInfo) && hasScope(authInfo, reach.scopes);
|
|
229
300
|
const approvalInput = async (decision, handlerContext, context, capabilities) => {
|
|
230
301
|
const at = options.approval?.at;
|
|
231
302
|
if (at === void 0 || !acceptsUrlElicitation(context, capabilities)) return;
|
|
@@ -258,7 +329,7 @@ function createPermDock(policy, options) {
|
|
|
258
329
|
inputRequired: url === void 0 ? void 0 : urlElicitation("step_up", `Sign in again to use ${permission.key}.`, url, void 0)
|
|
259
330
|
});
|
|
260
331
|
};
|
|
261
|
-
const check = async (permission, load, context, handlerContext, capabilities, completion) => {
|
|
332
|
+
const check = async (permission, reach, load, context, handlerContext, capabilities, completion) => {
|
|
262
333
|
const authInfo = context.http?.authInfo;
|
|
263
334
|
if (authInfo === void 0 && options.requireAuthInfo === true) return {
|
|
264
335
|
ok: false,
|
|
@@ -268,99 +339,80 @@ function createPermDock(policy, options) {
|
|
|
268
339
|
ok: false,
|
|
269
340
|
refusal: plainRefusal(permission, "Denied: the token was not issued for this server.", { error: "invalid_token" })
|
|
270
341
|
};
|
|
271
|
-
if (authInfo !== void 0 && !hasScope(authInfo,
|
|
342
|
+
if (authInfo !== void 0 && !hasScope(authInfo, reach.scopes)) {
|
|
272
343
|
const resourceMetadata = resourceMetadataOf(authInfo);
|
|
344
|
+
const challenged = reach.challenge;
|
|
273
345
|
return {
|
|
274
346
|
ok: false,
|
|
275
|
-
refusal: plainRefusal(permission, `Denied: ${permission.key} needs the ${
|
|
347
|
+
refusal: plainRefusal(permission, `Denied: ${permission.key} needs the ${challenged} scope.`, compact({
|
|
276
348
|
error: "insufficient_scope",
|
|
277
|
-
scope:
|
|
349
|
+
scope: challenged,
|
|
278
350
|
resource_metadata: resourceMetadata,
|
|
279
351
|
www_authenticate: bearerChallenge(compact({
|
|
280
352
|
error: "insufficient_scope",
|
|
281
|
-
scopes: [
|
|
353
|
+
scopes: [challenged],
|
|
282
354
|
resourceMetadata
|
|
283
355
|
}))
|
|
284
356
|
}))
|
|
285
357
|
};
|
|
286
358
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (data === null || data === void 0) return {
|
|
359
|
+
const binding = compact({
|
|
360
|
+
permission,
|
|
361
|
+
data: load === void 0 ? void 0 : () => load()
|
|
362
|
+
});
|
|
363
|
+
const call = compact({ authInfo });
|
|
364
|
+
if (completion !== void 0) {
|
|
365
|
+
const rechecked = await kernel.check(binding, void 0, call, { simulate: true });
|
|
366
|
+
if (!rechecked.ok) return {
|
|
367
|
+
ok: false,
|
|
368
|
+
refusal: failedRefusal(permission, rechecked.failure)
|
|
369
|
+
};
|
|
370
|
+
if (stillAllowed(rechecked.raw, completion.approved)) return { ok: true };
|
|
371
|
+
return {
|
|
301
372
|
ok: false,
|
|
302
|
-
refusal: plainRefusal(permission, `Denied: ${permission.key}
|
|
303
|
-
role: null,
|
|
304
|
-
reason: "validation"
|
|
305
|
-
}] })
|
|
373
|
+
refusal: rechecked.raw.outcome === "denied" ? deniedRefusal(rechecked.raw, permission, rechecked.data) : plainRefusal(permission, `Denied: ${permission.key} was revoked before the call completed.`, {})
|
|
306
374
|
};
|
|
307
375
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
376
|
+
const checked = await kernel.check(binding, void 0, call, compact({ resumeToken: approvalTokenOf(context) }));
|
|
377
|
+
if (!checked.ok) return {
|
|
378
|
+
ok: false,
|
|
379
|
+
refusal: failedRefusal(permission, checked.failure)
|
|
380
|
+
};
|
|
381
|
+
const { raw, decision, data } = checked;
|
|
382
|
+
switch (decision.outcome) {
|
|
383
|
+
case "granted": return raw.outcome === "approval-required" ? {
|
|
384
|
+
ok: true,
|
|
385
|
+
approved: raw.token
|
|
386
|
+
} : { ok: true };
|
|
387
|
+
case "denied": return {
|
|
388
|
+
ok: false,
|
|
389
|
+
refusal: decision.denials.some((denial) => denial.reason === "insufficient-user-authentication") ? stepUpRefusal(decision, permission, data, context, capabilities) : deniedRefusal(decision, permission, data)
|
|
390
|
+
};
|
|
391
|
+
case "approval-required": try {
|
|
317
392
|
return {
|
|
318
|
-
ok: false,
|
|
319
|
-
refusal: raw.outcome === "denied" ? deniedRefusal(raw, permission, data) : plainRefusal(permission, `Denied: ${permission.key} was revoked before the call completed.`, {})
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
const decision = await resumeDecision({
|
|
323
|
-
decision: raw,
|
|
324
|
-
permission,
|
|
325
|
-
subject: permdock.subject,
|
|
326
|
-
store: options.store,
|
|
327
|
-
resource: resourceRef(permission, data),
|
|
328
|
-
adapter: "mcp",
|
|
329
|
-
token: approvalTokenOf(context) ?? await storedApprovalToken(options.store, raw, false)
|
|
330
|
-
});
|
|
331
|
-
switch (decision.outcome) {
|
|
332
|
-
case "granted": return raw.outcome === "approval-required" ? {
|
|
333
|
-
ok: true,
|
|
334
|
-
approved: raw.token
|
|
335
|
-
} : { ok: true };
|
|
336
|
-
case "denied": return {
|
|
337
|
-
ok: false,
|
|
338
|
-
refusal: decision.denials.some((denial) => denial.reason === "insufficient-user-authentication") ? stepUpRefusal(decision, permission, data, context, capabilities) : deniedRefusal(decision, permission, data)
|
|
339
|
-
};
|
|
340
|
-
case "approval-required": return {
|
|
341
393
|
ok: false,
|
|
342
394
|
refusal: compact({
|
|
343
395
|
...approvalRefusal(decision, permission, data),
|
|
344
396
|
inputRequired: await approvalInput(decision, handlerContext, context, capabilities)
|
|
345
397
|
})
|
|
346
398
|
};
|
|
347
|
-
|
|
399
|
+
} catch {
|
|
400
|
+
return {
|
|
401
|
+
ok: false,
|
|
402
|
+
refusal: failedRefusal(permission, "failed")
|
|
403
|
+
};
|
|
348
404
|
}
|
|
349
|
-
|
|
350
|
-
return {
|
|
351
|
-
ok: false,
|
|
352
|
-
refusal: plainRefusal(permission, `Denied: ${permission.key} failed closed.`, {})
|
|
353
|
-
};
|
|
405
|
+
default: return decision;
|
|
354
406
|
}
|
|
355
407
|
};
|
|
356
|
-
const visible = async (context, permissionOf, keys) => {
|
|
408
|
+
const visible = async (context, permissionOf, keys, declaredOf = () => void 0) => {
|
|
357
409
|
const authInfo = context.http?.authInfo;
|
|
358
410
|
const shown = /* @__PURE__ */ new Set();
|
|
359
411
|
const guarded = [];
|
|
360
412
|
for (const key of keys) {
|
|
361
413
|
const permission = permissionOf(key);
|
|
362
414
|
if (permission === void 0) shown.add(key);
|
|
363
|
-
else if (reachable(authInfo, permission)) guarded.push({
|
|
415
|
+
else if (reachable(authInfo, reachOf(permission, declaredOf(key)))) guarded.push({
|
|
364
416
|
key,
|
|
365
417
|
permission
|
|
366
418
|
});
|
|
@@ -368,7 +420,7 @@ function createPermDock(policy, options) {
|
|
|
368
420
|
if (guarded.length === 0) return shown;
|
|
369
421
|
let permdock;
|
|
370
422
|
try {
|
|
371
|
-
permdock = await
|
|
423
|
+
permdock = await kernel.instance(compact({ authInfo }));
|
|
372
424
|
} catch {
|
|
373
425
|
return shown;
|
|
374
426
|
}
|
|
@@ -379,25 +431,28 @@ function createPermDock(policy, options) {
|
|
|
379
431
|
const raw = params.at(-1);
|
|
380
432
|
const context = contextOf(raw);
|
|
381
433
|
const loader = load === void 0 ? void 0 : () => load(...dataArgs(params));
|
|
382
|
-
const
|
|
434
|
+
const reach = extra.reach ?? reachOf(permission, void 0);
|
|
435
|
+
const checked = await check(permission, reach, loader, context, raw, extra.capabilities);
|
|
383
436
|
let result;
|
|
384
437
|
if (checked.ok) {
|
|
385
438
|
result = await handler(...params);
|
|
386
439
|
if (extra.longRunning === true) {
|
|
387
|
-
const again = await check(permission, loader, context, raw, extra.capabilities, { approved: checked.approved });
|
|
440
|
+
const again = await check(permission, reach, loader, context, raw, extra.capabilities, { approved: checked.approved });
|
|
388
441
|
if (!again.ok) result = onRefusal(again.refusal);
|
|
389
442
|
}
|
|
390
443
|
} else result = onRefusal(checked.refusal);
|
|
391
444
|
await extra.after?.(context);
|
|
392
445
|
return result;
|
|
393
446
|
};
|
|
394
|
-
const protectServer = (server) => {
|
|
447
|
+
const protectServer = (server, enforcement) => {
|
|
395
448
|
const tools = /* @__PURE__ */ new Map();
|
|
449
|
+
const toolScopes = /* @__PURE__ */ new Map();
|
|
396
450
|
const prompts = /* @__PURE__ */ new Map();
|
|
397
451
|
const resources = /* @__PURE__ */ new Map();
|
|
398
452
|
const templates = [];
|
|
399
453
|
const lastListed = boundedMap(SESSIONS_PER_SERVER);
|
|
400
454
|
const toolPermission = (name) => tools.get(name);
|
|
455
|
+
const toolDeclared = (name) => toolScopes.get(name);
|
|
401
456
|
const promptPermission = (name) => prompts.get(name);
|
|
402
457
|
const resourcePermission = (uri) => {
|
|
403
458
|
const direct = resources.get(uri);
|
|
@@ -406,16 +461,19 @@ function createPermDock(policy, options) {
|
|
|
406
461
|
};
|
|
407
462
|
const templatePermission = (uriTemplate) => templates.find((entry) => entry.template.uriTemplate.toString() === uriTemplate)?.permission;
|
|
408
463
|
const listFilter = (field, keyOf, permissionOf, remember) => async (result, rawContext) => {
|
|
409
|
-
if (!isRecord
|
|
464
|
+
if (!isRecord(result) || !Array.isArray(result[field])) return result;
|
|
410
465
|
const context = contextOf(rawContext);
|
|
411
466
|
const entries = result[field];
|
|
412
|
-
const shown = await visible(context, permissionOf, entries.map(keyOf));
|
|
467
|
+
const shown = await visible(context, permissionOf, entries.map(keyOf), remember ? toolDeclared : void 0);
|
|
413
468
|
const kept = entries.filter((entry) => shown.has(keyOf(entry)));
|
|
414
469
|
if (remember) lastListed.set(sessionKey(context), [...shown].toSorted().join(","));
|
|
415
|
-
return {
|
|
470
|
+
return definesCacheScope(context) ? {
|
|
416
471
|
...result,
|
|
417
472
|
[field]: kept,
|
|
418
473
|
cacheScope: "private"
|
|
474
|
+
} : {
|
|
475
|
+
...result,
|
|
476
|
+
[field]: kept
|
|
419
477
|
};
|
|
420
478
|
};
|
|
421
479
|
const filters = {
|
|
@@ -447,38 +505,55 @@ function createPermDock(policy, options) {
|
|
|
447
505
|
const key = sessionKey(context);
|
|
448
506
|
const before = lastListed.get(key);
|
|
449
507
|
if (before === void 0) return;
|
|
450
|
-
const after = [...await visible(context, toolPermission, [...tools.keys()])].toSorted().join(",");
|
|
508
|
+
const after = [...await visible(context, toolPermission, [...tools.keys()], toolDeclared)].toSorted().join(",");
|
|
451
509
|
if (after === before) return;
|
|
452
510
|
lastListed.set(key, after);
|
|
453
511
|
try {
|
|
454
512
|
await (context.mcpReq?.notify?.({ method: "notifications/tools/list_changed" }) ?? inner.sendToolListChanged?.());
|
|
455
513
|
} catch {}
|
|
456
514
|
};
|
|
457
|
-
const guardTool = (permission, load, handler, longRunning) => guard(permission, load, handler, (params) => params.length >= 2 ? [params[0]] : [void 0], toolRefusal, {
|
|
515
|
+
const guardTool = (permission, reach, load, handler, longRunning) => guard(permission, load, handler, (params) => params.length >= 2 ? [params[0]] : [void 0], toolRefusal, {
|
|
458
516
|
after: announce,
|
|
459
517
|
longRunning,
|
|
460
|
-
capabilities
|
|
518
|
+
capabilities,
|
|
519
|
+
reach
|
|
461
520
|
});
|
|
462
521
|
const originalTool = server.registerTool.bind(server);
|
|
522
|
+
const toolPermissionOf = (name, config) => {
|
|
523
|
+
if (enforcement === void 0 || config["permission"] !== void 0) return requirePermission("tool", name, config);
|
|
524
|
+
for (const field of ["data", "longRunning"]) if (config[field] !== void 0) throw new TypeError(`permdock/mcp: tool ${name} sets ${field}, but with enforce: 'procedure' its procedure decides.`);
|
|
525
|
+
return requirePermission("tool", name, { permission: enforcement.permissionFor(name) });
|
|
526
|
+
};
|
|
527
|
+
/** With `enforce: 'procedure'` the handler runs undecided: the procedure it calls decides. */
|
|
528
|
+
const wrapTool = (permission, reach, load, handler, longRunning) => enforcement === void 0 ? guardTool(permission, reach, load, handler, longRunning) : async (...params) => {
|
|
529
|
+
const result = await handler(...params);
|
|
530
|
+
await announce(contextOf(params.at(-1)));
|
|
531
|
+
return result;
|
|
532
|
+
};
|
|
463
533
|
const registerTool = (name, config, handler) => {
|
|
464
|
-
const permission =
|
|
465
|
-
const { permission: _permission, data, scopeChallenge, longRunning: rawLongRunning, ...passthrough } = config;
|
|
534
|
+
const permission = toolPermissionOf(name, config);
|
|
535
|
+
const { permission: _permission, data, scopeChallenge, longRunning: rawLongRunning, oauthScopes: rawScopes, ...passthrough } = config;
|
|
466
536
|
const load = data;
|
|
467
537
|
const longRunning = rawLongRunning === true;
|
|
538
|
+
const declared = declaredScopes(name, rawScopes === void 0 ? enforcement?.oauthScopesFor?.(name) : rawScopes);
|
|
539
|
+
const reach = reachOf(permission, declared);
|
|
468
540
|
const registered = originalTool(name, {
|
|
469
541
|
...passthrough,
|
|
470
542
|
annotations: {
|
|
471
543
|
...annotationsFor(permission),
|
|
472
544
|
...passthrough["annotations"]
|
|
473
545
|
},
|
|
474
|
-
scopeChallenge: challengeFor(
|
|
475
|
-
},
|
|
546
|
+
scopeChallenge: challengeFor(scopeChallenge, reach.scopes, reach.challenge)
|
|
547
|
+
}, wrapTool(permission, reach, load, handler, longRunning));
|
|
476
548
|
tools.set(name, permission);
|
|
549
|
+
if (declared !== void 0) toolScopes.set(name, declared);
|
|
477
550
|
let current = name;
|
|
478
|
-
guardUpdates(registered, (callback) =>
|
|
551
|
+
guardUpdates(registered, (callback) => wrapTool(permission, reach, load, callback, longRunning), (from, to) => {
|
|
479
552
|
tools.delete(from);
|
|
553
|
+
toolScopes.delete(from);
|
|
480
554
|
if (to !== null) {
|
|
481
555
|
tools.set(to, permission);
|
|
556
|
+
if (declared !== void 0) toolScopes.set(to, declared);
|
|
482
557
|
current = to;
|
|
483
558
|
}
|
|
484
559
|
}, () => current);
|
|
@@ -492,7 +567,7 @@ function createPermDock(policy, options) {
|
|
|
492
567
|
const wrap = (callback) => guard(permission, load, callback, (params) => params.length >= 2 ? [params[0]] : [void 0], throwRefusal, { capabilities });
|
|
493
568
|
const registered = originalPrompt(name, {
|
|
494
569
|
...passthrough,
|
|
495
|
-
scopeChallenge: challengeFor(permission,
|
|
570
|
+
scopeChallenge: challengeFor(scopeChallenge, scopesReaching(policy, permission), challengeScope(policy, permission))
|
|
496
571
|
}, wrap(handler));
|
|
497
572
|
prompts.set(name, permission);
|
|
498
573
|
guardUpdates(registered, wrap);
|
|
@@ -506,7 +581,7 @@ function createPermDock(policy, options) {
|
|
|
506
581
|
const wrap = (callback) => guard(permission, load, callback, (params) => params.slice(0, -1), throwRefusal, { capabilities });
|
|
507
582
|
const registered = originalResource(name, uriOrTemplate, {
|
|
508
583
|
...passthrough,
|
|
509
|
-
scopeChallenge: challengeFor(permission,
|
|
584
|
+
scopeChallenge: challengeFor(scopeChallenge, scopesReaching(policy, permission), challengeScope(policy, permission))
|
|
510
585
|
}, wrap(read));
|
|
511
586
|
if (typeof uriOrTemplate === "string") resources.set(uriOrTemplate, permission);
|
|
512
587
|
else templates.push({
|
|
@@ -525,39 +600,4 @@ function createPermDock(policy, options) {
|
|
|
525
600
|
return { protectServer };
|
|
526
601
|
}
|
|
527
602
|
//#endregion
|
|
528
|
-
//#region src/mcp/subject.ts
|
|
529
|
-
function isRecord(value) {
|
|
530
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
531
|
-
}
|
|
532
|
-
/**
|
|
533
|
-
* Maps the `AuthInfo` the MCP SDK's bearer verification produced to a
|
|
534
|
-
* `Subject`: the principal from the verified claims in `extra`, the client
|
|
535
|
-
* as an `mcp-client` actor, the granted scopes as the delegation. Never
|
|
536
|
-
* verifies and never throws; anything unusable is the anonymous subject.
|
|
537
|
-
*/
|
|
538
|
-
function subjectFromMcp(authInfo, options = {}) {
|
|
539
|
-
try {
|
|
540
|
-
if (authInfo === void 0 || !isRecord(authInfo.extra)) return anonymousSubject();
|
|
541
|
-
const claims = compact({
|
|
542
|
-
...authInfo.extra,
|
|
543
|
-
authorization_details: authInfo.extra["authorizationDetails"] ?? authInfo.extra["authorization_details"],
|
|
544
|
-
scope: authInfo.scopes?.join(" "),
|
|
545
|
-
client_id: authInfo.clientId,
|
|
546
|
-
exp: authInfo.expiresAt
|
|
547
|
-
});
|
|
548
|
-
const mapped = mapClaimsToSubject(claims, options);
|
|
549
|
-
if (mapped.invalidClaims || mapped.invalidChain || mapped.subject.principal === null) return anonymousSubject();
|
|
550
|
-
const clientId = authInfo.clientId;
|
|
551
|
-
return freezeDeep(compact({
|
|
552
|
-
...mapped.subject,
|
|
553
|
-
actor: typeof clientId === "string" && clientId !== "" ? {
|
|
554
|
-
id: clientId,
|
|
555
|
-
kind: "mcp-client"
|
|
556
|
-
} : mapped.subject.actor
|
|
557
|
-
}));
|
|
558
|
-
} catch {
|
|
559
|
-
return anonymousSubject();
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
//#endregion
|
|
563
603
|
export { APPROVAL_META_KEY, createPermDock, subjectFromMcp };
|