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

18 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
01-federation-mesh-hardening 09 execute 5
01-01
01-02
01-03
01-04
01-05
01-06
01-07
01-08
.planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md
core/archipelago/src/federation/storage.rs
core/archipelago/src/federation/sync.rs
core/archipelago/src/api/rpc/federation/handlers.rs
core/archipelago/src/fips/dial.rs
core/archipelago/src/mesh/mod.rs
core/archipelago/src/api/rpc/mesh/typed_messages.rs
true
FED-03
FED-01
truths prohibitions artifacts key_links
A findings document exists listing every issue the structured review of the federation/fleet area and the mesh area produced, with file and line citations
Every finding carries exactly one disposition — fixed, or deferred with a written reason — and no finding is left without one (FED-03 ordering edge)
Every reviewed area appears in the document, including areas where the review produced no findings, recorded as reviewed with none rather than omitted (FED-03 empty edge)
Every federation and mesh claim in the codebase concerns document is re-verified against current code and git history before being filed as a finding or dismissed, with the evidence cited (FED-03 adjacency edge)
Every finding marked fixed cites the commit and the test or command that demonstrates the fix
The known-fixed claims are recorded as already-fixed with their commit, not re-fixed
statement category
A finding MUST NOT be closed as fixed without evidence a reader can re-run — a disposition of fixed always cites a commit and a verifying command or test name, never an assertion alone transparency
statement category
A finding MUST NOT be dropped silently — an item judged out of scope is recorded as deferred with the reason and the phase or requirement that owns it, never deleted from the list transparency
path provides min_lines
.planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md The FED-03 structured review output with per-finding dispositions 60
from to via pattern
.planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md .planning/codebase/CONCERNS.md each federation/mesh concern is re-verified and cross-referenced by its finding id CONCERNS
Run the structured code review FED-03 requires over the federation/fleet area and the mesh area, and close it out: every finding fixed or explicitly deferred with a reason.

Purpose: FED-03. RESEARCH.md Pitfall 2 is the governing constraint — .planning/codebase/CONCERNS.md is NOT current truth for this phase. At least two of its federation claims were already fixed on main before this phase started (the tombstone-write-swallowed claim was fixed in 01cbec27; the peer-joined DID path does verify an ed25519 signature). Re-fixing an already-fixed bug wastes the review and risks reverting working code, so every claim gets a fresh code read plus a git-history check before it is filed or dismissed. Output: 01-REVIEW-FINDINGS.md with a disposition on every finding, the small findings fixed inline, and the phase's code deployed to the dev pair so plan 01-10's verification has something to test.

<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/codebase/CONCERNS.md @.planning/codebase/ARCHITECTURE.md @.planning/phases/01-federation-mesh-hardening/01-RESEARCH.md @.planning/phases/01-federation-mesh-hardening/01-01-SUMMARY.md @.planning/phases/01-federation-mesh-hardening/01-05-SUMMARY.md @.planning/phases/01-federation-mesh-hardening/01-07-SUMMARY.md

Artifacts this phase produces

Created or changed by this plan:

Symbol Kind File
01-REVIEW-FINDINGS.md new findings document with per-finding dispositions .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md
finding-dependent fixes code changes in the reviewed areas files listed in files_modified
dev-pair deployment the phase build running on archi-dev-box and x250-dev, sha256-verified (no repo file)
Task 1: End-to-end — one finding from discovery to closed disposition .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md - `.planning/codebase/CONCERNS.md` — the federation and mesh entries: the node-removal tombstone gap (cited at `federation/storage.rs:180-197`), the incomplete federation DID validation, the unbounded harness curl (cited as a multinode test-harness issue), the node-list dedup scaling note, and the mesh radio configuration boot race. - `.planning/phases/01-federation-mesh-hardening/01-RESEARCH.md` — the "Common Pitfalls" section (especially Pitfall 2's instruction to `git log -p` each cited range before acting) and the "Assumptions Log" rows A1, A2, and A5. A5 in particular is explicitly NOT independently re-verified and must be re-checked here. - The SUMMARYs from plans 01-01, 01-05, and 01-07 — what has already been fixed in this phase, so those items are recorded as fixed-by-this-phase rather than re-opened. Create `01-REVIEW-FINDINGS.md` with a table whose columns are: finding id (`F-01`, `F-02`, …), area (federation store / federation sync / federation RPC / FIPS-transport dial / mesh core / mesh RPC surface), severity, the file and line citation, the evidence (what was read and what `git log -p` or `git blame` showed), the disposition (`fixed` / `already-fixed` / `deferred`), and for `fixed` the commit plus the verifying command or test name, or for `deferred` the reason and the owning phase or requirement.
Then take exactly one finding all the way through in this task, to prove the pipeline: re-verify
the codebase-concerns claim about incomplete federation DID validation — specifically the part
RESEARCH.md flags as un-re-verified, whether anything checks proof of ownership of a DID on first
contact, as opposed to the peer-joined path which does verify a signature. Read the add-node and
peer-joined paths in the federation RPC handlers and run `git log -p` on them. File the finding
with its evidence, then either fix it (if the fix is contained and does not touch federation trust
or join cryptography beyond what correctness requires — CONTEXT.md's scope fence) or defer it with
a written reason naming what a fix would touch and why that belongs elsewhere.

Record the two claims RESEARCH.md already verified as fixed with their commits, as `already-fixed`
rows, so a future reader does not re-open them.
test -f .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md && grep -Eq '^\| *F-01' .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md && cd core && cargo test -p archipelago federation - `01-REVIEW-FINDINGS.md` exists with a header row and at least one `F-NN` row. - The first finding's row has a non-empty evidence cell naming the command that produced it and a non-empty disposition cell. - Rows exist recording both already-fixed claims with their commit hashes. - `cd core && cargo test -p archipelago federation` exits 0 (if the first finding was fixed here, its test is included). - The SUMMARY quotes the `git log -p` output excerpt that decided the first finding. The findings document exists and one finding has travelled the full path from claim to evidence to disposition. Task 2: Complete the review across both areas and disposition every finding .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md, core/archipelago/src/federation/storage.rs, core/archipelago/src/federation/sync.rs, core/archipelago/src/api/rpc/federation/handlers.rs, core/archipelago/src/fips/dial.rs, core/archipelago/src/mesh/mod.rs, core/archipelago/src/api/rpc/mesh/typed_messages.rs - `core/archipelago/src/federation/` — `storage.rs`, `sync.rs`, `types.rs`, `invites.rs`, `mod.rs` as left by plans 01-01, 01-05, and 01-06. - `core/archipelago/src/api/rpc/federation/handlers.rs` — the full RPC surface, including the peer-joined, peer-did-changed, and peer-address-changed signature-verification paths. - `core/archipelago/src/fips/dial.rs` and the transport dial/fallback path — the FIPS-to-Tor fast-fail behaviour FED-03 names as in scope. - `core/archipelago/src/mesh/mod.rs` — `purge_federation_peer`, `upsert_federation_peer`, `seed_federation_peers_into_mesh`; and `core/archipelago/src/api/rpc/mesh/typed_messages.rs` as left by plans 01-04 and 01-07. - `.planning/codebase/CONCERNS.md` — every remaining federation and mesh entry. - `.planning/phases/01-federation-mesh-hardening/01-02-SUMMARY.md` — the mock-parity residual class that plan flagged as a candidate finding for this review. - `.planning/phases/01-federation-mesh-hardening/01-CONTEXT.md` — the scope fence: do not touch federation trust or join cryptography beyond what removal and sync correctness require, and no data-destroying migrations. Review each area in turn and add its findings to the document. For each codebase-concerns claim, do the fresh read plus `git log -p` on the cited range BEFORE filing or dismissing it, and put that evidence in the row — a finding that merely restates a concerns bullet without fresh evidence is not admissible.
Areas to cover, each of which must appear in the document even when it produced no findings —
record those as reviewed with none rather than omitting them: federation store, federation sync,
federation RPC surface, FIPS and transport dial, mesh core, mesh RPC surface.

Required specific checks, each of which becomes a row:
- The mock-parity residual class flagged in the plan 01-02 SUMMARY (a mock case that exists but
  returns a differently-shaped success object than the daemon).
- Whether the paid-tick grep from plan 01-03 still finds exactly the two surfaces it found at
  planning time, or whether a third has appeared.
- The unbounded-curl concern: confirm it belongs to the multinode test harness and defer it to
  the phase that owns that requirement, with that phase named in the reason.
- The node-list dedup scaling note: disposition it with the peer counts this fleet actually runs.
- The mesh radio configuration boot race: confirm against current code and defer if it needs real
  LoRa hardware, naming that as the reason.

Fix findings that are contained — a bounded change inside the reviewed area with a test — and
commit each as its own focused commit per CLAUDE.md. Defer anything that would breach the
CONTEXT.md scope fence, require hardware this session lacks, or belong to another phase, and write
the reason and the owner in the row. Every row ends with exactly one disposition.

Finish with a short summary section stating the counts: findings filed, fixed, already-fixed, and
deferred; and a line stating that the counts sum to the number of rows.
cd core && cargo test -p archipelago && cd ../neode-ui && npx vitest run && node scripts/mock-rpc-parity.mjs - `cd core && cargo test -p archipelago` exits 0. - `cd neode-ui && npx vitest run` exits 0 and `node scripts/mock-rpc-parity.mjs` exits 0. - Every row in `01-REVIEW-FINDINGS.md` has a non-empty disposition cell — verify by counting rows and counting non-empty disposition cells and asserting the two numbers match; record both numbers in the SUMMARY. - All six named areas appear in the document. - The summary section's counts sum to the row count. - Every `fixed` row cites a commit hash and a verifying command or test name. - Every `deferred` row has a non-empty reason and names an owning phase or requirement. Both areas are reviewed, every finding has exactly one evidenced disposition, and the contained fixes are committed. Task 3: Build and deploy the phase to the dev pair, sha256-verified archi-dev-box and x250-dev are reachable over the fleet network — confirm with a bounded connectivity probe to each before starting; if either is unreachable, halt rather than deploying to a partial pair. .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md - `scripts/deploy-to-target.sh` — the established deploy path and the environment variable it takes for the target. Read it fully before running it; do not hand-roll a deploy. - `CLAUDE.md` — the build instructions (cargo from `core/`; frontend build outputs to `web/dist/neode-ui/`; grep the built bundle for new strings because the build can silently no-op) and the deploy discipline (dev pair before any OTA). - The project memory note on deploying via service restart while containers are running — confirm what the deploy script does about restarts before running it, and record the answer. Build the backend from `core/` and the frontend from `neode-ui/`, then grep the built frontend bundle for a string introduced by this phase to prove the build is not stale.
Deploy to archi-dev-box and then to x250-dev using the established deploy script, one at a time.
After each, verify the deployed binary's sha256 matches the locally built artifact, and record
both hashes. After each deploy, check that the node's app containers are still running and record
the result — a deploy that takes containers down is a finding, not a success.

Add a short deployment section to `01-REVIEW-FINDINGS.md` recording: the built artifact hashes,
the two target hostnames, the per-target sha256 match, the container-survival result, and the
frontend bundle grep result.

Do not deploy to any other fleet node, do not cut a release, and do not publish an OTA — this
phase ends at the dev pair plus the verification in plan 01-10.
grep -Eq 'sha256' .planning/phases/01-federation-mesh-hardening/01-REVIEW-FINDINGS.md - `cd core && cargo build --release -p archipelago` exits 0 and `cd neode-ui && npm run build` exits 0. - The built frontend bundle contains a string introduced by this phase — assert with a grep over `web/dist/neode-ui/assets/` for the badge ring class name added in plan 01-03. - The deployment section records two target hostnames, two sha256 pairs that match, and a container-survival result per target. - No release tag was created and no OTA manifest was published — confirmed by `git tag --points-at HEAD` producing no output, recorded in the SUMMARY. The phase's code is running on both dev-pair nodes, provably the artifact that was built, with containers intact.

<threat_model>

Trust Boundaries

Boundary Description
developer workstation → fleet node (deploy) A built binary crosses onto a live node over SSH
review process → codebase A fix applied during review changes federation trust-adjacent code

STRIDE Threat Register

Threat ID Category Component Severity Disposition Mitigation Plan
T-01-37 Tampering a deployed binary differing from the one built and tested high mitigate Per-target sha256 comparison against the local artifact, both hashes recorded (Task 3)
T-01-38 Denial of Service a deploy restarting the service and killing running app containers high mitigate The established deploy script is read before use and container survival is checked and recorded per target; a container loss is filed as a finding
T-01-39 Elevation of Privilege a review fix loosening federation trust or join verification high mitigate CONTEXT.md's scope fence is a required read; findings needing trust-code changes are deferred with the reason rather than patched here; the full test suite gates each fix
T-01-40 Repudiation a finding quietly dropped so a known issue leaves no trace medium mitigate The row-count-equals-disposition-count check and the summing counts section make an omission detectable; the prohibitions above state the rule
T-01-41 Information Disclosure deploy credentials or node passwords committed while recording deployment evidence high mitigate The deployment section records hostnames and hashes only; per CLAUDE.md, never commit secrets. Stage by explicit path and review the diff before committing
</threat_model>
- `cd core && cargo test -p archipelago` — green. - `cd neode-ui && npx vitest run && node scripts/mock-rpc-parity.mjs && npm run build` — green. - `01-REVIEW-FINDINGS.md` row count equals its disposition count, and the summary counts sum to it. - Both dev-pair nodes report a matching sha256 and surviving containers.

<success_criteria>

  • A findings document covers six named areas, including those with no findings.
  • Every finding has exactly one evidenced disposition; fixed rows cite commit and test, deferred rows cite reason and owner.
  • Every codebase-concerns federation/mesh claim was re-verified against current code and git history before being filed or dismissed.
  • The phase is deployed to the dev pair, sha256-verified, with containers intact and no release cut. </success_criteria>
Create `.planning/phases/01-federation-mesh-hardening/01-09-SUMMARY.md` when done. Stage by explicit path, commit each fix separately, and `git push gitea-ai main`.