@cobaltcore-dev/aurora 1.0.0 → 1.2.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 (205) hide show
  1. package/README.md +59 -9
  2. package/dist/client/App.d.ts +2 -1
  3. package/dist/client/AuroraApp.d.ts +45 -0
  4. package/dist/client/{AuthProvider-5TyZKZkx.mjs → AuthProvider-CVSAwW9f.mjs} +23 -9
  5. package/dist/client/AuthProvider-CVSAwW9f.mjs.map +1 -0
  6. package/dist/client/{ContentHeader-D64NtKvo.mjs → ContentHeader-CPJbgYWn.mjs} +18 -18
  7. package/dist/client/{ContentHeader-D64NtKvo.mjs.map → ContentHeader-CPJbgYWn.mjs.map} +1 -1
  8. package/dist/client/DeleteFlavorModal-V44QCJBd.mjs +773 -0
  9. package/dist/client/DeleteFlavorModal-V44QCJBd.mjs.map +1 -0
  10. package/dist/client/DynamicBreadcrumbContext-CVcUQFou.mjs +26 -0
  11. package/dist/client/DynamicBreadcrumbContext-CVcUQFou.mjs.map +1 -0
  12. package/dist/client/{FiltersInput-Bw8TFfwb.mjs → FiltersInput-CKI6zWnm.mjs} +22 -22
  13. package/dist/client/{FiltersInput-Bw8TFfwb.mjs.map → FiltersInput-CKI6zWnm.mjs.map} +1 -1
  14. package/dist/client/FloatingIpActionModals-CwEC5GR-.mjs +460 -0
  15. package/dist/client/FloatingIpActionModals-CwEC5GR-.mjs.map +1 -0
  16. package/dist/client/ImageToastNotifications-m6c3tVPb.mjs +1152 -0
  17. package/dist/client/ImageToastNotifications-m6c3tVPb.mjs.map +1 -0
  18. package/dist/client/{SortInput-DysAXpB3.mjs → SortInput-4g7nSTHW.mjs} +14 -14
  19. package/dist/client/SortInput-4g7nSTHW.mjs.map +1 -0
  20. package/dist/client/{TwoColumnDescriptionList-B3xunXmz.mjs → TwoColumnDescriptionList-NvgvErua.mjs} +6 -6
  21. package/dist/client/{TwoColumnDescriptionList-B3xunXmz.mjs.map → TwoColumnDescriptionList-NvgvErua.mjs.map} +1 -1
  22. package/dist/client/_-CAsCx-Ay.mjs +6 -0
  23. package/dist/client/_-CAsCx-Ay.mjs.map +1 -0
  24. package/dist/client/_auth-SrDjHL6j.mjs +12 -0
  25. package/dist/client/_auth-SrDjHL6j.mjs.map +1 -0
  26. package/dist/client/_flavorId-9PcBBW52.mjs +231 -0
  27. package/dist/client/_flavorId-9PcBBW52.mjs.map +1 -0
  28. package/dist/client/{_flavorId-Zj7LNL-R.mjs → _flavorId-a9Gu66R1.mjs} +3 -9
  29. package/dist/client/_flavorId-a9Gu66R1.mjs.map +1 -0
  30. package/dist/client/_floatingIpId-AE9Fu8l6.mjs +210 -0
  31. package/dist/client/_floatingIpId-AE9Fu8l6.mjs.map +1 -0
  32. package/dist/client/{_floatingIpId-DCQQpNO-.mjs → _floatingIpId-AZ11Ksmu.mjs} +3 -9
  33. package/dist/client/_floatingIpId-AZ11Ksmu.mjs.map +1 -0
  34. package/dist/client/_imageId-BtAql2Kr.mjs +570 -0
  35. package/dist/client/_imageId-BtAql2Kr.mjs.map +1 -0
  36. package/dist/client/_imageId-D76BxvFY.mjs +39 -0
  37. package/dist/client/_imageId-D76BxvFY.mjs.map +1 -0
  38. package/dist/client/_projectId-7Nl1MQTJ.mjs +99 -0
  39. package/dist/client/_projectId-7Nl1MQTJ.mjs.map +1 -0
  40. package/dist/client/_projectId-B3wmSala.mjs +281 -0
  41. package/dist/client/_projectId-B3wmSala.mjs.map +1 -0
  42. package/dist/client/_projectId-DPzv0CCp.mjs +77 -0
  43. package/dist/client/_projectId-DPzv0CCp.mjs.map +1 -0
  44. package/dist/client/_projectId-DfeVJy0G.mjs +30 -0
  45. package/dist/client/_projectId-DfeVJy0G.mjs.map +1 -0
  46. package/dist/client/_securityGroupId-C5huJNfO.mjs +1810 -0
  47. package/dist/client/_securityGroupId-C5huJNfO.mjs.map +1 -0
  48. package/dist/client/{_securityGroupId-Mj8NJT2-.mjs → _securityGroupId-D85mSigA.mjs} +3 -9
  49. package/dist/client/_securityGroupId-D85mSigA.mjs.map +1 -0
  50. package/dist/client/_serviceType-DS8DxsrP.mjs +20 -0
  51. package/dist/client/_serviceType-DS8DxsrP.mjs.map +1 -0
  52. package/dist/client/_serviceType-M8d9rOT6.mjs +6 -0
  53. package/dist/client/_serviceType-M8d9rOT6.mjs.map +1 -0
  54. package/dist/client/_storageType-BRWWJtow.mjs +14 -0
  55. package/dist/client/_storageType-BRWWJtow.mjs.map +1 -0
  56. package/dist/client/_storageType-CzZ4u9x_.mjs +12 -0
  57. package/dist/client/_storageType-CzZ4u9x_.mjs.map +1 -0
  58. package/dist/client/_storageType-Dy9uCVXr.mjs +845 -0
  59. package/dist/client/_storageType-Dy9uCVXr.mjs.map +1 -0
  60. package/dist/client/_storageType-zeSZe--V.mjs.map +1 -1
  61. package/dist/client/{about-WLyShNgE.mjs → about-BmQTyLWc.mjs} +2 -2
  62. package/dist/client/{about-WLyShNgE.mjs.map → about-BmQTyLWc.mjs.map} +1 -1
  63. package/dist/client/assets/{objectDownload.worker-BXFQIIU_.js.map → objectDownload.worker-CWWLPDyb.js.map} +1 -1
  64. package/dist/client/assets/{objectDownload.worker-ECvFtmOF.js.map → objectDownload.worker-kZlQuo3F.js.map} +1 -1
  65. package/dist/client/{aurora-IMO9HhqJ.mjs → aurora-CIml-f2f.mjs} +2 -2
  66. package/dist/client/{aurora-IMO9HhqJ.mjs.map → aurora-CIml-f2f.mjs.map} +1 -1
  67. package/dist/client/{build-DnD-T35u.mjs → build-WuxXRAqf.mjs} +2335 -2667
  68. package/dist/client/{build-DnD-T35u.mjs.map → build-WuxXRAqf.mjs.map} +1 -1
  69. package/dist/client/components/Breadcrumbs.d.ts +1 -0
  70. package/dist/client/components/ListToolbar/SortInput.d.ts +3 -0
  71. package/dist/client/context/BreadcrumbExtensionContext.d.ts +9 -0
  72. package/dist/client/context/DynamicBreadcrumbContext.d.ts +9 -0
  73. package/dist/client/{flavors-Cp0LEGOH.mjs → flavors-B0rbqffG.mjs} +3 -5
  74. package/dist/client/flavors-B0rbqffG.mjs.map +1 -0
  75. package/dist/client/flavors-DWMZ6TuJ.mjs.map +1 -1
  76. package/dist/client/flavors-Rl20bxVU.mjs +628 -0
  77. package/dist/client/flavors-Rl20bxVU.mjs.map +1 -0
  78. package/dist/client/floatingips-Cz9k80cc.mjs +8 -0
  79. package/dist/client/floatingips-Cz9k80cc.mjs.map +1 -0
  80. package/dist/client/floatingips-xbO_mu4f.mjs +576 -0
  81. package/dist/client/floatingips-xbO_mu4f.mjs.map +1 -0
  82. package/dist/client/hooks/useBreadcrumbs.d.ts +16 -0
  83. package/dist/client/hooks/usePushBreadcrumbs.d.ts +10 -0
  84. package/dist/client/hooks/useSetBreadcrumb.d.ts +11 -0
  85. package/dist/client/{hooks-CrriowRk.mjs → hooks-D0yKIumu.mjs} +2 -2
  86. package/dist/client/{hooks-CrriowRk.mjs.map → hooks-D0yKIumu.mjs.map} +1 -1
  87. package/dist/client/images-BGQv9kKT.mjs +1983 -0
  88. package/dist/client/images-BGQv9kKT.mjs.map +1 -0
  89. package/dist/client/{images-DWiM_72I.mjs → images-CPmMa4SQ.mjs} +3 -5
  90. package/dist/client/images-CPmMa4SQ.mjs.map +1 -0
  91. package/dist/client/images-NBf2bV43.mjs.map +1 -1
  92. package/dist/client/index.d.ts +9 -2
  93. package/dist/client/index.js +567 -695
  94. package/dist/client/index.js.map +1 -1
  95. package/dist/client/{md-DNzcRhmz.mjs → md-kvaGCNAK.mjs} +4 -22
  96. package/dist/client/{md-DNzcRhmz.mjs.map → md-kvaGCNAK.mjs.map} +1 -1
  97. package/dist/client/objects-BE_u5yRt.mjs +12950 -0
  98. package/dist/client/objects-BE_u5yRt.mjs.map +1 -0
  99. package/dist/client/objects-BN-59Th0.mjs +66 -0
  100. package/dist/client/objects-BN-59Th0.mjs.map +1 -0
  101. package/dist/client/objects-D9Luf9KB.mjs +66 -0
  102. package/dist/client/objects-D9Luf9KB.mjs.map +1 -0
  103. package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
  104. package/dist/client/routeInfo-DP3v74Wg.mjs +19 -0
  105. package/dist/client/routeInfo-DP3v74Wg.mjs.map +1 -0
  106. package/dist/client/router.d.ts +2 -1
  107. package/dist/client/{routes-B05u5bk4.mjs → routes-CJj7SR_K.mjs} +2 -2
  108. package/dist/client/routes-CJj7SR_K.mjs.map +1 -0
  109. package/dist/client/routes-xofA3ksU.mjs +110 -0
  110. package/dist/client/routes-xofA3ksU.mjs.map +1 -0
  111. package/dist/client/securitygroups-BjhgLBHm.mjs +620 -0
  112. package/dist/client/securitygroups-BjhgLBHm.mjs.map +1 -0
  113. package/dist/client/securitygroups-CtKne8UQ.mjs +8 -0
  114. package/dist/client/securitygroups-CtKne8UQ.mjs.map +1 -0
  115. package/dist/client/{securitygroups-_7SYN2jN.mjs → securitygroups-DEJQBcxm.mjs} +3 -5
  116. package/dist/client/securitygroups-DEJQBcxm.mjs.map +1 -0
  117. package/dist/client/services-D1PbooD1.mjs +6 -0
  118. package/dist/client/services-D1PbooD1.mjs.map +1 -0
  119. package/dist/client/services-DEMVtFyn.mjs +9 -0
  120. package/dist/client/services-DEMVtFyn.mjs.map +1 -0
  121. package/dist/client/trpcClient.d.ts +153 -370
  122. package/dist/client/useBreadcrumbs-ha3IlaxX.mjs +54 -0
  123. package/dist/client/useBreadcrumbs-ha3IlaxX.mjs.map +1 -0
  124. package/dist/client/useModalTracking-BcOKTYRN.mjs +33 -0
  125. package/dist/client/useModalTracking-BcOKTYRN.mjs.map +1 -0
  126. package/dist/client/{useSecurityGroupPermissions-qPwm4mFt.mjs → useSecurityGroupPermissions-BOyLQLdC.mjs} +78 -12
  127. package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs.map +1 -0
  128. package/dist/client/useSetBreadcrumb-tn7lBaQV.mjs +19 -0
  129. package/dist/client/useSetBreadcrumb-tn7lBaQV.mjs.map +1 -0
  130. package/dist/client/utils/formatSwiftDate.d.ts +30 -0
  131. package/dist/server/index.d.ts +179 -373
  132. package/dist/server/index.js +910 -530
  133. package/package.json +37 -38
  134. package/dist/client/AuthProvider-5TyZKZkx.mjs.map +0 -1
  135. package/dist/client/DeleteFlavorModal-C2K43ABZ.mjs +0 -732
  136. package/dist/client/DeleteFlavorModal-C2K43ABZ.mjs.map +0 -1
  137. package/dist/client/DeletePcaModal-D9v8E0Ki.mjs +0 -92
  138. package/dist/client/DeletePcaModal-D9v8E0Ki.mjs.map +0 -1
  139. package/dist/client/DetailsInfo-h7rPJ4Jf.mjs +0 -61
  140. package/dist/client/DetailsInfo-h7rPJ4Jf.mjs.map +0 -1
  141. package/dist/client/FloatingIpActionModals-BfEDfYg9.mjs +0 -417
  142. package/dist/client/FloatingIpActionModals-BfEDfYg9.mjs.map +0 -1
  143. package/dist/client/ImageToastNotifications-C0Tluzq-.mjs +0 -1125
  144. package/dist/client/ImageToastNotifications-C0Tluzq-.mjs.map +0 -1
  145. package/dist/client/RouteError-B-NPGIv7.mjs +0 -25
  146. package/dist/client/RouteError-B-NPGIv7.mjs.map +0 -1
  147. package/dist/client/SortInput-DysAXpB3.mjs.map +0 -1
  148. package/dist/client/StatusError-DX-GvLjq.mjs +0 -39
  149. package/dist/client/StatusError-DX-GvLjq.mjs.map +0 -1
  150. package/dist/client/_auth-R5H2yKFf.mjs +0 -11
  151. package/dist/client/_auth-R5H2yKFf.mjs.map +0 -1
  152. package/dist/client/_flavorId-Dit5mM8I.mjs +0 -210
  153. package/dist/client/_flavorId-Dit5mM8I.mjs.map +0 -1
  154. package/dist/client/_flavorId-Zj7LNL-R.mjs.map +0 -1
  155. package/dist/client/_floatingIpId-B0MCoqE3.mjs +0 -215
  156. package/dist/client/_floatingIpId-B0MCoqE3.mjs.map +0 -1
  157. package/dist/client/_floatingIpId-DCQQpNO-.mjs.map +0 -1
  158. package/dist/client/_imageId-CZYzBAVx.mjs +0 -558
  159. package/dist/client/_imageId-CZYzBAVx.mjs.map +0 -1
  160. package/dist/client/_pcaId-CHRRsWmO.mjs +0 -605
  161. package/dist/client/_pcaId-CHRRsWmO.mjs.map +0 -1
  162. package/dist/client/_projectId-B8wWSxPu.mjs +0 -98
  163. package/dist/client/_projectId-B8wWSxPu.mjs.map +0 -1
  164. package/dist/client/_projectId-C5DUYIjt.mjs +0 -291
  165. package/dist/client/_projectId-C5DUYIjt.mjs.map +0 -1
  166. package/dist/client/_projectId-D2pFfYIs.mjs +0 -46
  167. package/dist/client/_projectId-D2pFfYIs.mjs.map +0 -1
  168. package/dist/client/_projectId-DhSWowQo.mjs +0 -29
  169. package/dist/client/_projectId-DhSWowQo.mjs.map +0 -1
  170. package/dist/client/_securityGroupId-DZ4D4WwB.mjs +0 -1801
  171. package/dist/client/_securityGroupId-DZ4D4WwB.mjs.map +0 -1
  172. package/dist/client/_securityGroupId-Mj8NJT2-.mjs.map +0 -1
  173. package/dist/client/_storageType-C-9bNkmZ.mjs +0 -2211
  174. package/dist/client/_storageType-C-9bNkmZ.mjs.map +0 -1
  175. package/dist/client/components/Error/StatusError.d.ts +0 -11
  176. package/dist/client/components/ProjectView/ProjectInfoBox.d.ts +0 -12
  177. package/dist/client/flavors-Cp0LEGOH.mjs.map +0 -1
  178. package/dist/client/flavors-CwMbDRHm2.mjs +0 -650
  179. package/dist/client/flavors-CwMbDRHm2.mjs.map +0 -1
  180. package/dist/client/floatingips-ICwo-rV_.mjs +0 -591
  181. package/dist/client/floatingips-ICwo-rV_.mjs.map +0 -1
  182. package/dist/client/images-DOGZmr3D.mjs +0 -1937
  183. package/dist/client/images-DOGZmr3D.mjs.map +0 -1
  184. package/dist/client/images-DWiM_72I.mjs.map +0 -1
  185. package/dist/client/objects-D2MKUCxc.mjs +0 -56
  186. package/dist/client/objects-D2MKUCxc.mjs.map +0 -1
  187. package/dist/client/objects-DI1-tnKr.mjs +0 -56
  188. package/dist/client/objects-DI1-tnKr.mjs.map +0 -1
  189. package/dist/client/objects-DeK2WD5K.mjs +0 -10078
  190. package/dist/client/objects-DeK2WD5K.mjs.map +0 -1
  191. package/dist/client/pca-BokFv4Gz.mjs +0 -239
  192. package/dist/client/pca-BokFv4Gz.mjs.map +0 -1
  193. package/dist/client/pca-D5jHAl0b.mjs +0 -26
  194. package/dist/client/pca-D5jHAl0b.mjs.map +0 -1
  195. package/dist/client/pcaAccess-Br4kVjLQ.mjs +0 -9
  196. package/dist/client/pcaAccess-Br4kVjLQ.mjs.map +0 -1
  197. package/dist/client/routeInfo-CdTRlSxv.mjs +0 -32
  198. package/dist/client/routeInfo-CdTRlSxv.mjs.map +0 -1
  199. package/dist/client/routes-B05u5bk4.mjs.map +0 -1
  200. package/dist/client/routes-DOJr5onJ.mjs +0 -115
  201. package/dist/client/routes-DOJr5onJ.mjs.map +0 -1
  202. package/dist/client/securitygroups-Be2Qgmew.mjs +0 -595
  203. package/dist/client/securitygroups-Be2Qgmew.mjs.map +0 -1
  204. package/dist/client/securitygroups-_7SYN2jN.mjs.map +0 -1
  205. package/dist/client/useSecurityGroupPermissions-qPwm4mFt.mjs.map +0 -1
@@ -7,11 +7,7 @@ var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
9
  var __commonJS = (cb, mod) => function __require() {
10
- try {
11
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
12
- } catch (e) {
13
- throw mod = 0, e;
14
- }
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
11
  };
16
12
  var __export = (target, all) => {
17
13
  for (var name in all)
@@ -260,7 +256,7 @@ var require_error = __commonJS({
260
256
  }
261
257
  };
262
258
  exports2.SignalOpenstackError = SignalOpenstackError4;
263
- var SignalOpenstackApiError = class SignalOpenstackApiError extends Error {
259
+ var SignalOpenstackApiError2 = class SignalOpenstackApiError extends Error {
264
260
  static {
265
261
  __name(this, "SignalOpenstackApiError");
266
262
  }
@@ -271,7 +267,7 @@ var require_error = __commonJS({
271
267
  this.statusCode = statusCode;
272
268
  }
273
269
  };
274
- exports2.SignalOpenstackApiError = SignalOpenstackApiError;
270
+ exports2.SignalOpenstackApiError = SignalOpenstackApiError2;
275
271
  }
276
272
  });
277
273
 
@@ -27310,7 +27306,7 @@ var require_pathHelpers = __commonJS({
27310
27306
  });
27311
27307
  exports2.encodeOpenstackPathSegment = encodeOpenstackPathSegment2;
27312
27308
  exports2.encodeOpenstackPath = encodeOpenstackPath;
27313
- exports2.validateAndEncodeResourceId = validateAndEncodeResourceId7;
27309
+ exports2.validateAndEncodeResourceId = validateAndEncodeResourceId6;
27314
27310
  var error_1 = require_error();
27315
27311
  function encodeOpenstackPathSegment2(segment, label = "Path segment") {
27316
27312
  if (!segment || typeof segment !== "string") {
@@ -27332,10 +27328,10 @@ var require_pathHelpers = __commonJS({
27332
27328
  return segments.map((seg, idx) => encodeOpenstackPathSegment2(seg, `Path segment ${idx}`)).join("/");
27333
27329
  }
27334
27330
  __name(encodeOpenstackPath, "encodeOpenstackPath");
27335
- function validateAndEncodeResourceId7(id, resourceType = "Resource") {
27331
+ function validateAndEncodeResourceId6(id, resourceType = "Resource") {
27336
27332
  return encodeOpenstackPathSegment2(id, `${resourceType} ID`);
27337
27333
  }
27338
- __name(validateAndEncodeResourceId7, "validateAndEncodeResourceId");
27334
+ __name(validateAndEncodeResourceId6, "validateAndEncodeResourceId");
27339
27335
  }
27340
27336
  });
27341
27337
 
@@ -27346,7 +27342,7 @@ var require_esm = __commonJS({
27346
27342
  Object.defineProperty(exports2, "__esModule", {
27347
27343
  value: true
27348
27344
  });
27349
- exports2.validateAndEncodeResourceId = exports2.encodeOpenstackPath = exports2.encodeOpenstackPathSegment = exports2.redactSensitiveData = exports2.loggerConfig = exports2.logger = exports2.SignalOpenstackError = exports2.SignalOpenstackSession = void 0;
27345
+ exports2.validateAndEncodeResourceId = exports2.encodeOpenstackPath = exports2.encodeOpenstackPathSegment = exports2.redactSensitiveData = exports2.loggerConfig = exports2.logger = exports2.SignalOpenstackApiError = exports2.SignalOpenstackError = exports2.SignalOpenstackSession = void 0;
27350
27346
  var session_1 = require_session();
27351
27347
  Object.defineProperty(exports2, "SignalOpenstackSession", {
27352
27348
  enumerable: true,
@@ -27361,6 +27357,12 @@ var require_esm = __commonJS({
27361
27357
  return error_1.SignalOpenstackError;
27362
27358
  }, "get")
27363
27359
  });
27360
+ Object.defineProperty(exports2, "SignalOpenstackApiError", {
27361
+ enumerable: true,
27362
+ get: /* @__PURE__ */ __name(function() {
27363
+ return error_1.SignalOpenstackApiError;
27364
+ }, "get")
27365
+ });
27364
27366
  var logger_1 = require_logger();
27365
27367
  Object.defineProperty(exports2, "logger", {
27366
27368
  enumerable: true,
@@ -28569,10 +28571,12 @@ __export(server_exports, {
28569
28571
  createServer: () => createServer,
28570
28572
  domainScopedInputSchema: () => domainScopedInputSchema,
28571
28573
  domainScopedProcedure: () => domainScopedProcedure,
28574
+ parseOrThrow: () => parseOrThrow,
28572
28575
  projectScopedInputSchema: () => projectScopedInputSchema,
28573
28576
  projectScopedProcedure: () => projectScopedProcedure,
28574
28577
  protectedProcedure: () => protectedProcedure,
28575
- publicProcedure: () => publicProcedure
28578
+ publicProcedure: () => publicProcedure,
28579
+ validateOpenstackService: () => validateOpenstackService
28576
28580
  });
28577
28581
  module.exports = __toCommonJS(server_exports);
28578
28582
 
@@ -28591,11 +28595,69 @@ var import_zod2 = require("zod");
28591
28595
  // src/server/trpc.ts
28592
28596
  var import_server = require("@trpc/server");
28593
28597
  var import_zod = require("zod");
28598
+ var import_signal_openstack = __toESM(require_esm());
28594
28599
  var t = import_server.initTRPC.context().create();
28600
+ var openstackErrorMiddleware = t.middleware(async ({ next }) => {
28601
+ const result = await next();
28602
+ if (!result.ok) {
28603
+ const cause = result.error.cause;
28604
+ if (cause instanceof import_signal_openstack.SignalOpenstackApiError) {
28605
+ if (cause.statusCode === 401) {
28606
+ return {
28607
+ ...result,
28608
+ error: new import_server.TRPCError({
28609
+ code: "UNAUTHORIZED",
28610
+ message: "Session expired or invalid. Please log in again.",
28611
+ cause
28612
+ })
28613
+ };
28614
+ }
28615
+ if (cause.statusCode === 400) {
28616
+ return {
28617
+ ...result,
28618
+ error: new import_server.TRPCError({
28619
+ code: "BAD_REQUEST",
28620
+ message: "The OpenStack request was invalid.",
28621
+ cause
28622
+ })
28623
+ };
28624
+ }
28625
+ if (cause.statusCode === 404) {
28626
+ return {
28627
+ ...result,
28628
+ error: new import_server.TRPCError({
28629
+ code: "NOT_FOUND",
28630
+ message: "Resource not found or not accessible. This can happen if you switched domains in another tab.",
28631
+ cause
28632
+ })
28633
+ };
28634
+ }
28635
+ if (cause.statusCode === 403) {
28636
+ return {
28637
+ ...result,
28638
+ error: new import_server.TRPCError({
28639
+ code: "FORBIDDEN",
28640
+ message: "Access denied. You may not have the required role assignment.",
28641
+ cause
28642
+ })
28643
+ };
28644
+ }
28645
+ return {
28646
+ ...result,
28647
+ error: new import_server.TRPCError({
28648
+ code: "INTERNAL_SERVER_ERROR",
28649
+ message: "An unexpected OpenStack error occurred",
28650
+ cause
28651
+ })
28652
+ };
28653
+ }
28654
+ }
28655
+ return result;
28656
+ });
28595
28657
  var router = t.router;
28596
28658
  var auroraRouter = t.router;
28597
28659
  var mergeRouters = t.mergeRouters;
28598
- var publicProcedure = t.procedure;
28660
+ var publicProcedure = t.procedure.use(openstackErrorMiddleware);
28599
28661
  var createCallerFactory = t.createCallerFactory;
28600
28662
  var protectedProcedure = publicProcedure.use(/* @__PURE__ */ __name(async function isAuthenticated(opts) {
28601
28663
  if (opts.ctx.validateSession() === false) {
@@ -28688,11 +28750,20 @@ var discriminatedSchema = import_zod2.z.discriminatedUnion("type", [
28688
28750
  var sessionRouter = {
28689
28751
  getCurrentUserSession: publicProcedure.query(async ({ ctx }) => {
28690
28752
  const token = ctx.openstack?.getToken();
28691
- return token?.tokenData || null;
28692
- }),
28693
- getAuthToken: protectedProcedure.query(async ({ ctx }) => {
28694
- const token = ctx.openstack?.getToken();
28695
- return token?.authToken || null;
28753
+ if (!token) return null;
28754
+ return {
28755
+ user: token.tokenData.user,
28756
+ ...token.tokenData.expires_at && {
28757
+ expires_at: token.tokenData.expires_at
28758
+ },
28759
+ ...token.tokenData.issued_at && {
28760
+ issued_at: token.tokenData.issued_at
28761
+ },
28762
+ roles: token.tokenData.roles,
28763
+ project: token.tokenData.project,
28764
+ domain: token.tokenData.domain,
28765
+ catalog: token.tokenData.catalog
28766
+ };
28696
28767
  }),
28697
28768
  getCurrentScope: publicProcedure.query(async ({ ctx }) => {
28698
28769
  const token = ctx.openstack?.getToken();
@@ -28706,6 +28777,7 @@ var sessionRouter = {
28706
28777
  domain
28707
28778
  };
28708
28779
  }),
28780
+ // Errors from rescopeSession are handled by openstackErrorMiddleware
28709
28781
  setCurrentScope: protectedProcedure.input(discriminatedSchema).mutation(async ({ input, ctx }) => {
28710
28782
  switch (input.type) {
28711
28783
  case "domain": {
@@ -28713,9 +28785,15 @@ var sessionRouter = {
28713
28785
  domainId: input.domainId
28714
28786
  });
28715
28787
  const token = session?.getToken();
28788
+ if (!token?.tokenData.domain) {
28789
+ throw new import_server2.TRPCError({
28790
+ code: "NOT_FOUND",
28791
+ message: "Failed to rescope to the requested domain."
28792
+ });
28793
+ }
28716
28794
  return {
28717
28795
  project: null,
28718
- domain: token?.tokenData.domain
28796
+ domain: token.tokenData.domain
28719
28797
  };
28720
28798
  }
28721
28799
  case "project": {
@@ -28723,9 +28801,15 @@ var sessionRouter = {
28723
28801
  projectId: input.projectId
28724
28802
  });
28725
28803
  const token = session?.getToken();
28804
+ if (!token?.tokenData.project) {
28805
+ throw new import_server2.TRPCError({
28806
+ code: "NOT_FOUND",
28807
+ message: "Failed to rescope to the requested project."
28808
+ });
28809
+ }
28726
28810
  return {
28727
- project: token?.tokenData.project,
28728
- domain: token?.tokenData.project?.domain
28811
+ project: token.tokenData.project,
28812
+ domain: token.tokenData.project.domain
28729
28813
  };
28730
28814
  }
28731
28815
  case "unscoped": {
@@ -29848,7 +29932,8 @@ var imagesPaginatedResponseSchema = import_zod4.z.object({
29848
29932
  images: import_zod4.z.array(imageSchema),
29849
29933
  first: import_zod4.z.string().optional(),
29850
29934
  next: import_zod4.z.string().optional(),
29851
- schema: import_zod4.z.string().optional()
29935
+ schema: import_zod4.z.string().optional(),
29936
+ totalCount: import_zod4.z.number().optional()
29852
29937
  });
29853
29938
 
29854
29939
  // src/server/Compute/routers/imageRouter.ts
@@ -29863,22 +29948,26 @@ var imageRouter = {
29863
29948
  validateGlanceService(glance);
29864
29949
  const FRONTEND_PAGE_SIZE = 50;
29865
29950
  const OPENSTACK_PAGE_SIZE = 100;
29866
- const MIN_RESULTS_WHEN_SEARCHING = 50;
29867
29951
  const MAX_PAGES_TO_SEARCH = 1e3;
29868
29952
  const allImages = [];
29869
29953
  const hasSearchTerm = queryInput.name && queryInput.name.trim();
29870
29954
  const queryParams = new URLSearchParams();
29871
- const minimalQuery = {
29955
+ const apiQuery = {
29872
29956
  sort_key: queryInput.sort_key,
29873
29957
  sort_dir: queryInput.sort_dir,
29874
29958
  sort: queryInput.sort,
29875
29959
  limit: OPENSTACK_PAGE_SIZE,
29876
- marker
29960
+ // Only pass single-value filters to API (multi-value filters start with "in:")
29961
+ status: queryInput.status?.startsWith("in:") ? void 0 : queryInput.status,
29962
+ visibility: queryInput.visibility === "all" ? void 0 : queryInput.visibility,
29963
+ disk_format: queryInput.disk_format?.startsWith("in:") ? void 0 : queryInput.disk_format,
29964
+ container_format: queryInput.container_format?.startsWith("in:") ? void 0 : queryInput.container_format,
29965
+ protected: queryInput.protected,
29966
+ owner: queryInput.owner
29877
29967
  };
29878
- applyImageQueryParams(queryParams, minimalQuery);
29968
+ applyImageQueryParams(queryParams, apiQuery);
29879
29969
  let currentUrl = `v2/images?${queryParams.toString()}`;
29880
29970
  let pageCount = 0;
29881
- let nextMarker;
29882
29971
  while (currentUrl && pageCount < MAX_PAGES_TO_SEARCH) {
29883
29972
  const response = await glance.get(currentUrl).catch((error) => {
29884
29973
  throw mapErrorResponseToTRPCError(error, {
@@ -29891,41 +29980,7 @@ var imageRouter = {
29891
29980
  }
29892
29981
  allImages.push(...parsedData.data.images);
29893
29982
  pageCount++;
29894
- if (hasSearchTerm) {
29895
- let filteredSoFar = filterBySearchParams(allImages, queryInput.name, [
29896
- "name"
29897
- ]);
29898
- if (queryInput.visibility && queryInput.visibility !== "all") {
29899
- filteredSoFar = filteredSoFar.filter((img) => img.visibility === queryInput.visibility);
29900
- }
29901
- if (queryInput.status) {
29902
- const values = parseMultiValue(queryInput.status);
29903
- filteredSoFar = filteredSoFar.filter((img) => values.includes(img.status ?? ""));
29904
- }
29905
- if (queryInput.disk_format) {
29906
- const values = parseMultiValue(queryInput.disk_format);
29907
- filteredSoFar = filteredSoFar.filter((img) => values.includes(img.disk_format ?? ""));
29908
- }
29909
- if (queryInput.container_format) {
29910
- const values = parseMultiValue(queryInput.container_format);
29911
- filteredSoFar = filteredSoFar.filter((img) => values.includes(img.container_format ?? ""));
29912
- }
29913
- if (queryInput.protected !== void 0 && queryInput.protected !== null) {
29914
- const wantProtected = queryInput.protected === "true";
29915
- filteredSoFar = filteredSoFar.filter((img) => !!img.protected === wantProtected);
29916
- }
29917
- if (queryInput.owner) {
29918
- filteredSoFar = filteredSoFar.filter((img) => img.owner === queryInput.owner);
29919
- }
29920
- if (filteredSoFar.length >= MIN_RESULTS_WHEN_SEARCHING) {
29921
- nextMarker = parsedData.data.next;
29922
- break;
29923
- }
29924
- }
29925
- if (!hasSearchTerm) {
29926
- nextMarker = parsedData.data.next;
29927
- break;
29928
- }
29983
+ validateRelativeUrl(parsedData.data.next, "pagination URL");
29929
29984
  currentUrl = parsedData.data.next;
29930
29985
  }
29931
29986
  let filteredImages = allImages;
@@ -29956,16 +30011,21 @@ var imageRouter = {
29956
30011
  if (queryInput.owner) {
29957
30012
  filteredImages = filteredImages.filter((img) => img.owner === queryInput.owner);
29958
30013
  }
29959
- const startIndex = 0;
29960
- const endIndex = FRONTEND_PAGE_SIZE;
30014
+ let startIndex = 0;
30015
+ if (marker) {
30016
+ const markerIndex = filteredImages.findIndex((img) => img.id === marker);
30017
+ startIndex = markerIndex >= 0 ? markerIndex + 1 : 0;
30018
+ }
30019
+ const endIndex = startIndex + FRONTEND_PAGE_SIZE;
29961
30020
  const paginatedImages = filteredImages.slice(startIndex, endIndex);
29962
- const hasMore = filteredImages.length > FRONTEND_PAGE_SIZE || !!nextMarker;
29963
- const nextPageMarker = filteredImages.length > FRONTEND_PAGE_SIZE ? filteredImages[FRONTEND_PAGE_SIZE - 1]?.id : nextMarker;
30021
+ const hasMore = endIndex < filteredImages.length;
30022
+ const nextPageMarker = hasMore ? filteredImages[endIndex - 1]?.id : void 0;
29964
30023
  return {
29965
30024
  images: paginatedImages,
29966
30025
  first: void 0,
29967
30026
  next: hasMore ? nextPageMarker : void 0,
29968
- schema: "/v2/schemas/images"
30027
+ schema: "/v2/schemas/images",
30028
+ totalCount: filteredImages.length
29969
30029
  };
29970
30030
  }, "list images");
29971
30031
  }),
@@ -30101,16 +30161,25 @@ var imageRouter = {
30101
30161
  validateGlanceService(glance);
30102
30162
  const fileStream = import_node_stream.Readable.fromWeb(input);
30103
30163
  const { validatedImageId, validatedFileSize, validatedFile } = validateUploadInput(imageId, fileSize, fileStream);
30104
- uploadProgress.set(validatedImageId, {
30164
+ const token = openstackSession.getToken();
30165
+ const tokenProjectId = token?.tokenData.project?.id;
30166
+ if (!tokenProjectId) {
30167
+ throw new import_server6.TRPCError({
30168
+ code: "UNAUTHORIZED",
30169
+ message: "Project scope required for upload progress tracking"
30170
+ });
30171
+ }
30172
+ const scopedUploadId = `${tokenProjectId}:${validatedImageId}`;
30173
+ uploadProgress.set(scopedUploadId, {
30105
30174
  uploaded: 0,
30106
30175
  total: validatedFileSize
30107
30176
  });
30108
30177
  try {
30109
- const progress = uploadProgress.get(validatedImageId);
30178
+ const progress = uploadProgress.get(scopedUploadId);
30110
30179
  const progressTracker = new import_node_stream.Transform({
30111
30180
  transform(chunk, _encoding, callback) {
30112
30181
  progress.uploaded += chunk.length;
30113
- uploadProgressEmitter.emit(`progress:${validatedImageId}`, {
30182
+ uploadProgressEmitter.emit(`progress:${scopedUploadId}`, {
30114
30183
  uploaded: progress.uploaded,
30115
30184
  total: progress.total,
30116
30185
  percent: progress.total > 0 ? Math.round(progress.uploaded / progress.total * 100) : 0
@@ -30144,24 +30213,39 @@ var imageRouter = {
30144
30213
  progressTracker.destroy();
30145
30214
  throw ImageErrorHandlers.upload(uploadResponse, validatedImageId, "application/octet-stream");
30146
30215
  }
30147
- uploadProgressEmitter.emit(`progress:${validatedImageId}:complete`);
30216
+ uploadProgressEmitter.emit(`progress:${scopedUploadId}:complete`);
30148
30217
  return {
30149
30218
  success: true,
30150
30219
  imageId: validatedImageId
30151
30220
  };
30152
30221
  } catch (error) {
30153
- uploadProgressEmitter.emit(`progress:${validatedImageId}:error`, error);
30222
+ uploadProgressEmitter.emit(`progress:${scopedUploadId}:error`, error);
30154
30223
  throw ImageErrorHandlers.upload(error, validatedImageId, "application/octet-stream");
30155
30224
  } finally {
30156
- uploadProgress.delete(validatedImageId);
30225
+ uploadProgress.delete(scopedUploadId);
30157
30226
  }
30158
30227
  }, "upload image");
30159
30228
  }),
30160
30229
  watchUploadProgress: projectScopedProcedure.input(import_zod5.z.object({
30161
30230
  uploadId: import_zod5.z.string()
30162
- })).subscription(async function* ({ input }) {
30231
+ })).subscription(async function* ({ input, ctx }) {
30163
30232
  const uploadId = input.uploadId;
30164
- const current = uploadProgress.get(uploadId);
30233
+ if (uploadId.includes(":")) {
30234
+ throw new import_server6.TRPCError({
30235
+ code: "BAD_REQUEST",
30236
+ message: "Invalid uploadId format"
30237
+ });
30238
+ }
30239
+ const token = ctx.openstack?.getToken();
30240
+ const projectId = token?.tokenData.project?.id;
30241
+ if (!projectId) {
30242
+ throw new import_server6.TRPCError({
30243
+ code: "UNAUTHORIZED",
30244
+ message: "Project scope required for upload progress tracking"
30245
+ });
30246
+ }
30247
+ const scopedUploadId = `${projectId}:${uploadId}`;
30248
+ const current = uploadProgress.get(scopedUploadId);
30165
30249
  if (current) {
30166
30250
  yield {
30167
30251
  ...current,
@@ -30189,9 +30273,9 @@ var imageRouter = {
30189
30273
  waitResolver?.();
30190
30274
  waitResolver = null;
30191
30275
  }, "onError");
30192
- uploadProgressEmitter.on(`progress:${uploadId}`, onProgress);
30193
- uploadProgressEmitter.on(`progress:${uploadId}:complete`, onComplete);
30194
- uploadProgressEmitter.on(`progress:${uploadId}:error`, onError);
30276
+ uploadProgressEmitter.on(`progress:${scopedUploadId}`, onProgress);
30277
+ uploadProgressEmitter.on(`progress:${scopedUploadId}:complete`, onComplete);
30278
+ uploadProgressEmitter.on(`progress:${scopedUploadId}:error`, onError);
30195
30279
  try {
30196
30280
  while (!isComplete && !isError) {
30197
30281
  while (queue.length > 0) {
@@ -30218,9 +30302,9 @@ var imageRouter = {
30218
30302
  throw error;
30219
30303
  }
30220
30304
  } finally {
30221
- uploadProgressEmitter.off(`progress:${uploadId}`, onProgress);
30222
- uploadProgressEmitter.off(`progress:${uploadId}:complete`, onComplete);
30223
- uploadProgressEmitter.off(`progress:${uploadId}:error`, onError);
30305
+ uploadProgressEmitter.off(`progress:${scopedUploadId}`, onProgress);
30306
+ uploadProgressEmitter.off(`progress:${scopedUploadId}:complete`, onComplete);
30307
+ uploadProgressEmitter.off(`progress:${scopedUploadId}:error`, onError);
30224
30308
  }
30225
30309
  }),
30226
30310
  updateImage: projectScopedProcedure.input(updateImageInputSchema).mutation(async ({ input, ctx }) => {
@@ -30761,7 +30845,7 @@ var ERROR_CODES = {
30761
30845
  };
30762
30846
 
30763
30847
  // src/server/Compute/helpers/flavorHelpers.ts
30764
- var import_signal_openstack = __toESM(require_esm());
30848
+ var import_signal_openstack2 = __toESM(require_esm());
30765
30849
  function isErrorWithStatus(error) {
30766
30850
  return typeof error === "object" && error !== null && ("statusCode" in error || "status" in error);
30767
30851
  }
@@ -31116,9 +31200,9 @@ async function getFlavorById(compute, flavorId) {
31116
31200
  }
31117
31201
  let encodedId;
31118
31202
  try {
31119
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31203
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31120
31204
  } catch (error) {
31121
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31205
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31122
31206
  throw new import_server7.TRPCError({
31123
31207
  code: "BAD_REQUEST",
31124
31208
  message: ERROR_CODES.GET_FLAVOR_DETAILS_INVALID_ID,
@@ -31232,9 +31316,9 @@ async function deleteFlavor(compute, flavorId) {
31232
31316
  }
31233
31317
  let encodedId;
31234
31318
  try {
31235
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31319
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31236
31320
  } catch (error) {
31237
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31321
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31238
31322
  throw new import_server7.TRPCError({
31239
31323
  code: "BAD_REQUEST",
31240
31324
  message: ERROR_CODES.DELETE_FLAVOR_INVALID_ID,
@@ -31263,9 +31347,9 @@ __name(deleteFlavor, "deleteFlavor");
31263
31347
  async function createExtraSpecs(compute, flavorId, extra_specs) {
31264
31348
  let encodedId;
31265
31349
  try {
31266
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31350
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31267
31351
  } catch (error) {
31268
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31352
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31269
31353
  throw new import_server7.TRPCError({
31270
31354
  code: "BAD_REQUEST",
31271
31355
  message: ERROR_CODES.CREATE_EXTRA_SPECS_FAILED,
@@ -31303,9 +31387,9 @@ __name(createExtraSpecs, "createExtraSpecs");
31303
31387
  async function getExtraSpecs(compute, flavorId) {
31304
31388
  let encodedId;
31305
31389
  try {
31306
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31390
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31307
31391
  } catch (error) {
31308
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31392
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31309
31393
  throw new import_server7.TRPCError({
31310
31394
  code: "BAD_REQUEST",
31311
31395
  message: ERROR_CODES.GET_EXTRA_SPECS_FAILED,
@@ -31341,10 +31425,10 @@ __name(getExtraSpecs, "getExtraSpecs");
31341
31425
  async function deleteExtraSpec(compute, flavorId, key) {
31342
31426
  let encodedId, encodedKey;
31343
31427
  try {
31344
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31345
- encodedKey = (0, import_signal_openstack.encodeOpenstackPathSegment)(key, "Extra spec key");
31428
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31429
+ encodedKey = (0, import_signal_openstack2.encodeOpenstackPathSegment)(key, "Extra spec key");
31346
31430
  } catch (error) {
31347
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31431
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31348
31432
  throw new import_server7.TRPCError({
31349
31433
  code: "BAD_REQUEST",
31350
31434
  message: ERROR_CODES.DELETE_EXTRA_SPEC_FAILED,
@@ -31369,9 +31453,9 @@ __name(deleteExtraSpec, "deleteExtraSpec");
31369
31453
  async function getFlavorAccess(compute, flavorId) {
31370
31454
  let encodedId;
31371
31455
  try {
31372
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31456
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31373
31457
  } catch (error) {
31374
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31458
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31375
31459
  throw new import_server7.TRPCError({
31376
31460
  code: "BAD_REQUEST",
31377
31461
  message: ERROR_CODES.GET_FLAVOR_ACCESS_FAILED,
@@ -31407,9 +31491,9 @@ __name(getFlavorAccess, "getFlavorAccess");
31407
31491
  async function addTenantAccess(compute, flavorId, tenantId) {
31408
31492
  let encodedId;
31409
31493
  try {
31410
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31494
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31411
31495
  } catch (error) {
31412
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31496
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31413
31497
  throw new import_server7.TRPCError({
31414
31498
  code: "BAD_REQUEST",
31415
31499
  message: ERROR_CODES.ADD_TENANT_ACCESS_FAILED,
@@ -31450,9 +31534,9 @@ __name(addTenantAccess, "addTenantAccess");
31450
31534
  async function removeTenantAccess(compute, flavorId, tenantId) {
31451
31535
  let encodedId;
31452
31536
  try {
31453
- encodedId = (0, import_signal_openstack.validateAndEncodeResourceId)(flavorId, "Flavor");
31537
+ encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31454
31538
  } catch (error) {
31455
- if (error instanceof import_signal_openstack.SignalOpenstackError) {
31539
+ if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31456
31540
  throw new import_server7.TRPCError({
31457
31541
  code: "BAD_REQUEST",
31458
31542
  message: ERROR_CODES.REMOVE_TENANT_ACCESS_FAILED,
@@ -31493,7 +31577,7 @@ __name(removeTenantAccess, "removeTenantAccess");
31493
31577
 
31494
31578
  // src/server/Compute/routers/flavorRouter.ts
31495
31579
  var import_server8 = require("@trpc/server");
31496
- var import_signal_openstack2 = __toESM(require_esm());
31580
+ var import_signal_openstack3 = __toESM(require_esm());
31497
31581
  var flavorRouter = {
31498
31582
  getFlavorById: projectScopedProcedure.input(import_zod9.z.object({
31499
31583
  project_id: import_zod9.z.string(),
@@ -31738,9 +31822,9 @@ var flavorRouter = {
31738
31822
  }
31739
31823
  let encodedId;
31740
31824
  try {
31741
- encodedId = (0, import_signal_openstack2.validateAndEncodeResourceId)(flavorId, "Flavor");
31825
+ encodedId = (0, import_signal_openstack3.validateAndEncodeResourceId)(flavorId, "Flavor");
31742
31826
  } catch (error) {
31743
- if (error instanceof import_signal_openstack2.SignalOpenstackError) {
31827
+ if (error instanceof import_signal_openstack3.SignalOpenstackError) {
31744
31828
  throw new import_server8.TRPCError({
31745
31829
  code: "BAD_REQUEST",
31746
31830
  message: ERROR_CODES.GET_FLAVOR_ACCESS_FAILED,
@@ -34410,7 +34494,7 @@ var cephUploadProcedure = protectedProcedure.use(/* @__PURE__ */ __name(async fu
34410
34494
 
34411
34495
  // src/server/Storage/helpers/s3ErrorMapper.ts
34412
34496
  var import_server13 = require("@trpc/server");
34413
- var import_signal_openstack3 = __toESM(require_esm());
34497
+ var import_signal_openstack4 = __toESM(require_esm());
34414
34498
  var S3_ERROR_MAP = {
34415
34499
  NoSuchBucket: "NOT_FOUND",
34416
34500
  NoSuchKey: "NOT_FOUND",
@@ -34418,6 +34502,7 @@ var S3_ERROR_MAP = {
34418
34502
  NoSuchVersion: "NOT_FOUND",
34419
34503
  NoSuchBucketPolicy: "NOT_FOUND",
34420
34504
  NoSuchCORSConfiguration: "NOT_FOUND",
34505
+ NoSuchLifecycleConfiguration: "NOT_FOUND",
34421
34506
  BucketAlreadyExists: "CONFLICT",
34422
34507
  BucketAlreadyOwnedByYou: "CONFLICT",
34423
34508
  BucketNotEmpty: "PRECONDITION_FAILED",
@@ -34447,7 +34532,7 @@ function mapS3ErrorToTRPCError(error, context) {
34447
34532
  const errorCode = s3Error.Code ?? s3Error.name ?? "";
34448
34533
  const trpcCode = S3_ERROR_MAP[errorCode] ?? "INTERNAL_SERVER_ERROR";
34449
34534
  if (!S3_ERROR_MAP[errorCode] && errorCode) {
34450
- import_signal_openstack3.logger.warn("Unmapped S3 error code", {
34535
+ import_signal_openstack4.logger.warn("Unmapped S3 error code", {
34451
34536
  errorCode,
34452
34537
  operation: context.operation,
34453
34538
  errorName: s3Error.name
@@ -34873,6 +34958,187 @@ var setCorsInputSchema = projectScopedInputSchema.extend({
34873
34958
  var deleteCorsInputSchema = projectScopedInputSchema.extend({
34874
34959
  bucketName: existingBucketNameSchema
34875
34960
  });
34961
+ var lifecycleRuleStatusSchema = import_zod13.z.enum([
34962
+ "Enabled",
34963
+ "Disabled"
34964
+ ]);
34965
+ var lifecycleExpirationSchema = import_zod13.z.object({
34966
+ Days: import_zod13.z.number().int().min(1).max(3650).optional(),
34967
+ Date: import_zod13.z.string().datetime({
34968
+ offset: true
34969
+ }).optional(),
34970
+ ExpiredObjectDeleteMarker: import_zod13.z.boolean().optional()
34971
+ }).refine((val) => {
34972
+ return val.Days !== void 0 || val.Date !== void 0 || val.ExpiredObjectDeleteMarker !== void 0;
34973
+ }, "Expiration must specify either Days, Date, or ExpiredObjectDeleteMarker").refine((val) => {
34974
+ return !(val.Days !== void 0 && val.Date !== void 0);
34975
+ }, "Expiration cannot specify both Days and Date").refine((val) => !(val.ExpiredObjectDeleteMarker !== void 0 && (val.Days !== void 0 || val.Date !== void 0)), "ExpiredObjectDeleteMarker cannot be combined with Days or Date");
34976
+ var lifecycleTransitionSchema = import_zod13.z.object({
34977
+ Days: import_zod13.z.number().int().min(1).optional(),
34978
+ Date: import_zod13.z.string().datetime({
34979
+ offset: true
34980
+ }).optional(),
34981
+ StorageClass: import_zod13.z.string().min(1)
34982
+ }).refine((val) => {
34983
+ return val.Days !== void 0 !== (val.Date !== void 0);
34984
+ }, "Transition must specify exactly one of Days or Date");
34985
+ var lifecycleNoncurrentVersionExpirationSchema = import_zod13.z.object({
34986
+ NoncurrentDays: import_zod13.z.number().int().min(1),
34987
+ NewerNoncurrentVersions: import_zod13.z.number().int().min(1).optional()
34988
+ });
34989
+ var lifecycleNoncurrentVersionTransitionSchema = import_zod13.z.object({
34990
+ NoncurrentDays: import_zod13.z.number().int().min(1),
34991
+ StorageClass: import_zod13.z.string().min(1),
34992
+ NewerNoncurrentVersions: import_zod13.z.number().int().min(1).optional()
34993
+ });
34994
+ var lifecycleAbortIncompleteMultipartUploadSchema = import_zod13.z.object({
34995
+ DaysAfterInitiation: import_zod13.z.number().int().min(1)
34996
+ });
34997
+ var lifecycleTagSchema = import_zod13.z.object({
34998
+ Key: import_zod13.z.string().min(1).max(128),
34999
+ Value: import_zod13.z.string().max(256)
35000
+ });
35001
+ var lifecycleFilterAndSchema = import_zod13.z.object({
35002
+ Prefix: import_zod13.z.string().optional(),
35003
+ Tags: import_zod13.z.array(lifecycleTagSchema).optional(),
35004
+ ObjectSizeGreaterThan: import_zod13.z.number().int().min(0).optional(),
35005
+ ObjectSizeLessThan: import_zod13.z.number().int().min(0).optional()
35006
+ }).refine((val) => {
35007
+ const predicateCount = (val.Prefix !== void 0 && val.Prefix !== "" ? 1 : 0) + (val.Tags?.length ?? 0) + (val.ObjectSizeGreaterThan !== void 0 ? 1 : 0) + (val.ObjectSizeLessThan !== void 0 ? 1 : 0);
35008
+ return predicateCount >= 2;
35009
+ }, {
35010
+ message: "And filter must contain at least 2 predicates"
35011
+ });
35012
+ var lifecycleFilterSchema = import_zod13.z.object({
35013
+ Prefix: import_zod13.z.string().optional(),
35014
+ Tag: lifecycleTagSchema.optional(),
35015
+ ObjectSizeGreaterThan: import_zod13.z.number().int().min(0).optional(),
35016
+ ObjectSizeLessThan: import_zod13.z.number().int().min(0).optional(),
35017
+ And: lifecycleFilterAndSchema.optional()
35018
+ }).refine((val) => {
35019
+ const topLevelConditions = [
35020
+ val.Prefix !== void 0,
35021
+ val.Tag !== void 0,
35022
+ val.ObjectSizeGreaterThan !== void 0,
35023
+ val.ObjectSizeLessThan !== void 0
35024
+ ].filter(Boolean).length;
35025
+ if (topLevelConditions > 1) {
35026
+ return false;
35027
+ }
35028
+ if (val.And && topLevelConditions > 0) {
35029
+ return false;
35030
+ }
35031
+ return true;
35032
+ }, {
35033
+ message: "Multiple filter conditions (Prefix, Tag, ObjectSize) must be wrapped in an And clause"
35034
+ });
35035
+ var lifecycleRuleSchema = import_zod13.z.object({
35036
+ ID: import_zod13.z.string().max(255, "Rule ID must be at most 255 characters").optional(),
35037
+ Status: lifecycleRuleStatusSchema,
35038
+ Prefix: import_zod13.z.string().optional(),
35039
+ Filter: lifecycleFilterSchema.optional(),
35040
+ Expiration: lifecycleExpirationSchema.optional(),
35041
+ Transitions: import_zod13.z.array(lifecycleTransitionSchema).optional(),
35042
+ NoncurrentVersionExpiration: lifecycleNoncurrentVersionExpirationSchema.optional(),
35043
+ NoncurrentVersionTransitions: import_zod13.z.array(lifecycleNoncurrentVersionTransitionSchema).optional(),
35044
+ AbortIncompleteMultipartUpload: lifecycleAbortIncompleteMultipartUploadSchema.optional()
35045
+ }).refine((val) => {
35046
+ return val.Expiration !== void 0 || val.Transitions !== void 0 && val.Transitions.length > 0 || val.NoncurrentVersionExpiration !== void 0 || val.NoncurrentVersionTransitions !== void 0 && val.NoncurrentVersionTransitions.length > 0 || val.AbortIncompleteMultipartUpload !== void 0;
35047
+ }, {
35048
+ message: "Rule must have at least one action (Expiration, Transition, NoncurrentVersion, or AbortIncompleteMultipartUpload)"
35049
+ }).refine((val) => {
35050
+ return !(val.Filter !== void 0 && val.Prefix !== void 0);
35051
+ }, {
35052
+ message: "Rule cannot have both Filter and legacy Prefix field set (use Filter.Prefix instead)"
35053
+ }).refine((val) => {
35054
+ if (val.Expiration?.ExpiredObjectDeleteMarker !== true) {
35055
+ return true;
35056
+ }
35057
+ const hasTagFilter = val.Filter?.Tag !== void 0 || val.Filter?.And?.Tags !== void 0 && val.Filter.And.Tags.length > 0;
35058
+ return !hasTagFilter;
35059
+ }, {
35060
+ message: "ExpiredObjectDeleteMarker cannot be combined with tag-based filters"
35061
+ }).refine((val) => {
35062
+ if (val.AbortIncompleteMultipartUpload === void 0) return true;
35063
+ const hasTagFilter = val.Filter?.Tag !== void 0 || val.Filter?.And?.Tags !== void 0 && val.Filter.And.Tags.length > 0;
35064
+ return !hasTagFilter;
35065
+ }, {
35066
+ message: "AbortIncompleteMultipartUpload cannot be combined with tag-based filters"
35067
+ });
35068
+ var lifecycleRuleReadSchema = import_zod13.z.object({
35069
+ ID: import_zod13.z.string().optional(),
35070
+ Status: import_zod13.z.string(),
35071
+ Prefix: import_zod13.z.string().optional(),
35072
+ Filter: import_zod13.z.object({
35073
+ Prefix: import_zod13.z.string().optional(),
35074
+ Tag: import_zod13.z.object({
35075
+ Key: import_zod13.z.string(),
35076
+ Value: import_zod13.z.string()
35077
+ }).optional(),
35078
+ ObjectSizeGreaterThan: import_zod13.z.number().optional(),
35079
+ ObjectSizeLessThan: import_zod13.z.number().optional(),
35080
+ And: import_zod13.z.object({
35081
+ Prefix: import_zod13.z.string().optional(),
35082
+ Tags: import_zod13.z.array(import_zod13.z.object({
35083
+ Key: import_zod13.z.string(),
35084
+ Value: import_zod13.z.string()
35085
+ })).optional(),
35086
+ ObjectSizeGreaterThan: import_zod13.z.number().optional(),
35087
+ ObjectSizeLessThan: import_zod13.z.number().optional()
35088
+ }).optional()
35089
+ }).passthrough().optional(),
35090
+ Expiration: import_zod13.z.object({
35091
+ Days: import_zod13.z.number().optional(),
35092
+ Date: import_zod13.z.union([
35093
+ import_zod13.z.string(),
35094
+ import_zod13.z.date()
35095
+ ]).optional(),
35096
+ ExpiredObjectDeleteMarker: import_zod13.z.boolean().optional()
35097
+ }).passthrough().optional(),
35098
+ Transitions: import_zod13.z.array(import_zod13.z.object({
35099
+ Days: import_zod13.z.number().optional(),
35100
+ Date: import_zod13.z.union([
35101
+ import_zod13.z.string(),
35102
+ import_zod13.z.date()
35103
+ ]).optional(),
35104
+ StorageClass: import_zod13.z.string()
35105
+ }).passthrough()).optional(),
35106
+ NoncurrentVersionExpiration: import_zod13.z.object({
35107
+ NoncurrentDays: import_zod13.z.number().optional(),
35108
+ NewerNoncurrentVersions: import_zod13.z.number().optional()
35109
+ }).passthrough().optional(),
35110
+ NoncurrentVersionTransitions: import_zod13.z.array(import_zod13.z.object({
35111
+ NoncurrentDays: import_zod13.z.number().optional(),
35112
+ StorageClass: import_zod13.z.string(),
35113
+ NewerNoncurrentVersions: import_zod13.z.number().optional()
35114
+ }).passthrough()).optional(),
35115
+ AbortIncompleteMultipartUpload: import_zod13.z.object({
35116
+ DaysAfterInitiation: import_zod13.z.number().optional()
35117
+ }).passthrough().optional()
35118
+ });
35119
+ var lifecycleConfigurationSchema = import_zod13.z.object({
35120
+ Rules: import_zod13.z.array(lifecycleRuleSchema).min(1, "At least one lifecycle rule is required").max(100, "Maximum 100 lifecycle rules per bucket")
35121
+ }).refine((val) => {
35122
+ const ids = val.Rules.map((r) => r.ID).filter((id) => id !== void 0 && id !== "");
35123
+ const uniqueIds = new Set(ids);
35124
+ return ids.length === uniqueIds.size;
35125
+ }, {
35126
+ message: "Rule IDs must be unique within a lifecycle configuration"
35127
+ });
35128
+ var getLifecycleInputSchema = projectScopedInputSchema.extend({
35129
+ bucketName: existingBucketNameSchema
35130
+ });
35131
+ var getLifecycleOutputSchema = import_zod13.z.object({
35132
+ rules: import_zod13.z.array(lifecycleRuleReadSchema).nullable(),
35133
+ skippedRuleCount: import_zod13.z.number().int().min(0)
35134
+ });
35135
+ var setLifecycleInputSchema = projectScopedInputSchema.extend({
35136
+ bucketName: existingBucketNameSchema,
35137
+ lifecycleConfiguration: lifecycleConfigurationSchema
35138
+ });
35139
+ var deleteLifecycleInputSchema = projectScopedInputSchema.extend({
35140
+ bucketName: existingBucketNameSchema
35141
+ });
34876
35142
 
34877
35143
  // src/server/Storage/routers/ceph/containerRouter.ts
34878
35144
  var containerRouter = {
@@ -36297,20 +36563,60 @@ var ec2CredentialRouter = {
36297
36563
  }),
36298
36564
  /**
36299
36565
  * Deletes an EC2 credential by ID.
36566
+ * Verifies ownership before deletion to prevent IDOR attacks.
36300
36567
  */
36301
36568
  delete: projectScopedProcedure.input(projectScopedInputSchema.extend({
36302
36569
  credentialId: import_zod15.z.string().min(1)
36303
36570
  })).mutation(async ({ ctx, input }) => {
36304
36571
  const userId = ctx.openstack.getToken()?.tokenData.user?.id;
36572
+ const projectId = ctx.openstack.getToken()?.tokenData.project?.id;
36305
36573
  if (!userId) {
36306
36574
  throw new import_server15.TRPCError({
36307
36575
  code: "UNAUTHORIZED",
36308
36576
  message: "User ID not found in token"
36309
36577
  });
36310
36578
  }
36579
+ if (!projectId) {
36580
+ throw new import_server15.TRPCError({
36581
+ code: "UNAUTHORIZED",
36582
+ message: "Project ID not found in token"
36583
+ });
36584
+ }
36311
36585
  const identityService = ctx.openstack.service("identity");
36312
- const response = await identityService.del(`credentials/${input.credentialId}`);
36313
- if (!response.ok && response.status !== 404) {
36586
+ const getResponse = await identityService.get(`credentials/${input.credentialId}`);
36587
+ if (!getResponse.ok) {
36588
+ if (getResponse.status === 404) {
36589
+ return {
36590
+ success: true
36591
+ };
36592
+ }
36593
+ if (getResponse.status === 401) {
36594
+ throw new import_server15.TRPCError({
36595
+ code: "UNAUTHORIZED",
36596
+ message: "Authentication failed"
36597
+ });
36598
+ }
36599
+ if (getResponse.status === 403) {
36600
+ throw new import_server15.TRPCError({
36601
+ code: "FORBIDDEN",
36602
+ message: "Access denied"
36603
+ });
36604
+ }
36605
+ throw new import_server15.TRPCError({
36606
+ code: "INTERNAL_SERVER_ERROR",
36607
+ message: "Failed to fetch credential for verification"
36608
+ });
36609
+ }
36610
+ const credentialData = await getResponse.json();
36611
+ const credential = credentialData.credential;
36612
+ if (credential.user_id !== userId || credential.project_id !== projectId) {
36613
+ throw new import_server15.TRPCError({
36614
+ code: "NOT_FOUND",
36615
+ message: "Credential not found"
36616
+ });
36617
+ }
36618
+ const deleteResponse = await identityService.del(`credentials/${input.credentialId}`);
36619
+ if (!deleteResponse.ok && deleteResponse.status !== 404) {
36314
36620
  throw new import_server15.TRPCError({
36315
36621
  code: "INTERNAL_SERVER_ERROR",
36316
36622
  message: "Failed to delete EC2 credential"
@@ -36745,17 +37051,18 @@ function checkPolicySetRateLimit(bucketName, projectId) {
36745
37051
  const key = `${projectId}:${bucketName}`;
36746
37052
  const now = Date.now();
36747
37053
  const windowMs = 5 * 60 * 1e3;
36748
- for (const [k, v] of policySetRateLimits.entries()) {
36749
- if (now > v.resetAt) {
36750
- policySetRateLimits.delete(k);
36751
- }
36752
- }
36753
37054
  const limit = policySetRateLimits.get(key);
36754
37055
  if (!limit || now > limit.resetAt) {
36755
37056
  policySetRateLimits.set(key, {
36756
37057
  count: 1,
36757
37058
  resetAt: now + windowMs
36758
37059
  });
37060
+ setTimeout(() => {
37061
+ const current = policySetRateLimits.get(key);
37062
+ if (current && current.resetAt <= Date.now()) {
37063
+ policySetRateLimits.delete(key);
37064
+ }
37065
+ }, windowMs).unref();
36759
37066
  return;
36760
37067
  }
36761
37068
  if (limit.count >= 10) {
@@ -36973,17 +37280,18 @@ function checkCorsSetRateLimit(bucketName, projectId) {
36973
37280
  const key = `${projectId}:${bucketName}`;
36974
37281
  const now = Date.now();
36975
37282
  const windowMs = 60 * 1e3;
36976
- for (const [k, v] of corsSetRateLimits.entries()) {
36977
- if (now > v.resetAt) {
36978
- corsSetRateLimits.delete(k);
36979
- }
36980
- }
36981
37283
  const limit = corsSetRateLimits.get(key);
36982
37284
  if (!limit || now > limit.resetAt) {
36983
37285
  corsSetRateLimits.set(key, {
36984
37286
  count: 1,
36985
37287
  resetAt: now + windowMs
36986
37288
  });
37289
+ setTimeout(() => {
37290
+ const current = corsSetRateLimits.get(key);
37291
+ if (current && current.resetAt <= Date.now()) {
37292
+ corsSetRateLimits.delete(key);
37293
+ }
37294
+ }, windowMs).unref();
36987
37295
  return;
36988
37296
  }
36989
37297
  if (limit.count >= 10) {
@@ -37102,6 +37410,274 @@ var corsRouter = {
37102
37410
  })
37103
37411
  };
37104
37412
 
37413
+ // src/server/Storage/routers/ceph/lifecycleRouter.ts
37414
+ var import_client_s37 = require("@aws-sdk/client-s3");
37415
+ var import_server18 = require("@trpc/server");
37416
+
37417
+ // src/server/Storage/helpers/lifecycleMapper.ts
37418
+ function toMidnightUTC(date) {
37419
+ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
37420
+ }
37421
+ __name(toMidnightUTC, "toMidnightUTC");
37422
+ function toSdkLifecycleRules(wireRules) {
37423
+ return wireRules.map((rule) => {
37424
+ const result = {
37425
+ Status: rule.Status,
37426
+ ID: rule.ID,
37427
+ Prefix: rule.Prefix,
37428
+ Filter: rule.Filter
37429
+ };
37430
+ if (rule.Expiration) {
37431
+ result.Expiration = {
37432
+ Days: rule.Expiration.Days,
37433
+ ExpiredObjectDeleteMarker: rule.Expiration.ExpiredObjectDeleteMarker,
37434
+ // Only normalize Expiration.Date to midnight UTC (AWS requirement)
37435
+ Date: rule.Expiration.Date !== void 0 ? typeof rule.Expiration.Date === "string" ? toMidnightUTC(new Date(rule.Expiration.Date)) : toMidnightUTC(rule.Expiration.Date) : void 0
37436
+ };
37437
+ }
37438
+ if (rule.Transitions) {
37439
+ result.Transitions = rule.Transitions.map((t2) => ({
37440
+ Days: t2.Days,
37441
+ StorageClass: t2.StorageClass,
37442
+ Date: t2.Date !== void 0 ? typeof t2.Date === "string" ? new Date(t2.Date) : t2.Date : void 0
37443
+ }));
37444
+ }
37445
+ if (rule.NoncurrentVersionExpiration) {
37446
+ result.NoncurrentVersionExpiration = {
37447
+ NoncurrentDays: rule.NoncurrentVersionExpiration.NoncurrentDays,
37448
+ NewerNoncurrentVersions: rule.NoncurrentVersionExpiration.NewerNoncurrentVersions
37449
+ };
37450
+ }
37451
+ if (rule.NoncurrentVersionTransitions) {
37452
+ result.NoncurrentVersionTransitions = rule.NoncurrentVersionTransitions.map((t2) => ({
37453
+ NoncurrentDays: t2.NoncurrentDays,
37454
+ StorageClass: t2.StorageClass,
37455
+ NewerNoncurrentVersions: t2.NewerNoncurrentVersions
37456
+ }));
37457
+ }
37458
+ if (rule.AbortIncompleteMultipartUpload) {
37459
+ result.AbortIncompleteMultipartUpload = {
37460
+ DaysAfterInitiation: rule.AbortIncompleteMultipartUpload.DaysAfterInitiation
37461
+ };
37462
+ }
37463
+ return result;
37464
+ });
37465
+ }
37466
+ __name(toSdkLifecycleRules, "toSdkLifecycleRules");
37467
+ var toIso = /* @__PURE__ */ __name((d) => d === void 0 ? void 0 : d instanceof Date ? d.toISOString() : String(d), "toIso");
37468
+ function toWireLifecycleRule(rule) {
37469
+ const result = {
37470
+ Status: rule.Status ?? "Enabled"
37471
+ };
37472
+ if (rule.ID !== void 0) result.ID = rule.ID;
37473
+ if (rule.Prefix !== void 0) result.Prefix = rule.Prefix;
37474
+ if (rule.Filter !== void 0) result.Filter = rule.Filter;
37475
+ if (rule.Expiration) {
37476
+ result.Expiration = {
37477
+ Days: rule.Expiration.Days,
37478
+ ExpiredObjectDeleteMarker: rule.Expiration.ExpiredObjectDeleteMarker,
37479
+ Date: toIso(rule.Expiration.Date)
37480
+ };
37481
+ }
37482
+ if (rule.Transitions) {
37483
+ result.Transitions = rule.Transitions.map((t2) => ({
37484
+ Days: t2.Days,
37485
+ StorageClass: t2.StorageClass,
37486
+ Date: toIso(t2.Date)
37487
+ }));
37488
+ }
37489
+ if (rule.NoncurrentVersionExpiration) {
37490
+ result.NoncurrentVersionExpiration = {
37491
+ NoncurrentDays: rule.NoncurrentVersionExpiration.NoncurrentDays,
37492
+ NewerNoncurrentVersions: rule.NoncurrentVersionExpiration.NewerNoncurrentVersions
37493
+ };
37494
+ }
37495
+ if (rule.NoncurrentVersionTransitions) {
37496
+ result.NoncurrentVersionTransitions = rule.NoncurrentVersionTransitions.map((t2) => ({
37497
+ NoncurrentDays: t2.NoncurrentDays,
37498
+ StorageClass: t2.StorageClass,
37499
+ NewerNoncurrentVersions: t2.NewerNoncurrentVersions
37500
+ }));
37501
+ }
37502
+ if (rule.AbortIncompleteMultipartUpload) {
37503
+ result.AbortIncompleteMultipartUpload = {
37504
+ DaysAfterInitiation: rule.AbortIncompleteMultipartUpload.DaysAfterInitiation
37505
+ };
37506
+ }
37507
+ return result;
37508
+ }
37509
+ __name(toWireLifecycleRule, "toWireLifecycleRule");
37510
+
37511
+ // src/server/Storage/routers/ceph/lifecycleRouter.ts
37512
+ var lifecycleSetRateLimits = /* @__PURE__ */ new Map();
37513
+ function checkLifecycleSetRateLimit(bucketName, projectId) {
37514
+ const key = `${projectId}:${bucketName}`;
37515
+ const now = Date.now();
37516
+ const windowMs = 60 * 1e3;
37517
+ const limit = lifecycleSetRateLimits.get(key);
37518
+ if (!limit || now >= limit.resetAt) {
37519
+ lifecycleSetRateLimits.set(key, {
37520
+ count: 1,
37521
+ resetAt: now + windowMs
37522
+ });
37523
+ setTimeout(() => {
37524
+ const current = lifecycleSetRateLimits.get(key);
37525
+ if (current && current.resetAt <= Date.now()) {
37526
+ lifecycleSetRateLimits.delete(key);
37527
+ }
37528
+ }, windowMs).unref();
37529
+ return;
37530
+ }
37531
+ if (limit.count >= 10) {
37532
+ throw new import_server18.TRPCError({
37533
+ code: "TOO_MANY_REQUESTS",
37534
+ message: "Lifecycle modification rate limit exceeded. Maximum 10 lifecycle changes per minute per bucket."
37535
+ });
37536
+ }
37537
+ limit.count++;
37538
+ }
37539
+ __name(checkLifecycleSetRateLimit, "checkLifecycleSetRateLimit");
37540
+ var lifecycleRouter = {
37541
+ /**
37542
+ * Get the current lifecycle configuration for a bucket.
37543
+ *
37544
+ * Returns an array of lifecycle rules, or null if no lifecycle configuration is set.
37545
+ * Not having a lifecycle configuration is a normal state (not an error).
37546
+ *
37547
+ * Rules are mapped and validated individually a rule that fails the lenient read schema
37548
+ * (e.g. authored outside Aurora) is skipped rather than failing the whole response;
37549
+ * `skippedRuleCount` reports how many were skipped so the client can warn and disable mutations.
37550
+ *
37551
+ * @returns { rules: LifecycleRule[] | null; skippedRuleCount: number }
37552
+ * @throws TRPCError NOT_FOUND - bucket does not exist
37553
+ * @throws TRPCError FORBIDDEN - no credentials or access denied
37554
+ */
37555
+ get: cephProtectedProcedure.input(getLifecycleInputSchema).query(async ({ ctx, input }) => {
37556
+ const s3 = ctx.getCephClient();
37557
+ const { bucketName } = input;
37558
+ try {
37559
+ const response = await s3.send(new import_client_s37.GetBucketLifecycleConfigurationCommand({
37560
+ Bucket: bucketName
37561
+ }));
37562
+ const rawRules = response.Rules ?? null;
37563
+ if (!rawRules) {
37564
+ return {
37565
+ rules: null,
37566
+ skippedRuleCount: 0
37567
+ };
37568
+ }
37569
+ const rules = [];
37570
+ let skippedRuleCount = 0;
37571
+ for (const rawRule of rawRules) {
37572
+ try {
37573
+ const parsed = lifecycleRuleReadSchema.safeParse(toWireLifecycleRule(rawRule));
37574
+ if (parsed.success) {
37575
+ rules.push(parsed.data);
37576
+ continue;
37577
+ }
37578
+ skippedRuleCount++;
37579
+ } catch {
37580
+ skippedRuleCount++;
37581
+ }
37582
+ }
37583
+ return {
37584
+ rules,
37585
+ skippedRuleCount
37586
+ };
37587
+ } catch (error) {
37588
+ const s3Error = error;
37589
+ if (s3Error.name === "NoSuchLifecycleConfiguration" || s3Error.Code === "NoSuchLifecycleConfiguration") {
37590
+ return {
37591
+ rules: null,
37592
+ skippedRuleCount: 0
37593
+ };
37594
+ }
37595
+ throw mapS3ErrorToTRPCError(error, {
37596
+ operation: "get lifecycle configuration",
37597
+ bucket: bucketName
37598
+ });
37599
+ }
37600
+ }),
37601
+ /**
37602
+ * Set (create or replace) a lifecycle configuration for a bucket.
37603
+ *
37604
+ * Accepts a lifecycle configuration with an array of rules. Validates structure
37605
+ * before sending to S3. Replaces any existing lifecycle configuration completely.
37606
+ *
37607
+ * Rules are validated for:
37608
+ * - At least one action (Expiration, Transition, NoncurrentVersion, or AbortIncompleteMultipartUpload)
37609
+ * - ID: max 255 characters (optional)
37610
+ * - Filter: proper structure for Prefix, Tag, ObjectSize conditions
37611
+ * - Total rules: 1-100 per bucket
37612
+ *
37613
+ * @returns boolean - true on success
37614
+ * @throws TRPCError BAD_REQUEST - invalid lifecycle configuration structure
37615
+ * @throws TRPCError NOT_FOUND - bucket does not exist
37616
+ * @throws TRPCError FORBIDDEN - no credentials or access denied
37617
+ * @throws TRPCError TOO_MANY_REQUESTS - rate limit exceeded (10 changes per minute per bucket)
37618
+ */
37619
+ set: cephProtectedProcedure.input(setLifecycleInputSchema).mutation(async ({ ctx, input }) => {
37620
+ const s3 = ctx.getCephClient();
37621
+ const { bucketName, lifecycleConfiguration, project_id } = input;
37622
+ checkLifecycleSetRateLimit(bucketName, project_id);
37623
+ const transformedRules = toSdkLifecycleRules(lifecycleConfiguration.Rules).map((rule) => {
37624
+ const transformed = {
37625
+ ...rule
37626
+ };
37627
+ if (transformed.Prefix !== void 0 && transformed.Filter === void 0) {
37628
+ transformed.Filter = {
37629
+ Prefix: transformed.Prefix
37630
+ };
37631
+ }
37632
+ delete transformed.Prefix;
37633
+ return transformed;
37634
+ });
37635
+ try {
37636
+ await s3.send(new import_client_s37.PutBucketLifecycleConfigurationCommand({
37637
+ Bucket: bucketName,
37638
+ LifecycleConfiguration: {
37639
+ Rules: transformedRules
37640
+ }
37641
+ }));
37642
+ return true;
37643
+ } catch (error) {
37644
+ throw mapS3ErrorToTRPCError(error, {
37645
+ operation: "set lifecycle configuration",
37646
+ bucket: bucketName
37647
+ });
37648
+ }
37649
+ }),
37650
+ /**
37651
+ * Delete (remove) a lifecycle configuration from a bucket.
37652
+ *
37653
+ * Removes all lifecycle rules from the bucket. The bucket reverts to having no lifecycle config.
37654
+ * Not an error if no lifecycle configuration was set (idempotent).
37655
+ *
37656
+ * @returns boolean - true on success
37657
+ * @throws TRPCError NOT_FOUND - bucket does not exist
37658
+ * @throws TRPCError FORBIDDEN - no credentials or access denied
37659
+ */
37660
+ delete: cephProtectedProcedure.input(deleteLifecycleInputSchema).mutation(async ({ ctx, input }) => {
37661
+ const s3 = ctx.getCephClient();
37662
+ const { bucketName } = input;
37663
+ try {
37664
+ await s3.send(new import_client_s37.DeleteBucketLifecycleCommand({
37665
+ Bucket: bucketName
37666
+ }));
37667
+ return true;
37668
+ } catch (error) {
37669
+ const s3Error = error;
37670
+ if (s3Error.name === "NoSuchLifecycleConfiguration" || s3Error.Code === "NoSuchLifecycleConfiguration") {
37671
+ return true;
37672
+ }
37673
+ throw mapS3ErrorToTRPCError(error, {
37674
+ operation: "delete lifecycle configuration",
37675
+ bucket: bucketName
37676
+ });
37677
+ }
37678
+ })
37679
+ };
37680
+
37105
37681
  // src/server/Storage/routers/permissionRouter.ts
37106
37682
  var STORAGE_MAPPINGS = {
37107
37683
  // Container Operations (works for both Swift containers and Ceph buckets)
@@ -37141,6 +37717,10 @@ var STORAGE_MAPPINGS = {
37141
37717
  engine: "storage",
37142
37718
  rule: "storage:container_update_access_control"
37143
37719
  },
37720
+ "storage:containers:update_versioning": {
37721
+ engine: "storage",
37722
+ rule: "storage:container_versioning_update"
37723
+ },
37144
37724
  // Object Operations
37145
37725
  "storage:objects:read": {
37146
37726
  engine: "storage",
@@ -37174,6 +37754,10 @@ var STORAGE_MAPPINGS = {
37174
37754
  engine: "storage",
37175
37755
  rule: "storage:object_move"
37176
37756
  },
37757
+ "storage:objects:share": {
37758
+ engine: "storage",
37759
+ rule: "storage:object_share"
37760
+ },
37177
37761
  // Folder Operations
37178
37762
  "storage:folders:create_object": {
37179
37763
  engine: "storage",
@@ -37186,6 +37770,47 @@ var STORAGE_MAPPINGS = {
37186
37770
  "storage:folders:delete": {
37187
37771
  engine: "storage",
37188
37772
  rule: "storage:folder_delete"
37773
+ },
37774
+ // Object Version Operations
37775
+ "storage:object_versions:delete": {
37776
+ engine: "storage",
37777
+ rule: "storage:object_version_delete"
37778
+ },
37779
+ "storage:object_versions:restore": {
37780
+ engine: "storage",
37781
+ rule: "storage:object_version_restore"
37782
+ },
37783
+ // Container Policy Operations
37784
+ "storage:container_policies:update": {
37785
+ engine: "storage",
37786
+ rule: "storage:container_policy_update"
37787
+ },
37788
+ "storage:container_policies:delete": {
37789
+ engine: "storage",
37790
+ rule: "storage:container_policy_delete"
37791
+ },
37792
+ // CORS Operations
37793
+ "storage:container_cors_rules:update": {
37794
+ engine: "storage",
37795
+ rule: "storage:container_cors_update"
37796
+ },
37797
+ "storage:container_cors_rules:delete": {
37798
+ engine: "storage",
37799
+ rule: "storage:container_cors_delete"
37800
+ },
37801
+ // Lifecycle Operations
37802
+ "storage:container_lifecycle_rules:update": {
37803
+ engine: "storage",
37804
+ rule: "storage:container_lifecycle_update"
37805
+ },
37806
+ "storage:container_lifecycle_rules:delete": {
37807
+ engine: "storage",
37808
+ rule: "storage:container_lifecycle_delete"
37809
+ },
37810
+ // Credential Operations
37811
+ "storage:credentials:create": {
37812
+ engine: "storage",
37813
+ rule: "storage:credential_create"
37189
37814
  }
37190
37815
  };
37191
37816
  var buildStoragePermissionRouter = /* @__PURE__ */ __name((policyDir) => createPermissionRouter({
@@ -37222,6 +37847,9 @@ var buildObjectStorageRouters = /* @__PURE__ */ __name((policyDir) => ({
37222
37847
  }),
37223
37848
  cors: auroraRouter({
37224
37849
  ...corsRouter
37850
+ }),
37851
+ lifecycle: auroraRouter({
37852
+ ...lifecycleRouter
37225
37853
  })
37226
37854
  }),
37227
37855
  ...buildStoragePermissionRouter(policyDir)
@@ -37230,7 +37858,7 @@ var buildObjectStorageRouters = /* @__PURE__ */ __name((policyDir) => ({
37230
37858
 
37231
37859
  // src/server/Project/routers/projectRouter.ts
37232
37860
  var import_zod20 = require("zod");
37233
- var import_server18 = require("@trpc/server");
37861
+ var import_server19 = require("@trpc/server");
37234
37862
 
37235
37863
  // src/server/Project/types/models.ts
37236
37864
  var import_zod19 = require("zod");
@@ -37267,10 +37895,10 @@ var projectsResponseSchema = import_zod19.z.object({
37267
37895
  });
37268
37896
 
37269
37897
  // src/server/Project/routers/projectRouter.ts
37270
- var import_signal_openstack4 = __toESM(require_esm());
37898
+ var import_signal_openstack5 = __toESM(require_esm());
37271
37899
  async function callIdentityAPI(identityEndpoint, authToken, path3) {
37272
37900
  if (!identityEndpoint) {
37273
- throw new import_server18.TRPCError({
37901
+ throw new import_server19.TRPCError({
37274
37902
  code: "INTERNAL_SERVER_ERROR",
37275
37903
  message: "Identity endpoint not configured"
37276
37904
  });
@@ -37286,7 +37914,7 @@ async function callIdentityAPI(identityEndpoint, authToken, path3) {
37286
37914
  }
37287
37915
  });
37288
37916
  if (!response.ok) {
37289
- throw new import_server18.TRPCError({
37917
+ throw new import_server19.TRPCError({
37290
37918
  code: "INTERNAL_SERVER_ERROR",
37291
37919
  message: `Identity API call failed: ${response.status} ${response.statusText}`
37292
37920
  });
@@ -37326,14 +37954,14 @@ var projectRouter = {
37326
37954
  */
37327
37955
  getAuthProjects: protectedProcedure.query(async ({ ctx }) => {
37328
37956
  if (!ctx.openstack) {
37329
- throw new import_server18.TRPCError({
37957
+ throw new import_server19.TRPCError({
37330
37958
  code: "UNAUTHORIZED",
37331
37959
  message: "No authenticated session"
37332
37960
  });
37333
37961
  }
37334
37962
  const token = ctx.openstack.getToken();
37335
37963
  if (!token?.authToken) {
37336
- throw new import_server18.TRPCError({
37964
+ throw new import_server19.TRPCError({
37337
37965
  code: "UNAUTHORIZED",
37338
37966
  message: "No auth token available"
37339
37967
  });
@@ -37376,14 +38004,14 @@ var projectRouter = {
37376
38004
  search: import_zod20.z.string().optional()
37377
38005
  }).optional()).query(async ({ ctx, input }) => {
37378
38006
  if (!ctx.openstack) {
37379
- throw new import_server18.TRPCError({
38007
+ throw new import_server19.TRPCError({
37380
38008
  code: "UNAUTHORIZED",
37381
38009
  message: "No authenticated session"
37382
38010
  });
37383
38011
  }
37384
38012
  const token = ctx.openstack.getToken();
37385
38013
  if (!token?.authToken) {
37386
- throw new import_server18.TRPCError({
38014
+ throw new import_server19.TRPCError({
37387
38015
  code: "UNAUTHORIZED",
37388
38016
  message: "No auth token available"
37389
38017
  });
@@ -37407,21 +38035,21 @@ var projectRouter = {
37407
38035
  projectId: import_zod20.z.string()
37408
38036
  })).query(async ({ ctx, input }) => {
37409
38037
  if (!ctx.openstack) {
37410
- throw new import_server18.TRPCError({
38038
+ throw new import_server19.TRPCError({
37411
38039
  code: "UNAUTHORIZED",
37412
38040
  message: "No authenticated session"
37413
38041
  });
37414
38042
  }
37415
38043
  const token = ctx.openstack.getToken();
37416
38044
  if (!token?.authToken) {
37417
- throw new import_server18.TRPCError({
38045
+ throw new import_server19.TRPCError({
37418
38046
  code: "UNAUTHORIZED",
37419
38047
  message: "No auth token available"
37420
38048
  });
37421
38049
  }
37422
38050
  let encodedId;
37423
38051
  try {
37424
- encodedId = (0, import_signal_openstack4.validateAndEncodeResourceId)(input.projectId, "Project");
38052
+ encodedId = (0, import_signal_openstack5.validateAndEncodeResourceId)(input.projectId, "Project");
37425
38053
  } catch {
37426
38054
  return null;
37427
38055
  }
@@ -37440,22 +38068,25 @@ var projectRouters = {
37440
38068
  })
37441
38069
  };
37442
38070
 
38071
+ // src/server/Network/routers/floatingIpRouter.ts
38072
+ var import_server24 = require("@trpc/server");
38073
+
37443
38074
  // src/server/helpers/errorHandling.ts
37444
- var import_server19 = require("@trpc/server");
37445
- var import_signal_openstack5 = __toESM(require_esm());
38075
+ var import_server20 = require("@trpc/server");
38076
+ var import_signal_openstack6 = __toESM(require_esm());
37446
38077
  function wrapError3(error, operation) {
37447
- if (error instanceof import_server19.TRPCError) {
38078
+ if (error instanceof import_server20.TRPCError) {
37448
38079
  return error;
37449
38080
  }
37450
- if (error instanceof import_signal_openstack5.SignalOpenstackError) {
37451
- return new import_server19.TRPCError({
38081
+ if (error instanceof import_signal_openstack6.SignalOpenstackError) {
38082
+ return new import_server20.TRPCError({
37452
38083
  code: "BAD_REQUEST",
37453
38084
  message: error.message,
37454
38085
  cause: error
37455
38086
  });
37456
38087
  }
37457
38088
  const baseErrorMessage = `Error during ${operation}`;
37458
- return new import_server19.TRPCError({
38089
+ return new import_server20.TRPCError({
37459
38090
  code: "INTERNAL_SERVER_ERROR",
37460
38091
  message: typeof error !== "string" && error.message ? `${baseErrorMessage}: ${error.message}` : baseErrorMessage,
37461
38092
  cause: error
@@ -37495,11 +38126,11 @@ function appendQueryParamsFromObject(source, options) {
37495
38126
  __name(appendQueryParamsFromObject, "appendQueryParamsFromObject");
37496
38127
 
37497
38128
  // src/server/helpers/validateOpenstackService.ts
37498
- var import_server20 = require("@trpc/server");
38129
+ var import_server21 = require("@trpc/server");
37499
38130
  var capitalize = /* @__PURE__ */ __name((str) => str.charAt(0).toUpperCase() + str.slice(1), "capitalize");
37500
38131
  function validateOpenstackService(service, serviceName) {
37501
38132
  if (!service) {
37502
- throw new import_server20.TRPCError({
38133
+ throw new import_server21.TRPCError({
37503
38134
  code: "INTERNAL_SERVER_ERROR",
37504
38135
  message: `${capitalize(serviceName)} service is not available`
37505
38136
  });
@@ -37508,7 +38139,7 @@ function validateOpenstackService(service, serviceName) {
37508
38139
  __name(validateOpenstackService, "validateOpenstackService");
37509
38140
 
37510
38141
  // src/server/Network/routers/floatingIpRouter.ts
37511
- var import_signal_openstack6 = __toESM(require_esm());
38142
+ var import_signal_openstack7 = __toESM(require_esm());
37512
38143
 
37513
38144
  // src/server/Network/types/floatingIp.ts
37514
38145
  var import_zod22 = require("zod");
@@ -37621,8 +38252,7 @@ var FloatingIpIdInputSchema = import_zod22.z.object({
37621
38252
  floatingip_id: import_zod22.z.string()
37622
38253
  });
37623
38254
  var FloatingIpCreateRequestSchema = import_zod22.z.object({
37624
- tenant_id: import_zod22.z.string(),
37625
- project_id: import_zod22.z.string(),
38255
+ project_id: import_zod22.z.string().trim().min(1, "project_id must be a non-empty string"),
37626
38256
  floating_network_id: import_zod22.z.string(),
37627
38257
  fixed_ip_address: import_zod22.z.string().optional(),
37628
38258
  floating_ip_address: import_zod22.z.string().optional(),
@@ -37756,10 +38386,10 @@ var AvailablePortsResponseSchema = import_zod22.z.object({
37756
38386
  });
37757
38387
 
37758
38388
  // src/server/Network/helpers/errorHandling.ts
37759
- var import_server22 = require("@trpc/server");
38389
+ var import_server23 = require("@trpc/server");
37760
38390
 
37761
38391
  // src/server/Network/helpers/index.ts
37762
- var import_server21 = require("@trpc/server");
38392
+ var import_server22 = require("@trpc/server");
37763
38393
  var HTTP_STATUS_ERROR_MAP = {
37764
38394
  400: "BAD_REQUEST",
37765
38395
  401: "UNAUTHORIZED",
@@ -37779,7 +38409,7 @@ var parseOrThrow = /* @__PURE__ */ __name((schema, data, context) => {
37779
38409
  const parsed = schema.safeParse(data);
37780
38410
  if (!parsed.success) {
37781
38411
  console.error(`Zod Parsing Error in ${context}:`, parsed.error.issues);
37782
- throw new import_server21.TRPCError({
38412
+ throw new import_server22.TRPCError({
37783
38413
  code: "PARSE_ERROR",
37784
38414
  message: `Failed to parse response in ${context}`
37785
38415
  });
@@ -37789,27 +38419,27 @@ var parseOrThrow = /* @__PURE__ */ __name((schema, data, context) => {
37789
38419
 
37790
38420
  // src/server/Network/helpers/errorHandling.ts
37791
38421
  var DEFAULT_HANDLERS = {
37792
- 400: (response, resourceLabel) => new import_server22.TRPCError({
38422
+ 400: (response, resourceLabel) => new import_server23.TRPCError({
37793
38423
  code: HTTP_STATUS_ERROR_MAP[400],
37794
38424
  message: `Invalid request data for ${resourceLabel}: ${response.statusText || "Unknown error"}`
37795
38425
  }),
37796
- 401: (response, resourceLabel) => new import_server22.TRPCError({
38426
+ 401: (response, resourceLabel) => new import_server23.TRPCError({
37797
38427
  code: HTTP_STATUS_ERROR_MAP[401],
37798
38428
  message: `Unauthorized access to ${resourceLabel}: ${response.statusText || "Unknown error"}`
37799
38429
  }),
37800
- 403: (response, resourceLabel) => new import_server22.TRPCError({
38430
+ 403: (response, resourceLabel) => new import_server23.TRPCError({
37801
38431
  code: HTTP_STATUS_ERROR_MAP[403],
37802
38432
  message: `Access forbidden to ${resourceLabel}: ${response.statusText || "Unknown error"}`
37803
38433
  }),
37804
- 404: (response, resourceLabel) => new import_server22.TRPCError({
38434
+ 404: (response, resourceLabel) => new import_server23.TRPCError({
37805
38435
  code: HTTP_STATUS_ERROR_MAP[404],
37806
38436
  message: `${resourceLabel} not found: ${response.statusText || "Unknown error"}`
37807
38437
  }),
37808
- 409: (response, resourceLabel) => new import_server22.TRPCError({
38438
+ 409: (response, resourceLabel) => new import_server23.TRPCError({
37809
38439
  code: HTTP_STATUS_ERROR_MAP[409],
37810
38440
  message: `Conflict - ${resourceLabel} is in use: ${response.statusText || "Unknown error"}`
37811
38441
  }),
37812
- 412: (response, resourceLabel) => new import_server22.TRPCError({
38442
+ 412: (response, resourceLabel) => new import_server23.TRPCError({
37813
38443
  code: HTTP_STATUS_ERROR_MAP[412],
37814
38444
  message: `Precondition failed - revision number mismatch in ${resourceLabel}: ${response.statusText || "Unknown error"}`
37815
38445
  })
@@ -37824,7 +38454,7 @@ var ErrorHandler = /* @__PURE__ */ __name((resourceName, customHandlers) => {
37824
38454
  if (response.status && handlers[response.status]) {
37825
38455
  return handlers[response.status](response, resourceLabel);
37826
38456
  }
37827
- return new import_server22.TRPCError({
38457
+ return new import_server23.TRPCError({
37828
38458
  code: DEFAULT_ERROR_NAME,
37829
38459
  message: `Failed to process ${resourceLabel}: ${response.statusText || "Unknown error"}`
37830
38460
  });
@@ -37870,10 +38500,18 @@ var floatingIpRouter = {
37870
38500
  create: projectScopedProcedure.input(FloatingIpCreateRequestSchema).mutation(async ({ input, ctx }) => {
37871
38501
  return withErrorHandling3(async () => {
37872
38502
  const network = getNetworkService(ctx);
38503
+ const token = ctx.openstack?.getToken();
38504
+ const projectId = token?.tokenData.project?.id;
38505
+ if (!projectId) {
38506
+ throw new import_server24.TRPCError({
38507
+ code: "UNAUTHORIZED",
38508
+ message: "No project scope in session"
38509
+ });
38510
+ }
37873
38511
  const requestBody = {
37874
38512
  floatingip: {
37875
- tenant_id: input.tenant_id,
37876
- project_id: input.project_id,
38513
+ tenant_id: projectId,
38514
+ project_id: projectId,
37877
38515
  floating_network_id: input.floating_network_id,
37878
38516
  ...input.fixed_ip_address !== void 0 && {
37879
38517
  fixed_ip_address: input.fixed_ip_address
@@ -37916,7 +38554,7 @@ var floatingIpRouter = {
37916
38554
  return withErrorHandling3(async () => {
37917
38555
  const { floatingip_id } = input;
37918
38556
  const network = getNetworkService(ctx);
37919
- const encodedId = (0, import_signal_openstack6.validateAndEncodeResourceId)(floatingip_id, "Floating IP");
38557
+ const encodedId = (0, import_signal_openstack7.validateAndEncodeResourceId)(floatingip_id, "Floating IP");
37920
38558
  const response = await network.get(`${FLOATING_IPS_BASE_URL}/${encodedId}`);
37921
38559
  if (!response.ok) {
37922
38560
  throw FloatingIpErrorHandlers.get(response, floatingip_id);
@@ -37943,7 +38581,7 @@ var floatingIpRouter = {
37943
38581
  }
37944
38582
  }
37945
38583
  };
37946
- const encodedId = (0, import_signal_openstack6.validateAndEncodeResourceId)(floatingip_id, "Floating IP");
38584
+ const encodedId = (0, import_signal_openstack7.validateAndEncodeResourceId)(floatingip_id, "Floating IP");
37947
38585
  const response = await network.put(`${FLOATING_IPS_BASE_URL}/${encodedId}`, requestBody);
37948
38586
  if (!response.ok) {
37949
38587
  throw FloatingIpErrorHandlers.update(response, floatingip_id);
@@ -37956,7 +38594,7 @@ var floatingIpRouter = {
37956
38594
  return withErrorHandling3(async () => {
37957
38595
  const { floatingip_id } = input;
37958
38596
  const network = getNetworkService(ctx);
37959
- const encodedId = (0, import_signal_openstack6.validateAndEncodeResourceId)(floatingip_id, "Floating IP");
38597
+ const encodedId = (0, import_signal_openstack7.validateAndEncodeResourceId)(floatingip_id, "Floating IP");
37960
38598
  const response = await network.del(`${FLOATING_IPS_BASE_URL}/${encodedId}`);
37961
38599
  if (!response.ok) {
37962
38600
  throw FloatingIpErrorHandlers.delete(response, floatingip_id);
@@ -38112,7 +38750,7 @@ var createSecurityGroupRuleInputSchema = projectScopedInputSchema.extend({
38112
38750
  });
38113
38751
 
38114
38752
  // src/server/Network/helpers/securityGroupHelpers.ts
38115
- var import_server23 = require("@trpc/server");
38753
+ var import_server25 = require("@trpc/server");
38116
38754
  var SecurityGroupErrorHandlers = {
38117
38755
  /**
38118
38756
  * Handles errors specific to security group list operations
@@ -38122,17 +38760,17 @@ var SecurityGroupErrorHandlers = {
38122
38760
  list: /* @__PURE__ */ __name((response) => {
38123
38761
  switch (response.status) {
38124
38762
  case 401:
38125
- return new import_server23.TRPCError({
38763
+ return new import_server25.TRPCError({
38126
38764
  code: HTTP_STATUS_ERROR_MAP[401],
38127
38765
  message: "Unauthorized access"
38128
38766
  });
38129
38767
  case 403:
38130
- return new import_server23.TRPCError({
38768
+ return new import_server25.TRPCError({
38131
38769
  code: HTTP_STATUS_ERROR_MAP[403],
38132
38770
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
38133
38771
  });
38134
38772
  default:
38135
- return new import_server23.TRPCError({
38773
+ return new import_server25.TRPCError({
38136
38774
  code: DEFAULT_ERROR_NAME,
38137
38775
  message: `Failed to list security groups: ${response.statusText || "Unknown error"}`
38138
38776
  });
@@ -38147,22 +38785,22 @@ var SecurityGroupErrorHandlers = {
38147
38785
  getById: /* @__PURE__ */ __name((response, securityGroupId) => {
38148
38786
  switch (response.status) {
38149
38787
  case 401:
38150
- return new import_server23.TRPCError({
38788
+ return new import_server25.TRPCError({
38151
38789
  code: HTTP_STATUS_ERROR_MAP[401],
38152
38790
  message: "Unauthorized access"
38153
38791
  });
38154
38792
  case 403:
38155
- return new import_server23.TRPCError({
38793
+ return new import_server25.TRPCError({
38156
38794
  code: HTTP_STATUS_ERROR_MAP[403],
38157
38795
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
38158
38796
  });
38159
38797
  case 404:
38160
- return new import_server23.TRPCError({
38798
+ return new import_server25.TRPCError({
38161
38799
  code: HTTP_STATUS_ERROR_MAP[404],
38162
38800
  message: `Security group not found: ${securityGroupId}`
38163
38801
  });
38164
38802
  default:
38165
- return new import_server23.TRPCError({
38803
+ return new import_server25.TRPCError({
38166
38804
  code: DEFAULT_ERROR_NAME,
38167
38805
  message: `Failed to fetch security group: ${response.statusText || "Unknown error"}`
38168
38806
  });
@@ -38176,32 +38814,32 @@ var SecurityGroupErrorHandlers = {
38176
38814
  create: /* @__PURE__ */ __name((response) => {
38177
38815
  switch (response.status) {
38178
38816
  case 401:
38179
- return new import_server23.TRPCError({
38817
+ return new import_server25.TRPCError({
38180
38818
  code: HTTP_STATUS_ERROR_MAP[401],
38181
38819
  message: "Unauthorized access"
38182
38820
  });
38183
38821
  case 403:
38184
- return new import_server23.TRPCError({
38822
+ return new import_server25.TRPCError({
38185
38823
  code: HTTP_STATUS_ERROR_MAP[403],
38186
38824
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
38187
38825
  });
38188
38826
  case 409:
38189
- return new import_server23.TRPCError({
38827
+ return new import_server25.TRPCError({
38190
38828
  code: HTTP_STATUS_ERROR_MAP[409],
38191
38829
  message: `Conflict: ${response.statusText || "Security group already exists"}`
38192
38830
  });
38193
38831
  case 413:
38194
- return new import_server23.TRPCError({
38832
+ return new import_server25.TRPCError({
38195
38833
  code: "BAD_REQUEST",
38196
38834
  message: `Quota exceeded for security groups. Please delete an existing security group or contact your administrator to increase your quota.`
38197
38835
  });
38198
38836
  case 400:
38199
- return new import_server23.TRPCError({
38837
+ return new import_server25.TRPCError({
38200
38838
  code: "BAD_REQUEST",
38201
38839
  message: `Invalid request: ${response.statusText || "Unknown error"}`
38202
38840
  });
38203
38841
  default:
38204
- return new import_server23.TRPCError({
38842
+ return new import_server25.TRPCError({
38205
38843
  code: "INTERNAL_SERVER_ERROR",
38206
38844
  message: `Failed to create security group: ${response.statusText || "Unknown error"}`
38207
38845
  });
@@ -38216,22 +38854,22 @@ var SecurityGroupErrorHandlers = {
38216
38854
  delete: /* @__PURE__ */ __name((response, securityGroupId) => {
38217
38855
  switch (response.status) {
38218
38856
  case 401:
38219
- return new import_server23.TRPCError({
38857
+ return new import_server25.TRPCError({
38220
38858
  code: HTTP_STATUS_ERROR_MAP[401],
38221
38859
  message: "Unauthorized access"
38222
38860
  });
38223
38861
  case 404:
38224
- return new import_server23.TRPCError({
38862
+ return new import_server25.TRPCError({
38225
38863
  code: HTTP_STATUS_ERROR_MAP[404],
38226
38864
  message: `Security group not found: ${securityGroupId}`
38227
38865
  });
38228
38866
  case 409:
38229
- return new import_server23.TRPCError({
38867
+ return new import_server25.TRPCError({
38230
38868
  code: HTTP_STATUS_ERROR_MAP[409],
38231
38869
  message: "Cannot delete security group because it is in use by one or more ports. Please remove all associations before deleting."
38232
38870
  });
38233
38871
  default:
38234
- return new import_server23.TRPCError({
38872
+ return new import_server25.TRPCError({
38235
38873
  code: DEFAULT_ERROR_NAME,
38236
38874
  message: `Failed to delete security group: ${response.statusText || "Unknown error"}`
38237
38875
  });
@@ -38246,39 +38884,39 @@ var SecurityGroupErrorHandlers = {
38246
38884
  update: /* @__PURE__ */ __name((response, securityGroupId) => {
38247
38885
  const errorMessage = response.statusText || "";
38248
38886
  if (errorMessage.toLowerCase().includes("stateful") && errorMessage.toLowerCase().includes("in use")) {
38249
- return new import_server23.TRPCError({
38887
+ return new import_server25.TRPCError({
38250
38888
  code: "CONFLICT",
38251
38889
  message: "Cannot update the 'stateful' attribute because this security group is in use by one or more ports."
38252
38890
  });
38253
38891
  }
38254
38892
  switch (response.status) {
38255
38893
  case 401:
38256
- return new import_server23.TRPCError({
38894
+ return new import_server25.TRPCError({
38257
38895
  code: HTTP_STATUS_ERROR_MAP[401],
38258
38896
  message: "Unauthorized access"
38259
38897
  });
38260
38898
  case 403:
38261
- return new import_server23.TRPCError({
38899
+ return new import_server25.TRPCError({
38262
38900
  code: HTTP_STATUS_ERROR_MAP[403],
38263
38901
  message: `Access forbidden: ${errorMessage || "Unknown error"}`
38264
38902
  });
38265
38903
  case 404:
38266
- return new import_server23.TRPCError({
38904
+ return new import_server25.TRPCError({
38267
38905
  code: HTTP_STATUS_ERROR_MAP[404],
38268
38906
  message: `Security group not found: ${securityGroupId}`
38269
38907
  });
38270
38908
  case 409:
38271
- return new import_server23.TRPCError({
38909
+ return new import_server25.TRPCError({
38272
38910
  code: HTTP_STATUS_ERROR_MAP[409],
38273
38911
  message: `Conflict: ${errorMessage || "Security group conflict"}`
38274
38912
  });
38275
38913
  case 400:
38276
- return new import_server23.TRPCError({
38914
+ return new import_server25.TRPCError({
38277
38915
  code: HTTP_STATUS_ERROR_MAP[400],
38278
38916
  message: `Invalid request: ${errorMessage || "Unknown error"}`
38279
38917
  });
38280
38918
  default:
38281
- return new import_server23.TRPCError({
38919
+ return new import_server25.TRPCError({
38282
38920
  code: DEFAULT_ERROR_NAME,
38283
38921
  message: `Failed to update security group: ${errorMessage || "Unknown error"}`
38284
38922
  });
@@ -38296,48 +38934,48 @@ var SecurityGroupRuleErrorHandlers = {
38296
38934
  switch (response.status) {
38297
38935
  case 400:
38298
38936
  if (statusText.toLowerCase().includes("cidr")) {
38299
- return new import_server23.TRPCError({
38937
+ return new import_server25.TRPCError({
38300
38938
  code: "BAD_REQUEST",
38301
38939
  message: "Invalid CIDR format. Please provide a valid IP address block (e.g., 0.0.0.0/0)"
38302
38940
  });
38303
38941
  }
38304
38942
  if (statusText.toLowerCase().includes("port")) {
38305
- return new import_server23.TRPCError({
38943
+ return new import_server25.TRPCError({
38306
38944
  code: "BAD_REQUEST",
38307
38945
  message: "Invalid port range. Ports must be between 1 and 65535, and min must be <= max"
38308
38946
  });
38309
38947
  }
38310
- return new import_server23.TRPCError({
38948
+ return new import_server25.TRPCError({
38311
38949
  code: "BAD_REQUEST",
38312
38950
  message: `Invalid request: ${statusText}`
38313
38951
  });
38314
38952
  case 401:
38315
- return new import_server23.TRPCError({
38953
+ return new import_server25.TRPCError({
38316
38954
  code: "UNAUTHORIZED",
38317
38955
  message: "Unauthorized access"
38318
38956
  });
38319
38957
  case 403:
38320
- return new import_server23.TRPCError({
38958
+ return new import_server25.TRPCError({
38321
38959
  code: "FORBIDDEN",
38322
38960
  message: `Access forbidden: ${statusText}`
38323
38961
  });
38324
38962
  case 404:
38325
- return new import_server23.TRPCError({
38963
+ return new import_server25.TRPCError({
38326
38964
  code: "NOT_FOUND",
38327
38965
  message: "Security group not found"
38328
38966
  });
38329
38967
  case 409:
38330
- return new import_server23.TRPCError({
38968
+ return new import_server25.TRPCError({
38331
38969
  code: "CONFLICT",
38332
38970
  message: "A rule with these parameters already exists in this security group"
38333
38971
  });
38334
38972
  case 413:
38335
- return new import_server23.TRPCError({
38973
+ return new import_server25.TRPCError({
38336
38974
  code: "BAD_REQUEST",
38337
38975
  message: "Quota exceeded for security group rules. Please delete existing rules or contact your administrator."
38338
38976
  });
38339
38977
  default:
38340
- return new import_server23.TRPCError({
38978
+ return new import_server25.TRPCError({
38341
38979
  code: "INTERNAL_SERVER_ERROR",
38342
38980
  message: `Failed to create security group rule: ${statusText}`
38343
38981
  });
@@ -38356,22 +38994,22 @@ var SecurityGroupRuleErrorHandlers = {
38356
38994
  delete: /* @__PURE__ */ __name((response, ruleId) => {
38357
38995
  switch (response.status) {
38358
38996
  case 401:
38359
- return new import_server23.TRPCError({
38997
+ return new import_server25.TRPCError({
38360
38998
  code: "UNAUTHORIZED",
38361
38999
  message: "Unauthorized access"
38362
39000
  });
38363
39001
  case 404:
38364
- return new import_server23.TRPCError({
39002
+ return new import_server25.TRPCError({
38365
39003
  code: "NOT_FOUND",
38366
39004
  message: `Security group rule not found: ${ruleId}`
38367
39005
  });
38368
39006
  case 412:
38369
- return new import_server23.TRPCError({
39007
+ return new import_server25.TRPCError({
38370
39008
  code: "PRECONDITION_FAILED",
38371
39009
  message: `Cannot delete security group rule: precondition failed`
38372
39010
  });
38373
39011
  default:
38374
- return new import_server23.TRPCError({
39012
+ return new import_server25.TRPCError({
38375
39013
  code: "INTERNAL_SERVER_ERROR",
38376
39014
  message: `Failed to delete security group rule: ${response.statusText || "Unknown error"}`
38377
39015
  });
@@ -38382,7 +39020,7 @@ var parseOpenStackResponse = /* @__PURE__ */ __name((data, schema, operation, er
38382
39020
  const parsed = schema.safeParse(data);
38383
39021
  if (!parsed.success) {
38384
39022
  console.error(`Zod Parsing Error in ${operation}:`, parsed.error.format());
38385
- throw new import_server23.TRPCError({
39023
+ throw new import_server25.TRPCError({
38386
39024
  code: "INTERNAL_SERVER_ERROR",
38387
39025
  message: errorMessage
38388
39026
  });
@@ -38437,7 +39075,7 @@ var sortSecurityGroups = /* @__PURE__ */ __name((items, sortKey, sortDir = "asc"
38437
39075
  }, "sortSecurityGroups");
38438
39076
 
38439
39077
  // src/server/Network/routers/securityGroupRouter.ts
38440
- var import_signal_openstack7 = __toESM(require_esm());
39078
+ var import_signal_openstack8 = __toESM(require_esm());
38441
39079
  var SECURITY_GROUPS_BASE_URL = "v2.0/security-groups";
38442
39080
  var LIST_SECURITY_GROUPS_QUERY_KEY_MAP = {
38443
39081
  tags_any: "tags-any",
@@ -38504,7 +39142,7 @@ var securityGroupRouter = {
38504
39142
  return withErrorHandling3(async () => {
38505
39143
  const { securityGroupId } = input;
38506
39144
  const network = getNetworkService(ctx);
38507
- const encodedId = (0, import_signal_openstack7.validateAndEncodeResourceId)(securityGroupId, "Security group");
39145
+ const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(securityGroupId, "Security group");
38508
39146
  const response = await network.get(`${SECURITY_GROUPS_BASE_URL}/${encodedId}`);
38509
39147
  if (!response.ok) {
38510
39148
  throw SecurityGroupErrorHandlers.getById(response, securityGroupId);
@@ -38540,7 +39178,7 @@ var securityGroupRouter = {
38540
39178
  return withErrorHandling3(async () => {
38541
39179
  const { securityGroupId } = input;
38542
39180
  const network = getNetworkService(ctx);
38543
- const encodedId = (0, import_signal_openstack7.validateAndEncodeResourceId)(securityGroupId, "Security group");
39181
+ const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(securityGroupId, "Security group");
38544
39182
  const response = await network.del(`${SECURITY_GROUPS_BASE_URL}/${encodedId}`);
38545
39183
  if (!response?.ok) {
38546
39184
  throw SecurityGroupErrorHandlers.delete(response, securityGroupId);
@@ -38564,7 +39202,7 @@ var securityGroupRouter = {
38564
39202
  }
38565
39203
  }
38566
39204
  };
38567
- const encodedId = (0, import_signal_openstack7.validateAndEncodeResourceId)(securityGroupId, "Security group");
39205
+ const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(securityGroupId, "Security group");
38568
39206
  const response = await network.put(`${SECURITY_GROUPS_BASE_URL}/${encodedId}`, requestBody);
38569
39207
  if (!response.ok) {
38570
39208
  throw SecurityGroupErrorHandlers.update(response, securityGroupId);
@@ -38669,7 +39307,7 @@ var deleteRBACPolicyInputSchema = projectScopedInputSchema.extend({
38669
39307
  });
38670
39308
 
38671
39309
  // src/server/Network/helpers/rbacPolicyHelpers.ts
38672
- var import_server24 = require("@trpc/server");
39310
+ var import_server26 = require("@trpc/server");
38673
39311
  var RBACPolicyErrorHandlers = {
38674
39312
  /**
38675
39313
  * Handles errors specific to RBAC policy list operations
@@ -38679,17 +39317,17 @@ var RBACPolicyErrorHandlers = {
38679
39317
  list: /* @__PURE__ */ __name((response) => {
38680
39318
  switch (response.status) {
38681
39319
  case 401:
38682
- return new import_server24.TRPCError({
39320
+ return new import_server26.TRPCError({
38683
39321
  code: HTTP_STATUS_ERROR_MAP[401],
38684
39322
  message: "Unauthorized access"
38685
39323
  });
38686
39324
  case 403:
38687
- return new import_server24.TRPCError({
39325
+ return new import_server26.TRPCError({
38688
39326
  code: HTTP_STATUS_ERROR_MAP[403],
38689
39327
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
38690
39328
  });
38691
39329
  default:
38692
- return new import_server24.TRPCError({
39330
+ return new import_server26.TRPCError({
38693
39331
  code: DEFAULT_ERROR_NAME,
38694
39332
  message: `Failed to list RBAC policies: ${response.statusText || "Unknown error"}`
38695
39333
  });
@@ -38703,32 +39341,32 @@ var RBACPolicyErrorHandlers = {
38703
39341
  create: /* @__PURE__ */ __name((response) => {
38704
39342
  switch (response.status) {
38705
39343
  case 400:
38706
- return new import_server24.TRPCError({
39344
+ return new import_server26.TRPCError({
38707
39345
  code: HTTP_STATUS_ERROR_MAP[400],
38708
39346
  message: `Invalid request: ${response.statusText || "Unknown error"}`
38709
39347
  });
38710
39348
  case 401:
38711
- return new import_server24.TRPCError({
39349
+ return new import_server26.TRPCError({
38712
39350
  code: HTTP_STATUS_ERROR_MAP[401],
38713
39351
  message: "Unauthorized access"
38714
39352
  });
38715
39353
  case 403:
38716
- return new import_server24.TRPCError({
39354
+ return new import_server26.TRPCError({
38717
39355
  code: HTTP_STATUS_ERROR_MAP[403],
38718
39356
  message: "You don't have permission to share this security group"
38719
39357
  });
38720
39358
  case 404:
38721
- return new import_server24.TRPCError({
39359
+ return new import_server26.TRPCError({
38722
39360
  code: HTTP_STATUS_ERROR_MAP[404],
38723
39361
  message: "Security group not found or target project does not exist"
38724
39362
  });
38725
39363
  case 409:
38726
- return new import_server24.TRPCError({
39364
+ return new import_server26.TRPCError({
38727
39365
  code: HTTP_STATUS_ERROR_MAP[409],
38728
39366
  message: "This security group is already shared with the specified project"
38729
39367
  });
38730
39368
  default:
38731
- return new import_server24.TRPCError({
39369
+ return new import_server26.TRPCError({
38732
39370
  code: "INTERNAL_SERVER_ERROR",
38733
39371
  message: `Failed to create RBAC policy: ${response.statusText || "Unknown error"}`
38734
39372
  });
@@ -38743,27 +39381,27 @@ var RBACPolicyErrorHandlers = {
38743
39381
  update: /* @__PURE__ */ __name((response, policyId) => {
38744
39382
  switch (response.status) {
38745
39383
  case 400:
38746
- return new import_server24.TRPCError({
39384
+ return new import_server26.TRPCError({
38747
39385
  code: HTTP_STATUS_ERROR_MAP[400],
38748
39386
  message: `Invalid request: ${response.statusText || "Unknown error"}`
38749
39387
  });
38750
39388
  case 401:
38751
- return new import_server24.TRPCError({
39389
+ return new import_server26.TRPCError({
38752
39390
  code: HTTP_STATUS_ERROR_MAP[401],
38753
39391
  message: "Unauthorized access"
38754
39392
  });
38755
39393
  case 403:
38756
- return new import_server24.TRPCError({
39394
+ return new import_server26.TRPCError({
38757
39395
  code: HTTP_STATUS_ERROR_MAP[403],
38758
39396
  message: `Access forbidden: ${response.statusText || "Unknown error"}`
38759
39397
  });
38760
39398
  case 404:
38761
- return new import_server24.TRPCError({
39399
+ return new import_server26.TRPCError({
38762
39400
  code: HTTP_STATUS_ERROR_MAP[404],
38763
39401
  message: `RBAC policy not found: ${policyId}`
38764
39402
  });
38765
39403
  default:
38766
- return new import_server24.TRPCError({
39404
+ return new import_server26.TRPCError({
38767
39405
  code: "INTERNAL_SERVER_ERROR",
38768
39406
  message: `Failed to update RBAC policy: ${response.statusText || "Unknown error"}`
38769
39407
  });
@@ -38778,22 +39416,22 @@ var RBACPolicyErrorHandlers = {
38778
39416
  delete: /* @__PURE__ */ __name((response, policyId) => {
38779
39417
  switch (response.status) {
38780
39418
  case 401:
38781
- return new import_server24.TRPCError({
39419
+ return new import_server26.TRPCError({
38782
39420
  code: HTTP_STATUS_ERROR_MAP[401],
38783
39421
  message: "Unauthorized access"
38784
39422
  });
38785
39423
  case 404:
38786
- return new import_server24.TRPCError({
39424
+ return new import_server26.TRPCError({
38787
39425
  code: HTTP_STATUS_ERROR_MAP[404],
38788
39426
  message: `RBAC policy not found: ${policyId}`
38789
39427
  });
38790
39428
  case 409:
38791
- return new import_server24.TRPCError({
39429
+ return new import_server26.TRPCError({
38792
39430
  code: HTTP_STATUS_ERROR_MAP[409],
38793
39431
  message: "Cannot delete RBAC policy because it is in use"
38794
39432
  });
38795
39433
  default:
38796
- return new import_server24.TRPCError({
39434
+ return new import_server26.TRPCError({
38797
39435
  code: DEFAULT_ERROR_NAME,
38798
39436
  message: `Failed to delete RBAC policy: ${response.statusText || "Unknown error"}`
38799
39437
  });
@@ -38804,7 +39442,7 @@ var parseOpenStackResponse2 = /* @__PURE__ */ __name((data, schema, operation, e
38804
39442
  const parsed = schema.safeParse(data);
38805
39443
  if (!parsed.success) {
38806
39444
  console.error(`Zod Parsing Error in ${operation}:`, parsed.error.format());
38807
- throw new import_server24.TRPCError({
39445
+ throw new import_server26.TRPCError({
38808
39446
  code: "INTERNAL_SERVER_ERROR",
38809
39447
  message: errorMessage
38810
39448
  });
@@ -39120,266 +39758,8 @@ var buildNetworkRouters = /* @__PURE__ */ __name((policyDir) => ({
39120
39758
  })
39121
39759
  }), "buildNetworkRouters");
39122
39760
 
39123
- // src/server/Services/routers/pcaRouter.ts
39124
- var import_signal_openstack8 = __toESM(require_esm());
39125
-
39126
- // src/server/Services/types/pca.ts
39127
- var import_zod25 = require("zod");
39128
- var CertificateValiditySchema = import_zod25.z.object({
39129
- not_after: import_zod25.z.number().int(),
39130
- not_before: import_zod25.z.number().int().optional()
39131
- });
39132
- var CertificateAuthorityCertificateSchema = import_zod25.z.object({
39133
- /** PEM encoded certificate data. */
39134
- pem: import_zod25.z.string(),
39135
- validity: CertificateValiditySchema
39136
- });
39137
- var CertificateAuthorityCertificateChainSchema = import_zod25.z.object({
39138
- certificates: import_zod25.z.array(import_zod25.z.object({
39139
- pem: import_zod25.z.string()
39140
- })),
39141
- /** Concatenated PEM certificates of the chain. */
39142
- pem: import_zod25.z.string()
39143
- });
39144
- var CertificateAuthorityAdditionalAttributeSchema = import_zod25.z.object({
39145
- /** ASN.1 Object Identifier of the attribute */
39146
- key: import_zod25.z.array(import_zod25.z.number().int()),
39147
- value: import_zod25.z.string()
39148
- });
39149
- var stringOrStringArray = import_zod25.z.union([
39150
- import_zod25.z.array(import_zod25.z.string()),
39151
- import_zod25.z.string().transform((s) => [
39152
- s
39153
- ])
39154
- ]);
39155
- var CertificateAuthoritySubjectSchema = import_zod25.z.object({
39156
- additional_attribute: import_zod25.z.array(CertificateAuthorityAdditionalAttributeSchema).optional(),
39157
- named_attributes: import_zod25.z.object({
39158
- cn: import_zod25.z.string(),
39159
- /** Country codes (ISO 3166-1 alpha-2). */
39160
- c: stringOrStringArray.optional(),
39161
- /** Locality/city names. */
39162
- l: stringOrStringArray.optional(),
39163
- /** Organization names. */
39164
- o: stringOrStringArray.optional(),
39165
- /** Organizational unit names. */
39166
- ou: stringOrStringArray.optional(),
39167
- /** Postal/ZIP codes. */
39168
- postal_code: stringOrStringArray.optional(),
39169
- /** State or province names. */
39170
- st: stringOrStringArray.optional(),
39171
- serial_number: import_zod25.z.string().optional(),
39172
- street: stringOrStringArray.optional()
39173
- })
39174
- });
39175
- var CertificateAuthorityStateSchema = import_zod25.z.enum([
39176
- "CREATING",
39177
- "AWAITING_CERTIFICATE",
39178
- "READY",
39179
- "FAILED"
39180
- ]);
39181
- var CertificateAuthoritySchema = import_zod25.z.object({
39182
- certificate: CertificateAuthorityCertificateSchema.optional(),
39183
- /** Details of Certificate Authority certificate's issuers chain. */
39184
- certificate_chain: CertificateAuthorityCertificateChainSchema.optional(),
39185
- configuration: import_zod25.z.object({
39186
- /** X.509 subject of Certificate Authority. Required on create operation. */
39187
- subject: CertificateAuthoritySubjectSchema
39188
- }).optional(),
39189
- csr: import_zod25.z.string().optional(),
39190
- /** Human-readable subject string, e.g. "CN=demo-ca.test.sci". */
39191
- display_subject: import_zod25.z.string().optional(),
39192
- id: import_zod25.z.string(),
39193
- /**
39194
- * Required on import certificate operation.
39195
- * Certificate Authority certificate chain, in PEM format. Consists of concatenated string
39196
- * of Certificate Authority certificate, followed by its intermediate issuing CAs certificates
39197
- * and root issuing CA certificate last.
39198
- */
39199
- imported_certificate_chain: import_zod25.z.string().optional(),
39200
- /** Identifier of OpenStack project that Certificate Authority belongs. */
39201
- project_id: import_zod25.z.string(),
39202
- /** Current operational state of Certificate Authority. */
39203
- state: CertificateAuthorityStateSchema
39204
- });
39205
- var LinkSchema = import_zod25.z.object({
39206
- href: import_zod25.z.string(),
39207
- rel: import_zod25.z.string()
39208
- });
39209
- var CertificateAuthoritiesListSchema = import_zod25.z.object({
39210
- certificate_authorities: import_zod25.z.array(CertificateAuthoritySchema),
39211
- links: import_zod25.z.array(LinkSchema),
39212
- next_page_marker: import_zod25.z.string().optional()
39213
- });
39214
- var CertificateAuthoritiesListInputSchema = projectScopedInputSchema.extend({
39215
- limit: import_zod25.z.number().int().min(1).max(1e3).optional(),
39216
- next_page_marker: import_zod25.z.string().trim().min(1).optional()
39217
- });
39218
- var CertificateAuthorityCreateSchema = import_zod25.z.object({
39219
- configuration: import_zod25.z.object({
39220
- subject: import_zod25.z.object({
39221
- named_attributes: import_zod25.z.object({
39222
- cn: import_zod25.z.string().trim().min(1)
39223
- })
39224
- })
39225
- })
39226
- });
39227
- var CertificateAuthorityIdInputSchema = projectScopedInputSchema.extend({
39228
- certificate_authority_id: import_zod25.z.string().min(1)
39229
- });
39230
- var CertificateAuthorityCertificatesListInputSchema = CertificateAuthorityIdInputSchema.extend({
39231
- limit: import_zod25.z.number().int().min(1).max(1e3).optional(),
39232
- next_page_marker: import_zod25.z.string().trim().min(1).optional()
39233
- });
39234
- var CertificateAuthorityImportInputSchema = CertificateAuthorityIdInputSchema.extend({
39235
- imported_certificate_chain: import_zod25.z.string().min(1)
39236
- });
39237
- var CertificateIdInputSchema = CertificateAuthorityIdInputSchema.extend({
39238
- certificate_id: import_zod25.z.string().min(1)
39239
- });
39240
- var CertificateConfigurationSchema = import_zod25.z.object({
39241
- validity: CertificateValiditySchema
39242
- });
39243
- var CreateCertificateInputSchema = projectScopedInputSchema.extend({
39244
- certificate_authority_id: import_zod25.z.string().min(1),
39245
- csr: import_zod25.z.string().min(1),
39246
- configuration: CertificateConfigurationSchema
39247
- });
39248
- var CertificateSchema = import_zod25.z.object({
39249
- certificate: CertificateAuthorityCertificateSchema.optional(),
39250
- certificate_authority_id: import_zod25.z.string(),
39251
- certificate_chain: CertificateAuthorityCertificateChainSchema.optional(),
39252
- configuration: CertificateConfigurationSchema.optional(),
39253
- csr: import_zod25.z.string().optional(),
39254
- id: import_zod25.z.string(),
39255
- project_id: import_zod25.z.string()
39256
- });
39257
- var CertificatesListSchema = import_zod25.z.object({
39258
- certificates: import_zod25.z.array(CertificateSchema),
39259
- links: import_zod25.z.array(LinkSchema),
39260
- next_page_marker: import_zod25.z.string().optional()
39261
- });
39262
-
39263
- // src/server/Services/routers/pcaRouter.ts
39264
- var PCA_BASE_URL = "v1/certificate-authorities";
39265
- var pcaRouter = {
39266
- list: projectScopedProcedure.input(CertificateAuthoritiesListInputSchema).query(async ({ input, ctx }) => {
39267
- return withErrorHandling3(async () => {
39268
- const pca = ctx.openstack?.service("pca");
39269
- validateOpenstackService(pca, "pca");
39270
- const queryParams = new URLSearchParams();
39271
- if (input.limit !== void 0) queryParams.set("limit", String(input.limit));
39272
- if (input.next_page_marker !== void 0) queryParams.set("next_page_marker", input.next_page_marker);
39273
- const queryString = queryParams.toString();
39274
- const url = queryString ? `${PCA_BASE_URL}?${queryString}` : PCA_BASE_URL;
39275
- const response = await pca.get(url);
39276
- const data = await response.json();
39277
- return parseOrThrow(CertificateAuthoritiesListSchema, data, "pcaRouter.list");
39278
- }, "list certificate authorities");
39279
- }),
39280
- /**
39281
- * Creates a new Certificate Authority (CA).
39282
- * The CA is created in CREATING state and transitions to AWAITING_CERTIFICATE state once its CSR has been generated.
39283
- * CA in AWAITING_CERTIFICATE can't issue end-entity certificates, and needs to have its certificate imported - see the respective importCertificate endpoint.
39284
- */
39285
- create: projectScopedProcedure.input(CertificateAuthorityCreateSchema).mutation(async ({ input, ctx }) => {
39286
- return withErrorHandling3(async () => {
39287
- const pca = ctx.openstack?.service("pca");
39288
- validateOpenstackService(pca, "pca");
39289
- const response = await pca.post(PCA_BASE_URL, omit(input, "project_id"));
39290
- const data = await response.json();
39291
- return parseOrThrow(CertificateAuthoritySchema, data, "pcaRouter.create");
39292
- }, "create certificate authority");
39293
- }),
39294
- getById: projectScopedProcedure.input(CertificateAuthorityIdInputSchema).query(async ({ input, ctx }) => {
39295
- return withErrorHandling3(async () => {
39296
- const pca = ctx.openstack?.service("pca");
39297
- validateOpenstackService(pca, "pca");
39298
- const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_authority_id, "Certificate authority");
39299
- const url = `${PCA_BASE_URL}/${encodedId}`;
39300
- const response = await pca.get(url);
39301
- const data = await response.json();
39302
- return parseOrThrow(CertificateAuthoritySchema, data, "pcaRouter.getById");
39303
- }, "get certificate authority details");
39304
- }),
39305
- // Permanently deletes a Certificate Authority. This operation is irreversible.
39306
- delete: projectScopedProcedure.input(CertificateAuthorityIdInputSchema).mutation(async ({ input, ctx }) => {
39307
- return withErrorHandling3(async () => {
39308
- const pca = ctx.openstack?.service("pca");
39309
- validateOpenstackService(pca, "pca");
39310
- const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_authority_id, "Certificate authority");
39311
- const url = `${PCA_BASE_URL}/${encodedId}`;
39312
- await pca.del(url);
39313
- }, "delete certificate authority");
39314
- }),
39315
- /**
39316
- * Imports Certificate Authority certificate
39317
- * Transitioning the CA from AWAITING_CERTIFICATE to READY state
39318
- * after which the CA becomes fully operational and can issue certificates to end entities
39319
- */
39320
- import: projectScopedProcedure.input(CertificateAuthorityImportInputSchema).mutation(async ({ input, ctx }) => {
39321
- return withErrorHandling3(async () => {
39322
- const pca = ctx.openstack?.service("pca");
39323
- validateOpenstackService(pca, "pca");
39324
- const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_authority_id, "Certificate authority");
39325
- const url = `${PCA_BASE_URL}/${encodedId}:importCertificate`;
39326
- const response = await pca.post(url, {
39327
- imported_certificate_chain: input.imported_certificate_chain
39328
- });
39329
- const data = await response.json();
39330
- return parseOrThrow(CertificateAuthoritySchema, data, "pcaRouter.import");
39331
- }, "import certificate of certificate authority");
39332
- }),
39333
- listCertificates: projectScopedProcedure.input(CertificateAuthorityCertificatesListInputSchema).query(async ({ input, ctx }) => {
39334
- return withErrorHandling3(async () => {
39335
- const pca = ctx.openstack?.service("pca");
39336
- validateOpenstackService(pca, "pca");
39337
- const queryParams = new URLSearchParams();
39338
- if (input.limit !== void 0) queryParams.set("limit", String(input.limit));
39339
- if (input.next_page_marker !== void 0) queryParams.set("next_page_marker", input.next_page_marker);
39340
- const queryString = queryParams.toString();
39341
- const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_authority_id, "Certificate authority");
39342
- const baseUrl = `${PCA_BASE_URL}/${encodedId}/certificates`;
39343
- const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
39344
- const response = await pca.get(url);
39345
- const data = await response.json();
39346
- return parseOrThrow(CertificatesListSchema, data, "pcaRouter.listCertificates");
39347
- }, "list certificates for certificate authority");
39348
- }),
39349
- createCertificate: projectScopedProcedure.input(CreateCertificateInputSchema).mutation(async ({ input, ctx }) => {
39350
- return withErrorHandling3(async () => {
39351
- const pca = ctx.openstack?.service("pca");
39352
- validateOpenstackService(pca, "pca");
39353
- const encodedId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_authority_id, "Certificate authority");
39354
- const url = `${PCA_BASE_URL}/${encodedId}/certificates`;
39355
- const response = await pca.post(url, omit(input, "project_id", "certificate_authority_id"));
39356
- const data = await response.json();
39357
- return parseOrThrow(CertificateSchema, data, "pcaRouter.createCertificate");
39358
- }, "create certificate for certificate authority");
39359
- }),
39360
- getByIdCertificate: projectScopedProcedure.input(CertificateIdInputSchema).query(async ({ input, ctx }) => {
39361
- return withErrorHandling3(async () => {
39362
- const pca = ctx.openstack?.service("pca");
39363
- validateOpenstackService(pca, "pca");
39364
- const encodedAuthorityId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_authority_id, "Certificate authority");
39365
- const encodedCertId = (0, import_signal_openstack8.validateAndEncodeResourceId)(input.certificate_id, "Certificate");
39366
- const url = `${PCA_BASE_URL}/${encodedAuthorityId}/certificates/${encodedCertId}`;
39367
- const response = await pca.get(url);
39368
- const data = await response.json();
39369
- return parseOrThrow(CertificateSchema, data, "pcaRouter.getByIdCertificate");
39370
- }, "get certificate details");
39371
- })
39372
- };
39373
-
39374
- // src/server/Services/routers/index.ts
39375
- var serviceRouters = {
39376
- services: auroraRouter({
39377
- pca: pcaRouter
39378
- })
39379
- };
39380
-
39381
39761
  // src/server/routers.ts
39382
- var buildBaseRouter = /* @__PURE__ */ __name((policyDir) => mergeRouters(auroraRouter(authRouters), auroraRouter(buildComputeRouters(policyDir)), auroraRouter(buildObjectStorageRouters(policyDir)), auroraRouter(projectRouters), auroraRouter(buildNetworkRouters(policyDir)), auroraRouter(serviceRouters)), "buildBaseRouter");
39762
+ var buildBaseRouter = /* @__PURE__ */ __name((policyDir) => mergeRouters(auroraRouter(authRouters), auroraRouter(buildComputeRouters(policyDir)), auroraRouter(buildObjectStorageRouters(policyDir)), auroraRouter(projectRouters), auroraRouter(buildNetworkRouters(policyDir))), "buildBaseRouter");
39383
39763
  var buildAppRouter = /* @__PURE__ */ __name((policyDir, extraRouters = []) => {
39384
39764
  if (extraRouters.length === 0) return buildBaseRouter(policyDir);
39385
39765
  return mergeRouters(buildBaseRouter(policyDir), ...extraRouters);
@@ -39597,53 +39977,51 @@ async function createContext(opts, config) {
39597
39977
  return openstackSession;
39598
39978
  }
39599
39979
  const rescopeTokenPromise = (async () => {
39600
- try {
39601
- const newScope = newScopeProjectId ? {
39602
- project: {
39603
- id: newScopeProjectId
39604
- }
39605
- } : newScopeDomainId ? {
39606
- domain: {
39607
- id: newScopeDomainId
39608
- }
39609
- } : "unscoped";
39610
- await openstackSession.rescope(newScope);
39611
- const newToken = openstackSession.getToken();
39612
- const newAuthToken2 = newToken?.authToken;
39613
- if (newAuthToken2 && newAuthToken2 !== sessionToken) {
39614
- const oldPendingRescopes = sessionRescopes.get(sessionToken);
39615
- if (oldPendingRescopes) {
39616
- const existingRescopes = sessionRescopes.get(newAuthToken2);
39617
- if (existingRescopes) {
39618
- for (const [key, value] of oldPendingRescopes.entries()) {
39619
- if (!existingRescopes.has(key)) {
39620
- existingRescopes.set(key, value);
39621
- }
39980
+ const newScope = newScopeProjectId ? {
39981
+ project: {
39982
+ id: newScopeProjectId
39983
+ }
39984
+ } : newScopeDomainId ? {
39985
+ domain: {
39986
+ id: newScopeDomainId
39987
+ }
39988
+ } : "unscoped";
39989
+ await openstackSession.rescope(newScope);
39990
+ const newToken = openstackSession.getToken();
39991
+ const newAuthToken2 = newToken?.authToken;
39992
+ if (newAuthToken2 && newAuthToken2 !== sessionToken) {
39993
+ const oldPendingRescopes = sessionRescopes.get(sessionToken);
39994
+ if (oldPendingRescopes) {
39995
+ const existingRescopes = sessionRescopes.get(newAuthToken2);
39996
+ if (existingRescopes) {
39997
+ for (const [key, value] of oldPendingRescopes.entries()) {
39998
+ if (!existingRescopes.has(key)) {
39999
+ existingRescopes.set(key, value);
39622
40000
  }
39623
- } else {
39624
- sessionRescopes.set(newAuthToken2, oldPendingRescopes);
39625
40001
  }
39626
- sessionRescopes.delete(sessionToken);
40002
+ } else {
40003
+ sessionRescopes.set(newAuthToken2, oldPendingRescopes);
39627
40004
  }
39628
- }
39629
- cachedUserId = void 0;
39630
- cachedUserInfo = void 0;
39631
- return newAuthToken2 || null;
39632
- } catch (err) {
39633
- console.error("Rescope error:", err);
39634
- return null;
39635
- } finally {
39636
- pendingRescopes.delete(scopeKey);
39637
- if (pendingRescopes.size === 0) {
39638
40005
  sessionRescopes.delete(sessionToken);
39639
- const currentToken = openstackSession?.getToken()?.authToken;
39640
- if (currentToken && currentToken !== sessionToken && sessionRescopes.get(currentToken)?.size === 0) {
39641
- sessionRescopes.delete(currentToken);
39642
- }
39643
40006
  }
39644
40007
  }
40008
+ cachedUserId = void 0;
40009
+ cachedUserInfo = void 0;
40010
+ return newAuthToken2 || null;
39645
40011
  })();
40012
+ const cleanupPromise = rescopeTokenPromise.finally(() => {
40013
+ pendingRescopes.delete(scopeKey);
40014
+ if (pendingRescopes.size === 0) {
40015
+ sessionRescopes.delete(sessionToken);
40016
+ const currentToken = openstackSession?.getToken()?.authToken;
40017
+ if (currentToken && currentToken !== sessionToken && sessionRescopes.get(currentToken)?.size === 0) {
40018
+ sessionRescopes.delete(currentToken);
40019
+ }
40020
+ }
40021
+ });
39646
40022
  pendingRescopes.set(scopeKey, rescopeTokenPromise);
40023
+ cleanupPromise.catch(() => {
40024
+ });
39647
40025
  const newAuthToken = await rescopeTokenPromise;
39648
40026
  if (!newAuthToken) {
39649
40027
  return null;
@@ -39683,7 +40061,7 @@ __name(createContext, "createContext");
39683
40061
  // src/server/server.ts
39684
40062
  var import_path2 = __toESM(require("path"));
39685
40063
  var import_node_stream4 = require("stream");
39686
- var import_zod26 = require("zod");
40064
+ var import_zod25 = require("zod");
39687
40065
 
39688
40066
  // src/server/aurora-fastify-plugins/csrfProtection.ts
39689
40067
  var import_csrf_protection = __toESM(require("@fastify/csrf-protection"));
@@ -39793,6 +40171,19 @@ async function createServer(config) {
39793
40171
  }, (_req, payload, done) => {
39794
40172
  done(null, payload);
39795
40173
  });
40174
+ server.register(csrfProtection_default, {
40175
+ tokenRoute: "/csrf-token",
40176
+ cookieKey: "aurora-csrf-protection",
40177
+ tokenHeader: "x-csrf-token",
40178
+ excludePaths: [
40179
+ "/extensions"
40180
+ ],
40181
+ protectionMethods: [
40182
+ "POST",
40183
+ "PUT",
40184
+ "DELETE"
40185
+ ]
40186
+ });
39796
40187
  server.post(`${bffEndpoint}/upload-image-direct`, {
39797
40188
  config: {
39798
40189
  rawBody: false
@@ -39859,19 +40250,6 @@ async function createServer(config) {
39859
40250
  });
39860
40251
  }
39861
40252
  });
39862
- server.register(csrfProtection_default, {
39863
- tokenRoute: "/csrf-token",
39864
- cookieKey: "aurora-csrf-protection",
39865
- tokenHeader: "x-csrf-token",
39866
- excludePaths: [
39867
- "/extensions"
39868
- ],
39869
- protectionMethods: [
39870
- "POST",
39871
- "PUT",
39872
- "DELETE"
39873
- ]
39874
- });
39875
40253
  server.addHook("onRequest", (request, _reply, done) => {
39876
40254
  if (request.url.includes("/compute.uploadImage")) {
39877
40255
  request.raw.setTimeout(0);
@@ -39884,7 +40262,7 @@ async function createServer(config) {
39884
40262
  router: appRouter,
39885
40263
  createContext: /* @__PURE__ */ __name((opts) => createContext(opts, contextConfig), "createContext"),
39886
40264
  onError: /* @__PURE__ */ __name((err) => {
39887
- if (err.error.cause instanceof import_zod26.ZodError) err.error.message = err.error.cause.issues.map((e) => e.message).join(",");
40265
+ if (err.error.cause instanceof import_zod25.ZodError) err.error.message = err.error.cause.issues.map((e) => e.message).join(",");
39888
40266
  }, "onError")
39889
40267
  }
39890
40268
  });
@@ -39949,10 +40327,12 @@ __name(createServer, "createServer");
39949
40327
  createServer,
39950
40328
  domainScopedInputSchema,
39951
40329
  domainScopedProcedure,
40330
+ parseOrThrow,
39952
40331
  projectScopedInputSchema,
39953
40332
  projectScopedProcedure,
39954
40333
  protectedProcedure,
39955
- publicProcedure
40334
+ publicProcedure,
40335
+ validateOpenstackService
39956
40336
  });
39957
40337
  /*! Bundled license information:
39958
40338