diff --git a/tasks/new/2026-0824.01.jul.feat.spire-ffi.native-argon2-0352.md b/tasks/new/2026-0824.01.jul.feat.spire-ffi.native-argon2-0352.md new file mode 100644 index 0000000..e761502 --- /dev/null +++ b/tasks/new/2026-0824.01.jul.feat.spire-ffi.native-argon2-0352.md @@ -0,0 +1,46 @@ +# 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_ffi` Rust 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: true` in `Deno.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_ffi` Rust workspace. Avoiding a new npm dependency keeps the server and `@auth-yes/sdk` zero-dependency, adhering to our core architectural goals. + +## Proposed Implementation + +### 1. Update Rust Dependencies +- Add the `argon2` crate to `spire_ffi/Cargo.toml`: + ```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 standard `cargo build --release`. For optional optimized container builds, document the use of `RUSTFLAGS="-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 named `argon2id_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 `argon2` crate 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_derive` symbol to the `Deno.dlopen` definition. Critically, set `nonblocking: true` to prevent stalling the Deno event loop during hash computation. +- Create an exported async function `deriveArgon2idKey(password: Uint8Array, salt: Uint8Array): Promise`. +- 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 `dylib` is 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. \ No newline at end of file