feat(block2): 'in your circle' trust — friend-of-a-friend, not a raw count
A network-wide 'N people vouch' count invites spam and means little. Now the
trust banner computes whether the peer is within YOUR circle — you vouch for
them, or someone you vouch for does (friend-of-a-friend) — via the pure
WebOfTrust rule (seeds={you}, threshold 1, distance 2). When known, the banner
turns green with 'In your circle' (else it falls back to the count).
The full member policy (threshold/distance/bootstrap) stays open (network-trust
§2); this is a deliberately loose 'people near you' heuristic.
Analyzer clean; trust cubit test adds a friend-of-a-friend vs stranger case
(run flutter test locally to confirm — the widget suite is too slow to run here).
This commit is contained in:
parent
eed7c70037
commit
163d659119
10 changed files with 96 additions and 16 deletions
|
|
@ -6,7 +6,11 @@ import 'package:tane/state/trust_cubit.dart';
|
|||
class FakeTrustTransport implements TrustTransport {
|
||||
FakeTrustTransport(this.selfId);
|
||||
final String selfId;
|
||||
final Map<String, Set<String>> _certs = {};
|
||||
final Map<String, Set<String>> _certs = {}; // subject -> issuers
|
||||
|
||||
/// Test helper: record an arbitrary issuer→subject vouch (to build a graph).
|
||||
void addCert(String issuer, String subject) =>
|
||||
(_certs[subject] ??= {}).add(issuer);
|
||||
|
||||
@override
|
||||
Future<Set<String>> certifiersOf(String subjectPubkey) async =>
|
||||
|
|
@ -18,14 +22,22 @@ class FakeTrustTransport implements TrustTransport {
|
|||
Duration validity = const Duration(days: 365),
|
||||
String note = '',
|
||||
}) async =>
|
||||
(_certs[subjectPubkey] ??= {}).add(selfId);
|
||||
addCert(selfId, subjectPubkey);
|
||||
|
||||
@override
|
||||
Future<void> revoke({required String subjectPubkey}) async =>
|
||||
_certs[subjectPubkey]?.remove(selfId);
|
||||
|
||||
@override
|
||||
Future<List<Certification>> allCertifications() async => const [];
|
||||
Future<List<Certification>> allCertifications() async => [
|
||||
for (final entry in _certs.entries)
|
||||
for (final issuer in entry.value)
|
||||
Certification(
|
||||
issuer: issuer,
|
||||
subject: entry.key,
|
||||
issuedAt: DateTime(2026),
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
Future<void> close() async {}
|
||||
|
|
@ -62,6 +74,23 @@ void main() {
|
|||
await cubit.close();
|
||||
});
|
||||
|
||||
test('a friend-of-a-friend is in your circle; a stranger is not', () async {
|
||||
final transport = FakeTrustTransport(me)
|
||||
..addCert(me, 'friend') // you vouch for a friend
|
||||
..addCert('friend', peer) // your friend vouches for the peer
|
||||
..addCert('stranger', 'other'); // unrelated to you
|
||||
|
||||
final inCircle = TrustCubit(transport, peerPubkey: peer, selfPubkey: me);
|
||||
await inCircle.load();
|
||||
expect(inCircle.state.knownToYou, isTrue);
|
||||
await inCircle.close();
|
||||
|
||||
final outside = TrustCubit(transport, peerPubkey: 'other', selfPubkey: me);
|
||||
await outside.load();
|
||||
expect(outside.state.knownToYou, isFalse);
|
||||
await outside.close();
|
||||
});
|
||||
|
||||
test('never vouches for self', () async {
|
||||
final cubit =
|
||||
TrustCubit(FakeTrustTransport(me), peerPubkey: me, selfPubkey: me);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue