You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.9 KiB

+++ title = "Implement generate_id() in src/lib.rs — UUID v4 for WASM-compatible quote IDs" priority = 8 status = "done" ticket_type = "task" dependencies = [] +++

Resolved from TRIAGE ticket 6f2e18. The `nanoid` crate is not suitable for wasm32-unknown-unknown because it depends on `rand`, which relies on thread-local RNG — unavailable in WASM. The safe, WASM-compatible choice is UUID v4 via the `uuid` crate.

On the wasm32 target, uuid's v4 feature depends on getrandom, which requires the wasm_js feature (renamed from js in getrandom 0.2; uuid 1.21+ requires getrandom ^0.4) to source entropy from the Web Crypto API (crypto.getRandomValues()). This must be declared as a direct dependency in the application's Cargo.toml at the wasm32 cfg section.

UUID v4 produces 36-character hyphenated strings (e.g. 550e8400-e29b-41d4-a716-446655440000). The design doc originally specified NanoID (~21 chars); UUID v4 is slightly longer but universally supported and zero-risk on the Workers target. The DB schema comment should be updated accordingly.

Add a `generate_id()` public function to `src/lib.rs` that: - Returns a new UUID v4 as a `String` - Compiles correctly for both the native host target AND `wasm32-unknown-unknown` - Has a rustdoc comment with a doc-example (which also serves as a doctest)

1. Cargo.toml changes

Add uuid to the shared (all-targets) dependencies section:

[dependencies]
uuid = { version = "1", features = ["v4", "serde"] }

Add getrandom with the wasm_js feature under the wasm32 cfg section (so native builds don't pull in wasm-bindgen). uuid 1.21+ requires getrandom ^0.4; getrandom 0.4 renamed the js feature to wasm_js. Also shared with the passphrase generator (ticket 03bb91 / TRIAGE 6ed325):

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.4", features = ["wasm_js"] }

2. src/lib.rs — generate_id()

/// Generates a new UUID v4 string for use as a database primary key.
///
/// Returns a 36-character hyphenated UUID string. Compatible with both
/// native and `wasm32-unknown-unknown` targets (uses Web Crypto API via
/// `getrandom/wasm_js` on WASM).
///
/// # Examples
///
/// ```
/// let id = quotesdb::generate_id();
/// assert_eq!(id.len(), 36);
/// assert_eq!(id.chars().filter(|&c| c == '-').count(), 4);
/// ```
pub fn generate_id() -> String {
    uuid::Uuid::new_v4().to_string()
}

3. Callers

  • PUT /api/quotes handler (ticket 05f8ae): call generate_id() to produce the new quote's id
  • No other callers at this stage

4. DB schema comment update

In docs/plans/2026-02-27-quotesdb-design.md and CLAUDE.md design reference, update the schema comment from:

id  TEXT  PRIMARY KEY,   -- NanoID (~21 chars)

to:

id  TEXT  PRIMARY KEY,   -- UUID v4 (36 chars), generated by generate_id()
- `generate_id()` must be in `src/lib.rs` (shared code, not bin-specific) - UUID v4 is the only correct choice — do NOT use `nanoid`, `rand::thread_rng`, or any crate that pulls in thread-local RNG primitives for WASM - `getrandom = { version = "0.4", features = ["wasm_js"] }` must be in the wasm32 cfg section only, not in `[dependencies]`, to avoid pulling wasm-bindgen into native builds - Do NOT use getrandom 0.2 or the old `js` feature name — uuid 1.21+ requires getrandom ^0.4 - All public items must have rustdoc comments (per project style) Use `superpowers:test-driven-development` — write a unit test verifying length (36) and hyphen count (4) before implementing. Use `superpowers:verification-before-completion` before closing. Run in order from the `quotesdb/` directory:
cargo fmt
cargo check
cargo clippy
cargo test
`feat(quotesdb): add generate_id() using UUID v4 — WASM-compatible ID generation`