lum_ccc_rust/.agents/AGENTS.md

5.8 KiB

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

# 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

# Run all tests matching a string pattern
cargo test --workspace <TESTNAME>

# 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

# 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 firstuse std::... before workspace crates
  2. Workspace/crate imports seconduse 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:
    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:
    /// 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<T, CryptoError> 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:
    #[derive(Zeroize, ZeroizeOnDrop)]
    pub struct KemKeyPair { ... }
    
  4. Use OnceLock<T> for lazy-initialized singleton-like state

Error handling

  1. Use thiserror — Define error enums with #[derive(Error)]:
    #[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:
    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.