The agent host's vault and SilverBullet (M5.4) #166

Merged
dev-agent merged 8 commits from agent-host-vault into main 2026-10-19 22:22:39 +00:00
3 changed files with 24 additions and 2 deletions
Showing only changes of commit 1d33d50907 - Show all commits

No files matched your search

+5
View File
@@ -10,6 +10,11 @@ bad() { echo "FAIL: $1"; fail=1; }
cd "$stack" || { echo "FAIL: no $stack"; exit 1; }
[ "$(sudo docker compose ps --status running -q | wc -l)" -ge 1 ] \
&& ok "SilverBullet is running" || bad "SilverBullet isn't running"
if sudo docker compose logs --no-color silverbullet 2>/dev/null | grep -q 'boot mode: single-space'; then
bad "it booted a single space with no accounts (an SB_* setting?)"
else
ok "it keeps accounts (no single-space boot)"
fi
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/)
case $code in 2??|3??) ok "it answers locally ($code)" ;; *) bad "it answers $code" ;; esac
probe=.nisse-probe-$$
+2 -1
View File
@@ -8,9 +8,10 @@ services:
image: ghcr.io/silverbulletmd/silverbullet:2.11.1-slim
restart: unless-stopped
environment:
# Only these. Any SB_* setting (even SB_NAME) boots a single space with
# no accounts, serving /data instead of the vault.
PUID: "1000"
PGID: "1000"
SB_NAME: Nisse vault
ports:
# IPv4 only; setup.sh's firewall lets only the operator's Caddy in.
- "0.0.0.0:3000:3000"
+17 -1
View File
@@ -67,6 +67,12 @@ def test_no_secrets_in_the_compose_file() -> None:
assert not [k for k in environment if re.search(r"USER|TOKEN|PASS|SECRET|KEY", k)]
def test_it_boots_into_accounts_and_the_vault_not_a_bare_space() -> None:
# SB_NAME alone switched 2.11 to single-space mode: no accounts, no setup
# wizard, and /data served in place of the vault.
assert set(silverbullet()["environment"]) == {"PUID", "PGID"}
def test_its_port_caddys_and_the_firewalls_agree() -> None:
port = setting("SB_PORT")
assert silverbullet()["ports"] == [f"0.0.0.0:{port}:3000"] # IPv4 only
3
@@ -120,7 +126,9 @@ def test_the_firewall_lets_only_one_address_in_and_replaces_its_own_rule() -> No
SCRIPT = HOST.parents[1] / "scripts" / "agent-host.sh"
def _fake_host(tmp_path: Path, *, memory_writable: bool) -> dict[str, str]:
def _fake_host(
tmp_path: Path, *, memory_writable: bool, boot: str = "multi-space"
) -> dict[str, str]:
"""Commands standing in for the host's: ssh runs the command here, sudo
just runs it, and docker reads all of stdin, as docker compose exec does."""
bin_ = tmp_path / "bin"
@@ -134,6 +142,7 @@ def _fake_host(tmp_path: Path, *, memory_writable: bool) -> dict[str, str]:
"cat > /dev/null\n"
'case "$*" in\n'
' *"ps --status running"*) echo abc123 ;;\n'
f' *" logs "*) echo "boot mode: {boot}" ;;\n'
f' *"/vault/memory/"*) exit {0 if memory_writable else 1} ;;\n'
"esac"
),
@@ -167,6 +176,7 @@ def test_the_check_runs_every_step_even_though_docker_reads_stdin(
assert result.returncode == 0, result.stdout + result.stderr
assert result.stdout.splitlines() == [
"ok: SilverBullet is running",
"ok: it keeps accounts (no single-space boot)",
"ok: it answers locally (200)",
"ok: the operator's folders are writable",
"ok: memory/ is read-only to SilverBullet",
@@ -184,3 +194,9 @@ def test_a_writable_memory_folder_fails_the_check(tmp_path: Path) -> None:
)
assert "ok: the firewall rule is in place" in result.stdout # still checked
assert "all checks passed" not in result.stdout
def test_a_single_space_boot_fails_the_check(tmp_path: Path) -> None:
result = _check(_fake_host(tmp_path, memory_writable=False, boot="single-space"))
assert result.returncode == 1
assert "FAIL: it booted a single space with no accounts" in result.stdout