diff --git a/playbooks/wire-personal-worldtree-memory-allowlist.yaml b/playbooks/wire-personal-worldtree-memory-allowlist.yaml new file mode 100644 index 0000000..f391a88 --- /dev/null +++ b/playbooks/wire-personal-worldtree-memory-allowlist.yaml @@ -0,0 +1,65 @@ +# Add the ratatoskr memory-plane provider endpoint to the personal Worldtree's +# Bifrost client allowlist, so a consumer may BIND it at session-create. +# +# Worldtree gates `bifrost.endpoint_url` against BIFROST_CLIENT_ALLOWED_HOSTS +# (host:port CSV in /opt/worldtree-personal/.env). The affect plane :8390 was +# listed during its deploy; the memory plane :8391 (ratatoskr-memory-provider +# on nh3-dev) needs appending — otherwise POST /sessions 422s +# (`endpoint_url must be HTTPS or match BIFROST_CLIENT_ALLOWED_HOSTS`) before +# any handshake fires. See the eshpfi memory note `reference_bifrost_plane_wiring`. +# +# Idempotent + rerunnable: guards are sudo-free (live container env via the +# docker group; backup via `test -e`); the append self-guards inside its +# sudo bash -c; the recreate skips when the live env already carries the host. +# Surgical: recreates ONLY worldtree-api (the validator); matrix is untouched +# and picks up the value on its next natural redeploy. `--pull never` uses the +# local pinned image so the recreate needs no gitea registry auth. +# +# CRITICAL pin-preservation: WORLDTREE_IMAGE is injected by the Worldtree CI/CD +# at deploy time, NOT stored in .env, so a bare `compose up` falls back to the +# compose default `:latest` — a STALE locally-cached build whose stricter config +# validation crash-blocks startup on this instance's agent-profile drift (agents +# reference removed LLM profile qwen3.6-35-a3b-heretic). The recreate step below +# therefore re-derives the live pin from the untouched matrix sibling and passes +# it explicitly. (Learned the hard way 2026-06-15 — a pinless recreate took the +# personal API down for ~1 min until restored on the correct pin.) +# +# scripts/elway corviduo-dev --playbook playbooks/wire-personal-worldtree-memory-allowlist.yaml + +vars: + add_host: "10.100.10.50:8391" + proj_dir: /opt/worldtree-personal + env_file: /opt/worldtree-personal/.env + api_service: worldtree-api + api_container: worldtree-personal-worldtree-api-1 + +steps: + - name: Back up .env before editing the allowlist + shell: cp /opt/worldtree-personal/.env /opt/worldtree-personal/.env.bak-pre-memory-allowlist + sudo: true + creates: /opt/worldtree-personal/.env.bak-pre-memory-allowlist + + - name: Append the memory endpoint to BIFROST_CLIENT_ALLOWED_HOSTS (self-guarded) + shell: >- + grep -q '{{ add_host }}' {{ env_file }} + || sed -i '/^BIFROST_CLIENT_ALLOWED_HOSTS=/ s/$/,{{ add_host }}/' {{ env_file }} + sudo: true + + - name: Recreate worldtree-api so it loads the new allowlist (skip if already live) + when: "! docker exec {{ api_container }} printenv BIFROST_CLIENT_ALLOWED_HOSTS 2>/dev/null | grep -q '{{ add_host }}'" + # Re-derive the live image pin from the untouched matrix sibling so the + # recreate can't fall back to the crash-blocking :latest default. + shell: >- + WORLDTREE_IMAGE="$(docker inspect worldtree-personal-worldtree-matrix-1 --format '{{.Config.Image}}')" + docker compose --project-directory {{ proj_dir }} -f {{ proj_dir }}/compose.yaml + -p worldtree-personal up -d --pull never --force-recreate {{ api_service }} + sudo: true + +verify: + - name: Live worldtree-api env carries the memory endpoint + shell: docker exec {{ api_container }} printenv BIFROST_CLIENT_ALLOWED_HOSTS | grep -q '{{ add_host }}' + changed_when: "false" + + - name: worldtree-api container is running + shell: docker ps --filter name={{ api_container }} --filter status=running -q | grep -q . + changed_when: "false" diff --git a/servers/corviduo-dev/ssh-target b/servers/corviduo-dev/ssh-target index 73fe0b2..bcf69f9 100644 --- a/servers/corviduo-dev/ssh-target +++ b/servers/corviduo-dev/ssh-target @@ -1 +1 @@ -vh@10.250.50.152 +infra-ops@10.250.50.152