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
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
|
|
3
|
+
import { i as findPermission, s as getRegistry } from "./permissions-DVoF6dMt.js";
|
|
4
|
+
import { r as approverLeaves } from "./approvers-DT4AVyIg.js";
|
|
5
|
+
import { t as describe } from "./describe-B_gVZEVi.js";
|
|
6
|
+
import { t as parseDuration } from "./duration-xK2jGFVc.js";
|
|
7
|
+
import { i as relationReader, n as pendingRelations, o as resolveRelated } from "./relations-cjOL01hZ.js";
|
|
8
|
+
import { t as ApprovalError } from "./errors-DRnGZHzF.js";
|
|
9
|
+
import { f as approverRelationKey, l as APPROVAL_HEADER, n as assertApprover, s as listAllApprovals } from "./store-DMAWwAJV.js";
|
|
10
|
+
//#region src/approvals/relations.ts
|
|
11
|
+
const DEFAULT_PARENT_DEPTH = 16;
|
|
12
|
+
/** Every approver a request names: `by`, each stage and its escalation, and `escalation.to`, inside `anyOf` groups too. */
|
|
13
|
+
function requestApprovers(approvers) {
|
|
14
|
+
return [
|
|
15
|
+
...approverLeaves(approvers.by),
|
|
16
|
+
...(approvers.stages ?? []).flatMap((stage) => approverLeaves(stage.by).concat(approverLeaves(stage.escalation?.to))),
|
|
17
|
+
...approverLeaves(approvers.escalation?.to)
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
/** Reads until nothing is in flight: each round loads one more layer of facts. */
|
|
21
|
+
async function settled(read, unread, cache) {
|
|
22
|
+
for (;;) {
|
|
23
|
+
const value = read();
|
|
24
|
+
if (!unread(value)) return value;
|
|
25
|
+
const pending = pendingRelations(cache);
|
|
26
|
+
if (pending.length === 0) return value;
|
|
27
|
+
await Promise.all(pending);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** The id of `item.resource` the walk starts from, after following `through` links. */
|
|
31
|
+
async function startOf(item, resource, id, reader, cache, registry) {
|
|
32
|
+
if (!Array.isArray(item.through)) return resource === item.resource ? id : void 0;
|
|
33
|
+
let current = resource;
|
|
34
|
+
let at = id;
|
|
35
|
+
for (const link of item.through) {
|
|
36
|
+
const node = registry.get(current);
|
|
37
|
+
const target = node !== void 0 && Object.hasOwn(node.links, link) ? node.links[link] : void 0;
|
|
38
|
+
if (target === void 0) return;
|
|
39
|
+
const query = {
|
|
40
|
+
resource: current,
|
|
41
|
+
id: at,
|
|
42
|
+
depth: 1,
|
|
43
|
+
through: link
|
|
44
|
+
};
|
|
45
|
+
const chain = await settled(() => reader.chain(query), (value) => value === "pending", cache);
|
|
46
|
+
const next = chain === "pending" || chain === "failed" ? void 0 : chain.ancestors[0]?.id;
|
|
47
|
+
if (next === void 0) return;
|
|
48
|
+
current = target.resource;
|
|
49
|
+
at = next;
|
|
50
|
+
}
|
|
51
|
+
return current === item.resource ? at : void 0;
|
|
52
|
+
}
|
|
53
|
+
function depthOf(item) {
|
|
54
|
+
if (item.through === "parent") return item.depth ?? DEFAULT_PARENT_DEPTH;
|
|
55
|
+
return item.depth ?? 0;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The relation approvers of `request` that `subject` holds on its resource,
|
|
59
|
+
* keyed by `approverRelationKey`, for `ApprovalVerdict.relations`. Reads go
|
|
60
|
+
* through `relations` by the request's resource id; a request without an id,
|
|
61
|
+
* a missing source or a read that fails holds nothing.
|
|
62
|
+
*/
|
|
63
|
+
async function approverRelations(request, subject, options) {
|
|
64
|
+
const approvers = request.approvers;
|
|
65
|
+
const id = request.resource.id;
|
|
66
|
+
if (approvers === void 0 || id === void 0 || options.relations === void 0 || options.permissions === void 0 || subject.principal === null) return [];
|
|
67
|
+
const items = /* @__PURE__ */ new Map();
|
|
68
|
+
for (const item of requestApprovers(approvers)) if (item.kind === "relation") items.set(approverRelationKey(item), item);
|
|
69
|
+
if (items.size === 0) return [];
|
|
70
|
+
const registry = getRegistry(options.permissions);
|
|
71
|
+
const cache = /* @__PURE__ */ new Map();
|
|
72
|
+
const reader = relationReader(options.relations, cache, registry);
|
|
73
|
+
const now = (options.now ?? /* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
74
|
+
const holds = async (item) => {
|
|
75
|
+
const start = await startOf(item, request.resource.type, id, reader, cache, registry);
|
|
76
|
+
if (start === void 0) return false;
|
|
77
|
+
const condition = {
|
|
78
|
+
op: "related",
|
|
79
|
+
resource: item.resource,
|
|
80
|
+
relation: item.relation,
|
|
81
|
+
field: "id",
|
|
82
|
+
depth: depthOf(item)
|
|
83
|
+
};
|
|
84
|
+
return await settled(() => resolveRelated(condition, { id: start }, subject, now, reader), (value) => value === "relation-unavailable", cache) === true;
|
|
85
|
+
};
|
|
86
|
+
const entries = [...items];
|
|
87
|
+
const verdicts = await Promise.all(entries.map(([, item]) => holds(item)));
|
|
88
|
+
return entries.flatMap(([key], index) => verdicts[index] === true ? [key] : []);
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/approvals/permissions.ts
|
|
92
|
+
/**
|
|
93
|
+
* The `holder(permission)` approvers of `request` that `approver` holds, for
|
|
94
|
+
* `ApprovalVerdict.permissions`: each permission key the approver's own
|
|
95
|
+
* instance grants without a row. `approver` must be an instance for the
|
|
96
|
+
* approving principal in the request's tenant; for any other tenant, or an
|
|
97
|
+
* anonymous instance, it holds nothing. A check that throws holds nothing.
|
|
98
|
+
*/
|
|
99
|
+
function approverPermissions(request, approver) {
|
|
100
|
+
const approvers = request.approvers;
|
|
101
|
+
const principal = approver.subject.principal;
|
|
102
|
+
const tenant = request.subject.principal?.tenant;
|
|
103
|
+
if (approvers === void 0 || principal === null || tenant !== void 0 && principal.tenant !== tenant) return [];
|
|
104
|
+
const keys = /* @__PURE__ */ new Set();
|
|
105
|
+
for (const item of requestApprovers(approvers)) if (item.kind === "permission") keys.add(item.permission);
|
|
106
|
+
return [...keys].filter((key) => {
|
|
107
|
+
const leaf = findPermission(approver.permissions, key);
|
|
108
|
+
if (leaf === void 0) return false;
|
|
109
|
+
try {
|
|
110
|
+
const decide = approver.decide;
|
|
111
|
+
return decide(leaf).outcome === "granted";
|
|
112
|
+
} catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/** The permission approvers `subject` holds on `request`, read through `permdockFor`. */
|
|
118
|
+
async function heldPermissions(request, subject, permdockFor) {
|
|
119
|
+
if (permdockFor === void 0 || request.approvers === void 0) return [];
|
|
120
|
+
try {
|
|
121
|
+
return approverPermissions(request, await permdockFor(subject, request));
|
|
122
|
+
} catch {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/approvals/helpers.ts
|
|
128
|
+
function permissionMeta(permission) {
|
|
129
|
+
return {
|
|
130
|
+
key: permission.key,
|
|
131
|
+
scope: permission.scope,
|
|
132
|
+
resource: permission.resource
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function summariseSubject(subject) {
|
|
136
|
+
const principal = subject.principal;
|
|
137
|
+
return compact({
|
|
138
|
+
principal: principal === null ? null : compact({
|
|
139
|
+
id: principal.id,
|
|
140
|
+
roles: principal.roles ?? [],
|
|
141
|
+
tenant: principal.tenant
|
|
142
|
+
}),
|
|
143
|
+
actor: subject.actor === void 0 ? void 0 : {
|
|
144
|
+
id: subject.actor.id,
|
|
145
|
+
kind: subject.actor.kind
|
|
146
|
+
},
|
|
147
|
+
session: subject.session,
|
|
148
|
+
delegation: subject.delegation === void 0 ? void 0 : compact({
|
|
149
|
+
scopes: subject.delegation.scopes,
|
|
150
|
+
authorizationDetails: subject.delegation.authorizationDetails
|
|
151
|
+
})
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The window (`meta.ttl`, else the store's `ttl`, else the default) capped by the grant's
|
|
156
|
+
* `approval.ttl`: a grant shortens how long a request stays open, never
|
|
157
|
+
* extends it.
|
|
158
|
+
*/
|
|
159
|
+
function approvalTtl(storeTtl, approval) {
|
|
160
|
+
if (storeTtl !== void 0 && (!Number.isSafeInteger(storeTtl) || storeTtl <= 0)) throw new RangeError(`PermDock: approval ttl must be a positive whole number of milliseconds, got ${String(storeTtl)}`);
|
|
161
|
+
const base = storeTtl ?? 36e5;
|
|
162
|
+
const grant = approval === void 0 || approval === "human" ? void 0 : parseDuration(approval.ttl);
|
|
163
|
+
return grant === void 0 ? base : Math.min(base, grant * 1e3);
|
|
164
|
+
}
|
|
165
|
+
async function requestApproval(store, decision, meta) {
|
|
166
|
+
const now = meta.now ?? /* @__PURE__ */ new Date();
|
|
167
|
+
const leaf = permissionMeta(meta.permission);
|
|
168
|
+
const approval = decision.grant.approval;
|
|
169
|
+
const approvers = approval === void 0 || approval === "human" ? void 0 : compact({
|
|
170
|
+
by: approval.by,
|
|
171
|
+
mode: approval.mode,
|
|
172
|
+
stages: approval.stages,
|
|
173
|
+
distinct: approval.distinct,
|
|
174
|
+
staleOn: approval.staleOn,
|
|
175
|
+
quorum: approval.quorum,
|
|
176
|
+
escalation: approval.escalation
|
|
177
|
+
});
|
|
178
|
+
const ttl = approvalTtl(meta.ttl ?? store.ttl, approval);
|
|
179
|
+
const request = freezeDeep(compact({
|
|
180
|
+
v: 1,
|
|
181
|
+
token: decision.token,
|
|
182
|
+
permission: leaf.key,
|
|
183
|
+
scope: leaf.scope,
|
|
184
|
+
resource: meta.resource ?? { type: leaf.resource },
|
|
185
|
+
subject: summariseSubject(meta.subject),
|
|
186
|
+
membership: meta.membership,
|
|
187
|
+
approvers,
|
|
188
|
+
detail: meta.detail ?? describe(decision).detail,
|
|
189
|
+
adapter: meta.adapter,
|
|
190
|
+
createdAt: now.toISOString(),
|
|
191
|
+
expiresAt: new Date(now.getTime() + ttl).toISOString(),
|
|
192
|
+
status: "pending"
|
|
193
|
+
}));
|
|
194
|
+
await store.create(request);
|
|
195
|
+
return request;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Checks `verdict.by` and resolves the request. Relation approvers are read
|
|
199
|
+
* through `options.relations` unless `verdict.relations` is already set.
|
|
200
|
+
*/
|
|
201
|
+
async function resolveApproval(store, token, verdict, options = {}) {
|
|
202
|
+
const current = await store.get(token);
|
|
203
|
+
if (current === null) throw new ApprovalError("approval-not-found", "approval was not found");
|
|
204
|
+
const relations = verdict.relations ?? await approverRelations(current, verdict.by, options);
|
|
205
|
+
const permissions = verdict.permissions ?? await heldPermissions(current, verdict.by, options.permdockFor);
|
|
206
|
+
assertApprover(current, verdict.by, options.requireDistinctApprover === true, options.now, relations, permissions);
|
|
207
|
+
return store.resolve(token, {
|
|
208
|
+
...verdict,
|
|
209
|
+
relations,
|
|
210
|
+
permissions
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
async function vouchApproval(store, token, verdict) {
|
|
214
|
+
if (typeof verdict.rule !== "string" || verdict.rule === "") throw new TypeError("PermDock: vouchApproval needs the name of the rule that decided the verdict");
|
|
215
|
+
return await store.resolve(token, compact({
|
|
216
|
+
status: verdict.status,
|
|
217
|
+
by: verdict.by,
|
|
218
|
+
note: verdict.note,
|
|
219
|
+
vouched: verdict.rule
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
async function inspectApproval(store, token, now = /* @__PURE__ */ new Date()) {
|
|
223
|
+
await store.expire(now);
|
|
224
|
+
const request = await store.get(token);
|
|
225
|
+
if (request === null) return {
|
|
226
|
+
ok: false,
|
|
227
|
+
detail: "approval-not-found"
|
|
228
|
+
};
|
|
229
|
+
if (request.status === "pending") return {
|
|
230
|
+
ok: false,
|
|
231
|
+
detail: "approval-pending"
|
|
232
|
+
};
|
|
233
|
+
if (request.status === "rejected") return {
|
|
234
|
+
ok: false,
|
|
235
|
+
detail: "approval-rejected"
|
|
236
|
+
};
|
|
237
|
+
if (request.consumedAt !== void 0) return {
|
|
238
|
+
ok: false,
|
|
239
|
+
detail: "approval-consumed"
|
|
240
|
+
};
|
|
241
|
+
if (request.status === "expired" || Date.parse(request.expiresAt) <= now.getTime()) return {
|
|
242
|
+
ok: false,
|
|
243
|
+
detail: "approval-expired"
|
|
244
|
+
};
|
|
245
|
+
return {
|
|
246
|
+
ok: true,
|
|
247
|
+
request
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** Inspects `token` and, when it is approved, consumes it so it resumes once. */
|
|
251
|
+
async function consumeApproval(store, token, now = /* @__PURE__ */ new Date()) {
|
|
252
|
+
const inspected = await inspectApproval(store, token, now);
|
|
253
|
+
if (!inspected.ok) return inspected;
|
|
254
|
+
if (typeof store.consume !== "function") return {
|
|
255
|
+
ok: false,
|
|
256
|
+
detail: "approval-not-found"
|
|
257
|
+
};
|
|
258
|
+
const consumed = await store.consume(token, now);
|
|
259
|
+
if (consumed === null) return {
|
|
260
|
+
ok: false,
|
|
261
|
+
detail: "approval-consumed"
|
|
262
|
+
};
|
|
263
|
+
return {
|
|
264
|
+
ok: true,
|
|
265
|
+
request: consumed
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function approvalDenied(detail) {
|
|
269
|
+
return {
|
|
270
|
+
outcome: "denied",
|
|
271
|
+
denials: [{
|
|
272
|
+
role: null,
|
|
273
|
+
reason: "approval",
|
|
274
|
+
detail
|
|
275
|
+
}],
|
|
276
|
+
alternatives: []
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function staleOnChange(decision) {
|
|
280
|
+
const approval = decision.grant.approval;
|
|
281
|
+
return approval !== void 0 && approval !== "human" && approval.staleOn === "resource-change";
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* True when `token` names a pending or approved request for this permission,
|
|
285
|
+
* resource and principal: the same request, issued while the row had another
|
|
286
|
+
* `version`.
|
|
287
|
+
*/
|
|
288
|
+
async function isStaleToken(store, token, input) {
|
|
289
|
+
const principal = input.subject.principal;
|
|
290
|
+
if (principal === null) return false;
|
|
291
|
+
let request;
|
|
292
|
+
try {
|
|
293
|
+
request = await store.get(token);
|
|
294
|
+
} catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
return request !== null && (request.status === "approved" || request.status === "pending") && request.permission === input.permission.key && request.resource.type === input.resource.type && request.resource.id === input.resource.id && request.subject.principal?.id === principal.id;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Applies a resume token to a decision. The token only matters when the
|
|
301
|
+
* decision is `approval-required` and the token is the one this call was
|
|
302
|
+
* issued; otherwise a new approval is requested. A matching token is consumed
|
|
303
|
+
* unless `consume` is `false`, so an approval resumes exactly one call. Under
|
|
304
|
+
* `staleOn: 'resource-change'`, a token issued for an earlier version of the
|
|
305
|
+
* same row denies with `stale-approval`; the next call without it asks again.
|
|
306
|
+
*/
|
|
307
|
+
async function resumeDecision(input) {
|
|
308
|
+
const { decision, store, token } = input;
|
|
309
|
+
if (decision.outcome !== "approval-required") return decision;
|
|
310
|
+
if (token === void 0 || token !== decision.token) {
|
|
311
|
+
if (store !== void 0 && token !== void 0 && staleOnChange(decision) && await isStaleToken(store, token, input)) return {
|
|
312
|
+
outcome: "denied",
|
|
313
|
+
denials: [{
|
|
314
|
+
role: null,
|
|
315
|
+
reason: "stale-approval"
|
|
316
|
+
}],
|
|
317
|
+
alternatives: []
|
|
318
|
+
};
|
|
319
|
+
if (store !== void 0) await requestApproval(store, decision, compact({
|
|
320
|
+
permission: input.permission,
|
|
321
|
+
resource: input.resource,
|
|
322
|
+
subject: input.subject,
|
|
323
|
+
adapter: input.adapter,
|
|
324
|
+
ttl: input.ttl
|
|
325
|
+
}));
|
|
326
|
+
return decision;
|
|
327
|
+
}
|
|
328
|
+
if (store === void 0) return approvalDenied("approval-not-found");
|
|
329
|
+
let inspected;
|
|
330
|
+
try {
|
|
331
|
+
inspected = await inspectApproval(store, token, input.now);
|
|
332
|
+
if (inspected.ok) {
|
|
333
|
+
const { request } = inspected;
|
|
334
|
+
if (request.permission !== input.permission.key || request.resource.id !== void 0 && request.resource.id !== input.resource.id) return approvalDenied("approval-mismatch");
|
|
335
|
+
if (input.consume !== false) inspected = await consumeApproval(store, token, input.now);
|
|
336
|
+
}
|
|
337
|
+
} catch {
|
|
338
|
+
return approvalDenied("approval-not-found");
|
|
339
|
+
}
|
|
340
|
+
if (!inspected.ok) return approvalDenied(inspected.detail);
|
|
341
|
+
const principal = input.subject.principal;
|
|
342
|
+
if (principal === null) return approvalDenied("approval-mismatch");
|
|
343
|
+
return {
|
|
344
|
+
outcome: "granted",
|
|
345
|
+
subject: {
|
|
346
|
+
...input.subject,
|
|
347
|
+
principal
|
|
348
|
+
},
|
|
349
|
+
matched: decision.grant,
|
|
350
|
+
token: decision.token
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const SYSTEM_KIND = "system";
|
|
354
|
+
async function cancelApprovals(store, filter, meta) {
|
|
355
|
+
if (store.cancel !== void 0) return store.cancel(filter, meta);
|
|
356
|
+
const pending = await listAllApprovals(store, {
|
|
357
|
+
...filter,
|
|
358
|
+
status: "pending"
|
|
359
|
+
});
|
|
360
|
+
const by = {
|
|
361
|
+
principal: {
|
|
362
|
+
id: `system:${meta.by}`,
|
|
363
|
+
kind: "service",
|
|
364
|
+
roles: []
|
|
365
|
+
},
|
|
366
|
+
actor: {
|
|
367
|
+
id: `system:${meta.by}`,
|
|
368
|
+
kind: SYSTEM_KIND
|
|
369
|
+
},
|
|
370
|
+
context: {}
|
|
371
|
+
};
|
|
372
|
+
return (await Promise.all(pending.map(async (request) => {
|
|
373
|
+
try {
|
|
374
|
+
await store.resolve(request.token, compact({
|
|
375
|
+
status: "rejected",
|
|
376
|
+
by,
|
|
377
|
+
note: meta.note
|
|
378
|
+
}));
|
|
379
|
+
return true;
|
|
380
|
+
} catch {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
}))).filter(Boolean).length;
|
|
384
|
+
}
|
|
385
|
+
function readApprovalHeader(headers) {
|
|
386
|
+
const value = headers.get(APPROVAL_HEADER);
|
|
387
|
+
if (value === null || value.trim() === "") return;
|
|
388
|
+
return value.trim();
|
|
389
|
+
}
|
|
390
|
+
function resumeFromHeader(store, headers, now) {
|
|
391
|
+
const token = readApprovalHeader(headers);
|
|
392
|
+
if (token === void 0) return Promise.resolve({
|
|
393
|
+
ok: false,
|
|
394
|
+
detail: "approval-not-found"
|
|
395
|
+
});
|
|
396
|
+
return inspectApproval(store, token, now);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* The token to resume `decision` with when the caller carries none: the
|
|
400
|
+
* decision's own token when the store holds an approved or rejected request
|
|
401
|
+
* for it, so `resumeDecision` resumes (or denies) the call without the
|
|
402
|
+
* caller passing the token back. The token already binds permission,
|
|
403
|
+
* resource (or the call's data when there is no row id), subject and actor.
|
|
404
|
+
* A pending request counts only with `denyPending: true`, which makes the
|
|
405
|
+
* call deny with `approval-pending` instead of asking again. `undefined` when
|
|
406
|
+
* the decision needs no approval, there is no store, or the store has no
|
|
407
|
+
* unexpired request for the token; a store that throws counts as none.
|
|
408
|
+
*/
|
|
409
|
+
async function storedApprovalToken(store, decision, options = {}) {
|
|
410
|
+
if (store === void 0 || decision.outcome !== "approval-required") return;
|
|
411
|
+
const now = (options.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
412
|
+
try {
|
|
413
|
+
const record = await store.get(decision.token);
|
|
414
|
+
if (record === null || record.status === "pending" && options.denyPending !== true || record.status === "expired" || Date.parse(record.expiresAt) <= now) return;
|
|
415
|
+
return decision.token;
|
|
416
|
+
} catch {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
421
|
+
export { requestApproval as a, resumeFromHeader as c, vouchApproval as d, approverPermissions as f, readApprovalHeader as i, storedApprovalToken as l, approverRelations as m, consumeApproval as n, resolveApproval as o, heldPermissions as p, inspectApproval as r, resumeDecision as s, cancelApprovals as t, summariseSubject as u };
|
package/dist/hono/index.d.ts
CHANGED
|
@@ -1,35 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { f as ApprovalStore } from "../types-B8w5PFtS.js";
|
|
1
|
+
import { C as Policy, D as PolicyVocabulary, Nr as Principal, ln as PermDock } from "../policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission } from "../permissions-DttnqqxC.js";
|
|
4
3
|
import { n as RevocationFeed } from "../revocations-Cy06JNx2.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { S as ConnectionOptions, b as Connection, g as discoverViaSignatureAgent, h as WebBotAuthVerifier, n as OpenApiHooks, o as TenantOption, r as ProtectOptions, u as InvalidSignatureError, y as verifyWebBotAuth } from "../create-BKF3dgFk.js";
|
|
4
|
+
import { A as ConnectionOptions, O as Connection, h as InvalidSignatureError, i as ProtectOptions, n as OpenApiHooks, w as verifyWebBotAuth, x as discoverViaSignatureAgent } from "../create-BWyx3jua.js";
|
|
5
|
+
import { t as ServerAdapterOptions } from "../bind-CVy3Espv.js";
|
|
8
6
|
import { Context, Hono, MiddlewareHandler } from "hono";
|
|
9
7
|
import { SSEMessage, SSEStreamingApi } from "hono/streaming";
|
|
10
8
|
import { WSEvents } from "hono/ws";
|
|
11
9
|
//#region src/hono/create.d.ts
|
|
12
|
-
type HonoPermDockOptions<TUser = unknown> = {
|
|
13
|
-
readonly subject: (c: Context) => TUser | Promise<TUser>;
|
|
14
|
-
readonly tenant?: TenantOption<Context>;
|
|
15
|
-
readonly memberships?: MembershipSource | readonly MembershipSource[];
|
|
16
|
-
/** The object graph for relation grants that walk a parent chain; without it they deny. */
|
|
17
|
-
readonly relations?: RelationSource;
|
|
18
|
-
readonly entitlements?: EntitlementSource;
|
|
19
|
-
readonly customRoles?: RoleSource;
|
|
20
|
-
/** Hosted grants, read once per instance; see `PolicySource`. */
|
|
21
|
-
readonly policies?: PolicySource;
|
|
22
|
-
readonly store?: ApprovalStore;
|
|
23
|
-
readonly sink?: DecisionSink;
|
|
24
|
-
readonly limits?: LimitStore;
|
|
25
|
-
/** `createPermDock` from `permdock/pdp`; `protect` then decides delegated permissions remotely. */
|
|
26
|
-
readonly pdp?: PdpFactory;
|
|
27
|
-
/** Accepted for adapter parity; not read by this adapter. */
|
|
28
|
-
readonly snapshots?: SnapshotSource;
|
|
29
|
-
/** `(permdock) => withOtel(permdock, options)` from `permdock/otel`. */
|
|
30
|
-
readonly otel?: OtelWrap;
|
|
31
|
-
/** `(request) => verifyWebBotAuth(request, options)`; a verified bot becomes the actor. */
|
|
32
|
-
readonly webBotAuth?: WebBotAuthVerifier;
|
|
10
|
+
type HonoPermDockOptions<TUser = unknown> = ServerAdapterOptions<Context, TUser> & {
|
|
33
11
|
/** Ends or revalidates open sockets and streams. */
|
|
34
12
|
readonly revocations?: RevocationFeed;
|
|
35
13
|
};
|
|
@@ -42,7 +20,7 @@ type PermDockEnv<TData = unknown, V extends PolicyVocabulary = PolicyVocabulary>
|
|
|
42
20
|
};
|
|
43
21
|
type HonoPermDock<V extends PolicyVocabulary = PolicyVocabulary> = {
|
|
44
22
|
readonly permdock: () => MiddlewareHandler<PermDockEnv<unknown, V>>;
|
|
45
|
-
readonly protect: <TData = unknown>(permission: Permission, loadData?: (c: Context) => TData | Promise<TData>, protectOptions?: ProtectOptions) => MiddlewareHandler<PermDockEnv<NonNullable<TData>, V>>;
|
|
23
|
+
readonly protect: <TData = unknown>(permission: Permission | null, loadData?: (c: Context) => TData | Promise<TData>, protectOptions?: ProtectOptions) => MiddlewareHandler<PermDockEnv<NonNullable<TData>, V>>;
|
|
46
24
|
/** A long-lived connection for the request behind `c`. */
|
|
47
25
|
readonly connection: (c: Context, connectionOptions?: ConnectionOptions) => Promise<Connection>;
|
|
48
26
|
/** `upgradeWebSocket` events that close with `1008` when the connection aborts. */
|
package/dist/hono/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
-
import { r as PermDockRevokedError } from "../errors-
|
|
3
|
-
import { i as discoverViaSignatureAgent,
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { i as onRevoked, n as guardIterable, t as POLICY_VIOLATION } from "../stream-
|
|
2
|
+
import { r as PermDockRevokedError } from "../errors-Cz5zn0mW.js";
|
|
3
|
+
import { i as discoverViaSignatureAgent, r as InvalidSignatureError, s as verifyWebBotAuth } from "../evaluations-tz6D9A2G.js";
|
|
4
|
+
import { t as problemFromError } from "../map-error-pgUWNNtG.js";
|
|
5
|
+
import { r as bindKernel } from "../bind-VnYn2HKq.js";
|
|
6
|
+
import { i as onRevoked, n as guardIterable, t as POLICY_VIOLATION } from "../stream-DDpvynSB.js";
|
|
7
7
|
import { Hono } from "hono";
|
|
8
8
|
//#region src/hono/create.ts
|
|
9
9
|
function socket(connection, events) {
|
|
@@ -54,47 +54,18 @@ async function sse(connection, stream, source, options = {}) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
function mapDownstream(c) {
|
|
57
|
-
const mapped = c.error === void 0 ? void 0 : problemFromError(c.error);
|
|
57
|
+
const mapped = c.error === void 0 ? void 0 : problemFromError(c.error, { credentials: c.req.header("authorization") !== void 0 });
|
|
58
58
|
if (mapped !== void 0) {
|
|
59
59
|
c.res = void 0;
|
|
60
60
|
c.res = mapped;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
function createPermDock(policy, options) {
|
|
64
|
-
const
|
|
65
|
-
const kernel = createKernel(policy, compact({
|
|
66
|
-
subject: (request) => {
|
|
67
|
-
const c = contexts.get(request);
|
|
68
|
-
return c === void 0 ? null : options.subject(c);
|
|
69
|
-
},
|
|
70
|
-
memberships: options.memberships,
|
|
71
|
-
relations: options.relations,
|
|
72
|
-
entitlements: options.entitlements,
|
|
73
|
-
customRoles: options.customRoles,
|
|
74
|
-
policies: options.policies,
|
|
75
|
-
store: options.store,
|
|
76
|
-
sink: options.sink,
|
|
77
|
-
limits: options.limits,
|
|
78
|
-
pdp: options.pdp,
|
|
79
|
-
webBotAuth: options.webBotAuth,
|
|
80
|
-
revocations: options.revocations,
|
|
81
|
-
adapter: "hono",
|
|
82
|
-
wrap: options.otel
|
|
83
|
-
}));
|
|
84
|
-
const bind = (c) => {
|
|
85
|
-
const raw = c.req.raw;
|
|
86
|
-
if (!contexts.has(raw)) contexts.set(raw, c);
|
|
87
|
-
return raw;
|
|
88
|
-
};
|
|
89
|
-
const scopeOf = (c) => tenantScope(options.tenant, c);
|
|
64
|
+
const { kernel, bind, scopeOf, handlerScope, attach } = bindKernel(policy, options, "hono", (c) => c.req.raw);
|
|
90
65
|
const permdock = () => async (c, next) => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const response = invalidSignatureResponse(error);
|
|
95
|
-
if (response !== void 0) return response;
|
|
96
|
-
throw error;
|
|
97
|
-
}
|
|
66
|
+
const attached = await attach(c);
|
|
67
|
+
if (!attached.ok) return attached.response;
|
|
68
|
+
c.set("permdock", attached.permdock);
|
|
98
69
|
await next();
|
|
99
70
|
mapDownstream(c);
|
|
100
71
|
};
|
|
@@ -108,10 +79,7 @@ function createPermDock(policy, options) {
|
|
|
108
79
|
};
|
|
109
80
|
const connection = async (c, connectionOptions) => kernel.connection(bind(c), connectionOptions, await scopeOf(c));
|
|
110
81
|
const permdockHandler = () => {
|
|
111
|
-
const { POST, GET } = kernel.permdockHandler(
|
|
112
|
-
const c = contexts.get(request);
|
|
113
|
-
return c === void 0 ? { tenant: void 0 } : scopeOf(c);
|
|
114
|
-
});
|
|
82
|
+
const { POST, GET } = kernel.permdockHandler(handlerScope);
|
|
115
83
|
const app = new Hono();
|
|
116
84
|
app.post("/", (c) => POST(bind(c)));
|
|
117
85
|
app.get("/", (c) => GET(bind(c)));
|
|
@@ -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 { c as indexPolicy,
|
|
5
|
-
import { C as listPlans, b as findRole, s as flattenGrantee } from "./grantee-Bv04_Vzf.js";
|
|
2
|
+
import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
|
|
3
|
+
import { T as isForbiddenKey, c as getResource, g as isSelfParented, i as findPermission, k as splitPath } from "./permissions-DVoF6dMt.js";
|
|
4
|
+
import { c as indexPolicy, i as declaredRoleNames, m as role, o as deny, r as completeGrant, t as allow, v as normalizeWhere } from "./policy-xyWg7QdR.js";
|
|
6
5
|
import { t as parseDuration } from "./duration-xK2jGFVc.js";
|
|
6
|
+
import { S as findRole, T as listPlans, s as flattenGrantee } from "./grantee-Cv5Sogfv.js";
|
|
7
7
|
import { n as sha256, t as bytesToBase64Url } from "./sha256-BO0swRXL.js";
|
|
8
8
|
//#region src/core/hosted.ts
|
|
9
9
|
function memoryPolicySource(document = null) {
|
|
@@ -120,7 +120,8 @@ function declaredGrantee(policy, grantee, permissionResource) {
|
|
|
120
120
|
case "anyone":
|
|
121
121
|
case "authenticated":
|
|
122
122
|
case "actor":
|
|
123
|
-
case "assurance":
|
|
123
|
+
case "assurance":
|
|
124
|
+
case "inherit": return false;
|
|
124
125
|
default: return undeclaredKind(grantee);
|
|
125
126
|
}
|
|
126
127
|
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
+
import { i as parsedBody, r as headersFrom, t as firstHeader } from "./http-SO7qGttf.js";
|
|
1
2
|
//#region src/node/http.ts
|
|
2
3
|
function toRequest(req, stream = req) {
|
|
3
|
-
const host =
|
|
4
|
+
const host = firstHeader(req.headers.host) ?? "localhost";
|
|
4
5
|
const url = `${req.protocol ?? "http"}://${host}${req.originalUrl ?? req.url ?? "/"}`;
|
|
5
|
-
const headers =
|
|
6
|
-
for (const [key, value] of Object.entries(req.headers)) {
|
|
7
|
-
if (typeof value === "string") {
|
|
8
|
-
headers.set(key, value);
|
|
9
|
-
continue;
|
|
10
|
-
}
|
|
11
|
-
if (Array.isArray(value)) for (const item of value) headers.append(key, item);
|
|
12
|
-
}
|
|
6
|
+
const headers = headersFrom(req.headers);
|
|
13
7
|
const method = req.method ?? "GET";
|
|
14
8
|
if (method === "GET" || method === "HEAD") return new Request(url, {
|
|
15
9
|
method,
|
|
16
10
|
headers
|
|
17
11
|
});
|
|
18
|
-
const parsed =
|
|
12
|
+
const parsed = parsedBody(req.body, headers);
|
|
19
13
|
if (parsed !== void 0) return new Request(url, {
|
|
20
14
|
method,
|
|
21
15
|
headers,
|
|
@@ -87,16 +81,6 @@ function incomingBody(req) {
|
|
|
87
81
|
});
|
|
88
82
|
} }, { highWaterMark: 0 });
|
|
89
83
|
}
|
|
90
|
-
function headerValue(value) {
|
|
91
|
-
if (typeof value === "string" && value.length > 0) return value;
|
|
92
|
-
if (Array.isArray(value) && typeof value[0] === "string") return value[0];
|
|
93
|
-
}
|
|
94
|
-
function bodyOf(req, headers) {
|
|
95
|
-
if (req.body === void 0) return;
|
|
96
|
-
if (typeof req.body === "string") return req.body;
|
|
97
|
-
if (!headers.has("content-type")) headers.set("content-type", "application/json");
|
|
98
|
-
return JSON.stringify(req.body);
|
|
99
|
-
}
|
|
100
84
|
async function sendResponse(res, response) {
|
|
101
85
|
res.statusCode = response.status;
|
|
102
86
|
for (const [key, value] of response.headers.entries()) res.setHeader(key, value);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/server/http.ts
|
|
2
|
+
/** Node-style headers (`IncomingHttpHeaders`, Fastify's) as Fetch `Headers`; repeated values stay separate. */
|
|
3
|
+
function headersFrom(source) {
|
|
4
|
+
const headers = new Headers();
|
|
5
|
+
for (const [key, value] of Object.entries(source)) {
|
|
6
|
+
if (typeof value === "string") {
|
|
7
|
+
headers.set(key, value);
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
for (const item of value ?? []) headers.append(key, item);
|
|
11
|
+
}
|
|
12
|
+
return headers;
|
|
13
|
+
}
|
|
14
|
+
function firstHeader(value) {
|
|
15
|
+
if (typeof value === "string") return value.length > 0 ? value : void 0;
|
|
16
|
+
return value?.[0];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A body a framework already parsed, as the text a Fetch `Request` carries.
|
|
20
|
+
* A non-string body is serialised as JSON and, without a `content-type`,
|
|
21
|
+
* labelled `application/json` on `headers`.
|
|
22
|
+
*/
|
|
23
|
+
function parsedBody(body, headers) {
|
|
24
|
+
if (body === void 0) return;
|
|
25
|
+
if (typeof body === "string") return body;
|
|
26
|
+
if (!headers.has("content-type")) headers.set("content-type", "application/json");
|
|
27
|
+
return JSON.stringify(body);
|
|
28
|
+
}
|
|
29
|
+
/** The Fetch `Request` an RPC context carries as `request` or `req`. */
|
|
30
|
+
function requestFromContext(context) {
|
|
31
|
+
if ("request" in context && context.request instanceof Request) return context.request;
|
|
32
|
+
if ("req" in context && context.req instanceof Request) return context.req;
|
|
33
|
+
}
|
|
34
|
+
/** Whether the caller sent credentials, which turns a `401` into a `WWW-Authenticate` challenge. */
|
|
35
|
+
function hasCredentials(request) {
|
|
36
|
+
return request.headers.has("authorization");
|
|
37
|
+
}
|
|
38
|
+
/** The Problem Details `detail` of `cause`, or `fallback` when it has none. */
|
|
39
|
+
function problemMessage(cause, fallback) {
|
|
40
|
+
if (cause !== null && typeof cause === "object" && "detail" in cause && typeof cause.detail === "string" && cause.detail.length > 0) return cause.detail;
|
|
41
|
+
return fallback;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { problemMessage as a, parsedBody as i, hasCredentials as n, requestFromContext as o, headersFrom as r, firstHeader as t };
|