Changeset fbfd7a1 in Klonkt for src/config/database.js


Ignore:
Timestamp:
08/13/2026 10:34:36 PM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
6c4ff7e
Parents:
4101c89
Message:

Je berichten verhuizen mee: FEP-1580 plus een webinterface ervoor

FEP-7628 verhuist je volgers en zegt zelf dat de inhoud een ander probleem is.
Dat probleem stond open: na een Move bleven je berichten op de oude instantie
staan, en elke reactie van een derde wees naar een URI die verdwijnt zodra dat
domein opgezegd wordt. FEP-1580 regelt dat, status DRAFT.

DE AUTORISATIE IS DE MOVE, NIET EEN CODE. De bronkant behandelt een ondertekend
verzoek namens de doel-actor alsof de bron-actor het zelf deed. Dat mag omdat
moveAccount() no_backreference weigert: moved_to staat er alleen als de
doel-actor ons al in alsoKnownAs had. Beide kanten hebben ooit ja gezegd, dus er
is geen tweede vertrouwensmechanisme nodig. Een typefout komt hier niet binnen,
want die haalt de move zelf niet. Dat dit veilig is leunt op de keyId-binding
uit shaer-xd8i: zonder die controle is "wie tekende dit" te zacht om je hele
geschiedenis aan af te geven.

NIEUWE IDS ZIJN GEEN BUG, DE VERTAALTABEL IS HET ANTWOORD. Een verhuisd bericht
krijgt een eigen URI, want het staat op een ander domein. De migration-collectie
mapt oud naar nieuw en derden lezen die om hun eigen verwijzingen bij te werken.
Zonder die collectie is de draad kapot, met die collectie is het een
verhuisbericht. Niet-publieke items staan er alleen in voor wie ze mocht zien:
een lijst met de URIs van je fan-only posts is een lek, ook zonder de inhoud.

Er gaat geen Create de deur uit. Je volgers hebben die berichten jaren geleden
al gezien; driehonderd posts die als nieuw de tijdlijn in klateren is geen
verhuizing maar spam.

Daarnaast /admin/migrate: exporteren, importeren en ophalen via de
webinterface, zodat verhuizen geen SSH-toegang meer vraagt. Importeren gaat
altijd eerst droog, met een verslag en pas daarna een knop die het echt doet.

Getest op twee draaiende instanties, A verhuisd naar B via de echte
moveAccount. Anoniem zag A 3 van de 4 berichten; ondertekend als de doel-actor
kwamen alle 4 mee, inclusief de fan-only. Titel, webadres en publicatiedatum
blijven staan. Media komt echt over: gedownload, in de mediatabel, B serveert
het. Migration-collectie 4 rijen totaal, 3 publiek.

Changed files:
src/services/ActivityPubService.js

  • isMoveTarget: het hele autorisatiepredicaat van de bronkant
  • outboxAudience en mayReadNote: de doel-actor krijgt onze eigen kijkrechten
  • buildActor adverteert migration en moves, ook leeg (de FEP wijst er apart op dat "niets verhuisd" anders niet te onderscheiden is van "kent dit niet")
  • signedGetJson geexporteerd, de ingest heeft hem nodig
  • isMoveTarget en signedGetJson in de default export (movedLock verstopte zich een dag eerder precies zo)

src/services/ap-core.js

  • FEP-1580-termen in de JSON-LD-context

src/services/ArchiveImportService.js

  • een import uit een zip vult dezelfde vertaaltabel; de spec wil dat een geexporteerde collectie identiek behandeld wordt

src/routes/activitypub.js

  • /ap/users/:slug/migration en /moves
  • de blocked-collectie gaat open voor de doel-actor, want zichtbaarheidsvoorkeuren moeten meeverhuizen

src/config/database.js

  • ap_migration en ap_moves, plus sites.migration_complete

src/server.js

  • /admin/migrate aangesloten

src/views/pages/admin.ejs

  • knop naar Migreren

src/services/i18n.js

  • mig.* in nl/en/de

New file:
src/services/MigrationService.js

  • de doelkant: ingest-routine, migration- en moves-collectie, statusvlag

src/routes/admin-migrate.js

  • exporteren, droog importeren, echt importeren, ophalen bij de oude Klonkt

src/views/pages/admin-migrate.ejs

  • de pagina

test/fep1580-migration.test.js

  • 22 tests over beide rollen, plus de regressietest bij 4101c89

remarks: FEP-8b32 ontbreekt volledig (shaer-j1v0), dus er staat geen
handtekening onder de moves-collectie en we zijn niet naleveringsklaar. Bewust
geen leeg proof-veld: een derde die het controleert wordt dan misleid. De DERDE
rol zit er ook niet in, Klonkt leest nog geen migration-collecties van anderen,
dus andermans verhuizing repareert onze verwijzingen nog niet. Alle betrokken
FEPs zijn DRAFT, ook 7628 die we al volgden; 1580 is vers en de auteur schrijft
zelf dat het een audit verdient.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/config/database.js

    r4101c89 rfbfd7a1  
    218218  ensureColumn('sites', 'ap_aliases', 'TEXT');
    219219  ensureColumn('sites', 'moved_to', 'TEXT');   // FEP-7628 slice 2: waarheen dit account vertrok
     220  // FEP-1580: staat de ingest-routine nog open? 1 = klaar (en dat is ook de
     221  // stand van een site die nooit iets gemigreerd heeft, want er hangt niets).
     222  // Derden pollen op deze vlag, dus hij moet ook "er valt niets te wachten"
     223  // kunnen zeggen.
     224  ensureColumn('sites', 'migration_complete', 'INTEGER DEFAULT 1');
    220225
    221226  // Per-post noindex + type
     
    550555    -- de opstartkosten waren reacties maal tijdlijnrijen.
    551556    CREATE INDEX IF NOT EXISTS idx_ap_timeline_url ON ap_timeline(slug, url);
     557    -- FEP-1580: de vertaaltabel van een verhuizing. Per gemigreerd object waar
     558    -- het VANDAAN kwam en welke URI het HIER kreeg. Derden lezen deze mapping en
     559    -- werken er hun eigen inReplyTo/Like-verwijzingen mee bij; zonder deze tabel
     560    -- is "de berichten krijgen nieuwe adressen" een permanent kapotte draad.
     561    --
     562    -- De spec eist omgekeerd-chronologisch op het moment dat de kopie HIER is
     563    -- aangemaakt (niet de oorspronkelijke publicatiedatum). Daarom sorteren we
     564    -- op de autoincrement-id en niet op created_at: die heeft secondeprecisie,
     565    -- en een ingest zet er tientallen per seconde in.
     566    CREATE TABLE IF NOT EXISTS ap_migration (
     567      id INTEGER PRIMARY KEY AUTOINCREMENT,
     568      slug TEXT NOT NULL,          -- onze site, de DOELkant van de verhuizing
     569      origin TEXT NOT NULL,        -- object-URI op de broninstantie
     570      target TEXT NOT NULL,        -- de URI die het object hier kreeg
     571      source_actor TEXT NOT NULL DEFAULT '',
     572      is_public INTEGER NOT NULL DEFAULT 1,   -- niet-publieke items horen niet in een publieke pagina
     573      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
     574      UNIQUE(slug, origin)
     575    );
     576    CREATE INDEX IF NOT EXISTS idx_ap_migration_slug ON ap_migration(slug, id DESC);
     577    -- De Move-activities zelf, gededupliceerd. FEP-1580 wil dat deze collectie
     578    -- een op zichzelf staand bewijs vormt voor de items in ap_migration, met een
     579    -- FEP-8b32 integrity proof van de bron-actor plus een kopie van diens
     580    -- actor-document. Wij bewaren allebei die stukken al (activity_json en
     581    -- actor_json), maar Klonkt kent 8b32 nog niet: zie shaer-j1v0. Zolang dat
     582    -- open staat is deze collectie structureel goed en niet verifieerbaar.
     583    CREATE TABLE IF NOT EXISTS ap_moves (
     584      id INTEGER PRIMARY KEY AUTOINCREMENT,
     585      slug TEXT NOT NULL,
     586      move_id TEXT NOT NULL,       -- id van de Move-activity, tevens dedup-sleutel
     587      source_actor TEXT NOT NULL,
     588      target_actor TEXT NOT NULL,
     589      activity_json TEXT NOT NULL,
     590      actor_json TEXT,             -- inline kopie van het bron-actordocument
     591      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
     592      UNIQUE(slug, move_id)
     593    );
    552594    CREATE TABLE IF NOT EXISTS ap_blocks (
    553595      id INTEGER PRIMARY KEY AUTOINCREMENT,
Note: See TracChangeset for help on using the changeset viewer.