Skip to content

chore: scaffold adapter B (PGP-native)#301

Merged
EffortlessSteven merged 3 commits into
mainfrom
feat/v0.5.0-adapter-b-pgp
Mar 25, 2026
Merged

chore: scaffold adapter B (PGP-native)#301
EffortlessSteven merged 3 commits into
mainfrom
feat/v0.5.0-adapter-b-pgp

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

No description provided.

@coderabbitai

coderabbitai Bot commented Mar 25, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@EffortlessSteven has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 65c78c99-2809-4acf-93c6-81d194820e91

📥 Commits

Reviewing files that changed from the base of the PR and between a6b63b0 and b2233fc.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • Cargo.toml
  • README.md
  • crates/uselesskey-pgp-native/Cargo.toml
  • crates/uselesskey-pgp-native/README.md
  • crates/uselesskey-pgp-native/examples/pgp_native.rs
  • crates/uselesskey-pgp-native/src/lib.rs
  • crates/uselesskey-pgp-native/tests/integration.rs
  • docs/metadata/workspace-docs.json
  • xtask/src/main.rs

Walkthrough

A new OpenPGP native adapter crate uselesskey-pgp-native is introduced to the workspace, providing trait-based conversions from uselesskey_pgp fixtures to native pgp crate types, along with manifest configuration, documentation, examples, and tests.

Changes

Cohort / File(s) Summary
Workspace Setup
Cargo.toml, README.md, xtask/src/main.rs
Added uselesskey-pgp-native to workspace members list, root README adapter documentation, and publish-order configuration.
Core Adapter Implementation
crates/uselesskey-pgp-native/src/lib.rs, crates/uselesskey-pgp-native/tests/integration.rs
Implemented PgpNativeExt trait with four conversion methods (secret_key, public_key, secret_key_armor, public_key_armor) for uselesskey_pgp::PgpKeyPair, parsing binary and armored key bytes into pgp crate types. Added integration test verifying fingerprint consistency across conversions.
Crate Configuration & Documentation
crates/uselesskey-pgp-native/Cargo.toml, crates/uselesskey-pgp-native/README.md, crates/uselesskey-pgp-native/examples/pgp_native.rs
Added crate manifest with pgp dependencies and optional feature gating, crate-level README with feature matrix and usage example, and a standalone example demonstrating RSA 3072 keypair generation and fingerprint validation.
Metadata & Build System
docs/metadata/workspace-docs.json
Extended workspace metadata with adapter crate entry, feature matrix row (all crypto features disabled), and dependency snippet documenting pgp feature usage.

Sequence Diagram

sequenceDiagram
    actor User
    participant FactoryExt
    participant PgpKeyPair
    participant PgpNativeExt
    participant pgp Crate

    User->>FactoryExt: fx.pgp(PgpSpec::rsa_3072())
    FactoryExt-->>PgpKeyPair: returns PgpKeyPair
    User->>PgpNativeExt: keypair.secret_key_armor()
    PgpNativeExt->>pgp Crate: parse_armor(secret_bytes)
    pgp Crate-->>PgpNativeExt: SignedSecretKey
    PgpNativeExt-->>User: SignedSecretKey
    User->>PgpNativeExt: keypair.public_key_armor()
    PgpNativeExt->>pgp Crate: parse_armor(public_bytes)
    pgp Crate-->>PgpNativeExt: SignedPublicKey
    PgpNativeExt-->>User: SignedPublicKey
    User->>User: verify fingerprints match
Loading

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A new adapter hops into place,
Converting PGP with native grace,
Keys unlock through traits so clean,
The finest OpenPGP bridge we've seen!
Tests and docs, all fit and sound—
Fresh crypto magic, safe and sound! ✨🔐

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No description was provided by the author, making it impossible to assess whether it relates to the changeset. Add a pull request description explaining the purpose and scope of the new PGP-native adapter, even if brief.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: scaffold adapter B (PGP-native)' accurately describes the main change: introducing a new PGP-native adapter crate with all supporting infrastructure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/v0.5.0-adapter-b-pgp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, 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 establishes a new uselesskey-pgp-native crate, which acts as a crucial bridge for converting OpenPGP key fixtures generated by uselesskey-pgp into the native types used by the pgp crate. This addition significantly enhances the interoperability of uselesskey with other PGP-native applications and libraries, streamlining development and testing workflows by providing direct access to native PGP key structures.

Highlights

  • New uselesskey-pgp-native Crate: A new crate, uselesskey-pgp-native, has been introduced to provide adapters for converting uselesskey OpenPGP fixtures into native pgp crate types.
  • Integration with Workspace: The new crate has been integrated into the project's workspace, with updates to Cargo.toml, Cargo.lock, and xtask configurations for publishing.
  • Documentation and Examples: Comprehensive documentation, including a README.md for the new crate, updated project README.md, and an example, has been added to guide usage and demonstrate functionality.
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.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/uselesskey-pgp-native/examples/pgp_native.rs`:
- Around line 1-15: CI failed rustfmt due to import ordering and println
formatting; reorder the use statements so external crates are sorted (e.g.,
bring use pgp::types::KeyDetails before the uselesskey_* imports or follow your
repo's import-group convention) and ensure a blank line between external and
local imports, run cargo fmt to apply exact formatting, and adjust the two
println! lines in main (keeping fingerprint() comparisons but matching rustfmt's
preferred spacing/line breaks) so the file is formatted cleanly and ends with a
newline.

In `@crates/uselesskey-pgp-native/src/lib.rs`:
- Around line 27-49: The current PgpNativeExt impl panics on parse failures via
expect(...) in secret_key, public_key, secret_key_armor, and public_key_armor;
change the trait signatures for those methods to return a fallible Result (e.g.,
Result<SignedSecretKey, YourError> / Result<SignedPublicKey, YourError>) and
update the uselesskey_pgp::PgpKeyPair implementation to propagate parsing errors
instead of calling expect — call SignedSecretKey::from_bytes(...)? /
SignedPublicKey::from_bytes(...)? and SignedSecretKey::from_armor_single(...)? /
SignedPublicKey::from_armor_single(...)? and map/convert the returned error into
the chosen error type; keep the existing panic-throwing helpers only as separate
opt-in methods if desired.
- Around line 59-67: Replace the ad-hoc randomized #[test]
parse_round_trip_binary_and_armor with a property-based proptest that generates
the Factory (replace Factory::random() with a proptest strategy for the Factory)
and use rstest to parameterize the four key variants; specifically, convert the
test function parse_round_trip_binary_and_armor to take a generated Factory and
a parameter enum/flag for which accessor to call (secret_key, secret_key_armor,
public_key, public_key_armor) and assert the invariant keypair.fingerprint() ==
<accessor>().fingerprint().to_string() for each case; keep references to the
existing symbols Factory, parse_round_trip_binary_and_armor, keypair,
fingerprint(), secret_key(), secret_key_armor(), public_key(), and
public_key_armor() so the new test uses proptest strategies for randomness and
rstest for the four parameterized variants.
- Around line 64-67: The four assert_eq! lines using keypair.fingerprint() vs
secret_key()/secret_key_armor()/public_key()/public_key_armor() are misformatted
and failing rustfmt; reformat them to match project rustfmt style (or simply run
`cargo fmt`) so each assertion conforms to the repository's formatting rules,
ensuring calls to keypair.fingerprint(),
keypair.secret_key().fingerprint().to_string(),
keypair.secret_key_armor().fingerprint().to_string(),
keypair.public_key().fingerprint().to_string(), and
keypair.public_key_armor().fingerprint().to_string() are written in the
canonical formatted style.

In `@crates/uselesskey-pgp-native/tests/integration.rs`:
- Around line 1-21: The test file integration_parses_armored_vs_binary has
formatting issues—reorder imports to satisfy rustfmt (group std/lib crates then
local crates: pgp::types::KeyDetails together with external crates, then
uselesskey_*), and run cargo fmt to fix trailing/line-length formatting; also
reflow the assert_eq! calls in function integration_parses_armored_vs_binary so
each assertion fits rustfmt line-length rules (e.g., keep left and right args on
the same line or break after comma consistently) and ensure import ordering
matches rustfmt's default rules so cargo fmt passes.

In `@README.md`:
- Around line 180-187: Add a blank line before the fenced code block that
follows the "**pgp-native adapter**" heading to satisfy Markdown linting: locate
the "**pgp-native adapter**" heading and the subsequent "```toml" fence and
insert a single empty line between them so the code block is separated from the
preceding paragraph/heading.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c7062e33-e614-423b-87ef-cebb774351e6

📥 Commits

Reviewing files that changed from the base of the PR and between f06a9ca and a6b63b0.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • Cargo.toml
  • README.md
  • crates/uselesskey-pgp-native/Cargo.toml
  • crates/uselesskey-pgp-native/README.md
  • crates/uselesskey-pgp-native/examples/pgp_native.rs
  • crates/uselesskey-pgp-native/src/lib.rs
  • crates/uselesskey-pgp-native/tests/integration.rs
  • docs/metadata/workspace-docs.json
  • xtask/src/main.rs

Comment thread crates/uselesskey-pgp-native/examples/pgp_native.rs
Comment on lines +27 to +49
impl PgpNativeExt for uselesskey_pgp::PgpKeyPair {
fn secret_key(&self) -> SignedSecretKey {
SignedSecretKey::from_bytes(Cursor::new(self.private_key_binary()))
.expect("failed to parse uselesskey PGP private key bytes")
}

fn public_key(&self) -> SignedPublicKey {
SignedPublicKey::from_bytes(Cursor::new(self.public_key_binary()))
.expect("failed to parse uselesskey PGP public key bytes")
}

fn secret_key_armor(&self) -> SignedSecretKey {
let (key, _) = SignedSecretKey::from_armor_single(Cursor::new(self.private_key_armored()))
.expect("failed to parse armored uselesskey PGP private key");
key
}

fn public_key_armor(&self) -> SignedPublicKey {
let (key, _) = SignedPublicKey::from_armor_single(Cursor::new(self.public_key_armored()))
.expect("failed to parse armored uselesskey PGP public key");
key
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid panics in the public conversion surface.

Lines 29-30, 34-35, 39-40, and 45-46 use expect(...), which can abort consumers on parse failure. Expose fallible methods (Result) for this API and keep panic wrappers only if explicitly opt-in.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/uselesskey-pgp-native/src/lib.rs` around lines 27 - 49, The current
PgpNativeExt impl panics on parse failures via expect(...) in secret_key,
public_key, secret_key_armor, and public_key_armor; change the trait signatures
for those methods to return a fallible Result (e.g., Result<SignedSecretKey,
YourError> / Result<SignedPublicKey, YourError>) and update the
uselesskey_pgp::PgpKeyPair implementation to propagate parsing errors instead of
calling expect — call SignedSecretKey::from_bytes(...)? /
SignedPublicKey::from_bytes(...)? and SignedSecretKey::from_armor_single(...)? /
SignedPublicKey::from_armor_single(...)? and map/convert the returned error into
the chosen error type; keep the existing panic-throwing helpers only as separate
opt-in methods if desired.

Comment thread crates/uselesskey-pgp-native/src/lib.rs Outdated
Comment on lines +59 to +67
#[test]
fn parse_round_trip_binary_and_armor() {
let fx = Factory::random();
let keypair = fx.pgp("fixture", PgpSpec::ed25519());

assert_eq!(keypair.fingerprint(), keypair.secret_key().fingerprint().to_string());
assert_eq!(keypair.fingerprint(), keypair.secret_key_armor().fingerprint().to_string());
assert_eq!(keypair.fingerprint(), keypair.public_key().fingerprint().to_string());
assert_eq!(keypair.fingerprint(), keypair.public_key_armor().fingerprint().to_string());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use proptest + rstest for this randomized, repeated test pattern.

Line 60 introduces random input, and Lines 64-67 duplicate the same invariant across variants. Please convert this to a property-based test (proptest) with parameterized cases (rstest) to match repository test policy.

As per coding guidelines, "Use proptest crate for property-based tests" and "Use rstest crate for parameterized tests".

🧰 Tools
🪛 GitHub Actions: CI

[error] 61-61: cargo fmt --all -- --check failed (code formatting differences detected). Diff shows assert_eq! statements reformatted across multiple lines.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/uselesskey-pgp-native/src/lib.rs` around lines 59 - 67, Replace the
ad-hoc randomized #[test] parse_round_trip_binary_and_armor with a
property-based proptest that generates the Factory (replace Factory::random()
with a proptest strategy for the Factory) and use rstest to parameterize the
four key variants; specifically, convert the test function
parse_round_trip_binary_and_armor to take a generated Factory and a parameter
enum/flag for which accessor to call (secret_key, secret_key_armor, public_key,
public_key_armor) and assert the invariant keypair.fingerprint() ==
<accessor>().fingerprint().to_string() for each case; keep references to the
existing symbols Factory, parse_round_trip_binary_and_armor, keypair,
fingerprint(), secret_key(), secret_key_armor(), public_key(), and
public_key_armor() so the new test uses proptest strategies for randomness and
rstest for the four parameterized variants.

Comment thread crates/uselesskey-pgp-native/src/lib.rs Outdated
Comment thread crates/uselesskey-pgp-native/tests/integration.rs
Comment thread README.md

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

Copy link
Copy Markdown

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 a new uselesskey-pgp-native crate to the workspace, providing adapters to convert uselesskey-pgp generated fixtures into native pgp crate types such as SignedSecretKey and SignedPublicKey. The new crate includes its own Cargo.toml, README.md, an example, core lib.rs with the PgpNativeExt trait, and integration tests, with all relevant workspace configuration files updated. Feedback from the review suggests replacing the use of .expect() with Result types in the PgpNativeExt implementation for more robust error handling, particularly for negative fixtures. Additionally, minor documentation improvements are recommended for the README.md files, and several unused imports (KeyDetails and Deserializable) should be removed across the new crate's source, example, and test files for better code hygiene.

Comment on lines +27 to +49
impl PgpNativeExt for uselesskey_pgp::PgpKeyPair {
fn secret_key(&self) -> SignedSecretKey {
SignedSecretKey::from_bytes(Cursor::new(self.private_key_binary()))
.expect("failed to parse uselesskey PGP private key bytes")
}

fn public_key(&self) -> SignedPublicKey {
SignedPublicKey::from_bytes(Cursor::new(self.public_key_binary()))
.expect("failed to parse uselesskey PGP public key bytes")
}

fn secret_key_armor(&self) -> SignedSecretKey {
let (key, _) = SignedSecretKey::from_armor_single(Cursor::new(self.private_key_armored()))
.expect("failed to parse armored uselesskey PGP private key");
key
}

fn public_key_armor(&self) -> SignedPublicKey {
let (key, _) = SignedPublicKey::from_armor_single(Cursor::new(self.public_key_armored()))
.expect("failed to parse armored uselesskey PGP public key");
key
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using .expect() in a library can lead to panics, which is generally undesirable. It's better to return a Result to allow the caller to handle potential parsing errors gracefully. This is particularly relevant for uselesskey as it supports generating negative fixtures (e.g., corrupt keys) for testing error handling.

I recommend modifying the PgpNativeExt trait and its implementation to return pgp::errors::Result<T>.

For example:

use pgp::errors::Result as PgpResult;

pub trait PgpNativeExt {
    fn secret_key(&self) -> PgpResult<SignedSecretKey>;
    // ... other methods
}

impl PgpNativeExt for uselesskey_pgp::PgpKeyPair {
    fn secret_key(&self) -> PgpResult<SignedSecretKey> {
        SignedSecretKey::from_bytes(Cursor::new(self.private_key_binary()))
    }

    fn secret_key_armor(&self) -> PgpResult<SignedSecretKey> {
        SignedSecretKey::from_armor_single(Cursor::new(self.private_key_armored()))
            .map(|(key, _)| key)
    }

    // ... other methods
}

This change will require updating tests and examples to handle the Result, likely by using .unwrap() in those contexts.

Comment thread README.md
uselesskey-jsonwebtoken = { version = "0.4.1" }
```


Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This extra blank line can be removed for more concise formatting.

Comment on lines +30 to +31
- one smoke test that parses binary and armored fixture values
- one integration-style assertion test for deterministic conversion in an external path

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This "Tests" section reads like a developer's to-do list. For a crate's README, it would be better to either remove these informal notes or rephrase them to describe the testing strategy to users. For example:

"This crate includes tests to ensure correct parsing of both binary and armored key formats, and to verify deterministic conversion."

use uselesskey_core::Factory;
use uselesskey_pgp::{PgpFactoryExt, PgpSpec};
use uselesskey_pgp_native::PgpNativeExt;
use pgp::types::KeyDetails;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This import of KeyDetails is unused and can be removed.


use std::io::Cursor;

use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The Deserializable trait is imported but not used in this file. It can be removed to clean up the imports.

Suggested change
use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};
use pgp::composed::{SignedPublicKey, SignedSecretKey};


#[cfg(test)]
mod tests {
use pgp::types::KeyDetails;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This import of KeyDetails is unused within the tests module and can be removed.

@@ -0,0 +1,21 @@
use uselesskey_core::Factory;
use uselesskey_pgp::{PgpFactoryExt, PgpSpec};
use pgp::types::KeyDetails;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This import of KeyDetails is unused and can be removed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6b63b019f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

fn public_key_armor(&self) -> SignedPublicKey;
}

impl PgpNativeExt for uselesskey_pgp::PgpKeyPair {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate PgpKeyPair impl behind pgp-native feature

uselesskey-pgp is declared optional, but this impl is compiled unconditionally, so cargo check -p uselesskey-pgp-native --no-default-features fails with an unresolved uselesskey_pgp crate. That breaks consumers who disable default features (a common workspace policy) and makes the crate’s feature contract inconsistent. Either make uselesskey-pgp non-optional or add #[cfg(feature = "pgp-native")] gating so no-default builds still compile.

Useful? React with 👍 / 👎.

@EffortlessSteven EffortlessSteven force-pushed the feat/v0.5.0-adapter-b-pgp branch from 18005e6 to ba3af36 Compare March 25, 2026 10:20
@EffortlessSteven EffortlessSteven force-pushed the feat/v0.5.0-adapter-b-pgp branch from ba3af36 to b2233fc Compare March 25, 2026 10:46
@EffortlessSteven EffortlessSteven merged commit 93e70a8 into main Mar 25, 2026
4 checks passed
@EffortlessSteven EffortlessSteven deleted the feat/v0.5.0-adapter-b-pgp branch April 3, 2026 03:45
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.

1 participant