Changeset a9da2c0 in Klonkt


Ignore:
Timestamp:
07/30/2026 09:32:40 AM (6 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
67f7150
Parents:
d3a1abd
Message:

De outbox vergat de attachments: waarom de Mac speelde en de iPhone niet

De doorbraak zat in koffieengaars eigen outbox: atts: 0, terwijl de content
wel de video-tag droeg. De outbox-SELECT (en die van featured en de
nieuwe-volger-backfill) haalde c2s_attachments niet op, dus buildNote had
niets te federeren. Wie de post via DELIVERY kreeg had het attachment wel
(daarom werkte de Mac); wie hem via de outbox trok (backfill, boiert.eu)
kreeg alleen de content-tag met zijn relatieve, overal dode src: de kapotte
iPhone-speler.

De kolom zit nu in alle drie de smalle SELECTs; de losse-note-route deed al
SELECT * en was al goed.

Changed files:
src/routes/activitypub.js

  • outbox- en featured-SELECT dragen c2s_attachments

src/services/ActivityPubService.js

  • de nieuwe-volger-backfill-SELECT ook

test/c2s-compose.test.js

  • het outbox-contract vastgepind: dezelfde smalle SELECT levert via buildNote het Video-attachment, met schone content

remarks: 342 tests groen. koffieengaar.nl moet hierna bijgewerkt worden,
anders blijft zijn outbox kaal.

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

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/routes/activitypub.js

    rd3a1abd ra9da2c0  
    106106  const fanClause = audience === 'friend' ? '' : "AND (fan_only IS NULL OR fan_only = 0)";
    107107  const posts = db.prepare(
    108     `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, published_at, created_at
     108    `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, c2s_attachments, published_at, created_at
    109109     FROM posts WHERE site_id = ? AND status = 'published' ${fanClause}
    110110     ORDER BY COALESCE(published_at, created_at) DESC LIMIT 20`
     
    410410  // rank 1 last) → Mastodon flips it back to pin-rank ascending on the profile.
    411411  const posts = db.prepare(
    412     `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, published_at, created_at
     412    `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, c2s_attachments, published_at, created_at
    413413     FROM posts WHERE site_id = ? AND status = 'published' AND (fan_only IS NULL OR fan_only = 0)
    414414       AND pinned IS NOT NULL AND pinned > 0
  • src/services/ActivityPubService.js

    rd3a1abd ra9da2c0  
    19211921  if (!site) return;
    19221922  const recent = db.prepare(
    1923     `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, published_at, created_at
     1923    `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, c2s_attachments, published_at, created_at
    19241924     FROM posts WHERE site_id = ? AND status = 'published' AND (fan_only IS NULL OR fan_only = 0)
    19251925     ORDER BY COALESCE(published_at, created_at) DESC LIMIT 20`
  • test/c2s-compose.test.js

    rd3a1abd ra9da2c0  
    117117});
    118118
     119test('the OUTBOX serves the attachment too, not only the delivered Create', async () => {
     120  // Root of the broken iPhone player (Robins schermafdrukken, 30-7): the
     121  // outbox SELECT did not include c2s_attachments, so a note pulled via the
     122  // outbox (backfill, boiert.eu) had NO Video attachment and readers fell
     123  // back to the content tag with its relative, dead src. The delivered copy
     124  // was fine, which is why one device worked and the other did not. This
     125  // locks the outbox contract: the same narrow SELECT, through buildNote,
     126  // must carry the attachment.
     127  const r = await AP.ingestOutboxActivity(site, user, {
     128    type: 'Create',
     129    object: {
     130      type: 'Note', content: '<p>buiten</p>',
     131      to: ['https://test.example/ap/users/kid/followers'],
     132      cc: ['https://www.w3.org/ns/activitystreams#Public'],
     133      attachment: [{ type: 'Video', url: '/media/reply-media/buiten.mp4', mediaType: 'video/mp4' }],
     134    },
     135  });
     136  const row = db.prepare(
     137    `SELECT id, slug, title, content, cover_image_url, cover_video_url, nsfw, content_warning, c2s_attachments, published_at, created_at
     138     FROM posts WHERE id = ?`).get(r.id);
     139  const note = AP.buildNote('https://test.example', site, row);
     140  const vid = (note.attachment || []).find((a) => a.url.endsWith('buiten.mp4'));
     141  assert.ok(vid, 'the outbox-shaped row still yields the Video attachment');
     142  assert.equal(vid.type, 'Video');
     143  assert.ok(!/<video\b/i.test(note.content), 'and the content stays clean');
     144});
     145
    119146test('a media-only post is a post, not an empty-note error', async () => {
    120147  const r = await AP.ingestOutboxActivity(site, user, {
Note: See TracChangeset for help on using the changeset viewer.