v0.4.1: Security hardening, lock contention fixes, data cleanup

Security:
- Reaction signatures: ed25519 sign/verify (sign_reaction, verify_reaction_signature)
  Backward-compatible — unsigned reactions from old nodes still accepted
- Comment signature verification: verify_comment_signature now called on receipt
- Reaction removal authorization: only reactor or post author can remove
- BlobHeader author verification: lookup actual author from storage, don't trust payload

Lock contention (4 fixes):
- ManifestPush discovery: cm lock released before PostFetch I/O
- Pull request handler: load under lock, filter without lock, brief re-lock for is_deleted
- Pull sender: split into two brief locks (store posts, then batch upstream+sync)
- Engagement checker: batch all chunk results, single lock for writes

Data cleanup:
- Post deletion cleans post_downstream, post_upstream, seen_engagement tables
- Added TODO-hardening.md documenting remaining DOS/security/lock/data issues

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Reimers 2026-03-21 19:30:38 -04:00
parent bbaacf9b6c
commit bb6f2b64b0
11 changed files with 500 additions and 138 deletions

View file

@ -44,7 +44,8 @@
<p>This is the canonical technical reference for ItsGoin. It describes the vision, the architecture, and the current state of every subsystem &mdash; with full implementation detail. This document is versioned; each update records what changed.</p>
<div class="card" style="margin-top: 1rem;">
<strong style="font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">Changelog</strong>
<p style="margin-top: 0.5rem;"><strong>v0.4.0</strong> (2026-03-21): Protocol v4 &mdash; header-driven sync. ManifestPush as primary post notification. Slim PullSyncRequest (per-author timestamps, not full post ID list). Tiered engagement checks (5min/1hr/4hr/24hr by content age). Multi-upstream (3 max) with fallback chain. Auto-prefetch followed authors &lt;90d. Self Last Encounter per-author tracking. Encrypted-but-not-for-us CDN caching. Serial engagement polling. ~90% bandwidth reduction for established nodes.</p>
<p style="margin-top: 0.5rem;"><strong>v0.4.1</strong> (2026-03-21): Security hardening &mdash; reaction signatures (ed25519), comment signature verification on receipt, reaction removal authorization, BlobHeader author verification. Lock contention fixes &mdash; ManifestPush discovery (cm lock released during I/O), pull request handler (filter without lock), pull sender (split into brief locks), engagement checker (batch writes per chunk). Data cleanup &mdash; post deletion cleans downstream/upstream/seen tables.</p>
<p><strong>v0.4.0</strong> (2026-03-21): Protocol v4 &mdash; header-driven sync. ManifestPush as primary post notification. Slim PullSyncRequest (per-author timestamps, not full post ID list). Tiered engagement checks (5min/1hr/4hr/24hr by content age). Multi-upstream (3 max) with fallback chain. Auto-prefetch followed authors &lt;90d. Self Last Encounter per-author tracking. Encrypted-but-not-for-us CDN caching. Serial engagement polling. ~90% bandwidth reduction for established nodes.</p>
<p><strong>v0.3.6</strong> (2026-03-20): Active CDN replication &mdash; all devices proactively replicate recent posts to peers (desktops &gt; anchors &gt; phones priority). ReplicationRequest/Response (0xE1/0xE2). Device roles (Intermittent/Available/Persistent) advertised in InitialExchange. Bandwidth budgets: replication (pull to cache) + delivery (serve requests), hourly auto-reset, phones 100MB/1GB, desktops 200MB/2GB, anchors 200MB/1GB. Cache management: 1GB default, configurable, eviction cycle activated with share-link priority boost. Engagement distribution fix &mdash; BlobHeader JSON rebuilt after diff ops. Tombstone system &mdash; deleted reactions/comments tombstoned, propagate via pull sync. Persistent notifications via seen_engagement/seen_messages tables. DOS hardening: fan-out cap (10), prefetch cap (20), downstream registration cap (50), delivery budget enforcement. Pull preference reordered: non-anchors first. Network indicator &mdash; header dot (black/red/yellow/green) + capability labels. Tab badges &mdash; contextual counts (new posts, engagement, online, unread). Message read tracking on open/close/send. Stats bar removed.</p>
<p><strong>v0.3.5</strong> (2026-03-20): Private blob encryption &mdash; attachments on encrypted posts (Friends/Circle/Direct) now encrypted with same CEK as post text; public blobs unchanged; CID on ciphertext. Blob prefetch on sync &mdash; attachments eagerly fetched after post pull for offline availability. Crypto refactoring &mdash; extracted reusable primitives (encrypt/decrypt_bytes_with_cek, unwrap_cek_for_recipient, unwrap_group_cek). Intent-based post filtering &mdash; feed/myposts/messages filter on intentKind instead of encryption state. Blob decryption API (get_blob_for_post). Download filename sanitization. Encrypted receipt &amp; comment slots &mdash; private posts carry noise-prefilled encrypted slots in BlobHeader for delivery/read/react receipts and private comments; CDN-propagated as opaque bytes; slot key derived from post CEK; 3 new BlobHeaderDiffOps (WriteReceiptSlot, WriteCommentSlot, AddCommentSlots). Message UI &mdash; DM delivery indicators (checkmark/double/blue/emoji), auto-seen on view, react button on messages.</p>
<p><strong>v0.3.4</strong> (2026-03-18): Comment edit &amp; delete with trust-based propagation. Native notifications via Tauri plugin (messages, posts, reactions, comments). Forward-compatible BlobHeaderDiffOp::Unknown variant. Following Online/Offline lightbox. Comment threading scoping fix. Dropdown text legibility fix. Mobile hamburger nav for website.</p>

View file

@ -25,16 +25,16 @@
<section>
<h1 style="font-size: 2rem; font-weight: 800; letter-spacing: -0.03em; margin-bottom: 0.25rem;">Download ItsGoin</h1>
<p>Available for Android and Linux. Free and open source.</p>
<p style="color: var(--text-muted); font-size: 0.85rem;">Version 0.4.0 &mdash; March 15, 2026</p>
<p style="color: var(--text-muted); font-size: 0.85rem;">Version 0.4.1 &mdash; March 15, 2026</p>
<div class="downloads">
<a href="itsgoin-0.4.0.apk" class="download-btn btn-android">
<a href="itsgoin-0.4.1.apk" class="download-btn btn-android">
Android APK
<span class="sub">v0.4.0</span>
<span class="sub">v0.4.1</span>
</a>
<a href="itsgoin_0.4.0_amd64.AppImage" class="download-btn btn-linux">
<a href="itsgoin_0.4.1_amd64.AppImage" class="download-btn btn-linux">
Linux AppImage
<span class="sub">v0.4.0</span>
<span class="sub">v0.4.1</span>
</a>
</div>
</section>
@ -46,7 +46,7 @@
<h3 style="color: var(--accent);">Android</h3>
<ol class="steps">
<li><strong>Download the APK</strong> &mdash; Tap the button above. Your browser may warn that this type of file can be harmful &mdash; tap <strong>Download anyway</strong>.</li>
<li><strong>Open the file</strong> &mdash; When the download finishes, tap the notification or find <code>itsgoin-0.4.0.apk</code> in your Downloads folder and tap it.</li>
<li><strong>Open the file</strong> &mdash; When the download finishes, tap the notification or find <code>itsgoin-0.4.1.apk</code> in your Downloads folder and tap it.</li>
<li><strong>Allow installation</strong> &mdash; Android will ask you to allow installs from this source. Tap <strong>Settings</strong>, toggle <strong>"Allow from this source"</strong>, then go back and tap <strong>Install</strong>.</li>
<li><strong>Launch the app</strong> &mdash; Once installed, tap <strong>Open</strong> or find ItsGoin in your app drawer.</li>
</ol>
@ -59,8 +59,8 @@
<h3 style="color: var(--green);">Linux (AppImage)</h3>
<ol class="steps">
<li><strong>Download the AppImage</strong> &mdash; Click the button above to download.</li>
<li><strong>Make it executable</strong> &mdash; Open a terminal and run:<br><code>chmod +x itsgoin_0.4.0_amd64.AppImage</code></li>
<li><strong>Run it</strong> &mdash; Double-click the file, or from the terminal:<br><code>./itsgoin_0.4.0_amd64.AppImage</code></li>
<li><strong>Make it executable</strong> &mdash; Open a terminal and run:<br><code>chmod +x itsgoin_0.4.1_amd64.AppImage</code></li>
<li><strong>Run it</strong> &mdash; Double-click the file, or from the terminal:<br><code>./itsgoin_0.4.1_amd64.AppImage</code></li>
</ol>
<div class="note">
<strong>Note:</strong> If it doesn't launch, you may need to install FUSE:<br><code>sudo apt install libfuse2</code> (Debian/Ubuntu) or <code>sudo dnf install fuse</code> (Fedora).
@ -71,6 +71,19 @@
<section>
<h2>Changelog</h2>
<div class="changelog">
<div class="changelog-date">v0.4.1 &mdash; March 21, 2026</div>
<ul>
<li><strong>Security: Reaction signatures</strong> &mdash; Reactions now carry ed25519 signatures. Forged reactions from other NodeIds are rejected. Backward-compatible with unsigned reactions from older nodes.</li>
<li><strong>Security: Comment signature verification</strong> &mdash; Comment signatures (already present) are now verified on receipt. Forged comments rejected.</li>
<li><strong>Security: Reaction removal auth</strong> &mdash; Only the reactor or post author can remove reactions. Previously any peer could strip reactions.</li>
<li><strong>Security: BlobHeader author verification</strong> &mdash; Header rebuild verifies author against stored post, not trusted from payload.</li>
<li><strong>Lock contention: ManifestPush discovery</strong> &mdash; cm lock released before PostFetch network I/O. Was holding lock during entire discovery (5s+ freeze).</li>
<li><strong>Lock contention: Pull request handler</strong> &mdash; Load posts under lock, filter without lock, brief re-lock for is_deleted. Was holding lock during full post list iteration.</li>
<li><strong>Lock contention: Pull sender</strong> &mdash; Split into two brief locks (store, then batch upstream+sync). Was holding one long lock for all operations.</li>
<li><strong>Lock contention: Engagement checker</strong> &mdash; Batch writes per chunk with single lock. Was acquiring lock per post (100+ times).</li>
<li><strong>Data cleanup</strong> &mdash; Post deletion now cleans up post_downstream, post_upstream, and seen_engagement tables.</li>
</ul>
<div class="changelog-date">v0.4.0 &mdash; March 21, 2026</div>
<ul>
<li><strong>Protocol v4: Header-driven sync</strong> &mdash; Major sync protocol revision. ManifestPush now triggers post discovery from CDN tree headers. Bandwidth reduced ~90% for established nodes.</li>