feat(nh3-svos): credential-free SVOS offline shell before Basic auth; contract static routes; backup drill results
svos-dev: the service worker fetches its hash-pinned INVENTORY with credentials omitted. Exactly those files plus /sw.js are now served before basic_auth (GET/HEAD, exact files). The list is generated from the release's sw.js by svos-front-inventory, which hash-checks each file and validates before reload. Gated static routes follow the web/README hosting contract: missing assets 404 instead of index.html, other document requests get index.html, everything else 404, unversioned files no-cache. acceptance-matrix.sh: 35/35 live; 16 FAIL against the previous config (positive control). git added to the nh3-svos playbook (kernel's remote check). Live backup drill: quiesced backup ~1-2 s outage; a refused freeze does NOT abort vzdump (unfrozen backup, job reported successful); both images restore-mounted read-only and verified.
This commit is contained in:
@@ -33,6 +33,21 @@ https://svos.phasefinal.com:443 {
|
||||
request_header -Forwarded
|
||||
request_header -X-SVOS-Peer
|
||||
|
||||
# Credential-free offline shell (svos-dev 2026-10-05): the service worker fetches its hash-pinned INVENTORY
|
||||
# with credentials:'omit', so exactly those files plus /sw.js are served BEFORE Basic auth, GET/HEAD only,
|
||||
# exact files (no fallback). Public build bytes only; no API or connector path. The path list is GENERATED
|
||||
# from the live release's sw.js by /usr/local/sbin/svos-front-inventory, which must run after every release.
|
||||
@public_shell {
|
||||
method GET HEAD
|
||||
import /etc/caddy/svos-public-inventory
|
||||
}
|
||||
handle @public_shell {
|
||||
@revalidate path /sw.js /index.html /manifest.webmanifest /favicon.svg /icons/*
|
||||
header @revalidate Cache-Control no-cache
|
||||
root * /opt/svos/current/static
|
||||
file_server
|
||||
}
|
||||
|
||||
basic_auth argon2id SVOS {
|
||||
import /etc/caddy/svos-basic-auth.accounts
|
||||
}
|
||||
@@ -46,10 +61,32 @@ https://svos.phasefinal.com:443 {
|
||||
handle @connector {
|
||||
reverse_proxy 127.0.0.1:8403
|
||||
}
|
||||
handle {
|
||||
# Static routes per svoperatingsystem web/README.md "Hosting contract" (gated):
|
||||
# / and /status -> index.html; the static route space -> exact files, a missing file is 404 (never index.html);
|
||||
# other HTML document requests -> index.html (the app renders Page not found); everything else -> 404.
|
||||
@shell_doc path / /status
|
||||
handle @shell_doc {
|
||||
header Cache-Control no-cache
|
||||
root * /opt/svos/current/static
|
||||
try_files {path} /index.html
|
||||
rewrite * /index.html
|
||||
file_server
|
||||
}
|
||||
@static path /assets/* /icons/* /favicon.svg /manifest.webmanifest /index.html /sw.js
|
||||
handle @static {
|
||||
@revalidate path /sw.js /index.html /manifest.webmanifest /favicon.svg /icons/*
|
||||
header @revalidate Cache-Control no-cache
|
||||
root * /opt/svos/current/static
|
||||
file_server
|
||||
}
|
||||
@other_doc expression header({'Sec-Fetch-Dest': 'document'}) || header({'Accept': '*text/html*'})
|
||||
handle @other_doc {
|
||||
header Cache-Control no-cache
|
||||
root * /opt/svos/current/static
|
||||
rewrite * /index.html
|
||||
file_server
|
||||
}
|
||||
handle {
|
||||
respond 404
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user