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
package/dist/prisma/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
-
import { n as freezeDeep } from "../freeze-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as relatedRowGuard, l as renderGraphSql, n as escapeLike, s as relatedTargetsSql, t as compileWhere } from "../compile-
|
|
6
|
-
import { a as rowCheckOf, n as statementText, r as subjectStatements } from "../subject-settings-
|
|
2
|
+
import { n as freezeDeep } from "../freeze-CrU8nQeX.js";
|
|
3
|
+
import { w as assertSafeKey } from "../permissions-DVoF6dMt.js";
|
|
4
|
+
import { n as PermDockValidationError } from "../validation-error-CnjZ4t92.js";
|
|
5
|
+
import { a as relatedRowGuard, l as renderGraphSql, n as escapeLike, s as relatedTargetsSql, t as compileWhere, u as restrictedRowsSql } from "../compile-Ba4blROR.js";
|
|
6
|
+
import { a as rowCheckOf, n as statementText, r as subjectStatements } from "../subject-settings-BwBmCdTR.js";
|
|
7
7
|
//#region src/prisma/to-where.ts
|
|
8
8
|
function fieldTests(options) {
|
|
9
9
|
const mapped = (field) => fieldName(field, options.fields);
|
|
@@ -129,8 +129,10 @@ function permdockExtension() {
|
|
|
129
129
|
query: { $allModels: {
|
|
130
130
|
findMany: wrap,
|
|
131
131
|
findFirst: wrap,
|
|
132
|
+
findFirstOrThrow: wrap,
|
|
132
133
|
count: wrap,
|
|
133
134
|
aggregate: wrap,
|
|
135
|
+
groupBy: wrap,
|
|
134
136
|
updateMany: wrap,
|
|
135
137
|
deleteMany: wrap
|
|
136
138
|
} }
|
|
@@ -349,10 +351,42 @@ async function resolveRelated(where, options) {
|
|
|
349
351
|
async function resolveNode(node) {
|
|
350
352
|
if (resources === void 0) throw refused("related: the where() result carries no resource graph");
|
|
351
353
|
if (node.ids === void 0 && (subject === void 0 || subject === "")) return NOTHING;
|
|
352
|
-
const
|
|
354
|
+
const mapping = {
|
|
353
355
|
...options.relations,
|
|
354
356
|
resources
|
|
355
|
-
}
|
|
357
|
+
};
|
|
358
|
+
const ids = await readIds(relatedTargetsSql(node, mapping), node.field);
|
|
359
|
+
if (ids.length === 0) return NOTHING;
|
|
360
|
+
const reach = {
|
|
361
|
+
op: "in",
|
|
362
|
+
field: node.field,
|
|
363
|
+
value: ids
|
|
364
|
+
};
|
|
365
|
+
const guard = relatedRowGuard(node);
|
|
366
|
+
const conditions = [reach, ...guard === void 0 ? [] : [notRestricted(guard)]];
|
|
367
|
+
const above = node.restrictedAncestors;
|
|
368
|
+
if (above !== void 0) {
|
|
369
|
+
const closed = await readIds(restrictedRowsSql(above, mapping), above.parent);
|
|
370
|
+
if (closed.length > 0) conditions.push({
|
|
371
|
+
op: "or",
|
|
372
|
+
conditions: [{
|
|
373
|
+
op: "isNull",
|
|
374
|
+
field: above.parent,
|
|
375
|
+
value: true
|
|
376
|
+
}, {
|
|
377
|
+
op: "notIn",
|
|
378
|
+
field: above.parent,
|
|
379
|
+
value: closed
|
|
380
|
+
}]
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return conditions.length === 1 ? reach : {
|
|
384
|
+
op: "and",
|
|
385
|
+
conditions
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
async function readIds(parts, field) {
|
|
389
|
+
const query = renderGraphSql(parts, {
|
|
356
390
|
subject: subject ?? "",
|
|
357
391
|
placeholder: (index) => `$${String(index)}`,
|
|
358
392
|
/* v8 ignore next 3 */
|
|
@@ -360,26 +394,16 @@ async function resolveRelated(where, options) {
|
|
|
360
394
|
throw refused(`related: no row column '${name}' in an id query`);
|
|
361
395
|
}
|
|
362
396
|
});
|
|
363
|
-
|
|
397
|
+
return (await options.run({
|
|
364
398
|
sql: `select distinct r.id from (${query.sql}) r where r.id is not null`,
|
|
365
399
|
values: query.values
|
|
366
400
|
})).flatMap((row) => {
|
|
367
401
|
const id = row["id"];
|
|
368
402
|
if (typeof id !== "string" && typeof id !== "number") return [];
|
|
369
403
|
const text = String(id);
|
|
370
|
-
const parsed = options.parse === void 0 ? text : options.parse(text,
|
|
404
|
+
const parsed = options.parse === void 0 ? text : options.parse(text, field);
|
|
371
405
|
return typeof parsed === "string" || typeof parsed === "number" || typeof parsed === "boolean" ? [parsed] : [];
|
|
372
406
|
});
|
|
373
|
-
const reach = ids.length === 0 ? NOTHING : {
|
|
374
|
-
op: "in",
|
|
375
|
-
field: node.field,
|
|
376
|
-
value: ids
|
|
377
|
-
};
|
|
378
|
-
const guard = relatedRowGuard(node);
|
|
379
|
-
return guard === void 0 || ids.length === 0 ? reach : {
|
|
380
|
-
op: "and",
|
|
381
|
-
conditions: [reach, notRestricted(guard)]
|
|
382
|
-
};
|
|
383
407
|
}
|
|
384
408
|
async function resolve(node) {
|
|
385
409
|
switch (node.op) {
|
|
@@ -408,7 +432,8 @@ async function resolveRelated(where, options) {
|
|
|
408
432
|
case "notIn":
|
|
409
433
|
case "isNull":
|
|
410
434
|
case "memberOf":
|
|
411
|
-
case "opaque":
|
|
435
|
+
case "opaque":
|
|
436
|
+
case "liveSession": return node;
|
|
412
437
|
default: return node;
|
|
413
438
|
}
|
|
414
439
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
2
|
+
import { n as PermDockValidationError, t as PROBLEM_BASE } from "./validation-error-CnjZ4t92.js";
|
|
3
|
+
import { i as stepUpOf, n as problemDetails, t as notFoundDetails } from "./problem-details-_AMOYz-w.js";
|
|
4
|
+
import { a as deniedMessage, i as approvalMessage } from "./errors-Cz5zn0mW.js";
|
|
4
5
|
//#region src/server/problem.ts
|
|
5
|
-
const PROBLEM_BASE = "https://permdock.dev/problems";
|
|
6
6
|
function quoted(value) {
|
|
7
7
|
return `"${value.replaceAll(/["\\]/gu, "")}"`;
|
|
8
8
|
}
|
|
@@ -29,28 +29,12 @@ function protectedResourceMetadataUrl(resource) {
|
|
|
29
29
|
const path = resource.pathname === "/" ? "" : resource.pathname;
|
|
30
30
|
return `${resource.origin}/.well-known/oauth-protected-resource${path}`;
|
|
31
31
|
}
|
|
32
|
-
/** The `acr` values and the tightest `maxAge` the failing assurance grants ask for. */
|
|
33
|
-
function stepUpOf(decision) {
|
|
34
|
-
if (decision.outcome !== "denied") return {};
|
|
35
|
-
const acr = /* @__PURE__ */ new Set();
|
|
36
|
-
let maxAge;
|
|
37
|
-
for (const denial of decision.denials) {
|
|
38
|
-
if (denial.reason !== "insufficient-user-authentication") continue;
|
|
39
|
-
const grantees = denial.to === void 0 ? [] : Array.isArray(denial.to) ? denial.to : [denial.to];
|
|
40
|
-
for (const grantee of grantees) {
|
|
41
|
-
if (grantee.kind !== "assurance") continue;
|
|
42
|
-
for (const value of grantee.acr ?? []) acr.add(value);
|
|
43
|
-
if (grantee.maxAge !== void 0) maxAge = maxAge === void 0 ? grantee.maxAge : Math.min(maxAge, grantee.maxAge);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return compact({
|
|
47
|
-
acrValues: acr.size === 0 ? void 0 : [...acr],
|
|
48
|
-
maxAge
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
32
|
/** The `error_description` of every `invalid_token` challenge (RFC 6750 section 3.1). */
|
|
52
33
|
const INVALID_TOKEN = "The access token is invalid";
|
|
53
34
|
function wwwAuthenticate(decision, permission, credentials = true) {
|
|
35
|
+
return challengeFor(decision, permission?.scope, credentials);
|
|
36
|
+
}
|
|
37
|
+
function challengeFor(decision, scope, credentials = true) {
|
|
54
38
|
if (decision.outcome !== "denied") return;
|
|
55
39
|
const reasons = new Set(decision.denials.map((denial) => denial.reason));
|
|
56
40
|
if (reasons.has("insufficient-user-authentication")) return bearerChallenge({
|
|
@@ -63,7 +47,7 @@ function wwwAuthenticate(decision, permission, credentials = true) {
|
|
|
63
47
|
}) : "Bearer";
|
|
64
48
|
if (reasons.has("not-delegated") || reasons.has("no-delegation")) return bearerChallenge(compact({
|
|
65
49
|
error: "insufficient_scope",
|
|
66
|
-
scopes:
|
|
50
|
+
scopes: scope === void 0 ? void 0 : [scope]
|
|
67
51
|
}));
|
|
68
52
|
}
|
|
69
53
|
function problemResponse(details, permission, decision, extra, credentials) {
|
|
@@ -97,12 +81,8 @@ function validationProblem(detail) {
|
|
|
97
81
|
detail
|
|
98
82
|
}));
|
|
99
83
|
}
|
|
100
|
-
function resourceRef(permission
|
|
101
|
-
|
|
102
|
-
return compact({
|
|
103
|
-
type: permission.resource,
|
|
104
|
-
id: typeof id === "string" || typeof id === "number" ? String(id) : void 0
|
|
105
|
-
});
|
|
84
|
+
function resourceRef(permission) {
|
|
85
|
+
return { type: permission.resource };
|
|
106
86
|
}
|
|
107
87
|
function isLimitDetail(value) {
|
|
108
88
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -133,94 +113,79 @@ function rateLimitHeaders(decision, now = Date.now() / 1e3) {
|
|
|
133
113
|
"RateLimit-Policy": entries.map((entry) => `${entry.name};q=${entry.detail.count};w=${entry.detail.window}`).join(", ")
|
|
134
114
|
};
|
|
135
115
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
116
|
+
/**
|
|
117
|
+
* The response for a decision's Problem Details: `WWW-Authenticate` for a
|
|
118
|
+
* `401` or a missing delegation, and the rate-limit fields for a `429`. A
|
|
119
|
+
* hidden row's `404` carries neither, so it reads like a missing one.
|
|
120
|
+
*/
|
|
121
|
+
function decisionResponse(details, decision, options = {}) {
|
|
122
|
+
const headers = new Headers({
|
|
123
|
+
...details.status === 429 ? rateLimitHeaders(decision) : {},
|
|
124
|
+
"content-type": "application/problem+json"
|
|
125
|
+
});
|
|
126
|
+
const challenge = details.status === 404 ? void 0 : challengeFor(decision, options.scope, options.credentials);
|
|
127
|
+
if (challenge !== void 0) headers.set("WWW-Authenticate", challenge);
|
|
128
|
+
return new Response(JSON.stringify(details), {
|
|
129
|
+
status: details.status,
|
|
130
|
+
headers
|
|
131
|
+
});
|
|
132
|
+
}
|
|
142
133
|
function problemFromDecision(decision, permission, subject, options = {}) {
|
|
143
|
-
const base = PROBLEM_BASE;
|
|
144
134
|
if (decision.outcome === "granted") return new Response(null, { status: 204 });
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
message: approvalMessage(permission.key, decision.reason, decision.token)
|
|
152
|
-
}).toProblemDetails(compact({ instance: options.instance }));
|
|
153
|
-
const approval = options.approval === void 0 || options.approval.at === void 0 && options.approval.hint === void 0 ? void 0 : compact({
|
|
154
|
-
at: options.approval.at,
|
|
155
|
-
hint: options.approval.hint
|
|
156
|
-
});
|
|
157
|
-
return problemResponse(compact({
|
|
158
|
-
...details,
|
|
159
|
-
type: `${base}/approval-required`,
|
|
160
|
-
approval
|
|
161
|
-
}), permission, decision);
|
|
162
|
-
}
|
|
163
|
-
const reasons = new Set(decision.denials.map((denial) => denial.reason));
|
|
164
|
-
if (options.disclosure === "hide" && ![...reasons].every((reason) => HOLDS_GRANT.has(reason))) return notFoundProblem(options.instance);
|
|
165
|
-
if (decision.denials.some((denial) => denial.detail instanceof PermDockValidationError)) {
|
|
166
|
-
const validation = decision.denials[0]?.detail;
|
|
167
|
-
if (validation instanceof PermDockValidationError) return problemResponse(validation.toProblemDetails(), permission, decision);
|
|
168
|
-
}
|
|
169
|
-
const details = new PermDockDeniedError({
|
|
135
|
+
const validation = decision.outcome === "denied" ? decision.denials[0]?.detail : void 0;
|
|
136
|
+
if (options.disclosure !== "hide" && validation instanceof PermDockValidationError) return problemResponse(validation.toProblemDetails(), options.scope === void 0 ? permission : {
|
|
137
|
+
...permission,
|
|
138
|
+
scope: options.scope
|
|
139
|
+
}, decision);
|
|
140
|
+
const details = problemDetails(compact({
|
|
170
141
|
decision,
|
|
142
|
+
detail: decision.outcome === "approval-required" ? approvalMessage(permission.key, decision.reason, decision.token) : deniedMessage(permission.key, subject?.principal?.id, decision.denials, decision.alternatives.map((leaf) => leaf.key), subject !== void 0),
|
|
143
|
+
instance: options.instance,
|
|
171
144
|
permission: permission.key,
|
|
172
145
|
scope: permission.scope,
|
|
173
|
-
resource: resourceRef(permission
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
detail: "Authenticate and repeat the request",
|
|
182
|
-
instance: options.instance,
|
|
183
|
-
permission: permission.key
|
|
184
|
-
}), permission, decision, void 0, options.credentials);
|
|
185
|
-
if (reasons.has("insufficient-user-authentication")) return problemResponse(compact({
|
|
186
|
-
...details,
|
|
187
|
-
status: 401,
|
|
188
|
-
type: `${base}/step-up-required`,
|
|
189
|
-
...stepUpOf(decision)
|
|
190
|
-
}), permission, decision);
|
|
191
|
-
const plans = requiredPlans(decision);
|
|
192
|
-
if (plans.length > 0) return problemResponse({
|
|
193
|
-
...details,
|
|
194
|
-
type: `${base}/not-entitled`,
|
|
195
|
-
title: "Plan upgrade required",
|
|
196
|
-
plans
|
|
197
|
-
}, permission, decision);
|
|
198
|
-
if (reasons.size > 0 && [...reasons].every((reason) => reason === "limit")) return problemResponse({
|
|
199
|
-
...details,
|
|
200
|
-
status: 429,
|
|
201
|
-
type: `${base}/rate-limited`,
|
|
202
|
-
title: "Rate limit exceeded"
|
|
203
|
-
}, permission, decision, rateLimitHeaders(decision));
|
|
204
|
-
if (reasons.has("limit-unavailable") && [...reasons].every((reason) => reason === "limit" || reason === "limit-unavailable")) return problemResponse({
|
|
205
|
-
...details,
|
|
206
|
-
status: 503,
|
|
207
|
-
type: `${base}/limit-unavailable`,
|
|
208
|
-
title: "Rate limit unavailable"
|
|
209
|
-
}, permission, decision);
|
|
210
|
-
return problemResponse({
|
|
146
|
+
resource: resourceRef(permission),
|
|
147
|
+
disclosure: options.disclosure
|
|
148
|
+
}));
|
|
149
|
+
const approval = decision.outcome !== "approval-required" || options.approval === void 0 || options.approval.at === void 0 && options.approval.hint === void 0 ? void 0 : compact({
|
|
150
|
+
at: options.approval.at,
|
|
151
|
+
hint: options.approval.hint
|
|
152
|
+
});
|
|
153
|
+
return decisionResponse(approval === void 0 ? details : {
|
|
211
154
|
...details,
|
|
212
|
-
|
|
213
|
-
},
|
|
155
|
+
approval
|
|
156
|
+
}, decision, compact({
|
|
157
|
+
scope: options.scope ?? permission.scope,
|
|
158
|
+
credentials: options.credentials
|
|
159
|
+
}));
|
|
214
160
|
}
|
|
215
161
|
/** The `404` a missing row and a hidden one share, so the two read the same. */
|
|
216
162
|
function notFoundProblem(instance) {
|
|
217
|
-
return problemResponse(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
163
|
+
return problemResponse(notFoundDetails(instance));
|
|
164
|
+
}
|
|
165
|
+
const ANONYMOUS = {
|
|
166
|
+
outcome: "denied",
|
|
167
|
+
denials: [{
|
|
168
|
+
role: null,
|
|
169
|
+
reason: "anonymous"
|
|
170
|
+
}],
|
|
171
|
+
alternatives: []
|
|
172
|
+
};
|
|
173
|
+
/** The `401` for a request with no subject, with the RFC 6750 challenge its credentials call for. */
|
|
174
|
+
function unauthenticatedProblem(credentials) {
|
|
175
|
+
return decisionResponse(problemDetails({
|
|
176
|
+
decision: ANONYMOUS,
|
|
177
|
+
detail: "anonymous"
|
|
178
|
+
}), ANONYMOUS, { credentials });
|
|
179
|
+
}
|
|
180
|
+
function methodNotAllowed(allow) {
|
|
181
|
+
const response = problemResponse({
|
|
182
|
+
type: `${PROBLEM_BASE}/method-not-allowed`,
|
|
183
|
+
title: "Method not allowed",
|
|
184
|
+
status: 405,
|
|
185
|
+
detail: `use ${allow}`
|
|
186
|
+
});
|
|
187
|
+
response.headers.set("Allow", allow);
|
|
188
|
+
return response;
|
|
224
189
|
}
|
|
225
190
|
//#endregion
|
|
226
|
-
export {
|
|
191
|
+
export { notFoundProblem as a, protectedResourceMetadataUrl as c, wwwAuthenticate as d, methodNotAllowed as i, unauthenticatedProblem as l, bearerChallenge as n, problemFromDecision as o, decisionResponse as r, problemResponse as s, batchTooLarge as t, validationProblem as u };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Yn as Decision } from "./policy-CFZAr_Al.js";
|
|
2
|
+
//#region src/core/problem-details.d.ts
|
|
3
|
+
type Disclosure = "hide" | "reveal";
|
|
4
|
+
/** The plans a `not-entitled` denial asks for; empty unless every denial is `not-entitled`. */
|
|
5
|
+
declare function requiredPlans(decision: Decision): readonly string[];
|
|
6
|
+
//#endregion
|
|
7
|
+
export { requiredPlans as n, Disclosure as t };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { t as PROBLEM_BASE } from "./validation-error-CnjZ4t92.js";
|
|
3
|
+
//#region src/core/wire-denial.ts
|
|
4
|
+
const IN_PROCESS = /* @__PURE__ */ new Set(["closure-error", "validation"]);
|
|
5
|
+
function jsonDetail(value) {
|
|
6
|
+
if (value === void 0 || value === null || value instanceof Error) return;
|
|
7
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
8
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
9
|
+
if (typeof value !== "object") return;
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(JSON.stringify(value));
|
|
12
|
+
} catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function wireDenial(denial) {
|
|
17
|
+
return compact({
|
|
18
|
+
role: denial.role,
|
|
19
|
+
reason: denial.reason,
|
|
20
|
+
to: denial.to,
|
|
21
|
+
detail: IN_PROCESS.has(denial.reason) ? void 0 : jsonDetail(denial.detail)
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function wireDenials(denials) {
|
|
25
|
+
return denials.map(wireDenial);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/core/problem-details.ts
|
|
29
|
+
/** Reasons that only arise once a matching grant was found, so they reveal nothing hidden. */
|
|
30
|
+
const HOLDS_GRANT = /* @__PURE__ */ new Set([
|
|
31
|
+
"insufficient-user-authentication",
|
|
32
|
+
"limit",
|
|
33
|
+
"limit-unavailable"
|
|
34
|
+
]);
|
|
35
|
+
function granteesOf(to) {
|
|
36
|
+
if (to === void 0) return [];
|
|
37
|
+
return Array.isArray(to) ? to : [to];
|
|
38
|
+
}
|
|
39
|
+
/** The plans a `not-entitled` denial asks for; empty unless every denial is `not-entitled`. */
|
|
40
|
+
function requiredPlans(decision) {
|
|
41
|
+
if (decision.outcome !== "denied" || decision.denials.length === 0 || decision.denials.some((denial) => denial.reason !== "not-entitled")) return [];
|
|
42
|
+
const plans = /* @__PURE__ */ new Set();
|
|
43
|
+
for (const denial of decision.denials) for (const item of granteesOf(denial.to)) if (item.kind === "plan") plans.add(item.plan);
|
|
44
|
+
return [...plans];
|
|
45
|
+
}
|
|
46
|
+
/** The `acr` values and the tightest `maxAge` the failing assurance grants ask for. */
|
|
47
|
+
function stepUpOf(decision) {
|
|
48
|
+
if (decision.outcome !== "denied") return {};
|
|
49
|
+
const acr = /* @__PURE__ */ new Set();
|
|
50
|
+
let maxAge;
|
|
51
|
+
for (const denial of decision.denials) {
|
|
52
|
+
if (denial.reason !== "insufficient-user-authentication") continue;
|
|
53
|
+
for (const grantee of granteesOf(denial.to)) {
|
|
54
|
+
if (grantee.kind !== "assurance") continue;
|
|
55
|
+
for (const value of grantee.acr ?? []) acr.add(value);
|
|
56
|
+
if (grantee.maxAge !== void 0) maxAge = maxAge === void 0 ? grantee.maxAge : Math.min(maxAge, grantee.maxAge);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return compact({
|
|
60
|
+
acrValues: acr.size === 0 ? void 0 : [...acr],
|
|
61
|
+
maxAge
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** The `404` a missing row and a hidden one share, so the two read the same. */
|
|
65
|
+
function notFoundDetails(instance) {
|
|
66
|
+
return compact({
|
|
67
|
+
type: `${PROBLEM_BASE}/not-found`,
|
|
68
|
+
title: "Not found",
|
|
69
|
+
status: 404,
|
|
70
|
+
detail: "No such resource",
|
|
71
|
+
instance
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The RFC 9457 body for a decision that is not `granted`. One status matrix
|
|
76
|
+
* serves `protect`, a thrown `assert` and `problemFromError`: `401` for an
|
|
77
|
+
* anonymous subject or a step-up, `404` for a hidden row, `429` for an
|
|
78
|
+
* exhausted limit, `503` for an unavailable limit store, `403` otherwise.
|
|
79
|
+
*/
|
|
80
|
+
function problemDetails(input) {
|
|
81
|
+
const { decision } = input;
|
|
82
|
+
const base = compact({
|
|
83
|
+
instance: input.instance,
|
|
84
|
+
permission: input.permission,
|
|
85
|
+
scope: input.scope,
|
|
86
|
+
resource: input.resource
|
|
87
|
+
});
|
|
88
|
+
if (decision.outcome === "approval-required") return compact({
|
|
89
|
+
type: `${PROBLEM_BASE}/approval-required`,
|
|
90
|
+
title: "Approval required",
|
|
91
|
+
status: 403,
|
|
92
|
+
detail: input.detail,
|
|
93
|
+
...base,
|
|
94
|
+
reason: decision.reason,
|
|
95
|
+
token: decision.token
|
|
96
|
+
});
|
|
97
|
+
const reasons = new Set(decision.denials.map((denial) => denial.reason));
|
|
98
|
+
if (input.disclosure === "hide" && ![...reasons].every((reason) => HOLDS_GRANT.has(reason))) return notFoundDetails(input.instance);
|
|
99
|
+
if (reasons.has("anonymous")) return compact({
|
|
100
|
+
type: `${PROBLEM_BASE}/unauthenticated`,
|
|
101
|
+
title: "Authentication required",
|
|
102
|
+
status: 401,
|
|
103
|
+
detail: "Authenticate and repeat the request",
|
|
104
|
+
instance: input.instance,
|
|
105
|
+
permission: input.permission
|
|
106
|
+
});
|
|
107
|
+
const denied = compact({
|
|
108
|
+
type: `${PROBLEM_BASE}/denied`,
|
|
109
|
+
title: "Permission denied",
|
|
110
|
+
status: 403,
|
|
111
|
+
detail: input.detail,
|
|
112
|
+
...base,
|
|
113
|
+
denials: wireDenials(decision.denials),
|
|
114
|
+
alternatives: decision.alternatives.map((leaf) => leaf.key)
|
|
115
|
+
});
|
|
116
|
+
if (reasons.has("insufficient-user-authentication")) return {
|
|
117
|
+
...denied,
|
|
118
|
+
status: 401,
|
|
119
|
+
type: `${PROBLEM_BASE}/step-up-required`,
|
|
120
|
+
...stepUpOf(decision)
|
|
121
|
+
};
|
|
122
|
+
const plans = requiredPlans(decision);
|
|
123
|
+
if (plans.length > 0) return {
|
|
124
|
+
...denied,
|
|
125
|
+
type: `${PROBLEM_BASE}/not-entitled`,
|
|
126
|
+
title: "Plan upgrade required",
|
|
127
|
+
plans
|
|
128
|
+
};
|
|
129
|
+
if (reasons.size > 0 && [...reasons].every((reason) => reason === "limit")) return {
|
|
130
|
+
...denied,
|
|
131
|
+
status: 429,
|
|
132
|
+
type: `${PROBLEM_BASE}/rate-limited`,
|
|
133
|
+
title: "Rate limit exceeded"
|
|
134
|
+
};
|
|
135
|
+
if (reasons.has("limit-unavailable") && [...reasons].every((reason) => reason === "limit" || reason === "limit-unavailable")) return {
|
|
136
|
+
...denied,
|
|
137
|
+
status: 503,
|
|
138
|
+
type: `${PROBLEM_BASE}/limit-unavailable`,
|
|
139
|
+
title: "Rate limit unavailable"
|
|
140
|
+
};
|
|
141
|
+
return denied;
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
export { wireDenials as a, stepUpOf as i, problemDetails as n, requiredPlans as r, notFoundDetails as t };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { r as Role } from "./vocabulary-
|
|
4
|
-
import { a as FilterResult, c as
|
|
1
|
+
import { D as PolicyVocabulary, Mr as Membership, Yn as Decision } from "./policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission } from "./permissions-DttnqqxC.js";
|
|
3
|
+
import { r as Role } from "./vocabulary-DA8a8zif.js";
|
|
4
|
+
import { a as FilterResult, c as SubjectView, l as TenantView, o as PermissionSet, r as ClientPermDock, s as PermissionState, t as ApprovalHandle, u as UseRolesOptions } from "./types-kxznc7cn.js";
|
|
5
|
+
import { n as ProtectedProps } from "./types-C3s9xVJG.js";
|
|
5
6
|
import { ReactNode } from "react";
|
|
6
7
|
//#region src/react/hooks.d.ts
|
|
7
8
|
declare function usePermDock<V extends PolicyVocabulary = PolicyVocabulary>(): ClientPermDock<V>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { n as storeOf } from "./store-options-yO0V6gRn.js";
|
|
2
|
+
import { a as protectedView, c as subjectView, i as permissionSet, l as tenantView, n as filterResult, o as rolesView, s as scopedTenant, t as approvalHandle } from "./views-Soe7bGSC.js";
|
|
3
|
+
import { i as PermDockStoreContext, r as PermDockSnapshotPromiseContext } from "./live-options-H2eG8dfJ.js";
|
|
4
|
+
import { Suspense, use, useMemo, useSyncExternalStore } from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
//#region src/react/hooks.ts
|
|
7
|
+
function useStore() {
|
|
8
|
+
const store = use(PermDockStoreContext);
|
|
9
|
+
if (store === null) throw new Error("PermDock: hooks require <PermDockProvider>.");
|
|
10
|
+
const pending = use(PermDockSnapshotPromiseContext);
|
|
11
|
+
if (pending !== null) store.adopt(use(pending), pending);
|
|
12
|
+
return store;
|
|
13
|
+
}
|
|
14
|
+
function usePermDock() {
|
|
15
|
+
const store = useStore();
|
|
16
|
+
return useSyncExternalStore((listener) => store.subscribe(listener), () => store.get(), () => store.get());
|
|
17
|
+
}
|
|
18
|
+
function usePermission(permission, data) {
|
|
19
|
+
const permdock = usePermDock();
|
|
20
|
+
return useMemo(() => storeOf(permdock).permissionState(permission, data), [
|
|
21
|
+
permdock,
|
|
22
|
+
permission,
|
|
23
|
+
data
|
|
24
|
+
]);
|
|
25
|
+
}
|
|
26
|
+
function usePermissions(permissions, data) {
|
|
27
|
+
const permdock = usePermDock();
|
|
28
|
+
return useMemo(() => permissionSet(storeOf(permdock), permissions, data), [
|
|
29
|
+
permdock,
|
|
30
|
+
permissions,
|
|
31
|
+
data
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
function useFilter(permission, rows) {
|
|
35
|
+
const permdock = usePermDock();
|
|
36
|
+
return useMemo(() => filterResult(permdock, permission, rows), [
|
|
37
|
+
permdock,
|
|
38
|
+
permission,
|
|
39
|
+
rows
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
function useTenant() {
|
|
43
|
+
const permdock = usePermDock();
|
|
44
|
+
return useMemo(() => tenantView(permdock), [permdock]);
|
|
45
|
+
}
|
|
46
|
+
function useMemberships() {
|
|
47
|
+
const permdock = usePermDock();
|
|
48
|
+
return useMemo(() => permdock.memberships(), [permdock]);
|
|
49
|
+
}
|
|
50
|
+
function useRoles(options = {}) {
|
|
51
|
+
const permdock = usePermDock();
|
|
52
|
+
const { tenant, team } = options;
|
|
53
|
+
return useMemo(() => rolesView(permdock, {
|
|
54
|
+
...tenant === void 0 ? {} : { tenant },
|
|
55
|
+
...team === void 0 ? {} : { team }
|
|
56
|
+
}), [
|
|
57
|
+
permdock,
|
|
58
|
+
tenant,
|
|
59
|
+
team
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
function useAssignableRoles() {
|
|
63
|
+
const permdock = usePermDock();
|
|
64
|
+
return useMemo(() => permdock.assignableRoles(), [permdock]);
|
|
65
|
+
}
|
|
66
|
+
function useAssignablePermissions(options = {}) {
|
|
67
|
+
const permdock = usePermDock();
|
|
68
|
+
const { tenant } = options;
|
|
69
|
+
return useMemo(() => permdock.assignablePermissions(tenant === void 0 ? {} : { tenant }), [permdock, tenant]);
|
|
70
|
+
}
|
|
71
|
+
function useSubject() {
|
|
72
|
+
const permdock = usePermDock();
|
|
73
|
+
return useMemo(() => subjectView(permdock), [permdock]);
|
|
74
|
+
}
|
|
75
|
+
function useApproval(decision) {
|
|
76
|
+
return approvalHandle(storeOf(usePermDock()), decision);
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/react/protected.tsx
|
|
80
|
+
function Protected(props) {
|
|
81
|
+
if (props.pending === void 0) return /* @__PURE__ */ jsx(Guard, { ...props });
|
|
82
|
+
return /* @__PURE__ */ jsx(Suspense, {
|
|
83
|
+
fallback: props.pending,
|
|
84
|
+
children: /* @__PURE__ */ jsx(Guard, { ...props })
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function Guard(props) {
|
|
88
|
+
const root = usePermDock();
|
|
89
|
+
const local = usePermission(props.permission, props.data);
|
|
90
|
+
const scoped = useMemo(() => scopedTenant(root, props.tenant), [root, props.tenant]);
|
|
91
|
+
const view = protectedView(local, root, props.permission, props.data, scoped);
|
|
92
|
+
switch (view.slot) {
|
|
93
|
+
case "pending": return props.pending ?? null;
|
|
94
|
+
case "fallback": return typeof props.fallback === "function" ? props.fallback(view.decision) : props.fallback ?? null;
|
|
95
|
+
case "default": return typeof props.children === "function" ? props.children(view.decision) : props.children;
|
|
96
|
+
default: return view;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { useFilter as a, usePermission as c, useSubject as d, useTenant as f, useAssignableRoles as i, usePermissions as l, useApproval as n, useMemberships as o, useAssignablePermissions as r, usePermDock as s, Protected as t, useRoles as u };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Yn as Decision, er as GrantedDecision, ln as PermDock } from "./policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission } from "./permissions-DttnqqxC.js";
|
|
3
|
+
import { t as PermissionBoundaryState } from "./boundary-BmHxVH1J.js";
|
|
4
|
+
import { s as PermissionState } from "./types-kxznc7cn.js";
|
|
5
|
+
import { t as ClientStore } from "./store-D_pjn91-.js";
|
|
6
|
+
import { Snippet } from "svelte";
|
|
7
|
+
//#region src/svelte/boundary.d.ts
|
|
8
|
+
type PermissionBoundaryProps = {
|
|
9
|
+
readonly children?: Snippet;
|
|
10
|
+
/** Rendered in place of the children when one throws `PermDockDeniedError`. */
|
|
11
|
+
readonly denied?: Snippet<[PermissionBoundaryState]>;
|
|
12
|
+
/** Rendered for `PermDockApprovalRequiredError`; defaults to `denied`. */
|
|
13
|
+
readonly approval?: Snippet<[PermissionBoundaryState]>;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/client/views.d.ts
|
|
17
|
+
/** What `Protected` renders: `pending` while an endpoint answer is in flight, `fallback` unless granted. */
|
|
18
|
+
type ProtectedView = (PermissionState & {
|
|
19
|
+
readonly slot: "pending" | "fallback";
|
|
20
|
+
}) | {
|
|
21
|
+
readonly allowed: true;
|
|
22
|
+
readonly status: PermissionState["status"];
|
|
23
|
+
readonly decision: GrantedDecision;
|
|
24
|
+
readonly slot: "default";
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/svelte/protected.d.ts
|
|
28
|
+
type ProtectedProps = {
|
|
29
|
+
readonly permission: Permission;
|
|
30
|
+
readonly data?: unknown;
|
|
31
|
+
readonly tenant?: string;
|
|
32
|
+
readonly children?: Snippet<[Decision]>;
|
|
33
|
+
readonly pending?: Snippet;
|
|
34
|
+
readonly fallback?: Snippet<[Decision]>;
|
|
35
|
+
};
|
|
36
|
+
/** The instance for `tenant`, built once per store change rather than once per check. */
|
|
37
|
+
declare function scopedFor(store: ClientStore, tenant: string | undefined, _generation?: number): PermDock | undefined;
|
|
38
|
+
declare function viewFor(store: ClientStore, reference: Permission, data: unknown, scoped: PermDock | undefined, _generation?: number): ProtectedView;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { PermissionBoundaryProps as i, scopedFor as n, viewFor as r, ProtectedProps as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as PermDockProviderProps } from "./types-C3s9xVJG.js";
|
|
2
2
|
import { ReactElement } from "react";
|
|
3
3
|
//#region src/react/provider.d.ts
|
|
4
4
|
declare function PermDockProvider(props: PermDockProviderProps): ReactElement;
|