fix: add cache fallback for /accounts/:id to resolve lookup-cached actors
Deploy Indiekit Server / deploy (push) Successful in 1m25s

Profiles resolved via /api/v1/accounts/lookup were cached in ap_actor_cache
but /api/v1/accounts/:id only checked followers/following/timeline via
resolveActorData(), missing the cache entirely and returning 404 for new
or unknown actors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sven
2026-04-25 16:29:48 +02:00
parent 61a03a164b
commit 07b7d8902c
@@ -0,0 +1,62 @@
/**
* patch-ap-accounts-id-cache-fallback.mjs
*
* Fixes 404 on /api/v1/accounts/:id for actors resolved via /lookup but not
* in followers/following/timeline. After resolveActorData() returns null,
* checks in-memory idToUrl cache and ap_actor_cache MongoDB collection for
* the actor URL, then calls resolveRemoteAccount() if found.
*/
import { readFileSync, writeFileSync } from "node:fs";
const MARKER = "// [patch] ap-accounts-id-cache-fallback";
const TARGET = "/usr/local/indiekit/node_modules/@rmdes/indiekit-endpoint-activitypub/lib/mastodon/routes/accounts.js";
const src = readFileSync(TARGET, "utf8");
if (src.includes(MARKER)) {
console.log("[postinstall] ap-accounts-id-cache-fallback: already applied");
process.exit(0);
}
// Find the 404 return in the GET /accounts/:id handler.
// We need to insert a cache-fallback block BEFORE the 404 return.
// The pattern: after the resolveActorData block, before `return res.status(404)`
// in the :id handler.
const needle = ` return res.status(404).json({ error: "Record not found" });
} catch (error) {
next(error);
}
});
// ─── GET /api/v1/accounts/:id/statuses`;
if (!src.includes(needle)) {
console.error("[postinstall] ap-accounts-id-cache-fallback: cannot find insertion point");
process.exit(1);
}
const replacement = ` // Cache fallback: actor not in followers/following/timeline, ${MARKER}
// but may have been resolved via /lookup and cached in ap_actor_cache
let cachedActorUrl = getActorUrlFromId(id); ${MARKER}
if (!cachedActorUrl && collections.ap_actor_cache) { ${MARKER}
const cached = await collections.ap_actor_cache.findOne({ _id: id }); ${MARKER}
if (cached?.actorUrl) cachedActorUrl = cached.actorUrl; ${MARKER}
} ${MARKER}
if (cachedActorUrl) { ${MARKER}
const cachedAccount = await resolveRemoteAccount( ${MARKER}
cachedActorUrl, pluginOptions, baseUrl, collections, ${MARKER}
); ${MARKER}
if (cachedAccount) return res.json(cachedAccount); ${MARKER}
} ${MARKER}
return res.status(404).json({ error: "Record not found" });
} catch (error) {
next(error);
}
});
// ─── GET /api/v1/accounts/:id/statuses`;
writeFileSync(TARGET, src.replace(needle, replacement));
console.log("[postinstall] ap-accounts-id-cache-fallback: applied successfully");