permdock 0.7.0 → 0.9.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 +1 -3
- package/dist/a2a/index.d.ts +7 -7
- package/dist/a2a/index.js +8 -8
- package/dist/action-result-BcudBQOF.d.ts +19 -0
- package/dist/{adapter-context-CRhqyzCk.js → adapter-context-CIQpQxbE.js} +8 -2
- package/dist/{adoption-scan-D-feE7BE.js → adoption-scan-Ch07MdxN.js} +5 -5
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +1 -1
- package/dist/ai-sdk/index.d.ts +19 -13
- package/dist/ai-sdk/index.js +6 -6
- package/dist/{app-data-MuyzVqX8.js → app-data-UNNm07jV.js} +10 -7
- package/dist/{approval-header-CJACtHkv.js → approval-header-8QV6MU4H.js} +6 -3
- package/dist/{approval-prompt-K0faOLFp.d.ts → approval-prompt-3BqWczTt.d.ts} +13 -11
- package/dist/{approval-prompt-Dg5LeAcT.js → approval-prompt-B8hQY69x.js} +5 -6
- package/dist/approvals/index.d.ts +4 -4
- package/dist/approvals/index.js +6 -6
- package/dist/{approvals-CMRfsbBh.js → approvals-DnIBTuXE.js} +66 -42
- package/dist/{approvers-CqPOLD-o.js → approvers-B4r0N_Uz.js} +8 -2
- package/dist/{arazzo-ClrF3PVb.js → arazzo-BpS7LnV0.js} +2 -2
- package/dist/{arazzo-rdeJ8n1J.js → arazzo-CmQaGPkM.js} +6 -6
- package/dist/{args-CC3OwyHW.js → args-0FrVs5EH.js} +14 -7
- package/dist/astro/index.d.ts +30 -12
- package/dist/astro/index.js +2 -2
- package/dist/{audience-BrMs8c4o.js → audience-DTjR8xet.js} +8 -8
- package/dist/{auth-CscUX8Sy.js → auth--yPyZNgr.js} +19 -7
- package/dist/authzen/index.d.ts +34 -28
- package/dist/authzen/index.js +23 -20
- package/dist/{automation-DOtAFWdy.d.ts → automation-C6Jg75xq.d.ts} +42 -32
- package/dist/{automation-ySsxp_Yp.js → automation-x3KEUusw.js} +22 -21
- package/dist/better-auth/index.d.ts +2 -2
- package/dist/better-auth/index.js +13 -7
- package/dist/better-supabase/index.d.ts +357 -227
- package/dist/better-supabase/index.js +219 -140
- package/dist/{bind-D1nO6fiC.js → bind-BNQA9JK9.js} +26 -10
- package/dist/{bind-JDuvxjuW.d.ts → bind-YYjvfpB9.d.ts} +32 -12
- package/dist/{body-CH5of8Ne.js → body-CJQwYVa8.js} +3 -3
- package/dist/{body-text-QcXok_SI.js → body-text-DQhcmqdY.js} +8 -4
- package/dist/{boundary-BM8a_P6E.js → boundary-BV3O1eud.js} +8 -2
- package/dist/{boundary-BmHxVH1J.d.ts → boundary-C9ck-3uK.d.ts} +13 -4
- package/dist/{budget-NbEtbJC_.js → budget-BELja5A9.js} +6 -3
- package/dist/{budget-JqcRqyhK.d.ts → budget-hYsPz_yE.d.ts} +6 -3
- package/dist/{build-instance-DxE7czo9.js → build-instance-BWXqwQYU.js} +3 -3
- package/dist/{capability-L7NnfhiE.js → capability-BqX94r07.js} +31 -25
- package/dist/{capability-D4UC9TTW.d.ts → capability-Di9tiUvi.d.ts} +41 -29
- package/dist/{casbin-BHijLuHY.js → casbin-B7_yS-oo.js} +2 -2
- package/dist/{casbin-BW9pS47J.js → casbin-bHyIxTNQ.js} +16 -8
- package/dist/{casl-CmJlgziS.js → casl-C4OINZHI.js} +2 -2
- package/dist/{casl-UbI8v-Wq.js → casl-CHHoCldP.js} +19 -10
- package/dist/catalog/index.d.ts +51 -30
- package/dist/catalog/index.js +18 -15
- package/dist/{catalog-D69WhFii.js → catalog-CGlSwU6j.js} +20 -19
- package/dist/catalog-D3oS2GH3.js +1 -0
- package/dist/{catalog-BaMQfQ6Y.js → catalog-amPDr0JQ.js} +3 -3
- package/dist/{catalog-doc-CV9s6B1S.js → catalog-doc-DjMKzJp9.js} +28 -14
- package/dist/{catalog-fingerprint-C144oW4M.js → catalog-fingerprint-e6aCWosn.js} +18 -14
- package/dist/catalog-operations-DeHTrJSV.js +60 -0
- package/dist/{challenge-nGWma08S.js → challenge-DImNcR7B.js} +48 -27
- package/dist/chat/index.d.ts +1 -1
- package/dist/chat/index.js +13 -10
- package/dist/chat-sdk/index.d.ts +44 -26
- package/dist/chat-sdk/index.js +17 -17
- package/dist/{checks-BC_0mPIq.js → checks-CGkP3Z7A.js} +4 -1
- package/dist/{claims-map-7oQ3ue4X.js → claims-map-CKkoAAYF.js} +5 -2
- package/dist/{claims-map-Ca-QX8C6.d.ts → claims-map-D1Pb5oRq.d.ts} +8 -5
- package/dist/claude-agent/index.d.ts +6 -6
- package/dist/claude-agent/index.js +6 -3
- package/dist/clerk/index.d.ts +11 -7
- package/dist/clerk/index.js +6 -6
- package/dist/cli/bin.js +4 -4
- package/dist/cli/index.d.ts +82 -7
- package/dist/cli/index.js +6 -6
- package/dist/{clients-C7zLFuWT.d.ts → clients-C_NOET3z.d.ts} +5 -5
- package/dist/{clients-DjU5ABMy.js → clients-DYr3U86j.js} +3 -3
- package/dist/cloud/index.d.ts +84 -52
- package/dist/cloud/index.js +53 -39
- package/dist/{cloud-CO8pYtwr.js → cloud-3kWfjnYy.js} +4 -5
- package/dist/{codemod-BP6n8N9L.js → codemod-Bv5i-Mzo.js} +523 -201
- package/dist/{codemod-i4N2BhDc.js → codemod-D9Aiii1r.js} +3 -4
- package/dist/{collect-DNm3oKOk.js → collect-B80GYEot.js} +4 -5
- package/dist/collect-D-eroIfV.js +1 -0
- package/dist/{collect-BaWeMjwV.js → collect-WCl8cJQV.js} +26 -63
- package/dist/{compare-pfyVnBjE.js → compare-DTfyUunF.js} +2 -2
- package/dist/compile/index.d.ts +2 -2
- package/dist/compile/index.js +1 -1
- package/dist/{compile-COM2VKuN.d.ts → compile-BEklRUYo.d.ts} +36 -12
- package/dist/{compile-BAEO5bOk.js → compile-EzEMB-7v.js} +77 -33
- package/dist/{completion-BNdVf7X2.js → completion-_bc0OUQ-.js} +17 -8
- package/dist/config-BwPBfN0t.js +108 -0
- package/dist/{config-DGZzMV1B.js → config-D5XrLWpk.js} +2 -2
- package/dist/{config-report-Cm7UITNA.js → config-report-BmWIskD7.js} +9 -6
- package/dist/config-shape-ykV0Vm2n.js +134 -0
- package/dist/{connection-DjhIJSs2.js → connection-B72dg5Q2.js} +23 -22
- package/dist/{connector-schema-_VCSsdtD.js → connector-schema-CYLQNMYq.js} +3 -2
- package/dist/{context--uM9V3Ui.js → context-BnIzxTNE.js} +4 -3
- package/dist/convex/index.d.ts +13 -7
- package/dist/convex/index.js +9 -6
- package/dist/{core-CQkE8Esr.d.ts → core-CFepFiDP.d.ts} +49 -22
- package/dist/{core-B5-w6Kw9.js → core-DzVINFbU.js} +26 -20
- package/dist/{create-Cb86Z8Im.js → create-6EwRQlig.js} +10 -7
- package/dist/{create-DJrlhEp9.js → create-BLPKnJKa.js} +35 -25
- package/dist/{create-UTnUVETj.d.ts → create-BPUopdfL.d.ts} +70 -37
- package/dist/{create-QHuuPw3q.d.ts → create-BamXmeob.d.ts} +37 -29
- package/dist/{create-B2-CQqCI.d.ts → create-DBvUsgzK.d.ts} +49 -28
- package/dist/{credential-CIM7wHwA.js → credential-CyyyvCsL.js} +41 -38
- package/dist/{credentials-BpuTwd7a.js → credentials-CdDxp7jN.js} +6 -6
- package/dist/{deciding-columns-DRo2QM6E.js → deciding-columns-NB4wcyBf.js} +2 -2
- package/dist/{delegation-C5rOdTp5.js → delegation-CDB6_keF.js} +31 -22
- package/dist/delivery/index.d.ts +4 -4
- package/dist/delivery/index.js +5 -5
- package/dist/{delivery-rwOKLWRm.js → delivery-BupfvJIV.js} +34 -22
- package/dist/{delivery-event-xX4obB8F.js → delivery-event-JioK5YbS.js} +6 -6
- package/dist/denied-text-DHldhVUv.d.ts +22 -0
- package/dist/{describe-DZlnEtLy.js → describe-Bb4hGK5d.js} +5 -5
- package/dist/{describe-O0SwYIK8.d.ts → describe-BbFPBSms.d.ts} +5 -5
- package/dist/{device-BARQ8eYG.js → device-BwbJNmb2.js} +11 -8
- package/dist/{diff-Btr1c1Ow.js → diff-BwR1JdP2.js} +2 -2
- package/dist/{diff-DzT-xD13.js → diff-CQegtBAo.js} +22 -13
- package/dist/{digest-B3kc_PgQ.d.ts → digest-8Yx2CchM.d.ts} +3 -3
- package/dist/{doctor-BU1szn63.js → doctor-ClRVAtXQ.js} +287 -135
- package/dist/{doctor-BoK_y0KO.js → doctor-LPMYjSqO.js} +4 -4
- package/dist/drizzle/index.d.ts +33 -19
- package/dist/drizzle/index.js +17 -9
- package/dist/elysia/index.d.ts +17 -11
- package/dist/elysia/index.js +5 -5
- package/dist/{errors-BKy0EfhN.js → errors-B6R_lg2a.js} +13 -4
- package/dist/{errors-B_Qg9D3e.d.ts → errors-BIM4MFsJ.d.ts} +22 -6
- package/dist/{errors-BWXBMaKK.d.ts → errors-CHwoRRpB.d.ts} +4 -1
- package/dist/{errors-DpP_U6Bf.js → errors-Vpu6rKHl.js} +13 -10
- package/dist/{evaluate-B_oqFbWC.js → evaluate-BAmf_AQd.js} +153 -82
- package/dist/{evaluations-BCddEOfO.d.ts → evaluations-DOWuBpWv.d.ts} +11 -5
- package/dist/{evaluations-DReoiVBw.js → evaluations-IBceAeKT.js} +40 -19
- package/dist/eve/index.d.ts +9 -6
- package/dist/eve/index.js +4 -4
- package/dist/{event-time-CsegxXxB.js → event-time-BGy48400.js} +8 -4
- package/dist/{expiry-D4_YKRKD.js → expiry-6XByK0dm.js} +8 -5
- package/dist/express/index.d.ts +9 -6
- package/dist/express/index.js +9 -6
- package/dist/fastify/index.d.ts +16 -10
- package/dist/fastify/index.js +8 -5
- package/dist/{fetch-adapter-CuhyYwC1.d.ts → fetch-adapter-BIbBAtPZ.d.ts} +9 -6
- package/dist/{fetch-adapter-De-u6vhJ.js → fetch-adapter-dPTgJVHd.js} +14 -11
- package/dist/fields-D0vUI6dq.js +498 -0
- package/dist/{files-acUbNwWt.js → files-B3AA05f1.js} +8 -5
- package/dist/{files-D_JIzUrP.js → files-BSjrtIHw.js} +11 -4
- package/dist/{fixtures-BTMW6zgU.js → fixtures-A1_sp_tR.js} +15 -6
- package/dist/{flags-aaeRAdiD.js → flags-DXjoTVbS.js} +2 -2
- package/dist/{freeze-CrU8nQeX.js → freeze-jjan0lCv.js} +4 -1
- package/dist/{from-snapshot-Bz469dIh.js → from-snapshot-DCakWRsr.js} +18 -15
- package/dist/gen-BFfzZSLH.js +58 -0
- package/dist/gen-BtfFWGbz.js +827 -0
- package/dist/{generate-3FNO5P5Q.js → generate-CRVV5V7l.js} +14 -8
- package/dist/generate-CezbCaTI.js +275 -0
- package/dist/{grantee-BrRANrpT.js → grantee-Dke-9rd1.js} +4 -4
- package/dist/{grantee-conditions-C6P1Tvol.js → grantee-conditions-BrYPe-w0.js} +12 -12
- package/dist/{grantee-match-0RtHWQDx.js → grantee-match-7RZZvoT_.js} +12 -6
- package/dist/{graph-sql-B-dsAT6j.d.ts → graph-sql-BwFC4Qjs.d.ts} +3 -3
- package/dist/h3/index.d.ts +10 -7
- package/dist/h3/index.js +3 -3
- package/dist/headers-B9jQxjtW.d.ts +10 -0
- package/dist/{helpers-DY3vXuGs.js → helpers-DJicaG6f.js} +40 -28
- package/dist/hono/index.d.ts +16 -10
- package/dist/hono/index.js +5 -5
- package/dist/{hosted-XBgU6RGT.js → hosted-D0IzESu_.js} +42 -21
- package/dist/{hosted-BmjzxQhp.d.ts → hosted-DVxlLZMe.d.ts} +33 -21
- package/dist/{http-ujKm0JXE.js → http-DH94eh6f.js} +4 -4
- package/dist/{http-BBoKefeS.js → http-DKLXrFGk.js} +13 -7
- package/dist/{http-Ca3Sr5x1.js → http-DOL33cO0.js} +11 -8
- package/dist/{import-DB2EG_iy.js → import-ACkOrv6g.js} +6 -6
- package/dist/{import-Bz0GefWg.js → import-CST57XLp.js} +64 -51
- package/dist/{index-CMiPH2Tv.d.ts → index-BinlXeU-.d.ts} +64 -37
- package/dist/{index-BSfRl0hZ.d.ts → index-CV-7DWeD.d.ts} +64 -52
- package/dist/{index-BE8y3moU.d.ts → index-DJwEgYzA.d.ts} +127 -82
- package/dist/{index-DH9DUDEM.d.ts → index-Dj2qF9VC.d.ts} +54 -30
- package/dist/{index-BTkwrK7v.d.ts → index-vYjMrXyK.d.ts} +336 -173
- package/dist/{index-DLwcuCN_.d.ts → index-ymept53A.d.ts} +51 -30
- package/dist/index.d.ts +22 -22
- package/dist/index.js +34 -34
- package/dist/{init-B-4t1NzC.js → init-BjuFDYT1.js} +10 -10
- package/dist/{init-5TXNji88.js → init-txYTuW9u.js} +5 -5
- package/dist/{instance-options-CU0YQCLH.d.ts → instance-options-CoHn-0e8.d.ts} +4 -4
- package/dist/{instance-snapshot-CjcwnEiV.js → instance-snapshot-DuWf1cT3.js} +86 -61
- package/dist/{instant-BluqDvyS.js → instant-DK3Iz83e.js} +2 -2
- package/dist/{internals-Dk8A8fX3.js → internals-B3IgHrvo.js} +6 -3
- package/dist/{json-schema-B-vAwlde.js → json-schema-BPGa-RjQ.js} +9 -3
- package/dist/{json-schema-CN_iLFH2.d.ts → json-schema-BfXgnRNT.d.ts} +4 -4
- package/dist/jwt/index.d.ts +57 -27
- package/dist/jwt/index.js +24 -21
- package/dist/{kernel-DVExUwkp.js → kernel-qv4cr9w8.js} +32 -23
- package/dist/kysely/index.d.ts +49 -33
- package/dist/kysely/index.js +9 -7
- package/dist/{live-options-BaAFCIiu.js → live-options-BBIT68le.js} +2 -2
- package/dist/{load-DxroEzH1.js → load-DjSU5KXO.js} +6 -6
- package/dist/load-Dm0pSYH3.js +1 -0
- package/dist/{login-ClSJh5t5.js → login-CfImTJGb.js} +4 -4
- package/dist/{login-WC9HPJpU.js → login-CgfCTO3F.js} +16 -9
- package/dist/{manifest-Dv6q4i5s.js → manifest-B2QPh19C.js} +49 -38
- package/dist/{manifest-BVhExYhw.d.ts → manifest-CzzWtnAb.d.ts} +126 -31
- package/dist/{manifest-schema-Cv492Qev.js → manifest-schema-2r37XRhD.js} +44 -3
- package/dist/{manifest-B79YuF2T.js → manifest-wg8WkkpD.js} +6 -6
- package/dist/{map-claims-etGIS_Dv.js → map-claims-C-nv08_n.js} +16 -9
- package/dist/{map-error-BQGyDm_M.js → map-error-pasIGqMT.js} +7 -7
- package/dist/{markers-C6joDI3o.js → markers-BeHZ4x9Q.js} +20 -5
- package/dist/mcp/index.d.ts +114 -61
- package/dist/mcp/index.js +70 -40
- package/dist/{migrate-Dodel0IJ.js → migrate-B7oP_sQU.js} +35 -17
- package/dist/module-values-BJTBdo6y.js +107 -0
- package/dist/nest/index.d.ts +23 -13
- package/dist/nest/index.js +18 -11
- package/dist/next/client.d.ts +5 -2
- package/dist/next/client.js +1 -1
- package/dist/next/index.d.ts +79 -26
- package/dist/next/index.js +121 -10
- package/dist/next/plugin.d.ts +1 -1
- package/dist/next/plugin.js +4 -3
- package/dist/node/index.d.ts +5 -5
- package/dist/node/index.js +3 -3
- package/dist/{ocsf-BFp-PZZA.js → ocsf-TcjRBgIs.js} +15 -5
- package/dist/openai/index.d.ts +13 -7
- package/dist/openai/index.js +3 -3
- package/dist/openapi/index.d.ts +51 -30
- package/dist/openapi/index.js +2 -2
- package/dist/{openapi-ztVaux6j.js → openapi-BGeuunWC.js} +23 -14
- package/dist/{openapi-DMocl1bh.js → openapi-BIpw3Mb7.js} +4 -5
- package/dist/{openapi-Ddb4628T.js → openapi-BOsx0xn9.js} +33 -18
- package/dist/{operation-findings-kRcEp8lE.js → operation-findings-CXtFzlKJ.js} +3 -3
- package/dist/{operations-BNLes61x.d.ts → operations-Ci_rT6Uo.d.ts} +10 -7
- package/dist/orpc/index.d.ts +68 -14
- package/dist/orpc/index.js +62 -13
- package/dist/otel/index.d.ts +7 -4
- package/dist/otel/index.js +8 -5
- package/dist/{output-DgSDLrta.js → output-DV5dwOTs.js} +9 -5
- package/dist/output-files-BHOIlrfD.js +1 -0
- package/dist/{output-files-CCMdcFWb.js → output-files-BIQ_9pIs.js} +29 -17
- package/dist/ownership-DA5YdYTm.js +1059 -0
- package/dist/{parse-Ddhz2xf4.js → parse-1_ZheTW5.js} +16 -13
- package/dist/parse-local-manifest-CCmbhnxP.d.ts +10 -0
- package/dist/{parse-local-manifest-T1Q8X3A2.js → parse-local-manifest-DEiCF4ah.js} +19 -7
- package/dist/{parse-request-D_tUXG6M.js → parse-request-CwCZpyjV.js} +7 -8
- package/dist/{paths-DXSHAMIa.js → paths-CUvURzHp.js} +4 -1
- package/dist/pdp/index.d.ts +9 -6
- package/dist/pdp/index.js +20 -13
- package/dist/{peer-DOzzMfZL.js → peer-C9LvBCcb.js} +1 -1
- package/dist/{peer-12Q5I_RH.js → peer-Q0fuZ6hx.js} +9 -3
- package/dist/{permdock-BfWEeMqk.js → permdock-BvjivVb9.js} +200 -140
- package/dist/{permdock-Dco6dyCK.d.ts → permdock-CprAPN3w.d.ts} +260 -129
- package/dist/{permission-registry-DpPtSKNZ.js → permission-registry-B8tYxPIt.js} +23 -10
- package/dist/{permission-types-DhNEmoRG.d.ts → permission-types-CAY-GU7e.d.ts} +127 -41
- package/dist/{permissions-CoqCOfJ3.d.ts → permissions-Bx6UI8n1.d.ts} +6 -3
- package/dist/{permissions-CyH2MV_B.js → permissions-CVXmRILq.js} +3 -3
- package/dist/{permissions-DArULThq.js → permissions-CYcHj_w7.js} +8 -5
- package/dist/pg-DQTqRrou.js +60 -0
- package/dist/{pins-8ILTftC9.js → pins-nqarl3oE.js} +4 -1
- package/dist/{pkce-5h8NgMQJ.js → pkce-CnmmYqUZ.js} +1 -1
- package/dist/{policy-B7dg_yzu.d.ts → policy-BycVKnXv.d.ts} +5 -5
- package/dist/{policy-DaJy4nK4.js → policy-CLQ8__GF.js} +43 -23
- package/dist/{policy-from-catalog-DFWYkNdu.js → policy-from-catalog-CU3An8uP.js} +28 -25
- package/dist/{policy-module-CTlwMvLI.js → policy-module-xym9fnSq.js} +12 -6
- package/dist/{policy-types-B-F-qAZk.d.ts → policy-types-DGIO_gxq.d.ts} +782 -357
- package/dist/{postgres-store-BL9M_CA1.js → postgres-store-DcyrPS-r.js} +43 -16
- package/dist/{postgrest-r5faDIzD.js → postgrest-5Dr3W64L.js} +84 -86
- package/dist/{postgrest-CYacM_u7.d.ts → postgrest-D5nUGm-c.d.ts} +55 -35
- package/dist/powersync-B701tvhE.js +1 -0
- package/dist/{powersync-13odBwiM.js → powersync-Bg8u-JcR.js} +3 -3
- package/dist/{powersync-53ryOZip.js → powersync-CJrT1DSc.js} +127 -69
- package/dist/preset/index.d.ts +38 -28
- package/dist/preset/index.js +1 -1
- package/dist/{preset-CHTbd-DQ.js → preset-BjLzeFpp.js} +56 -32
- package/dist/{principal-source-pHneukrx.js → principal-source-C6N60GtM.js} +10 -10
- package/dist/prisma/index.d.ts +69 -41
- package/dist/prisma/index.js +21 -17
- package/dist/{problem-CTviyH5L.js → problem-BVLHFK33.js} +41 -21
- package/dist/{problem-details-cn5X30gZ.js → problem-details-CLDgX1KV.js} +13 -4
- package/dist/{problem-types-CJ2325SZ.js → problem-types-DSsRfONQ.js} +4 -1
- package/dist/{prompt-DwtVemER.js → prompt-BYc6drYW.js} +4 -1
- package/dist/protected-action-D8x73IGm.d.ts +58 -0
- package/dist/protected-action-DUYqb-Ma.js +80 -0
- package/dist/{protected-DXE3cQYg.js → protected-action-QEA8arRB.js} +48 -14
- package/dist/{provider-BQsTYYy0.js → provider-C55OGXJ7.js} +5 -4
- package/dist/{provider-Csk-THAn.d.ts → provider-DfLeek9O.d.ts} +1 -1
- package/dist/{provider-store-IgqQipCO.js → provider-store-CaTv00tr.js} +13 -9
- package/dist/{pull-CN5OLxrF.js → pull-2nJr0qg_.js} +12 -11
- package/dist/pull-C3EEGzSw.js +1 -0
- package/dist/{push-tVdG8dUL.js → push-Bn-lMEmI.js} +19 -13
- package/dist/{pushed-policy-CmYeSQqq.js → pushed-policy-CDuOL2de.js} +10 -7
- package/dist/{pushed-policy-BbcY9r_4.d.ts → pushed-policy-CryQheKq.d.ts} +12 -6
- package/dist/react/index.d.ts +9 -8
- package/dist/react/index.js +7 -6
- package/dist/react/provider-client.d.ts +1 -1
- package/dist/react/provider-client.js +1 -1
- package/dist/react-native/index.d.ts +94 -55
- package/dist/react-native/index.js +200 -61
- package/dist/{refs-CNJBiTFo.js → refs-C8BKxc_e.js} +2 -2
- package/dist/{relation-walk-3OyDBF0S.js → relation-walk-DK_gkgL7.js} +12 -9
- package/dist/{relations-BnCWnJGI.js → relations-BxvRvDHK.js} +3 -3
- package/dist/{replay-Du1tJjG7.js → replay-BU09ad4L.js} +1 -1
- package/dist/{replay-DCDD_ZfL.d.ts → replay-Bs9Df2fQ.d.ts} +1 -1
- package/dist/{request-context-BykKLmyE.js → request-context-Duzdf0cd.js} +8 -8
- package/dist/{request-schema-CMreVuFM.js → request-schema-DhX7UbfQ.js} +4 -1
- package/dist/resend/index.d.ts +34 -28
- package/dist/resend/index.js +29 -29
- package/dist/resolve-names-ConCSj1y.js +201 -0
- package/dist/{resource-relations-D_jw0BFx.js → resource-relations-8-pCScBO.js} +18 -9
- package/dist/{retire-Wj6dkyDE.js → retire-B2xffQgY.js} +15 -6
- package/dist/{revocations-R07lFBnX.d.ts → revocations-BaUXHM1N.d.ts} +6 -3
- package/dist/{rls-Ck_PocSp.js → rls-Ba9wN0SP.js} +13 -6
- package/dist/{rls-CxBZb4rZ.js → rls-Cx0dtsB7.js} +310 -128
- package/dist/{role-builder-C1VJzvcr.js → role-builder-BK2-T6oD.js} +41 -20
- package/dist/{row-conditions-h2HythXQ.js → row-conditions-BAGHOmVq.js} +4 -3
- package/dist/{rpc-Bk1bE-ch.js → rpc-vHIwyXCp.js} +8 -5
- package/dist/run-Ck22anC2.js +1 -0
- package/dist/{run-uLD2aWuO.js → run-PbRlXTfh.js} +26 -23
- package/dist/{run-ticket-BpNi7BCi.d.ts → run-ticket-B2o2Kxz8.d.ts} +29 -14
- package/dist/{run-ticket-B5d_63Ma.js → run-ticket-Dv7aF7Dk.js} +9 -9
- package/dist/{runtime-Vif3_-zf.js → runtime-BGnrOkVH.js} +5 -2
- package/dist/{saas-Az_Kz-4D.js → saas-DK4V-3Is.js} +42 -29
- package/dist/{scan-DSljDE1Y.js → scan-CRTj6fke.js} +1 -1
- package/dist/{schema-B4v0Qrac.js → schema-BOJjqlWL.js} +3 -2
- package/dist/{schema-gIcCx7zM.js → schema-BTsE1WRT.js} +8 -4
- package/dist/scim/index.d.ts +2 -2
- package/dist/scim/index.js +2 -2
- package/dist/{scim-C7JYhySg.js → scim-D8YupzX1.js} +2 -2
- package/dist/{scim-YNieBO1U.js → scim-jJBJ7g1Z.js} +33 -15
- package/dist/{scopes-BHsc-wp-.js → scopes-0Up_UA2t.js} +41 -23
- package/dist/server/index.d.ts +11 -11
- package/dist/server/index.js +12 -12
- package/dist/{server-Bnga6I50.js → server-3cVlTLde.js} +31 -31
- package/dist/{server-types-C4gZUEZy.d.ts → server-types-CyRN0-Cd.d.ts} +88 -46
- package/dist/{sha256-D9ihqmvd.js → sha256-C-4WXKIu.js} +4 -3
- package/dist/{shared-fMKOv8hP.js → shared-Afctg7B0.js} +65 -32
- package/dist/{shared-C8LjUdVU.js → shared-l0oGGetg.js} +9 -6
- package/dist/{signals-D3NcTKUS.js → signals-B1vHR3fN.js} +2 -2
- package/dist/{sink-Cp_Eot9W.d.ts → sink-B5zoUW_O.d.ts} +44 -20
- package/dist/{sink-BEZSlMS_.js → sink-D9_vh372.js} +32 -21
- package/dist/{skills-g_3BS9NC.js → skills-C9uKfSF5.js} +3 -3
- package/dist/{skills-Dcjw9_1C.js → skills-CQQcuGBi.js} +12 -8
- package/dist/{snapshot-CbGmYiJx.js → snapshot-CXlzi69u.js} +21 -18
- package/dist/{snapshot-cache-Pahd3IYJ.d.ts → snapshot-cache-BjAWkchD.d.ts} +21 -12
- package/dist/{snapshot-cache-DT2Kx1F8.js → snapshot-cache-Bx_4xC_6.js} +14 -11
- package/dist/solid/index.d.ts +55 -16
- package/dist/solid/index.js +46 -12
- package/dist/solid-start/index.d.ts +30 -12
- package/dist/solid-start/index.js +3 -3
- package/dist/{sources-B-zYB4GS.js → sources-CMAM-2A3.js} +46 -27
- package/dist/{sources-DEEuGb8S.d.ts → sources-CWG32C0G.d.ts} +126 -53
- package/dist/{sql-B96movIM.js → sql-0WjxIp9g.js} +28 -7
- package/dist/{sql-CDEPCA0g.d.ts → sql-B80DFdpG.d.ts} +2 -2
- package/dist/{src-DLFrtrrC.js → src-C_pi2Rnh.js} +292 -101
- package/dist/ssf/index.d.ts +3 -3
- package/dist/ssf/index.js +47 -35
- package/dist/{standard-webhooks-DgFFD-Ga.js → standard-webhooks-D67a3nzk.js} +5 -5
- package/dist/{standard-webhooks-B_qRg0ws.d.ts → standard-webhooks-DOYEuOLx.d.ts} +7 -7
- package/dist/{store-DSP9oGvh.js → store-RNFvaJJv.js} +32 -26
- package/dist/{store-options-B_poyYvg.js → store-options-Dil3lraY.js} +105 -15
- package/dist/stores-DZJvxFIZ.d.ts +59 -0
- package/dist/{stores-BqEuHC05.js → stores-DxZWDXCs.js} +42 -5
- package/dist/{stream-2Vwhl7Er.d.ts → stream-9y9qw51m.d.ts} +4 -3
- package/dist/{stream-CvdUS9V1.js → stream-CDvF0sJm.js} +5 -5
- package/dist/{style-Ds1gNm77.js → style-DblOtSga.js} +1 -1
- package/dist/{style-Cqo7-73x.js → style-Ds11Hmk4.js} +2 -1
- package/dist/{subject-settings-CkEwrw3W.js → subject-settings-8sH5HlII.js} +8 -4
- package/dist/{row-check-Dt35czLy.d.ts → subject-settings-vNW8qmUH.d.ts} +30 -18
- package/dist/supabase/index.d.ts +48 -38
- package/dist/supabase/index.js +5 -5
- package/dist/supabase/middleware.d.ts +19 -13
- package/dist/supabase/middleware.js +7 -7
- package/dist/{supabase--0aJdLEd.js → supabase-DnMMg5Fn.js} +79 -35
- package/dist/{supabase-Bqp7iIY2.js → supabase-SBs3MYUE.js} +3 -3
- package/dist/supabase-hook-C0FyEACZ.js +1 -0
- package/dist/{supabase-hook-Dg0SrQWR.js → supabase-hook-CrgU06WH.js} +175 -196
- package/dist/{supautils-MESd81bF.js → supautils-ByezN3b8.js} +385 -219
- package/dist/{support-session-Cna49-3f.js → support-session-BsmPCbz8.js} +21 -21
- package/dist/svelte/PermissionBoundary.svelte +2 -6
- package/dist/svelte/Protected.svelte +2 -8
- package/dist/svelte/index.d.ts +9 -8
- package/dist/svelte/index.js +10 -9
- package/dist/svelte/runtime.d.ts +4 -4
- package/dist/svelte/runtime.js +4 -4
- package/dist/svelte/source.d.ts +9 -8
- package/dist/svelte/source.js +6 -5
- package/dist/sveltekit/index.d.ts +30 -12
- package/dist/sveltekit/index.js +2 -2
- package/dist/{ownership-Z2LpxsGa.js → tables-BqrxBCir.js} +641 -1104
- package/dist/tanstack-start/index.d.ts +22 -10
- package/dist/tanstack-start/index.js +2 -2
- package/dist/{target-Bw37TFNA.js → target-qdEAnnhU.js} +6 -6
- package/dist/{tenancy-CmeBQ6Nv.js → tenancy-5d1zVBvK.js} +25 -19
- package/dist/terminal/index.d.ts +23 -14
- package/dist/terminal/index.js +17 -20
- package/dist/testing/core.d.ts +1 -1
- package/dist/testing/core.js +1 -1
- package/dist/testing/fixtures/index.d.ts +8 -5
- package/dist/testing/fixtures/index.js +78 -17
- package/dist/testing/index.d.ts +225 -141
- package/dist/testing/index.js +352 -234
- package/dist/testing/saas/index.d.ts +43 -27
- 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/{text-diff-DhITNCnD.js → text-diff-BtfSmdUo.js} +2 -2
- package/dist/{thenable-yD7SabqG.js → thenable-BNSM1U2R.js} +12 -3
- package/dist/{time-DkWjdL98.js → time-nR1JesoH.js} +32 -8
- package/dist/{token-2qYDvXz2.js → token-DC9EQiet.js} +14 -12
- package/dist/{tool-refusal-reAhIzdl.js → tool-refusal-Qpjs_W6M.js} +5 -2
- package/dist/trpc/index.d.ts +11 -8
- package/dist/trpc/index.js +15 -9
- package/dist/type-helpers-c7Xo_2Cu.d.ts +50 -0
- package/dist/{types-CfiKC5aN.d.ts → types-B2efzoSX.d.ts} +14 -11
- package/dist/{types-CIeZcG8v.d.ts → types-B6ExllNo.d.ts} +2 -2
- package/dist/{types-DBHftjgS.d.ts → types-BB-zWDcR.d.ts} +45 -33
- package/dist/{types-BfVmNJO5.d.ts → types-BMVDHvI0.d.ts} +128 -50
- package/dist/{types-DXmwu78Z.d.ts → types-CEinc15V.d.ts} +31 -14
- package/dist/{types-g7Oy6Zg4.d.ts → types-CN0LsqbK.d.ts} +47 -24
- package/dist/{types-CeIscIKp.d.ts → types-CWBsAwqn.d.ts} +23 -12
- package/dist/{types-DqzsnlSA.js → types-CcUXciSj.js} +17 -5
- package/dist/{types-BWZybqs9.d.ts → types-CzOeVvcC.d.ts} +384 -203
- package/dist/{types-DC44-hqb.d.ts → types-DLvhVm1r.d.ts} +59 -32
- package/dist/{types-D3A19w4A.d.ts → types-DlelvQk4.d.ts} +22 -13
- package/dist/{types-cTos-H7p.d.ts → types-DsHGPtkR.d.ts} +68 -32
- package/dist/{types-BXMYB7BY.d.ts → types-ZzRGoViD.d.ts} +77 -24
- package/dist/{types-CQVEQawv.d.ts → types-rCRV4Ge-.d.ts} +24 -14
- package/dist/types-tQB2CEnY.d.ts +262 -0
- package/dist/unplugin/index.d.ts +1 -1
- package/dist/unplugin/index.js +2 -2
- package/dist/usage-0hjZPIRX.js +1 -0
- package/dist/{usage-Bybmck7f.js → usage-B9EtHWLa.js} +50 -26
- package/dist/{usage-CDaLXCfL.js → usage-CBzgwfIs.js} +2 -2
- package/dist/{validation-error-ZfUHbKvf.js → validation-error-CYg2kJEw.js} +4 -1
- package/dist/{validation-error-CQpoquwj.d.ts → validation-error-uvp-kyfO.d.ts} +5 -2
- package/dist/{validity-CZ7-y0Cj.js → validity-Buc7w8E9.js} +13 -10
- package/dist/{verifier-DHuh-okk.js → verifier-DUV6pLqZ.js} +10 -4
- package/dist/{verify-pe8rL_Qw.js → verify-DlUcTDBz.js} +148 -487
- package/dist/version-DMQ0dnN5.js +48 -0
- package/dist/version-DizhmD72.js +1 -0
- package/dist/{views-BB8E9dTP.js → views-CD8wuL4Z.js} +19 -6
- package/dist/{vocabulary-Bg3eeT2H.d.ts → vocabulary-DEJ5j4mR.d.ts} +7 -4
- package/dist/vue/index.d.ts +71 -22
- package/dist/vue/index.js +50 -13
- package/dist/{waiter-DwEyouan.d.ts → waiter-CqUKX6CY.d.ts} +13 -10
- package/dist/{waiter-BGUtGYoU.js → waiter-aBLM63_f.js} +1 -1
- package/dist/{watch-C-4VmFlL.js → watch-BFDKqmUa.js} +8 -8
- package/dist/watch-ClLuO2TL.js +1 -0
- package/dist/webmcp/index.d.ts +11 -11
- package/dist/webmcp/index.js +8 -5
- package/dist/{where-scope-wq2coopv.js → where-scope-DlCdCM_8.js} +24 -18
- package/dist/{who-can-BwNsI_Js.js → who-can-BoDJm0Nc.js} +23 -20
- package/dist/workflow/index.d.ts +3 -3
- package/dist/workflow/index.js +13 -13
- package/dist/workflow-sdk/index.d.ts +19 -13
- package/dist/workflow-sdk/index.js +6 -6
- package/dist/{wrap-CiSc_KCq.js → wrap-B2wziJI_.js} +4 -4
- package/dist/{wrap-B6R0cMRL.d.ts → wrap-DxXB54Wu.d.ts} +8 -5
- package/package.json +8 -8
- package/schemas/catalog-v1.json +3 -0
- package/schemas/supabase-manifest-v1.json +33 -1
- package/skills/permdock-credentials/references/tokens-keys-links.md +8 -6
- package/skills/permdock-data/references/queries-and-rls.md +2 -1
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +2 -2
- package/skills/permdock-wire/references/adapters.md +16 -23
- package/dist/catalog-BCCjSAdH.js +0 -1
- package/dist/collect-k_Dulxr5.js +0 -1
- package/dist/config-CoQHDrDi.js +0 -166
- package/dist/denied-text-D4qkEtFz.d.ts +0 -19
- package/dist/fields-ClcQLrVc.js +0 -238
- package/dist/generate-CNU1pIOo.js +0 -171
- package/dist/headers-BIjfMaoC.js +0 -8
- package/dist/headers-CIbDTUTK.d.ts +0 -7
- package/dist/load-DrMHXzgN.js +0 -1
- package/dist/output-files-DPAY7-GX.js +0 -1
- package/dist/package-root-Dk_ETdkp.js +0 -31
- package/dist/parse-local-manifest-e4mdwAKd.d.ts +0 -10
- package/dist/policies-B2lZIurj.js +0 -295
- package/dist/powersync-CExtTLyA.js +0 -1
- package/dist/problem-details-Tcfmj3bV.d.ts +0 -7
- package/dist/protected-BwZYL1X_.d.ts +0 -39
- package/dist/pull-Cty6Ovyu.js +0 -1
- package/dist/run-Bz7DXGEv.js +0 -1
- package/dist/stores-BAZwSYZA.d.ts +0 -31
- package/dist/supabase-hook-DJxC4PoP.js +0 -1
- package/dist/types-CKV71kKh.d.ts +0 -172
- package/dist/usage-y-kBNdqs.js +0 -1
- package/dist/version-CEbQ5UeM.js +0 -18
- package/dist/version-DXkYUISx.js +0 -1
- package/dist/watch-Bd9mx3rd.js +0 -1
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
import { t as compact } from "./compact-CAf557ZB.js";
|
|
2
|
-
import { c as listPermissions, u as renamedKeys } from "./permission-registry-
|
|
3
|
-
import { i as dateAt } from "./time-
|
|
4
|
-
import { p as scopeField } from "./tenancy-
|
|
5
|
-
import { a as describeError, i as configError, o as exitCodeOfError, u as usageResult } from "./errors-
|
|
6
|
-
import { t as policyRowConditionKeys } from "./row-conditions-
|
|
7
|
-
import { o as sqlFiles } from "./files-
|
|
8
|
-
import { c as requirePolicy } from "./load-
|
|
9
|
-
import { i as qualifySqlTable, r as escapeSqlIdent } from "./sql-
|
|
10
|
-
import "./sources-
|
|
11
|
-
import { t as policyFromCatalog } from "./policy-from-catalog-
|
|
2
|
+
import { c as listPermissions, u as renamedKeys } from "./permission-registry-B8tYxPIt.js";
|
|
3
|
+
import { i as dateAt } from "./time-nR1JesoH.js";
|
|
4
|
+
import { p as scopeField } from "./tenancy-5d1zVBvK.js";
|
|
5
|
+
import { a as describeError, i as configError, o as exitCodeOfError, u as usageResult } from "./errors-Vpu6rKHl.js";
|
|
6
|
+
import { t as policyRowConditionKeys } from "./row-conditions-BAGHOmVq.js";
|
|
7
|
+
import { o as sqlFiles } from "./files-BSjrtIHw.js";
|
|
8
|
+
import { c as requirePolicy } from "./load-DjSU5KXO.js";
|
|
9
|
+
import { i as qualifySqlTable, r as escapeSqlIdent } from "./sql-0WjxIp9g.js";
|
|
10
|
+
import "./sources-CMAM-2A3.js";
|
|
11
|
+
import { t as policyFromCatalog } from "./policy-from-catalog-CU3An8uP.js";
|
|
12
12
|
import { t as beforeFirst } from "./text-BMFRfBqc.js";
|
|
13
|
-
import { i as INDEXES_MARKER, n as GRANTS_MARKER, o as SEEDS_MARKER, t as BACKFILL_MARKER } from "./markers-
|
|
14
|
-
import {
|
|
15
|
-
import { t as
|
|
16
|
-
import { t as
|
|
13
|
+
import { i as INDEXES_MARKER, n as GRANTS_MARKER, o as SEEDS_MARKER, t as BACKFILL_MARKER } from "./markers-BeHZ4x9Q.js";
|
|
14
|
+
import { a as nonEmptyOr } from "./output-DV5dwOTs.js";
|
|
15
|
+
import { i as requirePeer, n as packageManagerOf, t as addLine } from "./peer-Q0fuZ6hx.js";
|
|
16
|
+
import { t as POLICY_NOT_PUBLISHED } from "./problem-types-DSsRfONQ.js";
|
|
17
|
+
import { t as fetchProjectPolicy } from "./pull-2nJr0qg_.js";
|
|
17
18
|
import { n as MIGRATION_DIRS } from "./constants-DcJABbLW.js";
|
|
18
|
-
import { a as isSeedsDirectory, c as parseSplit, d as seedsMigration, f as writeOutputFiles, l as partPath, n as dataMigrationFile, r as driftOf, u as pgDeltaPath } from "./output-files-
|
|
19
|
-
import {
|
|
20
|
-
import { A as quoteQualified, D as qualified$1,
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { a as
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { a as
|
|
19
|
+
import { a as isSeedsDirectory, c as parseSplit, d as seedsMigration, f as writeOutputFiles, l as partPath, n as dataMigrationFile, r as driftOf, u as pgDeltaPath } from "./output-files-BIQ_9pIs.js";
|
|
20
|
+
import { d as schemasRefusal, f as declarativeSql, l as isSupabaseSchemas, o as supabaseHookSql, s as approvalsSql, t as grantsLabel, u as resolveSchemas, v as parseRbacAuthorize, y as rbacScaffold } from "./supabase-hook-CrgU06WH.js";
|
|
21
|
+
import { A as quoteQualified, D as qualified$1, I as scopeTypeOf, O as quoteIdent$1, _ as subjectClaimJsonSql, c as SESSION_LIVE_HELPER, g as sessionLiveHelperSql, j as quoteTable, k as quoteLiteral, r as HELPERS, t as CUSTOM_ROLES, y as subjectIdSql } from "./shared-Afctg7B0.js";
|
|
22
|
+
import { C as accessSql, G as byKey, T as seedSql, Z as graphHelper, ct as memberIdsHelper, ft as permittedIdsHelper, ht as scopeTable, mt as scopeSources, r as tableNames, s as graphSql, w as helpersSql, x as permittedByPermissionHelper, y as permissionHelpersSql } from "./tables-BqrxBCir.js";
|
|
23
|
+
import { c as breakGlassKey, i as assignmentSql, l as collectGrants, n as ownershipSql, s as breakGlassHolder } from "./ownership-DA5YdYTm.js";
|
|
24
|
+
import { a as splitUndiffed } from "./deciding-columns-NB4wcyBf.js";
|
|
25
|
+
import { t as connectPgPool } from "./pg-DQTqRrou.js";
|
|
26
|
+
import { n as permissionHoldersSql } from "./resolve-names-ConCSj1y.js";
|
|
27
|
+
import { a as fieldViewsSql, c as ACTOR_MAY_WRITE, f as readOnlyActorKinds, i as fieldViews, l as actorMayWriteSql, n as columnGrantSql, o as rowBranches, p as readOnlyActorPolicies, r as columnRevokeSql, u as assemblePolicies } from "./fields-D0vUI6dq.js";
|
|
28
|
+
import { _ as indexTargets, a as verifyResult, b as readTableIndexFacts, c as callsHelper, g as INDEX_COLUMNS_SQL, h as COLUMNS_SQL, i as verifyIgnores, l as helperCallKeys, m as tableFor, n as runRlsVerify, o as HELPER_TABLES, p as compileGrants, r as rlsFinding, v as indexesSql, y as pruneIndexTargets } from "./verify-DlUcTDBz.js";
|
|
29
|
+
import { a as buildContext, c as levelKeys, d as rebuildPlan, i as splitsPart, l as rowHelpersSql, n as generateOptions, o as CANDIDATES, r as isRefusal, s as inheritTargets, t as supautilsRejections, u as DROPPED_LIST } from "./supautils-ByezN3b8.js";
|
|
27
30
|
import { readFileSync } from "node:fs";
|
|
28
31
|
import { basename, delimiter, join } from "node:path";
|
|
29
32
|
import { spawn } from "node:child_process";
|
|
@@ -136,7 +139,7 @@ async function runRlsAdvisors(input) {
|
|
|
136
139
|
const message = [text(error, "message"), text(error, "suggestion")].filter((part) => part !== "").join(" ");
|
|
137
140
|
return {
|
|
138
141
|
code: 2,
|
|
139
|
-
output: `supabase db advisors failed: ${message === "" ? result.stderr.trim()
|
|
142
|
+
output: `supabase db advisors failed: ${message === "" ? nonEmptyOr(result.stderr.trim(), `exit ${String(result.status)}`) : message}`
|
|
140
143
|
};
|
|
141
144
|
}
|
|
142
145
|
const failing = findings.filter((finding) => finding.level === "WARN" || finding.level === "ERROR");
|
|
@@ -161,8 +164,8 @@ async function runRlsAdvisors(input) {
|
|
|
161
164
|
//#endregion
|
|
162
165
|
//#region src/cli/rls/bindings.ts
|
|
163
166
|
/**
|
|
164
|
-
* The table each resource with row policies binds to. With `helpersOnly`,
|
|
165
|
-
*
|
|
167
|
+
* The table each resource with row policies binds to. With `helpersOnly`, a
|
|
168
|
+
* resource `rls.tables` does not name has no table and no binding.
|
|
166
169
|
*/
|
|
167
170
|
function tableBindings(resources, tables, helpersOnly) {
|
|
168
171
|
const out = [];
|
|
@@ -177,16 +180,19 @@ function tableBindings(resources, tables, helpersOnly) {
|
|
|
177
180
|
}
|
|
178
181
|
return out;
|
|
179
182
|
}
|
|
180
|
-
/**
|
|
183
|
+
/**
|
|
184
|
+
* The generate notes for `bindings`: the inferred ones, and where to see them
|
|
185
|
+
* all.
|
|
186
|
+
*/
|
|
181
187
|
function bindingNotes(bindings, withDatabase) {
|
|
182
188
|
const inferred = bindings.filter((binding) => binding.inferred);
|
|
183
189
|
if (inferred.length === 0) return [];
|
|
184
190
|
return [`table bindings (no rls.tables entry, so the table is named after the resource): ${inferred.map((binding) => `${binding.resource} -> ${binding.table}`).join(", ")}${withDatabase ? "" : "; run permdock rls explain, or generate with --db-url-stdin, to check each table exists"}`];
|
|
185
191
|
}
|
|
186
192
|
/**
|
|
187
|
-
* The generate notes for the bindings whose table no project SQL file
|
|
188
|
-
*
|
|
189
|
-
*
|
|
193
|
+
* The generate notes for the bindings whose table no project SQL file creates.
|
|
194
|
+
* A project with no `create table` in those files gets none: its schema lives
|
|
195
|
+
* elsewhere (an ORM, another repository).
|
|
190
196
|
*/
|
|
191
197
|
function unknownTableNotes(bindings, created) {
|
|
192
198
|
if (created.size === 0) return [];
|
|
@@ -205,6 +211,7 @@ function unquote(name) {
|
|
|
205
211
|
function reasonOf(name) {
|
|
206
212
|
if (name === "permdock_custom_role_name_guard") return "customRoleWrites.roles: a tenant role cannot take a declared or shared role's name";
|
|
207
213
|
if (name === "permdock_custom_role_cascade") return "customRoleWrites.roles: a rename or delete of a role carries its grants";
|
|
214
|
+
if (name.startsWith("permdock_sync_custom_role_guard")) return "customRoles.from.sync: a signed-in caller writes only entries they may hand out";
|
|
208
215
|
if (name.startsWith("permdock_sync_custom_role")) return "customRoles.from.sync: each write to the legacy table rebuilds the role's grants";
|
|
209
216
|
if (name.startsWith("permdock_holders") || name.startsWith("permdock_transfer_only")) return "ownershipTriggers; set rls.ownershipTriggers.<scope>: false to skip";
|
|
210
217
|
if (name === "permdock_assignment") return "assignments: a role assignment is checked against the caller's own roles";
|
|
@@ -351,7 +358,10 @@ function splitRefusal(mode, plan) {
|
|
|
351
358
|
default: return mode;
|
|
352
359
|
}
|
|
353
360
|
}
|
|
354
|
-
/**
|
|
361
|
+
/**
|
|
362
|
+
* The files `generate` writes: one, or one per `--split` part, plus the hook's
|
|
363
|
+
* grants under migra.
|
|
364
|
+
*/
|
|
355
365
|
function outputFiles(plan) {
|
|
356
366
|
const { input } = plan;
|
|
357
367
|
const split = parseSplit(input.split);
|
|
@@ -481,12 +491,11 @@ function outputFiles(plan) {
|
|
|
481
491
|
//#endregion
|
|
482
492
|
//#region src/cli/rls/backfill.ts
|
|
483
493
|
/**
|
|
484
|
-
* The `--backfill-out` migration: every custom role in the application's
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
* nothing, so a role edited after the copy keeps its edits.
|
|
494
|
+
* The `--backfill-out` migration: every custom role in the application's roles
|
|
495
|
+
* table that has no rows in `custom_role_permissions` or `custom_role_includes`
|
|
496
|
+
* yet is saved through `permdock_trusted_replace_custom_role_grants`, with the
|
|
497
|
+
* entries PermDock cannot hold left out and listed in one warning. Running it
|
|
498
|
+
* again copies nothing, so a role edited after the copy keeps its edits.
|
|
490
499
|
*/
|
|
491
500
|
function backfillSql(ctx, from, migrate) {
|
|
492
501
|
const plan = rebuildPlan(ctx, from, migrate);
|
|
@@ -542,7 +551,10 @@ $permdock$;
|
|
|
542
551
|
}
|
|
543
552
|
//#endregion
|
|
544
553
|
//#region src/cli/rls/break-glass.ts
|
|
545
|
-
/**
|
|
554
|
+
/**
|
|
555
|
+
* The audit table every generated break-glass read writes to. Part of the SQL
|
|
556
|
+
* contract.
|
|
557
|
+
*/
|
|
546
558
|
const BREAK_GLASS_AUDIT = "permdock_break_glass_audit";
|
|
547
559
|
const IDENT$2 = /^[a-z][a-z0-9_]*$/u;
|
|
548
560
|
/**
|
|
@@ -583,10 +595,10 @@ function breakGlassEntries(policy, tables) {
|
|
|
583
595
|
}));
|
|
584
596
|
}
|
|
585
597
|
/**
|
|
586
|
-
* Rows the subject's roles reach for `p_permission`: a break-glass grant
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
*
|
|
598
|
+
* Rows the subject's roles reach for `p_permission`: a break-glass grant lifts
|
|
599
|
+
* denies, never the tenant boundary. A grant to no role reads the rows of the
|
|
600
|
+
* root scopes the subject is a member of, or every row when the policy declares
|
|
601
|
+
* no scopes.
|
|
590
602
|
*/
|
|
591
603
|
function rowsFilter(ctx, entry) {
|
|
592
604
|
const arms = entry.grants.flatMap((grant) => {
|
|
@@ -661,12 +673,12 @@ revoke execute on function ${fn}(text) from public, anon;
|
|
|
661
673
|
grant execute on function ${fn}(text) to authenticated;`;
|
|
662
674
|
}
|
|
663
675
|
/**
|
|
664
|
-
* The `security definer` read path for every `breakGlass` grant: an audit
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
676
|
+
* The `security definer` read path for every `breakGlass` grant: an audit table
|
|
677
|
+
* and one `permdock_break_glass_<resource>(permission)` per resource that
|
|
678
|
+
* checks a signed break-glass session, writes an audit row and returns the rows
|
|
679
|
+
* in the scope instances where the subject holds a role with the break-glass
|
|
680
|
+
* grant (bypassing the table's policies as the definer). Empty when the policy
|
|
681
|
+
* has no break-glass grant.
|
|
670
682
|
*/
|
|
671
683
|
function breakGlassSql(ctx, entries) {
|
|
672
684
|
if (entries.length === 0) return "";
|
|
@@ -677,7 +689,7 @@ function breakGlassSql(ctx, entries) {
|
|
|
677
689
|
const HEADER = "-- generated by permdock rls generate\n-- fail-closed: never target a bypass role\n";
|
|
678
690
|
const TRUSTED_READER_GRANT = /^grant usage on schema "[^"\n]+" to [^\n;]+;\ngrant execute on function [^\n]+\.permdock_trusted_role_permissions(?:_by_id)?\([^)\n]*\) to [^\n;]+;$/gmu;
|
|
679
691
|
function assertNoServiceRole(text) {
|
|
680
|
-
if (/\bservice_role\b/iu.test(text.
|
|
692
|
+
if (/\bservice_role\b/iu.test(text.replaceAll(TRUSTED_READER_GRANT, ""))) throw new Error("PermDock CLI: generated RLS must never emit service_role");
|
|
681
693
|
}
|
|
682
694
|
function assertSupautilsSafe(text) {
|
|
683
695
|
const [first] = supautilsRejections(text);
|
|
@@ -685,8 +697,8 @@ function assertSupautilsSafe(text) {
|
|
|
685
697
|
}
|
|
686
698
|
/**
|
|
687
699
|
* Neon's Data API and `pg_session_jwt` name the anonymous role `anonymous`;
|
|
688
|
-
* Supabase, PostgREST and the GUC pattern use `anon`. Role lists end a line
|
|
689
|
-
*
|
|
700
|
+
* Supabase, PostgREST and the GUC pattern use `anon`. Role lists end a line or
|
|
701
|
+
* a statement after `to` or `from`, so only those are renamed.
|
|
690
702
|
*/
|
|
691
703
|
function dialectRoles(text, dialect) {
|
|
692
704
|
if (dialect !== "neon") return text;
|
|
@@ -695,7 +707,10 @@ function dialectRoles(text, dialect) {
|
|
|
695
707
|
function tablesOf(policies) {
|
|
696
708
|
return [...new Set(policies.map((item) => item.table))];
|
|
697
709
|
}
|
|
698
|
-
/**
|
|
710
|
+
/**
|
|
711
|
+
* Enable (and force) row level security, then the table grants for the commands
|
|
712
|
+
* a policy allows.
|
|
713
|
+
*/
|
|
699
714
|
function tableSql(table, policies, force, views) {
|
|
700
715
|
const closed = views.find((view) => view.table === table && view.companion !== void 0);
|
|
701
716
|
const target = quoteQualified(table);
|
|
@@ -716,7 +731,10 @@ function tableSql(table, policies, force, views) {
|
|
|
716
731
|
if (closed !== void 0) lines.push(columnRevokeSql(closed));
|
|
717
732
|
return lines.join("\n");
|
|
718
733
|
}
|
|
719
|
-
/**
|
|
734
|
+
/**
|
|
735
|
+
* `drop policy if exists` and `create policy` for one policy, without the
|
|
736
|
+
* table's grants.
|
|
737
|
+
*/
|
|
720
738
|
function policySql(item) {
|
|
721
739
|
const target = quoteQualified(item.table);
|
|
722
740
|
const lines = [
|
|
@@ -743,8 +761,9 @@ function emitSql(policies, preamble, force = false, views = []) {
|
|
|
743
761
|
return text;
|
|
744
762
|
}
|
|
745
763
|
/**
|
|
746
|
-
* The SQL a Drizzle or Prisma schema cannot declare: helpers, grants, `force`
|
|
747
|
-
* `rls generate` writes it next to `out` for a custom
|
|
764
|
+
* The SQL a Drizzle or Prisma schema cannot declare: helpers, grants, `force`
|
|
765
|
+
* and field views. `rls generate` writes it next to `out` for a custom
|
|
766
|
+
* migration.
|
|
748
767
|
*/
|
|
749
768
|
function migrationSql(policies, preamble, force, views) {
|
|
750
769
|
const parts = [
|
|
@@ -762,7 +781,7 @@ function helpersNote(helpers, how) {
|
|
|
762
781
|
return helpers === void 0 ? [] : [`// run ${helpers} ${how}`];
|
|
763
782
|
}
|
|
764
783
|
function camelCase(name) {
|
|
765
|
-
return name.
|
|
784
|
+
return name.replaceAll(/[_-]+([a-z0-9])/giu, (_, char) => char.toUpperCase());
|
|
766
785
|
}
|
|
767
786
|
function tableName(table) {
|
|
768
787
|
return table.slice(table.lastIndexOf(".") + 1);
|
|
@@ -771,16 +790,16 @@ function pascalCase(name) {
|
|
|
771
790
|
const camel = camelCase(name);
|
|
772
791
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
773
792
|
}
|
|
774
|
-
const IDENTIFIER = /^[A-Za-z_$][\w$]
|
|
793
|
+
const IDENTIFIER = /^[A-Za-z_$][\w$]*$/u;
|
|
775
794
|
function identifier(name, what) {
|
|
776
795
|
if (!IDENTIFIER.test(name)) throw configError(`PermDock CLI: ${what} ${JSON.stringify(name)} is not an identifier`);
|
|
777
796
|
return name;
|
|
778
797
|
}
|
|
779
798
|
function quoted(text) {
|
|
780
|
-
return `'${text.
|
|
799
|
+
return `'${text.replaceAll(/[\\']/gu, (match) => `\\${match}`)}'`;
|
|
781
800
|
}
|
|
782
801
|
function templateText(text) {
|
|
783
|
-
return text.
|
|
802
|
+
return text.replaceAll(/[\\`]|\$\{/gu, (match) => `\\${match}`);
|
|
784
803
|
}
|
|
785
804
|
const AUTH_UID = "(select auth.uid())";
|
|
786
805
|
function drizzleRoles(list) {
|
|
@@ -825,7 +844,10 @@ function emitDrizzle(policies, options) {
|
|
|
825
844
|
assertNoServiceRole(text);
|
|
826
845
|
return text;
|
|
827
846
|
}
|
|
828
|
-
/**
|
|
847
|
+
/**
|
|
848
|
+
* Prisma 8 `policy_<command>` blocks; each target model declares `@@rls`
|
|
849
|
+
* itself.
|
|
850
|
+
*/
|
|
829
851
|
function emitPrisma(policies, options = {}) {
|
|
830
852
|
const modelOf = (table) => identifier(options.models?.[table] ?? pascalCase(tableName(table)), "model");
|
|
831
853
|
const models = [...new Set(policies.map((item) => modelOf(item.table)))];
|
|
@@ -882,9 +904,9 @@ function declaredScope(facts, scope, where) {
|
|
|
882
904
|
return scope;
|
|
883
905
|
}
|
|
884
906
|
/**
|
|
885
|
-
* The ids of `scope` where the subject holds `key` through an allow without
|
|
886
|
-
*
|
|
887
|
-
*
|
|
907
|
+
* The ids of `scope` where the subject holds `key` through an allow without a
|
|
908
|
+
* row condition, minus a deny of it, as text: `<value> in (…)`. A relationship
|
|
909
|
+
* or a `where` on the same permission never widens it.
|
|
888
910
|
*/
|
|
889
911
|
function permitted(ctx, value, scope, key) {
|
|
890
912
|
return `${value} in (select x::text from ${qualified$1(ctx, permittedByPermissionHelper(scope))}(${quoteLiteral(key)}) x)`;
|
|
@@ -988,9 +1010,9 @@ function storagePolicies(ctx, facts, storage, warnings) {
|
|
|
988
1010
|
* The `realtime.messages` and `storage.objects` policies `rls.realtime` and
|
|
989
1011
|
* `rls.storage` describe. Each one admits a row only where the subject holds
|
|
990
1012
|
* the permission in the scope instance its topic segment or folder names,
|
|
991
|
-
* through an allow without a row condition, so the helpers' API-key ceiling
|
|
992
|
-
*
|
|
993
|
-
*
|
|
1013
|
+
* through an allow without a row condition, so the helpers' API-key ceiling and
|
|
1014
|
+
* suspension rules apply and a relationship grant on the same permission never
|
|
1015
|
+
* reaches a topic or a folder.
|
|
994
1016
|
*/
|
|
995
1017
|
function realtimeStoragePolicies(ctx, facts, config, warnings = []) {
|
|
996
1018
|
if (config.realtime === void 0 && config.storage === void 0) return [];
|
|
@@ -1007,10 +1029,9 @@ function realtimeStoragePolicies(ctx, facts, config, warnings = []) {
|
|
|
1007
1029
|
//#region src/cli/rls/generate-policies.ts
|
|
1008
1030
|
const SERVICE_TABLES_HEADER = "-- Supabase Realtime and Storage: rls.realtime and rls.storage. RLS on both tables is Supabase's.";
|
|
1009
1031
|
/**
|
|
1010
|
-
* A `realtime.messages` or `storage.objects` policy that applies only where
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1013
|
-
* none.
|
|
1032
|
+
* A `realtime.messages` or `storage.objects` policy that applies only where the
|
|
1033
|
+
* table exists. The Realtime and Storage services create those tables, so a
|
|
1034
|
+
* local stack with the service off, and pg-delta's shadow database, have none.
|
|
1014
1035
|
*/
|
|
1015
1036
|
function guardedPolicySql(item) {
|
|
1016
1037
|
const body = policySql(item).trimEnd().split("\n").map((line) => ` ${line}`).join("\n");
|
|
@@ -1023,7 +1044,10 @@ end
|
|
|
1023
1044
|
$permdock$;
|
|
1024
1045
|
`;
|
|
1025
1046
|
}
|
|
1026
|
-
/**
|
|
1047
|
+
/**
|
|
1048
|
+
* Appends the `realtime.messages` and `storage.objects` policies, which never
|
|
1049
|
+
* get `tableSql`.
|
|
1050
|
+
*/
|
|
1027
1051
|
function withHelperTables(sql, helperTables) {
|
|
1028
1052
|
if (helperTables === void 0) return sql;
|
|
1029
1053
|
const tables = `${helperTables.trimEnd()}\n`;
|
|
@@ -1033,7 +1057,10 @@ function databaseModeWarnings(policy, { ctx }, warnings) {
|
|
|
1033
1057
|
if (ctx.authorize !== "database") return;
|
|
1034
1058
|
for (const { name } of ctx.scopes) if (policy.grants.some((grant) => grant.scope === name) && scopeTable(ctx, name) === void 0 && scopeSources(ctx, name).length === 0) warnings.push(`${name}-scoped grants read the ${name} memberships table in database mode: set rls.memberships.scopes.${name}, rls.membershipSources or supabase.hook.memberships (or --memberships for the first scope), otherwise they deny`);
|
|
1035
1059
|
}
|
|
1036
|
-
/**
|
|
1060
|
+
/**
|
|
1061
|
+
* The grants compiled into table policies, and the Realtime and Storage
|
|
1062
|
+
* policies beside them.
|
|
1063
|
+
*/
|
|
1037
1064
|
function generatePolicies(input, policy, options, built, warnings) {
|
|
1038
1065
|
const rls = input.config.rls;
|
|
1039
1066
|
const { ctx } = built;
|
|
@@ -1090,8 +1117,8 @@ function generatePolicies(input, policy, options, built, warnings) {
|
|
|
1090
1117
|
//#region src/cli/rls/shims.ts
|
|
1091
1118
|
const NAME$1 = /^[a-z_][a-z0-9_]*$/u;
|
|
1092
1119
|
/**
|
|
1093
|
-
* The key a legacy caller passes, mapped the way `rls migrate` maps it:
|
|
1094
|
-
*
|
|
1120
|
+
* The key a legacy caller passes, mapped the way `rls migrate` maps it: `keys`
|
|
1121
|
+
* and `renamed` exactly, then the longest `prefixes` entry.
|
|
1095
1122
|
*/
|
|
1096
1123
|
function mappedKey(config, renamed) {
|
|
1097
1124
|
const exact = {
|
|
@@ -1112,10 +1139,10 @@ function addKey(list, key) {
|
|
|
1112
1139
|
}
|
|
1113
1140
|
/**
|
|
1114
1141
|
* The grant keys behind each permission, per scope: the keys of its
|
|
1115
|
-
* unconditional allows, and every deny key. A shim cannot apply a row
|
|
1116
|
-
*
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1142
|
+
* unconditional allows, and every deny key. A shim cannot apply a row condition
|
|
1143
|
+
* or a validity window, so a conditional allow answers nothing and a
|
|
1144
|
+
* conditional deny always subtracts; the conditioned keys are listed apart. A
|
|
1145
|
+
* break-glass key answers only the break-glass read, so it is left out too.
|
|
1119
1146
|
* Rows seeded under a former key are left out; the shim maps a former key to
|
|
1120
1147
|
* the current one first.
|
|
1121
1148
|
*/
|
|
@@ -1169,7 +1196,10 @@ grant execute on function ${name}(${argTypes}) to authenticated;`;
|
|
|
1169
1196
|
function grantKeys(keys, scope, effect) {
|
|
1170
1197
|
return `pg_catalog.jsonb_array_elements_text(coalesce(${keys.map(scope)} -> (${keys.key}) -> ${quoteLiteral(effect)}, '[]'::jsonb)) g(grant_key)`;
|
|
1171
1198
|
}
|
|
1172
|
-
/**
|
|
1199
|
+
/**
|
|
1200
|
+
* The instances of `scope` the caller holds an unconditional allow of the key
|
|
1201
|
+
* in, minus those it holds a deny in.
|
|
1202
|
+
*/
|
|
1173
1203
|
function idsSql(ctx, keys, scope) {
|
|
1174
1204
|
const helper = qualified$1(ctx, permittedIdsHelper(scope));
|
|
1175
1205
|
return ` select a.id
|
|
@@ -1223,10 +1253,10 @@ function shim(ctx, config, keys, fn, helper) {
|
|
|
1223
1253
|
* One wrapper per `rls.migrate.helpers` entry under its legacy name, so SQL
|
|
1224
1254
|
* that `rls migrate` has not rewritten yet (function bodies, views, triggers)
|
|
1225
1255
|
* answers from the PermDock helpers. A wrapper maps the legacy key to the
|
|
1226
|
-
* permission key, then to the grant keys `grants` lists for the helper's
|
|
1227
|
-
*
|
|
1228
|
-
*
|
|
1229
|
-
*
|
|
1256
|
+
* permission key, then to the grant keys `grants` lists for the helper's scope,
|
|
1257
|
+
* so a permission whose grants are split by condition still answers. Each is
|
|
1258
|
+
* `security definer` with an empty `search_path`, so a caller needs `execute`
|
|
1259
|
+
* on the wrapper only, not usage on the helper schema.
|
|
1230
1260
|
*/
|
|
1231
1261
|
function shimsSql(ctx, config, shims, renamed, grants) {
|
|
1232
1262
|
const schema = shims.schema ?? "public";
|
|
@@ -1307,8 +1337,8 @@ function triggersSql(triggers, schema, tables) {
|
|
|
1307
1337
|
}
|
|
1308
1338
|
/**
|
|
1309
1339
|
* `rls.audit`: one call of the audit function per generated table, which
|
|
1310
|
-
* registers the table with the application's audit module. Statements that
|
|
1311
|
-
*
|
|
1340
|
+
* registers the table with the application's audit module. Statements that run
|
|
1341
|
+
* code, so they travel with the seeds.
|
|
1312
1342
|
*/
|
|
1313
1343
|
function auditSql(audit, schema, tables) {
|
|
1314
1344
|
if (audit === void 0) return "";
|
|
@@ -1327,7 +1357,10 @@ ${targets.map((table) => `select ${fn}(${quoteLiteral(`${quoteIdent$1(schema)}.$
|
|
|
1327
1357
|
}
|
|
1328
1358
|
//#endregion
|
|
1329
1359
|
//#region src/cli/rls/generate-sql.ts
|
|
1330
|
-
/**
|
|
1360
|
+
/**
|
|
1361
|
+
* The checks that need the SQL context: `--backfill-out`,
|
|
1362
|
+
* `rls.anonymousSignIns`, `rls.jsonSchema`.
|
|
1363
|
+
*/
|
|
1331
1364
|
function preflight(input, { ctx }) {
|
|
1332
1365
|
const rls = input.config.rls;
|
|
1333
1366
|
const from = typeof rls?.customRoles === "object" ? rls.customRoles.from : void 0;
|
|
@@ -1383,10 +1416,17 @@ function sectionsSql(input, policy, options, built, generated, jsonSchema, warni
|
|
|
1383
1416
|
if (typeof rls?.approvals === "object" && rls.approvals.delegations === true && ctx.authorize !== "database") warnings.push("rls.approvals.delegations with --authorize jwt: permdock_is_approver cannot read a delegator's permissions from the caller's token, so in SQL a cover never satisfies a holder() approver; approvalsHandler still does");
|
|
1384
1417
|
const graphed = graphSql(ctx, graph, tableNames(rls?.tables));
|
|
1385
1418
|
let rowHelpers = "";
|
|
1386
|
-
if (rls?.rowHelpers !== void 0 || inheritTargets(policy).length > 0)
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1419
|
+
if (rls?.rowHelpers !== void 0 || inheritTargets(policy).length > 0) {
|
|
1420
|
+
const readable = (grants) => [...options.fieldsMode === void 0 ? grants.branches : rowBranches(grants.branches), ...grants.actionBranches];
|
|
1421
|
+
try {
|
|
1422
|
+
const narrowed = compileGrants(policy, {
|
|
1423
|
+
...ctx,
|
|
1424
|
+
candidates: CANDIDATES
|
|
1425
|
+
}, tableNames(rls?.tables), [], input.skipClosures, true);
|
|
1426
|
+
rowHelpers = rowHelpersSql(ctx, policy, readable(compiled), rls?.rowHelpers ?? [], tableNames(rls?.tables), warnings, readable(narrowed));
|
|
1427
|
+
} catch (cause) {
|
|
1428
|
+
return { refusal: describeError(cause) };
|
|
1429
|
+
}
|
|
1390
1430
|
}
|
|
1391
1431
|
const breakGlass = breakGlassSql(ctx, breakGlassEntries(policy, tableNames(rls?.tables)));
|
|
1392
1432
|
return [
|
|
@@ -1397,7 +1437,10 @@ function sectionsSql(input, policy, options, built, generated, jsonSchema, warni
|
|
|
1397
1437
|
rowHelpers === "" ? void 0 : rowHelpers
|
|
1398
1438
|
];
|
|
1399
1439
|
}
|
|
1400
|
-
/**
|
|
1440
|
+
/**
|
|
1441
|
+
* Whether `anon` calls a helper: `rls.anonExecute`, an anon field view or an
|
|
1442
|
+
* anon branch reading the user id.
|
|
1443
|
+
*/
|
|
1401
1444
|
function anonExecutes(input, { compiled, views }) {
|
|
1402
1445
|
return input.config.rls?.anonExecute === true || views.some((view) => view.roles.includes("anon")) || compiled.branches.some((branch) => branch.roles.includes("anon") && [
|
|
1403
1446
|
branch.access,
|
|
@@ -1405,7 +1448,10 @@ function anonExecutes(input, { compiled, views }) {
|
|
|
1405
1448
|
branch.check
|
|
1406
1449
|
].some((sql) => sql?.includes("permdock_user_id") === true));
|
|
1407
1450
|
}
|
|
1408
|
-
/**
|
|
1451
|
+
/**
|
|
1452
|
+
* Everything before the table policies: helpers, sections, shims, scaffold and
|
|
1453
|
+
* triggers.
|
|
1454
|
+
*/
|
|
1409
1455
|
function preambleSql(input, policy, options, built, generated, jsonSchema, warnings) {
|
|
1410
1456
|
const rls = input.config.rls;
|
|
1411
1457
|
const { ctx } = built;
|
|
@@ -1437,7 +1483,7 @@ function preambleSql(input, policy, options, built, generated, jsonSchema, warni
|
|
|
1437
1483
|
...rls?.trustedReaders === void 0 ? {} : { trustedReaders: rls.trustedReaders }
|
|
1438
1484
|
}),
|
|
1439
1485
|
permissionHelpersSql(ctx, grants, renamed, anonExecute),
|
|
1440
|
-
permissionHoldersSql(ctx)
|
|
1486
|
+
nonEmptyOr(permissionHoldersSql(ctx), void 0),
|
|
1441
1487
|
actorKinds === void 0 ? void 0 : actorMayWriteSql(ctx, actorKinds),
|
|
1442
1488
|
usesLiveSession ? sessionLiveHelperSql(ctx) : void 0,
|
|
1443
1489
|
...sections,
|
|
@@ -1478,9 +1524,9 @@ function forceWarnings({ graph }, warnings) {
|
|
|
1478
1524
|
}
|
|
1479
1525
|
}
|
|
1480
1526
|
/**
|
|
1481
|
-
* The row columns that belong to a table. With `rls.tables` set, a resource
|
|
1482
|
-
*
|
|
1483
|
-
*
|
|
1527
|
+
* The row columns that belong to a table. With `rls.tables` set, a resource it
|
|
1528
|
+
* does not name is a table only when generated policies are written for it;
|
|
1529
|
+
* with `--helpers-only` it has none, so it gets no index.
|
|
1484
1530
|
*/
|
|
1485
1531
|
function tableColumns(rowColumns, tables, helpersOnly, warnings) {
|
|
1486
1532
|
if (tables === void 0) return rowColumns;
|
|
@@ -1530,7 +1576,10 @@ function emitTarget(input, built, generated, preamble) {
|
|
|
1530
1576
|
outRel
|
|
1531
1577
|
};
|
|
1532
1578
|
}
|
|
1533
|
-
/**
|
|
1579
|
+
/**
|
|
1580
|
+
* The generated SQL for one run, before `--db-url-stdin` prunes the index
|
|
1581
|
+
* targets.
|
|
1582
|
+
*/
|
|
1534
1583
|
function generateSql(input, policy, options, built, warnings) {
|
|
1535
1584
|
const rls = input.config.rls;
|
|
1536
1585
|
const { ctx } = built;
|
|
@@ -1564,7 +1613,11 @@ function generateSql(input, policy, options, built, warnings) {
|
|
|
1564
1613
|
}
|
|
1565
1614
|
//#endregion
|
|
1566
1615
|
//#region src/cli/rls/index-scan.ts
|
|
1567
|
-
/**
|
|
1616
|
+
/**
|
|
1617
|
+
* An index PermDock generated (`permdock_<table>_<columns>_idx`), in the
|
|
1618
|
+
* indexes part or in a migration derived from it: it never counts as serving
|
|
1619
|
+
* its own target.
|
|
1620
|
+
*/
|
|
1568
1621
|
const GENERATED_INDEX = /\bcreate\s+index\s+(?:if\s+not\s+exists\s+)?"?permdock_\w*_idx"?[^;]*;/giu;
|
|
1569
1622
|
const IDENT = String.raw`(?:"(?:[^"]|"")+"|[A-Za-z_][\w$]*)`;
|
|
1570
1623
|
const NAME = String.raw`${IDENT}(?:\s*\.\s*${IDENT})?`;
|
|
@@ -1587,7 +1640,10 @@ function qualified(raw) {
|
|
|
1587
1640
|
function stripComments(sql) {
|
|
1588
1641
|
return sql.replaceAll(/\/\*[\s\S]*?\*\//gu, " ").replaceAll(/--[^\n]*/gu, " ");
|
|
1589
1642
|
}
|
|
1590
|
-
/**
|
|
1643
|
+
/**
|
|
1644
|
+
* The text between the `(` that ends `match` and its closing `)`, and the index
|
|
1645
|
+
* after it.
|
|
1646
|
+
*/
|
|
1591
1647
|
function group(text, open) {
|
|
1592
1648
|
let depth = 1;
|
|
1593
1649
|
for (let index = open; index < text.length; index += 1) {
|
|
@@ -1641,7 +1697,10 @@ function keyColumns(body) {
|
|
|
1641
1697
|
}
|
|
1642
1698
|
return columns;
|
|
1643
1699
|
}
|
|
1644
|
-
/**
|
|
1700
|
+
/**
|
|
1701
|
+
* Key columns of each index, unique constraint and primary key the SQL creates,
|
|
1702
|
+
* per `schema.table`.
|
|
1703
|
+
*/
|
|
1645
1704
|
function indexKeysFromSql(sql) {
|
|
1646
1705
|
const text = stripComments(sql);
|
|
1647
1706
|
const keys = {};
|
|
@@ -1665,7 +1724,10 @@ function indexKeysFromSql(sql) {
|
|
|
1665
1724
|
}
|
|
1666
1725
|
return keys;
|
|
1667
1726
|
}
|
|
1668
|
-
/**
|
|
1727
|
+
/**
|
|
1728
|
+
* The index keys of the SQL files under the migration and schema folders of
|
|
1729
|
+
* `cwd`.
|
|
1730
|
+
*/
|
|
1669
1731
|
function indexKeysFromProject(cwd) {
|
|
1670
1732
|
const all = {};
|
|
1671
1733
|
for (const file of sqlFiles(cwd, [...MIGRATION_DIRS])) {
|
|
@@ -1678,13 +1740,19 @@ function indexKeysFromProject(cwd) {
|
|
|
1678
1740
|
function tablesFromSql(sql) {
|
|
1679
1741
|
return new Set([...stripComments(sql).matchAll(TABLE_NAME)].map((match) => qualified(captured(match))));
|
|
1680
1742
|
}
|
|
1681
|
-
/**
|
|
1743
|
+
/**
|
|
1744
|
+
* Every `schema.table` the SQL files under the migration and schema folders of
|
|
1745
|
+
* `cwd` create.
|
|
1746
|
+
*/
|
|
1682
1747
|
function tablesFromProject(cwd) {
|
|
1683
1748
|
const all = /* @__PURE__ */ new Set();
|
|
1684
1749
|
for (const file of sqlFiles(cwd, [...MIGRATION_DIRS])) for (const table of tablesFromSql(readFileSync(file, "utf8"))) all.add(table);
|
|
1685
1750
|
return all;
|
|
1686
1751
|
}
|
|
1687
|
-
/**
|
|
1752
|
+
/**
|
|
1753
|
+
* The targets no index in `keys` leads with: its key columns start with the
|
|
1754
|
+
* target's, as `pruneIndexTargets` reads a database.
|
|
1755
|
+
*/
|
|
1688
1756
|
function withoutServedTargets(targets, keys) {
|
|
1689
1757
|
return targets.filter((target) => !(keys[target.table] ?? []).some((key) => target.columns.every((column, at) => key[at] === column)));
|
|
1690
1758
|
}
|
|
@@ -1696,8 +1764,8 @@ function loadPolicy(cwd, config, from) {
|
|
|
1696
1764
|
}
|
|
1697
1765
|
const PROJECT_COMMAND = "permdock rls generate";
|
|
1698
1766
|
/**
|
|
1699
|
-
* The policy `policyFromCatalog` rebuilds from the project's pushed catalog
|
|
1700
|
-
*
|
|
1767
|
+
* The policy `policyFromCatalog` rebuilds from the project's pushed catalog and
|
|
1768
|
+
* policy; a project with no pushed policy fails with `policy-not-published`.
|
|
1701
1769
|
*/
|
|
1702
1770
|
async function projectPolicyOf(input, project) {
|
|
1703
1771
|
const fetched = await fetchProjectPolicy({
|
|
@@ -1876,7 +1944,10 @@ async function runRlsGenerate(input) {
|
|
|
1876
1944
|
//#endregion
|
|
1877
1945
|
//#region src/cli/rls/introspect.ts
|
|
1878
1946
|
const ROLES = ["anon", "authenticated"];
|
|
1879
|
-
/**
|
|
1947
|
+
/**
|
|
1948
|
+
* Neon's `anonymous` is the role `rls generate` writes as `anon` for the other
|
|
1949
|
+
* dialects.
|
|
1950
|
+
*/
|
|
1880
1951
|
function liveRole(role) {
|
|
1881
1952
|
return role === "anonymous" ? "anon" : role;
|
|
1882
1953
|
}
|
|
@@ -1892,14 +1963,107 @@ function normalizeTableName(table) {
|
|
|
1892
1963
|
return parts.length === 1 ? `public.${parts[0] ?? ""}` : parts.join(".");
|
|
1893
1964
|
}
|
|
1894
1965
|
const FUNCTION_HEADER = /create or replace function ("?)([A-Za-z_][\w$]*)\1\.("?)([A-Za-z_][\w$]*)\3\s*\(([\s\S]*?)\nas \$/gu;
|
|
1966
|
+
const TYPE_ALIASES = {
|
|
1967
|
+
int: "integer",
|
|
1968
|
+
int4: "integer",
|
|
1969
|
+
int2: "smallint",
|
|
1970
|
+
int8: "bigint",
|
|
1971
|
+
bool: "boolean",
|
|
1972
|
+
varchar: "character varying",
|
|
1973
|
+
char: "character",
|
|
1974
|
+
float4: "real",
|
|
1975
|
+
float8: "double precision",
|
|
1976
|
+
timestamp: "timestamp without time zone",
|
|
1977
|
+
timestamptz: "timestamp with time zone",
|
|
1978
|
+
time: "time without time zone",
|
|
1979
|
+
timetz: "time with time zone"
|
|
1980
|
+
};
|
|
1981
|
+
/**
|
|
1982
|
+
* A parameter type as `oidvectortypes` prints it: lower case, no quotes, no
|
|
1983
|
+
* schema, no type modifier, aliases spelled out. A `%type` reference is `*`,
|
|
1984
|
+
* which matches any type.
|
|
1985
|
+
*/
|
|
1986
|
+
function normalizeParameterType(type) {
|
|
1987
|
+
const text = type.trim().toLowerCase().replaceAll("\"", "");
|
|
1988
|
+
if (text.endsWith("%type")) return "*";
|
|
1989
|
+
const array = /(?:\[\d*\])+$/u.exec(text)?.[0] ?? "";
|
|
1990
|
+
const base = text.slice(0, text.length - array.length).replaceAll(/\([^)]*\)/gu, "").replaceAll(/\s+/gu, " ").trim();
|
|
1991
|
+
const unqualified = /^[\w$]+(?:\.[\w$]+)+$/u.test(base) ? base.split(".").at(-1) ?? base : base;
|
|
1992
|
+
return `${TYPE_ALIASES[unqualified] ?? unqualified}${"[]".repeat(array.split("[").length - 1)}`;
|
|
1993
|
+
}
|
|
1994
|
+
function splitTopLevel(text) {
|
|
1995
|
+
const parts = [];
|
|
1996
|
+
let depth = 0;
|
|
1997
|
+
let quoted = false;
|
|
1998
|
+
let start = 0;
|
|
1999
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
2000
|
+
const char = text[index];
|
|
2001
|
+
if (char === "'") quoted = !quoted;
|
|
2002
|
+
else if (!quoted && char === "(") depth += 1;
|
|
2003
|
+
else if (!quoted && char === ")") depth -= 1;
|
|
2004
|
+
else if (!quoted && depth === 0 && char === ",") {
|
|
2005
|
+
parts.push(text.slice(start, index));
|
|
2006
|
+
start = index + 1;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
parts.push(text.slice(start));
|
|
2010
|
+
return parts.map((part) => part.trim()).filter((part) => part !== "");
|
|
2011
|
+
}
|
|
2012
|
+
/**
|
|
2013
|
+
* The input parameter types of a function header that starts after its opening
|
|
2014
|
+
* parenthesis. Every generated parameter is named, so the first word of a
|
|
2015
|
+
* parameter with more than one is its name.
|
|
2016
|
+
*/
|
|
2017
|
+
function parameterTypes(header) {
|
|
2018
|
+
let depth = 0;
|
|
2019
|
+
let end = header.length;
|
|
2020
|
+
for (let index = 0; index < header.length; index += 1) {
|
|
2021
|
+
const char = header[index];
|
|
2022
|
+
if (char === "(") depth += 1;
|
|
2023
|
+
else if (char === ")") {
|
|
2024
|
+
if (depth === 0) {
|
|
2025
|
+
end = index;
|
|
2026
|
+
break;
|
|
2027
|
+
}
|
|
2028
|
+
depth -= 1;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
return splitTopLevel(header.slice(0, end)).flatMap((parameter) => {
|
|
2032
|
+
const words = parameter.replace(/\s+(?:default\b|=)[\s\S]*$/iu, "").split(/\s+/u);
|
|
2033
|
+
const mode = words[0]?.toLowerCase();
|
|
2034
|
+
if (mode === "out") return [];
|
|
2035
|
+
const rest = mode === "in" || mode === "inout" || mode === "variadic" ? words.slice(1) : words;
|
|
2036
|
+
return [normalizeParameterType((rest.length > 1 ? rest.slice(1) : rest).join(" "))];
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
/** `schema.name(type, type)`, the key a helper is checked by. */
|
|
2040
|
+
function signatureOf(name, types) {
|
|
2041
|
+
return `${name}(${types.join(", ")})`;
|
|
2042
|
+
}
|
|
1895
2043
|
function helpersOf(sql) {
|
|
1896
2044
|
const found = /* @__PURE__ */ new Set();
|
|
1897
2045
|
for (const match of sql.matchAll(FUNCTION_HEADER)) {
|
|
1898
|
-
const [header = "", , schema = "", , name = ""] = match;
|
|
1899
|
-
if (/\bsecurity definer\b/u.test(header)) found.add(`${schema}.${name}
|
|
2046
|
+
const [header = "", , schema = "", , name = "", rest = ""] = match;
|
|
2047
|
+
if (/\bsecurity definer\b/u.test(header)) found.add(signatureOf(`${schema}.${name}`, parameterTypes(rest)));
|
|
1900
2048
|
}
|
|
1901
2049
|
return [...found];
|
|
1902
2050
|
}
|
|
2051
|
+
function nameOfSignature(signature) {
|
|
2052
|
+
return signature.slice(0, signature.indexOf("("));
|
|
2053
|
+
}
|
|
2054
|
+
function typesOfSignature(signature) {
|
|
2055
|
+
return splitTopLevel(signature.slice(signature.indexOf("(") + 1, signature.lastIndexOf(")"))).map(normalizeParameterType);
|
|
2056
|
+
}
|
|
2057
|
+
/** The actual overload `expected` names; `*` matches any parameter type. */
|
|
2058
|
+
function matchHelper(expected, actual) {
|
|
2059
|
+
if (Object.hasOwn(actual, expected)) return actual[expected];
|
|
2060
|
+
const name = nameOfSignature(expected);
|
|
2061
|
+
const want = typesOfSignature(expected);
|
|
2062
|
+
for (const [signature, helper] of Object.entries(actual)) {
|
|
2063
|
+
const have = typesOfSignature(signature);
|
|
2064
|
+
if (nameOfSignature(signature) === name && have.length === want.length && want.every((type, index) => type === "*" || type === have[index])) return helper;
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
1903
2067
|
function expectedRls(policies, sql, indexes = []) {
|
|
1904
2068
|
const tables = [...new Set(policies.map((item) => normalizeTableName(item.table)))];
|
|
1905
2069
|
const grants = {};
|
|
@@ -1929,8 +2093,8 @@ function expectedRls(policies, sql, indexes = []) {
|
|
|
1929
2093
|
};
|
|
1930
2094
|
}
|
|
1931
2095
|
/**
|
|
1932
|
-
* One warning per index target no index starts with. A missing index slows
|
|
1933
|
-
*
|
|
2096
|
+
* One warning per index target no index starts with. A missing index slows the
|
|
2097
|
+
* policy down but grants nothing, so these do not fail `verify`.
|
|
1934
2098
|
*/
|
|
1935
2099
|
function missingIndexes(expected, actual) {
|
|
1936
2100
|
return expected.indexes.flatMap((target) => {
|
|
@@ -1944,7 +2108,10 @@ function sameList(left, right) {
|
|
|
1944
2108
|
const b = right.toSorted();
|
|
1945
2109
|
return a.length === b.length && a.every((item, index) => item === b[index]);
|
|
1946
2110
|
}
|
|
1947
|
-
/**
|
|
2111
|
+
/**
|
|
2112
|
+
* One finding per difference; policy expressions are not compared, since
|
|
2113
|
+
* Postgres rewrites their text.
|
|
2114
|
+
*/
|
|
1948
2115
|
function diffRls(expected, actual, options = {}) {
|
|
1949
2116
|
const out = [];
|
|
1950
2117
|
const found = new Map(actual.policies.map((item) => [`${item.table}\u0000${item.name}`, item]));
|
|
@@ -1973,7 +2140,7 @@ function diffRls(expected, actual, options = {}) {
|
|
|
1973
2140
|
}
|
|
1974
2141
|
}
|
|
1975
2142
|
for (const helper of expected.helpers) {
|
|
1976
|
-
const have = actual.helpers
|
|
2143
|
+
const have = matchHelper(helper, actual.helpers);
|
|
1977
2144
|
if (have === void 0) {
|
|
1978
2145
|
out.push(rlsFinding("helper-missing", helper, "helper", `${helper}: helper is missing`));
|
|
1979
2146
|
continue;
|
|
@@ -1995,19 +2162,22 @@ from information_schema.role_table_grants
|
|
|
1995
2162
|
where grantee in ('anon', 'anonymous', 'authenticated')
|
|
1996
2163
|
and lower(privilege_type) in ('select', 'insert', 'update', 'delete')
|
|
1997
2164
|
and table_schema || '.' || table_name = any($1::text[])`;
|
|
1998
|
-
const HELPERS_SQL = `select n.nspname || '.' || p.proname as target, p.prosecdef as definer,
|
|
2165
|
+
const HELPERS_SQL = `select n.nspname || '.' || p.proname || '(' || oidvectortypes(p.proargtypes) || ')' as target, p.prosecdef as definer,
|
|
1999
2166
|
coalesce(array_to_string(p.proconfig, ','), '') as config
|
|
2000
2167
|
from pg_proc p
|
|
2001
2168
|
join pg_namespace n on n.oid = p.pronamespace
|
|
2002
2169
|
where n.nspname || '.' || p.proname = any($1::text[])`;
|
|
2003
2170
|
function commandOf(cmd) {
|
|
2004
|
-
const text =
|
|
2171
|
+
const text = typeof cmd === "string" ? cmd.toLowerCase() : "";
|
|
2005
2172
|
return text === "*" ? "all" : text;
|
|
2006
2173
|
}
|
|
2007
2174
|
function connectIntrospect(db) {
|
|
2008
2175
|
return connectPgPool(db, "permdock rls verify --introspect");
|
|
2009
2176
|
}
|
|
2010
|
-
/**
|
|
2177
|
+
/**
|
|
2178
|
+
* Reads the catalogs for the tables and helpers `expected` names
|
|
2179
|
+
* (postgres-meta's queries, trimmed).
|
|
2180
|
+
*/
|
|
2011
2181
|
async function introspectRls(db, expected, connect = connectIntrospect) {
|
|
2012
2182
|
const client = await connect(db);
|
|
2013
2183
|
try {
|
|
@@ -2017,7 +2187,7 @@ async function introspectRls(db, expected, connect = connectIntrospect) {
|
|
|
2017
2187
|
client.query(POLICIES_SQL, [tables]),
|
|
2018
2188
|
client.query(TABLES_SQL, [tables]),
|
|
2019
2189
|
client.query(GRANTS_SQL, [tables]),
|
|
2020
|
-
client.query(HELPERS_SQL, [[...expected.helpers]]),
|
|
2190
|
+
client.query(HELPERS_SQL, [[...new Set(expected.helpers.map(nameOfSignature))]]),
|
|
2021
2191
|
client.query(INDEX_COLUMNS_SQL, [indexed]),
|
|
2022
2192
|
client.query(COLUMNS_SQL, [indexed])
|
|
2023
2193
|
]);
|
|
@@ -2045,7 +2215,7 @@ async function introspectRls(db, expected, connect = connectIntrospect) {
|
|
|
2045
2215
|
})),
|
|
2046
2216
|
rlsEnabled: Object.fromEntries(enabled.rows.map((row) => [String(row["target"]), row["enabled"] === true])),
|
|
2047
2217
|
grants: byTable,
|
|
2048
|
-
helpers: Object.fromEntries(helpers.rows.map((row) => [String(row["target"]), {
|
|
2218
|
+
helpers: Object.fromEntries(helpers.rows.map((row) => [signatureOf(nameOfSignature(String(row["target"])), typesOfSignature(String(row["target"]))), {
|
|
2049
2219
|
securityDefiner: row["definer"] === true,
|
|
2050
2220
|
emptySearchPath: String(row["config"]).split(",").some((item) => item === "search_path=\"\"" || item === "search_path=''")
|
|
2051
2221
|
}])),
|
|
@@ -2062,10 +2232,10 @@ const WRITES = [
|
|
|
2062
2232
|
"delete"
|
|
2063
2233
|
];
|
|
2064
2234
|
/**
|
|
2065
|
-
* Each table and write command whose permissive policies reach
|
|
2066
|
-
*
|
|
2067
|
-
*
|
|
2068
|
-
*
|
|
2235
|
+
* Each table and write command whose permissive policies reach `authenticated`
|
|
2236
|
+
* (or `public`) without the read-only actor check: no restrictive policy for
|
|
2237
|
+
* the command calls `permdock_actor_may_write()`, and some permissive one does
|
|
2238
|
+
* not.
|
|
2069
2239
|
*/
|
|
2070
2240
|
function unguardedWrites(policies, fn) {
|
|
2071
2241
|
const out = [];
|
|
@@ -2107,7 +2277,10 @@ function seedLine(row) {
|
|
|
2107
2277
|
function seedKey(line) {
|
|
2108
2278
|
return line.replace(" on ", " ").replaceAll(" ", "/");
|
|
2109
2279
|
}
|
|
2110
|
-
/**
|
|
2280
|
+
/**
|
|
2281
|
+
* Drift is an error; `info` names RLS tables whose policies call no PermDock
|
|
2282
|
+
* helper.
|
|
2283
|
+
*/
|
|
2111
2284
|
function diffMixed(expected, actual) {
|
|
2112
2285
|
const drift = [];
|
|
2113
2286
|
const seeds = `${expected.schema}.role_permissions`;
|
|
@@ -2147,7 +2320,10 @@ from pg_class c
|
|
|
2147
2320
|
join pg_namespace n on n.oid = c.relnamespace
|
|
2148
2321
|
where c.relkind in ('r', 'p') and c.relrowsecurity`;
|
|
2149
2322
|
const quoteIdent = escapeSqlIdent;
|
|
2150
|
-
/**
|
|
2323
|
+
/**
|
|
2324
|
+
* Reads `role_permissions`, `pg_policies` and the RLS-enabled tables for
|
|
2325
|
+
* {@link diffMixed}.
|
|
2326
|
+
*/
|
|
2151
2327
|
async function introspectMixed(db, schema, connect = connectIntrospect) {
|
|
2152
2328
|
const client = await connect(db);
|
|
2153
2329
|
try {
|
|
@@ -2170,7 +2346,7 @@ async function introspectMixed(db, schema, connect = connectIntrospect) {
|
|
|
2170
2346
|
expression: String(row["expression"]),
|
|
2171
2347
|
command: String(row["command"]),
|
|
2172
2348
|
restrictive: row["restrictive"] === true,
|
|
2173
|
-
roles:
|
|
2349
|
+
roles: (typeof row["roles"] === "string" ? row["roles"] : "").split(",").filter((role) => role !== "")
|
|
2174
2350
|
})).filter((row) => inScope(row.table)),
|
|
2175
2351
|
rlsTables: tables.rows.map((row) => String(row["target"])).filter(inScope).toSorted()
|
|
2176
2352
|
};
|
|
@@ -2298,7 +2474,7 @@ async function migrate(input) {
|
|
|
2298
2474
|
output: generated.output
|
|
2299
2475
|
};
|
|
2300
2476
|
await requirePeer(() => import("pgsql-parser"), "pgsql-parser", "permdock rls migrate", input.cwd, PGSQL_PARSER_MAJOR);
|
|
2301
|
-
const { migrateTarget, runRlsMigrate } = await import("./migrate-
|
|
2477
|
+
const { migrateTarget, runRlsMigrate } = await import("./migrate-B7oP_sQU.js");
|
|
2302
2478
|
return runRlsMigrate({
|
|
2303
2479
|
cwd: input.cwd,
|
|
2304
2480
|
sql: input.sql,
|
|
@@ -2314,7 +2490,10 @@ async function migrate(input) {
|
|
|
2314
2490
|
...input.io.now === void 0 ? {} : { now: input.io.now() }
|
|
2315
2491
|
});
|
|
2316
2492
|
}
|
|
2317
|
-
/**
|
|
2493
|
+
/**
|
|
2494
|
+
* `verify --introspect` with `--helpers-only`: helpers and seeds exactly,
|
|
2495
|
+
* hand-written policies by their keys.
|
|
2496
|
+
*/
|
|
2318
2497
|
async function introspectHelpersOnly(db, expected, generated, connect, readOnlyActors, ignore) {
|
|
2319
2498
|
const schema = generated.schema ?? "permdock";
|
|
2320
2499
|
try {
|
|
@@ -2343,7 +2522,10 @@ async function introspectHelpersOnly(db, expected, generated, connect, readOnlyA
|
|
|
2343
2522
|
return usageResult(cause);
|
|
2344
2523
|
}
|
|
2345
2524
|
}
|
|
2346
|
-
/**
|
|
2525
|
+
/**
|
|
2526
|
+
* `verify --introspect`: the catalogs against what `generate` would write with
|
|
2527
|
+
* the same flags.
|
|
2528
|
+
*/
|
|
2347
2529
|
async function introspect(input, ignore) {
|
|
2348
2530
|
if (input.db === void 0) return {
|
|
2349
2531
|
code: 2,
|
|
@@ -2408,7 +2590,7 @@ async function runRls(input) {
|
|
|
2408
2590
|
}
|
|
2409
2591
|
case "import": {
|
|
2410
2592
|
await requirePeer(() => import("pgsql-parser"), "pgsql-parser", "permdock rls import", input.cwd, PGSQL_PARSER_MAJOR);
|
|
2411
|
-
const { runRlsImport } = await import("./import-
|
|
2593
|
+
const { runRlsImport } = await import("./import-CST57XLp.js");
|
|
2412
2594
|
return runRlsImport({
|
|
2413
2595
|
cwd: input.cwd,
|
|
2414
2596
|
config: input.config,
|