2211 Commits

Author SHA1 Message Date
archipelago
f17a805654 docs(02): resolve research open questions and backfill validation strategy 2026-07-30 04:56:54 -04:00
archipelago
db18532e12 docs(02-ui-performance): create phase plan — 8 plans, 5 waves 2026-07-30 04:48:31 -04:00
archipelago
abba457e50 docs(phase-2): add validation strategy 2026-07-30 04:11:18 -04:00
archipelago
350c06bcaf docs(02-ui-performance): research phase domain
Codebase-grounded research for KeepAlive/SWR caching, serial-waterfall fixes,
and the AIUI D-14 ride-along dependency risk.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 04:10:32 -04:00
archipelago
2f99db5e6b fix(01-01): serialize federation node-store writes, close remove-vs-sync race (FED-01)
- Add FEDERATION_STORE_LOCK (tokio::sync::Mutex<()>) guarding every
  load-mutate-save cycle in federation/storage.rs, closing the race where
  the 90s auto-sync loop's stale pre-removal snapshot could silently
  re-save a peer the operator just removed (no error logged anywhere).
- Split load_nodes/save_nodes/tombstone_did/untombstone_did into thin
  locked outer wrappers + lock-free *_inner bodies so remove_node and
  add_node can hold the guard across their whole tombstone+save critical
  section without self-deadlocking (Mutex is not re-entrant).
- Route load_nodes, save_nodes, remove_node, add_node, tombstone_did,
  untombstone_did, set_trust_level, and update_node_state through the
  lock (set_trust_level pulled forward from Task 2's scope — required for
  test_concurrent_writes_do_not_lose_updates, part of Task 1's own
  required-green test suite, to pass; documented in SUMMARY).
- Convert save_nodes_inner to an atomic write: serialize to a sibling
  nodes.json.tmp in the same directory, then tokio::fs::rename onto the
  real path, so a crash mid-write never leaves a partially-written
  nodes.json for a concurrent reader.
- Add 3 new regression tests, two of which are fail-first proven: heavy
  tokio::spawn-based concurrency (not just tokio::join!, since
  remove_node's extra tombstone I/O hop structurally biased a simple
  2-task race toward the safe ordering) reliably reproduced both the lost
  concurrent write and the removed-node-reappears bug pre-fix; both are
  green post-fix along with the existing suite (13/13).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 04:04:08 -04:00
archipelago
2d9625ca74 docs(state): record phase 2 context session 2026-07-30 03:50:19 -04:00
archipelago
284f6fce39 docs(02): capture phase context 2026-07-30 03:50:18 -04:00
archipelago
7487aba2c2 docs(quick-260729-je5,hj1): summaries + state for UI-fixes and media batch
All checks were successful
Demo images / Build & push demo images (push) Successful in 4m55s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 14:20:06 -04:00
archipelago
d54517cf0b fix(demo): companion app skips the demo intro — lands straight on /login
When the demo build runs inside the Android companion WebView
(window.ArchipelagoNative bridge, detected via the existing
isCompanionApp()), all four IS_DEMO intro branch sites now skip the
typing splash and /onboarding/intro and route directly to /login, as if
the intro was already seen:
- App.vue root-boot replay request (companion never requests the splash)
- App.vue post-splash demo routing
- RootRedirect proceedToApp() and the server-up onMounted demo branch

The skip paths write nothing to localStorage/sessionStorage (RootRedirect
skips even its boot log() there), so the browser/PWA demo intro — which
replays on every fresh root boot — is byte-identical to before, and
non-demo builds short-circuit on IS_DEMO before isCompanionApp() runs.
Adds a small isCompanionApp() bridge-detection unit test (700 tests green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 14:11:12 -04:00
archipelago
b80e7c3487 fix(web5): connected-nodes list fills card height on xl — constant gap above footer buttons
The three tab panes (Trusted/Observers/Requests) were hard-capped at
max-h-72 with an mt-auto footer, so a tall sibling Node Visibility card
stretched the shared xl grid row and opened a growing dead gap between
the list end and the Find Nodes / Refresh buttons. The panes are now the
flexible middle of the card's column flex (flex-auto min-h-0, cap lifted
at xl via xl:max-h-none) so the gap is always exactly the footer's pt-4;
below xl the max-h-72 cap and current sizing are unchanged. Footer gets
shrink-0 so buttons can never be compressed by a long list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 14:04:17 -04:00
archipelago
b8243000e9 docs(260729-je5): pre-dispatch plan for connected-nodes margin + companion intro skip
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 14:02:44 -04:00
archipelago
3a59953c87 docs(quick-260729-hj1): peer-files media batch — summary
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 13:57:47 -04:00
archipelago
f52c540744 fix(peer-files): free-image lightbox, click-to-open routing, in-app open after every payment rail
- Card click now dispatches through openItem(): owned -> cached viewer,
  paid+playable -> 10% preview, paid non-playable -> pay modal (image is
  never fetched pre-purchase), FREE image -> full-screen lightbox streaming
  from /api/peer-content (fixes the click no-op where the old ternary fell
  through to undefined for non-playable free items)
- Viewer footer caption is state-aware: green 'Owned · unlocked' only for
  owned items, neutral 'Free · shared by peer' for free ones; Save streams
  free files instead of calling content.owned-get
- Lightning / invoice-QR / on-chain payment successes now share
  openPurchased() with the ecash flow: mark owned, autoplay audio in the
  bottom bar or open image/video in the viewer (previously a browser
  download that silently fails on the mobile companion)
- closeViewer only revokes blob: URLs (free items use plain stream URLs)
- Added a regression test: free image click opens the lightbox

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 13:51:36 -04:00
archipelago
14d1a453c7 feat(demo): Wavlake tracks, real photos, deduped peer catalog, working paid flow
- Two real Zazawowow tracks from Wavlake (metadata via catalog API, bytes +
  artwork committed): WEBFIVEFOURTHREETWOONE is the showcase PAID track
  (21 sats), Michael Michael Saylor is free
- Paid/owned downloads now return real file bytes with the correct mime_type
  (was a text/plain placeholder) so buying a song autoplays in the bottom bar
- content.owned-list seeded per session with dated purchases matching the
  session's federation onions; every purchase path appends to it so Owned
  state survives the post-purchase refresh (Paid Files tab now populated)
- peerCatalogFor: deterministic one-peer-per-item assignment + 3 POPULAR
  duplicates (was ~25% of items duplicated onto every third peer)
- demoFederationNodes memoised per session so catalogs/owned records/UI agree
- content.preview-peer serves a real audio slice for audio items (paid
  preview button plays music, not artwork bytes)
- New GET /api/peer-content/:onion/:content_id Range-capable streaming route
  (whitelist lookup, paid items 403) + /api dev proxy in vite.config.ts
- All ten photo-*.jpg picsum placeholders replaced with real Wikimedia
  Commons photographs (credited in each description, >=1920px wide)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 13:41:17 -04:00
archipelago
dcef3cb1bd docs(260729-hj1): pre-dispatch plan for peer-files media batch
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:49:31 -04:00
archipelago
d8903ad5f3 docs(quick-260729-gjd): demo IndeeHub iframe + signer + preinstall — summary + state
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:36:39 -04:00
archipelago
d00ca6242c feat(demo): IndeeHub pre-installed and running on fresh demo sessions
Add an indeedhub entry to staticDevApps in mock-backend.js (state running,
lanPort 8190, existing marketplace title/description/icon). Per-visitor
demo state is structuredClone(staticDevApps), so every fresh session shows
IndeeHub installed in My Apps with no install step. The demo launch URL
bypasses /app/indeedhub/ entirely (iframe loads the :2101 whole-origin
proxy), so no DEMO_APP_PAGES placeholder is added; marketplace metadata
already lists indeedhub following the same pattern as the other static
apps, and uninstall is blocked for static demo apps as usual.

Verified: mock-backend.js boots with DEMO=1 and the /ws/db initial dump of
a fresh session contains indeedhub state=running.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:34:08 -04:00
archipelago
66d540f8b5 feat(demo): launch IndeeHub in the in-app iframe via the :2101 proxy
- useDemoIntro: replace DEMO_EXTERNAL_URLS (external-tab workaround) with
  DEMO_PROXY_PORTS; demoAppUrl('indeedhub') now resolves to
  <protocol>//<current-hostname>:2101/ at runtime (no hardcoded host/IP);
  isDemoExternal returns false (kept exported so call sites compile
  unchanged); isDemoApp still true for indeedhub so the NEW_TAB bypass
  keeps it in the in-app session
- useAppIdentity: suppress the identity-picker modal under IS_DEMO — the
  embedded IndeeHub is already signed in via the seeded throwaway demo
  account; real-node picker behavior untouched (IS_DEMO compile-time false)

Verified: 195 unit tests green (IS_DEMO=false path); VITE_DEMO=1 build
bundle contains the :2101 launch logic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:28:21 -04:00
archipelago
69bc3d3f27 feat(demo): whole-origin IndeeHub proxy on :2101 with sign-in seeding
- nginx-demo.conf: new :2101 server block reverse-proxying the live
  indee.tx1138.com site with no path prefix (fixes the old sub_filter
  path-rewrite breakage), X-Frame-Options/CSP stripped, WS upgrade
  passthrough, and a demo sign-in script injected into <head>
- indee-demo-signin.js: PUBLIC-DEMO-ONLY seeder that writes a labelled
  throwaway "nsec" account (freshly generated keypair, not a secret) into
  the :2101 origin's indeedhub-accounts/indeedhub-active-account
  localStorage keys, idempotently, so IndeeHub boots signed in
- Dockerfile.web: copy the seeder into the demo web image, EXPOSE 2101
- docker-compose.demo.yml + demo-deploy/docker-compose.yml: publish 2101
  (DEMO_INDEE_PORT override documented in the thin deploy stack)

Verified: nginx -t clean in nginx:alpine; live proxy smoke shows 200 with
no framing headers, injected tag, seed script served, assets proxied.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:23:18 -04:00
archipelago
e2278ad518 docs: record session state — Phase 1 planned 2026-07-29 12:22:25 -04:00
archipelago
e52f458c12 docs(01): plan-checker fixes — 01-06 depends_on 01-04; lifecycle-gate step in 01-10 2026-07-29 12:20:37 -04:00
archipelago
bf96378d67 docs(01): create Phase 1 federation & mesh hardening plans (10 plans, 6 waves) 2026-07-29 12:16:39 -04:00
archipelago
db25545a9a docs(260729-gjd): pre-dispatch plan for demo IndeeHub iframe + signer + preinstall
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:13:21 -04:00
archipelago
2e54c3e40c docs(01): UI design contract — probe dismissal row for ring long-text 2026-07-29 11:41:00 -04:00
archipelago
6e2c8d7410 fix(apps): drop IndeeHub open-fullscreen default — opens as panel like other apps
All checks were successful
Demo images / Build & push demo images (push) Successful in 4m38s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 11:40:26 -04:00
archipelago
5bffba034e docs(quick-260729-fw7): mesh hop graphic redesign — summary + state
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 11:38:27 -04:00
archipelago
cb58a06d4b docs(01): revise UI-SPEC typography contract 2026-07-29 11:38:15 -04:00
archipelago
ac09fc5ded feat(mesh): redesign hop-route visualization — branded, animated, vertical on mobile
- New self-contained HopVizModal.vue (Teleport to body): 560px balanced panel,
  glowing endpoint medallions ringed with EQ segments (ScreensaverRing motif),
  per-transport accent track with staggered relay markers and an animated
  packet traveling sender → recipient
- Vertical stacked chain below 560px (sender top → recipient bottom, packet
  travels downward); prefers-reduced-motion disables all loops
- Accent colors match the chat transport pills exactly (meshtastic mint,
  meshcore orange, reticulum blue, lora amber, fips violet, tor indigo)
- Tor (3 anonymous relays), FIPS (direct P2P) and unknown-transport shapes
  preserved, as are SNR/RSSI + E2E/delivery metadata (now glass chips)
- Old inline modal markup removed from Mesh.vue; .mesh-hopviz-* rules removed
  from mesh-styles.css (shared transport-modal classes untouched)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 11:36:45 -04:00
archipelago
4e9741b013 docs(phase-1): UI design contract for FED-05/FED-06 2026-07-29 11:33:25 -04:00
archipelago
9432f42acc docs(260729-fw7): pre-dispatch plan for hop graphic redesign
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 11:30:16 -04:00
archipelago
c31d99e49f docs(phase-1): correct FED-05 scope — meshed peers with lightning, not lnd listpeers 2026-07-29 11:28:43 -04:00
archipelago
c899ab3591 docs(phase-1): capture FED-05 scope decision (connected peers) in CONTEXT.md 2026-07-29 11:27:34 -04:00
archipelago
1618a3ac53 docs(phase-1): add validation strategy 2026-07-29 11:25:30 -04:00
archipelago
b938449cbc docs(phase-1): federation/mesh hardening research
Codebase-derived research for Phase 1 (FED-01..06): identifies an
unlocked concurrent read-modify-write race on federation/nodes.json
as the likely root cause of nodes reappearing after removal, flags
two stale CONCERNS.md claims already fixed on main (01cbec27), maps
remaining mesh demo-parity gaps (contacts-list/save, reaction/edit/
delete stubs) beyond the already-shipped attachment-send parity fix
(c2ce71c6), and scopes the greenfield Lightning-URI/channel-open
surface needed for FED-05.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 11:24:09 -04:00
archipelago
b4acb34624 docs: add FED-06 on-brand paid-tick animation (screensaver ring + EQ segments) to Phase 1 2026-07-29 11:11:35 -04:00
archipelago
c2ce71c680 fix(demo): mesh attachment send parity with real nodes
All checks were successful
Demo images / Build & push demo images (push) Successful in 5m44s
Demo attach flow failed with 'Method not found: mesh.send-content-inline'
and force-opened the transport chooser modal real nodes don't show.

- mesh.transport-advice now mirrors the daemon's size-based tier logic
  (typed_messages.rs): chooser only in the fits-both 1-2.3KB band
- implement mesh.send-content-inline / send-content / fetch-content and
  POST /api/blob; bytes live in the per-visitor session store
- sent texts + attachments persist in mesh.messages so refresh-after-send
  shows them, same as a real node

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 11:03:21 -04:00
archipelago
8c2a55eb4c docs: add FED-05 inter-node lightning channel-open UX to Phase 1 2026-07-29 10:59:48 -04:00
archipelago
07b167d68e docs: insert Phase 1 federation/mesh hardening + Phase 2 UI performance; renumber 3-8 2026-07-29 10:59:08 -04:00
archipelago
21de734385 docs(qr): scanner snappiness research + companion-dev handover; 10/s native decode
All checks were successful
Demo images / Build & push demo images (push) Successful in 4m16s
Research findings and a concrete split of work: web-side items for this
repo (pre-warm camera, torch toggle, continuous focus, keep-stream-
alive) and a native handover list for the companion dev (pre-warmed
CameraX + ML Kit, QR-only format, 720p keep-latest analysis, torch,
zoom nudge, haptic dismiss) with acceptance criteria and how to
measure. Quick win landed now: live scan runs at 10 scans/sec when the
platform has a native BarcodeDetector, keeping 4/s only for the
JS-worker fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 10:51:39 -04:00
archipelago
8bea3707ca feat(lightning): instant pay feedback, balances never vanish mid-payment
Some checks failed
Demo images / Build & push demo images (push) Failing after 4m20s
Framework-pt report: a paid invoice stalled the UI with no success
shown, and lightning/total balances disappeared until it settled.
Three compounding causes, three fixes:

- Backend payinvoice's synchronous wait drops 120s → 8s. Fast payments
  (the majority) still settle in one round trip; slow multi-hop routes
  return pending + payment_hash quickly and the caller's 3s poll takes
  over — instead of the modal freezing for up to two minutes.
- payLightningInvoice gains an onPending hook: SendBitcoinModal and the
  scan modal now flip to a visible "Settling…" success pane the moment
  the payment goes pending (safe to close), and the ongoing poll
  upgrades it to Paid — or replaces it with LND's real failure.
- One slow lnd.getinfo poll (5s budget) flipped the Home wallet card to
  "disconnected", hiding balances the user already knew. Three
  consecutive failures are now required (~30s) before the card gives up;
  last-known balances keep rendering throughout.

rpc-client tests 75/75.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 10:47:39 -04:00
archipelago
b7310ecfaf docs: create onboarding summary 2026-07-29 10:46:33 -04:00
archipelago
938dfb1453 docs: ingest 11 docs from docs/ (#2387) 2026-07-29 10:45:57 -04:00
archipelago
49ec294dea fix(update): concurrent apply reads as progress, not failure; idle-IO extraction
All checks were successful
Demo images / Build & push demo images (push) Successful in 5m18s
"Another update operation is already running" surfaced as a scary
failure while the update was in fact applying fine (OptiPlex, v1.7.118
rollout). The apply path now joins the in-flight install — same
overlay, same wait-for-new-version polling — and a concurrent download
attempt shows a calm in-progress note (EN+ES strings added). The
backend's tarball extractions run under ionice -c3 nice -n10 so a
200MB update can't starve podman/status calls into multi-minute
timeouts on small disks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 10:38:11 -04:00
archipelago
00f1892bf8 feat(demo): auto-firing device-detection modal + transport pills on most peers
- ~8s into a session a second "freshly plugged" RNode appears on
  /dev/ttyACM0, so the global mesh setup modal (and its flash step)
  demos itself shortly after opening the Mesh page. Fixed plugged_at
  means "Not now" sticks for the whole browser session.
- Transport pills (LoRa/FIPS/Tor) now offered for every demo peer
  except mountain-node, which stays radio-only for contrast.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 10:36:43 -04:00
archipelago
9e77a4229c docs: map existing codebase 2026-07-29 10:25:54 -04:00
archipelago
bea7f24a4f feat(demo): mock coverage for v1.7.117/118 features
Some checks failed
Demo images / Build & push demo images (push) Failing after 3m19s
- mesh.transport-advice: peer 1 federated (LoRa/FIPS/Tor pills in the
  image modal), others radio-only.
- Scripted Flash LoRa job: flash-list-firmware + flash-device +
  flash-status advancing download → erase → write → done over ~35s
  with live log tail and percent, plus cancel.
- Demo messages carry per-message transport (meshcore/reticulum/fips/
  tor variety for the pills + animated route modal) and
  sender_pubkey/sender_seq so reactions/replies work.
- Chat-action acks: send-reaction/reply/read-receipt, edit/delete/
  forward, send-channel, mesh.refresh, reboot-radio.
- Services classification demo: self-deployed "podsteadr" stack — main
  app launchable, its MediaMTX backend (ui:null) files under Services
  with no Launch button, mirroring ui_detection's verdicts.

All verified against the running mock: 11/11 runtime checks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 10:20:41 -04:00
archipelago
14feb1feb9 chore: release v1.7.118-alpha
Some checks failed
Demo images / Build & push demo images (push) Failing after 2m19s
v1.7.118-alpha
2026-07-29 08:35:38 -04:00
archipelago
d2642856c1 chore: fold Cargo.lock version bump from v1.7.117 release
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 07:54:32 -04:00
archipelago
338bfd43a7 docs: v1.7.118-alpha changelog + What's New
Some checks failed
Demo images / Build & push demo images (push) Failing after 2m9s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 07:53:44 -04:00
archipelago
3da1d0b0f7 fix(ui): mesh unread badges persist seen-state; more button + animated route modal
Some checks failed
Demo images / Build & push demo images (push) Has been cancelled
Unread badges came back on every visit (framework showed a phantom "2"
with nothing new): unreadCounts was memory-only, so each page load
replayed the entire message history as "new". Seen-state now persists
as a per-contact highest-seen-message-id watermark in localStorage
(ids are backend-monotonic across restarts); first run after this
ships seeds the watermark from history so nobody gets a wall of stale
badges. Opening a chat advances and persists the watermark for all
twins of the merged conversation.

The hop-route modal the user asked for is now reachable from a visible
per-message "⋯" button (the transport pill remains clickable too), has
a fallback title/branch for messages that predate transport tracking,
and animates: endpoints and link reveal in sequence, a pulse travels
the link, and relay dots blink in order — all disabled under
prefers-reduced-motion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 07:52:56 -04:00