feat(block2): wire the social identity into app_seeds (DI, no UI)
Third slice: bridge Block 1's root seed to the Block 2 transport foundation. - SocialService: derives the secp256k1 Nostr identity from the SAME root seed the recovery QR backs up (no extra backup), exposes npub/pubkey, and opens a SocialSession = one shared connection carrying all three transports. - injector.dart: registers SocialService in get_it. Local-first — derivation is cheap + offline; no relay is contacted at startup. Replaces the old "nodeId slice of the seed is the social pubkey" placeholder; keeps the CRDT author id distinct (unifying it would rewrite authorship — a later decision). - Test: deterministic identity from the seed hex, matches commons_core, rejects malformed hex. 5 tests green; app_seeds analyzes clean (0 errors).
This commit is contained in:
parent
2b58fe40ce
commit
51f9338433
3 changed files with 132 additions and 2 deletions
48
apps/app_seeds/test/services/social_service_test.dart
Normal file
48
apps/app_seeds/test/services/social_service_test.dart
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import 'package:commons_core/commons_core.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tane/services/social_service.dart';
|
||||
|
||||
/// Wiring test: the app derives its social identity from the SAME root seed the
|
||||
/// recovery QR backs up, deterministically and without any network.
|
||||
void main() {
|
||||
// A fixed 32-byte seed (64 hex chars).
|
||||
const seedHex =
|
||||
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f';
|
||||
|
||||
test('derives a stable Nostr identity from the root-seed hex', () async {
|
||||
final service = await SocialService.fromRootSeedHex(seedHex);
|
||||
expect(service.npub, startsWith('npub1'));
|
||||
expect(service.publicKeyHex, matches(RegExp(r'^[0-9a-f]{64}$')));
|
||||
});
|
||||
|
||||
test('is deterministic: same seed → same public identity', () async {
|
||||
final a = await SocialService.fromRootSeedHex(seedHex);
|
||||
final b = await SocialService.fromRootSeedHex(seedHex);
|
||||
expect(a.publicKeyHex, b.publicKeyHex);
|
||||
expect(a.npub, b.npub);
|
||||
});
|
||||
|
||||
test('matches commons_core derivation on the same bytes', () async {
|
||||
final service = await SocialService.fromRootSeedHex(seedHex);
|
||||
final direct = await NostrKeyDerivation.deriveFromSeed([
|
||||
for (var i = 0; i < seedHex.length; i += 2)
|
||||
int.parse(seedHex.substring(i, i + 2), radix: 16),
|
||||
]);
|
||||
expect(service.publicKeyHex, direct.publicKeyHex);
|
||||
});
|
||||
|
||||
test('a different seed yields a different identity', () async {
|
||||
final a = await SocialService.fromRootSeedHex(seedHex);
|
||||
final b = await SocialService.fromRootSeedHex(
|
||||
'ff${seedHex.substring(2)}',
|
||||
);
|
||||
expect(a.publicKeyHex, isNot(b.publicKeyHex));
|
||||
});
|
||||
|
||||
test('rejects a malformed (odd-length) seed hex', () async {
|
||||
await expectLater(
|
||||
SocialService.fromRootSeedHex('abc'),
|
||||
throwsA(isA<ArgumentError>()),
|
||||
);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue