feat(app,learn): shared spaces' members on the device

Step 4 (e) of ADR 0044, its first part, for every app's screens.

- halkyon_app: `SharedSpaceGateway` on the module's `sharedSpace`
  endpoint (the spaces, their members and roles, inviting, handing on,
  leaving), refusals as `SpaceRefused`; `SharedKeys.trustIn` gives
  each member's safety code and whether it was compared or their keys
  changed, `markCompared`, and `trustNewKeys`, which pins the keys
  whose code was compared and never those the instance hands next.
  `FakeSharedSpaceServer` keeps the module's rules for tests, in step
  with `FakeSharedKeysServer`, which now knows members' handles.
- Learn's sharing makes its space through it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-11 14:39:12 +01:00
commit 02bb24428c
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -219,4 +219,43 @@ void main() {
expect(await bob.openMine(space), openedThese({}, refused: {'k1'}));
});
test("a member's safety code is the same on both sides, and is marked "
'compared once the person says so (D32)', () async {
final seen = (await alice.trustIn(space)).single;
expect(seen.person, 'bob');
expect(seen.changed, isFalse);
expect(seen.compared, isFalse);
expect(seen.code, (await bob.trustIn(space)).single.code);
await alice.markCompared('bob');
expect((await alice.trustIn(space)).single.compared, isTrue);
});
test('keys that changed are flagged with the code of the new ones, and '
'only the keys whose code was compared are trusted anew', () async {
await alice.trustIn(space);
await alice.markCompared('bob');
final mallorys = keysOf(malloryAccount);
final eves = keysOf((await crypto.newAccount('eve password')).keys);
server.handOutKeys('bob', mallorys);
final changed = (await alice.trustIn(space)).single;
expect(changed.changed, isTrue);
expect(changed.compared, isFalse);
expect(changed.code, aliceCipher.safetyCodeWith(mallorys));
// The instance hands out other keys again before the person trusts the
// ones they compared: those compared are pinned, and these differ.
server.handOutKeys('bob', eves);
await alice.trustNewKeys('bob', changed.keys);
final after = (await alice.trustIn(space)).single;
expect(after.changed, isTrue);
expect(after.code, aliceCipher.safetyCodeWith(eves));
server.handOutKeys('bob', mallorys);
final trusted = (await alice.trustIn(space)).single;
expect(trusted.changed, isFalse);
expect(trusted.compared, isTrue);
});
}