source: Klonkt/test/move-guardianship.test.js@ 44dfbd2

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

Eerst de guardianship verhuizen, dan pas de follow

Robins regel na zijn eigen verhuizing, en het log van beta bewijst hem:

[AP] outgoing Follow beta → https://soundfabrics.nl/ap/users/robo

(gated, awaiting guardians)

Beta is zelf een ward. Zijn UITGAANDE follow naar de verhuisde guardian werd
gepoort door §5.3, want op dat moment stond het nieuwe adres nog niet in zijn
guardian-lijst: handleMoveInbox werkte de relatie pas NA de follows bij. De
inkomende kant heeft precies hetzelfde: de ward gate't een Follow van een
onbekende, en de verhuisde guardian is op dat moment een onbekende.

Dus beide richtingen bleven hangen op een goedkeuring die niemand hoefde te geven,
omdat het om een guardian ging die er al was. Met de relatie eerst is de verhuisde
actor al erkend als de follows langskomen en gaat de auto-acceptatie door.

De volgorde is hier dus geen netheid maar de werking.

Changed files:
src/services/ActivityPubService.js

  • het guardianship-blok staat nu VOOR de follow-lus, met het waarom erbij

test/move-guardianship.test.js

  • test 5 meet de VOLGORDE, niet de uitkomst: hij leest de relatie uit binnen de injecteerbare followFn en eist dat die daar al op het nieuwe adres staat

remarks: de tegenproef is hier het punt. De vijf bestaande tests slagen ook met de
oude volgorde, want die kijken naar de eindtoestand. Met de guardianship-update er
wel in maar NA de follows valt alleen test 5 om. Suite 938 groen in UTC en
Europe/Amsterdam.

Dit is handmatig al rechtgezet voor beta en robo (relatie overgezet, follow opnieuw
gestuurd, beta's log gaat van "gated, awaiting guardians" naar "sig ok"). Deze commit
zorgt dat de volgende verhuizing die handmatige stap niet meer nodig heeft.

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 5.6 KB
Line 
1// Een Move is een Move: de guardian blijft dezelfde guardian.
2//
3// Toezicht is een gewone Follow (FEP-633c §5), en die verhuisde al mee. Maar de
4// guardianship-RELATIE bleef aan de oude URI hangen. Dat gaf de vervelendste
5// toestand van allemaal: de guardian ziet de posts van het kind gewoon
6// binnenkomen, terwijl alles dat op other_uri matcht omvalt. Half een vangnet
7// ziet eruit als een heel vangnet, en dan merk je het pas als het nodig is.
8import { test, beforeEach } from 'node:test';
9import assert from 'node:assert/strict';
10
11process.env.DATABASE_PATH = ':memory:';
12process.env.PUBLIC_BASE_URL = 'https://ons.example';
13
14const dbMod = await import('../src/config/database.js');
15const db = dbMod.default;
16{
17 const stil = console.log;
18 console.log = () => {};
19 try { dbMod.initializeDatabase(); } finally { console.log = stil; }
20}
21const AP = await import('../src/services/ActivityPubService.js');
22
23const OUD = 'https://oud.example/ap/users/kind';
24const NIEUW = 'https://nieuw.example/ap/users/kind';
25
26// De guardian zijn WIJ: een lokale site die het kind volgt en de relatie draagt.
27function zetKlaar({ status = 'accepted' } = {}) {
28 db.prepare('DELETE FROM ap_following').run();
29 db.prepare('DELETE FROM ap_guardianships').run();
30 db.prepare('INSERT OR IGNORE INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)')
31 .run('u1', 'u1', 'u1@test', 'x', 'god');
32 db.prepare('INSERT OR IGNORE INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)')
33 .run('s1', 'voogd', 'De voogd', 'u1');
34 db.prepare(`INSERT INTO ap_following (slug, actor_uri, handle, status, auto_boost)
35 VALUES (?,?,?,?,?)`).run('voogd', OUD, '@kind@oud.example', 'accepted', 1);
36 db.prepare(`INSERT INTO ap_guardianships (slug, other_uri, role, status)
37 VALUES (?,?,?,?)`).run('voogd', OUD, 'guardian', status);
38}
39
40const relatie = () => db.prepare('SELECT other_uri, role, status FROM ap_guardianships').all();
41
42// Geen netwerk: de Move-afhandeling accepteert injecteerbare functies.
43const stubs = {
44 verifiedActor: OUD,
45 fetchActorFn: async (uri) => ({ id: uri, inbox: `${uri}/inbox`, alsoKnownAs: [OUD] }),
46 followFn: async () => true,
47 unfollowFn: async () => true,
48};
49const move = { type: 'Move', actor: OUD, object: OUD, target: NIEUW };
50
51beforeEach(() => zetKlaar());
52
53test('na een Move wijst de guardianship naar het NIEUWE adres', async () => {
54 const stil = console.log; console.log = () => {};
55 try { await AP.handleMoveInbox(move, stubs); } finally { console.log = stil; }
56
57 const r = relatie();
58 assert.equal(r.length, 1, 'de relatie mag niet verdubbelen of verdwijnen');
59 assert.equal(r[0].other_uri, NIEUW, 'anders ziet de guardian de posts wel, maar valt de gate om');
60 assert.equal(r[0].role, 'guardian', 'de rol verandert niet: hij is dezelfde guardian');
61 assert.equal(r[0].status, 'accepted');
62});
63
64test('de Follow verhuist mee, met de uitgelicht-stand', async () => {
65 const gevolgd = [];
66 const stil = console.log; console.log = () => {};
67 try {
68 await AP.handleMoveInbox(move, {
69 ...stubs,
70 followFn: async (site, uri, boost) => { gevolgd.push([uri, boost]); return true; },
71 });
72 } finally { console.log = stil; }
73 assert.deepEqual(gevolgd, [[NIEUW, true]]);
74});
75
76test('een niet-geverifieerde Move raakt de guardianship niet aan', async () => {
77 const stil = console.warn; console.warn = () => {};
78 try {
79 // verifiedActor wijst niet naar de oude actor: dit is niet zijn Move.
80 await AP.handleMoveInbox(move, { ...stubs, verifiedActor: 'https://iemand.anders/ap/users/x' });
81 } finally { console.warn = stil; }
82 assert.equal(relatie()[0].other_uri, OUD,
83 'anders kan een vreemde het kind bij zijn guardians weghalen door een Move te sturen');
84});
85
86test('een relatie die nog niet geaccepteerd is blijft staan', async () => {
87 zetKlaar({ status: 'pending' });
88 const stil = console.log; console.log = () => {};
89 try { await AP.handleMoveInbox(move, stubs); } finally { console.log = stil; }
90 assert.equal(relatie()[0].other_uri, OUD,
91 'een verzoek dat nog loopt gaat over de OUDE actor; dat verhuizen zou een niet-bestaande relatie meenemen');
92});
93
94// De VOLGORDE, niet de uitkomst. De tests hierboven slagen ook als de relatie pas
95// na de follows wordt bijgewerkt, en juist dat ging mis bij Robins verhuizing:
96//
97// [AP] outgoing Follow beta → .../robo (gated, awaiting guardians)
98//
99// Beta is zelf een ward, dus zijn uitgaande follow naar de verhuisde guardian werd
100// gepoort omdat het nieuwe adres nog niet in zijn guardian-lijst stond. Beide
101// richtingen bleven hangen op een goedkeuring die niemand hoefde te geven.
102test('de guardianship is al bijgewerkt VOORDAT de follow uitgaat', async () => {
103 let standTijdensFollow = null;
104 const stil = console.log; console.log = () => {};
105 try {
106 await AP.handleMoveInbox(move, {
107 ...stubs,
108 followFn: async () => {
109 // Op dit moment moet de gate aan de andere kant ons al kennen.
110 standTijdensFollow = db.prepare('SELECT other_uri FROM ap_guardianships').get().other_uri;
111 return true;
112 },
113 });
114 } finally { console.log = stil; }
115
116 assert.equal(standTijdensFollow, NIEUW,
117 'staat de relatie hier nog op het oude adres, dan gate\'t de ward de follow van zijn eigen guardian');
118});
119
120test('een Move naar een geblokkeerde bestemming verandert niets', async () => {
121 db.prepare('INSERT INTO ap_blocks (slug, target, kind) VALUES (?,?,?)').run('voogd', NIEUW, 'actor');
122 const stil = console.log; console.log = () => {};
123 try { await AP.handleMoveInbox(move, stubs); } finally { console.log = stil; }
124 db.prepare('DELETE FROM ap_blocks').run();
125 assert.equal(relatie()[0].other_uri, OUD, 'geblokkeerd is geblokkeerd, ook voor een guardianship');
126});
Note: See TracBrowser for help on using the repository browser.