docs/ war leer. Jetzt drei Dateien, jede Behauptung am Code verifiziert: * deployment.md — docker compose, Migrationsweg, vollständige Env-Referenz mit den Fallstricken (P-256-taugliches PDS_JWT_SECRET, Pflicht-aber-tot S3_BUCKET_APPVIEW), Release-Build, systemd-Units, Reverse-Proxy inkl. des Hinweises, dass die AppView CORS Any liefert und der Proxy den Header ersetzen statt ergänzen muss, Health-Checks und Cursor-Verhalten beim Neustart. * architecture.md — Crate-Verantwortlichkeiten, ASCII-Datenfluss, beide DB-Schemata. Hält fest, was die Topologie erklärt: die eigene PDS speist keinen Firehose, eigene Records erreichen die AppView nur über den Best-Effort-Push. * tauri-release.md — Signing-Keys, v2-Updater-Config, latest.json, Build pro Plattform. Der _comment in tauri.conf.json war irreführend: active/dialog sind v1-Reste, die der v2-Updater ignoriert; dass nichts passiert, liegt daran, dass niemand check() aufruft und das Plugin nicht installiert ist. README bekommt Phase 8, eine Doku-Übersicht, korrigierte Testanleitung (src-tauri ist ein eigener Workspace und wird von cargo test --workspace nicht erfasst) und einen Abschnitt "Bekannte Lücken" statt der bisher lückenlosen Erfolgsmeldung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013HC9HLrUU1LNwkzp8nkDLX
121 lines
6.4 KiB
Markdown
121 lines
6.4 KiB
Markdown
# 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) + In-Memory-Store
|
|
├── 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, ProfileView, NotificationsView)
|
|
├── 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, notifications, profiles, jetstream_cursor)
|
|
docs/ Deployment, Architektur, Tauri-Release (siehe unten)
|
|
```
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
# 1) Datenbanken + MinIO starten
|
|
docker compose up -d
|
|
|
|
# 2) Umgebungsvariablen — beide Binaries laden .env selbst (dotenvy).
|
|
# PDS_JWT_SECRET muss Hex sein: openssl rand -hex 32
|
|
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 — `encode_key` = `base64url(sha256(raw_key))` per atproto-Spec, `split_around`/`wrap_with_split` threaden den recursive right_sub korrekt als `k_tree` weiter. 27 MST + 13 Repo + 4 Commit Tests grün. |
|
|
| 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, notifications, followers/following |
|
|
| 6 Tauri-UI-Logik an Backend koppeln | ✅ done — LoginScreen, NavRail, PostCard, ComposeBox, Profile/Compose/Search/Settings-Views |
|
|
| 7 Polish (Tray, Notifications, Auto-Update) | ✅ done — Tray-Icon custom (`tauri::include_image!`), Notification-Click navigiert via `app://notification`-Event + `openThread`-Helper zu Thread-Detail, Auto-Update in Dev inert (Production-Weg: [`docs/tauri-release.md`](docs/tauri-release.md)) |
|
|
| 8 Social-Graph + Benachrichtigungen | ✅ done — `notifications`-Tabelle, Schreibpfad im Jetstream-Indexer (idempotent, keine Selbst-Notifications), `/api/notifications[/count|/seen]`, `/api/followers`, `/api/following`, eigene `/api/thread`-Route; im Client Notifications-View mit Unread-Badge und klickbare Follower-/Following-Listen im Profil |
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
cargo test --workspace # Rust: PDS, AppView, at-* Crates
|
|
cd crates/tauri-app && npx vitest run # Svelte/TS
|
|
cd crates/tauri-app/src-tauri && cargo test # Tauri-IPC (eigener Workspace!)
|
|
```
|
|
|
|
Stand zuletzt gegen den lokalen Dev-Stack (docker compose + laufender PDS + AppView):
|
|
Rust-Workspace grün (u.a. 27 MST, 24 PDS-Integration, 49 AppView-Lib, 14 AppView-Integration),
|
|
Frontend grün. Zwei Vorbehalte:
|
|
|
|
* Die DB-gestützten Integrationstests sind *fail-open* — ohne erreichbare Postgres/PDS
|
|
überspringen sie sich selbst und melden das nur auf stderr. Ein grüner Lauf ohne
|
|
laufenden Stack sagt also weniger, als er aussieht.
|
|
* Einige Tests hängen am Zustand der Dev-Datenbank; auf einer frischen DB können
|
|
`handle_sync`-Tests abweichen. Wer sie ernst nimmt, prüft sie gegen eine definierte DB.
|
|
|
|
`crates/tauri-app/src-tauri` hat ein eigenes `[workspace]` und ist **nicht** Teil des
|
|
Root-Workspace; `cargo test --workspace` von oben erfasst den IPC-Layer nicht.
|
|
|
|
## Dokumentation
|
|
|
|
| Datei | Inhalt |
|
|
|---|---|
|
|
| [`docs/architecture.md`](docs/architecture.md) | Crate-Verantwortlichkeiten, Datenfluss PDS → Jetstream → AppView → Client, Tabellenübersicht |
|
|
| [`docs/deployment.md`](docs/deployment.md) | Betrieb: docker compose, Migrationen, alle Env-Variablen, Release-Build, systemd-Units, Reverse-Proxy, Health-Checks |
|
|
| [`docs/tauri-release.md`](docs/tauri-release.md) | Signing-Keys, Updater-Config, `latest.json`, Build pro Plattform, Artefaktpfade |
|
|
|
|
## Bekannte Lücken
|
|
|
|
* Die eigene PDS speist **keinen** Firehose (`com.atproto.sync.subscribeRepos` fehlt) —
|
|
eigene Records erreichen die AppView nur über den Best-Effort-Push
|
|
`POST /internal/ingest-commit`.
|
|
* Die AppView-Leseschnittstelle hat **keine Auth** und CORS `Any`; bei
|
|
`/api/notifications` sind das erstmals halbwegs private Daten.
|
|
* Notifications werden nie gelöscht: Unlike/Unfollow lässt die Zeile stehen, und der
|
|
Dedupe-Key macht sie „einmal pro (Empfänger, Autor, Art, Subject) für immer".
|
|
* Auto-Update ist nur dokumentiert, nicht verdrahtet: niemand ruft `check()` auf, das
|
|
Updater-Plugin ist nicht installiert (siehe `docs/tauri-release.md`).
|
|
* Reply-Notifications gehen verloren, wenn die Antwort vor ihrem Parent indiziert wird
|
|
(kein Nachlauf) — bei Jetstream möglich.
|
|
* `at-blob` spricht MinIO ohne Signature V4 — echtes AWS S3 funktioniert damit nicht.
|
|
* Die PDS liefert kein `.well-known/did.json`; `describeServer` gibt die DID hart
|
|
als `did:web:pds.maarcadetweet.local` zurück.
|
|
|
|
## 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`).
|