Unverified Commit 978d1368 authored by Hong Minhee's avatar Hong Minhee
Browse files

Merge pull request #252 from TryGhost/configure-default-signature-spec

parents cb93369f ca59c0df
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -19,8 +19,17 @@ To be released.
     -  `InProcessMessageQueue.nativeRetrial` is `false`.
     -  `ParallelMessageQueue.nativeRetrial` inherits from the wrapped queue.

 -  Added `FederationOptions.firstKnock` option to configure the HTTP
    Signatures specification used for the first signature attempt when
    communicating with unknown servers.  This implements the [double-knocking]
    mechanism for better compatibility across different ActivityPub servers.
    Defaults to `"rfc9421"` (RFC 9421: HTTP Message Signatures), with fallback
    to `"draft-cavage-http-signatures-12"` if the first attempt fails.
    [[#252] by Fabien O'Carroll]

[#250]: https://github.com/fedify-dev/fedify/issues/250
[#251]: https://github.com/fedify-dev/fedify/pull/251
[#252]: https://github.com/fedify-dev/fedify/pull/252


Version 1.6.2
+1 −1
Original line number Diff line number Diff line
@@ -746,7 +746,7 @@ Available options are:
`rfc9421` (default)
:   [RFC 9421]: HTTP Message Signatures, which is the final revision of
    the specification and is recommended, but not yet widely adopted
    in the fediverse as of May 2025.
    in the fediverse as of June 2025.

If the first signature attempt fails, Fedify will automatically try the other
specification format, implementing the [double-knocking] technique described in
+30 −0
Original line number Diff line number Diff line
@@ -310,6 +310,36 @@ an object for options.
>
> However, `Context.lookupObject()` method is affected by this settings.

### `firstKnock`

*This API is available since Fedify 1.7.0.*

The HTTP Signatures specification to use for the first signature attempt
when communicating with unknown servers. This option affects the
[double-knocking] mechanism.

When making HTTP requests to servers that haven't been encountered before,
Fedify will first attempt to sign the request using the specified
signature specification. If the request fails, it will retry with the
alternative specification.

Available options are:

`"draft-cavage-http-signatures-12"`
:   [HTTP Signatures], which is obsolete but still widely adopted in
    the fediverse as of May 2025.

`"rfc9421"` (default)
:   [RFC 9421]: HTTP Message Signatures, which is the final revision of
    the specification and is recommended, but not yet widely adopted
    in the fediverse as of May 2025.

Defaults to `"rfc9421"`.

[double-knocking]: https://swicg.github.io/activitypub-http-signature/#how-to-upgrade-supported-versions
[HTTP Signatures]: https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12
[RFC 9421]: https://www.rfc-editor.org/rfc/rfc9421

### `outboxRetryPolicy`

*This API is available since Fedify 0.12.0.*
+29 −0
Original line number Diff line number Diff line
@@ -138,6 +138,35 @@ test("FederationBuilder", async (t) => {
    assertEquals(impl.origin?.webOrigin, "https://example.com");
  });

  await t.step("should handle firstKnock option", async () => {
    const builder = createFederationBuilder<void>();
    const kv = new MemoryKvStore();

    // Test with default firstKnock (should be "rfc9421")
    const federationDefault = await builder.build({ kv });
    assertExists(federationDefault);
    const implDefault = federationDefault as FederationImpl<void>;
    assertEquals(implDefault.firstKnock, undefined); // Uses default when not specified

    // Test with custom firstKnock value
    const federationCustom = await builder.build({
      kv,
      firstKnock: "draft-cavage-http-signatures-12",
    });
    assertExists(federationCustom);
    const implCustom = federationCustom as FederationImpl<void>;
    assertEquals(implCustom.firstKnock, "draft-cavage-http-signatures-12");

    // Test with rfc9421 explicitly set
    const federationRfc = await builder.build({
      kv,
      firstKnock: "rfc9421",
    });
    assertExists(federationRfc);
    const implRfc = federationRfc as FederationImpl<void>;
    assertEquals(implRfc.firstKnock, "rfc9421");
  });

  await t.step(
    "should register multiple object dispatchers and verify them",
    async () => {
+20 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import type {
  DocumentLoaderFactory,
  GetUserAgentOptions,
} from "../runtime/docloader.ts";
import type { HttpMessageSignaturesSpec } from "../sig/http.ts";
import type { Actor, Recipient } from "../vocab/actor.ts";
import type { Activity, Hashtag, Object } from "../vocab/vocab.ts";
import type {
@@ -678,6 +679,25 @@ export interface FederationOptions<TContextData> {
   */
  skipSignatureVerification?: boolean;

  /**
   * The HTTP Signatures specification to use for the first signature
   * attempt when communicating with unknown servers. This option affects
   * the "double-knocking" mechanism as described in the ActivityPub HTTP
   * Signature documentation.
   *
   * When making HTTP requests to servers that haven't been encountered before,
   * Fedify will first attempt to sign the request using the specified
   * signature specification. If the request fails, it will retry with the
   * alternative specification.
   *
   * Defaults to `"rfc9421"` (HTTP Message Signatures).
   *
   * @see {@link https://swicg.github.io/activitypub-http-signature/#how-to-upgrade-supported-versions}
   * @default `"rfc9421"`
   * @since 1.7.0
   */
  firstKnock?: HttpMessageSignaturesSpec;

  /**
   * The retry policy for sending activities to recipients' inboxes.
   * By default, this uses an exponential backoff strategy with a maximum of
Loading