permdock 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -47
- package/dist/a2a/index.d.ts +7 -16
- package/dist/a2a/index.js +59 -98
- package/dist/adapter-context-mlWsVGGg.js +23 -0
- package/dist/ai-sdk/index.d.ts +37 -16
- package/dist/ai-sdk/index.js +30 -13
- package/dist/approvals/index.d.ts +3 -3
- package/dist/approvals/index.js +5 -4
- package/dist/{approvals-DaxY-Bdg.js → approvals-DbYAuNkG.js} +17 -11
- package/dist/approvers-DT4AVyIg.js +52 -0
- package/dist/{arazzo-CTeVuXr5.js → arazzo-BAgw9ap6.js} +2 -2
- package/dist/{arazzo-aoTkqYsJ.js → arazzo-cmvX2jDe.js} +2 -2
- package/dist/authzen/index.d.ts +4 -13
- package/dist/authzen/index.js +16 -50
- package/dist/better-auth/index.d.ts +20 -3
- package/dist/better-auth/index.js +27 -7
- package/dist/better-supabase/index.d.ts +206 -0
- package/dist/better-supabase/index.js +620 -0
- package/dist/bind-CVy3Espv.d.ts +25 -0
- package/dist/bind-VnYn2HKq.js +97 -0
- package/dist/boundary-BM8a_P6E.js +13 -0
- package/dist/boundary-BmHxVH1J.d.ts +15 -0
- package/dist/canonical-json-DemiK4Vp.js +26 -0
- package/dist/{capability-B68OFnZx.js → capability-4qPdO9gk.js} +7 -5
- package/dist/{capability-BDG_nkxt.d.ts → capability-Dq43tT1u.d.ts} +2 -2
- package/dist/catalog/index.d.ts +1 -1
- package/dist/catalog/index.js +1 -1
- package/dist/catalog-BjZSovXQ.js +2 -0
- package/dist/{catalog-doc-BSo_Q_-6.js → catalog-doc-Dsc9y7sd.js} +23 -12
- package/dist/{catalog-B0E6bggc.js → catalog-h2tlKFkq.js} +2 -2
- package/dist/{catalog-H-vFGwWK.js → catalog-z8q6bi_r.js} +4 -4
- package/dist/claude-agent/index.d.ts +5 -14
- package/dist/claude-agent/index.js +4 -10
- package/dist/clerk/index.d.ts +12 -3
- package/dist/clerk/index.js +26 -5
- package/dist/cli/bin.js +1 -1
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +2 -2
- package/dist/clients-C7zLFuWT.d.ts +12 -0
- package/dist/clients-DjU5ABMy.js +23 -0
- package/dist/cloud/index.d.ts +4 -5
- package/dist/cloud/index.js +20 -6
- package/dist/{cloud-BNQTrmrr.js → cloud-BGhHS-lY.js} +2 -2
- package/dist/{cloud-Cuxr6Czw.js → cloud-Bo3e9Ak3.js} +7 -6
- package/dist/{collect-O-tOtbnk.js → collect-DDDv_ESs.js} +194 -42
- package/dist/collect-DLlujdHC.js +83 -0
- package/dist/collect-rG2IQ3t0.js +2 -0
- package/dist/{commands-BMh_Etm2.js → commands-DWOrSQic.js} +16 -12
- package/dist/compile/index.d.ts +3 -0
- package/dist/compile/index.js +2 -0
- package/dist/{compile-D22iwvuV.js → compile-Ba4blROR.js} +85 -30
- package/dist/compile-CNnl6uIt.d.ts +94 -0
- package/dist/config-BJiM-xAm.js +157 -0
- package/dist/config-Bn00Z3ks.js +36 -0
- package/dist/config-report-Dw_JcUqT.js +44 -0
- package/dist/{connection-JvqwHODC.js → connection-CU8MQxRi.js} +1 -1
- package/dist/{context-CKEAabd7.js → context-Ttp0ekMT.js} +36 -27
- package/dist/convex/index.d.ts +9 -4
- package/dist/convex/index.js +14 -4
- package/dist/create-BWyx3jua.d.ts +245 -0
- package/dist/create-CPhDL6qx.js +253 -0
- package/dist/{credential-B_rkUNlY.js → credential-8P81ff4u.js} +26 -46
- package/dist/delegation-D8pUEuce.js +103 -0
- package/dist/{describe-Bt1YD5uS.js → describe-B_gVZEVi.js} +10 -15
- package/dist/{describe-DernyItf.d.ts → describe-PdoqESvg.d.ts} +9 -10
- package/dist/{diff-x5Il8LVa.js → diff-B8Tunc3o.js} +44 -11
- package/dist/{diff-BUzf5Poi.js → diff-CzqLxZ77.js} +2 -2
- package/dist/doctor-WpvG6p4k.js +1194 -0
- package/dist/doctor-collect-ByfYlNv1.js +664 -0
- package/dist/{doctor-Bqo6FwUa.js → doctor-rOr-4ZfS.js} +2 -2
- package/dist/drizzle/index.d.ts +4 -3
- package/dist/drizzle/index.js +3 -3
- package/dist/elysia/index.d.ts +6 -28
- package/dist/elysia/index.js +16 -60
- package/dist/{errors-DSMnAVNa.js → errors-CWfoNg9N.js} +8 -4
- package/dist/{errors-Iy71s7Oj.js → errors-Cz5zn0mW.js} +17 -71
- package/dist/{errors-DbZ1YOnb.d.ts → errors-DAqevpNk.d.ts} +8 -21
- package/dist/{errors-m3u9TmDu.js → errors-DRnGZHzF.js} +4 -1
- package/dist/evaluation-items-CfCCejQd.js +40 -0
- package/dist/{evaluations-DsAU9ppl.js → evaluations-tz6D9A2G.js} +28 -46
- package/dist/eve/index.d.ts +6 -15
- package/dist/eve/index.js +7 -12
- package/dist/expiry-BoBJ8Tvc.js +7 -0
- package/dist/express/index.d.ts +6 -29
- package/dist/express/index.js +28 -58
- package/dist/fastify/index.d.ts +6 -29
- package/dist/fastify/index.js +16 -65
- package/dist/fields-BMl1RxoX.js +26 -0
- package/dist/{files-B_wAGYmt.js → files-DWUN9PzI.js} +5 -1
- package/dist/{fixtures-Cvaw0gDG.js → fixtures-ht28Cplr.js} +5 -2
- package/dist/{freeze-y1_jQL4v.js → freeze-CrU8nQeX.js} +31 -2
- package/dist/{from-snapshot-BMGnhmgv.js → from-snapshot-C3sHpZNS.js} +65 -48
- package/dist/{grantee-Bv04_Vzf.js → grantee-Cv5Sogfv.js} +88 -7
- package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
- package/dist/{headers-B5RRv3Xm.js → headers-BZSDieNT.js} +1 -1
- package/dist/{headers-C8SHQccD.d.ts → headers-Cf-zWvsO.d.ts} +1 -1
- package/dist/helpers-H_KARDVC.js +421 -0
- package/dist/hono/index.d.ts +6 -28
- package/dist/hono/index.js +11 -43
- package/dist/{hosted-BwKQ1BTA.js → hosted-DJQw46hn.js} +6 -5
- package/dist/{http-GgVApX1k.js → http-BIhmLfCc.js} +4 -20
- package/dist/http-SO7qGttf.js +44 -0
- package/dist/ids-DC4V4CFu.js +18 -0
- package/dist/{index-LF_hS-yn.d.ts → index-A0YNL8jZ.d.ts} +1 -1
- package/dist/index-CtE07CBF.d.ts +6 -0
- package/dist/{index-xIxJLwOQ.d.ts → index-D3vbkoSI.d.ts} +75 -7
- package/dist/{index-CltcQ4Bf.d.ts → index-D6_cSa1z.d.ts} +68 -5
- package/dist/index.d.ts +14 -9
- package/dist/index.js +22 -17
- package/dist/instance-options-BK_rNOSC.d.ts +11 -0
- package/dist/instance-options-Dhhcnm3y.js +22 -0
- package/dist/{parse-DPfIvFMU.js → json-schema-BsAflUGW.js} +28 -57
- package/dist/jwt/index.d.ts +10 -6
- package/dist/jwt/index.js +32 -13
- package/dist/kernel-GSQnMz3O.js +208 -0
- package/dist/kysely/index.d.ts +4 -3
- package/dist/kysely/index.js +3 -3
- package/dist/live-options-H2eG8dfJ.js +60 -0
- package/dist/{load-BZ24CpZP.js → load-DhWEB9P1.js} +16 -10
- package/dist/load-DwJUafYN.js +2 -0
- package/dist/manifest-iaoBXHKc.js +783 -0
- package/dist/manifest-uDS9y5de.d.ts +206 -0
- package/dist/{map-DowSO96j.js → map-AcxK9o_D.js} +4 -15
- package/dist/{map-claims-B_6I1Rn-.js → map-claims-Z4QZOiFF.js} +13 -4
- package/dist/map-error-pgUWNNtG.js +23 -0
- package/dist/may-use-DndQ5tQ-.js +77 -0
- package/dist/mcp/index.d.ts +54 -22
- package/dist/mcp/index.js +218 -178
- package/dist/nest/index.d.ts +26 -31
- package/dist/nest/index.js +75 -84
- package/dist/next/client.d.ts +7 -8
- package/dist/next/client.js +11 -9
- package/dist/next/index.d.ts +30 -47
- package/dist/next/index.js +45 -60
- package/dist/next/plugin.d.ts +1 -1
- package/dist/next/plugin.js +32 -1
- package/dist/node/index.d.ts +9 -28
- package/dist/node/index.js +11 -43
- package/dist/openai/index.d.ts +6 -15
- package/dist/openai/index.js +7 -20
- package/dist/openapi/index.d.ts +87 -4
- package/dist/openapi/index.js +3 -3
- package/dist/{openapi-CwePaF7C.js → openapi-Bbg4wGVL.js} +3 -3
- package/dist/{openapi-DcqM8nU7.js → openapi-BqRBvAng.js} +237 -5
- package/dist/{openapi-DWD0Uc_4.js → openapi-CqqEbHsL.js} +5 -5
- package/dist/{openapi-import-BWRUNNeW.js → openapi-import-cmwetbzw.js} +1 -1
- package/dist/{openapi-schema-D8j_T9tO.js → openapi-schema--ARjyfQr.js} +2 -2
- package/dist/orpc/index.d.ts +15 -28
- package/dist/orpc/index.js +74 -117
- package/dist/otel/index.d.ts +2 -2
- package/dist/parse-BuyjxhZV.js +53 -0
- package/dist/parse-local-manifest-BkGQNzAh.d.ts +10 -0
- package/dist/parse-local-manifest-BrMozJCo.js +36 -0
- package/dist/pdp/index.d.ts +2 -2
- package/dist/pdp/index.js +14 -127
- package/dist/{permdock-yoZ7EjxX.js → permdock-CzqXjCpU.js} +641 -126
- package/dist/{permissions-B8vCg_bI.d.ts → permissions-CDgvKG5L.d.ts} +2 -2
- package/dist/{permissions-CofRqesP.js → permissions-CpZrivYv.js} +3 -3
- package/dist/{permissions-DC7GROPA.js → permissions-DVoF6dMt.js} +77 -15
- package/dist/{permissions-B4apnahQ.d.ts → permissions-DttnqqxC.d.ts} +34 -5
- package/dist/{pins-CqE1jZuF.js → pins-8ILTftC9.js} +2 -2
- package/dist/{policy-CInmNGkM.d.ts → policy-CFZAr_Al.d.ts} +330 -37
- package/dist/{policy-Cq2fB8Q5.d.ts → policy-D8UFyERw.d.ts} +2 -2
- package/dist/{policy-ANp36PnI.js → policy-xyWg7QdR.js} +173 -22
- package/dist/powersync-A8x_Yyvh.js +2 -0
- package/dist/powersync-C7kLglqX.js +540 -0
- package/dist/powersync-yW1UUFzp.js +62 -0
- package/dist/prisma/index.d.ts +3 -2
- package/dist/prisma/index.js +45 -20
- package/dist/{problem-Cgp9-KZA.js → problem-B43ztKIm.js} +74 -109
- package/dist/problem-details-CkL50EEf.d.ts +7 -0
- package/dist/problem-details-_AMOYz-w.js +144 -0
- package/dist/{protected-BuPAycJT.d.ts → protected-CNsMzrVd.d.ts} +5 -4
- package/dist/protected-Cs6kTaHo.js +100 -0
- package/dist/protected-bZs6rbT1.d.ts +40 -0
- package/dist/{provider-wTAUda2v.d.ts → provider-Cjr62YMV.d.ts} +1 -1
- package/dist/provider-DLzpb2Xz.js +52 -0
- package/dist/provider-store-DNyC1y48.js +43 -0
- package/dist/react/index.d.ts +7 -5
- package/dist/react/index.js +5 -4
- package/dist/react/provider-client.d.ts +1 -1
- package/dist/react/provider-client.js +1 -1
- package/dist/react-native/index.d.ts +166 -10
- package/dist/react-native/index.js +607 -85
- package/dist/{refs-ChLSxbST.js → refs-KYb4ntaz.js} +4 -3
- package/dist/{relations-r4soIFZB.js → relations-cjOL01hZ.js} +110 -31
- package/dist/replay-BsOyTrdV.js +28 -0
- package/dist/replay-sqBGMnNs.d.ts +5 -0
- package/dist/resource-ref-CaS9yVPi.js +20 -0
- package/dist/revocations-Bhr0aMIC.js +27 -0
- package/dist/rls-BMNydpHk.js +2521 -0
- package/dist/{rls-BOFU3chG.js → rls-CEvs64Kj.js} +8 -3
- package/dist/rls-fields-BMasREhR.js +3502 -0
- package/dist/{rls-graph-DxQ39PJj.js → rls-graph-pc9fuXYm.js} +100 -36
- package/dist/{rls-import-CXV6LBlS.js → rls-import-D8F7j35Q.js} +7 -6
- package/dist/{rls-migrate-DrFPbf8p.js → rls-migrate-7wikfrVI.js} +6 -5
- package/dist/rls-ownership-B5Lkq62W.js +843 -0
- package/dist/rls-shared-aOQ4hGTO.js +493 -0
- package/dist/rls-verify-D8B7dOTh.js +745 -0
- package/dist/{row-check-BajTgQZ-.d.ts → row-check-Dt35czLy.d.ts} +12 -15
- package/dist/rpc-DOK54_CS.js +89 -0
- package/dist/{run-CJ6UvS3a.js → run-YXCJDNYk.js} +31 -12
- package/dist/runtime-CB8gQFvS.js +11 -0
- package/dist/{saas-BRrZzJkM.js → saas-Bj_FFkjN.js} +17 -7
- package/dist/{schema-P8yoma__.js → schema-D3MnDMxa.js} +8 -4
- package/dist/scim/index.d.ts +1 -1
- package/dist/scim/index.js +1 -1
- package/dist/{scim-9NFa0XVZ.js → scim-BFGBBAqR.js} +1 -1
- package/dist/{scopes-cKVp_WTw.js → scopes-CVdPrWN-.js} +35 -8
- package/dist/server/index.d.ts +22 -11
- package/dist/server/index.js +11 -8
- package/dist/{credentials-BgRX3WEg.js → server-DlZ28Oz5.js} +1 -1
- package/dist/shared-DRu8VFVM.js +123 -0
- package/dist/{sink-Cfr9-7YC.d.ts → sink-Gs6TTVa-.d.ts} +1 -1
- package/dist/skills-Biq5uup3.js +192 -0
- package/dist/{skills-C_lpV4Jx.js → skills-JaymNCdK.js} +10 -4
- package/dist/{snapshot-DE8dE_hz.js → snapshot-Enxd0n-s.js} +138 -214
- package/dist/snapshot-cache-D6jLelln.js +44 -0
- package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
- package/dist/solid/index.d.ts +39 -9
- package/dist/solid/index.js +76 -85
- package/dist/sources-B0UvrJ21.js +534 -0
- package/dist/sources-BcJgw0lt.d.ts +192 -0
- package/dist/{sql-Bll1d7y0.js → sql-xdg5f4Fi.js} +6 -1
- package/dist/{src-CTNT-PBW.js → src-CSbUiozF.js} +149 -11
- package/dist/ssf/index.d.ts +3 -2
- package/dist/ssf/index.js +3 -29
- package/dist/store-DMAWwAJV.js +371 -0
- package/dist/{store-Bq90395i.d.ts → store-D_pjn91-.d.ts} +13 -4
- package/dist/store-options-yO0V6gRn.js +716 -0
- package/dist/{stores-CkG2HrSg.js → stores-4_sqiOA1.js} +10 -63
- package/dist/{stores-CvOnu_2T.d.ts → stores-DVR5NHLE.d.ts} +20 -9
- package/dist/{stream-Q_xlB6Ko.js → stream-DDpvynSB.js} +16 -2
- package/dist/{stream-BhMfZOwr.d.ts → stream-DlvG2hs-.d.ts} +2 -2
- package/dist/subject-settings-BwBmCdTR.js +128 -0
- package/dist/supabase/index.d.ts +122 -6
- package/dist/supabase/index.js +4 -3
- package/dist/supabase/middleware.d.ts +32 -27
- package/dist/supabase/middleware.js +56 -22
- package/dist/{supabase-D8UlBA7Z.js → supabase-CwafwxxF.js} +3 -3
- package/dist/{supabase-DTxGtYdi.js → supabase-DTBaC20O.js} +345 -367
- package/dist/supabase-config-Bs44dare.js +472 -0
- package/dist/{supabase-hook-D_OqGb_V.js → supabase-hook-BuxLQLpU.js} +994 -708
- package/dist/supabase-hook-D5qVd_D8.js +2 -0
- package/dist/supautils-DYZnzRWV.js +91 -0
- package/dist/svelte/PermissionBoundary.svelte +37 -0
- package/dist/svelte/Protected.svelte +8 -2
- package/dist/svelte/index.d.ts +9 -6
- package/dist/svelte/index.js +61 -7
- package/dist/svelte/runtime.d.ts +4 -3
- package/dist/svelte/runtime.js +4 -3
- package/dist/svelte/source.d.ts +9 -6
- package/dist/svelte/source.js +7 -4
- package/dist/terminal/index.d.ts +6 -14
- package/dist/terminal/index.js +44 -32
- package/dist/testing/index.d.ts +105 -16
- package/dist/testing/index.js +504 -40
- package/dist/testing/saas/index.d.ts +4 -4
- package/dist/testing/saas/index.js +2 -2
- package/dist/testing/saas/permissions.d.ts +1 -1
- package/dist/testing/saas/permissions.js +1 -1
- package/dist/token-CIWxJOCh.js +50 -0
- package/dist/trpc/index.d.ts +7 -26
- package/dist/trpc/index.js +17 -100
- package/dist/types-9AWO9EGt.d.ts +197 -0
- package/dist/{types-D6Z6-rKJ.d.ts → types-BPxgszlT.d.ts} +260 -22
- package/dist/{types-BvBk1wgn.d.ts → types-BVyImy5I.d.ts} +5 -3
- package/dist/{types-CxquUByI.d.ts → types-Bvc4oWT6.d.ts} +1 -1
- package/dist/types-C3s9xVJG.d.ts +48 -0
- package/dist/{types-BBK-exvJ.d.ts → types-Dnemwd77.d.ts} +7 -1
- package/dist/types-kxznc7cn.d.ts +52 -0
- package/dist/{types-B8w5PFtS.d.ts → types-vKyAMtcX.d.ts} +17 -1
- package/dist/{types-B9dmiiab.d.ts → types-vNSDF7Dq.d.ts} +1 -1
- package/dist/{sources-DOpW5Ila.d.ts → types-yF5LmQVD.d.ts} +86 -127
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +10 -9
- package/dist/{usage-1ozMubLY.js → usage-D07N9QJ3.js} +2 -2
- package/dist/usage-D82l1CwK.js +2 -0
- package/dist/{usage-CUnK6Ou9.js → usage-DG1oeCca.js} +225 -62
- package/dist/validation-error-CnjZ4t92.js +33 -0
- package/dist/validation-error-CtF23SrC.d.ts +26 -0
- package/dist/{validity-D0uRmJKJ.js → validity-uOp8UpYn.js} +57 -36
- package/dist/{verifier-B90agnhl.js → verifier-BxBo6I44.js} +10 -5
- package/dist/version-BvacVTZR.js +17 -0
- package/dist/views-Soe7bGSC.js +95 -0
- package/dist/{vocabulary-Dk0fs-Jk.d.ts → vocabulary-DA8a8zif.d.ts} +1 -1
- package/dist/vue/index.d.ts +35 -13
- package/dist/vue/index.js +86 -93
- package/dist/watch-Etoa_Mvr.js +2 -0
- package/dist/watch-UihESpsJ.js +128 -0
- package/dist/webmcp/index.d.ts +2 -2
- package/dist/webmcp/index.js +7 -13
- package/package.json +62 -36
- package/schemas/approval-request-v1.json +175 -0
- package/schemas/catalog-v1.json +29 -1
- package/schemas/supabase-claims-v1.json +6 -1
- package/schemas/supabase-manifest-v1.json +150 -6
- package/skills/permdock/SKILL.md +7 -7
- package/skills/permdock-agents/SKILL.md +5 -5
- package/skills/permdock-agents/references/runtimes.md +12 -10
- package/skills/permdock-approvals/SKILL.md +4 -4
- package/skills/permdock-approvals/references/stores-and-resume.md +15 -4
- package/skills/permdock-audit/SKILL.md +3 -3
- package/skills/permdock-credentials/SKILL.md +4 -4
- package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
- package/skills/permdock-data/SKILL.md +4 -4
- package/skills/permdock-data/references/queries-and-rls.md +14 -6
- package/skills/permdock-data/references/relationships.md +5 -3
- package/skills/permdock-tenancy/SKILL.md +9 -6
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +14 -8
- package/skills/permdock-wire/SKILL.md +4 -4
- package/skills/permdock-wire/references/adapters.md +42 -30
- package/skills/permdock-wire/references/policy-options.md +5 -3
- package/dist/approvers-aH0PJkmf.js +0 -20
- package/dist/catalog-idsHc0vo.js +0 -2
- package/dist/collect-B7_TIfmg.js +0 -49
- package/dist/collect-fRPAQIWb.js +0 -2
- package/dist/compile-CQbvyIBr.d.ts +0 -30
- package/dist/config-BPYmjTOp.js +0 -26
- package/dist/context-gtAwAILx.js +0 -6
- package/dist/create-BKF3dgFk.d.ts +0 -162
- package/dist/create-CSkhDU9T.js +0 -222
- package/dist/doctor-BGle8Gqi.js +0 -1314
- package/dist/helpers-DnSOrhB9.js +0 -682
- package/dist/index-fG6NSXlc.d.ts +0 -9
- package/dist/kernel-YOGCWNLf.js +0 -211
- package/dist/load-QOOm1z70.js +0 -2
- package/dist/manifest-DDQbC6K0.d.ts +0 -118
- package/dist/map-error-RJ3ZsUyA.js +0 -16
- package/dist/may-use-CnFEjVEp.js +0 -37
- package/dist/pg-4GJWDUxG.js +0 -953
- package/dist/plugin-4gr7IxFJ.js +0 -65
- package/dist/protected-B4K3BKoX.js +0 -138
- package/dist/protected-wY7nXhY9.d.ts +0 -23
- package/dist/provider-_wx46HpB.js +0 -48
- package/dist/rls-CJVja9Ww.js +0 -2119
- package/dist/rls-helpers-BxRuif0l.js +0 -1346
- package/dist/runtime-DP9ttFh1.js +0 -27
- package/dist/skills-Dx3QLnMY.js +0 -110
- package/dist/source-DoBBYJi2.js +0 -6
- package/dist/sources-DVHM3Mwq.js +0 -284
- package/dist/store-C6hFW6ta.js +0 -508
- package/dist/subject-settings-xt7V845g.js +0 -82
- package/dist/supabase-hook-DW-xP4hU.js +0 -2
- package/dist/types-DbWdEfcm.d.ts +0 -87
- package/dist/types-bva3i4Gf.d.ts +0 -98
- package/dist/types-i4BAOvdb.d.ts +0 -97
- package/dist/usage-PyEor6GA.js +0 -2
- package/dist/version-CnSh33Fj.js +0 -16
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { n as isReadonlyArray, r as sole, t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
-
import { n as freezeDeep } from "./freeze-
|
|
3
|
-
import {
|
|
4
|
-
import { c as isConditionRef, i as resolveConditionRef, s as isConditionDate, u as parentHop } from "./refs-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
|
|
3
|
+
import { E as ownGet, T as isForbiddenKey, i as findPermission } from "./permissions-DVoF6dMt.js";
|
|
4
|
+
import { c as isConditionRef, i as resolveConditionRef, s as isConditionDate, u as parentHop } from "./refs-KYb4ntaz.js";
|
|
5
|
+
import { t as expiredAt } from "./expiry-BoBJ8Tvc.js";
|
|
6
|
+
import { n as sameId } from "./ids-DC4V4CFu.js";
|
|
7
|
+
import { d as scopeList, l as scopeChain, m as tenantOf, o as resolveScope, p as subjectMemberships, r as findScope, t as activeFor, u as scopeIdOf } from "./scopes-CVdPrWN-.js";
|
|
8
|
+
import { E as listRoles, T as listPlans, _ as resourceRoleCondition } from "./grantee-Cv5Sogfv.js";
|
|
9
|
+
import { a as isMembershipExpired, c as membershipField, g as tenantsOf, i as inTeam, t as isActive } from "./validity-uOp8UpYn.js";
|
|
9
10
|
//#region src/conditions/evaluate.ts
|
|
10
|
-
function isExpired(membership, now) {
|
|
11
|
-
return membership.expiresAt !== void 0 && membership.expiresAt <= now;
|
|
12
|
-
}
|
|
13
11
|
function resolveRef(ref, subject) {
|
|
14
12
|
return resolveConditionRef(ref, subject);
|
|
15
13
|
}
|
|
@@ -78,7 +76,7 @@ function matchesParentHop(data, parents, on) {
|
|
|
78
76
|
for (const parent of parents ?? []) {
|
|
79
77
|
const hop = parentHop(parent);
|
|
80
78
|
if (hop.resource !== void 0 && hop.resource !== on.resource) continue;
|
|
81
|
-
if (ownGet(data, hop.field)
|
|
79
|
+
if (sameId(ownGet(data, hop.field), on.id)) return true;
|
|
82
80
|
}
|
|
83
81
|
return false;
|
|
84
82
|
}
|
|
@@ -92,10 +90,10 @@ function evaluateMemberOf(condition, data, subject, now, scopes) {
|
|
|
92
90
|
const scope = condition.scope === "resource" ? void 0 : resolveScope(scopes, condition.scope);
|
|
93
91
|
if (condition.scope !== "resource" && scope === void 0) return false;
|
|
94
92
|
for (const membership of memberships) {
|
|
95
|
-
if (
|
|
93
|
+
if (expiredAt(membership, now)) continue;
|
|
96
94
|
if (wanted.size > 0 && !membership.roles.some((role) => wanted.has(role))) continue;
|
|
97
95
|
if (scope !== void 0) {
|
|
98
|
-
if (membership.scope !== scope || membership.id
|
|
96
|
+
if (membership.scope !== scope || !sameId(membership.id, rowValue)) continue;
|
|
99
97
|
const tenant = tenantOf(membership, scopes);
|
|
100
98
|
if (active !== void 0 && tenant !== void 0 && tenant !== active) continue;
|
|
101
99
|
return true;
|
|
@@ -105,7 +103,7 @@ function evaluateMemberOf(condition, data, subject, now, scopes) {
|
|
|
105
103
|
if (matchesParentHop(data, condition.parents, membership.on)) return true;
|
|
106
104
|
continue;
|
|
107
105
|
}
|
|
108
|
-
if (membership.on.id
|
|
106
|
+
if (sameId(membership.on.id, rowValue)) return true;
|
|
109
107
|
if (matchesParentHop(data, condition.parents, membership.on)) return true;
|
|
110
108
|
}
|
|
111
109
|
return false;
|
|
@@ -146,6 +144,7 @@ function evaluateCondition(condition, data, subject, now = Date.now() / 1e3, sco
|
|
|
146
144
|
case "opaque":
|
|
147
145
|
onOpaque?.();
|
|
148
146
|
return false;
|
|
147
|
+
case "liveSession": return subject.liveSession === true;
|
|
149
148
|
default:
|
|
150
149
|
/* v8 ignore next */
|
|
151
150
|
return condition;
|
|
@@ -168,7 +167,7 @@ const denied = (reason) => freezeDeep({
|
|
|
168
167
|
}],
|
|
169
168
|
alternatives: []
|
|
170
169
|
});
|
|
171
|
-
function isRecord
|
|
170
|
+
function isRecord(value) {
|
|
172
171
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
173
172
|
}
|
|
174
173
|
function asString(value) {
|
|
@@ -179,13 +178,13 @@ function parseParameters(raw, components, where) {
|
|
|
179
178
|
if (!Array.isArray(raw)) return `${where}: parameters must be an array`;
|
|
180
179
|
const out = [];
|
|
181
180
|
for (const item of raw) {
|
|
182
|
-
if (!isRecord
|
|
181
|
+
if (!isRecord(item)) return `${where}: a parameter is not an object`;
|
|
183
182
|
const reference = asString(item["reference"]);
|
|
184
183
|
if (reference !== void 0) {
|
|
185
184
|
const match = /^\$components\.parameters\.(.+)$/u.exec(reference);
|
|
186
185
|
const target = match?.[1] === void 0 ? void 0 : components[match[1]];
|
|
187
|
-
const name = isRecord
|
|
188
|
-
if (!isRecord
|
|
186
|
+
const name = isRecord(target) ? asString(target["name"]) : void 0;
|
|
187
|
+
if (!isRecord(target) || name === void 0 || !("value" in target)) return `${where}: unresolved parameter reference ${reference}`;
|
|
189
188
|
out.push({
|
|
190
189
|
name,
|
|
191
190
|
value: "value" in item ? item["value"] : target["value"]
|
|
@@ -202,29 +201,29 @@ function parseParameters(raw, components, where) {
|
|
|
202
201
|
return out;
|
|
203
202
|
}
|
|
204
203
|
function parseDocument(arazzo) {
|
|
205
|
-
if (!isRecord
|
|
204
|
+
if (!isRecord(arazzo)) return "Arazzo document is not an object";
|
|
206
205
|
const version = arazzo["arazzo"];
|
|
207
206
|
if (typeof version !== "string" || !VERSION.test(version)) return "arazzo must be a 1.0.x or 1.1.x version";
|
|
208
|
-
if (!isRecord
|
|
207
|
+
if (!isRecord(arazzo["info"])) return "info is required";
|
|
209
208
|
const rawSources = arazzo["sourceDescriptions"];
|
|
210
209
|
if (!Array.isArray(rawSources) || rawSources.length === 0) return "sourceDescriptions needs at least one entry";
|
|
211
210
|
const sources = [];
|
|
212
211
|
for (const source of rawSources) {
|
|
213
|
-
const name = isRecord
|
|
214
|
-
if (!isRecord
|
|
212
|
+
const name = isRecord(source) ? asString(source["name"]) : void 0;
|
|
213
|
+
if (!isRecord(source) || name === void 0 || asString(source["url"]) === void 0) return "a sourceDescription needs a name and a url";
|
|
215
214
|
if (sources.some((item) => item.name === name)) return `duplicate sourceDescription ${name}`;
|
|
216
215
|
sources.push({
|
|
217
216
|
name,
|
|
218
217
|
type: asString(source["type"]) ?? "openapi"
|
|
219
218
|
});
|
|
220
219
|
}
|
|
221
|
-
const components = isRecord
|
|
220
|
+
const components = isRecord(arazzo["components"]) && isRecord(arazzo["components"]["parameters"]) ? arazzo["components"]["parameters"] : {};
|
|
222
221
|
const rawWorkflows = arazzo["workflows"];
|
|
223
222
|
if (!Array.isArray(rawWorkflows) || rawWorkflows.length === 0) return "workflows needs at least one entry";
|
|
224
223
|
const workflows = [];
|
|
225
224
|
for (const item of rawWorkflows) {
|
|
226
|
-
const workflowId = isRecord
|
|
227
|
-
if (!isRecord
|
|
225
|
+
const workflowId = isRecord(item) ? asString(item["workflowId"]) : void 0;
|
|
226
|
+
if (!isRecord(item) || workflowId === void 0) return "a workflow needs a workflowId";
|
|
228
227
|
if (workflows.some((workflow) => workflow.workflowId === workflowId)) return `duplicate workflowId ${workflowId}`;
|
|
229
228
|
const parameters = parseParameters(item["parameters"], components, workflowId);
|
|
230
229
|
if (typeof parameters === "string") return parameters;
|
|
@@ -232,8 +231,8 @@ function parseDocument(arazzo) {
|
|
|
232
231
|
if (!Array.isArray(rawSteps) || rawSteps.length === 0) return `${workflowId}: steps needs at least one entry`;
|
|
233
232
|
const steps = [];
|
|
234
233
|
for (const step of rawSteps) {
|
|
235
|
-
const stepId = isRecord
|
|
236
|
-
if (!isRecord
|
|
234
|
+
const stepId = isRecord(step) ? asString(step["stepId"]) : void 0;
|
|
235
|
+
if (!isRecord(step) || stepId === void 0) return `${workflowId}: a step needs a stepId`;
|
|
237
236
|
if (steps.some((other) => other.stepId === stepId)) return `${workflowId}: duplicate stepId ${stepId}`;
|
|
238
237
|
const targets = STEP_TARGETS.filter((field) => asString(step[field]) !== void 0);
|
|
239
238
|
if (targets.length !== 1 && !(targets.length === 2 && targets.includes("operationId") && targets.includes("channelPath"))) return `${workflowId}.${stepId}: a step needs exactly one of operationId, operationPath or workflowId`;
|
|
@@ -266,7 +265,7 @@ function readPointer(doc, pointer) {
|
|
|
266
265
|
if (!pointer.startsWith("#/")) return;
|
|
267
266
|
let current = doc;
|
|
268
267
|
for (const raw of pointer.slice(2).split("/")) {
|
|
269
|
-
if (!isRecord
|
|
268
|
+
if (!isRecord(current)) return;
|
|
270
269
|
let token;
|
|
271
270
|
try {
|
|
272
271
|
token = unescapePointer(decodeURIComponent(raw));
|
|
@@ -279,19 +278,19 @@ function readPointer(doc, pointer) {
|
|
|
279
278
|
return current;
|
|
280
279
|
}
|
|
281
280
|
function findOperation(openapi, operationId) {
|
|
282
|
-
if (!isRecord
|
|
281
|
+
if (!isRecord(openapi) || !isRecord(openapi["paths"])) return;
|
|
283
282
|
for (const pathItem of Object.values(openapi["paths"])) {
|
|
284
|
-
if (!isRecord
|
|
285
|
-
for (const [method, operation] of Object.entries(pathItem)) if (!method.startsWith("x-") && isRecord
|
|
283
|
+
if (!isRecord(pathItem)) continue;
|
|
284
|
+
for (const [method, operation] of Object.entries(pathItem)) if (!method.startsWith("x-") && isRecord(operation) && operation["operationId"] === operationId) return operation;
|
|
286
285
|
}
|
|
287
286
|
}
|
|
288
287
|
/** One description, or a map of descriptions keyed by source `name`. */
|
|
289
288
|
function descriptionFor(openapi, name) {
|
|
290
|
-
if (isRecord
|
|
289
|
+
if (isRecord(openapi) && !("openapi" in openapi) && !("paths" in openapi) && isRecord(openapi[name])) return openapi[name];
|
|
291
290
|
return openapi;
|
|
292
291
|
}
|
|
293
292
|
function permissionKeysOf(node) {
|
|
294
|
-
if (!isRecord
|
|
293
|
+
if (!isRecord(node)) return [];
|
|
295
294
|
const raw = node["x-permdock-permissions"];
|
|
296
295
|
if (!Array.isArray(raw)) return [];
|
|
297
296
|
return raw.filter((item) => typeof item === "string");
|
|
@@ -309,7 +308,7 @@ function valueOf(value, inputs) {
|
|
|
309
308
|
};
|
|
310
309
|
let current = inputs;
|
|
311
310
|
for (const part of match[1].split(".")) {
|
|
312
|
-
if (!isRecord
|
|
311
|
+
if (!isRecord(current) || !Object.hasOwn(current, part)) return { known: false };
|
|
313
312
|
current = current[part];
|
|
314
313
|
}
|
|
315
314
|
return {
|
|
@@ -407,7 +406,7 @@ function locate(doc, openapi, step) {
|
|
|
407
406
|
reason: "unsupported",
|
|
408
407
|
detail: "AsyncAPI steps are not evaluated"
|
|
409
408
|
};
|
|
410
|
-
if (hit === void 0 || hit.source.type === "arazzo" || !isRecord
|
|
409
|
+
if (hit === void 0 || hit.source.type === "arazzo" || !isRecord(hit.node)) return {
|
|
411
410
|
reason: "undocumented",
|
|
412
411
|
detail: "operation not found"
|
|
413
412
|
};
|
|
@@ -535,180 +534,52 @@ function simulateArazzo(input, tree, decide) {
|
|
|
535
534
|
});
|
|
536
535
|
}
|
|
537
536
|
function isArazzoSimulateInput(value) {
|
|
538
|
-
return isRecord
|
|
537
|
+
return isRecord(value) && "arazzo" in value;
|
|
539
538
|
}
|
|
540
539
|
//#endregion
|
|
541
|
-
//#region src/core/
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
return [permission.scope, ...formerScopes(permission)];
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* Whether a delegated caller may use a permission its principal holds, through
|
|
548
|
-
* OAuth `scopes`, RFC 9396 `authorizationDetails` or GNAP `access`.
|
|
549
|
-
* `undefined` means covered; otherwise the denial reason `decide` would add.
|
|
550
|
-
*/
|
|
551
|
-
function coveredByDelegation(permission, delegation, resourceId, hasActor = false) {
|
|
552
|
-
const unscoped = hasActor ? "no-delegation" : void 0;
|
|
553
|
-
if (delegation === void 0) return unscoped;
|
|
554
|
-
const hasScopes = delegation.scopes !== void 0;
|
|
555
|
-
const hasDetails = delegation.authorizationDetails !== void 0;
|
|
556
|
-
const hasAccess = delegation.access !== void 0;
|
|
557
|
-
if (!hasScopes && !hasDetails && !hasAccess) return unscoped;
|
|
558
|
-
const emptyScopes = hasScopes && (delegation.scopes?.length ?? 0) === 0;
|
|
559
|
-
const emptyAccess = hasAccess && (delegation.access?.length ?? 0) === 0;
|
|
560
|
-
if (emptyScopes && !hasDetails && !hasAccess) return "no-delegation";
|
|
561
|
-
if (emptyAccess && !hasScopes && !hasDetails) return "no-delegation";
|
|
562
|
-
if (emptyScopes && emptyAccess && !hasDetails) return "no-delegation";
|
|
563
|
-
const scopes = scopeNames(permission);
|
|
564
|
-
const scopeOk = delegation.scopes?.some((scope) => scopes.includes(scope)) ?? false;
|
|
565
|
-
const detailOk = delegation.authorizationDetails?.some((detail) => {
|
|
566
|
-
if (detail.type !== permission.resource) return false;
|
|
567
|
-
const identifier = detail["identifier"];
|
|
568
|
-
if (identifier !== void 0 && (typeof identifier !== "string" || identifier !== resourceId)) return false;
|
|
569
|
-
const actions = detail.actions;
|
|
570
|
-
if (actions === void 0) return true;
|
|
571
|
-
return Array.isArray(actions) && actions.includes(permission.action);
|
|
572
|
-
}) ?? false;
|
|
573
|
-
const accessOk = accessCovers(permission, delegation.access, resourceId);
|
|
574
|
-
if (scopeOk || detailOk || accessOk) return;
|
|
575
|
-
return "not-delegated";
|
|
576
|
-
}
|
|
577
|
-
function accessCovers(permission, access, resourceId) {
|
|
578
|
-
if (access === void 0) return false;
|
|
579
|
-
return access.some((entry) => {
|
|
580
|
-
if (typeof entry === "string") return scopeNames(permission).includes(entry);
|
|
581
|
-
if (entry === null || typeof entry !== "object") return false;
|
|
582
|
-
const type = entry["type"];
|
|
583
|
-
if (typeof type !== "string" || !typeMatches(type, permission.resource)) return false;
|
|
584
|
-
const actions = entry["actions"];
|
|
585
|
-
if (actions !== void 0 && (!Array.isArray(actions) || !actions.includes(permission.action))) return false;
|
|
586
|
-
const identifier = entry["identifier"];
|
|
587
|
-
if (identifier !== void 0 && (typeof identifier !== "string" || identifier !== resourceId)) return false;
|
|
588
|
-
return true;
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
function typeMatches(type, resource) {
|
|
592
|
-
if (type === resource) return true;
|
|
593
|
-
return type.endsWith(`/${resource}`);
|
|
594
|
-
}
|
|
595
|
-
function resourceIdOf(data) {
|
|
596
|
-
if (data === null || typeof data !== "object" || !("id" in data)) return;
|
|
597
|
-
const id = data.id;
|
|
598
|
-
return typeof id === "string" || typeof id === "number" ? String(id) : void 0;
|
|
540
|
+
//#region src/core/row-pair.ts
|
|
541
|
+
function isRowPair(value) {
|
|
542
|
+
return value !== null && typeof value === "object" && "current" in value && "next" in value;
|
|
599
543
|
}
|
|
600
544
|
/**
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
* row.
|
|
545
|
+
* The row a `where` reads and the row a `check` reads. An instance check
|
|
546
|
+
* takes a `{ current, next }` pair or one row for both; a collection check
|
|
547
|
+
* has no current row, only the input it creates.
|
|
605
548
|
*/
|
|
606
|
-
function
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* The permission keys the policy's delegations let `subject.actor` use for
|
|
618
|
-
* `subject.principal` right now: the union over every active delegation whose
|
|
619
|
-
* `to` matches the actor and whose `from` the principal holds. `undefined`
|
|
620
|
-
* when none applies, so the call falls back to the token delegation alone.
|
|
621
|
-
* An actor with `readOnly: true` gets only each delegation's read-only keys.
|
|
622
|
-
* Attenuation only: a key here still needs a matching allow and no deny.
|
|
623
|
-
*/
|
|
624
|
-
function delegatedPermissions(delegations, subject, heldRoles, now) {
|
|
625
|
-
const actor = subject.actor;
|
|
626
|
-
if (actor === void 0 || delegations === void 0) return;
|
|
627
|
-
let keys;
|
|
628
|
-
for (const delegation of delegations) {
|
|
629
|
-
if (delegation.to.kind !== actor.kind || delegation.to.id !== void 0 && delegation.to.id !== actor.id || !isActive(delegation.validity, now) || !handsOver(delegation, subject, heldRoles, now)) continue;
|
|
630
|
-
keys ??= /* @__PURE__ */ new Set();
|
|
631
|
-
for (const key of actor.readOnly === true ? delegation.readOnly : delegation.permissions) keys.add(key);
|
|
632
|
-
}
|
|
633
|
-
return keys;
|
|
634
|
-
}
|
|
635
|
-
//#endregion
|
|
636
|
-
//#region src/core/canonical-json.ts
|
|
637
|
-
function isRecord(value) {
|
|
638
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
639
|
-
}
|
|
640
|
-
/**
|
|
641
|
-
* JSON with sorted keys and `undefined` members dropped, so equal values hash
|
|
642
|
-
* equally. Dates become ISO strings, bigints `"<n>n"`, and a repeated object
|
|
643
|
-
* on the current path `"[Circular]"`, so any validated row serialises.
|
|
644
|
-
*/
|
|
645
|
-
function canonicalJson(value, path = /* @__PURE__ */ new Set()) {
|
|
646
|
-
if (typeof value === "bigint") return JSON.stringify(`${value}n`);
|
|
647
|
-
if (value instanceof Date) return JSON.stringify(Number.isNaN(value.getTime()) ? null : value.toISOString());
|
|
648
|
-
if (value !== null && typeof value === "object") {
|
|
649
|
-
if (path.has(value)) return "\"[Circular]\"";
|
|
650
|
-
path.add(value);
|
|
651
|
-
try {
|
|
652
|
-
if (Array.isArray(value)) return `[${value.map((item) => canonicalJson(item === void 0 ? null : item, path)).join(",")}]`;
|
|
653
|
-
if (isRecord(value)) return `{${Object.keys(value).toSorted().filter((key) => value[key] !== void 0).map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key], path)}`).join(",")}}`;
|
|
654
|
-
} finally {
|
|
655
|
-
path.delete(value);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
return JSON.stringify(value) ?? "null";
|
|
659
|
-
}
|
|
660
|
-
//#endregion
|
|
661
|
-
//#region src/core/token.ts
|
|
662
|
-
/**
|
|
663
|
-
* Only stable identity goes into the token, so refreshing a session (new
|
|
664
|
-
* roles, assurance or claims) does not orphan an outstanding approval.
|
|
665
|
-
*/
|
|
666
|
-
function principalIdentity(principal) {
|
|
667
|
-
if (principal === null) return null;
|
|
549
|
+
function rowValues(permission, data) {
|
|
550
|
+
if (permission.kind === "collection") return {
|
|
551
|
+
current: void 0,
|
|
552
|
+
next: data
|
|
553
|
+
};
|
|
554
|
+
if (permission.kind === "instance" && isRowPair(data)) return {
|
|
555
|
+
current: data.current,
|
|
556
|
+
next: data.next
|
|
557
|
+
};
|
|
668
558
|
return {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
issuer: principal.issuer ?? null
|
|
559
|
+
current: data,
|
|
560
|
+
next: data
|
|
672
561
|
};
|
|
673
562
|
}
|
|
674
|
-
/**
|
|
675
|
-
function
|
|
676
|
-
if (row === null || typeof row !== "object" || !Object.hasOwn(row, field)) return
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
return typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" ? String(value) : null;
|
|
680
|
-
}
|
|
681
|
-
/** The digest that binds a token to the call's data when no row id does. */
|
|
682
|
-
function payloadDigest(data) {
|
|
683
|
-
return bytesToBase64Url(sha256(canonicalJson(data)));
|
|
684
|
-
}
|
|
685
|
-
/**
|
|
686
|
-
* `version` is set only for an approval that goes stale on a resource
|
|
687
|
-
* change; without it the payload, and so every other token, is unchanged.
|
|
688
|
-
* `payload` is set when `resourceId` is `*` (a collection action or a row
|
|
689
|
-
* without an id), so an approval covers the arguments it was given and no
|
|
690
|
-
* others.
|
|
691
|
-
*/
|
|
692
|
-
function decisionToken(input) {
|
|
693
|
-
const payload = JSON.stringify({
|
|
694
|
-
key: input.key,
|
|
695
|
-
resourceId: input.resourceId,
|
|
696
|
-
principal: principalIdentity(input.principal),
|
|
697
|
-
actor: input.actor === void 0 ? null : {
|
|
698
|
-
id: input.actor.id,
|
|
699
|
-
kind: input.actor.kind
|
|
700
|
-
},
|
|
701
|
-
fingerprint: input.fingerprint,
|
|
702
|
-
...input.version === void 0 ? {} : { version: input.version },
|
|
703
|
-
...input.payload === void 0 ? {} : { payload: input.payload }
|
|
704
|
-
});
|
|
705
|
-
return `pd1.${bytesToBase64Url(sha256(payload))}`;
|
|
563
|
+
/** The row's id under `field` as a string, or `*` when the row has no string or number there. */
|
|
564
|
+
function rowIdOf(row, field = "id") {
|
|
565
|
+
if (row === null || typeof row !== "object" || !Object.hasOwn(row, field)) return "*";
|
|
566
|
+
const id = Reflect.get(row, field);
|
|
567
|
+
return typeof id === "string" || typeof id === "number" ? String(id) : "*";
|
|
706
568
|
}
|
|
707
569
|
//#endregion
|
|
708
570
|
//#region src/conditions/bind.ts
|
|
709
571
|
function isPrimitive(value) {
|
|
710
572
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
711
573
|
}
|
|
574
|
+
const ALWAYS$1 = {
|
|
575
|
+
op: "eq",
|
|
576
|
+
field: "_",
|
|
577
|
+
value: true
|
|
578
|
+
};
|
|
579
|
+
const NEVER = {
|
|
580
|
+
op: "or",
|
|
581
|
+
conditions: []
|
|
582
|
+
};
|
|
712
583
|
function bindValue(value, subject, only) {
|
|
713
584
|
if (isConditionRef(value) && only !== void 0 && !only(value.ref)) return value;
|
|
714
585
|
if (isConditionRef(value)) {
|
|
@@ -723,8 +594,9 @@ function bindArg(arg, subject, only) {
|
|
|
723
594
|
return arg !== null && typeof arg === "object" && "field" in arg && !isConditionRef(arg) ? arg : bindValue(arg, subject, only);
|
|
724
595
|
}
|
|
725
596
|
/**
|
|
726
|
-
* Replaces every `principal.*` / `context.*` ref with the subject's value,
|
|
727
|
-
* a `
|
|
597
|
+
* Replaces every `principal.*` / `context.*` ref with the subject's value, and
|
|
598
|
+
* a `liveSession` node with a constant, so a `where()` result compiles the
|
|
599
|
+
* same without the subject. A ref the subject
|
|
728
600
|
* does not hold binds to `null` (or `[]` in a list), which never matches, as
|
|
729
601
|
* in `evaluateCondition`. With `only`, refs it rejects stay refs.
|
|
730
602
|
*/
|
|
@@ -764,6 +636,7 @@ function bindConditionRefs(condition, subject, only) {
|
|
|
764
636
|
args: condition.args.map((arg) => bindArg(arg, subject, only)),
|
|
765
637
|
twin: bindConditionRefs(condition.twin, subject, only)
|
|
766
638
|
};
|
|
639
|
+
case "liveSession": return subject.liveSession === true ? ALWAYS$1 : NEVER;
|
|
767
640
|
case "isNull":
|
|
768
641
|
case "memberOf":
|
|
769
642
|
case "related":
|
|
@@ -793,7 +666,7 @@ function namedFilters(membership, scope) {
|
|
|
793
666
|
if (findScope(scope.scopes, membership.scope ?? "") === void 0 || !inTeam(membership, scope.scopes, scope.team) || !activeFor(membership, scope.scopes, scope.tenant) || membership.scope === void 0) return null;
|
|
794
667
|
const filters = [];
|
|
795
668
|
for (const name of scopeChain(scope.scopes, membership.scope).toReversed()) {
|
|
796
|
-
const key = findScope(scope.scopes, name)?.key;
|
|
669
|
+
const key = scope.fieldOf?.(name) ?? findScope(scope.scopes, name)?.key;
|
|
797
670
|
if (key !== void 0 && scope.partitioned(name, key)) filters.push(eq(key, scopeIdOf(membership, name)));
|
|
798
671
|
}
|
|
799
672
|
return filters;
|
|
@@ -913,7 +786,44 @@ function whereFromGrants(grants, scope) {
|
|
|
913
786
|
return freezeDeep(result);
|
|
914
787
|
}
|
|
915
788
|
//#endregion
|
|
789
|
+
//#region src/core/snapshot-sign.ts
|
|
790
|
+
async function signSnapshot(snapshot, signer, audience) {
|
|
791
|
+
const payload = { snapshot };
|
|
792
|
+
if (snapshot.subject.principal !== null) payload["sub"] = snapshot.subject.principal.id;
|
|
793
|
+
return await signer.sign(payload, compact({
|
|
794
|
+
typ: "permdock-snapshot+jwt",
|
|
795
|
+
audience,
|
|
796
|
+
expiresAt: snapshot.expiresAt
|
|
797
|
+
}));
|
|
798
|
+
}
|
|
799
|
+
//#endregion
|
|
916
800
|
//#region src/core/snapshot.ts
|
|
801
|
+
function plainPermission(leaf) {
|
|
802
|
+
return {
|
|
803
|
+
key: leaf.key,
|
|
804
|
+
scope: leaf.scope,
|
|
805
|
+
resource: leaf.resource,
|
|
806
|
+
action: leaf.action,
|
|
807
|
+
meta: leaf.meta,
|
|
808
|
+
kind: leaf.kind
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
function plainRole(leaf) {
|
|
812
|
+
return compact({
|
|
813
|
+
key: leaf.key,
|
|
814
|
+
on: leaf.on,
|
|
815
|
+
assignable: leaf.assignable,
|
|
816
|
+
meta: leaf.meta,
|
|
817
|
+
kind: leaf.kind
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
function plainPlan(leaf) {
|
|
821
|
+
return {
|
|
822
|
+
key: leaf.key,
|
|
823
|
+
meta: leaf.meta,
|
|
824
|
+
kind: leaf.kind
|
|
825
|
+
};
|
|
826
|
+
}
|
|
917
827
|
function snapshotGrant(grant, membership) {
|
|
918
828
|
const scope = grant.scope === "global" ? void 0 : typeof grant.scope === "string" ? grant.scope : { resource: grant.scope.resource };
|
|
919
829
|
const entry = compact({
|
|
@@ -932,9 +842,17 @@ function snapshotGrant(grant, membership) {
|
|
|
932
842
|
});
|
|
933
843
|
return freezeDeep(entry);
|
|
934
844
|
}
|
|
935
|
-
|
|
845
|
+
const CARRIED = /* @__PURE__ */ new Set([
|
|
846
|
+
"id",
|
|
847
|
+
"roles",
|
|
848
|
+
"plans",
|
|
849
|
+
"tenant",
|
|
850
|
+
"memberships"
|
|
851
|
+
]);
|
|
852
|
+
/** Principal refs the snapshot principal does not carry (`claims`, `teamIds`, …) are bound to the subject's values. */
|
|
936
853
|
function isClaimRef(ref) {
|
|
937
|
-
|
|
854
|
+
const [root, head] = ref.split(".", 2);
|
|
855
|
+
return root === "principal" && !CARRIED.has(String(head));
|
|
938
856
|
}
|
|
939
857
|
function bindClaims(grant, subject) {
|
|
940
858
|
if (grant.where === void 0 && grant.check === void 0) return grant;
|
|
@@ -964,13 +882,27 @@ function buildSnapshot(input) {
|
|
|
964
882
|
const include = input.include;
|
|
965
883
|
const included = (permission) => include === void 0 || include.length === 0 || include.some((prefix) => permission.key === prefix || permission.key.startsWith(`${prefix}.`) || permission.resource === prefix);
|
|
966
884
|
const grants = input.grants.filter((item) => included(item.grant.permission)).map((item) => bindClaims(snapshotGrant(item.grant, item.membership), input.subject));
|
|
885
|
+
const ids = {};
|
|
886
|
+
for (const item of input.grants) {
|
|
887
|
+
const name = item.grant.permission.resource;
|
|
888
|
+
const field = input.idOf?.(name);
|
|
889
|
+
if (field !== void 0 && field !== "id" && included(item.grant.permission)) ids[name] = field;
|
|
890
|
+
}
|
|
967
891
|
const assignableFor = input.assignable;
|
|
968
892
|
const assignable = assignableFor === void 0 ? [] : tenants.map((tenant) => {
|
|
969
893
|
const entry = assignableFor(tenant);
|
|
970
|
-
|
|
894
|
+
const permissions = entry.permissions.filter(included).map(plainPermission);
|
|
895
|
+
if (entry.levels === void 0) return {
|
|
971
896
|
...entry,
|
|
972
|
-
permissions
|
|
897
|
+
permissions
|
|
973
898
|
};
|
|
899
|
+
const keys = new Set(permissions.map((leaf) => leaf.key));
|
|
900
|
+
const levels = Object.fromEntries(Object.entries(entry.levels).filter(([key]) => keys.has(key)));
|
|
901
|
+
return compact({
|
|
902
|
+
...entry,
|
|
903
|
+
permissions,
|
|
904
|
+
levels: Object.keys(levels).length === 0 ? void 0 : levels
|
|
905
|
+
});
|
|
974
906
|
});
|
|
975
907
|
return freezeDeep(compact({
|
|
976
908
|
v: 1,
|
|
@@ -994,24 +926,16 @@ function buildSnapshot(input) {
|
|
|
994
926
|
simulated: input.simulated === true ? true : void 0,
|
|
995
927
|
expiresAt: input.subject.expiresAt,
|
|
996
928
|
scopes: input.scopes,
|
|
929
|
+
ids: Object.keys(ids).length === 0 ? void 0 : ids,
|
|
997
930
|
assignable: assignable.length > 0 ? assignable : void 0,
|
|
998
931
|
delegated: input.delegated === void 0 ? void 0 : [...input.delegated].toSorted(),
|
|
999
932
|
notEntitled: notEntitledOf((input.notEntitled ?? []).filter((item) => included(item.grant.permission))),
|
|
1000
933
|
vocabulary: input.vocabulary === void 0 ? void 0 : compact({
|
|
1001
|
-
roles: listRoles(input.vocabulary.roles).length === 0 ? void 0 : Object.fromEntries(listRoles(input.vocabulary.roles).map((leaf) => [leaf.key, leaf])),
|
|
1002
|
-
plans: listPlans(input.vocabulary.plans).length === 0 ? void 0 : Object.fromEntries(listPlans(input.vocabulary.plans).map((leaf) => [leaf.key, leaf]))
|
|
934
|
+
roles: listRoles(input.vocabulary.roles).length === 0 ? void 0 : Object.fromEntries(listRoles(input.vocabulary.roles).map((leaf) => [leaf.key, plainRole(leaf)])),
|
|
935
|
+
plans: listPlans(input.vocabulary.plans).length === 0 ? void 0 : Object.fromEntries(listPlans(input.vocabulary.plans).map((leaf) => [leaf.key, plainPlan(leaf)]))
|
|
1003
936
|
})
|
|
1004
937
|
}));
|
|
1005
938
|
}
|
|
1006
|
-
async function signSnapshot(snapshot, signer, audience) {
|
|
1007
|
-
const payload = { snapshot };
|
|
1008
|
-
if (snapshot.subject.principal !== null) payload["sub"] = snapshot.subject.principal.id;
|
|
1009
|
-
return await signer.sign(payload, compact({
|
|
1010
|
-
typ: "permdock-snapshot+jwt",
|
|
1011
|
-
audience,
|
|
1012
|
-
expiresAt: snapshot.expiresAt
|
|
1013
|
-
}));
|
|
1014
|
-
}
|
|
1015
939
|
/**
|
|
1016
940
|
* The token delegation as the client sees it. An actor with no token
|
|
1017
941
|
* delegation gets an empty `scopes` list so the client ceiling agrees with
|
|
@@ -1048,4 +972,4 @@ function parseSnapshot(json) {
|
|
|
1048
972
|
return freezeDeep(value);
|
|
1049
973
|
}
|
|
1050
974
|
//#endregion
|
|
1051
|
-
export { whereFromGrants as a,
|
|
975
|
+
export { whereFromGrants as a, rowIdOf as c, isArazzoSimulateInput as d, simulateArazzo as f, signSnapshot as i, rowValues as l, parseSnapshot as n, bindConditionRefs as o, evaluateCondition as p, snapshotGrant as r, isRowPair as s, buildSnapshot as t, arazzoFindings as u };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { n as payloadDigest } from "./token-CIWxJOCh.js";
|
|
2
|
+
//#region src/core/snapshot-cache.ts
|
|
3
|
+
/**
|
|
4
|
+
* `{ stale }` in seconds: `max` when the value never expires, otherwise the seconds left, clamped
|
|
5
|
+
* to `[min, max]`. A value with less than `min` seconds left gets its real remainder, so Next.js
|
|
6
|
+
* leaves it out of prefetches and an HTTP cache does not serve it past `expiresAt`.
|
|
7
|
+
*/
|
|
8
|
+
function cacheLifeFor(value, options = {}) {
|
|
9
|
+
const min = options.min ?? 30;
|
|
10
|
+
const max = Math.max(options.max ?? 300, min);
|
|
11
|
+
const expiresAt = value?.expiresAt;
|
|
12
|
+
if (expiresAt === void 0 || expiresAt === null) return { stale: max };
|
|
13
|
+
const issuedAt = value?.issuedAt !== void 0 && value.issuedAt > 0 ? value.issuedAt : void 0;
|
|
14
|
+
const now = options.now ?? issuedAt ?? Math.floor(Date.now() / 1e3);
|
|
15
|
+
const remaining = Math.floor(expiresAt - now);
|
|
16
|
+
if (remaining < min) return { stale: Math.max(0, remaining) };
|
|
17
|
+
return { stale: Math.min(max, remaining) };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The `cacheTag` for one subject's cached snapshots: `permdock:<sub>`, or `permdock:anon`
|
|
21
|
+
* without a subject. Tag the private cache with it and pass it to `updateTag` or
|
|
22
|
+
* `revalidateTag` on every write that changes the subject's snapshot.
|
|
23
|
+
*/
|
|
24
|
+
function snapshotTag(sub) {
|
|
25
|
+
return `permdock:${sub === void 0 || sub === null || sub === "" ? "anon" : sub}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Response headers for a loader or route that returns `snapshot`: `Cache-Control: private` with
|
|
29
|
+
* `max-age` from `cacheLifeFor`, `Vary: Authorization, Cookie`, an `ETag` over everything but
|
|
30
|
+
* `issuedAt`, and `Cache-Tag` with `snapshotTag(sub)` and `tags`.
|
|
31
|
+
*/
|
|
32
|
+
function snapshotHeaders(snapshot, options = {}) {
|
|
33
|
+
const content = {};
|
|
34
|
+
for (const [key, value] of Object.entries(snapshot)) if (key !== "issuedAt") content[key] = value;
|
|
35
|
+
const { tags, ...life } = options;
|
|
36
|
+
return {
|
|
37
|
+
"Cache-Control": `private, max-age=${cacheLifeFor(snapshot, life).stale}`,
|
|
38
|
+
Vary: "Authorization, Cookie",
|
|
39
|
+
ETag: `"${payloadDigest(content)}"`,
|
|
40
|
+
"Cache-Tag": [snapshotTag(snapshot.subject.principal?.id), ...tags ?? []].join(",")
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { snapshotHeaders as n, snapshotTag as r, cacheLifeFor as t };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Tt as Snapshot } from "./policy-CFZAr_Al.js";
|
|
2
|
+
//#region src/core/snapshot-cache.d.ts
|
|
3
|
+
type CacheLifeForOptions = {
|
|
4
|
+
/** Lower bound in seconds. Next.js includes a private entry in per-link prefetches from 30. */
|
|
5
|
+
readonly min?: number;
|
|
6
|
+
/** Upper bound in seconds. Next.js keeps a per-session App Shell entry from 300. */
|
|
7
|
+
readonly max?: number;
|
|
8
|
+
/** Seconds since the epoch; defaults to the snapshot's `issuedAt`, then the clock. */
|
|
9
|
+
readonly now?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* `{ stale }` in seconds: `max` when the value never expires, otherwise the seconds left, clamped
|
|
13
|
+
* to `[min, max]`. A value with less than `min` seconds left gets its real remainder, so Next.js
|
|
14
|
+
* leaves it out of prefetches and an HTTP cache does not serve it past `expiresAt`.
|
|
15
|
+
*/
|
|
16
|
+
declare function cacheLifeFor(value: {
|
|
17
|
+
readonly expiresAt?: number | null;
|
|
18
|
+
readonly issuedAt?: number;
|
|
19
|
+
} | null, options?: CacheLifeForOptions): {
|
|
20
|
+
readonly stale: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The `cacheTag` for one subject's cached snapshots: `permdock:<sub>`, or `permdock:anon`
|
|
24
|
+
* without a subject. Tag the private cache with it and pass it to `updateTag` or
|
|
25
|
+
* `revalidateTag` on every write that changes the subject's snapshot.
|
|
26
|
+
*/
|
|
27
|
+
declare function snapshotTag(sub?: string | null): string;
|
|
28
|
+
type SnapshotHeadersOptions = CacheLifeForOptions & {
|
|
29
|
+
/** Sent in `Cache-Tag` after `snapshotTag(sub)`, such as the app's own organisation tag. */
|
|
30
|
+
readonly tags?: readonly string[];
|
|
31
|
+
};
|
|
32
|
+
type SnapshotHeaders = {
|
|
33
|
+
readonly "Cache-Control": string;
|
|
34
|
+
readonly Vary: string;
|
|
35
|
+
readonly ETag: string;
|
|
36
|
+
readonly "Cache-Tag": string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Response headers for a loader or route that returns `snapshot`: `Cache-Control: private` with
|
|
40
|
+
* `max-age` from `cacheLifeFor`, `Vary: Authorization, Cookie`, an `ETag` over everything but
|
|
41
|
+
* `issuedAt`, and `Cache-Tag` with `snapshotTag(sub)` and `tags`.
|
|
42
|
+
*/
|
|
43
|
+
declare function snapshotHeaders(snapshot: Snapshot, options?: SnapshotHeadersOptions): SnapshotHeaders;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { snapshotHeaders as a, cacheLifeFor as i, SnapshotHeaders as n, snapshotTag as o, SnapshotHeadersOptions as r, CacheLifeForOptions as t };
|