v0.3.5: Encrypted receipt & comment slots, message delivery indicators
Encrypted slots in BlobHeader:
- Private posts get noise-prefilled receipt slots (64B, 1 per participant)
and comment slots (256B, ceil(participants/3), expandable)
- Slot key derived from post CEK via BLAKE3 — only participants can read
- CDN relays propagate opaque encrypted bytes without decryption
- 3 new BlobHeaderDiffOps: WriteReceiptSlot, WriteCommentSlot, AddCommentSlots
Receipt system:
- States: empty(0), delivered(1), seen(2), reacted(3)
- Slot index = position in sorted participant NodeId list
- Author can pre-feed emoji reaction at creation time
- 6 new crypto tests for slot encrypt/decrypt/derivation
Node methods:
- write_receipt_slot, write_comment_slot with upstream+downstream propagation
- read_receipt_slots, read_comment_slots with CEK-based decryption
- get_post_cek_and_participants helper for both Encrypted and GroupEncrypted
IPC: write_message_receipt, write_message_comment, get_message_receipts,
get_message_comments
Frontend:
- DM chat bubbles show delivery indicators (check → double → blue → emoji)
- Opening conversation auto-marks incoming messages as seen
- React button on messages with emoji prompt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a41b11c0b8
commit
b7f2d369fa
9 changed files with 882 additions and 4 deletions
|
|
@ -44,7 +44,7 @@
|
|||
<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;">
|
||||
<strong style="font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">Changelog</strong>
|
||||
<p style="margin-top: 0.5rem;"><strong>v0.3.5</strong> (2026-03-20): Private blob encryption — 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 — attachments eagerly fetched after post pull for offline availability. Crypto refactoring — extracted reusable primitives (encrypt/decrypt_bytes_with_cek, unwrap_cek_for_recipient, unwrap_group_cek). Intent-based post filtering — feed/myposts/messages filter on intentKind instead of encryption state. Blob decryption API (get_blob_for_post). Download filename sanitization.</p>
|
||||
<p style="margin-top: 0.5rem;"><strong>v0.3.5</strong> (2026-03-20): Private blob encryption — 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 — attachments eagerly fetched after post pull for offline availability. Crypto refactoring — extracted reusable primitives (encrypt/decrypt_bytes_with_cek, unwrap_cek_for_recipient, unwrap_group_cek). Intent-based post filtering — feed/myposts/messages filter on intentKind instead of encryption state. Blob decryption API (get_blob_for_post). Download filename sanitization. Encrypted receipt & comment slots — 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 — 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 & 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>
|
||||
<p><strong>v0.3.3</strong> (2026-03-16): Connection rate limiting — incoming auth failures rate-limited per source IP (3 attempts, exponential backoff to ~256s). Schema versioning — PRAGMA user_version tracks DB version with migration framework. N2/N3 freshness — TTL 7d→5h, full N1/N2 re-broadcast every 4h, startup sweep clears stale entries. Bootstrap isolation recovery — 24h check verifies bootstrap is in N1/N2/N3, reconnects + sticky N1 advertisement if absent. IPv6 HTTP address fix — nodes advertise actual public IPv6 (not 0.0.0.0) for share link redirects. Upstream tracking — post_upstream table records post source for engagement diff routing toward author. Video preload fix — share links and in-app videos use preload=auto. Following Online/Offline split. DM filter from My Posts. Any-type file attachments with download prompt + trust warning. Image lightbox. Audio player.</p>
|
||||
<p><strong>v0.3.2</strong> (2026-03-14): Bidirectional engagement propagation — BlobHeaderDiff flows upstream + downstream through CDN tree. Auto downstream registration on pull sync/push notification. TCP hole punch protocol (TcpPunchRequest/Result 0xD6/0xD7). Tiered web serving (redirect → TCP punch → QUIC proxy). Video playback fix (asset protocol + blob URL fallback). On-demand blob fetch for synced posts missing blob data.</p>
|
||||
|
|
@ -1076,6 +1076,44 @@ FAILURE: C → B → A: AnchorProbeResult { reachable: false }</code></pre
|
|||
|
||||
<h3>IPv6 HTTP address advertisement</h3>
|
||||
<p>Nodes with public IPv6 addresses advertise their actual routable address (from <code>endpoint.addr().ip_addrs()</code>) paired with their bound port, rather than the bind address (<code>0.0.0.0</code>). This enables direct browser-to-node HTTP serving for share links. Unroutable addresses (<code>0.0.0.0</code>, <code>127.x</code>) are filtered out in the tiered web serving redirect path.</p>
|
||||
|
||||
<h3>Encrypted receipt & comment slots</h3>
|
||||
<p>Private posts (Friends, Circle, Direct) carry encrypted slots in their BlobHeader for delivery receipts, read receipts, reactions, and private comments. The CDN propagates these as opaque bytes — only participants with the post’s CEK can decrypt them.</p>
|
||||
|
||||
<h4>Design principles</h4>
|
||||
<ul style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
<li><strong>Pre-filled noise</strong>: All slots are filled with random bytes on post creation. Writing to a slot replaces noise with encrypted content of the same size, making writes indistinguishable from creation to observers.</li>
|
||||
<li><strong>Slot key derivation</strong>: <code>slot_key = BLAKE3_derive_key("itsgoin/slot/v1", CEK)</code>. Only participants who can decrypt the post can read/write slots.</li>
|
||||
<li><strong>CDN-safe</strong>: Relay nodes store and propagate slot bytes without decryption. No new protocol messages needed — slots travel via <code>BlobHeaderDiff</code>.</li>
|
||||
</ul>
|
||||
|
||||
<h4>Receipt slots (64 bytes each)</h4>
|
||||
<ul style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
<li><strong>Allocation</strong>: 1 per participant (including author)</li>
|
||||
<li><strong>Slot assignment</strong>: Participants sorted by NodeId; slot index = position in sorted list</li>
|
||||
<li><strong>Decrypted format</strong>: <code>[1 byte: state][8 bytes: timestamp_ms BE][23 bytes: emoji/padding]</code></li>
|
||||
<li><strong>States</strong>: 0=empty/noise, 1=delivered, 2=seen, 3=reacted</li>
|
||||
<li><strong>Author pre-feed</strong>: Author can write their own slot with a reaction emoji at creation time</li>
|
||||
</ul>
|
||||
|
||||
<h4>Comment slots (256 bytes each)</h4>
|
||||
<ul style="padding-left: 1.25rem; margin: 0.5rem 0; color: var(--text-muted);">
|
||||
<li><strong>Allocation</strong>: <code>ceil(participants / 3)</code> initial slots, expandable via <code>AddCommentSlots</code> diff op</li>
|
||||
<li><strong>Decrypted format</strong>: <code>[32 bytes: author_node_id][8 bytes: timestamp_ms BE][216 bytes: UTF-8 content + zero padding]</code></li>
|
||||
<li><strong>Slot selection</strong>: First available (all-zero content after decryption = available)</li>
|
||||
<li><strong>Growth</strong>: When all comment slots are used, any participant can append new noise-filled slots</li>
|
||||
</ul>
|
||||
|
||||
<h4>Wire operations</h4>
|
||||
<table>
|
||||
<tr><th>Op</th><th>Purpose</th></tr>
|
||||
<tr><td><code>WriteReceiptSlot</code></td><td>Update a receipt slot (state change: delivered → seen → reacted)</td></tr>
|
||||
<tr><td><code>WriteCommentSlot</code></td><td>Write encrypted comment to a slot</td></tr>
|
||||
<tr><td><code>AddCommentSlots</code></td><td>Append new noise-filled comment slots when capacity is exhausted</td></tr>
|
||||
</table>
|
||||
|
||||
<h4>UI</h4>
|
||||
<p>DM conversations display delivery indicators: single checkmark (sent), double checkmark (delivered/on device), blue double checkmark (seen), emoji (reacted). Opening a conversation auto-marks incoming messages as seen. Messages have a react button for emoji responses.</p>
|
||||
</section>
|
||||
|
||||
<!-- 20. Encryption -->
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@
|
|||
<li><strong>Crypto refactoring</strong> — Extracted reusable primitives: <code>encrypt_bytes_with_cek</code>, <code>decrypt_bytes_with_cek</code>, <code>unwrap_cek_for_recipient</code>, <code>unwrap_group_cek</code>. Foundation for encrypted blob storage and future chunk-level encryption.</li>
|
||||
<li><strong>Intent-based post filtering</strong> — Feed, My Posts, and Messages now filter on the author's original visibility intent (<code>intentKind</code>) rather than encryption state. Direct messages are identified by intent, not by being “encrypted-for-me.” Backward-compatible with pre-intent posts.</li>
|
||||
<li><strong>Blob decryption on retrieval</strong> — New <code>get_blob_for_post</code> API decrypts private blobs in context of their post’s visibility. Public blobs pass through unchanged.</li>
|
||||
<li><strong>Encrypted receipt slots</strong> — Private messages get encrypted receipt and comment slots in their BlobHeader. Pre-filled with random noise so slot writes are indistinguishable from creation. Receipt states: delivered, seen, reacted. Only participants with the CEK can read slots; relay nodes propagate opaque bytes.</li>
|
||||
<li><strong>Message receipts & reactions</strong> — DM conversations show delivery indicators (checkmark → double checkmark → emoji). Opening a conversation marks messages as seen. React to messages with emoji.</li>
|
||||
<li><strong>Private comment slots</strong> — Encrypted comment capacity in private post headers (ceil(participants/3) slots, expandable). Participants can write short comments that propagate via CDN without revealing content to relays.</li>
|
||||
<li><strong>Download filename sanitization</strong> — Prevents path traversal in downloaded file names.</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue