Skip to content

Conversation

@SHAcollision
Copy link
Contributor

@SHAcollision SHAcollision commented Nov 27, 2025

WIP: do not review.

  • Introduced shared PublicKey/Keypair wrappers in pubky-common::crypto::keys so every crate displays identifiers as pubky<z32> by default while still exposing .z32() for raw hostnames and registry usage.
  • For now we go with pubky... as default prefix for the public key identifier. This will be easy to change if the product team decides otherwise.
  • Replaced remaining direct pkarr key usages across the workspace (SDK, JS bindings, homeserver, testnet) with the shared wrappers to guarantee consistent formatting and serde behavior. The pkarr-republisher keeps using pkarr keys.
  • Removed the re-exported pkarr keys, instead it now re-export pubky keys from pubky-sdk, keeping documentation and examples aligned with the new display defaults.

@ok300
Copy link
Contributor

ok300 commented Nov 28, 2025

Nice, I was about to look into a similar PR, glad this is already in place.

Can you please add a way to get from a Keypair to a PubkyId?

For example:

impl Keypair {
    fn pubky_id(&self) -> Result<PubkyId, String> {
        PubkyId::try_from(self.public_key().to_z32().as_str())
    }
}

which allows

// Before (verbose)
let pubky_id = PubkyId::try_from(&keypair.public_key().to_z32())?;

// After (concise)
let pubky_id = keypair.pubky_id()?;

@SHAcollision
Copy link
Contributor Author

SHAcollision commented Nov 28, 2025

Nice, I was about to look into a similar PR, glad this is already in place.

Can you please add a way to get from a Keypair to a PubkyId?

For example:

impl Keypair {
    fn pubky_id(&self) -> Result<PubkyId, String> {
        PubkyId::try_from(self.public_key().to_z32().as_str())
    }
}

which allows

// Before (verbose)
let pubky_id = PubkyId::try_from(&keypair.public_key().to_z32())?;

// After (concise)
let pubky_id = keypair.pubky_id()?;

This would introduce a dependency on pubky-app-specs here, right? Can we do it without this dependency? I don't think we want that under any circumstance. Instead we likely want a method in pubky-app-specs that can From a PubkyId from a pubky::PublicKey ?

@SHAcollision
Copy link
Contributor Author

@SeverinAlexB Marking as ready for review here. No rush:

  • There is a small conflict with the changes introduced in feat(sdk): added auth signup flow #268 . When this conflict is solved, tests fail: most likely we need to use the new stringification methods correctly on the new AuthFlow but needs some research.
  • Warning AI slop: there are large parts of this PR that have been fixed by AI agents (e2e tests, etc). I haven't dived into all changes line by line. A more conscious work to verify the whole PR is yet to be done, unsafe to merge without it!
  • Feel free to push commits here and make changes as you like, It's good to me if you want to take ownership of it and merge it when it's OK according to your view. That's much preferable to having it stale and possibly even block v0.6.0 release until January. Feel free to delegate to someone else as well!

@SHAcollision SHAcollision marked this pull request as ready for review December 3, 2025 15:28
Copy link
Collaborator

@SeverinAlexB SeverinAlexB left a comment

Choose a reason for hiding this comment

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

I think this is good. No idea if this will lead to accidental breaking changes in the homeserver.

Does the new KeyPair/PublicKey have the same lib export path as the old one? Maybe it is better to export it in a different path so one needs to explicitly upgrade to the new KeyPair/PublicKey so the dev can check each case.

Comment on lines +27 to +31
/// Construct a [`Keypair`] from a 32-byte secret key.
#[must_use]
pub fn from_secret_key(secret: &[u8; 32]) -> Self {
Self(pkarr::Keypair::from_secret_key(secret))
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing secret key as [u8; 32] export.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, working on this.

Comment on lines +168 to +198
impl TryFrom<&str> for PublicKey {
type Error = ParseError;

fn try_from(value: &str) -> Result<Self, Self::Error> {
parse_public_key(value).map(Self)
}
}

impl TryFrom<&String> for PublicKey {
type Error = ParseError;

fn try_from(value: &String) -> Result<Self, Self::Error> {
parse_public_key(value).map(Self)
}
}

impl TryFrom<String> for PublicKey {
type Error = ParseError;

fn try_from(value: String) -> Result<Self, Self::Error> {
parse_public_key(&value).map(Self)
}
}

impl FromStr for PublicKey {
type Err = ParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
parse_public_key(s).map(Self)
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Asking ignorantly, are the TryFrom<&str or String or &String> even needed when one implements FromStr?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This question makes sense. The explicit TryFrom<&str/String/&String> impls mirror the prior pkarr surface so existing calls using PublicKey::try_from(...) continue to compile without switching to FromStr::from_str; they’re intentionally redundant for API compatibility. We could go ahead a boyscout further but I fear there might be a rabbit hole somewhere around here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Makes sense

@SHAcollision
Copy link
Contributor Author

SHAcollision commented Dec 15, 2025

Does the new KeyPair/PublicKey have the same lib export path as the old one? Maybe it is better to export it in a different path so one needs to explicitly upgrade to the new KeyPair/PublicKey so the dev can check each case.

yeha, good question. The wrapper keep the same public export locations (pubky_common::crypto::Keypair/PublicKey, re‑exported via pubky::Keypair/PublicKey) , downstream code continues to use the existing paths. The change is behavioral (prefixed display) rather than a rename. Consumers will now be using pubky:: keys instead of pkarr:: keys so indeed they are different types on the same path, yet I believe it's correct to fully delete the previous pkarr keys export and replace tat path with the new type since pkarr:: keys are of no use at all because no function on SDK / Homeserver accepts them anymore.

Overall, 0.6.0 vs previous 0.5.4 upgrade (big breaking change) leads consumers to fully re-do their use of the crate, and this is probably one of the least impactful changes.

@SHAcollision
Copy link
Contributor Author

SHAcollision commented Jan 2, 2026

Merged main and fixes a myriad of conflicts and problems that rose from working in paralell with the new signup/signin authflow:

  • Pubky key wrappers wired through auth flow + deep link signup (hostnames use .z32() now) in auth_flow.rs and signup.rs.
  • Session export/import now compiles on native with a non‑WASM import guard in core.rs; native prepare_request added in native.rs.
  • JS bindings aligned to wrapper API in keys.rs and pkarr cache seeding uses wrapper conversion in http.rs.
  • Deterministic SQL ordering for list operations. I'm getting different ordering from deep list test local vs github runner. I losen the test to not expect some exact ordering. Needs more research.
  • Metrics test now uses z32 host strings in metrics.rs; macro doctest example ignored in lib.rs.
  • Tightened prefix handling in keys.rs to avoid misparsing raw keys that start with pubky. keys.rs (line 11)
  • Switched homeserver URL helpers back to .z32() for raw pkarr-style URLs.

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.

4 participants