From 9a424cb3465c6ae3afe5b686f31ced57a42eedf2 Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Fri, 28 Aug 2026 19:28:37 -0400 Subject: [PATCH] refactor(facade)!: rename the umbrella crate to didbot Co-Authored-By: Claude Opus 5 (1M context) Change-Id: I3224bfa3f0dba31628430c2a37e7640b12fdbf84 --- .gitignore | 2 +- Cargo.lock | 96 +++++++++---------- crates/{vibescrobble => didbot}/Cargo.toml | 2 +- crates/{vibescrobble => didbot}/release.toml | 0 crates/{vibescrobble => didbot}/src/lib.rs | 0 .../tests/conformance.rs | 32 +++---- .../tests/conformance/crypto.rs | 4 +- .../tests/conformance/data_model.rs | 2 +- .../tests/conformance/emit.rs | 60 ++++++------ .../tests/conformance/firehose.rs | 4 +- .../tests/conformance/mst.rs | 4 +- .../tests/conformance/mst_diff.rs | 4 +- .../tests/conformance/mst_inversion.rs | 4 +- .../tests/conformance/mst_vectors.rs | 4 +- .../tests/conformance/records.rs | 2 +- .../tests/conformance/vectors.rs | 0 .../tests/conformance/wire.rs | 24 ++--- .../tests/end_to_end.rs | 16 ++-- .../tests/firehose.rs | 16 ++-- .../tests/hook_to_record.rs | 10 +- .../tests/release_metadata.rs | 0 crates/vibescrobble-serve/src/routes.rs | 2 +- docs/conformance.md | 14 +-- docs/overview.md | 2 +- plan/local-dev.md | 4 +- scripts/fetch-mst-vectors.sh | 2 +- scripts/refresh-interop-vectors.sh | 2 +- vendor/atproto-interop-tests/PROVENANCE.md | 2 +- 28 files changed, 157 insertions(+), 157 deletions(-) rename crates/{vibescrobble => didbot}/Cargo.toml (98%) rename crates/{vibescrobble => didbot}/release.toml (100%) rename crates/{vibescrobble => didbot}/src/lib.rs (100%) rename crates/{vibescrobble => didbot}/tests/conformance.rs (84%) rename crates/{vibescrobble => didbot}/tests/conformance/crypto.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/data_model.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/emit.rs (89%) rename crates/{vibescrobble => didbot}/tests/conformance/firehose.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/mst.rs (97%) rename crates/{vibescrobble => didbot}/tests/conformance/mst_diff.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/mst_inversion.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/mst_vectors.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/records.rs (99%) rename crates/{vibescrobble => didbot}/tests/conformance/vectors.rs (100%) rename crates/{vibescrobble => didbot}/tests/conformance/wire.rs (97%) rename crates/{vibescrobble => didbot}/tests/end_to_end.rs (95%) rename crates/{vibescrobble => didbot}/tests/firehose.rs (96%) rename crates/{vibescrobble => didbot}/tests/hook_to_record.rs (98%) rename crates/{vibescrobble => didbot}/tests/release_metadata.rs (100%) diff --git a/.gitignore b/.gitignore index 8179e703..9e2367bb 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,7 @@ Thumbs.db # Fetched test corpora. The Merkle search tree diff suite is 24MB of JSON in # 16,384 files, which is too much to vendor the way the interop vectors are: # scripts/fetch-mst-vectors.sh clones it here instead, and the runner in -# crates/vibescrobble/tests/conformance/ fails with that instruction when it +# crates/didbot/tests/conformance/ fails with that instruction when it # is not here. /.cache diff --git a/Cargo.lock b/Cargo.lock index 345493cc..d767cd76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -529,6 +529,34 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +[[package]] +name = "didbot" +version = "0.1.0" +dependencies = [ + "axum", + "didbot-attest", + "didbot-data", + "didbot-dns", + "didbot-hook", + "didbot-hookd", + "didbot-identity", + "didbot-key", + "didbot-lexicon", + "didbot-mcp", + "didbot-name", + "didbot-repo", + "didbot-stack", + "reqwest", + "serde", + "serde_json", + "time", + "tokio", + "toml", + "tower", + "vibescrobble-pds", + "vibescrobble-serve", +] + [[package]] name = "didbot-attest" version = "0.1.0" @@ -603,6 +631,25 @@ dependencies = [ "thiserror", ] +[[package]] +name = "didbot-index" +version = "0.1.0" +dependencies = [ + "axum", + "didbot-identity", + "didbot-lexicon", + "futures-core", + "reqwest", + "serde", + "serde_json", + "thiserror", + "time", + "tokio", + "tower-http", + "tracing", + "tracing-subscriber", +] + [[package]] name = "didbot-key" version = "0.1.0" @@ -665,6 +712,7 @@ version = "0.1.0" dependencies = [ "axum", "didbot-identity", + "didbot-index", "reqwest", "serde", "serde_json", @@ -673,7 +721,6 @@ dependencies = [ "tower-http", "tracing", "tracing-subscriber", - "didbot-index", ] [[package]] @@ -2960,53 +3007,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vibescrobble" -version = "0.1.0" -dependencies = [ - "axum", - "didbot-attest", - "didbot-data", - "didbot-dns", - "didbot-hook", - "didbot-hookd", - "didbot-identity", - "didbot-key", - "didbot-lexicon", - "didbot-mcp", - "didbot-name", - "didbot-repo", - "didbot-stack", - "reqwest", - "serde", - "serde_json", - "time", - "tokio", - "toml", - "tower", - "vibescrobble-pds", - "vibescrobble-serve", -] - -[[package]] -name = "didbot-index" -version = "0.1.0" -dependencies = [ - "axum", - "didbot-identity", - "didbot-lexicon", - "futures-core", - "reqwest", - "serde", - "serde_json", - "thiserror", - "time", - "tokio", - "tower-http", - "tracing", - "tracing-subscriber", -] - [[package]] name = "vibescrobble-pds" version = "0.1.0" diff --git a/crates/vibescrobble/Cargo.toml b/crates/didbot/Cargo.toml similarity index 98% rename from crates/vibescrobble/Cargo.toml rename to crates/didbot/Cargo.toml index 9e1d7a5d..0ab68f36 100644 --- a/crates/vibescrobble/Cargo.toml +++ b/crates/didbot/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "vibescrobble" +name = "didbot" description = "Attestation-gated identity provider for AI agents, built as a custom ATProto PDS." version.workspace = true edition.workspace = true diff --git a/crates/vibescrobble/release.toml b/crates/didbot/release.toml similarity index 100% rename from crates/vibescrobble/release.toml rename to crates/didbot/release.toml diff --git a/crates/vibescrobble/src/lib.rs b/crates/didbot/src/lib.rs similarity index 100% rename from crates/vibescrobble/src/lib.rs rename to crates/didbot/src/lib.rs diff --git a/crates/vibescrobble/tests/conformance.rs b/crates/didbot/tests/conformance.rs similarity index 84% rename from crates/vibescrobble/tests/conformance.rs rename to crates/didbot/tests/conformance.rs index afb4fc35..9f703e80 100644 --- a/crates/vibescrobble/tests/conformance.rs +++ b/crates/didbot/tests/conformance.rs @@ -27,14 +27,14 @@ use conformance::vectors::Suite; /// TIDs: the sortable keys this server mints records under. #[test] fn tid_syntax() { - Suite::new("tid").run(vibescrobble::pds::tid::validate); + Suite::new("tid").run(didbot::pds::tid::validate); } /// Record keys, which are far looser than TIDs; see -/// [`vibescrobble::pds::records::validate_record_key`]. +/// [`didbot::pds::records::validate_record_key`]. #[test] fn record_key_syntax() { - Suite::new("recordkey").run(vibescrobble::pds::records::validate_record_key); + Suite::new("recordkey").run(didbot::pds::records::validate_record_key); } /// NSIDs, against the generic syntax validator rather than against the set of @@ -52,7 +52,7 @@ fn nsid_syntax() { Reported upstream, with a replacement pair that pins the boundary \ exactly: https://github.com/bluesky-social/atproto-interop-tests/issues/15", ) - .run(vibescrobble::nsid_syntax::validate); + .run(didbot::nsid_syntax::validate); } /// The one excused NSID vector is excused for the reason it says. @@ -93,13 +93,13 @@ fn the_excused_nsid_vector_exceeds_the_authority_limit_the_spec_sets() { /// Handles, against the generic validator. `AgentDid`'s hostname rules are /// deliberately stricter and are not what these vectors describe; see -/// [`vibescrobble::identity::handle`]. +/// [`didbot::identity::handle`]. #[test] fn handle_syntax() { - Suite::new("handle").run(vibescrobble::identity::validate_handle); + Suite::new("handle").run(didbot::identity::validate_handle); } -/// DIDs of every method, against [`vibescrobble::identity::validate_did`]. +/// DIDs of every method, against [`didbot::identity::validate_did`]. /// /// Explicitly *not* against `AgentDid::parse`, which is this project's own /// narrower rule — did:web only, hostname-level, loopback ports. Nearly every @@ -109,7 +109,7 @@ fn handle_syntax() { /// under the generic rule. #[test] fn did_syntax() { - Suite::new("did").run(vibescrobble::identity::validate_did); + Suite::new("did").run(didbot::identity::validate_did); } /// AT-identifiers: the union of a handle and a DID, as a query parameter that @@ -117,10 +117,10 @@ fn did_syntax() { #[test] fn at_identifier_syntax() { Suite::new("atidentifier").run(|candidate: &str| { - vibescrobble::identity::validate_did(candidate) + didbot::identity::validate_did(candidate) .map_err(|err| err.to_string()) .or_else(|did_err| { - vibescrobble::identity::validate_handle(candidate).map_err(|handle_err| { + didbot::identity::validate_handle(candidate).map_err(|handle_err| { format!("not a did ({did_err}); not a handle ({handle_err})") }) }) @@ -134,7 +134,7 @@ fn at_uri_syntax() { // The parsed value borrows its input, so it is dropped here rather // than returned: `run` is generic over the success type but not over // a lifetime tied to the candidate. - .run(|candidate: &str| vibescrobble::pds::AtUri::parse(candidate).map(|_| ())); + .run(|candidate: &str| didbot::pds::AtUri::parse(candidate).map(|_| ())); } /// Datetimes, syntax and calendar together. @@ -146,7 +146,7 @@ fn at_uri_syntax() { fn datetime_syntax() { Suite::new("datetime") .also_invalid("datetime_parse_invalid.txt") - .run(vibescrobble::pds::format::datetime::validate); + .run(didbot::pds::format::datetime::validate); } /// BCP 47 language tags, including the repeated-subtag rule that a grammar @@ -155,19 +155,19 @@ fn datetime_syntax() { fn language_syntax() { Suite::new("language") .also_invalid("language_parse_invalid.txt") - .run(vibescrobble::pds::format::language::validate); + .run(didbot::pds::format::language::validate); } /// Generic URIs, against the deliberately lenient rule atproto specifies. #[test] fn uri_syntax() { - Suite::new("uri").run(vibescrobble::pds::format::uri::validate); + Suite::new("uri").run(didbot::pds::format::uri::validate); } /// Content identifiers, by shape. This server emits none; see -/// [`vibescrobble::pds::format::cid`] for why the check is a shape and not a +/// [`didbot::pds::format::cid`] for why the check is a shape and not a /// decode. #[test] fn cid_syntax() { - Suite::new("cid").run(vibescrobble::pds::format::cid::validate); + Suite::new("cid").run(didbot::pds::format::cid::validate); } diff --git a/crates/vibescrobble/tests/conformance/crypto.rs b/crates/didbot/tests/conformance/crypto.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/crypto.rs rename to crates/didbot/tests/conformance/crypto.rs index dbba006f..e3d1ce8e 100644 --- a/crates/vibescrobble/tests/conformance/crypto.rs +++ b/crates/didbot/tests/conformance/crypto.rs @@ -16,8 +16,8 @@ use std::path::PathBuf; +use didbot::key::{secp256r1, Signature, SigningKey, VerifyingKey}; use serde::Deserialize; -use vibescrobble::key::{secp256r1, Signature, SigningKey, VerifyingKey}; /// Where the vendored vectors live, relative to this crate. fn crypto_dir() -> PathBuf { @@ -65,7 +65,7 @@ struct SignatureVector { /// /// `ES256K` is secp256k1, which this server signs and verifies with. `ES256` /// is P-256, which it verifies and never signs; see -/// [`vibescrobble::key::secp256r1`]. +/// [`didbot::key::secp256r1`]. const SECP256K1: &str = "ES256K"; const P256: &str = "ES256"; diff --git a/crates/vibescrobble/tests/conformance/data_model.rs b/crates/didbot/tests/conformance/data_model.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/data_model.rs rename to crates/didbot/tests/conformance/data_model.rs index b5d8c6d7..2ee051e4 100644 --- a/crates/vibescrobble/tests/conformance/data_model.rs +++ b/crates/didbot/tests/conformance/data_model.rs @@ -12,8 +12,8 @@ use std::path::PathBuf; +use didbot::data::{dag_cbor, Cid, Value}; use serde::Deserialize; -use vibescrobble::data::{dag_cbor, Cid, Value}; use super::vectors::vendor_dir; diff --git a/crates/vibescrobble/tests/conformance/emit.rs b/crates/didbot/tests/conformance/emit.rs similarity index 89% rename from crates/vibescrobble/tests/conformance/emit.rs rename to crates/didbot/tests/conformance/emit.rs index 1ee36780..cb6a98a6 100644 --- a/crates/vibescrobble/tests/conformance/emit.rs +++ b/crates/didbot/tests/conformance/emit.rs @@ -8,9 +8,9 @@ //! generating real output and feeding it back through the parsers the vectors //! validate. -use vibescrobble::identity::{validate_did, validate_handle, AgentDid, Zone}; -use vibescrobble::pds::Registry as _; -use vibescrobble::pds::{ +use didbot::identity::{validate_did, validate_handle, AgentDid, Zone}; +use didbot::pds::Registry as _; +use didbot::pds::{ tid, validate_record_key, AtUri, MemoryRecordStore, Precondition, RecordStore, }; @@ -31,13 +31,13 @@ const SAMPLES: usize = 2_000; fn sample(collection: &str) -> serde_json::Value { let created_at = "2026-08-25T10:00:00Z"; match collection { - vibescrobble::nsid::SCROBBLE => serde_json::json!({ + didbot::nsid::SCROBBLE => serde_json::json!({ "text": "minting a record key", "emoji": "\u{1f511}", "createdAt": created_at }), - vibescrobble::nsid::MEMORY => serde_json::json!({ + didbot::nsid::MEMORY => serde_json::json!({ "text": "what the minting run looked like", "createdAt": created_at }), - vibescrobble::nsid::ACTOR_REGISTRATION => serde_json::json!({ + didbot::nsid::ACTOR_REGISTRATION => serde_json::json!({ "did": "did:web:agent.example.com", "provisionedAt": created_at, "operator": "did:web:agents.example.com", @@ -52,7 +52,7 @@ fn sample(collection: &str) -> serde_json::Value { "admittedOn": "node-alpha", }, }), - vibescrobble::nsid::AGENT_VOUCH => serde_json::json!({ + didbot::nsid::AGENT_VOUCH => serde_json::json!({ "subject": "did:web:child.agents.example.com", "createdAt": created_at }), other => panic!("no sample record for {other}; add one beside the lexicon"), @@ -67,9 +67,9 @@ fn minted_keys() -> Vec { store .put( "did:web:agent.example.com", - vibescrobble::nsid::SCROBBLE, + didbot::nsid::SCROBBLE, None, - sample(vibescrobble::nsid::SCROBBLE), + sample(didbot::nsid::SCROBBLE), &Precondition::Unconditional, ) .expect("a known collection and a valid record must be writable") @@ -114,11 +114,11 @@ fn every_uri_this_server_builds_parses_back_to_its_parts() { let did = "did:web:agent.agents.example.com"; let store = MemoryRecordStore::new(); - for collection in vibescrobble::nsid::ALL { + for collection in didbot::nsid::ALL { // A collection this server authors is refused to callers, so the // fixture is written through the path the server itself uses. The // property under test is about the URI, not about who may write. - let rkey = if vibescrobble::pds::records::server_authored(collection) { + let rkey = if didbot::pds::records::server_authored(collection) { store.put_authored(did, collection, sample(collection)) } else { store @@ -132,7 +132,7 @@ fn every_uri_this_server_builds_parses_back_to_its_parts() { .map(|written| written.rkey) } .expect("every declared collection is writable by somebody"); - let uri = vibescrobble::serve::record_uri(did, collection, &rkey); + let uri = didbot::serve::record_uri(did, collection, &rkey); let parsed = AtUri::parse(&uri) .unwrap_or_else(|err| panic!("this server built an unparseable uri {uri:?}: {err}")); assert_eq!(parsed.authority(), did); @@ -143,8 +143,8 @@ fn every_uri_this_server_builds_parses_back_to_its_parts() { #[test] fn every_declared_nsid_is_a_valid_nsid() { - for collection in vibescrobble::nsid::ALL { - vibescrobble::nsid_syntax::validate(collection) + for collection in didbot::nsid::ALL { + didbot::nsid_syntax::validate(collection) .unwrap_or_else(|err| panic!("declared collection {collection} is not an nsid: {err}")); } } @@ -208,12 +208,12 @@ fn every_declared_collection_has_a_sample_that_satisfies_its_lexicon() { // a lexicon that gains a required field must fail here — where the sample // lives and can be fixed — rather than in whichever test happened to run // first. - for collection in vibescrobble::nsid::ALL { + for collection in didbot::nsid::ALL { // `validate_shape` rather than `validate`: the question here is // whether the sample satisfies the schema, and `validate` additionally // answers whether a caller may write it, which for a server-authored // collection is always no. - vibescrobble::pds::records::validate_shape(collection, &sample(collection)) + didbot::pds::records::validate_shape(collection, &sample(collection)) .unwrap_or_else(|err| panic!("the sample for {collection} is not valid: {err}")); } } @@ -238,42 +238,42 @@ const NODE: &str = "node-conformance"; /// A stubbed anything here would prove that a stub agrees with itself. fn provisioner( named: bool, -) -> vibescrobble::pds::Provisioner< - vibescrobble::attest::SharedSecretBackend, - vibescrobble::dns::InMemoryDns, - vibescrobble::pds::MemoryAccountStore, +) -> didbot::pds::Provisioner< + didbot::attest::SharedSecretBackend, + didbot::dns::InMemoryDns, + didbot::pds::MemoryAccountStore, > { - let zone = vibescrobble::identity::Zone::new(HANDLE_ZONE).expect("a subdomain is a zone"); - let pds = vibescrobble::pds::Provisioner::new( + let zone = didbot::identity::Zone::new(HANDLE_ZONE).expect("a subdomain is a zone"); + let pds = didbot::pds::Provisioner::new( "did:web:owner.example", zone, format!("https://{HANDLE_ZONE}"), - vibescrobble::attest::SharedSecretBackend::new(SECRET, [NODE]), - vibescrobble::dns::InMemoryDns::new(), - vibescrobble::pds::MemoryAccountStore::new(), + didbot::attest::SharedSecretBackend::new(SECRET, [NODE]), + didbot::dns::InMemoryDns::new(), + didbot::pds::MemoryAccountStore::new(), ); if !named { return pds; } let fragments = didbot_name::from_spec("mineral+creature").expect("the bundled lists load"); - pds.with_naming(std::sync::Arc::new(vibescrobble::pds::Naming::new( + pds.with_naming(std::sync::Arc::new(didbot::pds::Naming::new( std::sync::Arc::new(fragments), ))) } /// Provisions `count` accounts and returns them. fn provision_all( - pds: &dyn vibescrobble::pds::Registry, + pds: &dyn didbot::pds::Registry, count: usize, -) -> Vec { - let backend = vibescrobble::attest::SharedSecretBackend::new(SECRET, [NODE]); +) -> Vec { + let backend = didbot::attest::SharedSecretBackend::new(SECRET, [NODE]); (0..count) .map(|n| { let agent_id = format!("sess-{n:04}"); let claim = backend .produce_claim(NODE, &agent_id, time::OffsetDateTime::now_utc()) .expect("the development backend produces a claim it will accept"); - pds.provision(vibescrobble::pds::ProvisionRequest::new( + pds.provision(didbot::pds::ProvisionRequest::new( &agent_id, None, claim, )) .unwrap_or_else(|err| panic!("provisioning {agent_id} failed: {err}")) diff --git a/crates/vibescrobble/tests/conformance/firehose.rs b/crates/didbot/tests/conformance/firehose.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/firehose.rs rename to crates/didbot/tests/conformance/firehose.rs index 309002e3..41537838 100644 --- a/crates/vibescrobble/tests/conformance/firehose.rs +++ b/crates/didbot/tests/conformance/firehose.rs @@ -20,9 +20,9 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; +use didbot::data::mst::Tree; +use didbot::data::Cid; use serde::Deserialize; -use vibescrobble::data::mst::Tree; -use vibescrobble::data::Cid; use super::vectors::vendor_dir; diff --git a/crates/vibescrobble/tests/conformance/mst.rs b/crates/didbot/tests/conformance/mst.rs similarity index 97% rename from crates/vibescrobble/tests/conformance/mst.rs rename to crates/didbot/tests/conformance/mst.rs index c2fcdcbe..beb4acfd 100644 --- a/crates/vibescrobble/tests/conformance/mst.rs +++ b/crates/didbot/tests/conformance/mst.rs @@ -3,7 +3,7 @@ //! Upstream's `mst/` directory is named after a structure that none of its //! vectors requires. `key_heights.json` gives a key and the layer it sits on, and //! `common_prefix.json` gives two keys and how much of them is shared. Both -//! are checked against [`vibescrobble::data::mst`]; the tree itself does not +//! are checked against [`didbot::data::mst`]; the tree itself does not //! exist here yet, and neither file needs it. //! //! `example_keys.txt` is run as well, and it is the reason this file is worth @@ -20,8 +20,8 @@ use std::path::PathBuf; +use didbot::data::mst::{common_prefix_len, key_height}; use serde::Deserialize; -use vibescrobble::data::mst::{common_prefix_len, key_height}; use super::vectors::vendor_dir; diff --git a/crates/vibescrobble/tests/conformance/mst_diff.rs b/crates/didbot/tests/conformance/mst_diff.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/mst_diff.rs rename to crates/didbot/tests/conformance/mst_diff.rs index d34a96ca..cc433a26 100644 --- a/crates/vibescrobble/tests/conformance/mst_diff.rs +++ b/crates/didbot/tests/conformance/mst_diff.rs @@ -43,8 +43,8 @@ use std::collections::{BTreeMap, BTreeSet}; -use vibescrobble::data::mst::{self, Store}; -use vibescrobble::data::Cid; +use didbot::data::mst::{self, Store}; +use didbot::data::Cid; use super::mst_vectors::{Case, Corpus}; diff --git a/crates/vibescrobble/tests/conformance/mst_inversion.rs b/crates/didbot/tests/conformance/mst_inversion.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/mst_inversion.rs rename to crates/didbot/tests/conformance/mst_inversion.rs index 8b032d99..4028dd03 100644 --- a/crates/vibescrobble/tests/conformance/mst_inversion.rs +++ b/crates/didbot/tests/conformance/mst_inversion.rs @@ -42,8 +42,8 @@ use std::collections::{BTreeMap, BTreeSet}; -use vibescrobble::data::mst::{key_height, Node, Parts, Store}; -use vibescrobble::data::Cid; +use didbot::data::mst::{key_height, Node, Parts, Store}; +use didbot::data::Cid; use super::mst_vectors::{Case, Corpus}; diff --git a/crates/vibescrobble/tests/conformance/mst_vectors.rs b/crates/didbot/tests/conformance/mst_vectors.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/mst_vectors.rs rename to crates/didbot/tests/conformance/mst_vectors.rs index 18e41819..1dc39d6e 100644 --- a/crates/vibescrobble/tests/conformance/mst_vectors.rs +++ b/crates/didbot/tests/conformance/mst_vectors.rs @@ -26,8 +26,8 @@ use std::sync::OnceLock; use didbot_repo::car; use serde::Deserialize; -use vibescrobble::data::mst::Store; -use vibescrobble::data::Cid; +use didbot::data::mst::Store; +use didbot::data::Cid; /// The case type this runner understands. Upstream plans others. const CASE_TYPE: &str = "mst-diff"; diff --git a/crates/vibescrobble/tests/conformance/records.rs b/crates/didbot/tests/conformance/records.rs similarity index 99% rename from crates/vibescrobble/tests/conformance/records.rs rename to crates/didbot/tests/conformance/records.rs index 9085aefe..fe11fc15 100644 --- a/crates/vibescrobble/tests/conformance/records.rs +++ b/crates/didbot/tests/conformance/records.rs @@ -14,7 +14,7 @@ use std::path::PathBuf; use didbot_lexicon::lexicon::LexiconDoc; use serde::Deserialize; -use vibescrobble::pds::Catalog; +use didbot::pds::Catalog; use super::vectors::vendor_dir; diff --git a/crates/vibescrobble/tests/conformance/vectors.rs b/crates/didbot/tests/conformance/vectors.rs similarity index 100% rename from crates/vibescrobble/tests/conformance/vectors.rs rename to crates/didbot/tests/conformance/vectors.rs diff --git a/crates/vibescrobble/tests/conformance/wire.rs b/crates/didbot/tests/conformance/wire.rs similarity index 97% rename from crates/vibescrobble/tests/conformance/wire.rs rename to crates/didbot/tests/conformance/wire.rs index 51352a2d..d11f495a 100644 --- a/crates/vibescrobble/tests/conformance/wire.rs +++ b/crates/didbot/tests/conformance/wire.rs @@ -25,12 +25,12 @@ use axum::http::{Request, StatusCode}; use serde_json::{json, Value}; use tower::ServiceExt; -use vibescrobble::attest::{AttestationClaim, SharedSecretBackend}; -use vibescrobble::dns::LoopbackDns; -use vibescrobble::identity::Zone; -use vibescrobble::lexicon::LexiconDoc; -use vibescrobble::nsid; -use vibescrobble::pds::{Catalog, MemoryAccountStore, ProvisionRequest, Provisioner, Registry}; +use didbot::attest::{AttestationClaim, SharedSecretBackend}; +use didbot::dns::LoopbackDns; +use didbot::identity::Zone; +use didbot::lexicon::LexiconDoc; +use didbot::nsid; +use didbot::pds::{Catalog, MemoryAccountStore, ProvisionRequest, Provisioner, Registry}; const SECRET: &[u8] = b"quernstone-development-secret"; const NODE: &str = "dev-node-1"; @@ -138,7 +138,7 @@ fn server() -> (axum::Router, String) { .expect("provisioning succeeds") .account .did; - let app = vibescrobble::serve::app(pds as Arc); + let app = didbot::serve::app(pds as Arc); (app, did.to_string()) } @@ -329,7 +329,7 @@ async fn query(app: &axum::Router, nsid: &str, params: &str) -> Answer { /// write a case for. This one reads the route table instead. #[test] fn every_atproto_route_this_server_serves_is_a_vendored_method() { - let routes = vibescrobble::serve::ATPROTO_METHODS; + let routes = didbot::serve::ATPROTO_METHODS; assert!(!routes.is_empty(), "the server serves no atproto methods"); for nsid in routes { assert!( @@ -605,7 +605,7 @@ async fn a_foreign_record_conforms_and_is_reported_unknown() { /// binary encoding and no schema, which /// [`the_vendored_documents_declare_the_outputs_this_suite_checks`] asserts /// rather than assumes. What they return is checked by -/// `crates/vibescrobble/tests/conformance/emit.rs` and by the CAR tests, +/// `crates/didbot/tests/conformance/emit.rs` and by the CAR tests, /// which read the bytes. #[tokio::test] async fn the_sync_routes_answer_what_their_documents_promise() { @@ -650,7 +650,7 @@ async fn an_upload_answers_the_blob_shape_the_document_declares() { .method("POST") .uri("/xrpc/com.atproto.repo.uploadBlob") .header("content-type", "application/octet-stream") - .header(vibescrobble::serve::REPO_HEADER, &did) + .header(didbot::serve::REPO_HEADER, &did) .body(Body::from(bytes.clone())) .expect("request builds"); let uploaded = call(&app, request) @@ -859,7 +859,7 @@ async fn the_turn_header_does_not_reach_the_record() { .method("POST") .uri("/xrpc/com.atproto.repo.createRecord") .header("content-type", "application/json") - .header(vibescrobble::serve::TURN_HEADER, "toolu-01-conformance") + .header(didbot::serve::TURN_HEADER, "toolu-01-conformance") .body(Body::from( json!({ "repo": did, @@ -904,6 +904,6 @@ async fn the_turn_header_does_not_reach_the_record() { fn the_quiet_log_filter_is_the_servers_own_default() { assert_eq!( didbot_stack::QUIET_LOG_FILTER, - vibescrobble::serve::DEFAULT_LOG_FILTER + didbot::serve::DEFAULT_LOG_FILTER ); } diff --git a/crates/vibescrobble/tests/end_to_end.rs b/crates/didbot/tests/end_to_end.rs similarity index 95% rename from crates/vibescrobble/tests/end_to_end.rs rename to crates/didbot/tests/end_to_end.rs index ca88c4e9..5e206ce7 100644 --- a/crates/vibescrobble/tests/end_to_end.rs +++ b/crates/didbot/tests/end_to_end.rs @@ -19,10 +19,10 @@ use axum::body::Body; use axum::http::{Request, StatusCode}; use tower::ServiceExt; -use vibescrobble::attest::{AttestationClaim, SharedSecretBackend}; -use vibescrobble::dns::LoopbackDns; -use vibescrobble::identity::{resolve, AgentDid, DidDocumentSource, ResolveError, Zone}; -use vibescrobble::pds::{MemoryAccountStore, Provisioner, Registry}; +use didbot::attest::{AttestationClaim, SharedSecretBackend}; +use didbot::dns::LoopbackDns; +use didbot::identity::{resolve, AgentDid, DidDocumentSource, ResolveError, Zone}; +use didbot::pds::{MemoryAccountStore, Provisioner, Registry}; const SECRET: &[u8] = b"quernstone-development-secret"; const NODE: &str = "dev-node-1"; @@ -149,7 +149,7 @@ fn split_url(url: &str) -> (String, String) { #[tokio::test(flavor = "multi_thread")] async fn an_agent_is_provisioned_served_resolved_and_deleted() { let registry = registry(); - let app = vibescrobble::serve::app(registry.clone()); + let app = didbot::serve::app(registry.clone()); // 1. Provision. let (status, body) = post( @@ -207,7 +207,7 @@ async fn an_agent_is_provisioned_served_resolved_and_deleted() { #[tokio::test(flavor = "multi_thread")] async fn a_refused_attestation_provisions_nothing() { let registry = registry(); - let app = vibescrobble::serve::app(registry.clone()); + let app = didbot::serve::app(registry.clone()); let mut body: serde_json::Value = serde_json::from_str(&provision_body("impostor")).expect("body parses"); @@ -229,7 +229,7 @@ async fn a_refused_attestation_provisions_nothing() { #[tokio::test(flavor = "multi_thread")] async fn an_unknown_hostname_is_not_served() { - let app = vibescrobble::serve::app(registry()); + let app = didbot::serve::app(registry()); let (status, _) = call( &app, Request::builder() @@ -247,7 +247,7 @@ async fn two_agents_get_two_identifiers_and_two_hostnames() { // The premise of the whole project is one identity per agent context, so // it is worth one test that says so directly. let registry = registry(); - let app = vibescrobble::serve::app(registry.clone()); + let app = didbot::serve::app(registry.clone()); let (first, _) = post( &app, diff --git a/crates/vibescrobble/tests/firehose.rs b/crates/didbot/tests/firehose.rs similarity index 96% rename from crates/vibescrobble/tests/firehose.rs rename to crates/didbot/tests/firehose.rs index a4b8289d..477505a2 100644 --- a/crates/vibescrobble/tests/firehose.rs +++ b/crates/didbot/tests/firehose.rs @@ -18,13 +18,13 @@ use std::sync::Arc; use std::time::Duration; +use didbot::attest::{AttestationClaim, SharedSecretBackend}; +use didbot::dns::LoopbackDns; +use didbot::identity::Zone; +use didbot::nsid; +use didbot::pds::{MemoryAccountStore, ProvisionRequest, Provisioner, Registry, Swap}; +use didbot::serve::{app_with_streams, BroadcastSink, CommitFrame, Firehose, Info, InfoName}; use tokio::sync::mpsc; -use vibescrobble::attest::{AttestationClaim, SharedSecretBackend}; -use vibescrobble::dns::LoopbackDns; -use vibescrobble::identity::Zone; -use vibescrobble::nsid; -use vibescrobble::pds::{MemoryAccountStore, ProvisionRequest, Provisioner, Registry, Swap}; -use vibescrobble::serve::{app_with_streams, BroadcastSink, CommitFrame, Firehose, Info, InfoName}; /// A reader for the server-sent-event stream `/firehose` serves. mod sse { @@ -416,7 +416,7 @@ async fn every_frame_names_a_commit_the_repository_can_be_rebuilt_to() { .bytes() .await .expect("getRepo answers bytes"); - let root = vibescrobble::data::Cid::parse(&last.commit).expect("a frame's commit is a cid"); + let root = didbot::data::Cid::parse(&last.commit).expect("a frame's commit is a cid"); let header_len = usize::from(car[0]); assert!( car[1..=header_len] @@ -426,7 +426,7 @@ async fn every_frame_names_a_commit_the_repository_can_be_rebuilt_to() { ); // The record the last frame named is in that export. - let record = vibescrobble::data::Cid::parse(&last.cid).expect("a frame's record is a cid"); + let record = didbot::data::Cid::parse(&last.cid).expect("a frame's record is a cid"); assert!( car.windows(record.as_bytes().len()) .any(|window| window == record.as_bytes()), diff --git a/crates/vibescrobble/tests/hook_to_record.rs b/crates/didbot/tests/hook_to_record.rs similarity index 98% rename from crates/vibescrobble/tests/hook_to_record.rs rename to crates/didbot/tests/hook_to_record.rs index 2d68949e..3dbf3f3d 100644 --- a/crates/vibescrobble/tests/hook_to_record.rs +++ b/crates/didbot/tests/hook_to_record.rs @@ -24,10 +24,10 @@ use std::sync::Arc; use didbot_hook::{STAMP_KEY, TURN_KEY}; use serde_json::{json, Value}; -use vibescrobble::attest::SharedSecretBackend; -use vibescrobble::dns::LoopbackDns; -use vibescrobble::identity::Zone; -use vibescrobble::pds::{MemoryAccountStore, Provisioner, Registry}; +use didbot::attest::SharedSecretBackend; +use didbot::dns::LoopbackDns; +use didbot::identity::Zone; +use didbot::pds::{MemoryAccountStore, Provisioner, Registry}; /// The defaults `didbot-hookd` uses when nothing overrides them, so that /// a hook configured with no environment at all reaches this server. @@ -69,7 +69,7 @@ impl Server { LoopbackDns::new(), MemoryAccountStore::new(), )); - let app = vibescrobble::serve::app(registry); + let app = didbot::serve::app(registry); let task = tokio::spawn(async move { let _ = axum::serve(listener, app).await; }); diff --git a/crates/vibescrobble/tests/release_metadata.rs b/crates/didbot/tests/release_metadata.rs similarity index 100% rename from crates/vibescrobble/tests/release_metadata.rs rename to crates/didbot/tests/release_metadata.rs diff --git a/crates/vibescrobble-serve/src/routes.rs b/crates/vibescrobble-serve/src/routes.rs index 7d2c89e6..78d2348b 100644 --- a/crates/vibescrobble-serve/src/routes.rs +++ b/crates/vibescrobble-serve/src/routes.rs @@ -56,7 +56,7 @@ macro_rules! atproto_methods { /// Every `com.atproto.*` method this router answers, in NSID order. /// /// Public because it is what - /// `crates/vibescrobble/tests/conformance/wire.rs` reads: every name + /// `crates/didbot/tests/conformance/wire.rs` reads: every name /// here must be a method in the vendored upstream documents, so a /// route this server invents fails a test rather than shipping. pub const ATPROTO_METHODS: &[&str] = &[$($nsid),*]; diff --git a/docs/conformance.md b/docs/conformance.md index 59fc7735..2874ac50 100644 --- a/docs/conformance.md +++ b/docs/conformance.md @@ -22,7 +22,7 @@ reads them is described under [the wire](#the-wire-checked-against-the-documents They are dual MIT/Apache-2.0 rather than CC-0, so the licence files are copied beside them and `PROVENANCE.md` is the attribution. -The executable half is `crates/vibescrobble/tests/conformance.rs`. It is an +The executable half is `crates/didbot/tests/conformance.rs`. It is an ordinary `cargo test` target and adds no dependency to anything. ## What runs @@ -50,7 +50,7 @@ list of strings they are a small catalog of lexicon documents plus two lists of records that must and must not validate against them. They exercise blobs, bytes, unions, refs and closed enumerations — none of which this project's own five lexicons use — so they test the record validator far harder than -`lexicons/` can. `crates/vibescrobble/tests/conformance/records.rs` runs them +`lexicons/` can. `crates/didbot/tests/conformance/records.rs` runs them against [`crate::pds::Catalog`]. The `data-model/` vectors are a third shape again, and the only ones that @@ -58,7 +58,7 @@ check *bytes* rather than a verdict. Two of the three files are the familiar accept-and-refuse pair, run against [`crate::data::Value::object_from_json`]; the third, `data-model-fixtures.json`, gives a value, the exact DAG-CBOR encoding it must produce, and the CID that encoding must hash to. -`crates/vibescrobble/tests/conformance/data_model.rs` checks all three, and +`crates/didbot/tests/conformance/data_model.rs` checks all three, and the fixtures are why the suite is worth having: an encoder checked against its own decoder round-trips perfectly whatever map ordering or integer width it picked, and would still give every record an identity no other implementation @@ -78,7 +78,7 @@ protocol's framed DAG-CBOR stream, which this project deliberately does not speak. They do not. `commit-proof-fixtures.json` gives a leaf set, the root over it, a set of adds and deletes, the root after them, and the blocks a subscriber needs to check the operation without holding the repository. -`crates/vibescrobble/tests/conformance/firehose.rs` runs all six. +`crates/didbot/tests/conformance/firehose.rs` runs all six. That makes it the only upstream vector asserting **a root CID over a set of records**, which is the one claim `mst/` does not make, and the six shapes are @@ -106,7 +106,7 @@ A key's height is the count of leading zero bits of its sha-256 divided by two — the fanout is four, so two zero bits buy one layer — and a common prefix length is how many leading bytes two adjacent keys share, which is what lets a node store a suffix instead of a whole key. Both live in -[`crate::data::mst`], and `crates/vibescrobble/tests/conformance/mst.rs` runs +[`crate::data::mst`], and `crates/didbot/tests/conformance/mst.rs` runs `key_heights.json` and `common_prefix.json` against them. It also runs `example_keys.txt`, which is a vector file that does not announce @@ -238,7 +238,7 @@ The suites above check strings and bytes. They say nothing about whether a client written against the lexicons can talk to the routes, which is the epic's actual exit criterion. -`crates/vibescrobble/tests/conformance/wire.rs` is the automated half. It +`crates/didbot/tests/conformance/wire.rs` is the automated half. It drives every `com.atproto.*` route the router serves and checks each response body against the `output` schema the *upstream* document declares — `vendor/atproto-lexicons/`, Bluesky's own documents copied unedited by @@ -476,7 +476,7 @@ key holding it up was deleted, the tree empties, the tree fills. A suite written by hand holds the cases its author thought of. Each case names two CAR files and lists five results. Four are checked in -`crates/vibescrobble/tests/conformance/mst_diff.rs`: +`crates/didbot/tests/conformance/mst_diff.rs`: | Field | What it is | | --- | --- | diff --git a/docs/overview.md b/docs/overview.md index 6667e2e8..bd8b0967 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -23,6 +23,6 @@ namespace, and the Claude Code hook protocol. ## Status Early. Nothing here federates, and the namespace is a placeholder — see -`vibescrobble::nsid::AUTHORITY`. Local development runs with federation +`didbot::nsid::AUTHORITY`. Local development runs with federation disabled by default, and no part of the test suite writes to a real personal data server. diff --git a/plan/local-dev.md b/plan/local-dev.md index b982a38e..2d02e20c 100644 --- a/plan/local-dev.md +++ b/plan/local-dev.md @@ -137,7 +137,7 @@ that is what fills a machine: see the dev profile under Done. reached 31 GB and rebuilt from clean, whole workspace and every test binary, into 3.4 GB. - [x] **Simulate failure, not only the happy path.** A server that goes away - mid-stream is now a test: `crates/vibescrobble/tests/firehose.rs` cuts a + mid-stream is now a test: `crates/didbot/tests/firehose.rs` cuts a subscriber's connection, keeps writing records it cannot see, and requires the frames it missed back in order with nothing repeated. It needs a proxy in front of the server, because aborting the task that owns @@ -158,7 +158,7 @@ that is what fills a machine: see the dev profile under Done. touched in the last hour is reported as in use and never offered, and an idle one is somebody else's to clear. - [x] **An integration test harness: a server and a fake agent, in process.** - `crates/vibescrobble/tests/hook_to_record.rs` drives a real listener, the + `crates/didbot/tests/hook_to_record.rs` drives a real listener, the real hook handler and the real scrobble host: a session opens, a payload becomes a stamped call, the call becomes a record, the record reads back over HTTP, and the session ends taking its accounts with it. It needs a diff --git a/scripts/fetch-mst-vectors.sh b/scripts/fetch-mst-vectors.sh index edad3cdf..0bf5dddb 100755 --- a/scripts/fetch-mst-vectors.sh +++ b/scripts/fetch-mst-vectors.sh @@ -33,7 +33,7 @@ UPSTREAM="https://github.com/DavidBuchanan314/mst-test-suite.git" cd "$(dirname "$0")/.." # Where the runner looks. Kept in step with `suite_dir` in -# `crates/vibescrobble/tests/conformance/mst_vectors.rs`, and checked against it +# `crates/didbot/tests/conformance/mst_vectors.rs`, and checked against it # by `the_fetch_script_and_the_runner_agree_on_where_the_corpus_is`. cache_home="${XDG_CACHE_HOME:-$HOME/.cache}" dest="$cache_home/vibescrobble/mst-test-suite" diff --git a/scripts/refresh-interop-vectors.sh b/scripts/refresh-interop-vectors.sh index ef265463..cc80538e 100755 --- a/scripts/refresh-interop-vectors.sh +++ b/scripts/refresh-interop-vectors.sh @@ -76,7 +76,7 @@ Several vectors are exactly a trailing space, a leading space, or an empty line away from valid — \`one.two.three \` is in \`nsid_syntax_invalid.txt\` for that reason alone. The file-hygiene hooks in \`prek.toml\` exclude this directory so that they cannot quietly repair a test case into passing, and the -runner in \`crates/vibescrobble/tests/conformance/\` never trims a candidate. +runner in \`crates/didbot/tests/conformance/\` never trims a candidate. EOF echo "vendored $commit into $dest" diff --git a/vendor/atproto-interop-tests/PROVENANCE.md b/vendor/atproto-interop-tests/PROVENANCE.md index 4b1f8a47..2d547d95 100644 --- a/vendor/atproto-interop-tests/PROVENANCE.md +++ b/vendor/atproto-interop-tests/PROVENANCE.md @@ -24,4 +24,4 @@ Several vectors are exactly a trailing space, a leading space, or an empty line away from valid — `one.two.three ` is in `nsid_syntax_invalid.txt` for that reason alone. The file-hygiene hooks in `prek.toml` exclude this directory so that they cannot quietly repair a test case into passing, and the -runner in `crates/vibescrobble/tests/conformance/` never trims a candidate. +runner in `crates/didbot/tests/conformance/` never trims a candidate. -- 2.51.2