@keboola/api-client 54.0.0 → 56.0.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/API-SURFACE.md +3 -1
- package/CHANGELOG.md +61 -0
- package/README.md +1 -1
- package/dist/{adminRoles-BTKVwEy8.d.cts → adminRoles-BFOPSedO.d.cts} +2 -2
- package/dist/{adminRoles-Cm513r1G.d.ts → adminRoles-CUB0JddB.d.ts} +2 -2
- package/dist/ai/index.d.cts +2 -2
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/types.d.cts +1 -1
- package/dist/ai/types.d.ts +1 -1
- package/dist/apps/index.d.cts +2 -2
- package/dist/apps/index.d.ts +2 -2
- package/dist/apps/types.d.cts +1 -1
- package/dist/apps/types.d.ts +1 -1
- package/dist/assets/index.d.cts +1 -1
- package/dist/assets/index.d.ts +1 -1
- package/dist/auth/index.cjs +1 -1
- package/dist/auth/index.d.cts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/types.d.cts +1 -1
- package/dist/auth/types.d.ts +1 -1
- package/dist/{authClient-BM4L8XEN.js → authClient-B_Mb4Vzs.js} +3 -45
- package/dist/authClient-B_Mb4Vzs.js.map +1 -0
- package/dist/{authClient-DspK50e7.cjs → authClient-C9QqhT2M.cjs} +6 -60
- package/dist/authClient-C9QqhT2M.cjs.map +1 -0
- package/dist/{authClient-NBi0pqD5.d.cts → authClient-DOetdp2k.d.cts} +4 -4
- package/dist/{authClient-ij_Rm2Yn.d.ts → authClient-Dgyb0EFi.d.ts} +4 -4
- package/dist/billing/index.d.cts +1 -1
- package/dist/billing/index.d.ts +1 -1
- package/dist/billing/types.d.cts +1 -1
- package/dist/billing/types.d.ts +1 -1
- package/dist/chat/index.d.cts +2 -2
- package/dist/chat/index.d.ts +2 -2
- package/dist/chat/types.d.cts +1 -1
- package/dist/chat/types.d.ts +1 -1
- package/dist/collectByCursor-2-8SuJ-8.js +76 -0
- package/dist/collectByCursor-2-8SuJ-8.js.map +1 -0
- package/dist/collectByCursor-D58__WD1.cjs +105 -0
- package/dist/collectByCursor-D58__WD1.cjs.map +1 -0
- package/dist/{componentId-Cps6WBy1.js → componentId-Ba4gsJ9O.js} +3 -1
- package/dist/componentId-Ba4gsJ9O.js.map +1 -0
- package/dist/{componentId-_tRhEv6W.cjs → componentId-Ba_1Gv_A.cjs} +3 -1
- package/dist/componentId-Ba_1Gv_A.cjs.map +1 -0
- package/dist/componentsMcp/index.d.cts +1 -1
- package/dist/componentsMcp/index.d.ts +1 -1
- package/dist/componentsMcp/types.d.cts +1 -1
- package/dist/componentsMcp/types.d.ts +1 -1
- package/dist/constants/index.cjs +3 -2
- package/dist/constants/index.d.cts +4 -4
- package/dist/constants/index.d.ts +4 -4
- package/dist/constants/index.js +3 -3
- package/dist/{constants-DLPkpnGv.js → constants-HccvU5kx.js} +9 -2
- package/dist/constants-HccvU5kx.js.map +1 -0
- package/dist/{constants-Day8CU5i.cjs → constants-V9hAyPTo.cjs} +14 -1
- package/dist/constants-V9hAyPTo.cjs.map +1 -0
- package/dist/dataScience/index.d.cts +3 -3
- package/dist/dataScience/index.d.ts +3 -3
- package/dist/dataScience/types.d.cts +1 -1
- package/dist/dataScience/types.d.ts +1 -1
- package/dist/developerPortal/index.d.cts +2 -2
- package/dist/developerPortal/index.d.ts +2 -2
- package/dist/developerPortal/types.d.cts +1 -1
- package/dist/developerPortal/types.d.ts +1 -1
- package/dist/domain/permissions/index.d.cts +1 -1
- package/dist/domain/permissions/index.d.ts +1 -1
- package/dist/editor/index.d.cts +2 -2
- package/dist/editor/index.d.ts +2 -2
- package/dist/editor/types.d.cts +1 -1
- package/dist/editor/types.d.ts +1 -1
- package/dist/encryption/index.d.cts +1 -1
- package/dist/encryption/index.d.ts +1 -1
- package/dist/encryption/types.d.cts +1 -1
- package/dist/encryption/types.d.ts +1 -1
- package/dist/import/index.d.cts +3 -3
- package/dist/import/index.d.ts +3 -3
- package/dist/{index-DLWMm1-T.d.ts → index-A8udJCGv.d.ts} +4 -4
- package/dist/{index-d9zxFmNI.d.cts → index-B-HhOTVk.d.cts} +4 -4
- package/dist/{index-BVe4S2CK.d.ts → index-B2YNTI4p.d.ts} +4 -4
- package/dist/{index-CEDjFidH.d.ts → index-B30dBBBH.d.ts} +3 -3
- package/dist/{index-DbStyQKc.d.ts → index-B7Ogo2SK.d.ts} +12 -3
- package/dist/{index-CdeWTy8t.d.ts → index-BH1jo-bb.d.ts} +4 -4
- package/dist/{index-DTGOEke4.d.ts → index-BaJ-GMa7.d.ts} +3 -3
- package/dist/{index-DzqHh0lE.d.ts → index-Bgu3hnMO.d.ts} +528 -32
- package/dist/{index-DCfumWzq.d.ts → index-C6FI_Lc7.d.ts} +3 -3
- package/dist/{index-BGE3eZfd.d.cts → index-CLqZfRpv.d.cts} +3 -3
- package/dist/{index-CZvBjQvl.d.ts → index-CLxvW_pn.d.ts} +4 -4
- package/dist/{index-CQNwp6wX.d.ts → index-C_A0JS9s.d.ts} +3 -3
- package/dist/{index-B04rWq_0.d.cts → index-CmtqbTse.d.cts} +3 -3
- package/dist/{index-DX7qciZA.d.cts → index-CpidrJQc.d.cts} +528 -32
- package/dist/{index-Cd0naVic.d.cts → index-CxoJuIzB.d.cts} +12 -3
- package/dist/{index-B8K-Bbdq.d.cts → index-DAb1g6je.d.cts} +3 -3
- package/dist/{index-BtvWJBYh.d.cts → index-DPhGNQC5.d.cts} +150 -67
- package/dist/{index-CNJBmCHM.d.cts → index-DXNRd61K.d.cts} +4 -4
- package/dist/{index-FrsEkDvX.d.cts → index-DcKc3_Y1.d.cts} +3 -2
- package/dist/{index-FrsEkDvX.d.ts → index-DcKc3_Y1.d.ts} +3 -2
- package/dist/{index-8QhOqFLY.d.cts → index-Dx02AUpZ.d.cts} +4 -4
- package/dist/{index-BXgjPlZN.d.cts → index-DxbqDi_0.d.cts} +4 -4
- package/dist/{index-Df30jjpZ.d.ts → index-GlHJ4j3a.d.ts} +150 -67
- package/dist/{index-iFCann29.d.cts → index-RHYdFrfn.d.cts} +3 -3
- package/dist/index.cjs +14 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +10 -15
- package/dist/index.js.map +1 -1
- package/dist/kaiAgent/index.d.cts +2 -2
- package/dist/kaiAgent/index.d.ts +2 -2
- package/dist/kaiAgent/types.d.cts +1 -1
- package/dist/kaiAgent/types.d.ts +1 -1
- package/dist/management/index.cjs +1 -1
- package/dist/management/index.d.cts +1 -1
- package/dist/management/index.d.ts +1 -1
- package/dist/management/index.js +1 -1
- package/dist/management/types.d.cts +2 -2
- package/dist/management/types.d.ts +2 -2
- package/dist/{management-BAfg8BmK.js → management-BlMQnPNS.js} +10 -16
- package/dist/management-BlMQnPNS.js.map +1 -0
- package/dist/{management-BuNIc7Mr.cjs → management-dIMrTTpI.cjs} +10 -16
- package/dist/management-dIMrTTpI.cjs.map +1 -0
- package/dist/{metaObject-D7oudegV.d.cts → metaObject-BsBMgWRt.d.cts} +2 -2
- package/dist/{metaObject-ClvW342q.d.ts → metaObject-qWyZAD-5.d.ts} +2 -2
- package/dist/metastore/index.d.cts +1 -1
- package/dist/metastore/index.d.ts +1 -1
- package/dist/metastore/types.d.cts +1 -1
- package/dist/metastore/types.d.ts +1 -1
- package/dist/microsoftGraph/index.d.cts +2 -2
- package/dist/microsoftGraph/index.d.ts +2 -2
- package/dist/microsoftGraph/types.d.cts +1 -1
- package/dist/microsoftGraph/types.d.ts +1 -1
- package/dist/notifications/index.d.cts +2 -2
- package/dist/notifications/index.d.ts +2 -2
- package/dist/notifications/types.d.cts +1 -1
- package/dist/notifications/types.d.ts +1 -1
- package/dist/oauth/index.cjs +1 -1
- package/dist/oauth/index.d.cts +9 -2
- package/dist/oauth/index.d.ts +9 -2
- package/dist/oauth/index.js +1 -1
- package/dist/oauth/types.d.cts +2 -2
- package/dist/oauth/types.d.ts +2 -2
- package/dist/{oauth-CXcrilOp.cjs → oauth-CEW2AvDV.cjs} +9 -1
- package/dist/{oauth-CXcrilOp.cjs.map → oauth-CEW2AvDV.cjs.map} +1 -1
- package/dist/{oauth-Ci0qeaS2.js → oauth-Fri6IthS.js} +9 -1
- package/dist/{oauth-Ci0qeaS2.js.map → oauth-Fri6IthS.js.map} +1 -1
- package/dist/omnisearch/index.d.cts +2 -2
- package/dist/omnisearch/index.d.ts +2 -2
- package/dist/omnisearch/types.d.cts +1 -1
- package/dist/omnisearch/types.d.ts +1 -1
- package/dist/{project-DS0HOV3M.d.ts → project-CmV1OhK4.d.ts} +3 -3
- package/dist/{project-BGk9CtOq.d.cts → project-F6eHCACz.d.cts} +3 -3
- package/dist/queryService/index.d.cts +1 -1
- package/dist/queryService/index.d.ts +1 -1
- package/dist/queryService/types.d.cts +1 -1
- package/dist/queryService/types.d.ts +1 -1
- package/dist/queue/index.d.cts +3 -3
- package/dist/queue/index.d.ts +3 -3
- package/dist/queue/types.d.cts +1 -1
- package/dist/queue/types.d.ts +1 -1
- package/dist/scheduler/index.d.cts +2 -2
- package/dist/scheduler/index.d.ts +2 -2
- package/dist/scheduler/types.d.cts +1 -1
- package/dist/scheduler/types.d.ts +1 -1
- package/dist/sdk/configurations/index.cjs +47 -2
- package/dist/sdk/configurations/index.cjs.map +1 -1
- package/dist/sdk/configurations/index.d.cts +231 -3
- package/dist/sdk/configurations/index.d.ts +231 -3
- package/dist/sdk/configurations/index.js +47 -2
- package/dist/sdk/configurations/index.js.map +1 -1
- package/dist/sdk/dataAppServer/index.cjs +1 -1
- package/dist/sdk/dataAppServer/index.cjs.map +1 -1
- package/dist/sdk/dataAppServer/index.d.cts +1 -1
- package/dist/sdk/dataAppServer/index.d.ts +1 -1
- package/dist/sdk/dataAppServer/index.js +1 -1
- package/dist/sdk/dataAppServer/index.js.map +1 -1
- package/dist/sdk/developerPortal/index.d.cts +3 -3
- package/dist/sdk/developerPortal/index.d.ts +3 -3
- package/dist/sdk/kaiMemory/index.d.cts +1 -1
- package/dist/sdk/kaiMemory/index.d.ts +1 -1
- package/dist/sdk/kaiMemory/types.d.cts +1 -1
- package/dist/sdk/kaiMemory/types.d.ts +1 -1
- package/dist/sdk/queryService/index.d.cts +1 -1
- package/dist/sdk/queryService/index.d.ts +1 -1
- package/dist/sdk/securityPolicy/index.cjs +13 -3
- package/dist/sdk/securityPolicy/index.cjs.map +1 -1
- package/dist/sdk/securityPolicy/index.d.cts +13 -3
- package/dist/sdk/securityPolicy/index.d.ts +13 -3
- package/dist/sdk/securityPolicy/index.js +12 -4
- package/dist/sdk/securityPolicy/index.js.map +1 -1
- package/dist/sdk/securityPolicy/types.d.cts +1 -1
- package/dist/sdk/securityPolicy/types.d.ts +1 -1
- package/dist/sdk/semanticLayer/index.d.cts +1 -1
- package/dist/sdk/semanticLayer/index.d.ts +1 -1
- package/dist/sdk/semanticLayer/types.d.cts +1 -1
- package/dist/sdk/semanticLayer/types.d.ts +1 -1
- package/dist/sdk/tag/index.d.cts +2 -2
- package/dist/sdk/tag/index.d.ts +2 -2
- package/dist/sdk/tag/types.d.cts +1 -1
- package/dist/sdk/tag/types.d.ts +1 -1
- package/dist/sdk/vault/index.cjs +3 -12
- package/dist/sdk/vault/index.cjs.map +1 -1
- package/dist/sdk/vault/index.d.cts +1 -1
- package/dist/sdk/vault/index.d.ts +1 -1
- package/dist/sdk/vault/index.js +3 -12
- package/dist/sdk/vault/index.js.map +1 -1
- package/dist/status/index.d.cts +1 -1
- package/dist/status/index.d.ts +1 -1
- package/dist/storage/index.cjs +4 -4
- package/dist/storage/index.d.cts +3 -3
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +2 -2
- package/dist/storage/types.d.cts +6 -6
- package/dist/storage/types.d.ts +6 -6
- package/dist/{storage--2FvvLAw.js → storage-Bw-HSnPp.js} +56 -3
- package/dist/storage-Bw-HSnPp.js.map +1 -0
- package/dist/{storage-BMrYlyLB.cjs → storage-jLhVrKZh.cjs} +58 -5
- package/dist/storage-jLhVrKZh.cjs.map +1 -0
- package/dist/stream/index.d.cts +2 -2
- package/dist/stream/index.d.ts +2 -2
- package/dist/stream/types.d.cts +1 -1
- package/dist/stream/types.d.ts +1 -1
- package/dist/syncActions/index.cjs +1 -1
- package/dist/syncActions/index.d.cts +2 -2
- package/dist/syncActions/index.d.ts +2 -2
- package/dist/syncActions/index.js +1 -1
- package/dist/syncActions/types.d.cts +1 -1
- package/dist/syncActions/types.d.ts +1 -1
- package/dist/{syncActions-CR7xvuIv.cjs → syncActions-B9JTiSao.cjs} +2 -2
- package/dist/{syncActions-CR7xvuIv.cjs.map → syncActions-B9JTiSao.cjs.map} +1 -1
- package/dist/{syncActions-CU4cIGRf.js → syncActions-W98Jme2Z.js} +2 -2
- package/dist/{syncActions-CU4cIGRf.js.map → syncActions-W98Jme2Z.js.map} +1 -1
- package/dist/telemetry/index.d.cts +2 -2
- package/dist/telemetry/index.d.ts +2 -2
- package/dist/telemetry/types.d.cts +1 -1
- package/dist/telemetry/types.d.ts +1 -1
- package/dist/{types-B6f6LpZ_.d.cts → types--mz2z0Zm.d.cts} +2 -2
- package/dist/{types-B7FKoyfy.d.cts → types-2CMPwArl.d.ts} +820 -389
- package/dist/{types-CRC4lbPw.d.cts → types-3ZE32k8V.d.cts} +2 -2
- package/dist/{types-Do3__S4Q.d.cts → types-6oLbURTK.d.cts} +2 -2
- package/dist/{types-B4Vwz45w.d.cts → types-B452bFfS.d.ts} +2 -2
- package/dist/{types-zlYUn0oi.d.ts → types-B5FgsIiY.d.ts} +3 -3
- package/dist/{types-DFcj9YyQ.d.ts → types-B6OG1lLf.d.cts} +222 -55
- package/dist/{types-DNwIMEuB.d.cts → types-BDGkMVWf.d.cts} +2 -2
- package/dist/{types-CQYyULrw.d.ts → types-BEEGI4aq.d.ts} +2 -2
- package/dist/{types-Bv2Ds1hL.d.cts → types-BJRRAQ9R.d.cts} +2 -2
- package/dist/{types-D5bxXqEU.d.ts → types-B_yv00AL.d.ts} +2 -2
- package/dist/{types-DoSZQ1Bi.d.ts → types-BhGr9OQ4.d.ts} +2 -2
- package/dist/{types-D-ufoskb.d.cts → types-BmcZyKgM.d.cts} +17 -2
- package/dist/{types-dU3EA8gk.d.ts → types-BnkHyxdp.d.ts} +2 -2
- package/dist/{types-B4ezB18r.d.cts → types-BqJycQNM.d.cts} +2 -2
- package/dist/{types-CaBcgsT2.d.cts → types-ByKSM08P.d.ts} +222 -55
- package/dist/{types-Y4e8GGa3.d.cts → types-C3Kf_ggm.d.cts} +2 -2
- package/dist/{types-CIlBSV99.d.cts → types-CF5ZROX5.d.cts} +2 -2
- package/dist/{types-ChOJ-Az7.d.cts → types-CFuT8zr3.d.cts} +2 -2
- package/dist/{types-BXKL0wTI.d.cts → types-CNDemlfn.d.cts} +3 -3
- package/dist/{types-Rrcx-8LM.d.ts → types-CUovU--e.d.ts} +2 -2
- package/dist/{types-DU8aPTFW.d.cts → types-C_JO7FI9.d.cts} +2 -2
- package/dist/{types-BVJmcoqA.d.cts → types-CbPO9cGq.d.cts} +2 -2
- package/dist/{types-Dsf7CYmm.d.ts → types-Cg_66Toy.d.ts} +2 -2
- package/dist/{types-COb2O9c1.d.ts → types-CjqFLXVx.d.cts} +820 -389
- package/dist/{types-CSE8bHiq.d.cts → types-Cm1iOHE5.d.cts} +3 -3
- package/dist/{types-BD0B1KQ6.d.ts → types-CnKiVVb8.d.ts} +2 -2
- package/dist/{types-D2hhEGem.d.cts → types-CrXoqs8E.d.cts} +2 -2
- package/dist/{types-DCARsJWs.d.cts → types-CuYaiy4R.d.cts} +4 -4
- package/dist/{types-DjSjUKUl.d.ts → types-Cvbcjdgf.d.ts} +2 -2
- package/dist/{types-DKKHKj19.d.cts → types-D0BOES7q.d.cts} +2 -2
- package/dist/{types-kGZQQcIK.d.ts → types-D0Gqu-Xz.d.cts} +2 -2
- package/dist/{types-d5Bt8Mr3.d.ts → types-D2J3SaoY.d.ts} +2 -2
- package/dist/{types-Bp8G9yta.d.ts → types-D4knWlwr.d.ts} +2 -2
- package/dist/{types-BDgOF2WN.d.ts → types-D6Fbf_y3.d.ts} +4 -4
- package/dist/{types-Tg3euEN_.d.ts → types-DMEl2iet.d.ts} +2 -2
- package/dist/{types-CTYTMXXj.d.ts → types-DPFG6AAA.d.ts} +2 -2
- package/dist/{types-BynQKst1.d.cts → types-DQguGTlM.d.cts} +2 -2
- package/dist/{types-DbthI3r-.d.ts → types-DaRxZt3v.d.ts} +2 -2
- package/dist/{types-DX1Dz0xK.d.ts → types-DgAMVyiT.d.ts} +2 -2
- package/dist/{types-Cr6WA6CN.d.ts → types-DhE7iY90.d.ts} +17 -2
- package/dist/{types-B6JcEPEu.d.ts → types-DiXeO0yB.d.ts} +2 -2
- package/dist/{types-CKdNf_2k.d.cts → types-DslO1S5E.d.cts} +3 -3
- package/dist/{types-Cf0WE6qK.d.cts → types-DtS7qAdz.d.cts} +2 -2
- package/dist/{types-C5B3Pfob.d.cts → types-DykEfF2N.d.cts} +2 -2
- package/dist/{types-DSWIIMdv.d.ts → types-EdL0Eb0B.d.ts} +3 -3
- package/dist/{types-DK1bSUNr.d.ts → types-Foy0RnqF.d.ts} +3 -3
- package/dist/{types-BEw98Dd2.d.cts → types-LOf_GCej.d.cts} +2 -2
- package/dist/{types-OHt0D_f2.d.ts → types-lZRyNwOH.d.ts} +2 -2
- package/dist/{types-CepTvkfm.d.ts → types-p6UYqJo_.d.ts} +2 -2
- package/dist/vault/index.d.cts +1 -1
- package/dist/vault/index.d.ts +1 -1
- package/dist/vault/types.d.cts +1 -1
- package/dist/vault/types.d.ts +1 -1
- package/package.json +3 -3
- package/surface/management.md +25 -25
- package/surface/storage.md +5 -0
- package/dist/authClient-BM4L8XEN.js.map +0 -1
- package/dist/authClient-DspK50e7.cjs.map +0 -1
- package/dist/componentId-Cps6WBy1.js.map +0 -1
- package/dist/componentId-_tRhEv6W.cjs.map +0 -1
- package/dist/constants-DLPkpnGv.js.map +0 -1
- package/dist/constants-Day8CU5i.cjs.map +0 -1
- package/dist/management-BAfg8BmK.js.map +0 -1
- package/dist/management-BuNIc7Mr.cjs.map +0 -1
- package/dist/storage--2FvvLAw.js.map +0 -1
- package/dist/storage-BMrYlyLB.cjs.map +0 -1
- package/dist/validateConnectionStatus-DV00sDmu.js +0 -34
- package/dist/validateConnectionStatus-DV00sDmu.js.map +0 -1
- package/dist/validateConnectionStatus-ckaHcRx8.cjs +0 -51
- package/dist/validateConnectionStatus-ckaHcRx8.cjs.map +0 -1
|
@@ -110,6 +110,15 @@ const securityPolicyReadSchema = require_metaObject.metastoreObjectReadSchema(po
|
|
|
110
110
|
const DEFAULT_BRANCH = "main";
|
|
111
111
|
/** The rule schema Kai writes; a policy created under another version keeps its own. */
|
|
112
112
|
const CURRENT_SCHEMA_VERSION = "1.2.0";
|
|
113
|
+
/** A policy stored under an older rule schema: the metastore refuses current rules for it. */
|
|
114
|
+
const isLegacySecurityPolicy = (meta) => meta.schemaVersion !== void 0 && meta.schemaVersion !== CURRENT_SCHEMA_VERSION;
|
|
115
|
+
const onDefaultBranch = (policy) => policy.meta.branch === void 0 || policy.meta.branch === DEFAULT_BRANCH;
|
|
116
|
+
/**
|
|
117
|
+
* Whether `projectId` owns the policy on `main`: a create for its table replaces it.
|
|
118
|
+
*
|
|
119
|
+
* - Others' policies on the table are never replaced; they stack with the project's own.
|
|
120
|
+
*/
|
|
121
|
+
const isReplaceableSecurityPolicy = (policy, projectId) => policy.meta.projectId === projectId && onDefaultBranch(policy);
|
|
113
122
|
/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */
|
|
114
123
|
var SecurityPolicyAmbiguousError = class extends Error {
|
|
115
124
|
policyType;
|
|
@@ -211,7 +220,6 @@ const parsePolicies = (policyType, data) => {
|
|
|
211
220
|
};
|
|
212
221
|
const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
213
222
|
const isOwn = (policy) => policy.meta.projectId === projectId;
|
|
214
|
-
const onDefaultBranch = (policy) => policy.meta.branch === void 0 || policy.meta.branch === DEFAULT_BRANCH;
|
|
215
223
|
/**
|
|
216
224
|
* Every policy of one type the caller can read.
|
|
217
225
|
*
|
|
@@ -268,7 +276,7 @@ const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
|
268
276
|
known = listed.policies;
|
|
269
277
|
}
|
|
270
278
|
const onTable = known.filter((policy) => policy.data.table === table && onDefaultBranch(policy));
|
|
271
|
-
const owned = onTable.filter(
|
|
279
|
+
const owned = onTable.filter((policy) => isReplaceableSecurityPolicy(policy, projectId));
|
|
272
280
|
const otherPolicyUuids = onTable.filter((policy) => !isOwn(policy)).map((policy) => policy.uuid);
|
|
273
281
|
const current = options.uuid === void 0 ? owned[0] : owned.find((policy) => policy.uuid === options.uuid);
|
|
274
282
|
if (options.uuid !== void 0 && current === void 0) throw new SecurityPolicyNotFoundError({
|
|
@@ -282,7 +290,7 @@ const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
|
282
290
|
uuids: owned.map((policy) => policy.uuid)
|
|
283
291
|
});
|
|
284
292
|
if (current) {
|
|
285
|
-
if (current.meta
|
|
293
|
+
if (isLegacySecurityPolicy(current.meta)) throw new SecurityPolicyLegacyError({
|
|
286
294
|
policyType,
|
|
287
295
|
uuid: current.uuid,
|
|
288
296
|
schemaVersion: current.meta.schemaVersion
|
|
@@ -350,6 +358,8 @@ exports.SecurityPolicyNotFoundError = SecurityPolicyNotFoundError;
|
|
|
350
358
|
exports.SecurityPolicyUnreadableError = SecurityPolicyUnreadableError;
|
|
351
359
|
exports.clsPolicySchema = clsPolicySchema;
|
|
352
360
|
exports.createSecurityPolicySdk = createSecurityPolicySdk;
|
|
361
|
+
exports.isLegacySecurityPolicy = isLegacySecurityPolicy;
|
|
362
|
+
exports.isReplaceableSecurityPolicy = isReplaceableSecurityPolicy;
|
|
353
363
|
exports.rlsPolicySchema = rlsPolicySchema;
|
|
354
364
|
|
|
355
365
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["z","z","metastoreObjectReadSchema","parseOrThrow","z","formatValidationIssues","isApiError","metastoreErrorMessage"],"sources":["../../../src/sdks/securityPolicy/vocabulary.ts","../../../src/sdks/securityPolicy/schemas.ts","../../../src/sdks/securityPolicy/readSchemas.ts","../../../src/sdks/securityPolicy/securityPolicySdk.ts"],"sourcesContent":["/**\n * The metastore's row- and column-level security vocabulary, schema version 1.2.0.\n *\n * - Each list is the one place a value is added; the types in `./types` derive from it.\n */\n\nexport const SECURITY_POLICY_TYPES = ['rls-policy', 'cls-policy'] as const;\n\nexport const POLICY_SQL_DIALECTS = ['snowflake', 'bigquery'] as const;\n\nexport const RLS_COMPARISON_OPS = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'] as const;\n\nexport const RLS_LIST_OPS = ['in', 'not_in'] as const;\n\nexport const RLS_NULL_OPS = ['is_null', 'is_not_null'] as const;\n","import { z } from 'zod';\n\nimport type { ClsPolicyData, RlsCondition, RlsPolicyData } from './types';\nimport { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS } from './vocabulary';\n\n/** A `<bucket>.<table>` key; also the policy's metastore name. */\nconst POLICY_TABLE_PATTERN = /^[A-Za-z0-9_.-]+\\.[A-Za-z0-9_-]+$/;\n\n/** Columns are SQL identifiers that cannot be parameterised, so this pattern is the boundary. */\nconst POLICY_COLUMN_PATTERN = /^[A-Za-z0-9_]+$/;\n\n/** A reader selector `<idp>|<sub>`: the identity provider's issuer, a `|`, the user's `sub`. */\nconst POLICY_SUBJECT_PATTERN = /^[^|\\s]+\\|\\S.*$/;\n\n/**\n * Write validators for untrusted policy input, mirroring metastore schema 1.2.0.\n *\n * - Strict: an unknown key fails, as `additionalProperties: false` does in the metastore.\n * - The identifier patterns are the boundary: `table` and `column` reach SQL unparameterised.\n * - Stricter than the metastore on purpose: a `value` is a string, number, boolean or null, and\n * `values` holds the same; the metastore also lets an arbitrary JSON value through.\n * - The metastore stays the authority; this reports the first problem in words the model can act on.\n */\n\nconst column = z.string().regex(POLICY_COLUMN_PATTERN, 'column must match [A-Za-z0-9_]+');\n\nconst literal = z.union([z.string(), z.number(), z.boolean(), z.null()]);\n\nconst identityEmail = z.strictObject({ $identity: z.literal('email') });\nconst identityGroups = z.strictObject({ $identity: z.literal('groups') });\n\nconst rlsCondition: z.ZodType<RlsCondition> = z.lazy(() =>\n z.union([\n z.strictObject({ true: z.literal(true) }),\n z.strictObject({ false: z.literal(true) }),\n z.strictObject({ and: z.array(rlsCondition).min(2) }),\n z.strictObject({ or: z.array(rlsCondition).min(2) }),\n z.strictObject({\n column,\n op: z.enum(RLS_COMPARISON_OPS),\n value: z.union([literal, identityEmail]),\n }),\n z.strictObject({\n column,\n op: z.enum(RLS_LIST_OPS),\n values: z.union([z.array(literal).min(1), identityGroups]),\n }),\n z.strictObject({ column, op: z.enum(RLS_NULL_OPS) }),\n ]),\n);\n\n/** `[\"*\"]` is everyone and must be the only entry. */\nconst selectorList = (item: z.ZodType<string>) =>\n z\n .array(item)\n .min(1)\n .refine((list) => !list.includes('*') || list.length === 1, {\n message: '\"*\" must be the only entry',\n });\n\nconst subjects = selectorList(\n z.union([\n z.literal('*'),\n z\n .string()\n .max(1024)\n .regex(POLICY_SUBJECT_PATTERN, 'a subject is \"<idp>|<sub>\", never an email'),\n ]),\n);\nconst groups = selectorList(z.string().min(1));\n\n/** A rule selects readers by exactly one of `subjects` or `groups`, then carries `shape`. */\nconst rule = <Shape extends z.ZodRawShape>(shape: Shape) =>\n z.union([z.strictObject({ subjects, ...shape }), z.strictObject({ groups, ...shape })]);\n\nconst table = z.string().regex(POLICY_TABLE_PATTERN, 'table must be \"<bucket>.<table>\"');\nconst dialect = z.enum(POLICY_SQL_DIALECTS).optional();\n\nexport const rlsPolicySchema: z.ZodType<RlsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ condition: rlsCondition })).min(1),\n default: rlsCondition.optional(),\n});\n\nexport const clsPolicySchema: z.ZodType<ClsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ visible_columns: z.array(column).min(1) })).min(1),\n});\n","import { z } from 'zod';\n\nimport { metastoreObjectReadSchema } from '../../clients/metastore/metaObject';\n\nimport type { SecurityPolicyReadData } from './types';\nimport { POLICY_SQL_DIALECTS } from './vocabulary';\n\n/**\n * What a read of the metastore may hand back for a policy.\n *\n * - `looseObject`: fields the metastore adds still reach callers.\n * - An unknown `dialect` reads as absent; a missing `table` or `rules` drops the object.\n * - The envelope is the metastore's own, shared with every object family.\n */\n\nconst policyReadDataSchema: z.ZodType<SecurityPolicyReadData, unknown> = z.looseObject({\n table: z.string(),\n dialect: z.enum(POLICY_SQL_DIALECTS).optional().catch(undefined),\n rules: z.array(z.record(z.string(), z.unknown())),\n default: z.unknown().optional(),\n});\n\nexport const securityPolicyReadSchema = metastoreObjectReadSchema(policyReadDataSchema);\n","import { z } from 'zod';\n\nimport { metastoreErrorMessage } from '../../clients/metastore/errorMessage';\nimport { formatValidationIssues, parseOrThrow } from '../../errors';\nimport { isApiError } from '../../fetchClient';\n\nimport { securityPolicyReadSchema } from './readSchemas';\nimport type {\n MetastoreClient,\n SecurityPolicy,\n SecurityPolicyDataMap,\n SecurityPolicyType,\n} from './types';\n\nconst DEFAULT_BRANCH = 'main';\n\n/** The rule schema Kai writes; a policy created under another version keeps its own. */\nconst CURRENT_SCHEMA_VERSION = '1.2.0';\n\n/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */\nexport class SecurityPolicyAmbiguousError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuids: string[];\n\n constructor({\n policyType,\n table,\n uuids,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuids: string[];\n }) {\n super(\n `The project has ${uuids.length} ${policyType} policies for table '${table}' ` +\n `(${uuids.join(', ')}); pass the uuid of the one to replace.`,\n );\n this.name = 'SecurityPolicyAmbiguousError';\n this.policyType = policyType;\n this.table = table;\n this.uuids = uuids;\n }\n}\n\n/**\n * Thrown by `deletePolicy` on a `409`: other objects still reference the policy, nothing was deleted.\n *\n * - The metastore does not name the referencing objects, so none is reported here.\n */\nexport class SecurityPolicyInUseError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n\n constructor({\n policyType,\n uuid,\n reason,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n reason?: string;\n }) {\n super(reason ?? `The ${policyType} policy '${uuid}' is still bound and was not deleted.`);\n this.name = 'SecurityPolicyInUseError';\n this.policyType = policyType;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when some policy of the type could not be read.\n *\n * - Whether that policy governs the table is unknown, and a second policy on it would AND with it.\n */\nexport class SecurityPolicyUnreadableError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly count: number;\n\n constructor({ policyType, count }: { policyType: SecurityPolicyType; count: number }) {\n super(\n `${count} ${policyType} polic${count === 1 ? 'y' : 'ies'} of the project could not be read, ` +\n `so it is unknown whether the table already has one; nothing was written.`,\n );\n this.name = 'SecurityPolicyUnreadableError';\n this.policyType = policyType;\n this.count = count;\n }\n}\n\n/** The caller named a policy by `uuid` that the project does not own for the table. */\nexport class SecurityPolicyNotFoundError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuid: string;\n\n constructor({\n policyType,\n table,\n uuid,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuid: string;\n }) {\n super(`The project owns no ${policyType} '${uuid}' for table '${table}'.`);\n this.name = 'SecurityPolicyNotFoundError';\n this.policyType = policyType;\n this.table = table;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when the policy to replace was written under an older schema.\n *\n * - The metastore validates a write against the schema version the object already has, so 1.2.0\n * `subjects` on a 1.0.0 or 1.1.0 policy (`principal`, `principals`) fail with a 422.\n * - Nothing was written. Delete the policy and create it again; a policy an app binds cannot be deleted.\n */\nexport class SecurityPolicyLegacyError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n readonly schemaVersion: string;\n\n constructor({\n policyType,\n uuid,\n schemaVersion,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n schemaVersion: string;\n }) {\n super(\n `The ${policyType} '${uuid}' is on schema ${schemaVersion}, not ${CURRENT_SCHEMA_VERSION}, ` +\n `and the metastore keeps a policy on the schema it was created with; nothing was written.`,\n );\n this.name = 'SecurityPolicyLegacyError';\n this.policyType = policyType;\n this.uuid = uuid;\n this.schemaVersion = schemaVersion;\n }\n}\n\ntype Options = {\n metastoreClient: MetastoreClient;\n /** The project the caller writes as; a policy it owns carries this in `meta.projectId`. */\n projectId: number;\n};\n\n/**\n * The policies in a metastore collection response.\n *\n * - A malformed element is dropped, logged without its payload and counted in `unreadable`.\n * - A response that is not a collection throws.\n */\nconst parsePolicies = (\n policyType: SecurityPolicyType,\n data: unknown,\n): { policies: SecurityPolicy[]; unreadable: number } => {\n const items = parseOrThrow(z.array(z.unknown()), data);\n\n const policies: SecurityPolicy[] = [];\n let unreadable = 0;\n for (const item of items) {\n const result = securityPolicyReadSchema.safeParse(item);\n if (result.success) {\n policies.push(result.data);\n continue;\n }\n\n unreadable += 1;\n // Never log the payload: it holds customer identities.\n console.warn(\n `securityPolicySdk: dropped a ${policyType} from the metastore response, it does not ` +\n `match its declared shape`,\n formatValidationIssues(result.error.issues),\n );\n }\n return { policies, unreadable };\n};\n\nexport const createSecurityPolicySdk = ({ metastoreClient, projectId }: Options) => {\n const isOwn = (policy: SecurityPolicy) => policy.meta.projectId === projectId;\n\n // A list without `branch` returns every branch, and a create always writes `main`: a policy on\n // another branch is neither the one to replace nor one that stacks with it.\n const onDefaultBranch = (policy: SecurityPolicy) =>\n policy.meta.branch === undefined || policy.meta.branch === DEFAULT_BRANCH;\n\n /**\n * Every policy of one type the caller can read.\n *\n * - A project admin reads only the policies the project owns. An organization admin also reads\n * organization-scope policies and ones shared into the project; `meta.projectId` tells them apart.\n * - A malformed element is dropped and logged; `listPoliciesWithUnreadable` also counts them.\n * - A response that is not a collection throws.\n */\n const listPoliciesWithUnreadable = async (\n policyType: SecurityPolicyType,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjects(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data);\n };\n\n const listPolicies = async (policyType: SecurityPolicyType, signal?: AbortSignal) =>\n (await listPoliciesWithUnreadable(policyType, signal)).policies;\n\n /**\n * One policy by UUID, from any project or scope the caller can read.\n *\n * - A policy that does not parse throws a `ValidationError` rather than reading as missing.\n * - `404`: no such policy, or the caller cannot see it.\n */\n const getPolicy = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObject(\n { objectType: policyType, UUID: policyUUID },\n signal,\n );\n return parseOrThrow(securityPolicyReadSchema, response.data);\n };\n\n /**\n * Every revision of one policy, newest first.\n *\n * - The metastore lists revisions per object type only, so this reads them all and keeps the policy's.\n * - A revision that does not parse is dropped and logged, as in `listPolicies`.\n */\n const listRevisions = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjectRevisions(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data)\n .policies.filter((revision) => revision.uuid === policyUUID)\n .sort((a, b) => (b.meta.revision ?? 0) - (a.meta.revision ?? 0));\n };\n\n /**\n * Creates the policy for its table, or replaces the one the project owns for it (a PUT).\n *\n * - Found by table on `main`; several owned ones throw `SecurityPolicyAmbiguousError`, `uuid` picks one.\n * - Others' policies are never replaced and come back in `otherPolicyUuids`; no scope is sent.\n * - Refused, nothing written: an unreadable policy of the type, or a legacy-schema one to replace.\n * - `existing`: a batch shares one listing, checks `unreadable` itself and must not repeat a table.\n */\n const upsertPolicy = async <T extends SecurityPolicyType>(\n policyType: T,\n data: SecurityPolicyDataMap[T],\n options: { existing?: SecurityPolicy[]; uuid?: string } = {},\n ): Promise<{ action: 'created' | 'updated'; uuid: string; otherPolicyUuids: string[] }> => {\n const { table } = data;\n let known = options.existing;\n if (known === undefined) {\n const listed = await listPoliciesWithUnreadable(policyType);\n if (listed.unreadable > 0) {\n throw new SecurityPolicyUnreadableError({ policyType, count: listed.unreadable });\n }\n known = listed.policies;\n }\n const onTable = known.filter(\n (policy) => policy.data.table === table && onDefaultBranch(policy),\n );\n const owned = onTable.filter(isOwn);\n const otherPolicyUuids = onTable\n .filter((policy) => !isOwn(policy))\n .map((policy) => policy.uuid);\n\n const current =\n options.uuid === undefined ? owned[0] : owned.find((policy) => policy.uuid === options.uuid);\n if (options.uuid !== undefined && current === undefined) {\n throw new SecurityPolicyNotFoundError({ policyType, table, uuid: options.uuid });\n }\n if (options.uuid === undefined && owned.length > 1) {\n throw new SecurityPolicyAmbiguousError({\n policyType,\n table,\n uuids: owned.map((policy) => policy.uuid),\n });\n }\n\n if (current) {\n if (\n current.meta.schemaVersion !== undefined &&\n current.meta.schemaVersion !== CURRENT_SCHEMA_VERSION\n ) {\n throw new SecurityPolicyLegacyError({\n policyType,\n uuid: current.uuid,\n schemaVersion: current.meta.schemaVersion,\n });\n }\n await metastoreClient.repository.replaceMetaObject({\n objectType: policyType,\n UUID: current.uuid,\n data,\n name: current.meta.name ?? table,\n });\n return { action: 'updated', uuid: current.uuid, otherPolicyUuids };\n }\n\n const created = await metastoreClient.repository.createMetaObject({\n objectType: policyType,\n data,\n branch: DEFAULT_BRANCH,\n name: table,\n });\n return { action: 'created', uuid: created.data.id, otherPolicyUuids };\n };\n\n /**\n * - `SecurityPolicyInUseError` (`409`): other objects still reference the policy; nothing was deleted.\n * - `404`: no such policy, or it was already deleted.\n */\n const deletePolicy = async (policyType: SecurityPolicyType, policyUUID: string) => {\n try {\n await metastoreClient.repository.deleteMetaObject({\n objectType: policyType,\n UUID: policyUUID,\n });\n } catch (error) {\n if (!isApiError(error) || error.response.status !== 409) throw error;\n throw new SecurityPolicyInUseError({\n policyType,\n uuid: policyUUID,\n reason: metastoreErrorMessage(error.data),\n });\n }\n };\n\n return {\n listPolicies,\n listPoliciesWithUnreadable,\n getPolicy,\n listRevisions,\n upsertPolicy,\n deletePolicy,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["z","z","metastoreObjectReadSchema","parseOrThrow","z","formatValidationIssues","isApiError","metastoreErrorMessage"],"sources":["../../../src/sdks/securityPolicy/vocabulary.ts","../../../src/sdks/securityPolicy/schemas.ts","../../../src/sdks/securityPolicy/readSchemas.ts","../../../src/sdks/securityPolicy/securityPolicySdk.ts"],"sourcesContent":["/**\n * The metastore's row- and column-level security vocabulary, schema version 1.2.0.\n *\n * - Each list is the one place a value is added; the types in `./types` derive from it.\n */\n\nexport const SECURITY_POLICY_TYPES = ['rls-policy', 'cls-policy'] as const;\n\nexport const POLICY_SQL_DIALECTS = ['snowflake', 'bigquery'] as const;\n\nexport const RLS_COMPARISON_OPS = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'] as const;\n\nexport const RLS_LIST_OPS = ['in', 'not_in'] as const;\n\nexport const RLS_NULL_OPS = ['is_null', 'is_not_null'] as const;\n","import { z } from 'zod';\n\nimport type { ClsPolicyData, RlsCondition, RlsPolicyData } from './types';\nimport { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS } from './vocabulary';\n\n/** A `<bucket>.<table>` key; also the policy's metastore name. */\nconst POLICY_TABLE_PATTERN = /^[A-Za-z0-9_.-]+\\.[A-Za-z0-9_-]+$/;\n\n/** Columns are SQL identifiers that cannot be parameterised, so this pattern is the boundary. */\nconst POLICY_COLUMN_PATTERN = /^[A-Za-z0-9_]+$/;\n\n/** A reader selector `<idp>|<sub>`: the identity provider's issuer, a `|`, the user's `sub`. */\nconst POLICY_SUBJECT_PATTERN = /^[^|\\s]+\\|\\S.*$/;\n\n/**\n * Write validators for untrusted policy input, mirroring metastore schema 1.2.0.\n *\n * - Strict: an unknown key fails, as `additionalProperties: false` does in the metastore.\n * - The identifier patterns are the boundary: `table` and `column` reach SQL unparameterised.\n * - Stricter than the metastore on purpose: a `value` is a string, number, boolean or null, and\n * `values` holds the same; the metastore also lets an arbitrary JSON value through.\n * - The metastore stays the authority; this reports the first problem in words the model can act on.\n */\n\nconst column = z.string().regex(POLICY_COLUMN_PATTERN, 'column must match [A-Za-z0-9_]+');\n\nconst literal = z.union([z.string(), z.number(), z.boolean(), z.null()]);\n\nconst identityEmail = z.strictObject({ $identity: z.literal('email') });\nconst identityGroups = z.strictObject({ $identity: z.literal('groups') });\n\nconst rlsCondition: z.ZodType<RlsCondition> = z.lazy(() =>\n z.union([\n z.strictObject({ true: z.literal(true) }),\n z.strictObject({ false: z.literal(true) }),\n z.strictObject({ and: z.array(rlsCondition).min(2) }),\n z.strictObject({ or: z.array(rlsCondition).min(2) }),\n z.strictObject({\n column,\n op: z.enum(RLS_COMPARISON_OPS),\n value: z.union([literal, identityEmail]),\n }),\n z.strictObject({\n column,\n op: z.enum(RLS_LIST_OPS),\n values: z.union([z.array(literal).min(1), identityGroups]),\n }),\n z.strictObject({ column, op: z.enum(RLS_NULL_OPS) }),\n ]),\n);\n\n/** `[\"*\"]` is everyone and must be the only entry. */\nconst selectorList = (item: z.ZodType<string>) =>\n z\n .array(item)\n .min(1)\n .refine((list) => !list.includes('*') || list.length === 1, {\n message: '\"*\" must be the only entry',\n });\n\nconst subjects = selectorList(\n z.union([\n z.literal('*'),\n z\n .string()\n .max(1024)\n .regex(POLICY_SUBJECT_PATTERN, 'a subject is \"<idp>|<sub>\", never an email'),\n ]),\n);\nconst groups = selectorList(z.string().min(1));\n\n/** A rule selects readers by exactly one of `subjects` or `groups`, then carries `shape`. */\nconst rule = <Shape extends z.ZodRawShape>(shape: Shape) =>\n z.union([z.strictObject({ subjects, ...shape }), z.strictObject({ groups, ...shape })]);\n\nconst table = z.string().regex(POLICY_TABLE_PATTERN, 'table must be \"<bucket>.<table>\"');\nconst dialect = z.enum(POLICY_SQL_DIALECTS).optional();\n\nexport const rlsPolicySchema: z.ZodType<RlsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ condition: rlsCondition })).min(1),\n default: rlsCondition.optional(),\n});\n\nexport const clsPolicySchema: z.ZodType<ClsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ visible_columns: z.array(column).min(1) })).min(1),\n});\n","import { z } from 'zod';\n\nimport { metastoreObjectReadSchema } from '../../clients/metastore/metaObject';\n\nimport type { SecurityPolicyReadData } from './types';\nimport { POLICY_SQL_DIALECTS } from './vocabulary';\n\n/**\n * What a read of the metastore may hand back for a policy.\n *\n * - `looseObject`: fields the metastore adds still reach callers.\n * - An unknown `dialect` reads as absent; a missing `table` or `rules` drops the object.\n * - The envelope is the metastore's own, shared with every object family.\n */\n\nconst policyReadDataSchema: z.ZodType<SecurityPolicyReadData, unknown> = z.looseObject({\n table: z.string(),\n dialect: z.enum(POLICY_SQL_DIALECTS).optional().catch(undefined),\n rules: z.array(z.record(z.string(), z.unknown())),\n default: z.unknown().optional(),\n});\n\nexport const securityPolicyReadSchema = metastoreObjectReadSchema(policyReadDataSchema);\n","import { z } from 'zod';\n\nimport { metastoreErrorMessage } from '../../clients/metastore/errorMessage';\nimport { formatValidationIssues, parseOrThrow } from '../../errors';\nimport { isApiError } from '../../fetchClient';\n\nimport { securityPolicyReadSchema } from './readSchemas';\nimport type {\n MetastoreClient,\n SecurityPolicy,\n SecurityPolicyDataMap,\n SecurityPolicyType,\n} from './types';\n\nconst DEFAULT_BRANCH = 'main';\n\n/** The rule schema Kai writes; a policy created under another version keeps its own. */\nconst CURRENT_SCHEMA_VERSION = '1.2.0';\n\n/** A policy stored under an older rule schema: the metastore refuses current rules for it. */\nexport const isLegacySecurityPolicy = (\n meta: SecurityPolicy['meta'],\n): meta is SecurityPolicy['meta'] & { schemaVersion: string } =>\n meta.schemaVersion !== undefined && meta.schemaVersion !== CURRENT_SCHEMA_VERSION;\n\n// A list without `branch` returns every branch, and a create always writes `main`: a policy on\n// another branch is neither the one to replace nor one that stacks with it.\nconst onDefaultBranch = (policy: SecurityPolicy) =>\n policy.meta.branch === undefined || policy.meta.branch === DEFAULT_BRANCH;\n\n/**\n * Whether `projectId` owns the policy on `main`: a create for its table replaces it.\n *\n * - Others' policies on the table are never replaced; they stack with the project's own.\n */\nexport const isReplaceableSecurityPolicy = (policy: SecurityPolicy, projectId: number) =>\n policy.meta.projectId === projectId && onDefaultBranch(policy);\n\n/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */\nexport class SecurityPolicyAmbiguousError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuids: string[];\n\n constructor({\n policyType,\n table,\n uuids,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuids: string[];\n }) {\n super(\n `The project has ${uuids.length} ${policyType} policies for table '${table}' ` +\n `(${uuids.join(', ')}); pass the uuid of the one to replace.`,\n );\n this.name = 'SecurityPolicyAmbiguousError';\n this.policyType = policyType;\n this.table = table;\n this.uuids = uuids;\n }\n}\n\n/**\n * Thrown by `deletePolicy` on a `409`: other objects still reference the policy, nothing was deleted.\n *\n * - The metastore does not name the referencing objects, so none is reported here.\n */\nexport class SecurityPolicyInUseError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n\n constructor({\n policyType,\n uuid,\n reason,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n reason?: string;\n }) {\n super(reason ?? `The ${policyType} policy '${uuid}' is still bound and was not deleted.`);\n this.name = 'SecurityPolicyInUseError';\n this.policyType = policyType;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when some policy of the type could not be read.\n *\n * - Whether that policy governs the table is unknown, and a second policy on it would AND with it.\n */\nexport class SecurityPolicyUnreadableError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly count: number;\n\n constructor({ policyType, count }: { policyType: SecurityPolicyType; count: number }) {\n super(\n `${count} ${policyType} polic${count === 1 ? 'y' : 'ies'} of the project could not be read, ` +\n `so it is unknown whether the table already has one; nothing was written.`,\n );\n this.name = 'SecurityPolicyUnreadableError';\n this.policyType = policyType;\n this.count = count;\n }\n}\n\n/** The caller named a policy by `uuid` that the project does not own for the table. */\nexport class SecurityPolicyNotFoundError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuid: string;\n\n constructor({\n policyType,\n table,\n uuid,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuid: string;\n }) {\n super(`The project owns no ${policyType} '${uuid}' for table '${table}'.`);\n this.name = 'SecurityPolicyNotFoundError';\n this.policyType = policyType;\n this.table = table;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when the policy to replace was written under an older schema.\n *\n * - The metastore validates a write against the schema version the object already has, so 1.2.0\n * `subjects` on a 1.0.0 or 1.1.0 policy (`principal`, `principals`) fail with a 422.\n * - Nothing was written. Delete the policy and create it again; a policy an app binds cannot be deleted.\n */\nexport class SecurityPolicyLegacyError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n readonly schemaVersion: string;\n\n constructor({\n policyType,\n uuid,\n schemaVersion,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n schemaVersion: string;\n }) {\n super(\n `The ${policyType} '${uuid}' is on schema ${schemaVersion}, not ${CURRENT_SCHEMA_VERSION}, ` +\n `and the metastore keeps a policy on the schema it was created with; nothing was written.`,\n );\n this.name = 'SecurityPolicyLegacyError';\n this.policyType = policyType;\n this.uuid = uuid;\n this.schemaVersion = schemaVersion;\n }\n}\n\ntype Options = {\n metastoreClient: MetastoreClient;\n /** The project the caller writes as; a policy it owns carries this in `meta.projectId`. */\n projectId: number;\n};\n\n/**\n * The policies in a metastore collection response.\n *\n * - A malformed element is dropped, logged without its payload and counted in `unreadable`.\n * - A response that is not a collection throws.\n */\nconst parsePolicies = (\n policyType: SecurityPolicyType,\n data: unknown,\n): { policies: SecurityPolicy[]; unreadable: number } => {\n const items = parseOrThrow(z.array(z.unknown()), data);\n\n const policies: SecurityPolicy[] = [];\n let unreadable = 0;\n for (const item of items) {\n const result = securityPolicyReadSchema.safeParse(item);\n if (result.success) {\n policies.push(result.data);\n continue;\n }\n\n unreadable += 1;\n // Never log the payload: it holds customer identities.\n console.warn(\n `securityPolicySdk: dropped a ${policyType} from the metastore response, it does not ` +\n `match its declared shape`,\n formatValidationIssues(result.error.issues),\n );\n }\n return { policies, unreadable };\n};\n\nexport const createSecurityPolicySdk = ({ metastoreClient, projectId }: Options) => {\n const isOwn = (policy: SecurityPolicy) => policy.meta.projectId === projectId;\n\n /**\n * Every policy of one type the caller can read.\n *\n * - A project admin reads only the policies the project owns. An organization admin also reads\n * organization-scope policies and ones shared into the project; `meta.projectId` tells them apart.\n * - A malformed element is dropped and logged; `listPoliciesWithUnreadable` also counts them.\n * - A response that is not a collection throws.\n */\n const listPoliciesWithUnreadable = async (\n policyType: SecurityPolicyType,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjects(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data);\n };\n\n const listPolicies = async (policyType: SecurityPolicyType, signal?: AbortSignal) =>\n (await listPoliciesWithUnreadable(policyType, signal)).policies;\n\n /**\n * One policy by UUID, from any project or scope the caller can read.\n *\n * - A policy that does not parse throws a `ValidationError` rather than reading as missing.\n * - `404`: no such policy, or the caller cannot see it.\n */\n const getPolicy = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObject(\n { objectType: policyType, UUID: policyUUID },\n signal,\n );\n return parseOrThrow(securityPolicyReadSchema, response.data);\n };\n\n /**\n * Every revision of one policy, newest first.\n *\n * - The metastore lists revisions per object type only, so this reads them all and keeps the policy's.\n * - A revision that does not parse is dropped and logged, as in `listPolicies`.\n */\n const listRevisions = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjectRevisions(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data)\n .policies.filter((revision) => revision.uuid === policyUUID)\n .sort((a, b) => (b.meta.revision ?? 0) - (a.meta.revision ?? 0));\n };\n\n /**\n * Creates the policy for its table, or replaces the one the project owns for it (a PUT).\n *\n * - Found by table on `main`; several owned ones throw `SecurityPolicyAmbiguousError`, `uuid` picks one.\n * - Others' policies are never replaced and come back in `otherPolicyUuids`; no scope is sent.\n * - Refused, nothing written: an unreadable policy of the type, or a legacy-schema one to replace.\n * - `existing`: a batch shares one listing, checks `unreadable` itself and must not repeat a table.\n */\n const upsertPolicy = async <T extends SecurityPolicyType>(\n policyType: T,\n data: SecurityPolicyDataMap[T],\n options: { existing?: SecurityPolicy[]; uuid?: string } = {},\n ): Promise<{ action: 'created' | 'updated'; uuid: string; otherPolicyUuids: string[] }> => {\n const { table } = data;\n let known = options.existing;\n if (known === undefined) {\n const listed = await listPoliciesWithUnreadable(policyType);\n if (listed.unreadable > 0) {\n throw new SecurityPolicyUnreadableError({ policyType, count: listed.unreadable });\n }\n known = listed.policies;\n }\n const onTable = known.filter(\n (policy) => policy.data.table === table && onDefaultBranch(policy),\n );\n const owned = onTable.filter((policy) => isReplaceableSecurityPolicy(policy, projectId));\n const otherPolicyUuids = onTable\n .filter((policy) => !isOwn(policy))\n .map((policy) => policy.uuid);\n\n const current =\n options.uuid === undefined ? owned[0] : owned.find((policy) => policy.uuid === options.uuid);\n if (options.uuid !== undefined && current === undefined) {\n throw new SecurityPolicyNotFoundError({ policyType, table, uuid: options.uuid });\n }\n if (options.uuid === undefined && owned.length > 1) {\n throw new SecurityPolicyAmbiguousError({\n policyType,\n table,\n uuids: owned.map((policy) => policy.uuid),\n });\n }\n\n if (current) {\n if (isLegacySecurityPolicy(current.meta)) {\n throw new SecurityPolicyLegacyError({\n policyType,\n uuid: current.uuid,\n schemaVersion: current.meta.schemaVersion,\n });\n }\n await metastoreClient.repository.replaceMetaObject({\n objectType: policyType,\n UUID: current.uuid,\n data,\n name: current.meta.name ?? table,\n });\n return { action: 'updated', uuid: current.uuid, otherPolicyUuids };\n }\n\n const created = await metastoreClient.repository.createMetaObject({\n objectType: policyType,\n data,\n branch: DEFAULT_BRANCH,\n name: table,\n });\n return { action: 'created', uuid: created.data.id, otherPolicyUuids };\n };\n\n /**\n * - `SecurityPolicyInUseError` (`409`): other objects still reference the policy; nothing was deleted.\n * - `404`: no such policy, or it was already deleted.\n */\n const deletePolicy = async (policyType: SecurityPolicyType, policyUUID: string) => {\n try {\n await metastoreClient.repository.deleteMetaObject({\n objectType: policyType,\n UUID: policyUUID,\n });\n } catch (error) {\n if (!isApiError(error) || error.response.status !== 409) throw error;\n throw new SecurityPolicyInUseError({\n policyType,\n uuid: policyUUID,\n reason: metastoreErrorMessage(error.data),\n });\n }\n };\n\n return {\n listPolicies,\n listPoliciesWithUnreadable,\n getPolicy,\n listRevisions,\n upsertPolicy,\n deletePolicy,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import { n as MetastoreObjectMeta } from "../../metaObject-
|
|
2
|
-
import { _ as RLS_COMPARISON_OPS, b as SECURITY_POLICY_TYPES, f as SecurityPolicy, g as POLICY_SQL_DIALECTS, h as SecurityPolicyType, m as SecurityPolicyReadData, p as SecurityPolicyDataMap, r as MetastoreClient, t as ClsPolicyData, u as RlsPolicyData, v as RLS_LIST_OPS, y as RLS_NULL_OPS } from "../../types-
|
|
1
|
+
import { n as MetastoreObjectMeta } from "../../metaObject-BsBMgWRt.cjs";
|
|
2
|
+
import { _ as RLS_COMPARISON_OPS, b as SECURITY_POLICY_TYPES, f as SecurityPolicy, g as POLICY_SQL_DIALECTS, h as SecurityPolicyType, m as SecurityPolicyReadData, p as SecurityPolicyDataMap, r as MetastoreClient, t as ClsPolicyData, u as RlsPolicyData, v as RLS_LIST_OPS, y as RLS_NULL_OPS } from "../../types-CNDemlfn.cjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
declare const rlsPolicySchema: z.ZodType<RlsPolicyData>;
|
|
5
5
|
declare const clsPolicySchema: z.ZodType<ClsPolicyData>;
|
|
6
|
+
/** A policy stored under an older rule schema: the metastore refuses current rules for it. */
|
|
7
|
+
declare const isLegacySecurityPolicy: (meta: SecurityPolicy['meta']) => meta is SecurityPolicy['meta'] & {
|
|
8
|
+
schemaVersion: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Whether `projectId` owns the policy on `main`: a create for its table replaces it.
|
|
12
|
+
*
|
|
13
|
+
* - Others' policies on the table are never replaced; they stack with the project's own.
|
|
14
|
+
*/
|
|
15
|
+
declare const isReplaceableSecurityPolicy: (policy: SecurityPolicy, projectId: number) => boolean;
|
|
6
16
|
/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */
|
|
7
17
|
declare class SecurityPolicyAmbiguousError extends Error {
|
|
8
18
|
readonly policyType: SecurityPolicyType;
|
|
@@ -96,5 +106,5 @@ declare const createSecurityPolicySdk: ({ metastoreClient, projectId }: Options)
|
|
|
96
106
|
}>;
|
|
97
107
|
deletePolicy: (policyType: SecurityPolicyType, policyUUID: string) => Promise<void>;
|
|
98
108
|
};
|
|
99
|
-
export { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS, SECURITY_POLICY_TYPES, SecurityPolicyAmbiguousError, SecurityPolicyInUseError, SecurityPolicyLegacyError, SecurityPolicyNotFoundError, SecurityPolicyUnreadableError, clsPolicySchema, createSecurityPolicySdk, rlsPolicySchema };
|
|
109
|
+
export { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS, SECURITY_POLICY_TYPES, SecurityPolicyAmbiguousError, SecurityPolicyInUseError, SecurityPolicyLegacyError, SecurityPolicyNotFoundError, SecurityPolicyUnreadableError, clsPolicySchema, createSecurityPolicySdk, isLegacySecurityPolicy, isReplaceableSecurityPolicy, rlsPolicySchema };
|
|
100
110
|
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import { n as MetastoreObjectMeta } from "../../metaObject-
|
|
2
|
-
import { _ as RLS_COMPARISON_OPS, b as SECURITY_POLICY_TYPES, f as SecurityPolicy, g as POLICY_SQL_DIALECTS, h as SecurityPolicyType, m as SecurityPolicyReadData, p as SecurityPolicyDataMap, r as MetastoreClient, t as ClsPolicyData, u as RlsPolicyData, v as RLS_LIST_OPS, y as RLS_NULL_OPS } from "../../types-
|
|
1
|
+
import { n as MetastoreObjectMeta } from "../../metaObject-qWyZAD-5.js";
|
|
2
|
+
import { _ as RLS_COMPARISON_OPS, b as SECURITY_POLICY_TYPES, f as SecurityPolicy, g as POLICY_SQL_DIALECTS, h as SecurityPolicyType, m as SecurityPolicyReadData, p as SecurityPolicyDataMap, r as MetastoreClient, t as ClsPolicyData, u as RlsPolicyData, v as RLS_LIST_OPS, y as RLS_NULL_OPS } from "../../types-Foy0RnqF.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
declare const rlsPolicySchema: z.ZodType<RlsPolicyData>;
|
|
5
5
|
declare const clsPolicySchema: z.ZodType<ClsPolicyData>;
|
|
6
|
+
/** A policy stored under an older rule schema: the metastore refuses current rules for it. */
|
|
7
|
+
declare const isLegacySecurityPolicy: (meta: SecurityPolicy['meta']) => meta is SecurityPolicy['meta'] & {
|
|
8
|
+
schemaVersion: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Whether `projectId` owns the policy on `main`: a create for its table replaces it.
|
|
12
|
+
*
|
|
13
|
+
* - Others' policies on the table are never replaced; they stack with the project's own.
|
|
14
|
+
*/
|
|
15
|
+
declare const isReplaceableSecurityPolicy: (policy: SecurityPolicy, projectId: number) => boolean;
|
|
6
16
|
/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */
|
|
7
17
|
declare class SecurityPolicyAmbiguousError extends Error {
|
|
8
18
|
readonly policyType: SecurityPolicyType;
|
|
@@ -96,5 +106,5 @@ declare const createSecurityPolicySdk: ({ metastoreClient, projectId }: Options)
|
|
|
96
106
|
}>;
|
|
97
107
|
deletePolicy: (policyType: SecurityPolicyType, policyUUID: string) => Promise<void>;
|
|
98
108
|
};
|
|
99
|
-
export { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS, SECURITY_POLICY_TYPES, SecurityPolicyAmbiguousError, SecurityPolicyInUseError, SecurityPolicyLegacyError, SecurityPolicyNotFoundError, SecurityPolicyUnreadableError, clsPolicySchema, createSecurityPolicySdk, rlsPolicySchema };
|
|
109
|
+
export { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS, SECURITY_POLICY_TYPES, SecurityPolicyAmbiguousError, SecurityPolicyInUseError, SecurityPolicyLegacyError, SecurityPolicyNotFoundError, SecurityPolicyUnreadableError, clsPolicySchema, createSecurityPolicySdk, isLegacySecurityPolicy, isReplaceableSecurityPolicy, rlsPolicySchema };
|
|
100
110
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -109,6 +109,15 @@ const securityPolicyReadSchema = metastoreObjectReadSchema(policyReadDataSchema)
|
|
|
109
109
|
const DEFAULT_BRANCH = "main";
|
|
110
110
|
/** The rule schema Kai writes; a policy created under another version keeps its own. */
|
|
111
111
|
const CURRENT_SCHEMA_VERSION = "1.2.0";
|
|
112
|
+
/** A policy stored under an older rule schema: the metastore refuses current rules for it. */
|
|
113
|
+
const isLegacySecurityPolicy = (meta) => meta.schemaVersion !== void 0 && meta.schemaVersion !== CURRENT_SCHEMA_VERSION;
|
|
114
|
+
const onDefaultBranch = (policy) => policy.meta.branch === void 0 || policy.meta.branch === DEFAULT_BRANCH;
|
|
115
|
+
/**
|
|
116
|
+
* Whether `projectId` owns the policy on `main`: a create for its table replaces it.
|
|
117
|
+
*
|
|
118
|
+
* - Others' policies on the table are never replaced; they stack with the project's own.
|
|
119
|
+
*/
|
|
120
|
+
const isReplaceableSecurityPolicy = (policy, projectId) => policy.meta.projectId === projectId && onDefaultBranch(policy);
|
|
112
121
|
/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */
|
|
113
122
|
var SecurityPolicyAmbiguousError = class extends Error {
|
|
114
123
|
policyType;
|
|
@@ -210,7 +219,6 @@ const parsePolicies = (policyType, data) => {
|
|
|
210
219
|
};
|
|
211
220
|
const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
212
221
|
const isOwn = (policy) => policy.meta.projectId === projectId;
|
|
213
|
-
const onDefaultBranch = (policy) => policy.meta.branch === void 0 || policy.meta.branch === DEFAULT_BRANCH;
|
|
214
222
|
/**
|
|
215
223
|
* Every policy of one type the caller can read.
|
|
216
224
|
*
|
|
@@ -267,7 +275,7 @@ const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
|
267
275
|
known = listed.policies;
|
|
268
276
|
}
|
|
269
277
|
const onTable = known.filter((policy) => policy.data.table === table && onDefaultBranch(policy));
|
|
270
|
-
const owned = onTable.filter(
|
|
278
|
+
const owned = onTable.filter((policy) => isReplaceableSecurityPolicy(policy, projectId));
|
|
271
279
|
const otherPolicyUuids = onTable.filter((policy) => !isOwn(policy)).map((policy) => policy.uuid);
|
|
272
280
|
const current = options.uuid === void 0 ? owned[0] : owned.find((policy) => policy.uuid === options.uuid);
|
|
273
281
|
if (options.uuid !== void 0 && current === void 0) throw new SecurityPolicyNotFoundError({
|
|
@@ -281,7 +289,7 @@ const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
|
281
289
|
uuids: owned.map((policy) => policy.uuid)
|
|
282
290
|
});
|
|
283
291
|
if (current) {
|
|
284
|
-
if (current.meta
|
|
292
|
+
if (isLegacySecurityPolicy(current.meta)) throw new SecurityPolicyLegacyError({
|
|
285
293
|
policyType,
|
|
286
294
|
uuid: current.uuid,
|
|
287
295
|
schemaVersion: current.meta.schemaVersion
|
|
@@ -337,6 +345,6 @@ const createSecurityPolicySdk = ({ metastoreClient, projectId }) => {
|
|
|
337
345
|
deletePolicy
|
|
338
346
|
};
|
|
339
347
|
};
|
|
340
|
-
export { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS, SECURITY_POLICY_TYPES, SecurityPolicyAmbiguousError, SecurityPolicyInUseError, SecurityPolicyLegacyError, SecurityPolicyNotFoundError, SecurityPolicyUnreadableError, clsPolicySchema, createSecurityPolicySdk, rlsPolicySchema };
|
|
348
|
+
export { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS, SECURITY_POLICY_TYPES, SecurityPolicyAmbiguousError, SecurityPolicyInUseError, SecurityPolicyLegacyError, SecurityPolicyNotFoundError, SecurityPolicyUnreadableError, clsPolicySchema, createSecurityPolicySdk, isLegacySecurityPolicy, isReplaceableSecurityPolicy, rlsPolicySchema };
|
|
341
349
|
|
|
342
350
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/sdks/securityPolicy/vocabulary.ts","../../../src/sdks/securityPolicy/schemas.ts","../../../src/sdks/securityPolicy/readSchemas.ts","../../../src/sdks/securityPolicy/securityPolicySdk.ts"],"sourcesContent":["/**\n * The metastore's row- and column-level security vocabulary, schema version 1.2.0.\n *\n * - Each list is the one place a value is added; the types in `./types` derive from it.\n */\n\nexport const SECURITY_POLICY_TYPES = ['rls-policy', 'cls-policy'] as const;\n\nexport const POLICY_SQL_DIALECTS = ['snowflake', 'bigquery'] as const;\n\nexport const RLS_COMPARISON_OPS = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'] as const;\n\nexport const RLS_LIST_OPS = ['in', 'not_in'] as const;\n\nexport const RLS_NULL_OPS = ['is_null', 'is_not_null'] as const;\n","import { z } from 'zod';\n\nimport type { ClsPolicyData, RlsCondition, RlsPolicyData } from './types';\nimport { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS } from './vocabulary';\n\n/** A `<bucket>.<table>` key; also the policy's metastore name. */\nconst POLICY_TABLE_PATTERN = /^[A-Za-z0-9_.-]+\\.[A-Za-z0-9_-]+$/;\n\n/** Columns are SQL identifiers that cannot be parameterised, so this pattern is the boundary. */\nconst POLICY_COLUMN_PATTERN = /^[A-Za-z0-9_]+$/;\n\n/** A reader selector `<idp>|<sub>`: the identity provider's issuer, a `|`, the user's `sub`. */\nconst POLICY_SUBJECT_PATTERN = /^[^|\\s]+\\|\\S.*$/;\n\n/**\n * Write validators for untrusted policy input, mirroring metastore schema 1.2.0.\n *\n * - Strict: an unknown key fails, as `additionalProperties: false` does in the metastore.\n * - The identifier patterns are the boundary: `table` and `column` reach SQL unparameterised.\n * - Stricter than the metastore on purpose: a `value` is a string, number, boolean or null, and\n * `values` holds the same; the metastore also lets an arbitrary JSON value through.\n * - The metastore stays the authority; this reports the first problem in words the model can act on.\n */\n\nconst column = z.string().regex(POLICY_COLUMN_PATTERN, 'column must match [A-Za-z0-9_]+');\n\nconst literal = z.union([z.string(), z.number(), z.boolean(), z.null()]);\n\nconst identityEmail = z.strictObject({ $identity: z.literal('email') });\nconst identityGroups = z.strictObject({ $identity: z.literal('groups') });\n\nconst rlsCondition: z.ZodType<RlsCondition> = z.lazy(() =>\n z.union([\n z.strictObject({ true: z.literal(true) }),\n z.strictObject({ false: z.literal(true) }),\n z.strictObject({ and: z.array(rlsCondition).min(2) }),\n z.strictObject({ or: z.array(rlsCondition).min(2) }),\n z.strictObject({\n column,\n op: z.enum(RLS_COMPARISON_OPS),\n value: z.union([literal, identityEmail]),\n }),\n z.strictObject({\n column,\n op: z.enum(RLS_LIST_OPS),\n values: z.union([z.array(literal).min(1), identityGroups]),\n }),\n z.strictObject({ column, op: z.enum(RLS_NULL_OPS) }),\n ]),\n);\n\n/** `[\"*\"]` is everyone and must be the only entry. */\nconst selectorList = (item: z.ZodType<string>) =>\n z\n .array(item)\n .min(1)\n .refine((list) => !list.includes('*') || list.length === 1, {\n message: '\"*\" must be the only entry',\n });\n\nconst subjects = selectorList(\n z.union([\n z.literal('*'),\n z\n .string()\n .max(1024)\n .regex(POLICY_SUBJECT_PATTERN, 'a subject is \"<idp>|<sub>\", never an email'),\n ]),\n);\nconst groups = selectorList(z.string().min(1));\n\n/** A rule selects readers by exactly one of `subjects` or `groups`, then carries `shape`. */\nconst rule = <Shape extends z.ZodRawShape>(shape: Shape) =>\n z.union([z.strictObject({ subjects, ...shape }), z.strictObject({ groups, ...shape })]);\n\nconst table = z.string().regex(POLICY_TABLE_PATTERN, 'table must be \"<bucket>.<table>\"');\nconst dialect = z.enum(POLICY_SQL_DIALECTS).optional();\n\nexport const rlsPolicySchema: z.ZodType<RlsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ condition: rlsCondition })).min(1),\n default: rlsCondition.optional(),\n});\n\nexport const clsPolicySchema: z.ZodType<ClsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ visible_columns: z.array(column).min(1) })).min(1),\n});\n","import { z } from 'zod';\n\nimport { metastoreObjectReadSchema } from '../../clients/metastore/metaObject';\n\nimport type { SecurityPolicyReadData } from './types';\nimport { POLICY_SQL_DIALECTS } from './vocabulary';\n\n/**\n * What a read of the metastore may hand back for a policy.\n *\n * - `looseObject`: fields the metastore adds still reach callers.\n * - An unknown `dialect` reads as absent; a missing `table` or `rules` drops the object.\n * - The envelope is the metastore's own, shared with every object family.\n */\n\nconst policyReadDataSchema: z.ZodType<SecurityPolicyReadData, unknown> = z.looseObject({\n table: z.string(),\n dialect: z.enum(POLICY_SQL_DIALECTS).optional().catch(undefined),\n rules: z.array(z.record(z.string(), z.unknown())),\n default: z.unknown().optional(),\n});\n\nexport const securityPolicyReadSchema = metastoreObjectReadSchema(policyReadDataSchema);\n","import { z } from 'zod';\n\nimport { metastoreErrorMessage } from '../../clients/metastore/errorMessage';\nimport { formatValidationIssues, parseOrThrow } from '../../errors';\nimport { isApiError } from '../../fetchClient';\n\nimport { securityPolicyReadSchema } from './readSchemas';\nimport type {\n MetastoreClient,\n SecurityPolicy,\n SecurityPolicyDataMap,\n SecurityPolicyType,\n} from './types';\n\nconst DEFAULT_BRANCH = 'main';\n\n/** The rule schema Kai writes; a policy created under another version keeps its own. */\nconst CURRENT_SCHEMA_VERSION = '1.2.0';\n\n/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */\nexport class SecurityPolicyAmbiguousError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuids: string[];\n\n constructor({\n policyType,\n table,\n uuids,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuids: string[];\n }) {\n super(\n `The project has ${uuids.length} ${policyType} policies for table '${table}' ` +\n `(${uuids.join(', ')}); pass the uuid of the one to replace.`,\n );\n this.name = 'SecurityPolicyAmbiguousError';\n this.policyType = policyType;\n this.table = table;\n this.uuids = uuids;\n }\n}\n\n/**\n * Thrown by `deletePolicy` on a `409`: other objects still reference the policy, nothing was deleted.\n *\n * - The metastore does not name the referencing objects, so none is reported here.\n */\nexport class SecurityPolicyInUseError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n\n constructor({\n policyType,\n uuid,\n reason,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n reason?: string;\n }) {\n super(reason ?? `The ${policyType} policy '${uuid}' is still bound and was not deleted.`);\n this.name = 'SecurityPolicyInUseError';\n this.policyType = policyType;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when some policy of the type could not be read.\n *\n * - Whether that policy governs the table is unknown, and a second policy on it would AND with it.\n */\nexport class SecurityPolicyUnreadableError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly count: number;\n\n constructor({ policyType, count }: { policyType: SecurityPolicyType; count: number }) {\n super(\n `${count} ${policyType} polic${count === 1 ? 'y' : 'ies'} of the project could not be read, ` +\n `so it is unknown whether the table already has one; nothing was written.`,\n );\n this.name = 'SecurityPolicyUnreadableError';\n this.policyType = policyType;\n this.count = count;\n }\n}\n\n/** The caller named a policy by `uuid` that the project does not own for the table. */\nexport class SecurityPolicyNotFoundError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuid: string;\n\n constructor({\n policyType,\n table,\n uuid,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuid: string;\n }) {\n super(`The project owns no ${policyType} '${uuid}' for table '${table}'.`);\n this.name = 'SecurityPolicyNotFoundError';\n this.policyType = policyType;\n this.table = table;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when the policy to replace was written under an older schema.\n *\n * - The metastore validates a write against the schema version the object already has, so 1.2.0\n * `subjects` on a 1.0.0 or 1.1.0 policy (`principal`, `principals`) fail with a 422.\n * - Nothing was written. Delete the policy and create it again; a policy an app binds cannot be deleted.\n */\nexport class SecurityPolicyLegacyError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n readonly schemaVersion: string;\n\n constructor({\n policyType,\n uuid,\n schemaVersion,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n schemaVersion: string;\n }) {\n super(\n `The ${policyType} '${uuid}' is on schema ${schemaVersion}, not ${CURRENT_SCHEMA_VERSION}, ` +\n `and the metastore keeps a policy on the schema it was created with; nothing was written.`,\n );\n this.name = 'SecurityPolicyLegacyError';\n this.policyType = policyType;\n this.uuid = uuid;\n this.schemaVersion = schemaVersion;\n }\n}\n\ntype Options = {\n metastoreClient: MetastoreClient;\n /** The project the caller writes as; a policy it owns carries this in `meta.projectId`. */\n projectId: number;\n};\n\n/**\n * The policies in a metastore collection response.\n *\n * - A malformed element is dropped, logged without its payload and counted in `unreadable`.\n * - A response that is not a collection throws.\n */\nconst parsePolicies = (\n policyType: SecurityPolicyType,\n data: unknown,\n): { policies: SecurityPolicy[]; unreadable: number } => {\n const items = parseOrThrow(z.array(z.unknown()), data);\n\n const policies: SecurityPolicy[] = [];\n let unreadable = 0;\n for (const item of items) {\n const result = securityPolicyReadSchema.safeParse(item);\n if (result.success) {\n policies.push(result.data);\n continue;\n }\n\n unreadable += 1;\n // Never log the payload: it holds customer identities.\n console.warn(\n `securityPolicySdk: dropped a ${policyType} from the metastore response, it does not ` +\n `match its declared shape`,\n formatValidationIssues(result.error.issues),\n );\n }\n return { policies, unreadable };\n};\n\nexport const createSecurityPolicySdk = ({ metastoreClient, projectId }: Options) => {\n const isOwn = (policy: SecurityPolicy) => policy.meta.projectId === projectId;\n\n // A list without `branch` returns every branch, and a create always writes `main`: a policy on\n // another branch is neither the one to replace nor one that stacks with it.\n const onDefaultBranch = (policy: SecurityPolicy) =>\n policy.meta.branch === undefined || policy.meta.branch === DEFAULT_BRANCH;\n\n /**\n * Every policy of one type the caller can read.\n *\n * - A project admin reads only the policies the project owns. An organization admin also reads\n * organization-scope policies and ones shared into the project; `meta.projectId` tells them apart.\n * - A malformed element is dropped and logged; `listPoliciesWithUnreadable` also counts them.\n * - A response that is not a collection throws.\n */\n const listPoliciesWithUnreadable = async (\n policyType: SecurityPolicyType,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjects(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data);\n };\n\n const listPolicies = async (policyType: SecurityPolicyType, signal?: AbortSignal) =>\n (await listPoliciesWithUnreadable(policyType, signal)).policies;\n\n /**\n * One policy by UUID, from any project or scope the caller can read.\n *\n * - A policy that does not parse throws a `ValidationError` rather than reading as missing.\n * - `404`: no such policy, or the caller cannot see it.\n */\n const getPolicy = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObject(\n { objectType: policyType, UUID: policyUUID },\n signal,\n );\n return parseOrThrow(securityPolicyReadSchema, response.data);\n };\n\n /**\n * Every revision of one policy, newest first.\n *\n * - The metastore lists revisions per object type only, so this reads them all and keeps the policy's.\n * - A revision that does not parse is dropped and logged, as in `listPolicies`.\n */\n const listRevisions = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjectRevisions(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data)\n .policies.filter((revision) => revision.uuid === policyUUID)\n .sort((a, b) => (b.meta.revision ?? 0) - (a.meta.revision ?? 0));\n };\n\n /**\n * Creates the policy for its table, or replaces the one the project owns for it (a PUT).\n *\n * - Found by table on `main`; several owned ones throw `SecurityPolicyAmbiguousError`, `uuid` picks one.\n * - Others' policies are never replaced and come back in `otherPolicyUuids`; no scope is sent.\n * - Refused, nothing written: an unreadable policy of the type, or a legacy-schema one to replace.\n * - `existing`: a batch shares one listing, checks `unreadable` itself and must not repeat a table.\n */\n const upsertPolicy = async <T extends SecurityPolicyType>(\n policyType: T,\n data: SecurityPolicyDataMap[T],\n options: { existing?: SecurityPolicy[]; uuid?: string } = {},\n ): Promise<{ action: 'created' | 'updated'; uuid: string; otherPolicyUuids: string[] }> => {\n const { table } = data;\n let known = options.existing;\n if (known === undefined) {\n const listed = await listPoliciesWithUnreadable(policyType);\n if (listed.unreadable > 0) {\n throw new SecurityPolicyUnreadableError({ policyType, count: listed.unreadable });\n }\n known = listed.policies;\n }\n const onTable = known.filter(\n (policy) => policy.data.table === table && onDefaultBranch(policy),\n );\n const owned = onTable.filter(isOwn);\n const otherPolicyUuids = onTable\n .filter((policy) => !isOwn(policy))\n .map((policy) => policy.uuid);\n\n const current =\n options.uuid === undefined ? owned[0] : owned.find((policy) => policy.uuid === options.uuid);\n if (options.uuid !== undefined && current === undefined) {\n throw new SecurityPolicyNotFoundError({ policyType, table, uuid: options.uuid });\n }\n if (options.uuid === undefined && owned.length > 1) {\n throw new SecurityPolicyAmbiguousError({\n policyType,\n table,\n uuids: owned.map((policy) => policy.uuid),\n });\n }\n\n if (current) {\n if (\n current.meta.schemaVersion !== undefined &&\n current.meta.schemaVersion !== CURRENT_SCHEMA_VERSION\n ) {\n throw new SecurityPolicyLegacyError({\n policyType,\n uuid: current.uuid,\n schemaVersion: current.meta.schemaVersion,\n });\n }\n await metastoreClient.repository.replaceMetaObject({\n objectType: policyType,\n UUID: current.uuid,\n data,\n name: current.meta.name ?? table,\n });\n return { action: 'updated', uuid: current.uuid, otherPolicyUuids };\n }\n\n const created = await metastoreClient.repository.createMetaObject({\n objectType: policyType,\n data,\n branch: DEFAULT_BRANCH,\n name: table,\n });\n return { action: 'created', uuid: created.data.id, otherPolicyUuids };\n };\n\n /**\n * - `SecurityPolicyInUseError` (`409`): other objects still reference the policy; nothing was deleted.\n * - `404`: no such policy, or it was already deleted.\n */\n const deletePolicy = async (policyType: SecurityPolicyType, policyUUID: string) => {\n try {\n await metastoreClient.repository.deleteMetaObject({\n objectType: policyType,\n UUID: policyUUID,\n });\n } catch (error) {\n if (!isApiError(error) || error.response.status !== 409) throw error;\n throw new SecurityPolicyInUseError({\n policyType,\n uuid: policyUUID,\n reason: metastoreErrorMessage(error.data),\n });\n }\n };\n\n return {\n listPolicies,\n listPoliciesWithUnreadable,\n getPolicy,\n listRevisions,\n upsertPolicy,\n deletePolicy,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/sdks/securityPolicy/vocabulary.ts","../../../src/sdks/securityPolicy/schemas.ts","../../../src/sdks/securityPolicy/readSchemas.ts","../../../src/sdks/securityPolicy/securityPolicySdk.ts"],"sourcesContent":["/**\n * The metastore's row- and column-level security vocabulary, schema version 1.2.0.\n *\n * - Each list is the one place a value is added; the types in `./types` derive from it.\n */\n\nexport const SECURITY_POLICY_TYPES = ['rls-policy', 'cls-policy'] as const;\n\nexport const POLICY_SQL_DIALECTS = ['snowflake', 'bigquery'] as const;\n\nexport const RLS_COMPARISON_OPS = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'] as const;\n\nexport const RLS_LIST_OPS = ['in', 'not_in'] as const;\n\nexport const RLS_NULL_OPS = ['is_null', 'is_not_null'] as const;\n","import { z } from 'zod';\n\nimport type { ClsPolicyData, RlsCondition, RlsPolicyData } from './types';\nimport { POLICY_SQL_DIALECTS, RLS_COMPARISON_OPS, RLS_LIST_OPS, RLS_NULL_OPS } from './vocabulary';\n\n/** A `<bucket>.<table>` key; also the policy's metastore name. */\nconst POLICY_TABLE_PATTERN = /^[A-Za-z0-9_.-]+\\.[A-Za-z0-9_-]+$/;\n\n/** Columns are SQL identifiers that cannot be parameterised, so this pattern is the boundary. */\nconst POLICY_COLUMN_PATTERN = /^[A-Za-z0-9_]+$/;\n\n/** A reader selector `<idp>|<sub>`: the identity provider's issuer, a `|`, the user's `sub`. */\nconst POLICY_SUBJECT_PATTERN = /^[^|\\s]+\\|\\S.*$/;\n\n/**\n * Write validators for untrusted policy input, mirroring metastore schema 1.2.0.\n *\n * - Strict: an unknown key fails, as `additionalProperties: false` does in the metastore.\n * - The identifier patterns are the boundary: `table` and `column` reach SQL unparameterised.\n * - Stricter than the metastore on purpose: a `value` is a string, number, boolean or null, and\n * `values` holds the same; the metastore also lets an arbitrary JSON value through.\n * - The metastore stays the authority; this reports the first problem in words the model can act on.\n */\n\nconst column = z.string().regex(POLICY_COLUMN_PATTERN, 'column must match [A-Za-z0-9_]+');\n\nconst literal = z.union([z.string(), z.number(), z.boolean(), z.null()]);\n\nconst identityEmail = z.strictObject({ $identity: z.literal('email') });\nconst identityGroups = z.strictObject({ $identity: z.literal('groups') });\n\nconst rlsCondition: z.ZodType<RlsCondition> = z.lazy(() =>\n z.union([\n z.strictObject({ true: z.literal(true) }),\n z.strictObject({ false: z.literal(true) }),\n z.strictObject({ and: z.array(rlsCondition).min(2) }),\n z.strictObject({ or: z.array(rlsCondition).min(2) }),\n z.strictObject({\n column,\n op: z.enum(RLS_COMPARISON_OPS),\n value: z.union([literal, identityEmail]),\n }),\n z.strictObject({\n column,\n op: z.enum(RLS_LIST_OPS),\n values: z.union([z.array(literal).min(1), identityGroups]),\n }),\n z.strictObject({ column, op: z.enum(RLS_NULL_OPS) }),\n ]),\n);\n\n/** `[\"*\"]` is everyone and must be the only entry. */\nconst selectorList = (item: z.ZodType<string>) =>\n z\n .array(item)\n .min(1)\n .refine((list) => !list.includes('*') || list.length === 1, {\n message: '\"*\" must be the only entry',\n });\n\nconst subjects = selectorList(\n z.union([\n z.literal('*'),\n z\n .string()\n .max(1024)\n .regex(POLICY_SUBJECT_PATTERN, 'a subject is \"<idp>|<sub>\", never an email'),\n ]),\n);\nconst groups = selectorList(z.string().min(1));\n\n/** A rule selects readers by exactly one of `subjects` or `groups`, then carries `shape`. */\nconst rule = <Shape extends z.ZodRawShape>(shape: Shape) =>\n z.union([z.strictObject({ subjects, ...shape }), z.strictObject({ groups, ...shape })]);\n\nconst table = z.string().regex(POLICY_TABLE_PATTERN, 'table must be \"<bucket>.<table>\"');\nconst dialect = z.enum(POLICY_SQL_DIALECTS).optional();\n\nexport const rlsPolicySchema: z.ZodType<RlsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ condition: rlsCondition })).min(1),\n default: rlsCondition.optional(),\n});\n\nexport const clsPolicySchema: z.ZodType<ClsPolicyData> = z.strictObject({\n table,\n dialect,\n rules: z.array(rule({ visible_columns: z.array(column).min(1) })).min(1),\n});\n","import { z } from 'zod';\n\nimport { metastoreObjectReadSchema } from '../../clients/metastore/metaObject';\n\nimport type { SecurityPolicyReadData } from './types';\nimport { POLICY_SQL_DIALECTS } from './vocabulary';\n\n/**\n * What a read of the metastore may hand back for a policy.\n *\n * - `looseObject`: fields the metastore adds still reach callers.\n * - An unknown `dialect` reads as absent; a missing `table` or `rules` drops the object.\n * - The envelope is the metastore's own, shared with every object family.\n */\n\nconst policyReadDataSchema: z.ZodType<SecurityPolicyReadData, unknown> = z.looseObject({\n table: z.string(),\n dialect: z.enum(POLICY_SQL_DIALECTS).optional().catch(undefined),\n rules: z.array(z.record(z.string(), z.unknown())),\n default: z.unknown().optional(),\n});\n\nexport const securityPolicyReadSchema = metastoreObjectReadSchema(policyReadDataSchema);\n","import { z } from 'zod';\n\nimport { metastoreErrorMessage } from '../../clients/metastore/errorMessage';\nimport { formatValidationIssues, parseOrThrow } from '../../errors';\nimport { isApiError } from '../../fetchClient';\n\nimport { securityPolicyReadSchema } from './readSchemas';\nimport type {\n MetastoreClient,\n SecurityPolicy,\n SecurityPolicyDataMap,\n SecurityPolicyType,\n} from './types';\n\nconst DEFAULT_BRANCH = 'main';\n\n/** The rule schema Kai writes; a policy created under another version keeps its own. */\nconst CURRENT_SCHEMA_VERSION = '1.2.0';\n\n/** A policy stored under an older rule schema: the metastore refuses current rules for it. */\nexport const isLegacySecurityPolicy = (\n meta: SecurityPolicy['meta'],\n): meta is SecurityPolicy['meta'] & { schemaVersion: string } =>\n meta.schemaVersion !== undefined && meta.schemaVersion !== CURRENT_SCHEMA_VERSION;\n\n// A list without `branch` returns every branch, and a create always writes `main`: a policy on\n// another branch is neither the one to replace nor one that stacks with it.\nconst onDefaultBranch = (policy: SecurityPolicy) =>\n policy.meta.branch === undefined || policy.meta.branch === DEFAULT_BRANCH;\n\n/**\n * Whether `projectId` owns the policy on `main`: a create for its table replaces it.\n *\n * - Others' policies on the table are never replaced; they stack with the project's own.\n */\nexport const isReplaceableSecurityPolicy = (policy: SecurityPolicy, projectId: number) =>\n policy.meta.projectId === projectId && onDefaultBranch(policy);\n\n/** The project owns more than one policy for the table, so which to replace is not for the SDK to guess. */\nexport class SecurityPolicyAmbiguousError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuids: string[];\n\n constructor({\n policyType,\n table,\n uuids,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuids: string[];\n }) {\n super(\n `The project has ${uuids.length} ${policyType} policies for table '${table}' ` +\n `(${uuids.join(', ')}); pass the uuid of the one to replace.`,\n );\n this.name = 'SecurityPolicyAmbiguousError';\n this.policyType = policyType;\n this.table = table;\n this.uuids = uuids;\n }\n}\n\n/**\n * Thrown by `deletePolicy` on a `409`: other objects still reference the policy, nothing was deleted.\n *\n * - The metastore does not name the referencing objects, so none is reported here.\n */\nexport class SecurityPolicyInUseError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n\n constructor({\n policyType,\n uuid,\n reason,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n reason?: string;\n }) {\n super(reason ?? `The ${policyType} policy '${uuid}' is still bound and was not deleted.`);\n this.name = 'SecurityPolicyInUseError';\n this.policyType = policyType;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when some policy of the type could not be read.\n *\n * - Whether that policy governs the table is unknown, and a second policy on it would AND with it.\n */\nexport class SecurityPolicyUnreadableError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly count: number;\n\n constructor({ policyType, count }: { policyType: SecurityPolicyType; count: number }) {\n super(\n `${count} ${policyType} polic${count === 1 ? 'y' : 'ies'} of the project could not be read, ` +\n `so it is unknown whether the table already has one; nothing was written.`,\n );\n this.name = 'SecurityPolicyUnreadableError';\n this.policyType = policyType;\n this.count = count;\n }\n}\n\n/** The caller named a policy by `uuid` that the project does not own for the table. */\nexport class SecurityPolicyNotFoundError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly table: string;\n readonly uuid: string;\n\n constructor({\n policyType,\n table,\n uuid,\n }: {\n policyType: SecurityPolicyType;\n table: string;\n uuid: string;\n }) {\n super(`The project owns no ${policyType} '${uuid}' for table '${table}'.`);\n this.name = 'SecurityPolicyNotFoundError';\n this.policyType = policyType;\n this.table = table;\n this.uuid = uuid;\n }\n}\n\n/**\n * Thrown by `upsertPolicy` when the policy to replace was written under an older schema.\n *\n * - The metastore validates a write against the schema version the object already has, so 1.2.0\n * `subjects` on a 1.0.0 or 1.1.0 policy (`principal`, `principals`) fail with a 422.\n * - Nothing was written. Delete the policy and create it again; a policy an app binds cannot be deleted.\n */\nexport class SecurityPolicyLegacyError extends Error {\n readonly policyType: SecurityPolicyType;\n readonly uuid: string;\n readonly schemaVersion: string;\n\n constructor({\n policyType,\n uuid,\n schemaVersion,\n }: {\n policyType: SecurityPolicyType;\n uuid: string;\n schemaVersion: string;\n }) {\n super(\n `The ${policyType} '${uuid}' is on schema ${schemaVersion}, not ${CURRENT_SCHEMA_VERSION}, ` +\n `and the metastore keeps a policy on the schema it was created with; nothing was written.`,\n );\n this.name = 'SecurityPolicyLegacyError';\n this.policyType = policyType;\n this.uuid = uuid;\n this.schemaVersion = schemaVersion;\n }\n}\n\ntype Options = {\n metastoreClient: MetastoreClient;\n /** The project the caller writes as; a policy it owns carries this in `meta.projectId`. */\n projectId: number;\n};\n\n/**\n * The policies in a metastore collection response.\n *\n * - A malformed element is dropped, logged without its payload and counted in `unreadable`.\n * - A response that is not a collection throws.\n */\nconst parsePolicies = (\n policyType: SecurityPolicyType,\n data: unknown,\n): { policies: SecurityPolicy[]; unreadable: number } => {\n const items = parseOrThrow(z.array(z.unknown()), data);\n\n const policies: SecurityPolicy[] = [];\n let unreadable = 0;\n for (const item of items) {\n const result = securityPolicyReadSchema.safeParse(item);\n if (result.success) {\n policies.push(result.data);\n continue;\n }\n\n unreadable += 1;\n // Never log the payload: it holds customer identities.\n console.warn(\n `securityPolicySdk: dropped a ${policyType} from the metastore response, it does not ` +\n `match its declared shape`,\n formatValidationIssues(result.error.issues),\n );\n }\n return { policies, unreadable };\n};\n\nexport const createSecurityPolicySdk = ({ metastoreClient, projectId }: Options) => {\n const isOwn = (policy: SecurityPolicy) => policy.meta.projectId === projectId;\n\n /**\n * Every policy of one type the caller can read.\n *\n * - A project admin reads only the policies the project owns. An organization admin also reads\n * organization-scope policies and ones shared into the project; `meta.projectId` tells them apart.\n * - A malformed element is dropped and logged; `listPoliciesWithUnreadable` also counts them.\n * - A response that is not a collection throws.\n */\n const listPoliciesWithUnreadable = async (\n policyType: SecurityPolicyType,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjects(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data);\n };\n\n const listPolicies = async (policyType: SecurityPolicyType, signal?: AbortSignal) =>\n (await listPoliciesWithUnreadable(policyType, signal)).policies;\n\n /**\n * One policy by UUID, from any project or scope the caller can read.\n *\n * - A policy that does not parse throws a `ValidationError` rather than reading as missing.\n * - `404`: no such policy, or the caller cannot see it.\n */\n const getPolicy = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObject(\n { objectType: policyType, UUID: policyUUID },\n signal,\n );\n return parseOrThrow(securityPolicyReadSchema, response.data);\n };\n\n /**\n * Every revision of one policy, newest first.\n *\n * - The metastore lists revisions per object type only, so this reads them all and keeps the policy's.\n * - A revision that does not parse is dropped and logged, as in `listPolicies`.\n */\n const listRevisions = async (\n policyType: SecurityPolicyType,\n policyUUID: string,\n signal?: AbortSignal,\n ) => {\n const response = await metastoreClient.repository.getMetaObjectRevisions(\n { objectType: policyType },\n signal,\n );\n return parsePolicies(policyType, response.data)\n .policies.filter((revision) => revision.uuid === policyUUID)\n .sort((a, b) => (b.meta.revision ?? 0) - (a.meta.revision ?? 0));\n };\n\n /**\n * Creates the policy for its table, or replaces the one the project owns for it (a PUT).\n *\n * - Found by table on `main`; several owned ones throw `SecurityPolicyAmbiguousError`, `uuid` picks one.\n * - Others' policies are never replaced and come back in `otherPolicyUuids`; no scope is sent.\n * - Refused, nothing written: an unreadable policy of the type, or a legacy-schema one to replace.\n * - `existing`: a batch shares one listing, checks `unreadable` itself and must not repeat a table.\n */\n const upsertPolicy = async <T extends SecurityPolicyType>(\n policyType: T,\n data: SecurityPolicyDataMap[T],\n options: { existing?: SecurityPolicy[]; uuid?: string } = {},\n ): Promise<{ action: 'created' | 'updated'; uuid: string; otherPolicyUuids: string[] }> => {\n const { table } = data;\n let known = options.existing;\n if (known === undefined) {\n const listed = await listPoliciesWithUnreadable(policyType);\n if (listed.unreadable > 0) {\n throw new SecurityPolicyUnreadableError({ policyType, count: listed.unreadable });\n }\n known = listed.policies;\n }\n const onTable = known.filter(\n (policy) => policy.data.table === table && onDefaultBranch(policy),\n );\n const owned = onTable.filter((policy) => isReplaceableSecurityPolicy(policy, projectId));\n const otherPolicyUuids = onTable\n .filter((policy) => !isOwn(policy))\n .map((policy) => policy.uuid);\n\n const current =\n options.uuid === undefined ? owned[0] : owned.find((policy) => policy.uuid === options.uuid);\n if (options.uuid !== undefined && current === undefined) {\n throw new SecurityPolicyNotFoundError({ policyType, table, uuid: options.uuid });\n }\n if (options.uuid === undefined && owned.length > 1) {\n throw new SecurityPolicyAmbiguousError({\n policyType,\n table,\n uuids: owned.map((policy) => policy.uuid),\n });\n }\n\n if (current) {\n if (isLegacySecurityPolicy(current.meta)) {\n throw new SecurityPolicyLegacyError({\n policyType,\n uuid: current.uuid,\n schemaVersion: current.meta.schemaVersion,\n });\n }\n await metastoreClient.repository.replaceMetaObject({\n objectType: policyType,\n UUID: current.uuid,\n data,\n name: current.meta.name ?? table,\n });\n return { action: 'updated', uuid: current.uuid, otherPolicyUuids };\n }\n\n const created = await metastoreClient.repository.createMetaObject({\n objectType: policyType,\n data,\n branch: DEFAULT_BRANCH,\n name: table,\n });\n return { action: 'created', uuid: created.data.id, otherPolicyUuids };\n };\n\n /**\n * - `SecurityPolicyInUseError` (`409`): other objects still reference the policy; nothing was deleted.\n * - `404`: no such policy, or it was already deleted.\n */\n const deletePolicy = async (policyType: SecurityPolicyType, policyUUID: string) => {\n try {\n await metastoreClient.repository.deleteMetaObject({\n objectType: policyType,\n UUID: policyUUID,\n });\n } catch (error) {\n if (!isApiError(error) || error.response.status !== 409) throw error;\n throw new SecurityPolicyInUseError({\n policyType,\n uuid: policyUUID,\n reason: metastoreErrorMessage(error.data),\n });\n }\n };\n\n return {\n listPolicies,\n listPoliciesWithUnreadable,\n getPolicy,\n listRevisions,\n upsertPolicy,\n deletePolicy,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PolicySelector, c as RlsIdentityGroups, d as RlsRule, f as SecurityPolicy, h as SecurityPolicyType, i as PolicyDialect, l as RlsLiteral, m as SecurityPolicyReadData, n as ClsRule, o as RlsCondition, p as SecurityPolicyDataMap, r as MetastoreClient, s as RlsIdentityEmail, t as ClsPolicyData, u as RlsPolicyData } from "../../types-
|
|
1
|
+
import { a as PolicySelector, c as RlsIdentityGroups, d as RlsRule, f as SecurityPolicy, h as SecurityPolicyType, i as PolicyDialect, l as RlsLiteral, m as SecurityPolicyReadData, n as ClsRule, o as RlsCondition, p as SecurityPolicyDataMap, r as MetastoreClient, s as RlsIdentityEmail, t as ClsPolicyData, u as RlsPolicyData } from "../../types-CNDemlfn.cjs";
|
|
2
2
|
export { ClsPolicyData, ClsRule, MetastoreClient, PolicyDialect, PolicySelector, RlsCondition, RlsIdentityEmail, RlsIdentityGroups, RlsLiteral, RlsPolicyData, RlsRule, SecurityPolicy, SecurityPolicyDataMap, SecurityPolicyReadData, SecurityPolicyType };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PolicySelector, c as RlsIdentityGroups, d as RlsRule, f as SecurityPolicy, h as SecurityPolicyType, i as PolicyDialect, l as RlsLiteral, m as SecurityPolicyReadData, n as ClsRule, o as RlsCondition, p as SecurityPolicyDataMap, r as MetastoreClient, s as RlsIdentityEmail, t as ClsPolicyData, u as RlsPolicyData } from "../../types-
|
|
1
|
+
import { a as PolicySelector, c as RlsIdentityGroups, d as RlsRule, f as SecurityPolicy, h as SecurityPolicyType, i as PolicyDialect, l as RlsLiteral, m as SecurityPolicyReadData, n as ClsRule, o as RlsCondition, p as SecurityPolicyDataMap, r as MetastoreClient, s as RlsIdentityEmail, t as ClsPolicyData, u as RlsPolicyData } from "../../types-Foy0RnqF.js";
|
|
2
2
|
export { ClsPolicyData, ClsRule, MetastoreClient, PolicyDialect, PolicySelector, RlsCondition, RlsIdentityEmail, RlsIdentityGroups, RlsLiteral, RlsPolicyData, RlsRule, SecurityPolicy, SecurityPolicyDataMap, SecurityPolicyReadData, SecurityPolicyType };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as CONSTRAINT_TYPES, D as UpdateSemanticObjectMeta, F as SQL_DIALECTS, M as RELATIONSHIP_JOIN_TYPES, N as RULE_OPERATORS, O as CONSTRAINT_SCOPES, P as SEMANTIC_OBJECT_SCOPES, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, j as FIELD_ROLES, k as CONSTRAINT_SEVERITIES, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, t as CreateSemanticObjectMeta, u as SemanticDatasetData, x as SemanticRelationshipData } from "../../types-
|
|
1
|
+
import { A as CONSTRAINT_TYPES, D as UpdateSemanticObjectMeta, F as SQL_DIALECTS, M as RELATIONSHIP_JOIN_TYPES, N as RULE_OPERATORS, O as CONSTRAINT_SCOPES, P as SEMANTIC_OBJECT_SCOPES, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, j as FIELD_ROLES, k as CONSTRAINT_SEVERITIES, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, t as CreateSemanticObjectMeta, u as SemanticDatasetData, x as SemanticRelationshipData } from "../../types-CuYaiy4R.cjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
/**
|
|
4
4
|
* The message out of a metastore error body.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as CONSTRAINT_TYPES, D as UpdateSemanticObjectMeta, F as SQL_DIALECTS, M as RELATIONSHIP_JOIN_TYPES, N as RULE_OPERATORS, O as CONSTRAINT_SCOPES, P as SEMANTIC_OBJECT_SCOPES, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, j as FIELD_ROLES, k as CONSTRAINT_SEVERITIES, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, t as CreateSemanticObjectMeta, u as SemanticDatasetData, x as SemanticRelationshipData } from "../../types-
|
|
1
|
+
import { A as CONSTRAINT_TYPES, D as UpdateSemanticObjectMeta, F as SQL_DIALECTS, M as RELATIONSHIP_JOIN_TYPES, N as RULE_OPERATORS, O as CONSTRAINT_SCOPES, P as SEMANTIC_OBJECT_SCOPES, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, j as FIELD_ROLES, k as CONSTRAINT_SEVERITIES, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, t as CreateSemanticObjectMeta, u as SemanticDatasetData, x as SemanticRelationshipData } from "../../types-D6Fbf_y3.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
/**
|
|
4
4
|
* The message out of a metastore error body.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as SemanticRuleExpression, D as UpdateSemanticObjectMeta, E as SemanticValidationQuery, S as SemanticRelationshipJoinType, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, c as SemanticConstraintSeverity, d as SemanticFieldData, f as SemanticFieldRole, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, l as SemanticConstraintType, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, r as SemanticAiMetadata, s as SemanticConstraintScope, t as CreateSemanticObjectMeta, u as SemanticDatasetData, v as SemanticObjectMeta, w as SemanticRuleOperator, x as SemanticRelationshipData, y as SemanticObjectScope } from "../../types-
|
|
1
|
+
import { C as SemanticRuleExpression, D as UpdateSemanticObjectMeta, E as SemanticValidationQuery, S as SemanticRelationshipJoinType, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, c as SemanticConstraintSeverity, d as SemanticFieldData, f as SemanticFieldRole, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, l as SemanticConstraintType, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, r as SemanticAiMetadata, s as SemanticConstraintScope, t as CreateSemanticObjectMeta, u as SemanticDatasetData, v as SemanticObjectMeta, w as SemanticRuleOperator, x as SemanticRelationshipData, y as SemanticObjectScope } from "../../types-CuYaiy4R.cjs";
|
|
2
2
|
export { CreateSemanticObjectMeta, MetastoreClient, SemanticAiMetadata, SemanticChildObjectDataMap, SemanticChildObjectType, SemanticConstraintData, SemanticConstraintScope, SemanticConstraintSeverity, SemanticConstraintType, SemanticDatasetData, SemanticFieldData, SemanticFieldRole, SemanticGlossaryData, SemanticMetricData, SemanticModelChildRef, SemanticModelData, SemanticObject, SemanticObjectMeta, SemanticObjectScope, SemanticObjectType, SemanticRelationshipData, SemanticRelationshipJoinType, SemanticRuleExpression, SemanticRuleOperator, SemanticUnreadableObjectRef, SemanticValidationQuery, UpdateSemanticObjectMeta };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as SemanticRuleExpression, D as UpdateSemanticObjectMeta, E as SemanticValidationQuery, S as SemanticRelationshipJoinType, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, c as SemanticConstraintSeverity, d as SemanticFieldData, f as SemanticFieldRole, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, l as SemanticConstraintType, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, r as SemanticAiMetadata, s as SemanticConstraintScope, t as CreateSemanticObjectMeta, u as SemanticDatasetData, v as SemanticObjectMeta, w as SemanticRuleOperator, x as SemanticRelationshipData, y as SemanticObjectScope } from "../../types-
|
|
1
|
+
import { C as SemanticRuleExpression, D as UpdateSemanticObjectMeta, E as SemanticValidationQuery, S as SemanticRelationshipJoinType, T as SemanticUnreadableObjectRef, _ as SemanticObject, a as SemanticChildObjectType, b as SemanticObjectType, c as SemanticConstraintSeverity, d as SemanticFieldData, f as SemanticFieldRole, g as SemanticModelData, h as SemanticModelChildRef, i as SemanticChildObjectDataMap, l as SemanticConstraintType, m as SemanticMetricData, n as MetastoreClient, o as SemanticConstraintData, p as SemanticGlossaryData, r as SemanticAiMetadata, s as SemanticConstraintScope, t as CreateSemanticObjectMeta, u as SemanticDatasetData, v as SemanticObjectMeta, w as SemanticRuleOperator, x as SemanticRelationshipData, y as SemanticObjectScope } from "../../types-D6Fbf_y3.js";
|
|
2
2
|
export { CreateSemanticObjectMeta, MetastoreClient, SemanticAiMetadata, SemanticChildObjectDataMap, SemanticChildObjectType, SemanticConstraintData, SemanticConstraintScope, SemanticConstraintSeverity, SemanticConstraintType, SemanticDatasetData, SemanticFieldData, SemanticFieldRole, SemanticGlossaryData, SemanticMetricData, SemanticModelChildRef, SemanticModelData, SemanticObject, SemanticObjectMeta, SemanticObjectScope, SemanticObjectType, SemanticRelationshipData, SemanticRelationshipJoinType, SemanticRuleExpression, SemanticRuleOperator, SemanticUnreadableObjectRef, SemanticValidationQuery, UpdateSemanticObjectMeta };
|
package/dist/sdk/tag/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { v as KeboolaObjectId } from "../../index-24GpnYhn.cjs";
|
|
2
|
-
import { S as MetaObject } from "../../types-
|
|
3
|
-
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, t as CreateMetaObjectMetaDataInput } from "../../types-
|
|
2
|
+
import { S as MetaObject } from "../../types-CF5ZROX5.cjs";
|
|
3
|
+
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, t as CreateMetaObjectMetaDataInput } from "../../types-DslO1S5E.cjs";
|
|
4
4
|
type Options = {
|
|
5
5
|
metastoreClient: MetastoreClient;
|
|
6
6
|
};
|
package/dist/sdk/tag/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { v as KeboolaObjectId } from "../../index-BUZ-vTRt.js";
|
|
2
|
-
import { S as MetaObject } from "../../types-
|
|
3
|
-
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, t as CreateMetaObjectMetaDataInput } from "../../types-
|
|
2
|
+
import { S as MetaObject } from "../../types-D4knWlwr.js";
|
|
3
|
+
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, t as CreateMetaObjectMetaDataInput } from "../../types-EdL0Eb0B.js";
|
|
4
4
|
type Options = {
|
|
5
5
|
metastoreClient: MetastoreClient;
|
|
6
6
|
};
|
package/dist/sdk/tag/types.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, r as TagBindingData, t as CreateMetaObjectMetaDataInput } from "../../types-
|
|
1
|
+
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, r as TagBindingData, t as CreateMetaObjectMetaDataInput } from "../../types-DslO1S5E.cjs";
|
|
2
2
|
export { CreateMetaObjectMetaDataInput, MetastoreClient, TagBindingData, TagData, TagWithBindings, UpdateMetaObjectMetaDataInput };
|
package/dist/sdk/tag/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, r as TagBindingData, t as CreateMetaObjectMetaDataInput } from "../../types-
|
|
1
|
+
import { a as TagWithBindings, i as TagData, n as MetastoreClient, o as UpdateMetaObjectMetaDataInput, r as TagBindingData, t as CreateMetaObjectMetaDataInput } from "../../types-EdL0Eb0B.js";
|
|
2
2
|
export { CreateMetaObjectMetaDataInput, MetastoreClient, TagBindingData, TagData, TagWithBindings, UpdateMetaObjectMetaDataInput };
|
package/dist/sdk/vault/index.cjs
CHANGED
|
@@ -16,18 +16,9 @@ const vaultRef = {
|
|
|
16
16
|
decode: (s) => s.match(VAULT_REF_RE)?.[1] ?? null,
|
|
17
17
|
isMatch: (s) => VAULT_REF_RE.test(s)
|
|
18
18
|
};
|
|
19
|
-
const partitionByOauth = (variables) =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
oauth: [...acc.oauth, variable]
|
|
23
|
-
};
|
|
24
|
-
return {
|
|
25
|
-
...acc,
|
|
26
|
-
regular: [...acc.regular, variable]
|
|
27
|
-
};
|
|
28
|
-
}, {
|
|
29
|
-
oauth: [],
|
|
30
|
-
regular: []
|
|
19
|
+
const partitionByOauth = (variables) => ({
|
|
20
|
+
oauth: variables.filter((variable) => isVariableOauth(variable)),
|
|
21
|
+
regular: variables.filter((variable) => !isVariableOauth(variable))
|
|
31
22
|
});
|
|
32
23
|
// src/sdks/vault/vaultSdk.ts
|
|
33
24
|
const resolveBranchType = (variable, defaultBranchId) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["concurrent"],"sources":["../../../src/sdks/vault/helpers.ts","../../../src/sdks/vault/vaultSdk.ts"],"sourcesContent":["import type { AnyVariable, CreateVariableBody } from '../../clients/vault/types';\n\nexport const isVariableEncryptionRequired = (variable: AnyVariable): boolean =>\n !!variable.flags?.includes('encrypted');\n\nexport const isVariableOauth = (variable: AnyVariable): boolean =>\n !!variable.flags?.includes('oauthCredentialsId');\n\nconst isSameAttributes = (\n a: CreateVariableBody['attributes'],\n b: CreateVariableBody['attributes'],\n): boolean => {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k) => a[k] === b[k]);\n};\n\nexport const isSameVariable = (a: AnyVariable, b: AnyVariable): boolean =>\n a.key === b.key && isSameAttributes(a.attributes, b.attributes);\n\nconst VAULT_REF_RE = /^\\{\\{ vault\\.(.+) \\}\\}$/;\n\nexport const vaultRef = {\n encode: (key: string): string => `{{ vault.${key} }}`,\n decode: (s: string): string | null => s.match(VAULT_REF_RE)?.[1] ?? null,\n isMatch: (s: string): boolean => VAULT_REF_RE.test(s),\n};\n\nexport const partitionByOauth = <T extends AnyVariable>(\n variables: T[],\n): { oauth: T[]; regular: T[] }
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["concurrent"],"sources":["../../../src/sdks/vault/helpers.ts","../../../src/sdks/vault/vaultSdk.ts"],"sourcesContent":["import type { AnyVariable, CreateVariableBody } from '../../clients/vault/types';\n\nexport const isVariableEncryptionRequired = (variable: AnyVariable): boolean =>\n !!variable.flags?.includes('encrypted');\n\nexport const isVariableOauth = (variable: AnyVariable): boolean =>\n !!variable.flags?.includes('oauthCredentialsId');\n\nconst isSameAttributes = (\n a: CreateVariableBody['attributes'],\n b: CreateVariableBody['attributes'],\n): boolean => {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k) => a[k] === b[k]);\n};\n\nexport const isSameVariable = (a: AnyVariable, b: AnyVariable): boolean =>\n a.key === b.key && isSameAttributes(a.attributes, b.attributes);\n\nconst VAULT_REF_RE = /^\\{\\{ vault\\.(.+) \\}\\}$/;\n\nexport const vaultRef = {\n encode: (key: string): string => `{{ vault.${key} }}`,\n decode: (s: string): string | null => s.match(VAULT_REF_RE)?.[1] ?? null,\n isMatch: (s: string): boolean => VAULT_REF_RE.test(s),\n};\n\nexport const partitionByOauth = <T extends AnyVariable>(\n variables: T[],\n): { oauth: T[]; regular: T[] } => ({\n oauth: variables.filter((variable) => isVariableOauth(variable)),\n regular: variables.filter((variable) => !isVariableOauth(variable)),\n});\n","import type { EncryptQuery } from '../../clients/encryption/types';\nimport type { CreateVariableBody, VariableWithHash } from '../../clients/vault/types';\nimport { concurrent } from '../../utils';\n\nimport { isVariableEncryptionRequired } from './helpers';\nimport type { EncryptionClient, EncryptionCtx, VaultClient } from './types';\n\ntype Options = {\n vaultClient: VaultClient;\n encryptionClient: EncryptionClient;\n};\n\n// branchType is a property of each variable's own branchId, not of the batch — resolving it\n// here (rather than letting callers pre-compute one value) keeps a group write correct when it\n// spans branch scopes.\nconst resolveBranchType = (\n variable: CreateVariableBody,\n defaultBranchId: string,\n): EncryptQuery['branchType'] => {\n const branchId = variable.attributes?.branchId;\n if (!branchId) return null;\n return branchId === defaultBranchId ? 'default' : 'dev';\n};\n\n// The vault API rejects optional fields when they're present as empty strings — `group: ''`\n// and `attributes.branchId: ''` both 400 the request. The strict thing for an SDK to do is\n// throw and force callers to clean their input at the edge. We tolerate empties only because\n// kbc-ui's form state defaults un-filled text inputs to '' and the cost of fixing every form\n// submit to normalize before calling is too high right now. Remove this helper once the\n// caller side stops emitting empties — the SDK should ideally be strict about its inputs.\nconst stripEmptyOptionals = (body: CreateVariableBody): CreateVariableBody => {\n const { group, attributes, ...rest } = body;\n const { branchId, ...restAttrs } = attributes ?? {};\n return {\n ...rest,\n ...(group ? { group } : {}),\n attributes: branchId ? { ...restAttrs, branchId } : restAttrs,\n };\n};\n\nexport const createVaultSdk = ({ vaultClient, encryptionClient }: Options) => {\n const createVariable = async (variable: CreateVariableBody, encryption: EncryptionCtx) => {\n const body = stripEmptyOptionals(variable);\n\n const encryptedValue = isVariableEncryptionRequired(body)\n ? await encryptionClient.encrypt({\n projectId: encryption.projectId,\n data: body.value,\n branchType: resolveBranchType(body, encryption.defaultBranchId),\n })\n : body.value;\n\n return vaultClient.createVariable({ ...body, value: encryptedValue });\n };\n\n const deleteVariable = async (variable: VariableWithHash, signal?: AbortSignal) => {\n if (!variable.hash) throw new Error('Variable hash is missing');\n await vaultClient.deleteVariable(variable.hash, signal);\n };\n\n const updateVariable = async (\n variable: VariableWithHash,\n encryption: EncryptionCtx,\n signal?: AbortSignal,\n ) => {\n await deleteVariable(variable, signal);\n return createVariable(variable, encryption);\n };\n\n const setVariablesGroup = async (\n group: string,\n variables: VariableWithHash[],\n encryption: EncryptionCtx,\n signal?: AbortSignal,\n ) =>\n concurrent({\n items: variables,\n process: (variable) => updateVariable({ ...variable, group }, encryption, signal),\n concurrency: 3,\n });\n\n return {\n createVariable,\n deleteVariable,\n updateVariable,\n setVariablesGroup,\n };\n};\n"],"mappings":";;;AAEA,MAAa,gCAAgC,aAC3C,CAAC,CAAC,SAAS,OAAO,SAAS,WAAW;AAExC,MAAa,mBAAmB,aAC9B,CAAC,CAAC,SAAS,OAAO,SAAS,oBAAoB;AAEjD,MAAM,oBACJ,GACA,MACY;CACZ,MAAM,QAAQ,OAAO,KAAK,CAAC;CAC3B,MAAM,QAAQ,OAAO,KAAK,CAAC;CAC3B,IAAI,MAAM,WAAW,MAAM,QAAQ,OAAO;CAC1C,OAAO,MAAM,OAAO,MAAM,EAAE,OAAO,EAAE,EAAE;AACzC;AAEA,MAAa,kBAAkB,GAAgB,MAC7C,EAAE,QAAQ,EAAE,OAAO,iBAAiB,EAAE,YAAY,EAAE,UAAU;AAEhE,MAAM,eAAe;AAErB,MAAa,WAAW;CACtB,SAAS,QAAwB,YAAY,IAAI;CACjD,SAAS,MAA6B,EAAE,MAAM,YAAY,CAAC,GAAG,MAAM;CACpE,UAAU,MAAuB,aAAa,KAAK,CAAC;AACtD;AAEA,MAAa,oBACX,eACkC;CAClC,OAAO,UAAU,QAAQ,aAAa,gBAAgB,QAAQ,CAAC;CAC/D,SAAS,UAAU,QAAQ,aAAa,CAAC,gBAAgB,QAAQ,CAAC;AACpE;;ACnBA,MAAM,qBACJ,UACA,oBAC+B;CAC/B,MAAM,WAAW,SAAS,YAAY;CACtC,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,aAAa,kBAAkB,YAAY;AACpD;AAQA,MAAM,uBAAuB,SAAiD;CAC5E,MAAM,EAAE,OAAO,YAAY,GAAG,SAAS;CACvC,MAAM,EAAE,UAAU,GAAG,cAAc,cAAc,CAAC;CAClD,OAAO;EACL,GAAG;EACH,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EACzB,YAAY,WAAW;GAAE,GAAG;GAAW;EAAS,IAAI;CACtD;AACF;AAEA,MAAa,kBAAkB,EAAE,aAAa,uBAAgC;CAC5E,MAAM,iBAAiB,OAAO,UAA8B,eAA8B;EACxF,MAAM,OAAO,oBAAoB,QAAQ;EAEzC,MAAM,iBAAiB,6BAA6B,IAAI,IACpD,MAAM,iBAAiB,QAAQ;GAC7B,WAAW,WAAW;GACtB,MAAM,KAAK;GACX,YAAY,kBAAkB,MAAM,WAAW,eAAe;EAChE,CAAC,IACD,KAAK;EAET,OAAO,YAAY,eAAe;GAAE,GAAG;GAAM,OAAO;EAAe,CAAC;CACtE;CAEA,MAAM,iBAAiB,OAAO,UAA4B,WAAyB;EACjF,IAAI,CAAC,SAAS,MAAM,MAAM,IAAI,MAAM,0BAA0B;EAC9D,MAAM,YAAY,eAAe,SAAS,MAAM,MAAM;CACxD;CAEA,MAAM,iBAAiB,OACrB,UACA,YACA,WACG;EACH,MAAM,eAAe,UAAU,MAAM;EACrC,OAAO,eAAe,UAAU,UAAU;CAC5C;CAEA,MAAM,oBAAoB,OACxB,OACA,WACA,YACA,WAEAA,mBAAAA,WAAW;EACT,OAAO;EACP,UAAU,aAAa,eAAe;GAAE,GAAG;GAAU;EAAM,GAAG,YAAY,MAAM;EAChF,aAAa;CACf,CAAC;CAEH,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _t as vaultRef, gt as partitionByOauth, ht as isVariableOauth, mt as isVariableEncryptionRequired, pt as isSameVariable, vt as createVaultSdk, yt as EncryptionCtx } from "../../index-
|
|
1
|
+
import { _t as vaultRef, gt as partitionByOauth, ht as isVariableOauth, mt as isVariableEncryptionRequired, pt as isSameVariable, vt as createVaultSdk, yt as EncryptionCtx } from "../../index-DPhGNQC5.cjs";
|
|
2
2
|
export { type EncryptionCtx, createVaultSdk, isSameVariable, isVariableEncryptionRequired, isVariableOauth, partitionByOauth, vaultRef };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _t as vaultRef, gt as partitionByOauth, ht as isVariableOauth, mt as isVariableEncryptionRequired, pt as isSameVariable, vt as createVaultSdk, yt as EncryptionCtx } from "../../index-
|
|
1
|
+
import { _t as vaultRef, gt as partitionByOauth, ht as isVariableOauth, mt as isVariableEncryptionRequired, pt as isSameVariable, vt as createVaultSdk, yt as EncryptionCtx } from "../../index-GlHJ4j3a.js";
|
|
2
2
|
export { type EncryptionCtx, createVaultSdk, isSameVariable, isVariableEncryptionRequired, isVariableOauth, partitionByOauth, vaultRef };
|
package/dist/sdk/vault/index.js
CHANGED
|
@@ -15,18 +15,9 @@ const vaultRef = {
|
|
|
15
15
|
decode: (s) => s.match(VAULT_REF_RE)?.[1] ?? null,
|
|
16
16
|
isMatch: (s) => VAULT_REF_RE.test(s)
|
|
17
17
|
};
|
|
18
|
-
const partitionByOauth = (variables) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
oauth: [...acc.oauth, variable]
|
|
22
|
-
};
|
|
23
|
-
return {
|
|
24
|
-
...acc,
|
|
25
|
-
regular: [...acc.regular, variable]
|
|
26
|
-
};
|
|
27
|
-
}, {
|
|
28
|
-
oauth: [],
|
|
29
|
-
regular: []
|
|
18
|
+
const partitionByOauth = (variables) => ({
|
|
19
|
+
oauth: variables.filter((variable) => isVariableOauth(variable)),
|
|
20
|
+
regular: variables.filter((variable) => !isVariableOauth(variable))
|
|
30
21
|
});
|
|
31
22
|
// src/sdks/vault/vaultSdk.ts
|
|
32
23
|
const resolveBranchType = (variable, defaultBranchId) => {
|