Files
archy/.planning/phases/01-federation-mesh-hardening/01-18-PLAN.md
T

15 KiB
Raw Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, gap_closure, must_haves
phase plan type wave depends_on files_modified autonomous requirements gap_closure must_haves
01-federation-mesh-hardening 18 execute 9
01-12
01-13
01-14
01-15
01-17
false
UIFIX-01
UIFIX-02
UIFIX-03
UIFIX-04
UIFIX-05
UIFIX-06
true
truths prohibitions artifacts key_links
All six UI fixes are exercised on real node hardware, not only on the local preview, because two of them are about how the app behaves on a device rather than in a viewport
The connected-nodes list scrolls at a sibling-matched height on the node's own screen and at a phone width
The onboarding tickbox is discoverable on a genuinely short viewport on the node
A purchased picture opens in the app's lightbox on the node, with the wait visible
Picture-in-picture closes the lightbox with a handoff and survives a real tab change and a real buffering pause on the node
The FIPS/Tor pills are readable at phone width on the node
Every surface that was not supposed to change is confirmed unchanged on the node — the standing visual-invisibility rule is verified, not assumed
statement category
This phase's frontend MUST NOT be deployed beyond the dev pair — no OTA, no release, no fleet node, no alpha-tester path; a verification step is never a reason to widen a deploy safety
statement category
Sign-off MUST NOT be given on local-preview evidence alone for any check that names the node — the local preview and a real device disagree exactly where these fixes matter, which is why phase 2's on-device pass found four issues the preview did not transparency
Put all six UI fixes in front of a human, on the node, once.

Purpose: each of plans 01-12 through 01-17 verifies itself with tests and a local-preview observation, which is the right granularity for an autonomous plan but is not sufficient evidence for a user-reported blocker. Two of these fixes — picture-in-picture surviving a tab change, and the pills at phone width — are about device behaviour that a desktop preview cannot reproduce. Rather than interrupting five plans with five checkpoints, they are gathered here so the operator is asked once, after the code is on archi-dev-box. This mirrors how plan 01-10 consolidates the federation and Lightning sign-offs. Output: a recorded sign-off, or a numbered issue list that becomes the input to a gap-closure pass.

<execution_context> @$HOME/.claude/gsd-core/workflows/execute-plan.md @$HOME/.claude/gsd-core/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/STATE.md @.planning/phases/01-federation-mesh-hardening/01-12-SUMMARY.md @.planning/phases/01-federation-mesh-hardening/01-13-SUMMARY.md @.planning/phases/01-federation-mesh-hardening/01-14-SUMMARY.md @.planning/phases/01-federation-mesh-hardening/01-15-SUMMARY.md @.planning/phases/01-federation-mesh-hardening/01-17-SUMMARY.md Task 1: Put the six fixes on archi-dev-box, frontend only, dev pair only none — this task builds, deploys and verifies delivery; it modifies no file in the repository archi-dev-box resolves and answers over HTTP from this machine, and `scripts/deploy-config.sh` exists (it is gitignored; `scripts/deploy-config.example` documents it) so the deploy script can authenticate - `scripts/deploy-to-target.sh` lines 1-30 — the usage block. `--frontend-only` skips the Rust build and container rebuilds; `--live` targets the default host; `--both` fans out to additional hosts; `--tailscale` reaches the alpha-tester nodes and must not be used here. - `.planning/phases/02-ui-performance/02-08-SUMMARY.md` — the exact command phase 2 used for the same kind of dev-pair frontend deploy, and its record of archy-x250-dev being offline. Reuse the command shape rather than inventing one. - The five plan SUMMARYs listed in `` — specifically each one's recorded local-preview observations, so you know what the node is expected to reproduce. Build the frontend and deploy it to archi-dev-box with the dev-pair frontend-only path. Record the exact command in the SUMMARY.
Do not use the Tailscale or alpha-tester paths, do not cut a release, do not touch the OTA manifest,
and do not deploy to any fleet node. Note that this plan set's FED-07 work is backend and is
verified separately by plan 01-16 — this deploy is frontend only.

Check whether archy-x250-dev is reachable. It has been offline since phase 2. If it is still
offline, record that plainly as a gap rather than waiting for it or pretending the pair was
covered; single-node verification on archi-dev-box with the second-node gap recorded honestly is
the expected pattern for this phase.

Then confirm the node is actually serving this build before handing over to the checkpoint — fetch
the served bundle from archi-dev-box and grep it for strings this plan set introduced (the
onboarding cue copy, the picture-in-picture handoff class, and the paid-item viewer). Grep the
served asset, not the local `web/dist` copy: per CLAUDE.md the frontend build can silently no-op,
and a checkpoint run against a stale bundle is worse than no checkpoint.
curl -fsS --max-time 20 "${ARCHY_DEV_URL:?set ARCHY_DEV_URL to archi-dev-box's UI base URL}/" -o /dev/null && echo served - The SUMMARY records the exact deploy command and the host list it targeted, and that list contains no fleet, alpha-tester or Tailscale host. - The SUMMARY records the served-bundle grep result for all three introduced strings, naming the URL fetched. - The SUMMARY records archy-x250-dev's reachability, and if unreachable records it as an explicit gap. - No release artifact, OTA manifest or catalog was modified — `git status --short -- release-manifest.json releases/ app-catalog/` is empty. archi-dev-box is serving a bundle that provably contains all six fixes, and the second-node gap is recorded. Task 2: Six-fix sign-off on archi-dev-box Six user-reported UI issues, now on archi-dev-box: - **Connected nodes (UIFIX-02).** On the Web5 tab, the connected-nodes card no longer grows to fit every node. Its height now comes from the card beside it in the row and the list scrolls inside that height, with a floor so a short neighbour cannot squash it. Below the two-column breakpoint nothing changed. - **Onboarding tickbox (UIFIX-03).** On a screen too short to show the whole seed step, a soft gradient and a small glass pill reading "One more step below" now appear at the bottom edge of the scrolling area. Clicking it scrolls the confirmation tickbox into view, and it disappears once the tickbox is visible. On a tall screen it never appears at all. - **Paid Files pictures (UIFIX-04).** Purchased pictures and videos now open in the app's own lightbox instead of a browser tab. Purchased music still goes to the bottom-bar player, and purchased documents still open the way they did. - **Loader states (UIFIX-06).** Opening a purchased file now shows a spinner and an "Opening…" label on its row for as long as the fetch takes, and a failure now shows an error instead of appearing to do nothing. Every other surface that was flagged as slow was audited and its verdict recorded. - **Picture-in-picture (UIFIX-05).** Entering picture-in-picture now closes the lightbox with a handoff animation, and the video keeps playing. The session survives switching main tabs and survives buffering pauses; only explicitly stopping it ends it. - **FIPS/Tor pills (UIFIX-01).** The pills are now pinned by a test so no future cleanup can remove them, and every site that could not be read at phone width was fixed. Run all of this against archi-dev-box's own UI, not the local preview. Use a real phone or the browser's device emulation for the narrow checks, and say which you used.
1. **Connected nodes scroll (UIFIX-02).** Open the Web5 tab on a wide window. Expected: the
  connected-nodes card and the card to its right are the same height, and if there are more nodes
  than fit, the list scrolls inside the card — the row does not get taller. Switch between the
  trusted, observers and requests tabs: expected the card's height does not change. Then narrow the
  window to a single column: expected exactly the layout you had before this change.

2. **Onboarding cue (UIFIX-03).** Open the onboarding seed step at a short viewport (a small laptop
  height, or device emulation at roughly 1280×620). Expected: a soft fade and a small pill reading
  "One more step below" at the bottom of the scrolling area; clicking it brings the tickbox into
  view and the cue disappears. Confirm the cue does not tick the box for you and the Continue
  button stays disabled until you tick it yourself. Then open the same step at full height:
  expected no cue at all and a step that looks exactly as it did before.

3. **Paid Files in the lightbox (UIFIX-04) and the loader (UIFIX-06).** Go to Cloud → Paid Files
  and click a purchased picture. Expected: the row shows a spinner and "Opening…" while it loads,
  then the picture opens in the app's lightbox — no new browser tab. Click a purchased video:
  expected the same, in the lightbox with player controls. Click a purchased music track: expected
  the bottom-bar player, not the lightbox. If you can, click one twice quickly: expected one load,
  not two.

4. **Picture-in-picture (UIFIX-05).** Open a video in the lightbox and click the
  picture-in-picture button. Expected: the lightbox animates away in a way that reads as the video
  moving into the small window rather than the lightbox being dismissed, and the video keeps
  playing. Now switch between main tabs a few times: expected playback continues. Now cause a
  buffering pause — throttle the network in devtools, or seek far ahead: expected it recovers and
  the small window stays. Now close the small window explicitly: expected playback stops and
  nothing is left behind. Finally open the lightbox again and close it with the close button and
  with Escape: expected exactly the close animation it had before.

5. **FIPS/Tor pills at phone width (UIFIX-01).** At a phone width, go to Cloud and look at the peer
  cards, then open a peer's files. Expected: wherever a FIPS or Tor pill appears on desktop it
  appears here too, fully readable, not clipped and not overlapping anything, including when a peer
  name or filename is long. Compare the same screens at desktop width: expected unchanged.

6. **Nothing else moved.** Move through the main tabs and the Cloud sub-tabs. Expected: the page
  margins, the slide transitions between tabs, and every existing animation look exactly as they
  did before this plan set. Phase 2 broke margins and slide transitions this way once, so this is a
  real check, not a formality.

If anything fails, say which numbered step and what you saw — that becomes the gap list rather than
a re-run of the whole plan set.
Type "approved" to sign off UIFIX-01 through UIFIX-06, or describe the issues by step number.

Planner Assumptions (flagged, unresolved)

  • archy-x250-dev is assumed to still be offline. Phase 2 checked three times and found it gone. Task 1 re-checks rather than assuming, and records the gap either way; nothing in this plan blocks on it.
  • Whether archi-dev-box has purchased content to test step 3 with is unknown to the planner. If it has none, say so in the sign-off rather than marking step 3 passed on the demo — a demo-only pass for a paid-content path is exactly the divergence class this phase exists to remove.

<threat_model>

Trust Boundaries

Boundary Description
operator judgement → sign-off A human verdict gates whether these six blockers are considered closed
deploy host → node A frontend bundle crosses this boundary onto a live node
live node → operator observation Verification runs against a real node holding real federation trust, real purchases and real funds

STRIDE Threat Register

Threat ID Category Component Severity Disposition Mitigation Plan
T-01-82 Elevation of Privilege a verification deploy reaching fleet or alpha-tester nodes high mitigate Task 1 requires the frontend-only dev-pair path, forbids the Tailscale and alpha-tester flags and any release or OTA path, and requires the exact command and host list to be recorded for audit
T-01-83 Repudiation signing off against a stale bundle the node never actually received high mitigate Task 1 requires grepping the bundle served by the node — not the local build output — for three strings this plan set introduced, before the checkpoint runs
T-01-84 Information Disclosure a screenshot or recording of the verification exposing a recovery seed from step 2 high mitigate Step 2 exercises the onboarding step's layout only; the operator is not asked to capture or transcribe the words, and nothing in this plan asks for an image of that screen
T-01-85 Repudiation a demo-only pass on the paid-content path being recorded as a node pass medium mitigate The prohibition forbids local-preview evidence for node-named checks, and the planner assumption requires saying so explicitly if the node has no purchased content
T-01-SC Tampering npm/pip/cargo installs high mitigate This plan installs nothing and modifies no source file — it builds, deploys and asks. If a fix arising from the checkpoint needs a dependency, it belongs in a gap-closure plan whose research covers the Package Legitimacy Gate first
</threat_model>
The operator's response is the verification. An "approved" response closes UIFIX-01 through UIFIX-06; any described issue is captured verbatim in the SUMMARY as a gap for `/gsd-plan-phase 1 --gaps`.

<success_criteria>

  • All six numbered checks were exercised on archi-dev-box, at the widths each one names.
  • The operator either approved or produced a numbered issue list.
  • The outcome is recorded in the SUMMARY, including which device or emulation was used for the narrow checks.
  • The archy-x250-dev gap is recorded rather than glossed over. </success_criteria>
Create `.planning/phases/01-federation-mesh-hardening/01-18-SUMMARY.md` when done, recording the verdict, the deploy command, the served-bundle grep evidence, the device used for narrow checks, and any issue text verbatim. Stage by explicit path, commit, and `git push gitea-ai main`.