@rmdes/indiekit-endpoint-activitypub 3.8.1 → 3.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -238,6 +238,21 @@ export default class ActivityPubEndpoint {
238
238
  console.info(`[federation-diag] POST ${req.path} from=${ua.slice(0, 60)} bodyParsed=${bodyParsed} readable=${req.readable}`);
239
239
  }
240
240
 
241
+ // Fedify's acceptsJsonLd() treats Accept: */* as NOT accepting JSON-LD
242
+ // (it only returns true for explicit application/activity+json etc.).
243
+ // Remote servers fetching actor URLs for HTTP Signature verification
244
+ // (e.g. tags.pub) often omit Accept or use */* — they get HTML back
245
+ // instead of the actor JSON, causing "public key not found" errors.
246
+ // Fix: for GET requests to actor paths, upgrade ambiguous Accept headers
247
+ // to application/activity+json so Fedify serves JSON-LD. Explicit
248
+ // text/html requests (browsers) are unaffected.
249
+ if (req.method === "GET" && /^\/users\/[^/]+\/?$/.test(req.path)) {
250
+ const accept = req.get("accept") || "";
251
+ if (!accept.includes("text/html") && !accept.includes("application/xhtml+xml")) {
252
+ req.headers["accept"] = "application/activity+json";
253
+ }
254
+ }
255
+
241
256
  return self._fedifyMiddleware(req, res, next);
242
257
  });
243
258
 
@@ -764,7 +779,7 @@ export default class ActivityPubEndpoint {
764
779
  (remoteActor.icon
765
780
  ? (await remoteActor.icon)?.url?.href || ""
766
781
  : "");
767
- const inbox = remoteActor.inbox?.id?.href || "";
782
+ const inbox = remoteActor.inboxId?.href || "";
768
783
  const sharedInbox = remoteActor.endpoints?.sharedInbox?.href || "";
769
784
 
770
785
  await this._collections.ap_following.updateOne(
@@ -154,7 +154,16 @@ export function setupFederation(options) {
154
154
  };
155
155
  if (keyPairs.length > 0) {
156
156
  appOptions.publicKey = keyPairs[0].cryptographicKey;
157
- appOptions.assertionMethods = keyPairs.map((k) => k.multikey);
157
+ // Only include Ed25519 keys in assertionMethod (Object Integrity Proofs).
158
+ // RSA keys belong only in publicKey (HTTP Signatures). Putting the RSA
159
+ // Multikey in assertionMethod with the same #main-key id as the
160
+ // CryptographicKey in publicKey causes id collisions — servers that
161
+ // traverse JSON-LD properties alphabetically (assertionMethod before
162
+ // publicKey) find the Multikey first, which has no publicKeyPem,
163
+ // and fail signature verification.
164
+ appOptions.assertionMethods = keyPairs
165
+ .filter((k) => k.privateKey.algorithm.name !== "RSASSA-PKCS1-v1_5")
166
+ .map((k) => k.multikey);
158
167
  }
159
168
  return new Application(appOptions);
160
169
  }
@@ -753,7 +762,12 @@ export async function buildPersonActor(
753
762
 
754
763
  if (keyPairs.length > 0) {
755
764
  personOptions.publicKey = keyPairs[0].cryptographicKey;
756
- personOptions.assertionMethods = keyPairs.map((k) => k.multikey);
765
+ // Only include Ed25519 keys in assertionMethod (Object Integrity Proofs).
766
+ // RSA keys belong only in publicKey (HTTP Signatures). See instance actor
767
+ // above for the full explanation of why this filter is necessary.
768
+ personOptions.assertionMethods = keyPairs
769
+ .filter((k) => k.privateKey.algorithm.name !== "RSASSA-PKCS1-v1_5")
770
+ .map((k) => k.multikey);
757
771
  }
758
772
 
759
773
  // Build profile field attachments (PropertyValue).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-activitypub",
3
- "version": "3.8.1",
3
+ "version": "3.8.3",
4
4
  "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
5
5
  "keywords": [
6
6
  "indiekit",