ws: migrate push stream to data streaming

- daemon: send full snapshot on connect; versions/tick now carry the
  full state of one subsystem (subsystem + data); no legacy
  updated/subsystems payloads; refresh_state and POST /status/refresh
  broadcast per-subsystem versions with data
- client: modelSet() patches models in place; onMessage/topic refresh
  retired; 3s initial-load fallback via new POST /api/status/refresh
- schema: lib/schema.py TypedDicts + hoover/schema.js defaults +
  docs/state-model.md as single source of truth for state shapes
- system: poll at 1s, volatile metrics registered, dashboard uses a
  dedicated system model (status model removed)
- firewall: refuse to strip both https and ssh from the default zone
  (409, force override via UI confirm); set_zone_services persists
  services to the declarative config; collector exposes default_zone
- UI: pages migrate to flat state shapes; post-mutation modelFetch
  refreshes removed (WS delta covers it)
- tests: ws snapshot/delta/broadcast, refresh-state, schema types,
  model-set/js ws handler and reconnect fallback
This commit is contained in:
2026-08-20 01:38:00 +00:00
parent 9c9f92ad04
commit 332d14e37d
45 changed files with 2819 additions and 496 deletions
+4 -4
View File
@@ -239,8 +239,8 @@ export function openBackendModal(state, backend) {
if (res.ok) {
toast(isEdit ? 'Backend updated' : 'Backend added', 'success');
closeModal();
await modelFetch('backends');
modelFetch('nginx');
await modelFetch('backends'); // not state-store-backed — explicit fetch
// No nginx modelFetch — daemon broadcasts nginx via WS delta.
} else {
toast(res.error || 'Failed', 'error');
}
@@ -290,7 +290,7 @@ export default definePage({
deleteKey=${name}
message=${'Remove backend ' + enc(name) + '?'}
success="Backend removed"
refresh=["backends", "nginx"]
onComplete=${() => modelFetch('backends')}
label="Delete" />`
}
</td>
@@ -303,7 +303,7 @@ export default definePage({
url: '/api/proxy/apply',
successMsg: 'Nginx applied & reloaded',
label: 'Apply',
refresh: ['backends', 'nginx'],
onSuccess: () => modelFetch('backends'),
}),
);