Ignore:
Timestamp:
08/06/2026 01:27:37 PM (5 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
621126b
Parents:
279ca0b
git-author:
Robin <roboburr@…> (08/06/2026 01:27:28 PM)
git-committer:
roboburr <roboburr@…> (08/06/2026 01:27:37 PM)
Message:

Onthoud de URI van antwoorden die we al ontvangen (shaer-e9g)

Antwoorden van accounts die je volgt komen gewoon binnen, ondertekend door de
schrijver zelf. belongsInTimeline houdt ze uit de Krant -- een antwoord hoort in
zijn draad, niet in de tijdlijn -- en daarna bewaarden we ze nergens. Kwam er
later een DOORGESTUURD antwoord op zo'n bericht, dan kende knownNoteUri de ouder
niet en werd het afgewezen. Terwijl we die ouder wel degelijk hadden gehad.

Op boiert ging daar 72% van het doorstuurverkeer op stuk: 18 unieke reacties
geweigerd tegen 7 geaccepteerd, in drie uur. Alle achttien waren echte antwoorden
in echte gesprekken, en de ontbrekende ouders waren stuk voor stuk geschreven
door accounts die boiert volgt.

Nieuwe tabel ap_seen_notes, alleen de URI. Geen inhoud, niets extra's op het
scherm, geen tweede administratie naast ap_timeline: dit beantwoordt uitsluitend
de vraag 'kennen wij dit bericht?'. Na 30 dagen gesnoeid, af en toe tijdens het
schrijven zodat een server die weken doorloopt ook opruimt -- doorsturen gebeurt
kort na het antwoord.

De grens zit in WIE er onthouden wordt, en dat is de hele veiligheidsvraag.
Alleen schrijvers die je zelf volgt. Zou het voor iedereen gelden, dan kan een
vreemde eerst een bericht neerleggen en daarna met een doorgestuurd antwoord
daarop de dereference naar een adres van zijn keuze sturen. Er wordt dus niets
van een onbekende aangenomen dat we niet al hadden.

Dit volgt op Barts keuze om gesprekken van anderen NIET te gaan volgen: dat
blijft zo. We stoppen alleen met weggooien wat we al kregen.

Gecontroleerd dat de tests bijten: haal de lookup uit knownNoteUri en geval 5
valt om, haal de volg-eis weg en geval 3. Suite 478/478.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r279ca0b r32a4ffb  
    17151715    if (db.prepare('SELECT 1 FROM ap_timeline WHERE id = ? LIMIT 1').get(uri)) return true;
    17161716    if (db.prepare('SELECT 1 FROM ap_interactions WHERE object_uri = ? LIMIT 1').get(uri)) return true;
     1717    // Een antwoord dat we al bezorgd kregen van iemand die we volgen (shaer-e9g).
     1718    if (db.prepare('SELECT 1 FROM ap_seen_notes WHERE uri = ? LIMIT 1').get(uri)) return true;
    17171719  } catch { /* bij twijfel niet ophalen */ }
    17181720  return false;
    17191721}
     1722
     1723/**
     1724 * Onthoud dat we dit bericht al eens bezorgd kregen.
     1725 *
     1726 * Alleen de URI. Geen inhoud, niets op het scherm, geen tweede weergave -- dit
     1727 * beantwoordt uitsluitend de vraag "kennen wij dit bericht?" die knownNoteUri
     1728 * stelt voordat er iets bij de bron wordt opgehaald.
     1729 *
     1730 * De beller bepaalt WIE er onthouden wordt, en dat is de hele veiligheidsvraag:
     1731 * onthouden we zomaar alles wat iemand aflevert, dan kan een vreemde eerst een
     1732 * bericht neerleggen en daarna met een doorgestuurd antwoord dáárop ons naar een
     1733 * adres van zijn keuze sturen. Vandaar dat handleInbox dit alleen doet voor
     1734 * schrijvers die je zelf volgt.
     1735 */
     1736const SEEN_NOTES_DAYS = 30;
     1737let _seenSinceSnoei = 0;
     1738function rememberNoteUri(uri) {
     1739  if (!uri || typeof uri !== 'string') return;
     1740  try {
     1741    db.prepare('INSERT OR IGNORE INTO ap_seen_notes (uri) VALUES (?)').run(uri);
     1742    // Af en toe opruimen, niet bij het opstarten: een server die weken doorloopt
     1743    // zou anders nooit snoeien. Doorsturen gebeurt kort na het antwoord, dus wat
     1744    // ouder is dan een maand beantwoordt geen enkele vraag meer.
     1745    if (++_seenSinceSnoei >= 500) {
     1746      _seenSinceSnoei = 0;
     1747      const r = db.prepare(`DELETE FROM ap_seen_notes WHERE created_at < datetime('now', '-${SEEN_NOTES_DAYS} days')`).run();
     1748      if (r.changes) console.log(`[AP] seen notes: ${r.changes} pruned`);
     1749    }
     1750  } catch { /* niet fataal */ }
     1751}
     1752const isFollowedActor = (uri) => {
     1753  try { return !!db.prepare('SELECT 1 FROM ap_following WHERE actor_uri = ? LIMIT 1').get(uri); } catch { return false; }
     1754};
    17201755
    17211756// Mislukte dereferences kort onthouden. Mastodon herhaalt een bezorging
     
    21242159        console.log('[AP] timeline +', actorUri, 'x' + subs.length);
    21252160      }
     2161    }
     2162    // Een ANTWOORD van iemand die we volgen: bewaar de URI (shaer-e9g). Zo'n
     2163    // bericht komt hier gewoon binnen, ondertekend door de schrijver zelf, maar
     2164    // belongsInTimeline houdt het uit de Krant en daarna raakten we het kwijt.
     2165    // Kwam er later een doorgestuurd antwoord OP dat bericht, dan kenden we de
     2166    // ouder niet en wezen we het af -- terwijl we hem wel degelijk hadden gehad.
     2167    // Er verandert niets aan wat we tonen of van vreemden aannemen: de schrijver
     2168    // moet iemand zijn die je zelf bent gaan volgen.
     2169    if (actorUri && !isLocalActor && o.id && o.inReplyTo && noteVisibility(o) !== 'direct' && isFollowedActor(actorUri)) {
     2170      rememberNoteUri(o.id);
    21262171    }
    21272172    // Mentioned in a post that is NOT a reply to our content (a reply to us already returned
Note: See TracChangeset for help on using the changeset viewer.