@stacksjs/ts-cloud 0.16.1 → 0.16.2

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 (84) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/{chunk-ghbd1dcz.js → chunk-35p4sfb5.js} +1 -1
  3. package/dist/bin/{chunk-fae1s9p5.js → chunk-8595qcv0.js} +1 -1
  4. package/dist/bin/{chunk-8qmc6yvq.js → chunk-fqajjdy7.js} +23 -23
  5. package/dist/bin/cli.js +4 -4
  6. package/dist/bin/dashboard-server.js +1 -1
  7. package/dist/{chunk-azcvwr5m.js → chunk-11s59686.js} +2 -2
  8. package/dist/{chunk-etmbw4er.js → chunk-aszeyg2w.js} +2 -2
  9. package/dist/{chunk-xacvkpf8.js → chunk-bvspqd2m.js} +1 -1
  10. package/dist/{chunk-b9pm7mbd.js → chunk-c3pvfcme.js} +13 -13
  11. package/dist/{chunk-f9pzjzye.js → chunk-f0t7y458.js} +2 -2
  12. package/dist/{chunk-tg6yasej.js → chunk-f27a8et2.js} +1 -1
  13. package/dist/{chunk-dky93h4d.js → chunk-fgww8ya2.js} +1 -1
  14. package/dist/chunk-gk5ehe62.js +1 -0
  15. package/dist/{chunk-bkv2p4hp.js → chunk-hhy358y8.js} +2 -2
  16. package/dist/{chunk-jnt7ab86.js → chunk-nnfdz28e.js} +2 -2
  17. package/dist/{chunk-d51q92t7.js → chunk-qzbmm0f6.js} +42 -42
  18. package/dist/{chunk-cwjskpj4.js → chunk-r5pjnw74.js} +2 -2
  19. package/dist/{chunk-epqpf6jd.js → chunk-scy8mzqk.js} +1 -1
  20. package/dist/{chunk-dp93dqcr.js → chunk-ttgff76x.js} +38 -38
  21. package/dist/{chunk-a0d0h33y.js → chunk-yqfkq6q7.js} +1 -1
  22. package/dist/deploy/index.js +1 -1
  23. package/dist/dns/index.js +1 -1
  24. package/dist/drivers/index.js +1 -1
  25. package/dist/index.js +26 -26
  26. package/dist/operations/index.js +1 -1
  27. package/dist/protection/index.js +1 -1
  28. package/dist/spend/index.js +1 -1
  29. package/dist/ui/404.html +1 -1
  30. package/dist/ui/accept-invitation.html +1 -1
  31. package/dist/ui/access-denied.html +1 -1
  32. package/dist/ui/account/automation.html +5 -5
  33. package/dist/ui/account/security.html +2 -2
  34. package/dist/ui/applications/compose.html +6 -6
  35. package/dist/ui/applications/new.html +2 -2
  36. package/dist/ui/data/backups.html +6 -6
  37. package/dist/ui/data/services.html +5 -5
  38. package/dist/ui/data/volumes.html +5 -5
  39. package/dist/ui/index.html +6 -6
  40. package/dist/ui/infrastructure/topology.html +6 -6
  41. package/dist/ui/integrations.html +1 -1
  42. package/dist/ui/operations/alerts.html +5 -5
  43. package/dist/ui/operations/configuration.html +5 -5
  44. package/dist/ui/operations/jobs.html +5 -5
  45. package/dist/ui/operations/maintenance.html +5 -5
  46. package/dist/ui/operations/observability.html +6 -6
  47. package/dist/ui/operations/previews.html +6 -6
  48. package/dist/ui/operations/queue.html +5 -5
  49. package/dist/ui/operations/regions.html +5 -5
  50. package/dist/ui/operations/releases.html +6 -6
  51. package/dist/ui/operations/spend.html +6 -6
  52. package/dist/ui/operations/workloads.html +5 -5
  53. package/dist/ui/security.html +2 -2
  54. package/dist/ui/server/actions.html +6 -6
  55. package/dist/ui/server/activity.html +2 -2
  56. package/dist/ui/server/capacity.html +6 -6
  57. package/dist/ui/server/database.html +6 -6
  58. package/dist/ui/server/deployments.html +6 -6
  59. package/dist/ui/server/diagnostics.html +2 -2
  60. package/dist/ui/server/firewall.html +5 -5
  61. package/dist/ui/server/fleet.html +6 -6
  62. package/dist/ui/server/logs.html +6 -6
  63. package/dist/ui/server/metrics.html +6 -6
  64. package/dist/ui/server/security.html +2 -2
  65. package/dist/ui/server/services.html +1 -1
  66. package/dist/ui/server/sites.html +5 -5
  67. package/dist/ui/server/ssh-keys.html +6 -6
  68. package/dist/ui/server/team.html +6 -6
  69. package/dist/ui/server/terminal.html +2 -2
  70. package/dist/ui/serverless/alarms.html +6 -6
  71. package/dist/ui/serverless/assets.html +2 -2
  72. package/dist/ui/serverless/cost.html +2 -2
  73. package/dist/ui/serverless/data.html +6 -6
  74. package/dist/ui/serverless/deployments.html +2 -2
  75. package/dist/ui/serverless/firewall.html +2 -2
  76. package/dist/ui/serverless/functions.html +6 -6
  77. package/dist/ui/serverless/logs.html +6 -6
  78. package/dist/ui/serverless/metrics.html +2 -2
  79. package/dist/ui/serverless/queues.html +6 -6
  80. package/dist/ui/serverless/secrets.html +6 -6
  81. package/dist/ui/serverless/traces.html +6 -6
  82. package/dist/ui/serverless.html +6 -6
  83. package/package.json +3 -3
  84. package/dist/chunk-h1anhx3y.js +0 -1
@@ -1,5 +1,5 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mucyniusp75leg"><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 · Backups &amp; recovery</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-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <script data-stx-scoped>
2
- function __stx_setup_1790098878687_4() {
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mudcq5hty15x8q"><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 · Backups &amp; recovery</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-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <script data-stx-scoped>
2
+ function __stx_setup_1790122515975_7() {
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, 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
  var actionError = undefined;
@@ -367,9 +367,9 @@ verifyPoint = __stxBundle_0750f100c970["verifyPoint"];
367
367
  when = __stxBundle_0750f100c970["when"];
368
368
  return { actionError, activeJobs, api, busy, bytes, createDestination, createPolicy, destinationName, destinationOpen, endpoint, inventory, jobsForPoint, lastUpdatedAt, latestFailures, load, notice, openRestore, policyName, policyOpen, pollingError, pollingState, post, protectPoint, refresh, restorePlan, restoreTarget, runPolicy, safeError, selectedPoint, services, submitRestore, tab, testDestination, tone, values, verifyPoint, when, __stxBundle_0750f100c970 };
369
369
  }
370
- window.__stx_latestSetup=__stx_setup_1790098878687_4;
371
- if(window.stx)window.stx._latestSetup=__stx_setup_1790098878687_4;
372
- </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_1790098878687_4"><a data-stx-scope="stx_scope_nav_5" 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="active" 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>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">
370
+ window.__stx_latestSetup=__stx_setup_1790122515975_7;
371
+ if(window.stx)window.stx._latestSetup=__stx_setup_1790122515975_7;
372
+ </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_1790122515975_7"><a data-stx-scope="stx_scope_nav_10" 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="active" 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>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">
373
373
  (function() {
374
374
  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;
375
375
  var __destroyHooks = [];
@@ -720,6 +720,6 @@ if(window.stx)window.stx._latestSetup=__stx_setup_1790098878687_4;
720
720
 
721
721
 
722
722
  try { if (typeof __stxScopeRenames !== 'undefined' && __stxScopeRenames) { for (var __stxRK in __stxScopeRenames) __scopeRegistration[__stxRK] = __stxScopeRenames[__stxRK]; } } catch (e) { /* no renames */ }
723
- window.stx._scopes['stx_scope_nav_5'] = __scopeRegistration;
723
+ window.stx._scopes['stx_scope_nav_10'] = __scopeRegistration;
724
724
  })();
725
725
  </script> <main class="recovery-wrap wrap" id="main-content"><div class="crumbs">Operations <span class="sep">/</span> Backups &amp; recovery</div><header class="page"><div><h1>Backups &amp; recovery</h1><p>One inventory for scheduled protection, verified recovery points, retention, restores, and drills.</p></div><div class="header-actions" x-cloak><span class="pill" :class="pollingState()==='live'?'ok':'warn'" x-cloak>{{ pollingState() }}</span><small x-cloak>{{ lastUpdatedAt()?.toLocaleTimeString() || 'connecting' }}</small><button class="btn ghost sm" @click="refresh()">Refresh</button><button class="btn ghost sm" @click="destinationOpen.set(!destinationOpen())">New destination</button><button class="btn sm" @click="policyOpen.set(!policyOpen())">New policy</button></div></header><p class="notice" role="status" @show="!!notice()" x-cloak>{{ notice() }}</p><p class="bad notice" role="alert" @show="!!actionError() || !!pollingError()" x-cloak>{{ actionError() || pollingError() }}</p><section class="summary"><article class="panel"><b>Protected policies</b><strong x-cloak>{{ inventory().coverage.filter(item=>!item.missedRpo).length }}/{{ inventory().coverage.length }}</strong><small>inside expected RPO</small></article><article class="panel"><b>Missed RPO</b><strong :class="inventory().coverage.some(item=>item.missedRpo)?'bad':''" x-cloak>{{ inventory().coverage.filter(item=>item.missedRpo).length }}</strong><small>requires operator attention</small></article><article class="panel"><b>Unverified points</b><strong :class="inventory().coverage.some(item=>item.unverified)?'warn':''" x-cloak>{{ inventory().coverage.reduce((sum,item)=>sum+item.unverified,0) }}</strong><small>uploaded but not trusted</small></article><article class="panel"><b>Active work</b><strong x-cloak>{{ activeJobs().length }}</strong><small x-cloak>{{ latestFailures() }} failed / cleanup required</small></article></section><nav class="tabs" aria-label="Recovery views"><button :class="{active:tab()==='overview'}" @click="tab.set('overview')">Coverage</button><button :class="{active:tab()==='recovery'}" @click="tab.set('recovery')">Recovery points</button><button :class="{active:tab()==='policies'}" @click="tab.set('policies')">Policies</button><button :class="{active:tab()==='destinations'}" @click="tab.set('destinations')">Destinations</button><button :class="{active:tab()==='jobs'}" @click="tab.set('jobs')">Jobs</button></nav><form class="form-grid panel" @show="destinationOpen()" @submit="createDestination($event)" x-cloak><div class="wide"><h2>Connect a destination</h2><p class="note">Credentials and client-side encryption keys are encrypted at rest, never returned by the API, and excluded from logs.</p></div><label>Name<input name="name" required pattern="[a-z0-9][a-z0-9-]{1,62}" placeholder="production-recovery"></label><label>Provider<select name="provider"><option value="aws_s3">AWS S3</option><option value="s3_compatible">S3-compatible</option><option value="aws_backup">AWS Backup</option></select></label><label>Bucket<input name="bucket" placeholder="acme-recovery"></label><label>Region<input name="region" value="us-east-1"></label><label class="wide">Endpoint (S3-compatible)<input name="endpoint" type="url" placeholder="https://objects.example.com"></label><label>Endpoint network policy<select name="endpointPolicy"><option value="public_https">Public HTTPS only</option><option value="allow_private">Allow private endpoint</option></select></label><label>Prefix<input name="prefix" placeholder="production"></label><label>Access key ID<input name="accessKeyId" autocomplete="off"></label><label>Secret access key<input name="secretAccessKey" type="password" autocomplete="new-password"></label><label>Session token<input name="sessionToken" type="password" autocomplete="new-password"></label><label>Credential expires<input name="credentialExpiresAt" type="datetime-local"></label><label>Encryption<select name="encryption"><option value="provider">Provider managed</option><option value="both">Provider + client side</option><option value="client_side">Client side</option></select></label><label class="wide">Client encryption key<input name="encryptionKey" type="password" minlength="32" autocomplete="new-password"></label><label>Object-lock days<input name="lockDays" type="number" min="1"></label><label class="check"><input name="objectLock" type="checkbox"> Object lock enabled</label><label class="check"><input name="forcePathStyle" type="checkbox"> Force path-style URLs</label><button class="btn wide" type="submit" :disabled="busy()" x-cloak>{{ busy()?'Saving…':'Save destination' }}</button></form><form class="form-grid panel" @show="policyOpen()" @submit="createPolicy($event)" x-cloak><div class="wide"><h2>Schedule protection</h2><p class="note">RPO is the maximum acceptable point age; RTO is the recovery time target shown during incidents and drills.</p></div><label>Name<input name="name" required pattern="[a-z0-9][a-z0-9-]{1,62}" placeholder="orders-hourly"></label><label x-cloak>Destination<select name="destinationId" required><template :for="item in inventory().destinations"><option :value="item.id">{{ item.name }} · {{ item.status }}</option></template></select></label><label>Resource kind<select name="resourceKind"><option value="managed_database">Managed database snapshot</option><option value="logical_database">Logical database dump</option><option value="volume">Named volume</option><option value="files">Application files</option><option value="control_plane">Control plane + config</option><option value="infrastructure">AWS infrastructure resource</option></select></label><label>Data service<select name="dataServiceId"><option value="">Not a database</option><template :for="item in services()"><option :value="item.id">{{ item.name }} · {{ item.engine }} · {{ item.provider }}</option></template></select></label><label>Application / resource<select name="resourceId"><option value="">Not an application volume</option><template :for="item in inventory().resources"><option :value="item.id">{{ item.name }} · {{ item.kind }}</option></template></select></label><label>Named volume<input name="volumeName" placeholder="orders-data"></label><label class="wide">Include paths / resource settings<textarea name="includePatterns" rows="2" placeholder="storage/uploads, public/media — or resource:arn:…, role:arn:…, vault:Default"></textarea></label><label class="wide">Exclude patterns<textarea name="excludePatterns" rows="2" placeholder="*.tmp, cache/**"></textarea></label><label>Schedule<input name="schedule" value="hourly" required></label><label>Timezone<input name="timezone" value="UTC" required></label><label>RPO minutes<input name="expectedRpoMinutes" type="number" min="1" value="60"></label><label>RTO minutes<input name="expectedRtoMinutes" type="number" min="1" value="120"></label><label>Keep last<input name="keepLast" type="number" min="1" value="24"></label><label>Daily<input name="daily" type="number" min="0" value="7"></label><label>Weekly<input name="weekly" type="number" min="0" value="4"></label><label>Monthly<input name="monthly" type="number" min="0" value="12"></label><label>Expire after days<input name="expireAfterDays" type="number" min="1" value="30"></label><label>Compression<select name="compression"><option value="gzip">gzip</option><option value="zstd">zstd</option><option value="none">none</option></select></label><label>Encryption<select name="encryption"><option value="destination">Destination policy</option><option value="both">Destination + source</option><option value="client_side">Client side</option></select></label><label class="check"><input name="enabled" type="checkbox" checked> Enabled</label><button class="btn wide" type="submit" :disabled="busy()" x-cloak>{{ busy()?'Scheduling…':'Create policy' }}</button></form><section @show="tab()==='overview'" class="stack" x-cloak><template :for="item in inventory().coverage"><article class="coverage-card panel" x-cloak><div x-cloak><span class="pill" :class="item.missedRpo?'bad':'ok'" x-cloak>{{ item.missedRpo?'missed RPO':'protected' }}</span><span class="pill" :class="item.destinationHealthy?'ok':'bad'" x-cloak>{{ item.destinationHealthy?'destination healthy':'destination attention' }}</span><h2 x-cloak>{{ item.policy.name }}</h2><p x-cloak>{{ item.policy.resourceKind.replaceAll('_',' ') }} · every {{ item.policy.schedule }} · RPO {{ item.policy.expectedRpoMinutes }}m · RTO {{ item.policy.expectedRtoMinutes }}m</p></div><div class="coverage-latest"><small>Latest recovery point</small><b x-cloak>{{ when(item.lastRecoveryPoint?.pointInTime) }}</b><span x-cloak>{{ item.lastRecoveryPoint ? item.lastRecoveryPoint.verificationState : 'No recovery point yet' }}</span></div><button class="btn sm" @click="runPolicy(item.policy)" :disabled="busy()">Run now</button></article></template><div class="empty panel" @show="!inventory().coverage.length" x-cloak><strong>No protection policies</strong><span>Connect a destination, then define the first RPO-backed schedule.</span></div></section><section @show="tab()==='recovery'" class="stack" x-cloak><template :for="item in inventory().recoveryPoints"><article class="panel point-card" x-cloak><div class="point-head" x-cloak><div x-cloak><span class="pill" :class="tone(item.status)" x-cloak>{{ item.status }}</span><span class="pill" :class="tone(item.verificationState)" x-cloak>{{ item.verificationState }}</span><span class="pill" @show="item.held" x-cloak>legal hold</span><span class="pill" @show="item.pinned" x-cloak>pinned</span><h2 x-cloak>{{ policyName(item.policyId) }}</h2></div><button class="btn sm" @click="openRestore(item)" :disabled="item.status!=='available'||item.verificationState!=='verified'">Restore / drill</button></div><div class="point-grid"><div><small>Point in time</small><b x-cloak>{{ when(item.pointInTime) }}</b></div><div><small>Kind</small><b x-cloak>{{ item.kind.replaceAll('_',' ') }}</b></div><div><small>Stored</small><b x-cloak>{{ bytes(item.sizeBytes) }}</b></div><div><small>Expires</small><b x-cloak>{{ when(item.expiresAt) }}</b></div><div><small>Destination</small><b x-cloak>{{ destinationName(item.destinationId) }}</b></div><div><small>Recent jobs</small><b x-cloak>{{ jobsForPoint(item.id).length }}</b></div></div><div class="actions"><button class="btn ghost sm" @click="verifyPoint(item)" :disabled="busy()">Verify again</button><button class="btn ghost sm" @click="protectPoint(item,'pinned')" x-cloak>{{ item.pinned?'Unpin':'Pin' }}</button><button class="btn ghost sm" @click="protectPoint(item,'held')" x-cloak>{{ item.held?'Release hold':'Legal hold' }}</button></div></article></template><div class="empty panel" @show="!inventory().recoveryPoints.length" x-cloak><strong>No recovery points</strong><span>Run a policy to create the first independently verified recovery point.</span></div></section><section id="restore-workspace" class="panel restore" @show="!!selectedPoint()" x-cloak><div class="restore-head"><div><small>Selected recovery point</small><h2 x-cloak>{{ policyName(selectedPoint()?.policyId) }}</h2><p x-cloak>{{ when(selectedPoint()?.pointInTime) }} · {{ selectedPoint()?.kind?.replaceAll('_',' ') }}</p></div><button class="btn ghost sm" @click="selectedPoint.set(null)">Close</button></div><form class="form-grid" @submit="submitRestore($event)"><label>Mode<select name="mode"><option value="isolated">Isolated target (recommended)</option><option value="in_place">In-place replacement</option></select></label><label>Target name / ID<input name="targetName" required placeholder="orders-recovery-drill"></label><label>Safety recovery point<select name="safetyBackupId"><option value="">Required for in-place only</option><template :for="item in inventory().recoveryPoints.filter(item=>item.id!==selectedPoint()?.id&&item.verificationState==='verified')"><option :value="item.id">{{ policyName(item.policyId) }} · {{ when(item.pointInTime) }}</option></template></select></label><label>Typed confirmation<input name="confirm" placeholder="Same as target for in-place"></label><label class="wide" @show="selectedPoint()?.kind==='infrastructure'" x-cloak>AWS restore metadata (JSON)<textarea name="providerMetadata" rows="3" placeholder='{"availabilityZone":"us-east-1a"}'></textarea></label><label class="check"><input name="downtimeAcknowledged" type="checkbox"> I acknowledge downtime and data replacement</label><label class="check"><input name="drill" type="checkbox" :disabled="selectedPoint()?.kind==='infrastructure'"> Drill: validate health, then clean isolated target</label><div class="actions wide"><button class="btn ghost" type="submit" value="plan">Validate plan</button><button class="btn danger" type="submit" value="execute" :disabled="busy()" x-cloak>{{ busy()?'Queueing…':'Queue restore' }}</button></div></form><div class="plan" @show="!!restorePlan()" x-cloak><h3>Validated plan</h3><span class="pill" x-cloak>{{ restorePlan()?.mode }}</span><ul><template :for="warning in restorePlan()?.warnings || []"><li x-cloak>{{ warning }}</li></template></ul></div></section><section @show="tab()==='policies'" class="stack" x-cloak><template :for="item in inventory().policies"><article class="row-card panel" x-cloak><div x-cloak><span class="pill" :class="item.enabled?'ok':'warn'" x-cloak>{{ item.enabled?'enabled':'disabled' }}</span><b x-cloak>{{ item.name }}</b><code x-cloak>{{ item.schedule }} · {{ item.timezone }}</code><p class="note" x-cloak>{{ item.resourceKind.replaceAll('_',' ') }} · {{ destinationName(item.destinationId) }} · RPO {{ item.expectedRpoMinutes }}m / RTO {{ item.expectedRtoMinutes }}m · next {{ when(item.nextRunAt) }}</p></div><button class="btn sm" @click="runPolicy(item)">Run now</button></article></template></section><section @show="tab()==='destinations'" class="stack" x-cloak><template :for="item in inventory().destinations"><article class="row-card panel" x-cloak><div x-cloak><span class="pill" :class="tone(item.status)" x-cloak>{{ item.status }}</span><span class="pill" :class="['expired','invalid'].includes(item.credentialStatus?.status)?'bad':item.credentialStatus?.status==='expiring'?'warn':'ok'" x-cloak>credentials {{ item.credentialStatus?.status || 'unknown' }}</span><b x-cloak>{{ item.name }}</b><code x-cloak>{{ item.provider }} · {{ item.bucket || 'provider vault' }}</code><p class="note" x-cloak>{{ item.endpoint || item.region || 'provider default' }} · {{ item.encryption }} encryption · last tested {{ when(item.lastTestedAt) }}<span @show="!!item.credentialStatus?.expiresAt" x-cloak> · credentials expire {{ when(item.credentialStatus?.expiresAt) }}</span></p><p class="bad note" @show="!!item.lastError" x-cloak>{{ item.lastError }}</p></div><button class="btn ghost sm" @click="testDestination(item)" :disabled="item.provider==='aws_backup'||busy()">Test write/read</button></article></template></section><section @show="tab()==='jobs'" class="stack" x-cloak><template :for="item in inventory().jobs"><article class="job-card panel" x-cloak><span class="pill" :class="tone(item.status)" x-cloak>{{ item.status }}</span><div x-cloak><b x-cloak>{{ item.kind }}</b><code x-cloak>{{ item.id }}</code><p class="note" x-cloak>{{ item.progress?.phase || 'queued' }} · {{ when(item.startedAt || item.createdAt) }}<span @show="!!item.error" x-cloak> · {{ item.error }}</span></p></div><span x-cloak>{{ item.cancellability.replaceAll('_',' ') }}</span></article></template><div class="empty panel" @show="!inventory().jobs.length" x-cloak><strong>No recovery jobs</strong><span>Scheduled and manual work appears here with durable progress and failures.</span></div></section></main><style> .recovery-wrap{max-width:1500px}.header-actions,.actions,.point-head>div{display:flex;gap:7px;align-items:center;flex-wrap:wrap}.summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:14px}.summary article{display:grid;gap:5px}.summary strong{font-size:28px}.summary small,.point-grid small,.restore small{color:var(--txt3)}.tabs{display:flex;gap:5px;border-bottom:1px solid var(--line);margin-bottom:14px;overflow:auto}.tabs button{border:0;background:none;color:var(--txt3);padding:10px 13px;border-bottom:2px solid transparent;white-space:nowrap}.tabs button.active{color:var(--txt);border-color:var(--accent)}.form-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:14px}.form-grid label{display:grid;gap:5px;color:var(--txt3);font-size:11px}.form-grid input,.form-grid select,.form-grid textarea{width:100%;background:var(--bg2);border:1px solid var(--line);border-radius:8px;color:var(--txt);padding:9px}.form-grid textarea{resize:vertical}.form-grid .check{display:flex;align-items:center;gap:7px}.form-grid .check input{width:auto}.wide{grid-column:1/-1}.stack{display:grid;gap:10px}.coverage-card{display:grid;grid-template-columns:minmax(0,1fr) minmax(220px,.4fr) auto;gap:16px;align-items:center}.coverage-card h2,.point-card h2,.restore h2{margin:7px 0 3px}.coverage-card p,.restore p{margin:0;color:var(--txt3)}.coverage-latest{display:grid;gap:4px}.point-head,.restore-head,.row-card{display:flex;justify-content:space-between;gap:14px;align-items:center}.point-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:9px;margin:14px 0}.point-grid>div{display:grid;gap:4px;min-width:0}.point-grid b{overflow-wrap:anywhere}.restore{margin:14px 0;border-color:var(--accent)}.restore .form-grid{margin:14px 0 0}.plan{background:var(--bg2);border-radius:8px;padding:12px}.row-card>div{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.row-card p{flex-basis:100%;margin:0}.job-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:12px;align-items:center}.job-card div{display:grid;gap:4px}.job-card p{margin:0}.mono,code{font-family:var(--mono)}@media(max-width:1050px){.form-grid{grid-template-columns:repeat(2,1fr)}.point-grid{grid-template-columns:repeat(3,1fr)}.coverage-card{grid-template-columns:1fr auto}.coverage-latest{grid-column:1/-1}.summary{grid-template-columns:repeat(2,1fr)}}@media(max-width:650px){.form-grid,.point-grid,.summary{grid-template-columns:1fr}.form-grid>*{grid-column:1!important}.coverage-card,.job-card{grid-template-columns:1fr}.row-card,.point-head,.restore-head{align-items:flex-start;flex-direction:column}.header-actions{justify-content:flex-start}} </style></body></html>
@@ -1,5 +1,5 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mucyniusp75leg"><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 · Data services</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-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <script data-stx-scoped>
2
- function __stx_setup_1790098878686_3() {
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mudcq5hty15x8q"><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 · Data services</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-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <script data-stx-scoped>
2
+ function __stx_setup_1790122515960_3() {
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, 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
  var actionError = undefined;
@@ -331,9 +331,9 @@ tone = __stxBundle_0ec490371d35["tone"];
331
331
  when = __stxBundle_0ec490371d35["when"];
332
332
  return { actionError, actionLabels, api, busy, chooseAction, copy, createOpen, createService, engineFilter, filtered, formBody, guidance, inspect, lastUpdatedAt, load, notice, observationEntries, oneTime, operationAction, operations, plan, pollingError, pollingState, previewAction, providerFilter, refresh, reveal, runAction, runConfiguredAction, search, selected, serviceOperations, services, statusFilter, tone, when, __stxBundle_0ec490371d35 };
333
333
  }
334
- window.__stx_latestSetup=__stx_setup_1790098878686_3;
335
- if(window.stx)window.stx._latestSetup=__stx_setup_1790098878686_3;
336
- </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_1790098878686_3"><a data-stx-scope="stx_scope_nav_4" 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="active" 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>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">
334
+ window.__stx_latestSetup=__stx_setup_1790122515960_3;
335
+ if(window.stx)window.stx._latestSetup=__stx_setup_1790122515960_3;
336
+ </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_1790122515960_3"><a data-stx-scope="stx_scope_nav_4" 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="active" 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>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">
337
337
  (function() {
338
338
  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;
339
339
  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="mucyniusp75leg"><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 · Persistent volumes</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-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <script data-stx-scoped>
2
- function __stx_setup_1790098878682_0() {
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mudcq5hty15x8q"><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 · Persistent volumes</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-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <script data-stx-scoped>
2
+ function __stx_setup_1790122515957_0() {
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, 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
  var adopt = undefined;
@@ -219,9 +219,9 @@ tone = __stxBundle_87f7d53bdfa9["tone"];
219
219
  volumes = __stxBundle_87f7d53bdfa9["volumes"];
220
220
  return { adopt, api, attach, body, bytes, create, detach, discover, filtered, lastUpdatedAt, load, mutate, operationFor, pollingError, pollingState, refresh, remove, resize, restore, snapshot, tone, volumes, __stxBundle_87f7d53bdfa9 };
221
221
  }
222
- window.__stx_latestSetup=__stx_setup_1790098878682_0;
223
- if(window.stx)window.stx._latestSetup=__stx_setup_1790098878682_0;
224
- </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_1790098878682_0"><a data-stx-scope="stx_scope_nav_1" 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="active" 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="active" 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>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">
222
+ window.__stx_latestSetup=__stx_setup_1790122515957_0;
223
+ if(window.stx)window.stx._latestSetup=__stx_setup_1790122515957_0;
224
+ </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_1790122515957_0"><a data-stx-scope="stx_scope_nav_1" 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="active" 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="active" 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>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">
225
225
  (function() {
226
226
  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;
227
227
  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="mucyniusp75leg"><meta name="title" content="ts-cloud - Dashboard"><meta name="description" content="ts-cloud server &amp; deployment dashboard"><meta property="og:title" content="ts-cloud - Dashboard"><meta property="og:description" content="ts-cloud server &amp; deployment dashboard"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="ts-cloud - Dashboard"><meta name="twitter:description" content="ts-cloud server &amp; deployment dashboard"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Dashboard</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"><meta name="description" content="ts-cloud server &amp; deployment dashboard"> <script data-stx-scoped>
2
- function __stx_setup_1790098882143_32() {
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mudcq5hty15x8q"><meta name="title" content="ts-cloud - Dashboard"><meta name="description" content="ts-cloud server &amp; deployment dashboard"><meta property="og:title" content="ts-cloud - Dashboard"><meta property="og:description" content="ts-cloud server &amp; deployment dashboard"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="ts-cloud - Dashboard"><meta name="twitter:description" content="ts-cloud server &amp; deployment dashboard"> <script data-stx-runtime src="/_stx/runtime.dbee66d1.js"></script> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Dashboard</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"><meta name="description" content="ts-cloud server &amp; deployment dashboard"> <script data-stx-scoped>
2
+ function __stx_setup_1790122519332_30() {
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
  var initialData = null;
@@ -161,9 +161,9 @@ servicesC = __stxBundle_87ebf77e804c["servicesC"];
161
161
  svcTone = __stxBundle_87ebf77e804c["svcTone"];
162
162
  return { barCss, barStyle, cpuP, cpuSub, data, diskP, gbVal, indicator, liveData, loadP, memP, memSub, n, overallC, overallWordC, pDisp, pTone, pctOf, pollingError, pollingState, servicesC, svcTone, __stxBundle_87ebf77e804c };
163
163
  }
164
- window.__stx_latestSetup=__stx_setup_1790098882143_32;
165
- if(window.stx)window.stx._latestSetup=__stx_setup_1790098882143_32;
166
- </script> <style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.b7a99a5c.css"></head><body data-stx="__stx_setup_1790098882143_32"><a data-stx-scope="stx_scope_nav_49" 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>stacks-production-app</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="active" 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>stacks-production-app</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">
164
+ window.__stx_latestSetup=__stx_setup_1790122519332_30;
165
+ if(window.stx)window.stx._latestSetup=__stx_setup_1790122519332_30;
166
+ </script> <style data-stx-cloak>[x-cloak]{display:none !important}</style><link data-crosswind="generated" rel="stylesheet" href="/_stx/crosswind.b7a99a5c.css"></head><body data-stx="__stx_setup_1790122519332_30"><a data-stx-scope="stx_scope_nav_43" 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>stacks-production-app</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="active" 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>stacks-production-app</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">
167
167
  (function() {
168
168
  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;
169
169
  var __destroyHooks = [];
@@ -514,6 +514,6 @@ if(window.stx)window.stx._latestSetup=__stx_setup_1790098882143_32;
514
514
 
515
515
 
516
516
  try { if (typeof __stxScopeRenames !== 'undefined' && __stxScopeRenames) { for (var __stxRK in __stxScopeRenames) __scopeRegistration[__stxRK] = __stxScopeRenames[__stxRK]; } } catch (e) { /* no renames */ }
517
- window.stx._scopes['stx_scope_nav_49'] = __scopeRegistration;
517
+ window.stx._scopes['stx_scope_nav_43'] = __scopeRegistration;
518
518
  })();
519
519
  </script> <div class="wrap"><header class="page"><div><h1>Server Dashboard</h1><p>Hetzner · fsn1 · Linux</p><div class="server-line"><span>IP <b>-</b></span><span>Uptime <b>-</b></span><span>CPUs <b>4</b></span><span class="pill" :class="overallC()" x-cloak>{{ overallWordC() }}</span></div></div><div class="header-actions" x-cloak><span class="env" :class="{ bad: pollingState() === 'stale' }" :title="pollingState() === 'stale' ? pollingError() : 'Auto-refreshing every 10s'" x-cloak>{{ indicator() }}</span><a class="btn ghost" href="/server/actions">Operations</a></div></header><div class="grid cards"><a class="panel" href="/server/metrics"><h3>CPU utilization</h3><div class="stat" x-cloak>{{ pDisp(cpuP()) }}<small x-cloak>{{ cpuSub() }}</small></div><div :class="barCss(cpuP())"><i :style="barStyle(cpuP())"></i></div></a><a class="panel" href="/server/metrics"><h3>Memory</h3><div class="stat" x-cloak>{{ pDisp(memP()) }}<small x-cloak>{{ memSub() }}</small></div><div :class="barCss(memP())"><i :style="barStyle(memP())"></i></div></a><a class="panel" href="/server/metrics"><h3>Disk</h3><div class="stat" x-cloak>{{ pDisp(diskP()) }}<small></small></div><div :class="barCss(diskP())"><i :style="barStyle(diskP())"></i></div></a><a class="panel" href="/data/backups"><h3>Backups</h3><div class="stat">0 MB</div><p style="color: var(--txt2); font-size: 13px; margin-top: 8px;">Last not configured</p></a></div><div class="grid cards-3" style="margin-top:16px;"><a class="panel" href="/server/security"><h3>Security</h3><div class="stat"><span class="pill ok">configured</span></div><p style="color: var(--txt2); font-size: 13px; margin-top: 8px;">0 listeners · 0 certs</p></a><a class="panel" href="/server/diagnostics"><h3>Diagnostics</h3><div class="stat">0<small> fail</small></div><p style="color: var(--txt2); font-size: 13px; margin-top: 8px;">0 warnings</p></a><a class="panel" href="/server/activity"><h3>Activity</h3><div class="stat">0</div><p style="color: var(--txt2); font-size: 13px; margin-top: 8px;">deploys, warnings, key changes</p></a></div><div class="section"><h2>Resource Shape <a class="more" href="/server/metrics">Open health →</a></h2><div class="chart-panel panel"><svg class="chart resource-chart" viewBox="0 0 640 210" role="img" aria-label="Server resource chart"><rect x="1" y="1" width="638" height="208" rx="14" class="chart-shell"></rect><line x1="38" x2="620" y1="166" y2="166" class="chart-grid"></line><text x="28" y="170" text-anchor="end" class="chart-axis">0</text><line x1="38" x2="620" y1="129" y2="129" class="chart-grid"></line><text x="28" y="133" text-anchor="end" class="chart-axis">25</text><line x1="38" x2="620" y1="92" y2="92" class="chart-grid"></line><text x="28" y="96" text-anchor="end" class="chart-axis">50</text><line x1="38" x2="620" y1="55" y2="55" class="chart-grid"></line><text x="28" y="59" text-anchor="end" class="chart-axis">75</text><line x1="38" x2="620" y1="18" y2="18" class="chart-grid"></line><text x="28" y="22" text-anchor="end" class="chart-axis">100</text><g class="bar-mark ok"><rect x="61.59459459459464" y="149.72" width="141.56756756756755" height="16.28" rx="7"></rect><text x="132.37837837837841" y="141.72" text-anchor="middle" class="chart-value">11%</text><text x="132.37837837837841" y="190" text-anchor="middle" class="chart-label">CPU</text><title>11% busy · 0.42 load / 4 vCPU</title></g><g class="bar-mark ok"><rect x="258.21621621621625" y="118.64" width="141.56756756756755" height="47.36" rx="7"></rect><text x="329" y="110.64" text-anchor="middle" class="chart-value">32%</text><text x="329" y="190" text-anchor="middle" class="chart-label">Memory</text><title>2.4 / 7.7 GB</title></g><g class="bar-mark ok"><rect x="454.83783783783787" y="109.76" width="141.56756756756755" height="56.239999999999995" rx="7"></rect><text x="525.6216216216217" y="101.76" text-anchor="middle" class="chart-value">38%</text><text x="525.6216216216217" y="190" text-anchor="middle" class="chart-label">Disk</text><title>0 / 0 GB</title></g></svg></div></div><div class="section"><h2>Services <span class="more"><a href="/server/services">View all →</a><a href="/server/logs">Logs →</a><a href="/server/security">Security →</a></span></h2><div class="panel" x-cloak><div class="svc" x-cloak><template :for="svc in servicesC()"><div class="item" x-cloak>{{ svc.name }} <span class="pill" :class="svcTone(svc.status)" x-cloak>{{ svc.status }}</span></div></template></div><div class="compact empty" @show="servicesC().length === 0" x-cloak><strong>No managed services</strong><span>Configured services will appear after the next successful server probe.</span></div></div></div><div class="section"><h2>SSH Keys <a class="more" href="/server/ssh-keys">Manage →</a></h2><div class="panel"><div class="compact empty"><strong>No SSH keys configured</strong><span>Add keys from the management page and apply them on the next deploy.</span></div><p class="note">SSH keys are managed in <span class="mono">infrastructure.compute.sshKeys</span> in your cloud config and applied on the next <span class="mono">cloud deploy</span>.</p></div></div><div class="section"><h2>Sites <a class="more" href="/server/sites">View all →</a></h2><div class="panel"><table><thead><tr><th scope="col">Site</th><th scope="col">Project</th><th scope="col">Route</th><th scope="col">Response</th><th scope="col">TLS</th><th scope="col">Deploy</th><th scope="col">Status</th></tr></thead><tbody><tr><td><b>main</b></td><td><span class="tag">stacks</span></td><td><a href="https://stacksjs.com" class="mono">stacksjs.com</a></td><td class="mono">pending</td><td><span class="warn pill">https</span></td><td style="color: var(--txt2)">service</td><td><span class="pill ok">live</span></td></tr><tr><td><b>api</b></td><td><span class="tag">stacks</span></td><td><span class="mono">internal</span></td><td class="mono">pending</td><td><span class="warn pill">loopback</span></td><td style="color: var(--txt2)">service</td><td><span class="pill ok">live</span></td></tr><tr><td><b>docs</b></td><td><span class="tag">stacks</span></td><td><a href="https://stacksjs.com/docs" class="mono">stacksjs.com/docs</a></td><td class="mono">pending</td><td><span class="warn pill">https</span></td><td style="color: var(--txt2)">server static</td><td><span class="pill ok">live</span></td></tr><tr><td><b>blog</b></td><td><span class="tag">stacks</span></td><td><a href="https://stacksjs.com/blog" class="mono">stacksjs.com/blog</a></td><td class="mono">pending</td><td><span class="warn pill">https</span></td><td style="color: var(--txt2)">server static</td><td><span class="pill ok">live</span></td></tr><tr><td><b>public</b></td><td><span class="tag">stacks</span></td><td><a href="https://stacksjs.com" class="mono">stacksjs.com</a></td><td class="mono">pending</td><td><span class="warn pill">https</span></td><td style="color: var(--txt2)">server static</td><td><span class="pill warn">shadowed</span></td></tr><tr><td><b>verygoodadblock</b></td><td><span class="tag">stacks</span></td><td><a href="https://verygoodadblock.org" class="mono">verygoodadblock.org</a></td><td class="mono">pending</td><td><span class="warn pill">https</span></td><td style="color: var(--txt2)">server static</td><td><span class="pill ok">live</span></td></tr></tbody></table></div></div><div class="cols section"><div><h2>Recent Deployments <a class="more" href="/server/deployments">View all →</a></h2><div class="panel"><svg class="chart deployment-chart disabled" viewBox="0 0 640 164" role="img" aria-label="No deployment history"><rect x="1" y="1" width="638" height="162" rx="14" class="chart-shell"></rect><text x="320" y="76" text-anchor="middle" class="chart-empty-title">No deploy records yet</text><text x="320" y="100" text-anchor="middle" class="chart-empty-sub">Deploy again and this timeline will fill in automatically.</text></svg><div class="compact empty"><strong>No recent deployments</strong><span>No deployment history has been recorded yet.</span></div></div></div><div><h2>Queues &amp; Scheduler <a class="more" href="/server/workers">Details →</a></h2><div class="panel"><div class="kv"><span>queue:default ×2</span><span class="pill ok">running</span></div><div class="kv"><span>queue:emails ×1</span><span class="pill ok">running</span></div><div class="kv"><span>scheduler</span><span class="ok pill">on · 36s ago</span></div></div><div style="height: 16px"></div><h2>Backups <a class="more" href="/data/backups">Details →</a></h2><div class="panel"><div class="kv"><span>destination</span><span class="mono">off</span></div><div class="kv"><span>retention</span><span>0 copies</span></div><div class="kv"><span>last run</span><span style="color: var(--txt2)">not configured</span></div></div></div></div></div></body></html>
@@ -1,5 +1,5 @@
1
- <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mucyniusp75leg"><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> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Infrastructure map</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_1790098878695_6() {
1
+ <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mudcq5hty15x8q"><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> <script data-stx-composables src="/_stx/chunk.5ddb5087.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Infrastructure map</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_1790122515961_4() {
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, 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
  var initialTopology = {"mode":"server","project":"sample-project","environment":"production","provider":"hetzner","region":"fsn1","generatedAt":"","layers":[{"index":0,"id":"clients","label":"Clients"},{"index":1,"id":"dns","label":"DNS & TLS"},{"index":2,"id":"edge","label":"Edge"},{"index":3,"id":"routing","label":"Routing"},{"index":4,"id":"apps","label":"Applications"},{"index":5,"id":"runtime","label":"Background runtime"},{"index":6,"id":"data","label":"Data services"},{"index":7,"id":"durability","label":"Durability"}],"groups":[{"id":"box","label":"sample-production-app","sub":"hetzner · fsn1"}],"nodes":[{"id":"internet","label":"Internet","kind":"internet","layer":0,"status":"ok","sub":"Public traffic","facts":[],"external":true},{"id":"dns","label":"example.com","kind":"dns","layer":1,"status":"ok","sub":"DNS & certificates","facts":[],"external":true},{"id":"firewall","label":"Host firewall","kind":"firewall","layer":2,"status":"ok","sub":"Inbound filtering","facts":[],"group":"box"},{"id":"proxy","label":"rpx-gateway","kind":"proxy","layer":3,"status":"ok","sub":"TLS termination & routing","facts":[],"group":"box"},{"id":"site:main","label":"main","kind":"site","layer":4,"status":"ok","sub":"bun","facts":[],"group":"box"},{"id":"site:docs","label":"docs","kind":"site","layer":4,"status":"ok","sub":"static/bun","facts":[],"group":"box"},{"id":"worker:default","label":"default","kind":"worker","layer":5,"status":"ok","sub":"2 processes","facts":[],"group":"box"},{"id":"data:redis","label":"Redis","kind":"cache","layer":6,"status":"ok","sub":"redis","facts":[],"group":"box"},{"id":"data:mysql","label":"MySQL","kind":"database","layer":6,"status":"ok","sub":"mysql","facts":[],"group":"box"},{"id":"backup","label":"Backups","kind":"backup","layer":7,"status":"ok","sub":"off-box","facts":[]}],"links":[{"source":"internet","target":"dns","flow":"request","label":"https"},{"source":"dns","target":"firewall","flow":"request","label":"443/80"},{"source":"firewall","target":"proxy","flow":"request"},{"source":"proxy","target":"site:main","flow":"request"},{"source":"proxy","target":"site:docs","flow":"request"},{"source":"site:main","target":"worker:default","flow":"async","label":"queue"},{"source":"site:main","target":"data:redis","flow":"data","label":"localhost"},{"source":"site:main","target":"data:mysql","flow":"data","label":"localhost"},{"source":"worker:default","target":"data:mysql","flow":"data","label":"localhost"},{"source":"data:mysql","target":"backup","flow":"backup","label":"snapshot"}],"notes":[]};
@@ -858,9 +858,9 @@ zoomBy = __stxBundle_aadcc1d88d59["zoomBy"];
858
858
  zoomTo = __stxBundle_aadcc1d88d59["zoomTo"];
859
859
  return { STAGE_H, STAGE_W, animate, atPointer, builtAtLabel, canvasScale, canvasTransform, clear, counts, dim, dragging, fit, fitScale, flows, focus, geo, groups, hoveredId, isSample, isSnapshot, labelledLinks, lanes, lastUpdatedAt, linkClasses, linkOff, linkOn, links, load, manageHref, model, nodeClasses, nodes, notes, onDown, onMove, onUp, onWheel, panX, panY, pollingError, pollingState, query, refresh, restatus, select, selected, selectedFacts, selectedId, selectedLinks, shapeOf, stageCrop, toggleFlow, visible, zoom, zoomBy, zoomTo, __stxBundle_aadcc1d88d59 };
860
860
  }
861
- window.__stx_latestSetup=__stx_setup_1790098878695_6;
862
- if(window.stx)window.stx._latestSetup=__stx_setup_1790098878695_6;
863
- </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_1790098878695_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>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="active" 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>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">
861
+ window.__stx_latestSetup=__stx_setup_1790122515961_4;
862
+ if(window.stx)window.stx._latestSetup=__stx_setup_1790122515961_4;
863
+ </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_1790122515961_4"><a data-stx-scope="stx_scope_nav_5" 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="active" 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>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">
864
864
  (function() {
865
865
  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;
866
866
  var __destroyHooks = [];
@@ -1211,6 +1211,6 @@ if(window.stx)window.stx._latestSetup=__stx_setup_1790098878695_6;
1211
1211
 
1212
1212
 
1213
1213
  try { if (typeof __stxScopeRenames !== 'undefined' && __stxScopeRenames) { for (var __stxRK in __stxScopeRenames) __scopeRegistration[__stxRK] = __stxScopeRenames[__stxRK]; } } catch (e) { /* no renames */ }
1214
- window.stx._scopes['stx_scope_nav_9'] = __scopeRegistration;
1214
+ window.stx._scopes['stx_scope_nav_5'] = __scopeRegistration;
1215
1215
  })();
1216
1216
  </script> <main class="topo-wrap wrap" id="main-content"><div class="crumbs">Infrastructure <span class="sep">/</span> Map</div><header class="page"><div><h1>Infrastructure map</h1><p>Every resource this environment deploys, in the order a request meets them. Hover to trace a path, click to inspect.</p></div><div class="header-actions"><span class="pill warn" @show="isSample()" x-cloak>sample topology</span><span class="pill" :class="pollingState() === 'live' ? 'ok' : 'warn'" x-cloak>{{ pollingState() }}</span><small x-cloak>{{ isSnapshot() ? builtAtLabel() : lastUpdatedAt() ? lastUpdatedAt().toLocaleTimeString() : 'connecting' }}</small><button class="btn ghost sm" type="button" @show="!isSnapshot()" @click="refresh()" x-cloak>Refresh</button></div></header><p class="topo-notice bad" role="alert" @show="!!pollingError()" x-cloak>{{ pollingError() }}</p><p class="topo-notice" role="status" @show="isSample() && !pollingError()" x-cloak>Showing a representative topology until this deployment reports one.</p><p class="topo-notice" role="status" @show="isSnapshot() && !isSample()" x-cloak>This cockpit was exported without its control plane, so the map cannot refresh. It shows the infrastructure as it stood when the dashboard was built.</p><p class="topo-notice" :for="note in notes" x-cloak>{{ note }}</p><section class="topo-summary" aria-label="Topology summary" x-cloak><article class="panel" x-cloak><b x-cloak>{{ model().mode === 'serverless' ? 'Serverless' : 'Server' }}</b><small x-cloak>{{ model().provider }} · {{ model().region }}</small></article><article class="panel" x-cloak><b x-cloak>{{ geo().nodes.length }} resources</b><small x-cloak>{{ geo().lanes.length }} layers · {{ geo().links.length }} connections</small></article><article class="panel" x-cloak><b x-cloak>{{ counts().ok }} healthy</b><small x-cloak>{{ counts().warn }} attention · {{ counts().bad }} failing · {{ counts().idle }} idle</small></article><article class="panel" x-cloak><b x-cloak>{{ model().environment }}</b><small x-cloak>{{ model().project }}</small></article></section><section class="topo-controls panel" aria-label="Diagram controls"><label class="topo-search"><span class="sr-only">Filter resources</span><input type="search" placeholder="Filter resources (name, kind, value)" :value="query()" @input="query.set($event.target.value)"></label><div class="topo-flows" role="group" aria-label="Connection types"><button type="button" class="chip request" :class="flows().request ? '' : 'off'" @click="toggleFlow('request')">Requests</button><button type="button" class="async chip" :class="flows().async ? '' : 'off'" @click="toggleFlow('async')">Async</button><button type="button" class="chip data" :class="flows().data ? '' : 'off'" @click="toggleFlow('data')">Data</button><button type="button" class="backup chip" :class="flows().backup ? '' : 'off'" @click="toggleFlow('backup')">Backup</button></div><div class="topo-zoom" x-cloak><button class="btn ghost sm" type="button" @click="animate.set(!animate())" x-cloak>{{ animate() ? 'Pause flow' : 'Animate flow' }}</button><button class="btn ghost sm" type="button" aria-label="Zoom out" @click="zoomBy(1 / 1.2)">−</button><span class="topo-level" x-cloak>{{ Math.round(zoom() * 100) }}%</span><button class="btn ghost sm" type="button" aria-label="Zoom in" @click="zoomBy(1.2)">+</button><button class="btn ghost sm" type="button" @click="fit()">Fit</button><button class="btn ghost sm" type="button" @click="clear()">Reset</button></div></section><div class="topo-stage"><section class="topo-panel panel"><div class="topo-viewport" :style="'aspect-ratio: 1600 / ' + stageCrop()"><svg class="topo-canvas" viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMin meet" role="img" aria-label="Infrastructure topology diagram" @wheel="onWheel($event)" @pointerdown="onDown($event)" @pointermove="onMove($event)" @pointerup="onUp()" @pointerleave="onUp()"><defs><marker id="topo-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="currentColor"></path></marker></defs><g class="topo-canvas-inner" :transform="canvasTransform()"><g class="topo-lanes"><g :for="lane in lanes"><rect class="topo-lane" :x="lane.x" :y="lane.y" :width="lane.width" :height="lane.height" rx="18"></rect><text class="topo-lane-label" :x="lane.x + lane.width / 2" :y="lane.y - 24" text-anchor="middle" :text="lane.label"></text><text class="topo-lane-count" :x="lane.x + lane.width / 2" :y="lane.y - 8" text-anchor="middle" :text="lane.count + (lane.count === 1 ? ' resource' : ' resources')"></text></g></g><g class="topo-groups"><g :for="group in groups"><rect class="topo-group" :x="group.x" :y="group.y" :width="group.width" :height="group.height" rx="20"></rect><text class="topo-group-label" :x="group.x + 16" :y="group.y + 22" :text="group.sub ? group.label + ' · ' + group.sub : group.label"></text></g></g><g class="topo-edges"><path :for="link in links" class="topo-link" :class="linkClasses(link)" :d="link.d" marker-end="url(#topo-arrow)"></path></g><g class="topo-edge-labels"><text :for="link in labelledLinks" class="topo-edge-label" :class="{ dim: linkOff(link) }" :x="link.labelX" :y="link.labelY" text-anchor="middle" :text="link.label"></text></g><g class="topo-nodes"><g :for="node in nodes" class="topo-node" :class="nodeClasses(node)" :transform="'translate(' + node.x + ',' + node.y + ')'" tabindex="0" role="button" :aria-label="node.label + ', ' + node.kind + ', ' + node.status" @pointerenter="hoveredId.set(node.id)" @pointerleave="hoveredId.set('')" @focus="hoveredId.set(node.id)" @blur="hoveredId.set('')" @click="select(node)" @keydown.enter="select(node)"><rect class="topo-box" :width="node.width" :height="node.height" rx="14"></rect><g class="topo-icon" transform="translate(15,20) scale(0.83)"><path :d="node.icon"></path></g><text class="topo-label" x="48" y="27" :text="node.label"></text><text class="topo-sub" x="48" y="45" :text="node.sub || node.kind"></text><circle class="topo-dot" :cx="node.width - 17" cy="20" r="4.5"></circle></g></g></g></svg></div><p class="topo-hint">Drag to pan · scroll to zoom · Tab to walk the graph. Hovering a resource keeps its upstream path lit.</p></section><aside class="topo-detail panel" @show="!!selected()" aria-label="Resource detail" x-cloak><div class="topo-detail-head" x-cloak><div x-cloak><span class="pill" :class="selected()?.status === 'ok' ? 'ok' : selected()?.status === 'bad' ? 'bad' : 'warn'" x-cloak>{{ selected()?.status }}</span><h2 x-cloak>{{ selected()?.label }}</h2><p x-cloak>{{ selected()?.kind }} · {{ selected()?.sub }}</p></div><button class="btn ghost sm" type="button" @click="selectedId.set('')">Close</button></div><div class="kv" :for="fact in selectedFacts" x-cloak><span x-cloak>{{ fact.label }}</span><b x-cloak>{{ fact.value }}</b></div><p class="topo-empty-facts" @show="!selectedFacts().length" x-cloak>No further detail is reported for this resource.</p><h3>Connections</h3><div class="topo-conn" :for="link in selectedLinks" x-cloak><span class="chip" :class="link.flow" x-cloak>{{ link.flow }}</span><span x-cloak>{{ link.arrow }} {{ link.other }}</span><small x-cloak>{{ link.note }}</small></div><a class="btn sm" :href="manageHref(selected())" @show="!!selected()?.href" x-cloak>Manage this resource</a></aside></div><section class="topo-legend" aria-label="Legend"><span><i class="ok swatch"></i>healthy</span><span><i class="swatch warn"></i>needs attention</span><span><i class="bad swatch"></i>failing</span><span><i class="idle swatch"></i>idle</span><span><i class="swatch unknown"></i>not reported</span><span class="topo-legend-sep"></span><span><i class="stroke request"></i>request</span><span><i class="stroke async"></i>async</span><span><i class="stroke data"></i>data</span><span><i class="stroke backup"></i>backup</span></section></main><style> .topo-wrap { max-width: 1560px; } .topo-notice { margin: 10px 0; padding: 10px 14px; border-radius: 12px; background: rgba(255,255,255,0.04); border: 1px solid var(--panel-br); color: var(--txt2); font-size: 13px; } .topo-notice.bad { background: var(--badbg); border-color: rgba(240,115,110,0.3); color: var(--bad); } .topo-summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 16px 0 12px; } .topo-summary article { display: grid; gap: 5px; } .topo-summary b { font-size: 19px; } .topo-summary small { color: var(--txt3); } .topo-controls { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 12px 14px; } .topo-search { flex: 1 1 260px; } .topo-search input { width: 100%; background: var(--bg2); border: 1px solid var(--panel-br); border-radius: 10px; color: var(--txt); padding: 8px 12px; } .topo-flows, .topo-zoom { display: flex; align-items: center; gap: 7px; } .topo-level { min-width: 46px; text-align: center; color: var(--txt3); font: 600 12px var(--mono); } .chip { border: 1px solid var(--panel-br); background: rgba(255,255,255,0.04); color: var(--txt2); border-radius: 999px; padding: 5px 11px; font-size: 12px; font-weight: 600; cursor: pointer; } .chip::before { content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 7px; vertical-align: 0; background: currentColor; } .chip.request { color: var(--accent); } .chip.async { color: #c08ae8; } .chip.data { color: var(--ok); } .chip.backup { color: var(--txt3); } .chip.off { opacity: .38; } .topo-stage { position: relative; } .topo-panel { padding: 8px; min-width: 0; } /* The svg is a fixed, over-tall stage; the viewport crops it to the band the drawing occupies. That crop is bound to the live geometry, so the diagram fills the panel even when a re-layout is taller than the baked stage. */ .topo-viewport { position: relative; width: 100%; max-height: 78vh; overflow: hidden; } .topo-canvas { display: block; width: 100%; height: auto; touch-action: none; cursor: grab; color: var(--txt3); } .topo-canvas:active { cursor: grabbing; } .topo-hint { padding: 6px 12px 4px; color: var(--txt3); font-size: 11.5px; } .topo-lane { fill: rgba(255,255,255,0.016); stroke: rgba(255,255,255,0.05); } .topo-lane-label { fill: var(--txt3); font: 700 13px 'Inter', sans-serif; letter-spacing: .09em; text-transform: uppercase; } .topo-lane-count { fill: var(--txt3); font: 600 12px var(--mono); opacity: .6; } .topo-group { fill: none; stroke: rgba(90,139,224,0.34); stroke-dasharray: 6 6; } .topo-group-label { fill: var(--accent); font: 700 13px 'Inter', sans-serif; } .topo-group-sub { fill: var(--txt3); font-weight: 500; } .topo-link { fill: none; stroke: var(--accent); stroke-width: 1.7; opacity: .55; color: var(--accent); transition: opacity .18s ease; } .topo-link.async { stroke: #c08ae8; color: #c08ae8; stroke-dasharray: 7 5; } .topo-link.data { stroke: var(--ok); color: var(--ok); } .topo-link.backup { stroke: var(--txt3); color: var(--txt3); stroke-dasharray: 2 6; } .topo-link.animate { stroke-dasharray: 9 7; animation: topo-flow 1.5s linear infinite; } .topo-link.dim { opacity: .07; animation: none; } @keyframes topo-flow { to { stroke-dashoffset: -32; } } @media (prefers-reduced-motion: reduce) { .topo-link.animate { animation: none; } } .topo-edge-label { fill: var(--txt3); font: 600 11.5px var(--mono); paint-order: stroke; stroke: var(--bg); stroke-width: 4px; } .topo-edge-label.dim { opacity: .06; } .topo-node { cursor: pointer; } .topo-node .topo-box { fill: rgba(20,26,38,0.94); stroke: var(--panel-br); stroke-width: 1.2; transition: stroke .18s ease, fill .18s ease; } .topo-node .topo-icon { fill: none; stroke: var(--txt2); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; } .topo-node .topo-label { fill: var(--txt); font: 700 15px 'Inter', sans-serif; } .topo-node .topo-sub { fill: var(--txt3); font: 500 12px var(--mono); } .topo-node .topo-dot { fill: var(--txt3); } .topo-node.ok .topo-dot { fill: var(--ok); } .topo-node.warn .topo-dot { fill: var(--warn); } .topo-node.bad .topo-dot { fill: var(--bad); } .topo-node.idle .topo-dot { fill: var(--txt3); opacity: .5; } .topo-node.bad .topo-box { stroke: rgba(240,115,110,0.5); } .topo-node.warn .topo-box { stroke: rgba(237,185,73,0.42); } .topo-node.external .topo-box { fill: rgba(255,255,255,0.02); stroke-dasharray: 5 5; } .topo-node:hover .topo-box, .topo-node:focus-visible .topo-box { stroke: var(--accent); fill: rgba(28,38,58,0.98); } .topo-node:focus { outline: none; } .topo-node:focus-visible .topo-box { stroke-width: 2; } .topo-node.selected .topo-box { stroke: var(--accent); stroke-width: 2; } .topo-node.selected .topo-icon { stroke: var(--accent); } .topo-node.dim { opacity: .16; } /* Opaque: it floats over the diagram, and a translucent panel over moving edges is unreadable. */ .topo-detail { position: absolute; z-index: 5; top: 12px; right: 12px; width: 340px; display: grid; gap: 4px; max-height: calc(100% - 24px); overflow: auto; background: #0e131d; box-shadow: 0 22px 60px rgba(0,0,0,0.6); } .topo-detail-head { display: flex; justify-content: space-between; gap: 12px; align-items: start; margin-bottom: 8px; } .topo-detail-head h2 { font-size: 19px; margin-top: 6px; } .topo-detail-head p { color: var(--txt3); font-size: 12px; } .topo-detail h3 { margin: 16px 0 4px; font-size: 12px; letter-spacing: .09em; text-transform: uppercase; color: var(--txt3); } .topo-detail .kv b { font-family: var(--mono); font-size: 12.5px; text-align: right; word-break: break-all; } .topo-empty-facts { color: var(--txt3); font-size: 12px; padding: 8px 0; } .topo-conn { display: flex; align-items: center; gap: 9px; padding: 6px 0; color: var(--txt2); font-size: 12px; } .topo-conn .chip { cursor: default; padding: 2px 9px; font-size: 11px; } .topo-detail .btn { margin-top: 14px; text-align: center; text-decoration: none; } .topo-legend { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 14px 4px 0; color: var(--txt3); font-size: 12px; } .topo-legend span { display: inline-flex; align-items: center; gap: 7px; } .topo-legend .swatch { width: 9px; height: 9px; border-radius: 50%; background: var(--txt3); } .topo-legend .swatch.ok { background: var(--ok); } .topo-legend .swatch.warn { background: var(--warn); } .topo-legend .swatch.bad { background: var(--bad); } .topo-legend .swatch.idle { background: var(--txt3); opacity: .5; } .topo-legend .stroke { width: 20px; height: 0; border-top: 2px solid var(--accent); } .topo-legend .stroke.async { border-top-style: dashed; border-color: #c08ae8; } .topo-legend .stroke.data { border-color: var(--ok); } .topo-legend .stroke.backup { border-top-style: dotted; border-color: var(--txt3); } .topo-legend-sep { width: 1px; height: 14px; background: var(--panel-br); } @media (max-width: 1100px) { .topo-detail { position: static; width: auto; max-height: none; margin-top: 12px; } .topo-summary { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 640px) { .topo-summary { grid-template-columns: 1fr; } .topo-controls > * { width: 100%; } } </style></body></html>