From 296745fcf87dc8a0fcd8942aef0f8326c25c8b05 Mon Sep 17 00:00:00 2001 From: Sven Date: Sat, 14 Mar 2026 22:21:25 +0100 Subject: [PATCH] fix: skip PeerTube View activities before Fedify JSON-LD parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .on(View) inbox handler from the previous commit is never reached because Fedify crashes parsing PeerTube's View activity before dispatch — its JSON-LD deserialiser doesn't recognise Schema.org InteractionCounter, throwing "Failed to parse activity: TypeError: Invalid type". Add a guard at the top of createFedifyMiddleware that short-circuits any POST with body.type === "View" and returns 200 immediately, bypassing federation.fetch() entirely. Co-Authored-By: Claude Sonnet 4.6 --- package.json | 2 +- .../patch-inbox-skip-view-activity-parse.mjs | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 scripts/patch-inbox-skip-view-activity-parse.mjs diff --git a/package.json b/package.json index e2a031f2..0fd13bd8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "postinstall": "xattr -w com.apple.fileprovider.ignore#P 1 node_modules 2>/dev/null || true && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-conversations-mastodon-disconnect.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node scripts/patch-inbox-ignore-view-activity.mjs", + "postinstall": "xattr -w com.apple.fileprovider.ignore#P 1 node_modules 2>/dev/null || true && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-conversations-mastodon-disconnect.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node scripts/patch-inbox-ignore-view-activity.mjs && node scripts/patch-inbox-skip-view-activity-parse.mjs", "serve":"export NODE_ENV=${NODE_ENV:-production} INDIEKIT_DEBUG=${INDIEKIT_DEBUG:-0} && node scripts/preflight-production-security.mjs && node scripts/preflight-mongo-connection.mjs && node scripts/preflight-activitypub-rsa-key.mjs && node scripts/preflight-activitypub-profile-urls.mjs && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-endpoint-activitypub-locales.mjs && node scripts/patch-endpoint-homepage-locales.mjs && node scripts/patch-endpoint-homepage-identity-defaults.mjs && node scripts/patch-federation-unlisted-guards.mjs && node scripts/patch-endpoint-micropub-where-note-visibility.mjs && node scripts/patch-endpoint-posts-ai-fields.mjs && node scripts/patch-endpoint-posts-ai-cleanup.mjs && node scripts/patch-endpoint-podroll-opml-upload.mjs && node scripts/patch-preset-eleventy-ai-frontmatter.mjs && node scripts/patch-micropub-ai-block-resync.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-endpoint-comments-locales.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-conversations-mastodon-disconnect.mjs && node scripts/patch-indiekit-routes-rate-limits.mjs && node scripts/patch-indiekit-error-production-stack.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-listening-endpoint-runtime-guards.mjs && node scripts/patch-endpoint-github-changelog-categories.mjs && node scripts/patch-microsub-reader-ap-dispatch.mjs && node scripts/patch-endpoint-blogroll-feeds-alias.mjs && node scripts/patch-endpoint-posts-uid-lookup.mjs && node scripts/patch-endpoint-posts-prefill-url.mjs && node scripts/patch-microsub-feed-discovery.mjs && node scripts/patch-conversations-bluesky-self-filter.mjs && node scripts/patch-conversations-bluesky-cursor-fix.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs", "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/scripts/patch-inbox-skip-view-activity-parse.mjs b/scripts/patch-inbox-skip-view-activity-parse.mjs new file mode 100644 index 00000000..2fd218f6 --- /dev/null +++ b/scripts/patch-inbox-skip-view-activity-parse.mjs @@ -0,0 +1,100 @@ +/** + * Patch: skip PeerTube View (WatchAction) activities before Fedify parses them. + * + * PeerTube's View activities embed Schema.org extensions such as + * `InteractionCounter` that Fedify's JSON-LD deserializer doesn't recognise. + * This causes a hard "Failed to parse activity" error *before* any inbox + * listener is reached, so the .on(View, ...) no-op handler added earlier + * never fires. + * + * Fix: in createFedifyMiddleware (federation-bridge.js), add an early-return + * guard that checks req.body.type === "View" and responds 200 immediately, + * so Fedify never attempts to parse the activity. Returning 200 (rather than + * 4xx) prevents the sending server from retrying. + */ + +import { access, readFile, writeFile } from "node:fs/promises"; + +const candidates = [ + "node_modules/@rmdes/indiekit-endpoint-activitypub/lib/federation-bridge.js", + "node_modules/@indiekit/indiekit/node_modules/@rmdes/indiekit-endpoint-activitypub/lib/federation-bridge.js", +]; + +const patchSpecs = [ + { + name: "inbox-skip-view-activity-parse", + marker: "// PeerTube View parse skip", + oldSnippet: ` return async (req, res, next) => { + try { + const request = fromExpressRequest(req);`, + newSnippet: ` return async (req, res, next) => { + try { + // Short-circuit PeerTube View (WatchAction) activities before Fedify + // attempts JSON-LD parsing. Fedify's vocab parser throws on PeerTube's + // Schema.org extensions (e.g. InteractionCounter), causing a + // "Failed to parse activity" error. Return 200 to prevent retries. + // PeerTube View parse skip + if (req.method === "POST" && req.body?.type === "View") { + return res.status(200).end(); + } + const request = fromExpressRequest(req);`, + }, +]; + +async function exists(filePath) { + try { + await access(filePath); + return true; + } catch { + return false; + } +} + +const checkedFiles = new Set(); +const patchedFiles = new Set(); + +for (const spec of patchSpecs) { + let foundAnyTarget = false; + + for (const filePath of candidates) { + if (!(await exists(filePath))) { + continue; + } + + foundAnyTarget = true; + checkedFiles.add(filePath); + + const source = await readFile(filePath, "utf8"); + + if (spec.marker && source.includes(spec.marker)) { + continue; + } + + if (!source.includes(spec.oldSnippet)) { + continue; + } + + const updated = source.replace(spec.oldSnippet, spec.newSnippet); + + if (updated === source) { + continue; + } + + await writeFile(filePath, updated, "utf8"); + patchedFiles.add(filePath); + } + + if (!foundAnyTarget) { + console.log(`[postinstall] ${spec.name}: no target files found`); + } +} + +if (checkedFiles.size === 0) { + console.log("[postinstall] No federation-bridge files found for View activity parse-skip patch"); +} else if (patchedFiles.size === 0) { + console.log("[postinstall] inbox-skip-view-activity-parse patch already applied"); +} else { + console.log( + `[postinstall] Patched inbox-skip-view-activity-parse in ${patchedFiles.size}/${checkedFiles.size} file(s)`, + ); +}