itsgoin/project-notes-from-elitebook.md
Scott Reimers 800388cda4 ItsGoin v0.3.2 — Decentralized social media network
No central server, user-owned data, reverse-chronological feed.
Rust core + Tauri desktop + Android app + plain HTML/CSS/JS frontend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 20:23:09 -04:00

5.2 KiB

Project Notes from EliteBook (sologretto-HP-EliteBook-840-G3)

Last updated: 2026-03-14

These notes capture practical knowledge learned during development that isn't in CLAUDE.md. Other Claude instances: read this to avoid re-learning things the hard way.

CRITICAL: Git + Nextcloud

The git repo lives inside a Nextcloud-synced folder. Nextcloud IS the git transport between machines. NEVER run git commands without confirming with the user that Nextcloud sync is paused. After git operations, ALWAYS remind the user to restart Nextcloud sync. Violating this can corrupt the repo.

User Preferences

  • Terse responses, no trailing summaries — user can read diffs
  • cargo tauri dev reports "completed" when compilation finishes but the app is STILL RUNNING (~45s startup). Don't say it closed.
  • Session relay is OPT-IN ONLY and DISABLED BY DEFAULT. Never enable it as a fallback.
  • The canonical design document is website/design.html. Consult it FIRST using the section index below.

design.html Section Index

Read targeted sections with Read(file_path="website/design.html", offset=LINE, limit=RANGE). Lines shift when edited — grep for section ID if not found.

Lines Section ID Topic
152-175 nplus10 N+10 Identification — preferred peers in profile
176-234 connections Connections & Growth — 101 slots, growth loop
235-300 lifecycle Connection Lifecycle — connect cascade (7 steps)
301-335 layers Network Knowledge Layers — N1/N2/N3
356-437 anchors Anchors — detection, registration, self-verification
454-586 relay Relay & NAT Traversal — hole punch, sessions, NAT types
679-713 worm Worm Search — burst/nova, content search, PostFetch
864-941 files File Layer — blobs, CDN manifest, hosting tree, eviction
942-1030 sync Sync Protocol — pull sync, push, engagement propagation
1020-1089 encryption Encryption — envelope, group keys, circles
1216-1314 share-links Share Links — QUIC proxy, itsgoin.net handler

iroh 0.96 API Gotchas

  • endpoint.connect(addr, alpn) — addr is EndpointAddr, not NodeAddr
  • EndpointId::from_bytes(&[u8; 32]) — fallible, returns Result
  • endpoint.id() not .endpoint_id()
  • endpoint.direct_addresses() is a stream, use .next().await
  • connection.remote_endpoint_id() not .remote_node_id()
  • Module: iroh::endpoint::Connection, iroh::EndpointId, iroh::EndpointAddr
  • Version pins required: curve25519-dalek = "=5.0.0-pre.1", ed25519-dalek = "=3.0.0-pre.1"
  • Crypto: use rand::rng() not OsRng (iroh re-exports conflict)

Bugs Fixed (DO NOT REINTRODUCE)

  1. IPv6-only DNS blocks mobile — Always use all addresses (v4 + v6), never filter to just one family
  2. Mesh peer addresses not persisted — Must call upsert_peer() after connection, not just in-memory
  3. Target-side hole punch discarded — Register hole-punch results as sessions, not dropped
  4. IPv4-mapped IPv6 breaks connectivity — Use normalize_addr() everywhere
  5. Stale anchor addresses block reconnect — Update from fresh DNS, not cached
  6. Session peers invisible to relayremote_addr field required on SessionConnection
  7. Sequential hole punch wastes 30s — Use hole_punch_parallel() for all attempts
  8. Requester sends unfiltered IPs in relay intro — Filter via is_publicly_routable()

Technical Lessons

  • rusqlite Storage is NOT Send/Sync — always access behind Arc<Mutex<Storage>>
  • QUIC CONNECTION_CLOSE can race with stream reads — handle gracefully
  • Tauri: withGlobalTauri: truewindow.__TAURI__.core.invoke()
  • Tauri: shared tokio runtime via tauri::async_runtime::set()
  • Desktop data dir: ~/.local/share/itsgoin/ (or next to AppImage executable)
  • Connect string format: <64-hex-node-id>@<ip:port>
  • WebKitGTK needs GStreamer codec packages for video (gstreamer1.0-plugins-bad/ugly/libav)
  • Asset protocol needs protocol-asset feature in Cargo.toml + assetProtocol scope in tauri.conf.json

Web Handler (itsgoin.net)

  • Must fetch posts ON-DEMAND via QUIC, not rely on local sync
  • Apache reverse proxy in ~/domains/itsgoin.net/public_html/.htaccess forwards /p/* and /b/* to localhost:8080
  • Tiered serving: redirect to HTTP holder → TCP punch → QUIC proxy fallback
  • Anchor process: /home/itsgoin/bin/itsgoin /home/itsgoin/itsgoin-anchor-data --bind 0.0.0.0:4433 --daemon --web 8080

Deploy Procedures

  • APK signing: keystore itsgoin.keystore, alias itsgoin (password in local credential file)
  • Anchor deploy: build release CLI → scp to server → stop/swap/start (see local deploy notes)
  • Website: scp to server ~/public_html/
  • Creds: in local credential file (not in repo)

Current Engagement Architecture (v0.3.2)

  • BlobHeaderDiff (0xD0) flows both upstream and downstream through CDN tree
  • post_upstream table tracks who each post was received from
  • Auto downstream registration on pull sync and push notification
  • Pull cycle (5 min) fetches engagement headers as safety net
  • Reactions/comments: store_reaction upserts, store_comment inserts with ON CONFLICT DO NOTHING (additive merge)
  • Planned: pull engagement from both upstream AND downstream peers