# AGENTS.md This file documents how AI agents should interact with this Rust codebase for the CCC (Copious Cipher Chain) cryptography system. ## Project Overview A multi-crate Rust workspace providing cryptographic primitives (AEAD, KDF, MAC, Hash, KEM) via pluggable providers (currently wolfSSL/wolfCrypt). The project targets mobile platforms (iOS, Android, macOS) and interoperates with a Dart/Flutter frontend via FFI. **Workspace members:** - `crates/ccc-crypto-core` — Core types, traits, algorithm enums, registry - `crates/ccc-crypto-wolfssl` — wolfSSL provider implementation - `tests/conformance` — Conformance test binary with NIST/RFC vectors ## Build and Test Commands ### Basic commands ```sh # Run all tests across workspace cargo test --workspace # Run tests for a specific package cargo test -p ccc-crypto-core cargo test -p ccc-crypto-wolfssl # Run conformance tests (binary) cargo run -p ccc-conformance-tests # Build for specific target (aliases defined in .cargo/config.toml) cargo build-ios cargo build-android-arm64 cargo build-macos-arm64 cargo build-all-apple ``` ### Running a single test ```sh # Run all tests matching a string pattern cargo test --workspace # Example: run only KEM-related tests cargo test --workspace kem # Run specific test function cargo test --workspace test_function_name # Compile without running cargo test --workspace --no-run ``` ### Linting and formatting ```sh # Format code (uses rustfmt from rust-toolchain.toml) cargo fmt # Check for clippy warnings cargo clippy --workspace -- -D warnings # Combined check cargo fmt --check && cargo clippy --workspace -- -D warnings ``` ## Code Style Guidelines ### Imports and module organization 1. **Standard library first** — `use std::...` before workspace crates 2. **Workspace/crate imports second** — `use ccc_crypto_core::...` or `use crate::...` 3. **External dependencies last** — third-party crates from `[dependencies]` 4. **Group related items** — use parentheses to group multi-line imports: ```rust use ccc_crypto_core::{ algorithms::{AeadAlgorithm, HashAlgorithm}, error::CryptoError, types::{KemKeyPair, KemEncapResult}, }; ``` ### File structure and documentation 1. **Module headers** — Every `.rs` file starts with a `//!` doc comment explaining its purpose 2. **Section separators** — Use ASCII art dividers (`// ─────────────`) to separate logical sections 3. **Public APIs** — Document all public items with `///` comments; use `# Parameters`, `# Returns`, `# Errors` where applicable 4. **Algorithm constants** — When defining enum discriminants, comment the matching Dart constant value: ```rust /// AES-256-GCM. Dart constant `12`. AesGcm256 = 12, ``` ### Naming conventions - **Types**: PascalCase (`CryptoError`, `ProviderCapabilities`, `WolfSslProvider`) - **Functions/methods**: snake_case (`encrypt_aead`, `derive_key`, `from_u32`) - **Modules**: snake_case (`algorithms`, `capabilities`, `error`) - **Constants/enum variants**: PascalCase with full names (`AesGcm256`, `MlKem768`) - **Private items**: Prefix with underscore if needed for clarity (`_unused_var`) ### Type system and generics 1. Prefer `Result` over `panic!` for recoverable errors 2. Use `#[repr(u32)]` on enums that cross FFI boundaries (match Dart `int` values) 3. Mark sensitive data with `zeroize::Zeroize` / `ZeroizeOnDrop`: ```rust #[derive(Zeroize, ZeroizeOnDrop)] pub struct KemKeyPair { ... } ``` 4. Use `OnceLock` for lazy-initialized singleton-like state ### Error handling 1. **Use `thiserror`** — Define error enums with `#[derive(Error)]`: ```rust #[derive(Debug, Error)] pub enum CryptoError { #[error("unsupported algorithm: {0}")] UnsupportedAlgorithm(String), #[error("authentication failed")] AuthenticationFailed, // Do not leak details to users } ``` 2. **Authentication failures** — Surface only `AuthenticationFailed` to end users; never leak raw error details 3. **Internal errors** — Use `InternalError(String)` for unexpected library errors with diagnostics ### Formatting rules 1. **Max line length**: 100 characters (rustfmt default) 2. **Brace style**: Allman/stroustrup hybrid — opening brace on same line for items, next line for blocks 3. **Single-line matches** — Keep simple match arms on one line when concise 4. **Multi-line chains** — Use `.` at start of continuation lines: ```rust let result = provider .encrypt_aead(algo, key, nonce, plaintext, aad)? .to_hex(); ``` ### Testing conventions 1. **Test vectors as static slices** — Define test data in `static` arrays with clear naming (`AEAD_VECS`, `KDF_VECTORS`) 2. **Cross-provider conformance** — Tests should verify identical output across different providers 3. **NIST/RFC references** — Comment the source of each vector (e.g., "RFC 8439 §2.8.2") ### Platform-specific code 1. Use conditional compilation for platform differences: `#[cfg(target_os = "...")]` 2. Linker flags and build scripts should be in `.cargo/config.toml` or `build.rs` 3. Document target-specific behavior in module headers ## Important Notes - **Dart compatibility**: All algorithm discriminant values (`#[repr(u32)]`) must match constants in `cipher_constants.dart`. Changing them requires coordinated changes across Rust and Dart codebases. - **Wire format consistency**: Output byte layouts (e.g., `ciphertext || tag` for AEAD) must match the Dart implementation exactly for conformance tests to pass. - **Security-sensitive data**: Always use `zeroize` types for keys, nonces, and shared secrets; never log raw cryptographic material. ## Existing Rules No `.cursor/rules/`, `.cursorrules`, or `.github/copilot-instructions.md` files exist in this repository. Follow the conventions documented above.