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