Skip to content

Serve a stored post's attachments as Documents, with their mime - #2172

Merged
karlitschek merged 2 commits into
masterfrom
fix/attachment-media-type
Sep 14, 2026
Merged

Serve a stored post's attachments as Documents, with their mime#2172
karlitschek merged 2 commits into
masterfrom
fix/attachment-media-type

Conversation

@karlitschek

Copy link
Copy Markdown
Member

Item 6 of the fresh look: every Social photo arrived on Pixelfed with no photo. Pixelfed validates an attachment with in_array($media['mediaType'], $allowed); Mastodon sniffs the URL and hid the bug for weeks.

Two halves, both in the re-read path (the original Create was already right — roadmap #39 said so):

  1. The stored row had no mime. StreamRequest::save() writes MediaAttachment::asLocal(), Mastodon's client entity, which has no mime; import() hydrated it back with mediaType = ''. The row now carries media_type (this app's own key — a Mastodon client ignores it), import() reads it back, and a row from before the key existed gets a guess from the file extension, or the commonest type of its kind (image/jpeg, video/mp4, audio/mpeg), rather than an empty string Pixelfed refuses.
  2. A re-served post carried the client shape under the ActivityPub key. Stream::jsonSerialize() handed the hydrated MediaAttachment objects straight through as attachment, in whatever export format they were in — the local one, after hydration. It now maps every attachment through asDocument(), so a post fetched by a peer (single status, outbox, featured, replies) goes out as {"type": "Document", "mediaType": "image/png", "name": …} exactly like the original Create.

Roadmap items 13 and 39 in docs/Mastodon-Compatibility.md are marked done; docs/API.md documents the extra media_type key.

Verification

  • Full PHP suite green (4611 tests, run on the Mac); psalm no errors; php-cs-fixer clean.
  • New tests: the mime survives the stored row and comes back on the Document; the guess for old rows; StreamTest::testAHydratedPostServesItsAttachmentsAsDocuments (local-format attachments → Document with mediaType when the post is exported as ActivityPub, and no attachment key in the client format).
  • Not yet verified against a live Pixelfed — that needs a peer; the fixture-based WireCompatibilityTest covers the inbound side only.

Version 0.19.36.

🤖 Generated with Claude Code

@karlitschek
karlitschek force-pushed the fix/attachment-media-type branch 2 times, most recently from 5aaefa2 to 95dcdf8 Compare September 13, 2026 23:38
Frank Karlitschek and others added 2 commits September 14, 2026 01:38
Every Social photo arrived on Pixelfed with no photo. Two halves to it:

The stored row (`MediaAttachment::asLocal()`, what `StreamRequest::save()`
writes) carried Mastodon's client entity, which has no mime, so a post
read back from the database had `mediaType` '' on every attachment — and
Pixelfed validates an attachment with `in_array($media['mediaType'],
$allowed)`. Mastodon sniffs the URL and hid it. The row now carries
`media_type`, `import()` reads it back, and a row from before it existed
gets a guess from the extension (or the commonest type of its kind) rather
than nothing.

And `Stream::jsonSerialize()` handed the hydrated attachment objects
straight through under `attachment`, in whatever export format they were
in — the local one, after hydration — so a re-served post carried Mastodon's
client shape under an ActivityPub key. It maps every attachment through
`asDocument()` now, so a post fetched by a peer goes out the same as the
original `Create` did.

Closes roadmap items 13 and 39 in docs/Mastodon-Compatibility.md.

Signed-off-by: Frank Karlitschek <frank@nextcloud.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Frank Karlitschek <frank@nextcloud.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@karlitschek
karlitschek force-pushed the fix/attachment-media-type branch from 95dcdf8 to ca94876 Compare September 13, 2026 23:38
@karlitschek
karlitschek merged commit 7e5d4bb into master Sep 14, 2026
43 checks passed
@karlitschek
karlitschek deleted the fix/attachment-media-type branch September 14, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant