MOB-02 — Core package — HTTP client, interceptors, errors, storage, logging
hoco_core: flavor config, dio with auth/locale/app-version/Idempotency-Key interceptors, error-envelope mapping, secure storage, connectivity, Sentry.
| Field | Details |
|---|---|
| Task code | MOB-02 |
| Phase | P0 — Foundations (cadrage, UX/UI, architecture & contract) |
| Product scope | V1 |
| Status | Planned |
| Start | Mon 19 Oct 2026 |
| Due | Mon 19 Oct 2026 |
| Responsible | Imad — Mobile developer (Flutter) |
| Co-responsible | — |
| Effort | 1 person-day(s) planned · 4 from scratch · size S |
| Area · app | Mobile foundation · mobile |
| Depends on | MOB-01 |
| Unblocks | MOB-03 |
| Milestones | — |
Summary
hoco_core: flavor config, dio with auth/locale/app-version/Idempotency-Key interceptors, error-envelope mapping, secure storage, connectivity, Sentry.
Description
Every feature in both apps must send the same headers, authenticate the same way and turn the server's error envelope into the same typed failures, so this logic lives once in hoco_core. Scope: flavor config, a dio factory with interceptors for Authorization: Bearer, Accept-Language, X-App-Version, X-App-Platform, X-Device-Id and Idempotency-Key, mapping of { error: { code, message, details, requestId } } to a sealed ApiFailure, secure session storage, connectivity, logging and Sentry. Feature repositories and generated clients are out of scope (MOB-03). It needs the error-code registry and auth contract from Anis (SRV-03, SRV-05); nothing from Akram. MOB-03 plugs the generated client onto this dio instance, MOB-05 listens to its 426/503 streams, and MOB-09 reuses its idempotency helpers for the outbox.
Subtasks
| # | Subtask | Owner |
|---|---|---|
| 1 | FlavorConfig and Env (apiBaseUrl, sentryDsn, flavor, contract version) loaded from dart-define, exposed as a Riverpod provider | Imad |
| 2 | HocoDio factory: base URL …/v1, connect 10 s / receive 30 s timeouts, retry only for GETs and for mutations that carry an Idempotency-Key (3 attempts, exponential backoff, on network errors, 502, 503, 504) | Imad |
| 3 | ClientHeadersInterceptor: Accept-Language (fr default, ar, en), X-App-Version from package_info_plus, X-App-Platform android|ios, X-Device-Id (UUIDv7 generated once and kept in secure storage) | Imad |
| 4 | SessionStore on flutter_secure_storage (sessionToken, expiresAt, userType) and AuthInterceptor adding the bearer token; 401 UNAUTHENTICATED clears the store and emits AuthEvent.signedOut | Imad |
| 5 | Idempotency helpers: UUIDv7 generator and a request option that pins one key per user action so retries reuse it; Idempotent-Replayed: true treated as success | Imad |
| 6 | Sealed ApiFailure (network, timeout, unauthenticated, forbidden(code), notFound, conflict(code), businessRule(code, details), validation(fieldErrors), rateLimited(retryAfter), upgradeRequired(storeUrl), maintenance(until), server) mapped from the error envelope with requestId kept | Imad |
| 7 | App-wide event streams for 426 UPGRADE_REQUIRED and 503 MAINTENANCE consumed by the router (MOB-05) | Imad |
| 8 | ConnectivityService: connectivity_plus plus a reachability probe on GET /app-config, exposed as a StreamProvider used by offline banners and the outbox | Imad |
| 9 | Sentry (sentry_flutter + sentry_dio): one project per app, environment = flavor, release = version+build, requestId tag, beforeSend scrubbing Authorization, tokens, phone numbers and OTPs | Imad |
| 10 | Logger with redaction; verbose HTTP logging only in the dev flavor | Imad |
Deliverables
- packages/hoco_core/lib/src/config/, http/, errors/, storage/, connectivity/, observability/
- packages/hoco_core/test/ with interceptor and error-mapping tests
- Sentry projects hoco-reseller and hoco-delegate with dev/staging/prod environments
Acceptance criteria
- Every request carries Accept-Language, X-App-Version, X-App-Platform and X-Device-Id; authenticated requests carry the bearer token (AUTH-06)
- X-Device-Id stays the same across restarts and changes only after reinstall
- A 401 UNAUTHENTICATED clears the stored session and routes to sign-in; a 426 UPGRADE_REQUIRED raises the forced-update event with details.storeUrl
- Envelope codes such as ORDER_MIN_AMOUNT_NOT_MET or GPS_OUT_OF_TOLERANCE reach the UI as typed failures with the localised message and requestId
- A retried mutation reuses its Idempotency-Key; 409 IDEMPOTENCY_KEY_REUSED is surfaced and never retried; 409 IDEMPOTENCY_IN_PROGRESS is retried after 1 s (SYN-05)
- No session token, OTP or phone number appears in Sentry events or logs (NFR-08)
Requirements covered
| Requirement | Title | Release |
|---|---|---|
| AUTH-06 | Sessions: expiry, multi-device, listing and revocation, sign-out | V1 |
| NFR-08 | Logging of sensitive actions and technical errors; monitoring and alerting | V1 |
| SYN-05 | Sync queue handling retries, duplicates (idempotency), errors and conflicts | V1 |
API surface
| Endpoint group | Operations |
|---|---|
| Authentication & sessions | 10 |
| Me, devices, app config & reference data | 9 |
Test measures
- Unit tests with http_mock_adapter for each interceptor and each ApiFailure class
- Unit test that a POST without Idempotency-Key is never auto-retried
- Unit test of the Sentry beforeSend scrubber on a captured request with Authorization and phone fields
Risks
- Secure-storage keys lost on some Android OEMs after backup/restore — disable backup and treat unreadable storage as signed out instead of crashing
KPI
- Delivered by Mon 19 Oct 2026 within 1 person-day(s).
- Every acceptance criterion above demonstrated before hand-off; linked requirements' acceptance criteria pass.
- Zero open critical defects, permission gaps or data-integrity regressions at sign-off.
Generated from content/plan/tasks.json by scripts/generate-team-tasks.mjs. Dates are computed by the scheduler (Sunday–Thursday weeks, holidays excluded) — change the plan, not this page.
MOB-01 — Flutter monorepo — workspace, two apps, flavors, CI
hoco-mobile repo under Imad's account: Dart pub workspace + Melos, apps/reseller and apps/delegate, dev/staging/prod flavors, application ids, signing, lints, GitHub Actions (analyze, test, build APK).
MOB-07 — Localisation & formatting
ARB files (fr now; ar and en scaffolded), RTL-safe layouts, DZD money and date formatting helpers.