Status: Accepted Date: 2026-02-16 Authors: OSHUN Platform Engineering, OSHUN Mobile Engineering, OSHUN Web Engineering Reviewers: Domain Leads (Tara, Veritas, Nyx, Arete) Supersedes: N/A Superseded by: N/A
Context and Problem Statement#
OSHUN must remain useful under intermittent or absent network conditions across:
- mobile (iOS/Android)
- website/PWA
Repository evidence shows strong but fragmented offline approaches:
- Tara web SW uses cache-first for static/audio and network-first for navigation.
- Veritas web includes service worker caching plus background sync queue patterns.
- Nyx PWA uses Workbox runtime caching (
NetworkFirstAPI,CacheFirstassets/fonts/images) and local data persistence. - Veritas mobile has offline article cache + sync queue + eviction logic.
- Tara mobile includes queue-driven download manager and storage controls.
We need one OSHUN policy for what to cache, how to sync writes, and how to handle failures safely.
Decision Drivers#
- Reliability for core shell journeys during connectivity loss.
- Consistency across mobile and web/PWA behavior.
- Safety for write operations and conflict handling.
- Performance through predictable caching and prefetch policies.
- Storage discipline on constrained mobile devices.
- Observability for offline failure and recovery behavior.
Considered Options#
Option 1: Network-Only Dynamic Data, Minimal Offline#
Description: cache static assets only; all dynamic content requires network.
Pros:
- ✅ Lowest complexity
- ✅ Minimal cache invalidation risk
Cons:
- ❌ Poor user experience in weak connectivity
- ❌ Shell feels fragile in daily mobile contexts
- ❌ Misses key OSHUN reliability goals
Option 2: Cache-First for Most Data#
Description: aggressive cache-first for static and dynamic data.
Pros:
- ✅ Very fast perceived loads
- ✅ More content available offline
Cons:
- ❌ High staleness risk for time-sensitive data
- ❌ Complex invalidation and consistency issues
- ❌ Risky for personalized/entitled content
Option 3: Hybrid Policy - Cache-First Static, Network-First Dynamic (Chosen)#
Description: static assets use cache-first; dynamic personalized/API data uses network-first with stale fallback; write operations queue offline and sync later.
Pros:
- ✅ Strong balance of freshness and resilience
- ✅ Aligns with proven patterns already in repo
- ✅ Better control over stale-data risk
- ✅ Clear policy matrix for implementation and QA
Cons:
- ❌ Requires robust sync queue/conflict handling
- ❌ More moving parts than minimal offline strategy
Decision Outcome#
Chosen option: Option 3 - hybrid offline strategy.
Normative Cache Policy Matrix#
| Data Class | Examples | Strategy | Notes |
|---|---|---|---|
| Static shell assets | JS/CSS/fonts/icons/manifest | CacheFirst |
Versioned, immutable cache keys |
| Navigation documents | shell routes | NetworkFirst + offline fallback |
return cached/offline page on failure |
| Dynamic API read data | home/activity/search/domain cards | NetworkFirst + stale fallback |
short TTL and explicit staleness metadata |
| Media | audio/images/star maps/downloads | CacheFirst or managed download cache |
entry caps + eviction required |
| Auth/session endpoints | login/refresh/logout/entitlements | NetworkOnly |
never served from cache |
| Mutating writes | save/unsave, settings, check-ins | queue offline + replay | idempotency required |
Offline Write Queue Rules (Mandatory)#
- Queue all non-destructive writes when offline.
- Each queued op includes:
- stable operation id
- operation type
- payload
- creation time
- retry count
- Replay on reconnect with exponential backoff + jitter.
- Stop retry after max attempts and surface recoverable UI state.
- Queue processor must be idempotent-safe to prevent duplicate side effects.
Conflict Resolution Rules#
- Default strategy: server-authoritative merge for shared resources.
- Local optimistic state must rollback on authoritative rejection.
- For preference toggles, last-write-wins with server timestamp.
- For list toggles (save/unsave), de-duplicate by operation id and latest intent.
Storage and Eviction Rules#
- Define per-platform cache budgets and hard ceilings.
- Evict using policy by class:
- media: LRU with bookmark/pin protections where applicable
- feed/API cache: TTL-based purge + LRU fallback
- Display user-visible storage usage and allow manual cleanup actions.
Prefetch Rules#
- Prefetch only on adequate connection (prefer Wi-Fi, respect data saver).
- Prioritize:
- continue/resume items
- recently used domain surfaces
- user-saved critical content
- Abort/limit prefetch when offline, low battery, or constrained network.
UX and Product Rules#
- Always show global online/offline state indicator in shell.
- For stale fallback content, show freshness timestamp.
- Provide explicit retry actions on failed fetch/sync.
- Never silently drop user write actions.
Platform Implementation Guidance#
Mobile#
- Use managed local stores (AsyncStorage/SQLite/file system) by data class.
- Use queued sync for write actions and media download manager for offline media.
- Persist sync queue across app restarts.
Web/PWA#
- Use service worker strategies per matrix.
- Use IndexedDB for offline data models and sync queues.
- Use Background Sync where supported; fallback to foreground replay.
Existing Pattern Alignment#
- Aligns with Tara web SW strategy for static/nav split.
- Aligns with Veritas web sync-manager queue model.
- Aligns with Nyx Workbox runtime caching patterns.
- Aligns with Veritas mobile offline cache + queue + eviction pattern.
Implementation Plan#
Phase 1: Policy and Contracts#
- Define
libs/oshun/offlinepolicy APIs and cache classes. - Define queue item schema and sync result taxonomy.
- Define per-endpoint cache classification.
Phase 2: Shell Integration#
- Integrate global offline status and retry UX in shell.
- Integrate queue persistence and replay orchestration.
- Integrate stale-data indicators for fallback reads.
Phase 3: Hardening#
- Add cache budget enforcement and eviction diagnostics.
- Add conflict resolution integration tests.
- Add partial-outage and airplane-mode scenario tests.
Phase 4: Observability#
- Emit offline/sync events for dashboarding.
- Add alerts for queue growth, replay failures, and stale fallback spikes.
Success Metrics#
- Core shell routes render with meaningful fallback in offline mode.
- Queue replay success rate >= 98% after reconnection.
- No silent write loss for queued operations.
- Cache growth remains within configured budgets across target devices.
- Offline-to-online recovery latency meets UX SLA.
Consequences#
Positive Consequences#
- ✅ Stronger reliability for real-world network conditions.
- ✅ Consistent offline behavior across mobile and web/PWA.
- ✅ Explicit and testable policy for caching and sync.
- ✅ Better trust via visible state/retry/fallback behavior.
Negative Consequences#
- ❌ Higher implementation complexity (queue + conflict logic).
- ❌ More QA permutations (network/state/storage combinations).
- ❌ Ongoing tuning needed for cache and prefetch budgets.
Risks and Mitigations#
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Stale data shown too long | Medium | Medium | TTL + staleness indicators + refresh triggers |
| Queue replay duplicates writes | Medium | High | idempotency keys + server dedupe |
| Cache pressure on low-storage devices | Medium | Medium | strict budgets + LRU + user cleanup controls |
| Offline logic drift across platforms | Medium | High | shared policy contracts in libs/oshun/offline |
Security and Compliance#
- Do not cache sensitive auth/session responses.
- Encrypt or protect sensitive local data where required by policy.
- Respect user consent/privacy settings in offline telemetry collection.
Monitoring and Observability#
Track:
- offline entry/exit events
- cache hit/miss rates by data class
- queue depth and replay outcomes
- conflict resolution outcomes
- fallback-render counts and stale age distributions
Related Decisions#
docs/adr/ADR-0014-oshun-web-and-pwa-strategy.mddocs/adr/ADR-0016-shared-identity-and-cross-domain-session-model.md
References#
apps/tara/web/public/sw.jsapps/veritas/web/public/sw.jsapps/veritas/web/src/lib/offline/sync-manager.tsapps/nyx/mobile/vite.config.tsapps/veritas/mobile/src/services/offline.tsapps/tara/mobile/src/services/download.ts