~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

knotless takes its keys, JWTs, base32 and TIDs from the atproto crate

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:atproto/keys

What changes

knotless now takes atproto's primitives from the atproto crate, which lives in its own repository (https://knotless.dev/chadtmiller.com/atproto) and is published to that repository's Cargo registry. .cargo/config.toml names the registry, and the workspace depends on atproto = { version = "0.1.1", registry = "atproto" }. This is the first of several pulls.

Keys and JWTs. crypto::PublicKey is now the crate's. P256Key stays as a small wrapper over the crate's Keypair, so its callers don't change. jwt_parts and verify_jwt call the crate's JOSE code. verify_jwt still refuses a high-S signature, as before: the crate's own jose::verify accepts either, but knotless keeps its stricter check. Four methods have different names in the crate (did_key, to_sec1, curve().alg(), and verify, which returns a bool), and their callers are updated. The tests of key parsing moved to the crate, which checks them against atproto's interop vectors.

base32 and TIDs. knotless::base32 is gone. drisl and space_sync use the crate's base32, and keys::tid_from and tid_micros use the crate's tid module. The output is the same, and so is what counts as a TID.

AGENTS.md says where these come from now, and that a primitive knotless needs goes into the crate first.

Why

knotless, group-host and grain's Rust rewrite each had their own copy of these primitives, and the copies had drifted. With one crate, a fix lands once, and it's checked against the interop vectors.

How it was checked

cargo check --workspace --tests is clean, and the knotless library's unit tests pass (219). The crate's own check and test pass, with every line in src/ covered. Everything else is left to CI.

Shortcomings

  • Builds now fetch from knotless.dev. A build without the crate in its Cargo cache has to reach knotless.dev's registry. The Docker build keeps that cache between runs, and so do the runner's jobs. But a deploy from scratch while knotless.dev is down can't fetch the crate. Vendoring it, or a mirror, would fix that if it ever matters.
  • The crate's base32 decode is as strict as knotless's was from 0.1.1 on, which this pull takes: 0.1.0 accepted a whole character of zero bits left over.

Changeset: none

🤖 Generated with Claude Code

Approved

This swaps knotless's own keys, JWT, base32 and TID code for the atproto crate. P256Key stays as a thin wrapper, so its callers keep working, and the call sites move to the crate's names. I read the whole diff and found nothing that must change.

  • High-S refusal: verify_jwt and the commit check in archive.rs both now go through the crate's PublicKey::verify and rely on it to refuse high-S signatures, as the old code did. The new high-S test in crypto.rs covers verify_jwt only. archive::checked has no such test, so check that the crate's verify itself refuses high-S, since that is what keeps commit verification as strict as before.
  • base32 decode: The looser decode in the crate means drisl will now take a non-canonical $link such as maa, and re-encode it differently. The body names this and the 0.1.1 fix. It is harmless for CIDs from others, but update to 0.1.1 soon.
  • Builds: They now depend on knotless.dev's registry being reachable, as the body says. I couldn't confirm that the deploy image's build context includes .cargo/config.toml, so check that.

The check, test, e2e and docs runs were still queued when I looked. The coverage gate and clippy are what to watch. web, shots, lexicons and ios were skipped as unaffected.

Approved

Since my approval, the only change is the bump to atproto 0.1.1, in Cargo.toml and Cargo.lock. The new checksum is in the lockfile. This is the stricter base32 decode my last review asked for, so the non-canonical $link concern is resolved. The earlier approval stands.

I couldn't check from here that the crate's verify refuses high-S signatures, so that is still open for the archive::checked path. The check and test runs were still queued when I looked, so clippy and the coverage gate haven't reported.

Some checks were cancelled

1 cancelled, 1 passed, 1 skipped

1 cancelled check deployCancelled in 1m 55s
1 passed check releaseSuccess in 6m 53s
1 skipped check publish-lexiconsSkipped
Merged as f1f484b