auths-sdk 0.1.3

Application services layer for Auths identity operations
Documentation
# Duplicated from workspace clippy.toml — keep in sync
# Clippy does NOT merge per-crate configs with workspace config.
# Any changes to the workspace clippy.toml must be replicated here.

allow-unwrap-in-tests = true
allow-expect-in-tests = true

disallowed-methods = [
  # === Workspace rules (duplicated from root clippy.toml) ===
  { path = "chrono::offset::Utc::now", reason = "inject ClockProvider instead of calling Utc::now() directly", allow-invalid = true },
  { path = "std::time::SystemTime::now", reason = "inject ClockProvider instead of calling SystemTime::now() directly", allow-invalid = true },
  { path = "std::env::var", reason = "use EnvironmentConfig abstraction instead of reading env vars directly", allow-invalid = true },
  { path = "uuid::Uuid::new_v4", reason = "Use UuidProvider::new_id() instead. Inject SystemUuidProvider in production and DeterministicUuidProvider in tests." },

  # === DID/newtype construction: prefer parse() for external input ===
  { path = "auths_verifier::types::IdentityDID::new_unchecked", reason = "Use IdentityDID::parse() for external input. Use #[allow(clippy::disallowed_methods)] with INVARIANT comment for proven-safe paths.", allow-invalid = true },
  { path = "auths_verifier::types::CanonicalDid::new_unchecked", reason = "Use CanonicalDid::parse() for external input. Use #[allow(clippy::disallowed_methods)] with INVARIANT comment for proven-safe paths.", allow-invalid = true },
  { path = "auths_verifier::core::CommitOid::new_unchecked", reason = "Use CommitOid::parse() for external input. Use #[allow(clippy::disallowed_methods)] with INVARIANT comment for proven-safe paths.", allow-invalid = true },
  { path = "auths_verifier::core::PublicKeyHex::new_unchecked", reason = "Use PublicKeyHex::parse() for external input. Use #[allow(clippy::disallowed_methods)] with INVARIANT comment for proven-safe paths.", allow-invalid = true },

  # === Sans-IO: filesystem ===
  { path = "std::fs::read", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::read_to_string", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::write", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::create_dir", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::create_dir_all", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::remove_file", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::remove_dir", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::remove_dir_all", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::copy", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::rename", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::metadata", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::read_dir", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::canonicalize", reason = "sans-IO crate — use a port trait" },

  # === Sans-IO: process ===
  { path = "std::process::Command::new", reason = "sans-IO crate — use a port trait" },
  { path = "std::process::exit", reason = "sans-IO crate — return errors instead" },

  # === Sans-IO: dirs ===
  { path = "dirs::home_dir", reason = "sans-IO crate — inject paths via config", allow-invalid = true },
  { path = "dirs::config_dir", reason = "sans-IO crate — inject paths via config", allow-invalid = true },
  { path = "dirs::data_dir", reason = "sans-IO crate — inject paths via config", allow-invalid = true },
  { path = "dirs::data_local_dir", reason = "sans-IO crate — inject paths via config", allow-invalid = true },

  # === Sans-IO: network ===
  { path = "reqwest::Client::new", reason = "sans-IO crate — use a port trait for HTTP", allow-invalid = true },
  { path = "reqwest::get", reason = "sans-IO crate — use a port trait for HTTP", allow-invalid = true },

  # === Curve-agnostic refactor (fn-114) — ban Ed25519-hardcoded APIs ===
  # Removed in fn-114.40 cleanup after all sweeps complete.
  { path = "ring::signature::Ed25519KeyPair::from_pkcs8", reason = "use TypedSignerKey::from_pkcs8 — dispatches on curve.", allow-invalid = true },
  { path = "ring::signature::Ed25519KeyPair::from_seed_unchecked", reason = "use auths_crypto::sign(&TypedSeed, msg).", allow-invalid = true },
  { path = "ring::signature::Ed25519KeyPair::generate_pkcs8", reason = "use inception::generate_keypair_for_init(curve).", allow-invalid = true },
  { path = "ring::signature::UnparsedPublicKey::new", reason = "use DevicePublicKey::verify — dispatches on curve.", allow-invalid = true },
  { path = "auths_crypto::parse_ed25519_seed", reason = "use parse_key_material — returns TypedSeed.", allow-invalid = true },
  { path = "auths_crypto::parse_ed25519_key_material", reason = "use parse_key_material — returns TypedSeed.", allow-invalid = true },
  # === fn-128.T6 RNG discipline ===
  { path = "rand::thread_rng", reason = "use rand::rngs::OsRng for security-sensitive randomness; see docs/security/rng-policy.md", allow-invalid = true },
  { path = "rand::random", reason = "use rand::rngs::OsRng explicitly; rand::random() may delegate to thread_rng.", allow-invalid = true },
]

disallowed-types = [
  { path = "std::fs::File", reason = "sans-IO crate — use a port trait" },
  { path = "std::fs::OpenOptions", reason = "sans-IO crate — use a port trait" },
  { path = "std::process::Command", reason = "sans-IO crate — use a port trait" },
  { path = "std::net::TcpStream", reason = "sans-IO crate — use a port trait" },
  { path = "std::net::TcpListener", reason = "sans-IO crate — use a port trait" },
  { path = "rand::rngs::ThreadRng", reason = "use rand::rngs::OsRng; see docs/security/rng-policy.md" },
]