source: Klonkt/test/move-guardianship.test.js@ 47db4b5

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

Een Move is een Move: de guardianship verhuist mee

Robins redenering, en die is korter dan de mijne: de guardian is nog steeds
dezelfde guardian, dus dat mag gewoon gebeuren. Dat klopt met de spec. FEP-633c §5
zegt dat toezicht een gewone Follow is, en die verhuisde hier al mee, inclusief de
uitgelicht-stand.

Alleen de RELATIE bleef aan de oude URI hangen. Daar stond een console.warn met
"left untouched (shaer-tge)" en verder niets. Dat gaf de vervelendste toestand van
allemaal: de guardian ziet de posts van het kind gewoon binnenkomen, terwijl alles
dat op other_uri matcht omvalt (de gate op een nieuwe volger, het escalatiepad,
listGuardians bij het kind). Half een vangnet ziet eruit als een heel vangnet, en
dan merk je het pas op het moment dat het nodig is.

Nu een UPDATE naast de re-follow, met dezelfde bescherming eromheen: alleen na een
geverifieerde Move, alleen voor een geaccepteerde relatie, en niet naar een
geblokkeerde bestemming.

De twee harde randen van shaer-tge blijven staan en gaan over iets anders dan ik
eerst dacht: weigeren te verhuizen naar een instance die shaer:guardians niet kan
dragen is een controle aan de UITGAANDE kant, en terugkeren-zonder-set is een
alsoKnownAs-kwestie. Die bead blijft dus open, maar smaller.

Changed files:
src/services/ActivityPubService.js

  • handleMoveInbox werkt ap_guardianships.other_uri bij in plaats van te waarschuwen

New file:
test/move-guardianship.test.js

  • de relatie wijst na de Move naar het nieuwe adres, en verdubbelt niet
  • de Follow verhuist mee met de uitgelicht-stand
  • een NIET-geverifieerde Move raakt hem niet aan (anders haalt een vreemde een kind bij zijn guardians weg met een verzonnen Move)
  • een nog niet geaccepteerde relatie blijft staan
  • een geblokkeerde bestemming verandert niets

remarks: tegenproef gedaan. Zonder de fix valt alleen test 1 om en blijven de vier
bewakingstests groen, dus ze meten de reparatie en niet zichzelf. Suite 932 groen in
UTC en Europe/Amsterdam. Onderweg had ik de kolomnaam van ap_blocks verkeerd
(target, niet actor_uri); dat was mijn test, niet de code.

FEP-633c zegt NIETS over verhuizen. Dat is een gat in de spec, niet alleen in
Klonkt, en het is een paragraaf waard.

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

  • Property mode set to 100644
File size: 4.5 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
94test('een Move naar een geblokkeerde bestemming verandert niets', async () => {
95 db.prepare('INSERT INTO ap_blocks (slug, target, kind) VALUES (?,?,?)').run('voogd', NIEUW, 'actor');
96 const stil = console.log; console.log = () => {};
97 try { await AP.handleMoveInbox(move, stubs); } finally { console.log = stil; }
98 db.prepare('DELETE FROM ap_blocks').run();
99 assert.equal(relatie()[0].other_uri, OUD, 'geblokkeerd is geblokkeerd, ook voor een guardianship');
100});
Note: See TracBrowser for help on using the repository browser.