- Generated Kanban markdown file adhering to tasks/GUIDELINES.md. - Documented requirements for SIMD, Deno FFI non-blocking bindings, and `hash-wasm` alternatives. - Specified development/production fallback strategies. Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
4.1 KiB
4.1 KiB
TASK METADATA
- Target Files:
spire_ffi/Cargo.toml,spire_ffi/src/lib.rs,server/spire_ffi.ts,server/spire_ffi.test.ts - Core Objective: Implement high-throughput native Argon2id derivation (12 iterations, 64 MiB memory, 128-bit salt, 256-bit output key) via the
spire_ffiRust crate to accelerate zero-knowledge hashing. - Dependencies: The Deno application must be able to compile or load the Rust dynamic library (
libspire_ffi.so/spire_ffi.dll/libspire_ffi.dylib). - Additional Important Notes: Fallback behavior for local dev/testing must mimic the existing pattern in
spire_ffi.ts, returning deterministic mock data when the library is unavailable, but throwing a fatal error in production contexts.
Architectural Considerations & Risks
Risks
- FFI Memory Safety: Exposing a new C-compatible function via FFI (
argon2id_derive) involves raw pointer manipulation. Incorrectly sizing the output buffer, failing to free memory properly, or reading past the bounds of input buffers (password/salt) could lead to segfaults or memory leaks. - Platform Compatibility: Relying on native code means the target environment must support the compiled architecture. The CI/CD pipeline must build the Rust crate for all supported deployment targets (x86_64, aarch64).
- Blocking the Event Loop: Hashing with Argon2id is intentionally slow and CPU-intensive. If the Deno FFI call is blocking, it will stall the Deno event loop. The FFI function must be marked as
nonblocking: trueinDeno.dlopen, and the Rust implementation must be executed asynchronously or off the main thread.
Alternatives
- WASM (e.g.,
hash-wasm): An alternative is to use WebAssembly to perform the hashing directly in Deno without FFI.- Justification against: Native SIMD provides 3–5x greater throughput compared to V8 WebAssembly for 64 MiB memory-hard hashing. Furthermore, we already have and maintain the
spire_ffiRust workspace. Avoiding a new npm dependency keeps the server and@auth-yes/sdkzero-dependency, adhering to our core architectural goals.
- Justification against: Native SIMD provides 3–5x greater throughput compared to V8 WebAssembly for 64 MiB memory-hard hashing. Furthermore, we already have and maintain the
Proposed Implementation
1. Update Rust Dependencies
- Add the
argon2crate tospire_ffi/Cargo.toml:[dependencies] argon2 = { version = "0.5", features = ["std"] } - Note on SIMD: Version 0.5.x automatically uses runtime CPU feature detection (e.g.,
std::is_x86_feature_detected!("avx2")). For portable builds, use standardcargo build --release. For optional optimized container builds, document the use ofRUSTFLAGS="-C target-cpu=native" cargo build --release.
2. Implement Rust FFI Export
- In
spire_ffi/src/lib.rs, create a new#[no_mangle]extern "C" function namedargon2id_derive. - The function signature should accept pointers and lengths for the password and salt, iteration count, memory size (in KB), and a pointer/length for the output buffer.
- Use the
argon2crate to compute the hash and write the result into the provided output buffer. Ensure all FFI safety boundaries are respected (e.g., checking for null pointers).
3. Expose via Deno FFI (server/spire_ffi.ts)
- Add the
argon2id_derivesymbol to theDeno.dlopendefinition. Critically, setnonblocking: trueto prevent stalling the Deno event loop during hash computation. - Create an exported async function
deriveArgon2idKey(password: Uint8Array, salt: Uint8Array): Promise<Uint8Array>. - Hardcode the security parameters: 12 iterations, 64 MiB (65536 KB) memory, and a 32-byte (256-bit) output key length.
- Implement the fallback pattern: If
dylibis null, log[SPIRE FFI] Dynamic library (...) is not loaded. Mocking Argon2id derivation for local development.and return a deterministic 32-byte mock buffer (e.g., filled with a repeating pattern).
4. Write Unit Tests
- In
server/spire_ffi.test.ts, write tests to ensure:- The fallback mechanism works when the library isn't loaded (returns the mock buffer).
- When the library is available, the function successfully returns a 32-byte Uint8Array.
- (Optional) Verify the output matches a known standard Argon2id test vector to confirm correctness across the FFI boundary.