← All docs  Β·  Home

Freedback architecture

Freedback is a federated feedback protocol: anyone can attach typed feedback (stars, scalar, thumbs, comments, tags) to any URI, publish it to a server they choose, and have it discovered and aggregated across servers β€” without a central authority. The wire format is a W3C Web Annotation (JSON-LD), so existing annotation tooling can read it.

The big picture

flowchart TB
  core["<b>protocol-lib</b> (Rust)<br/>model Β· JCS dedup Β· P-256 Β· JSON-LD Β· SHACL<br/><i>(native + wasm32 core)</i>"]
  core --> fb["<b>feedback-server</b><br/>WAP container + /sync"]
  core --> disc["<b>discovery-server</b><br/>registry Β· /.well-known"]
  core --> coll["<b>collection-server</b><br/>index Β· cache Β· equivalence"]
  fb <-->|announce / resolve| disc
  disc <--> coll
  fb -->|store| store[("FeedbackStore<br/>Oxigraph (prod) Β· SQLite/memory (mock)")]
  coll -->|index| agent["AI equivalence agent"]

Clients: cli-client (native + wasm) Β· advanced-client (local sync copy). Surfaces: web widgets (JS) Β· Firefox extension (JS) Β· 3rd-party WA demo Β· mobile app (Tauri 2 + Rust, Android-first).

Components and responsibilities

# Component Crate / dir Native/WASM Role
β€” Protocol core protocol-lib both model, dedup id, signing, JSON-LD, SHACL
β€” Storage storage native FeedbackStore trait + Oxigraph/SQLite/memory
β€” Server core server-lib native shared WAP semantics + Freedback net-new
1 Feedback server feedback-server native POST-to-container, paging, /sync, /.well-known
2 Discovery server discovery-server native announce + verify + resolve
3 Web widgets widgets/ JS (+wasm) drop-in stars/scalar/thumb/comment/tag
4 Basic client cli-client both read/write/sync; collection vs publication points
5 Interop demo demo-third-party/ JS load Freedback output in Annotorious/RecogitoJS
6 Advanced client advanced-client native local sync copy + resume cursor + dedup-on-merge
7 Collection server collection-server native cache, per-URI index, equivalence, politeness
8 Equivalence agent agent-prompts/ native job propose URI equivalences for component 7
9 Firefox extension firefox-extension/ JS (+wasm) list feedback for the current page
10 Mobile app apps/mobile/ native (own workspace) Tauri 2 + Rust, Android-first: scan/share a barcode/URL/ISBN, view and contribute feedback, manage your own posts and key

Two identities, two trust models (INVARIANT 4)

Data lifecycle

write:  build Annotation (Β± rights license IRI, ADR 0022) β†’ (optional) P-256 sign β†’ POST /annotations/
        → auth (verify JWS  OR  OAuth bearer→(app,user))
        → JSON-LD expand → SHACL validate (reject→422+report)
        β†’ FeedbackStore::put (dedup by content id)

read:   GET /annotations/?target=&page=  β†’ FeedbackStore::query
        β†’ JSON-LD frame/compact to pinned @context β†’ OrderedCollectionPage

sync:   GET /sync?target=&gt_iat=&latest_edits_only=true
        β†’ only items with iat > cursor, edit-chains collapsed to latest

delete: DELETE /annotations/{dedup_id} + author proof
        (ES256 over JCS of {"type":"Delete","annotation":id,"created":ts}
         by the annotation's own key  OR  OAuth bearer→same (app,user))
        β†’ content erased; content-free tombstone {dedup_id, deleted_at, proof}
        β†’ GET/re-POST of that id β†’ 410 Gone; caches evict on next sync

Why these choices

The non-obvious decisions are written up as ADRs in docs/adr/:

See roadmap.md for milestones and the issue map, and attributions.md for harvested-code provenance.