permdock 0.3.0 → 0.4.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/dist/a2a/index.d.ts +7 -5
- package/dist/a2a/index.js +14 -21
- package/dist/ai-sdk/index.d.ts +18 -6
- package/dist/ai-sdk/index.js +8 -5
- package/dist/app-data-CV8pqqMi.js +59 -0
- package/dist/approvals/index.d.ts +2 -2
- package/dist/approvals/index.js +3 -3
- package/dist/{approvals-DbYAuNkG.js → approvals-DZL76lKW.js} +35 -19
- package/dist/{approvers-DT4AVyIg.js → approvers-CqPOLD-o.js} +1 -1
- package/dist/{arazzo-BAgw9ap6.js → arazzo-C4BcskbX.js} +6 -5
- package/dist/{arazzo-CKwwqFWz.js → arazzo-CD8d0WLb.js} +2 -2
- package/dist/authzen/index.d.ts +3 -3
- package/dist/authzen/index.js +161 -23
- package/dist/better-auth/index.d.ts +2 -2
- package/dist/better-auth/index.js +6 -19
- package/dist/better-supabase/index.d.ts +112 -87
- package/dist/better-supabase/index.js +257 -156
- package/dist/{bind-C_ob3LKa.d.ts → bind-BzqG8SMb.d.ts} +16 -5
- package/dist/{bind-CuzGytRf.js → bind-kk-uyCwH.js} +14 -6
- package/dist/build-instance-DIIV9DbC.js +51 -0
- package/dist/{canonical-json-DemiK4Vp.js → canonical-json-CFKyFOke.js} +1 -3
- package/dist/{capability-2kYTMWDv.d.ts → capability-CksyCWDH.d.ts} +2 -2
- package/dist/{capability-4qPdO9gk.js → capability-txATtKV4.js} +3 -2
- package/dist/catalog/index.d.ts +1 -1
- package/dist/catalog/index.js +1 -1
- package/dist/catalog-6yWAX6Ps.js +2 -0
- package/dist/{catalog-dFZdWCGN.js → catalog-WHG4kBq7.js} +2 -2
- package/dist/{catalog-doc-DdGm82XT.js → catalog-doc-DWtg0gGR.js} +17 -10
- package/dist/{catalog-DWF5cYqB.js → catalog-tZUyOfOv.js} +4 -4
- package/dist/claude-agent/index.d.ts +4 -4
- package/dist/claude-agent/index.js +4 -5
- package/dist/clerk/index.d.ts +3 -3
- package/dist/clerk/index.js +8 -33
- package/dist/cli/bin.js +1 -1
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +3 -3
- package/dist/cloud/index.d.ts +4 -4
- package/dist/cloud/index.js +9 -15
- package/dist/{cloud-CB_ELYuX.js → cloud-C7bSDgX4.js} +2 -2
- package/dist/{cloud-DWLXO2af.js → cloud-PeBN3IEn.js} +5 -5
- package/dist/{collect-DSTE3ml9.js → collect-2SrB7lfk.js} +6 -8
- package/dist/collect-Bw2Jdq1q.js +2 -0
- package/dist/{collect-DClJsheJ.js → collect-CQx4hX4N.js} +3 -3
- package/dist/{commands-DSxCqG9A.js → commands-Cpip4ULx.js} +13 -13
- package/dist/{compact-y6vfu2_f.js → compact-CAf557ZB.js} +11 -1
- package/dist/compile/index.d.ts +1 -1
- package/dist/compile/index.js +1 -1
- package/dist/{compile-Ba4blROR.js → compile-CcEu2ZQ1.js} +6 -5
- package/dist/{compile-BkRyBDBw.d.ts → compile-CtTP7eur.d.ts} +2 -2
- package/dist/{config-BJiM-xAm.js → config-BIjREpyE.js} +4 -4
- package/dist/{config-Dnszbv-6.js → config-DLt6BvV7.js} +2 -2
- package/dist/{config-report-DMvWKUxL.js → config-report--Xb9APJS.js} +5 -6
- package/dist/{connection-CU8MQxRi.js → connection-DUsczpB5.js} +3 -2
- package/dist/constants-DcJABbLW.js +20 -0
- package/dist/{context-Bcy85rGi.js → context-DieZVJXu.js} +16 -5
- package/dist/convex/index.d.ts +4 -4
- package/dist/convex/index.js +14 -16
- package/dist/create-BBO24vj6.js +324 -0
- package/dist/{credential-8P81ff4u.js → credential-kue0qpbm.js} +4 -4
- package/dist/deciding-columns-Sq12mEA6.js +123 -0
- package/dist/delegation-input-FTxMK3ji.js +19 -0
- package/dist/denied-text-DfRk15uw.d.ts +19 -0
- package/dist/{describe-DMYiCjJV.d.ts → describe-C3ldA9os.d.ts} +11 -2
- package/dist/{describe-B_gVZEVi.js → describe-Cgkp7eP0.js} +5 -4
- package/dist/{diff-DBIhz_f2.js → diff-Cnghh_Ip.js} +2 -2
- package/dist/{diff-2VaeChzX.js → diff-rpqoe7Ag.js} +9 -9
- package/dist/{doctor-BwCAMLx_.js → doctor-CuVJvhV_.js} +2 -2
- package/dist/doctor-owlv6ddh.js +2166 -0
- package/dist/drizzle/index.d.ts +2 -2
- package/dist/drizzle/index.js +6 -14
- package/dist/elysia/index.d.ts +4 -4
- package/dist/elysia/index.js +7 -7
- package/dist/{errors-DPdqI50v.d.ts → errors-OD_4c__H.d.ts} +2 -2
- package/dist/{errors-Cz5zn0mW.js → errors-drnfxYtm.js} +3 -3
- package/dist/{evaluations-tz6D9A2G.js → evaluations-C9YJsv3H.js} +45 -7
- package/dist/eve/index.d.ts +5 -5
- package/dist/eve/index.js +5 -5
- package/dist/express/index.d.ts +4 -4
- package/dist/express/index.js +8 -7
- package/dist/fastify/index.d.ts +15 -5
- package/dist/fastify/index.js +9 -29
- package/dist/fields-fwfXN01n.js +1016 -0
- package/dist/{files-DWUN9PzI.js → files-D_JIzUrP.js} +12 -3
- package/dist/{fixtures-ht28Cplr.js → fixtures-h2eG2OZV.js} +5 -6
- package/dist/{from-snapshot-CTLijvdm.js → from-snapshot-7REQZe0H.js} +32 -22
- package/dist/{generate-CH7ThJ14.js → generate-CNU1pIOo.js} +1 -3
- package/dist/grantee-CXY-0C87.js +254 -0
- package/dist/grantee-conditions-MQs5NIuX.js +270 -0
- package/dist/grantee-match-fxYp9Nmt.js +141 -0
- package/dist/{helpers-H_KARDVC.js → helpers-C9YmyBIa.js} +7 -6
- package/dist/hono/index.d.ts +4 -4
- package/dist/hono/index.js +8 -8
- package/dist/hosted-CBHgkzDl.js +655 -0
- package/dist/{http-SO7qGttf.js → http-BBoKefeS.js} +35 -2
- package/dist/{http-BIhmLfCc.js → http-BEbdMZ05.js} +2 -24
- package/dist/{rls-import-BTFVk3jH.js → import-BFIlhetD.js} +86 -80
- package/dist/{openapi-import-cmwetbzw.js → import-UHk1N7vH.js} +6 -7
- package/dist/{index-C8z4RjQV.d.ts → index-BwMe94Xq.d.ts} +1 -1
- package/dist/{index-0nNqHspG.d.ts → index-DgM7w96K.d.ts} +2 -2
- package/dist/{index-C7Tw7MaW.d.ts → index-Dz7didpC.d.ts} +3 -3
- package/dist/{index-BNc7Wer_.d.ts → index-UdVQgq48.d.ts} +105 -38
- package/dist/index.d.ts +15 -13
- package/dist/index.js +22 -22
- package/dist/{instance-options-jARdwfPN.d.ts → instance-options-plkrsAog.d.ts} +1 -1
- package/dist/{json-schema-BsAflUGW.js → json-schema-DBkdUuCO.js} +1 -3
- package/dist/jwt/index.d.ts +4 -4
- package/dist/jwt/index.js +13 -13
- package/dist/{kernel-_RRHmnMY.js → kernel-CB3LrIJM.js} +81 -32
- package/dist/kysely/index.d.ts +2 -2
- package/dist/kysely/index.js +6 -14
- package/dist/{live-options-H2eG8dfJ.js → live-options-BaAFCIiu.js} +16 -3
- package/dist/load-B_shHrmd.js +2 -0
- package/dist/{load-DhWEB9P1.js → load-C3_oTHyO.js} +11 -3
- package/dist/{manifest-iaoBXHKc.js → manifest-BngWKryL.js} +5 -18
- package/dist/{map-claims-Z4QZOiFF.js → map-claims-AVlBaJoa.js} +7 -16
- package/dist/{map-error-pgUWNNtG.js → map-error-BE27PYkE.js} +5 -5
- package/dist/{markers-B0hYLvMD.js → markers-CiwAOZtO.js} +6 -2
- package/dist/{may-use-DndQ5tQ-.js → may-use-BOn_dR_w.js} +4 -3
- package/dist/mcp/index.d.ts +26 -9
- package/dist/mcp/index.js +456 -446
- package/dist/{rls-migrate-CN4TlJTO.js → migrate-BwlB5-Wk.js} +75 -15
- package/dist/nest/index.d.ts +4 -4
- package/dist/nest/index.js +11 -12
- package/dist/next/index.d.ts +31 -8
- package/dist/next/index.js +29 -33
- package/dist/next/plugin.d.ts +1 -1
- package/dist/next/plugin.js +1 -1
- package/dist/node/index.d.ts +4 -4
- package/dist/node/index.js +4 -4
- package/dist/ocsf-uYFXGVw2.js +115 -0
- package/dist/openai/index.d.ts +5 -5
- package/dist/openai/index.js +4 -4
- package/dist/openapi/index.d.ts +3 -3
- package/dist/openapi/index.js +1 -1
- package/dist/{openapi-CqqEbHsL.js → openapi-BJdBmYDG.js} +19 -23
- package/dist/{openapi-BqRBvAng.js → openapi-DBzHQbov.js} +2 -5
- package/dist/{openapi-l0xYHkcv.js → openapi-DcQ1Kg40.js} +3 -3
- package/dist/orpc/index.d.ts +5 -5
- package/dist/orpc/index.js +9 -11
- package/dist/otel/index.d.ts +2 -2
- package/dist/otel/index.js +26 -23
- package/dist/output-files-CgIsvdSa.js +140 -0
- package/dist/{rls-ownership-RuFqaqGz.js → ownership-BgnbOJFT.js} +387 -379
- package/dist/{package-root-zGkxO3oN.js → package-root-DtNnpmUd.js} +3 -2
- package/dist/{parse-BuyjxhZV.js → parse-CVFQHk6c.js} +3 -3
- package/dist/{parse-local-manifest-BrMozJCo.js → parse-local-manifest-C-q02Pal.js} +2 -4
- package/dist/{parse-local-manifest-JLnaBH0S.d.ts → parse-local-manifest-DvYUR0QL.d.ts} +1 -1
- package/dist/pdp/index.d.ts +2 -2
- package/dist/pdp/index.js +8 -9
- package/dist/{permdock-CbgvLnuo.js → permdock-L26udHSk.js} +1387 -1220
- package/dist/{rls-fields-74oZPXWL.js → permission-keys-B26jeyUv.js} +1289 -2066
- package/dist/permission-registry-BsblpB-z.js +385 -0
- package/dist/{permissions-DttnqqxC.d.ts → permission-types-Dg39z9Kv.d.ts} +59 -31
- package/dist/{permissions-RJrovw98.js → permissions-CCJ6lmxB.js} +3 -3
- package/dist/{permissions-CDgvKG5L.d.ts → permissions-COH-KRgT.d.ts} +2 -2
- package/dist/{policy-IB6yxpC3.d.ts → policy-types-sp9P1iIV.d.ts} +661 -582
- package/dist/{policy-D2W7uv19.d.ts → policy-ur0BBK_e.d.ts} +2 -2
- package/dist/{powersync-DliZK_-y.js → powersync-BFSbSElQ.js} +2 -2
- package/dist/powersync-DCDgZgfZ.js +2 -0
- package/dist/{powersync-BylawD_U.js → powersync-cZe4kzhL.js} +26 -27
- package/dist/prisma/index.d.ts +1 -1
- package/dist/prisma/index.js +6 -12
- package/dist/{problem-B43ztKIm.js → problem-CnWraVhC.js} +8 -7
- package/dist/{problem-details-_AMOYz-w.js → problem-details-DECUnXAn.js} +2 -2
- package/dist/{problem-details-DX075l9V.d.ts → problem-details-rIIo8B2C.d.ts} +1 -1
- package/dist/{protected-BdnIEFkY.d.ts → protected-B3_P7xuw.d.ts} +9 -6
- package/dist/{protected-utU-SLuy.js → protected-BN7BUdY1.js} +20 -8
- package/dist/{provider-CSQd7m92.js → provider-Bi-0HNL3.js} +23 -10
- package/dist/{provider-DZY281jO.d.ts → provider-kwHC9CZD.d.ts} +1 -1
- package/dist/{provider-store-Cfbvo4DE.js → provider-store-Ctt-81Ni.js} +6 -3
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +5 -5
- package/dist/react/provider-client.d.ts +1 -1
- package/dist/react/provider-client.js +1 -1
- package/dist/react-native/index.d.ts +20 -11
- package/dist/react-native/index.js +33 -17
- package/dist/{refs-KYb4ntaz.js → refs-f3imMjNW.js} +1 -1
- package/dist/relation-walk-BXnlLtg2.js +186 -0
- package/dist/relations-CvmSpG67.js +163 -0
- package/dist/{replay-CYyiLiwO.d.ts → replay-COpmZUfx.d.ts} +1 -1
- package/dist/request-context-BVM7aWNs.js +71 -0
- package/dist/request-context-C2_1lchh.d.ts +5 -0
- package/dist/resource-relations-D1Un3pcz.js +243 -0
- package/dist/retire-BFcxL6un.js +240 -0
- package/dist/{rls-B4ur8nKQ.js → rls-55DQTuf5.js} +14 -2
- package/dist/{rls-DQtdgTHB.js → rls-BEktUaqg.js} +884 -484
- package/dist/{policy-xyWg7QdR.js → role-builder-B4GbKM-i.js} +235 -541
- package/dist/{rpc-DL9Sqvb1.js → rpc-nYC3cR_u.js} +15 -5
- package/dist/{run-DKDbM4Du.js → run-DMcNW_8T.js} +3 -3
- package/dist/{runtime-CB8gQFvS.js → runtime-D_tMXnsq.js} +1 -1
- package/dist/{saas-DhpJjnBA.js → saas-DtaA4JuW.js} +9 -8
- package/dist/{openapi-schema--ARjyfQr.js → schema-Bol6gqXA.js} +3 -5
- package/dist/{schema-D3MnDMxa.js → schema-DjQBcAP9.js} +4 -2
- package/dist/scim/index.d.ts +1 -1
- package/dist/scim/index.js +1 -1
- package/dist/{scim-BFGBBAqR.js → scim-vFR1O5oG.js} +6 -12
- package/dist/{scopes-CVdPrWN-.js → scopes-tvpa34ep.js} +10 -2
- package/dist/server/index.d.ts +18 -8
- package/dist/server/index.js +8 -8
- package/dist/{server-DlZ28Oz5.js → server-ZYEHtNHS.js} +4 -4
- package/dist/{create-B1d519XK.d.ts → server-types-DdqBwZN_.d.ts} +69 -33
- package/dist/shared-1uhI-e-b.js +294 -0
- package/dist/{shared-DRu8VFVM.js → shared-JhMeOsDF.js} +1 -1
- package/dist/{sink-Bd9PSyfq.js → sink-BTtmfPnE.js} +1 -1
- package/dist/{sink-B1fZzIMf.d.ts → sink-CPN4zLfs.d.ts} +1 -1
- package/dist/{skills-Biq5uup3.js → skills-BZdRQkxs.js} +4 -3
- package/dist/{skills-Bx-U0irG.js → skills-Dle4ZoLF.js} +2 -2
- package/dist/{snapshot-Enxd0n-s.js → snapshot-Dc9CHPME.js} +116 -13
- package/dist/{snapshot-cache-D6jLelln.js → snapshot-cache-Cod40D-X.js} +1 -1
- package/dist/{snapshot-cache-B-LxUahj.d.ts → snapshot-cache-J5T7t_vD.d.ts} +1 -1
- package/dist/solid/index.d.ts +22 -22
- package/dist/solid/index.js +40 -10
- package/dist/{sources-4p0-4xQm.js → sources-B1-b-R0t.js} +25 -26
- package/dist/{sources-BdOYLw9j.d.ts → sources-Dljy06zL.d.ts} +6 -2
- package/dist/{sql-xdg5f4Fi.js → sql-t8teWOfo.js} +19 -3
- package/dist/{src-BDwEZWrZ.js → src-Bb7no-hS.js} +194 -123
- package/dist/ssf/index.d.ts +3 -3
- package/dist/ssf/index.js +58 -61
- package/dist/store-9KO4BlkB.d.ts +147 -0
- package/dist/{store-DMAWwAJV.js → store-ILkLUj_o.js} +4 -4
- package/dist/{store-options-ByhZq1jV.js → store-options-CbUHDoSe.js} +16 -7
- package/dist/{stores-BT2pSCub.js → stores-BHXdSbw9.js} +7 -3
- package/dist/stores-Cxz_80g-.d.ts +31 -0
- package/dist/{stream-DDpvynSB.js → stream-BMui98KK.js} +2 -1
- package/dist/{stream-D1RXubw2.d.ts → stream-Dwsg6WwE.d.ts} +2 -2
- package/dist/{subject-settings-BwBmCdTR.js → subject-settings-CkEwrw3W.js} +23 -5
- package/dist/supabase/index.d.ts +4 -4
- package/dist/supabase/index.js +3 -3
- package/dist/supabase/middleware.d.ts +11 -5
- package/dist/supabase/middleware.js +10 -7
- package/dist/{supabase-C0qESOa-.js → supabase-C1TWlnYt.js} +36 -52
- package/dist/{supabase-Boqb9a_Y.js → supabase-Dbqr141s.js} +2 -2
- package/dist/supabase-hook-BULg7Ut_.js +2 -0
- package/dist/{supabase-hook-CSLQ4zJ3.js → supabase-hook-Cva3ikXz.js} +731 -782
- package/dist/{supautils-Cn4R4cJ4.js → supautils-B6HYL9eL.js} +2 -2
- package/dist/svelte/Protected.svelte +9 -2
- package/dist/svelte/index.d.ts +6 -6
- package/dist/svelte/index.js +25 -11
- package/dist/svelte/runtime.d.ts +10 -3
- package/dist/svelte/runtime.js +4 -3
- package/dist/svelte/source.d.ts +6 -6
- package/dist/svelte/source.js +4 -4
- package/dist/{validity-uOp8UpYn.js → tenancy-DshjqY0n.js} +3 -39
- package/dist/terminal/index.d.ts +5 -5
- package/dist/terminal/index.js +18 -34
- package/dist/testing/index.d.ts +89 -77
- package/dist/testing/index.js +1276 -1262
- 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/thenable-QSmvt-vZ.js +65 -0
- package/dist/{token-CIWxJOCh.js → token-Bx9qy30p.js} +1 -1
- package/dist/tool-refusal-CQ7OEia9.js +41 -0
- package/dist/trpc/index.d.ts +5 -5
- package/dist/trpc/index.js +7 -8
- package/dist/{types-DbjRN55U.d.ts → types-7rJVLWe5.d.ts} +82 -4
- package/dist/{types-aqOHTHcp.d.ts → types-Br9IXUBG.d.ts} +1 -1
- package/dist/types-ByUo56un.d.ts +88 -0
- package/dist/{types-Cq_H8N_X.d.ts → types-C0dee0Qf.d.ts} +2 -2
- package/dist/{types-DxiCGmmd.d.ts → types-CIlTojhq.d.ts} +2 -2
- package/dist/{types-QCuYJh4q.d.ts → types-CUcFZfpU.d.ts} +1 -1
- package/dist/{types-C97IskBw.d.ts → types-CqrjB9o6.d.ts} +1 -1
- package/dist/{types-BnIEz1sU.d.ts → types-DHrmBJLH.d.ts} +24 -6
- package/dist/{types-Dnemwd77.d.ts → types-DpWfQdSh.d.ts} +5 -1
- package/dist/{types-Bvc4oWT6.d.ts → types-DvupZE0w.d.ts} +1 -1
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +1 -1
- package/dist/{usage-GTixvDDU.js → usage-4G6t643F.js} +2 -2
- package/dist/{usage-ItS7nLcl.js → usage-CG9nOYZw.js} +7 -7
- package/dist/usage-iFLJ0-rr.js +2 -0
- package/dist/{validation-error-Ba264OaJ.d.ts → validation-error-BSSw0l_8.d.ts} +1 -1
- package/dist/{validation-error-CnjZ4t92.js → validation-error-ZfUHbKvf.js} +1 -1
- package/dist/validity-dVrUEPJt.js +62 -0
- package/dist/{verifier-BxBo6I44.js → verifier-DMr_Zmb_.js} +51 -15
- package/dist/{rls-verify-CVQTHTh5.js → verify-BztUB3GX.js} +668 -239
- package/dist/{version-BvacVTZR.js → version-BEogC-rB.js} +1 -1
- package/dist/{views-Soe7bGSC.js → views-CJsrBS1f.js} +23 -1
- package/dist/{vocabulary-DA8a8zif.d.ts → vocabulary-hhEFLFoL.d.ts} +15 -6
- package/dist/vue/index.d.ts +24 -19
- package/dist/vue/index.js +24 -8
- package/dist/watch-C8TpsAl4.js +2 -0
- package/dist/{watch-DVBJ9cBq.js → watch-zeucB7eF.js} +6 -6
- package/dist/webmcp/index.d.ts +2 -2
- package/dist/webmcp/index.js +13 -37
- package/dist/wrap-Cr93qqdP.d.ts +14 -0
- package/dist/wrap-DWsU_5Bd.js +26 -0
- package/package.json +8 -8
- package/schemas/catalog-v1.json +6 -0
- package/skills/permdock-credentials/SKILL.md +1 -1
- package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
- package/skills/permdock-data/references/queries-and-rls.md +4 -0
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +1 -0
- package/skills/permdock-wire/SKILL.md +2 -2
- package/skills/permdock-wire/references/adapters.md +9 -1
- package/skills/permdock-wire/references/policy-options.md +10 -1
- package/dist/catalog-CRW5Mx_B.js +0 -2
- package/dist/collect-DSWOk19R.js +0 -2
- package/dist/create-CMwIl-w2.js +0 -253
- package/dist/delegation-D8pUEuce.js +0 -103
- package/dist/doctor-collect-CHk6XWOA.js +0 -665
- package/dist/doctor-igIiM_Hl.js +0 -1194
- package/dist/evaluation-items-CfCCejQd.js +0 -40
- package/dist/fields-BMl1RxoX.js +0 -26
- package/dist/grantee-Cv5Sogfv.js +0 -602
- package/dist/hosted-DJQw46hn.js +0 -266
- package/dist/instance-options-Dhhcnm3y.js +0 -22
- package/dist/load-DwJUafYN.js +0 -2
- package/dist/map-AcxK9o_D.js +0 -147
- package/dist/permissions-DVoF6dMt.js +0 -662
- package/dist/powersync-e_AZrKbg.js +0 -2
- package/dist/protected-xAr24FEC.d.ts +0 -40
- package/dist/relations-cjOL01hZ.js +0 -505
- package/dist/rls-graph-CHwx0V8q.js +0 -435
- package/dist/rls-shared-Cewd_-zI.js +0 -495
- package/dist/store-jOBYpiXC.d.ts +0 -36
- package/dist/stores-C0IMQrGI.d.ts +0 -52
- package/dist/supabase-config-BpPXt3x1.js +0 -472
- package/dist/supabase-hook-6sYLXg_u.js +0 -2
- package/dist/thenable-okc2xDsj.js +0 -10
- package/dist/types-CKNSyIf_.d.ts +0 -52
- package/dist/usage-DorAJiU_.js +0 -2
- package/dist/watch-BwxLTYMZ.js +0 -2
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { n as isReadonlyArray, t as compact } from "./compact-CAf557ZB.js";
|
|
2
|
+
import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
|
|
3
|
+
import { a as assertSafeKey, c as ownKeys, o as isForbiddenKey } from "./thenable-QSmvt-vZ.js";
|
|
4
|
+
import { r as parseAppData, t as assertAppData } from "./app-data-CV8pqqMi.js";
|
|
5
|
+
import { f as normaliseRelation, h as restrictedStopsOf, i as assertIncludes, n as RESOURCE_NAME, r as assertGraphTargets, t as LEVEL_NAME } from "./resource-relations-D1Un3pcz.js";
|
|
6
|
+
//#region src/core/brands.ts
|
|
7
|
+
const RESOURCE_BRAND = Symbol.for("permdock.resource");
|
|
8
|
+
const TREE_REGISTRY = Symbol.for("permdock.registry");
|
|
9
|
+
const NODE_RESOURCE = Symbol.for("permdock.resource");
|
|
10
|
+
const TREE_LEAVES = Symbol.for("permdock.leaves");
|
|
11
|
+
const LEAF_FORMER = Symbol.for("permdock.former");
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/core/permission-leaf.ts
|
|
14
|
+
function isStandardSchema(value) {
|
|
15
|
+
return value !== null && typeof value === "object" && "~standard" in value && typeof value["~standard"]?.version === "number";
|
|
16
|
+
}
|
|
17
|
+
function isResourceInit(value) {
|
|
18
|
+
return value !== null && typeof value === "object" && RESOURCE_BRAND in value && value[RESOURCE_BRAND] === true;
|
|
19
|
+
}
|
|
20
|
+
function isResourceOptions(value) {
|
|
21
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && !isStandardSchema(value);
|
|
22
|
+
}
|
|
23
|
+
function metaFor(list, action, schema) {
|
|
24
|
+
if (list === void 0 || Array.isArray(list)) return freezeDeep({});
|
|
25
|
+
const meta = list[action];
|
|
26
|
+
if (meta?.x === void 0) return freezeDeep({ ...meta });
|
|
27
|
+
return freezeDeep({
|
|
28
|
+
...meta,
|
|
29
|
+
x: parseAppData(schema, meta.x, `meta.x of action '${action}'`)
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function resourceMetaFor(name, meta, schema) {
|
|
33
|
+
if (meta === void 0) return;
|
|
34
|
+
assertAppData(meta, `meta of resource '${name}'`);
|
|
35
|
+
for (const field of ["title", "description"]) if (meta[field] !== void 0 && typeof meta[field] !== "string") throw new TypeError(`PermDock: meta.${field} of resource '${name}' must be a string`);
|
|
36
|
+
return freezeDeep(compact({
|
|
37
|
+
title: meta.title,
|
|
38
|
+
description: meta.description,
|
|
39
|
+
x: meta.x === void 0 ? void 0 : parseAppData(schema, meta.x, `meta.x of resource '${name}'`)
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* MCP and WebMCP tool hints from a permission's `meta`. Hints only inform the
|
|
44
|
+
* client; every call is still decided on the server.
|
|
45
|
+
*/
|
|
46
|
+
function annotationsFor(permission) {
|
|
47
|
+
const { meta } = permission;
|
|
48
|
+
const readOnlyHint = meta.readOnly ?? (permission.action === "read" || permission.action === "list");
|
|
49
|
+
return compact({
|
|
50
|
+
readOnlyHint,
|
|
51
|
+
destructiveHint: readOnlyHint ? void 0 : meta.destructive,
|
|
52
|
+
idempotentHint: meta.idempotent
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function actionNames(list) {
|
|
56
|
+
if (list === void 0) return [];
|
|
57
|
+
if (isReadonlyArray(list)) return list;
|
|
58
|
+
return Object.keys(list);
|
|
59
|
+
}
|
|
60
|
+
function keyToScope(key) {
|
|
61
|
+
return key.replaceAll(".", ":");
|
|
62
|
+
}
|
|
63
|
+
function makeLeaf(key, resourceName, action, meta, kind, former) {
|
|
64
|
+
const leaf = {
|
|
65
|
+
key,
|
|
66
|
+
scope: keyToScope(key),
|
|
67
|
+
resource: resourceName,
|
|
68
|
+
action,
|
|
69
|
+
meta
|
|
70
|
+
};
|
|
71
|
+
Object.defineProperty(leaf, "kind", {
|
|
72
|
+
value: kind,
|
|
73
|
+
enumerable: false,
|
|
74
|
+
writable: false,
|
|
75
|
+
configurable: false
|
|
76
|
+
});
|
|
77
|
+
if (former !== void 0 && former.length > 0) Object.defineProperty(leaf, LEAF_FORMER, {
|
|
78
|
+
value: Object.freeze([...former].toSorted()),
|
|
79
|
+
enumerable: false,
|
|
80
|
+
writable: false,
|
|
81
|
+
configurable: false
|
|
82
|
+
});
|
|
83
|
+
return Object.freeze(leaf);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The keys `permission` was renamed from, sorted. Empty for a leaf without
|
|
87
|
+
* renames and for one that crossed a serialisation boundary.
|
|
88
|
+
*/
|
|
89
|
+
function formerKeys(permission) {
|
|
90
|
+
if (!Object.hasOwn(permission, LEAF_FORMER)) return [];
|
|
91
|
+
const value = Reflect.get(permission, LEAF_FORMER);
|
|
92
|
+
return isReadonlyArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
93
|
+
}
|
|
94
|
+
/** The OAuth scope strings `permission` used to have: each former key with `.` as `:`. */
|
|
95
|
+
function formerScopes(permission) {
|
|
96
|
+
return formerKeys(permission).map(keyToScope);
|
|
97
|
+
}
|
|
98
|
+
function resource(schemaOrOptions, options) {
|
|
99
|
+
if (schemaOrOptions === void 0 && options === void 0) throw new Error("PermDock: resource() requires a schema or options");
|
|
100
|
+
if (isStandardSchema(schemaOrOptions)) return {
|
|
101
|
+
[RESOURCE_BRAND]: true,
|
|
102
|
+
schema: schemaOrOptions,
|
|
103
|
+
options: options ?? {}
|
|
104
|
+
};
|
|
105
|
+
if (isResourceOptions(schemaOrOptions) && options === void 0) return {
|
|
106
|
+
[RESOURCE_BRAND]: true,
|
|
107
|
+
schema: void 0,
|
|
108
|
+
options: schemaOrOptions
|
|
109
|
+
};
|
|
110
|
+
throw new Error("PermDock: resource() first argument must be a schema or options");
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/core/materialise-resource.ts
|
|
114
|
+
function materialiseResource(init, path, registry, leaves, build) {
|
|
115
|
+
const { former } = build;
|
|
116
|
+
const segment = path.at(-1);
|
|
117
|
+
if (segment === void 0) throw new Error("PermDock: resource() cannot be the root of definePermissions");
|
|
118
|
+
const name = init.options.name ?? segment;
|
|
119
|
+
assertSafeKey(name, "resource");
|
|
120
|
+
if (init.options.name !== void 0 && !RESOURCE_NAME.test(name)) throw new Error(`PermDock: resource name '${name}' must start with a letter and hold only letters, digits, '_' and '-'`);
|
|
121
|
+
if (registry.has(name)) throw new Error(`PermDock: duplicate resource name '${name}'`);
|
|
122
|
+
const prefix = path.join(".");
|
|
123
|
+
const instanceNames = actionNames(init.options.actions);
|
|
124
|
+
const collectionNames = actionNames(init.options.collection);
|
|
125
|
+
if (instanceNames.length === 0 && collectionNames.length === 0) throw new Error(`PermDock: resource '${name}' has no actions or collection`);
|
|
126
|
+
const instanceSet = /* @__PURE__ */ new Set();
|
|
127
|
+
const collectionSet = /* @__PURE__ */ new Set();
|
|
128
|
+
const node = {};
|
|
129
|
+
for (const action of instanceNames) {
|
|
130
|
+
assertSafeKey(action, "action");
|
|
131
|
+
if (instanceSet.has(action)) throw new Error(`PermDock: duplicate action '${action}' on '${name}'`);
|
|
132
|
+
instanceSet.add(action);
|
|
133
|
+
const key = `${prefix}.${action}`;
|
|
134
|
+
const leaf = makeLeaf(key, name, action, metaFor(init.options.actions, action, build.x?.permission), "instance", former.get(key));
|
|
135
|
+
node[action] = leaf;
|
|
136
|
+
leaves.push(leaf);
|
|
137
|
+
}
|
|
138
|
+
for (const action of collectionNames) {
|
|
139
|
+
assertSafeKey(action, "action");
|
|
140
|
+
if (instanceSet.has(action) || collectionSet.has(action)) throw new Error(`PermDock: duplicate action '${action}' on '${name}'`);
|
|
141
|
+
collectionSet.add(action);
|
|
142
|
+
const key = `${prefix}.${action}`;
|
|
143
|
+
const leaf = makeLeaf(key, name, action, metaFor(init.options.collection, action, build.x?.permission), "collection", former.get(key));
|
|
144
|
+
node[action] = leaf;
|
|
145
|
+
leaves.push(leaf);
|
|
146
|
+
}
|
|
147
|
+
const parent = init.options.parent;
|
|
148
|
+
if (parent !== void 0) {
|
|
149
|
+
assertSafeKey(parent.field, "parent field");
|
|
150
|
+
assertSafeKey(parent.resource, "parent resource");
|
|
151
|
+
}
|
|
152
|
+
const version = init.options.version;
|
|
153
|
+
if (version !== void 0) assertSafeKey(version, "version field");
|
|
154
|
+
const restrictedOption = init.options.restricted;
|
|
155
|
+
const restricted = typeof restrictedOption === "string" ? restrictedOption : restrictedOption?.field;
|
|
156
|
+
if (restrictedOption !== void 0) {
|
|
157
|
+
if (typeof restricted !== "string") throw new TypeError(`PermDock: resource "${name}" restricted must name a field`);
|
|
158
|
+
assertSafeKey(restricted, "restricted field");
|
|
159
|
+
}
|
|
160
|
+
const disclosure = init.options.disclosure ?? "reveal";
|
|
161
|
+
if (disclosure !== "hide" && disclosure !== "reveal") throw new Error(`PermDock: resource "${name}" disclosure must be 'hide' or 'reveal'`);
|
|
162
|
+
const relations = {};
|
|
163
|
+
for (const [relationName, spec] of Object.entries(init.options.relations ?? {})) {
|
|
164
|
+
assertSafeKey(relationName, "relation");
|
|
165
|
+
relations[relationName] = freezeDeep(normaliseRelation(name, relationName, spec));
|
|
166
|
+
}
|
|
167
|
+
const links = {};
|
|
168
|
+
for (const [linkName, link] of Object.entries(init.options.links ?? {})) {
|
|
169
|
+
assertSafeKey(linkName, "link");
|
|
170
|
+
if (linkName === "parent") throw new Error(`PermDock: link 'parent' on '${name}' is reserved; declare it as parent`);
|
|
171
|
+
assertSafeKey(link.field, "link field");
|
|
172
|
+
assertSafeKey(link.resource, "link resource");
|
|
173
|
+
links[linkName] = freezeDeep({
|
|
174
|
+
field: link.field,
|
|
175
|
+
resource: link.resource
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const restrictedStopList = typeof restrictedOption === "object" ? restrictedStopsOf(name, restrictedOption, parent, links) : void 0;
|
|
179
|
+
const levels = {};
|
|
180
|
+
for (const [levelName, condition] of Object.entries(init.options.levels ?? {})) {
|
|
181
|
+
if (!LEVEL_NAME.test(levelName)) throw new Error(`PermDock: level '${levelName}' on '${name}' must match ^[a-z][a-z0-9_]*$`);
|
|
182
|
+
if (condition === null || typeof condition !== "object" || Array.isArray(condition)) throw new Error(`PermDock: level '${levelName}' on '${name}' must be a condition object`);
|
|
183
|
+
levels[levelName] = freezeDeep({ ...condition });
|
|
184
|
+
}
|
|
185
|
+
if (Object.keys(levels).length > 0 && instanceSet.size === 0) throw new Error(`PermDock: resource '${name}' declares levels but no instance actions`);
|
|
186
|
+
const meta = resourceMetaFor(name, init.options.meta, build.x?.resource);
|
|
187
|
+
const resourceNode = Object.freeze({
|
|
188
|
+
...meta === void 0 ? {} : { meta },
|
|
189
|
+
name,
|
|
190
|
+
path: prefix,
|
|
191
|
+
schema: init.schema,
|
|
192
|
+
id: init.options.id ?? "id",
|
|
193
|
+
parent: parent === void 0 ? void 0 : freezeDeep({ ...parent }),
|
|
194
|
+
links: freezeDeep(links),
|
|
195
|
+
relations: freezeDeep(relations),
|
|
196
|
+
version,
|
|
197
|
+
restricted,
|
|
198
|
+
...restrictedStopList === void 0 ? {} : { restrictedStops: restrictedStopList },
|
|
199
|
+
disclosure,
|
|
200
|
+
instanceActions: instanceSet,
|
|
201
|
+
collectionActions: collectionSet,
|
|
202
|
+
levels: Object.freeze(levels)
|
|
203
|
+
});
|
|
204
|
+
assertIncludes(resourceNode);
|
|
205
|
+
registry.set(name, resourceNode);
|
|
206
|
+
Object.defineProperty(node, NODE_RESOURCE, {
|
|
207
|
+
value: resourceNode,
|
|
208
|
+
enumerable: false,
|
|
209
|
+
writable: false,
|
|
210
|
+
configurable: false
|
|
211
|
+
});
|
|
212
|
+
return freezeDeep(node);
|
|
213
|
+
}
|
|
214
|
+
/** The resource a `definePermissions` resource node was built from, read from the node itself. */
|
|
215
|
+
function resourceOfNode(node) {
|
|
216
|
+
if (!Object.hasOwn(node, NODE_RESOURCE)) return;
|
|
217
|
+
const value = Reflect.get(node, NODE_RESOURCE);
|
|
218
|
+
return isResourceNode(value) ? value : void 0;
|
|
219
|
+
}
|
|
220
|
+
function isResourceNode(value) {
|
|
221
|
+
return value !== null && typeof value === "object" && "name" in value && "instanceActions" in value;
|
|
222
|
+
}
|
|
223
|
+
function walk(input, path, registry, leaves, depth, build) {
|
|
224
|
+
if (depth > 10) throw new Error(`PermDock: permission group nesting exceeds 10`);
|
|
225
|
+
if (isResourceInit(input)) return materialiseResource(input, path, registry, leaves, build);
|
|
226
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) throw new Error(`PermDock: definePermissions expected a group or resource at '${path.join(".")}'`);
|
|
227
|
+
const group = {};
|
|
228
|
+
for (const key of Object.keys(input)) {
|
|
229
|
+
assertSafeKey(key, "group");
|
|
230
|
+
group[key] = walk(input[key], [...path, key], registry, leaves, depth + 1, build);
|
|
231
|
+
}
|
|
232
|
+
return group;
|
|
233
|
+
}
|
|
234
|
+
function attachRegistry(tree, registry, leaves) {
|
|
235
|
+
const attached = tree;
|
|
236
|
+
Object.defineProperty(attached, TREE_REGISTRY, {
|
|
237
|
+
value: registry,
|
|
238
|
+
enumerable: false,
|
|
239
|
+
writable: false,
|
|
240
|
+
configurable: false
|
|
241
|
+
});
|
|
242
|
+
Object.defineProperty(attached, TREE_LEAVES, {
|
|
243
|
+
value: Object.freeze([...leaves]),
|
|
244
|
+
enumerable: false,
|
|
245
|
+
writable: false,
|
|
246
|
+
configurable: false
|
|
247
|
+
});
|
|
248
|
+
return attached;
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/core/permission-registry.ts
|
|
252
|
+
function isRegistryTree(tree) {
|
|
253
|
+
return TREE_REGISTRY in tree;
|
|
254
|
+
}
|
|
255
|
+
function getRegistry(tree) {
|
|
256
|
+
if (!isRegistryTree(tree)) throw new Error("PermDock: permission tree is missing its registry");
|
|
257
|
+
return tree[TREE_REGISTRY];
|
|
258
|
+
}
|
|
259
|
+
function getResource(tree, name) {
|
|
260
|
+
if (isForbiddenKey(name)) return;
|
|
261
|
+
return getRegistry(tree).get(name);
|
|
262
|
+
}
|
|
263
|
+
const RENAMED_KEY = /^\S+$/u;
|
|
264
|
+
/** Current key to its former keys, from the `renamed` option; targets are checked once leaves exist. */
|
|
265
|
+
function formerByKey(renamed) {
|
|
266
|
+
const former = /* @__PURE__ */ new Map();
|
|
267
|
+
if (renamed === void 0) return former;
|
|
268
|
+
if (renamed === null || typeof renamed !== "object") throw new TypeError("PermDock: renamed must map old keys to current keys");
|
|
269
|
+
for (const [old, current] of Object.entries(renamed)) {
|
|
270
|
+
if (!RENAMED_KEY.test(old) || old.split(".").some(isForbiddenKey)) throw new Error(`PermDock: renamed key '${old}' is not a valid key`);
|
|
271
|
+
if (typeof current !== "string") throw new TypeError(`PermDock: renamed key '${old}' must map to a current key`);
|
|
272
|
+
former.set(current, [...former.get(current) ?? [], old]);
|
|
273
|
+
}
|
|
274
|
+
return former;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Every current key is unique, every former key names exactly one leaf, and
|
|
278
|
+
* no former key is also a current key, so a string resolves to one leaf.
|
|
279
|
+
*/
|
|
280
|
+
function assertKeys(leaves, former) {
|
|
281
|
+
const current = /* @__PURE__ */ new Set();
|
|
282
|
+
for (const leaf of leaves) {
|
|
283
|
+
if (current.has(leaf.key))
|
|
284
|
+
/* v8 ignore next */
|
|
285
|
+
throw new Error(`PermDock: duplicate permission key '${leaf.key}'`);
|
|
286
|
+
current.add(leaf.key);
|
|
287
|
+
}
|
|
288
|
+
for (const target of former?.keys() ?? []) if (!current.has(target)) throw new Error(`PermDock: renamed target '${target}' is not a permission key`);
|
|
289
|
+
const olds = /* @__PURE__ */ new Map();
|
|
290
|
+
for (const leaf of leaves) for (const old of formerKeys(leaf)) {
|
|
291
|
+
if (current.has(old)) throw new Error(`PermDock: renamed key '${old}' is still a permission key`);
|
|
292
|
+
const other = olds.get(old);
|
|
293
|
+
if (other !== void 0 && other !== leaf.key) throw new Error(`PermDock: renamed key '${old}' maps to both '${other}' and '${leaf.key}'`);
|
|
294
|
+
olds.set(old, leaf.key);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function collectLeaves(node) {
|
|
298
|
+
if ("key" in node && "scope" in node && "action" in node) return [node];
|
|
299
|
+
const out = [];
|
|
300
|
+
for (const key of ownKeys(node)) {
|
|
301
|
+
const child = node[key];
|
|
302
|
+
if (child !== void 0) out.push(...collectLeaves(child));
|
|
303
|
+
}
|
|
304
|
+
return out;
|
|
305
|
+
}
|
|
306
|
+
function listPermissions(tree) {
|
|
307
|
+
if (isRegistryTree(tree)) return tree[TREE_LEAVES];
|
|
308
|
+
return collectLeaves(tree);
|
|
309
|
+
}
|
|
310
|
+
function findPermission(tree, keyOrScope) {
|
|
311
|
+
if (isForbiddenKey(keyOrScope)) return;
|
|
312
|
+
const leaves = listPermissions(tree);
|
|
313
|
+
for (const leaf of leaves) if (leaf.key === keyOrScope || leaf.scope === keyOrScope) return leaf;
|
|
314
|
+
for (const leaf of leaves) if (formerKeys(leaf).includes(keyOrScope) || formerScopes(leaf).includes(keyOrScope)) return leaf;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* A permission leaf: string `key`, `scope`, `resource` and `action` plus an
|
|
318
|
+
* object `meta`. `kind` is non-enumerable and does not survive
|
|
319
|
+
* `JSON.stringify`, so a leaf that crossed a serialisation boundary passes
|
|
320
|
+
* without it; when present it must be `instance` or `collection`.
|
|
321
|
+
*/
|
|
322
|
+
function isPermission(value) {
|
|
323
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
324
|
+
for (const field of [
|
|
325
|
+
"key",
|
|
326
|
+
"scope",
|
|
327
|
+
"resource",
|
|
328
|
+
"action"
|
|
329
|
+
]) if (!Object.hasOwn(value, field) || typeof Reflect.get(value, field) !== "string") return false;
|
|
330
|
+
const meta = Object.hasOwn(value, "meta") ? Reflect.get(value, "meta") : void 0;
|
|
331
|
+
if (meta === null || typeof meta !== "object" || Array.isArray(meta)) return false;
|
|
332
|
+
if (!Object.hasOwn(value, "kind")) return true;
|
|
333
|
+
const kind = Reflect.get(value, "kind");
|
|
334
|
+
return kind === "instance" || kind === "collection";
|
|
335
|
+
}
|
|
336
|
+
function mergeNodes(target, source, keys, registry, sourceRegistry) {
|
|
337
|
+
for (const key of ownKeys(source)) {
|
|
338
|
+
assertSafeKey(key, "group");
|
|
339
|
+
const incoming = source[key];
|
|
340
|
+
if (incoming === void 0)
|
|
341
|
+
/* v8 ignore next */
|
|
342
|
+
continue;
|
|
343
|
+
const existing = target[key];
|
|
344
|
+
if (existing === void 0) {
|
|
345
|
+
target[key] = incoming;
|
|
346
|
+
if (isPermission(incoming)) {
|
|
347
|
+
if (keys.has(incoming.key))
|
|
348
|
+
/* v8 ignore next */
|
|
349
|
+
throw new Error(`PermDock: duplicate permission key '${incoming.key}'`);
|
|
350
|
+
keys.add(incoming.key);
|
|
351
|
+
}
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (isPermission(existing) || isPermission(incoming)) {
|
|
355
|
+
const keyName = isPermission(incoming) ? incoming.key : isPermission(existing) ? existing.key : key;
|
|
356
|
+
throw new Error(`PermDock: duplicate permission key '${keyName}'`);
|
|
357
|
+
}
|
|
358
|
+
const nested = { ...existing };
|
|
359
|
+
mergeNodes(nested, incoming, keys, registry, sourceRegistry);
|
|
360
|
+
target[key] = freezeDeep(nested);
|
|
361
|
+
}
|
|
362
|
+
if (sourceRegistry !== void 0) for (const [name, node] of sourceRegistry) {
|
|
363
|
+
if (registry.has(name) && registry.get(name) !== node) throw new Error(`PermDock: duplicate resource name '${name}'`);
|
|
364
|
+
registry.set(name, node);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function mergePermissions(...trees) {
|
|
368
|
+
if (trees.length === 0) throw new Error("PermDock: mergePermissions() requires at least one tree");
|
|
369
|
+
const merged = {};
|
|
370
|
+
const keys = /* @__PURE__ */ new Set();
|
|
371
|
+
const registry = /* @__PURE__ */ new Map();
|
|
372
|
+
for (const tree of trees) mergeNodes(merged, tree, keys, registry, isRegistryTree(tree) ? tree[TREE_REGISTRY] : void 0);
|
|
373
|
+
assertGraphTargets(registry);
|
|
374
|
+
const leaves = collectLeaves(merged);
|
|
375
|
+
assertKeys(leaves);
|
|
376
|
+
return freezeDeep(attachRegistry(merged, registry, leaves));
|
|
377
|
+
}
|
|
378
|
+
/** Former key to current key, for every leaf of `tree`. */
|
|
379
|
+
function renamedKeys(tree) {
|
|
380
|
+
const map = /* @__PURE__ */ new Map();
|
|
381
|
+
for (const leaf of listPermissions(tree)) for (const old of formerKeys(leaf)) map.set(old, leaf.key);
|
|
382
|
+
return map;
|
|
383
|
+
}
|
|
384
|
+
//#endregion
|
|
385
|
+
export { resource as _, getResource as a, listPermissions as c, attachRegistry as d, resourceOfNode as f, formerScopes as g, formerKeys as h, getRegistry as i, mergePermissions as l, annotationsFor as m, findPermission as n, isPermission as o, walk as p, formerByKey as r, isRegistryTree as s, assertKeys as t, renamedKeys as u };
|
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
-
//#region src/core/
|
|
2
|
+
//#region src/core/app-data.d.ts
|
|
3
|
+
/** A JSON value in an app `x` field. */
|
|
4
|
+
type MetaValue = string | number | boolean | null | readonly MetaValue[] | {
|
|
5
|
+
readonly [key: string]: MetaValue;
|
|
6
|
+
};
|
|
7
|
+
/** The default shape of an app `x` field: a plain JSON object. */
|
|
8
|
+
type AppData = Readonly<Record<string, MetaValue>>;
|
|
9
|
+
/**
|
|
10
|
+
* A Standard Schema for one kind of app data. It must validate synchronously;
|
|
11
|
+
* its output is the type PermDock gives the `x` field it checks.
|
|
12
|
+
*/
|
|
13
|
+
type AppDataSchema<X = AppData> = StandardSchemaV1<unknown, X>;
|
|
14
|
+
/** A leaf whose `meta.x` is typed by a schema; intersected so it stays assignable to the untyped leaf. */
|
|
15
|
+
type WithX<L, X> = [X] extends [never] ? L : L & {
|
|
16
|
+
readonly meta: {
|
|
17
|
+
readonly x?: Readonly<X>;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/core/brands.d.ts
|
|
3
22
|
declare const RESOURCE_BRAND: unique symbol;
|
|
23
|
+
/**
|
|
24
|
+
* Phantom key carrying a tree's resource `x` type for `getResource`. Exported
|
|
25
|
+
* as a type only, so a consumer's declaration emit can name it; it has no value.
|
|
26
|
+
*/
|
|
27
|
+
declare const RESOURCE_X: unique symbol;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/core/permission-types.d.ts
|
|
4
30
|
/** `definePermissions` options. */
|
|
5
|
-
type DefinePermissionsOptions = {
|
|
31
|
+
type DefinePermissionsOptions<PX = never, RX = never> = {
|
|
6
32
|
/**
|
|
7
33
|
* Keys a permission used to have, mapped to its current key. Old keys are
|
|
8
34
|
* accepted wherever a key arrives as a string (stored custom roles, OAuth
|
|
@@ -10,6 +36,27 @@ type DefinePermissionsOptions = {
|
|
|
10
36
|
* the current leaf; code, decisions and audit only ever see the current key.
|
|
11
37
|
*/
|
|
12
38
|
readonly renamed?: Readonly<Record<string, string>>;
|
|
39
|
+
/**
|
|
40
|
+
* Standard Schemas for app data. `permission` checks every action's
|
|
41
|
+
* `meta.x` and types it on the leaves; `resource` checks every resource's
|
|
42
|
+
* `meta.x` and types it on `getResource`. Both validate synchronously at
|
|
43
|
+
* definition time and throw on invalid data.
|
|
44
|
+
*/
|
|
45
|
+
readonly x?: {
|
|
46
|
+
readonly permission?: AppDataSchema<PX>;
|
|
47
|
+
readonly resource?: AppDataSchema<RX>;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/** A resource's metadata. PermDock carries it to the catalog and never reads `x`. */
|
|
51
|
+
type ResourceMeta<X = AppData> = {
|
|
52
|
+
readonly title?: string;
|
|
53
|
+
readonly description?: string;
|
|
54
|
+
/** Data the application owns. Plain JSON, typed by `definePermissions(…, { x: { resource } })`. */
|
|
55
|
+
readonly x?: X;
|
|
56
|
+
};
|
|
57
|
+
/** A tree whose resources carry `meta.x` of type `X`, read through `getResource`. */
|
|
58
|
+
type ResourceXTree<X> = {
|
|
59
|
+
readonly [RESOURCE_X]?: X;
|
|
13
60
|
};
|
|
14
61
|
type ActionMeta = {
|
|
15
62
|
readonly title?: string;
|
|
@@ -30,13 +77,9 @@ type ActionMeta = {
|
|
|
30
77
|
/**
|
|
31
78
|
* Data the application owns, such as a risk level or an undo window. Plain
|
|
32
79
|
* JSON; PermDock carries it on the leaf, the catalog and snapshots and
|
|
33
|
-
* never reads it.
|
|
80
|
+
* never reads it. `definePermissions(…, { x: { permission } })` types it.
|
|
34
81
|
*/
|
|
35
|
-
readonly x?:
|
|
36
|
-
};
|
|
37
|
-
/** A JSON value in `ActionMeta.x`. */
|
|
38
|
-
type MetaValue = string | number | boolean | null | readonly MetaValue[] | {
|
|
39
|
-
readonly [key: string]: MetaValue;
|
|
82
|
+
readonly x?: AppData;
|
|
40
83
|
};
|
|
41
84
|
type PermissionKind = "instance" | "collection";
|
|
42
85
|
type Permission<K extends string = string, T = unknown, Kind extends PermissionKind = PermissionKind> = {
|
|
@@ -159,6 +202,8 @@ type ResourceOptions<A extends ActionList | undefined = ActionList | undefined,
|
|
|
159
202
|
* it; it reaches only instance actions. Names match `^[a-z][a-z0-9_]*$`.
|
|
160
203
|
*/
|
|
161
204
|
readonly levels?: Readonly<Record<string, ResourceLevel>>;
|
|
205
|
+
/** Display text and app data for the resource; carried to the catalog, never read in evaluation. */
|
|
206
|
+
readonly meta?: ResourceMeta;
|
|
162
207
|
};
|
|
163
208
|
/** A level's row condition: `where` shorthand or a normalised `Condition`, checked by `definePolicy`. */
|
|
164
209
|
type ResourceLevel = Readonly<Record<string, unknown>>;
|
|
@@ -183,32 +228,15 @@ type ResourceNode<T = unknown> = {
|
|
|
183
228
|
readonly collectionActions: ReadonlySet<string>;
|
|
184
229
|
/** Declared level names to their raw condition; `definePolicy` normalises them. */
|
|
185
230
|
readonly levels?: Readonly<Record<string, ResourceLevel>>;
|
|
231
|
+
/** The resource's `meta`, when it declares one. */
|
|
232
|
+
readonly meta?: ResourceMeta;
|
|
186
233
|
};
|
|
187
234
|
type PermissionTree = {
|
|
188
235
|
readonly [key: string]: PermissionTree | Permission;
|
|
189
236
|
};
|
|
190
237
|
type ActionNames<A extends ActionList | undefined> = A extends readonly string[] ? A[number] : A extends Record<string, ActionMeta> ? keyof A & string : never;
|
|
191
|
-
type LeavesFrom<Prefix extends string, Names extends string, T, Kind extends PermissionKind> = [Names] extends [never] ? object : { readonly [K in Names]: Permission<Prefix extends "" ? K : `${Prefix}.${K}`, T, Kind>; };
|
|
192
|
-
type InferResourceLeaves<R extends ResourceInit, Prefix extends string> = R extends ResourceInit<infer T, infer A, infer C> ? LeavesFrom<Prefix, ActionNames<A>, T, "instance"> & LeavesFrom<Prefix, ActionNames<C>, T, "collection"> : object;
|
|
193
|
-
type InferPermissionTree<Input, Prefix extends string = ""> = Input extends ResourceInit ? InferResourceLeaves<Input, Prefix> : Input extends Record<string, unknown> ? { readonly [K in keyof Input & string]: InferPermissionTree<Input[K], Prefix extends "" ? K : `${Prefix}.${K}
|
|
194
|
-
/**
|
|
195
|
-
* The keys `permission` was renamed from, sorted. Empty for a leaf without
|
|
196
|
-
* renames and for one that crossed a serialisation boundary.
|
|
197
|
-
*/
|
|
198
|
-
declare function formerKeys(permission: object): readonly string[];
|
|
199
|
-
declare function resource<T, const A extends ActionList = readonly [], const C extends ActionList = readonly []>(schema: StandardSchemaV1<unknown, T>, options?: ResourceOptions<A, C>): ResourceInit<T, A, C>;
|
|
200
|
-
declare function resource<const A extends ActionList = readonly [], const C extends ActionList = readonly []>(options: ResourceOptions<A, C>): ResourceInit<unknown, A, C>;
|
|
201
|
-
declare function getResource(tree: PermissionTree, name: string): ResourceNode | undefined;
|
|
202
|
-
declare function definePermissions<const Input>(input: Input, options?: DefinePermissionsOptions): InferPermissionTree<Input>;
|
|
203
|
-
declare function listPermissions(tree: PermissionTree | Permission): readonly Permission[];
|
|
204
|
-
declare function findPermission(tree: PermissionTree, keyOrScope: string): Permission | undefined;
|
|
205
|
-
/**
|
|
206
|
-
* A permission leaf: string `key`, `scope`, `resource` and `action` plus an
|
|
207
|
-
* object `meta`. `kind` is non-enumerable and does not survive
|
|
208
|
-
* `JSON.stringify`, so a leaf that crossed a serialisation boundary passes
|
|
209
|
-
* without it; when present it must be `instance` or `collection`.
|
|
210
|
-
*/
|
|
211
|
-
declare function isPermission(value: unknown): value is Permission;
|
|
212
|
-
declare function mergePermissions<const Trees extends readonly PermissionTree[]>(...trees: Trees): PermissionTree;
|
|
238
|
+
type LeavesFrom<Prefix extends string, Names extends string, T, Kind extends PermissionKind, X = never> = [Names] extends [never] ? object : { readonly [K in Names]: WithX<Permission<Prefix extends "" ? K : `${Prefix}.${K}`, T, Kind>, X>; };
|
|
239
|
+
type InferResourceLeaves<R extends ResourceInit, Prefix extends string, X = never> = R extends ResourceInit<infer T, infer A, infer C> ? LeavesFrom<Prefix, ActionNames<A>, T, "instance", X> & LeavesFrom<Prefix, ActionNames<C>, T, "collection", X> : object;
|
|
240
|
+
type InferPermissionTree<Input, Prefix extends string = "", X = never> = Input extends ResourceInit ? InferResourceLeaves<Input, Prefix, X> : Input extends Record<string, unknown> ? { readonly [K in keyof Input & string]: InferPermissionTree<Input[K], Prefix extends "" ? K : `${Prefix}.${K}`, X>; } : never;
|
|
213
241
|
//#endregion
|
|
214
|
-
export {
|
|
242
|
+
export { WithX as A, ResourceRelationInput as C, AppData as D, RESOURCE_X as E, AppDataSchema as O, ResourceRelation as S, ResourceXTree as T, ResourceLink as _, EdgeGroup as a, ResourceOptions as b, EdgeRelation as c, Permission as d, PermissionKind as f, ResourceLevel as g, ResourceInit as h, DefinePermissionsOptions as i, MetaValue as k, FieldRelation as l, PrincipalRelation as m, ActionMeta as n, EdgeGroups as o, PermissionTree as p, ComputedRelation as r, EdgeMatch as s, ActionList as t, InferPermissionTree as u, ResourceMeta as v, ResourceRestricted as w, ResourceParent as x, ResourceNode as y };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { i as crud, s as definePermissions } from "./src-Bb7no-hS.js";
|
|
2
|
+
import { _ as resource } from "./permission-registry-BsblpB-z.js";
|
|
3
|
+
import { f as definePlans, p as defineRoles } from "./grantee-CXY-0C87.js";
|
|
4
4
|
//#region src/testing/saas/schema.ts
|
|
5
5
|
function accepts(kind, value) {
|
|
6
6
|
switch (kind) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as Role, t as Plan } from "./vocabulary-
|
|
1
|
+
import { h as ResourceInit, u as InferPermissionTree } from "./permission-types-Dg39z9Kv.js";
|
|
2
|
+
import { r as Role, t as Plan } from "./vocabulary-hhEFLFoL.js";
|
|
3
3
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
4
4
|
//#region src/testing/saas/permissions.d.ts
|
|
5
5
|
declare const SaasProjectSchema: StandardSchemaV1<SaasProject>;
|