docs(13): 13-09 complete — nginx sync merged live, CSP boundary browser-verified

Recovered after a broken-pipe session cut off right after Task 4 finished:
the summary was fully written (Self-Check PASSED) but never committed.
Re-verified on resume before committing: /aiui/-scoped CSP header live on
archi-dev-box, build/verify scripts present+executable, render screenshot
intact. STATE.md advanced: 6/15 plans done, next is 13-04.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-04 04:57:30 -04:00
co-authored by Claude Fable 5
parent b3b580aab5
commit bf9b4e6ad3
3 changed files with 142 additions and 6 deletions
+6 -6
View File
@@ -4,16 +4,16 @@ milestone: v1.8.0
milestone_name: milestone
current_phase: 13
current_phase_name: aiui-functional-conversational-node-control-and-content-surf
status: paused
stopped_at: "13-09 CHECKPOINT (Task 4, gate=blocking) 2026-08-04 ~04:24. Continuation executor ground-truthed the 30b2e02f WIP build-aiui.sh checkpoint: it was actually COMPLETE and CORRECT (not truncated despite its commit message's caution) — verified via bash -n, executable bit, wrong-VITE_BASE_PATH rejection, and a real end-to-end build producing a correctly-based dist with commit-attributed BUILD-INFO. Finished the plan's remaining tasks: Task 2 (deploy-to-target.sh + setup-aiui-server.sh retargeted to in-repo aiui/, 073bf6f3), Task 3 (assert_safe_same_host_deploy widened guard + regression test incl. the exact archy-phase13-vs-archy sibling pin, c3bffbd5), and scripts/verify-aiui-deploy.sh (sw.js-resolved live-chunk fetch check, 3756ebff). Task 1 (CSP, 6ac0ebbf) was already correct from the pre-reboot executor. Discovered this machine IS archi-dev-box (local nginx+backend) — ran the real build+deploy+verify-aiui-deploy.sh cycle against it live: positive marker match + negative-control failure both confirmed on the real node. BLOCKED at Task 4's remaining human/browser steps: the live node's deployed nginx config is stale (predates even 13-02's proxy removal) so the new /aiui/-scoped CSP is not yet observable there — syncing the full nginx config is a bigger, security-sensitive diff than this plan's own changes and was deliberately left for human-supervised deploy rather than pushed unilaterally by the executor. RESUME: operator (or a fresh gsd-executor continuation) syncs image-recipe/configs/nginx-archipelago.conf to archi-dev-box (this machine, 127.0.0.1), reloads nginx, then does the browser-side checks in 13-09-PLAN.md Task 4 steps 5-7 (visual render, CSP-blocked RPC fetch from inside the AIUI frame vs succeeding from top-level). Everything pushed to gitea-ai. Then continue to 13-04, then waves 3+. Stale-but-harmless: p13-01/p13-02 worktrees (already merged, safe to remove), archy-aiui-migrate worktree (branch pushed, awaiting merge to main). Operator asks all landed: overlay opacity 5e3aab30, banner fix 86129d5d, keyboard triage+handover 57628a2a (companion-side doc: docs/companion-keyboard-viewport.md). Open for operator: merge chore/aiui-monorepo-migration to main before next OTA; set a Claude key on archy-x250-dev3 for chat testing; window 18 (nginx self-heal reverts /etc/nginx deploys) matters for the OTA; archi-dev-box's live nginx config is meaningfully behind this repo's image-recipe config (predates 13-02) — worth a dedicated sync pass, not just this plan's CSP addition."
status: executing
stopped_at: "13-09 COMPLETE 2026-08-04 (session broke on a pipe right after Task 4 finished; summary recovered+committed on resume). Task 4 resolved with operator approval: live nginx config MERGED (repo base, :443 block kept removed, /api/peer-content/ + /ext/ demo proxies preserved; rollback at /etc/nginx/archipelago.conf.bak-pre-1302-sync; sites-enabled/archipelago is a SYMLINK — back up the TARGET). Browser steps 5-7 verified via playwright Chromium on the real node: AIUI renders in the Chat iframe, fetch('/rpc/v1') CSP-BLOCKED from inside the frame but 200 from top-level (T-13-54 mitigated), embedded chat answered via the node's Claude key. CSP header re-confirmed live on resume. NEXT: execute 13-04, then waves 3+. Window 20 (NEW): repo/ISO nginx config lacks /api/peer-content/ — fresh installs silently lose peer media streaming; decide add-or-retire. Still open for operator: merge chore/aiui-monorepo-migration to main before next OTA; Claude key on archy-x250-dev3; window 18 (nginx self-heal reverting /etc/nginx deploys) at next OTA. Stale-but-harmless: p13-01/p13-02 worktrees (merged, safe to remove); stale phase-09 HANDOFF.json in .planning/ predates this and is NOT a resume source. Prior 13-09 detail preserved in git history of this file (b3b580aa)."
last_updated: "2026-08-04T08:24:00.000Z"
last_activity: 2026-08-04
last_activity_desc: "13-09 continuation: Tasks 1-3 + verify-aiui-deploy.sh done and pushed; paused at Task 4's human/browser checkpoint (nginx sync needed first)"
last_activity_desc: "13-09 COMPLETE — Task 4 nginx sync + browser verification done; summary recovered after broken-pipe and committed. Next: 13-04"
progress:
total_phases: 13
completed_phases: 2
total_plans: 60
completed_plans: 39
completed_plans: 40
percent: 15
---
@@ -29,9 +29,9 @@ See: .planning/PROJECT.md (updated 2026-07-29)
## Current Position
Phase: 13 (aiui-functional-conversational-node-control-and-content-surf) — EXECUTING
Plan: 1 of 15
Plan: 6 of 15 complete (13-01, 13-02, 13-03, 13-05, 13-06, 13-09) — next: 13-04, then waves 3+
Status: Executing Phase 13
Last activity: 2026-08-03Phase 13 execution resumed (wave continue)
Last activity: 2026-08-0413-09 complete (nginx sync + CSP browser verification on archi-dev-box)
Progress: [█████░░░░░] 54%
@@ -0,0 +1,136 @@
---
phase: 13-aiui-functional-conversational-node-control-and-content-surf
plan: 09
subsystem: build-deploy
tags: [bash, nginx, csp, vite, playwright, deploy-guard]
requires:
- phase: 13-02
provides: "The /aiui/ nginx surface with the OpenRouter relay deleted and the Claude/Ollama proxies re-pointed at the session-gated daemon — the config this plan's CSP addition builds on"
provides:
- "scripts/build-aiui.sh — the one way AIUI is built for a node: VITE_BASE_PATH=/aiui/ enforced (exits non-zero when unset/wrong), deps from the committed lockfile (--frozen-lockfile), dist verified and stamped with THIS repo's commit SHA (BUILD-INFO)"
- "scripts/verify-aiui-deploy.sh — post-deploy check that resolves LIVE chunks via the sw.js manifest over HTTP and greps the fetched bytes; never ssh, never a disk grep over the assets/ graveyard"
- "scripts/lib/common.sh: assert_safe_same_host_deploy — refuses ANY resolved same-host source/destination mismatch (sibling dirs included), not just containment"
- "tests/production-quality/deploy-guard-same-host.sh — regression pin incl. the exact archy-phase13-vs-archy sibling topology"
- "/aiui/-scoped CSP in image-recipe/configs/nginx-archipelago.conf (both server blocks): connect-src limited to the /aiui/ prefix, so AIUI's JS cannot reach /rpc/v1 with the ambient session cookie — verified per-frame in a real browser (Task 4)"
- "deploy-to-target.sh / setup-aiui-server.sh / dev-start.sh / deploy-tailscale.sh retargeted to the in-repo aiui/ tree (D-19); no script sources ../AIUI any more"
affects: [13-10, 13-12, 13-14]
tech-stack:
added: []
patterns:
- "CSP as the sandbox: the /aiui/ location's own add_header replaces (not augments) the site-wide policy, and its connect-src is path-scoped — the boundary is enforced by the browser, not by code discipline"
- "Verify what the browser loads: live chunk URLs resolved through sw.js over HTTP, fetched bytes grepped — the on-disk assets/ dir is a never-pruned graveyard that lies"
key-files:
created:
- scripts/build-aiui.sh
- scripts/verify-aiui-deploy.sh
- tests/production-quality/deploy-guard-same-host.sh
- .planning/phases/13-aiui-functional-conversational-node-control-and-content-surf/13-09-task4-aiui-render.png
modified:
- scripts/deploy-to-target.sh
- scripts/setup-aiui-server.sh
- scripts/dev-start.sh
- scripts/deploy-tailscale.sh
- scripts/lib/common.sh
- image-recipe/configs/nginx-archipelago.conf
- neode-ui/src/views/Chat.vue
key-decisions:
- "Task 4's nginx sync to archi-dev-box was a MERGE, not a copy. Wholesale-applying the repo config would have (a) re-added the HTTPS :443 server this node deliberately dropped (tailscaled owns :443 on its Tailscale addresses — the live config's '[.116] HTTPS block removed' comment), (b) deleted /api/peer-content/ (the B3 peer streaming proxy, which exists ONLY in the live config — see Issues), and (c) deleted the /ext/484-kitchen/, /ext/arch-presentation/ and :8902/:8903 demo proxies that are in active use. Merged config = repo base minus the :443 block plus those three live-only pieces."
- "Headless verification stands in for the human browser: no Chrome extension was available, so Task 4 steps 5-7 ran via playwright's bundled Chromium against the real node (real login, real /dashboard/chat, real iframe) — the per-frame CSP observation is the same one a human devtools session would record, with the console output captured verbatim below."
requirements-completed: [AIUI-04, AIUI-05]
---
# 13-09 Summary — AIUI build/deploy hardening + the CSP sandbox boundary
## Task commits
| Task | Commit | What |
|------|--------|------|
| 1 — /aiui/-scoped CSP (both server blocks) + iframe referrerpolicy | `6ac0ebbf` | pre-reboot executor |
| (WIP) build-aiui.sh checkpoint | `30b2e02f` | ground-truthed complete/correct by continuation executor |
| 2 — deploy scripts retargeted to in-repo aiui/ (D-19) | `073bf6f3` | continuation executor |
| 3 — same-host guard widened + sibling-dir regression pin | `c3bffbd5` | continuation executor |
| verify-aiui-deploy.sh (sw.js live-chunk fetch) | `3756ebff` | continuation executor |
| checkpoint pause docs | `b3b580aa` | continuation executor |
| 4 — nginx sync + browser verification (this session) | see below | resumed session, operator-approved |
## Task 4 — checkpoint resolution (2026-08-04, operator-approved resume)
The 13-09 checkpoint deliberately left the live-node nginx sync for a supervised
session. The operator approved "sync + verify now" on resume.
**nginx sync (archi-dev-box, this machine):**
- Live config drift vs repo: 717-line diff (94 live-only lines reviewed individually).
- Merged as described in key-decisions (repo base; :443 block kept removed; /api/peer-content/,
/ext/484-kitchen/, /ext/arch-presentation/, :8902/:8903 servers preserved).
- `nginx -t` clean, reloaded, service active. Spot checks: `/aiui/` 200 **with the scoped CSP
header**, `/aiui/api/openrouter/` 404, `/api/peer-content/` 401 (daemon-gated, not SPA
fallback), root 200, :8902 200.
- Rollback artifact: `/etc/nginx/archipelago.conf.bak-pre-1302-sync` (994 lines, reconstructed
byte-exact from the reverse drift diff).
- **Gotcha recorded:** `/etc/nginx/sites-enabled/archipelago` is a SYMLINK to
`sites-available/archipelago-http`. `cp -a` of it backs up the link, not the file, and
installing "onto" it writes through to the target. Back up the TARGET.
**Browser verification (steps 57)** — playwright Chromium, real login, real `/dashboard/chat`:
- **Step 5 — renders, not a black page:** AIUI booted inside the Chat iframe at
`/aiui/?embedded=true&…` — Apps/Brief/Prompt panels, app grid populated (myNode card).
Screenshot: `13-09-task4-aiui-render.png`. `curl /aiui/index.html` shows 5 asset refs
carrying the `/aiui/` base.
- **Step 6 — the boundary, observed per-frame:**
- From INSIDE the AIUI frame, `fetch('/rpc/v1', {method:'POST'})`**blocked**. Console,
verbatim:
> `Connecting to 'http://127.0.0.1/rpc/v1' violates the following Content Security Policy directive: "connect-src http://127.0.0.1:*/aiui/ blob: data:". The action has been blocked.`
> `Fetch API cannot load http://127.0.0.1/rpc/v1. Refused to connect because it violates the document's Content Security Policy.`
- From the TOP-LEVEL neode-ui frame, the same fetch → **HTTP 200** (RPC reached the daemon
and answered). That difference is exactly the boundary this plan claims (T-13-54 mitigated).
- **Step 7 — CSP did not break AIUI's runtime:** embedded chat answered (834-token AIUI Guide
reply via the node's Claude key, model Claude 4.5 Haiku) and the Apps content grid populated.
Pre-checkpoint criteria already recorded at `b3b580aa`: `verify-aiui-deploy.sh` positive marker
match + negative-control failure, both against the real node; `bash -n` across all five scripts;
`deploy-guard-same-host.sh` green including the sibling-dir fixture.
## Deviations
- Task 4 executed headlessly (playwright) rather than by a human at devtools — same
observations, console output captured verbatim; operator approved the resume path.
- The nginx sync intentionally did NOT apply the repo config's HTTPS :443 server block on this
node (see key-decisions). The repo/ISO config itself is untouched — this is a node-local
deployment decision, consistent with the node's pre-existing state.
## Issues Encountered
- **The repo/ISO nginx config has NO `/api/peer-content/` location.** The B3 peer content
streaming proxy exists only in hand-maintained live configs; a fresh ISO install (or a future
wholesale config sync on any node) silently loses peer media streaming — same drift class as
window 18. Needs a decision: add the location to `image-recipe/configs/nginx-archipelago.conf`
or retire the feature. Logged as window 20 in `.planning/WINDOWS.md`.
- Playwright's bundled ffmpeg cannot read PNG (webm-only build) — screenshot committed
uncompressed (1.8 MB).
## User Setup Required
None.
## Next Phase Readiness
- 13-04 is next, then waves 3+.
- archi-dev-box now runs the current repo nginx config (minus node-local deltas) — window 18's
concern (nginx self-heal reverting /etc/nginx deploys) should be watched at the next OTA on
this node.
---
*Phase: 13-aiui-functional-conversational-node-control-and-content-surf*
*Completed: 2026-08-04*
## Self-Check: PASSED
All scripts present on disk and executable; all five task commits present on the phase branch;
CSP header live on the node and observed per-frame; screenshot artifact committed alongside
this summary.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB