Changeset 2708282 in Klonkt


Ignore:
Timestamp:
07/28/2026 10:45:26 AM (6 weeks ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
d9ad6c5
Parents:
65abc85
Message:

De knop deed niets: AP.deliverTo bestond niet

Op Propose link previews drukken gaf geen zichtbaar resultaat. Oorzaak: de route
riep AP.deliverTo aan, maar die naam bestond alleen als sleutel in het
deps-object dat we aan de guardianship-module doorgeven, niet als export. Dus een
TypeError, een 500 uit Express, en de knop die zichzelf netjes weer inschakelde.
Van buiten af: er gebeurt niks.

Mijn fout zat in de aanname: ik zag deliverTo in een grep-treffer staan en nam
aan dat het een export was. Een grep-treffer is geen export. Er staat nu een test
die alle AP-helpers controleert die de guardian-route aanroept, zodat deze klasse
fout niet nog eens stil kan blijven.

Changed files:
src/services/ActivityPubService.js

  • deliverToActor geexporteerd (stond alleen in de deps)

src/routes/guardian.js

  • gebruikt AP.deliverToActor

test/gated-settings.test.js

  • test dat elke AP-helper die de route aanroept ook echt bestaat
  • test op de Offer-vorm (ward, feature, value, geadresseerd aan de ward)

remarks: 230 tests groen.

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

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/routes/guardian.js

    r65abc85 r2708282  
    317317    return res.json({ ok: true, allow, state: r.state, need: r.need, of: r.of });
    318318  }
    319   AP.deliverTo(site, uri, offer).catch(() => { /* queued, best-effort */ });
     319  AP.deliverToActor(site, uri, offer).catch(() => { /* queued, best-effort */ });
    320320  res.json({ ok: true, allow, state: 'open', federated: true });
    321321});
  • src/services/ActivityPubService.js

    r65abc85 r2708282  
    36473647// { delivered, inbox }: delivered=false means the account could not be
    36483648// resolved at all (a bad handle) — the offer stays recorded regardless.
    3649 async function deliverToActor(site, actorUri, activity) {
     3649export async function deliverToActor(site, actorUri, activity) {
    36503650  const me = selfActorId(site.slug);
    36513651  const keys = getOrCreateKeys(site.slug);
     
    37083708  getInteractions, getInteractionById, setInteractionBoosted, setInteractionLiked, setMyReaction, getMyReactions, buildReplyNote, getOutboxNote, deliverReply, resolveRemoteNote,
    37093709  listOutbox, deliverOutboxDelete, deliverOutboxUpdate, deliverDirectNote,
    3710   webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, backfillFromOutbox, getTimeline, timelineAttachments, timelineEmojis, timelineObjectLinks, timelineQuote, timelineEmbed, applyQuoteProps, sendInteraction, voteOnPoll, voteOnRemotePoll,
     3710  webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, backfillFromOutbox, getTimeline, timelineAttachments, timelineEmojis, timelineObjectLinks, timelineQuote, timelineEmbed, applyQuoteProps, deliverToActor, sendInteraction, voteOnPoll, voteOnRemotePoll,
    37113711  acceptGatedFollow, rejectGatedFollow, isWardGuardian, sendFollowDecision,
    37123712  parseOwnPoll, pollTally, ownPollView, deliverPollUpdate, maybeCrawlThread, sendReport, localMentionSlugs,
  • test/gated-settings.test.js

    r65abc85 r2708282  
    6161  assert.equal(featureColumn('external_embeds = 1; DROP TABLE sites'), null);
    6262});
     63
     64// Guard against the mistake that made the button do nothing: the route called
     65// AP.deliverTo, which existed only as a key in the guardianship deps object and
     66// not as an export. It threw a TypeError, Express answered 500, and the button
     67// silently reset. A grep hit is not an export.
     68test('the guardian route can reach every ActivityPub helper it calls', async () => {
     69  const AP = (await import('../src/services/ActivityPubService.js')).default;
     70  for (const fn of ['actorId', 'deliverToActor', 'followActor', 'backfillFromOutbox', 'getTimeline']) {
     71    assert.equal(typeof AP[fn], 'function', `AP.${fn} must be exported, the guardian route calls it`);
     72  }
     73});
     74
     75test('a gated-setting Offer carries ward, feature and value', async () => {
     76  const { buildGatedOffer, parseGatedSetting } = await import('../src/services/guardianship/gated.js');
     77  const o = buildGatedOffer('https://a/gated/1', 'https://a/g1', 'https://b/ward', 'shaer:externalEmbeds', true);
     78  assert.equal(o.type, 'Offer');
     79  assert.deepEqual(o.to, ['https://b/ward'], 'addressed to the ward server, which tallies');
     80  const parsed = parseGatedSetting(o.object);
     81  assert.deepEqual(parsed, { ward: 'https://b/ward', feature: 'shaer:externalEmbeds', value: true });
     82  assert.equal(parseGatedSetting({ type: 'Relationship' }), null, 'a different Offer is not ours');
     83});
Note: See TracChangeset for help on using the changeset viewer.