@cobaltcore-dev/aurora 0.4.0 → 0.6.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.
Files changed (178) hide show
  1. package/README.md +73 -77
  2. package/dist/client/AuroraApp.d.ts +15 -0
  3. package/dist/client/{AuthProvider-D-5Jpa6F.mjs → AuthProvider-Co4d0WzB.mjs} +3 -3
  4. package/dist/client/{AuthProvider-D-5Jpa6F.mjs.map → AuthProvider-Co4d0WzB.mjs.map} +1 -1
  5. package/dist/client/{ContentHeader-BXZoN3B9.mjs → ContentHeader-kx1Th5Sq.mjs} +29 -29
  6. package/dist/client/{ContentHeader-BXZoN3B9.mjs.map → ContentHeader-kx1Th5Sq.mjs.map} +1 -1
  7. package/dist/client/DeleteFlavorModal-C3cb7YiJ.mjs +638 -0
  8. package/dist/client/DeleteFlavorModal-C3cb7YiJ.mjs.map +1 -0
  9. package/dist/client/{EditSecurityGroupModal-DK3WYikA.mjs → EditSecurityGroupModal-CpP54WIK.mjs} +22 -22
  10. package/dist/client/{EditSecurityGroupModal-DK3WYikA.mjs.map → EditSecurityGroupModal-CpP54WIK.mjs.map} +1 -1
  11. package/dist/client/{FiltersInput-OVeIJzIo.mjs → FiltersInput-DxcyR6Bp.mjs} +18 -18
  12. package/dist/client/{FiltersInput-OVeIJzIo.mjs.map → FiltersInput-DxcyR6Bp.mjs.map} +1 -1
  13. package/dist/client/{FloatingIpActionModals-Dok7fJss.mjs → FloatingIpActionModals-BP8RWHbu.mjs} +77 -77
  14. package/dist/client/{FloatingIpActionModals-Dok7fJss.mjs.map → FloatingIpActionModals-BP8RWHbu.mjs.map} +1 -1
  15. package/dist/client/ImageToastNotifications-TZ3EfQg-.mjs +1219 -0
  16. package/dist/client/ImageToastNotifications-TZ3EfQg-.mjs.map +1 -0
  17. package/dist/client/{RouteError-pDEWC_k7.mjs → RouteError-QSV7qOoJ.mjs} +6 -6
  18. package/dist/client/{RouteError-pDEWC_k7.mjs.map → RouteError-QSV7qOoJ.mjs.map} +1 -1
  19. package/dist/client/{SortInput-DXWSqSny.mjs → SortInput-CYv2_Pur.mjs} +6 -6
  20. package/dist/client/{SortInput-DXWSqSny.mjs.map → SortInput-CYv2_Pur.mjs.map} +1 -1
  21. package/dist/client/{_auth-CJj1Cnbm.mjs → _auth-DXJkv9QO.mjs} +3 -3
  22. package/dist/client/{_auth-CJj1Cnbm.mjs.map → _auth-DXJkv9QO.mjs.map} +1 -1
  23. package/dist/client/{_flavorId-BoNcxYmF.mjs → _flavorId-C2x43-6S.mjs} +15 -15
  24. package/dist/client/_flavorId-C2x43-6S.mjs.map +1 -0
  25. package/dist/client/_flavorId-CR8ZUI-P.mjs +194 -0
  26. package/dist/client/_flavorId-CR8ZUI-P.mjs.map +1 -0
  27. package/dist/client/{_floatingIpId-D33bOEmH.mjs → _floatingIpId-BCk41_Lb.mjs} +3 -3
  28. package/dist/client/{_floatingIpId-D33bOEmH.mjs.map → _floatingIpId-BCk41_Lb.mjs.map} +1 -1
  29. package/dist/client/{_floatingIpId-DF_BSJN6.mjs → _floatingIpId-BGrOAmPT.mjs} +48 -48
  30. package/dist/client/{_floatingIpId-DF_BSJN6.mjs.map → _floatingIpId-BGrOAmPT.mjs.map} +1 -1
  31. package/dist/client/_imageId-CvfD832b.mjs +534 -0
  32. package/dist/client/_imageId-CvfD832b.mjs.map +1 -0
  33. package/dist/client/_pcaId-BxBt5DXi.mjs +459 -0
  34. package/dist/client/_pcaId-BxBt5DXi.mjs.map +1 -0
  35. package/dist/client/{_pcaId-BYCoeK6_.mjs → _pcaId-DOHycvCf.mjs} +3 -3
  36. package/dist/client/{_pcaId-BYCoeK6_.mjs.map → _pcaId-DOHycvCf.mjs.map} +1 -1
  37. package/dist/client/_projectId-BDSWnMGj.mjs +46 -0
  38. package/dist/client/_projectId-BDSWnMGj.mjs.map +1 -0
  39. package/dist/client/{_projectId-OW2xkK43.mjs → _projectId-DOgwFiqD.mjs} +3 -3
  40. package/dist/client/{_projectId-OW2xkK43.mjs.map → _projectId-DOgwFiqD.mjs.map} +1 -1
  41. package/dist/client/_projectId-DS4nR59B.mjs +299 -0
  42. package/dist/client/_projectId-DS4nR59B.mjs.map +1 -0
  43. package/dist/client/{_projectId-BwLMEMGC.mjs → _projectId-MxcHrXW4.mjs} +21 -21
  44. package/dist/client/_projectId-MxcHrXW4.mjs.map +1 -0
  45. package/dist/client/{_securityGroupId-B-Z-CzLp.mjs → _securityGroupId-CJJanWiY.mjs} +3 -3
  46. package/dist/client/{_securityGroupId-B-Z-CzLp.mjs.map → _securityGroupId-CJJanWiY.mjs.map} +1 -1
  47. package/dist/client/{_securityGroupId-B1bOYRbX.mjs → _securityGroupId-KKw4RPdH.mjs} +445 -446
  48. package/dist/client/{_securityGroupId-B1bOYRbX.mjs.map → _securityGroupId-KKw4RPdH.mjs.map} +1 -1
  49. package/dist/client/{containers-BjWqjNOx.mjs → _storageType-4wSxI__0.mjs} +19 -16
  50. package/dist/client/_storageType-4wSxI__0.mjs.map +1 -0
  51. package/dist/client/_storageType-DYjo-6ej.mjs +3243 -0
  52. package/dist/client/_storageType-DYjo-6ej.mjs.map +1 -0
  53. package/dist/client/_storageType-zeSZe--V.mjs +7 -0
  54. package/dist/client/_storageType-zeSZe--V.mjs.map +1 -0
  55. package/dist/client/about-Bo9vxGHy.mjs +92 -0
  56. package/dist/client/{about-DLn1ShhF.mjs.map → about-Bo9vxGHy.mjs.map} +1 -1
  57. package/dist/client/aurora-DDzsst74.mjs +19 -0
  58. package/dist/client/{aurora-CRcxVUCo.mjs.map → aurora-DDzsst74.mjs.map} +1 -1
  59. package/dist/client/{build-BJDfnAyi.mjs → build-DeJcDjPi.mjs} +3802 -3376
  60. package/dist/client/build-DeJcDjPi.mjs.map +1 -0
  61. package/dist/client/{buildFilterParams-TeyosGyK.mjs → buildFilterParams-DoZzMKX9.mjs} +1 -1
  62. package/dist/client/{buildFilterParams-TeyosGyK.mjs.map → buildFilterParams-DoZzMKX9.mjs.map} +1 -1
  63. package/dist/client/{cn-C3laVXMm.mjs → cn-DM4Cy3jv.mjs} +1 -1
  64. package/dist/client/{cn-C3laVXMm.mjs.map → cn-DM4Cy3jv.mjs.map} +1 -1
  65. package/dist/client/constants-BmcGYeR-.mjs +153 -0
  66. package/dist/client/constants-BmcGYeR-.mjs.map +1 -0
  67. package/dist/client/{flavors-D8oElC2K.mjs → flavors-BxFVqgnb.mjs} +2 -2
  68. package/dist/client/{flavors-D8oElC2K.mjs.map → flavors-BxFVqgnb.mjs.map} +1 -1
  69. package/dist/client/flavors-CfdgjsZY.mjs +632 -0
  70. package/dist/client/flavors-CfdgjsZY.mjs.map +1 -0
  71. package/dist/client/{flavors-BXPYAFyQ.mjs → flavors-DWMZ6TuJ.mjs} +2 -2
  72. package/dist/client/{flavors-BXPYAFyQ.mjs.map → flavors-DWMZ6TuJ.mjs.map} +1 -1
  73. package/dist/client/{floatingips-Fa6ocNUu.mjs → floatingips-ByRb82wS.mjs} +138 -139
  74. package/dist/client/{floatingips-Fa6ocNUu.mjs.map → floatingips-ByRb82wS.mjs.map} +1 -1
  75. package/dist/client/{formatBytes-tQBEnPoL.mjs → formatBytes-CZv_XyCY.mjs} +1 -1
  76. package/dist/client/{formatBytes-tQBEnPoL.mjs.map → formatBytes-CZv_XyCY.mjs.map} +1 -1
  77. package/dist/client/{helpers--JWXi40U.mjs → helpers-1PpYf-fC.mjs} +1 -1
  78. package/dist/client/{helpers--JWXi40U.mjs.map → helpers-1PpYf-fC.mjs.map} +1 -1
  79. package/dist/client/hooks-dSArr2Ca.mjs +2 -0
  80. package/dist/client/images-CKqIXUq52.mjs +1873 -0
  81. package/dist/client/images-CKqIXUq52.mjs.map +1 -0
  82. package/dist/client/{images-tYfyOkX8.mjs → images-C_dX7nY6.mjs} +3 -3
  83. package/dist/client/{images-tYfyOkX8.mjs.map → images-C_dX7nY6.mjs.map} +1 -1
  84. package/dist/client/{images-CTLCY-yY.mjs → images-CenluYV8.mjs} +2 -2
  85. package/dist/client/{images-CTLCY-yY.mjs.map → images-CenluYV8.mjs.map} +1 -1
  86. package/dist/client/{images-DM9I8G0p.mjs → images-NBf2bV43.mjs} +2 -2
  87. package/dist/client/{images-DM9I8G0p.mjs.map → images-NBf2bV43.mjs.map} +1 -1
  88. package/dist/client/index.js +428 -477
  89. package/dist/client/index.js.map +1 -1
  90. package/dist/client/{md-BivyCkGC.mjs → md-CYTrL5dq.mjs} +58 -22
  91. package/dist/client/{md-BivyCkGC.mjs.map → md-CYTrL5dq.mjs.map} +1 -1
  92. package/dist/client/{network-rYLHyf15.mjs → network-DuZm76BZ.mjs} +2 -2
  93. package/dist/client/{network-rYLHyf15.mjs.map → network-DuZm76BZ.mjs.map} +1 -1
  94. package/dist/client/objects-BJM6YeuF.mjs +5708 -0
  95. package/dist/client/objects-BJM6YeuF.mjs.map +1 -0
  96. package/dist/client/objects-gxSjvbvF.mjs +101 -0
  97. package/dist/client/objects-gxSjvbvF.mjs.map +1 -0
  98. package/dist/client/objects-o2Cj_ndZ.mjs +8 -0
  99. package/dist/client/objects-o2Cj_ndZ.mjs.map +1 -0
  100. package/dist/client/{pca-COmKvp3J.mjs → pca-Bl8NmoVZ.mjs} +2 -2
  101. package/dist/client/{pca-COmKvp3J.mjs.map → pca-Bl8NmoVZ.mjs.map} +1 -1
  102. package/dist/client/pca-RSiWpJs9.mjs +182 -0
  103. package/dist/client/pca-RSiWpJs9.mjs.map +1 -0
  104. package/dist/client/projects-CgclWI16.mjs +105 -0
  105. package/dist/client/projects-CgclWI16.mjs.map +1 -0
  106. package/dist/client/{projects-DI_L4oDw.mjs → projects-D2iewAzu.mjs} +2 -2
  107. package/dist/client/{projects-DI_L4oDw.mjs.map → projects-D2iewAzu.mjs.map} +1 -1
  108. package/dist/client/{projects-Dl5XkXUP.mjs → projects-pe2_dCnV.mjs} +3 -3
  109. package/dist/client/{projects-Dl5XkXUP.mjs.map → projects-pe2_dCnV.mjs.map} +1 -1
  110. package/dist/client/{projects-HoQ0gE5Y.mjs → projects-yiK0HGSA.mjs} +2 -2
  111. package/dist/client/{projects-HoQ0gE5Y.mjs.map → projects-yiK0HGSA.mjs.map} +1 -1
  112. package/dist/client/{securitygroups-BjkmHk2J.mjs → securitygroups-DahZkVYQ.mjs} +139 -140
  113. package/dist/client/{securitygroups-BjkmHk2J.mjs.map → securitygroups-DahZkVYQ.mjs.map} +1 -1
  114. package/dist/client/{trpcClient-BxguzNYF.mjs → trpcClient-BzPUgiM2.mjs} +1 -1
  115. package/dist/client/{trpcClient-BxguzNYF.mjs.map → trpcClient-BzPUgiM2.mjs.map} +1 -1
  116. package/dist/client/{useErrorTranslation-TZVwIAzq.mjs → useErrorTranslation-Dc0eE8Zt.mjs} +1 -1
  117. package/dist/client/{useErrorTranslation-TZVwIAzq.mjs.map → useErrorTranslation-Dc0eE8Zt.mjs.map} +1 -1
  118. package/dist/client/useListWithFiltering-DaYcu5AB.mjs +157 -0
  119. package/dist/client/useListWithFiltering-DaYcu5AB.mjs.map +1 -0
  120. package/dist/client/{useModal-DxxlilRm.mjs → useModal-DCs1OJh7.mjs} +1 -1
  121. package/dist/client/{useModal-DxxlilRm.mjs.map → useModal-DCs1OJh7.mjs.map} +1 -1
  122. package/dist/client/{useProjectId-OQv2KBbG.mjs → useProjectId-DBc5lpoU.mjs} +1 -1
  123. package/dist/client/{useProjectId-OQv2KBbG.mjs.map → useProjectId-DBc5lpoU.mjs.map} +1 -1
  124. package/dist/server/index.js +1285 -435
  125. package/package.json +5 -4
  126. package/dist/client/DeleteFlavorModal-BusYn32r.mjs +0 -629
  127. package/dist/client/DeleteFlavorModal-BusYn32r.mjs.map +0 -1
  128. package/dist/client/ImageToastNotifications-BG9LPnXf.mjs +0 -1267
  129. package/dist/client/ImageToastNotifications-BG9LPnXf.mjs.map +0 -1
  130. package/dist/client/ListToolbar-BojRTNbo.mjs +0 -129
  131. package/dist/client/ListToolbar-BojRTNbo.mjs.map +0 -1
  132. package/dist/client/_flavorId-BRonXvCo.mjs +0 -188
  133. package/dist/client/_flavorId-BRonXvCo.mjs.map +0 -1
  134. package/dist/client/_flavorId-BoNcxYmF.mjs.map +0 -1
  135. package/dist/client/_imageId-BL0I5_pv.mjs +0 -527
  136. package/dist/client/_imageId-BL0I5_pv.mjs.map +0 -1
  137. package/dist/client/_pcaId-CbBhBrX1.mjs +0 -466
  138. package/dist/client/_pcaId-CbBhBrX1.mjs.map +0 -1
  139. package/dist/client/_projectId-5NiasyXm.mjs +0 -26
  140. package/dist/client/_projectId-5NiasyXm.mjs.map +0 -1
  141. package/dist/client/_projectId-BwLMEMGC.mjs.map +0 -1
  142. package/dist/client/_projectId-D35MN1kY.mjs +0 -316
  143. package/dist/client/_projectId-D35MN1kY.mjs.map +0 -1
  144. package/dist/client/about-DLn1ShhF.mjs +0 -92
  145. package/dist/client/aurora-CRcxVUCo.mjs +0 -19
  146. package/dist/client/build-BJDfnAyi.mjs.map +0 -1
  147. package/dist/client/constants-B-P2r5F1.mjs +0 -128
  148. package/dist/client/constants-B-P2r5F1.mjs.map +0 -1
  149. package/dist/client/containers-BjWqjNOx.mjs.map +0 -1
  150. package/dist/client/containers-DsRWc1L5.mjs +0 -7
  151. package/dist/client/containers-DsRWc1L5.mjs.map +0 -1
  152. package/dist/client/containers-J7WFA18U.mjs +0 -3120
  153. package/dist/client/containers-J7WFA18U.mjs.map +0 -1
  154. package/dist/client/flavors-qvgPSI7J.mjs +0 -613
  155. package/dist/client/flavors-qvgPSI7J.mjs.map +0 -1
  156. package/dist/client/hooks-DEjb9d1F.mjs +0 -2
  157. package/dist/client/images-CSFfefAu.mjs +0 -1901
  158. package/dist/client/images-CSFfefAu.mjs.map +0 -1
  159. package/dist/client/objects-BciXwZ00.mjs +0 -86
  160. package/dist/client/objects-BciXwZ00.mjs.map +0 -1
  161. package/dist/client/objects-Cdew99tK.mjs +0 -8
  162. package/dist/client/objects-Cdew99tK.mjs.map +0 -1
  163. package/dist/client/objects-DaElrban.mjs +0 -5340
  164. package/dist/client/objects-DaElrban.mjs.map +0 -1
  165. package/dist/client/overview-BMhjFMIV.mjs +0 -15
  166. package/dist/client/overview-BMhjFMIV.mjs.map +0 -1
  167. package/dist/client/overview-BYIRj7_X.mjs +0 -15
  168. package/dist/client/overview-BYIRj7_X.mjs.map +0 -1
  169. package/dist/client/overview-DRCKNBH2.mjs +0 -15
  170. package/dist/client/overview-DRCKNBH2.mjs.map +0 -1
  171. package/dist/client/overview-urYLOVQE.mjs +0 -173
  172. package/dist/client/overview-urYLOVQE.mjs.map +0 -1
  173. package/dist/client/pca-oc7J0_Xd.mjs +0 -167
  174. package/dist/client/pca-oc7J0_Xd.mjs.map +0 -1
  175. package/dist/client/projects-BUabCzvw.mjs +0 -95
  176. package/dist/client/projects-BUabCzvw.mjs.map +0 -1
  177. package/dist/client/useListWithFiltering-CbhHJO4V.mjs +0 -32
  178. package/dist/client/useListWithFiltering-CbhHJO4V.mjs.map +0 -1
@@ -30779,11 +30779,11 @@ var flavorRouter = {
30779
30779
  })
30780
30780
  };
30781
30781
 
30782
- // src/server/Compute/routers/permissionRouter.ts
30782
+ // src/server/policies/createPermissionRouter.ts
30783
30783
  var import_zod10 = require("zod");
30784
30784
  var import_server8 = require("@trpc/server");
30785
30785
 
30786
- // src/server/policyEngineLoader.ts
30786
+ // src/server/policies/policyEngineLoader.ts
30787
30787
  var import_path = __toESM(require("path"));
30788
30788
  var import_fs = __toESM(require("fs"));
30789
30789
  var import_policy_engine = __toESM(require_esm());
@@ -30804,8 +30804,8 @@ Pass an absolute path via the policyDir option in createServer.`);
30804
30804
  return (0, import_policy_engine.createPolicyEngineFromFile)(file);
30805
30805
  }, "loadPolicyEngine");
30806
30806
 
30807
- // src/server/Compute/routers/permissionRouter.ts
30808
- var getPolicy = /* @__PURE__ */ __name((ctx, policyEngineName, engines) => {
30807
+ // src/server/policies/createPermissionRouter.ts
30808
+ var getPolicy = /* @__PURE__ */ __name((ctx, engine) => {
30809
30809
  const openstackSession = ctx.openstack;
30810
30810
  const token = openstackSession?.getToken();
30811
30811
  if (!token) {
@@ -30814,15 +30814,80 @@ var getPolicy = /* @__PURE__ */ __name((ctx, policyEngineName, engines) => {
30814
30814
  message: "No valid OpenStack token found"
30815
30815
  });
30816
30816
  }
30817
- const policyEngine = policyEngineName === "compute" ? engines.compute : engines.image;
30818
- return policyEngine.policy(token.tokenData, {
30817
+ return engine.policy(token.tokenData, {
30819
30818
  debug: true,
30820
30819
  defaultParams: {
30821
30820
  project_id: token.tokenData.project?.id
30822
30821
  }
30823
30822
  });
30824
30823
  }, "getPolicy");
30825
- var POLICY_MAPPINGS = {
30824
+ function createPermissionRouter(config) {
30825
+ const loadedEngines = Object.fromEntries(Object.entries(config.engines).map(([name, { fileName }]) => [
30826
+ name,
30827
+ loadPolicyEngine(fileName, config.policyDir)
30828
+ ]));
30829
+ for (const [permissionKey, mapping] of Object.entries(config.mappings)) {
30830
+ if (!Object.hasOwn(loadedEngines, mapping.engine)) {
30831
+ throw new Error(`Configuration error: Permission '${permissionKey}' references engine '${mapping.engine}', but no such engine is configured. Available engines: ${Object.keys(loadedEngines).join(", ")}`);
30832
+ }
30833
+ }
30834
+ const PERMISSION_KEY = import_zod10.z.string().superRefine((value, ctx) => {
30835
+ if (!Object.hasOwn(config.mappings, value)) {
30836
+ ctx.addIssue({
30837
+ code: "custom",
30838
+ message: `Unknown permission: ${value}`
30839
+ });
30840
+ }
30841
+ }).transform((value) => value);
30842
+ const checkSinglePermission = /* @__PURE__ */ __name((ctx, permission, engines) => {
30843
+ const mapping = config.mappings[permission];
30844
+ const engine = engines[mapping.engine];
30845
+ if (!engine) {
30846
+ throw new import_server8.TRPCError({
30847
+ code: "INTERNAL_SERVER_ERROR",
30848
+ message: `Policy engine '${mapping.engine}' not found for permission '${String(permission)}'`
30849
+ });
30850
+ }
30851
+ const policy = getPolicy(ctx, engine);
30852
+ return policy.check(mapping.rule);
30853
+ }, "checkSinglePermission");
30854
+ return {
30855
+ /**
30856
+ * Permission checking endpoint that determines whether a user has one or more specific permissions.
30857
+ *
30858
+ * Usage:
30859
+ * - `canUser({ project_id: "abc", permission: "servers:list" })` → returns `[boolean]`
30860
+ * - `canUser({ project_id: "abc", permission: ["servers:list", "flavors:create"] })` → returns `boolean[]`
30861
+ *
30862
+ * Input must be:
30863
+ * - A project_id (required, validated by projectScopedInputSchema), and
30864
+ * - A single valid permission key (string in mappings), or
30865
+ * - An array of valid permission keys.
30866
+ *
30867
+ * Invalid keys are rejected with a `BAD_REQUEST` error before the handler runs.
30868
+ * Empty array input returns an empty array (`[]`).
30869
+ * Always returns `boolean[]` for consistent destructuring on the client.
30870
+ */
30871
+ canUser: projectScopedProcedure.input(projectScopedInputSchema.extend({
30872
+ permission: import_zod10.z.union([
30873
+ PERMISSION_KEY,
30874
+ import_zod10.z.array(PERMISSION_KEY)
30875
+ ])
30876
+ })).query(async ({ ctx, input }) => {
30877
+ const permissions = Array.isArray(input.permission) ? input.permission : [
30878
+ input.permission
30879
+ ];
30880
+ if (permissions.length === 0) {
30881
+ return [];
30882
+ }
30883
+ return permissions.map((permission) => checkSinglePermission(ctx, permission, loadedEngines));
30884
+ })
30885
+ };
30886
+ }
30887
+ __name(createPermissionRouter, "createPermissionRouter");
30888
+
30889
+ // src/server/Compute/routers/permissionRouter.ts
30890
+ var COMPUTE_IMAGE_MAPPINGS = {
30826
30891
  // Servers
30827
30892
  "servers:list": {
30828
30893
  engine: "compute",
@@ -30912,41 +30977,18 @@ var POLICY_MAPPINGS = {
30912
30977
  rule: "modify_member"
30913
30978
  }
30914
30979
  };
30915
- var checkSinglePermission = /* @__PURE__ */ __name((ctx, permission, engines) => {
30916
- const policyMapping = POLICY_MAPPINGS[permission];
30917
- const policy = getPolicy(ctx, policyMapping.engine, engines);
30918
- return policy.check(policyMapping.rule);
30919
- }, "checkSinglePermission");
30920
- var PERMISSION_KEY = import_zod10.z.string().superRefine((value, ctx) => {
30921
- if (!Object.hasOwn(POLICY_MAPPINGS, value)) {
30922
- ctx.addIssue({
30923
- code: "custom",
30924
- message: `Unknown permission: ${value}`
30925
- });
30926
- }
30927
- }).transform((value) => value);
30928
- var buildPermissionRouter = /* @__PURE__ */ __name((policyDir) => {
30929
- const engines = {
30930
- compute: loadPolicyEngine("compute.yaml", policyDir),
30931
- image: loadPolicyEngine("image.yaml", policyDir)
30932
- };
30933
- return {
30934
- canUser: projectScopedProcedure.input(projectScopedInputSchema.extend({
30935
- permission: import_zod10.z.union([
30936
- PERMISSION_KEY,
30937
- import_zod10.z.array(PERMISSION_KEY)
30938
- ])
30939
- })).query(async ({ ctx, input }) => {
30940
- const permissions = typeof input.permission === "string" ? [
30941
- input.permission
30942
- ] : input.permission;
30943
- if (permissions.length === 0) {
30944
- return [];
30945
- }
30946
- return permissions.map((permission) => checkSinglePermission(ctx, permission, engines));
30947
- })
30948
- };
30949
- }, "buildPermissionRouter");
30980
+ var buildPermissionRouter = /* @__PURE__ */ __name((policyDir) => createPermissionRouter({
30981
+ policyDir,
30982
+ engines: {
30983
+ compute: {
30984
+ fileName: "compute.json"
30985
+ },
30986
+ image: {
30987
+ fileName: "image.json"
30988
+ }
30989
+ },
30990
+ mappings: COMPUTE_IMAGE_MAPPINGS
30991
+ }), "buildPermissionRouter");
30950
30992
 
30951
30993
  // src/server/Compute/routers/index.ts
30952
30994
  var buildComputeRouters = /* @__PURE__ */ __name((policyDir) => ({
@@ -33261,11 +33303,13 @@ var cephProtectedProcedure = cephCredentialMiddleware.use(/* @__PURE__ */ __name
33261
33303
 
33262
33304
  // src/server/Storage/helpers/s3ErrorMapper.ts
33263
33305
  var import_server12 = require("@trpc/server");
33306
+ var import_signal_openstack = __toESM(require_esm2());
33264
33307
  var S3_ERROR_MAP = {
33265
33308
  NoSuchBucket: "NOT_FOUND",
33266
33309
  NoSuchKey: "NOT_FOUND",
33267
33310
  NoSuchUpload: "NOT_FOUND",
33268
33311
  NoSuchVersion: "NOT_FOUND",
33312
+ NoSuchBucketPolicy: "NOT_FOUND",
33269
33313
  BucketAlreadyExists: "CONFLICT",
33270
33314
  BucketAlreadyOwnedByYou: "CONFLICT",
33271
33315
  BucketNotEmpty: "PRECONDITION_FAILED",
@@ -33279,6 +33323,7 @@ var S3_ERROR_MAP = {
33279
33323
  RequestTimeTooSkewed: "UNAUTHORIZED",
33280
33324
  InvalidBucketName: "BAD_REQUEST",
33281
33325
  KeyTooLongError: "BAD_REQUEST",
33326
+ MalformedPolicy: "BAD_REQUEST",
33282
33327
  EntityTooLarge: "PAYLOAD_TOO_LARGE",
33283
33328
  EntityTooSmall: "BAD_REQUEST"
33284
33329
  };
@@ -33290,7 +33335,10 @@ function mapS3ErrorToTRPCError(error, context) {
33290
33335
  const errorCode = s3Error.Code ?? s3Error.name ?? "";
33291
33336
  const trpcCode = S3_ERROR_MAP[errorCode] ?? "INTERNAL_SERVER_ERROR";
33292
33337
  if (!S3_ERROR_MAP[errorCode] && errorCode) {
33293
- console.warn(`[s3] Unmapped S3 error code: ${errorCode}`);
33338
+ import_signal_openstack.logger.warn("Unmapped S3 error code", {
33339
+ errorCode,
33340
+ operation: context.operation
33341
+ });
33294
33342
  }
33295
33343
  const parts = [
33296
33344
  `Failed to ${context.operation}`
@@ -33336,8 +33384,10 @@ var containerSchema = import_zod13.z.object({
33336
33384
  var listContainersInputSchema2 = projectScopedInputSchema.extend({
33337
33385
  includeMetadata: import_zod13.z.boolean().optional().default(false)
33338
33386
  });
33387
+ var bucketNameSchema = import_zod13.z.string().min(3, "Bucket name must be at least 3 characters").max(63, "Bucket name must be at most 63 characters").regex(/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/, "Bucket name must contain only lowercase letters, numbers, hyphens, and periods").refine((name) => !name.includes(".."), "Bucket name cannot contain consecutive periods").refine((name) => !/^\d+\.\d+\.\d+\.\d+$/.test(name), "Bucket name cannot be formatted as an IP address");
33388
+ var existingBucketNameSchema = import_zod13.z.string().min(1, "Bucket name is required").max(255, "Bucket name exceeds maximum length");
33339
33389
  var createBucketInputSchema = projectScopedInputSchema.extend({
33340
- bucketName: import_zod13.z.string().min(3).max(63),
33390
+ bucketName: bucketNameSchema,
33341
33391
  enableVersioning: import_zod13.z.boolean().optional().default(false)
33342
33392
  });
33343
33393
  var createBucketOutputSchema = import_zod13.z.object({
@@ -33459,6 +33509,83 @@ var s3ServiceInfoSchema = import_zod13.z.object({
33459
33509
  region: import_zod13.z.string().optional()
33460
33510
  });
33461
33511
  var getServiceInfoInputSchema = import_zod13.z.object({});
33512
+ var bucketPolicyStatementSchema = import_zod13.z.object({
33513
+ Sid: import_zod13.z.string().optional(),
33514
+ Effect: import_zod13.z.enum([
33515
+ "Allow",
33516
+ "Deny"
33517
+ ]),
33518
+ Principal: import_zod13.z.union([
33519
+ import_zod13.z.string(),
33520
+ import_zod13.z.object({
33521
+ AWS: import_zod13.z.union([
33522
+ import_zod13.z.string(),
33523
+ import_zod13.z.array(import_zod13.z.string())
33524
+ ]).optional(),
33525
+ Service: import_zod13.z.union([
33526
+ import_zod13.z.string(),
33527
+ import_zod13.z.array(import_zod13.z.string())
33528
+ ]).optional(),
33529
+ Federated: import_zod13.z.union([
33530
+ import_zod13.z.string(),
33531
+ import_zod13.z.array(import_zod13.z.string())
33532
+ ]).optional()
33533
+ })
33534
+ ]).superRefine((val, ctx) => {
33535
+ if (typeof val === "object" && !val.AWS && !val.Service && !val.Federated) {
33536
+ ctx.addIssue({
33537
+ code: "custom",
33538
+ message: "Principal object must contain at least one of: AWS, Service, or Federated"
33539
+ });
33540
+ }
33541
+ if (typeof val === "object" && val.AWS) {
33542
+ const arns = Array.isArray(val.AWS) ? val.AWS : [
33543
+ val.AWS
33544
+ ];
33545
+ for (const arn of arns) {
33546
+ if (arn !== "*" && !/^arn:aws:iam::\d{12}:(?:root|user\/.+|role\/.+)$/.test(arn)) {
33547
+ ctx.addIssue({
33548
+ code: "custom",
33549
+ message: `Invalid AWS principal ARN format: ${arn}. Expected arn:aws:iam::ACCOUNT-ID:root or arn:aws:iam::ACCOUNT-ID:(user|role)/NAME`
33550
+ });
33551
+ }
33552
+ }
33553
+ }
33554
+ }),
33555
+ Action: import_zod13.z.union([
33556
+ import_zod13.z.string(),
33557
+ import_zod13.z.array(import_zod13.z.string())
33558
+ ]),
33559
+ Resource: import_zod13.z.union([
33560
+ import_zod13.z.string(),
33561
+ import_zod13.z.array(import_zod13.z.string())
33562
+ ]),
33563
+ Condition: import_zod13.z.record(import_zod13.z.string(), import_zod13.z.record(import_zod13.z.string(), import_zod13.z.union([
33564
+ import_zod13.z.string(),
33565
+ import_zod13.z.array(import_zod13.z.string()),
33566
+ import_zod13.z.number(),
33567
+ import_zod13.z.boolean()
33568
+ ]))).optional()
33569
+ });
33570
+ var bucketPolicyDocumentSchema = import_zod13.z.object({
33571
+ Version: import_zod13.z.string().default("2012-10-17"),
33572
+ Id: import_zod13.z.string().optional(),
33573
+ Statement: import_zod13.z.array(bucketPolicyStatementSchema).min(1, "Policy must contain at least one statement")
33574
+ });
33575
+ var getBucketPolicyInputSchema = projectScopedInputSchema.extend({
33576
+ bucketName: existingBucketNameSchema
33577
+ });
33578
+ var getBucketPolicyOutputSchema = import_zod13.z.object({
33579
+ policy: bucketPolicyDocumentSchema.nullable(),
33580
+ policyText: import_zod13.z.string().nullable()
33581
+ });
33582
+ var setBucketPolicyInputSchema = projectScopedInputSchema.extend({
33583
+ bucketName: existingBucketNameSchema,
33584
+ policy: import_zod13.z.string().min(1).max(20480, "Policy document exceeds maximum size of 20KB")
33585
+ });
33586
+ var deleteBucketPolicyInputSchema = projectScopedInputSchema.extend({
33587
+ bucketName: existingBucketNameSchema
33588
+ });
33462
33589
 
33463
33590
  // src/server/Storage/constants.ts
33464
33591
  var S3_MAX_KEYS_PER_REQUEST = 1e3;
@@ -33495,7 +33622,7 @@ var containerRouter = {
33495
33622
  }));
33496
33623
  }
33497
33624
  const CONCURRENCY_LIMIT = 5;
33498
- const containersWithMetadata = [];
33625
+ const bucketsWithMetadata = [];
33499
33626
  for (let i = 0; i < buckets.length; i += CONCURRENCY_LIMIT) {
33500
33627
  const batch = buckets.slice(i, i + CONCURRENCY_LIMIT);
33501
33628
  const batchResults = await Promise.all(batch.map(async (bucket) => {
@@ -33531,9 +33658,9 @@ var containerRouter = {
33531
33658
  });
33532
33659
  }
33533
33660
  }));
33534
- containersWithMetadata.push(...batchResults);
33661
+ bucketsWithMetadata.push(...batchResults);
33535
33662
  }
33536
- return containersWithMetadata;
33663
+ return bucketsWithMetadata;
33537
33664
  } catch (error) {
33538
33665
  throw mapS3ErrorToTRPCError(error, {
33539
33666
  operation: "list containers"
@@ -34413,8 +34540,307 @@ var versioningRouter = {
34413
34540
  })
34414
34541
  };
34415
34542
 
34543
+ // src/server/Storage/routers/ceph/bucketPolicyRouter.ts
34544
+ var import_client_s35 = require("@aws-sdk/client-s3");
34545
+ var import_server15 = require("@trpc/server");
34546
+ var import_zod17 = require("zod");
34547
+ var policySetRateLimits = /* @__PURE__ */ new Map();
34548
+ function checkPolicySetRateLimit(bucketName, projectId) {
34549
+ const key = `${projectId}:${bucketName}`;
34550
+ const now = Date.now();
34551
+ const windowMs = 5 * 60 * 1e3;
34552
+ for (const [k, v] of policySetRateLimits.entries()) {
34553
+ if (now > v.resetAt) {
34554
+ policySetRateLimits.delete(k);
34555
+ }
34556
+ }
34557
+ const limit = policySetRateLimits.get(key);
34558
+ if (!limit || now > limit.resetAt) {
34559
+ policySetRateLimits.set(key, {
34560
+ count: 1,
34561
+ resetAt: now + windowMs
34562
+ });
34563
+ return;
34564
+ }
34565
+ if (limit.count >= 10) {
34566
+ throw new import_server15.TRPCError({
34567
+ code: "TOO_MANY_REQUESTS",
34568
+ message: "Policy modification rate limit exceeded. Maximum 10 policy changes per 5 minutes per bucket."
34569
+ });
34570
+ }
34571
+ limit.count++;
34572
+ }
34573
+ __name(checkPolicySetRateLimit, "checkPolicySetRateLimit");
34574
+ function validateResourceARNsMatchBucket(policy, bucketName) {
34575
+ for (const statement of policy.Statement) {
34576
+ const resources = Array.isArray(statement.Resource) ? statement.Resource : [
34577
+ statement.Resource
34578
+ ];
34579
+ for (const resource of resources) {
34580
+ const arnRegex = /^arn:aws:s3:::([^/]+)/;
34581
+ const match = resource.match(arnRegex);
34582
+ if (!match) {
34583
+ throw new import_server15.TRPCError({
34584
+ code: "BAD_REQUEST",
34585
+ message: `Policy Resource '${resource}' is not a valid S3 bucket ARN for bucket '${bucketName}'. Expected: arn:aws:s3:::${bucketName} or arn:aws:s3:::${bucketName}/*`
34586
+ });
34587
+ }
34588
+ if (match[1] !== bucketName) {
34589
+ throw new import_server15.TRPCError({
34590
+ code: "BAD_REQUEST",
34591
+ message: `Policy Resource ARN '${resource}' does not match bucket '${bucketName}'`
34592
+ });
34593
+ }
34594
+ }
34595
+ }
34596
+ }
34597
+ __name(validateResourceARNsMatchBucket, "validateResourceARNsMatchBucket");
34598
+ function validatePolicySemantics(policy) {
34599
+ if (policy.Statement.length > 100) {
34600
+ throw new import_server15.TRPCError({
34601
+ code: "BAD_REQUEST",
34602
+ message: "Policy exceeds maximum of 100 statements"
34603
+ });
34604
+ }
34605
+ const denyAllStatement = policy.Statement.find((s) => {
34606
+ if (s.Effect !== "Deny") return false;
34607
+ const actions = Array.isArray(s.Action) ? s.Action : [
34608
+ s.Action
34609
+ ];
34610
+ return actions.some((a) => a === "*" || a === "s3:*");
34611
+ });
34612
+ if (denyAllStatement) {
34613
+ throw new import_server15.TRPCError({
34614
+ code: "BAD_REQUEST",
34615
+ message: "Policy contains 'Deny *' or 'Deny s3:*' which may lock out all access including the bucket owner. Please use more specific deny rules."
34616
+ });
34617
+ }
34618
+ }
34619
+ __name(validatePolicySemantics, "validatePolicySemantics");
34620
+ var bucketPolicyRouter = {
34621
+ /**
34622
+ * Get the current bucket policy.
34623
+ *
34624
+ * Returns the policy as both a parsed object and raw JSON string.
34625
+ * Returns null if no policy is set (not an error).
34626
+ *
34627
+ * @throws TRPCError NOT_FOUND - bucket does not exist
34628
+ * @throws TRPCError FORBIDDEN - no credentials or access denied
34629
+ */
34630
+ get: cephProtectedProcedure.input(getBucketPolicyInputSchema).query(async ({ ctx, input }) => {
34631
+ const s3 = ctx.getCephClient();
34632
+ const { bucketName } = input;
34633
+ try {
34634
+ const response = await s3.send(new import_client_s35.GetBucketPolicyCommand({
34635
+ Bucket: bucketName
34636
+ }));
34637
+ const policyText = response.Policy ?? null;
34638
+ if (!policyText) {
34639
+ return {
34640
+ policy: null,
34641
+ policyText: null
34642
+ };
34643
+ }
34644
+ const policyObj = JSON.parse(policyText);
34645
+ const policy = bucketPolicyDocumentSchema.parse(policyObj);
34646
+ return {
34647
+ policy,
34648
+ policyText
34649
+ };
34650
+ } catch (error) {
34651
+ const s3Error = error;
34652
+ if (s3Error.name === "NoSuchBucketPolicy" || s3Error.Code === "NoSuchBucketPolicy") {
34653
+ return {
34654
+ policy: null,
34655
+ policyText: null
34656
+ };
34657
+ }
34658
+ throw mapS3ErrorToTRPCError(error, {
34659
+ operation: "get bucket policy",
34660
+ bucket: bucketName
34661
+ });
34662
+ }
34663
+ }),
34664
+ /**
34665
+ * Set (create or replace) a bucket policy.
34666
+ *
34667
+ * Accepts a policy document as a JSON string. Validates structure before
34668
+ * sending to S3. Replaces any existing policy completely.
34669
+ *
34670
+ * @throws TRPCError BAD_REQUEST - invalid policy JSON or structure
34671
+ * @throws TRPCError NOT_FOUND - bucket does not exist
34672
+ * @throws TRPCError FORBIDDEN - no credentials or access denied
34673
+ */
34674
+ set: cephProtectedProcedure.input(setBucketPolicyInputSchema).mutation(async ({ ctx, input }) => {
34675
+ const s3 = ctx.getCephClient();
34676
+ const { bucketName, policy } = input;
34677
+ checkPolicySetRateLimit(bucketName, input.project_id);
34678
+ if (policy.length > 20480) {
34679
+ throw new import_server15.TRPCError({
34680
+ code: "PAYLOAD_TOO_LARGE",
34681
+ message: "Policy document exceeds maximum size of 20KB"
34682
+ });
34683
+ }
34684
+ const openBrackets = (policy.match(/[{[]/g) || []).length;
34685
+ if (openBrackets > 50) {
34686
+ throw new import_server15.TRPCError({
34687
+ code: "BAD_REQUEST",
34688
+ message: "Policy JSON is too deeply nested (maximum 50 levels)"
34689
+ });
34690
+ }
34691
+ try {
34692
+ const policyObj = JSON.parse(policy);
34693
+ const validatedPolicy = bucketPolicyDocumentSchema.parse(policyObj);
34694
+ validateResourceARNsMatchBucket(validatedPolicy, bucketName);
34695
+ validatePolicySemantics(validatedPolicy);
34696
+ const policyText = JSON.stringify(validatedPolicy);
34697
+ await s3.send(new import_client_s35.PutBucketPolicyCommand({
34698
+ Bucket: bucketName,
34699
+ Policy: policyText
34700
+ }));
34701
+ return true;
34702
+ } catch (error) {
34703
+ if (error instanceof SyntaxError || error instanceof import_zod17.z.ZodError) {
34704
+ const errorDetails = error instanceof import_zod17.z.ZodError ? error.message : "Invalid JSON format";
34705
+ throw new import_server15.TRPCError({
34706
+ code: "BAD_REQUEST",
34707
+ message: `Invalid policy JSON structure: ${errorDetails}`
34708
+ });
34709
+ }
34710
+ throw mapS3ErrorToTRPCError(error, {
34711
+ operation: "set bucket policy",
34712
+ bucket: bucketName
34713
+ });
34714
+ }
34715
+ }),
34716
+ /**
34717
+ * Delete (remove) a bucket policy.
34718
+ *
34719
+ * Removes the policy from the bucket. The bucket reverts to having no policy.
34720
+ * Not an error if no policy was set.
34721
+ *
34722
+ * @throws TRPCError NOT_FOUND - bucket does not exist
34723
+ * @throws TRPCError FORBIDDEN - no credentials or access denied
34724
+ */
34725
+ delete: cephProtectedProcedure.input(deleteBucketPolicyInputSchema).mutation(async ({ ctx, input }) => {
34726
+ const s3 = ctx.getCephClient();
34727
+ const { bucketName } = input;
34728
+ try {
34729
+ await s3.send(new import_client_s35.DeleteBucketPolicyCommand({
34730
+ Bucket: bucketName
34731
+ }));
34732
+ return true;
34733
+ } catch (error) {
34734
+ const s3Error = error;
34735
+ if (s3Error.name === "NoSuchBucketPolicy" || s3Error.Code === "NoSuchBucketPolicy") {
34736
+ return true;
34737
+ }
34738
+ throw mapS3ErrorToTRPCError(error, {
34739
+ operation: "delete bucket policy",
34740
+ bucket: bucketName
34741
+ });
34742
+ }
34743
+ })
34744
+ };
34745
+
34746
+ // src/server/Storage/routers/permissionRouter.ts
34747
+ var STORAGE_MAPPINGS = {
34748
+ // Container Operations (works for both Swift containers and Ceph buckets)
34749
+ "storage:containers:read": {
34750
+ engine: "storage",
34751
+ rule: "storage:container_get"
34752
+ },
34753
+ "storage:containers:list": {
34754
+ engine: "storage",
34755
+ rule: "storage:container_list"
34756
+ },
34757
+ "storage:containers:create": {
34758
+ engine: "storage",
34759
+ rule: "storage:container_create"
34760
+ },
34761
+ "storage:containers:update": {
34762
+ engine: "storage",
34763
+ rule: "storage:container_update"
34764
+ },
34765
+ "storage:containers:delete": {
34766
+ engine: "storage",
34767
+ rule: "storage:container_delete"
34768
+ },
34769
+ "storage:containers:empty": {
34770
+ engine: "storage",
34771
+ rule: "storage:container_empty"
34772
+ },
34773
+ "storage:containers:manage_acls": {
34774
+ engine: "storage",
34775
+ rule: "storage:container_check_acls"
34776
+ },
34777
+ "storage:containers:read_acls": {
34778
+ engine: "storage",
34779
+ rule: "storage:container_show_access_control"
34780
+ },
34781
+ "storage:containers:update_acls": {
34782
+ engine: "storage",
34783
+ rule: "storage:container_update_access_control"
34784
+ },
34785
+ // Object Operations
34786
+ "storage:objects:read": {
34787
+ engine: "storage",
34788
+ rule: "storage:object_get"
34789
+ },
34790
+ "storage:objects:list": {
34791
+ engine: "storage",
34792
+ rule: "storage:object_list"
34793
+ },
34794
+ "storage:objects:download": {
34795
+ engine: "storage",
34796
+ rule: "storage:object_download"
34797
+ },
34798
+ "storage:objects:create": {
34799
+ engine: "storage",
34800
+ rule: "storage:object_update"
34801
+ },
34802
+ "storage:objects:update": {
34803
+ engine: "storage",
34804
+ rule: "storage:object_update"
34805
+ },
34806
+ "storage:objects:delete": {
34807
+ engine: "storage",
34808
+ rule: "storage:object_delete"
34809
+ },
34810
+ "storage:objects:copy": {
34811
+ engine: "storage",
34812
+ rule: "storage:object_create_copy"
34813
+ },
34814
+ "storage:objects:move": {
34815
+ engine: "storage",
34816
+ rule: "storage:object_move"
34817
+ },
34818
+ // Folder Operations
34819
+ "storage:folders:create_object": {
34820
+ engine: "storage",
34821
+ rule: "storage:folder_create_object"
34822
+ },
34823
+ "storage:folders:create": {
34824
+ engine: "storage",
34825
+ rule: "storage:folder_create_folder"
34826
+ },
34827
+ "storage:folders:delete": {
34828
+ engine: "storage",
34829
+ rule: "storage:folder_delete"
34830
+ }
34831
+ };
34832
+ var buildStoragePermissionRouter = /* @__PURE__ */ __name((policyDir) => createPermissionRouter({
34833
+ policyDir,
34834
+ engines: {
34835
+ storage: {
34836
+ fileName: "storage.json"
34837
+ }
34838
+ },
34839
+ mappings: STORAGE_MAPPINGS
34840
+ }), "buildStoragePermissionRouter");
34841
+
34416
34842
  // src/server/Storage/routers/index.ts
34417
- var objectStorageRouters = {
34843
+ var buildObjectStorageRouters = /* @__PURE__ */ __name((policyDir) => ({
34418
34844
  storage: {
34419
34845
  swift: auroraRouter({
34420
34846
  ...swiftRouter
@@ -34431,53 +34857,57 @@ var objectStorageRouters = {
34431
34857
  }),
34432
34858
  versioning: auroraRouter({
34433
34859
  ...versioningRouter
34860
+ }),
34861
+ bucketPolicy: auroraRouter({
34862
+ ...bucketPolicyRouter
34434
34863
  })
34435
- })
34864
+ }),
34865
+ ...buildStoragePermissionRouter(policyDir)
34436
34866
  }
34437
- };
34867
+ }), "buildObjectStorageRouters");
34438
34868
 
34439
34869
  // src/server/Project/routers/projectRouter.ts
34440
- var import_zod18 = require("zod");
34441
- var import_server15 = require("@trpc/server");
34870
+ var import_zod19 = require("zod");
34871
+ var import_server16 = require("@trpc/server");
34442
34872
 
34443
34873
  // src/server/Project/types/models.ts
34444
- var import_zod17 = require("zod");
34445
- var baseProjectSchema = import_zod17.z.object({
34446
- id: import_zod17.z.string(),
34447
- name: import_zod17.z.string(),
34448
- enabled: import_zod17.z.boolean(),
34449
- domain_id: import_zod17.z.string().nullable().optional(),
34450
- parent_id: import_zod17.z.string().nullable().optional(),
34451
- is_domain: import_zod17.z.boolean().nullable().optional(),
34452
- tags: import_zod17.z.array(import_zod17.z.string()).nullable().optional(),
34453
- options: import_zod17.z.record(import_zod17.z.string(), import_zod17.z.string().or(import_zod17.z.boolean())).nullable().optional(),
34454
- description: import_zod17.z.string().nullable().optional(),
34455
- links: import_zod17.z.object({
34456
- self: import_zod17.z.string().url().nullable().optional()
34874
+ var import_zod18 = require("zod");
34875
+ var baseProjectSchema = import_zod18.z.object({
34876
+ id: import_zod18.z.string(),
34877
+ name: import_zod18.z.string(),
34878
+ enabled: import_zod18.z.boolean(),
34879
+ domain_id: import_zod18.z.string().nullable().optional(),
34880
+ parent_id: import_zod18.z.string().nullable().optional(),
34881
+ is_domain: import_zod18.z.boolean().nullable().optional(),
34882
+ tags: import_zod18.z.array(import_zod18.z.string()).nullable().optional(),
34883
+ options: import_zod18.z.record(import_zod18.z.string(), import_zod18.z.string().or(import_zod18.z.boolean())).nullable().optional(),
34884
+ description: import_zod18.z.string().nullable().optional(),
34885
+ links: import_zod18.z.object({
34886
+ self: import_zod18.z.string().url().nullable().optional()
34457
34887
  }).optional()
34458
34888
  });
34459
34889
  var projectSchema = baseProjectSchema.extend({
34460
- domain_name: import_zod17.z.string().optional(),
34461
- parents: import_zod17.z.array(import_zod17.z.object({
34890
+ domain_name: import_zod18.z.string().optional(),
34891
+ parents: import_zod18.z.array(import_zod18.z.object({
34462
34892
  project: baseProjectSchema
34463
34893
  })).optional()
34464
34894
  });
34465
- var projectResponseSchema = import_zod17.z.object({
34895
+ var projectResponseSchema = import_zod18.z.object({
34466
34896
  project: projectSchema
34467
34897
  });
34468
- var projectsResponseSchema = import_zod17.z.object({
34469
- projects: import_zod17.z.array(projectSchema),
34470
- links: import_zod17.z.object({
34471
- self: import_zod17.z.string().url().optional(),
34472
- previous: import_zod17.z.string().url().nullable().optional(),
34473
- next: import_zod17.z.string().url().nullable().optional()
34898
+ var projectsResponseSchema = import_zod18.z.object({
34899
+ projects: import_zod18.z.array(projectSchema),
34900
+ links: import_zod18.z.object({
34901
+ self: import_zod18.z.string().url().optional(),
34902
+ previous: import_zod18.z.string().url().nullable().optional(),
34903
+ next: import_zod18.z.string().url().nullable().optional()
34474
34904
  }).optional()
34475
34905
  });
34476
34906
 
34477
34907
  // src/server/Project/routers/projectRouter.ts
34478
34908
  async function callIdentityAPI(identityEndpoint, authToken, path3) {
34479
34909
  if (!identityEndpoint) {
34480
- throw new import_server15.TRPCError({
34910
+ throw new import_server16.TRPCError({
34481
34911
  code: "INTERNAL_SERVER_ERROR",
34482
34912
  message: "Identity endpoint not configured"
34483
34913
  });
@@ -34493,7 +34923,7 @@ async function callIdentityAPI(identityEndpoint, authToken, path3) {
34493
34923
  }
34494
34924
  });
34495
34925
  if (!response.ok) {
34496
- throw new import_server15.TRPCError({
34926
+ throw new import_server16.TRPCError({
34497
34927
  code: "INTERNAL_SERVER_ERROR",
34498
34928
  message: `Identity API call failed: ${response.status} ${response.statusText}`
34499
34929
  });
@@ -34533,14 +34963,14 @@ var projectRouter = {
34533
34963
  */
34534
34964
  getAuthProjects: protectedProcedure.query(async ({ ctx }) => {
34535
34965
  if (!ctx.openstack) {
34536
- throw new import_server15.TRPCError({
34966
+ throw new import_server16.TRPCError({
34537
34967
  code: "UNAUTHORIZED",
34538
34968
  message: "No authenticated session"
34539
34969
  });
34540
34970
  }
34541
34971
  const token = ctx.openstack.getToken();
34542
34972
  if (!token?.authToken) {
34543
- throw new import_server15.TRPCError({
34973
+ throw new import_server16.TRPCError({
34544
34974
  code: "UNAUTHORIZED",
34545
34975
  message: "No auth token available"
34546
34976
  });
@@ -34556,10 +34986,10 @@ var projectRouter = {
34556
34986
  return void 0;
34557
34987
  }
34558
34988
  const domainsData = domainsResponse ? await domainsResponse.json().catch(() => null) : null;
34559
- const domainsResponseSchema = import_zod18.z.object({
34560
- domains: import_zod18.z.array(import_zod18.z.object({
34561
- id: import_zod18.z.string(),
34562
- name: import_zod18.z.string()
34989
+ const domainsResponseSchema = import_zod19.z.object({
34990
+ domains: import_zod19.z.array(import_zod19.z.object({
34991
+ id: import_zod19.z.string(),
34992
+ name: import_zod19.z.string()
34563
34993
  }))
34564
34994
  });
34565
34995
  const parsedDomains = domainsResponseSchema.safeParse(domainsData);
@@ -34579,18 +35009,18 @@ var projectRouter = {
34579
35009
  * filtered by the optional search term. Uses the OpenStack /v3/auth/projects
34580
35010
  * endpoint which works with any valid token.
34581
35011
  */
34582
- searchProjects: protectedProcedure.input(import_zod18.z.object({
34583
- search: import_zod18.z.string().optional()
35012
+ searchProjects: protectedProcedure.input(import_zod19.z.object({
35013
+ search: import_zod19.z.string().optional()
34584
35014
  }).optional()).query(async ({ ctx, input }) => {
34585
35015
  if (!ctx.openstack) {
34586
- throw new import_server15.TRPCError({
35016
+ throw new import_server16.TRPCError({
34587
35017
  code: "UNAUTHORIZED",
34588
35018
  message: "No authenticated session"
34589
35019
  });
34590
35020
  }
34591
35021
  const token = ctx.openstack.getToken();
34592
35022
  if (!token?.authToken) {
34593
- throw new import_server15.TRPCError({
35023
+ throw new import_server16.TRPCError({
34594
35024
  code: "UNAUTHORIZED",
34595
35025
  message: "No auth token available"
34596
35026
  });
@@ -34633,12 +35063,12 @@ var projectRouter = {
34633
35063
  * If in the future we need to access project-specific resources (compute, network, etc.),
34634
35064
  * we should create a separate procedure using projectScopedProcedure.
34635
35065
  */
34636
- getProjectById: protectedProcedure.input(import_zod18.z.object({
34637
- id: import_zod18.z.string()
35066
+ getProjectById: protectedProcedure.input(import_zod19.z.object({
35067
+ id: import_zod19.z.string()
34638
35068
  })).query(async ({ input, ctx }) => {
34639
35069
  const identityService = ctx.openstack?.service("identity");
34640
35070
  if (!ctx.openstack || !identityService) {
34641
- throw new import_server15.TRPCError({
35071
+ throw new import_server16.TRPCError({
34642
35072
  code: "INTERNAL_SERVER_ERROR",
34643
35073
  message: "Identity service unavailable"
34644
35074
  });
@@ -34660,13 +35090,13 @@ var projectRouters = {
34660
35090
  };
34661
35091
 
34662
35092
  // src/server/helpers/errorHandling.ts
34663
- var import_server16 = require("@trpc/server");
35093
+ var import_server17 = require("@trpc/server");
34664
35094
  function wrapError3(error, operation) {
34665
- if (error instanceof import_server16.TRPCError) {
35095
+ if (error instanceof import_server17.TRPCError) {
34666
35096
  return error;
34667
35097
  }
34668
35098
  const baseErrorMessage = `Error during ${operation}`;
34669
- return new import_server16.TRPCError({
35099
+ return new import_server17.TRPCError({
34670
35100
  code: "INTERNAL_SERVER_ERROR",
34671
35101
  message: typeof error !== "string" && error.message ? `${baseErrorMessage}: ${error.message}` : baseErrorMessage,
34672
35102
  cause: error
@@ -34706,11 +35136,11 @@ function appendQueryParamsFromObject(source, options) {
34706
35136
  __name(appendQueryParamsFromObject, "appendQueryParamsFromObject");
34707
35137
 
34708
35138
  // src/server/helpers/validateOpenstackService.ts
34709
- var import_server17 = require("@trpc/server");
35139
+ var import_server18 = require("@trpc/server");
34710
35140
  var capitalize = /* @__PURE__ */ __name((str) => str.charAt(0).toUpperCase() + str.slice(1), "capitalize");
34711
35141
  function validateOpenstackService(service, serviceName) {
34712
35142
  if (!service) {
34713
- throw new import_server17.TRPCError({
35143
+ throw new import_server18.TRPCError({
34714
35144
  code: "INTERNAL_SERVER_ERROR",
34715
35145
  message: `${capitalize(serviceName)} service is not available`
34716
35146
  });
@@ -34719,16 +35149,16 @@ function validateOpenstackService(service, serviceName) {
34719
35149
  __name(validateOpenstackService, "validateOpenstackService");
34720
35150
 
34721
35151
  // src/server/Network/types/floatingIp.ts
34722
- var import_zod20 = require("zod");
35152
+ var import_zod21 = require("zod");
34723
35153
 
34724
35154
  // src/server/Network/types/index.ts
34725
- var import_zod19 = require("zod");
34726
- var ISO8601TimestampSchema = import_zod19.z.string().brand("ISO8601Timestamp");
34727
- var SortDirSchema = import_zod19.z.enum([
35155
+ var import_zod20 = require("zod");
35156
+ var ISO8601TimestampSchema = import_zod20.z.string().brand("ISO8601Timestamp");
35157
+ var SortDirSchema = import_zod20.z.enum([
34728
35158
  "asc",
34729
35159
  "desc"
34730
35160
  ]);
34731
- var NetworkPortStatusSchema = import_zod19.z.enum([
35161
+ var NetworkPortStatusSchema = import_zod20.z.enum([
34732
35162
  "ACTIVE",
34733
35163
  "DOWN",
34734
35164
  "BUILD",
@@ -34736,154 +35166,154 @@ var NetworkPortStatusSchema = import_zod19.z.enum([
34736
35166
  ]);
34737
35167
 
34738
35168
  // src/server/Network/types/floatingIp.ts
34739
- var FloatingIpStatusSchema = import_zod20.z.enum([
35169
+ var FloatingIpStatusSchema = import_zod21.z.enum([
34740
35170
  "ACTIVE",
34741
35171
  "DOWN",
34742
35172
  "ERROR"
34743
35173
  ]);
34744
- var PortDetailsSchema = import_zod20.z.object({
35174
+ var PortDetailsSchema = import_zod21.z.object({
34745
35175
  /** The status of the port */
34746
35176
  status: FloatingIpStatusSchema,
34747
35177
  /** The name of the port */
34748
- name: import_zod20.z.string(),
35178
+ name: import_zod21.z.string(),
34749
35179
  /** Administrative state of the port (true = UP, false = DOWN) */
34750
- admin_state_up: import_zod20.z.boolean(),
35180
+ admin_state_up: import_zod21.z.boolean(),
34751
35181
  /** The ID of the network the port is attached to */
34752
- network_id: import_zod20.z.string(),
35182
+ network_id: import_zod21.z.string(),
34753
35183
  /** The owner of the port device */
34754
- device_owner: import_zod20.z.string(),
35184
+ device_owner: import_zod21.z.string(),
34755
35185
  /** The MAC address of the port */
34756
- mac_address: import_zod20.z.string(),
35186
+ mac_address: import_zod21.z.string(),
34757
35187
  /** The ID of the device the port is attached to */
34758
- device_id: import_zod20.z.string()
35188
+ device_id: import_zod21.z.string()
34759
35189
  });
34760
- var PortForwardingSchema = import_zod20.z.object({
35190
+ var PortForwardingSchema = import_zod21.z.object({
34761
35191
  /** Port forwarding protocol */
34762
- protocol: import_zod20.z.enum([
35192
+ protocol: import_zod21.z.enum([
34763
35193
  "tcp",
34764
35194
  "udp"
34765
35195
  ]),
34766
35196
  /** The internal fixed IP address associated with the port forwarding */
34767
- internal_ip_address: import_zod20.z.string(),
35197
+ internal_ip_address: import_zod21.z.string(),
34768
35198
  /** The internal port number or starting port of the range */
34769
- internal_port: import_zod20.z.number().optional(),
35199
+ internal_port: import_zod21.z.number().optional(),
34770
35200
  /** The internal port range (e.g., "1024:2048") */
34771
- internal_port_range: import_zod20.z.string().optional(),
35201
+ internal_port_range: import_zod21.z.string().optional(),
34772
35202
  /** The internal port ID for the port forwarding (requires floating-ip-port-forwarding-detail extension) */
34773
- internal_port_id: import_zod20.z.string().optional(),
35203
+ internal_port_id: import_zod21.z.string().optional(),
34774
35204
  /** The external port number or starting port of the range */
34775
- external_port: import_zod20.z.number().optional(),
35205
+ external_port: import_zod21.z.number().optional(),
34776
35206
  /** The external port range (e.g., "8000:9000") */
34777
- external_port_range: import_zod20.z.string().optional(),
35207
+ external_port_range: import_zod21.z.string().optional(),
34778
35208
  /** The ID of the port forwarding resource */
34779
- id: import_zod20.z.string(),
35209
+ id: import_zod21.z.string(),
34780
35210
  /** Description of the port forwarding rule (requires floating-ip-port-forwarding-description extension) */
34781
- description: import_zod20.z.string().nullable().optional()
35211
+ description: import_zod21.z.string().nullable().optional()
34782
35212
  });
34783
- var FloatingIpSchema = import_zod20.z.object({
35213
+ var FloatingIpSchema = import_zod21.z.object({
34784
35214
  /** The ID of the router for the floating IP (null if not associated) */
34785
- router_id: import_zod20.z.string().nullable(),
35215
+ router_id: import_zod21.z.string().nullable(),
34786
35216
  /** A human-readable description for the resource */
34787
- description: import_zod20.z.string().nullable().optional(),
35217
+ description: import_zod21.z.string().nullable().optional(),
34788
35218
  /** Whether this is a distributed floating IP (requires floating-ip-distributed extension) */
34789
- distributed: import_zod20.z.boolean().optional(),
35219
+ distributed: import_zod21.z.boolean().optional(),
34790
35220
  /** A valid DNS domain (requires dns-integration extension) */
34791
- dns_domain: import_zod20.z.string().optional(),
35221
+ dns_domain: import_zod21.z.string().optional(),
34792
35222
  /** A valid DNS name (requires dns-integration extension) */
34793
- dns_name: import_zod20.z.string().optional(),
35223
+ dns_name: import_zod21.z.string().optional(),
34794
35224
  /** Time at which the resource was created (UTC ISO8601 format, requires standard-attr-timestamp extension) */
34795
35225
  created_at: ISO8601TimestampSchema.optional(),
34796
35226
  /** Time at which the resource was last updated (UTC ISO8601 format, requires standard-attr-timestamp extension) */
34797
35227
  updated_at: ISO8601TimestampSchema.optional(),
34798
35228
  /** The revision number of the resource (set by server, for concurrency control) */
34799
- revision_number: import_zod20.z.number(),
35229
+ revision_number: import_zod21.z.number(),
34800
35230
  /** The ID of the project that owns the floating IP */
34801
- project_id: import_zod20.z.string(),
35231
+ project_id: import_zod21.z.string(),
34802
35232
  /** The ID of the tenant (deprecated, use project_id) */
34803
- tenant_id: import_zod20.z.string(),
35233
+ tenant_id: import_zod21.z.string(),
34804
35234
  /** The ID of the network associated with the floating IP */
34805
- floating_network_id: import_zod20.z.string(),
35235
+ floating_network_id: import_zod21.z.string(),
34806
35236
  /** The fixed IP address associated with the floating IP (null if not associated) */
34807
- fixed_ip_address: import_zod20.z.string().nullable(),
35237
+ fixed_ip_address: import_zod21.z.string().nullable(),
34808
35238
  /** The floating IP address */
34809
- floating_ip_address: import_zod20.z.string(),
35239
+ floating_ip_address: import_zod21.z.string(),
34810
35240
  /** The ID of the port associated with the floating IP (null if not associated) */
34811
- port_id: import_zod20.z.string().nullable(),
35241
+ port_id: import_zod21.z.string().nullable(),
34812
35242
  /** The ID of the floating IP address */
34813
- id: import_zod20.z.string(),
35243
+ id: import_zod21.z.string(),
34814
35244
  /** The status of the floating IP */
34815
35245
  status: FloatingIpStatusSchema,
34816
35246
  /** The information of the associated port (null if not associated, requires fip-port-details extension) */
34817
35247
  port_details: PortDetailsSchema.nullable().optional(),
34818
35248
  /** The list of tags on the resource (requires standard-attr-tag extension) */
34819
- tags: import_zod20.z.array(import_zod20.z.string()).optional(),
35249
+ tags: import_zod21.z.array(import_zod21.z.string()).optional(),
34820
35250
  /** The associated port forwarding resources for the floating IP (requires expose-port-forwarding-in-fip extension) */
34821
- port_forwardings: import_zod20.z.array(PortForwardingSchema).nullish(),
35251
+ port_forwardings: import_zod21.z.array(PortForwardingSchema).nullish(),
34822
35252
  /** The ID of the QoS policy of the network where this floating IP is plugged (requires qos-fip extension) */
34823
- qos_network_policy_id: import_zod20.z.string().optional(),
35253
+ qos_network_policy_id: import_zod21.z.string().optional(),
34824
35254
  /** The ID of the QoS policy associated with the floating IP (requires qos extension) */
34825
- qos_policy_id: import_zod20.z.string().optional()
34826
- });
34827
- var FloatingIpIdInputSchema = import_zod20.z.object({
34828
- project_id: import_zod20.z.string(),
34829
- floatingip_id: import_zod20.z.string()
34830
- });
34831
- var FloatingIpCreateRequestSchema = import_zod20.z.object({
34832
- tenant_id: import_zod20.z.string(),
34833
- project_id: import_zod20.z.string(),
34834
- floating_network_id: import_zod20.z.string(),
34835
- fixed_ip_address: import_zod20.z.string().optional(),
34836
- floating_ip_address: import_zod20.z.string().optional(),
34837
- port_id: import_zod20.z.string().optional(),
34838
- subnet_id: import_zod20.z.string().optional(),
34839
- distributed: import_zod20.z.boolean().optional(),
34840
- description: import_zod20.z.string().optional(),
34841
- dns_domain: import_zod20.z.string().optional(),
34842
- dns_name: import_zod20.z.string().optional(),
34843
- qos_policy_id: import_zod20.z.string().optional()
34844
- });
34845
- var FloatingIpUpdateRequestSchema = import_zod20.z.object({
34846
- project_id: import_zod20.z.string(),
34847
- floatingip_id: import_zod20.z.string(),
34848
- port_id: import_zod20.z.string().nullable(),
34849
- fixed_ip_address: import_zod20.z.string().optional(),
34850
- description: import_zod20.z.string().optional(),
34851
- distributed: import_zod20.z.boolean().optional()
34852
- });
34853
- var FloatingIpResponseSchema = import_zod20.z.object({
35255
+ qos_policy_id: import_zod21.z.string().optional()
35256
+ });
35257
+ var FloatingIpIdInputSchema = import_zod21.z.object({
35258
+ project_id: import_zod21.z.string(),
35259
+ floatingip_id: import_zod21.z.string()
35260
+ });
35261
+ var FloatingIpCreateRequestSchema = import_zod21.z.object({
35262
+ tenant_id: import_zod21.z.string(),
35263
+ project_id: import_zod21.z.string(),
35264
+ floating_network_id: import_zod21.z.string(),
35265
+ fixed_ip_address: import_zod21.z.string().optional(),
35266
+ floating_ip_address: import_zod21.z.string().optional(),
35267
+ port_id: import_zod21.z.string().optional(),
35268
+ subnet_id: import_zod21.z.string().optional(),
35269
+ distributed: import_zod21.z.boolean().optional(),
35270
+ description: import_zod21.z.string().optional(),
35271
+ dns_domain: import_zod21.z.string().optional(),
35272
+ dns_name: import_zod21.z.string().optional(),
35273
+ qos_policy_id: import_zod21.z.string().optional()
35274
+ });
35275
+ var FloatingIpUpdateRequestSchema = import_zod21.z.object({
35276
+ project_id: import_zod21.z.string(),
35277
+ floatingip_id: import_zod21.z.string(),
35278
+ port_id: import_zod21.z.string().nullable(),
35279
+ fixed_ip_address: import_zod21.z.string().optional(),
35280
+ description: import_zod21.z.string().optional(),
35281
+ distributed: import_zod21.z.boolean().optional()
35282
+ });
35283
+ var FloatingIpResponseSchema = import_zod21.z.object({
34854
35284
  floatingip: FloatingIpSchema
34855
35285
  });
34856
- var FloatingIpListResponseSchema = import_zod20.z.object({
35286
+ var FloatingIpListResponseSchema = import_zod21.z.object({
34857
35287
  /** A list of floating IP objects */
34858
- floatingips: import_zod20.z.array(FloatingIpSchema)
35288
+ floatingips: import_zod21.z.array(FloatingIpSchema)
34859
35289
  });
34860
- var FloatingIpQueryParametersSchema = import_zod20.z.object({
35290
+ var FloatingIpQueryParametersSchema = import_zod21.z.object({
34861
35291
  /** Project ID for rescoping (required for projectScopedProcedure) */
34862
- project_id: import_zod20.z.string(),
35292
+ project_id: import_zod21.z.string(),
34863
35293
  /** Filter by the ID of the floating IP */
34864
- id: import_zod20.z.string().optional(),
35294
+ id: import_zod21.z.string().optional(),
34865
35295
  /** Filter by the ID of the router for the floating IP */
34866
- router_id: import_zod20.z.string().nullable().optional(),
35296
+ router_id: import_zod21.z.string().nullable().optional(),
34867
35297
  /** Filter by the status of the floating IP */
34868
35298
  status: FloatingIpStatusSchema.optional(),
34869
35299
  /** Filter by the ID of the project that owns the resource */
34870
- tenant_id: import_zod20.z.string().optional(),
35300
+ tenant_id: import_zod21.z.string().optional(),
34871
35301
  /** Filter by the revision number of the resource */
34872
- revision_number: import_zod20.z.number().optional(),
35302
+ revision_number: import_zod21.z.number().optional(),
34873
35303
  /** Filter by the human-readable description of the resource */
34874
- description: import_zod20.z.string().nullable().optional(),
35304
+ description: import_zod21.z.string().nullable().optional(),
34875
35305
  /** Filter by the ID of the network associated with the floating IP */
34876
- floating_network_id: import_zod20.z.string().optional(),
35306
+ floating_network_id: import_zod21.z.string().optional(),
34877
35307
  /** Filter by the fixed IP address associated with the floating IP */
34878
- fixed_ip_address: import_zod20.z.string().optional(),
35308
+ fixed_ip_address: import_zod21.z.string().optional(),
34879
35309
  /** Filter by the floating IP address */
34880
- floating_ip_address: import_zod20.z.string().optional(),
35310
+ floating_ip_address: import_zod21.z.string().optional(),
34881
35311
  /** Filter by the ID of a port associated with the floating IP */
34882
- port_id: import_zod20.z.string().nullable().optional(),
35312
+ port_id: import_zod21.z.string().nullable().optional(),
34883
35313
  /** Sort direction (asc or desc) */
34884
35314
  sort_dir: SortDirSchema.optional(),
34885
35315
  /** Sort key - valid keys: fixed_ip_address, floating_ip_address, floating_network_id, id, router_id, status, tenant_id, project_id */
34886
- sort_key: import_zod20.z.enum([
35316
+ sort_key: import_zod21.z.enum([
34887
35317
  "fixed_ip_address",
34888
35318
  "floating_ip_address",
34889
35319
  "floating_network_id",
@@ -34894,80 +35324,80 @@ var FloatingIpQueryParametersSchema = import_zod20.z.object({
34894
35324
  "project_id"
34895
35325
  ]).optional(),
34896
35326
  /** Filter by tags (comma-separated, resources must match all tags) - requires standard-attr-tag extension */
34897
- tags: import_zod20.z.array(import_zod20.z.string()).optional(),
35327
+ tags: import_zod21.z.array(import_zod21.z.string()).optional(),
34898
35328
  /** Filter by tags with OR logic (comma-separated, resources match any tag) */
34899
- "tags-any": import_zod20.z.string().optional(),
35329
+ "tags-any": import_zod21.z.string().optional(),
34900
35330
  /** Exclude resources with these tags (comma-separated, resources must match all excluded tags) */
34901
- "not-tags": import_zod20.z.string().optional(),
35331
+ "not-tags": import_zod21.z.string().optional(),
34902
35332
  /** Exclude resources with these tags using OR logic (comma-separated, resources match any excluded tag) */
34903
- "not-tags-any": import_zod20.z.string().optional(),
35333
+ "not-tags-any": import_zod21.z.string().optional(),
34904
35334
  /** Specific fields to return (can be repeated) */
34905
- fields: import_zod20.z.union([
34906
- import_zod20.z.string(),
34907
- import_zod20.z.array(import_zod20.z.string())
35335
+ fields: import_zod21.z.union([
35336
+ import_zod21.z.string(),
35337
+ import_zod21.z.array(import_zod21.z.string())
34908
35338
  ]).optional(),
34909
35339
  /** Pagination limit */
34910
- limit: import_zod20.z.number().optional(),
35340
+ limit: import_zod21.z.number().optional(),
34911
35341
  /** Pagination marker (ID of the last item in the previous list) */
34912
- marker: import_zod20.z.string().optional(),
35342
+ marker: import_zod21.z.string().optional(),
34913
35343
  /** Pagination direction (false = ascending, true = descending) */
34914
- page_reverse: import_zod20.z.boolean().optional(),
35344
+ page_reverse: import_zod21.z.boolean().optional(),
34915
35345
  // BFF-side search (filtered in BFF layer, not sent to OpenStack)
34916
- searchTerm: import_zod20.z.string().optional()
34917
- });
34918
- var ExternalNetworksQuerySchema = import_zod20.z.object({
34919
- project_id: import_zod20.z.string(),
34920
- "router:external": import_zod20.z.literal(true).default(true)
34921
- });
34922
- var ExternalNetworkSchema = import_zod20.z.object({
34923
- id: import_zod20.z.string(),
34924
- name: import_zod20.z.string(),
34925
- project_id: import_zod20.z.string(),
34926
- "router:external": import_zod20.z.boolean().optional(),
34927
- shared: import_zod20.z.boolean(),
35346
+ searchTerm: import_zod21.z.string().optional()
35347
+ });
35348
+ var ExternalNetworksQuerySchema = import_zod21.z.object({
35349
+ project_id: import_zod21.z.string(),
35350
+ "router:external": import_zod21.z.literal(true).default(true)
35351
+ });
35352
+ var ExternalNetworkSchema = import_zod21.z.object({
35353
+ id: import_zod21.z.string(),
35354
+ name: import_zod21.z.string(),
35355
+ project_id: import_zod21.z.string(),
35356
+ "router:external": import_zod21.z.boolean().optional(),
35357
+ shared: import_zod21.z.boolean(),
34928
35358
  status: NetworkPortStatusSchema,
34929
35359
  updated_at: ISO8601TimestampSchema.optional(),
34930
- is_default: import_zod20.z.boolean().optional()
35360
+ is_default: import_zod21.z.boolean().optional()
34931
35361
  });
34932
- var ExternalNetworksResponseSchema = import_zod20.z.object({
34933
- networks: import_zod20.z.array(ExternalNetworkSchema)
35362
+ var ExternalNetworksResponseSchema = import_zod21.z.object({
35363
+ networks: import_zod21.z.array(ExternalNetworkSchema)
34934
35364
  });
34935
- var DnsDomainSchema = import_zod20.z.object({
34936
- id: import_zod20.z.string(),
34937
- name: import_zod20.z.string()
35365
+ var DnsDomainSchema = import_zod21.z.object({
35366
+ id: import_zod21.z.string(),
35367
+ name: import_zod21.z.string()
34938
35368
  });
34939
- var DnsDomainResponseSchema = import_zod20.z.object({
34940
- zones: import_zod20.z.array(DnsDomainSchema)
35369
+ var DnsDomainResponseSchema = import_zod21.z.object({
35370
+ zones: import_zod21.z.array(DnsDomainSchema)
34941
35371
  });
34942
- var AvailablePortsQuerySchema = import_zod20.z.object({
34943
- project_id: import_zod20.z.string(),
35372
+ var AvailablePortsQuerySchema = import_zod21.z.object({
35373
+ project_id: import_zod21.z.string(),
34944
35374
  /** Only ACTIVE ports are eligible for floating IP association */
34945
- status: import_zod20.z.literal("ACTIVE").default("ACTIVE"),
35375
+ status: import_zod21.z.literal("ACTIVE").default("ACTIVE"),
34946
35376
  /** Only administratively UP ports are eligible for floating IP association */
34947
- admin_state_up: import_zod20.z.literal(true).default(true)
35377
+ admin_state_up: import_zod21.z.literal(true).default(true)
34948
35378
  });
34949
- var AvailablePortSchema = import_zod20.z.object({
35379
+ var AvailablePortSchema = import_zod21.z.object({
34950
35380
  /** The ID of the port */
34951
- id: import_zod20.z.string(),
35381
+ id: import_zod21.z.string(),
34952
35382
  /** Human-readable name of the port */
34953
- name: import_zod20.z.string().nullable().optional(),
35383
+ name: import_zod21.z.string().nullable().optional(),
34954
35384
  /** List of fixed IPs assigned to the port, each entry pairs an IP address with its subnet. */
34955
- fixed_ips: import_zod20.z.array(import_zod20.z.object({
35385
+ fixed_ips: import_zod21.z.array(import_zod21.z.object({
34956
35386
  /** The fixed IP address assigned to the port */
34957
- ip_address: import_zod20.z.string(),
35387
+ ip_address: import_zod21.z.string(),
34958
35388
  /** The ID of the subnet the IP belongs to */
34959
- subnet_id: import_zod20.z.string().optional()
35389
+ subnet_id: import_zod21.z.string().optional()
34960
35390
  })).optional()
34961
35391
  });
34962
- var AvailablePortsResponseSchema = import_zod20.z.object({
34963
- ports: import_zod20.z.array(AvailablePortSchema)
35392
+ var AvailablePortsResponseSchema = import_zod21.z.object({
35393
+ ports: import_zod21.z.array(AvailablePortSchema)
34964
35394
  });
34965
35395
 
34966
35396
  // src/server/Network/helpers/errorHandling.ts
34967
- var import_server19 = require("@trpc/server");
35397
+ var import_server20 = require("@trpc/server");
34968
35398
 
34969
35399
  // src/server/Network/helpers/index.ts
34970
- var import_server18 = require("@trpc/server");
35400
+ var import_server19 = require("@trpc/server");
34971
35401
  var HTTP_STATUS_ERROR_MAP = {
34972
35402
  400: "BAD_REQUEST",
34973
35403
  401: "UNAUTHORIZED",
@@ -34987,7 +35417,7 @@ var parseOrThrow = /* @__PURE__ */ __name((schema, data, context) => {
34987
35417
  const parsed = schema.safeParse(data);
34988
35418
  if (!parsed.success) {
34989
35419
  console.error(`Zod Parsing Error in ${context}:`, parsed.error.issues);
34990
- throw new import_server18.TRPCError({
35420
+ throw new import_server19.TRPCError({
34991
35421
  code: "PARSE_ERROR",
34992
35422
  message: `Failed to parse response in ${context}`
34993
35423
  });
@@ -34997,27 +35427,27 @@ var parseOrThrow = /* @__PURE__ */ __name((schema, data, context) => {
34997
35427
 
34998
35428
  // src/server/Network/helpers/errorHandling.ts
34999
35429
  var DEFAULT_HANDLERS = {
35000
- 400: (response, resourceLabel) => new import_server19.TRPCError({
35430
+ 400: (response, resourceLabel) => new import_server20.TRPCError({
35001
35431
  code: HTTP_STATUS_ERROR_MAP[400],
35002
35432
  message: `Invalid request data for ${resourceLabel}: ${response.statusText || "Unknown error"}`
35003
35433
  }),
35004
- 401: (response, resourceLabel) => new import_server19.TRPCError({
35434
+ 401: (response, resourceLabel) => new import_server20.TRPCError({
35005
35435
  code: HTTP_STATUS_ERROR_MAP[401],
35006
35436
  message: `Unauthorized access to ${resourceLabel}: ${response.statusText || "Unknown error"}`
35007
35437
  }),
35008
- 403: (response, resourceLabel) => new import_server19.TRPCError({
35438
+ 403: (response, resourceLabel) => new import_server20.TRPCError({
35009
35439
  code: HTTP_STATUS_ERROR_MAP[403],
35010
35440
  message: `Access forbidden to ${resourceLabel}: ${response.statusText || "Unknown error"}`
35011
35441
  }),
35012
- 404: (response, resourceLabel) => new import_server19.TRPCError({
35442
+ 404: (response, resourceLabel) => new import_server20.TRPCError({
35013
35443
  code: HTTP_STATUS_ERROR_MAP[404],
35014
35444
  message: `${resourceLabel} not found: ${response.statusText || "Unknown error"}`
35015
35445
  }),
35016
- 409: (response, resourceLabel) => new import_server19.TRPCError({
35446
+ 409: (response, resourceLabel) => new import_server20.TRPCError({
35017
35447
  code: HTTP_STATUS_ERROR_MAP[409],
35018
35448
  message: `Conflict - ${resourceLabel} is in use: ${response.statusText || "Unknown error"}`
35019
35449
  }),
35020
- 412: (response, resourceLabel) => new import_server19.TRPCError({
35450
+ 412: (response, resourceLabel) => new import_server20.TRPCError({
35021
35451
  code: HTTP_STATUS_ERROR_MAP[412],
35022
35452
  message: `Precondition failed - revision number mismatch in ${resourceLabel}: ${response.statusText || "Unknown error"}`
35023
35453
  })
@@ -35032,7 +35462,7 @@ var ErrorHandler = /* @__PURE__ */ __name((resourceName, customHandlers) => {
35032
35462
  if (response.status && handlers[response.status]) {
35033
35463
  return handlers[response.status](response, resourceLabel);
35034
35464
  }
35035
- return new import_server19.TRPCError({
35465
+ return new import_server20.TRPCError({
35036
35466
  code: DEFAULT_ERROR_NAME,
35037
35467
  message: `Failed to process ${resourceLabel}: ${response.statusText || "Unknown error"}`
35038
35468
  });
@@ -35207,114 +35637,114 @@ var floatingIpRouter = {
35207
35637
  };
35208
35638
 
35209
35639
  // src/server/Network/types/securityGroup.ts
35210
- var import_zod21 = require("zod");
35211
- var securityGroupRuleSchema = import_zod21.z.object({
35212
- id: import_zod21.z.string(),
35213
- direction: import_zod21.z.enum([
35640
+ var import_zod22 = require("zod");
35641
+ var securityGroupRuleSchema = import_zod22.z.object({
35642
+ id: import_zod22.z.string(),
35643
+ direction: import_zod22.z.enum([
35214
35644
  "ingress",
35215
35645
  "egress"
35216
35646
  ]).optional(),
35217
- ethertype: import_zod21.z.enum([
35647
+ ethertype: import_zod22.z.enum([
35218
35648
  "IPv4",
35219
35649
  "IPv6"
35220
35650
  ]).optional(),
35221
- description: import_zod21.z.string().nullable().optional(),
35222
- security_group_id: import_zod21.z.string().optional(),
35223
- protocol: import_zod21.z.string().nullable().optional(),
35224
- port_range_min: import_zod21.z.number().nullable().optional(),
35225
- port_range_max: import_zod21.z.number().nullable().optional(),
35226
- remote_ip_prefix: import_zod21.z.string().nullable().optional(),
35227
- remote_group_id: import_zod21.z.string().nullable().optional(),
35228
- remote_address_group_id: import_zod21.z.string().nullable().optional(),
35229
- tenant_id: import_zod21.z.string().nullable().optional(),
35230
- project_id: import_zod21.z.string().nullable().optional(),
35231
- revision_number: import_zod21.z.number().optional(),
35232
- tags: import_zod21.z.array(import_zod21.z.string()).optional(),
35233
- created_at: import_zod21.z.string().optional(),
35234
- updated_at: import_zod21.z.string().nullable().optional()
35235
- });
35236
- var securityGroupSchema = import_zod21.z.object({
35237
- id: import_zod21.z.string(),
35238
- name: import_zod21.z.string().nullable().optional(),
35239
- description: import_zod21.z.string().nullable().optional(),
35240
- tenant_id: import_zod21.z.string().nullable().optional(),
35241
- project_id: import_zod21.z.string().nullable().optional(),
35242
- stateful: import_zod21.z.boolean().optional(),
35243
- shared: import_zod21.z.boolean().optional(),
35244
- tags: import_zod21.z.array(import_zod21.z.string()).optional(),
35245
- security_group_rules: import_zod21.z.array(securityGroupRuleSchema).optional(),
35246
- revision_number: import_zod21.z.number().optional(),
35247
- created_at: import_zod21.z.string().optional(),
35248
- updated_at: import_zod21.z.string().nullable().optional()
35249
- });
35250
- var securityGroupsResponseSchema = import_zod21.z.object({
35251
- security_groups: import_zod21.z.array(securityGroupSchema)
35651
+ description: import_zod22.z.string().nullable().optional(),
35652
+ security_group_id: import_zod22.z.string().optional(),
35653
+ protocol: import_zod22.z.string().nullable().optional(),
35654
+ port_range_min: import_zod22.z.number().nullable().optional(),
35655
+ port_range_max: import_zod22.z.number().nullable().optional(),
35656
+ remote_ip_prefix: import_zod22.z.string().nullable().optional(),
35657
+ remote_group_id: import_zod22.z.string().nullable().optional(),
35658
+ remote_address_group_id: import_zod22.z.string().nullable().optional(),
35659
+ tenant_id: import_zod22.z.string().nullable().optional(),
35660
+ project_id: import_zod22.z.string().nullable().optional(),
35661
+ revision_number: import_zod22.z.number().optional(),
35662
+ tags: import_zod22.z.array(import_zod22.z.string()).optional(),
35663
+ created_at: import_zod22.z.string().optional(),
35664
+ updated_at: import_zod22.z.string().nullable().optional()
35252
35665
  });
35253
- var securityGroupResponseSchema = import_zod21.z.object({
35666
+ var securityGroupSchema = import_zod22.z.object({
35667
+ id: import_zod22.z.string(),
35668
+ name: import_zod22.z.string().nullable().optional(),
35669
+ description: import_zod22.z.string().nullable().optional(),
35670
+ tenant_id: import_zod22.z.string().nullable().optional(),
35671
+ project_id: import_zod22.z.string().nullable().optional(),
35672
+ stateful: import_zod22.z.boolean().optional(),
35673
+ shared: import_zod22.z.boolean().optional(),
35674
+ tags: import_zod22.z.array(import_zod22.z.string()).optional(),
35675
+ security_group_rules: import_zod22.z.array(securityGroupRuleSchema).optional(),
35676
+ revision_number: import_zod22.z.number().optional(),
35677
+ created_at: import_zod22.z.string().optional(),
35678
+ updated_at: import_zod22.z.string().nullable().optional()
35679
+ });
35680
+ var securityGroupsResponseSchema = import_zod22.z.object({
35681
+ security_groups: import_zod22.z.array(securityGroupSchema)
35682
+ });
35683
+ var securityGroupResponseSchema = import_zod22.z.object({
35254
35684
  security_group: securityGroupSchema
35255
35685
  });
35256
- var securityGroupRuleResponseSchema = import_zod21.z.object({
35686
+ var securityGroupRuleResponseSchema = import_zod22.z.object({
35257
35687
  security_group_rule: securityGroupRuleSchema
35258
35688
  });
35259
35689
  var listSecurityGroupsInputSchema = projectScopedInputSchema.extend({
35260
35690
  // Sorting
35261
- sort_key: import_zod21.z.string().optional(),
35691
+ sort_key: import_zod22.z.string().optional(),
35262
35692
  sort_dir: SortDirSchema.optional(),
35263
35693
  // Basic filtering
35264
- name: import_zod21.z.string().optional(),
35265
- description: import_zod21.z.string().optional(),
35266
- tenant_id: import_zod21.z.string().optional(),
35267
- shared: import_zod21.z.boolean().optional(),
35694
+ name: import_zod22.z.string().optional(),
35695
+ description: import_zod22.z.string().optional(),
35696
+ tenant_id: import_zod22.z.string().optional(),
35697
+ shared: import_zod22.z.boolean().optional(),
35268
35698
  // Tag-based filtering (string values follow Neutron semantics)
35269
- tags: import_zod21.z.string().optional(),
35270
- tags_any: import_zod21.z.string().optional(),
35271
- not_tags: import_zod21.z.string().optional(),
35272
- not_tags_any: import_zod21.z.string().optional(),
35699
+ tags: import_zod22.z.string().optional(),
35700
+ tags_any: import_zod22.z.string().optional(),
35701
+ not_tags: import_zod22.z.string().optional(),
35702
+ not_tags_any: import_zod22.z.string().optional(),
35273
35703
  // BFF-side search (filtered in BFF layer, not sent to OpenStack)
35274
- searchTerm: import_zod21.z.string().optional()
35704
+ searchTerm: import_zod22.z.string().optional()
35275
35705
  });
35276
35706
  var getSecurityGroupByIdInputSchema = projectScopedInputSchema.extend({
35277
- securityGroupId: import_zod21.z.string()
35707
+ securityGroupId: import_zod22.z.string()
35278
35708
  });
35279
35709
  var createSecurityGroupInputSchema = projectScopedInputSchema.extend({
35280
- name: import_zod21.z.string().min(1, "Name is required"),
35281
- description: import_zod21.z.string().optional(),
35282
- stateful: import_zod21.z.boolean().optional()
35710
+ name: import_zod22.z.string().min(1, "Name is required"),
35711
+ description: import_zod22.z.string().optional(),
35712
+ stateful: import_zod22.z.boolean().optional()
35283
35713
  });
35284
35714
  var deleteSecurityGroupInputSchema = projectScopedInputSchema.extend({
35285
- securityGroupId: import_zod21.z.string()
35715
+ securityGroupId: import_zod22.z.string()
35286
35716
  });
35287
35717
  var updateSecurityGroupInputSchema = projectScopedInputSchema.extend({
35288
- securityGroupId: import_zod21.z.string(),
35289
- name: import_zod21.z.string().min(1, "Name is required").optional(),
35290
- description: import_zod21.z.string().optional(),
35291
- stateful: import_zod21.z.boolean().optional()
35718
+ securityGroupId: import_zod22.z.string(),
35719
+ name: import_zod22.z.string().min(1, "Name is required").optional(),
35720
+ description: import_zod22.z.string().optional(),
35721
+ stateful: import_zod22.z.boolean().optional()
35292
35722
  });
35293
35723
  var deleteSecurityGroupRuleInputSchema = projectScopedInputSchema.extend({
35294
- ruleId: import_zod21.z.string()
35724
+ ruleId: import_zod22.z.string()
35295
35725
  });
35296
35726
  var createSecurityGroupRuleInputSchema = projectScopedInputSchema.extend({
35297
- security_group_id: import_zod21.z.string(),
35298
- direction: import_zod21.z.enum([
35727
+ security_group_id: import_zod22.z.string(),
35728
+ direction: import_zod22.z.enum([
35299
35729
  "ingress",
35300
35730
  "egress"
35301
35731
  ]),
35302
- ethertype: import_zod21.z.enum([
35732
+ ethertype: import_zod22.z.enum([
35303
35733
  "IPv4",
35304
35734
  "IPv6"
35305
35735
  ]).default("IPv4"),
35306
- description: import_zod21.z.string().optional(),
35307
- protocol: import_zod21.z.string().nullable().optional(),
35308
- port_range_min: import_zod21.z.number().int().max(65535).nullable().optional(),
35309
- port_range_max: import_zod21.z.number().int().max(65535).nullable().optional(),
35736
+ description: import_zod22.z.string().optional(),
35737
+ protocol: import_zod22.z.string().nullable().optional(),
35738
+ port_range_min: import_zod22.z.number().int().max(65535).nullable().optional(),
35739
+ port_range_max: import_zod22.z.number().int().max(65535).nullable().optional(),
35310
35740
  // Transform empty strings to undefined for proper validation
35311
- remote_ip_prefix: import_zod21.z.string().nullable().optional().transform((val) => val === "" ? void 0 : val),
35312
- remote_group_id: import_zod21.z.string().nullable().optional().transform((val) => val === "" ? void 0 : val),
35313
- remote_address_group_id: import_zod21.z.string().nullable().optional().transform((val) => val === "" ? void 0 : val)
35741
+ remote_ip_prefix: import_zod22.z.string().nullable().optional().transform((val) => val === "" ? void 0 : val),
35742
+ remote_group_id: import_zod22.z.string().nullable().optional().transform((val) => val === "" ? void 0 : val),
35743
+ remote_address_group_id: import_zod22.z.string().nullable().optional().transform((val) => val === "" ? void 0 : val)
35314
35744
  });
35315
35745
 
35316
35746
  // src/server/Network/helpers/securityGroupHelpers.ts
35317
- var import_server20 = require("@trpc/server");
35747
+ var import_server21 = require("@trpc/server");
35318
35748
  var SecurityGroupErrorHandlers = {
35319
35749
  /**
35320
35750
  * Handles errors specific to security group list operations
@@ -35324,17 +35754,17 @@ var SecurityGroupErrorHandlers = {
35324
35754
  list: /* @__PURE__ */ __name((response) => {
35325
35755
  switch (response.status) {
35326
35756
  case 401:
35327
- return new import_server20.TRPCError({
35757
+ return new import_server21.TRPCError({
35328
35758
  code: HTTP_STATUS_ERROR_MAP[401],
35329
35759
  message: "Unauthorized access"
35330
35760
  });
35331
35761
  case 403:
35332
- return new import_server20.TRPCError({
35762
+ return new import_server21.TRPCError({
35333
35763
  code: HTTP_STATUS_ERROR_MAP[403],
35334
35764
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
35335
35765
  });
35336
35766
  default:
35337
- return new import_server20.TRPCError({
35767
+ return new import_server21.TRPCError({
35338
35768
  code: DEFAULT_ERROR_NAME,
35339
35769
  message: `Failed to list security groups: ${response.statusText || "Unknown error"}`
35340
35770
  });
@@ -35349,22 +35779,22 @@ var SecurityGroupErrorHandlers = {
35349
35779
  getById: /* @__PURE__ */ __name((response, securityGroupId) => {
35350
35780
  switch (response.status) {
35351
35781
  case 401:
35352
- return new import_server20.TRPCError({
35782
+ return new import_server21.TRPCError({
35353
35783
  code: HTTP_STATUS_ERROR_MAP[401],
35354
35784
  message: "Unauthorized access"
35355
35785
  });
35356
35786
  case 403:
35357
- return new import_server20.TRPCError({
35787
+ return new import_server21.TRPCError({
35358
35788
  code: HTTP_STATUS_ERROR_MAP[403],
35359
35789
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
35360
35790
  });
35361
35791
  case 404:
35362
- return new import_server20.TRPCError({
35792
+ return new import_server21.TRPCError({
35363
35793
  code: HTTP_STATUS_ERROR_MAP[404],
35364
35794
  message: `Security group not found: ${securityGroupId}`
35365
35795
  });
35366
35796
  default:
35367
- return new import_server20.TRPCError({
35797
+ return new import_server21.TRPCError({
35368
35798
  code: DEFAULT_ERROR_NAME,
35369
35799
  message: `Failed to fetch security group: ${response.statusText || "Unknown error"}`
35370
35800
  });
@@ -35378,32 +35808,32 @@ var SecurityGroupErrorHandlers = {
35378
35808
  create: /* @__PURE__ */ __name((response) => {
35379
35809
  switch (response.status) {
35380
35810
  case 401:
35381
- return new import_server20.TRPCError({
35811
+ return new import_server21.TRPCError({
35382
35812
  code: HTTP_STATUS_ERROR_MAP[401],
35383
35813
  message: "Unauthorized access"
35384
35814
  });
35385
35815
  case 403:
35386
- return new import_server20.TRPCError({
35816
+ return new import_server21.TRPCError({
35387
35817
  code: HTTP_STATUS_ERROR_MAP[403],
35388
35818
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
35389
35819
  });
35390
35820
  case 409:
35391
- return new import_server20.TRPCError({
35821
+ return new import_server21.TRPCError({
35392
35822
  code: HTTP_STATUS_ERROR_MAP[409],
35393
35823
  message: `Conflict: ${response.statusText || "Security group already exists"}`
35394
35824
  });
35395
35825
  case 413:
35396
- return new import_server20.TRPCError({
35826
+ return new import_server21.TRPCError({
35397
35827
  code: "BAD_REQUEST",
35398
35828
  message: `Quota exceeded for security groups. Please delete an existing security group or contact your administrator to increase your quota.`
35399
35829
  });
35400
35830
  case 400:
35401
- return new import_server20.TRPCError({
35831
+ return new import_server21.TRPCError({
35402
35832
  code: "BAD_REQUEST",
35403
35833
  message: `Invalid request: ${response.statusText || "Unknown error"}`
35404
35834
  });
35405
35835
  default:
35406
- return new import_server20.TRPCError({
35836
+ return new import_server21.TRPCError({
35407
35837
  code: "INTERNAL_SERVER_ERROR",
35408
35838
  message: `Failed to create security group: ${response.statusText || "Unknown error"}`
35409
35839
  });
@@ -35418,22 +35848,22 @@ var SecurityGroupErrorHandlers = {
35418
35848
  delete: /* @__PURE__ */ __name((response, securityGroupId) => {
35419
35849
  switch (response.status) {
35420
35850
  case 401:
35421
- return new import_server20.TRPCError({
35851
+ return new import_server21.TRPCError({
35422
35852
  code: HTTP_STATUS_ERROR_MAP[401],
35423
35853
  message: "Unauthorized access"
35424
35854
  });
35425
35855
  case 404:
35426
- return new import_server20.TRPCError({
35856
+ return new import_server21.TRPCError({
35427
35857
  code: HTTP_STATUS_ERROR_MAP[404],
35428
35858
  message: `Security group not found: ${securityGroupId}`
35429
35859
  });
35430
35860
  case 409:
35431
- return new import_server20.TRPCError({
35861
+ return new import_server21.TRPCError({
35432
35862
  code: HTTP_STATUS_ERROR_MAP[409],
35433
35863
  message: "Cannot delete security group because it is in use by one or more ports. Please remove all associations before deleting."
35434
35864
  });
35435
35865
  default:
35436
- return new import_server20.TRPCError({
35866
+ return new import_server21.TRPCError({
35437
35867
  code: DEFAULT_ERROR_NAME,
35438
35868
  message: `Failed to delete security group: ${response.statusText || "Unknown error"}`
35439
35869
  });
@@ -35448,39 +35878,39 @@ var SecurityGroupErrorHandlers = {
35448
35878
  update: /* @__PURE__ */ __name((response, securityGroupId) => {
35449
35879
  const errorMessage = response.statusText || "";
35450
35880
  if (errorMessage.toLowerCase().includes("stateful") && errorMessage.toLowerCase().includes("in use")) {
35451
- return new import_server20.TRPCError({
35881
+ return new import_server21.TRPCError({
35452
35882
  code: "CONFLICT",
35453
35883
  message: "Cannot update the 'stateful' attribute because this security group is in use by one or more ports."
35454
35884
  });
35455
35885
  }
35456
35886
  switch (response.status) {
35457
35887
  case 401:
35458
- return new import_server20.TRPCError({
35888
+ return new import_server21.TRPCError({
35459
35889
  code: HTTP_STATUS_ERROR_MAP[401],
35460
35890
  message: "Unauthorized access"
35461
35891
  });
35462
35892
  case 403:
35463
- return new import_server20.TRPCError({
35893
+ return new import_server21.TRPCError({
35464
35894
  code: HTTP_STATUS_ERROR_MAP[403],
35465
35895
  message: `Access forbidden: ${errorMessage || "Unknown error"}`
35466
35896
  });
35467
35897
  case 404:
35468
- return new import_server20.TRPCError({
35898
+ return new import_server21.TRPCError({
35469
35899
  code: HTTP_STATUS_ERROR_MAP[404],
35470
35900
  message: `Security group not found: ${securityGroupId}`
35471
35901
  });
35472
35902
  case 409:
35473
- return new import_server20.TRPCError({
35903
+ return new import_server21.TRPCError({
35474
35904
  code: HTTP_STATUS_ERROR_MAP[409],
35475
35905
  message: `Conflict: ${errorMessage || "Security group conflict"}`
35476
35906
  });
35477
35907
  case 400:
35478
- return new import_server20.TRPCError({
35908
+ return new import_server21.TRPCError({
35479
35909
  code: HTTP_STATUS_ERROR_MAP[400],
35480
35910
  message: `Invalid request: ${errorMessage || "Unknown error"}`
35481
35911
  });
35482
35912
  default:
35483
- return new import_server20.TRPCError({
35913
+ return new import_server21.TRPCError({
35484
35914
  code: DEFAULT_ERROR_NAME,
35485
35915
  message: `Failed to update security group: ${errorMessage || "Unknown error"}`
35486
35916
  });
@@ -35498,48 +35928,48 @@ var SecurityGroupRuleErrorHandlers = {
35498
35928
  switch (response.status) {
35499
35929
  case 400:
35500
35930
  if (statusText.toLowerCase().includes("cidr")) {
35501
- return new import_server20.TRPCError({
35931
+ return new import_server21.TRPCError({
35502
35932
  code: "BAD_REQUEST",
35503
35933
  message: "Invalid CIDR format. Please provide a valid IP address block (e.g., 0.0.0.0/0)"
35504
35934
  });
35505
35935
  }
35506
35936
  if (statusText.toLowerCase().includes("port")) {
35507
- return new import_server20.TRPCError({
35937
+ return new import_server21.TRPCError({
35508
35938
  code: "BAD_REQUEST",
35509
35939
  message: "Invalid port range. Ports must be between 1 and 65535, and min must be <= max"
35510
35940
  });
35511
35941
  }
35512
- return new import_server20.TRPCError({
35942
+ return new import_server21.TRPCError({
35513
35943
  code: "BAD_REQUEST",
35514
35944
  message: `Invalid request: ${statusText}`
35515
35945
  });
35516
35946
  case 401:
35517
- return new import_server20.TRPCError({
35947
+ return new import_server21.TRPCError({
35518
35948
  code: "UNAUTHORIZED",
35519
35949
  message: "Unauthorized access"
35520
35950
  });
35521
35951
  case 403:
35522
- return new import_server20.TRPCError({
35952
+ return new import_server21.TRPCError({
35523
35953
  code: "FORBIDDEN",
35524
35954
  message: `Access forbidden: ${statusText}`
35525
35955
  });
35526
35956
  case 404:
35527
- return new import_server20.TRPCError({
35957
+ return new import_server21.TRPCError({
35528
35958
  code: "NOT_FOUND",
35529
35959
  message: "Security group not found"
35530
35960
  });
35531
35961
  case 409:
35532
- return new import_server20.TRPCError({
35962
+ return new import_server21.TRPCError({
35533
35963
  code: "CONFLICT",
35534
35964
  message: "A rule with these parameters already exists in this security group"
35535
35965
  });
35536
35966
  case 413:
35537
- return new import_server20.TRPCError({
35967
+ return new import_server21.TRPCError({
35538
35968
  code: "BAD_REQUEST",
35539
35969
  message: "Quota exceeded for security group rules. Please delete existing rules or contact your administrator."
35540
35970
  });
35541
35971
  default:
35542
- return new import_server20.TRPCError({
35972
+ return new import_server21.TRPCError({
35543
35973
  code: "INTERNAL_SERVER_ERROR",
35544
35974
  message: `Failed to create security group rule: ${statusText}`
35545
35975
  });
@@ -35558,22 +35988,22 @@ var SecurityGroupRuleErrorHandlers = {
35558
35988
  delete: /* @__PURE__ */ __name((response, ruleId) => {
35559
35989
  switch (response.status) {
35560
35990
  case 401:
35561
- return new import_server20.TRPCError({
35991
+ return new import_server21.TRPCError({
35562
35992
  code: "UNAUTHORIZED",
35563
35993
  message: "Unauthorized access"
35564
35994
  });
35565
35995
  case 404:
35566
- return new import_server20.TRPCError({
35996
+ return new import_server21.TRPCError({
35567
35997
  code: "NOT_FOUND",
35568
35998
  message: `Security group rule not found: ${ruleId}`
35569
35999
  });
35570
36000
  case 412:
35571
- return new import_server20.TRPCError({
36001
+ return new import_server21.TRPCError({
35572
36002
  code: "PRECONDITION_FAILED",
35573
36003
  message: `Cannot delete security group rule: precondition failed`
35574
36004
  });
35575
36005
  default:
35576
- return new import_server20.TRPCError({
36006
+ return new import_server21.TRPCError({
35577
36007
  code: "INTERNAL_SERVER_ERROR",
35578
36008
  message: `Failed to delete security group rule: ${response.statusText || "Unknown error"}`
35579
36009
  });
@@ -35584,7 +36014,7 @@ var parseOpenStackResponse = /* @__PURE__ */ __name((data, schema, operation, er
35584
36014
  const parsed = schema.safeParse(data);
35585
36015
  if (!parsed.success) {
35586
36016
  console.error(`Zod Parsing Error in ${operation}:`, parsed.error.format());
35587
- throw new import_server20.TRPCError({
36017
+ throw new import_server21.TRPCError({
35588
36018
  code: "INTERNAL_SERVER_ERROR",
35589
36019
  message: errorMessage
35590
36020
  });
@@ -35828,46 +36258,46 @@ var securityGroupRuleRouter = {
35828
36258
  };
35829
36259
 
35830
36260
  // src/server/Network/types/rbacPolicy.ts
35831
- var import_zod22 = require("zod");
35832
- var rbacPolicySchema = import_zod22.z.object({
35833
- id: import_zod22.z.string(),
35834
- object_type: import_zod22.z.enum([
36261
+ var import_zod23 = require("zod");
36262
+ var rbacPolicySchema = import_zod23.z.object({
36263
+ id: import_zod23.z.string(),
36264
+ object_type: import_zod23.z.enum([
35835
36265
  "qos_policy",
35836
36266
  "network",
35837
36267
  "security_group"
35838
36268
  ]),
35839
- object_id: import_zod22.z.string(),
35840
- action: import_zod22.z.enum([
36269
+ object_id: import_zod23.z.string(),
36270
+ action: import_zod23.z.enum([
35841
36271
  "access_as_shared",
35842
36272
  "access_as_external"
35843
36273
  ]),
35844
- target_tenant: import_zod22.z.string(),
35845
- tenant_id: import_zod22.z.string().nullable().optional(),
35846
- project_id: import_zod22.z.string().nullable().optional()
36274
+ target_tenant: import_zod23.z.string(),
36275
+ tenant_id: import_zod23.z.string().nullable().optional(),
36276
+ project_id: import_zod23.z.string().nullable().optional()
35847
36277
  });
35848
- var rbacPoliciesResponseSchema = import_zod22.z.object({
35849
- rbac_policies: import_zod22.z.array(rbacPolicySchema)
36278
+ var rbacPoliciesResponseSchema = import_zod23.z.object({
36279
+ rbac_policies: import_zod23.z.array(rbacPolicySchema)
35850
36280
  });
35851
- var rbacPolicyResponseSchema = import_zod22.z.object({
36281
+ var rbacPolicyResponseSchema = import_zod23.z.object({
35852
36282
  rbac_policy: rbacPolicySchema
35853
36283
  });
35854
36284
  var listRBACPoliciesForSecurityGroupInputSchema = projectScopedInputSchema.extend({
35855
- securityGroupId: import_zod22.z.string()
36285
+ securityGroupId: import_zod23.z.string()
35856
36286
  });
35857
36287
  var createRBACPolicyInputSchema = projectScopedInputSchema.extend({
35858
- securityGroupId: import_zod22.z.string(),
35859
- targetTenant: import_zod22.z.string().trim().min(1, "Target project ID is required")
36288
+ securityGroupId: import_zod23.z.string(),
36289
+ targetTenant: import_zod23.z.string().trim().min(1, "Target project ID is required")
35860
36290
  });
35861
36291
  var updateRBACPolicyInputSchema = projectScopedInputSchema.extend({
35862
- policyId: import_zod22.z.string(),
35863
- targetTenant: import_zod22.z.string().trim().min(1, "Target project ID is required")
36292
+ policyId: import_zod23.z.string(),
36293
+ targetTenant: import_zod23.z.string().trim().min(1, "Target project ID is required")
35864
36294
  });
35865
36295
  var deleteRBACPolicyInputSchema = projectScopedInputSchema.extend({
35866
- policyId: import_zod22.z.string()
36296
+ policyId: import_zod23.z.string()
35867
36297
  });
35868
36298
 
35869
36299
  // src/server/Network/helpers/rbacPolicyHelpers.ts
35870
- var import_server21 = require("@trpc/server");
36300
+ var import_server22 = require("@trpc/server");
35871
36301
  var RBACPolicyErrorHandlers = {
35872
36302
  /**
35873
36303
  * Handles errors specific to RBAC policy list operations
@@ -35877,17 +36307,17 @@ var RBACPolicyErrorHandlers = {
35877
36307
  list: /* @__PURE__ */ __name((response) => {
35878
36308
  switch (response.status) {
35879
36309
  case 401:
35880
- return new import_server21.TRPCError({
36310
+ return new import_server22.TRPCError({
35881
36311
  code: HTTP_STATUS_ERROR_MAP[401],
35882
36312
  message: "Unauthorized access"
35883
36313
  });
35884
36314
  case 403:
35885
- return new import_server21.TRPCError({
36315
+ return new import_server22.TRPCError({
35886
36316
  code: HTTP_STATUS_ERROR_MAP[403],
35887
36317
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
35888
36318
  });
35889
36319
  default:
35890
- return new import_server21.TRPCError({
36320
+ return new import_server22.TRPCError({
35891
36321
  code: DEFAULT_ERROR_NAME,
35892
36322
  message: `Failed to list RBAC policies: ${response.statusText || "Unknown error"}`
35893
36323
  });
@@ -35901,32 +36331,32 @@ var RBACPolicyErrorHandlers = {
35901
36331
  create: /* @__PURE__ */ __name((response) => {
35902
36332
  switch (response.status) {
35903
36333
  case 400:
35904
- return new import_server21.TRPCError({
36334
+ return new import_server22.TRPCError({
35905
36335
  code: HTTP_STATUS_ERROR_MAP[400],
35906
36336
  message: `Invalid request: ${response.statusText || "Unknown error"}`
35907
36337
  });
35908
36338
  case 401:
35909
- return new import_server21.TRPCError({
36339
+ return new import_server22.TRPCError({
35910
36340
  code: HTTP_STATUS_ERROR_MAP[401],
35911
36341
  message: "Unauthorized access"
35912
36342
  });
35913
36343
  case 403:
35914
- return new import_server21.TRPCError({
36344
+ return new import_server22.TRPCError({
35915
36345
  code: HTTP_STATUS_ERROR_MAP[403],
35916
36346
  message: "You don't have permission to share this security group"
35917
36347
  });
35918
36348
  case 404:
35919
- return new import_server21.TRPCError({
36349
+ return new import_server22.TRPCError({
35920
36350
  code: HTTP_STATUS_ERROR_MAP[404],
35921
36351
  message: "Security group not found or target project does not exist"
35922
36352
  });
35923
36353
  case 409:
35924
- return new import_server21.TRPCError({
36354
+ return new import_server22.TRPCError({
35925
36355
  code: HTTP_STATUS_ERROR_MAP[409],
35926
36356
  message: "This security group is already shared with the specified project"
35927
36357
  });
35928
36358
  default:
35929
- return new import_server21.TRPCError({
36359
+ return new import_server22.TRPCError({
35930
36360
  code: "INTERNAL_SERVER_ERROR",
35931
36361
  message: `Failed to create RBAC policy: ${response.statusText || "Unknown error"}`
35932
36362
  });
@@ -35941,27 +36371,27 @@ var RBACPolicyErrorHandlers = {
35941
36371
  update: /* @__PURE__ */ __name((response, policyId) => {
35942
36372
  switch (response.status) {
35943
36373
  case 400:
35944
- return new import_server21.TRPCError({
36374
+ return new import_server22.TRPCError({
35945
36375
  code: HTTP_STATUS_ERROR_MAP[400],
35946
36376
  message: `Invalid request: ${response.statusText || "Unknown error"}`
35947
36377
  });
35948
36378
  case 401:
35949
- return new import_server21.TRPCError({
36379
+ return new import_server22.TRPCError({
35950
36380
  code: HTTP_STATUS_ERROR_MAP[401],
35951
36381
  message: "Unauthorized access"
35952
36382
  });
35953
36383
  case 403:
35954
- return new import_server21.TRPCError({
36384
+ return new import_server22.TRPCError({
35955
36385
  code: HTTP_STATUS_ERROR_MAP[403],
35956
36386
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
35957
36387
  });
35958
36388
  case 404:
35959
- return new import_server21.TRPCError({
36389
+ return new import_server22.TRPCError({
35960
36390
  code: HTTP_STATUS_ERROR_MAP[404],
35961
36391
  message: `RBAC policy not found: ${policyId}`
35962
36392
  });
35963
36393
  default:
35964
- return new import_server21.TRPCError({
36394
+ return new import_server22.TRPCError({
35965
36395
  code: "INTERNAL_SERVER_ERROR",
35966
36396
  message: `Failed to update RBAC policy: ${response.statusText || "Unknown error"}`
35967
36397
  });
@@ -35976,22 +36406,22 @@ var RBACPolicyErrorHandlers = {
35976
36406
  delete: /* @__PURE__ */ __name((response, policyId) => {
35977
36407
  switch (response.status) {
35978
36408
  case 401:
35979
- return new import_server21.TRPCError({
36409
+ return new import_server22.TRPCError({
35980
36410
  code: HTTP_STATUS_ERROR_MAP[401],
35981
36411
  message: "Unauthorized access"
35982
36412
  });
35983
36413
  case 404:
35984
- return new import_server21.TRPCError({
36414
+ return new import_server22.TRPCError({
35985
36415
  code: HTTP_STATUS_ERROR_MAP[404],
35986
36416
  message: `RBAC policy not found: ${policyId}`
35987
36417
  });
35988
36418
  case 409:
35989
- return new import_server21.TRPCError({
36419
+ return new import_server22.TRPCError({
35990
36420
  code: HTTP_STATUS_ERROR_MAP[409],
35991
36421
  message: "Cannot delete RBAC policy because it is in use"
35992
36422
  });
35993
36423
  default:
35994
- return new import_server21.TRPCError({
36424
+ return new import_server22.TRPCError({
35995
36425
  code: DEFAULT_ERROR_NAME,
35996
36426
  message: `Failed to delete RBAC policy: ${response.statusText || "Unknown error"}`
35997
36427
  });
@@ -36002,7 +36432,7 @@ var parseOpenStackResponse2 = /* @__PURE__ */ __name((data, schema, operation, e
36002
36432
  const parsed = schema.safeParse(data);
36003
36433
  if (!parsed.success) {
36004
36434
  console.error(`Zod Parsing Error in ${operation}:`, parsed.error.format());
36005
- throw new import_server21.TRPCError({
36435
+ throw new import_server22.TRPCError({
36006
36436
  code: "INTERNAL_SERVER_ERROR",
36007
36437
  message: errorMessage
36008
36438
  });
@@ -36089,125 +36519,344 @@ var rbacPolicyRouter = {
36089
36519
  })
36090
36520
  };
36091
36521
 
36522
+ // src/server/Network/routers/permissionRouter.ts
36523
+ var NETWORK_MAPPINGS = {
36524
+ // Network Operations
36525
+ "network:networks:read": {
36526
+ engine: "network",
36527
+ rule: "get_network"
36528
+ },
36529
+ "network:networks:list": {
36530
+ engine: "network",
36531
+ rule: "get_network"
36532
+ },
36533
+ "network:networks:create": {
36534
+ engine: "network",
36535
+ rule: "create_network"
36536
+ },
36537
+ "network:networks:update": {
36538
+ engine: "network",
36539
+ rule: "update_network"
36540
+ },
36541
+ "network:networks:delete": {
36542
+ engine: "network",
36543
+ rule: "delete_network"
36544
+ },
36545
+ // Subnet Operations
36546
+ "network:subnets:read": {
36547
+ engine: "network",
36548
+ rule: "get_subnet"
36549
+ },
36550
+ "network:subnets:list": {
36551
+ engine: "network",
36552
+ rule: "get_subnet"
36553
+ },
36554
+ "network:subnets:create": {
36555
+ engine: "network",
36556
+ rule: "create_subnet"
36557
+ },
36558
+ "network:subnets:update": {
36559
+ engine: "network",
36560
+ rule: "update_subnet"
36561
+ },
36562
+ "network:subnets:delete": {
36563
+ engine: "network",
36564
+ rule: "delete_subnet"
36565
+ },
36566
+ // Subnet Pool Operations
36567
+ "network:subnet_pools:read": {
36568
+ engine: "network",
36569
+ rule: "get_subnetpool"
36570
+ },
36571
+ "network:subnet_pools:list": {
36572
+ engine: "network",
36573
+ rule: "get_subnetpool"
36574
+ },
36575
+ "network:subnet_pools:create": {
36576
+ engine: "network",
36577
+ rule: "create_subnetpool"
36578
+ },
36579
+ "network:subnet_pools:update": {
36580
+ engine: "network",
36581
+ rule: "update_subnetpool"
36582
+ },
36583
+ "network:subnet_pools:delete": {
36584
+ engine: "network",
36585
+ rule: "delete_subnetpool"
36586
+ },
36587
+ // Router Operations
36588
+ "network:routers:read": {
36589
+ engine: "network",
36590
+ rule: "get_router"
36591
+ },
36592
+ "network:routers:list": {
36593
+ engine: "network",
36594
+ rule: "get_router"
36595
+ },
36596
+ "network:routers:create": {
36597
+ engine: "network",
36598
+ rule: "create_router"
36599
+ },
36600
+ "network:routers:update": {
36601
+ engine: "network",
36602
+ rule: "update_router"
36603
+ },
36604
+ "network:routers:delete": {
36605
+ engine: "network",
36606
+ rule: "delete_router"
36607
+ },
36608
+ "network:routers:attach_interface": {
36609
+ engine: "network",
36610
+ rule: "add_router_interface"
36611
+ },
36612
+ "network:routers:detach_interface": {
36613
+ engine: "network",
36614
+ rule: "remove_router_interface"
36615
+ },
36616
+ // Floating IP Operations
36617
+ "network:floatingips:read": {
36618
+ engine: "network",
36619
+ rule: "get_floatingip"
36620
+ },
36621
+ "network:floatingips:list": {
36622
+ engine: "network",
36623
+ rule: "get_floatingip"
36624
+ },
36625
+ "network:floatingips:create": {
36626
+ engine: "network",
36627
+ rule: "create_floatingip"
36628
+ },
36629
+ "network:floatingips:update": {
36630
+ engine: "network",
36631
+ rule: "update_floatingip"
36632
+ },
36633
+ "network:floatingips:delete": {
36634
+ engine: "network",
36635
+ rule: "delete_floatingip"
36636
+ },
36637
+ "network:floatingips:associate": {
36638
+ engine: "network",
36639
+ rule: "update_floatingip"
36640
+ },
36641
+ "network:floatingips:disassociate": {
36642
+ engine: "network",
36643
+ rule: "update_floatingip"
36644
+ },
36645
+ // Security Group Operations
36646
+ "network:security_groups:read": {
36647
+ engine: "network",
36648
+ rule: "get_security_group"
36649
+ },
36650
+ "network:security_groups:list": {
36651
+ engine: "network",
36652
+ rule: "get_security_groups"
36653
+ },
36654
+ "network:security_groups:create": {
36655
+ engine: "network",
36656
+ rule: "create_security_group"
36657
+ },
36658
+ "network:security_groups:update": {
36659
+ engine: "network",
36660
+ rule: "update_security_group"
36661
+ },
36662
+ "network:security_groups:delete": {
36663
+ engine: "network",
36664
+ rule: "delete_security_group"
36665
+ },
36666
+ // Security Group Rule Operations
36667
+ "network:security_group_rules:read": {
36668
+ engine: "network",
36669
+ rule: "get_security_group_rule"
36670
+ },
36671
+ "network:security_group_rules:list": {
36672
+ engine: "network",
36673
+ rule: "get_security_group_rules"
36674
+ },
36675
+ "network:security_group_rules:create": {
36676
+ engine: "network",
36677
+ rule: "create_security_group_rule"
36678
+ },
36679
+ "network:security_group_rules:update": {
36680
+ engine: "network",
36681
+ rule: "update_security_group_rule"
36682
+ },
36683
+ "network:security_group_rules:delete": {
36684
+ engine: "network",
36685
+ rule: "delete_security_group_rule"
36686
+ },
36687
+ // Port Operations
36688
+ "network:ports:read": {
36689
+ engine: "network",
36690
+ rule: "get_port"
36691
+ },
36692
+ "network:ports:list": {
36693
+ engine: "network",
36694
+ rule: "get_port"
36695
+ },
36696
+ "network:ports:create": {
36697
+ engine: "network",
36698
+ rule: "create_port"
36699
+ },
36700
+ "network:ports:update": {
36701
+ engine: "network",
36702
+ rule: "update_port"
36703
+ },
36704
+ "network:ports:delete": {
36705
+ engine: "network",
36706
+ rule: "delete_port"
36707
+ },
36708
+ // RBAC Policy Operations
36709
+ "network:rbac_policies:read": {
36710
+ engine: "network",
36711
+ rule: "get_rbac_policy"
36712
+ },
36713
+ "network:rbac_policies:list": {
36714
+ engine: "network",
36715
+ rule: "get_rbac_policy"
36716
+ },
36717
+ "network:rbac_policies:create": {
36718
+ engine: "network",
36719
+ rule: "create_rbac_policy"
36720
+ },
36721
+ "network:rbac_policies:update": {
36722
+ engine: "network",
36723
+ rule: "update_rbac_policy"
36724
+ },
36725
+ "network:rbac_policies:delete": {
36726
+ engine: "network",
36727
+ rule: "delete_rbac_policy"
36728
+ }
36729
+ };
36730
+ var buildNetworkPermissionRouter = /* @__PURE__ */ __name((policyDir) => createPermissionRouter({
36731
+ policyDir,
36732
+ engines: {
36733
+ network: {
36734
+ fileName: "networking.json"
36735
+ }
36736
+ },
36737
+ mappings: NETWORK_MAPPINGS
36738
+ }), "buildNetworkPermissionRouter");
36739
+
36092
36740
  // src/server/Network/routers/index.ts
36093
- var networkRouters = {
36741
+ var buildNetworkRouters = /* @__PURE__ */ __name((policyDir) => ({
36094
36742
  network: auroraRouter({
36095
36743
  floatingIp: floatingIpRouter,
36096
36744
  securityGroup: securityGroupRouter,
36097
36745
  securityGroupRule: securityGroupRuleRouter,
36098
- rbacPolicy: rbacPolicyRouter
36746
+ rbacPolicy: rbacPolicyRouter,
36747
+ ...buildNetworkPermissionRouter(policyDir)
36099
36748
  })
36100
- };
36749
+ }), "buildNetworkRouters");
36101
36750
 
36102
36751
  // src/server/Services/types/pca.ts
36103
- var import_zod23 = require("zod");
36104
- var CertificateValiditySchema = import_zod23.z.object({
36105
- not_after: import_zod23.z.number().int(),
36106
- not_before: import_zod23.z.number().int().optional()
36752
+ var import_zod24 = require("zod");
36753
+ var CertificateValiditySchema = import_zod24.z.object({
36754
+ not_after: import_zod24.z.number().int(),
36755
+ not_before: import_zod24.z.number().int().optional()
36107
36756
  });
36108
- var CertificateAuthorityCertificateSchema = import_zod23.z.object({
36757
+ var CertificateAuthorityCertificateSchema = import_zod24.z.object({
36109
36758
  /** PEM encoded certificate data. */
36110
- pem: import_zod23.z.string(),
36759
+ pem: import_zod24.z.string(),
36111
36760
  validity: CertificateValiditySchema
36112
36761
  });
36113
- var CertificateAuthorityCertificateChainSchema = import_zod23.z.object({
36114
- certificates: import_zod23.z.array(import_zod23.z.object({
36115
- pem: import_zod23.z.string()
36762
+ var CertificateAuthorityCertificateChainSchema = import_zod24.z.object({
36763
+ certificates: import_zod24.z.array(import_zod24.z.object({
36764
+ pem: import_zod24.z.string()
36116
36765
  })),
36117
36766
  /** Concatenated PEM certificates of the chain. */
36118
- pem: import_zod23.z.string()
36767
+ pem: import_zod24.z.string()
36119
36768
  });
36120
- var CertificateAuthorityAdditionalAttributeSchema = import_zod23.z.object({
36769
+ var CertificateAuthorityAdditionalAttributeSchema = import_zod24.z.object({
36121
36770
  /** ASN.1 Object Identifier of the attribute */
36122
- key: import_zod23.z.array(import_zod23.z.number().int()),
36123
- value: import_zod23.z.string()
36771
+ key: import_zod24.z.array(import_zod24.z.number().int()),
36772
+ value: import_zod24.z.string()
36124
36773
  });
36125
- var CertificateAuthoritySubjectSchema = import_zod23.z.object({
36126
- additional_attribute: import_zod23.z.array(CertificateAuthorityAdditionalAttributeSchema).optional(),
36774
+ var CertificateAuthoritySubjectSchema = import_zod24.z.object({
36775
+ additional_attribute: import_zod24.z.array(CertificateAuthorityAdditionalAttributeSchema).optional(),
36127
36776
  /** Typically domain name */
36128
- common_name: import_zod23.z.string(),
36777
+ common_name: import_zod24.z.string(),
36129
36778
  /** Country codes (ISO 3166-1 alpha-2). */
36130
- country: import_zod23.z.array(import_zod23.z.string()).optional(),
36779
+ country: import_zod24.z.array(import_zod24.z.string()).optional(),
36131
36780
  /** Locality/city names. */
36132
- locality: import_zod23.z.array(import_zod23.z.string()).optional(),
36781
+ locality: import_zod24.z.array(import_zod24.z.string()).optional(),
36133
36782
  /** Organization names. */
36134
- organization: import_zod23.z.array(import_zod23.z.string()).optional(),
36783
+ organization: import_zod24.z.array(import_zod24.z.string()).optional(),
36135
36784
  /** Organizational unit names. */
36136
- organizational_unit: import_zod23.z.array(import_zod23.z.string()).optional(),
36785
+ organizational_unit: import_zod24.z.array(import_zod24.z.string()).optional(),
36137
36786
  /** Postal/ZIP codes. */
36138
- postal_code: import_zod23.z.array(import_zod23.z.string()).optional(),
36787
+ postal_code: import_zod24.z.array(import_zod24.z.string()).optional(),
36139
36788
  /** State or province names. */
36140
- province: import_zod23.z.array(import_zod23.z.string()).optional(),
36141
- serial_number: import_zod23.z.string().optional(),
36142
- street_address: import_zod23.z.array(import_zod23.z.string()).optional()
36789
+ province: import_zod24.z.array(import_zod24.z.string()).optional(),
36790
+ serial_number: import_zod24.z.string().optional(),
36791
+ street_address: import_zod24.z.array(import_zod24.z.string()).optional()
36143
36792
  });
36144
- var CertificateAuthorityStateSchema = import_zod23.z.enum([
36793
+ var CertificateAuthorityStateSchema = import_zod24.z.enum([
36145
36794
  "CREATING",
36146
36795
  "AWAITING_CERTIFICATE",
36147
36796
  "READY",
36148
36797
  "FAILED",
36149
36798
  "UNEXPECTED"
36150
36799
  ]);
36151
- var CertificateAuthoritySchema = import_zod23.z.object({
36800
+ var CertificateAuthoritySchema = import_zod24.z.object({
36152
36801
  certificate: CertificateAuthorityCertificateSchema.optional(),
36153
36802
  /** Details of Certificate Authority certificate's issuers chain. */
36154
36803
  certificate_chain: CertificateAuthorityCertificateChainSchema.optional(),
36155
- configuration: import_zod23.z.object({
36804
+ configuration: import_zod24.z.object({
36156
36805
  /** X.509 subject of Certificate Authority. Required on create operation. */
36157
36806
  subject: CertificateAuthoritySubjectSchema
36158
36807
  }).optional(),
36159
- csr: import_zod23.z.string().optional(),
36160
- id: import_zod23.z.string(),
36808
+ csr: import_zod24.z.string().optional(),
36809
+ id: import_zod24.z.string(),
36161
36810
  /**
36162
36811
  * Required on import certificate operation.
36163
36812
  * Certificate Authority certificate chain, in PEM format. Consists of concatenated string
36164
36813
  * of Certificate Authority certificate, followed by its intermediate issuing CAs certificates
36165
36814
  * and root issuing CA certificate last.
36166
36815
  */
36167
- imported_certificate_chain: import_zod23.z.string().optional(),
36816
+ imported_certificate_chain: import_zod24.z.string().optional(),
36168
36817
  /** Identifier of OpenStack project that Certificate Authority belongs. */
36169
- project_id: import_zod23.z.string(),
36818
+ project_id: import_zod24.z.string(),
36170
36819
  /** Current operational state of Certificate Authority. */
36171
36820
  state: CertificateAuthorityStateSchema
36172
36821
  });
36173
- var CertificateAuthoritiesListSchema = import_zod23.z.object({
36174
- certificate_authorities: import_zod23.z.array(CertificateAuthoritySchema)
36822
+ var CertificateAuthoritiesListSchema = import_zod24.z.object({
36823
+ certificate_authorities: import_zod24.z.array(CertificateAuthoritySchema)
36175
36824
  });
36176
- var CertificateAuthorityCreateSchema = import_zod23.z.object({
36177
- configuration: import_zod23.z.object({
36825
+ var CertificateAuthorityCreateSchema = import_zod24.z.object({
36826
+ configuration: import_zod24.z.object({
36178
36827
  subject: CertificateAuthoritySubjectSchema
36179
36828
  })
36180
36829
  });
36181
- var CertificateAuthorityIdInputSchema = import_zod23.z.object({
36182
- project_id: import_zod23.z.string(),
36183
- certificate_authority_id: import_zod23.z.string().min(1)
36830
+ var CertificateAuthorityIdInputSchema = import_zod24.z.object({
36831
+ project_id: import_zod24.z.string(),
36832
+ certificate_authority_id: import_zod24.z.string().min(1)
36184
36833
  });
36185
36834
  var CertificateAuthorityImportInputSchema = CertificateAuthorityIdInputSchema.extend({
36186
- imported_certificate_chain: import_zod23.z.string().min(1)
36835
+ imported_certificate_chain: import_zod24.z.string().min(1)
36187
36836
  });
36188
36837
  var CertificateIdInputSchema = CertificateAuthorityIdInputSchema.extend({
36189
- certificate_id: import_zod23.z.string().min(1)
36838
+ certificate_id: import_zod24.z.string().min(1)
36190
36839
  });
36191
- var CertificateConfigurationSchema = import_zod23.z.object({
36840
+ var CertificateConfigurationSchema = import_zod24.z.object({
36192
36841
  validity: CertificateValiditySchema
36193
36842
  });
36194
- var CreateCertificateInputSchema = import_zod23.z.object({
36195
- project_id: import_zod23.z.string(),
36196
- certificate_authority_id: import_zod23.z.string().min(1),
36197
- csr: import_zod23.z.string().min(1),
36843
+ var CreateCertificateInputSchema = import_zod24.z.object({
36844
+ project_id: import_zod24.z.string(),
36845
+ certificate_authority_id: import_zod24.z.string().min(1),
36846
+ csr: import_zod24.z.string().min(1),
36198
36847
  configuration: CertificateConfigurationSchema
36199
36848
  });
36200
- var CertificateSchema = import_zod23.z.object({
36849
+ var CertificateSchema = import_zod24.z.object({
36201
36850
  certificate: CertificateAuthorityCertificateSchema.optional(),
36202
- certificate_authority_id: import_zod23.z.string(),
36851
+ certificate_authority_id: import_zod24.z.string(),
36203
36852
  certificate_chain: CertificateAuthorityCertificateChainSchema.optional(),
36204
36853
  configuration: CertificateConfigurationSchema.optional(),
36205
- csr: import_zod23.z.string().optional(),
36206
- id: import_zod23.z.string(),
36207
- project_id: import_zod23.z.string()
36854
+ csr: import_zod24.z.string().optional(),
36855
+ id: import_zod24.z.string(),
36856
+ project_id: import_zod24.z.string()
36208
36857
  });
36209
- var CertificatesListSchema = import_zod23.z.object({
36210
- certificates: import_zod23.z.array(CertificateSchema)
36858
+ var CertificatesListSchema = import_zod24.z.object({
36859
+ certificates: import_zod24.z.array(CertificateSchema)
36211
36860
  });
36212
36861
 
36213
36862
  // src/server/Services/routers/pcaRouter.ts
@@ -36312,10 +36961,10 @@ var serviceRouters = {
36312
36961
  };
36313
36962
 
36314
36963
  // src/server/routers.ts
36315
- var buildAppRouter = /* @__PURE__ */ __name((policyDir) => mergeRouters(auroraRouter(authRouters), auroraRouter(buildComputeRouters(policyDir)), auroraRouter(objectStorageRouters), auroraRouter(projectRouters), auroraRouter(networkRouters), auroraRouter(serviceRouters)), "buildAppRouter");
36964
+ var buildAppRouter = /* @__PURE__ */ __name((policyDir) => mergeRouters(auroraRouter(authRouters), auroraRouter(buildComputeRouters(policyDir)), auroraRouter(buildObjectStorageRouters(policyDir)), auroraRouter(projectRouters), auroraRouter(buildNetworkRouters(policyDir)), auroraRouter(serviceRouters)), "buildAppRouter");
36316
36965
 
36317
36966
  // src/server/context.ts
36318
- var import_signal_openstack = __toESM(require_esm2());
36967
+ var import_signal_openstack2 = __toESM(require_esm2());
36319
36968
 
36320
36969
  // src/server/sessionCookie.ts
36321
36970
  var import_cookie = require("@fastify/cookie");
@@ -36416,7 +37065,7 @@ async function createContext(opts, config) {
36416
37065
  writable: false
36417
37066
  });
36418
37067
  if (currentAuthToken) {
36419
- openstackSession = await (0, import_signal_openstack.SignalOpenstackSession)(normalizedEndpoint, {
37068
+ openstackSession = await (0, import_signal_openstack2.SignalOpenstackSession)(normalizedEndpoint, {
36420
37069
  auth: {
36421
37070
  identity: {
36422
37071
  methods: [
@@ -36479,7 +37128,7 @@ async function createContext(opts, config) {
36479
37128
  }
36480
37129
  }, "getUserInfo");
36481
37130
  const createSession = /* @__PURE__ */ __name(async (params) => {
36482
- openstackSession = await (0, import_signal_openstack.SignalOpenstackSession)(normalizedEndpoint, {
37131
+ openstackSession = await (0, import_signal_openstack2.SignalOpenstackSession)(normalizedEndpoint, {
36483
37132
  auth: {
36484
37133
  identity: {
36485
37134
  methods: [
@@ -36624,7 +37273,7 @@ __name(createContext, "createContext");
36624
37273
  // src/server/server.ts
36625
37274
  var import_path2 = __toESM(require("path"));
36626
37275
  var import_node_stream3 = require("stream");
36627
- var import_zod24 = require("zod");
37276
+ var import_zod25 = require("zod");
36628
37277
 
36629
37278
  // src/server/aurora-fastify-plugins/csrfProtection.ts
36630
37279
  var import_csrf_protection = __toESM(require("@fastify/csrf-protection"));
@@ -36693,7 +37342,195 @@ var csrfProtection_default = (0, import_fastify_plugin.default)(csrfPlugin, {
36693
37342
  fastify: "5.x"
36694
37343
  });
36695
37344
 
37345
+ // src/server/aurora-fastify-plugins/httpMetricsCollector.ts
37346
+ var import_fastify_plugin2 = __toESM(require("fastify-plugin"));
37347
+ var import_prom_client = require("prom-client");
37348
+ var LABEL_NAMES = [
37349
+ "status_code",
37350
+ "method",
37351
+ "route",
37352
+ "endpoint_type",
37353
+ "project_id"
37354
+ ];
37355
+ var EXCLUDE_PATHS = [
37356
+ "/metrics"
37357
+ ];
37358
+ async function httpMetricsCollectorPlugin(fastify, options) {
37359
+ const prefix = options.prefix || "aurora";
37360
+ const excludePaths = options.excludePaths || EXCLUDE_PATHS;
37361
+ const registry = options.registry || new import_prom_client.Registry();
37362
+ const bffEndpoint = options.bffEndpoint || "/polaris-bff";
37363
+ const requestsTotal = new import_prom_client.Counter({
37364
+ name: `${prefix}_requests_total`,
37365
+ help: "The total number of HTTP requests handled by the application",
37366
+ labelNames: LABEL_NAMES,
37367
+ registers: [
37368
+ registry
37369
+ ]
37370
+ });
37371
+ const requestDurationSeconds = new import_prom_client.Histogram({
37372
+ name: `${prefix}_request_duration_seconds`,
37373
+ help: "The HTTP response duration of the application",
37374
+ labelNames: LABEL_NAMES,
37375
+ registers: [
37376
+ registry
37377
+ ]
37378
+ });
37379
+ const exceptionsTotal = new import_prom_client.Counter({
37380
+ name: `${prefix}_exceptions_total`,
37381
+ help: "The total number of exceptions raised by the application",
37382
+ labelNames: [
37383
+ "exception"
37384
+ ],
37385
+ registers: [
37386
+ registry
37387
+ ]
37388
+ });
37389
+ fastify.addHook("onRequest", async (request) => {
37390
+ request.metricsStartTime = process.hrtime.bigint();
37391
+ });
37392
+ fastify.addHook("onResponse", async (request, reply) => {
37393
+ const path3 = request.url.split("?")[0];
37394
+ if (excludePaths.some((excludePath) => path3.startsWith(excludePath))) {
37395
+ return;
37396
+ }
37397
+ if (!request.metricsStartTime) {
37398
+ fastify.log.debug({
37399
+ url: request.url
37400
+ }, "Metrics start time missing, skipping metric collection");
37401
+ return;
37402
+ }
37403
+ const endTime = process.hrtime.bigint();
37404
+ const duration = Number(endTime - request.metricsStartTime) / 1e9;
37405
+ const labels = extractLabels(request, reply, bffEndpoint);
37406
+ try {
37407
+ requestsTotal.inc(labels);
37408
+ requestDurationSeconds.observe(labels, duration);
37409
+ } catch (error) {
37410
+ fastify.log.error({
37411
+ err: error
37412
+ }, "Failed to record HTTP metrics");
37413
+ }
37414
+ });
37415
+ fastify.addHook("onError", async (_request, _reply, error) => {
37416
+ try {
37417
+ exceptionsTotal.inc({
37418
+ exception: error.constructor.name
37419
+ });
37420
+ } catch (err) {
37421
+ fastify.log.error({
37422
+ err
37423
+ }, "Failed to record exception metric");
37424
+ }
37425
+ });
37426
+ fastify.decorate("metricsRegistry", registry);
37427
+ }
37428
+ __name(httpMetricsCollectorPlugin, "httpMetricsCollectorPlugin");
37429
+ function extractLabels(request, reply, bffEndpoint) {
37430
+ const urlPath = request.url.split("?")[0];
37431
+ let endpointType;
37432
+ let route = urlPath;
37433
+ let projectId = "";
37434
+ if (urlPath.includes(bffEndpoint)) {
37435
+ endpointType = "trpc";
37436
+ const procedurePath = urlPath.split(bffEndpoint + "/")[1];
37437
+ if (procedurePath) {
37438
+ const cleanPath = procedurePath.split("?")[0];
37439
+ const parts = cleanPath.split(".");
37440
+ if (parts.length >= 2) {
37441
+ const service = parts[0];
37442
+ const action = parts.slice(1).join(".");
37443
+ route = `${service}/${action}`;
37444
+ } else {
37445
+ route = cleanPath;
37446
+ }
37447
+ }
37448
+ const url = new URL(request.url, "http://localhost");
37449
+ const inputParam = url.searchParams.get("input");
37450
+ if (inputParam) {
37451
+ try {
37452
+ const input = JSON.parse(inputParam);
37453
+ if (input.project_id) {
37454
+ projectId = input.project_id;
37455
+ } else if (typeof input === "object") {
37456
+ const firstKey = Object.keys(input)[0];
37457
+ if (firstKey && input[firstKey]?.project_id) {
37458
+ projectId = input[firstKey].project_id;
37459
+ }
37460
+ }
37461
+ } catch {
37462
+ }
37463
+ }
37464
+ } else if (urlPath.startsWith("/api/")) {
37465
+ endpointType = "api";
37466
+ route = normalizeApiPath(urlPath);
37467
+ } else if (urlPath.startsWith("/@")) {
37468
+ endpointType = "vite-dev";
37469
+ route = "vite-dev";
37470
+ } else if (urlPath.match(/\.(js|jsx|ts|tsx|mjs|css|json|map)$/)) {
37471
+ endpointType = "module";
37472
+ const ext = urlPath.split(".").pop() || "unknown";
37473
+ route = `*.${ext}`;
37474
+ } else if (urlPath.match(/\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico|webp)$/)) {
37475
+ endpointType = "asset";
37476
+ const ext = urlPath.split(".").pop() || "unknown";
37477
+ route = `*.${ext}`;
37478
+ } else if (urlPath === "/" || urlPath === "/index.html") {
37479
+ endpointType = "spa";
37480
+ route = "/";
37481
+ } else {
37482
+ endpointType = "spa";
37483
+ route = normalizeSpaRoute(urlPath);
37484
+ const projectMatch = urlPath.match(/^\/projects\/([^/?]+)/);
37485
+ if (projectMatch) {
37486
+ projectId = projectMatch[1];
37487
+ }
37488
+ }
37489
+ return {
37490
+ status_code: reply.statusCode.toString(),
37491
+ method: request.method.toLowerCase(),
37492
+ route,
37493
+ endpoint_type: endpointType,
37494
+ project_id: projectId
37495
+ };
37496
+ }
37497
+ __name(extractLabels, "extractLabels");
37498
+ function normalizeSpaRoute(path3) {
37499
+ const segments = path3.split("/").filter(Boolean);
37500
+ if (segments[0] === "projects" && segments.length >= 3) {
37501
+ const service = segments[2];
37502
+ return `/projects/:id/${service}`;
37503
+ }
37504
+ if (segments[0] === "accounts" && segments.length >= 2) {
37505
+ return "/accounts/:id";
37506
+ }
37507
+ return "/" + segments.map((segment) => {
37508
+ if (segment.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)) {
37509
+ return ":id";
37510
+ }
37511
+ if (segment.match(/^[a-zA-Z0-9_-]{20,}$/)) {
37512
+ return ":id";
37513
+ }
37514
+ return segment;
37515
+ }).join("/");
37516
+ }
37517
+ __name(normalizeSpaRoute, "normalizeSpaRoute");
37518
+ function normalizeApiPath(path3) {
37519
+ return path3.split("/").map((segment) => {
37520
+ if (segment.match(/^\d+$/) || segment.match(/^[0-9a-f-]{36}$/i)) {
37521
+ return ":id";
37522
+ }
37523
+ return segment;
37524
+ }).join("/");
37525
+ }
37526
+ __name(normalizeApiPath, "normalizeApiPath");
37527
+ var AuroraHttpMetricsCollector = (0, import_fastify_plugin2.default)(httpMetricsCollectorPlugin, {
37528
+ name: "aurora-http-metrics-collector",
37529
+ fastify: "5.x"
37530
+ });
37531
+
36696
37532
  // src/server/server.ts
37533
+ var import_prom_client2 = require("prom-client");
36697
37534
  async function createServer(config) {
36698
37535
  const isProduction = process.env.NODE_ENV === "production";
36699
37536
  const rawBffEndpoint = config.bffEndpoint ?? "/polaris-bff";
@@ -36722,6 +37559,19 @@ async function createServer(config) {
36722
37559
  server.register(import_cookie2.default, {
36723
37560
  secret: void 0
36724
37561
  });
37562
+ const metricsRegistry = new import_prom_client2.Registry();
37563
+ await server.register(AuroraHttpMetricsCollector, {
37564
+ prefix: "aurora",
37565
+ excludePaths: [
37566
+ "/metrics"
37567
+ ],
37568
+ registry: metricsRegistry,
37569
+ bffEndpoint
37570
+ });
37571
+ server.get("/metrics", async (_request, reply) => {
37572
+ reply.header("Content-Type", metricsRegistry.contentType);
37573
+ return reply.send(await metricsRegistry.metrics());
37574
+ });
36725
37575
  await server.register(import_rate_limit.default, {
36726
37576
  max: 200,
36727
37577
  timeWindow: "1 minute"
@@ -36832,7 +37682,7 @@ async function createServer(config) {
36832
37682
  router: appRouter,
36833
37683
  createContext: /* @__PURE__ */ __name((opts) => createContext(opts, contextConfig), "createContext"),
36834
37684
  onError: /* @__PURE__ */ __name((err) => {
36835
- if (err.error.cause instanceof import_zod24.ZodError) err.error.message = err.error.cause.issues.map((e) => e.message).join(",");
37685
+ if (err.error.cause instanceof import_zod25.ZodError) err.error.message = err.error.cause.issues.map((e) => e.message).join(",");
36836
37686
  }, "onError")
36837
37687
  }
36838
37688
  });