@stacksjs/ts-cloud 0.16.91 → 0.16.92

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 (65) hide show
  1. package/dist/bin/{chunk-97j6xrfe.js → chunk-00arzt4m.js} +1 -1
  2. package/dist/bin/{chunk-vbsk8b9d.js → chunk-eb591jvz.js} +1 -1
  3. package/dist/bin/{chunk-g21yhm1b.js → chunk-v72zwetk.js} +1 -1
  4. package/dist/bin/cli.js +4 -4
  5. package/dist/bin/dashboard-server.js +1 -1
  6. package/dist/{chunk-n95wbpge.js → chunk-cjm5j58y.js} +1 -1
  7. package/dist/{chunk-mvmxy0z7.js → chunk-zjkxhvn0.js} +1 -1
  8. package/dist/deploy/index.js +1 -1
  9. package/dist/drivers/index.js +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/ui/404.html +1 -1
  12. package/dist/ui/accept-invitation.html +1 -1
  13. package/dist/ui/access-denied.html +1 -1
  14. package/dist/ui/account/automation.html +5 -5
  15. package/dist/ui/account/security.html +1 -1
  16. package/dist/ui/applications/compose.html +5 -5
  17. package/dist/ui/applications/new.html +1 -1
  18. package/dist/ui/data/backups.html +6 -6
  19. package/dist/ui/data/services.html +6 -6
  20. package/dist/ui/data/volumes.html +6 -6
  21. package/dist/ui/index.html +6 -6
  22. package/dist/ui/infrastructure/topology.html +5 -5
  23. package/dist/ui/integrations.html +2 -2
  24. package/dist/ui/operations/alerts.html +6 -6
  25. package/dist/ui/operations/configuration.html +6 -6
  26. package/dist/ui/operations/jobs.html +6 -6
  27. package/dist/ui/operations/maintenance.html +5 -5
  28. package/dist/ui/operations/observability.html +6 -6
  29. package/dist/ui/operations/previews.html +6 -6
  30. package/dist/ui/operations/queue.html +6 -6
  31. package/dist/ui/operations/regions.html +5 -5
  32. package/dist/ui/operations/releases.html +6 -6
  33. package/dist/ui/operations/spend.html +6 -6
  34. package/dist/ui/operations/workloads.html +6 -6
  35. package/dist/ui/security.html +1 -1
  36. package/dist/ui/server/actions.html +6 -6
  37. package/dist/ui/server/activity.html +1 -1
  38. package/dist/ui/server/capacity.html +6 -6
  39. package/dist/ui/server/database.html +6 -6
  40. package/dist/ui/server/deployments.html +5 -5
  41. package/dist/ui/server/diagnostics.html +2 -2
  42. package/dist/ui/server/firewall.html +6 -6
  43. package/dist/ui/server/fleet.html +6 -6
  44. package/dist/ui/server/logs.html +5 -5
  45. package/dist/ui/server/metrics.html +5 -5
  46. package/dist/ui/server/security.html +2 -2
  47. package/dist/ui/server/services.html +1 -1
  48. package/dist/ui/server/sites.html +5 -5
  49. package/dist/ui/server/ssh-keys.html +5 -5
  50. package/dist/ui/server/team.html +5 -5
  51. package/dist/ui/server/terminal.html +2 -2
  52. package/dist/ui/serverless/alarms.html +6 -6
  53. package/dist/ui/serverless/assets.html +2 -2
  54. package/dist/ui/serverless/cost.html +2 -2
  55. package/dist/ui/serverless/data.html +6 -6
  56. package/dist/ui/serverless/deployments.html +2 -2
  57. package/dist/ui/serverless/firewall.html +1 -1
  58. package/dist/ui/serverless/functions.html +5 -5
  59. package/dist/ui/serverless/logs.html +6 -6
  60. package/dist/ui/serverless/metrics.html +2 -2
  61. package/dist/ui/serverless/queues.html +6 -6
  62. package/dist/ui/serverless/secrets.html +5 -5
  63. package/dist/ui/serverless/traces.html +6 -6
  64. package/dist/ui/serverless.html +6 -6
  65. package/package.json +3 -3
@@ -160,7 +160,7 @@ await (${Ls.toString()})(JSON.parse(await Bun.file(process.env.TS_CLOUD_STORAGE_
160
160
  [Service]
161
161
  MemoryAccounting=true
162
162
  MemoryHigh=%sM
163
- ' "$TS_CLOUD_MEM_MB" "$TS_CLOUD_HIGH_MB" > /etc/systemd/system/${e}.d/50-ts-cloud-memory.conf`,"systemctl daemon-reload",'echo "[ts-cloud] memoryHigh=auto resolved to ${TS_CLOUD_HIGH_MB}M (one eighth of ${TS_CLOUD_MEM_MB}M)"',...An()]}function wr(e,t={auto:!0}){let r=t.auto===!1?[]:[`/etc/systemd/system/${e}.d/50-ts-cloud-memory.conf`];for(let n of["/etc/systemd/system.control","/run/systemd/system.control"]){if(t.high)r.push(`${n}/${e}.d/50-MemoryHigh.conf`);if(t.max)r.push(`${n}/${e}.d/50-MemoryMax.conf`)}if(r.length===0)return[];return["TS_CLOUD_MEM_CLEARED=0",...r.map((n)=>`if [ -f ${n} ]; then rm -f ${n}; TS_CLOUD_MEM_CLEARED=1; echo "[ts-cloud] removed ${n}: memory limits now come from config"; fi`),'if [ "$TS_CLOUD_MEM_CLEARED" = 1 ]; then systemctl daemon-reload; fi']}function An(){return[`TS_CLOUD_COMMIT=$(for f in /sys/fs/cgroup/system.slice/*.service/memory.high /sys/fs/cgroup/system.slice/*.slice/*.service/memory.high; do [ -f "$f" ] || continue; v=$(cat "$f" 2>/dev/null); [ "$v" = "max" ] && continue; echo "$v"; done | awk '{s+=$1} END {print int(s/1048576)}')`,"TS_CLOUD_RAM=$(awk '/^MemTotal:/{print int($2/1024)}' /proc/meminfo)",'if [ -n "$TS_CLOUD_COMMIT" ] && [ "$TS_CLOUD_COMMIT" -gt 0 ] && [ "$TS_CLOUD_RAM" -gt 0 ]; then TS_CLOUD_PCT=$((TS_CLOUD_COMMIT * 100 / TS_CLOUD_RAM)); if [ "$TS_CLOUD_PCT" -gt 300 ]; then echo "[ts-cloud] WARNING: services on this box declare ${TS_CLOUD_COMMIT}M of MemoryHigh against ${TS_CLOUD_RAM}M of RAM (${TS_CLOUD_PCT}% committed). Soft ceilings, so this is not fatal - but no ceiling can protect the box once enough of them are drawn on at once."; else echo "[ts-cloud] memory commitment: ${TS_CLOUD_COMMIT}M declared against ${TS_CLOUD_RAM}M RAM (${TS_CLOUD_PCT}%)"; fi; fi']}function _c(e){return[`TS_CLOUD_SLICE=$(systemctl show ${e} -p Slice --value 2>/dev/null || true)`,'if [ -n "$TS_CLOUD_SLICE" ] && [ "$TS_CLOUD_SLICE" != "system.slice" ]; then systemctl set-property --runtime "$TS_CLOUD_SLICE" MemoryHigh=infinity MemoryMax=infinity 2>/dev/null || true; systemctl set-property "$TS_CLOUD_SLICE" MemoryHigh=infinity MemoryMax=infinity 2>/dev/null || true; fi']}var et={path:"/",intervalSeconds:60,failuresBeforeRestart:3,timeoutSeconds:10,startupGraceSeconds:600,maxBackoffSeconds:3600,backoffBaseSeconds:300};function jt(e,t,r){return typeof e==="number"&&Number.isFinite(e)?Math.max(r,Math.floor(e)):t}function Ws(e){let{unitBase:t,unitPattern:r,port:n}=e,s=e.path&&e.path.startsWith("/")?e.path:et.path,i=jt(e.intervalSeconds,et.intervalSeconds,10),a=jt(e.failuresBeforeRestart,et.failuresBeforeRestart,1),c=jt(e.timeoutSeconds,et.timeoutSeconds,1),f=jt(e.startupGraceSeconds,et.startupGraceSeconds,0),g=jt(e.maxBackoffSeconds,et.maxBackoffSeconds,0),h=Math.min(et.backoffBaseSeconds,g),S=`/usr/local/sbin/${t}-liveness`,_=`/run/${t}-liveness`,v=`${t}-liveness`,y=`127.0.0.1:${n}${s}`,L=r.includes("@*")?`TS_CLOUD_UNIT=$(systemctl list-units --plain --no-legend --type=service '${r}' 2>/dev/null | awk '{print $1}' | head -1)`:`TS_CLOUD_UNIT=${r}`;return[`cat > ${S} <<'TS_CLOUD_LIVENESS_EOF'`,"#!/bin/sh",`# Liveness check for ${t}, written by ts-cloud on every deploy.`,`# Settings: interval=${i}s timeout=${c}s failures=${a} startup-grace=${f}s max-backoff=${g}s`,"set -eu",`TS_CLOUD_STATE=${_}`,'exec 9>"$TS_CLOUD_STATE.lock"',"flock -n 9 || exit 0",L,'[ -n "$TS_CLOUD_UNIT" ] || exit 0','systemctl is-active --quiet "$TS_CLOUD_UNIT" || exit 0',"TS_CLOUD_RC=0",`curl -s -o /dev/null --max-time ${c} "http://${y}" || TS_CLOUD_RC=$?`,'if [ "$TS_CLOUD_RC" -eq 0 ]; then',' rm -f "$TS_CLOUD_STATE.fail"',' if [ -f "$TS_CLOUD_STATE.restarts" ]; then',` TS_CLOUD_LAST=$(awk '{print $2}' "$TS_CLOUD_STATE.restarts" 2>/dev/null || true)`,` case "$TS_CLOUD_LAST" in ''|*[!0-9]*) TS_CLOUD_LAST=0 ;; esac`,` [ $(($(date +%s) - TS_CLOUD_LAST)) -lt ${g} ] || rm -f "$TS_CLOUD_STATE.restarts"`," fi"," exit 0","fi",'case "$TS_CLOUD_RC" in'," 7) TS_CLOUD_WHY='connection refused' ;;",` 28) TS_CLOUD_WHY='no response within ${c}s' ;;`,' *) TS_CLOUD_WHY="curl exit $TS_CLOUD_RC" ;;',"esac",'TS_CLOUD_SINCE=$(systemctl show "$TS_CLOUD_UNIT" -p ActiveEnterTimestampMonotonic --value 2>/dev/null || true)',"TS_CLOUD_UPTIME=$(cut -d' ' -f1 /proc/uptime 2>/dev/null || true)",`TS_CLOUD_AGE=$(awk -v up="$TS_CLOUD_UPTIME" -v since="$TS_CLOUD_SINCE" 'BEGIN { if (since + 0 > 0 && up + 0 > 0) print int(up - since / 1000000); else print -1 }')`,`case "$TS_CLOUD_AGE" in ''|*[!0-9-]*) TS_CLOUD_AGE=-1 ;; esac`,'if [ "$TS_CLOUD_AGE" -lt 0 ]; then',' TS_CLOUD_PID=$(systemctl show "$TS_CLOUD_UNIT" -p MainPID --value 2>/dev/null || true)',` case "$TS_CLOUD_PID" in ''|0|*[!0-9]*) ;; *) TS_CLOUD_AGE=$(ps -o etimes= -p "$TS_CLOUD_PID" 2>/dev/null | tr -d ' ' || true) ;; esac`,` case "$TS_CLOUD_AGE" in ''|*[!0-9]*) TS_CLOUD_AGE=-1 ;; esac`,"fi",`if [ "$TS_CLOUD_AGE" -ge 0 ] && [ "$TS_CLOUD_AGE" -lt ${f} ]; then`,' rm -f "$TS_CLOUD_STATE.fail"',` logger -t ${v} "$TS_CLOUD_UNIT is \${TS_CLOUD_AGE}s old, inside its ${f}s startup grace; not counting this failed check on ${y} ($TS_CLOUD_WHY)"`," exit 0","fi",'TS_CLOUD_FAILS=$(cat "$TS_CLOUD_STATE.fail" 2>/dev/null || echo 0)',`case "$TS_CLOUD_FAILS" in ''|*[!0-9]*) TS_CLOUD_FAILS=0 ;; esac`,"TS_CLOUD_FAILS=$((TS_CLOUD_FAILS + 1))",'echo "$TS_CLOUD_FAILS" > "$TS_CLOUD_STATE.fail"',`if [ "$TS_CLOUD_FAILS" -lt ${a} ]; then`,` logger -t ${v} "check $TS_CLOUD_FAILS of ${a} failed on ${y} ($TS_CLOUD_WHY)"`," exit 0","fi","TS_CLOUD_NOW=$(date +%s)","TS_CLOUD_STREAK=0","TS_CLOUD_LAST=0",'[ ! -f "$TS_CLOUD_STATE.restarts" ] || read -r TS_CLOUD_STREAK TS_CLOUD_LAST < "$TS_CLOUD_STATE.restarts" || true',`case "$TS_CLOUD_STREAK" in ''|*[!0-9]*) TS_CLOUD_STREAK=0 ;; esac`,`case "$TS_CLOUD_LAST" in ''|*[!0-9]*) TS_CLOUD_LAST=0 ;; esac`,'if [ "$TS_CLOUD_STREAK" -gt 0 ]; then',` TS_CLOUD_WAIT=${h}`," TS_CLOUD_I=1",` while [ "$TS_CLOUD_I" -lt "$TS_CLOUD_STREAK" ] && [ "$TS_CLOUD_WAIT" -lt ${g} ]; do TS_CLOUD_WAIT=$((TS_CLOUD_WAIT * 2)); TS_CLOUD_I=$((TS_CLOUD_I + 1)); done`,` [ "$TS_CLOUD_WAIT" -le ${g} ] || TS_CLOUD_WAIT=${g}`," TS_CLOUD_ELAPSED=$((TS_CLOUD_NOW - TS_CLOUD_LAST))",' if [ "$TS_CLOUD_ELAPSED" -lt "$TS_CLOUD_WAIT" ]; then',` logger -t ${v} "holding off: $TS_CLOUD_STREAK liveness restart(s) in a row have not brought $TS_CLOUD_UNIT back; next restart allowed in $((TS_CLOUD_WAIT - TS_CLOUD_ELAPSED))s ($TS_CLOUD_WHY on ${y})"`," exit 0"," fi","fi","TS_CLOUD_STREAK=$((TS_CLOUD_STREAK + 1))",`logger -t ${v} "no HTTP response on ${y} after $TS_CLOUD_FAILS checks ($TS_CLOUD_WHY); restarting $TS_CLOUD_UNIT (liveness restart $TS_CLOUD_STREAK in a row)"`,'echo "$TS_CLOUD_STREAK $TS_CLOUD_NOW" > "$TS_CLOUD_STATE.restarts"','rm -f "$TS_CLOUD_STATE.fail"','systemctl restart "$TS_CLOUD_UNIT"',"TS_CLOUD_LIVENESS_EOF",`chmod +x ${S}`,`rm -f ${_}.fail ${_}.restarts`,`cat > /etc/systemd/system/${t}-liveness.service <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=Liveness check for ${t} (managed by ts-cloud)`,"","[Service]","Type=oneshot",`ExecStart=${S}`,"TS_CLOUD_UNIT_EOF",`cat > /etc/systemd/system/${t}-liveness.timer <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=Run the ${t} liveness check every ${i}s`,"","[Timer]",`OnUnitActiveSec=${i}s`,`OnBootSec=${i}s`,"Persistent=true","","[Install]","WantedBy=timers.target","TS_CLOUD_UNIT_EOF","systemctl daemon-reload",`systemctl enable --now ${t}-liveness.timer >/dev/null 2>&1 || true`]}var Ys=20,xn=3,vc=5,$c=60;function yc(e){let{paths:t,unitBase:r,releaseId:n,port:s}=e,i=`${r}@${n}.service`,a=`${r}.service`,c=Math.max(1,e.healthGateSeconds??5),f=e.healthCheckPath?e.healthCheckPath.startsWith("/")?e.healthCheckPath:`/${e.healthCheckPath}`:null,g=f?`curl -sf -o /dev/null --max-time ${vc} "http://127.0.0.1:${s}${f}"`:null,h=(S)=>`{ echo "[ts-cloud] release ${n} ${S}" >&2; ts_cloud_restore_previous; exit 1; }`;return[`TS_CLOUD_OLD_UNITS=$(systemctl list-units --plain --no-legend --type=service "${r}@*.service" 2>/dev/null | awk '{print $1}' | grep -v "^${i}$" || true)`,`TS_CLOUD_PREV_CURRENT="$(readlink ${t.current} 2>/dev/null || true)"`,"TS_CLOUD_LEGACY_STOPPED=0","ts_cloud_restore_previous() {",` journalctl -u ${i} -n 50 --no-pager >&2 || true`,` systemctl stop ${i} 2>/dev/null || true`,` systemctl disable ${i} 2>/dev/null || true`,` if [ -n "$TS_CLOUD_PREV_CURRENT" ] && [ -d "$TS_CLOUD_PREV_CURRENT" ]; then ln -sfn "$TS_CLOUD_PREV_CURRENT" ${t.current}.tmp && mv -Tf ${t.current}.tmp ${t.current}; fi`,' for TS_CLOUD_RU in ${TS_CLOUD_OLD_UNITS}; do systemctl enable "$TS_CLOUD_RU" 2>/dev/null || true; systemctl start "$TS_CLOUD_RU" 2>/dev/null || true; done',` if [ "$TS_CLOUD_LEGACY_STOPPED" -eq 1 ]; then systemctl start ${a} 2>/dev/null || true; fi`,' if [ -n "$TS_CLOUD_OLD_UNITS" ] || [ "$TS_CLOUD_LEGACY_STOPPED" -eq 1 ]; then echo "[ts-cloud] previous release restored and serving" >&2; else echo "[ts-cloud] there was no previous release to restore" >&2; fi',"}",`if [ -f /etc/systemd/system/${a} ] && systemctl is-active --quiet ${a}; then echo "[ts-cloud] retiring pre-zero-downtime unit ${a} (one-time restart cutover)"; systemctl stop ${a}; TS_CLOUD_LEGACY_STOPPED=1; fi`,'TS_CLOUD_STARTED_AT="@$(date +%s)"',`systemctl restart ${i}`,`TS_CLOUD_GATE_OK=1; for TS_CLOUD_I in $(seq 1 ${c}); do sleep 1; systemctl is-active --quiet ${i} || { TS_CLOUD_GATE_OK=0; break; }; done`,'if [ "$TS_CLOUD_GATE_OK" -ne 1 ]; then',` if journalctl -u ${i} --since "$TS_CLOUD_STARTED_AT" -o cat --no-pager 2>/dev/null | grep -iE 'EADDRINUSE|address already in use|port [0-9]+ (is )?in use|Failed to start server' >/dev/null; then`,` echo "[ts-cloud] release ${n} could not share :${s} with the previous release (no SO_REUSEPORT?) — retiring it and retrying" >&2`,' for TS_CLOUD_RU in ${TS_CLOUD_OLD_UNITS}; do systemctl stop "$TS_CLOUD_RU" 2>/dev/null || true; done',` systemctl restart ${i}`,` for TS_CLOUD_I in $(seq 1 ${c}); do sleep 1; systemctl is-active --quiet ${i} || ${h("failed its health gate on the free port")}; done`," else",` ${h("crashed on start — the previous release was never stopped")}`," fi","fi",`if ss -ltnpH "sport = :${s}" >/dev/null 2>&1; then`," TS_CLOUD_BOUND=0",` for TS_CLOUD_I in $(seq 1 ${$c}); do`,` TS_CLOUD_NEW_PID="$(systemctl show -p MainPID --value ${i} 2>/dev/null || true)"`,` if [ -n "$TS_CLOUD_NEW_PID" ] && [ "$TS_CLOUD_NEW_PID" != "0" ] && ss -ltnpH "sport = :${s}" 2>/dev/null | grep "pid=$TS_CLOUD_NEW_PID," >/dev/null; then TS_CLOUD_BOUND=1; break; fi`,` systemctl is-active --quiet ${i} || break`,` sleep ${xn}`," done",` [ "$TS_CLOUD_BOUND" -eq 1 ] || ${h(`never took :${s}`)}`,"else",' echo "[ts-cloud] cannot read listener PIDs on this host — the response probes run without the bind check" >&2',"fi",...g?[`TS_CLOUD_HEALTHY=0; for TS_CLOUD_I in $(seq 1 ${Ys}); do if ${g}; then TS_CLOUD_HEALTHY=1; break; fi; sleep ${xn}; done`,`[ "$TS_CLOUD_HEALTHY" -eq 1 ] || ${h(`never answered ${f}`)}`]:[],...dt(t),`systemctl enable ${i} 2>/dev/null || true`,'for TS_CLOUD_U in ${TS_CLOUD_OLD_UNITS}; do systemctl stop "$TS_CLOUD_U" 2>/dev/null || true; systemctl disable "$TS_CLOUD_U" 2>/dev/null || true; done',`TS_CLOUD_LISTENING=0; for TS_CLOUD_I in $(seq 1 ${c}); do if ss -ltnH "sport = :${s}" 2>/dev/null | grep . >/dev/null; then TS_CLOUD_LISTENING=1; break; fi; sleep 1; done`,`if [ "$TS_CLOUD_LISTENING" -ne 1 ]; then echo "[ts-cloud] nothing is listening on ${s} after retiring the previous release — restarting ${i} on the now-free port" >&2; systemctl restart ${i}; for TS_CLOUD_I in $(seq 1 ${c}); do if ss -ltnH "sport = :${s}" 2>/dev/null | grep . >/dev/null; then TS_CLOUD_LISTENING=1; break; fi; sleep 1; done; fi`,`[ "$TS_CLOUD_LISTENING" -eq 1 ] || ${h(`is active but never bound :${s}`)}`,...g?[`TS_CLOUD_HEALTHY=0; for TS_CLOUD_I in $(seq 1 ${Ys}); do if ${g}; then TS_CLOUD_HEALTHY=1; break; fi; sleep ${xn}; done`,`[ "$TS_CLOUD_HEALTHY" -eq 1 ] || ${h(`stopped answering ${f} once it served alone`)}`]:[],...Pn(t),`systemctl list-unit-files --plain --no-legend "${r}@*.service" 2>/dev/null | awk '{print $1}' | { grep -v -e "^${i}$" -e "^${r}@\\.service$" || true; } | while read -r TS_CLOUD_U; do systemctl disable "$TS_CLOUD_U" 2>/dev/null || true; done`,`if [ -f /etc/systemd/system/${a} ]; then systemctl disable ${a} 2>/dev/null || true; rm -f /etc/systemd/system/${a}; systemctl daemon-reload; fi`]}function Js(e,t){if(!t.length)return[];let r=Ve(e.release);return[`if [ -e ${r} ] || [ -L ${r} ]; then`,...t,"fi"]}function ai(e){let{siteName:t,slug:r,artifactFetch:n,releaseId:s,execStart:i,envEntries:a,port:c,keepReleases:f=Mt,preStartCommands:g=[],postActivateCommands:h=[],beforeResetCommands:S=[],healthCheckPath:_,healthGateSeconds:v=5,liveness:y,memoryHigh:T="auto",memoryMax:L,cpuWeight:j,ioWeight:M,tasksMax:O,stopTimeout:N}=e,k=[...j!=null?[`CPUWeight=${j}`]:[],...M!=null?[`IOWeight=${M}`]:[],...O!=null?[`TasksMax=${O}`]:[],...N?[`TimeoutStopSec=${N}`]:[]],G=e.zeroDowntime??c!=null,W=e.appDir??`/var/www/${t}`,B=er(W,s),re=`${r}-${t}`,ee=`${re}.service`,ne=di(r,t,s),ie=e.sharedPaths??[],ce=Ns([".env",...ie,...Tr(a,ie)]),se=hr(a),me=Xs(B.release,g,a),fe=["set -euo pipefail",...yn(B),...n,...Ft(B,ce),...Js(B,S),Tn(B),...bn(B),`tar xzf ${ne} -C "$TS_CLOUD_STAGED"`,`rm -f ${ne}`,`cat > ${B.shared}/.env <<'TS_CLOUD_ENV_EOF'`,se,"TS_CLOUD_ENV_EOF",`chmod 600 ${B.shared}/.env`,...wn(B),`find ${B.release} -maxdepth 1 \\( -type f -o -type l \\) -name '.env*' ! -name '.env.example' ! -name '*.example' -delete`,`sed -i -E '/^[[:space:]]*(PORT|PORT_BACKEND|PORT_ADMIN|PORT_FRONTEND)[[:space:]]*=/d' ${B.shared}/.env 2>/dev/null || true`,...yr(B,ce),...me,...e.isolation?Us(e.slug||t,B.base,ce.flatMap((X)=>typeof X==="string"||!X.target?[]:[X.target])):[]];if(G&&c!=null){let X=`${re}@${s}.service`,P=_?_.startsWith("/")?_:`/${_}`:null;return[...fe,`cat > /etc/systemd/system/${re}@.service <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=${t} release %i (managed by ts-cloud)`,"After=network.target","","[Service]","Type=simple",...e.isolation?Ht(pt(e.slug||t),B.base,e.slug||t):[],`WorkingDirectory=${B.releases}/%i`,`ExecStart=${i}`,"Restart=always","RestartSec=5","MemoryAccounting=true",...T&&T!=="auto"?[`MemoryHigh=${T}`]:[],...L?[`MemoryMax=${L}`]:[],...k,`EnvironmentFile=${B.releases}/%i/.env`,`Environment=PORT=${c}`,`Environment=STX_IMAGE_CACHE_DIR=${vr(B)}`,`Environment=STX_BUNDLE_CACHE_DIR=${zt(B)}`,`Environment=STX_BUNDLE_CACHE_DIR=${zt(B)}`,"","[Install]","WantedBy=multi-user.target","TS_CLOUD_UNIT_EOF","systemctl daemon-reload",...T==="auto"?qs(`${re}@.service`):[...wr(`${re}@.service`),...An()],..._c(X),...yc({paths:B,unitBase:re,releaseId:s,port:c,healthCheckPath:P,healthGateSeconds:v}),...h,...mt(B,f),...y===!1?[]:Ws({...y,unitBase:re,unitPattern:`${re}@*.service`,port:c,path:y?.path??_})]}return[...fe,`cat > /etc/systemd/system/${ee} <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=${t} (managed by ts-cloud)`,"After=network.target","","[Service]","Type=simple",...e.isolation?Ht(pt(e.slug||t),B.base,e.slug||t):[],`WorkingDirectory=${B.current}`,`ExecStart=${i}`,"Restart=always","RestartSec=5","MemoryAccounting=true",...T&&T!=="auto"?[`MemoryHigh=${T}`]:[],...L?[`MemoryMax=${L}`]:[],...k,`EnvironmentFile=${B.current}/.env`,...c?[`Environment=PORT=${c}`]:[],`Environment=STX_IMAGE_CACHE_DIR=${vr(B)}`,`Environment=STX_BUNDLE_CACHE_DIR=${zt(B)}`,"","[Install]","WantedBy=multi-user.target","TS_CLOUD_UNIT_EOF","systemctl daemon-reload",...wr(ee,{auto:T!=="auto",high:T!=="auto",max:Boolean(L)}),...T==="auto"?qs(ee):An(),`systemctl enable ${ee}`,`TS_CLOUD_PREV_CURRENT="$(readlink ${B.current} 2>/dev/null || true)"`,...dt(B),`systemctl restart ${ee}`,`for TS_CLOUD_I in $(seq 1 ${Math.max(1,v)}); do sleep 1; systemctl is-active --quiet ${ee} || { echo "[ts-cloud] release ${s} of ${ee} did not stay up — restoring the previous release" >&2; journalctl -u ${ee} -n 50 --no-pager >&2 || true; if [ -n "$TS_CLOUD_PREV_CURRENT" ] && [ -d "$TS_CLOUD_PREV_CURRENT" ] && [ "$(readlink -f "$TS_CLOUD_PREV_CURRENT")" != "$(readlink -f ${B.release})" ]; then ln -sfn "$TS_CLOUD_PREV_CURRENT" ${B.current}.tmp && mv -Tf ${B.current}.tmp ${B.current}; systemctl restart ${ee} || true; fi; exit 1; }; done`,...Pn(B),...h,...mt(B,f),...y===!1||!c?[]:Ws({...y,unitBase:re,unitPattern:ee,port:c,path:y?.path??_})]}function ci(e){let{siteName:t,artifactFetch:r,releaseId:n,keepReleases:s=Mt,preStartCommands:i=[],postActivateCommands:a=[],beforeResetCommands:c=[]}=e,f=e.appDir??`/var/www/${t}`,g=er(f,n),h=di(e.slug,t,n),S=Xs(g.release,i);return["set -euo pipefail",...yn(g),...r,...Ft(g,[]),...Js(g,c),Tn(g),...bn(g),`tar xzf ${h} -C "$TS_CLOUD_STAGED"`,...wn(g),`rm -f ${h}`,...S,...dt(g),...a,...mt(g,s)]}function di(e,t,r){return`/tmp/${[e,t,r].filter(Boolean).join("-")}-release.tar.gz`}function jc(e,t,r,n){return[`aws s3 cp "s3://${e}/${t}" ${n} --region ${r}`]}function zc(e,t){return[`mv "${e}" ${t}`]}function Ve(e){return`'${e.replace(/'/g,`'"'"'`)}'`}function Cr(e,t,r){return["set -euo pipefail",`chmod 600 ${Ve(e)}`,`mv -f -- ${Ve(e)} ${Ve(t)}`,`cp -- ${Ve(t)} ${Ve(r)}`].join(`
163
+ ' "$TS_CLOUD_MEM_MB" "$TS_CLOUD_HIGH_MB" > /etc/systemd/system/${e}.d/50-ts-cloud-memory.conf`,"systemctl daemon-reload",'echo "[ts-cloud] memoryHigh=auto resolved to ${TS_CLOUD_HIGH_MB}M (one eighth of ${TS_CLOUD_MEM_MB}M)"',...An()]}function wr(e,t={auto:!0}){let r=t.auto===!1?[]:[`/etc/systemd/system/${e}.d/50-ts-cloud-memory.conf`];for(let n of["/etc/systemd/system.control","/run/systemd/system.control"]){if(t.high)r.push(`${n}/${e}.d/50-MemoryHigh.conf`);if(t.max)r.push(`${n}/${e}.d/50-MemoryMax.conf`)}if(r.length===0)return[];return["TS_CLOUD_MEM_CLEARED=0",...r.map((n)=>`if [ -f ${n} ]; then rm -f ${n}; TS_CLOUD_MEM_CLEARED=1; echo "[ts-cloud] removed ${n}: memory limits now come from config"; fi`),'if [ "$TS_CLOUD_MEM_CLEARED" = 1 ]; then systemctl daemon-reload; fi']}function An(){return[`TS_CLOUD_COMMIT=$(for f in /sys/fs/cgroup/system.slice/*.service/memory.high /sys/fs/cgroup/system.slice/*.slice/*.service/memory.high; do [ -f "$f" ] || continue; v=$(cat "$f" 2>/dev/null); [ "$v" = "max" ] && continue; echo "$v"; done | awk '{s+=$1} END {print int(s/1048576)}')`,"TS_CLOUD_RAM=$(awk '/^MemTotal:/{print int($2/1024)}' /proc/meminfo)",'if [ -n "$TS_CLOUD_COMMIT" ] && [ "$TS_CLOUD_COMMIT" -gt 0 ] && [ "$TS_CLOUD_RAM" -gt 0 ]; then TS_CLOUD_PCT=$((TS_CLOUD_COMMIT * 100 / TS_CLOUD_RAM)); if [ "$TS_CLOUD_PCT" -gt 300 ]; then echo "[ts-cloud] WARNING: services on this box declare ${TS_CLOUD_COMMIT}M of MemoryHigh against ${TS_CLOUD_RAM}M of RAM (${TS_CLOUD_PCT}% committed). Soft ceilings, so this is not fatal - but no ceiling can protect the box once enough of them are drawn on at once."; else echo "[ts-cloud] memory commitment: ${TS_CLOUD_COMMIT}M declared against ${TS_CLOUD_RAM}M RAM (${TS_CLOUD_PCT}%)"; fi; fi']}function _c(e){return[`TS_CLOUD_SLICE=$(systemctl show ${e} -p Slice --value 2>/dev/null || true)`,'if [ -n "$TS_CLOUD_SLICE" ] && [ "$TS_CLOUD_SLICE" != "system.slice" ]; then systemctl set-property --runtime "$TS_CLOUD_SLICE" MemoryHigh=infinity MemoryMax=infinity 2>/dev/null || true; systemctl set-property "$TS_CLOUD_SLICE" MemoryHigh=infinity MemoryMax=infinity 2>/dev/null || true; fi']}var et={path:"/",intervalSeconds:60,failuresBeforeRestart:3,timeoutSeconds:10,startupGraceSeconds:600,maxBackoffSeconds:3600,backoffBaseSeconds:300};function jt(e,t,r){return typeof e==="number"&&Number.isFinite(e)?Math.max(r,Math.floor(e)):t}function Ws(e){let{unitBase:t,unitPattern:r,port:n}=e,s=e.path&&e.path.startsWith("/")?e.path:et.path,i=jt(e.intervalSeconds,et.intervalSeconds,10),a=jt(e.failuresBeforeRestart,et.failuresBeforeRestart,1),c=jt(e.timeoutSeconds,et.timeoutSeconds,1),f=jt(e.startupGraceSeconds,et.startupGraceSeconds,0),g=jt(e.maxBackoffSeconds,et.maxBackoffSeconds,0),h=Math.min(et.backoffBaseSeconds,g),S=`/usr/local/sbin/${t}-liveness`,_=`/run/${t}-liveness`,v=`${t}-liveness`,y=`127.0.0.1:${n}${s}`,L=r.includes("@*")?`TS_CLOUD_UNIT=$(systemctl list-units --plain --no-legend --type=service '${r}' 2>/dev/null | awk '{print $1}' | head -1)`:`TS_CLOUD_UNIT=${r}`;return[`cat > ${S} <<'TS_CLOUD_LIVENESS_EOF'`,"#!/bin/sh",`# Liveness check for ${t}, written by ts-cloud on every deploy.`,`# Settings: interval=${i}s timeout=${c}s failures=${a} startup-grace=${f}s max-backoff=${g}s`,"set -eu",`TS_CLOUD_STATE=${_}`,'exec 9>"$TS_CLOUD_STATE.lock"',"flock -n 9 || exit 0",L,'[ -n "$TS_CLOUD_UNIT" ] || exit 0','systemctl is-active --quiet "$TS_CLOUD_UNIT" || exit 0',"TS_CLOUD_RC=0",`curl -s -o /dev/null --max-time ${c} "http://${y}" || TS_CLOUD_RC=$?`,'if [ "$TS_CLOUD_RC" -eq 0 ]; then',' rm -f "$TS_CLOUD_STATE.fail"',' if [ -f "$TS_CLOUD_STATE.restarts" ]; then',` TS_CLOUD_LAST=$(awk '{print $2}' "$TS_CLOUD_STATE.restarts" 2>/dev/null || true)`,` case "$TS_CLOUD_LAST" in ''|*[!0-9]*) TS_CLOUD_LAST=0 ;; esac`,` [ $(($(date +%s) - TS_CLOUD_LAST)) -lt ${g} ] || rm -f "$TS_CLOUD_STATE.restarts"`," fi"," exit 0","fi",'case "$TS_CLOUD_RC" in'," 7) TS_CLOUD_WHY='connection refused' ;;",` 28) TS_CLOUD_WHY='no response within ${c}s' ;;`,' *) TS_CLOUD_WHY="curl exit $TS_CLOUD_RC" ;;',"esac",'TS_CLOUD_SINCE=$(systemctl show "$TS_CLOUD_UNIT" -p ActiveEnterTimestampMonotonic --value 2>/dev/null || true)',"TS_CLOUD_UPTIME=$(cut -d' ' -f1 /proc/uptime 2>/dev/null || true)",`TS_CLOUD_AGE=$(awk -v up="$TS_CLOUD_UPTIME" -v since="$TS_CLOUD_SINCE" 'BEGIN { if (since + 0 > 0 && up + 0 > 0) print int(up - since / 1000000); else print -1 }')`,`case "$TS_CLOUD_AGE" in ''|*[!0-9-]*) TS_CLOUD_AGE=-1 ;; esac`,'if [ "$TS_CLOUD_AGE" -lt 0 ]; then',' TS_CLOUD_PID=$(systemctl show "$TS_CLOUD_UNIT" -p MainPID --value 2>/dev/null || true)',` case "$TS_CLOUD_PID" in ''|0|*[!0-9]*) ;; *) TS_CLOUD_AGE=$(ps -o etimes= -p "$TS_CLOUD_PID" 2>/dev/null | tr -d ' ' || true) ;; esac`,` case "$TS_CLOUD_AGE" in ''|*[!0-9]*) TS_CLOUD_AGE=-1 ;; esac`,"fi",`if [ "$TS_CLOUD_AGE" -ge 0 ] && [ "$TS_CLOUD_AGE" -lt ${f} ]; then`,' rm -f "$TS_CLOUD_STATE.fail"',` logger -t ${v} "$TS_CLOUD_UNIT is \${TS_CLOUD_AGE}s old, inside its ${f}s startup grace; not counting this failed check on ${y} ($TS_CLOUD_WHY)"`," exit 0","fi",'TS_CLOUD_FAILS=$(cat "$TS_CLOUD_STATE.fail" 2>/dev/null || echo 0)',`case "$TS_CLOUD_FAILS" in ''|*[!0-9]*) TS_CLOUD_FAILS=0 ;; esac`,"TS_CLOUD_FAILS=$((TS_CLOUD_FAILS + 1))",'echo "$TS_CLOUD_FAILS" > "$TS_CLOUD_STATE.fail"',`if [ "$TS_CLOUD_FAILS" -lt ${a} ]; then`,` logger -t ${v} "check $TS_CLOUD_FAILS of ${a} failed on ${y} ($TS_CLOUD_WHY)"`," exit 0","fi","TS_CLOUD_NOW=$(date +%s)","TS_CLOUD_STREAK=0","TS_CLOUD_LAST=0",'[ ! -f "$TS_CLOUD_STATE.restarts" ] || read -r TS_CLOUD_STREAK TS_CLOUD_LAST < "$TS_CLOUD_STATE.restarts" || true',`case "$TS_CLOUD_STREAK" in ''|*[!0-9]*) TS_CLOUD_STREAK=0 ;; esac`,`case "$TS_CLOUD_LAST" in ''|*[!0-9]*) TS_CLOUD_LAST=0 ;; esac`,'if [ "$TS_CLOUD_STREAK" -gt 0 ]; then',` TS_CLOUD_WAIT=${h}`," TS_CLOUD_I=1",` while [ "$TS_CLOUD_I" -lt "$TS_CLOUD_STREAK" ] && [ "$TS_CLOUD_WAIT" -lt ${g} ]; do TS_CLOUD_WAIT=$((TS_CLOUD_WAIT * 2)); TS_CLOUD_I=$((TS_CLOUD_I + 1)); done`,` [ "$TS_CLOUD_WAIT" -le ${g} ] || TS_CLOUD_WAIT=${g}`," TS_CLOUD_ELAPSED=$((TS_CLOUD_NOW - TS_CLOUD_LAST))",' if [ "$TS_CLOUD_ELAPSED" -lt "$TS_CLOUD_WAIT" ]; then',` logger -t ${v} "holding off: $TS_CLOUD_STREAK liveness restart(s) in a row have not brought $TS_CLOUD_UNIT back; next restart allowed in $((TS_CLOUD_WAIT - TS_CLOUD_ELAPSED))s ($TS_CLOUD_WHY on ${y})"`," exit 0"," fi","fi","TS_CLOUD_STREAK=$((TS_CLOUD_STREAK + 1))",`logger -t ${v} "no HTTP response on ${y} after $TS_CLOUD_FAILS checks ($TS_CLOUD_WHY); restarting $TS_CLOUD_UNIT (liveness restart $TS_CLOUD_STREAK in a row)"`,'echo "$TS_CLOUD_STREAK $TS_CLOUD_NOW" > "$TS_CLOUD_STATE.restarts"','rm -f "$TS_CLOUD_STATE.fail"','systemctl restart "$TS_CLOUD_UNIT"',"TS_CLOUD_LIVENESS_EOF",`chmod +x ${S}`,`rm -f ${_}.fail ${_}.restarts`,`cat > /etc/systemd/system/${t}-liveness.service <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=Liveness check for ${t} (managed by ts-cloud)`,"","[Service]","Type=oneshot",`ExecStart=${S}`,"TS_CLOUD_UNIT_EOF",`cat > /etc/systemd/system/${t}-liveness.timer <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=Run the ${t} liveness check every ${i}s`,"","[Timer]",`OnUnitActiveSec=${i}s`,`OnBootSec=${i}s`,"Persistent=true","","[Install]","WantedBy=timers.target","TS_CLOUD_UNIT_EOF","systemctl daemon-reload",`systemctl enable --now ${t}-liveness.timer >/dev/null 2>&1 || true`]}var Ys=20,xn=3,vc=5,$c=60;function yc(e){let{paths:t,unitBase:r,releaseId:n,port:s}=e,i=`${r}@${n}.service`,a=`${r}.service`,c=Math.max(1,e.healthGateSeconds??5),f=e.healthCheckPath?e.healthCheckPath.startsWith("/")?e.healthCheckPath:`/${e.healthCheckPath}`:null,g=f?`curl -sf -o /dev/null --max-time ${vc} "http://127.0.0.1:${s}${f}"`:null,h=(S)=>`{ echo "[ts-cloud] release ${n} ${S}" >&2; ts_cloud_restore_previous; exit 1; }`;return[`TS_CLOUD_OLD_UNITS=$(systemctl list-units --plain --no-legend --type=service "${r}@*.service" 2>/dev/null | awk '{print $1}' | grep -v "^${i}$" || true)`,`TS_CLOUD_PREV_CURRENT="$(readlink ${t.current} 2>/dev/null || true)"`,"TS_CLOUD_LEGACY_STOPPED=0","ts_cloud_restore_previous() {",` journalctl -u ${i} -n 50 --no-pager >&2 || true`,` systemctl stop ${i} 2>/dev/null || true`,` systemctl disable ${i} 2>/dev/null || true`,` if [ -n "$TS_CLOUD_PREV_CURRENT" ] && [ -d "$TS_CLOUD_PREV_CURRENT" ]; then ln -sfn "$TS_CLOUD_PREV_CURRENT" ${t.current}.tmp && mv -Tf ${t.current}.tmp ${t.current}; fi`,' for TS_CLOUD_RU in ${TS_CLOUD_OLD_UNITS}; do systemctl enable "$TS_CLOUD_RU" 2>/dev/null || true; systemctl start "$TS_CLOUD_RU" 2>/dev/null || true; done',` if [ "$TS_CLOUD_LEGACY_STOPPED" -eq 1 ]; then systemctl start ${a} 2>/dev/null || true; fi`,' if [ -n "$TS_CLOUD_OLD_UNITS" ] || [ "$TS_CLOUD_LEGACY_STOPPED" -eq 1 ]; then echo "[ts-cloud] previous release restored and serving" >&2; else echo "[ts-cloud] there was no previous release to restore" >&2; fi',"}",`if [ -f /etc/systemd/system/${a} ] && systemctl is-active --quiet ${a}; then echo "[ts-cloud] retiring pre-zero-downtime unit ${a} (one-time restart cutover)"; systemctl stop ${a}; TS_CLOUD_LEGACY_STOPPED=1; fi`,'TS_CLOUD_STARTED_AT="@$(date +%s)"',`systemctl restart ${i}`,`TS_CLOUD_GATE_OK=1; for TS_CLOUD_I in $(seq 1 ${c}); do sleep 1; systemctl is-active --quiet ${i} || { TS_CLOUD_GATE_OK=0; break; }; done`,'if [ "$TS_CLOUD_GATE_OK" -ne 1 ]; then',` if journalctl -u ${i} --since "$TS_CLOUD_STARTED_AT" -o cat --no-pager 2>/dev/null | grep -iE 'EADDRINUSE|address already in use|port [0-9]+ (is )?in use|Failed to start server' >/dev/null; then`,` echo "[ts-cloud] release ${n} could not share :${s} with the previous release (no SO_REUSEPORT?) — retiring it and retrying" >&2`,' for TS_CLOUD_RU in ${TS_CLOUD_OLD_UNITS}; do systemctl stop "$TS_CLOUD_RU" 2>/dev/null || true; done',` systemctl restart ${i}`,` for TS_CLOUD_I in $(seq 1 ${c}); do sleep 1; systemctl is-active --quiet ${i} || ${h("failed its health gate on the free port")}; done`," else",` ${h("crashed on start — the previous release was never stopped")}`," fi","fi",`if ss -ltnpH "sport = :${s}" >/dev/null 2>&1; then`," TS_CLOUD_BOUND=0",` for TS_CLOUD_I in $(seq 1 ${$c}); do`,` TS_CLOUD_NEW_PID="$(systemctl show -p MainPID --value ${i} 2>/dev/null || true)"`,` if [ -n "$TS_CLOUD_NEW_PID" ] && [ "$TS_CLOUD_NEW_PID" != "0" ] && ss -ltnpH "sport = :${s}" 2>/dev/null | grep "pid=$TS_CLOUD_NEW_PID," >/dev/null; then TS_CLOUD_BOUND=1; break; fi`,` systemctl is-active --quiet ${i} || break`,` sleep ${xn}`," done",` [ "$TS_CLOUD_BOUND" -eq 1 ] || ${h(`never took :${s}`)}`,"else",' echo "[ts-cloud] cannot read listener PIDs on this host — the response probes run without the bind check" >&2',"fi",...g?[`TS_CLOUD_HEALTHY=0; for TS_CLOUD_I in $(seq 1 ${Ys}); do if ${g}; then TS_CLOUD_HEALTHY=1; break; fi; sleep ${xn}; done`,`[ "$TS_CLOUD_HEALTHY" -eq 1 ] || ${h(`never answered ${f}`)}`]:[],...dt(t),`systemctl enable ${i} 2>/dev/null || true`,'for TS_CLOUD_U in ${TS_CLOUD_OLD_UNITS}; do systemctl stop "$TS_CLOUD_U" 2>/dev/null || true; systemctl disable "$TS_CLOUD_U" 2>/dev/null || true; done',`TS_CLOUD_LISTENING=0; for TS_CLOUD_I in $(seq 1 ${c}); do if ss -ltnH "sport = :${s}" 2>/dev/null | grep . >/dev/null; then TS_CLOUD_LISTENING=1; break; fi; sleep 1; done`,`if [ "$TS_CLOUD_LISTENING" -ne 1 ]; then echo "[ts-cloud] nothing is listening on ${s} after retiring the previous release — restarting ${i} on the now-free port" >&2; systemctl restart ${i}; for TS_CLOUD_I in $(seq 1 ${c}); do if ss -ltnH "sport = :${s}" 2>/dev/null | grep . >/dev/null; then TS_CLOUD_LISTENING=1; break; fi; sleep 1; done; fi`,`[ "$TS_CLOUD_LISTENING" -eq 1 ] || ${h(`is active but never bound :${s}`)}`,...g?[`TS_CLOUD_HEALTHY=0; for TS_CLOUD_I in $(seq 1 ${Ys}); do if ${g}; then TS_CLOUD_HEALTHY=1; break; fi; sleep ${xn}; done`,`[ "$TS_CLOUD_HEALTHY" -eq 1 ] || ${h(`stopped answering ${f} once it served alone`)}`]:[],...Pn(t),`systemctl list-unit-files --plain --no-legend "${r}@*.service" 2>/dev/null | awk '{print $1}' | { grep -v -e "^${i}$" -e "^${r}@\\.service$" || true; } | while read -r TS_CLOUD_U; do systemctl disable "$TS_CLOUD_U" 2>/dev/null || true; done`,`if [ -f /etc/systemd/system/${a} ]; then systemctl disable ${a} 2>/dev/null || true; rm -f /etc/systemd/system/${a}; systemctl daemon-reload; fi`]}function Js(e,t){if(!t.length)return[];let r=Ve(e.release);return[`if [ -e ${r} ] || [ -L ${r} ]; then`,...t,"fi"]}function ai(e){let{siteName:t,slug:r,artifactFetch:n,releaseId:s,execStart:i,envEntries:a,port:c,keepReleases:f=Mt,preStartCommands:g=[],postActivateCommands:h=[],beforeResetCommands:S=[],healthCheckPath:_,healthGateSeconds:v=5,liveness:y,memoryHigh:T="auto",memoryMax:L,cpuWeight:j,ioWeight:M,tasksMax:O,stopTimeout:N}=e,k=[...j!=null?[`CPUWeight=${j}`]:[],...M!=null?[`IOWeight=${M}`]:[],...O!=null?[`TasksMax=${O}`]:[],...N?[`TimeoutStopSec=${N}`]:[]],G=e.zeroDowntime??c!=null,W=e.appDir??`/var/www/${t}`,B=er(W,s),re=`${r}-${t}`,ee=`${re}.service`,ne=di(r,t,s),ie=e.sharedPaths??[],ce=Ns([".env",...ie,...Tr(a,ie)]),se=hr(a),me=Xs(B.release,g,a),fe=["set -euo pipefail",...yn(B),...n,...Ft(B,ce),...Js(B,S),Tn(B),...bn(B),`tar xzf ${ne} --no-same-owner -C "$TS_CLOUD_STAGED"`,`rm -f ${ne}`,`cat > ${B.shared}/.env <<'TS_CLOUD_ENV_EOF'`,se,"TS_CLOUD_ENV_EOF",`chmod 600 ${B.shared}/.env`,...wn(B),`find ${B.release} -maxdepth 1 \\( -type f -o -type l \\) -name '.env*' ! -name '.env.example' ! -name '*.example' -delete`,`sed -i -E '/^[[:space:]]*(PORT|PORT_BACKEND|PORT_ADMIN|PORT_FRONTEND)[[:space:]]*=/d' ${B.shared}/.env 2>/dev/null || true`,...yr(B,ce),...me,...e.isolation?Us(e.slug||t,B.base,ce.flatMap((X)=>typeof X==="string"||!X.target?[]:[X.target])):[]];if(G&&c!=null){let X=`${re}@${s}.service`,P=_?_.startsWith("/")?_:`/${_}`:null;return[...fe,`cat > /etc/systemd/system/${re}@.service <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=${t} release %i (managed by ts-cloud)`,"After=network.target","","[Service]","Type=simple",...e.isolation?Ht(pt(e.slug||t),B.base,e.slug||t):[],`WorkingDirectory=${B.releases}/%i`,`ExecStart=${i}`,"Restart=always","RestartSec=5","MemoryAccounting=true",...T&&T!=="auto"?[`MemoryHigh=${T}`]:[],...L?[`MemoryMax=${L}`]:[],...k,`EnvironmentFile=${B.releases}/%i/.env`,`Environment=PORT=${c}`,`Environment=STX_IMAGE_CACHE_DIR=${vr(B)}`,`Environment=STX_BUNDLE_CACHE_DIR=${zt(B)}`,`Environment=STX_BUNDLE_CACHE_DIR=${zt(B)}`,"","[Install]","WantedBy=multi-user.target","TS_CLOUD_UNIT_EOF","systemctl daemon-reload",...T==="auto"?qs(`${re}@.service`):[...wr(`${re}@.service`),...An()],..._c(X),...yc({paths:B,unitBase:re,releaseId:s,port:c,healthCheckPath:P,healthGateSeconds:v}),...h,...mt(B,f),...y===!1?[]:Ws({...y,unitBase:re,unitPattern:`${re}@*.service`,port:c,path:y?.path??_})]}return[...fe,`cat > /etc/systemd/system/${ee} <<'TS_CLOUD_UNIT_EOF'`,"[Unit]",`Description=${t} (managed by ts-cloud)`,"After=network.target","","[Service]","Type=simple",...e.isolation?Ht(pt(e.slug||t),B.base,e.slug||t):[],`WorkingDirectory=${B.current}`,`ExecStart=${i}`,"Restart=always","RestartSec=5","MemoryAccounting=true",...T&&T!=="auto"?[`MemoryHigh=${T}`]:[],...L?[`MemoryMax=${L}`]:[],...k,`EnvironmentFile=${B.current}/.env`,...c?[`Environment=PORT=${c}`]:[],`Environment=STX_IMAGE_CACHE_DIR=${vr(B)}`,`Environment=STX_BUNDLE_CACHE_DIR=${zt(B)}`,"","[Install]","WantedBy=multi-user.target","TS_CLOUD_UNIT_EOF","systemctl daemon-reload",...wr(ee,{auto:T!=="auto",high:T!=="auto",max:Boolean(L)}),...T==="auto"?qs(ee):An(),`systemctl enable ${ee}`,`TS_CLOUD_PREV_CURRENT="$(readlink ${B.current} 2>/dev/null || true)"`,...dt(B),`systemctl restart ${ee}`,`for TS_CLOUD_I in $(seq 1 ${Math.max(1,v)}); do sleep 1; systemctl is-active --quiet ${ee} || { echo "[ts-cloud] release ${s} of ${ee} did not stay up — restoring the previous release" >&2; journalctl -u ${ee} -n 50 --no-pager >&2 || true; if [ -n "$TS_CLOUD_PREV_CURRENT" ] && [ -d "$TS_CLOUD_PREV_CURRENT" ] && [ "$(readlink -f "$TS_CLOUD_PREV_CURRENT")" != "$(readlink -f ${B.release})" ]; then ln -sfn "$TS_CLOUD_PREV_CURRENT" ${B.current}.tmp && mv -Tf ${B.current}.tmp ${B.current}; systemctl restart ${ee} || true; fi; exit 1; }; done`,...Pn(B),...h,...mt(B,f),...y===!1||!c?[]:Ws({...y,unitBase:re,unitPattern:ee,port:c,path:y?.path??_})]}function ci(e){let{siteName:t,artifactFetch:r,releaseId:n,keepReleases:s=Mt,preStartCommands:i=[],postActivateCommands:a=[],beforeResetCommands:c=[]}=e,f=e.appDir??`/var/www/${t}`,g=er(f,n),h=di(e.slug,t,n),S=Xs(g.release,i);return["set -euo pipefail",...yn(g),...r,...Ft(g,[]),...Js(g,c),Tn(g),...bn(g),`tar xzf ${h} --no-same-owner -C "$TS_CLOUD_STAGED"`,...wn(g),`rm -f ${h}`,...S,...dt(g),...a,...mt(g,s)]}function di(e,t,r){return`/tmp/${[e,t,r].filter(Boolean).join("-")}-release.tar.gz`}function jc(e,t,r,n){return[`aws s3 cp "s3://${e}/${t}" ${n} --region ${r}`]}function zc(e,t){return[`mv "${e}" ${t}`]}function Ve(e){return`'${e.replace(/'/g,`'"'"'`)}'`}function Cr(e,t,r){return["set -euo pipefail",`chmod 600 ${Ve(e)}`,`mv -f -- ${Ve(e)} ${Ve(t)}`,`cp -- ${Ve(t)} ${Ve(r)}`].join(`
164
164
  `)}function Pr(e){return`rm -f -- ${Ve(e)} 2>/dev/null || true`}function In(e={}){let t=Math.max(1,e.appServers??e.instances??1),r=!!e.servicesServer||t>1,n=t>1||!!e.server?.loadBalancer;return{appServers:t,loadBalancer:n,dedicatedServices:r,servicesOnApp:!r}}function Zs(e,t){let r={REDIS_HOST:e,MEILISEARCH_HOST:`http://${e}:7700`};if(t?.name){if(r.DB_CONNECTION=t.engine==="postgres"?"pgsql":"mysql",r.DB_HOST=e,r.DB_PORT=String(t.port??(t.engine==="postgres"?5432:3306)),r.DB_DATABASE=t.name,t.username)r.DB_USERNAME=t.username;if(t.password)r.DB_PASSWORD=t.password}return r}function Ln(e){let t=e.infrastructure?.compute??{},r=p(e);return[...cr(t.managedServices??{mysql:!0,redis:!0},{bindPrivate:!0}),...ct(r,t.managedServices??{mysql:!0}),...Me(!0),...Ue(!0),...lt(t.sshKeys),...Xe(e.notifications),...t.backups?.enabled?[...Ut({database:r,backups:t.backups})]:[]]}var Gt=["-S","ssh"];function li(e={},t="ssh"){let r=[];if(e.identityFile)r.push("-i",e.identityFile);if(e.port)r.push(t==="scp"?"-P":"-p",String(e.port));return r.push("-o","StrictHostKeyChecking=no","-o","UserKnownHostsFile=/dev/null","-o","LogLevel=ERROR","-o",`ConnectTimeout=${e.connectTimeoutSec??10}`),r}async function Hr(e,t,r={}){let n=Bun.spawn(["ssh",...li(r),`${r.user??"root"}@${e}`,t],{stdout:"pipe",stderr:"pipe"}),[s,i]=await Promise.all([new Response(n.stdout).text(),new Response(n.stderr).text()]);return{code:await n.exited,stdout:s,stderr:i}}async function Ce(e,t,r={}){let n=await Hr(e,t,r);if(n.code!==0)throw Error(`ssh \`${t}\` on ${e} failed (${n.code}): ${n.stderr.trim()||n.stdout.trim()}`);return n.stdout}async function Kc(e,t,r,n={}){let s=Bun.spawn(["scp",...Gt,...li(n,"scp"),...t,`${n.user??"root"}@${e}:${r}`],{stdout:"pipe",stderr:"pipe"}),i=await s.exited;if(i!==0){let a=await new Response(s.stderr).text();throw Error(`scp to ${e}:${r} failed (${i}): ${a.trim()}`)}}async function yt(e,t={}){let r=t.timeoutMs??180000,n=t.pollIntervalMs??5000,s=Date.now();while(Date.now()-s<r){let i=await Hr(e,"echo ready",t);if(i.code===0&&i.stdout.includes("ready"))return;await new Promise((a)=>setTimeout(a,n))}throw Error(`SSH not ready on ${e} after ${r}ms`)}async function Wc(e,t={}){let r=t.timeoutMs??300000,n=t.pollIntervalMs??5000,s=Date.now();while(Date.now()-s<r){let i=await Hr(e,"cloud-init status 2>/dev/null || echo unknown",t);if(i.stdout.includes("status: done"))return;if(i.stdout.includes("status: error"))throw Error(`cloud-init reported an error on ${e}; check /var/log/cloud-init-output.log`);await new Promise((a)=>setTimeout(a,n))}throw Error(`cloud-init did not finish on ${e} after ${r}ms`)}function ui(e={}){return["set -e","ts_cloud_script=$(mktemp /tmp/ts-cloud-deploy.XXXXXXXX)",`trap 'rm -f "$ts_cloud_script"' EXIT`,'cat > "$ts_cloud_script"',e.sudo?'sudo -n -H bash "$ts_cloud_script" < /dev/null':'bash "$ts_cloud_script" < /dev/null'].join(`
165
165
  `)}var Jc=ui();import{homedir as bc}from"node:os";import{join as Tc}from"node:path";var Er={location:"fsn1",image:"ubuntu-24.04",sshUser:"root",sshPrivateKeyPath:"~/.ssh/id_ed25519"};function Rr(e){return e.startsWith("~/")?Tc(bc(),e.slice(2)):e}function ft(...e){for(let t of e){let r=process.env[t]?.trim();if(r)return r}return}function gt(...e){for(let t of e){let r=t?.trim();if(r)return r}return}function Vt(e,t){return gt(e,t?.hetzner?.apiToken,ft("HCLOUD_TOKEN","HETZNER_API_TOKEN"))}function Xc(e,t){return gt(t,e?.hetzner?.location,ft("HCLOUD_LOCATION","HETZNER_LOCATION"))??Er.location}function qt(e,t){let r=e?.infrastructure?.compute;return gt(t,r?.image,e?.hetzner?.image,ft("HCLOUD_IMAGE","HETZNER_IMAGE"))??Er.image}function wc(e,t){return gt(t,e?.hetzner?.sshUser,ft("HCLOUD_SSH_USER","HETZNER_SSH_USER"))??Er.sshUser}function Qs(e,t){return Rr(gt(t,e?.hetzner?.sshPrivateKeyPath,ft("HCLOUD_SSH_KEY","HETZNER_SSH_KEY"))??Er.sshPrivateKeyPath)}function Cc(e,t,r){let n=gt(t,e?.hetzner?.sshPublicKeyPath,ft("HCLOUD_SSH_PUBLIC_KEY","HETZNER_SSH_PUBLIC_KEY"));if(n)return Rr(n);return`${r??Qs(e)}.pub`}function eo(e,t={}){let r=Qs(e,t.sshPrivateKeyPath);return{apiToken:Vt(t.apiToken,e),location:Xc(e,t.location),image:qt(e,t.image),sshUser:wc(e,t.sshUser),sshPrivateKeyPath:r,sshPublicKeyPath:Cc(e,t.sshPublicKeyPath,r)}}var Pc="https://api.hetzner.cloud/v1";class Or extends Error{status;code;details;constructor(e,t,r,n){super(e);this.status=t;this.code=r;this.details=n;this.name="HetznerApiError"}}class Dr extends Error{action;constructor(e,t){super(e);this.action=t;this.name="HetznerActionError"}}function to(e){return e.map((t)=>({type:"server",server:{id:t.server}}))}class Gr{name="hetzner";apiToken;baseUrl;fetchImpl;constructor(e){this.apiToken=e.apiToken,this.baseUrl=e.baseUrl??Pc,this.fetchImpl=e.fetchImpl??fetch}async request(e,t,r){let n=await this.fetchImpl(`${this.baseUrl}${t}`,{method:e,headers:{Authorization:`Bearer ${this.apiToken}`,"Content-Type":"application/json"},body:r===void 0?void 0:JSON.stringify(r)}),s=await n.text(),i;try{i=s?JSON.parse(s):{}}catch{if(!n.ok){let a=s.trim().slice(0,200)||n.statusText||"Hetzner API error";throw Error(`Hetzner API ${e} ${t} (${n.status}): ${a}`)}throw Error(`Hetzner API ${e} ${t}: unexpected non-JSON response`)}if(!n.ok){let a=i.error?.message||n.statusText||"Hetzner API error",c=i.error?.code?` [${i.error.code}]`:"";throw new Or(`Hetzner API ${e} ${t} (${n.status})${c}: ${a}`,n.status,i.error?.code,i.error?.details)}return i}async requestAll(e,t){let r=[],n=1;for(;;){let s=e.includes("?")?"&":"?",i=await this.request("GET",`${e}${s}per_page=50&page=${n}`);r.push(...i[t]??[]);let a=i.meta?.pagination?.next_page;if(!a)return r;n=a}}async listServers(){return this.requestAll("/servers","servers")}async getLocation(e){let r=(await this.request("GET",`/locations?name=${encodeURIComponent(e)}`)).locations.find((n)=>n.name===e);if(!r)throw Error(`Hetzner location not found: ${e}`);return r}async getServer(e){return(await this.request("GET",`/servers/${e}`)).server}async changeServerReverseDns(e,t,r){return(await this.request("POST",`/servers/${e}/actions/change_dns_ptr`,{ip:t,dns_ptr:r})).action}async listVolumes(){return this.requestAll("/volumes","volumes")}async getVolume(e){return(await this.request("GET",`/volumes/${e}`)).volume}async createVolume(e){return this.request("POST","/volumes",{...e,automount:!1})}async attachVolume(e,t){return(await this.request("POST",`/volumes/${e}/actions/attach`,{server:t,automount:!1})).action}async resizeVolume(e,t){return(await this.request("POST",`/volumes/${e}/actions/resize`,{size:t})).action}async protectVolume(e,t){return(await this.request("POST",`/volumes/${e}/actions/change_protection`,{delete:t})).action}async getServerMetrics(e,t){let r=new URLSearchParams({type:t.types.join(","),start:t.start.toISOString(),end:t.end.toISOString(),step:String(Math.max(60,Math.floor(t.step??60)))});return(await this.request("GET",`/servers/${e}/metrics?${r}`)).metrics}async listServerTypes(e){let t=e?`?name=${encodeURIComponent(e)}`:"";return this.requestAll(`/server_types${t}`,"server_types")}async getServerType(e){return(await this.listServerTypes(e)).find((t)=>t.name===e)??null}async createServer(e){let t=await this.request("POST","/servers",{name:e.name,server_type:e.serverType,image:e.image,location:e.location,datacenter:e.datacenter,ssh_keys:e.sshKeys,user_data:e.userData,labels:e.labels,firewalls:e.firewalls,networks:e.networks,start_after_create:!0});return{server:t.server,action:t.action}}async listNetworks(){return this.requestAll("/networks","networks")}async createNetwork(e){let t=e.ipRange??"10.0.0.0/16";return(await this.request("POST","/networks",{name:e.name,ip_range:t,subnets:[{type:"cloud",ip_range:t,network_zone:"eu-central"}],labels:e.labels})).network}async deleteNetwork(e){await this.request("DELETE",`/networks/${e}`)}async listLoadBalancers(){return this.requestAll("/load_balancers","load_balancers")}async createLoadBalancer(e){return(await this.request("POST","/load_balancers",{name:e.name,load_balancer_type:e.type??"lb11",location:e.location,network_zone:e.network?void 0:e.networkZone??"eu-central",network:e.network,labels:e.labels,targets:[{type:"label_selector",label_selector:{selector:e.labelSelector},use_private_ip:!!e.network}],services:e.services.map((r)=>({protocol:r.protocol??"tcp",listen_port:r.listenPort,destination_port:r.destinationPort,health_check:{protocol:"http",port:80,interval:15,timeout:10,retries:3,http:{path:"/",status_codes:["2??","3??"]}}}))})).load_balancer}async deleteLoadBalancer(e){await this.request("DELETE",`/load_balancers/${e}`)}async deleteServer(e){return(await this.request("DELETE",`/servers/${e}`)).action}async listFirewalls(){return this.requestAll("/firewalls","firewalls")}async createFirewall(e){let t=await this.request("POST","/firewalls",{name:e.name,rules:e.rules,labels:e.labels,apply_to:e.applyTo?to(e.applyTo):void 0});return{firewall:t.firewall,actions:t.actions}}async setFirewallRules(e,t){return(await this.request("POST",`/firewalls/${e}/actions/set_rules`,{rules:t})).actions??[]}async deleteFirewall(e){await this.request("DELETE",`/firewalls/${e}`)}async applyFirewallToResources(e,t){return(await this.request("POST",`/firewalls/${e}/actions/apply_to_resources`,{apply_to:to(t)})).actions}async listSshKeys(){return this.requestAll("/ssh_keys","ssh_keys")}async createSshKey(e){return(await this.request("POST","/ssh_keys",{name:e.name,public_key:e.publicKey,labels:e.labels})).ssh_key}async deleteSshKey(e){await this.request("DELETE",`/ssh_keys/${e}`)}async getAction(e){return(await this.request("GET",`/actions/${e}`)).action}async shutdownServer(e){return(await this.request("POST",`/servers/${e}/actions/shutdown`,{})).action}async powerOnServer(e){return(await this.request("POST",`/servers/${e}/actions/poweron`,{})).action}async changeServerType(e,t,r){return(await this.request("POST",`/servers/${e}/actions/change_type`,{server_type:t,upgrade_disk:r})).action}async powerOffServer(e){return(await this.request("POST",`/servers/${e}/actions/poweroff`,{})).action}async stopServer(e,t){if((await this.getServer(e)).status==="off")return;await this.shutdownServer(e);let n=t?.gracefulWaitMs??120000,s=t?.pollIntervalMs??3000,i=Date.now();while(Date.now()-i<n){if((await this.getServer(e)).status==="off")return;await new Promise((c)=>setTimeout(c,s))}let a=await this.powerOffServer(e);await this.waitForAction(a.id),await this.waitForServerStatus(e,"off")}async renameServer(e,t){return(await this.request("PUT",`/servers/${e}`,{name:t})).server}async listImages(e){let t=e?.type?`?type=${encodeURIComponent(e.type)}`:"";return this.requestAll(`/images${t}`,"images")}async getImage(e){return(await this.request("GET",`/images/${e}`)).image}async createImage(e,t){return this.request("POST",`/servers/${e}/actions/create_image`,{description:t.description,type:t.type??"snapshot",labels:t.labels})}async deleteImage(e){await this.request("DELETE",`/images/${e}`)}async rebuildServer(e,t){return(await this.request("POST",`/servers/${e}/actions/rebuild`,{image:t})).action}async listPrimaryIps(){return this.requestAll("/primary_ips","primary_ips")}async unassignPrimaryIp(e){return(await this.request("POST",`/primary_ips/${e}/actions/unassign`,{})).action}async assignPrimaryIp(e,t){return(await this.request("POST",`/primary_ips/${e}/actions/assign`,{assignee_id:t,assignee_type:"server"})).action}async waitForAction(e,t){let r=t?.pollIntervalMs??2000,n=t?.maxWaitMs??300000,s=Date.now();while(Date.now()-s<n){let i=await this.getAction(e);if(i.status==="success")return i;if(i.status==="error")throw new Dr(i.error?.message||"Hetzner action failed",i);await new Promise((a)=>setTimeout(a,r))}throw Error(`Timed out waiting for Hetzner action ${e}`)}async waitForServerRunning(e,t){let r=t?.pollIntervalMs??3000,n=t?.maxWaitMs??600000,s=Date.now();while(Date.now()-s<n){let i=await this.getServer(e);if(i.status==="running")return i;await new Promise((a)=>setTimeout(a,r))}throw Error(`Timed out waiting for server ${e} to reach running state`)}async waitForServerStatus(e,t,r){let n=r?.pollIntervalMs??3000,s=r?.maxWaitMs??600000,i=Date.now();while(Date.now()-i<s){let a=await this.getServer(e);if(a.status===t)return a;await new Promise((c)=>setTimeout(c,n))}throw Error(`Timed out waiting for server ${e} to reach ${t} state`)}}function Yc(e,t){let r=Vt(e,t);if(!r)throw Error("Hetzner API token required. Set hetzner.apiToken in cloud.config.ts or HCLOUD_TOKEN / HETZNER_API_TOKEN.");return r}function ze(e){let[t,r]=e.trim().split(/\s+/);return r?`${t} ${r}`:t}function ro(e,t){if(!t)return[];if(t.length>253||!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z0-9-]*$/i.test(t))throw Error("Reverse DNS requires a valid fully qualified hostname");let r=[],{ipv4:n,ipv6:s}=e.public_net;if(n?.ip&&n.dns_ptr!==t)r.push({ip:n.ip,hostname:t});let i=oe(s?.ip);if(i&&!s?.dns_ptr?.some((a)=>a.ip===i&&a.dns_ptr===t))r.push({ip:i,hostname:t});return r}function no(e){if(!e)return"";return e.endsWith(`
166
166
  `)?e:`${e}
@@ -1 +1 @@
1
- import{Nn,Bn,og,Rs,ag,cg,dg,oc,lg,ug,Rh,gg,v,pg,Ds,Ue,mg,fg,iI,hg,Ag,yg,Sg,Ig,Dh,sI,oI,aI,Ph,kh,cI,dI,Nh,Bh,lI,Ps,Er,ac,xn,On,vr,ut,Ht,ks,xh,_n,bg,Cg,cc,Bs,$n,xs,Cc}from"../chunk-n95wbpge.js";import{Ec,Mn,Un,Os,_s,Ls,$s,vc,Tc}from"../chunk-9f18pebj.js";import{wc}from"../chunk-c6kb5c5v.js";import"../chunk-fne338jr.js";import"../chunk-h6kptkce.js";import"../chunk-zy3kr4s2.js";import"../chunk-1087xz1v.js";import"../chunk-hcbrgyfz.js";import"../chunk-zwayp7fz.js";import"../chunk-tpvmpmxj.js";import{Ug,Gc,Qg,oe,Vc,ei,Hg,qc,pd,mo,md,rr,Pi,fo}from"../chunk-mvmxy0z7.js";import"../chunk-dmv3vryr.js";import"../chunk-a77mhcs7.js";import"../chunk-by7hejhg.js";import"../chunk-1psh3mhm.js";import"../chunk-7d9ek8rc.js";import{wt,LA,Td,_i,Li,$i,tm}from"../chunk-xs9m0v31.js";import{Q,Kr,Wr,wd,Eo,d,$A,rm,nm,GI,VI}from"../chunk-x7cnfn7y.js";import"../chunk-fe6m7wb0.js";import"../chunk-72p2tdpe.js";import"../chunk-sjfc9my3.js";export{LA as DEFAULT_SITE_PORT_RANGE,wt as HOST_SITES_DIR,Vc as IPV6_EXCLUDED_HOST_LABELS,pd as MANAGEMENT_DASHBOARD_SITE,Nn as addSiteToCloudConfig,tm as allocateSitePorts,lI as buildAndPushContainerImage,wc as buildAndPushServerlessImage,Er as buildFunctionEnv,Li as buildHostSitePortsScript,fo as buildManagementDashboardArtifact,Ht as buildServerTopology,ks as buildServerlessTopology,xh as buildTopology,cc as collectEgressMetrics,Ug as collectServerDnsDomains,Bh as createContainerImageDependencies,Ph as createExistingStaticFullStackDependencies,Dh as createStaticApiOriginDependencies,$n as dashboardActions,mo as dashboardCredentialsFile,mg as dashboardPageRoutes,Sg as deleteFailoverReplicaBuckets,vc as deleteStaticSite,cI as deployExistingStaticFullStack,ac as deployServerlessApp,VI as deployShipsFiles,Ig as deploySite,sI as deployStaticApiOrigin,_s as deployStaticSite,Tc as deployStaticSiteFull,Mn as deployStaticSiteWithExternalDns,Un as deployStaticSiteWithExternalDnsFull,bg as egressReportMetrics,v as ensureDashboardActor,hg as ensureFailoverReplicaBuckets,Pi as ensureManagementDashboard,dI as estimateExistingStaticFullStackMonthlyCost,aI as estimateStaticApiOriginMonthlyCost,Cg as fetchEgressReport,kh as generateExistingStaticFullStackTemplate,Ec as generateExternalDnsStaticSiteTemplate,Os as generateStaticSiteTemplate,Ag as grantFailoverReplicaAccess,$A as hasComputeConfigured,wd as hasProxyUpstream,Nh as hashContainerContext,ei as hostAcceptsIpv6,Ps as infraEnvFromOutputs,pg as initializeDashboardControlPlane,$s as invalidateCache,Kr as isPhpSite,oc as isValidHostname,oe as normalizePublicIpv6,_i as occupiedHostPorts,$i as parseHostSiteFragments,Td as parseUpstreamPort,Hg as reconcileAddressRecords,xn as redeployServerlessApp,Qg as removeAddressRecords,Bn as removeSiteFromCloudConfig,Gc as removeStaleServerAddressRecords,lg as renderAliasesValue,dg as renderEnvValue,ug as renderRedirectsValue,Rh as renderSiteSnippet,ag as renderSslValue,cg as renderStringValue,xs as resolveDashboardAction,md as resolveDashboardAuth,_n as resolveDashboardData,fg as resolveLegacyDashboardRoute,Wr as resolveProxyUpstreams,Eo as resolveSiteDeployTarget,d as resolveSiteKind,rr as resolveUiSource,On as rollbackServerlessApp,iI as routesForDashboard,ut as runRemoteCommand,Bs as sanitizeCloudConfig,yg as seedFailoverReplicas,gg as setAttachToInCloudConfig,vr as setMaintenance,Rs as setSitePropertyInCloudConfig,nm as shipsARelease,GI as shipsToBucket,Q as siteInstallBase,Cc as startLocalDashboardServer,Ds as synchronizeDashboardUsers,Ue as trackDashboardOperation,og as updateSiteInCloudConfig,Ls as uploadStaticFiles,rm as validateDeploymentConfig,qc as verifyAddressRecord,oI as verifyStaticApiOrigin};
1
+ import{Nn,Bn,og,Rs,ag,cg,dg,oc,lg,ug,Rh,gg,v,pg,Ds,Ue,mg,fg,iI,hg,Ag,yg,Sg,Ig,Dh,sI,oI,aI,Ph,kh,cI,dI,Nh,Bh,lI,Ps,Er,ac,xn,On,vr,ut,Ht,ks,xh,_n,bg,Cg,cc,Bs,$n,xs,Cc}from"../chunk-cjm5j58y.js";import{Ec,Mn,Un,Os,_s,Ls,$s,vc,Tc}from"../chunk-9f18pebj.js";import{wc}from"../chunk-c6kb5c5v.js";import"../chunk-fne338jr.js";import"../chunk-h6kptkce.js";import"../chunk-zy3kr4s2.js";import"../chunk-1087xz1v.js";import"../chunk-hcbrgyfz.js";import"../chunk-zwayp7fz.js";import"../chunk-tpvmpmxj.js";import{Ug,Gc,Qg,oe,Vc,ei,Hg,qc,pd,mo,md,rr,Pi,fo}from"../chunk-zjkxhvn0.js";import"../chunk-dmv3vryr.js";import"../chunk-a77mhcs7.js";import"../chunk-by7hejhg.js";import"../chunk-1psh3mhm.js";import"../chunk-7d9ek8rc.js";import{wt,LA,Td,_i,Li,$i,tm}from"../chunk-xs9m0v31.js";import{Q,Kr,Wr,wd,Eo,d,$A,rm,nm,GI,VI}from"../chunk-x7cnfn7y.js";import"../chunk-fe6m7wb0.js";import"../chunk-72p2tdpe.js";import"../chunk-sjfc9my3.js";export{LA as DEFAULT_SITE_PORT_RANGE,wt as HOST_SITES_DIR,Vc as IPV6_EXCLUDED_HOST_LABELS,pd as MANAGEMENT_DASHBOARD_SITE,Nn as addSiteToCloudConfig,tm as allocateSitePorts,lI as buildAndPushContainerImage,wc as buildAndPushServerlessImage,Er as buildFunctionEnv,Li as buildHostSitePortsScript,fo as buildManagementDashboardArtifact,Ht as buildServerTopology,ks as buildServerlessTopology,xh as buildTopology,cc as collectEgressMetrics,Ug as collectServerDnsDomains,Bh as createContainerImageDependencies,Ph as createExistingStaticFullStackDependencies,Dh as createStaticApiOriginDependencies,$n as dashboardActions,mo as dashboardCredentialsFile,mg as dashboardPageRoutes,Sg as deleteFailoverReplicaBuckets,vc as deleteStaticSite,cI as deployExistingStaticFullStack,ac as deployServerlessApp,VI as deployShipsFiles,Ig as deploySite,sI as deployStaticApiOrigin,_s as deployStaticSite,Tc as deployStaticSiteFull,Mn as deployStaticSiteWithExternalDns,Un as deployStaticSiteWithExternalDnsFull,bg as egressReportMetrics,v as ensureDashboardActor,hg as ensureFailoverReplicaBuckets,Pi as ensureManagementDashboard,dI as estimateExistingStaticFullStackMonthlyCost,aI as estimateStaticApiOriginMonthlyCost,Cg as fetchEgressReport,kh as generateExistingStaticFullStackTemplate,Ec as generateExternalDnsStaticSiteTemplate,Os as generateStaticSiteTemplate,Ag as grantFailoverReplicaAccess,$A as hasComputeConfigured,wd as hasProxyUpstream,Nh as hashContainerContext,ei as hostAcceptsIpv6,Ps as infraEnvFromOutputs,pg as initializeDashboardControlPlane,$s as invalidateCache,Kr as isPhpSite,oc as isValidHostname,oe as normalizePublicIpv6,_i as occupiedHostPorts,$i as parseHostSiteFragments,Td as parseUpstreamPort,Hg as reconcileAddressRecords,xn as redeployServerlessApp,Qg as removeAddressRecords,Bn as removeSiteFromCloudConfig,Gc as removeStaleServerAddressRecords,lg as renderAliasesValue,dg as renderEnvValue,ug as renderRedirectsValue,Rh as renderSiteSnippet,ag as renderSslValue,cg as renderStringValue,xs as resolveDashboardAction,md as resolveDashboardAuth,_n as resolveDashboardData,fg as resolveLegacyDashboardRoute,Wr as resolveProxyUpstreams,Eo as resolveSiteDeployTarget,d as resolveSiteKind,rr as resolveUiSource,On as rollbackServerlessApp,iI as routesForDashboard,ut as runRemoteCommand,Bs as sanitizeCloudConfig,yg as seedFailoverReplicas,gg as setAttachToInCloudConfig,vr as setMaintenance,Rs as setSitePropertyInCloudConfig,nm as shipsARelease,GI as shipsToBucket,Q as siteInstallBase,Cc as startLocalDashboardServer,Ds as synchronizeDashboardUsers,Ue as trackDashboardOperation,og as updateSiteInCloudConfig,Ls as uploadStaticFiles,rm as validateDeploymentConfig,qc as verifyAddressRecord,oI as verifyStaticApiOrigin};
@@ -1 +1 @@
1
- import{ti,Yt,_r,Zt,Lr,F,Mr,ri,ni,Fr,Ur,Jh,Xh,Kg,Wg,Yh,Zh,eA,Qr,ii,Jg,ao,si,oi,ai,ci,di,jc,zc,li,Hr,Ce,Kc,yt,Wc,ui,Jc,Gr,Yc,ze,ae,tr,Xg,gi,Zc,ed,td,rd,St,Ke,We,It,pi,mi,Ne,co,lo,Yg,Zg,nd,ep,bt,fi,id,tp,rp,sd,Ct,Be,od,np,ip,uo,hi,Et,sp,op,ap,cp,dp,lp,up,gp,pp,Ai,yi,Si,Ii,bi,Ci,Ei,mp,fp,Vr,U,go,hp,Ap,yp,ad,Sp,Ip,tA,rA,nA,cd,bp,iA,sA,oA,vi,Ti,wi,Ri,dd,ld,Di,ud,aA,po,Cp,Ep,vp,Tp,wp,gd,cA,ho,fd,ki,hd,Rp,Dp,Pp,dA}from"../chunk-mvmxy0z7.js";import{yo,Io,bo,lA,Sd,x,nr,HI,Co,xp,Je,V,xe}from"../chunk-dmv3vryr.js";import"../chunk-a77mhcs7.js";import"../chunk-by7hejhg.js";import"../chunk-1psh3mhm.js";import"../chunk-7d9ek8rc.js";import"../chunk-x7cnfn7y.js";import"../chunk-72p2tdpe.js";import"../chunk-sjfc9my3.js";export{ud as AwsBoxProvisioner,Mr as AwsDriver,yp as BOOT_PARTITION_LABEL,Cp as BOX_PANTRY_BIN_DIR,po as BOX_PANTRY_CLI_DIR,go as CloudDriverFactory,Wg as DEFAULT_HOST_CLEANUP_ESCALATED,Zh as DEFAULT_HOST_CLEANUP_HIGH_WATER_PERCENT,Yh as DEFAULT_HOST_CLEANUP_LOW_WATER_PERCENT,Kg as DEFAULT_HOST_CLEANUP_RETENTION,eA as DEFAULT_HOST_CLEANUP_SCHEDULE,yo as DEFAULT_RPX_CERTS_DIR,Ap as FIRST_BOOT_SCRIPT_PATH,Ur as HOST_ARTIFACT_CACHE_DIR,Jh as HOST_CLEANUP_SCRIPT_PATH,Xh as HOST_CLEANUP_UNIT,Di as HetznerBoxProvisioner,Gr as HetznerClient,Ne as HetznerDriver,rd as LEGACY_DRIVER_STATE_DIR,co as LocalBoxDriver,Dp as MANAGED_CACHE_POLICY_DISABLED,Rp as MANAGED_CACHE_POLICY_OPTIMIZED,Pp as MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER,ip as RASPBERRY_PI_DEFAULT_SWAP_GB,Jc as REMOTE_SCRIPT_RUNNER,Co as RPX_DIR,xp as RPX_LAUNCHER_PATH,Je as RPX_SERVICE_NAME,od as SSH_BOOTSTRAP_MARKER_DIR,Be as SSH_BOOTSTRAP_VERSION,Et as SSH_DEFAULTS,Ei as SSH_DEPLOY_STORAGE_PATH,Yg as SSH_INSECURE_HOST_KEY_OPTS,Zg as SSH_KEEPALIVE_OPTS,yi as SSH_PREFLIGHT_SCRIPT,mp as SSH_SKIP_BOOTSTRAP_ENV,Vr as SshDriver,Ct as SystemSshTransport,dd as UBUNTU_2404_AMI_PARAM,oA as acquireResizeLock,tA as applyHetznerHostOptimization,mi as applyHetznerVolumes,uo as assertArchSupported,fp as assertSshComputeConfig,jc as buildAwsArtifactFetch,wp as buildBoxConvergeScript,Ep as buildBoxSandboxConvergeScript,ld as buildBoxUserData,dA as buildCloudFrontOriginConfig,ad as buildCloudInitFirstBoot,ni as buildComputeStorageInstallScript,Fr as buildComputeStorageSiteScript,Ip as buildHetznerHostOptimizationScript,si as buildHostCleanupDeployScript,Jg as buildHostCleanupExecutable,ao as buildHostCleanupInstallScript,ii as buildHostCleanupScript,zc as buildLocalArtifactFetch,x as buildRpxConfig,xe as buildRpxFragmentRefreshScript,nr as buildRpxLbConfig,V as buildRpxProvisionScript,ep as buildScpArgsFor,ai as buildSiteDeployScript,li as buildSshArgs,nd as buildSshArgsFor,hi as buildSshBootstrapScript,ci as buildStaticSiteDeployScript,hp as cloudDrivers,rA as collectHetznerHostOptimizationReport,Zc as collectHetznerResizeManifest,aA as createBoxProvisioner,U as createCloudDriver,fd as deployAllComputeSites,ho as deploySiteRelease,Sd as deriveRouteId,ti as describeScriptSyntaxError,St as driverStateDir,Ke as driverStatePath,Ti as ensureFirewall,wi as ensureServer,vi as ensureSshKey,Ii as evaluatePreflight,gi as executeHetznerServerResize,rp as findKnownHostKey,Ci as formatPreflightFindings,Yt as formatSshFailure,bo as gatewayHostnames,F as generateUbuntuAppCloudInit,Io as hasAutoWwwVariant,lo as isBoxMode,Xg as isHetznerCapacityError,Lr as isLocalDatabase,tp as knownHostsLine,id as knownHostsToken,lA as normalizeRoutePath,ze as normalizeSshPublicKey,gd as parseBoxReport,Si as parsePreflightFacts,tr as planHetznerServerResize,pi as planHetznerVolumes,bi as preflightFailed,ed as prepareHetznerResize,cA as provisionBox,We as readDriverState,iA as readResizeCheckpoint,di as releaseTarballTmpPath,ki as reloadRpxGateway,ui as remoteScriptRunner,Tp as renderBoxUnit,vp as renderEnvFile,HI as renderRpxLauncher,hd as renewRpxCertificates,cd as resizeCheckpointPath,bp as resizeLockPath,ri as resolveComputeVolumes,oi as resolveExecStart,Yc as resolveHetznerApiToken,Sp as resolveHetznerHostOptimizationPlan,Qr as resolveHostCleanupConfig,dp as resolveSshHostKeyPolicy,sp as resolveSshHosts,pp as resolveSshLan,ap as resolveSshPort,cp as resolveSshPrivateKeyPath,up as resolveSshProfile,gp as resolveSshPublicIp,Ai as resolveSshSettings,lp as resolveSshSudo,op as resolveSshUser,fi as scanHostKey,Kc as scpUpload,Ri as serverPublicIpv4,np as sshBootstrapMarkerPath,Hr as sshExec,Ce as sshExecOrThrow,bt as sshHostKeyFingerprint,sd as sshKnownHostsPath,Zt as summarizeRemoteFailures,_r as surfaceRemoteNotices,nA as verifyHetznerHostOptimization,td as verifyHetznerResize,Wc as waitForCloudInit,yt as waitForSsh,ae as wrapCloudInitUserData,It as writeDriverState,sA as writeResizeCheckpoint};
1
+ import{ti,Yt,_r,Zt,Lr,F,Mr,ri,ni,Fr,Ur,Jh,Xh,Kg,Wg,Yh,Zh,eA,Qr,ii,Jg,ao,si,oi,ai,ci,di,jc,zc,li,Hr,Ce,Kc,yt,Wc,ui,Jc,Gr,Yc,ze,ae,tr,Xg,gi,Zc,ed,td,rd,St,Ke,We,It,pi,mi,Ne,co,lo,Yg,Zg,nd,ep,bt,fi,id,tp,rp,sd,Ct,Be,od,np,ip,uo,hi,Et,sp,op,ap,cp,dp,lp,up,gp,pp,Ai,yi,Si,Ii,bi,Ci,Ei,mp,fp,Vr,U,go,hp,Ap,yp,ad,Sp,Ip,tA,rA,nA,cd,bp,iA,sA,oA,vi,Ti,wi,Ri,dd,ld,Di,ud,aA,po,Cp,Ep,vp,Tp,wp,gd,cA,ho,fd,ki,hd,Rp,Dp,Pp,dA}from"../chunk-zjkxhvn0.js";import{yo,Io,bo,lA,Sd,x,nr,HI,Co,xp,Je,V,xe}from"../chunk-dmv3vryr.js";import"../chunk-a77mhcs7.js";import"../chunk-by7hejhg.js";import"../chunk-1psh3mhm.js";import"../chunk-7d9ek8rc.js";import"../chunk-x7cnfn7y.js";import"../chunk-72p2tdpe.js";import"../chunk-sjfc9my3.js";export{ud as AwsBoxProvisioner,Mr as AwsDriver,yp as BOOT_PARTITION_LABEL,Cp as BOX_PANTRY_BIN_DIR,po as BOX_PANTRY_CLI_DIR,go as CloudDriverFactory,Wg as DEFAULT_HOST_CLEANUP_ESCALATED,Zh as DEFAULT_HOST_CLEANUP_HIGH_WATER_PERCENT,Yh as DEFAULT_HOST_CLEANUP_LOW_WATER_PERCENT,Kg as DEFAULT_HOST_CLEANUP_RETENTION,eA as DEFAULT_HOST_CLEANUP_SCHEDULE,yo as DEFAULT_RPX_CERTS_DIR,Ap as FIRST_BOOT_SCRIPT_PATH,Ur as HOST_ARTIFACT_CACHE_DIR,Jh as HOST_CLEANUP_SCRIPT_PATH,Xh as HOST_CLEANUP_UNIT,Di as HetznerBoxProvisioner,Gr as HetznerClient,Ne as HetznerDriver,rd as LEGACY_DRIVER_STATE_DIR,co as LocalBoxDriver,Dp as MANAGED_CACHE_POLICY_DISABLED,Rp as MANAGED_CACHE_POLICY_OPTIMIZED,Pp as MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER,ip as RASPBERRY_PI_DEFAULT_SWAP_GB,Jc as REMOTE_SCRIPT_RUNNER,Co as RPX_DIR,xp as RPX_LAUNCHER_PATH,Je as RPX_SERVICE_NAME,od as SSH_BOOTSTRAP_MARKER_DIR,Be as SSH_BOOTSTRAP_VERSION,Et as SSH_DEFAULTS,Ei as SSH_DEPLOY_STORAGE_PATH,Yg as SSH_INSECURE_HOST_KEY_OPTS,Zg as SSH_KEEPALIVE_OPTS,yi as SSH_PREFLIGHT_SCRIPT,mp as SSH_SKIP_BOOTSTRAP_ENV,Vr as SshDriver,Ct as SystemSshTransport,dd as UBUNTU_2404_AMI_PARAM,oA as acquireResizeLock,tA as applyHetznerHostOptimization,mi as applyHetznerVolumes,uo as assertArchSupported,fp as assertSshComputeConfig,jc as buildAwsArtifactFetch,wp as buildBoxConvergeScript,Ep as buildBoxSandboxConvergeScript,ld as buildBoxUserData,dA as buildCloudFrontOriginConfig,ad as buildCloudInitFirstBoot,ni as buildComputeStorageInstallScript,Fr as buildComputeStorageSiteScript,Ip as buildHetznerHostOptimizationScript,si as buildHostCleanupDeployScript,Jg as buildHostCleanupExecutable,ao as buildHostCleanupInstallScript,ii as buildHostCleanupScript,zc as buildLocalArtifactFetch,x as buildRpxConfig,xe as buildRpxFragmentRefreshScript,nr as buildRpxLbConfig,V as buildRpxProvisionScript,ep as buildScpArgsFor,ai as buildSiteDeployScript,li as buildSshArgs,nd as buildSshArgsFor,hi as buildSshBootstrapScript,ci as buildStaticSiteDeployScript,hp as cloudDrivers,rA as collectHetznerHostOptimizationReport,Zc as collectHetznerResizeManifest,aA as createBoxProvisioner,U as createCloudDriver,fd as deployAllComputeSites,ho as deploySiteRelease,Sd as deriveRouteId,ti as describeScriptSyntaxError,St as driverStateDir,Ke as driverStatePath,Ti as ensureFirewall,wi as ensureServer,vi as ensureSshKey,Ii as evaluatePreflight,gi as executeHetznerServerResize,rp as findKnownHostKey,Ci as formatPreflightFindings,Yt as formatSshFailure,bo as gatewayHostnames,F as generateUbuntuAppCloudInit,Io as hasAutoWwwVariant,lo as isBoxMode,Xg as isHetznerCapacityError,Lr as isLocalDatabase,tp as knownHostsLine,id as knownHostsToken,lA as normalizeRoutePath,ze as normalizeSshPublicKey,gd as parseBoxReport,Si as parsePreflightFacts,tr as planHetznerServerResize,pi as planHetznerVolumes,bi as preflightFailed,ed as prepareHetznerResize,cA as provisionBox,We as readDriverState,iA as readResizeCheckpoint,di as releaseTarballTmpPath,ki as reloadRpxGateway,ui as remoteScriptRunner,Tp as renderBoxUnit,vp as renderEnvFile,HI as renderRpxLauncher,hd as renewRpxCertificates,cd as resizeCheckpointPath,bp as resizeLockPath,ri as resolveComputeVolumes,oi as resolveExecStart,Yc as resolveHetznerApiToken,Sp as resolveHetznerHostOptimizationPlan,Qr as resolveHostCleanupConfig,dp as resolveSshHostKeyPolicy,sp as resolveSshHosts,pp as resolveSshLan,ap as resolveSshPort,cp as resolveSshPrivateKeyPath,up as resolveSshProfile,gp as resolveSshPublicIp,Ai as resolveSshSettings,lp as resolveSshSudo,op as resolveSshUser,fi as scanHostKey,Kc as scpUpload,Ri as serverPublicIpv4,np as sshBootstrapMarkerPath,Hr as sshExec,Ce as sshExecOrThrow,bt as sshHostKeyFingerprint,sd as sshKnownHostsPath,Zt as summarizeRemoteFailures,_r as surfaceRemoteNotices,nA as verifyHetznerHostOptimization,td as verifyHetznerResize,Wc as waitForCloudInit,yt as waitForSsh,ae as wrapCloudInitUserData,It as writeDriverState,sA as writeResizeCheckpoint};
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{WI,JI,ul,Dm,gl,pl,ln,H,l,ml,Pm,W,fl,p,gy,b,tt,Yi,un,w,le,hl,py,r,t,XI,YI,m,ZI,eb,tb,rb,nb,ur,Al,Zi,my,ib,sb,_e,rt,yl,km,Nm,ob,Bm,xm,Om,Ko,Sl,ue,gn,Nt,Wo,Bt,ve,fy,Il,Jo,_m,Lm,$m,Mm,bl,ab,J,E,hy,Ay,Fm,a,S,nt,f,Um,it,X,xt,cb,Qm,Y,Cl,Le,gr,Xo,ge,El,pe,yy,Yo,Z,ee,L,es,D,pr,Ot,te,e,pn,db,Hm,vl,lb,ub,gb,pb,Tl,mb,fb,hb,Ab,yb,Sb,Ib,bb,Cb,Eb,vb,Tb,Sy,Iy,by,Cy,Ey,vy,Ty,mr,Gm,Vm,fr,ts,wb,qm,Rb,Db,mn,Pb,kb,Nb,Bb,xb,Ob,jm,k,Te,rs,Zo,fn,ns,ea,wy,_b,is,ta,Ry,Dy,Py,ky,Ny,By,ss,Lb,ra,xy,zm,q,Oy,st,na,_t,_y,Km,Ly,$y,My,Wm,j,$b,Mb,Fb,Ub,Fy,Qb,re,Hb,Gb,Vb,wl,Rl,Uy,Jm,Xm,qb,jb,zb,Kb,Wb,Qy,Dl,Jb,Xb,Yb,Zb,eC,Hy,Gy,tC,rC,nC,iC,sC,oC,aC,Vy,cC,Ym,Pl,dC,lC,uC,gC,Zm,ef,tf,pC,kl,qy,jy,zy,Ky,Nl,Wy,mC,fC,hC,AC,yC,SC,IC,Jy,Xy,Yy,Zy,rf,bC,CC,EC,vC,TC,wC,RC,DC,PC,eS,tS,rS,nS,kC,NC,nf,BC,sf,of,af,cf,xC,OC,_C,LC,$e,os,$C,MC,FC,UC,QC,HC,GC,VC,iS,qC,jC,df,lf,zC,KC,sS,WC,JC,XC,YC,ZC,eE,tE,rE,nE,iE,sE,oE,aE,cE,dE,lE,uE,gE,pE,mE,fE,Bl,oS,xl,aS,Ol,cS,_l,dS,Ll,lS,hr,uS,$l,gS,as,pS,Ml,mS,Fl,fS,uf,hE,gf,AE,Ul,hS,Ar,AS,pf,yE,Ql,yS,mf,SE,ff,IE,hf,bE,Hl,SS,Af,CE,yf,EE,Sf,vE,If,TE,Gl,IS,Vl,bS,bf,wE,Cf,RE,Ef,DE,vf,PE,Tf,kE,wf,NE,ql,CS,Rf,BE,Df,xE,Pf,OE,kf,_E,Nf,LE,Bf,$E,xf,Of,_f,Lf,$f,ME,Mf,FE,Ff,UE,Uf,QE,ot,Qf,ES,ia,jl,hn,vS,cs,yr,zl,Kl,TS,wS,Wl,Hf,Jl,Gf,HE,GE,sa,oa,aa,Xl,An,Yl,Zl,ds,ca,da,Vf,RS,DS,PS,VE,qf,jf,qE,kS,zf,NS,BS,xS,jE,Kf,yn,eu,Wf,zE,OS,la,ua,tu,Jf,KE,ru,_S,Xf,WE,Yf,JE,Zf,XE}from"./chunk-72p2tdpe.js";import{nu,N,iu,ga,MS,eh,FS,US,QS,HS,GS,VS,qS,jS}from"./chunk-sjfc9my3.js";import{ya,th,gu,KS,ms,pu,Sa,rh,nh,In,Ia,mu,at,fu,hu,Au,fs,bn,ih,ct,yu,ba,Ca,Ea,Su,Iu,bu,hs,va,Cu,Cn,As,Ta,Lt,sh,Eu,vu,oh,Tu,wa,Sr,wu,Ru,Du,Pu,dt,ah,ku,Ir,Ra,Da,Pa,ys,Ss,En,Nu,Is,ka,Na,vn,Bu,Tn,ch,dh,$t,wn,Ba,lh,xu,Ou,xa,_u,Lu,$u,WS,me,Mu,JS,XS,bs,Cs,YS,we,uh,Mt,Me,Fe,Ft,Fu,Uu,Qu,Hu,gh,ph,Oa,mh,fh,_a,Gu,Vu,hh,fe,Ah,qu,Re,La,lt,Ut,Qt,Rn,Es,ju,ZS,yh,Sh,Ih,bh,$a,Ma,zu,Fa,Dn,Ua,Ku,vs,Wu,Qa,Ha,Ga,Va,qa,ja,za,Ka,Ju,br,Wa,Xu,Pn,Yu,Ja,Xa,Zu,Cr,Ya,Za,Ch,eI,Ts,tI,rI,nI,ec,tc,eg,Eh,rc,kn,tg,ws,rg,ng,ig,nc,vh,ic,sg,Th,sc,wh,Nn,Bn,og,Rs,gg,hg,Ag,yg,Sg,Ig,Ps,Er,ac,xn,On,vr,ut,Oh,dc,_h,Lh,Eg,lc,Ns,vg,uc,Gt,Qe,Tg,gc,pc,wg,mc,fc,hc,Ac,Rg,Dg,Ln,yc,Sc,Ic,bc,Pg,Bs,$n,xs,Cc}from"./chunk-n95wbpge.js";import{uu}from"./chunk-kcem6dzk.js";import{Q,Wr,wd,Eo,d,rm,nm}from"./chunk-x7cnfn7y.js";import{wt,Td,_i,Li,$i,tm}from"./chunk-xs9m0v31.js";import{gA,pA,mA,Lp,$p,Mp,fA,Fp,Up,hA,AA,Qp,yA,SA,Ed,Hp,IA,bA,Gp,CA,EA,vA,TA,wA,RA,DA,Oi,vd,Vp,qp,jp,zp,Kp,Wp,Jp,Xp,Yp,Zp,em,PA,kA,NA,BA,xA,OA,_A}from"./chunk-byr76jcy.js";import{Ye,Rd,Ee,ir,Dd,O,sr,Rt,Pd,vo,MA,im,kd,s,Mi,To,Jr,Nd,Bd,Xr,FA,xd,qI,jI,wo,zI,KI,Od,_d,Fi,Ro,de,c,Do,Ze,Yr,UA,QA,Ld,HA,Po,GA,VA,ko,$d,Zr,No,qA,or,Md,sm,ar,en,jA,Bo,zA,_,KA,Fd,om,xo,WA,JA,XA,Ud,Ui,Oo,Qd,cr,Dt,YA,tn,ZA,Hd,am,cm,_o,Gd,Vd,Pt,dm,Qi,qd,Lo,rn,lm,Hi,jd,zd,Gi,um,Kd,Wd,Jd,Xd,$o,gm,pm,ey,mm,Yd,Vi,fm,hm,Mo,nn,Fo,Uo,Qo,Zd,Am,el,Ho,ty,dr,ry,tl,sn,rl,ny,nl,ym,qi,on,Go,ji,et,iy,Sm,Im,lr,il,sl,ol,zi,Ki,Wi,sy,oy,kt,Vo,ay,an,bm,qo,cy,Cm,Em,vm,dy,Tm,wm,ly,i,uy,Ji,jo,zo}from"./chunk-fe6m7wb0.js";import{n}from"./chunk-7d9ek8rc.js";import{ke,ft,Wn}from"./chunk-zy3kr4s2.js";import{De,Us,Qs,Bg,Rc,Dc,Hs,Pc,gt,ne,pt,he,T,Pe,Hn,kc,He,Nc,Gn,Vn,qn,Vt,qt,jt,jn,wr,Bc,Rr,Dr,mt,zn,Oc,zt,Pr,Kn,Lc,$g,Mg,$c,kr}from"./chunk-fne338jr.js";import{o}from"./chunk-1psh3mhm.js";import{A}from"./chunk-by7hejhg.js";import{jr,Oe}from"./chunk-a77mhcs7.js";import{Mc,Ge,I}from"./chunk-1087xz1v.js";import{C}from"./chunk-tpvmpmxj.js";import{ht,Se,qe,Fg,Kt,Fc,Uc,Wt,G,Jn,Jt,Xt,Xn,js,zs,Nr,Br,Yn,xr,Ks,Ws,Js,Xs,se,Ys,Zs,eo,to,Ie,ro,no,io,B,Qc,Zn,Hc,be,Or}from"./chunk-zwayp7fz.js";import{Ve}from"./chunk-hcbrgyfz.js";import{ie}from"./chunk-h6kptkce.js";import{Ug,Gc,Qg,oe,Vc,ei,Hg,qc,Gg,Vg,Wh,Lr,oo,F,Mr,ri,ni,Fr,Qr,ii,ao,si,oi,ai,ci,li,Hr,Ce,Kc,yt,Wc,Gr,Yc,ze,ae,Ke,We,It,pi,mi,Ne,Ct,Be,hi,Ai,yi,Si,Ii,bi,Ci,Vr,U,go,hp,ad,vi,Ti,wi,Ri,pd,mo,md,rr,Pi,fo,ho,fd,ki,hd}from"./chunk-mvmxy0z7.js";import{yo,Io,bo,x,xe}from"./chunk-dmv3vryr.js";import{su,pa,us,gs,ma,ou,au,ps,fa,ha,du,lu,Aa}from"./chunk-qra9k26f.js";import{Ec,Mn,Un,Os,_s,Ls,$s,vc,Tc}from"./chunk-9f18pebj.js";import{wc}from"./chunk-c6kb5c5v.js";import{ce,Ni,Ao,Ad,Bi,kp}from"./chunk-4m5gpp6w.js";import{al,cn,cl,dl,ll,Xi,Rm,dn}from"./chunk-sxqe8e9c.js";import{LS,ls}from"./chunk-jz6dacx1.js";var eR="https://api.machines.dev/v1";class So extends Error{status;path;constructor(u,g,h){super(u);this.status=g;this.path=h;this.name="FlyApiError"}}function sd(u){let g=u.ip.includes(":");if(g&&u.ip.startsWith("fdaa:"))return"private_v6";if(u.shared)return"shared_v4";return g?"v6":"v4"}class Cp{token;fetch;constructor(u){if(!u.token)throw Error("Fly.io needs an API token: set FLY_API_TOKEN (`fly tokens create deploy` makes one scoped to an app).");this.token=u.token,this.fetch=u.fetch??fetch}async rest(u,g,h={}){let y=new URL(`https://api.machines.dev/v1${g}`);for(let[M,V]of Object.entries(h.query??{}))y.searchParams.set(M,V);let R=await this.fetch(y,{method:u,headers:{Authorization:`Bearer ${this.token}`,...h.body!==void 0?{"Content-Type":"application/json"}:{},...h.headers},body:h.body===void 0?void 0:JSON.stringify(h.body)});if(R.status===404&&h.notFound==="null")return null;let v=await R.text(),P=v?Sp(v):void 0;if(!R.ok){let M=typeof P==="object"&&P&&"error"in P?String(P.error):v||R.statusText;throw new So(`Fly.io ${u} ${g} failed (${R.status}): ${M}`,R.status,g)}return P}getApp(u){return this.rest("GET",`/apps/${encodeURIComponent(u)}`,{notFound:"null"})}createApp(u,g){return this.rest("POST","/apps",{body:{app_name:u,org_slug:g}})}async listMachines(u){return await this.rest("GET",`/apps/${encodeURIComponent(u)}/machines`)??[]}createMachine(u,g){return this.rest("POST",`/apps/${encodeURIComponent(u)}/machines`,{body:g})}updateMachine(u,g,h,y){return this.rest("POST",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}`,{body:h,headers:{"fly-machine-lease-nonce":y}})}async acquireLease(u,g,h=120){let R=(await this.rest("POST",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}/lease`,{body:{ttl:h}})).data?.nonce;if(!R)throw new So(`Fly.io gave no lease nonce for Machine ${g}`,200,`/machines/${g}/lease`);return R}async releaseLease(u,g,h){await this.rest("DELETE",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}/lease`,{headers:{"fly-machine-lease-nonce":h}})}async waitForState(u,g,h,y={}){await this.rest("GET",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}/wait`,{query:{state:h,timeout:String(y.timeoutSeconds??60),...y.instanceId?{instance_id:y.instanceId}:{}}})}async listVolumes(u){return await this.rest("GET",`/apps/${encodeURIComponent(u)}/volumes`)??[]}createVolume(u,g){return this.rest("POST",`/apps/${encodeURIComponent(u)}/volumes`,{body:{...g,encrypted:!0}})}async setSecrets(u,g){return(await this.rest("POST",`/apps/${encodeURIComponent(u)}/secrets`,{body:{values:g}})).version}async listIpAssignments(u){return(await this.rest("GET",`/apps/${encodeURIComponent(u)}/ip_assignments`)).ips??[]}async assignIp(u,g){let h=await this.rest("POST",`/apps/${encodeURIComponent(u)}/ip_assignments`,{body:{type:g}});if(!h.ip)throw new So(`Fly.io assigned no ${g} address to ${u}`,200,`/apps/${u}/ip_assignments`);return{ip:h.ip,shared:h.shared??g==="shared_v4",region:h.region}}async requestCertificate(u,g){return this.rest("POST",`/apps/${encodeURIComponent(u)}/certificates/acme`,{body:{hostname:g}})}}function Sp(u){try{return JSON.parse(u)}catch{return}}var zc="ts-cloud-role";function nR(u,g){let h=u.fly??{},y=h.app??`${u.project.slug}-${g.environment}`;if(!/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(y))throw Error(`"${y}" is not a valid Fly app name: lowercase letters, digits and dashes, 3 to 63 characters.`);let R=h.internalPort??3000,v=h.count??1;if(!Number.isInteger(v)||v<1)throw Error(`fly.count must be a whole number of at least 1, got ${v}.`);return{app:y,org:h.org??"personal",image:g.image,regions:h.regions?.length?h.regions:["iad"],count:v,internalPort:R,healthPath:h.healthPath??"/",vm:{cpuKind:h.vm?.cpuKind??"shared",cpus:h.vm?.cpus??1,memoryMb:h.vm?.memoryMb??512},...h.volume?{volume:{name:h.volume.name??"data",sizeGb:h.volume.sizeGb,path:h.volume.path}}:{},autoStop:h.autoStop??!1,env:{...g.env,PORT:String(R)},secrets:g.secrets??{},hostnames:h.hostnames??[],release:g.release}}function Rp(u){return{image:u.image,env:u.env,guest:{cpu_kind:u.vm.cpuKind,cpus:u.vm.cpus,memory_mb:u.vm.memoryMb},services:[{protocol:"tcp",internal_port:u.internalPort,ports:[{port:80,handlers:["http"],force_https:!0},{port:443,handlers:["tls","http"]}],autostop:u.autoStop?"stop":"off",autostart:!0,...u.autoStop?{min_machines_running:0}:{},checks:[{type:"http",method:"GET",path:u.healthPath,interval:"15s",timeout:"5s",grace_period:"10s"}]}],restart:{policy:"on-failure",max_retries:10},metadata:{[zc]:"app","ts-cloud-release":u.release}}}async function iR(u,g,h=()=>{}){let y=!1;if(!await u.getApp(g.app))h(`Creating Fly app ${g.app} in ${g.org}`),await u.createApp(g.app,g.org),y=!0;let R;if(Object.keys(g.secrets).length>0)R=await u.setSecrets(g.app,g.secrets),h(`Set ${Object.keys(g.secrets).length} secret(s) (version ${R})`);let v=await u.listIpAssignments(g.app),P=new Set(v.map(sd));if(!P.has("v6"))v.push(await u.assignIp(g.app,"v6")),h("Assigned a dedicated IPv6");if(!P.has("v4")&&!P.has("shared_v4"))v.push(await u.assignIp(g.app,"shared_v4")),h("Assigned a shared IPv4");let M=Rp(g),V=(await u.listMachines(g.app)).filter((Ue)=>{let je=Ue.config?.metadata??{};if(je[zc])return je[zc]==="app";return!je.fly_process_group||je.fly_process_group==="app"}),Ae=g.volume?await u.listVolumes(g.app):[],ye=[],At=[],Tt=new Set;for(let Ue of g.regions){let je=V.filter((K)=>K.region===Ue).sort((K,St)=>K.id.localeCompare(St.id));for(let K=0;K<g.count;K++){let St=je[K];if(St){Tt.add(St.id),await bp(u,g.app,St,M,R),At.push(St.id),h(`Updated ${St.id} (${Ue}) to ${g.image}`);continue}let z=g.volume?[{volume:(await Ap(u,g,Ue,Ae)).id,path:g.volume.path}]:void 0,Xe=await u.createMachine(g.app,{region:Ue,name:`${g.app}-${Ue}-${K+1}`,config:{...M,...z?{mounts:z}:{}},...R!==void 0?{min_secrets_version:R}:{}});await u.waitForState(g.app,Xe.id,"started",{instanceId:Xe.instance_id}),ye.push(Xe.id),h(`Created ${Xe.id} in ${Ue}`)}}let Je=[];for(let Ue of g.hostnames)Je.push(await u.requestCertificate(g.app,Ue));return{app:g.app,url:`https://${g.app}.fly.dev`,createdApp:y,created:ye,updated:At,untouched:V.filter((Ue)=>!Tt.has(Ue.id)).map((Ue)=>Ue.id),ips:v,certificates:Je}}async function bp(u,g,h,y,R){let v=await u.acquireLease(g,h.id);try{let P=await u.updateMachine(g,h.id,{config:{...y,...h.config?.mounts?.length?{mounts:h.config.mounts}:{}},...R!==void 0?{min_secrets_version:R}:{}},v);await u.waitForState(g,h.id,"started",{instanceId:P.instance_id})}finally{await u.releaseLease(g,h.id,v)}}async function Ap(u,g,h,y){let R=y.find((P)=>P.region===h&&P.name===g.volume.name&&!P.attached_machine_id);if(R)return R.attached_machine_id="pending",R;let v=await u.createVolume(g.app,{name:g.volume.name,region:h,size_gb:g.volume.sizeGb});return y.push({...v,attached_machine_id:"pending"}),v}import{createHmac as cd,createSign as Pp,timingSafeEqual as Tp}from"node:crypto";function Di(u){let g=u instanceof Date?u.getTime():u;if(!Number.isFinite(g))throw TypeError("Media access timestamp must be finite");return Math.floor(g/1000)}function ld(u){return Buffer.from(u).toString("base64").replaceAll("+","-").replaceAll("=","_").replaceAll("/","~")}function wp(u){return Buffer.from(u).toString("base64url")}function ud(u,g=!1){if(!u||/[\r\n]/.test(u))throw TypeError("Media resource is invalid");let h=g?u.replaceAll("*","wildcard"):u,y=new URL(h);if(!["http:","https:"].includes(y.protocol))throw TypeError("Media resource must use HTTP or HTTPS");if(!g&&u.includes("*"))throw TypeError("Canned policies cannot contain wildcards")}function dd(u,g){let h=Pp("RSA-SHA1");return h.update(u),h.end(),ld(h.sign(g))}function gd(u){ud(u.resource,!0);let h={DateLessThan:{"AWS:EpochTime":Di(u.expiresAt)}};if(u.activeAt!==void 0)h.DateGreaterThan={"AWS:EpochTime":Di(u.activeAt)};if(u.ipAddress)h.IpAddress={"AWS:SourceIp":u.ipAddress};return JSON.stringify({Statement:[{Resource:u.resource,Condition:h}]})}function uR(u,g,h){ud(u);let y=Di(g),R=u.includes("?")?"&":"?",v=gd({resource:u,expiresAt:g}),P=dd(v,h.privateKey);return`${u}${R}Expires=${y}&Signature=${encodeURIComponent(P)}&Key-Pair-Id=${encodeURIComponent(h.keyPairId)}`}function dR(u,g){let h=gd(u);return{"CloudFront-Key-Pair-Id":g.keyPairId,"CloudFront-Policy":ld(Buffer.from(h)),"CloudFront-Signature":dd(h,g.privateKey)}}function pR(u){if(!u.resource||/[\r\n]/.test(u.resource))throw TypeError("Media resource is invalid");let g=wp(Buffer.from(JSON.stringify({resource:u.resource,expiresAt:Di(u.expiresAt),...u.keyId?{keyId:u.keyId}:{},...u.audience?{audience:u.audience}:{}}))),h=cd("sha256",u.secret).update(g).digest("base64url");return`${g}.${h}`}function mR(u,g){let[h,y,R]=u.split(".");if(!h||!y||R)return null;let v=cd("sha256",g.secret).update(h).digest(),P;try{P=Buffer.from(y,"base64url")}catch{return null}if(v.length!==P.length||!Tp(v,P))return null;try{let M=JSON.parse(Buffer.from(h,"base64url").toString("utf8")),V=Di(g.now??Date.now());if(!M.resource||!Number.isSafeInteger(M.expiresAt)||M.expiresAt<=V)return null;if(g.resource&&M.resource!==g.resource)return null;if(g.audience&&M.audience!==g.audience)return null;return M}catch{return null}}function gR(u,g=!1){let h=new URL(u,"https://media.invalid").pathname.toLowerCase(),y=/\.(?:m3u8|mpd|vtt|json)$/.test(h),R=/\.(?:key|license)$/.test(h)||h.includes("/keys/")||h.includes("/licenses/");return{"Accept-Ranges":"bytes","Cache-Control":g&&(y||R)?"private, no-store":y?"public, max-age=5, s-maxage=30, stale-while-revalidate=30":"public, max-age=31536000, immutable","Cross-Origin-Resource-Policy":"cross-origin","X-Content-Type-Options":"nosniff"}}function fR(u){if(!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(u.bucket))throw TypeError("Media bucket is invalid");if(!/^[a-z0-9-]+$/.test(u.region))throw TypeError("Media bucket region is invalid");let g=u.prefix?`/${u.prefix.replace(/^\/+|\/+$/g,"")}`:"",h=u.protected??!1,y="public, max-age=31536000, immutable",R=h?"private, no-store":"public, max-age=5, s-maxage=30, stale-while-revalidate=30";return{originDomain:`${u.bucket}.s3.${u.region}.amazonaws.com`,originPath:g,domain:u.domain,trustedKeyGroupIds:[...new Set(u.trustedKeyGroupIds??[])],behaviors:[{pathPattern:"*.m3u8",cacheControl:R,compress:!0,signed:h},{pathPattern:"*.mpd",cacheControl:R,compress:!0,signed:h},{pathPattern:"*.vtt",cacheControl:R,compress:!0,signed:h},{pathPattern:"*",cacheControl:y,compress:!1,signed:h}],responseHeaders:{"Access-Control-Allow-Headers":"Range, If-Range","Access-Control-Allow-Methods":"GET, HEAD, OPTIONS","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Accept-Ranges, Content-Length, Content-Range, ETag","X-Content-Type-Options":"nosniff"}}}class Ip{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;storageFailoverReplicas=[];constructor(u){this.config=u.config,this.environment=u.environment,this.builder=new hl(`${this.config.project.name} - ${this.environment}`),this.mergedConfig=this.mergeEnvironmentConfig()}mergeEnvironmentConfig(){let g=this.config.environments[this.environment]?.infrastructure;if(!g)return this.config;return{...this.config,infrastructure:{...this.config.infrastructure,...g,compute:{...this.config.infrastructure?.compute,...g.compute},storage:{...this.config.infrastructure?.storage,...g.storage},functions:{...this.config.infrastructure?.functions,...g.functions},servers:{...this.config.infrastructure?.servers,...g.servers},databases:{...this.config.infrastructure?.databases,...g.databases},cdn:{...this.config.infrastructure?.cdn,...g.cdn},sftp:g.sftp??this.config.infrastructure?.sftp,queues:{...this.config.infrastructure?.queues,...g.queues},redirects:{...this.config.infrastructure?.redirects,...g.redirects},realtime:{...this.config.infrastructure?.realtime,...g.realtime},cache:{...this.config.infrastructure?.cache,...g.cache},fileSystem:{...this.config.infrastructure?.fileSystem,...g.fileSystem},email:{...this.config.infrastructure?.email,...g.email},search:{...this.config.infrastructure?.search,...g.search},ai:{...this.config.infrastructure?.ai,...g.ai}}}}shouldDeploy(u){if(u.environments&&!u.environments.includes(this.environment))return!1;if(u.requiresFeatures){let g=this.config.features||{};if(!u.requiresFeatures.every((y)=>g[y]===!0))return!1}if(u.regions){let g=this.config.environments[this.environment]?.region||this.config.project.region;if(!u.regions.includes(g))return!1}if(u.condition&&typeof u.condition==="function")return u.condition(this.config,this.environment);return!0}resolveApiOriginPort(){let u=this.mergedConfig.infrastructure?.api?.port??this.mergedConfig.ports?.api,g=Number(u||3008);return Number.isFinite(g)&&g>0?g:3008}defaultComputeCachePathPatterns(){return["/api/*","/auth/*","/publisher/api/*","/publisher/*","/publish","/publish/*","/analytics/*","/packages/*","/npm/*","/zig/*","/php/*","/commits/*","/health","/dashboard/*","/search","/login","/logout","/signup","/account","/account/*"]}shouldRouteStorageBucketToCompute(u,g){return u==="public"||g.routeCompute===!0}storageBucketName(u,g,h){return this.mergedConfig.infrastructure?.storage?.[h]?.bucket??`${u}-${g}-${h}`}fileSystemLogicalId(u,g,h){return t(r({slug:`${u}-${h}`,environment:g,resourceType:"efs"}))}resolveSftpStorage(u,g,h){let y=u.storage;if(y?.type==="efs"&&y.fileSystem){if(!this.mergedConfig.infrastructure?.fileSystem?.[y.fileSystem])throw Error(`sftp: storage.fileSystem "${y.fileSystem}" is not defined in infrastructure.fileSystem`);return{type:"efs",fileSystemId:{Ref:this.fileSystemLogicalId(g,h,y.fileSystem)},posixProfile:y.posixProfile}}if(y?.type==="s3"&&y.storageBucket){if(!this.mergedConfig.infrastructure?.storage?.[y.storageBucket])throw Error(`sftp: storage.storageBucket "${y.storageBucket}" is not defined in infrastructure.storage`);return{type:"s3",bucket:this.storageBucketName(g,h,y.storageBucket)}}return}resolveComputeCachePathPatterns(u){if(u&&u.length>0)return u;return this.defaultComputeCachePathPatterns()}createComputeCacheBehavior(u,g){return{PathPattern:u,TargetOriginId:g,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac"}}appendComputeAppOrigin(u,g,h,y,R,v){let P=this.serverEipLogicalIds.get("app"),M=this.serverEipLogicalIds.get("appInstance");if(!P)return;let V=`EC2-${y}-${R}-api`,Ae=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",ye=Ae==="us-east-1"?".compute-1.amazonaws.com":`.${Ae}.compute.amazonaws.com`,At={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:P}]}]},ye]]},Tt=this.resolveApiOriginPort();if(u.push({Id:V,DomainName:At,CustomOriginConfig:{HTTPPort:Tt,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),h.push(P),M)h.push(M);for(let Je of v)g.push(this.createComputeCacheBehavior(Je,V))}buildCaddyfile(u){let g=u.filter(([,R])=>typeof R.domain==="string"&&R.domain&&typeof R.port==="number");if(g.length===0)return;let h=new Map;for(let[,R]of g){let v=h.get(R.domain)??[];v.push({port:R.port,path:R.path}),h.set(R.domain,v)}let y=[];for(let[R,v]of h){let M=[...v].sort((V,Ae)=>{let ye=!V.path||V.path==="/",At=!Ae.path||Ae.path==="/";if(ye&&!At)return 1;if(!ye&&At)return-1;return(Ae.path?.length??0)-(V.path?.length??0)}).map((V)=>{let Ae=!V.path||V.path==="/",ye=`reverse_proxy localhost:${V.port}`;return Ae?` handle {
1
+ import{WI,JI,ul,Dm,gl,pl,ln,H,l,ml,Pm,W,fl,p,gy,b,tt,Yi,un,w,le,hl,py,r,t,XI,YI,m,ZI,eb,tb,rb,nb,ur,Al,Zi,my,ib,sb,_e,rt,yl,km,Nm,ob,Bm,xm,Om,Ko,Sl,ue,gn,Nt,Wo,Bt,ve,fy,Il,Jo,_m,Lm,$m,Mm,bl,ab,J,E,hy,Ay,Fm,a,S,nt,f,Um,it,X,xt,cb,Qm,Y,Cl,Le,gr,Xo,ge,El,pe,yy,Yo,Z,ee,L,es,D,pr,Ot,te,e,pn,db,Hm,vl,lb,ub,gb,pb,Tl,mb,fb,hb,Ab,yb,Sb,Ib,bb,Cb,Eb,vb,Tb,Sy,Iy,by,Cy,Ey,vy,Ty,mr,Gm,Vm,fr,ts,wb,qm,Rb,Db,mn,Pb,kb,Nb,Bb,xb,Ob,jm,k,Te,rs,Zo,fn,ns,ea,wy,_b,is,ta,Ry,Dy,Py,ky,Ny,By,ss,Lb,ra,xy,zm,q,Oy,st,na,_t,_y,Km,Ly,$y,My,Wm,j,$b,Mb,Fb,Ub,Fy,Qb,re,Hb,Gb,Vb,wl,Rl,Uy,Jm,Xm,qb,jb,zb,Kb,Wb,Qy,Dl,Jb,Xb,Yb,Zb,eC,Hy,Gy,tC,rC,nC,iC,sC,oC,aC,Vy,cC,Ym,Pl,dC,lC,uC,gC,Zm,ef,tf,pC,kl,qy,jy,zy,Ky,Nl,Wy,mC,fC,hC,AC,yC,SC,IC,Jy,Xy,Yy,Zy,rf,bC,CC,EC,vC,TC,wC,RC,DC,PC,eS,tS,rS,nS,kC,NC,nf,BC,sf,of,af,cf,xC,OC,_C,LC,$e,os,$C,MC,FC,UC,QC,HC,GC,VC,iS,qC,jC,df,lf,zC,KC,sS,WC,JC,XC,YC,ZC,eE,tE,rE,nE,iE,sE,oE,aE,cE,dE,lE,uE,gE,pE,mE,fE,Bl,oS,xl,aS,Ol,cS,_l,dS,Ll,lS,hr,uS,$l,gS,as,pS,Ml,mS,Fl,fS,uf,hE,gf,AE,Ul,hS,Ar,AS,pf,yE,Ql,yS,mf,SE,ff,IE,hf,bE,Hl,SS,Af,CE,yf,EE,Sf,vE,If,TE,Gl,IS,Vl,bS,bf,wE,Cf,RE,Ef,DE,vf,PE,Tf,kE,wf,NE,ql,CS,Rf,BE,Df,xE,Pf,OE,kf,_E,Nf,LE,Bf,$E,xf,Of,_f,Lf,$f,ME,Mf,FE,Ff,UE,Uf,QE,ot,Qf,ES,ia,jl,hn,vS,cs,yr,zl,Kl,TS,wS,Wl,Hf,Jl,Gf,HE,GE,sa,oa,aa,Xl,An,Yl,Zl,ds,ca,da,Vf,RS,DS,PS,VE,qf,jf,qE,kS,zf,NS,BS,xS,jE,Kf,yn,eu,Wf,zE,OS,la,ua,tu,Jf,KE,ru,_S,Xf,WE,Yf,JE,Zf,XE}from"./chunk-72p2tdpe.js";import{nu,N,iu,ga,MS,eh,FS,US,QS,HS,GS,VS,qS,jS}from"./chunk-sjfc9my3.js";import{ya,th,gu,KS,ms,pu,Sa,rh,nh,In,Ia,mu,at,fu,hu,Au,fs,bn,ih,ct,yu,ba,Ca,Ea,Su,Iu,bu,hs,va,Cu,Cn,As,Ta,Lt,sh,Eu,vu,oh,Tu,wa,Sr,wu,Ru,Du,Pu,dt,ah,ku,Ir,Ra,Da,Pa,ys,Ss,En,Nu,Is,ka,Na,vn,Bu,Tn,ch,dh,$t,wn,Ba,lh,xu,Ou,xa,_u,Lu,$u,WS,me,Mu,JS,XS,bs,Cs,YS,we,uh,Mt,Me,Fe,Ft,Fu,Uu,Qu,Hu,gh,ph,Oa,mh,fh,_a,Gu,Vu,hh,fe,Ah,qu,Re,La,lt,Ut,Qt,Rn,Es,ju,ZS,yh,Sh,Ih,bh,$a,Ma,zu,Fa,Dn,Ua,Ku,vs,Wu,Qa,Ha,Ga,Va,qa,ja,za,Ka,Ju,br,Wa,Xu,Pn,Yu,Ja,Xa,Zu,Cr,Ya,Za,Ch,eI,Ts,tI,rI,nI,ec,tc,eg,Eh,rc,kn,tg,ws,rg,ng,ig,nc,vh,ic,sg,Th,sc,wh,Nn,Bn,og,Rs,gg,hg,Ag,yg,Sg,Ig,Ps,Er,ac,xn,On,vr,ut,Oh,dc,_h,Lh,Eg,lc,Ns,vg,uc,Gt,Qe,Tg,gc,pc,wg,mc,fc,hc,Ac,Rg,Dg,Ln,yc,Sc,Ic,bc,Pg,Bs,$n,xs,Cc}from"./chunk-cjm5j58y.js";import{uu}from"./chunk-kcem6dzk.js";import{Q,Wr,wd,Eo,d,rm,nm}from"./chunk-x7cnfn7y.js";import{wt,Td,_i,Li,$i,tm}from"./chunk-xs9m0v31.js";import{gA,pA,mA,Lp,$p,Mp,fA,Fp,Up,hA,AA,Qp,yA,SA,Ed,Hp,IA,bA,Gp,CA,EA,vA,TA,wA,RA,DA,Oi,vd,Vp,qp,jp,zp,Kp,Wp,Jp,Xp,Yp,Zp,em,PA,kA,NA,BA,xA,OA,_A}from"./chunk-byr76jcy.js";import{Ye,Rd,Ee,ir,Dd,O,sr,Rt,Pd,vo,MA,im,kd,s,Mi,To,Jr,Nd,Bd,Xr,FA,xd,qI,jI,wo,zI,KI,Od,_d,Fi,Ro,de,c,Do,Ze,Yr,UA,QA,Ld,HA,Po,GA,VA,ko,$d,Zr,No,qA,or,Md,sm,ar,en,jA,Bo,zA,_,KA,Fd,om,xo,WA,JA,XA,Ud,Ui,Oo,Qd,cr,Dt,YA,tn,ZA,Hd,am,cm,_o,Gd,Vd,Pt,dm,Qi,qd,Lo,rn,lm,Hi,jd,zd,Gi,um,Kd,Wd,Jd,Xd,$o,gm,pm,ey,mm,Yd,Vi,fm,hm,Mo,nn,Fo,Uo,Qo,Zd,Am,el,Ho,ty,dr,ry,tl,sn,rl,ny,nl,ym,qi,on,Go,ji,et,iy,Sm,Im,lr,il,sl,ol,zi,Ki,Wi,sy,oy,kt,Vo,ay,an,bm,qo,cy,Cm,Em,vm,dy,Tm,wm,ly,i,uy,Ji,jo,zo}from"./chunk-fe6m7wb0.js";import{n}from"./chunk-7d9ek8rc.js";import{ke,ft,Wn}from"./chunk-zy3kr4s2.js";import{De,Us,Qs,Bg,Rc,Dc,Hs,Pc,gt,ne,pt,he,T,Pe,Hn,kc,He,Nc,Gn,Vn,qn,Vt,qt,jt,jn,wr,Bc,Rr,Dr,mt,zn,Oc,zt,Pr,Kn,Lc,$g,Mg,$c,kr}from"./chunk-fne338jr.js";import{o}from"./chunk-1psh3mhm.js";import{A}from"./chunk-by7hejhg.js";import{jr,Oe}from"./chunk-a77mhcs7.js";import{Mc,Ge,I}from"./chunk-1087xz1v.js";import{C}from"./chunk-tpvmpmxj.js";import{ht,Se,qe,Fg,Kt,Fc,Uc,Wt,G,Jn,Jt,Xt,Xn,js,zs,Nr,Br,Yn,xr,Ks,Ws,Js,Xs,se,Ys,Zs,eo,to,Ie,ro,no,io,B,Qc,Zn,Hc,be,Or}from"./chunk-zwayp7fz.js";import{Ve}from"./chunk-hcbrgyfz.js";import{ie}from"./chunk-h6kptkce.js";import{Ug,Gc,Qg,oe,Vc,ei,Hg,qc,Gg,Vg,Wh,Lr,oo,F,Mr,ri,ni,Fr,Qr,ii,ao,si,oi,ai,ci,li,Hr,Ce,Kc,yt,Wc,Gr,Yc,ze,ae,Ke,We,It,pi,mi,Ne,Ct,Be,hi,Ai,yi,Si,Ii,bi,Ci,Vr,U,go,hp,ad,vi,Ti,wi,Ri,pd,mo,md,rr,Pi,fo,ho,fd,ki,hd}from"./chunk-zjkxhvn0.js";import{yo,Io,bo,x,xe}from"./chunk-dmv3vryr.js";import{su,pa,us,gs,ma,ou,au,ps,fa,ha,du,lu,Aa}from"./chunk-qra9k26f.js";import{Ec,Mn,Un,Os,_s,Ls,$s,vc,Tc}from"./chunk-9f18pebj.js";import{wc}from"./chunk-c6kb5c5v.js";import{ce,Ni,Ao,Ad,Bi,kp}from"./chunk-4m5gpp6w.js";import{al,cn,cl,dl,ll,Xi,Rm,dn}from"./chunk-sxqe8e9c.js";import{LS,ls}from"./chunk-jz6dacx1.js";var eR="https://api.machines.dev/v1";class So extends Error{status;path;constructor(u,g,h){super(u);this.status=g;this.path=h;this.name="FlyApiError"}}function sd(u){let g=u.ip.includes(":");if(g&&u.ip.startsWith("fdaa:"))return"private_v6";if(u.shared)return"shared_v4";return g?"v6":"v4"}class Cp{token;fetch;constructor(u){if(!u.token)throw Error("Fly.io needs an API token: set FLY_API_TOKEN (`fly tokens create deploy` makes one scoped to an app).");this.token=u.token,this.fetch=u.fetch??fetch}async rest(u,g,h={}){let y=new URL(`https://api.machines.dev/v1${g}`);for(let[M,V]of Object.entries(h.query??{}))y.searchParams.set(M,V);let R=await this.fetch(y,{method:u,headers:{Authorization:`Bearer ${this.token}`,...h.body!==void 0?{"Content-Type":"application/json"}:{},...h.headers},body:h.body===void 0?void 0:JSON.stringify(h.body)});if(R.status===404&&h.notFound==="null")return null;let v=await R.text(),P=v?Sp(v):void 0;if(!R.ok){let M=typeof P==="object"&&P&&"error"in P?String(P.error):v||R.statusText;throw new So(`Fly.io ${u} ${g} failed (${R.status}): ${M}`,R.status,g)}return P}getApp(u){return this.rest("GET",`/apps/${encodeURIComponent(u)}`,{notFound:"null"})}createApp(u,g){return this.rest("POST","/apps",{body:{app_name:u,org_slug:g}})}async listMachines(u){return await this.rest("GET",`/apps/${encodeURIComponent(u)}/machines`)??[]}createMachine(u,g){return this.rest("POST",`/apps/${encodeURIComponent(u)}/machines`,{body:g})}updateMachine(u,g,h,y){return this.rest("POST",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}`,{body:h,headers:{"fly-machine-lease-nonce":y}})}async acquireLease(u,g,h=120){let R=(await this.rest("POST",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}/lease`,{body:{ttl:h}})).data?.nonce;if(!R)throw new So(`Fly.io gave no lease nonce for Machine ${g}`,200,`/machines/${g}/lease`);return R}async releaseLease(u,g,h){await this.rest("DELETE",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}/lease`,{headers:{"fly-machine-lease-nonce":h}})}async waitForState(u,g,h,y={}){await this.rest("GET",`/apps/${encodeURIComponent(u)}/machines/${encodeURIComponent(g)}/wait`,{query:{state:h,timeout:String(y.timeoutSeconds??60),...y.instanceId?{instance_id:y.instanceId}:{}}})}async listVolumes(u){return await this.rest("GET",`/apps/${encodeURIComponent(u)}/volumes`)??[]}createVolume(u,g){return this.rest("POST",`/apps/${encodeURIComponent(u)}/volumes`,{body:{...g,encrypted:!0}})}async setSecrets(u,g){return(await this.rest("POST",`/apps/${encodeURIComponent(u)}/secrets`,{body:{values:g}})).version}async listIpAssignments(u){return(await this.rest("GET",`/apps/${encodeURIComponent(u)}/ip_assignments`)).ips??[]}async assignIp(u,g){let h=await this.rest("POST",`/apps/${encodeURIComponent(u)}/ip_assignments`,{body:{type:g}});if(!h.ip)throw new So(`Fly.io assigned no ${g} address to ${u}`,200,`/apps/${u}/ip_assignments`);return{ip:h.ip,shared:h.shared??g==="shared_v4",region:h.region}}async requestCertificate(u,g){return this.rest("POST",`/apps/${encodeURIComponent(u)}/certificates/acme`,{body:{hostname:g}})}}function Sp(u){try{return JSON.parse(u)}catch{return}}var zc="ts-cloud-role";function nR(u,g){let h=u.fly??{},y=h.app??`${u.project.slug}-${g.environment}`;if(!/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(y))throw Error(`"${y}" is not a valid Fly app name: lowercase letters, digits and dashes, 3 to 63 characters.`);let R=h.internalPort??3000,v=h.count??1;if(!Number.isInteger(v)||v<1)throw Error(`fly.count must be a whole number of at least 1, got ${v}.`);return{app:y,org:h.org??"personal",image:g.image,regions:h.regions?.length?h.regions:["iad"],count:v,internalPort:R,healthPath:h.healthPath??"/",vm:{cpuKind:h.vm?.cpuKind??"shared",cpus:h.vm?.cpus??1,memoryMb:h.vm?.memoryMb??512},...h.volume?{volume:{name:h.volume.name??"data",sizeGb:h.volume.sizeGb,path:h.volume.path}}:{},autoStop:h.autoStop??!1,env:{...g.env,PORT:String(R)},secrets:g.secrets??{},hostnames:h.hostnames??[],release:g.release}}function Rp(u){return{image:u.image,env:u.env,guest:{cpu_kind:u.vm.cpuKind,cpus:u.vm.cpus,memory_mb:u.vm.memoryMb},services:[{protocol:"tcp",internal_port:u.internalPort,ports:[{port:80,handlers:["http"],force_https:!0},{port:443,handlers:["tls","http"]}],autostop:u.autoStop?"stop":"off",autostart:!0,...u.autoStop?{min_machines_running:0}:{},checks:[{type:"http",method:"GET",path:u.healthPath,interval:"15s",timeout:"5s",grace_period:"10s"}]}],restart:{policy:"on-failure",max_retries:10},metadata:{[zc]:"app","ts-cloud-release":u.release}}}async function iR(u,g,h=()=>{}){let y=!1;if(!await u.getApp(g.app))h(`Creating Fly app ${g.app} in ${g.org}`),await u.createApp(g.app,g.org),y=!0;let R;if(Object.keys(g.secrets).length>0)R=await u.setSecrets(g.app,g.secrets),h(`Set ${Object.keys(g.secrets).length} secret(s) (version ${R})`);let v=await u.listIpAssignments(g.app),P=new Set(v.map(sd));if(!P.has("v6"))v.push(await u.assignIp(g.app,"v6")),h("Assigned a dedicated IPv6");if(!P.has("v4")&&!P.has("shared_v4"))v.push(await u.assignIp(g.app,"shared_v4")),h("Assigned a shared IPv4");let M=Rp(g),V=(await u.listMachines(g.app)).filter((Ue)=>{let je=Ue.config?.metadata??{};if(je[zc])return je[zc]==="app";return!je.fly_process_group||je.fly_process_group==="app"}),Ae=g.volume?await u.listVolumes(g.app):[],ye=[],At=[],Tt=new Set;for(let Ue of g.regions){let je=V.filter((K)=>K.region===Ue).sort((K,St)=>K.id.localeCompare(St.id));for(let K=0;K<g.count;K++){let St=je[K];if(St){Tt.add(St.id),await bp(u,g.app,St,M,R),At.push(St.id),h(`Updated ${St.id} (${Ue}) to ${g.image}`);continue}let z=g.volume?[{volume:(await Ap(u,g,Ue,Ae)).id,path:g.volume.path}]:void 0,Xe=await u.createMachine(g.app,{region:Ue,name:`${g.app}-${Ue}-${K+1}`,config:{...M,...z?{mounts:z}:{}},...R!==void 0?{min_secrets_version:R}:{}});await u.waitForState(g.app,Xe.id,"started",{instanceId:Xe.instance_id}),ye.push(Xe.id),h(`Created ${Xe.id} in ${Ue}`)}}let Je=[];for(let Ue of g.hostnames)Je.push(await u.requestCertificate(g.app,Ue));return{app:g.app,url:`https://${g.app}.fly.dev`,createdApp:y,created:ye,updated:At,untouched:V.filter((Ue)=>!Tt.has(Ue.id)).map((Ue)=>Ue.id),ips:v,certificates:Je}}async function bp(u,g,h,y,R){let v=await u.acquireLease(g,h.id);try{let P=await u.updateMachine(g,h.id,{config:{...y,...h.config?.mounts?.length?{mounts:h.config.mounts}:{}},...R!==void 0?{min_secrets_version:R}:{}},v);await u.waitForState(g,h.id,"started",{instanceId:P.instance_id})}finally{await u.releaseLease(g,h.id,v)}}async function Ap(u,g,h,y){let R=y.find((P)=>P.region===h&&P.name===g.volume.name&&!P.attached_machine_id);if(R)return R.attached_machine_id="pending",R;let v=await u.createVolume(g.app,{name:g.volume.name,region:h,size_gb:g.volume.sizeGb});return y.push({...v,attached_machine_id:"pending"}),v}import{createHmac as cd,createSign as Pp,timingSafeEqual as Tp}from"node:crypto";function Di(u){let g=u instanceof Date?u.getTime():u;if(!Number.isFinite(g))throw TypeError("Media access timestamp must be finite");return Math.floor(g/1000)}function ld(u){return Buffer.from(u).toString("base64").replaceAll("+","-").replaceAll("=","_").replaceAll("/","~")}function wp(u){return Buffer.from(u).toString("base64url")}function ud(u,g=!1){if(!u||/[\r\n]/.test(u))throw TypeError("Media resource is invalid");let h=g?u.replaceAll("*","wildcard"):u,y=new URL(h);if(!["http:","https:"].includes(y.protocol))throw TypeError("Media resource must use HTTP or HTTPS");if(!g&&u.includes("*"))throw TypeError("Canned policies cannot contain wildcards")}function dd(u,g){let h=Pp("RSA-SHA1");return h.update(u),h.end(),ld(h.sign(g))}function gd(u){ud(u.resource,!0);let h={DateLessThan:{"AWS:EpochTime":Di(u.expiresAt)}};if(u.activeAt!==void 0)h.DateGreaterThan={"AWS:EpochTime":Di(u.activeAt)};if(u.ipAddress)h.IpAddress={"AWS:SourceIp":u.ipAddress};return JSON.stringify({Statement:[{Resource:u.resource,Condition:h}]})}function uR(u,g,h){ud(u);let y=Di(g),R=u.includes("?")?"&":"?",v=gd({resource:u,expiresAt:g}),P=dd(v,h.privateKey);return`${u}${R}Expires=${y}&Signature=${encodeURIComponent(P)}&Key-Pair-Id=${encodeURIComponent(h.keyPairId)}`}function dR(u,g){let h=gd(u);return{"CloudFront-Key-Pair-Id":g.keyPairId,"CloudFront-Policy":ld(Buffer.from(h)),"CloudFront-Signature":dd(h,g.privateKey)}}function pR(u){if(!u.resource||/[\r\n]/.test(u.resource))throw TypeError("Media resource is invalid");let g=wp(Buffer.from(JSON.stringify({resource:u.resource,expiresAt:Di(u.expiresAt),...u.keyId?{keyId:u.keyId}:{},...u.audience?{audience:u.audience}:{}}))),h=cd("sha256",u.secret).update(g).digest("base64url");return`${g}.${h}`}function mR(u,g){let[h,y,R]=u.split(".");if(!h||!y||R)return null;let v=cd("sha256",g.secret).update(h).digest(),P;try{P=Buffer.from(y,"base64url")}catch{return null}if(v.length!==P.length||!Tp(v,P))return null;try{let M=JSON.parse(Buffer.from(h,"base64url").toString("utf8")),V=Di(g.now??Date.now());if(!M.resource||!Number.isSafeInteger(M.expiresAt)||M.expiresAt<=V)return null;if(g.resource&&M.resource!==g.resource)return null;if(g.audience&&M.audience!==g.audience)return null;return M}catch{return null}}function gR(u,g=!1){let h=new URL(u,"https://media.invalid").pathname.toLowerCase(),y=/\.(?:m3u8|mpd|vtt|json)$/.test(h),R=/\.(?:key|license)$/.test(h)||h.includes("/keys/")||h.includes("/licenses/");return{"Accept-Ranges":"bytes","Cache-Control":g&&(y||R)?"private, no-store":y?"public, max-age=5, s-maxage=30, stale-while-revalidate=30":"public, max-age=31536000, immutable","Cross-Origin-Resource-Policy":"cross-origin","X-Content-Type-Options":"nosniff"}}function fR(u){if(!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(u.bucket))throw TypeError("Media bucket is invalid");if(!/^[a-z0-9-]+$/.test(u.region))throw TypeError("Media bucket region is invalid");let g=u.prefix?`/${u.prefix.replace(/^\/+|\/+$/g,"")}`:"",h=u.protected??!1,y="public, max-age=31536000, immutable",R=h?"private, no-store":"public, max-age=5, s-maxage=30, stale-while-revalidate=30";return{originDomain:`${u.bucket}.s3.${u.region}.amazonaws.com`,originPath:g,domain:u.domain,trustedKeyGroupIds:[...new Set(u.trustedKeyGroupIds??[])],behaviors:[{pathPattern:"*.m3u8",cacheControl:R,compress:!0,signed:h},{pathPattern:"*.mpd",cacheControl:R,compress:!0,signed:h},{pathPattern:"*.vtt",cacheControl:R,compress:!0,signed:h},{pathPattern:"*",cacheControl:y,compress:!1,signed:h}],responseHeaders:{"Access-Control-Allow-Headers":"Range, If-Range","Access-Control-Allow-Methods":"GET, HEAD, OPTIONS","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Accept-Ranges, Content-Length, Content-Range, ETag","X-Content-Type-Options":"nosniff"}}}class Ip{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;storageFailoverReplicas=[];constructor(u){this.config=u.config,this.environment=u.environment,this.builder=new hl(`${this.config.project.name} - ${this.environment}`),this.mergedConfig=this.mergeEnvironmentConfig()}mergeEnvironmentConfig(){let g=this.config.environments[this.environment]?.infrastructure;if(!g)return this.config;return{...this.config,infrastructure:{...this.config.infrastructure,...g,compute:{...this.config.infrastructure?.compute,...g.compute},storage:{...this.config.infrastructure?.storage,...g.storage},functions:{...this.config.infrastructure?.functions,...g.functions},servers:{...this.config.infrastructure?.servers,...g.servers},databases:{...this.config.infrastructure?.databases,...g.databases},cdn:{...this.config.infrastructure?.cdn,...g.cdn},sftp:g.sftp??this.config.infrastructure?.sftp,queues:{...this.config.infrastructure?.queues,...g.queues},redirects:{...this.config.infrastructure?.redirects,...g.redirects},realtime:{...this.config.infrastructure?.realtime,...g.realtime},cache:{...this.config.infrastructure?.cache,...g.cache},fileSystem:{...this.config.infrastructure?.fileSystem,...g.fileSystem},email:{...this.config.infrastructure?.email,...g.email},search:{...this.config.infrastructure?.search,...g.search},ai:{...this.config.infrastructure?.ai,...g.ai}}}}shouldDeploy(u){if(u.environments&&!u.environments.includes(this.environment))return!1;if(u.requiresFeatures){let g=this.config.features||{};if(!u.requiresFeatures.every((y)=>g[y]===!0))return!1}if(u.regions){let g=this.config.environments[this.environment]?.region||this.config.project.region;if(!u.regions.includes(g))return!1}if(u.condition&&typeof u.condition==="function")return u.condition(this.config,this.environment);return!0}resolveApiOriginPort(){let u=this.mergedConfig.infrastructure?.api?.port??this.mergedConfig.ports?.api,g=Number(u||3008);return Number.isFinite(g)&&g>0?g:3008}defaultComputeCachePathPatterns(){return["/api/*","/auth/*","/publisher/api/*","/publisher/*","/publish","/publish/*","/analytics/*","/packages/*","/npm/*","/zig/*","/php/*","/commits/*","/health","/dashboard/*","/search","/login","/logout","/signup","/account","/account/*"]}shouldRouteStorageBucketToCompute(u,g){return u==="public"||g.routeCompute===!0}storageBucketName(u,g,h){return this.mergedConfig.infrastructure?.storage?.[h]?.bucket??`${u}-${g}-${h}`}fileSystemLogicalId(u,g,h){return t(r({slug:`${u}-${h}`,environment:g,resourceType:"efs"}))}resolveSftpStorage(u,g,h){let y=u.storage;if(y?.type==="efs"&&y.fileSystem){if(!this.mergedConfig.infrastructure?.fileSystem?.[y.fileSystem])throw Error(`sftp: storage.fileSystem "${y.fileSystem}" is not defined in infrastructure.fileSystem`);return{type:"efs",fileSystemId:{Ref:this.fileSystemLogicalId(g,h,y.fileSystem)},posixProfile:y.posixProfile}}if(y?.type==="s3"&&y.storageBucket){if(!this.mergedConfig.infrastructure?.storage?.[y.storageBucket])throw Error(`sftp: storage.storageBucket "${y.storageBucket}" is not defined in infrastructure.storage`);return{type:"s3",bucket:this.storageBucketName(g,h,y.storageBucket)}}return}resolveComputeCachePathPatterns(u){if(u&&u.length>0)return u;return this.defaultComputeCachePathPatterns()}createComputeCacheBehavior(u,g){return{PathPattern:u,TargetOriginId:g,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac"}}appendComputeAppOrigin(u,g,h,y,R,v){let P=this.serverEipLogicalIds.get("app"),M=this.serverEipLogicalIds.get("appInstance");if(!P)return;let V=`EC2-${y}-${R}-api`,Ae=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",ye=Ae==="us-east-1"?".compute-1.amazonaws.com":`.${Ae}.compute.amazonaws.com`,At={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:P}]}]},ye]]},Tt=this.resolveApiOriginPort();if(u.push({Id:V,DomainName:At,CustomOriginConfig:{HTTPPort:Tt,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),h.push(P),M)h.push(M);for(let Je of v)g.push(this.createComputeCacheBehavior(Je,V))}buildCaddyfile(u){let g=u.filter(([,R])=>typeof R.domain==="string"&&R.domain&&typeof R.port==="number");if(g.length===0)return;let h=new Map;for(let[,R]of g){let v=h.get(R.domain)??[];v.push({port:R.port,path:R.path}),h.set(R.domain,v)}let y=[];for(let[R,v]of h){let M=[...v].sort((V,Ae)=>{let ye=!V.path||V.path==="/",At=!Ae.path||Ae.path==="/";if(ye&&!At)return 1;if(!ye&&At)return-1;return(Ae.path?.length??0)-(V.path?.length??0)}).map((V)=>{let Ae=!V.path||V.path==="/",ye=`reverse_proxy localhost:${V.port}`;return Ae?` handle {
2
2
  ${ye}
3
3
  }`:` handle ${V.path} {
4
4
  ${ye}
package/dist/ui/404.html CHANGED
@@ -2,7 +2,7 @@
2
2
  <html lang="en" data-theme="dark">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
- <meta name="stx-build" content="mvvnmghx195v0e">
5
+ <meta name="stx-build" content="mw2gzoetf2jnq5">
6
6
 
7
7
  <!-- stx SEO Tags -->
8
8
  <meta name="title" content="Page not found · ts-cloud">
@@ -1,4 +1,4 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mvvng2ccz30ktp"><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Accept invitation</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"><style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.616c25f3.css"></head><body class="auth-page"><main class="auth-card" id="main-content"><a class="brand" href="/"><span class="dot"></span><span>ts-cloud</span></a><div><span class="context-label">Organization invitation</span><h1>Join your team</h1><p>Choose the dashboard username and password you will use after this invitation is accepted.</p></div><form id="accept-invitation-form" class="auth-form"><div class="field-block"><label for="invite-name">Name</label><input id="invite-name" name="name" autocomplete="name" placeholder="Chris Breuer"></div><div class="field-block"><label for="invite-username">Username</label><input id="invite-username" name="username" autocomplete="username" minlength="2" maxlength="32" required></div><div class="field-block"><label for="invite-password">Password</label><input id="invite-password" name="password" type="password" autocomplete="new-password" minlength="12" required><small>At least 12 characters.</small></div><button class="btn" type="submit">Accept invitation</button><div id="invitation-status" class="auth-status" role="status"></div></form><p class="note">If this link expired or was already used, ask an organization owner to resend the invitation.</p></main> <script data-stx-scoped data-stx-run="always">
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mw2gvnw2j8btfq"><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Accept invitation</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"><style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.616c25f3.css"></head><body class="auth-page"><main class="auth-card" id="main-content"><a class="brand" href="/"><span class="dot"></span><span>ts-cloud</span></a><div><span class="context-label">Organization invitation</span><h1>Join your team</h1><p>Choose the dashboard username and password you will use after this invitation is accepted.</p></div><form id="accept-invitation-form" class="auth-form"><div class="field-block"><label for="invite-name">Name</label><input id="invite-name" name="name" autocomplete="name" placeholder="Chris Breuer"></div><div class="field-block"><label for="invite-username">Username</label><input id="invite-username" name="username" autocomplete="username" minlength="2" maxlength="32" required></div><div class="field-block"><label for="invite-password">Password</label><input id="invite-password" name="password" type="password" autocomplete="new-password" minlength="12" required><small>At least 12 characters.</small></div><button class="btn" type="submit">Accept invitation</button><div id="invitation-status" class="auth-status" role="status"></div></form><p class="note">If this link expired or was already used, ask an organization owner to resend the invitation.</p></main> <script data-stx-scoped data-stx-run="always">
2
2
  ;(function() {
3
3
  'use strict';
4
4
  (() => {
@@ -1,4 +1,4 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mvvng2ccz30ktp"><meta name="title" content="Access unavailable · ts-cloud"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="Access unavailable · ts-cloud"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Access unavailable · ts-cloud"><meta name="twitter:description" content="A website built with stx templating engine"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Access unavailable · ts-cloud</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"><style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.906ee17c.css"></head><body data-stx-auto><a data-stx-scope="stx_scope_nav_50" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>ts-cloud</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a class="" href="/operations/spend?env=production">Spend & budgets</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/infrastructure/topology?env=production">Infrastructure map</a><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>ts-cloud</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped data-stx-run="always">
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mw2gvnw2j8btfq"><meta name="title" content="Access unavailable · ts-cloud"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="Access unavailable · ts-cloud"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Access unavailable · ts-cloud"><meta name="twitter:description" content="A website built with stx templating engine"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Access unavailable · ts-cloud</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"><style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.906ee17c.css"></head><body data-stx-auto><a data-stx-scope="stx_scope_nav_50" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>ts-cloud</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a class="" href="/operations/spend?env=production">Spend & budgets</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/infrastructure/topology?env=production">Infrastructure map</a><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>ts-cloud</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped data-stx-run="always">
2
2
  (function() {
3
3
  var { batch, computed, configureFetch, defineEmits, defineExpose, definePageMeta, defineProps, defineSlots, defineStore, derived, effect, goBack, goForward, inject, invalidateRoute, isDerived, isSignal, navigate, nextTick, onBeforeMount, onBeforeUnmount, onDestroy, onMount, onMounted, onUnmounted, peek, provide, reactive, ref, refresh, registerStoresClient, setRouteParams, state, untrack, useAsync, useClickOutside, useColorMode, useCookie, useCounter, useDark, useDebounce, useDebouncedValue, useEventListener, useFetch, useFocus, useHead, useId, useInterval, useLocalStorage, useMediaQuery, useMutation, useOptimistic, usePreferredContrast, usePreferredDark, usePreferredLight, usePreferredReducedMotion, useQuery, useReactiveProp, useRef, useRoute, useRouteParam, useRouteParams, useScrollLock, useSearchParams, useSeoMeta, useSessionStorage, useSlots, useStore, useThrottle, useTimeout, useToggle, useWebSocket, watch, watchEffect, watchMultiple, withDefaults } = window.stx;
4
4
  var __destroyHooks = [];
@@ -1,5 +1,5 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mvvng2ccz30ktp"><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - API &amp; automation</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"> <script data-stx-scoped>
2
- function __stx_setup_1793405694633_6() {
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mw2gvnw2j8btfq"><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - API &amp; automation</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"> <script data-stx-scoped>
2
+ function __stx_setup_1793817928311_6() {
3
3
  const { batch, computed, configureFetch, defineEmits, defineExpose, definePageMeta, defineProps, defineSlots, defineStore, derived, effect, goBack, goForward, inject, invalidateRoute, isDerived, isSignal, navigate, nextTick, onBeforeMount, onBeforeUnmount, onDestroy, onMount, onMounted, onUnmounted, peek, provide, reactive, ref, refresh, registerStoresClient, setRouteParams, state, untrack, useAsync, useClickOutside, useColorMode, useCookie, useCounter, useDark, useDebounce, useDebouncedValue, useEventListener, useFetch, useFocus, useHead, useId, useInterval, useLocalStorage, useMediaQuery, useMutation, useOptimistic, usePreferredContrast, usePreferredDark, usePreferredLight, usePreferredReducedMotion, useQuery, useReactiveProp, useRef, useRoute, useRouteParam, useRouteParams, useScrollLock, useSearchParams, useSeoMeta, useSessionStorage, useSlots, useStore, useThrottle, useTimeout, useToggle, useWebSocket, watch, watchEffect, watchMultiple, withDefaults } = window.stx;
4
4
 
5
5
  const accounts = state([]);
@@ -189,9 +189,9 @@ onMount(() => {
189
189
 
190
190
  return { accounts, project, environments, resources, message, messageKind, reveal, accountSlug, accountName, accountRole, accountScopeType, accountScopeId, selectedAccount, tokenName, tokenCapabilities, tokenScopeType, tokenScopeId, tokenExpiry, password, mfaCode, capabilities, setMessage, setScope, scopeLabel, tokenState, toggleCapability, load, selectAccount, stepUp, createAccount, createToken, tokenAction, disableAccount, curlExample, cliExample, copy };
191
191
  }
192
- window.__stx_latestSetup=__stx_setup_1793405694633_6;
193
- if(window.stx)window.stx._latestSetup=__stx_setup_1793405694633_6;
194
- </script> <style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.906ee17c.css"></head><body data-stx="__stx_setup_1793405694633_6"><a data-stx-scope="stx_scope_nav_9" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>ts-cloud</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a class="" href="/operations/spend?env=production">Spend & budgets</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/infrastructure/topology?env=production">Infrastructure map</a><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="active" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>ts-cloud</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped data-stx-run="always">
192
+ window.__stx_latestSetup=__stx_setup_1793817928311_6;
193
+ if(window.stx)window.stx._latestSetup=__stx_setup_1793817928311_6;
194
+ </script> <style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.906ee17c.css"></head><body data-stx="__stx_setup_1793817928311_6"><a data-stx-scope="stx_scope_nav_9" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>ts-cloud</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a class="" href="/operations/spend?env=production">Spend & budgets</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/infrastructure/topology?env=production">Infrastructure map</a><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="active" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>ts-cloud</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped data-stx-run="always">
195
195
  (function() {
196
196
  var { batch, computed, configureFetch, defineEmits, defineExpose, definePageMeta, defineProps, defineSlots, defineStore, derived, effect, goBack, goForward, inject, invalidateRoute, isDerived, isSignal, navigate, nextTick, onBeforeMount, onBeforeUnmount, onDestroy, onMount, onMounted, onUnmounted, peek, provide, reactive, ref, refresh, registerStoresClient, setRouteParams, state, untrack, useAsync, useClickOutside, useColorMode, useCookie, useCounter, useDark, useDebounce, useDebouncedValue, useEventListener, useFetch, useFocus, useHead, useId, useInterval, useLocalStorage, useMediaQuery, useMutation, useOptimistic, usePreferredContrast, usePreferredDark, usePreferredLight, usePreferredReducedMotion, useQuery, useReactiveProp, useRef, useRoute, useRouteParam, useRouteParams, useScrollLock, useSearchParams, useSeoMeta, useSessionStorage, useSlots, useStore, useThrottle, useTimeout, useToggle, useWebSocket, watch, watchEffect, watchMultiple, withDefaults } = window.stx;
197
197
  var __destroyHooks = [];
@@ -1,4 +1,4 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mvvng2ccz30ktp"><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Sign-in &amp; security</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"><style> .security-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, .7fr); gap: 18px; align-items: start; } .security-stack { display: grid; gap: 18px; } .security-summary { display: grid; gap: 10px; } .security-summary .kv { padding: 8px 0; } .session-list { display: grid; gap: 10px; } .session-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 13px; border: 1px solid var(--panel-br); border-radius: 11px; } .session-copy { display: grid; gap: 4px; min-width: 0; } .session-copy strong, .session-copy span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .session-copy span { color: var(--txt3); font-size: 11px; } .security-form { display: grid; gap: 13px; } .security-form label { display: grid; gap: 6px; color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; } .security-form input { width: 100%; } .security-status { min-height: 20px; color: var(--txt2); font-size: 12px; } .mfa-secret { display: block; margin: 9px 0; padding: 10px; overflow-wrap: anywhere; border: 1px solid var(--panel-br); border-radius: 9px; background: rgba(255,255,255,.025); color: var(--accent); font: 700 12px var(--mono); } .recovery-codes { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 10px; } .recovery-codes code { padding: 7px; border: 1px solid var(--panel-br); border-radius: 7px; text-align: center; } .hidden { display: none !important; } @media (max-width: 900px) { .security-layout { grid-template-columns: 1fr; } } </style><style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.222ed683.css"></head><body data-stx-auto><a data-stx-scope="stx_scope_nav_8" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>Project</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a class="" href="/operations/spend?env=production">Spend & budgets</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/infrastructure/topology?env=production">Infrastructure map</a><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="active" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>Project</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped data-stx-run="always">
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mw2gvnw2j8btfq"><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Sign-in &amp; security</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="/_stx/style.448ab192.css"><style> .security-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, .7fr); gap: 18px; align-items: start; } .security-stack { display: grid; gap: 18px; } .security-summary { display: grid; gap: 10px; } .security-summary .kv { padding: 8px 0; } .session-list { display: grid; gap: 10px; } .session-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 13px; border: 1px solid var(--panel-br); border-radius: 11px; } .session-copy { display: grid; gap: 4px; min-width: 0; } .session-copy strong, .session-copy span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .session-copy span { color: var(--txt3); font-size: 11px; } .security-form { display: grid; gap: 13px; } .security-form label { display: grid; gap: 6px; color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; } .security-form input { width: 100%; } .security-status { min-height: 20px; color: var(--txt2); font-size: 12px; } .mfa-secret { display: block; margin: 9px 0; padding: 10px; overflow-wrap: anywhere; border: 1px solid var(--panel-br); border-radius: 9px; background: rgba(255,255,255,.025); color: var(--accent); font: 700 12px var(--mono); } .recovery-codes { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 10px; } .recovery-codes code { padding: 7px; border: 1px solid var(--panel-br); border-radius: 7px; text-align: center; } .hidden { display: none !important; } @media (max-width: 900px) { .security-layout { grid-template-columns: 1fr; } } </style><style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.222ed683.css"></head><body data-stx-auto><a data-stx-scope="stx_scope_nav_8" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>Project</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a class="" href="/operations/spend?env=production">Spend & budgets</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/infrastructure/topology?env=production">Infrastructure map</a><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="active" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>Project</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped data-stx-run="always">
2
2
  (function() {
3
3
  var { batch, computed, configureFetch, defineEmits, defineExpose, definePageMeta, defineProps, defineSlots, defineStore, derived, effect, goBack, goForward, inject, invalidateRoute, isDerived, isSignal, navigate, nextTick, onBeforeMount, onBeforeUnmount, onDestroy, onMount, onMounted, onUnmounted, peek, provide, reactive, ref, refresh, registerStoresClient, setRouteParams, state, untrack, useAsync, useClickOutside, useColorMode, useCookie, useCounter, useDark, useDebounce, useDebouncedValue, useEventListener, useFetch, useFocus, useHead, useId, useInterval, useLocalStorage, useMediaQuery, useMutation, useOptimistic, usePreferredContrast, usePreferredDark, usePreferredLight, usePreferredReducedMotion, useQuery, useReactiveProp, useRef, useRoute, useRouteParam, useRouteParams, useScrollLock, useSearchParams, useSeoMeta, useSessionStorage, useSlots, useStore, useThrottle, useTimeout, useToggle, useWebSocket, watch, watchEffect, watchMultiple, withDefaults } = window.stx;
4
4
  var __destroyHooks = [];