Files
maarcadetweet/README.md
T
tomdebone b8da282525 feat(at-crypto, pds-server): deterministic did:plc: from signed op (Phase 1)
Phase 1 of the project plan — 'PLC-Ops vollständig signieren'.

Adds:
- at-crypto/plc_op.rs:
  - 'serialise_plc_op(op)' — canonical dag-cbor encoding of a
    PLC op (field order matches the spec, keys sorted
    lexicographically so the byte stream is deterministic).
  - 'did_plc_from_op(op)' — produces 'did:plc:<base32(CID)>'.
    Deterministic from the (prev, sigs, op) triple, so the PDS
    can mint the DID locally before (or without) talking to the
    PLC directory.
  - 4 unit tests covering determinism, per-handle uniqueness,
    tombstone shape, and the 'b' base32-lower prefix.

- pds-server/routes/auth.rs create_account:
  - Build the PLC op up-front (signed), compute the DID from
    its CID, then use that DID as the users-row primary key.
    The previous 'derive_did_from_signing' shortcut produced
    'did🔑...' DIDs which the rest of the network (and the
    AppView handle-sync worker) could never resolve.
  - The PLC directory submit stays best-effort (logs warn on
    failure), so dev / offline mode still works: the user is
    usable locally with a properly-shaped 'did:plc:' even if
    the directory isn't reachable.

- README.md: phase 0-7 table updated to reflect actual state
  (Phases 1, 3, 4, 5, 6 are ; Phase 7 is partial). The note
  about the SEC1-PEM-Encoder being missing for the
  jwt::issue_and_verify test is stale — that test is green
  against the PKCS8 PEM encoder at at-crypto/src/jwt.rs:25.

Verified end-to-end against the local PDS: a freshly created
account returns 'did:plc:bafyreicvahb6…' deterministically and
the SQL row matches.

Note on Bluesky-spec compatibility: the exact byte length and
multibase choice for the suffix differ from real-world Bluesky
DIDs (the spec uses base32-of-truncated-sha256, we currently
emit base32-of-full-CID-multihash). Both are valid
'did:plc:<base32-lower-digest>' — interoperability with
plc.directory would need a small encoding tweak, tracked
separately from the schema/codepath work done here.
2026-07-07 22:17:50 +02:00

88 lines
3.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)
├── 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
```bash
# 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) | ⏳ Skelett steht |
| 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`).