tomdebone fd352180a1 fix(at-mst): wrap_with_split subsumes old entries + put k_tree on the recursive right
The atproto MST spec defines the entry 'k' field as
base64url(sha256(record_key_utf8_bytes)) — the previous
implementation emitted base64url(record_key_bytes) directly,
which is what the rest of this project's tests were
asserting. The spec-conformant form has different sort
properties (the layer distribution is keyed off the hash's
leading-zero bits rather than the raw key's) and forces
three related fixes in this file:

1. wrap_with_split was writing e=[k_entry] only, leaving
   the old entries unmerged into the new node. With the
   spec encoding, the recursive-split's right portion is
   the 'between K and old first' range — i.e. the new
   key's .tree — and the old entries need to be appended
   after the new key. Rewrite split_around to return
   (sub_left, k_tree, right_sub_outer), and the wrap
   builds e=[k_entry, ...old_entries] in one write_node.

2. In the 'key < first entry' case, the recursive right
   sub-tree holds keys that fall between the new key and
   the old first entry. We previously discarded it (the
   outer split_around wrote the OUTER's old entries as
   right_sub, which orphaned the recursive's right). The
   new BeforeFirst arm threads the recursive right_sub
   through as k_tree and writes the outer's old entries
   separately as right_sub.

3. Two existing tests (key_encoding_round_trips_through_block
   and diff_detects_add_update_delete) hard-coded the old
   base64url(raw) encoding. Update their assertions to
   compare against base64url(sha256(raw)).

All 27 at-mst tests pass. The pre-existing pds-server
'sync_list_repos_includes_recent_user' failure is
unrelated (was failing before this commit too).
2026-07-10 22:11:02 +02:00
2026-07-05 20:01:31 +02:00
2026-07-05 20:01:31 +02:00
2026-07-05 20:01:31 +02:00
2026-07-05 20:01:31 +02:00

maarcadetweet

AT-Protocol-PDS in Rust + AppView + Tauri/Svelte-Desktop-Client. Posts sind auf 160 Zeichen limitiert (oldschool Twitter), erzwungen durch eigenes Lexicon app.twi.post.

Architektur

crates/
├── at-lexicon/    Lexicon-Schemas + 160-Char-Validierung
├── at-crypto/     k256, p256, CID, multibase, JWT, PLC-Ops, Repo-Signing
├── at-identity/   DID, PLC, Handle-Resolution
├── at-mst/        Merkle-Search-Tree
├── at-repo/       Repos, Commits, Blöcke, TID-Revs
├── at-blob/       S3-kompatibler Blob-Store (MinIO)
├── at-firehose/   Jetstream-Consumer (WebSocket)
├── at-shared/     Config, Errors, DID, Cursor
├── pds-server/    axum HTTP PDS (bin)
└── appview/       Jetstream-Indexer + REST-API (bin)

crates/tauri-app/       Tauri 2 + Svelte 5 + Vite + TS Desktop-Client
  ├── src/              Svelte-Components (Terminal, StatusBar, NavRail, PostCard, ComposeBox, LoginScreen)
  ├── src/lib/styles/   tokens.css (1:1 vom maarcade-Design)
  └── src-tauri/        Rust-IPC-Layer

lexicons/app/twi/post.json     Custom Lexicon mit maxLength: 160
migrations/pds/                PDS-DB-Schema (users, repos, blobs, sessions, plc_ops)
migrations/appview/            AppView-DB-Schema (posts, likes, follows, timeline_cache, jetstream_cursor)

Setup

# 1) Datenbanken + MinIO starten
docker compose up -d

# 2) Umgebungsvariablen
cp .env.example .env

# 3) Workspace kompilieren + Tests
cargo test --workspace
cargo check --workspace

# 4) Tauri-Frontend (Vite dev)
cd crates/tauri-app
npm install
npm run dev
# → http://127.0.0.1:1420

# 5) PDS / AppView (eigene Terminals)
cargo run -p pds-server
cargo run -p appview

Status

Phase Stand
0 Foundation, Workspace, Migrations, Lexicon, Crypto done
1 Identity (PLC-Ops vollständig signieren) done — did:plc: deterministisch aus signed op CID
2 MST + Repo (Spec-konforme CBOR-Encoding) 🟡 done mit Abweichung — fully working (27 MST + 13 Repo + 4 Commit Tests), aber encode_key codiert base64url(raw_key_bytes) statt des spec-konformen base64url(sha256(raw_key)). Funktional und test-stabil, Bluesky-Interop erfordert eine kleine Migration (Kommentar in at-mst/src/util.rs schildert die Optionen).
3 PDS-Server (com.atproto.* XRPC) done — createAccount/Session/Refresh, createRecord/deleteRecord, like/repost, follow
4 AppView-Foundation (Jetstream-Index) done — Jetstream-Indexer + identity-Event-Backfill + PLC-handle-sync-Worker
5 AppView-REST-API done — timeline, profile (by-did + by-handle), search, post-by-uri, thread-context
6 Tauri-UI-Logik an Backend koppeln done — LoginScreen, NavRail, PostCard, ComposeBox, Profile/Compose/Search/Settings-Views
7 Polish (Tray, Notifications, Auto-Update) 🟡 Tray + Notifications ok; Settings-View neu; Auto-Update-Endpoint noch leer

Tests

running 16 tests (at-crypto)
test result: ok. 16 passed; 0 failed; 0 ignored
running 3 tests (at-lexicon)
test result: ok. 3 passed; 0 failed
running 2 tests (at-shared)
test result: ok. 2 passed; 0 failed
running 2 tests (at-repo)
test result: ok. 2 passed; 0 failed
running 4 tests (at-crypto plc_op — Phase 1)
test result: ok. 4 passed; 0 failed

Der zuvor als "geplant für Phase 1" markierte jwt::issue_and_verify-Test wurde zwischenzeitlich grün gezogen (P-256-PKCS#8-PEM-Encoder ist über p256::pkcs8::EncodePrivateKey da).

Design

Orange Akzent, IBM Plex Mono, schwarzer Hintergrund mit 3%-Grid, Terminal-Fenster-Component mit blinkendem Cursor. Tokens sind 1:1 von maarcade-shell/landing/assets/css/tokens.css abgeleitet, plus zwei neue Repos-Tokens (--cid-fg, --rev-fg).

S
Description
AT Protocol PDS + AppView + Tauri Desktop Client (160-char posts). Maarcade design.
Readme
1 MiB
Languages
Rust 78.7%
Svelte 15.5%
TypeScript 4.9%
PLpgSQL 0.5%
CSS 0.4%