permdock 0.1.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 +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-cmvX2jDe.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 +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/canonical-json-DemiK4Vp.js +26 -0
- package/dist/{capability-B68OFnZx.js → capability-4qPdO9gk.js} +7 -5
- package/dist/{capability-BDG_nkxt.d.ts → capability-Dq43tT1u.d.ts} +2 -2
- package/dist/catalog/index.d.ts +1 -1
- package/dist/catalog/index.js +1 -1
- package/dist/catalog-BjZSovXQ.js +2 -0
- package/dist/{catalog-doc-BSo_Q_-6.js → catalog-doc-Dsc9y7sd.js} +23 -12
- package/dist/{catalog-B0E6bggc.js → catalog-h2tlKFkq.js} +2 -2
- package/dist/{catalog-H-vFGwWK.js → catalog-z8q6bi_r.js} +4 -4
- 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-BGhHS-lY.js} +2 -2
- package/dist/{cloud-Cuxr6Czw.js → cloud-Bo3e9Ak3.js} +7 -6
- package/dist/{collect-O-tOtbnk.js → collect-DDDv_ESs.js} +194 -42
- package/dist/collect-DLlujdHC.js +83 -0
- package/dist/collect-rG2IQ3t0.js +2 -0
- package/dist/{commands-BMh_Etm2.js → commands-DWOrSQic.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-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-JvqwHODC.js → connection-CU8MQxRi.js} +1 -1
- package/dist/{context-CKEAabd7.js → context-Ttp0ekMT.js} +36 -27
- package/dist/convex/index.d.ts +9 -4
- package/dist/convex/index.js +14 -4
- package/dist/create-BWyx3jua.d.ts +245 -0
- package/dist/create-CPhDL6qx.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-PdoqESvg.d.ts} +9 -10
- package/dist/{diff-x5Il8LVa.js → diff-B8Tunc3o.js} +44 -11
- package/dist/{diff-BUzf5Poi.js → diff-CzqLxZ77.js} +2 -2
- package/dist/doctor-WpvG6p4k.js +1194 -0
- package/dist/doctor-collect-ByfYlNv1.js +664 -0
- package/dist/{doctor-Bqo6FwUa.js → doctor-rOr-4ZfS.js} +2 -2
- 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-DAqevpNk.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-C3sHpZNS.js} +65 -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-LF_hS-yn.d.ts → index-A0YNL8jZ.d.ts} +1 -1
- package/dist/index-CtE07CBF.d.ts +6 -0
- package/dist/{index-xIxJLwOQ.d.ts → index-D3vbkoSI.d.ts} +75 -7
- package/dist/{index-CltcQ4Bf.d.ts → index-D6_cSa1z.d.ts} +68 -5
- package/dist/index.d.ts +14 -9
- package/dist/index.js +22 -17
- package/dist/instance-options-BK_rNOSC.d.ts +11 -0
- package/dist/instance-options-Dhhcnm3y.js +22 -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-GSQnMz3O.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-CwePaF7C.js → openapi-Bbg4wGVL.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-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-BkGQNzAh.d.ts +10 -0
- package/dist/parse-local-manifest-BrMozJCo.js +36 -0
- package/dist/pdp/index.d.ts +2 -2
- package/dist/pdp/index.js +14 -127
- package/dist/{permdock-yoZ7EjxX.js → permdock-CzqXjCpU.js} +641 -126
- package/dist/{permissions-B8vCg_bI.d.ts → permissions-CDgvKG5L.d.ts} +2 -2
- package/dist/{permissions-CofRqesP.js → permissions-CpZrivYv.js} +3 -3
- package/dist/{permissions-DC7GROPA.js → permissions-DVoF6dMt.js} +77 -15
- package/dist/{permissions-B4apnahQ.d.ts → permissions-DttnqqxC.d.ts} +34 -5
- package/dist/{pins-CqE1jZuF.js → pins-8ILTftC9.js} +2 -2
- package/dist/{policy-CInmNGkM.d.ts → policy-CFZAr_Al.d.ts} +330 -37
- package/dist/{policy-Cq2fB8Q5.d.ts → policy-D8UFyERw.d.ts} +2 -2
- package/dist/{policy-ANp36PnI.js → policy-xyWg7QdR.js} +173 -22
- 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 +3 -2
- package/dist/prisma/index.js +45 -20
- package/dist/{problem-Cgp9-KZA.js → problem-B43ztKIm.js} +74 -109
- package/dist/problem-details-CkL50EEf.d.ts +7 -0
- package/dist/problem-details-_AMOYz-w.js +144 -0
- package/dist/{protected-BuPAycJT.d.ts → protected-CNsMzrVd.d.ts} +5 -4
- package/dist/protected-Cs6kTaHo.js +100 -0
- package/dist/protected-bZs6rbT1.d.ts +40 -0
- package/dist/{provider-wTAUda2v.d.ts → provider-Cjr62YMV.d.ts} +1 -1
- package/dist/provider-DLzpb2Xz.js +52 -0
- package/dist/provider-store-DNyC1y48.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-sqBGMnNs.d.ts +5 -0
- package/dist/resource-ref-CaS9yVPi.js +20 -0
- package/dist/revocations-Bhr0aMIC.js +27 -0
- package/dist/rls-BMNydpHk.js +2521 -0
- package/dist/{rls-BOFU3chG.js → rls-CEvs64Kj.js} +8 -3
- package/dist/rls-fields-BMasREhR.js +3502 -0
- package/dist/{rls-graph-DxQ39PJj.js → rls-graph-pc9fuXYm.js} +100 -36
- package/dist/{rls-import-CXV6LBlS.js → rls-import-D8F7j35Q.js} +7 -6
- package/dist/{rls-migrate-DrFPbf8p.js → rls-migrate-7wikfrVI.js} +6 -5
- 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-BajTgQZ-.d.ts → row-check-Dt35czLy.d.ts} +12 -15
- package/dist/rpc-DOK54_CS.js +89 -0
- package/dist/{run-CJ6UvS3a.js → run-YXCJDNYk.js} +31 -12
- package/dist/runtime-CB8gQFvS.js +11 -0
- package/dist/{saas-BRrZzJkM.js → saas-Bj_FFkjN.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-Gs6TTVa-.d.ts} +1 -1
- package/dist/skills-Biq5uup3.js +192 -0
- package/dist/{skills-C_lpV4Jx.js → skills-JaymNCdK.js} +10 -4
- package/dist/{snapshot-DE8dE_hz.js → snapshot-Enxd0n-s.js} +138 -214
- package/dist/snapshot-cache-D6jLelln.js +44 -0
- package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
- package/dist/solid/index.d.ts +39 -9
- package/dist/solid/index.js +76 -85
- package/dist/sources-B0UvrJ21.js +534 -0
- package/dist/sources-BcJgw0lt.d.ts +192 -0
- package/dist/{sql-Bll1d7y0.js → sql-xdg5f4Fi.js} +6 -1
- package/dist/{src-CTNT-PBW.js → src-CSbUiozF.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-D_pjn91-.d.ts} +13 -4
- package/dist/store-options-yO0V6gRn.js +716 -0
- package/dist/{stores-CkG2HrSg.js → stores-4_sqiOA1.js} +10 -63
- package/dist/{stores-CvOnu_2T.d.ts → stores-DVR5NHLE.d.ts} +20 -9
- package/dist/{stream-Q_xlB6Ko.js → stream-DDpvynSB.js} +16 -2
- package/dist/{stream-BhMfZOwr.d.ts → stream-DlvG2hs-.d.ts} +2 -2
- package/dist/subject-settings-BwBmCdTR.js +128 -0
- package/dist/supabase/index.d.ts +122 -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-CwafwxxF.js} +3 -3
- package/dist/{supabase-DTxGtYdi.js → supabase-DTBaC20O.js} +345 -367
- package/dist/supabase-config-Bs44dare.js +472 -0
- package/dist/{supabase-hook-D_OqGb_V.js → supabase-hook-BuxLQLpU.js} +994 -708
- 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 +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-9AWO9EGt.d.ts +197 -0
- package/dist/{types-D6Z6-rKJ.d.ts → types-BPxgszlT.d.ts} +260 -22
- package/dist/{types-BvBk1wgn.d.ts → types-BVyImy5I.d.ts} +5 -3
- package/dist/{types-CxquUByI.d.ts → types-Bvc4oWT6.d.ts} +1 -1
- package/dist/types-C3s9xVJG.d.ts +48 -0
- package/dist/{types-BBK-exvJ.d.ts → types-Dnemwd77.d.ts} +7 -1
- package/dist/types-kxznc7cn.d.ts +52 -0
- package/dist/{types-B8w5PFtS.d.ts → types-vKyAMtcX.d.ts} +17 -1
- package/dist/{types-B9dmiiab.d.ts → types-vNSDF7Dq.d.ts} +1 -1
- package/dist/{sources-DOpW5Ila.d.ts → types-yF5LmQVD.d.ts} +86 -127
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +10 -9
- package/dist/{usage-1ozMubLY.js → usage-D07N9QJ3.js} +2 -2
- package/dist/usage-D82l1CwK.js +2 -0
- package/dist/{usage-CUnK6Ou9.js → usage-DG1oeCca.js} +225 -62
- package/dist/validation-error-CnjZ4t92.js +33 -0
- package/dist/validation-error-CtF23SrC.d.ts +26 -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-Etoa_Mvr.js +2 -0
- package/dist/watch-UihESpsJ.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
|
@@ -1,40 +1,77 @@
|
|
|
1
|
-
import { c as getResource } from "./permissions-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
-
import { resolve } from "node:path";
|
|
10
|
-
import {
|
|
1
|
+
import { c as getResource } from "./permissions-DVoF6dMt.js";
|
|
2
|
+
import { o as usageResult } from "./errors-CWfoNg9N.js";
|
|
3
|
+
import { a as USAGE_REPORT_SCHEMA } from "./version-BvacVTZR.js";
|
|
4
|
+
import { o as jsonSchemaOf } from "./catalog-doc-Dsc9y7sd.js";
|
|
5
|
+
import { i as rel, r as listSourceFiles } from "./files-DWUN9PzI.js";
|
|
6
|
+
import { a as loadModule, n as asPolicy, o as pickNamed } from "./load-DhWEB9P1.js";
|
|
7
|
+
import { r as runCollect } from "./collect-DDDv_ESs.js";
|
|
8
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
9
|
+
import { dirname, resolve } from "node:path";
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
|
+
import { createJiti } from "jiti";
|
|
12
|
+
import { Visitor, parseSync } from "oxc-parser";
|
|
13
|
+
import { isBuiltin } from "node:module";
|
|
11
14
|
//#region src/cli/doctor-source.ts
|
|
15
|
+
/** Entries a client file must not import; `tests/cli/doctor-entries.test.ts` keeps it in step with `exports`. */
|
|
12
16
|
const SERVER_SPECIFIERS = [
|
|
13
|
-
"permdock/
|
|
14
|
-
"permdock/
|
|
15
|
-
"permdock/hono",
|
|
16
|
-
"permdock/mcp",
|
|
17
|
+
"permdock/a2a",
|
|
18
|
+
"permdock/ai-sdk",
|
|
17
19
|
"permdock/approvals",
|
|
18
|
-
"permdock/
|
|
19
|
-
"permdock/supabase",
|
|
20
|
-
"permdock/ssf",
|
|
20
|
+
"permdock/authzen",
|
|
21
21
|
"permdock/better-auth",
|
|
22
|
+
"permdock/better-supabase",
|
|
23
|
+
"permdock/claude-agent",
|
|
22
24
|
"permdock/clerk",
|
|
25
|
+
"permdock/cloud",
|
|
23
26
|
"permdock/convex",
|
|
24
|
-
"permdock/
|
|
25
|
-
"permdock/
|
|
26
|
-
"permdock/claude-agent",
|
|
27
|
+
"permdock/drizzle",
|
|
28
|
+
"permdock/elysia",
|
|
27
29
|
"permdock/eve",
|
|
28
|
-
"permdock/
|
|
29
|
-
|
|
30
|
-
const ADAPTER_SPECIFIERS = [
|
|
30
|
+
"permdock/express",
|
|
31
|
+
"permdock/fastify",
|
|
31
32
|
"permdock/hono",
|
|
32
|
-
"permdock/
|
|
33
|
+
"permdock/jwt",
|
|
34
|
+
"permdock/kysely",
|
|
33
35
|
"permdock/mcp",
|
|
36
|
+
"permdock/nest",
|
|
37
|
+
"permdock/next",
|
|
38
|
+
"permdock/node",
|
|
39
|
+
"permdock/openai",
|
|
40
|
+
"permdock/openapi",
|
|
41
|
+
"permdock/orpc",
|
|
42
|
+
"permdock/otel",
|
|
43
|
+
"permdock/pdp",
|
|
44
|
+
"permdock/prisma",
|
|
45
|
+
"permdock/scim",
|
|
46
|
+
"permdock/server",
|
|
47
|
+
"permdock/ssf",
|
|
48
|
+
"permdock/supabase",
|
|
49
|
+
"permdock/supabase/middleware",
|
|
50
|
+
"permdock/terminal",
|
|
51
|
+
"permdock/trpc"
|
|
52
|
+
];
|
|
53
|
+
/** Entries that feed request, tool or model data into a check. */
|
|
54
|
+
const ADAPTER_SPECIFIERS = [
|
|
55
|
+
"permdock/a2a",
|
|
34
56
|
"permdock/ai-sdk",
|
|
57
|
+
"permdock/authzen",
|
|
35
58
|
"permdock/claude-agent",
|
|
59
|
+
"permdock/elysia",
|
|
60
|
+
"permdock/eve",
|
|
36
61
|
"permdock/express",
|
|
37
|
-
"permdock/fastify"
|
|
62
|
+
"permdock/fastify",
|
|
63
|
+
"permdock/hono",
|
|
64
|
+
"permdock/mcp",
|
|
65
|
+
"permdock/nest",
|
|
66
|
+
"permdock/next",
|
|
67
|
+
"permdock/node",
|
|
68
|
+
"permdock/openai",
|
|
69
|
+
"permdock/orpc",
|
|
70
|
+
"permdock/server",
|
|
71
|
+
"permdock/supabase/middleware",
|
|
72
|
+
"permdock/terminal",
|
|
73
|
+
"permdock/trpc",
|
|
74
|
+
"permdock/webmcp"
|
|
38
75
|
];
|
|
39
76
|
const UNTRUSTED_CLAIMS = [
|
|
40
77
|
"user_metadata",
|
|
@@ -43,7 +80,6 @@ const UNTRUSTED_CLAIMS = [
|
|
|
43
80
|
"clientMetadata",
|
|
44
81
|
"preferred_username"
|
|
45
82
|
];
|
|
46
|
-
const JWKS_OPTION = /(?<!\b(?:const|let|var)\s+)\bjwks\s*:/u;
|
|
47
83
|
function withoutComments(source) {
|
|
48
84
|
const { comments } = parseSync(source.file, source.text);
|
|
49
85
|
let text = source.text;
|
|
@@ -53,10 +89,62 @@ function withoutComments(source) {
|
|
|
53
89
|
function isClientSource(source, clientEntries) {
|
|
54
90
|
return clientEntries.has(source.file) || source.text.includes("'use client'") || source.text.includes("\"use client\"") || source.file.includes(".client.");
|
|
55
91
|
}
|
|
56
|
-
|
|
92
|
+
/** Specifiers a module loads at runtime: value imports, re-exports and literal dynamic imports. */
|
|
93
|
+
function runtimeSpecifiers(source) {
|
|
94
|
+
const { module } = parseSync(source.file, source.text);
|
|
95
|
+
const out = /* @__PURE__ */ new Set();
|
|
96
|
+
for (const item of module.staticImports) if (item.entries.length === 0 || item.entries.some((entry) => !entry.isType)) out.add(item.moduleRequest.value);
|
|
97
|
+
for (const item of module.staticExports) for (const entry of item.entries) if (entry.moduleRequest !== null && !entry.isType) out.add(entry.moduleRequest.value);
|
|
98
|
+
for (const item of module.dynamicImports) {
|
|
99
|
+
const literal = /^\s*(['"`])([^'"`$]+)\1\s*$/u.exec(source.text.slice(item.moduleRequest.start, item.moduleRequest.end));
|
|
100
|
+
if (literal?.[2] !== void 0) out.add(literal[2]);
|
|
101
|
+
}
|
|
102
|
+
return [...out];
|
|
103
|
+
}
|
|
104
|
+
function realFile(path) {
|
|
105
|
+
try {
|
|
106
|
+
return realpathSync(path);
|
|
107
|
+
} catch {
|
|
108
|
+
return path;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* A resolver for imports of `file`, the way the bundler resolves them:
|
|
113
|
+
* relative paths with or without an extension, the `paths` of the nearest
|
|
114
|
+
* `tsconfig.json`, and package names through `node_modules` and each
|
|
115
|
+
* package's `exports`. An unresolvable specifier gives `undefined`.
|
|
116
|
+
*/
|
|
117
|
+
function resolverFor(file) {
|
|
118
|
+
const jiti = createJiti(file, { tsconfigPaths: dirname(file) });
|
|
119
|
+
const parentURL = pathToFileURL(file);
|
|
120
|
+
return (specifier) => {
|
|
121
|
+
if (specifier === "" || isBuiltin(specifier)) return;
|
|
122
|
+
try {
|
|
123
|
+
const url = jiti.esmResolve(specifier, {
|
|
124
|
+
parentURL,
|
|
125
|
+
try: true
|
|
126
|
+
});
|
|
127
|
+
const path = url?.startsWith("file:") === true ? fileURLToPath(url) : void 0;
|
|
128
|
+
return path !== void 0 && existsSync(path) ? realFile(path) : void 0;
|
|
129
|
+
} catch {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function pd001(sources, clientEntries = /* @__PURE__ */ new Set(), policy) {
|
|
57
135
|
const findings = [];
|
|
136
|
+
const policyFile = policy === void 0 ? void 0 : realFile(resolve(policy.cwd, policy.path));
|
|
58
137
|
for (const source of sources) {
|
|
59
138
|
if (!isClientSource(source, clientEntries)) continue;
|
|
139
|
+
if (policy !== void 0 && policyFile !== void 0) {
|
|
140
|
+
const resolveImport = resolverFor(resolve(policy.cwd, source.file));
|
|
141
|
+
for (const specifier of runtimeSpecifiers(source)) if (specifier !== "permdock" && !specifier.startsWith("permdock/") && resolveImport(specifier) === policyFile) findings.push({
|
|
142
|
+
code: "PD001",
|
|
143
|
+
severity: "error",
|
|
144
|
+
message: `${source.file} imports the policy module through ${specifier}`,
|
|
145
|
+
fix: "decide on the server and pass a snapshot to the client ('permdock/react'); never import the policy into a client entry"
|
|
146
|
+
});
|
|
147
|
+
}
|
|
60
148
|
for (const spec of SERVER_SPECIFIERS) if (source.text.includes(`'${spec}'`) || source.text.includes(`"${spec}"`)) findings.push({
|
|
61
149
|
code: "PD001",
|
|
62
150
|
severity: "error",
|
|
@@ -137,29 +225,92 @@ function pd013(sources) {
|
|
|
137
225
|
}
|
|
138
226
|
return findings;
|
|
139
227
|
}
|
|
228
|
+
function unwrapped(node) {
|
|
229
|
+
let current = node ?? void 0;
|
|
230
|
+
while (current?.type === "TSAsExpression" || current?.type === "TSSatisfiesExpression" || current?.type === "ParenthesizedExpression") current = current.expression;
|
|
231
|
+
return current;
|
|
232
|
+
}
|
|
233
|
+
function propertyName(property) {
|
|
234
|
+
if (property.computed) return;
|
|
235
|
+
const key = property.key;
|
|
236
|
+
if (key.type === "Identifier") return key.name;
|
|
237
|
+
return key.type === "Literal" && typeof key.value === "string" ? key.value : void 0;
|
|
238
|
+
}
|
|
239
|
+
function stringValue(node) {
|
|
240
|
+
const value = unwrapped(node);
|
|
241
|
+
if (value?.type === "Literal") return typeof value.value === "string" ? value.value : void 0;
|
|
242
|
+
return value?.type === "TemplateLiteral" ? value.quasis[0]?.value.cooked ?? void 0 : void 0;
|
|
243
|
+
}
|
|
244
|
+
function isPermDockSpecifier(value) {
|
|
245
|
+
return value === "permdock" || value.startsWith("permdock/");
|
|
246
|
+
}
|
|
247
|
+
function permdockOptionObjects(source) {
|
|
248
|
+
const { program } = parseSync(source.file, source.text);
|
|
249
|
+
const functions = /* @__PURE__ */ new Set();
|
|
250
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
251
|
+
const constants = /* @__PURE__ */ new Map();
|
|
252
|
+
const calls = [];
|
|
253
|
+
new Visitor({
|
|
254
|
+
ImportDeclaration(node) {
|
|
255
|
+
if (node.importKind === "type" || !isPermDockSpecifier(node.source.value)) return;
|
|
256
|
+
for (const specifier of node.specifiers) if (specifier.type === "ImportNamespaceSpecifier") namespaces.add(specifier.local.name);
|
|
257
|
+
else if (specifier.type === "ImportDefaultSpecifier" || specifier.importKind !== "type") functions.add(specifier.local.name);
|
|
258
|
+
},
|
|
259
|
+
VariableDeclarator(node) {
|
|
260
|
+
const init = unwrapped(node.init);
|
|
261
|
+
if (node.id.type === "Identifier" && init?.type === "ObjectExpression") constants.set(node.id.name, init);
|
|
262
|
+
},
|
|
263
|
+
CallExpression(node) {
|
|
264
|
+
calls.push(node);
|
|
265
|
+
}
|
|
266
|
+
}).visit(program);
|
|
267
|
+
const objects = [];
|
|
268
|
+
const collect = (node) => {
|
|
269
|
+
const value = unwrapped(node);
|
|
270
|
+
const target = value?.type === "Identifier" ? constants.get(value.name) : value;
|
|
271
|
+
if (target?.type !== "ObjectExpression" || objects.includes(target)) return;
|
|
272
|
+
objects.push(target);
|
|
273
|
+
for (const property of target.properties) if (property.type === "Property") collect(property.value);
|
|
274
|
+
};
|
|
275
|
+
for (const call of calls) {
|
|
276
|
+
const callee = call.callee;
|
|
277
|
+
if (callee.type === "Identifier" && functions.has(callee.name) || callee.type === "MemberExpression" && callee.object.type === "Identifier" && namespaces.has(callee.object.name)) for (const argument of call.arguments) collect(argument);
|
|
278
|
+
}
|
|
279
|
+
return objects;
|
|
280
|
+
}
|
|
140
281
|
function pd014(sources) {
|
|
141
282
|
const findings = [];
|
|
142
283
|
for (const source of sources) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
284
|
+
if (!source.text.includes("permdock")) continue;
|
|
285
|
+
for (const object of permdockOptionObjects(source)) {
|
|
286
|
+
const keys = /* @__PURE__ */ new Map();
|
|
287
|
+
for (const property of object.properties) {
|
|
288
|
+
if (property.type !== "Property") continue;
|
|
289
|
+
const name = propertyName(property);
|
|
290
|
+
if (name !== void 0) keys.set(name, property.value);
|
|
291
|
+
}
|
|
292
|
+
const discovery = keys.get("discovery");
|
|
293
|
+
const setsDiscovery = keys.has("discovery");
|
|
294
|
+
const setsJwks = keys.has("jwks");
|
|
295
|
+
if (stringValue(discovery)?.startsWith("http:") === true) findings.push({
|
|
296
|
+
code: "PD014",
|
|
297
|
+
severity: "error",
|
|
298
|
+
message: `${source.file} uses a plain-HTTP discovery URL`,
|
|
299
|
+
fix: "use an https: issuer"
|
|
300
|
+
});
|
|
301
|
+
if (setsDiscovery && (setsJwks || keys.has("issuer"))) findings.push({
|
|
302
|
+
code: "PD014",
|
|
303
|
+
severity: "error",
|
|
304
|
+
message: `${source.file} sets discovery together with jwks or issuer`,
|
|
305
|
+
fix: "use discovery alone, or jwks plus issuer"
|
|
306
|
+
});
|
|
307
|
+
if (setsJwks && !setsDiscovery && !keys.has("issuer")) findings.push({
|
|
308
|
+
code: "PD014",
|
|
309
|
+
severity: "error",
|
|
310
|
+
message: `${source.file} sets jwks without issuer`,
|
|
311
|
+
fix: "set issuer with jwks, or switch to discovery"
|
|
312
|
+
});
|
|
313
|
+
}
|
|
163
314
|
}
|
|
164
315
|
return findings;
|
|
165
316
|
}
|
|
@@ -288,7 +439,7 @@ function pd036(sources) {
|
|
|
288
439
|
for (const match of source.text.matchAll(PROTECT_CALL)) {
|
|
289
440
|
const open = match.index + match[0].length - 1;
|
|
290
441
|
const args = callArguments(source.text, open);
|
|
291
|
-
if (args?.length !== 1) continue;
|
|
442
|
+
if (args?.length !== 1 || args[0]?.trim() === "null") continue;
|
|
292
443
|
const route = idRouteOf(source, match.index);
|
|
293
444
|
if (route === void 0) continue;
|
|
294
445
|
const line = source.text.slice(0, match.index).split("\n").length;
|
|
@@ -305,14 +456,14 @@ function pd036(sources) {
|
|
|
305
456
|
//#endregion
|
|
306
457
|
//#region src/cli/usage.ts
|
|
307
458
|
async function runUsage(input) {
|
|
308
|
-
const collected = await runCollect({
|
|
459
|
+
const collected = input.collected === void 0 ? await runCollect({
|
|
309
460
|
cwd: input.cwd,
|
|
310
461
|
config: input.config,
|
|
311
462
|
collect: input.config.collect ?? {},
|
|
312
463
|
check: true,
|
|
313
464
|
now: input.now,
|
|
314
465
|
io: input.io
|
|
315
|
-
});
|
|
466
|
+
}) : await input.collected();
|
|
316
467
|
if (collected.document === void 0 || collected.scan === void 0) return {
|
|
317
468
|
code: 2,
|
|
318
469
|
output: collected.message
|
|
@@ -322,17 +473,8 @@ async function runUsage(input) {
|
|
|
322
473
|
code: 2,
|
|
323
474
|
output: "usage: set policy in permdock.config.ts"
|
|
324
475
|
};
|
|
325
|
-
const
|
|
326
|
-
if (!
|
|
327
|
-
code: 2,
|
|
328
|
-
output: `PermDock CLI: policy module not found: ${policyRel}`
|
|
329
|
-
};
|
|
330
|
-
let policy;
|
|
331
|
-
try {
|
|
332
|
-
policy = asPolicy(pickNamed(await loadModule(policyAbs), ["policy"]));
|
|
333
|
-
} catch (error) {
|
|
334
|
-
return usageResult(error);
|
|
335
|
-
}
|
|
476
|
+
const policy = await usagePolicy(input.cwd, policyRel, input.policy);
|
|
477
|
+
if (!("roles" in policy)) return policy;
|
|
336
478
|
const granted = /* @__PURE__ */ new Set();
|
|
337
479
|
const mergedRoles = /* @__PURE__ */ new Set();
|
|
338
480
|
for (const role of policy.roles) {
|
|
@@ -395,6 +537,22 @@ async function runUsage(input) {
|
|
|
395
537
|
output: input.json ? `${JSON.stringify(report, null, 2)}\n` : formatUsage(report)
|
|
396
538
|
};
|
|
397
539
|
}
|
|
540
|
+
async function usagePolicy(cwd, policyRel, loaded) {
|
|
541
|
+
if (loaded !== void 0) return await loaded() ?? {
|
|
542
|
+
code: 2,
|
|
543
|
+
output: `PermDock CLI: policy module failed to load: ${policyRel}`
|
|
544
|
+
};
|
|
545
|
+
const policyAbs = resolve(cwd, policyRel);
|
|
546
|
+
if (!existsSync(policyAbs)) return {
|
|
547
|
+
code: 2,
|
|
548
|
+
output: `PermDock CLI: policy module not found: ${policyRel}`
|
|
549
|
+
};
|
|
550
|
+
try {
|
|
551
|
+
return asPolicy(pickNamed(await loadModule(policyAbs), ["policy"]));
|
|
552
|
+
} catch (error) {
|
|
553
|
+
return usageResult(error);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
398
556
|
const CLIENT_CALLS = /* @__PURE__ */ new Set([
|
|
399
557
|
"usePermission",
|
|
400
558
|
"can",
|
|
@@ -462,8 +620,13 @@ function conditionFields(condition, out) {
|
|
|
462
620
|
case "related":
|
|
463
621
|
add(condition.field);
|
|
464
622
|
if (condition.restricted !== void 0) add(condition.restricted);
|
|
623
|
+
if (condition.restrictedAncestors !== void 0) {
|
|
624
|
+
add(condition.restrictedAncestors.id);
|
|
625
|
+
add(condition.restrictedAncestors.parent);
|
|
626
|
+
}
|
|
465
627
|
break;
|
|
466
|
-
case "opaque":
|
|
628
|
+
case "opaque":
|
|
629
|
+
case "liveSession": break;
|
|
467
630
|
default: throw new Error(`unknown condition ${String(condition)}`);
|
|
468
631
|
}
|
|
469
632
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
//#region src/core/validation-error.ts
|
|
3
|
+
/** The base of every Problem Details `type` URI; defined here so a validation error does not pull in the Problem Details builders. */
|
|
4
|
+
const PROBLEM_BASE = "https://permdock.com/problems";
|
|
5
|
+
var PermDockValidationError = class extends Error {
|
|
6
|
+
name = "PermDockValidationError";
|
|
7
|
+
code;
|
|
8
|
+
permission;
|
|
9
|
+
resource;
|
|
10
|
+
issues;
|
|
11
|
+
boundary;
|
|
12
|
+
constructor(input) {
|
|
13
|
+
super(input.message);
|
|
14
|
+
this.code = input.code;
|
|
15
|
+
this.permission = input.permission;
|
|
16
|
+
this.resource = input.resource;
|
|
17
|
+
this.issues = input.issues ?? [];
|
|
18
|
+
this.boundary = input.boundary;
|
|
19
|
+
}
|
|
20
|
+
toProblemDetails(options) {
|
|
21
|
+
return compact({
|
|
22
|
+
type: `${PROBLEM_BASE}/validation`,
|
|
23
|
+
title: "Invalid resource data",
|
|
24
|
+
status: 400,
|
|
25
|
+
detail: this.message,
|
|
26
|
+
instance: options?.instance,
|
|
27
|
+
permission: this.permission,
|
|
28
|
+
issues: this.issues
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PermDockValidationError as n, PROBLEM_BASE as t };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { a as ProblemDetails } from "./errors-DAqevpNk.js";
|
|
2
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
//#region src/core/validation-error.d.ts
|
|
4
|
+
/** The base of every Problem Details `type` URI; defined here so a validation error does not pull in the Problem Details builders. */
|
|
5
|
+
declare const PROBLEM_BASE = "https://permdock.com/problems";
|
|
6
|
+
declare class PermDockValidationError extends Error {
|
|
7
|
+
override readonly name: "PermDockValidationError";
|
|
8
|
+
readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
|
|
9
|
+
readonly permission: string;
|
|
10
|
+
readonly resource: string;
|
|
11
|
+
readonly issues: readonly StandardSchemaV1.Issue[];
|
|
12
|
+
readonly boundary: string;
|
|
13
|
+
constructor(input: {
|
|
14
|
+
readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
|
|
15
|
+
readonly permission: string;
|
|
16
|
+
readonly resource: string;
|
|
17
|
+
readonly issues?: readonly StandardSchemaV1.Issue[];
|
|
18
|
+
readonly boundary: string;
|
|
19
|
+
readonly message: string;
|
|
20
|
+
});
|
|
21
|
+
toProblemDetails(options?: {
|
|
22
|
+
readonly instance?: string;
|
|
23
|
+
}): ProblemDetails;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { PermDockValidationError as n, PROBLEM_BASE as t };
|
|
@@ -1,35 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
function sanitizeFields(fields) {
|
|
6
|
-
if (fields === void 0) return;
|
|
7
|
-
return fields.filter((field) => field.length > 0 && !isForbiddenKey(field));
|
|
8
|
-
}
|
|
9
|
-
function grantCoversField(fields, field, effect) {
|
|
10
|
-
if (fields === void 0) return true;
|
|
11
|
-
if (fields.length === 0) return false;
|
|
12
|
-
if (field === void 0) return effect === "allow";
|
|
13
|
-
return fields.includes(field);
|
|
14
|
-
}
|
|
15
|
-
function pickVisible(row, canField) {
|
|
16
|
-
const out = {};
|
|
17
|
-
for (const key of ownKeys(row)) if (canField(key)) out[key] = ownGet(row, key);
|
|
18
|
-
return freezeDeep(out);
|
|
19
|
-
}
|
|
20
|
-
function sanitizeContext(value) {
|
|
21
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
|
|
22
|
-
const out = {};
|
|
23
|
-
for (const key of ownKeys(value)) out[key] = ownGet(value, key);
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
//#endregion
|
|
1
|
+
import { f as isFieldRelation } from "./permissions-DVoF6dMt.js";
|
|
2
|
+
import { t as expiredAt } from "./expiry-BoBJ8Tvc.js";
|
|
3
|
+
import { n as sameId } from "./ids-DC4V4CFu.js";
|
|
4
|
+
import { c as rootScope, l as scopeChain, m as tenantOf, o as resolveScope, r as findScope, t as activeFor, u as scopeIdOf } from "./scopes-CVdPrWN-.js";
|
|
27
5
|
//#region src/core/tenancy.ts
|
|
28
6
|
function nowSeconds(now) {
|
|
29
7
|
return now ?? Date.now() / 1e3;
|
|
30
8
|
}
|
|
31
9
|
function isMembershipExpired(membership, now) {
|
|
32
|
-
return membership
|
|
10
|
+
return expiredAt(membership, now ?? nowSeconds());
|
|
33
11
|
}
|
|
34
12
|
/** The instances of the first scope the subject holds a live membership in. */
|
|
35
13
|
function tenantsOf(principal, scopes, now) {
|
|
@@ -42,6 +20,11 @@ function tenantsOf(principal, scopes, now) {
|
|
|
42
20
|
}
|
|
43
21
|
return [...tenants];
|
|
44
22
|
}
|
|
23
|
+
function heldRoleNamesIn(principal, scopes, tenant, now) {
|
|
24
|
+
const names = /* @__PURE__ */ new Set();
|
|
25
|
+
for (const membership of principal?.memberships ?? []) if (!isMembershipExpired(membership, now) && membership.keep === void 0 && tenantOf(membership, scopes) === tenant) for (const name of membership.roles) names.add(name);
|
|
26
|
+
return [...names];
|
|
27
|
+
}
|
|
45
28
|
/** `requested` when a live membership sits in that instance of the first scope; never a default. */
|
|
46
29
|
function resolveActiveTenant(principal, requested, scopes, now) {
|
|
47
30
|
if (requested === void 0) return principal.tenant;
|
|
@@ -62,9 +45,30 @@ function relatesTo(resource, field, scope, scopes) {
|
|
|
62
45
|
if (resource === void 0) return false;
|
|
63
46
|
return Object.values(resource.relations).some((relation) => isFieldRelation(relation) && relation.field === field && relation.memberOf !== void 0 && resolveScope(scopes, relation.memberOf) === scope);
|
|
64
47
|
}
|
|
65
|
-
/** The
|
|
48
|
+
/** The fields of `resource`'s `memberOf` relations to `scope`. */
|
|
49
|
+
function memberOfFields(resource, scope, scopes) {
|
|
50
|
+
return [...new Set(Object.values(resource.relations).flatMap((relation) => isFieldRelation(relation) && relation.memberOf !== void 0 && resolveScope(scopes, relation.memberOf) === scope ? [relation.field] : []))];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The field of `resource` that holds `scope`'s instance id: the scope's
|
|
54
|
+
* `key` when one of the resource's `memberOf` relations names it, otherwise
|
|
55
|
+
* the field of its one `memberOf` relation to the scope. A table whose own
|
|
56
|
+
* id is the instance (`organizations.id`) declares
|
|
57
|
+
* `{ self: { field: 'id', memberOf: 'organization' } }`.
|
|
58
|
+
*/
|
|
59
|
+
function scopeField(resource, scope, scopes) {
|
|
60
|
+
const key = findScope(scopes, scope)?.key;
|
|
61
|
+
if (resource === void 0) return key;
|
|
62
|
+
const fields = memberOfFields(resource, scope, scopes);
|
|
63
|
+
if (key !== void 0 && fields.includes(key)) return key;
|
|
64
|
+
return fields.length === 1 ? fields[0] : key;
|
|
65
|
+
}
|
|
66
|
+
/** The scopes that partition `resource`, from its `memberOf` relations. */
|
|
66
67
|
function partitionsOf(resource, scopes) {
|
|
67
|
-
return scopes.filter((scope) =>
|
|
68
|
+
return scopes.filter((scope) => {
|
|
69
|
+
const field = scopeField(resource, scope.name, scopes);
|
|
70
|
+
return field !== void 0 && relatesTo(resource, field, scope.name, scopes);
|
|
71
|
+
}).map((scope) => scope.name);
|
|
68
72
|
}
|
|
69
73
|
/**
|
|
70
74
|
* Whether `row` lies inside a named membership's instance: for the scope and
|
|
@@ -72,23 +76,36 @@ function partitionsOf(resource, scopes) {
|
|
|
72
76
|
* resource declares it) must hold the membership's id for it. There is no
|
|
73
77
|
* cascade: the membership's own scope is checked, never a scope below it.
|
|
74
78
|
*/
|
|
75
|
-
function rowInScope(membership, scopes, row, partitioned) {
|
|
79
|
+
function rowInScope(membership, scopes, row, partitioned, fieldOf) {
|
|
76
80
|
if (membership.scope === void 0 || row === null || typeof row !== "object") return { ok: true };
|
|
77
81
|
const root = rootScope(scopes);
|
|
78
82
|
const chain = scopeChain(scopes, membership.scope).toReversed();
|
|
79
83
|
for (const name of chain) {
|
|
80
|
-
const key = findScope(scopes, name)?.key;
|
|
84
|
+
const key = fieldOf?.(name) ?? findScope(scopes, name)?.key;
|
|
81
85
|
if (key === void 0) continue;
|
|
82
86
|
const value = Object.hasOwn(row, key) ? row[key] : void 0;
|
|
83
|
-
if ((value !== void 0 || partitioned(name, key)) && value
|
|
87
|
+
if ((value !== void 0 || partitioned(name, key)) && !sameId(value, scopeIdOf(membership, name))) return {
|
|
84
88
|
ok: false,
|
|
85
89
|
reason: name === root ? "tenant-mismatch" : "scope"
|
|
86
90
|
};
|
|
87
91
|
}
|
|
88
92
|
return { ok: true };
|
|
89
93
|
}
|
|
90
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Whether a membership answers an instance check for `row`: any membership
|
|
96
|
+
* with a row object, otherwise only the first scope or the instance of the
|
|
97
|
+
* second scope that `team(id)` selected.
|
|
98
|
+
*/
|
|
99
|
+
function nestedAppliesWithoutRow(membership, scopes, row, team) {
|
|
100
|
+
if (row !== null && typeof row === "object") return true;
|
|
101
|
+
return membership.scope === rootScope(scopes) || team !== void 0 && membership.scope === scopes[1]?.name;
|
|
102
|
+
}
|
|
103
|
+
function matchScopedMembership(subject, scope, roleName, row, scopes, resource, resources, now, rolesOf = (membership) => membership.roles, team, walk, instance = false, only) {
|
|
91
104
|
if (scope === "global") return { ok: true };
|
|
105
|
+
if (only !== void 0 && scope !== only) return {
|
|
106
|
+
ok: false,
|
|
107
|
+
reason: "scope"
|
|
108
|
+
};
|
|
92
109
|
const principal = subject.principal;
|
|
93
110
|
if (principal === null) return {
|
|
94
111
|
ok: false,
|
|
@@ -108,7 +125,11 @@ function matchScopedMembership(subject, scope, roleName, row, scopes, resource,
|
|
|
108
125
|
}
|
|
109
126
|
if (typeof scope === "string") {
|
|
110
127
|
if (findScope(scopes, scope) === void 0 || membership.scope !== scope || !inTeam(membership, scopes, team) || !activeFor(membership, scopes, principal.tenant)) continue;
|
|
111
|
-
|
|
128
|
+
if (instance && !nestedAppliesWithoutRow(membership, scopes, row, team)) {
|
|
129
|
+
sawWrongScope = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const inside = rowInScope(membership, scopes, row, (name, key) => relatesTo(resource, key, name, scopes), (name) => scopeField(resource, name, scopes));
|
|
112
133
|
if (!inside.ok) {
|
|
113
134
|
if (inside.reason === "tenant-mismatch") sawTenantMismatch = true;
|
|
114
135
|
else sawWrongScope = true;
|
|
@@ -165,7 +186,7 @@ function matchResourceMembership(membership, roleResource, row, resource, resour
|
|
|
165
186
|
if (row === null || typeof row !== "object") return false;
|
|
166
187
|
if (on.resource !== roleResource && membershipField(resources.get(roleResource), on.resource, resources) === void 0) return false;
|
|
167
188
|
const field = membershipField(resource, on.resource, resources);
|
|
168
|
-
return field !== void 0 && row[field]
|
|
189
|
+
return field !== void 0 && sameId(row[field], on.id);
|
|
169
190
|
}
|
|
170
191
|
/**
|
|
171
192
|
* The row field that holds the id of a `membershipResource` membership: the
|
|
@@ -221,4 +242,4 @@ function isActive(validity, now) {
|
|
|
221
242
|
return validity.until === void 0 || now < validity.until;
|
|
222
243
|
}
|
|
223
244
|
//#endregion
|
|
224
|
-
export {
|
|
245
|
+
export { isMembershipExpired as a, membershipField as c, partitionsOf as d, relatesTo as f, tenantsOf as g, scopeField as h, inTeam as i, nestedAppliesWithoutRow as l, rowInScope as m, normalizeValidity as n, matchScopedMembership as o, resolveActiveTenant as p, heldRoleNamesIn as r, memberOfFields as s, isActive as t, nowSeconds as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as isReadonlyArray, t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
-
import {
|
|
2
|
+
import { T as isForbiddenKey, k as splitPath } from "./permissions-DVoF6dMt.js";
|
|
3
3
|
import { t as loadJose } from "./load-jose-BL6LH4bL.js";
|
|
4
4
|
//#region src/jwt/header.ts
|
|
5
5
|
function compactParts(token) {
|
|
@@ -173,7 +173,9 @@ function createKeyCache(options) {
|
|
|
173
173
|
const jwksInFlight = /* @__PURE__ */ new Map();
|
|
174
174
|
let discoveryInFlight;
|
|
175
175
|
let discoveryCache;
|
|
176
|
+
/** Keyed by `jwks_uri`: keys cached for one URI never answer for another. */
|
|
176
177
|
let jwksCache;
|
|
178
|
+
const cachedJwks = (href, now) => jwksCache?.href === href && jwksCache.expiresAt > now ? jwksCache.value : void 0;
|
|
177
179
|
let cooldownUntil = 0;
|
|
178
180
|
let discoveryCause;
|
|
179
181
|
const readDiscovery = async (href, issuer, now) => {
|
|
@@ -251,9 +253,10 @@ function createKeyCache(options) {
|
|
|
251
253
|
};
|
|
252
254
|
};
|
|
253
255
|
const loadJwks = (href, now, force) => {
|
|
254
|
-
|
|
256
|
+
const cached = force ? void 0 : cachedJwks(href, now);
|
|
257
|
+
if (cached !== void 0) return Promise.resolve({
|
|
255
258
|
ok: true,
|
|
256
|
-
jwks:
|
|
259
|
+
jwks: cached
|
|
257
260
|
});
|
|
258
261
|
const pending = jwksInFlight.get(href);
|
|
259
262
|
if (pending !== void 0) return pending;
|
|
@@ -273,6 +276,7 @@ function createKeyCache(options) {
|
|
|
273
276
|
const body = await response.json();
|
|
274
277
|
if (!Array.isArray(body.keys) || body.keys.length === 0) throw new Error("empty jwks");
|
|
275
278
|
jwksCache = {
|
|
279
|
+
href,
|
|
276
280
|
value: body,
|
|
277
281
|
expiresAt: now + clampTtl(cacheControlMaxAge(response.headers.get("cache-control")) ?? maxTtl, minTtl, maxTtl)
|
|
278
282
|
};
|
|
@@ -281,9 +285,10 @@ function createKeyCache(options) {
|
|
|
281
285
|
jwks: body
|
|
282
286
|
};
|
|
283
287
|
} catch {
|
|
284
|
-
|
|
288
|
+
const stale = cachedJwks(href, now);
|
|
289
|
+
if (stale !== void 0) return {
|
|
285
290
|
ok: true,
|
|
286
|
-
jwks:
|
|
291
|
+
jwks: stale
|
|
287
292
|
};
|
|
288
293
|
return {
|
|
289
294
|
ok: false,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { t as packageRoot } from "./package-root-zGkxO3oN.js";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
//#region src/cli/version.ts
|
|
5
|
+
function cliVersion() {
|
|
6
|
+
return JSON.parse(readFileSync(join(packageRoot(), "package.json"), "utf8")).version;
|
|
7
|
+
}
|
|
8
|
+
function generatorBanner() {
|
|
9
|
+
return `permdock@${cliVersion()}`;
|
|
10
|
+
}
|
|
11
|
+
const CATALOG_SCHEMA = "https://permdock.com/schemas/catalog-v1.json";
|
|
12
|
+
const SUPABASE_MANIFEST_SCHEMA = "https://permdock.com/schemas/supabase-manifest-v1.json";
|
|
13
|
+
const USAGE_REPORT_SCHEMA = "https://permdock.com/schemas/usage-report-v1.json";
|
|
14
|
+
const DOCTOR_REPORT_SCHEMA = "https://permdock.com/schemas/doctor-report-v1.json";
|
|
15
|
+
const CONFIG_REPORT_SCHEMA = "https://permdock.com/schemas/config-report-v1.json";
|
|
16
|
+
//#endregion
|
|
17
|
+
export { USAGE_REPORT_SCHEMA as a, SUPABASE_MANIFEST_SCHEMA as i, CONFIG_REPORT_SCHEMA as n, cliVersion as o, DOCTOR_REPORT_SCHEMA as r, generatorBanner as s, CATALOG_SCHEMA as t };
|