@stacksjs/ts-cloud 0.7.105 → 0.7.109

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 (149) hide show
  1. package/dist/alerts/delivery.d.ts +10 -0
  2. package/dist/alerts/model.d.ts +1 -1
  3. package/dist/api/client.d.ts +53 -0
  4. package/dist/api/handler.d.ts +10 -0
  5. package/dist/api/service.d.ts +1 -0
  6. package/dist/aws/index.js +10 -10
  7. package/dist/aws/lambda.d.ts +19 -0
  8. package/dist/bin/cli.js +1677 -1370
  9. package/dist/bin/dashboard-server.js +926 -620
  10. package/dist/{chunk-fmt40tpw.js → chunk-53jatzaw.js} +2 -2
  11. package/dist/{chunk-ef2dwfrg.js → chunk-8kh577qh.js} +5 -5
  12. package/dist/{chunk-s9c2x5jv.js → chunk-9v2pwxv9.js} +2 -2
  13. package/dist/chunk-aa2dkn7b.js +205 -0
  14. package/dist/{chunk-vkd2y0fs.js → chunk-cktwk9hy.js} +7169 -14800
  15. package/dist/{chunk-dmzez5f8.js → chunk-d3vx2ekv.js} +123 -28
  16. package/dist/chunk-grx1rp09.js +12163 -0
  17. package/dist/{chunk-c6db5m63.js → chunk-t2s3gdq6.js} +253 -8
  18. package/dist/chunk-va2yd85b.js +200 -0
  19. package/dist/{chunk-3g4r09dd.js → chunk-wmbep3b5.js} +1 -1
  20. package/dist/{chunk-ybcz6sxc.js → chunk-x6yzgv7y.js} +33 -0
  21. package/dist/chunk-xrtwv3v2.js +420 -0
  22. package/dist/control-plane/types.d.ts +1 -1
  23. package/dist/deploy/dashboard-bundle-encoding.test.d.ts +1 -0
  24. package/dist/deploy/dashboard-payload.d.ts +20 -0
  25. package/dist/deploy/dashboard-payload.test.d.ts +1 -0
  26. package/dist/deploy/dashboard-protection.test.d.ts +1 -0
  27. package/dist/deploy/dashboard-spend.test.d.ts +1 -0
  28. package/dist/deploy/dashboard-topology.d.ts +85 -0
  29. package/dist/deploy/dashboard-topology.test.d.ts +1 -0
  30. package/dist/deploy/egress-collection.d.ts +60 -0
  31. package/dist/deploy/index.d.ts +2 -0
  32. package/dist/deploy/index.js +23 -8
  33. package/dist/deploy/local-dashboard-server.d.ts +2 -0
  34. package/dist/drivers/index.js +4 -2
  35. package/dist/drivers/shared/protection.d.ts +43 -0
  36. package/dist/drivers/shared/protection.test.d.ts +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.js +364 -102
  39. package/dist/protection/controls.d.ts +113 -0
  40. package/dist/protection/controls.test.d.ts +1 -0
  41. package/dist/protection/ddos.d.ts +130 -0
  42. package/dist/protection/ddos.test.d.ts +1 -0
  43. package/dist/protection/index.d.ts +11 -0
  44. package/dist/protection/index.js +87 -0
  45. package/dist/protection/ratelimit.d.ts +154 -0
  46. package/dist/protection/ratelimit.test.d.ts +1 -0
  47. package/dist/protection/waf.d.ts +143 -0
  48. package/dist/protection/waf.test.d.ts +1 -0
  49. package/dist/spend/anomaly-config.d.ts +130 -0
  50. package/dist/spend/anomaly-config.test.d.ts +1 -0
  51. package/dist/spend/anomaly.d.ts +114 -0
  52. package/dist/spend/anomaly.test.d.ts +1 -0
  53. package/dist/spend/api.d.ts +42 -0
  54. package/dist/spend/api.test.d.ts +1 -0
  55. package/dist/spend/appliers.d.ts +126 -0
  56. package/dist/spend/docs.test.d.ts +1 -0
  57. package/dist/spend/enforcement.d.ts +111 -0
  58. package/dist/spend/enforcement.integration.test.d.ts +1 -0
  59. package/dist/spend/evaluator.d.ts +70 -0
  60. package/dist/spend/evaluator.test.d.ts +1 -0
  61. package/dist/spend/focus.d.ts +93 -0
  62. package/dist/spend/focus.test.d.ts +1 -0
  63. package/dist/spend/gate.d.ts +96 -0
  64. package/dist/spend/index.d.ts +20 -0
  65. package/dist/spend/index.js +173 -0
  66. package/dist/spend/lease.d.ts +54 -0
  67. package/dist/spend/lease.test.d.ts +1 -0
  68. package/dist/spend/meter.d.ts +70 -0
  69. package/dist/spend/meter.test.d.ts +1 -0
  70. package/dist/spend/model.d.ts +228 -0
  71. package/dist/spend/notifications.d.ts +58 -0
  72. package/dist/spend/pricing.d.ts +109 -0
  73. package/dist/spend/pricing.test.d.ts +1 -0
  74. package/dist/spend/projection.d.ts +36 -0
  75. package/dist/spend/runner.d.ts +130 -0
  76. package/dist/spend/service.d.ts +129 -0
  77. package/dist/spend/signals.d.ts +110 -0
  78. package/dist/spend/signals.test.d.ts +1 -0
  79. package/dist/spend/sms-sdk.test.d.ts +1 -0
  80. package/dist/spend/spend.integration.test.d.ts +1 -0
  81. package/dist/spend/store.d.ts +166 -0
  82. package/dist/spend/transports.d.ts +169 -0
  83. package/dist/spend/transports.test.d.ts +1 -0
  84. package/dist/spend/window.d.ts +52 -0
  85. package/dist/spend/window.test.d.ts +1 -0
  86. package/dist/ui/404.html +2 -0
  87. package/dist/ui/access-denied.html +2 -2
  88. package/dist/ui/account/automation.html +4 -4
  89. package/dist/ui/account/security.html +2 -2
  90. package/dist/ui/applications/compose.html +4 -4
  91. package/dist/ui/applications/new.html +2 -2
  92. package/dist/ui/data/backups.html +22 -9
  93. package/dist/ui/data/services.html +22 -9
  94. package/dist/ui/data/volumes.html +22 -9
  95. package/dist/ui/index.html +22 -9
  96. package/dist/ui/infrastructure/topology.html +2223 -0
  97. package/dist/ui/integrations.html +2 -2
  98. package/dist/ui/operations/alerts.html +22 -9
  99. package/dist/ui/operations/configuration.html +4 -4
  100. package/dist/ui/operations/jobs.html +22 -9
  101. package/dist/ui/operations/maintenance.html +4 -4
  102. package/dist/ui/operations/observability.html +22 -9
  103. package/dist/ui/operations/previews.html +4 -4
  104. package/dist/ui/operations/queue.html +4 -4
  105. package/dist/ui/operations/regions.html +3 -3
  106. package/dist/ui/operations/releases.html +3 -3
  107. package/dist/ui/operations/spend.html +1634 -0
  108. package/dist/ui/operations/workloads.html +22 -9
  109. package/dist/ui/security.html +2 -2
  110. package/dist/ui/server/actions.html +4 -4
  111. package/dist/ui/server/activity.html +2 -2
  112. package/dist/ui/server/capacity.html +4 -4
  113. package/dist/ui/server/database.html +4 -4
  114. package/dist/ui/server/deployments.html +4 -4
  115. package/dist/ui/server/diagnostics.html +2 -2
  116. package/dist/ui/server/firewall.html +100 -161
  117. package/dist/ui/server/fleet.html +22 -9
  118. package/dist/ui/server/logs.html +22 -9
  119. package/dist/ui/server/metrics.html +130 -14
  120. package/dist/ui/server/security.html +2 -2
  121. package/dist/ui/server/services.html +1 -1
  122. package/dist/ui/server/sites.html +22 -9
  123. package/dist/ui/server/ssh-keys.html +3 -3
  124. package/dist/ui/server/team.html +4 -4
  125. package/dist/ui/server/terminal.html +2 -2
  126. package/dist/ui/serverless/alarms.html +4 -4
  127. package/dist/ui/serverless/assets.html +2 -2
  128. package/dist/ui/serverless/cost.html +2 -2
  129. package/dist/ui/serverless/data.html +4 -4
  130. package/dist/ui/serverless/deployments.html +2 -2
  131. package/dist/ui/serverless/firewall.html +2 -2
  132. package/dist/ui/serverless/functions.html +4 -4
  133. package/dist/ui/serverless/logs.html +22 -9
  134. package/dist/ui/serverless/metrics.html +2 -2
  135. package/dist/ui/serverless/queues.html +4 -4
  136. package/dist/ui/serverless/secrets.html +4 -4
  137. package/dist/ui/serverless/traces.html +4 -4
  138. package/dist/ui/serverless.html +4 -4
  139. package/dist/ui-src/functions/requestJson.ts +41 -0
  140. package/dist/ui-src/functions/useOpConfirm.ts +132 -0
  141. package/dist/ui-src/functions/usePolling.ts +98 -0
  142. package/dist/ui-src/functions/useTerminal.ts +79 -0
  143. package/dist/ui-src/pages/infrastructure/topology.stx +517 -0
  144. package/dist/ui-src/pages/operations/spend.stx +225 -0
  145. package/dist/ui-src/pages/partials/nav.stx +4 -0
  146. package/dist/ui-src/pages/server/firewall.stx +89 -0
  147. package/dist/ui-src/pages/server/metrics.stx +140 -6
  148. package/dist/ui-src/src/topology.ts +485 -0
  149. package/package.json +11 -3
@@ -1,14 +1,3 @@
1
- import {
2
- deploymentCoexistenceError,
3
- hasManagementDashboardSite,
4
- isManagementDashboardSiteName,
5
- resolveAppDatabase,
6
- resolveCloudProvider,
7
- resolveManagementDashboardSites,
8
- resolveProjectStackName,
9
- resolveStatePath,
10
- statePath
11
- } from "./chunk-c6db5m63.js";
12
1
  import {
13
2
  EC2Client,
14
3
  SSMClient
@@ -19,6 +8,23 @@ import {
19
8
  import {
20
9
  S3Client
21
10
  } from "./chunk-wj3s95p9.js";
11
+ import {
12
+ renderWafInstallScript
13
+ } from "./chunk-va2yd85b.js";
14
+ import {
15
+ renderDdosInstallScript
16
+ } from "./chunk-aa2dkn7b.js";
17
+ import {
18
+ deploymentCoexistenceError,
19
+ hasManagementDashboardSite,
20
+ isManagementDashboardSiteName,
21
+ resolveAppDatabase,
22
+ resolveCloudProvider,
23
+ resolveManagementDashboardSites,
24
+ resolveProjectStackName,
25
+ resolveStatePath,
26
+ statePath
27
+ } from "./chunk-t2s3gdq6.js";
22
28
  import {
23
29
  __require
24
30
  } from "./chunk-v0bahtg2.js";
@@ -752,9 +758,12 @@ function buildAutoUpdatesScript(enabled3 = true) {
752
758
  // src/drivers/shared/monitoring.ts
753
759
  var METRICS_PATH = "/var/lib/ts-cloud/metrics.json";
754
760
  var ALERT_STATE_PATH = "/var/lib/ts-cloud/alert-state";
761
+ var BANDWIDTH_STATE_PATH = "/var/lib/ts-cloud/bandwidth-state";
762
+ var BANDWIDTH_ALERT_STATE_PATH = "/var/lib/ts-cloud/bandwidth-alert-state";
755
763
  var DEFAULT_CPU_LOAD_PER_CORE = 2;
756
764
  var DEFAULT_MEM_PERCENT = 90;
757
765
  var DEFAULT_DISK_PERCENT = 90;
766
+ var DEFAULT_BANDWIDTH_PERCENT = 80;
758
767
  var SERVICE_PROBES = [
759
768
  ["nginx", 80],
760
769
  ["https", 443],
@@ -769,17 +778,21 @@ var SERVICE_PROBES = [
769
778
  function resolveMonitoring(monitoring = true) {
770
779
  const obj = typeof monitoring === "object" ? monitoring : {};
771
780
  const enabled3 = typeof monitoring === "boolean" ? monitoring : monitoring.enabled !== false;
781
+ const bandwidthTb = Number(obj.alerts?.bandwidthTb ?? 0);
772
782
  return {
773
783
  enabled: enabled3,
774
784
  cpuLoadPerCore: obj.alerts?.cpuLoadPerCore ?? DEFAULT_CPU_LOAD_PER_CORE,
775
785
  memPercent: obj.alerts?.memPercent ?? DEFAULT_MEM_PERCENT,
776
- diskPercent: obj.alerts?.diskPercent ?? DEFAULT_DISK_PERCENT
786
+ diskPercent: obj.alerts?.diskPercent ?? DEFAULT_DISK_PERCENT,
787
+ bandwidthTb: Number.isFinite(bandwidthTb) && bandwidthTb > 0 ? bandwidthTb : 0,
788
+ bandwidthPercent: obj.alerts?.bandwidthPercent ?? DEFAULT_BANDWIDTH_PERCENT
777
789
  };
778
790
  }
779
791
  function buildMonitoringScript(monitoring = true) {
780
- const { enabled: enabled3, cpuLoadPerCore, memPercent, diskPercent } = resolveMonitoring(monitoring);
792
+ const { enabled: enabled3, cpuLoadPerCore, memPercent, diskPercent, bandwidthTb, bandwidthPercent } = resolveMonitoring(monitoring);
781
793
  if (!enabled3)
782
794
  return [];
795
+ const bandwidthBudgetBytes = Math.round(bandwidthTb * 1000 ** 4);
783
796
  const probeLines = SERVICE_PROBES.map(([name, port]) => `SVC_${name.toUpperCase()}=$(probe ${port})`);
784
797
  const servicesJson = SERVICE_PROBES.map(([name]) => `"${name}":"$SVC_${name.toUpperCase()}"`).join(",");
785
798
  return [
@@ -798,6 +811,36 @@ EOF`,
798
811
  `UPTIME_SEC=$(cut -d' ' -f1 /proc/uptime | cut -d. -f1)`,
799
812
  `RX_BYTES=$(awk -F'[: ]+' 'NR>2 && $2!="lo"{rx+=$3} END{print rx+0}' /proc/net/dev)`,
800
813
  `TX_BYTES=$(awk -F'[: ]+' 'NR>2 && $2!="lo"{tx+=$11} END{print tx+0}' /proc/net/dev)`,
814
+ "NOW_EPOCH=$(date -u +%s); TODAY=$(date -u +%Y-%m-%d); MONTH=$(date -u +%Y-%m)",
815
+ `if [ -r ${BANDWIDTH_STATE_PATH} ]; then . ${BANDWIDTH_STATE_PATH}; fi`,
816
+ "PREV_EPOCH=${PREV_EPOCH:-0}; PREV_RX=${PREV_RX:-0}; PREV_TX=${PREV_TX:-0}",
817
+ "DAY_KEY=${DAY_KEY:-$TODAY}; MONTH_KEY=${MONTH_KEY:-$MONTH}",
818
+ "DAY_RX=${DAY_RX:-0}; DAY_TX=${DAY_TX:-0}; MONTH_RX=${MONTH_RX:-0}; MONTH_TX=${MONTH_TX:-0}",
819
+ "ELAPSED=$(( NOW_EPOCH - PREV_EPOCH ))",
820
+ 'if [ "$PREV_EPOCH" -le 0 ] || [ "$ELAPSED" -le 0 ] || [ "$RX_BYTES" -lt "$PREV_RX" ] || [ "$TX_BYTES" -lt "$PREV_TX" ]; then',
821
+ " DELTA_RX=0; DELTA_TX=0; ELAPSED=0",
822
+ "else",
823
+ " DELTA_RX=$(( RX_BYTES - PREV_RX )); DELTA_TX=$(( TX_BYTES - PREV_TX ))",
824
+ "fi",
825
+ 'if [ "$DAY_KEY" != "$TODAY" ]; then DAY_KEY=$TODAY; DAY_RX=0; DAY_TX=0; fi',
826
+ 'if [ "$MONTH_KEY" != "$MONTH" ]; then MONTH_KEY=$MONTH; MONTH_RX=0; MONTH_TX=0; fi',
827
+ "DAY_RX=$(( DAY_RX + DELTA_RX )); DAY_TX=$(( DAY_TX + DELTA_TX ))",
828
+ "MONTH_RX=$(( MONTH_RX + DELTA_RX )); MONTH_TX=$(( MONTH_TX + DELTA_TX ))",
829
+ 'if [ "$ELAPSED" -gt 0 ]; then RX_RATE=$(( DELTA_RX / ELAPSED )); TX_RATE=$(( DELTA_TX / ELAPSED )); else RX_RATE=0; TX_RATE=0; fi',
830
+ `cat > ${BANDWIDTH_STATE_PATH}.tmp <<BWSTATE`,
831
+ "PREV_EPOCH=$NOW_EPOCH",
832
+ "PREV_RX=$RX_BYTES",
833
+ "PREV_TX=$TX_BYTES",
834
+ "RX_RATE=$RX_RATE",
835
+ "TX_RATE=$TX_RATE",
836
+ "DAY_KEY=$DAY_KEY",
837
+ "DAY_RX=$DAY_RX",
838
+ "DAY_TX=$DAY_TX",
839
+ "MONTH_KEY=$MONTH_KEY",
840
+ "MONTH_RX=$MONTH_RX",
841
+ "MONTH_TX=$MONTH_TX",
842
+ "BWSTATE",
843
+ `mv -f ${BANDWIDTH_STATE_PATH}.tmp ${BANDWIDTH_STATE_PATH}`,
801
844
  "probe(){ (exec 3<>/dev/tcp/127.0.0.1/$1) 2>/dev/null && echo up || echo down; }",
802
845
  ...probeLines,
803
846
  "LOAD=${LOAD:-0}; CPUS=${CPUS:-1}; MEM_TOTAL=${MEM_TOTAL:-0}; MEM_USED=${MEM_USED:-0}",
@@ -805,7 +848,7 @@ EOF`,
805
848
  "UPTIME_SEC=${UPTIME_SEC:-0}; RX_BYTES=${RX_BYTES:-0}; TX_BYTES=${TX_BYTES:-0}",
806
849
  "MEM_PCT=$(( MEM_TOTAL > 0 ? MEM_USED * 100 / MEM_TOTAL : 0 ))",
807
850
  `cat > ${METRICS_PATH}.tmp <<JSON`,
808
- '{"load":$LOAD,"cpus":$CPUS,"memTotalMb":$MEM_TOTAL,"memUsedMb":$MEM_USED,"memUsedPct":$MEM_PCT,"swapTotalMb":$SWAP_TOTAL,"swapUsedMb":$SWAP_USED,"diskUsedPct":$DISK_PCT,"uptimeSec":$UPTIME_SEC,"network":{"rxBytes":$RX_BYTES,"txBytes":$TX_BYTES},"services":{' + servicesJson + "}}",
851
+ '{"load":$LOAD,"cpus":$CPUS,"memTotalMb":$MEM_TOTAL,"memUsedMb":$MEM_USED,"memUsedPct":$MEM_PCT,"swapTotalMb":$SWAP_TOTAL,"swapUsedMb":$SWAP_USED,"diskUsedPct":$DISK_PCT,"uptimeSec":$UPTIME_SEC,' + '"network":{"rxBytes":$RX_BYTES,"txBytes":$TX_BYTES,"rxBytesPerSec":$RX_RATE,"txBytesPerSec":$TX_RATE,' + '"dayKey":"$DAY_KEY","rxBytesToday":$DAY_RX,"txBytesToday":$DAY_TX,' + `"monthKey":"$MONTH_KEY","rxBytesMonth":$MONTH_RX,"txBytesMonth":$MONTH_TX,"budgetBytes":${bandwidthBudgetBytes}},"services":{` + servicesJson + "}}",
809
852
  "JSON",
810
853
  `mv -f ${METRICS_PATH}.tmp ${METRICS_PATH}`,
811
854
  'ALERTS=""',
@@ -820,6 +863,18 @@ EOF`,
820
863
  ' if [ "$PREV" = alert ] && [ -x /usr/local/bin/ts-cloud-notify ]; then /usr/local/bin/ts-cloud-notify "✅ $(hostname): resource usage back to normal" || true; fi',
821
864
  ` echo ok > ${ALERT_STATE_PATH}`,
822
865
  "fi",
866
+ ...bandwidthBudgetBytes > 0 ? [
867
+ "BW_TOTAL=$(( MONTH_RX + MONTH_TX ))",
868
+ `BW_PCT=$(( BW_TOTAL * 100 / ${bandwidthBudgetBytes} ))`,
869
+ `BW_PREV=$(cat ${BANDWIDTH_ALERT_STATE_PATH} 2>/dev/null || echo ok)`,
870
+ `if [ "$BW_PCT" -ge ${bandwidthPercent} ]; then`,
871
+ ` if [ "$BW_PREV" != alert ] && [ -x /usr/local/bin/ts-cloud-notify ]; then /usr/local/bin/ts-cloud-notify "⚠️ $(hostname): bandwidth at \${BW_PCT}% of the ${bandwidthTb} TB monthly allowance ($MONTH_KEY)" || true; fi`,
872
+ ` echo alert > ${BANDWIDTH_ALERT_STATE_PATH}`,
873
+ "else",
874
+ ` if [ "$BW_PREV" = alert ] && [ -x /usr/local/bin/ts-cloud-notify ]; then /usr/local/bin/ts-cloud-notify "✅ $(hostname): bandwidth back under the monthly allowance (\${BW_PCT}%)" || true; fi`,
875
+ ` echo ok > ${BANDWIDTH_ALERT_STATE_PATH}`,
876
+ "fi"
877
+ ] : [],
823
878
  "TS_CLOUD_METRICS_EOF",
824
879
  "chmod +x /usr/local/bin/ts-cloud-metrics.sh",
825
880
  `cat > /etc/systemd/system/ts-cloud-metrics.service <<'TS_CLOUD_METRICS_SVC_EOF'`,
@@ -1877,6 +1932,45 @@ function escapeSed(value) {
1877
1932
  return value.replace(/[.*[\]\\/^$]/g, "\\$&");
1878
1933
  }
1879
1934
 
1935
+ // src/drivers/shared/protection.ts
1936
+ function runAsScript(name, script) {
1937
+ const path = `/tmp/ts-cloud-${name}.sh`;
1938
+ const marker = `TS_CLOUD_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_EOF`;
1939
+ return [
1940
+ `cat > ${path} <<'${marker}'`,
1941
+ script.replace(/\n$/, ""),
1942
+ marker,
1943
+ `chmod +x ${path}`,
1944
+ `bash ${path} || echo "ts-cloud: ${name} setup did not complete; continuing" >&2`,
1945
+ `rm -f ${path}`
1946
+ ];
1947
+ }
1948
+ function resolve(setting, fallback) {
1949
+ if (setting === false)
1950
+ return;
1951
+ if (setting === true || setting === undefined)
1952
+ return fallback;
1953
+ return setting;
1954
+ }
1955
+ var DEFAULT_COMPUTE_DDOS = { enabled: true, ports: [80, 443] };
1956
+ var DEFAULT_COMPUTE_WAF = { mode: "detection", paranoiaLevel: 1 };
1957
+ function buildDdosScript(setting = true, extraPorts = []) {
1958
+ const config = resolve(setting, DEFAULT_COMPUTE_DDOS);
1959
+ if (!config || config.enabled === false)
1960
+ return [];
1961
+ const ports = [...new Set([...config.ports ?? DEFAULT_COMPUTE_DDOS.ports ?? [], ...extraPorts])].sort((a, b) => a - b);
1962
+ return runAsScript("ddos", renderDdosInstallScript({ ...config, ports }));
1963
+ }
1964
+ function buildWafScript(setting = true) {
1965
+ const config = resolve(setting, DEFAULT_COMPUTE_WAF);
1966
+ if (!config || config.mode === "off")
1967
+ return [];
1968
+ return runAsScript("waf", renderWafInstallScript(config));
1969
+ }
1970
+ function buildProtectionScript(protection = {}, extraPorts = []) {
1971
+ return [...buildDdosScript(protection.ddos, extraPorts), ...buildWafScript(protection.waf)];
1972
+ }
1973
+
1880
1974
  // src/drivers/shared/ufw.ts
1881
1975
  var UFW_BASE_PORTS = [80, 443];
1882
1976
  function buildUfwScript(firewall = {}) {
@@ -1925,6 +2019,7 @@ function buildComputeProvisionScripts(config) {
1925
2019
  extras.push(...buildServicesProvisionScript(compute.managedServices), ...buildDatabaseSetupScript(appDatabase, compute.managedServices));
1926
2020
  }
1927
2021
  extras.push(...buildUfwScript(compute.firewall ?? (phpBox ? { enabled: true } : { enabled: false })));
2022
+ extras.push(...buildProtectionScript({ ddos: compute.ddos, waf: compute.waf }, compute.firewall?.allowedPorts ?? []));
1928
2023
  extras.push(...buildAutoUpdatesScript(compute.autoUpdates ?? phpBox));
1929
2024
  extras.push(...buildMonitoringScript(compute.monitoring ?? phpBox));
1930
2025
  extras.push(...buildAuthorizedKeysScript(compute.sshKeys));
@@ -2458,7 +2553,7 @@ class AwsDriver {
2458
2553
  const terminalStatuses = new Set(["Success", "Failed", "Cancelled", "TimedOut"]);
2459
2554
  let lastInvocations = [];
2460
2555
  while (Date.now() - startTime < maxWait) {
2461
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
2556
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
2462
2557
  try {
2463
2558
  const invocations = await ssm.listCommandInvocations({ CommandId: commandId, Details: true });
2464
2559
  lastInvocations = invocations;
@@ -2837,7 +2932,7 @@ class HetznerClient {
2837
2932
  while (Date.now() - start < grace) {
2838
2933
  if ((await this.getServer(serverId)).status === "off")
2839
2934
  return;
2840
- await new Promise((resolve) => setTimeout(resolve, poll));
2935
+ await new Promise((resolve2) => setTimeout(resolve2, poll));
2841
2936
  }
2842
2937
  const action = await this.powerOffServer(serverId);
2843
2938
  await this.waitForAction(action.id);
@@ -2892,7 +2987,7 @@ class HetznerClient {
2892
2987
  if (action.status === "error") {
2893
2988
  throw new HetznerActionError(action.error?.message || "Hetzner action failed", action);
2894
2989
  }
2895
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
2990
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
2896
2991
  }
2897
2992
  throw new Error(`Timed out waiting for Hetzner action ${actionId}`);
2898
2993
  }
@@ -2904,7 +2999,7 @@ class HetznerClient {
2904
2999
  const server = await this.getServer(serverId);
2905
3000
  if (server.status === "running")
2906
3001
  return server;
2907
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
3002
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
2908
3003
  }
2909
3004
  throw new Error(`Timed out waiting for server ${serverId} to reach running state`);
2910
3005
  }
@@ -2916,7 +3011,7 @@ class HetznerClient {
2916
3011
  const server = await this.getServer(serverId);
2917
3012
  if (server.status === status)
2918
3013
  return server;
2919
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
3014
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
2920
3015
  }
2921
3016
  throw new Error(`Timed out waiting for server ${serverId} to reach ${status} state`);
2922
3017
  }
@@ -3864,7 +3959,7 @@ class HetznerDriver {
3864
3959
  return [...ports].filter((port) => ![80, 443].includes(port));
3865
3960
  }
3866
3961
  async sleep(ms) {
3867
- await new Promise((resolve) => setTimeout(resolve, ms));
3962
+ await new Promise((resolve2) => setTimeout(resolve2, ms));
3868
3963
  }
3869
3964
  async waitForSshReady(host) {
3870
3965
  const { sshIntervalMs, sshTimeoutMs } = this.bootWait;
@@ -4275,7 +4370,7 @@ async function waitForSsh(host, options = {}) {
4275
4370
  const r = await sshExec(host, "echo ready", options);
4276
4371
  if (r.code === 0 && r.stdout.includes("ready"))
4277
4372
  return;
4278
- await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
4373
+ await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
4279
4374
  }
4280
4375
  throw new Error(`SSH not ready on ${host} after ${timeoutMs}ms`);
4281
4376
  }
@@ -4289,7 +4384,7 @@ async function waitForCloudInit(host, options = {}) {
4289
4384
  return;
4290
4385
  if (r.stdout.includes("status: error"))
4291
4386
  throw new Error(`cloud-init reported an error on ${host}; check /var/log/cloud-init-output.log`);
4292
- await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
4387
+ await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
4293
4388
  }
4294
4389
  throw new Error(`cloud-init did not finish on ${host} after ${timeoutMs}ms`);
4295
4390
  }
@@ -4885,7 +4980,7 @@ class HetznerBoxProvisioner {
4885
4980
  } catch {
4886
4981
  if (i === 9)
4887
4982
  break;
4888
- await new Promise((resolve) => setTimeout(resolve, 3000));
4983
+ await new Promise((resolve2) => setTimeout(resolve2, 3000));
4889
4984
  }
4890
4985
  }
4891
4986
  }
@@ -4925,7 +5020,7 @@ class AwsBoxProvisioner {
4925
5020
  const instance = await this.ec2.getInstance(instanceId);
4926
5021
  if (instance?.State?.Name === "running" && instance.PublicIpAddress)
4927
5022
  return instance;
4928
- await new Promise((resolve) => setTimeout(resolve, 5000));
5023
+ await new Promise((resolve2) => setTimeout(resolve2, 5000));
4929
5024
  }
4930
5025
  throw new Error(`EC2 instance ${instanceId} did not reach running with a public IP within ${timeoutMs}ms`);
4931
5026
  }
@@ -5001,7 +5096,7 @@ class AwsBoxProvisioner {
5001
5096
  const current = await this.ec2.getInstance(instance.InstanceId);
5002
5097
  if (!current || current.State?.Name === "terminated")
5003
5098
  break;
5004
- await new Promise((resolve) => setTimeout(resolve, 5000));
5099
+ await new Promise((resolve2) => setTimeout(resolve2, 5000));
5005
5100
  }
5006
5101
  }
5007
5102
  const groups = await this.ec2.describeSecurityGroups({
@@ -5017,7 +5112,7 @@ class AwsBoxProvisioner {
5017
5112
  } catch {
5018
5113
  if (i === 9)
5019
5114
  break;
5020
- await new Promise((resolve) => setTimeout(resolve, 3000));
5115
+ await new Promise((resolve2) => setTimeout(resolve2, 3000));
5021
5116
  }
5022
5117
  }
5023
5118
  }
@@ -5452,7 +5547,7 @@ import { execSync as execSync2 } from "node:child_process";
5452
5547
  import { randomBytes } from "node:crypto";
5453
5548
  import { chmodSync, copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3, statSync, writeFileSync } from "node:fs";
5454
5549
  import { tmpdir } from "node:os";
5455
- import { basename, dirname, isAbsolute, join as join5, resolve } from "node:path";
5550
+ import { basename, dirname, isAbsolute, join as join5, resolve as resolve2 } from "node:path";
5456
5551
  import { fileURLToPath } from "node:url";
5457
5552
 
5458
5553
  // src/deploy/dashboard-config-module.ts
@@ -5572,7 +5667,7 @@ function stageLiveDashboardRoot(config, cwd, logger) {
5572
5667
  let dependency = resolveDashboardVersion();
5573
5668
  if (dependency.startsWith("file:")) {
5574
5669
  const requested = dependency.slice("file:".length);
5575
- const source = isAbsolute(requested) ? requested : resolve(cwd, requested);
5670
+ const source = isAbsolute(requested) ? requested : resolve2(cwd, requested);
5576
5671
  if (!existsSync2(source) || !statSync(source).isFile()) {
5577
5672
  dependency = resolvePackagedDashboardVersion();
5578
5673
  logger.warn(`Management dashboard: TS_CLOUD_UI_VERSION points to a missing package file (${source}); using the deploying ts-cloud version ${dependency} instead.`);