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,18 +1,18 @@
|
|
|
1
1
|
import { t as compact } from "./compact-CAf557ZB.js";
|
|
2
|
-
import { n as freezeDeep } from "./freeze-
|
|
3
|
-
import { r as ownGet } from "./paths-
|
|
4
|
-
import { n as internalsOf } from "./internals-
|
|
5
|
-
import { a as getResource } from "./permission-registry-
|
|
6
|
-
import { a as expandRelation, c as isEdgeRelation, l as isFieldRelation, u as isPrincipalRelation } from "./resource-relations-
|
|
7
|
-
import { s as instantAt } from "./time-
|
|
8
|
-
import { f as scopeList, l as rootScope, o as normalizeMemberships, s as resolveScope } from "./scopes-
|
|
9
|
-
import { o as flattenGrantee } from "./grantee-
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { D as emptyListeners, t as evaluate } from "./evaluate-
|
|
14
|
-
import { n as relationId, t as pendingRelations } from "./relations-
|
|
15
|
-
import { t as relationWalk } from "./relation-walk-
|
|
2
|
+
import { n as freezeDeep } from "./freeze-jjan0lCv.js";
|
|
3
|
+
import { r as ownGet } from "./paths-CUvURzHp.js";
|
|
4
|
+
import { n as internalsOf } from "./internals-B3IgHrvo.js";
|
|
5
|
+
import { a as getResource } from "./permission-registry-B8tYxPIt.js";
|
|
6
|
+
import { a as expandRelation, c as isEdgeRelation, l as isFieldRelation, u as isPrincipalRelation } from "./resource-relations-8-pCScBO.js";
|
|
7
|
+
import { s as instantAt } from "./time-nR1JesoH.js";
|
|
8
|
+
import { f as scopeList, l as rootScope, o as normalizeMemberships, s as resolveScope } from "./scopes-0Up_UA2t.js";
|
|
9
|
+
import { o as flattenGrantee } from "./grantee-Dke-9rd1.js";
|
|
10
|
+
import { t as byCodePoint } from "./compare-DTfyUunF.js";
|
|
11
|
+
import { r as relationCondition } from "./grantee-conditions-BrYPe-w0.js";
|
|
12
|
+
import { c as nowSeconds, p as scopeField } from "./tenancy-5d1zVBvK.js";
|
|
13
|
+
import { D as emptyListeners, t as evaluate } from "./evaluate-BAmf_AQd.js";
|
|
14
|
+
import { n as relationId, t as pendingRelations } from "./relations-BxvRvDHK.js";
|
|
15
|
+
import { t as relationWalk } from "./relation-walk-DK_gkgL7.js";
|
|
16
16
|
//#region src/core/who-can.ts
|
|
17
17
|
const MAX_ROUNDS = 48;
|
|
18
18
|
async function settle(cache) {
|
|
@@ -22,7 +22,10 @@ async function settle(cache) {
|
|
|
22
22
|
await Promise.all(pending);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* The holders on each instance a graph relation reads, or `undefined` when the
|
|
27
|
+
* graph cannot say.
|
|
28
|
+
*/
|
|
26
29
|
async function walkHolders(condition, row, reader, cache) {
|
|
27
30
|
let walk = relationWalk(condition, row, reader);
|
|
28
31
|
if (walk === "relation-unavailable") {
|
|
@@ -246,11 +249,11 @@ function memberLister(source, scopes) {
|
|
|
246
249
|
};
|
|
247
250
|
}
|
|
248
251
|
/**
|
|
249
|
-
* Who holds `permission` on `resource` for the instance's policy and how
|
|
250
|
-
*
|
|
251
|
-
* `RelationSource.related`. It lists and never grants; `complete: false`
|
|
252
|
-
*
|
|
253
|
-
*
|
|
252
|
+
* Who holds `permission` on `resource` for the instance's policy and how (role,
|
|
253
|
+
* relation or share), from `MembershipSource.list` and
|
|
254
|
+
* `RelationSource.related`. It lists and never grants; `complete: false` means
|
|
255
|
+
* some holders could not be listed. An instance built from a snapshot answers
|
|
256
|
+
* an empty, incomplete list.
|
|
254
257
|
*/
|
|
255
258
|
function whoCan(permdock, permission, resource) {
|
|
256
259
|
const internals = internalsOf(permdock);
|
package/dist/workflow/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as AutomationSource, i as AutomationRequest, l as memoryAutomationSource, n as AutomationDecision, r as AutomationMode, s as MemoryAutomationSource, t as Automation, u as parseAutomation } from "../automation-
|
|
2
|
-
import { i as pollingApprovalWaiter, n as ApprovalWaiter, r as PollingApprovalWaiterOptions, t as ApprovalWaitOptions } from "../waiter-
|
|
3
|
-
import { a as WorkflowPermDockOptions, i as WorkflowPermDock, n as AwaitApprovalOptions, o as createPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-
|
|
1
|
+
import { a as AutomationSource, i as AutomationRequest, l as memoryAutomationSource, n as AutomationDecision, r as AutomationMode, s as MemoryAutomationSource, t as Automation, u as parseAutomation } from "../automation-C6Jg75xq.js";
|
|
2
|
+
import { i as pollingApprovalWaiter, n as ApprovalWaiter, r as PollingApprovalWaiterOptions, t as ApprovalWaitOptions } from "../waiter-CqUKX6CY.js";
|
|
3
|
+
import { a as WorkflowPermDockOptions, i as WorkflowPermDock, n as AwaitApprovalOptions, o as createPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-BamXmeob.js";
|
|
4
4
|
import "../index-CaxrMD1A.js";
|
|
5
5
|
export { type ApprovalWaitOptions, type ApprovalWaiter, type Automation, type AutomationDecision, type AutomationMode, type AutomationOptions, type AutomationRequest, type AutomationSource, type AwaitApprovalOptions, type MemoryAutomationSource, type PollingApprovalWaiterOptions, type StartAutomationResult, type WorkflowPermDock, type WorkflowPermDockOptions, createPermDock, memoryAutomationSource, parseAutomation, pollingApprovalWaiter };
|
package/dist/workflow/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as compact } from "../compact-CAf557ZB.js";
|
|
2
|
-
import { n as freezeDeep } from "../freeze-
|
|
3
|
-
import { n as findPermission } from "../permission-registry-
|
|
4
|
-
import { n as isThenable } from "../thenable-
|
|
5
|
-
import { n as memoryAutomationSource, r as parseAutomation } from "../automation-
|
|
6
|
-
import { l as withApp, t as getPermDock } from "../permdock-
|
|
7
|
-
import { o as automationEvent } from "../sink-
|
|
8
|
-
import { a as requestApproval, s as resumeDecision } from "../helpers-
|
|
9
|
-
import { i as subjectFromRunTicket, r as signRunTicket } from "../run-ticket-
|
|
10
|
-
import { t as pollingApprovalWaiter } from "../waiter-
|
|
2
|
+
import { n as freezeDeep } from "../freeze-jjan0lCv.js";
|
|
3
|
+
import { n as findPermission } from "../permission-registry-B8tYxPIt.js";
|
|
4
|
+
import { n as isThenable } from "../thenable-BNSM1U2R.js";
|
|
5
|
+
import { n as memoryAutomationSource, r as parseAutomation } from "../automation-x3KEUusw.js";
|
|
6
|
+
import { l as withApp, t as getPermDock } from "../permdock-BvjivVb9.js";
|
|
7
|
+
import { o as automationEvent } from "../sink-D9_vh372.js";
|
|
8
|
+
import { a as requestApproval, s as resumeDecision } from "../helpers-DJicaG6f.js";
|
|
9
|
+
import { i as subjectFromRunTicket, r as signRunTicket } from "../run-ticket-Dv7aF7Dk.js";
|
|
10
|
+
import { t as pollingApprovalWaiter } from "../waiter-aBLM63_f.js";
|
|
11
11
|
//#region src/workflow/create.ts
|
|
12
12
|
function writeQuietly(sink, event) {
|
|
13
13
|
try {
|
|
@@ -47,10 +47,10 @@ function targetOf(permission, data, resource) {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Creates the PermDock for durable runs of published automations. A run
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* Creates the PermDock for durable runs of published automations. A run acts as
|
|
51
|
+
* the automation's principal with that principal's rights at each step,
|
|
52
|
+
* narrowed to the automation's operations; the trigger is recorded and never
|
|
53
|
+
* grants.
|
|
54
54
|
*/
|
|
55
55
|
function createPermDock(policy, given) {
|
|
56
56
|
const { signer, verifier, principals, automations, store: approvals, waiter, audience, issuer, expiresIn = DEFAULT_TTL, onAuth, ...permdockOptions } = withApp(policy, given);
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { u as Permission } from "../permission-types-
|
|
3
|
-
import { a as PermDock } from "../permdock-
|
|
4
|
-
import { n as ApprovalWaiter } from "../waiter-
|
|
5
|
-
import { i as WorkflowPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-
|
|
1
|
+
import { Un as Decision } from "../policy-types-DGIO_gxq.js";
|
|
2
|
+
import { u as Permission } from "../permission-types-CAY-GU7e.js";
|
|
3
|
+
import { a as PermDock } from "../permdock-CprAPN3w.js";
|
|
4
|
+
import { n as ApprovalWaiter } from "../waiter-CqUKX6CY.js";
|
|
5
|
+
import { i as WorkflowPermDock, r as StartAutomationResult, t as AutomationOptions } from "../create-BamXmeob.js";
|
|
6
6
|
//#region src/workflow-sdk/index.d.ts
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* The part of a Workflow SDK `Hook` the waiter reads: awaiting it suspends the
|
|
9
|
+
* run.
|
|
10
|
+
*/
|
|
8
11
|
export type WorkflowSdkHook = {
|
|
9
12
|
readonly then: PromiseLike<unknown>["then"];
|
|
10
|
-
dispose()
|
|
13
|
+
dispose: () => void;
|
|
11
14
|
};
|
|
12
15
|
/** `createHook` from `workflow`; valid only inside a `"use workflow"` function. */
|
|
13
16
|
export type WorkflowSdkCreateHook = (options: {
|
|
@@ -22,16 +25,19 @@ export type WorkflowSdkStart<TArgs extends unknown[], TRun> = (workflow: (ticket
|
|
|
22
25
|
export type WorkflowSdkWaiterOptions = {
|
|
23
26
|
readonly createHook: WorkflowSdkCreateHook;
|
|
24
27
|
readonly resumeHook: WorkflowSdkResumeHook;
|
|
25
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* With `sleep`, a wait ends at the request's `expiresAt`; without it, only a
|
|
30
|
+
* wake ends it.
|
|
31
|
+
*/
|
|
26
32
|
readonly sleep?: WorkflowSdkSleep;
|
|
27
33
|
};
|
|
28
34
|
/** The Workflow SDK hook token a run parks on while approval `token` is pending. */
|
|
29
35
|
export declare function approvalHookToken(token: string): string;
|
|
30
36
|
/**
|
|
31
37
|
* An `ApprovalWaiter` over Workflow SDK hooks. `wait` parks the run on a hook
|
|
32
|
-
* and must run inside the workflow function; `wake` resumes it from an
|
|
33
|
-
*
|
|
34
|
-
*
|
|
38
|
+
* and must run inside the workflow function; `wake` resumes it from an approval
|
|
39
|
+
* handler. The hook carries no verdict: the run decides again from the approval
|
|
40
|
+
* store after it wakes.
|
|
35
41
|
*/
|
|
36
42
|
export declare function workflowSdkWaiter(options: WorkflowSdkWaiterOptions): ApprovalWaiter;
|
|
37
43
|
export type StartAutomationRunResult<TRun> = (Extract<StartAutomationResult, {
|
|
@@ -49,8 +55,8 @@ export type StartAutomationRunResult<TRun> = (Extract<StartAutomationResult, {
|
|
|
49
55
|
export declare function startAutomation<TArgs extends unknown[], TRun>(workflow: Pick<WorkflowPermDock, "start">, start: WorkflowSdkStart<TArgs, TRun>, run: (ticket: string, ...args: TArgs) => Promise<unknown>, id: string, args: TArgs, options?: AutomationOptions): Promise<StartAutomationRunResult<TRun>>;
|
|
50
56
|
/**
|
|
51
57
|
* Resumes hook `token` with `payload` only when `caller` is granted
|
|
52
|
-
* `permission` on `row`. A token alone never resumes a run. A hook that is
|
|
53
|
-
*
|
|
58
|
+
* `permission` on `row`. A token alone never resumes a run. A hook that is gone
|
|
59
|
+
* or a resume that throws denies with `validation`.
|
|
54
60
|
*/
|
|
55
61
|
export declare function authorizeHook(resumeHook: WorkflowSdkResumeHook, caller: PermDock, permission: Permission, row: unknown, token: string, payload: unknown): Promise<Decision>;
|
|
56
62
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as freezeDeep } from "../freeze-
|
|
1
|
+
import { n as freezeDeep } from "../freeze-jjan0lCv.js";
|
|
2
2
|
//#region src/workflow-sdk/index.ts
|
|
3
3
|
const HOOK_PREFIX = "permdock:approval:";
|
|
4
4
|
/** The Workflow SDK hook token a run parks on while approval `token` is pending. */
|
|
@@ -7,9 +7,9 @@ function approvalHookToken(token) {
|
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* An `ApprovalWaiter` over Workflow SDK hooks. `wait` parks the run on a hook
|
|
10
|
-
* and must run inside the workflow function; `wake` resumes it from an
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* and must run inside the workflow function; `wake` resumes it from an approval
|
|
11
|
+
* handler. The hook carries no verdict: the run decides again from the approval
|
|
12
|
+
* store after it wakes.
|
|
13
13
|
*/
|
|
14
14
|
function workflowSdkWaiter(options) {
|
|
15
15
|
const { createHook, resumeHook, sleep } = options;
|
|
@@ -61,8 +61,8 @@ function hookDenied() {
|
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* Resumes hook `token` with `payload` only when `caller` is granted
|
|
64
|
-
* `permission` on `row`. A token alone never resumes a run. A hook that is
|
|
65
|
-
*
|
|
64
|
+
* `permission` on `row`. A token alone never resumes a run. A hook that is gone
|
|
65
|
+
* or a resume that throws denies with `validation`.
|
|
66
66
|
*/
|
|
67
67
|
async function authorizeHook(resumeHook, caller, permission, row, token, payload) {
|
|
68
68
|
const decision = caller.decide(permission, row);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { n as internalsOf, t as attachInternals } from "./internals-
|
|
2
|
-
import { i as decideAllWith, n as canAllWith } from "./checks-
|
|
1
|
+
import { n as internalsOf, t as attachInternals } from "./internals-B3IgHrvo.js";
|
|
2
|
+
import { i as decideAllWith, n as canAllWith } from "./checks-CGkP3Z7A.js";
|
|
3
3
|
//#region src/core/wrap.ts
|
|
4
4
|
/**
|
|
5
5
|
* A frozen copy of `permdock` with the members `overrides` returns replaced.
|
|
6
|
-
* `overrides` runs again for every instance `tenant()`, `team()` and
|
|
7
|
-
*
|
|
6
|
+
* `overrides` runs again for every instance `tenant()`, `team()` and `derive()`
|
|
7
|
+
* return, so a wrapper never falls off a derived instance.
|
|
8
8
|
*/
|
|
9
9
|
function wrapPermDock(permdock, overrides) {
|
|
10
10
|
const wrap = (next) => wrapPermDock(next, overrides);
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { j as PolicyVocabulary } from "./policy-types-
|
|
2
|
-
import { a as PermDock } from "./permdock-
|
|
1
|
+
import { j as PolicyVocabulary } from "./policy-types-DGIO_gxq.js";
|
|
2
|
+
import { a as PermDock } from "./permdock-CprAPN3w.js";
|
|
3
3
|
//#region src/core/wrap.d.ts
|
|
4
4
|
/** A wrapper an adapter applies to each instance it builds, as `withOtel` does. */
|
|
5
5
|
type PermDockWrap = <V extends PolicyVocabulary>(permdock: PermDock<V>) => PermDock<V>;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* The members `wrapPermDock` replaces; it re-wraps the derived instances
|
|
8
|
+
* itself.
|
|
9
|
+
*/
|
|
7
10
|
type PermDockOverrides<V extends PolicyVocabulary = PolicyVocabulary> = Partial<Omit<PermDock<V>, "tenant" | "team" | "derive">>;
|
|
8
11
|
/**
|
|
9
12
|
* A frozen copy of `permdock` with the members `overrides` returns replaced.
|
|
10
|
-
* `overrides` runs again for every instance `tenant()`, `team()` and
|
|
11
|
-
*
|
|
13
|
+
* `overrides` runs again for every instance `tenant()`, `team()` and `derive()`
|
|
14
|
+
* return, so a wrapper never falls off a derived instance.
|
|
12
15
|
*/
|
|
13
16
|
declare function wrapPermDock<V extends PolicyVocabulary = PolicyVocabulary>(permdock: PermDock<V>, overrides: (permdock: PermDock<V>) => PermDockOverrides<V>): PermDock<V>;
|
|
14
17
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "permdock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Typed permissions for TypeScript apps, APIs, databases, and AI agents, with the permdock CLI and test runners.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -353,8 +353,8 @@
|
|
|
353
353
|
"ajv": "8.20.0",
|
|
354
354
|
"astro": "7.4.0",
|
|
355
355
|
"babel-plugin-react-compiler": "1.0.0",
|
|
356
|
-
"better-supabase": "0.
|
|
357
|
-
"better-supabase-floor": "npm:better-supabase@0.
|
|
356
|
+
"better-supabase": "0.13.0",
|
|
357
|
+
"better-supabase-floor": "npm:better-supabase@0.13.0",
|
|
358
358
|
"chat": "4.42.0",
|
|
359
359
|
"diff": "9.0.0",
|
|
360
360
|
"drizzle-orm": "1.0.0-rc.5-5935859",
|
|
@@ -364,12 +364,12 @@
|
|
|
364
364
|
"fastest-levenshtein": "1.0.16",
|
|
365
365
|
"fastify": "5.12.7",
|
|
366
366
|
"h3": "2.0.2",
|
|
367
|
-
"happy-dom": "
|
|
367
|
+
"happy-dom": "21.0.4",
|
|
368
368
|
"hono": "4.13.13",
|
|
369
369
|
"jose": "6.2.12",
|
|
370
370
|
"kysely": "0.29.6",
|
|
371
371
|
"next": "16.4.1",
|
|
372
|
-
"oxlint": "1.
|
|
372
|
+
"oxlint": "1.89.0",
|
|
373
373
|
"oxlint-tsgolint": "7.0.2004",
|
|
374
374
|
"package-manager-detector": "1.9.0",
|
|
375
375
|
"pg": "8.23.1",
|
|
@@ -411,7 +411,7 @@
|
|
|
411
411
|
"@trpc/server": ">=11",
|
|
412
412
|
"ai": ">=5",
|
|
413
413
|
"astro": ">=5",
|
|
414
|
-
"better-supabase": ">=0.
|
|
414
|
+
"better-supabase": ">=0.13.0",
|
|
415
415
|
"chat": ">=4",
|
|
416
416
|
"drizzle-orm": ">=0.40 || >=1.0.0-rc.0",
|
|
417
417
|
"elysia": ">=1",
|
|
@@ -420,12 +420,12 @@
|
|
|
420
420
|
"fastify": ">=5",
|
|
421
421
|
"h3": ">=2",
|
|
422
422
|
"hono": ">=4",
|
|
423
|
-
"jose": "
|
|
423
|
+
"jose": ">=6",
|
|
424
424
|
"kysely": ">=0.27",
|
|
425
425
|
"next": ">=16.3",
|
|
426
426
|
"pg": ">=8",
|
|
427
427
|
"pgsql-parser": ">=18",
|
|
428
|
-
"react": "
|
|
428
|
+
"react": ">=19",
|
|
429
429
|
"reflect-metadata": ">=0.1",
|
|
430
430
|
"resend": ">=6",
|
|
431
431
|
"rxjs": ">=7",
|
package/schemas/catalog-v1.json
CHANGED
|
@@ -329,6 +329,38 @@
|
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
},
|
|
332
|
+
"names": {
|
|
333
|
+
"description": "The SQL names the generated RLS exposes to application SQL, unqualified, in `schema`: per scope and per resource, as `resolveNames` gives them. Absent from a manifest written before 0.8.",
|
|
334
|
+
"type": "object",
|
|
335
|
+
"required": ["schema", "gucPrefix", "claims", "scopes", "resources"],
|
|
336
|
+
"properties": {
|
|
337
|
+
"schema": { "type": "string" },
|
|
338
|
+
"gucPrefix": { "type": "string" },
|
|
339
|
+
"claims": {
|
|
340
|
+
"type": "object",
|
|
341
|
+
"required": ["tenant", "role"],
|
|
342
|
+
"properties": {
|
|
343
|
+
"tenant": { "type": "string" },
|
|
344
|
+
"role": { "type": "string" }
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"teamScope": { "type": "string" },
|
|
348
|
+
"scopes": {
|
|
349
|
+
"type": "object",
|
|
350
|
+
"additionalProperties": {
|
|
351
|
+
"type": "object",
|
|
352
|
+
"additionalProperties": { "type": "string" }
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
"resources": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"additionalProperties": {
|
|
358
|
+
"type": "object",
|
|
359
|
+
"additionalProperties": { "type": "string" }
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
},
|
|
332
364
|
"requires": {
|
|
333
365
|
"description": "The supabase/sdk capability-matrix feature ids the hook, the helpers and subjectFromSupabase depend on, as of the matrix release tag.",
|
|
334
366
|
"type": "object",
|
|
@@ -457,7 +489,7 @@
|
|
|
457
489
|
},
|
|
458
490
|
"helperName": {
|
|
459
491
|
"type": "string",
|
|
460
|
-
"pattern": "^(permdock_has(_for)?|permitted_[a-z][a-z0-9_]*_(ids|permission_keys)(_for)?|permitted_[a-z][a-z0-9_]*_users|member_[a-z][a-z0-9_]*_ids(_for)?|permdock_can_assign(_any|_custom_role)?(_for)?|permdock_api_key_allows|permdock_token_scope_allows|permdock_actor_may_write|permdock_is_approver|permdock_user_id)$"
|
|
492
|
+
"pattern": "^(permdock_has(_for)?|permitted_[a-z][a-z0-9_]*_(ids|permission_keys)(_for)?|permitted_[a-z][a-z0-9_]*_users|member_[a-z][a-z0-9_]*_ids(_for|_of)?|permdock_can_assign(_any|_custom_role)?(_for)?|permdock_api_key_allows|permdock_token_scope_allows|permdock_actor_may_write|permdock_is_approver|permdock_user_id)$"
|
|
461
493
|
},
|
|
462
494
|
"column": {
|
|
463
495
|
"type": "object",
|
|
@@ -47,11 +47,13 @@ const decision = await decideCredential(
|
|
|
47
47
|
);
|
|
48
48
|
if (decision.outcome === "granted") {
|
|
49
49
|
const key = generateApiKey(decision.credential.id);
|
|
50
|
-
await db
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
await db
|
|
51
|
+
.insert(apiKeys)
|
|
52
|
+
.values({
|
|
53
|
+
id: decision.credential.id,
|
|
54
|
+
hash: await hashApiKey(key),
|
|
55
|
+
credential: decision.credential,
|
|
56
|
+
});
|
|
55
57
|
return key; // shown once
|
|
56
58
|
}
|
|
57
59
|
```
|
|
@@ -123,7 +125,7 @@ const subject = await subjectFromCapability(token, {
|
|
|
123
125
|
- The result is a `kind: 'link'` principal with one `{ on, roles, via: 'link' }` membership. It never holds a scope or global role.
|
|
124
126
|
- `linkPolicy` returns the tenant's `LinkPolicy` (`maxLifetime`, `redeemers`, `once`). Passing the same policy to `signCapability` refuses to mint a link the resolver would refuse.
|
|
125
127
|
- Never an unguessable id without expiry, and never a security-definer RPC that reads the guest page's rows.
|
|
126
|
-
- The one exception is resolving a stored link. When links live in better-supabase's share-links block, its `resolve_share_link` is `security definer` and reads only the link table. `subjectFromShareLink(token, { shareLinks, links, ttl })` from `permdock/better-supabase` turns the row into the same link subject. The page's rows are then read through `exchangeCapability` and RLS, as for a signed link. `links` maps each `subjectType` to a resource and maps the row's role to PermDock roles. An unmapped type or role, and a revoked or expired row, are anonymous. A link pinned to a version is refused, because a capability reads the current rows; read it through better-supabase's `versions.getShared(token)`. See [row-backed links](https://permdock.com/docs/concepts/capabilities#row-backed-links).
|
|
128
|
+
- The one exception is resolving a stored link. When links live in better-supabase's share-links block, its `resolve_share_link` is `security definer` and reads only the link table. `subjectFromShareLink(token, { shareLinks, links, ttl })` from `permdock/better-supabase` turns the row into the same link subject. The page's rows are then read through `exchangeCapability` and RLS, as for a signed link. `links` maps each subject type (`subject.type` from better-supabase 0.14, `subjectType` before it) to a resource and maps the row's role to PermDock roles. An unmapped type or role, and a revoked or expired row, are anonymous. A link pinned to a version is refused, because a capability reads the current rows; read it through better-supabase's `versions.getShared(token)`. See [row-backed links](https://permdock.com/docs/concepts/capabilities#row-backed-links).
|
|
127
129
|
|
|
128
130
|
With Supabase, let RLS serve the link through an exchange, never the link token itself:
|
|
129
131
|
|
|
@@ -36,9 +36,10 @@ pnpm exec permdock rls verify --introspect
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
- List the scope instances a permission reaches in process with `permdock.permittedIds(permission, scope, { within })`, never a loop of `can` over memberships with a made-up row.
|
|
39
|
-
- Generated policies call `permdock_has('<key>')` and one `permitted_<scope>_ids('<key>')` per declared scope, which Postgres runs once per statement. Hand-written policies that only need membership (an organization switcher) call `member_<scope>_ids()` instead of inventing a permission key. Trusted SQL that acts for a stored user (a job, a trigger, a deferred approval) calls `permdock_has_for(p_user, '<key>')` and `permitted_<scope>_ids_for(p_user, '<key>')` in `database` mode, or the generated `permitted_<resource>_rows_for`, never a hand-written function that rewrites `request.jwt.claims`. With `rls.rowHelpers`, a hand-written policy or function that needs the rows a permission reaches through the graph calls `permitted_<resource>_rows('<permission key>')` instead of restating closure walks, link hops and `includes`. A table's own `select` or `insert` policy calls the row-valued `permitted_<resource>_row(<table>, '<permission key>')` instead, so `insert ... returning` sees the new row. Hand-written policies and functions that apply no row condition call `permitted_<scope>_ids_by_permission('<permission key>')` or `permdock_has_permission('<permission key>')` instead of spelling a positional `#n` grant key. A screen or RPC that checks many permissions on one organization calls `permitted_<scope>_permission_keys(<id>)` once (or `(<id>, array['<key>', ...])` for a few keys) instead of one helper call per key. A role editor or admin screen lists a role's keys with `permdock_role_permissions(p_role, p_scope, p_tenant, p_scope_id)` (declared roles, and custom roles of the caller's tenant in `database` mode) and the catalog with `permdock_permission_keys()` (`permdock_permission_keys('<scope>')` for the keys a role on that scope can hold), instead of joining `role_permissions` and the custom-role tables by hand; server code reads any tenant's roles with `permdock_trusted_role_permissions`, granted through `rls.trustedReaders`. Set `--tenant-type` (or `rls.
|
|
39
|
+
- Generated policies call `permdock_has('<key>')` and one `permitted_<scope>_ids('<key>')` per declared scope, which Postgres runs once per statement. Hand-written policies that only need membership (an organization switcher) call `member_<scope>_ids()` instead of inventing a permission key. A policy that passes a user id, such as better-supabase's team sharing, calls `member_team_ids_of(<user>)` on Supabase: it answers only when the id is the caller's. Trusted SQL that acts for a stored user (a job, a trigger, a deferred approval) calls `permdock_has_for(p_user, '<key>')` and `permitted_<scope>_ids_for(p_user, '<key>')` in `database` mode, or the generated `permitted_<resource>_rows_for`, never a hand-written function that rewrites `request.jwt.claims`. With `rls.rowHelpers`, a hand-written policy or function that needs the rows a permission reaches through the graph calls `permitted_<resource>_rows('<permission key>')` instead of restating closure walks, link hops and `includes`. A table's own `select` or `insert` policy calls the row-valued `permitted_<resource>_row(<table>, '<permission key>')` instead, so `insert ... returning` sees the new row. A function that checks a known set of rows (one tenant's, a page, a batch) calls `permitted_<resource>_rows('<permission key>', <text[] of ids>)`, which reads only those ids, instead of the one-argument form, which reads the whole table, or a `permitted_<resource>_row` call per row. Hand-written policies and functions that apply no row condition call `permitted_<scope>_ids_by_permission('<permission key>')` or `permdock_has_permission('<permission key>')` instead of spelling a positional `#n` grant key. A screen or RPC that checks many permissions on one organization calls `permitted_<scope>_permission_keys(<id>)` once (or `(<id>, array['<key>', ...])` for a few keys) instead of one helper call per key. A role editor or admin screen lists a role's keys with `permdock_role_permissions(p_role, p_scope, p_tenant, p_scope_id)` (declared roles, and custom roles of the caller's tenant in `database` mode) and the catalog with `permdock_permission_keys()` (`permdock_permission_keys('<scope>')` for the keys a role on that scope can hold), instead of joining `role_permissions` and the custom-role tables by hand; server code reads any tenant's roles with `permdock_trusted_role_permissions`, granted through `rls.trustedReaders`. Set `--tenant-type` (or `rls.scopeTypes`, keyed by scope name or `tenant` and `team`) to the scope columns' types.
|
|
40
40
|
- `--authorize database` (default) reads the membership tables per statement; map each under `rls.memberships.scopes.<scope>` with `columns` for its id and its ancestors', and `via` so roles with `for` apply: a column name, or `{ value: 'staff' }` when every row has that kind (never add a generated column for it). `--authorize jwt` reads token claims and stays stale until the token refreshes; keep the token lifetime at 3600 seconds or less (PD019).
|
|
41
41
|
- When the role column holds values that are not role keys, give the membership source `role: { column, map: { value: 'role' } }`; a value mapped to `null` grants nothing. `permdock rls explain` prints the tables, membership sources, custom roles table and triggers a generate run binds to, without writing a file. `rls.seeds: 'function'` writes the `role_permissions` rows as `<schema>.seed()` instead of inserts; run `select <schema>.seed();` after each deploy, and PD054 checks the function body.
|
|
42
|
+
- `rls verify --introspect` checks each `security definer` helper by its full signature, so every overload is checked on its own. A helper finding id names the signature (`helper-definer:permdock.permdock_has(text):helper`); write `rls.verify.ignore` entries with it.
|
|
42
43
|
- `permdock rls verify --kind pgtap` writes `supabase/tests/permdock_rls.test.sql` (or `--out`) and, in `database` mode, inserts each fixture's memberships before it switches role.
|
|
43
44
|
- The helpers narrow to the tenant claim (`rls.tenantClaim`) whenever the token carries one; the Supabase hook writes it from `activeFrom`. When the app takes the tenant from the URL and one session spans tenants, set `rls.tenants: 'all'` so the database admits every member tenant, and keep filtering each query by the URL's tenant.
|
|
44
45
|
- `--policy-per-role` keeps one policy per role for review. `--custom-roles` (or `rls.customRoles: true`) resolves tenant-defined roles inside the `permdock_ceiling` view. In `database` mode, save a custom role with `permdock_replace_custom_role_grants(tenant, scope, scope_id, role, allow, deny, include)` and rename or delete it with `permdock_rename_custom_role_grants` and `permdock_delete_custom_role_grants`, never with hand-written `security definer` functions or direct writes; failures raise `22023` or `42501` with the reason as the `hint`. A platform custom role passes a null tenant and scope `global`; a shared custom role passes a null tenant and scope id at its scope. Seeds, jobs and backends with no member caller use the `permdock_trusted_*` variants, which keep the definition checks; grant `execute` on them to a backend role in a migration of your own, never to `authenticated`. Set `rls.customRoleWrites.requires` to the permission your role editor asserts (or `'manageRoles'`) so the database refuses members who may not manage roles (`manage-roles`).
|
|
@@ -79,7 +79,7 @@ type CustomRole = {
|
|
|
79
79
|
|
|
80
80
|
- The ceiling of a scope is the code allows of the declared roles marked `assignable` in that scope. A custom role never exceeds it, and hosted grants never widen it.
|
|
81
81
|
- An own allow inherits the conditions of the ceiling grants for that permission. To keep a narrower condition ("own posts only"), include the declared role that has it.
|
|
82
|
-
- A resource may declare `levels: { own: { ownerId: principal.id }, team: { teamId: { in: principal.teamIds } }, all: {} }`. A grant `{ permission: 'job.read', level: 'team' }` ANDs that condition into the ceiling grant. An undeclared level, or a level on a collection action, is dropped as `unknown-level` and removes the permission; a level on a deny is `condition-not-allowed`. `permdock.assignableLevels(leaf)` lists the levels the subject may hand out.
|
|
82
|
+
- A resource may declare `levels: { own: { ownerId: principal.id }, team: { teamId: { in: principal.teamIds } }, all: {} }`. A grant `{ permission: 'job.read', level: 'team' }` ANDs that condition into the ceiling grant. An undeclared level, or a level on a collection action, is dropped as `unknown-level` and removes the permission; a level on a deny is `condition-not-allowed`. `permdock.assignableLevels(leaf)` lists the levels the subject may hand out. Levels are unordered: holding `team` does not hand out `own`. Add `orderedLevels: true` to the resource when the levels nest from narrowest to widest in declaration order; a held level then also hands out every earlier one, and evaluation is unchanged.
|
|
83
83
|
- An own deny removes the permission from this custom role only. Deny it in code when it must win across roles.
|
|
84
84
|
- Pass a `CustomRoleSource` (`memoryCustomRoleSource(roles)` in tests), or a `CustomRoleSourceFactory` `(subject) => CustomRoleSource` when the source reads one principal's roles, as `customRoles` on `createPermDock` or any adapter. To add every role of a tenant on a role-management request, `await permdock.derive({ customRoles })` instead of building a second instance. Build it with `customRoleSource({ rolesFor })`, where `rolesFor(tenant)` reads every custom role of the tenant, not only the held ones: `assignableRoles` and `decideRoleChange` see only what the source returns. `{ read: 'held', policy }` skips the read on requests that never manage roles. Check it with `testCustomRoleSource(source, { every })`.
|
|
85
85
|
- `permdock.assignableRoles({ tenant })` lists declared roles, then the tenant's custom roles whose every permission and level the subject may hand out at the custom role's scope. `decideRoleChange` assigns and revokes a custom role like a declared one, with no holder count; it inherits `for` and `exclusiveWith` from its included roles.
|
|
@@ -90,4 +90,4 @@ type CustomRole = {
|
|
|
90
90
|
- A stored grant under a key renamed with `definePermissions(..., { renamed })` still resolves; `validateCustomRole` lists it in `renamed` as `{ from, to }`, and `permdock doctor` PD055 prints the `update` that rewrites it.
|
|
91
91
|
- For generated RLS, add `--custom-roles` (or `rls.customRoles: true`) to `permdock rls generate`. Platform roles are rows with `scope = 'global'` and a null `tenant_id`, or the top-level `role_grants` claim in `jwt` mode. With levels, `custom_role_permissions` gains a `level` column and the claim writes `key@level`.
|
|
92
92
|
- To adopt custom roles the app already stores in its own tables, set `rls.customRoles.from` and `rls.customRoleWrites.roles`, then run `permdock rls generate --backfill-out <migrations dir>/`. The migration saves each role through the trusted replace function, drops entries outside the ceiling with a warning, and skips roles that already have rows; never write the copy by hand ([backfill](https://permdock.com/docs/cli/rls#backfill-from-existing-tables)).
|
|
93
|
-
- To keep the copy current instead of copying once, set `rls.customRoles.from.sync: 'trigger'`: after-row triggers on the app's permission and include tables rewrite the copy through the trusted replace function. The generated name guard on `rls.customRoleWrites.roles` refuses a tenant row named like a declared role (`declared-role`) or a shared role (`name-taken`). A stored entry is `<permission>[@<level>]`; check one with `parseCustomRoleEntry(policy, entry, { scope })` in process or `permdock_custom_role_entry_problem(p_scope, p_entry)` in SQL, which answer `unknown-permission`, `outside-ceiling` or `unknown-level`.
|
|
93
|
+
- To keep the copy current instead of copying once, set `rls.customRoles.from.sync: 'trigger'`: after-row triggers on the app's permission and include tables rewrite the copy through the trusted replace function. Before-row triggers hold a signed-in write to the checks of `permdock_replace_custom_role_grants` against the copy as it stood before the statement, so a member who manages roles cannot add a permission they lack, even to a role they hold. A write path of your own calls the stable `permdock_custom_role_guard(p_tenant, p_scope, p_scope_id, p_role)` first, then `permdock_custom_role_beyond(p_tenant, p_scope, p_scope_id, p_allow, p_deny, p_include)` on the new entries only, from a `security definer` trigger that runs before the copy changes. The generated name guard on `rls.customRoleWrites.roles` refuses a tenant row named like a declared role (`declared-role`) or a shared role (`name-taken`). A stored entry is `<permission>[@<level>]`; check one with `parseCustomRoleEntry(policy, entry, { scope })` in process or `permdock_custom_role_entry_problem(p_scope, p_entry)` in SQL, which answer `unknown-permission`, `outside-ceiling` or `unknown-level`.
|
|
@@ -17,9 +17,7 @@ export const {
|
|
|
17
17
|
requirePermission,
|
|
18
18
|
PermDockProvider,
|
|
19
19
|
permdockHandler,
|
|
20
|
-
} = createPermDock(policy, {
|
|
21
|
-
subject: async () => getUser(),
|
|
22
|
-
});
|
|
20
|
+
} = createPermDock(policy, { subject: async () => getUser() });
|
|
23
21
|
```
|
|
24
22
|
|
|
25
23
|
Needs Next.js 16.3 or later. Guard with `getPermission(permissions.post.update, post)` or `assert`. For a page or Server Action that must stop on a denial, `await requirePermission(permission, data, { tenant })` calls `forbidden()` (or `unauthorized()` for a signed-out user); enable `experimental.authInterrupts` and add `app/forbidden.tsx` and `app/unauthorized.tsx`. When only part of a page is gated, let a Server Component `assert` inside `<PermissionBoundary denied={...} approval={...}>` from `permdock/next/client` (with a `Suspense` inside it); `usePermissionBoundary()` in the fallback gives the permission, the approval `token` and `retry()`. Client components use `permdock/react` inside the server `PermDockProvider`, which never awaits: it streams a `snapshotPromise`, and permission hooks answer `pending` until it lands (add `suspend` to make them suspend).
|
|
@@ -104,9 +102,7 @@ import { createPermDock } from "permdock/authzen";
|
|
|
104
102
|
|
|
105
103
|
export const { permdockHandler } = createPermDock(policy, {
|
|
106
104
|
subject: fromBearer,
|
|
107
|
-
resources: {
|
|
108
|
-
post: { data: (id) => loadPost(id), list: () => listPosts() },
|
|
109
|
-
},
|
|
105
|
+
resources: { post: { data: (id) => loadPost(id), list: () => listPosts() } },
|
|
110
106
|
});
|
|
111
107
|
```
|
|
112
108
|
|
|
@@ -137,7 +133,7 @@ import { PermDockProvider, usePermission } from "permdock/react-native";
|
|
|
137
133
|
|
|
138
134
|
`subjectId` is required: the signed-in user's id, or `null` when signed out. A stored snapshot of another principal is cleared. `storage` is `{ getItem, setItem, removeItem }`; `secureStoreStorage(SecureStore)` and `mmkvStorage(mmkv)` wrap Expo SecureStore and MMKV. `snapshotUrl` revalidates in the background; `subscribeForeground={appStateForeground(AppState)}` revalidates on return to the foreground. For Expo Router guards use `usePermissionGuard(permission, data?)`, which is `false` while `pending`, and `useSnapshotReady()` for a splash screen. `permdock.clear()` drops the persisted snapshot on sign-out. Do not import `policy.ts` on the client.
|
|
139
135
|
|
|
140
|
-
To answer guards from synced rows, write `localSnapshotManifest(policy)` (from `permdock`) to a JSON file at build time and pass `source={localSnapshot({ manifest, read, subscribe })}`. `read()` returns `{ principal: { id, tenant, roles, memberships, attributes }, customRoles }` from the local database; `subscribe` re-reads on row changes. It decides like the server snapshot except relation grantees (server-only)
|
|
136
|
+
To answer guards from synced rows, write `localSnapshotManifest(policy)` (from `permdock`) to a JSON file at build time and pass `source={localSnapshot({ manifest, read, subscribe })}`. `read()` returns `{ principal: { id, tenant, roles, memberships, attributes }, customRoles }` from the local database; `subscribe` re-reads on row changes. It decides like the server snapshot except relation grantees (server-only). With a `tenant`, the assignable roles, permissions and levels match the server's for the same rows. Never import `policy.ts` into the app for this. Docs: [local snapshot](https://permdock.com/docs/adapters/react-native#local-snapshot).
|
|
141
137
|
|
|
142
138
|
For an offline app on PowerSync, set `powersync: { out: 'sync-config.yaml' }` in `permdock.config.ts` and run `permdock powersync generate`: one edition 3 Sync Stream per resource, from the `rls.tables` and `rls.memberships` the RLS generator reads. It under-syncs, never over-syncs: a resource with a deny grant gets no stream, and a grant with a global role, approval, break-glass, validity, request context or a condition without a Sync Streams form syncs nothing, each with a warning. The app reads what does not sync from the server. It also writes `permdock_*` streams for the user's own membership, global-role and custom-role rows; with `powersync.manifest` set it writes the manifest too, and `powerSyncSource(db, { manifest, queries, read })` from `permdock/react-native` builds the local snapshot from `db.watch` queries. `permdock powersync verify` fails when a stream holds a fixture row the policy denies; doctor PD058 flags a stale file or manifest. Doctor PD065 lists server-only grants read from React Native code, which the device denies offline. Docs: [`permdock powersync`](https://permdock.com/docs/cli/powersync).
|
|
143
139
|
|
|
@@ -193,11 +189,13 @@ export const { middleware, protect } = createPermDock(policy, {
|
|
|
193
189
|
subject: ({ store }) => store.user ?? null,
|
|
194
190
|
});
|
|
195
191
|
|
|
196
|
-
const app = new Elysia()
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
192
|
+
const app = new Elysia()
|
|
193
|
+
.use(middleware())
|
|
194
|
+
.delete("/posts/:id", handler, {
|
|
195
|
+
beforeHandle: protect(permissions.post.delete, ({ params }) =>
|
|
196
|
+
loadPost(params.id),
|
|
197
|
+
),
|
|
198
|
+
});
|
|
201
199
|
```
|
|
202
200
|
|
|
203
201
|
Fetch-native plugin via `derive`. Denials are `403 application/problem+json`; anonymous callers get `401` plus `WWW-Authenticate`. For `.ws` routes, `connection(ws, { permission })` in `open` returns the socket's connection (memoised); it closes the socket with `1008` when revoked.
|
|
@@ -278,9 +276,7 @@ import { createPermDock } from "permdock/node";
|
|
|
278
276
|
|
|
279
277
|
export const { getPermDock, protect, send, permdockHandler } = createPermDock(
|
|
280
278
|
policy,
|
|
281
|
-
{
|
|
282
|
-
subject: (req) => userFromCookie(req.headers.cookie),
|
|
283
|
-
},
|
|
279
|
+
{ subject: (req) => userFromCookie(req.headers.cookie) },
|
|
284
280
|
);
|
|
285
281
|
```
|
|
286
282
|
|
|
@@ -360,9 +356,7 @@ import { PermDockProvider, Protected, usePermission } from 'permdock/solid';
|
|
|
360
356
|
```ts
|
|
361
357
|
import { instrument } from "permdock/otel";
|
|
362
358
|
|
|
363
|
-
instrument(permdock, {
|
|
364
|
-
logger: { info: console.info, warn: console.warn },
|
|
365
|
-
});
|
|
359
|
+
instrument(permdock, { logger: { info: console.info, warn: console.warn } });
|
|
366
360
|
```
|
|
367
361
|
|
|
368
362
|
HTTP adapters accept the same options as `otel`. `@opentelemetry/api` is optional; without it the adapter writes only through `logger`.
|
|
@@ -507,7 +501,7 @@ const subject = subjectFromSupabase(claims, {
|
|
|
507
501
|
|
|
508
502
|
Write the claims with `permdock supabase hook generate`; `permdock supabase inspect --out` writes the manifest (helper names, tenant claim, budget, claims written) that `authorizationProvider` from `permdock/better-supabase` turns into better-supabase's `authorization` config. No `@supabase/supabase-js` peer. Pair with `permdock rls generate`, or keep SQL as authority and run `permdock rls verify --db-url-stdin` against `sqlFunction` twins ([database-first](https://permdock.com/docs/adapters/rls)); the generic RLS workflow is in the `permdock-data` skill.
|
|
509
503
|
|
|
510
|
-
With better-supabase, set `authorization: authorizationProvider({ manifest, catalog })` in `better-supabase.config.ts` (with `rls.customRoles` its `canAssign` and `canAssignFor` call `permdock_can_assign_any` and its `_for` form, so custom roles are assignable through better-supabase; regenerate the manifest after turning custom roles on), pass `authorizer({ policy })` to the server (`createNext`, `createHono`, `createMcp`) so every `permission` a resource, action, route guard or tool declares is decided by PermDock from the verified claims (`operations` maps tables for `permissions: true`; a missing or anonymous claim denies), build bucket and topic `access` policies with `bucketPolicy` and `topicPolicy`, and map its session with `subjectFromBetterSupabase(session)` (all from `permdock/better-supabase`): the active tenant's `features` become `principal.plans`. Pass `plans: { keys }` when better-supabase's `entitlements.claim.keys` shortens feature keys, and `apiKeys: { permissions, manifest }` so an `apiKey` session maps to the key's credential subject instead of the anonymous one. For `createMcp` tools, put the permission in `meta` and spread `toolPolicy({ permdock })` into the options: tools without one are hidden and refused, and approval-required calls are refused because `createMcp` collects no approvals. Wrap a `CredentialProvider` with `credentialGuard(provider, { permdock, use, revoke? })` so PermDock decides each token use. `authorizationProvider({ ..., approver })` lets holders of that permission approve AI tool calls, never their own. `approvers: { 'ai-tool': holder(p), 'support-session': ..., 'invoice.send': ... }` fills `isApprover` through `permdock_is_approver` (needs `rls.approvals`); only `user()`, `holder()` and `anyOf()` approvers, and a kind it does not name has no approver. `accessReviewApplier({ client, reviews, policy, demoteTo?, email?, permdockFor? })` applies a review's revoked items: `update_member_role` to the `demoteTo` role when that role lacks the permission, else `remove_member`, plus `revoke_invitation` for the member's matching invitations, then `markApplied`; pass the reviewer's client so the blocks' own checks run. better-supabase's `createAgentRuntime({ toolApproval })` takes `toolApproval` from `permdock/ai-sdk` as it is. Validate its claims with `betterSupabase.claims(supabaseClaims().extend(appSchema))` (`supabaseClaims` from `permdock/supabase`, any Standard Schema as `appSchema`) instead of a hand-written copy of the claim shape. A `supabase.hook.claims` function that needs the user's organizations calls `<schema>.member_organization_ids_for(user_id)` (generated by `rls generate`, executable by `supabase_auth_admin` only) instead of querying the membership tables itself. A token Supabase's OAuth server issued to a third-party app (`client_id`) becomes an `oauth-client` actor limited to its `scope`; `deny(permission, { to: actor('oauth-client') })` keeps such apps out, in the app and, through `rls generate`, in Postgres. A better-supabase support session (`act.kind: 'support'`) is actor kind `support` with `sessionId` and `readOnly`, and `actingAs` (`act.kind: 'impersonation'`) is kind `impersonation`; neither has a delegation, so they reach nothing until a policy delegation names `actor('support')` or `actor('impersonation')`, and `readOnly: true` (also when `read_only` is absent) narrows that to read-only permissions. Generated RLS reads memberships, not `act`, so a support token sent to the Data API writes as the user: add a restrictive `for update` (and `insert` / `delete`) policy per writable table that requires `act ->> 'read_only' = 'false'` when `act` is a support or session level ([support access](https://permdock.com/docs/guides/support-access)). With `rls.anonymousSignIns: 'deny'`, pass `anonymousSignIns: 'deny'` to the subject mapper too (doctor PD057). Check a deployed database against the generated policies with `permdock rls verify --introspect`.
|
|
504
|
+
With better-supabase, set `authorization: authorizationProvider({ manifest, catalog })` in `better-supabase.config.ts` (with `rls.customRoles` its `canAssign` and `canAssignFor` call `permdock_can_assign_any` and its `_for` form, so custom roles are assignable through better-supabase; regenerate the manifest after turning custom roles on), pass `authorizer({ policy })` to the server (`createNext`, `createHono`, `createMcp`) so every `permission` a resource, action, route guard or tool declares is decided by PermDock from the verified claims (`operations` maps tables for `permissions: true`; a missing or anonymous claim denies), build bucket and topic `access` policies with `bucketPolicy` and `topicPolicy`, and map its session with `subjectFromBetterSupabase(session)` (all from `permdock/better-supabase`): the active tenant's `features` become `principal.plans`. Pass `plans: { keys }` when better-supabase's `entitlements.claim.keys` shortens feature keys, and `apiKeys: { permissions, manifest }` so an `apiKey` session maps to the key's credential subject instead of the anonymous one. For `createMcp` tools, put the permission in `meta` and spread `toolPolicy({ permdock })` into the options: tools without one are hidden and refused, and approval-required calls are refused because `createMcp` collects no approvals. Wrap a `CredentialProvider` with `credentialGuard(provider, { permdock, use, revoke? })` so PermDock decides each token use. `authorizationProvider({ ..., approver })` lets holders of that permission approve AI tool calls, never their own. `approvers: { 'ai-tool': holder(p), 'support-session': ..., 'invoice.send': ... }` fills `isApprover` through `permdock_is_approver` (needs `rls.approvals`); only `user()`, `holder()` and `anyOf()` approvers, and a kind it does not name has no approver. `accessReviewApplier({ client, reviews, policy, demoteTo?, email?, permdockFor? })` applies a review's revoked items: `update_member_role` to the `demoteTo` role when that role lacks the permission, else `remove_member`, plus `revoke_invitation` for the member's matching invitations, then `markApplied`; pass the reviewer's client so the blocks' own checks run. better-supabase's `createAgentRuntime({ toolApproval })` takes `toolApproval` from `permdock/ai-sdk` as it is. Validate its claims with `betterSupabase.claims(supabaseClaims().extend(appSchema))` (`supabaseClaims` from `permdock/supabase`, any Standard Schema as `appSchema`) instead of a hand-written copy of the claim shape. A `supabase.hook.claims` function that needs the user's organizations calls `<schema>.member_organization_ids_for(user_id)` (generated by `rls generate`, executable by `supabase_auth_admin` only) instead of querying the membership tables itself. With a scope named `team` or `teams`, `authorizationProvider` fills better-supabase's `teamIdsOf` with `<schema>.member_team_ids_of(user)`, which answers only for the caller, so with `blocks.access.model: 'provider'` better-supabase's `team_ids_of()` and team-sharing policies read PermDock's memberships. A token Supabase's OAuth server issued to a third-party app (`client_id`) becomes an `oauth-client` actor limited to its `scope`; `deny(permission, { to: actor('oauth-client') })` keeps such apps out, in the app and, through `rls generate`, in Postgres. A better-supabase support session (`act.kind: 'support'`) is actor kind `support` with `sessionId` and `readOnly`, and `actingAs` (`act.kind: 'impersonation'`) is kind `impersonation`; neither has a delegation, so they reach nothing until a policy delegation names `actor('support')` or `actor('impersonation')`, and `readOnly: true` (also when `read_only` is absent) narrows that to read-only permissions. Generated RLS reads memberships, not `act`, so a support token sent to the Data API writes as the user: add a restrictive `for update` (and `insert` / `delete`) policy per writable table that requires `act ->> 'read_only' = 'false'` when `act` is a support or session level ([support access](https://permdock.com/docs/guides/support-access)). With `rls.anonymousSignIns: 'deny'`, pass `anonymousSignIns: 'deny'` to the subject mapper too (doctor PD057). Check a deployed database against the generated policies with `permdock rls verify --introspect`.
|
|
511
505
|
|
|
512
506
|
The other better-supabase slots, all from `permdock/better-supabase` ([better-supabase](https://permdock.com/docs/adapters/better-supabase)): `hookCan(permdock)` and `handlerCan({ getPermDock })` are the `can` options of `authorizeHook` and `protectWebHandler` in `better-supabase/workflow-sdk`; they decide with no row, so a permission with a row condition denies there and is checked inside the handler, and `handlerCan` answers `undefined` (401) without a signed-in principal. `supportPolicy({ policy, options?, writable?, approval?, approved? })` is the `authorize` option of `supportSessions`; it decides each start with `decideSupportSession` as the admin, and an `approval-required` start passes only once `approved(input, pending)` returns `{ approvedBy }` for an approver other than the admin. `subscriberPolicy({ policy, principals, events, row?, sender? })` filters outbox, webhook or realtime subscribers to those who may read the event (exact type, then the longest `prefix.*`, then `*`; a type with no entry reaches no one). `principalSource({ claims, identities? })` is a `PrincipalSource` over the claims better-supabase mints, for `decideFor`, `subscribersFor` and delivery; only links the app created through a signed-in flow or a verified address go in `identities`. `authorizationHooks({ policy, claims, service?, principals?, events?, approvers?, support?, tickets? })` is the `authorization` option of `createServer`: it answers automation publish and run-as, delegated OAuth scopes, `approverOf`, identities, delivery audiences, support sessions and run tickets from the claims better-supabase mints now, never from the request.
|
|
513
507
|
|
|
@@ -523,7 +517,8 @@ Supabase specifics for generated RLS (the generic flags and parity checks are in
|
|
|
523
517
|
- Under `migra`, generate `--split helpers,seeds,policies,hook --out supabase/schemas/identity/056_permdock_{part}.sql --seeds-out supabase/migrations/` and write the schema and function privileges and the `security_invoker` view option with `--grants-out` into a migration created by `supabase migration new` after the first `db diff`; `db diff` drops those, so never append them to a migration by hand. Table grants and policies stay in the schema files, where `db diff` keeps them. Keep the helpers part ahead of every file that calls the helpers in `schema_paths` (`permdock doctor` PD042, PD043).
|
|
524
518
|
- `--authorize jwt` reads the hook's claims: enable the printed `[auth.hook.custom_access_token]` stanza in `supabase/config.toml`. The generated hook writes the canonical `memberships` claim from the `rls.memberships.scopes` tables, so do not hand-write one.
|
|
525
519
|
- For more than one membership table, declare `tableMembershipSource` / `junctionMembershipSource` sources once (from `permdock/supabase`, with a `query` on the server), pass the array as `memberships` (wrapped in `claimsFirst(sources, { version: authzVersion({ query }) })` to trust the token until it is truncated or stale), put the same sources under `supabase.hook.memberships` in `permdock.config.ts`, and run `permdock supabase hook generate`; add the printed `config.toml` block (`jwt_expiry = 900`). List member-removal and payout permissions in `definePolicy({ fresh })`.
|
|
526
|
-
- When the server has only supabase-js (no `SqlQuery`), never re-read memberships, global roles or custom roles with the admin client: grant `subject_for(p_user)` and `authz_version_for(p_user)` (written next to the hook) to the backend role, expose them through `public` wrappers when `permdock` is not an exposed schema, and use `postgrestSources(admin, { schema, fn, versionFn, policy })`: `claimsFirst(sources.memberships)` (with `onStale: 'reread'` a fresh token costs one version call, and with `policy` a token that claims a custom role costs one `subject_for` call), `customRoles: sources.customRoles(principal)`, and `await sources.subject(userId)` for a job acting for a stored user.
|
|
520
|
+
- When the server has only supabase-js (no `SqlQuery`), never re-read memberships, global roles or custom roles with the admin client: grant `subject_for(p_user)` and `authz_version_for(p_user)` (written next to the hook) to the backend role, expose them through `public` wrappers when `permdock` is not an exposed schema, and use `postgrestSources(admin, { schema, fn, versionFn, policy })`: `claimsFirst(sources.memberships)` (with `onStale: 'reread'` a fresh token costs one version call, and with `policy` a token that claims a custom role costs one `subject_for` call), `customRoles: sources.customRoles(principal)`, and `await sources.subject(userId)` for a job acting for a stored user. Create `postgrestSources` and the `claimsFirst` source once at module scope, never per request or per cache scope: they keep no answers, and `getPermDock` shares each read within one instance.
|
|
521
|
+
- When a page builds many instances (Next.js `'use cache: private'` islands, PPR) or an API serves many `GET`s per user, add `versions: memoryVersionCache({ maxStaleMs: 5_000 })` to `claimsFirst(sources.memberships, { onStale: 'reread' })` at module scope. Rendering and `GET` / `HEAD` / `OPTIONS` use intent `read` and share one version call per `maxStaleMs`; `protectAction`, other HTTP methods and core `getPermDock` use `write` and read live. Before a mutation outside `protectAction` in Next.js, call `getPermDock({ intent: 'write' })`. After a role change call `versions.evict(userId)` ([freshness and the version cache](https://permdock.com/docs/adapters/supabase#freshness-and-the-version-cache)).
|
|
527
522
|
- When a role table stores a role id (`user_roles.role_id`, `organization_users.role_id` referencing `roles`), read the key through it with `{ through: 'roles', on: { role_id: 'id' }, column: 'key' }`: in `rls.roles`, in `tableMembershipSource` `columns.role` or `junctionMembershipSource` `roles`, and in an `rls.memberships` table's `role`. Never copy keys into the membership table. Keep tenant custom-role keys apart from declared role names.
|
|
528
523
|
- When one membership row holds roles in several columns (a `tier` and a `role_id`), list them instead of building a union view: `role: ['tier', { through: 'roles', on: { role_id: 'id' }, column: 'key' }]` in `rls.memberships` and `tableMembershipSource` `columns.role`, `roles: { sources: [...] }` in `junctionMembershipSource`. The row holds every non-null key, and the holder-count triggers stay on the real table.
|
|
529
524
|
- When a membership table names a profile instead of a login (`customer_contacts.contact_profile_id` referencing `contact_profiles`, whose `user_id` is the login), read the user through it with `junctionMembershipSource` `user` or `tableMembershipSource` `columns.user`: `{ through: 'contact_profiles', on: { contact_profile_id: 'id' }, column: 'user_id' }`. Never copy `user_id` onto the membership rows. Keep `contact_profiles.user_id` server-owned (PD028).
|
|
@@ -540,9 +535,7 @@ import { createPermDock } from "permdock/supabase/middleware";
|
|
|
540
535
|
const { withPermDock, permdockHandler } = createPermDock(policy, {
|
|
541
536
|
subject: (ctx) =>
|
|
542
537
|
subjectFromSupabase(ctx.jwtClaims, {
|
|
543
|
-
claims: {
|
|
544
|
-
roles: "user_role",
|
|
545
|
-
},
|
|
538
|
+
claims: { roles: "user_role" },
|
|
546
539
|
declared: ["member", "admin"],
|
|
547
540
|
}),
|
|
548
541
|
});
|
package/dist/catalog-BCCjSAdH.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { t as catalogFile, n as runCatalog } from "./catalog-D69WhFii.js";
|
package/dist/collect-k_Dulxr5.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { r as runCollect } from "./collect-BaWeMjwV.js";
|