high priority low complexity infrastructure pending backend specialist Tier 1

Acceptance Criteria

SearchDebounceUtility constructor accepts named parameters: debounceDelay (Duration, default 300ms) and minQueryLength (int, default 2)
Passing debounceDelay: Duration(milliseconds: 500) results in the debounced stream only emitting 500ms after the last input
Passing minQueryLength: 3 filters out strings of length 0, 1, and 2; strings of length 3+ pass through
debouncedOutput is typed as Stream<String> — no dynamic or Object types in the public API
Calling dispose() when no subscription has been created (i.e., debouncedOutput was never listened to) does not throw
Calling dispose() twice does not throw a StateError or double-cancel exception
After dispose(), the debouncedOutput stream is closed (done = true)
All existing unit tests from task-001 continue to pass with the new configurable constructor
New unit tests cover: custom delay, custom minQueryLength, double-dispose safety

Technical Requirements

frameworks
rxdart
flutter_test
fake_async
apis
dart:async StreamController
StreamSubscription.cancel()
performance requirements
No additional allocations beyond the single internal StreamController and subscription
dispose() must complete synchronously (no async gaps)
security requirements
No query string persistence inside the utility class

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use Dart named parameters with defaults for the constructor — avoid positional parameters to prevent breaking callers when adding future parameters. The Duration type makes the debounceDelay parameter self-documenting (caller writes Duration(milliseconds: 500) not a raw int). For dispose() idempotency, guard with a bool _disposed flag and early-return if already disposed. If using rxdart Subject, calling close() on an already-closed Subject throws — check isClosed before closing.

Consider adding an assert(!_disposed, 'SearchDebounceUtility used after dispose') in debug mode to help catch lifecycle errors during development, while still being safe in production.

Testing Requirements

Extend the existing unit test file. Add parametrised tests using test() with different constructor arguments. Test double-dispose safety with expect(() => utility.dispose(), returnsNormally). Test that debouncedOutput.isBroadcast or behaviour matches the documented contract (single-subscription vs broadcast — document and test the choice).

Test that listening to debouncedOutput after dispose() throws or returns an immediately closed stream (document and test the chosen behaviour).

Component
Search Debounce Utility
infrastructure low
Epic Risks (2)
medium impact medium prob technical

Cancelling in-flight Supabase HTTP requests via RxDart switchMap may not actually abort the server-side query if the Supabase Dart client does not support request cancellation tokens, leading to wasted API calls and potential race conditions where a slow earlier response arrives after a faster later one.

Mitigation & Contingency

Mitigation: Audit the supabase-flutter client's cancellation support before implementation. Use RxDart switchMap to discard stale emissions even if HTTP cancellation is unavailable, ensuring only the latest result reaches the UI.

Contingency: If race conditions surface in testing, add a query sequence counter to tag each emission and discard any response whose sequence number is lower than the most recently emitted one.

medium impact low prob technical

Connectivity detection used to route between online and offline repositories may have latency or give false positives on flaky connections, causing the service to attempt Supabase queries that time out instead of falling back to the cache promptly.

Mitigation & Contingency

Mitigation: Use a try/catch with a short timeout on Supabase calls. On network error, immediately fall back to the offline repository and emit a cached result with an offline indicator rather than surfacing an error state.

Contingency: If the timeout-based fallback proves insufficient, implement a connection health check stream that pre-validates connectivity before each query batch.