Problem
replicant_enroll_request / replicant_enroll_claim are synchronous blocking calls (connect timeout ~10s, request timeout ~30s). Consumers calling from a UI thread stall the UI for the duration; today every consumer must spawn its own thread around a library primitive.
Enrollment is a replicant-protocol operation (endpoints, token exchange, credential format are all the library's contract), so the concurrency belongs in the library — consumers should only have to marshal the completion to their own thread.
Design (agreed 2026-07-14)
- Add additive (non-breaking) async variants alongside the sync ones:
replicant_enroll_request_async(base_url, email, cb, ctx)
replicant_enroll_claim_async(base_url, email, token, cb, ctx)
- Internally reuse the existing dedicated-thread + runtime-guard machinery the sync paths already use; invoke the completion callback instead of returning.
- Threading contract (document loudly): unlike the Client event callbacks (which fire on the consumer-pumped event thread), these fire on a lib-owned worker thread — necessarily, since enrollment runs before any
Client/event pump exists. Consumers marshal to their UI thread themselves.
- Callback carries the same result surface as the sync versions (status/error + credentials out for claim);
ctx lifetime rules documented (must outlive the call; no cancellation in v1 — the existing timeouts bound the wait).
- Update
include/replicant.hpp and the JUCE wrapper; regenerate replicant.h with the pinned cbindgen.
Consumer side
entonal-common TonalDB will wrap these into std::function<void(Result)> completions marshalled onto its message thread (tracked in the Entonal Studio Linear project). The BLOCKING doc comments on TonalDB's enrollment API mark the current behaviour.
https://claude.ai/code/session_01GwMbERgLK4KAuLrz4b4Liw
Problem
replicant_enroll_request/replicant_enroll_claimare synchronous blocking calls (connect timeout ~10s, request timeout ~30s). Consumers calling from a UI thread stall the UI for the duration; today every consumer must spawn its own thread around a library primitive.Enrollment is a replicant-protocol operation (endpoints, token exchange, credential format are all the library's contract), so the concurrency belongs in the library — consumers should only have to marshal the completion to their own thread.
Design (agreed 2026-07-14)
replicant_enroll_request_async(base_url, email, cb, ctx)replicant_enroll_claim_async(base_url, email, token, cb, ctx)Client/event pump exists. Consumers marshal to their UI thread themselves.ctxlifetime rules documented (must outlive the call; no cancellation in v1 — the existing timeouts bound the wait).include/replicant.hppand the JUCE wrapper; regeneratereplicant.hwith the pinned cbindgen.Consumer side
entonal-common TonalDB will wrap these into
std::function<void(Result)>completions marshalled onto its message thread (tracked in the Entonal Studio Linear project). The BLOCKING doc comments on TonalDB's enrollment API mark the current behaviour.https://claude.ai/code/session_01GwMbERgLK4KAuLrz4b4Liw