Standalone backlog (split out of #319, closed as interop-complete). This is a refinement / tech-debt item, not a client-interop gap.
What
The NIP-55 batch path enforces MAX_BATCH_SIZE (20) in two places: the Rust handle_batch_request and the Kotlin Nip55Activity accumulation loop. The constant is duplicated and must be kept in sync — a minor RMP-boundary drift (the cap is policy and should live solely in Rust).
Why it exists
keep-android does NOT call the bulk handle_batch_request; it runs a Kotlin loop calling handleRequest per request, because each sign_event needs a per-request preApproveNostrEvent interleave (a separate keep-mobile call) before signing, plus per-request permission-grant + audit. The bulk Rust entry point has no hook for that interleave, so the loop (and thus the cap) lives Kotlin-side.
Proposed fix (when revisited)
Fold the per-request preApprove into a Rust batch entry point so the whole loop — preApprove + handle_request + per-request grant + the MAX_BATCH_SIZE cap — lives in handle_batch_request. Android would then call one Rust function and only render the multi-event approval + run the biometric gate. Removes the duplicated constant and makes Rust the sole owner of batch policy.
Priority
Low. The duplication is documented in #320; the batch path is correct and bounded today. This is purity/maintainability, not a bug.
Standalone backlog (split out of #319, closed as interop-complete). This is a refinement / tech-debt item, not a client-interop gap.
What
The NIP-55 batch path enforces
MAX_BATCH_SIZE(20) in two places: the Rusthandle_batch_requestand the KotlinNip55Activityaccumulation loop. The constant is duplicated and must be kept in sync — a minor RMP-boundary drift (the cap is policy and should live solely in Rust).Why it exists
keep-android does NOT call the bulk
handle_batch_request; it runs a Kotlin loop callinghandleRequestper request, because eachsign_eventneeds a per-requestpreApproveNostrEventinterleave (a separate keep-mobile call) before signing, plus per-request permission-grant + audit. The bulk Rust entry point has no hook for that interleave, so the loop (and thus the cap) lives Kotlin-side.Proposed fix (when revisited)
Fold the per-request preApprove into a Rust batch entry point so the whole loop — preApprove + handle_request + per-request grant + the
MAX_BATCH_SIZEcap — lives inhandle_batch_request. Android would then call one Rust function and only render the multi-event approval + run the biometric gate. Removes the duplicated constant and makes Rust the sole owner of batch policy.Priority
Low. The duplication is documented in #320; the batch path is correct and bounded today. This is purity/maintainability, not a bug.