Skip to content

Conversation

@tibisabau
Copy link

Summary

Added Context.getActorKeysByUsage() and Context.getActorFirstKeyByUsage()
methods to simplify retrieval of actor keys grouped by usage type for
ActivityPub actor dispatchers.

Related issue

Changes

  • Added getActorKeysByUsage() method signature to Context interface in
    packages/fedify/src/federation/context.ts
  • Added getActorFirstKeyByUsage() method signature to Context interface
    in packages/fedify/src/federation/context.ts
  • Implemented getActorKeysByUsage() method in ContextImpl class in
    packages/fedify/src/federation/middleware.ts
  • Implemented getActorFirstKeyByUsage() method in ContextImpl class in
    packages/fedify/src/federation/middleware.ts
  • Added default implementations for both methods in testing context helper
    in packages/fedify/src/testing/context.ts
  • Updated CHANGES.md with changelog entry for Version 2.0.0

Benefits

  • Eliminates confusing manual mapping of key pairs when setting up actor
    dispatchers
  • Provides a cleaner, more intuitive API for common key usage patterns
  • Reduces boilerplate code by 2-3 lines per actor dispatcher implementation
  • Makes the distinction between publicKey (CryptographicKey) and
    assertionMethod (Multikey) usage explicit and clear
  • Improves developer experience by providing convenience methods for the
    most common use cases

Checklist

  • Did you add a changelog entry to the CHANGES.md?
  • Did you write some relevant docs about this change (if it's a new feature)?
  • Did you write a regression test to reproduce the bug (if it's a bug fix)?
  • Did you write some tests for this change (if it's a new feature)?
  • Did you run mise test on your machine?

Additional notes

The code in this pull request was generated by GitHub Copilot with the Claude Sonnet 4.5 model.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @tibisabau, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the Context interface by introducing two new utility methods, getActorKeysByUsage and getActorFirstKeyByUsage. These additions streamline the process of accessing actor keys, specifically for ActivityPub dispatchers, by providing a structured way to retrieve keys based on their intended usage. The change aims to simplify key management, reduce repetitive code, and offer a more explicit API for handling different types of cryptographic keys within the application.

Highlights

  • New Context Methods for Actor Keys: Introduced Context.getActorKeysByUsage() and Context.getActorFirstKeyByUsage() to simplify the retrieval of actor keys, grouped by usage type (e.g., publicKey, assertionMethod), for ActivityPub actor dispatchers.
  • Improved Developer Experience: These methods provide a cleaner, more intuitive API, reducing boilerplate code and eliminating the need for manual mapping of key pairs, thereby improving the developer experience when setting up actor dispatchers.
  • Explicit Key Usage Distinction: The new methods make the distinction between publicKey (CryptographicKey) and assertionMethod (Multikey) usage explicit and clear, enhancing code readability and maintainability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces two convenient helper methods, getActorKeysByUsage() and getActorFirstKeyByUsage(), to simplify retrieving actor keys from the context. The changes are well-structured across the interface, implementation, and testing files.

My review focuses on improving the robustness and readability of the new implementations. I've identified a critical issue in getActorFirstKeyByUsage where it doesn't handle cases where no keys are available, which could lead to runtime errors. I've provided a suggestion to fix this and also to refactor both new methods to use async/await for better consistency with the existing codebase. Additionally, I've suggested a minor naming improvement in the test mocks for better clarity.

Once these points are addressed, this will be a solid enhancement to the library's developer experience.

Comment on lines 1949 to 1969
getActorKeysByUsage(identifier: string): Promise<{
publicKeys: CryptographicKey[];
assertionMethods: Multikey[];
}> {
return this.getActorKeyPairs(identifier)
.then((keys) => ({
publicKeys: keys.map((k) => k.cryptographicKey),
assertionMethods: keys.map((k) => k.multikey),
}));
}

getActorFirstKeyByUsage(identifier: string): Promise<{
publicKey: CryptographicKey;
assertionMethod: Multikey;
}> {
return this.getActorKeysByUsage(identifier)
.then(({ publicKeys, assertionMethods }) => ({
publicKey: publicKeys[0],
assertionMethod: assertionMethods[0],
}));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

These new methods can be improved for readability and robustness.

  1. Both methods can be simplified by using async/await instead of .then(), which is more consistent with the surrounding code style.
  2. getActorFirstKeyByUsage has a potential runtime error. If getActorKeysByUsage returns empty arrays, accessing publicKeys[0] and assertionMethods[0] will result in undefined, which violates the return type contract. You should add a check for empty arrays and throw an error if no keys are found, similar to the behavior in the testing context.
  async getActorKeysByUsage(identifier: string): Promise<{
    publicKeys: CryptographicKey[];
    assertionMethods: Multikey[];
  }> {
    const keys = await this.getActorKeyPairs(identifier);
    return {
      publicKeys: keys.map((k) => k.cryptographicKey),
      assertionMethods: keys.map((k) => k.multikey),
    };
  }

  async getActorFirstKeyByUsage(identifier: string): Promise<{
    publicKey: CryptographicKey;
    assertionMethod: Multikey;
  }> {
    const { publicKeys, assertionMethods } = await this.getActorKeysByUsage(
      identifier,
    );
    if (publicKeys.length < 1 || assertionMethods.length < 1) {
      throw new Error(`No actor keys available for identifier: ${identifier}`);
    }
    return {
      publicKey: publicKeys[0],
      assertionMethod: assertionMethods[0],
    };
  }

Comment on lines 87 to 96
getActorKeysByUsage: getActorKeysByUsage ??
((_handle) =>
Promise.resolve({
publicKeys: [],
assertionMethods: [],
})),
getActorFirstKeyByUsage: getActorFirstKeyByUsage ??
((_handle) => {
throw new Error("No actor keys available");
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with the method signatures in the Context interface, which use identifier as the parameter name, it would be clearer to name the parameter _identifier instead of _handle in these mock implementations.

Suggested change
getActorKeysByUsage: getActorKeysByUsage ??
((_handle) =>
Promise.resolve({
publicKeys: [],
assertionMethods: [],
})),
getActorFirstKeyByUsage: getActorFirstKeyByUsage ??
((_handle) => {
throw new Error("No actor keys available");
}),
getActorKeysByUsage: getActorKeysByUsage ??
((_identifier) =>
Promise.resolve({
publicKeys: [],
assertionMethods: [],
})),
getActorFirstKeyByUsage: getActorFirstKeyByUsage ??
((_identifier) => {
throw new Error("No actor keys available");
}),

@dahlia
Copy link
Member

dahlia commented Feb 2, 2026

Did you vibe-code it? Please read our AI usage policy first. Thanks.

@dahlia dahlia closed this Feb 2, 2026
@tibisabau
Copy link
Author

Did you vibe-code it? Please read our AI usage policy first. Thanks.

AI Assistance is disclosed at the bottom of the PR description. Is there something else I missed?

@dahlia
Copy link
Member

dahlia commented Feb 2, 2026

No unit tests and wrong documentation (@since 1.6.0) made me consider it blindly vibe-coded without any human reviews…

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.

Add Context.getActorFirstKeyByUsage(id) and Context.getActorKeysByUsage(id).

2 participants