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:commons_core/commons_core.dart';
|
|
|
|
import '../security/secret_store.dart';
|
|
|
|
/// Persists the web-of-trust parameters (Duniter sigQty / stepMax / validity),
|
|
/// so a young network can loosen them and tighten as it grows — exactly how Ğ1
|
|
/// itself evolved. Defaults to [WotParams.duniter]. Keystore-backed.
|
|
class WotSettings {
|
|
WotSettings(this._store);
|
|
|
|
final SecretStore _store;
|
|
|
|
static const _sigQtyKey = 'tane.social.wot.sigQty';
|
|
static const _stepMaxKey = 'tane.social.wot.stepMax';
|
|
static const _validityDaysKey = 'tane.social.wot.validityDays';
|
|
|
|
/// The active parameters (any unset field falls back to the Duniter default).
|
|
Future<WotParams> params() async {
|
|
const base = WotParams.duniter;
|
|
final sigQty = await _readInt(_sigQtyKey) ?? base.sigQty;
|
|
final stepMax = await _readInt(_stepMaxKey) ?? base.stepMax;
|
|
final validityDays =
|
|
await _readInt(_validityDaysKey) ?? base.sigValidity.inDays;
|
|
return WotParams(
|
|
sigQty: sigQty,
|
|
stepMax: stepMax,
|
|
sigValidity: Duration(days: validityDays),
|
|
);
|
|
}
|
|
|
|
Future<void> save(WotParams params) async {
|
|
await _store.write(_sigQtyKey, '${params.sigQty}');
|
|
await _store.write(_stepMaxKey, '${params.stepMax}');
|
|
await _store.write(_validityDaysKey, '${params.sigValidity.inDays}');
|
|
}
|
|
|
|
/// Restores the Ğ1 reference values.
|
|
Future<void> reset() => save(WotParams.duniter);
|
|
|
|
Future<int?> _readInt(String key) async {
|
|
final raw = await _store.read(key);
|
|
if (raw == null || raw.isEmpty) return null;
|
|
return int.tryParse(raw);
|
|
}
|
|
}
|