From 3a59953c87512ad3c28e7ad92e53e9e1ce360faa Mon Sep 17 00:00:00 2001 From: archipelago Date: Wed, 29 Jul 2026 13:57:47 -0400 Subject: [PATCH] =?UTF-8?q?docs(quick-260729-hj1):=20peer-files=20media=20?= =?UTF-8?q?batch=20=E2=80=94=20summary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../260729-hj1-SUMMARY.md | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .planning/quick/260729-hj1-peer-files-media-batch-wavlake-paid-trac/260729-hj1-SUMMARY.md diff --git a/.planning/quick/260729-hj1-peer-files-media-batch-wavlake-paid-trac/260729-hj1-SUMMARY.md b/.planning/quick/260729-hj1-peer-files-media-batch-wavlake-paid-trac/260729-hj1-SUMMARY.md new file mode 100644 index 00000000..ca2c5ceb --- /dev/null +++ b/.planning/quick/260729-hj1-peer-files-media-batch-wavlake-paid-trac/260729-hj1-SUMMARY.md @@ -0,0 +1,89 @@ +--- +phase: quick-260729-hj1 +plan: 01 +subsystem: demo / peer-files +status: complete +requirements: [A1, A2, A3, A4, A5, A6, A7, A8] +key-files: + created: + - "demo/content/music/Zazawowow - WEBFIVEFOURTHREETWOONE.mp3 (6,041,903 B, MPEG audio)" + - "demo/content/music/Zazawowow - Michael Michael Saylor.mp3 (4,517,590 B, MPEG audio)" + - demo/peer-media/artwork-webfive.jpg (1400x1400 JPEG) + - demo/peer-media/artwork-michael-saylor.jpg (1400x1400 JPEG) + modified: + - neode-ui/mock-backend.js + - neode-ui/vite.config.ts + - neode-ui/src/views/PeerFiles.vue + - neode-ui/src/views/__tests__/PeerFilesRefresh.test.ts + - demo/peer-media/photo-*.jpg (all 10 replaced with real Wikimedia Commons photos) +commits: + - "14d1a453 feat(demo): Wavlake tracks, real photos, deduped peer catalog, working paid flow" + - "f52c5407 fix(peer-files): free-image lightbox, click-to-open routing, in-app open after every payment rail" +metrics: + duration: 64m + tasks: 3 + completed: 2026-07-29 +--- + +# Quick Task 260729-hj1: Peer-Files Media Batch (Wavlake, Paid Track, Real Photos) Summary + +Two real Wavlake tracks (paid buy->autoplay flow now delivers real mp3 bytes), seeded purchase history, deduped peer catalog, ten real Commons photographs, and a shared-frontend fix so every peer file click opens the right viewer (free images finally open in the lightbox). + +## What Was Done + +### Task 1 — Demo dataset (commit 14d1a453, demo/mock only) + +- **Wavlake tracks (A1-A3):** metadata fetched live from `catalog.wavlake.com/v1/tracks/{id}` (title/artist/album/duration confirmed against plan recon), mp3 bytes + 1400x1400 artwork downloaded from the CloudFront CDN and committed. `song-webfive` ("WEBFIVEFOURTHREETWOONE" by Zazawowow, 21 sats, PAID) and `song-michael-saylor` (free). Both verified as real MPEG audio with `file(1)`. +- **Real paid bytes (A3):** the shared `content.owned-get` / `download-peer-paid` / `-invoice` / `-onchain` handler now returns real disk bytes with the correct `mime_type` when the entry has them (text placeholder only for the fictional no-disk films/books). Ecash rail-deduction logic preserved verbatim. +- **Purchase history (A4):** per-session `sessionOwnedContent()` store lazily seeds 3 dated purchases (song-builders 100 sats — audio with real bytes; film-the-signal 2100; book-cypherpunk-essays 210), computed against the session's own federation onions/catalog slices. Every purchase path appends, so Owned badges survive the post-purchase `loadOwned()` refresh. `song-builders` was converted from free to paid (100 sats) so the seeded history contains a playable paid audio item without pre-owning the showcase Wavlake track. +- **Dedupe (A5):** `peerCatalogFor` is now a deterministic one-peer-per-item assignment (index % 12 against the session's node order) plus a 3-item POPULAR list (`song-webfive`, `film-block-height`, `photo-aurora-fjord`) that appears on exactly one extra peer each. Verified: 29/29 ids present, exactly 3 duplicated ids, both Wavlake tracks on trusted peers. +- **Session-stable onions:** `demoFederationNodes()` was regenerated (fresh random onions) on every RPC call; it is now memoised per session (`sessionFederationNodes()`) so catalogs, owned records and the Federation view agree. +- **Real photos (A6):** all ten `photo-*.jpg` picsum placeholders replaced with real Wikimedia Commons photographs (aurora over Lofoten fjord, Lago di Limides/Dolomites, Dotonbori Osaka neon, Erg Chebbi dunes, Black Forest mist, Cliffs of Moher, Iceland winter road, Stowe VT autumn, St Ives harbour, Grindelwald ridge hiker). Each is >=1920px wide, visually inspected, license-credited in its description; `size_bytes` updated to real sizes; filenames kept so `PEER_MEDIA` refs are unchanged. +- **Streaming route:** new `GET /api/peer-content/:onion/:content_id` serving `entry.disk` via `res.sendFile` (Range/206 works — probed). Whitelist lookup only (T-hj1-03), paid entries return 403 so full paid bytes are unreachable without purchase. Demo nginx already proxies `/api/` -> :5959; added the missing `/api` proxy to the vite dev config so dev works too. +- **Paid audio preview:** `content.preview-peer` serves a ~10% leading slice of the real mp3 for audio entries (the Preview button plays it), images unchanged. + +### Task 2 — Shared viewer routing (commit f52c5407, both builds) + +- **A8 fix + A7 routing:** card click goes through `openItem()`: owned -> cached viewer/bottom bar; paid playable -> 10% preview; paid non-playable -> pay modal (image never fetched pre-purchase, T-hj1-04); free image -> existing Teleport-to-body viewer as a lightbox with `viewerUrl` pointed at the stream URL (no base64 round-trip); free audio/video -> `playMedia` (bottom bar / video modal). +- **Viewer footer:** "Owned · unlocked" (green) only for owned items; "Free · shared by peer" (neutral) otherwise — also the bundle-grep sentinel. Save button streams free files (`streamDownload`) instead of calling `content.owned-get`. +- **Unified post-payment:** `payWithLightning`, `pollInvoice` and `pollOnchain` now share `openPurchased()` with the ecash flow — mark owned, refresh owned list, audio autoplays in the bottom bar, image/video open in the viewer. `triggerDownload` remains for the explicit Save path. +- **Blob-URL hygiene:** `releaseViewerUrl()` only revokes `blob:` URLs (free items use plain URLs). +- Preview-thumbnail watcher deliberately NOT extended to audio (real nodes return audio bytes there). Cloud.vue/CloudFolder.vue verified to already open free images via MediaLightbox — untouched. +- Regression test added: free image click opens the lightbox. + +### Task 3 — Verification + +- Full unit suite: **697/697 passed** (baseline in plan said 195; suite has since grown — all green). +- `npm run build` (vue-tsc + vite): success; `grep -rl "Free · shared by peer" web/dist/neode-ui/assets/` hits `PeerFiles-DsotBwvS.js` (build did not no-op). +- Mock RPC smoke (20 checks, all pass): browse-peer aggregation contains both Wavlake titles; paid purchase deducts 21 sats ecash and returns `audio/mpeg` >1MB; purchase appended to owned-list; `/api/peer-content` answers 206 to a Range probe, 403 for paid items, 404 for unknown/traversal ids; paid audio preview is audio bytes; image previews still jpeg. +- `grep -rn "146.59.87.168" neode-ui/mock-backend.js demo/` — empty (T-hj1-02). +- Git: two focused code commits, nothing staged under `indeedhub/`, only other agents' pre-existing untracked files remain. + +## Deviations from Plan + +**1. [Rule 3 - Blocking] Session-memoised federation nodes.** The plan assumed onions were "random per session"; they were actually random per RPC call, which would have made seeded owned-content onions never match what the frontend sees. Added `sessionFederationNodes()` memoisation (per-visitor via the existing session store). Commit 14d1a453. + +**2. [Rule 2 - Missing critical] `/api` dev proxy in vite.config.ts.** The demo nginx proxies `/api/` to the mock, but the vite dev server did not — the new route (and the existing `/api/blob`, `/api/app-catalog`) would 404 on :8100 dev. Added a `/api` proxy entry (dev-server-only config; real nodes use nginx). Commit 14d1a453. + +**3. [Minor scope choice] `song-builders` converted free -> paid (100 sats).** The plan required a seeded audio purchase backed by real disk bytes, but the only paid audio item is the showcase Wavlake track, which must NOT be pre-owned (it would kill the A3 buy demo). Making one existing song paid provides a legitimately purchasable audio item for the seeded history and an Owned-badge example in the gallery. + +## Post-Deploy Live Checklist — http://146.59.87.168:2100 (orchestrator deploys) + +1. **Search (A1/A2):** Cloud -> search "Zazawowow" (or "WEBFIVE" / "Michael") — both tracks appear as peer-file results. +2. **Paid buy -> autoplay (A3):** open the peer holding "Zazawowow - WEBFIVEFOURTHREETWOONE.mp3" (21 sats), Buy -> ecash -> Pay: the bottom GlobalAudioPlayer bar appears and the track audibly plays; card flips to green "Owned". +3. **Preview before buying (A3):** the paid track's Preview button plays ~25s of real audio, not silence/artwork. +4. **Paid Files tab (A4):** Cloud -> Paid Files shows 3+ seeded purchases with sats + dates; clicking "Builders, not talkers (Remastered).mp3" plays it in the bottom bar; the fresh Wavlake purchase from step 2 is now listed too. +5. **Dedupe (A5):** browsing several peers, each file appears on ~1 peer; only 3 files (WEBFIVE track, Block Height film, aurora photo) appear on two. +6. **Real photos (A6):** photo cards show real photographs (aurora, Dolomites lake, Osaka neon, dunes, mist, cliffs, Iceland road, Vermont autumn, St Ives, Grindelwald) — no picsum grey placeholders. +7. **Free image lightbox (A8):** clicking any photo card opens the full-screen viewer with backdrop; footer reads "Free · shared by peer"; Save downloads it. +8. **Free audio/video (A7):** clicking "Zazawowow - Michael Michael Saylor.mp3" (free) plays in the bottom bar; a free video (if on the browsed peer) opens the video modal. +9. **Paid gating (A7):** a blurred paid image click opens the pay modal, never the image; paying via the Lightning QR path also opens the content in-app (no orphan browser download). + +## Self-Check: PASSED + +- demo/content/music/Zazawowow - WEBFIVEFOURTHREETWOONE.mp3 — FOUND (MPEG audio) +- demo/content/music/Zazawowow - Michael Michael Saylor.mp3 — FOUND (MPEG audio) +- demo/peer-media/artwork-webfive.jpg, artwork-michael-saylor.jpg — FOUND (JPEG) +- All 10 demo/peer-media/photo-*.jpg — FOUND (JPEG, >=1920px wide) +- Commit 14d1a453 — FOUND in git log +- Commit f52c5407 — FOUND in git log