Ignore:
Timestamp:
08/06/2026 09:19:49 AM (5 weeks ago)
Author:
Claude (agent) <aiclaude@…>
Branches:
main
Children:
7842ca1
Parents:
68a4d1b
git-author:
Robin <roboburr@…> (08/06/2026 09:19:48 AM)
git-committer:
Claude (agent) <aiclaude@…> (08/06/2026 09:19:49 AM)
Message:

Interact-pagina toonde geen reactie: twee sleutelruimtes samengetrokken

Robins melding: sound-fabrics.com/effortlesseffect is geliket EN geboost, maar
de knoppen op de interact-pagina lichtten niet op.

Een post heeft twee URI's. Zijn AP-object-id (.../ap/notes/<uuid>), die de Krant
en het C2S-pad spreken, en zijn leesbare permalink (.../effortlesseffect), waar
de interact-pagina mee binnenkomt. De tussentabel stond vol object-URI's -- alle
zestien rijen -- en de interact-pagina zocht op de permalink. De reactie bestond
dus wel; we keken op de verkeerde sleutel.

Dit is de naad die ik in fase 1 bewust open liet met de opmerking dat
samentrekken werk voor fase 2 was. Dat uitstel was fout: zodra het leespad de
tussentabel volgde, werd een bestaande reactie onzichtbaar in plaats van
inconsistent. canonicalReactionUri vertaalt nu bij zowel lezen als schrijven naar
de object-URI, met de permalink als ingang. Kennen we de post niet, dan blijft de
invoer de sleutel, zodat een reactie op iets buiten je tijdlijn blijft werken.

setReaction gebruikt daarmee EEN sleutel voor beide bronnen in plaats van de
gestuurde voor de tussentabel en de opgeloste voor de vlag.

Drie tests erbij, waaronder Robins geval bij naam: liken via de object-URI en
uitlezen via de permalink, en andersom.

LET OP BIJ UITROL ELDERS: op dev staan alle tussentabel-rijen al op de
object-URI, dus daar viel niets te migreren. Op een instance waar de
interact-pagina eerder is gebruikt kunnen rijen op de permalink staan; die worden
na deze wijziging niet meer gevonden. Meet dat vóór de uitrol:

SELECT COUNT(*) FROM ap_my_reactions r

WHERE NOT EXISTS (SELECT 1 FROM ap_timeline t

WHERE t.slug=r.site_slug AND t.id=r.target_uri);

Suite 434/434.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • test/reactions-characterization.test.js

    r68a4d1b r6bc5ebd  
    193193});
    194194
    195 test('setReaction: gescheiden sleutels blijven werken zolang ze bestaan', () => {
    196   // De tussentabel wordt gesleuteld op wat de client stuurde, de vlag op de
    197   // opgeloste object-URI. Meestal gelijk, niet gegarandeerd. flagUri houdt dat
    198   // uit elkaar tot fase 2 ze samentrekt.
     195test('setReaction: flagUri bepaalt de sleutel voor BEIDE bronnen', () => {
     196  // Vroeger kreeg de tussentabel de URI die de client stuurde en de vlag de
     197  // opgeloste. Nu is het er één, anders is dezelfde like onvindbaar vanaf een
     198  // pagina die de andere URI kent.
    199199  const gestuurd = 'https://r.test/@anna/123';
    200200  const opgelost = uri('sr3');
    201201  seedTimeline(opgelost);
    202202  AP.setReaction('me', gestuurd, 'like', true, { flagUri: opgelost });
    203   assert.equal(AP.getMyReactions('me', gestuurd).liked, true, 'op de gestuurde uri');
    204   assert.equal(AP.getTimelineReaction('me', opgelost).liked, true, 'op de opgeloste uri');
     203  assert.equal(AP.getReaction('me', opgelost).liked, true, 'onder de opgeloste uri');
     204  assert.equal(AP.getTimelineReaction('me', opgelost).liked, true, 'en de vlag ook');
     205  assert.equal(AP.getMyReactions('me', gestuurd).liked, false, 'niet meer onder de gestuurde');
    205206});
    206207
     
    273274  }
    274275});
     276
     277// ── De permalink en de object-URI zijn dezelfde post ─────────────────────
     278
     279test('een like uit de Krant is zichtbaar op de interact-pagina (Robins melding)', () => {
     280  // De Krant kent een post als AP-object-URI, de interact-pagina als permalink.
     281  // Zochten die twee in verschillende sleutelruimtes, dan toonde een geboost en
     282  // geliket bericht daar geen enkele highlight -- terwijl de reactie bestond.
     283  const obj = uri('perm1');
     284  const permalink = 'https://sound-fabrics.com/effortlesseffect';
     285  db.prepare(`INSERT OR IGNORE INTO ap_timeline (id, slug, author_uri, author_name, content, url, created_at)
     286              VALUES (?,?,?,?,?,?,?)`)
     287    .run(obj, 'me', 'https://r.test/users/anna', 'Anna', '<p>x</p>', permalink, '2026-08-06 09:00:00');
     288
     289  AP.setReaction('me', obj, 'like', true);      // zoals de Krant het doet
     290  AP.setReaction('me', obj, 'boost', true);
     291  // en de interact-pagina vraagt het met de permalink:
     292  assert.deepEqual(AP.getReaction('me', permalink), { liked: true, boosted: true });
     293});
     294
     295test('andersom net zo: reageren via de permalink landt op de object-URI', () => {
     296  const obj = uri('perm2');
     297  const permalink = 'https://sound-fabrics.com/tweede';
     298  db.prepare(`INSERT OR IGNORE INTO ap_timeline (id, slug, author_uri, author_name, content, url, created_at)
     299              VALUES (?,?,?,?,?,?,?)`)
     300    .run(obj, 'me', 'https://r.test/users/bo', 'Bo', '<p>y</p>', permalink, '2026-08-06 09:00:00');
     301
     302  AP.setReaction('me', permalink, 'like', true);   // zoals de interact-pagina het doet
     303  assert.equal(AP.getReaction('me', obj).liked, true, 'onder de object-uri opgeslagen');
     304  assert.equal(AP.getTimelineReaction('me', obj).liked, true, 'dus de vlag landt ook goed');
     305  assert.equal(AP.getReaction('me', permalink).liked, true, 'en blijft vindbaar via de permalink');
     306});
     307
     308test('een reactie op iets buiten je tijdlijn blijft gewoon werken', () => {
     309  // Kennen we de post niet, dan is er niets te canoniseren en blijft de invoer
     310  // de sleutel. Een like op een vreemde post mag daar niet op stuklopen.
     311  const onbekend = 'https://elders.test/notes/xyz';
     312  AP.setReaction('me', onbekend, 'like', true);
     313  assert.equal(AP.getReaction('me', onbekend).liked, true);
     314});
Note: See TracChangeset for help on using the changeset viewer.