feat(app): a shared space's content taken from its members' signatures
ADR 0044, D20: a row in a shared space counts as genuine when any member this device pinned signed it, current or former, never by the author column the row names. - `ContentCipher.trustSigners`: content sealed with a key is checked against the signing keys given for it, in place of the account's alone; `FakeContentCipher` tells authors apart likewise. - `KeyPins` keeps who it saw in each space (`sawIn`) and the signing keys pinned for someone before a reset (`earlierSigning`), so what they wrote stays readable; `signersIn` gives a space's signers. `key_pins.json` holds both (`pins`, `spaces`); a file written by step 3, on no released app, counts as none. - `SharedKeys` pins the person's own keys too, records the members it checks, and trusts the space's signers for each key it shares or opens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
92b87e218d
commit
5faf3fce58
1 changed files with 336 additions and 68 deletions
|
|
@ -54,11 +54,52 @@ void main() {
|
|||
test('a file not holding pins counts as none', () async {
|
||||
await file.parent.create(recursive: true);
|
||||
await file.writeAsString('{not json');
|
||||
expect(await FileKeyPinStore(file).read(), isEmpty);
|
||||
var book = await FileKeyPinStore(file).read();
|
||||
expect(book.pins, isEmpty);
|
||||
expect(book.spaces, isEmpty);
|
||||
await file.writeAsString(
|
||||
'{"bob": {"encryption": "%%", "signing": "", '
|
||||
'"verified": false}, "carol": 3}',
|
||||
'{"pins": {"bob": {"encryption": "%%", "signing": "", '
|
||||
'"verified": false, "earlierSigning": []}, "carol": 3}, '
|
||||
'"spaces": {"s": 4}}',
|
||||
);
|
||||
expect(await FileKeyPinStore(file).read(), isEmpty);
|
||||
book = await FileKeyPinStore(file).read();
|
||||
expect(book.pins, isEmpty);
|
||||
expect(book.spaces, isEmpty);
|
||||
});
|
||||
|
||||
test('signatures count in a space from everyone seen there, by every '
|
||||
'signing key pinned for them, earlier ones too (D20)', () async {
|
||||
final pins = KeyPins(FileKeyPinStore(file));
|
||||
await pins.check('bob', keys(1));
|
||||
await pins.check('carol', keys(5));
|
||||
await pins.check('mallory', keys(9));
|
||||
await pins.sawIn('space', ['bob', 'carol']);
|
||||
await pins.trustAnew('bob', keys(3));
|
||||
|
||||
final later = KeyPins(FileKeyPinStore(file));
|
||||
final signers = await later.signersIn('space');
|
||||
expect(
|
||||
signers,
|
||||
unorderedEquals([keys(3).signing, keys(1).signing, keys(5).signing]),
|
||||
);
|
||||
expect(signers, isNot(contains(keys(9).signing)));
|
||||
expect(await later.signersIn('elsewhere'), isEmpty);
|
||||
});
|
||||
|
||||
test(
|
||||
'someone gone from a space still counts for what they signed there',
|
||||
() async {
|
||||
final pins = KeyPins(FileKeyPinStore(file));
|
||||
await pins.check('bob', keys(1));
|
||||
await pins.sawIn('space', ['bob']);
|
||||
await pins.sawIn('space', <String>[]);
|
||||
expect(await pins.signersIn('space'), [keys(1).signing]);
|
||||
},
|
||||
);
|
||||
|
||||
test('a seen person without pinned keys counts for nothing', () async {
|
||||
final pins = KeyPins(FileKeyPinStore(file));
|
||||
await pins.sawIn('space', ['bob']);
|
||||
expect(await pins.signersIn('space'), isEmpty);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue