use WebOfTrust registry for screening dialog mutuals

This commit is contained in:
2026-10-20 09:47:34 +07:00
parent 80f4bc387e
commit 66768e71a6
4 changed files with 678 additions and 35 deletions
+19 -14
View File
@@ -101,17 +101,19 @@ entity update -> `cx.emit`):
1. **Hydrate from the local database** on creation and on
`StateEvent::SignerChanged`:
- own kind 3 (newest event, authors sorted by `Reverse(created_at)` like
`Directory::track` does) -> `follows`;
- one batch query `Filter::new().kind(Kind::ContactList).authors(follows)`
-> dedupe per author keeping the newest -> seed `lists`/`reverse`.
2. **Stay fresh**: one persistent subscription with a dedicated
`SubscriptionId` (add `WOT_CONTACTS` beside `DEVICE_GIFTWRAP`/`USER_GIFTWRAP`
in `state::constants`), filter `kind(Kind::ContactList).authors(follows)`.
The background listener accepts any kind 3 whose author is in `follows`
(don't couple to subscription ids), diffs it against the cached list, and
updates the reverse index. Re-issue the subscription when the user's own
contact list changes.
- own kind 3 (newest event, `limit(1)` like `Directory::track` and
`query_chat_rooms` do) -> `follows`;
- applied immediately so the dialog has data before the relays respond.
2. **Stay fresh with NIP-77** (`WebOfTrust::sync`, no persistent subscription):
- `client.sync(Filter::new().kind(Kind::ContactList).authors(follows + self))`
reconciles with every relay in the pool and downloads only the contact
lists the local database is missing (negentropy items come from the
database, direction is down-only);
- after each reconcile, the newest stored list per covered author is applied
to the graph and a `Ready`/`Updated` event marks what changed;
- triggers: hydrate, a 15-minute timer (Amethyst's D10 cadence), and a
follow-set change; when a reconcile grows the follow set (fresh install),
it re-syncs once more to cover the new authors.
3. **Rules ported from `WoTService`**:
- exclude the follower and `self_key` from every ingested list;
- on follow-set change, un-credit removed followers from the reverse index;
@@ -121,12 +123,16 @@ entity update -> `cx.emit`):
No persistence: the graph rebuilds from the LMDB cache on every start, the same
way `ChatRegistry` rebuilds rooms. No new relay events, no settings file, no new
dependencies.
dependencies. Relays without NIP-77 fail their reconcile (logged); the graph
then reflects whatever the database already holds.
## 3. Consumers (in order)
### Phase 1 — screening dialog (`crates/workspace/src/dialogs/screening.rs`)
Status: **implemented**. The `WebOfTrust` registry lives in `crates/person/src/wot.rs` and
is initialized in `person::init`.
Replace `check_wot`'s database query (which only sees contact lists that happen
to be cached, so "mutual contacts" is usually empty) with the registry:
@@ -179,8 +185,7 @@ follows already), notification feeds (coop has none), muting/spam scoring.
- NIP-85 trust providers (kind 10040/30382), Brainstorm onboarding, rank
thresholds — revisit only if coop ever needs a network-scale gate.
- Persisting the graph or multi-hop (3+) scores — kind 3s are one LMDB query
away on restart.
- Background jobs / WorkManager equivalents — hydration is two local queries.
away on restart, and negentropy keeps them current.
## 5. Testing