@stacksjs/ts-cloud 0.12.1 → 0.12.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.
- package/dist/aws/index.js +1 -1
- package/dist/bin/chunk-0zwknfwp.js +1 -0
- package/dist/bin/chunk-33ct22z0.js +1 -0
- package/dist/bin/chunk-3aph4c1w.js +2 -0
- package/dist/bin/{chunk-5bhx3bsa.js → chunk-4q6tad44.js} +121 -121
- package/dist/bin/chunk-5nkqza92.js +1 -0
- package/dist/bin/chunk-64vczwwt.js +1 -0
- package/dist/bin/chunk-6tfwm33r.js +6 -0
- package/dist/bin/chunk-71t1gmsq.js +1 -0
- package/dist/bin/chunk-7g2ahkse.js +1 -0
- package/dist/bin/chunk-7zhgmp1s.js +3 -0
- package/dist/bin/chunk-82mj52xr.js +141 -0
- package/dist/bin/chunk-8ewncfce.js +37 -0
- package/dist/bin/chunk-9a88fp00.js +2 -0
- package/dist/bin/chunk-9kf0np8j.js +44 -0
- package/dist/bin/chunk-a7w13qfm.js +2 -0
- package/dist/bin/chunk-anx2a852.js +585 -0
- package/dist/bin/chunk-b4wt9jcg.js +60 -0
- package/dist/bin/chunk-btdq3w81.js +512 -0
- package/dist/bin/chunk-btsyjhk7.js +92 -0
- package/dist/bin/chunk-c0bdafbx.js +2 -0
- package/dist/bin/chunk-cd0ps58j.js +1 -0
- package/dist/bin/chunk-cxt74wsj.js +1 -0
- package/dist/bin/chunk-d7ke90zt.js +2 -0
- package/dist/bin/chunk-djg4zyqk.js +1 -0
- package/dist/bin/chunk-dkaz333b.js +1 -0
- package/dist/bin/chunk-dkf4qsp2.js +1 -0
- package/dist/bin/{chunk-scqmd4qv.js → chunk-dz1ec589.js} +30 -30
- package/dist/bin/chunk-e2bybahr.js +3 -0
- package/dist/bin/chunk-e5ab5twy.js +50 -0
- package/dist/bin/chunk-edvvx3hg.js +1 -0
- package/dist/bin/chunk-ehc63fvs.js +2 -0
- package/dist/bin/chunk-f06c5np9.js +1 -0
- package/dist/bin/chunk-gq8794k6.js +1 -0
- package/dist/bin/chunk-hq9x489e.js +70 -0
- package/dist/bin/chunk-ja1vjdn1.js +6 -0
- package/dist/bin/chunk-k3120rx6.js +1 -0
- package/dist/bin/chunk-kg61p5hw.js +3 -0
- package/dist/bin/chunk-mcr0r4at.js +2 -0
- package/dist/bin/chunk-mfrf9q4b.js +2 -0
- package/dist/bin/chunk-my3ewh3a.js +34 -0
- package/dist/bin/chunk-nw3d4k52.js +1 -0
- package/dist/bin/chunk-p70bc9yr.js +1 -0
- package/dist/bin/chunk-q5cmfpzt.js +1 -0
- package/dist/bin/chunk-rtecnmts.js +4 -0
- package/dist/bin/chunk-s4yzes15.js +2 -0
- package/dist/bin/chunk-sj5csg49.js +2 -0
- package/dist/bin/chunk-tfbs8k8v.js +111 -0
- package/dist/bin/chunk-tvz9c388.js +1 -0
- package/dist/bin/{chunk-9vdc7adf.js → chunk-w32xv8n4.js} +6 -6
- package/dist/bin/chunk-x6f61g36.js +9 -0
- package/dist/bin/chunk-xhwqpgwq.js +2 -0
- package/dist/bin/chunk-xk08030d.js +6 -0
- package/dist/bin/chunk-xkfrqqcs.js +1 -0
- package/dist/bin/chunk-y1h63vpm.js +1 -0
- package/dist/bin/chunk-zdt2rjk6.js +1 -0
- package/dist/bin/chunk-zh2d4704.js +1 -0
- package/dist/bin/chunk-zpe64t4r.js +1 -0
- package/dist/bin/cli.js +435 -444
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/{chunk-rr1yaj55.js → chunk-13qjvbqh.js} +1 -1
- package/dist/chunk-152he7m3.js +92 -0
- package/dist/chunk-1qdne0bf.js +1 -0
- package/dist/chunk-3mgj3hrh.js +5 -0
- package/dist/chunk-6kpbveb8.js +5 -0
- package/dist/chunk-73ztr55z.js +2 -0
- package/dist/{chunk-y1dh3znq.js → chunk-86ss83s2.js} +52 -52
- package/dist/chunk-a84gmpyh.js +1 -0
- package/dist/chunk-aj025v2s.js +4 -0
- package/dist/chunk-by2bwzk6.js +141 -0
- package/dist/chunk-h42zck7h.js +60 -0
- package/dist/chunk-hn40z11p.js +37 -0
- package/dist/chunk-hvwbgcs7.js +704 -0
- package/dist/{chunk-6xcbfs2r.js → chunk-jm5mg890.js} +111 -111
- package/dist/chunk-kqnpprnh.js +445 -0
- package/dist/chunk-m8fs0233.js +34 -0
- package/dist/chunk-mz0dk78z.js +6 -0
- package/dist/chunk-nms5q44e.js +1 -0
- package/dist/chunk-qm32ytbr.js +1 -0
- package/dist/chunk-t0xgmhd6.js +114 -0
- package/dist/chunk-t3t9ymec.js +1 -0
- package/dist/chunk-tz9myq9a.js +2 -0
- package/dist/chunk-wavjkdb8.js +2 -0
- package/dist/chunk-x3hay61c.js +44 -0
- package/dist/chunk-xcj8zfmg.js +2 -0
- package/dist/chunk-y2v22hkv.js +1 -0
- package/dist/chunk-y4xkj2f1.js +50 -0
- package/dist/deploy/index.js +1 -1
- package/dist/dns/index.js +1 -1
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/shared/deploy-script.d.ts +46 -0
- package/dist/index.js +90 -90
- package/dist/protection/index.js +1 -1
- package/dist/push/index.js +1 -1
- package/dist/spend/index.js +1 -1
- package/dist/ui/404.html +2 -2
- package/dist/ui/_stx/{router.fa5bc4dc.js → router.229f89ab.js} +1 -1
- package/dist/ui/_stx/runtime.dbee66d1.js +1 -0
- package/dist/ui/accept-invitation.html +2 -2
- package/dist/ui/access-denied.html +1 -1
- package/dist/ui/account/automation.html +6 -6
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +6 -6
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +80 -80
- package/dist/ui/data/services.html +77 -77
- package/dist/ui/data/volumes.html +50 -50
- package/dist/ui/index.html +50 -50
- package/dist/ui/infrastructure/topology.html +118 -118
- package/dist/ui/integrations.html +1 -1
- package/dist/ui/operations/alerts.html +47 -47
- package/dist/ui/operations/configuration.html +6 -6
- package/dist/ui/operations/jobs.html +75 -75
- package/dist/ui/operations/maintenance.html +6 -6
- package/dist/ui/operations/observability.html +82 -82
- package/dist/ui/operations/previews.html +6 -6
- package/dist/ui/operations/queue.html +6 -6
- package/dist/ui/operations/regions.html +6 -6
- package/dist/ui/operations/releases.html +6 -6
- package/dist/ui/operations/spend.html +54 -54
- package/dist/ui/operations/workloads.html +104 -104
- package/dist/ui/security.html +2 -2
- package/dist/ui/server/actions.html +56 -56
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +6 -6
- package/dist/ui/server/database.html +106 -106
- package/dist/ui/server/deployments.html +50 -50
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +75 -75
- package/dist/ui/server/fleet.html +34 -34
- package/dist/ui/server/logs.html +24 -24
- package/dist/ui/server/metrics.html +112 -112
- package/dist/ui/server/security.html +1 -1
- package/dist/ui/server/services.html +27 -27
- package/dist/ui/server/sites.html +120 -120
- package/dist/ui/server/ssh-keys.html +52 -52
- package/dist/ui/server/team.html +144 -144
- package/dist/ui/server/terminal.html +16 -16
- package/dist/ui/serverless/alarms.html +52 -52
- package/dist/ui/serverless/assets.html +28 -28
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +36 -36
- package/dist/ui/serverless/deployments.html +28 -28
- package/dist/ui/serverless/firewall.html +2 -2
- package/dist/ui/serverless/functions.html +39 -39
- package/dist/ui/serverless/logs.html +24 -24
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +48 -48
- package/dist/ui/serverless/secrets.html +52 -52
- package/dist/ui/serverless/traces.html +6 -6
- package/dist/ui/serverless.html +54 -54
- package/dist/ui-src/src/charts.ts +4644 -16118
- package/dist/ui-src/src/topology.ts +2 -2
- package/package.json +6 -6
- package/dist/bin/chunk-0rtn6q5x.js +0 -3
- package/dist/bin/chunk-258ehp9s.js +0 -1
- package/dist/bin/chunk-2yctv06c.js +0 -1
- package/dist/bin/chunk-3276rveh.js +0 -37
- package/dist/bin/chunk-3m665jwp.js +0 -70
- package/dist/bin/chunk-3s2p9vxj.js +0 -1
- package/dist/bin/chunk-4esma5m9.js +0 -1
- package/dist/bin/chunk-4n0j3n3b.js +0 -2
- package/dist/bin/chunk-54bqchag.js +0 -92
- package/dist/bin/chunk-5zagqd20.js +0 -1
- package/dist/bin/chunk-7hw2js5h.js +0 -512
- package/dist/bin/chunk-8h1qr6x4.js +0 -50
- package/dist/bin/chunk-a1dd6sby.js +0 -1
- package/dist/bin/chunk-a4dw35gs.js +0 -1
- package/dist/bin/chunk-a9d55ker.js +0 -1
- package/dist/bin/chunk-awa1qade.js +0 -9
- package/dist/bin/chunk-b6by94pk.js +0 -2
- package/dist/bin/chunk-c8sypnbe.js +0 -2
- package/dist/bin/chunk-cx4e3d4w.js +0 -1
- package/dist/bin/chunk-d5a3vheh.js +0 -2
- package/dist/bin/chunk-e1fym2bd.js +0 -1
- package/dist/bin/chunk-ej4h0q2y.js +0 -1
- package/dist/bin/chunk-ett305ym.js +0 -4
- package/dist/bin/chunk-f11xf3n6.js +0 -2
- package/dist/bin/chunk-fq7ktvgy.js +0 -3
- package/dist/bin/chunk-fyq4th2m.js +0 -1
- package/dist/bin/chunk-g67qr8yf.js +0 -1
- package/dist/bin/chunk-gc82cx4h.js +0 -1
- package/dist/bin/chunk-hchtvpr9.js +0 -1
- package/dist/bin/chunk-hpe4jjce.js +0 -1
- package/dist/bin/chunk-k5vprsef.js +0 -6
- package/dist/bin/chunk-m22krd4z.js +0 -3
- package/dist/bin/chunk-mkppcwz8.js +0 -1
- package/dist/bin/chunk-mpjg0kc7.js +0 -2
- package/dist/bin/chunk-mrm4m4dk.js +0 -2
- package/dist/bin/chunk-nff46rxd.js +0 -1
- package/dist/bin/chunk-np1z3bgt.js +0 -1
- package/dist/bin/chunk-nskxkk6r.js +0 -1
- package/dist/bin/chunk-pez932b1.js +0 -111
- package/dist/bin/chunk-qsdf5kzk.js +0 -2
- package/dist/bin/chunk-r61qmhv1.js +0 -2
- package/dist/bin/chunk-r6gdcz5c.js +0 -1
- package/dist/bin/chunk-satwnr42.js +0 -2
- package/dist/bin/chunk-smbycpt5.js +0 -44
- package/dist/bin/chunk-sn7e0sn7.js +0 -2
- package/dist/bin/chunk-ss574pka.js +0 -1
- package/dist/bin/chunk-tj0xb2d8.js +0 -585
- package/dist/bin/chunk-v3rzf9d0.js +0 -141
- package/dist/bin/chunk-wnpma6t3.js +0 -34
- package/dist/bin/chunk-xan0e052.js +0 -5
- package/dist/bin/chunk-xbk2y43r.js +0 -60
- package/dist/bin/chunk-xjp3v95e.js +0 -6
- package/dist/bin/chunk-xyt490vp.js +0 -6
- package/dist/bin/chunk-yn9r02gy.js +0 -1
- package/dist/bin/chunk-zhkhn9cc.js +0 -1
- package/dist/chunk-0zf72ngj.js +0 -1
- package/dist/chunk-2hpjte1d.js +0 -704
- package/dist/chunk-4m6gwhwr.js +0 -5
- package/dist/chunk-5m29dhke.js +0 -34
- package/dist/chunk-6fzeemcs.js +0 -114
- package/dist/chunk-bpnhqb70.js +0 -6
- package/dist/chunk-ead1nkbr.js +0 -60
- package/dist/chunk-fea461tj.js +0 -141
- package/dist/chunk-fvjczc73.js +0 -1
- package/dist/chunk-gearw6rk.js +0 -4
- package/dist/chunk-j60hesb3.js +0 -2
- package/dist/chunk-pmgtmt3d.js +0 -1
- package/dist/chunk-prf2pkvq.js +0 -5
- package/dist/chunk-q0wffgw5.js +0 -37
- package/dist/chunk-qcemnt35.js +0 -50
- package/dist/chunk-qvbwsaay.js +0 -1
- package/dist/chunk-r2pbqcnz.js +0 -2
- package/dist/chunk-r6110zv2.js +0 -1
- package/dist/chunk-wcrj06cg.js +0 -44
- package/dist/chunk-wte9mh18.js +0 -92
- package/dist/chunk-y6e86wjs.js +0 -445
- package/dist/chunk-y8b7ht4v.js +0 -1
- package/dist/chunk-yf487g6e.js +0 -2
- package/dist/chunk-zmmc9j5f.js +0 -2
- package/dist/ui/_stx/runtime.c696d17a.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="
|
|
2
|
-
function
|
|
1
|
+
<!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mt97hddjthae8y"><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 · Environment & secrets</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-scoped>
|
|
2
|
+
function __stx_setup_1787695061130_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, refresh, registerStoresClient, setRouteParams, state, untrack, useAsync, useClickOutside, useColorMode, useCookie, useCounter, useDark, useDebounce, useDebouncedValue, useEventListener, useFetch, useFocus, useHead, useId, useInterval, useLocalStorage, useMediaQuery, useMutation, useOptimistic, usePreferredContrast, usePreferredDark, usePreferredLight, usePreferredReducedMotion, useQuery, useReactiveProp, useRef, useRoute, useRouteParam, useRouteParams, useScrollLock, useSearchParams, useSeoMeta, useSessionStorage, useSlots, useStore, useThrottle, useTimeout, useToggle, useWebSocket, watch, watchEffect, watchMultiple, withDefaults } = window.stx;
|
|
4
4
|
|
|
5
5
|
const entries = state([]);
|
|
@@ -266,9 +266,9 @@ onMount(() => {
|
|
|
266
266
|
|
|
267
267
|
return { entries, effectiveEntries, scopeProject, environments, resources, functions, previews, warnings, configurationHash, tab, scopeType, scopeId, search, effective, selected, notice, error, busy, plan, editorOpen, importOpen, dotenvSource, secretKeys, currentEnv, endpoint, api, scopeContext, chooseDefault, changeScope, load, shown, selectTab, toggle, allSelected, when, scopeLabel, formData, previewChange, save, reveal, removeEntry, bulkDelete, transfer, importDotenv, exportVariables, searchTimer, searchChanged };
|
|
268
268
|
}
|
|
269
|
-
window.__stx_latestSetup=
|
|
270
|
-
if(window.stx)window.stx._latestSetup=
|
|
271
|
-
</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="
|
|
269
|
+
window.__stx_latestSetup=__stx_setup_1787695061130_4;
|
|
270
|
+
if(window.stx)window.stx._latestSetup=__stx_setup_1787695061130_4;
|
|
271
|
+
</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_1787695061130_4"><a data-stx-scope="stx_scope_nav_6" 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="active" href="/operations/configuration?env=production">Environment & secrets</a><a class="" href="/data/backups?env=production">Backups & 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">
|
|
272
272
|
(function() {
|
|
273
273
|
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;
|
|
274
274
|
var __destroyHooks = [];
|
|
@@ -619,6 +619,6 @@ if(window.stx)window.stx._latestSetup=__stx_setup_1787597620482_1;
|
|
|
619
619
|
|
|
620
620
|
|
|
621
621
|
try { if (typeof __stxScopeRenames !== 'undefined' && __stxScopeRenames) { for (var __stxRK in __stxScopeRenames) __scopeRegistration[__stxRK] = __stxScopeRenames[__stxRK]; } } catch (e) { /* no renames */ }
|
|
622
|
-
window.stx._scopes['
|
|
622
|
+
window.stx._scopes['stx_scope_nav_6'] = __scopeRegistration;
|
|
623
623
|
})();
|
|
624
624
|
</script> <main class="configuration-wrap wrap" id="main-content"><div class="crumbs">Operations <span class="sep">/</span> Environment & secrets</div><header class="page"><div><h1>Environment & secrets</h1><p>Manage inherited runtime configuration across project, environment, service, and preview scopes from one deploy-safe control plane.</p></div><div class="header-actions"><button class="btn ghost" @click="importOpen.set(!importOpen())">Import .env</button><button class="btn ghost" @click="exportVariables()">Export variables</button><button class="btn" @click="editorOpen.set(!editorOpen())" x-cloak>New {{ tab() }}</button></div></header><p class="notice" role="status" @show="!!notice()" x-cloak>{{ notice() }}</p><p class="bad notice" role="alert" @show="!!error()" x-cloak>{{ error() }}</p><section class="panel scope-bar" aria-label="Configuration scope"><div><span class="eyebrow">Scope</span><div class="segmented"><button :class="{active:scopeType()==='project'}" @click="changeScope('project')">Project</button><button :class="{active:scopeType()==='environment'}" @click="changeScope('environment')">Environment</button><button :class="{active:scopeType()==='service'}" @click="changeScope('service')">Service</button><button :class="{active:scopeType()==='function'}" @click="changeScope('function')">Function</button><button :class="{active:scopeType()==='preview'}" @click="changeScope('preview')">Preview</button></div></div><label @show="scopeType()==='project'" x-cloak><span>Target</span><select :value="scopeId()" @change="scopeId.set($event.currentTarget.value);selected.set([]);load()"><option :value="scopeProject()?.id">{{ scopeProject()?.name || 'Project' }}</option></select></label><label @show="scopeType()==='environment'" x-cloak><span>Target environment</span><select :value="scopeId()" @change="scopeId.set($event.currentTarget.value);selected.set([]);load()"><template :for="item in environments()"><option :value="item.id">{{ item.name || item.slug }}</option></template></select></label><label @show="scopeType()==='service'" x-cloak><span>Target service</span><select :value="scopeId()" @change="scopeId.set($event.currentTarget.value);selected.set([]);load()"><template :for="item in resources()"><option :value="item.id">{{ item.name || item.slug }}</option></template></select></label><label @show="scopeType()==='function'" x-cloak><span>Target function</span><select :value="scopeId()" @change="scopeId.set($event.currentTarget.value);selected.set([]);load()"><template :for="item in functions()"><option :value="item.id">{{ item.name || item.slug }}</option></template></select></label><label @show="scopeType()==='preview'" x-cloak><span>Target preview</span><select :value="scopeId()" @change="scopeId.set($event.currentTarget.value);selected.set([]);load()"><template :for="item in previews()"><option :value="item.id">{{ item.name }} · {{ item.status }}</option></template></select></label><div class="scope-health" x-cloak><span class="pill" :class="warnings().length?'warn':'ok'" x-cloak>{{ warnings().length ? warnings().length+' warning(s)' : 'references healthy' }}</span><code :title="configurationHash()" x-cloak>{{ configurationHash().slice(0,18) || 'not resolved' }}</code></div></section><section class="import-panel panel" @show="importOpen()" x-cloak><div><h2>Import dotenv</h2><p class="note">Paste or upload content. Conflicting duplicates stop the import; the preview and audit trail contain key names only.</p></div><form @submit="importDotenv($event)"><label>Dotenv content<textarea required rows="8" class="mono" :value="dotenvSource()" @input="dotenvSource.set($event.currentTarget.value)" placeholder="PUBLIC_URL=https://example.com DATABASE_URL=..."></textarea></label><label>Secret keys <input :value="secretKeys()" @input="secretKeys.set($event.currentTarget.value)" placeholder="DATABASE_URL, API_TOKEN"><span>Comma-separated. All other keys are plaintext variables and may be exported.</span></label><button class="btn" :disabled="busy()">Validate & import</button></form></section><section class="editor-panel panel" @show="editorOpen()" x-cloak><form @submit="save($event)"><div x-cloak><h2 x-cloak>Set {{ tab() }}</h2><p class="note">Existing production values require typed confirmation. Secret values are write-only.</p></div><label>Key<input name="key" required pattern="[A-Za-z_][A-Za-z0-9_]*" placeholder="DATABASE_URL" autocomplete="off"></label><label @show="tab()==='secret'" x-cloak>Backend<select name="backend"><option value="local_encrypted">Encrypted local/box</option><option value="aws_secrets_manager">AWS Secrets Manager</option><option value="aws_ssm">AWS SSM Parameter Store</option><option value="external">External reference</option></select></label><label class="wide" x-cloak>{{ tab()==='secret'?'Value (write-only)':'Value' }}<textarea name="value" rows="3" :type="tab()==='secret'?'password':'text'" placeholder="Value, including multiline content"></textarea></label><label class="wide" @show="tab()==='secret'" x-cloak>External reference<input name="reference" placeholder="vault://team/app/token"><span>Used only when External reference is selected.</span></label><label class="check"><input name="required" type="checkbox"> Required at deployment</label><div class="actions"><button class="btn ghost" type="button" @click="previewChange($event.currentTarget.form)">Preview key diff</button><button class="btn" type="submit" :disabled="busy()" x-cloak>Save {{ tab() }}</button></div></form><div class="change-plan" @show="!!plan()" x-cloak><h3>Change preview</h3><p x-cloak><b x-cloak>{{ plan()?.added.length || 0 }}</b> add · <b x-cloak>{{ plan()?.changed.length || 0 }}</b> change · <b x-cloak>{{ plan()?.removed.length || 0 }}</b> remove · <b x-cloak>{{ plan()?.affectedResourceIds.length || 0 }}</b> affected services</p><code x-cloak>{{ [...(plan()?.added||[]),...(plan()?.changed||[]),...(plan()?.removed||[])].join(', ') }}</code></div></section><nav class="tabs" aria-label="Configuration kind" x-cloak><button :class="{active:tab()==='variable'}" @click="selectTab('variable')" x-cloak>Variables <span x-cloak>{{ entries().filter(item=>item.kind==='variable').length }}</span></button><button :class="{active:tab()==='secret'}" @click="selectTab('secret')" x-cloak>Secrets <span x-cloak>{{ entries().filter(item=>item.kind==='secret').length }}</span></button></nav><section class="panel table-tools"><input type="search" placeholder="Search keys" aria-label="Search configuration" @input="searchChanged($event.currentTarget.value)"><label class="check"><input type="checkbox" :checked="effective()" @change="effective.set($event.currentTarget.checked)"> Show inherited effective values</label><span class="spacer"></span><button class="btn danger sm" @show="selected().length" @click="bulkDelete()" x-cloak>Delete {{ selected().length }} selected</button><button class="btn ghost sm" @click="load()">Refresh</button></section><section class="config-table panel"><table><thead><tr><th scope="col"><input type="checkbox" aria-label="Select all" @change="allSelected()"></th><th scope="col">Key</th><th scope="col">Scope & precedence</th><th scope="col" x-cloak>{{ tab()==='secret'?'Backend':'Value' }}</th><th scope="col">Use & rotation</th><th scope="col" class="table-actions">Actions</th></tr></thead><tbody><template :for="item in shown()"><tr><td><input type="checkbox" :checked="selected().includes(item.id)" :disabled="item.inherited" :aria-label="'Select '+item.key" @change="toggle(item.id)"></td><td x-cloak><div class="key-cell" x-cloak><code x-cloak>{{ item.key }}</code><span class="pill" @show="item.required" x-cloak>required</span><span class="pill warn" @show="item.inherited" x-cloak>inherited</span><span class="pill" @show="item.overridden" x-cloak>overrides</span></div></td><td x-cloak><b x-cloak>{{ scopeLabel(item) }}</b><small x-cloak>{{ item.scope.type }} · v{{ item.version }}</small></td><td x-cloak><div @show="item.kind==='secret'" x-cloak><b x-cloak>{{ item.backend || 'restricted' }}</b><small x-cloak>{{ item.backendVersion ? 'backend v'+item.backendVersion : 'metadata hidden' }}</small><code @show="!!item.reference" x-cloak>{{ item.reference }}</code></div><code class="value-preview" @show="item.kind==='variable'" x-cloak>{{ item.value }}</code></td><td x-cloak><b x-cloak>{{ item.rotatedAt ? 'Rotated '+when(item.rotatedAt) : 'Not rotated' }}</b><small x-cloak>Last used {{ when(item.lastUsedAt) }}</small><small x-cloak>Updated {{ when(item.updatedAt) }}</small></td><td class="table-actions"><div class="row-actions"><button class="btn ghost sm" @show="item.kind==='secret'" @click="reveal(item)" x-cloak>Reveal & copy</button><button class="btn ghost sm" @show="!item.inherited" @click="transfer(item)" x-cloak>Move / copy</button><button class="btn danger sm" @show="!item.inherited" @click="removeEntry(item)" x-cloak>Delete</button></div></td></tr></template><tr @show="!shown().length" x-cloak><td colspan="6" x-cloak><div class="compact empty" x-cloak><strong x-cloak>No {{ tab() }}s at this scope</strong><span>Create one here, import dotenv, or enable the inherited view.</span></div></td></tr></tbody></table></section><aside class="warning-list" @show="warnings().length" x-cloak><h2>Deployment warnings</h2><template :for="warning in warnings()"><p class="notice warn" x-cloak><code x-cloak>{{ warning.key || 'scope' }}</code> {{ warning.message }}</p></template></aside></main><style> .configuration-wrap{max-width:1500px}.scope-bar{display:grid;grid-template-columns:1.4fr 1fr auto;gap:24px;align-items:end}.eyebrow,.scope-bar label span{display:block;color:var(--txt3);font-size:12px;margin-bottom:8px;text-transform:uppercase;letter-spacing:.08em}.segmented{display:flex;gap:4px;background:var(--bg);padding:4px;border-radius:8px;width:max-content}.segmented button{border:0;background:transparent;color:var(--txt3);padding:8px 12px;border-radius:6px}.segmented button.active{background:var(--panel2);color:var(--txt)}.scope-bar select{min-width:240px;background:var(--bg)!important;color:var(--txt)!important;border:1px solid var(--line)!important}.scope-health{display:flex;flex-direction:column;align-items:flex-end;gap:8px}.import-panel,.editor-panel{margin-top:18px;padding:22px;display:grid;grid-template-columns:minmax(240px,.7fr) minmax(420px,1.3fr);gap:28px}.import-panel form,.editor-panel form{display:grid;grid-template-columns:1fr 1fr;gap:14px}.import-panel label:first-child,.wide{grid-column:1/-1}.editor-panel>form>div:first-child{grid-column:1/-1}.editor-panel label,.import-panel label{display:flex;flex-direction:column;gap:7px}.editor-panel label span,.import-panel label span{color:var(--txt3);font-size:12px}.change-plan{border-left:1px solid var(--line);padding-left:24px}.tabs{display:flex;gap:4px;margin-top:22px;border-bottom:1px solid var(--line)}.tabs button{border:0;background:transparent;color:var(--txt3);padding:12px 16px;border-bottom:2px solid transparent}.tabs button.active{color:var(--txt);border-bottom-color:var(--accent)}.tabs button span{opacity:.6}.table-tools{display:flex;gap:16px;align-items:center;padding:12px 16px;border-radius:0}.table-tools input[type=search]{max-width:360px}.spacer{flex:1}.config-table{overflow:auto;border-top-left-radius:0;border-top-right-radius:0}.config-table table{min-width:1100px}.config-table td{vertical-align:top}.config-table td:nth-child(3),.config-table td:nth-child(4),.config-table td:nth-child(5){display:table-cell}.config-table td b,.config-table td small,.config-table td code{display:block;margin-bottom:5px}.key-cell{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.key-cell code{font-weight:700;margin:0}.value-preview{max-width:320px;white-space:pre-wrap;overflow-wrap:anywhere}.row-actions{flex-wrap:wrap}.warning-list{margin-top:20px}.check{display:flex!important;flex-direction:row!important;align-items:center;gap:8px!important}.actions{display:flex;gap:10px;align-items:end}@media(max-width:900px){.scope-bar,.import-panel,.editor-panel{grid-template-columns:1fr}.scope-health{align-items:flex-start}.import-panel form,.editor-panel form{grid-template-columns:1fr}.config-table{overflow-x:auto}} </style></body></html>
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="
|
|
2
|
-
function
|
|
1
|
+
<!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mt97hddjthae8y"><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 · Workers & schedules</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_1787695062226_8() {
|
|
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
|
-
var workers = undefined;
|
|
6
|
-
var when = undefined;
|
|
7
|
-
var tone = undefined;
|
|
8
|
-
var tab = undefined;
|
|
9
|
-
var statusFilter = undefined;
|
|
10
|
-
var showHistory = undefined;
|
|
11
|
-
var setPreset = undefined;
|
|
12
|
-
var selectedJob = undefined;
|
|
13
|
-
var search = undefined;
|
|
14
|
-
var restartWorker = undefined;
|
|
15
|
-
var refresh = undefined;
|
|
16
|
-
var reconcile = undefined;
|
|
17
|
-
var queuePreview = undefined;
|
|
18
|
-
var providerFilter = undefined;
|
|
19
|
-
var previewTimer = undefined;
|
|
20
|
-
var previewForm = undefined;
|
|
21
|
-
var preview = undefined;
|
|
22
|
-
var pollingState = undefined;
|
|
23
|
-
var pollingError = undefined;
|
|
24
|
-
var operations = undefined;
|
|
25
|
-
var notice = undefined;
|
|
26
|
-
var mode = undefined;
|
|
27
|
-
var load = undefined;
|
|
28
|
-
var lastUpdatedAt = undefined;
|
|
29
|
-
var jobs = undefined;
|
|
30
|
-
var jobAction = undefined;
|
|
31
|
-
var history = undefined;
|
|
32
|
-
var formBody = undefined;
|
|
33
|
-
var filteredJobs = undefined;
|
|
34
|
-
var editJob = undefined;
|
|
35
|
-
var duration = undefined;
|
|
36
|
-
var createJob = undefined;
|
|
37
|
-
var busy = undefined;
|
|
38
|
-
var api = undefined;
|
|
39
5
|
var actionError = undefined;
|
|
6
|
+
var api = undefined;
|
|
7
|
+
var busy = undefined;
|
|
8
|
+
var createJob = undefined;
|
|
9
|
+
var duration = undefined;
|
|
10
|
+
var editJob = undefined;
|
|
11
|
+
var filteredJobs = undefined;
|
|
12
|
+
var formBody = undefined;
|
|
13
|
+
var history = undefined;
|
|
14
|
+
var jobAction = undefined;
|
|
15
|
+
var jobs = undefined;
|
|
16
|
+
var lastUpdatedAt = undefined;
|
|
17
|
+
var load = undefined;
|
|
18
|
+
var mode = undefined;
|
|
19
|
+
var notice = undefined;
|
|
20
|
+
var operations = undefined;
|
|
21
|
+
var pollingError = undefined;
|
|
22
|
+
var pollingState = undefined;
|
|
23
|
+
var preview = undefined;
|
|
24
|
+
var previewForm = undefined;
|
|
25
|
+
var previewTimer = undefined;
|
|
26
|
+
var providerFilter = undefined;
|
|
27
|
+
var queuePreview = undefined;
|
|
28
|
+
var reconcile = undefined;
|
|
29
|
+
var refresh = undefined;
|
|
30
|
+
var restartWorker = undefined;
|
|
31
|
+
var search = undefined;
|
|
32
|
+
var selectedJob = undefined;
|
|
33
|
+
var setPreset = undefined;
|
|
34
|
+
var showHistory = undefined;
|
|
35
|
+
var statusFilter = undefined;
|
|
36
|
+
var tab = undefined;
|
|
37
|
+
var tone = undefined;
|
|
38
|
+
var when = undefined;
|
|
39
|
+
var workers = undefined;
|
|
40
40
|
var __stxBundle_da87383c4b96 = (function() {
|
|
41
41
|
|
|
42
42
|
function servedWithoutApi(error) {
|
|
@@ -276,48 +276,48 @@ async function restartWorker(item) {
|
|
|
276
276
|
actionError.set(error.message);
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
-
return { "
|
|
279
|
+
return { "actionError": actionError, "api": api, "busy": busy, "createJob": createJob, "duration": duration, "editJob": editJob, "filteredJobs": filteredJobs, "formBody": formBody, "history": history, "jobAction": jobAction, "jobs": jobs, "lastUpdatedAt": lastUpdatedAt, "load": load, "mode": mode, "notice": notice, "operations": operations, "pollingError": pollingError, "pollingState": pollingState, "preview": preview, "previewForm": previewForm, "previewTimer": previewTimer, "providerFilter": providerFilter, "queuePreview": queuePreview, "reconcile": reconcile, "refresh": refresh, "restartWorker": restartWorker, "search": search, "selectedJob": selectedJob, "setPreset": setPreset, "showHistory": showHistory, "statusFilter": statusFilter, "tab": tab, "tone": tone, "when": when, "workers": workers };
|
|
280
280
|
})();
|
|
281
|
-
workers = __stxBundle_da87383c4b96["workers"];
|
|
282
|
-
when = __stxBundle_da87383c4b96["when"];
|
|
283
|
-
tone = __stxBundle_da87383c4b96["tone"];
|
|
284
|
-
tab = __stxBundle_da87383c4b96["tab"];
|
|
285
|
-
statusFilter = __stxBundle_da87383c4b96["statusFilter"];
|
|
286
|
-
showHistory = __stxBundle_da87383c4b96["showHistory"];
|
|
287
|
-
setPreset = __stxBundle_da87383c4b96["setPreset"];
|
|
288
|
-
selectedJob = __stxBundle_da87383c4b96["selectedJob"];
|
|
289
|
-
search = __stxBundle_da87383c4b96["search"];
|
|
290
|
-
restartWorker = __stxBundle_da87383c4b96["restartWorker"];
|
|
291
|
-
refresh = __stxBundle_da87383c4b96["refresh"];
|
|
292
|
-
reconcile = __stxBundle_da87383c4b96["reconcile"];
|
|
293
|
-
queuePreview = __stxBundle_da87383c4b96["queuePreview"];
|
|
294
|
-
providerFilter = __stxBundle_da87383c4b96["providerFilter"];
|
|
295
|
-
previewTimer = __stxBundle_da87383c4b96["previewTimer"];
|
|
296
|
-
previewForm = __stxBundle_da87383c4b96["previewForm"];
|
|
297
|
-
preview = __stxBundle_da87383c4b96["preview"];
|
|
298
|
-
pollingState = __stxBundle_da87383c4b96["pollingState"];
|
|
299
|
-
pollingError = __stxBundle_da87383c4b96["pollingError"];
|
|
300
|
-
operations = __stxBundle_da87383c4b96["operations"];
|
|
301
|
-
notice = __stxBundle_da87383c4b96["notice"];
|
|
302
|
-
mode = __stxBundle_da87383c4b96["mode"];
|
|
303
|
-
load = __stxBundle_da87383c4b96["load"];
|
|
304
|
-
lastUpdatedAt = __stxBundle_da87383c4b96["lastUpdatedAt"];
|
|
305
|
-
jobs = __stxBundle_da87383c4b96["jobs"];
|
|
306
|
-
jobAction = __stxBundle_da87383c4b96["jobAction"];
|
|
307
|
-
history = __stxBundle_da87383c4b96["history"];
|
|
308
|
-
formBody = __stxBundle_da87383c4b96["formBody"];
|
|
309
|
-
filteredJobs = __stxBundle_da87383c4b96["filteredJobs"];
|
|
310
|
-
editJob = __stxBundle_da87383c4b96["editJob"];
|
|
311
|
-
duration = __stxBundle_da87383c4b96["duration"];
|
|
312
|
-
createJob = __stxBundle_da87383c4b96["createJob"];
|
|
313
|
-
busy = __stxBundle_da87383c4b96["busy"];
|
|
314
|
-
api = __stxBundle_da87383c4b96["api"];
|
|
315
281
|
actionError = __stxBundle_da87383c4b96["actionError"];
|
|
316
|
-
|
|
282
|
+
api = __stxBundle_da87383c4b96["api"];
|
|
283
|
+
busy = __stxBundle_da87383c4b96["busy"];
|
|
284
|
+
createJob = __stxBundle_da87383c4b96["createJob"];
|
|
285
|
+
duration = __stxBundle_da87383c4b96["duration"];
|
|
286
|
+
editJob = __stxBundle_da87383c4b96["editJob"];
|
|
287
|
+
filteredJobs = __stxBundle_da87383c4b96["filteredJobs"];
|
|
288
|
+
formBody = __stxBundle_da87383c4b96["formBody"];
|
|
289
|
+
history = __stxBundle_da87383c4b96["history"];
|
|
290
|
+
jobAction = __stxBundle_da87383c4b96["jobAction"];
|
|
291
|
+
jobs = __stxBundle_da87383c4b96["jobs"];
|
|
292
|
+
lastUpdatedAt = __stxBundle_da87383c4b96["lastUpdatedAt"];
|
|
293
|
+
load = __stxBundle_da87383c4b96["load"];
|
|
294
|
+
mode = __stxBundle_da87383c4b96["mode"];
|
|
295
|
+
notice = __stxBundle_da87383c4b96["notice"];
|
|
296
|
+
operations = __stxBundle_da87383c4b96["operations"];
|
|
297
|
+
pollingError = __stxBundle_da87383c4b96["pollingError"];
|
|
298
|
+
pollingState = __stxBundle_da87383c4b96["pollingState"];
|
|
299
|
+
preview = __stxBundle_da87383c4b96["preview"];
|
|
300
|
+
previewForm = __stxBundle_da87383c4b96["previewForm"];
|
|
301
|
+
previewTimer = __stxBundle_da87383c4b96["previewTimer"];
|
|
302
|
+
providerFilter = __stxBundle_da87383c4b96["providerFilter"];
|
|
303
|
+
queuePreview = __stxBundle_da87383c4b96["queuePreview"];
|
|
304
|
+
reconcile = __stxBundle_da87383c4b96["reconcile"];
|
|
305
|
+
refresh = __stxBundle_da87383c4b96["refresh"];
|
|
306
|
+
restartWorker = __stxBundle_da87383c4b96["restartWorker"];
|
|
307
|
+
search = __stxBundle_da87383c4b96["search"];
|
|
308
|
+
selectedJob = __stxBundle_da87383c4b96["selectedJob"];
|
|
309
|
+
setPreset = __stxBundle_da87383c4b96["setPreset"];
|
|
310
|
+
showHistory = __stxBundle_da87383c4b96["showHistory"];
|
|
311
|
+
statusFilter = __stxBundle_da87383c4b96["statusFilter"];
|
|
312
|
+
tab = __stxBundle_da87383c4b96["tab"];
|
|
313
|
+
tone = __stxBundle_da87383c4b96["tone"];
|
|
314
|
+
when = __stxBundle_da87383c4b96["when"];
|
|
315
|
+
workers = __stxBundle_da87383c4b96["workers"];
|
|
316
|
+
return { actionError, api, busy, createJob, duration, editJob, filteredJobs, formBody, history, jobAction, jobs, lastUpdatedAt, load, mode, notice, operations, pollingError, pollingState, preview, previewForm, previewTimer, providerFilter, queuePreview, reconcile, refresh, restartWorker, search, selectedJob, setPreset, showHistory, statusFilter, tab, tone, when, workers, __stxBundle_da87383c4b96 };
|
|
317
317
|
}
|
|
318
|
-
window.__stx_latestSetup=
|
|
319
|
-
if(window.stx)window.stx._latestSetup=
|
|
320
|
-
</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="
|
|
318
|
+
window.__stx_latestSetup=__stx_setup_1787695062226_8;
|
|
319
|
+
if(window.stx)window.stx._latestSetup=__stx_setup_1787695062226_8;
|
|
320
|
+
</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_1787695062226_8"><a data-stx-scope="stx_scope_nav_11" 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="active" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment & secrets</a><a class="" href="/data/backups?env=production">Backups & 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">
|
|
321
321
|
(function() {
|
|
322
322
|
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;
|
|
323
323
|
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="
|
|
2
|
-
function
|
|
1
|
+
<!DOCTYPE html><html lang="en" data-theme="dark"><head><meta charset="UTF-8"><meta name="stx-build" content="mt97hddjthae8y"><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 · Maintenance & disaster 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-scoped>
|
|
2
|
+
function __stx_setup_1787695062347_15() {
|
|
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
|
const data = state({ manifests: [], windows: [], campaigns: [], cleanups: [], drills: [] }), tab = state("upgrades"), error = state(""), notice = state(""), busy = state(false);
|
|
@@ -60,9 +60,9 @@ function bytes(value) {
|
|
|
60
60
|
|
|
61
61
|
return { data, api, load, pollingState, pollingError, lastUpdatedAt, refresh, post, preview, cleanup, drill, runDrill, tone, bytes };
|
|
62
62
|
}
|
|
63
|
-
window.__stx_latestSetup=
|
|
64
|
-
if(window.stx)window.stx._latestSetup=
|
|
65
|
-
</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="
|
|
63
|
+
window.__stx_latestSetup=__stx_setup_1787695062347_15;
|
|
64
|
+
if(window.stx)window.stx._latestSetup=__stx_setup_1787695062347_15;
|
|
65
|
+
</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_1787695062347_15"><a data-stx-scope="stx_scope_nav_19" 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="active" 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 & secrets</a><a class="" href="/data/backups?env=production">Backups & 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">
|
|
66
66
|
(function() {
|
|
67
67
|
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;
|
|
68
68
|
var __destroyHooks = [];
|
|
@@ -413,6 +413,6 @@ if(window.stx)window.stx._latestSetup=__stx_setup_1787597622102_13;
|
|
|
413
413
|
|
|
414
414
|
|
|
415
415
|
try { if (typeof __stxScopeRenames !== 'undefined' && __stxScopeRenames) { for (var __stxRK in __stxScopeRenames) __scopeRegistration[__stxRK] = __stxScopeRenames[__stxRK]; } } catch (e) { /* no renames */ }
|
|
416
|
-
window.stx._scopes['
|
|
416
|
+
window.stx._scopes['stx_scope_nav_19'] = __scopeRegistration;
|
|
417
417
|
})();
|
|
418
418
|
</script> <main class="wrap" id="main-content"><div class="crumbs">Operations <span class="sep">/</span> Maintenance & DR</div><header class="page"><div><h1>Maintenance & disaster recovery</h1><p>Verified updates, approved windows, reversible rollout, dry-run cleanup, and isolated restore drills.</p></div><div class="actions" x-cloak><span class="pill" :class="pollingState()==='live'?'ok':'warn'" x-cloak>{{ pollingState() }}</span><small x-cloak>{{ lastUpdatedAt()?.toLocaleTimeString()||'connecting' }}</small></div></header><p class="notice" role="status" @show="!!notice()" x-cloak>{{ notice() }}</p><p class="bad notice" role="alert" @show="!!error()||!!pollingError()" x-cloak>{{ error()||pollingError() }}</p><nav class="tabs" aria-label="Maintenance areas"><button :class="tab()==='upgrades'?'active':''" @click="tab.set('upgrades')">Platform updates</button><button :class="tab()==='cleanup'?'active':''" @click="tab.set('cleanup')">Safe cleanup</button><button :class="tab()==='dr'?'active':''" @click="tab.set('dr')">Recovery drills</button></nav><section @show="tab()==='upgrades'" x-cloak><div class="panel safety"><b>Update trust chain</b><span>Ed25519 signature → schema and platform compatibility → verified backup → approved window → canary → health gate → rolling cohorts.</span></div><div class="grid"><section class="panel"><h2>Verified manifests</h2><template :for="item in data().manifests"><article class="item" x-cloak><span class="pill" :class="item.compatibility.compatible?'ok':'bad'" x-cloak>{{ item.compatibility.compatible?'compatible':'blocked' }}</span><b x-cloak>{{ item.version }}</b><small x-cloak>{{ item.channel }} · key {{ item.keyId }}</small><p x-cloak>{{ item.compatibility.reasons.join('; ')||'Signature and compatibility verified.' }}</p></article></template><p class="empty" @show="!data().manifests.length" x-cloak>Import signed manifests with the CLI or library; raw unsigned URLs are never offered here.</p></section><section class="panel"><h2>Staged campaigns</h2><template :for="item in data().campaigns"><article class="item" x-cloak><span class="pill" :class="tone(item.campaign.status)" x-cloak>{{ item.campaign.status }}</span><b x-cloak>{{ item.campaign.strategy }} from {{ item.campaign.fromVersion }}</b><small x-cloak>{{ item.campaign.currentStage||'not started' }} · backup {{ item.campaign.backupId }}</small><div class="target-row" x-cloak><template :for="target in item.targets"><span x-cloak>{{ target.target }} · {{ target.status }}</span></template></div></article></template><p class="empty" @show="!data().campaigns.length" x-cloak>No upgrade campaigns.</p></section></div></section><section @show="tab()==='cleanup'" x-cloak><div class="panel safety"><b>Nothing is deleted during discovery.</b><span>Each preview expires, has a digest over the exact candidates, and requires a count-and-kind confirmation.</span></div><form class="form panel" @submit="preview($event)"><label>Resource type<select name="kind"><option>releases</option><option>artifacts</option><option>operations</option><option>logs</option><option>previews</option><option>snapshots</option><option>orphaned_resources</option></select></label><label>Older than days<input name="olderThanDays" type="number" min="1" value="30"></label><button class="btn" type="submit" :disabled="busy()">Generate dry-run preview</button></form><div class="cards" x-cloak><template :for="plan in data().cleanups"><article class="panel" x-cloak><span class="pill" :class="tone(plan.status)" x-cloak>{{ plan.status }}</span><h2 x-cloak>{{ plan.kind }}</h2><p x-cloak>{{ plan.candidates.length }} candidates · {{ bytes(plan.estimatedBytes) }}</p><small x-cloak>expires {{ plan.expiresAt }} · digest {{ plan.candidateDigest.slice(0,12) }}</small><details><summary>Inspect candidates</summary><template :for="candidate in plan.candidates"><p class="row" x-cloak><span x-cloak>{{ candidate.label }}</span><b x-cloak>{{ bytes(candidate.bytes) }}</b></p></template></details><button class="btn danger sm" @show="plan.status==='preview'" @click="cleanup(plan)" x-cloak>Confirm exact candidate set</button></article></template></div></section><section @show="tab()==='dr'" x-cloak><div class="panel safety"><b>Drills never target production.</b><span>Only <code>isolated://</code> targets are accepted. RPO/RTO and health evidence are recorded, and cleanup runs even after failure.</span></div><form class="drill form panel" @submit="drill($event)"><label>Scenario<select name="scenario"><option>control_plane</option><option>database</option><option>volume</option><option>regional</option></select></label><label>Isolated target<input name="isolatedTarget" required value="isolated://drills/latest"></label><label>Recovery point<input name="recoveryPointId" placeholder="optional"></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="30"></label><button class="btn" type="submit">Plan isolated drill</button></form><div class="cards" x-cloak><template :for="item in data().drills"><article class="panel" x-cloak><span class="pill" :class="tone(item.status)" x-cloak>{{ item.status }}</span><h2 x-cloak>{{ item.scenario }}</h2><p x-cloak>{{ item.isolatedTarget }}</p><small x-cloak>objective {{ item.expectedRpoMinutes }}m RPO / {{ item.expectedRtoMinutes }}m RTO</small><p @show="item.measuredRpoMinutes!=null" x-cloak>measured {{ item.measuredRpoMinutes.toFixed(1) }}m RPO / {{ item.measuredRtoMinutes?.toFixed(1) }}m RTO · cleanup {{ item.cleanupVerified?'verified':'pending' }}</p><button class="btn sm" @show="item.status==='planned'" @click="runDrill(item.id)" x-cloak>Run drill</button></article></template></div></section></main><style>.actions,.target-row{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}.tabs{display:flex;gap:.5rem;margin:1rem 0;border-bottom:1px solid var(--border)}.tabs button{background:none;border:0;color:var(--muted);padding:.75rem}.tabs .active{color:var(--text);border-bottom:2px solid var(--accent)}.safety{display:grid;grid-template-columns:auto 1fr;gap:1rem;margin-bottom:1rem}.grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem}.item{display:grid;grid-template-columns:auto 1fr auto;gap:.5rem;align-items:center;border-bottom:1px solid var(--border);padding:.75rem 0}.item p,.target-row{grid-column:1/-1}.form{display:flex;gap:1rem;align-items:end;margin-bottom:1rem}.form label{display:grid;gap:.3rem}.drill{display:grid;grid-template-columns:repeat(5,1fr) auto}.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}.row{display:flex;justify-content:space-between;border-bottom:1px solid var(--border);padding:.4rem 0}.empty{color:var(--muted)}@media(max-width:900px){.grid,.cards{grid-template-columns:1fr}.drill{grid-template-columns:1fr 1fr}}@media(max-width:560px){.form,.drill{display:grid;grid-template-columns:1fr}.safety{grid-template-columns:1fr}}</style></body></html>
|