feat(nh3-svos): SVOS a737a06 refresh — app-terminal on its own mesh origin (svos-terminal.phasefinal.com), app-knowledge, app-postoffice units; quiesce hook covers the new units
This commit is contained in:
@@ -11,7 +11,8 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
SERVICES = ('svos-kernel.service', 'svos-interface.service')
|
SERVICES = ('svos-kernel.service', 'svos-interface.service', 'svos-terminal.service',
|
||||||
|
'svos-knowledge.service', 'svos-postoffice.service')
|
||||||
|
|
||||||
class Quiesce:
|
class Quiesce:
|
||||||
def __init__(self, directory, *, run=None):
|
def __init__(self, directory, *, run=None):
|
||||||
|
|||||||
@@ -10,3 +10,6 @@
|
|||||||
- Runs under `../fsfreeze-dispatch`, which qemu-ga calls via `/etc/qemu/qemu-ga.conf`. Without that config,
|
- Runs under `../fsfreeze-dispatch`, which qemu-ga calls via `/etc/qemu/qemu-ga.conf`. Without that config,
|
||||||
Debian's qemu-ga runs no hooks at all.
|
Debian's qemu-ga runs no hooks at all.
|
||||||
- If the voice service is ever enabled, add it to `SERVICES` before enabling it (svos-dev).
|
- If the voice service is ever enabled, add it to `SERVICES` before enabling it (svos-dev).
|
||||||
|
- 2026-10-07 (a737a06 refresh): `SERVICES` gained `svos-terminal`, `svos-knowledge` and `svos-postoffice` before
|
||||||
|
they were started. The hook restores only the units that were active at freeze, so a declared-but-stopped app
|
||||||
|
(postoffice until its bridge handle exists) is recorded as inactive and left stopped.
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ class QuiesceTests(unittest.TestCase):
|
|||||||
loader=importlib.machinery.SourceFileLoader('svos_quiesce',str(Path(__file__).with_name('50-svos')))
|
loader=importlib.machinery.SourceFileLoader('svos_quiesce',str(Path(__file__).with_name('50-svos')))
|
||||||
spec=importlib.util.spec_from_loader('svos_quiesce',loader)
|
spec=importlib.util.spec_from_loader('svos_quiesce',loader)
|
||||||
self.module=importlib.util.module_from_spec(spec);spec.loader.exec_module(self.module)
|
self.module=importlib.util.module_from_spec(spec);spec.loader.exec_module(self.module)
|
||||||
self.states={'svos-kernel.service':('active','success'),'svos-interface.service':('inactive','success')}
|
self.states={'svos-kernel.service':('active','success'),'svos-interface.service':('inactive','success'),
|
||||||
|
'svos-terminal.service':('inactive','success'),'svos-knowledge.service':('inactive','success'),'svos-postoffice.service':('inactive','success')}
|
||||||
self.calls=[];self.stop_fail=False;self.start_fail=False;self.dirty_stop=False
|
self.calls=[];self.stop_fail=False;self.start_fail=False;self.dirty_stop=False
|
||||||
def run(args,**kwargs):
|
def run(args,**kwargs):
|
||||||
self.calls.append(args)
|
self.calls.append(args)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# eshpfi configs/svos-apps/ (infra-ops, 2026-10-07, a737a06 refresh), modelled on svoperatingsystem
|
||||||
|
# deployment/nh3-svos/svos-interface.service. The credential is /etc/svos/knowledge.env (root 0600, SVOS_APP_CREDENTIAL),
|
||||||
|
# minted by enrollment on the private kernel listener. Listed in the qemu-ga quiesce hook (configs/qemu-ga/svos/50-svos).
|
||||||
|
[Unit]
|
||||||
|
Description=SVOS Knowledge-read app (app-knowledge, U14)
|
||||||
|
After=svos-kernel.service
|
||||||
|
Requires=svos-kernel.service
|
||||||
|
ConditionPathExists=/etc/svos/knowledge.env
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=svc-svos
|
||||||
|
Group=svc-svos
|
||||||
|
UMask=0077
|
||||||
|
WorkingDirectory=/var/lib/svos
|
||||||
|
EnvironmentFile=/etc/svos/knowledge.env
|
||||||
|
Environment=SVOS_KERNEL_URL=http://127.0.0.1:8400
|
||||||
|
Environment=SVOS_DATA_ROOT=/var/lib/svos
|
||||||
|
Environment=SVOS_APP_LISTEN=127.0.0.1:8405
|
||||||
|
ExecStart=/opt/svos/current/apps-env/bin/svos-knowledge
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=3
|
||||||
|
TimeoutStopSec=20
|
||||||
|
KillMode=control-group
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ReadWritePaths=/var/lib/svos
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# eshpfi configs/svos-apps/ (infra-ops, 2026-10-07, a737a06 refresh), modelled on svoperatingsystem
|
||||||
|
# deployment/nh3-svos/svos-interface.service. The credential is /etc/svos/postoffice.env (root 0600, SVOS_APP_CREDENTIAL),
|
||||||
|
# minted by enrollment on the private kernel listener. Listed in the qemu-ga quiesce hook (configs/qemu-ga/svos/50-svos).
|
||||||
|
[Unit]
|
||||||
|
Description=SVOS Post office bridge (app-postoffice, U9)
|
||||||
|
After=svos-kernel.service
|
||||||
|
Requires=svos-kernel.service
|
||||||
|
ConditionPathExists=/etc/svos/postoffice.env
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=svc-svos
|
||||||
|
Group=svc-svos
|
||||||
|
UMask=0077
|
||||||
|
WorkingDirectory=/var/lib/svos
|
||||||
|
EnvironmentFile=/etc/svos/postoffice.env
|
||||||
|
Environment=SVOS_KERNEL_URL=http://127.0.0.1:8400
|
||||||
|
Environment=SVOS_DATA_ROOT=/var/lib/svos
|
||||||
|
Environment=SVOS_APP_LISTEN=127.0.0.1:8406
|
||||||
|
ExecStart=/opt/svos/current/apps-env/bin/svos-postoffice
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=3
|
||||||
|
TimeoutStopSec=20
|
||||||
|
KillMode=control-group
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ReadWritePaths=/var/lib/svos
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# eshpfi configs/svos-apps/ (infra-ops, 2026-10-07, a737a06 refresh), modelled on svoperatingsystem
|
||||||
|
# deployment/nh3-svos/svos-interface.service. The credential is /etc/svos/terminal.env (root 0600, SVOS_APP_CREDENTIAL),
|
||||||
|
# minted by enrollment on the private kernel listener. Listed in the qemu-ga quiesce hook (configs/qemu-ga/svos/50-svos).
|
||||||
|
[Unit]
|
||||||
|
Description=SVOS Terminal connector (app-terminal, U8)
|
||||||
|
After=svos-kernel.service
|
||||||
|
Requires=svos-kernel.service
|
||||||
|
ConditionPathExists=/etc/svos/terminal.env
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=svc-svos
|
||||||
|
Group=svc-svos
|
||||||
|
UMask=0077
|
||||||
|
WorkingDirectory=/var/lib/svos
|
||||||
|
EnvironmentFile=/etc/svos/terminal.env
|
||||||
|
Environment=SVOS_KERNEL_URL=http://127.0.0.1:8400
|
||||||
|
Environment=SVOS_DATA_ROOT=/var/lib/svos
|
||||||
|
Environment=SVOS_APP_LISTEN=127.0.0.1:8404
|
||||||
|
ExecStart=/opt/svos/current/apps-env/bin/svos-terminal
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=3
|
||||||
|
TimeoutStopSec=20
|
||||||
|
KillMode=control-group
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ReadWritePaths=/var/lib/svos
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -110,3 +110,90 @@ https://svos.phasefinal.com:443 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# app-terminal's own origin (svos-dev 2026-10-07, U8 + U10c "a pane needs its own origin"). The interface embeds this
|
||||||
|
# page in a cross-origin iframe; the browser derives its URL from the registry's base_url
|
||||||
|
# (instance.toml: base_url = "https://svos-terminal.phasefinal.com"), so the kernel's signed calls (/health, /verbs/*)
|
||||||
|
# also arrive here, from the box itself, and pass to the connector on 127.0.0.1:8404.
|
||||||
|
# - NO Basic auth and no identity header: Chromium cancels Basic prompts for cross-origin frames and subresources, so a
|
||||||
|
# gate here kills the pane. The lease is the page's auth (GET / without one is a waiting page by ruling A105;
|
||||||
|
# /terminal/session|stream|close refuse without the bearer); /verbs/* and /health refuse without the kernel's
|
||||||
|
# Ed25519 signature. As defence in depth, /verbs/* and /health are refused unless they come from the box itself.
|
||||||
|
# - The app sets Content-Security-Policy: frame-ancestors https://svos.phasefinal.com (its frame_ancestors config);
|
||||||
|
# it passes through unmodified. /terminal/stream is a long-lived ndjson stream: no buffering (flush_interval -1)
|
||||||
|
# and no write/idle deadline (none is set anywhere in this file). Same 1 MiB body cap.
|
||||||
|
# - Mesh-only like the main site: headscale MagicDNS extra record -> 100.64.0.9; nh3-svos resolves it via /etc/hosts.
|
||||||
|
(svos_terminal_upstream) {
|
||||||
|
reverse_proxy 127.0.0.1:8404 {
|
||||||
|
flush_interval -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
https://svos-terminal.phasefinal.com:443 {
|
||||||
|
bind 100.64.0.9
|
||||||
|
tls {
|
||||||
|
dns cloudflare {env.CF_API_TOKEN}
|
||||||
|
resolvers 1.1.1.1 8.8.8.8
|
||||||
|
}
|
||||||
|
route {
|
||||||
|
request_header -Tailscale-User-*
|
||||||
|
request_header -X-Forwarded-*
|
||||||
|
request_header -Tailscale-Headers-Info
|
||||||
|
request_header -X-Real-IP
|
||||||
|
request_header -Forwarded
|
||||||
|
request_header -X-SVOS-Peer
|
||||||
|
|
||||||
|
request_body {
|
||||||
|
max_size 1MiB
|
||||||
|
}
|
||||||
|
|
||||||
|
# The kernel's signed calls come from the box itself (its source on the mesh address); anything else is refused.
|
||||||
|
@not_from_box {
|
||||||
|
path /verbs/* /health
|
||||||
|
not remote_ip 100.64.0.9 127.0.0.1
|
||||||
|
}
|
||||||
|
handle @not_from_box {
|
||||||
|
respond 403
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exactly the paths the connector serves (svos-dev 2026-10-07), method-pinned; everything else is 404.
|
||||||
|
@page {
|
||||||
|
method GET HEAD
|
||||||
|
path / /assets/*
|
||||||
|
}
|
||||||
|
handle @page {
|
||||||
|
import svos_terminal_upstream
|
||||||
|
}
|
||||||
|
@lease_get {
|
||||||
|
method GET
|
||||||
|
path /terminal/session /terminal/stream
|
||||||
|
}
|
||||||
|
handle @lease_get {
|
||||||
|
import svos_terminal_upstream
|
||||||
|
}
|
||||||
|
@lease_close {
|
||||||
|
method POST
|
||||||
|
path /terminal/close
|
||||||
|
}
|
||||||
|
handle @lease_close {
|
||||||
|
import svos_terminal_upstream
|
||||||
|
}
|
||||||
|
@verbs {
|
||||||
|
method POST
|
||||||
|
path /verbs/*
|
||||||
|
}
|
||||||
|
handle @verbs {
|
||||||
|
import svos_terminal_upstream
|
||||||
|
}
|
||||||
|
@health {
|
||||||
|
method GET
|
||||||
|
path /health
|
||||||
|
}
|
||||||
|
handle @health {
|
||||||
|
import svos_terminal_upstream
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
respond 404
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ Every vLLM seat on a shared card (GPU 0, GPU 1) has byte-pinned KV (`--kv-cache-
|
|||||||
|
|
||||||
- `[2026-10-06]` **Scriberr diarization fixed: gated pyannote, a torchcodec/torch mismatch, and WhisperX's CPU defaults; model caches on /tank, HF_TOKEN a placeholder (Prime), GPU+speaker profiles.** Patch 0003 waits for the next rebuild (tracked at `stacks/scriberr/patches/README.md`). → `persistent-memory.d/2026-10-06-scriberr-diarization-fixed.md`
|
- `[2026-10-06]` **Scriberr diarization fixed: gated pyannote, a torchcodec/torch mismatch, and WhisperX's CPU defaults; model caches on /tank, HF_TOKEN a placeholder (Prime), GPU+speaker profiles.** Patch 0003 waits for the next rebuild (tracked at `stacks/scriberr/patches/README.md`). → `persistent-memory.d/2026-10-06-scriberr-diarization-fixed.md`
|
||||||
- `[2026-10-06]` **Backup checker: destroyed guests reported as residue, an ssh stdin swallow fixed, snapshot age from the name; residue pruned (Prime); pbs-nh3 mirror keeps pbs-ana's history (Prime "match history"), first prune 10-07 00:00.** → `persistent-memory.d/2026-10-06-backup-checker-fixes-and-mirror-retention.md`
|
- `[2026-10-06]` **Backup checker: destroyed guests reported as residue, an ssh stdin swallow fixed, snapshot age from the name; residue pruned (Prime); pbs-nh3 mirror keeps pbs-ana's history (Prime "match history"), first prune 10-07 00:00.** → `persistent-memory.d/2026-10-06-backup-checker-fixes-and-mirror-retention.md`
|
||||||
|
- `[2026-10-07]` **nh3-svos refreshed to SVOS a737a06 (schema 11) at svos-dev's ask (Prime's 2240 decision).** Live: app-knowledge (Albok token per A111), plus app-terminal, degraded by design (no seat on the box), on its own origin `svos-terminal.phasefinal.com` (no Basic auth, mesh-only). app-postoffice is declared and stopped (⚠ the bridge handle is Prime's to declare); Miranda's packages are only staged, for U13. Acceptance: 17/17 HTTPS checks and the Chromium phone/desk checks passed. ⚠ The interface fails once on thaw (it starts before the kernel listens); the restart recovers it, but the hook's single status check can race it. Reported to svos-dev. → `servers/nh3-svos/README.md`
|
||||||
- `[2026-10-07]` **Gateway: glm-5.3 added; gen-frontier / gen-frontier-reasoning moved 5.2 → 5.3 (Prime); every GLM 5.2/5.3 entry advertises 1,048,576 in / 131,072 out with max_tokens 131,072 as the default.** 5.3 cannot turn reasoning off, so the gen-frontier pair is now effort low / high (measured ~260 vs ~1,490 reasoning tokens). ⚠ z.ai's `thinking: disabled` is light thinking, not zero, on 5.1/5.2/5.3 alike (220–340 reasoning tokens on a hard prompt). Restarted 1725 (61 s), held 2 h for albok-dev's load A/B. The gate script's first two runs could never pass: `grep -c` exits 1 on a zero count. Images: glm-5.x is text only (z.ai rejects image parts); glm-4.6v and glm-5.3-flash read images on our plan, but neither is on the gateway. → `stacks/litellm/conf/config.yaml`
|
- `[2026-10-07]` **Gateway: glm-5.3 added; gen-frontier / gen-frontier-reasoning moved 5.2 → 5.3 (Prime); every GLM 5.2/5.3 entry advertises 1,048,576 in / 131,072 out with max_tokens 131,072 as the default.** 5.3 cannot turn reasoning off, so the gen-frontier pair is now effort low / high (measured ~260 vs ~1,490 reasoning tokens). ⚠ z.ai's `thinking: disabled` is light thinking, not zero, on 5.1/5.2/5.3 alike (220–340 reasoning tokens on a hard prompt). Restarted 1725 (61 s), held 2 h for albok-dev's load A/B. The gate script's first two runs could never pass: `grep -c` exits 1 on a zero count. Images: glm-5.x is text only (z.ai rejects image parts); glm-4.6v and glm-5.3-flash read images on our plan, but neither is on the gateway. → `stacks/litellm/conf/config.yaml`
|
||||||
- `[2026-10-07]` **Hermes launchers repaired (Miranda relay 8462):** svos-dev's scratch probe had rewritten `~/.hermes/hermes-agent/.hermes/bin/{hermes,hermes-acp}` to exec a /tmp scratch Python. Repointed to `~/.hermes/tools/python-3.14.7…`; the gateway was not restarted. ⚠ Don't run `git` in `~/.hermes/hermes-agent`: a `status` there looped on auto-gc.
|
- `[2026-10-07]` **Hermes launchers repaired (Miranda relay 8462):** svos-dev's scratch probe had rewritten `~/.hermes/hermes-agent/.hermes/bin/{hermes,hermes-acp}` to exec a /tmp scratch Python. Repointed to `~/.hermes/tools/python-3.14.7…`; the gateway was not restarted. ⚠ Don't run `git` in `~/.hermes/hermes-agent`: a `status` there looped on auto-gc.
|
||||||
- `[2026-10-07]` **albok-service 0.1.14 (unit 4.3: sidecar listing, byte-less ingest, a `.browse/` view; detector 2) deployed at 1804 at albok-dev's ask 8524.** `leaks` went from 8 to 6 when the placeholder false positives cleared. Reindexes ran one per wing afterwards to render the view. ⚠ **OWED: the `.browse/` exposure test.** Pick a share surface (sshfs `follow_symlinks` is the lead), rename `.browse/` on the server, and check that a fresh open through the client's cached listing FAILS. Nothing is shared until it passes; report to albok-dev. → `stacks/albok-service/README.md`
|
- `[2026-10-07]` **albok-service 0.1.14 (unit 4.3: sidecar listing, byte-less ingest, a `.browse/` view; detector 2) deployed at 1804 at albok-dev's ask 8524.** `leaks` went from 8 to 6 when the placeholder false positives cleared. Reindexes ran one per wing afterwards to render the view. ⚠ **OWED: the `.browse/` exposure test.** Pick a share surface (sshfs `follow_symlinks` is the lead), rename `.browse/` on the server, and check that a fresh open through the client's cached listing FAILS. Nothing is shared until it passes; report to albok-dev. → `stacks/albok-service/README.md`
|
||||||
|
|||||||
@@ -23,6 +23,37 @@ configuration, enrollment and acceptance.
|
|||||||
| App-consistent hook | svos-dev's `/etc/qemu/fsfreeze-hook.d/50-svos` stops the SVOS services on freeze and restarts the ones that were running on thaw. ⚠ **Debian's qemu-ga does NOT run fsfreeze hooks unless configured** (no `-F` in the unit, no `qemu-ga.conf` by default). Here `/etc/qemu/qemu-ga.conf` points it at **`/usr/local/sbin/fsfreeze-dispatch`** (`configs/qemu-ga/fsfreeze-dispatch`), which unlike the stock `/etc/qemu/fsfreeze-hook` propagates failure: if a freeze hook fails, it thaws that hook and the completed ones and exits 1, so qemu-ga refuses the freeze. **Live drill 2026-10-05 1952–1953 (services running):** quiesced backup `vm/111/2026-10-06T02:52:11Z` → kernel+interface down ~1–2 s, back by themselves, health ok. Refused freeze (temporary `60-drill-refuse` after 50-svos, since removed) `vm/111/2026-10-06T02:53:03Z` → the dispatcher unwound and restarted the services, and then **⚠ vzdump did NOT abort: it logged `ERROR: unable to freeze guest fs`, backed up UNFROZEN (crash-consistent, app live), and reported `Backup job finished successfully`, rc 0.** Both images mapped from PBS and mounted read-only (`ro,noload`) on nh3-pve-2, never booted: `svos.db` integrity ok (each image still carries its ~0.9 MB WAL: keep `-wal` with the db when restoring), interface `pins.sqlite3` integrity ok, config/key/config-generation hashes equal live, table counts equal live except `events`. **Monitoring:** `scripts/check-backup-freshness.sh` now reads the LOG of every OK vzdump task and reports ERROR lines; a freeze/thaw error is an APPLICATION-CONSISTENCY FAILURE, verdict **DEGRADED, exit 4** (alerted by the daily wrapper to infra-hermes). nh3-pve-2 was not in the check's node lists at all before 2026-10-05; it is now. Drill B is acknowledged by UPID in the script |
|
| App-consistent hook | svos-dev's `/etc/qemu/fsfreeze-hook.d/50-svos` stops the SVOS services on freeze and restarts the ones that were running on thaw. ⚠ **Debian's qemu-ga does NOT run fsfreeze hooks unless configured** (no `-F` in the unit, no `qemu-ga.conf` by default). Here `/etc/qemu/qemu-ga.conf` points it at **`/usr/local/sbin/fsfreeze-dispatch`** (`configs/qemu-ga/fsfreeze-dispatch`), which unlike the stock `/etc/qemu/fsfreeze-hook` propagates failure: if a freeze hook fails, it thaws that hook and the completed ones and exits 1, so qemu-ga refuses the freeze. **Live drill 2026-10-05 1952–1953 (services running):** quiesced backup `vm/111/2026-10-06T02:52:11Z` → kernel+interface down ~1–2 s, back by themselves, health ok. Refused freeze (temporary `60-drill-refuse` after 50-svos, since removed) `vm/111/2026-10-06T02:53:03Z` → the dispatcher unwound and restarted the services, and then **⚠ vzdump did NOT abort: it logged `ERROR: unable to freeze guest fs`, backed up UNFROZEN (crash-consistent, app live), and reported `Backup job finished successfully`, rc 0.** Both images mapped from PBS and mounted read-only (`ro,noload`) on nh3-pve-2, never booted: `svos.db` integrity ok (each image still carries its ~0.9 MB WAL: keep `-wal` with the db when restoring), interface `pins.sqlite3` integrity ok, config/key/config-generation hashes equal live, table counts equal live except `events`. **Monitoring:** `scripts/check-backup-freshness.sh` now reads the LOG of every OK vzdump task and reports ERROR lines; a freeze/thaw error is an APPLICATION-CONSISTENCY FAILURE, verdict **DEGRADED, exit 4** (alerted by the daily wrapper to infra-hermes). nh3-pve-2 was not in the check's node lists at all before 2026-10-05; it is now. Drill B is acknowledged by UPID in the script |
|
||||||
| Monitoring | Beszel native agent 0.18.7 (`playbooks/beszel-native.yaml`, `configs/beszel-agent/hosts/nh3-svos.env`), hub system `t6y646ifa3x7xxv`, alerts CPU>95%/15m, Disk>85%/5m, Memory>90%/10m, offline/2m. Up 2026-10-05 |
|
| Monitoring | Beszel native agent 0.18.7 (`playbooks/beszel-native.yaml`, `configs/beszel-agent/hosts/nh3-svos.env`), hub system `t6y646ifa3x7xxv`, alerts CPU>95%/15m, Disk>85%/5m, Memory>90%/10m, offline/2m. Up 2026-10-05 |
|
||||||
|
|
||||||
|
## Release a737a06 + apps (2026-10-07, svos-dev thread `01M4D1GNYBW7QVY7RF05R412V2`, Prime's 2240 decision)
|
||||||
|
|
||||||
|
- **Release:** `/opt/svos/current` → `releases/a737a06` (previous `6c6abbe` kept: it cannot read schema 11, and the
|
||||||
|
front door's previous-asset handle still points at it). Built by infra-ops from a clean `git archive`: 9 wheels,
|
||||||
|
the `web/` 0.0.6 static build, `kernel-requirements.txt` (uv export) and `apps-requirements.txt` (uv pip compile
|
||||||
|
against the kernel pins, hashed), `vendor/bifrost-1.2.1` (gitea vh index, sha256-verified, because PyPI has an
|
||||||
|
unrelated `bifrost`), and `hermes-plugin/svos` (staged for U13). Kernel 0.0.5 migrated schema 9 → 11 on first start.
|
||||||
|
- **Pre-change backups:** vzdump `vm/111/2026-10-08T06:02:14Z` (freeze/thaw clean) and an online sqlite `.backup`
|
||||||
|
plus config, keys and app state at `/var/lib/svos/backup/pre-a737a06/` (integrity ok, user_version 9).
|
||||||
|
- **Apps:**
|
||||||
|
| slug | listener | unit | state |
|
||||||
|
|---|---|---|---|
|
||||||
|
| app-interface | 127.0.0.1:8403 | svos-interface | up |
|
||||||
|
| app-knowledge | 127.0.0.1:8405 | svos-knowledge | up; Albok token `01M4D22HHJ7AJHX30WPDE02DFC`, vault `nh3-svos/albok-token-knowledge`, grants per A111 `read:fleet/memory`, `read:fleet/stash`, `read:personal/notes` (no wildcard, no restricted wing, no class grant) |
|
||||||
|
| app-terminal | 127.0.0.1:8404, base_url **https://svos-terminal.phasefinal.com** | svos-terminal | **degraded by design**: no zellij and no fleet session on this box |
|
||||||
|
| app-postoffice | 127.0.0.1:8406 | svos-postoffice (installed, NOT enabled) | declared + enrolled, stopped until Prime declares the bridge handle; `handle = "svos"` in its config is the example's placeholder |
|
||||||
|
| app-miranda, svos-agent | — | — | packages in apps-env only (U13) |
|
||||||
|
Credentials `/etc/svos/<app>.env` (root 0600); units in `configs/svos-apps/`; the quiesce hook lists all three new units.
|
||||||
|
- **Terminal origin:** `svos-terminal.phasefinal.com` = headscale MagicDNS extra record → 100.64.0.9, its own Caddy
|
||||||
|
site (LE via DNS-01). **No Basic auth** (Chromium cancels Basic prompts in cross-origin frames; the lease is the
|
||||||
|
page's auth). `/verbs/*` and `/health` are refused unless they come from the box itself. The kernel's signed calls
|
||||||
|
reach the app through Caddy, so nh3-svos resolves the name via `/etc/hosts` (`100.64.0.9 svos-terminal.phasefinal.com
|
||||||
|
svos.phasefinal.com`): it has no MagicDNS (`accept-dns=false`). The terminal is `up` only while Caddy is.
|
||||||
|
- **Acceptance 2026-10-07 ~2315:** 17/17 HTTPS controls through an SSH forward to the real listener (the 12 from 10-05,
|
||||||
|
plus: health schema 11 with 2 up and 1 degraded; the terminal registered on its own origin; knowledge `wings`
|
||||||
|
= exactly the 3 token wings; knowledge `search` hits; terminal `attach` refused `404 unknown seat`). Chromium
|
||||||
|
phone + desk: shell, inbox, stream, reload, `/status`, `/graph`, `/feed`, no overflow, no page errors; desk
|
||||||
|
"Open Terminal here" → pane open, framed from `https://svos-terminal.phasefinal.com/`, body `waiting` (no lease).
|
||||||
|
From mesh peer fv-ml1, the terminal origin returns: `/` 200 with `frame-ancestors https://svos.phasefinal.com`;
|
||||||
|
lease routes 401; `/verbs/*` and `/health` 403; anything else 404.
|
||||||
|
|
||||||
## Build (reproducible)
|
## Build (reproducible)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
Reference in New Issue
Block a user