Changeset 6d7ea52 in Klonkt for src


Ignore:
Timestamp:
09/04/2026 12:40:22 PM (4 days ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
21cebed
Parents:
1d1fdc9
Message:

De noodknop is niet meer door een vreemde uit te zetten (shaer-gt70)

De markering op een hulpvraag werd van IEDEREEN aangenomen: de enige
voorwaarde was dat de actor niet lokaal is. Ondertekening zegt WIE, niet
of het MAG, en die tweede laag stond er niet. Afgehandeld kent geen
terugdraai en de vraag verdwijnt daarna uit de teller van elke guardian,
dus elke ondertekende actor die de URI kende kon de noodknop van een kind
uitzetten.

DE WARD IS DE BRON VAN WAARHEID over wie zijn guardians zijn -- onze
eigen tabel kent alleen onze relatie. existingGuardiansOf stelt die vraag
op de goede plek: lokaal als wij de ward hosten, anders shaer:guardians
van zijn actor. En WELKE ward erbij hoort komt uit onze eigen
administratie (de hulpvraag zoals wij hem opsloegen), nooit uit wat de
afzender beweert. Kennen we die hulpvraag niet, dan is er niets te
markeren.

Met een cache van vijf minuten, want het remote geval is een
netwerkaanroep in het inbox-pad -- zonder cache is dat een manier om onze
inbox te laten wachten. Een MISLUKTE ophaal wordt niet als lege lijst
onthouden: dan zou een tijdelijk onbereikbare server vijf minuten lang
elke markering weigeren.

TWEEDE VONDST, gemeten tijdens het bouwen: dezelfde regels riepen
wakeGuardian(slug) aan met een slug die in die scope niet bestaat. De
markering werd dus vastgelegd en daarna gooide de handler een
ReferenceError -- het paneel hoorde het nooit en de rest van de
verwerking van die activiteit viel weg. Nu wakeGuardian(vraag.slug): het
paneel dat de hulpvraag houdt. slugParam zou ook fout zijn, want die is
null op de gedeelde inbox.

Vijf toetsen, tegenbewijs tegen de code van hiervoor: daar vallen ze alle
vijf. Volle suite 1260 groen.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ap-inbox.js

    r1d1fdc9 r6d7ea52  
    138138  try { return !!db.prepare('SELECT 1 FROM ap_following WHERE actor_uri = ? LIMIT 1').get(uri); } catch { return false; }
    139139};
     140
     141/**
     142 * De hulpvraag zoals WIJ hem opsloegen (shaer-gt70).
     143 *
     144 * Een markering wijst naar een note-URI, en die komt van de afzender. Welke
     145 * ward erbij hoort mag daarom niet uit die markering komen maar uit onze eigen
     146 * rij: de hulpvraag kwam hier binnen als directe vermelding met help_request=1,
     147 * en `actor_uri` daarvan IS de ward.
     148 *
     149 * Geen rij, geen markering. Dat sluit meteen de aardigste variant af: iemand
     150 * die markeringen stuurt voor hulpvragen die hij ergens anders zag.
     151 */
     152function helpRequestRow(noteUri) {
     153  if (!noteUri || typeof noteUri !== 'string') return null;
     154  try {
     155    return db.prepare('SELECT slug, actor_uri FROM ap_mentions WHERE object_uri = ? AND help_request = 1 LIMIT 1').get(noteUri) || null;
     156  } catch { return null; }
     157}
     158
     159/**
     160 * Is deze actor guardian van deze ward?
     161 *
     162 * De WARD is de bron van waarheid over zijn eigen guardians -- onze tabel kent
     163 * alleen onze eigen relatie. existingGuardiansOf stelt de vraag op de goede
     164 * plek: hosten wij de ward, dan is het een databaselezing; woont hij elders,
     165 * dan komt het uit shaer:guardians op zijn actor.
     166 *
     167 * MET EEN CACHE, want dat tweede geval is een netwerkaanroep in het inbox-pad.
     168 * Zonder zou een vreemde onze inbox kunnen laten wachten door markeringen te
     169 * blijven sturen. De lokale tak raakt de cache ook, en dat kost daar niets.
     170 *
     171 * Vijf minuten is kort genoeg dat een verse guardian niet lang buiten staat, en
     172 * lang genoeg om herhaald bevragen te dempen. Een geweigerde markering is niet
     173 * verloren: de andere kant levert opnieuw af, en dan is de cache ververst.
     174 */
     175const _guardiansOfWard = new Map();   // ward-uri -> { at, set }
     176const GUARDIAN_CACHE_MS = 5 * 60 * 1000;
     177async function isGuardianOfWard(actorUri, wardUri) {
     178  if (!actorUri || !wardUri) return false;
     179  const nu = Date.now();
     180  const gecached = _guardiansOfWard.get(wardUri);
     181  if (gecached && nu - gecached.at < GUARDIAN_CACHE_MS) return gecached.set.has(actorUri);
     182  let lijst = [];
     183  try { lijst = await Guardianship.existingGuardiansOf(wardUri); } catch { lijst = []; }
     184  // Een MISLUKTE ophaal niet als lege lijst wegschrijven: dan zou een tijdelijk
     185  // onbereikbare server vijf minuten lang elke markering weigeren. Bij twijfel
     186  // niets onthouden en de volgende keer opnieuw kijken.
     187  if (Array.isArray(lijst) && lijst.length) {
     188    if (_guardiansOfWard.size > 500) _guardiansOfWard.clear();   // simpele begrenzing
     189    _guardiansOfWard.set(wardUri, { at: nu, set: new Set(lijst) });
     190  }
     191  return Array.isArray(lijst) && lijst.includes(actorUri);
     192}
    140193
    141194// Mislukte dereferences kort onthouden. Mastodon herhaalt een bezorging
     
    687740      const mark = Guardianship.help.parseMarker(o);
    688741      if (mark) {
    689         const ai = actorInfo(await resolveActor(actorUri).catch(() => null), actorUri);
    690         Guardianship.help.record(mark.noteUri, actorUri, mark.kind, ai && ai.handle);
    691         wakeGuardian(slug);   // een mede-guardian pakte iets op: het paneel hoort het meteen
    692         console.log('[AP] help', mark.kind, actorUri, '→', mark.noteUri);
     742        // WIE MAG DIT (shaer-gt70). Hier stond alleen "de actor is niet lokaal",
     743        // en dat is geen poort: elke ondertekende actor die de URI van een
     744        // hulpvraag kende kon hem op 'handled' zetten. Afgehandeld kent geen
     745        // terugdraai en de vraag verdwijnt daarna uit de teller van ELKE
     746        // guardian -- een vreemde kon dus de noodknop van een kind uitzetten.
     747        //
     748        // Ondertekening zegt WIE, niet OF HET MAG. Die tweede laag stond er niet.
     749        //
     750        // DE WARD IS DE BRON VAN WAARHEID over wie zijn guardians zijn; onze
     751        // eigen tabel kent alleen ONZE relatie. existingGuardiansOf stelt die
     752        // vraag op de goede plek: lokaal opzoeken als wij de ward hosten,
     753        // anders shaer:guardians van zijn actor.
     754        //
     755        // En WELKE ward dat is komt uit onze EIGEN administratie -- de
     756        // hulpvraag zoals wij hem opsloegen -- nooit uit wat de afzender
     757        // beweert. Kennen we die hulpvraag niet, dan is er niets te markeren.
     758        const vraag = helpRequestRow(mark.noteUri);
     759        if (!vraag) {
     760          console.warn('[AP] help-markering voor een onbekende hulpvraag, genegeerd:', actorUri, '→', mark.noteUri);
     761        } else if (!(await isGuardianOfWard(actorUri, vraag.actor_uri))) {
     762          console.warn('[AP] help-markering van iemand die geen guardian van deze ward is, geweigerd:', actorUri, '→', mark.noteUri);
     763        } else {
     764          const ai = actorInfo(await resolveActor(actorUri).catch(() => null), actorUri);
     765          Guardianship.help.record(mark.noteUri, actorUri, mark.kind, ai && ai.handle);
     766          // Het paneel dat de hulpvraag HOUDT wordt gewekt, en dat is
     767          // `vraag.slug`. Hier stond `slug`, en die bestaat in deze scope niet:
     768          // de markering werd vastgelegd en daarna gooide de handler een
     769          // ReferenceError, dus het paneel hoorde het nooit en de rest van de
     770          // verwerking van deze activiteit viel weg. Gemeten, niet geredeneerd.
     771          // slugParam zou hier ook fout zijn: op de gedeelde inbox is die null.
     772          wakeGuardian(vraag.slug);   // een mede-guardian pakte iets op: het paneel hoort het meteen
     773          console.log('[AP] help', mark.kind, actorUri, '→', mark.noteUri);
     774        }
    693775      }
    694776    }
Note: See TracChangeset for help on using the changeset viewer.