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:
vh
2026-10-07 23:17:18 -07:00
parent 9e972872e6
commit 469b3ba3cf
9 changed files with 216 additions and 2 deletions
+87
View File
@@ -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
}
}
}