Audit fixes: key permissions, lock contention, Docker IP filter, doc updates
Security: identity.key written with 0600 permissions (Unix). Docker bridge IPs (172.17-31.x) filtered from is_shareable_addr to prevent topology disclosure in relay introductions. Lock contention: ManifestPush relay and DeleteRecord CDN notify now gather connections under lock, then send outside lock. UI: syncBtn null guard prevents crash on hidden element. Documentation: design.html version badge updated to v0.4.4. Self Last Encounter threshold corrected from 3h to 4h. Multi-Device Identity section rewritten for multi-identity-per-device (complete) + multi-device (planned) + post merge (planned). MEMORY.md updated to v0.4.4+ status. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
18a40756d8
commit
fb1e92985c
5 changed files with 85 additions and 58 deletions
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
<div class="container wide">
|
||||
<section>
|
||||
<span class="version-badge">v0.3.1 — 2026-03-13</span>
|
||||
<span class="version-badge">v0.4.4 — 2026-03-31</span>
|
||||
<h1 style="font-size: 2rem; font-weight: 800; letter-spacing: -0.03em; margin-bottom: 0.5rem;">Design Document</h1>
|
||||
<p>This is the canonical technical reference for ItsGoin. It describes the vision, the architecture, and the current state of every subsystem — with full implementation detail. This document is versioned; each update records what changed.</p>
|
||||
<div class="card" style="margin-top: 1rem;">
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
<ol style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
<li><strong>Dead connection removal</strong>: Remove connections with <code>close_reason()</code> set, or idle > 600s (zombie)</li>
|
||||
<li><strong>Stale entry pruning</strong>: N2/N3 entries tagged to a peer that is no longer connected are pruned immediately (on disconnect and on startup sweep). Age-based fallback: entries older than 7 days. Social route watchers older than 30 days.</li>
|
||||
<li><strong>Priority 0 — Preferred peer reconnection</strong>: Iterate <code>preferred_peers</code> table, reconnect any that are disconnected. If at capacity, evict the lowest-diversity non-preferred peer to make room. Prune preferred peers unreachable for 7+ days (slot released, does NOT auto-return on reconnect — must re-negotiate via MeshPrefer). After 7 days, social checkin frequency drops from 1–3 hours to daily until the 30-day reconnect watcher expires.</li>
|
||||
<li><strong>Priority 0 — Preferred peer reconnection</strong>: Iterate <code>preferred_peers</code> table, reconnect any that are disconnected. If at capacity, evict the lowest-diversity non-preferred peer to make room. Prune preferred peers unreachable for 7+ days (slot released, does NOT auto-return on reconnect — must re-negotiate via MeshPrefer). After 7 days, social checkin frequency drops from 1–4 hours to daily until the 30-day reconnect watcher expires.</li>
|
||||
<li><strong>Priority 1 — Reconnect recently dead</strong>: Re-establish dropped non-preferred connections. <strong>Skip blacklisted nodes</strong> — do not attempt reconnection to peers in <code>mesh_blacklist</code>.</li>
|
||||
<li><strong>Priority 2 — Signal growth loop</strong>: Fill remaining empty slots via growth loop</li>
|
||||
<li><strong>Idle session cleanup</strong>: Reap interactive sessions idle > 300s (5 min). Keep-alive sessions are NOT reaped by idle timeout.</li>
|
||||
|
|
@ -355,7 +355,7 @@
|
|||
<table>
|
||||
<tr><th>Layer</th><th>Purpose</th><th>Connections</th><th>Sync trigger</th></tr>
|
||||
<tr><td><strong>Mesh</strong></td><td>Structural backbone: N1/N2/N3 routing, diversity, discovery</td><td>101 mesh slots (preferred + non-preferred)</td><td>N/A — mesh is infrastructure, not content</td></tr>
|
||||
<tr><td><strong>Social</strong></td><td>Follows, audience, DMs — the human relationships</td><td>Social routes + keep-alive sessions as needed</td><td>Pull posts when Self Last Encounter > 3 hours</td></tr>
|
||||
<tr><td><strong>Social</strong></td><td>Follows, audience, DMs — the human relationships</td><td>Social routes + keep-alive sessions as needed</td><td>Pull posts when Self Last Encounter > 4 hours</td></tr>
|
||||
<tr><td><strong>File</strong></td><td>Content storage and distribution — blobs, CDN trees</td><td>Upstream/downstream file peers + keep-alive sessions as needed</td><td>Pull on blob request, push on post creation</td></tr>
|
||||
</table>
|
||||
|
||||
|
|
@ -1017,7 +1017,7 @@ FAILURE: C → B → A: AnchorProbeResult { reachable: false }</code></pre
|
|||
<div class="note">
|
||||
<strong>v0.2.0 change</strong>: Pull sync pulls posts from <strong>social layer peers</strong> (follows, audience) and <strong>upstream file peers</strong>, NOT from mesh peers. Mesh connections exist for routing diversity, not content. This separates infrastructure from content flow.
|
||||
</div>
|
||||
<p><strong>Self Last Encounter</strong>: For each peer we sync with, we track the timestamp of our last successful sync. When Self Last Encounter ages beyond <strong>3 hours</strong>, a pull sync is triggered. Self Last Encounter is updated to the newer of: (a) what's currently stored, or (b) the "file last update" timestamp from file headers received during blob transfers. Since file headers include the author's recent post list, downloading a blob from any peer hosting that author's content can update Self Last Encounter for the author.</p>
|
||||
<p><strong>Self Last Encounter</strong>: For each peer we sync with, we track the timestamp of our last successful sync. When Self Last Encounter ages beyond <strong>4 hours</strong>, a pull sync is triggered. Self Last Encounter is updated to the newer of: (a) what's currently stored, or (b) the "file last update" timestamp from file headers received during blob transfers. Since file headers include the author's recent post list, downloading a blob from any peer hosting that author's content can update Self Last Encounter for the author.</p>
|
||||
|
||||
<h3>Pull sync filtering</h3>
|
||||
<ul style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
|
|
@ -1417,22 +1417,27 @@ END</code></pre>
|
|||
|
||||
<!-- 23. Multi-Device Identity -->
|
||||
<section id="multidevice">
|
||||
<h2>23. Multi-Device Identity</h2>
|
||||
<h3>Status: <span class="badge badge-planned">Planned</span></h3>
|
||||
<h2>23. Identity Management</h2>
|
||||
|
||||
<h3>Concept</h3>
|
||||
<p>Multiple devices share the <strong>same identity key</strong> (ed25519 keypair, same NodeId). All devices ARE the same node from the network's perspective. Posts from any device appear as the same author.</p>
|
||||
|
||||
<h3>Device identity</h3>
|
||||
<p>Each device also generates a unique <strong>device identity</strong> (separate ed25519 keypair). This device-specific key is used to:</p>
|
||||
<h3>Multi-identity per device <span class="badge badge-complete">Complete</span></h3>
|
||||
<p>A single device can hold <strong>multiple identities</strong>, each with its own ed25519 keypair, database, blob store, follows, and posts. One identity is active at a time — switching performs a hot-swap (Node teardown + rebuild, ~3-5 seconds).</p>
|
||||
<ul style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
<li><strong>Find each other</strong>: Devices with the same shared identity can search for each other using their device identities to facilitate syncs and self-routing</li>
|
||||
<li><strong>Own-device relay</strong>: Route traffic through your own devices (e.g., home computer relaying for your phone) using the device identity for authentication</li>
|
||||
<li><strong>Conflict resolution</strong>: When devices post simultaneously, device identity helps order and deduplicate</li>
|
||||
<li><strong>Directory structure</strong>: <code>itsgoin-data/identities/{node_id_hex}/</code> — each identity gets its own subdirectory with <code>identity.key</code>, <code>itsgoin.db</code>, <code>blobs/</code>, and <code>meta.json</code></li>
|
||||
<li><strong>Legacy migration</strong>: Flat <code>itsgoin-data/</code> layout auto-migrates to per-identity subdirectories on first launch</li>
|
||||
<li><strong>Create, import, switch, delete</strong> via Settings UI</li>
|
||||
<li><strong>Key permissions</strong>: <code>identity.key</code> files written with 0600 permissions (Unix)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Setup</h3>
|
||||
<p>Export <code>identity.key</code> from one device, import on another. The device identity is generated automatically on each device. Once two devices share an identity key, they can discover each other through normal network routing (same NodeId appears at multiple addresses).</p>
|
||||
<h3>Multi-device identity <span class="badge badge-planned">Planned</span></h3>
|
||||
<p>Multiple devices share the <strong>same identity key</strong> (ed25519 keypair, same NodeId). All devices ARE the same node from the network’s perspective. Posts from any device appear as the same author.</p>
|
||||
<ul style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
<li><strong>Setup</strong>: Export <code>identity.key</code> from one device, import on another using the identity management UI</li>
|
||||
<li><strong>Device identity</strong>: Each device generates a unique device keypair for self-routing and conflict resolution (planned)</li>
|
||||
<li><strong>Own-device relay</strong>: Route traffic through your own devices (planned)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Post import & merge <span class="badge badge-planned">Planned</span></h3>
|
||||
<p>Import posts from another identity into the current one. Public posts imported directly. Encrypted posts require the original identity’s key for decryption, then re-encrypted under the current identity. Merge creates <strong>new posts</strong> (new PostId, new author) with original timestamps preserved and prior author noted in BlobHeader.</p>
|
||||
</section>
|
||||
|
||||
<!-- 24. Phase 2 -->
|
||||
|
|
@ -1599,7 +1604,7 @@ END</code></pre>
|
|||
<tr><td>MESH_KEEPALIVE_INTERVAL</td><td>30s</td><td>Ping to prevent zombie detection</td></tr>
|
||||
<tr><td>ZOMBIE_TIMEOUT</td><td>600s (10 min)</td><td>No activity → dead connection</td></tr>
|
||||
<tr><td>SESSION_IDLE_TIMEOUT</td><td>300s (5 min)</td><td>Reap idle interactive sessions (NOT keep-alive)</td></tr>
|
||||
<tr><td>SELF_LAST_ENCOUNTER_THRESHOLD</td><td>10800s (3 hours)</td><td>Trigger pull sync when last encounter exceeds this</td></tr>
|
||||
<tr><td>SELF_LAST_ENCOUNTER_THRESHOLD</td><td>14400s (4 hours)</td><td>Trigger pull sync when last encounter exceeds this</td></tr>
|
||||
<tr><td>QUIC_CONNECT_TIMEOUT</td><td>15s</td><td>Direct connection establishment</td></tr>
|
||||
<tr><td>HOLE_PUNCH_TIMEOUT</td><td>30s</td><td>Overall hole punch window</td></tr>
|
||||
<tr><td>HOLE_PUNCH_ATTEMPT</td><td>2s</td><td>Per-address attempt within window</td></tr>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue