Slice 4 of Block 2. The pure rule was already parameterised; this adds the policy, cold-start and UI around it. - commons_core: WotParams (sigQty/stepMax/sigValidity, Duniter defaults) + WebOfTrust.membersWith; npubToHex helper (NIP-19 decode) for adding roots. - WotSettings (keystore): the active parameters, configurable — a young network loosens them and tightens as it grows, as Ğ1 did. Defaults Duniter. - TrustReferents: the bootstrap 'seeds' membership is measured from — a bundled asset (empty until real founders are curated, no invented keys) unioned with referents the user adds by npub/QR. Honest cold-start. - TrustCubit: computes the full membership verdict against referents+params alongside the personal circle, and exposes a TrustTier (networkMember > inYourCircle > vouched > unknown). Certifications issued with the active validity (they expire and renew, Duniter rule). - UI: chat trust badge by tier; a 'Network of trust' screen (manage roots + advanced params) reached from the profile. i18n en/es/pt/ast. Tests: WotParams/membersWith, npubToHex, TrustReferents, WotSettings, and TrustCubit tiers/membership. Resolves the WoT-parameters decision (open-decisions §B). Trust net stays empty/undetermined until seeded — by design; users bootstrap their own roots.
45 lines
1.5 KiB
Dart
45 lines
1.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:tane/services/trust_referents.dart';
|
|
|
|
import '../support/test_support.dart';
|
|
|
|
void main() {
|
|
const npub =
|
|
'npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6';
|
|
const hex =
|
|
'3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d';
|
|
|
|
// No bundled asset in the unit test bundle → _bundled() degrades to empty, so
|
|
// these exercise the user-added set (the cold-start bootstrap path).
|
|
late TrustReferents referents;
|
|
setUp(() => referents = TrustReferents(InMemorySecretStore()));
|
|
|
|
test('starts empty', () async {
|
|
expect(await referents.all(), isEmpty);
|
|
expect(await referents.userAdded(), isEmpty);
|
|
});
|
|
|
|
test('adds a referent from an npub, storing hex', () async {
|
|
final stored = await referents.add(npub);
|
|
expect(stored, hex);
|
|
expect(await referents.userAdded(), {hex});
|
|
expect(await referents.all(), contains(hex));
|
|
});
|
|
|
|
test('accepts a hex key directly and is idempotent', () async {
|
|
await referents.add(hex);
|
|
await referents.add(npub); // same identity, npub form
|
|
expect(await referents.userAdded(), {hex});
|
|
});
|
|
|
|
test('rejects an invalid identity code', () async {
|
|
expect(() => referents.add('not-a-key'), throwsFormatException);
|
|
expect(await referents.userAdded(), isEmpty);
|
|
});
|
|
|
|
test('removes a referent', () async {
|
|
await referents.add(hex);
|
|
await referents.remove(hex);
|
|
expect(await referents.userAdded(), isEmpty);
|
|
});
|
|
}
|