source: Klonkt/test/guardian-follow-queues.test.js@ 4c1e327

main
Last change on this file since 4c1e327 was 4c1e327, checked in by roboburr <roboburr@…>, 5 weeks ago

Guardianship Fase 2: gate-verzoeken bereiken een C2S-client (shaer-jdb)

Barts melding: in GuardianshipView staan de volgverzoeken niet, inkomend noch
uitgaand. De SECTIES in de app zijn er wel; er kwam alleen nooit iets binnen.

WELKE FASE 2 DIT IS. De faseplanning komt uit 780a7c6 "Guardianship Fase 0+1: de
echte multi-party handshake" -- Fase 0 het datamodel, Fase 1 de state-machine.
queues.js noemt Fase 2 twee keer, allebei over dit: "follows: pending gated
follows for my wards (5.3)". De gating ZELF is al gebouwd (shaer-hxg, gesloten
25 juli, getest en live); wat nooit gebeurde is het doorgeven aan een client.
Dat was een koersbesluit: shaer-sqo is in juli gesloten als vervallen met
"doorbouwen op de PWA-guardian, niet een aparte iOS-UI". Die koers is met de
Guardian-chip uit shaer-f8g omgedraaid, dus de stub kan nu dicht.

DRIE LAGEN, van onder naar boven.

  1. shaer:direction werd gezet en nooit gelezen. Bij een uitgaande gate stuurt de ward een Offer met 'shaer:direction': 'outgoing'; die vlag kwam in de hele codebase precies een keer voor, bij het versturen. De guardian sloeg hem op in dezelfde tak als een inkomende, waar follower de actor van de Follow is en wardUri die van de Offer -- bij een uitgaande allebei de ward. Het doel, waar het antwoord over gaat, viel weg. ap_follow_reviews heeft nu direction, target_uri en target_handle, en de inbox leest de vlag. Terugval voor oudere afzenders: is de volger de ward zelf, dan is het uitgaand -- dat volgt uit de vorm en hoeft niet geloofd te worden.
  1. followsCollection gaf een lege lijst terug. Vult nu uit twee bronnen: de doorgestuurde kopie van een remote ward, en een ward op deze instance. Die tweede hoort op termijn ook over de lijn (shaer-h6u).
  1. outgoingFollowsCollection serveerde alleen listForWard(slug): wat DEZE account als ward wil volgen. Voor een guardian is dat per definitie leeg. Nu bedient dezelfde wachtrij beide lezers, en dat kan omdat 5.1 een ward en een guardian wederzijds uitsluit: je bent het een of het ander.

Bij een remote ward wordt shaer:guardianCount WEGGELATEN in plaats van op nul
gezet: die set wordt op diens eigen server bijgehouden, en nul leest als "dit
kind heeft geen guardians" -- het tegenovergestelde van onbekend.

Bestaande rijen missen de richting en zijn niet te repareren; die vallen terug op
inkomend, want dat waren ze toen ook.

5 tests. Gecontroleerd dat ze bijten: leeg de follows-wachtrij en er vallen er
vier om. Suite 556/556.

  • Property mode set to 100644
File size: 4.1 KB
Line 
1// Guardianship Fase 2 (shaer-jdb): gate-verzoeken bereiken een C2S-client.
2//
3// De gating zelf werkt sinds shaer-hxg. Wat ontbrak was het DOORGEVEN: de
4// wachtrij `follows` gaf hardgecodeerd een lege lijst terug ("not built in
5// Klonkt yet (Fase 2)") en `outgoing-follows` serveerde alleen de ward-kant.
6// Daardoor bleven beide secties in Shaer altijd leeg.
7//
8// En daaronder zat de echte fout: shaer:direction werd bij het versturen gezet
9// en nergens gelezen, dus een UITGAAND verzoek werd opgeslagen als "deze ward
10// wil deze ward volgen" met het doel weggegooid.
11//
12// Run: npm test
13
14import { test } from 'node:test';
15import assert from 'node:assert/strict';
16
17process.env.DATABASE_PATH = ':memory:';
18process.env.PUBLIC_BASE_URL = 'https://klonkt.test';
19
20const dbMod = await import('../src/config/database.js');
21const db = dbMod.default;
22dbMod.initializeDatabase();
23const G = await import('../src/services/guardianship/index.js');
24
25db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)')
26 .run('u1', 'oma', 'o@test', 'x', 'god');
27db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)').run('s1', 'oma', 'Oma', 'u1');
28
29const WARD = 'https://kind.test/ap/users/kind';
30const VREEMDE = 'https://elders.test/users/vreemde';
31const DOEL = 'https://muziek.test/users/band';
32const ME = 'https://klonkt.test/ap/users/oma';
33
34test('een INKOMEND verzoek komt in de follows-wachtrij', () => {
35 G.follows.recordReview('oma', {
36 id: 'f-in', wardUri: WARD, follower: VREEMDE, followerHandle: '@vreemde@elders.test',
37 direction: 'incoming',
38 });
39 const c = G.followsCollection(`${ME}/queues/follows`, 'oma', ME);
40 assert.equal(c.totalItems, 1, 'deze wachtrij gaf hiervoor altijd een lege lijst terug');
41 const it = c.orderedItems[0];
42 assert.equal(it.actor, VREEMDE, 'de vreemde is de volger');
43 assert.equal(it.object, WARD, 'en de ward is het doel');
44 assert.equal(it['shaer:direction'], 'incoming');
45});
46
47test('een UITGAAND verzoek komt in de outgoing-wachtrij, met het doel erin', () => {
48 // De kern van de bug: hiervoor werd dit als inkomend opgeslagen met ward ==
49 // follower, en het doel -- waar het antwoord over gaat -- viel weg.
50 G.follows.recordReview('oma', {
51 id: 'f-uit', wardUri: WARD, follower: WARD, direction: 'outgoing',
52 target: DOEL, targetHandle: '@band@muziek.test',
53 });
54 const c = G.outgoingFollowsCollection(`${ME}/queues/outgoing-follows`, 'oma', ME);
55 const it = c.orderedItems.find((x) => x.id === 'f-uit');
56 assert.ok(it, 'een guardian zag hier nooit iets: de wachtrij serveerde alleen de ward-kant');
57 assert.equal(it.actor, WARD, 'de ward is hier de volger');
58 assert.equal(it.object, DOEL);
59 assert.equal(it['shaer:target'], DOEL, 'zonder dit valt er niets te beoordelen');
60 assert.equal(it['shaer:targetHandle'], '@band@muziek.test');
61 assert.equal(it['shaer:direction'], 'outgoing');
62});
63
64test('de twee richtingen lopen niet door elkaar', () => {
65 const inn = G.followsCollection(`${ME}/q/f`, 'oma', ME).orderedItems.map((x) => x.id);
66 const uit = G.outgoingFollowsCollection(`${ME}/q/o`, 'oma', ME).orderedItems.map((x) => x.id);
67 assert.deepEqual(inn, ['f-in']);
68 assert.ok(uit.includes('f-uit') && !uit.includes('f-in'));
69});
70
71test('bij een remote ward wordt het aantal guardians WEGGELATEN, niet op nul gezet', () => {
72 // De guardian-set van een remote ward wordt op diens eigen server bijgehouden.
73 // Nul sturen zou lezen als "dit kind heeft geen guardians", en dat is het
74 // tegenovergestelde van onbekend.
75 const it = G.followsCollection(`${ME}/q/f`, 'oma', ME).orderedItems[0];
76 assert.equal(it['shaer:guardianCount'], undefined);
77});
78
79test('een oude rij zonder richting telt als inkomend', () => {
80 // Bestaande rijen missen de kolom en zijn niet te repareren -- de informatie
81 // stond er nooit in. Ze horen terug te vallen op het geval dat ze toen waren.
82 db.prepare(`INSERT INTO ap_follow_reviews (id, guardian_slug, ward_uri, follower_uri, direction)
83 VALUES ('f-oud','oma',?,?,NULL)`).run(WARD, VREEMDE);
84 const inn = G.followsCollection(`${ME}/q/f`, 'oma', ME).orderedItems.map((x) => x.id);
85 assert.ok(inn.includes('f-oud'));
86});
Note: See TracBrowser for help on using the repository browser.