Something went wrong. Try again.
atproto made easy crates.io/crates/jacquard
atproto rust
Something went wrong. Try again.
7.8 kB · 193 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194//! Provider fixture model: deterministic identities and run coordinates//! exported by the lifecycle controller.
use std::fmt;
/// The Tranquil fixture's did:web identity. Tranquil fetches did:web/// documents over plain HTTP when the domain starts with `localhost` (its/// own documented loopback exception); `localhost.jacquard-e2e.test` rides/// that exception while remaining a real DNS name inside the bridge. The/// proxy forwards port 80 (Tranquil's HTTP fetch) to the ingress HTTP/// listener and port 443 (host-side TLS resolution) to the ingress TLS/// listener.pub const TRANQUIL_IDENTITY_DID: &str = "did:web:localhost.jacquard-e2e.test";
pub const TRANQUIL_MEMBER_DID: &str = "did:web:localhost.jacquard-e2e.test:member";
/// Simulator-seeded repo DID. The jetstream simulator backfills a fixed/// synthetic firehose; this DID appears in its sealed segments.pub const JETSTREAM_SEED_DID: &str = "did:plc:simulator.jacquard-e2e.test";
/// Service DID used by the Tranquil proxy scenario. Its document is served by/// the native ingress and names the generated endpoint fragment.pub const TRANQUIL_SERVICE_DID: &str = "did:web:localhost.jacquard-e2e.test:service";
/// Which provider fixture a scenario run targets.#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]pub enum Provider { /// Tranquil PDS (`atcr.io/tranquil.farm/tranquil-pds`). Tranquil, /// Reference PDS spaces-alpha (`ghcr.io/bluesky-social/atproto:pds-spaces-alpha`). Reference, /// Jetstream v2 server with a simulator-seeded archive. Not a PDS: /// scenarios exercise the jetstream client surface (plan, segments, /// live subscription) rather than repo operations. Jetstream,}
impl Provider { /// Stable identifier used in environment variables, Compose profiles, /// nextest filters, and artifact paths. pub const fn name(&self) -> &'static str { match self { Self::Tranquil => "tranquil", Self::Reference => "reference", Self::Jetstream => "jetstream", } }
/// Parse from the lifecycle controller's `JACQUARD_E2E_PROVIDER`. pub fn from_name(name: &str) -> Option<Self> { match name { "tranquil" => Some(Self::Tranquil), "reference" => Some(Self::Reference), "jetstream" => Some(Self::Jetstream), _ => None, } }
/// Deterministic fixture identity for this provider. DIDs, handles, and /// emails are distinct per provider so concurrent runs cannot cross-wire /// resolver caches. None of them touch PLC. The Tranquil DID rides /// Tranquil's `localhost`-prefix HTTP exception (see /// [`TRANQUIL_IDENTITY_DID`]). pub const fn primary_identity(&self) -> FixtureIdentity { match self { Self::Tranquil => FixtureIdentity { did: TRANQUIL_IDENTITY_DID, handle: "primary.tranquil.jacquard-e2e.test", email: "primary@tranquil.jacquard-e2e.test", }, Self::Reference => FixtureIdentity { did: "did:web:reference-identity.jacquard-e2e.test", handle: "primary.reference.jacquard-e2e.test", email: "primary@reference.jacquard-e2e.test", }, // Jetstream is not a PDS: no fixture account exists. The // identity satisfies the context shape; jetstream scenarios // use the simulator-seeded DIDs instead. Self::Jetstream => FixtureIdentity { did: "did:web:jetstream.jacquard-e2e.test", handle: "jetstream.jacquard-e2e.test", email: "jetstream@jacquard-e2e.test", }, } }
/// Second deterministic identity, used only by the reference provider for /// authenticated spaces membership boundaries. pub const fn member_identity(&self) -> FixtureIdentity { match self { Self::Tranquil => FixtureIdentity { did: TRANQUIL_MEMBER_DID, handle: "member.tranquil.jacquard-e2e.test", email: "member@tranquil.jacquard-e2e.test", }, Self::Reference => FixtureIdentity { did: "did:web:reference-member.jacquard-e2e.test", handle: "member.reference.jacquard-e2e.test", email: "member@reference.jacquard-e2e.test", }, Self::Jetstream => FixtureIdentity { did: "did:web:jetstream.jacquard-e2e.test", handle: "jetstream.jacquard-e2e.test", email: "jetstream@jacquard-e2e.test", }, } }}
impl fmt::Display for Provider { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.name()) }}
/// A deterministic fixture identity imported into a fresh provider volume.////// Signing material lives as fixture data under `e2e/identities/`; the DID/// document's `#atproto_pds` service always names the owning provider.#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub struct FixtureIdentity { /// The stable `did:web` identifier. pub did: &'static str, /// The account handle. pub handle: &'static str, /// The account email. pub email: &'static str,}
/// Non-secret run coordinates exported by the lifecycle controller.////// Secrets (app passwords, signing keys) never travel through the/// environment; they are read from fixture files whose root the controller/// exports as `JACQUARD_E2E_FIXTURE_ROOT`.#[derive(Debug, Clone, PartialEq, Eq)]pub struct RunCoordinates { /// Unique run id (also the Compose project name and artifact directory). pub run_id: String, /// Provider base URL as seen from the host test process. pub provider_url: String, /// Effective image digest the provider was launched from (recorded by the /// controller after tag resolution or an explicit override). pub effective_digest: String, /// Root directory of fixture data (identities, CA, credentials). pub fixture_root: String, /// Directory for run diagnostics retained on failure. pub artifact_dir: String,}
impl RunCoordinates { /// Read run coordinates from the environment as exported by /// `scripts/e2e.sh`. Every variable is required: a scenario must never /// guess its fixture topology. pub fn from_env() -> Result<Self, String> { let req = |key: &str| std::env::var(key).map_err(|_| format!("missing required env var {key}")); Ok(Self { run_id: req("JACQUARD_E2E_RUN_ID")?, provider_url: req("JACQUARD_E2E_PROVIDER_URL")?, effective_digest: req("JACQUARD_E2E_EFFECTIVE_DIGEST")?, fixture_root: req("JACQUARD_E2E_FIXTURE_ROOT")?, artifact_dir: req("JACQUARD_E2E_ARTIFACT_DIR")?, }) }}
/// Fully resolved provider context for one scenario run.#[derive(Debug, Clone)]pub struct ProviderContext { /// The provider fixture. pub provider: Provider, /// The provider's stable primary identity. pub identity: FixtureIdentity, /// Run coordinates from the lifecycle controller. pub coordinates: RunCoordinates,}
impl ProviderContext { /// Resolve the provider context from lifecycle environment variables. pub fn from_env() -> Result<Self, String> { let provider = Provider::from_name( &std::env::var("JACQUARD_E2E_PROVIDER") .map_err(|_| "missing required env var JACQUARD_E2E_PROVIDER")?, ) .ok_or_else(|| "unknown JACQUARD_E2E_PROVIDER".to_string())?;
Ok(Self { provider, identity: provider.primary_identity(), coordinates: RunCoordinates::from_env()?, }) }}