Status: Accepted Date: 2026-02-16 Authors: OSHUN Product, OSHUN Mobile Engineering, OSHUN Platform Engineering Reviewers: Domain Leads (Tara, Veritas, Nyx, Arete) Supersedes: N/A Superseded by: N/A
Context and Problem Statement#
OSHUN must deliver one cohesive product surface that exposes Tara, Veritas, Nyx, and Arete across:
- iOS and Android via React Native
- web and installable PWA via
apps/oshun/web
Current repository reality creates asymmetric integration constraints:
apps/tara/mobilealready uses Expo Router + React Native.apps/veritas/mobilealready uses Expo Router + React Native.apps/nyx/mobileis currently a Vite-based PWA.libs/arete/*currently provides domain logic libraries without a dedicated Arete mobile app shell.
We need a production architecture that allows:
- fast MVP delivery without rewriting every domain
- consistent UX/navigation from one OSHUN shell
- resilient partial-failure behavior per domain
- clean ownership boundaries between shell and domain teams
Decision Drivers#
- Time-to-value: ship MVP shell quickly with high quality.
- UX consistency: one ergonomic interaction model across domains.
- Reuse: leverage existing Tara/Veritas apps and Arete libraries.
- Resilience: one domain outage must not crash the whole shell.
- Maintainability: avoid tight coupling between shell UI and domain internals.
- Extensibility: support deeper domain integration over time.
- Cross-platform parity: same conceptual model for mobile and web/PWA.
Considered Options#
Option 1: Keep Domains as Separate Apps with Only Deep Links#
Description: OSHUN is effectively a launcher that sends users to standalone apps/sites.
Pros:
- ✅ Minimal integration engineering
- ✅ Domain teams stay fully independent
- ✅ Lowest short-term implementation risk
Cons:
- ❌ Breaks core OSHUN promise (one unified experience)
- ❌ Poor continuity for auth, activity, save, notifications
- ❌ Inconsistent UI/UX and analytics model
- ❌ High context-switch cost for users
Option 2: WebView/Micro-Frontend Embedding as Primary Model#
Description: Embed domain experiences directly (especially Nyx-like web modules) inside shell as the default architecture.
Pros:
- ✅ Fast for web-native modules
- ✅ Single runtime container in shell
- ✅ Can avoid some native rewrites
Cons:
- ❌ Inconsistent native feel and gesture ergonomics
- ❌ Performance/debug complexity across native-web boundaries
- ❌ Offline and instrumentation become fragmented
- ❌ Long-term maintainability risk if used as default for all domains
Option 3: Full Rewrite of All Domain Experiences into a New OSHUN App#
Description: Build all domain UIs and integration logic from scratch inside new OSHUN projects.
Pros:
- ✅ Maximum consistency and architectural purity
- ✅ Full control over every flow
Cons:
- ❌ Highest cost and slowest path to MVP
- ❌ Discards existing mature implementation assets
- ❌ High delivery risk and delayed user feedback loops
Option 4: Single OSHUN Shell + Domain Adapter Pattern (Chosen)#
Description: Build one OSHUN shell and integrate each domain through explicit adapter contracts. Domain adapters normalize domain-specific APIs/models into shell contracts while preserving domain ownership.
Pros:
- ✅ Preserves one-shell user experience
- ✅ Maximizes reuse of existing domain assets
- ✅ Enables incremental delivery per domain
- ✅ Keeps boundaries explicit and testable
- ✅ Supports graceful fallback when a domain is unavailable
Cons:
- ❌ Requires disciplined contract management
- ❌ Requires adapter maintenance when domain APIs evolve
- ❌ Introduces translation layer complexity
Decision Outcome#
Chosen option: Option 4 - Single OSHUN shell with domain adapter contracts.
Decision Summary#
OSHUN will be implemented as:
- One React Native shell app (
apps/oshun/mobile) for iOS + Android. - One web/PWA surface (
apps/oshun/web) aligned to the same shell concepts. - Domain adapters (
libs/oshun/domain-*) that map each domain to common shell contracts. - One domain registry (
libs/oshun/domain-registry) for metadata, capability flags, launch contracts, and availability state. - One shared BFF (
apps/oshun/bff) that aggregates and normalizes cross-domain shell data when needed.
Ownership Boundaries#
- Shell owns:
- navigation model
- shared UX components and design tokens
- unified auth/session orchestration
- shell-level analytics, notifications center, save/activity surfaces
- Domain adapters own:
- translation from domain APIs/models to shell contracts
- domain launch actions and deep-link mappings
- domain-specific fallback behavior mapping
- Domain products own:
- core domain business logic and service APIs
- domain-specific content semantics and integrity
Contract Shape (Normative)#
Every domain adapter must expose at least:
getMetadata()getHomeCards(userContext)getContinueItems(userContext)search(query, filters)launch(target, context)getAvailability()
Suggested baseline interface:
export interface OshunDomainAdapter {
getMetadata(): Promise<DomainMetadata>;
getAvailability(): Promise<DomainAvailability>;
getHomeCards(ctx: UserContext): Promise<DomainCard[]>;
getContinueItems(ctx: UserContext): Promise<ContinueItem[]>;
search(input: SearchInput): Promise<SearchResult[]>;
launch(input: LaunchInput): Promise<LaunchResolution>;
}
Adapter Rules#
- Adapters must not leak domain-internal DTOs into shell UI layers.
- Shell surfaces consume only canonical OSHUN models.
- Adapter failures must be contained and converted to typed fallback states.
- Each adapter must emit standardized launch/failure latency telemetry.
Architecture Implications#
Runtime Topology#
- Shell loads domain registry and shared session context.
- Shell requests cross-domain data (direct adapter call and/or BFF aggregate).
- Adapters map domain data to shell contracts.
- Shell renders consistent UI with domain-accented presentation.
- Domain launch actions route to native screens, embedded modules, or web/PWA destinations via normalized launch responses.
Nyx and Arete Specific Notes#
- Nyx: allowed to start with embed-first mode if native parity is not yet viable. This is an implementation mode, not a shell architecture exception.
- Arete: adapter-first integration from
libs/arete/*is the primary path; standalone app generation is optional and deferred unless justified.
Implementation Plan#
Phase 1: Contracts and Registry#
- Define canonical shell DTOs and adapter interfaces.
- Create
libs/oshun/domain-registrywith domain metadata contracts. - Define error/fallback states and telemetry requirements.
Phase 2: Shell Baseline#
- Scaffold
apps/oshun/mobileand shared libs (ui,navigation,auth,analytics,offline). - Build shell home/explore/activity/profile using canonical contracts.
Phase 3: Adapter Integration#
- Integrate Tara adapter and Veritas adapter first.
- Integrate Nyx according to selected mode (embed/native baseline).
- Integrate Arete adapter from existing domain libraries.
Phase 4: Hardening#
- Add adapter contract tests and outage simulation tests.
- Validate launch latency and resilience SLOs.
- Validate analytics and deep-link consistency across domains.
Success Metrics#
- Domain launch success rate >= 99.0% per domain.
- Domain launch p95 from shell card tap <= 1.2s (excluding external outage).
- No full-shell crash caused by single-domain adapter failure.
-
= 90% of shell UI surfaces consume canonical contracts only.
- Cross-domain weekly active usage reflects multi-domain adoption targets in
docs/releases/v1/reports/metrics.md.
Consequences#
Positive Consequences#
- ✅ Delivers OSHUN core value proposition without full domain rewrites.
- ✅ Supports parallel domain integration tracks.
- ✅ Establishes enforceable boundaries for maintainability.
- ✅ Makes resilience behavior explicit and testable.
Negative Consequences#
- ❌ Adapter drift risk when upstream domain APIs change.
- ❌ Additional governance required for contract versioning.
- ❌ Some duplication in model mapping logic across adapters.
Risks and Mitigations#
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Adapter contracts diverge from shell needs | Medium | High | Introduce contract review gate and semantic versioning |
| Domain API changes break adapter at runtime | Medium | High | Add contract tests and staged rollout with telemetry alerts |
| Nyx embed mode harms UX consistency | Medium | Medium | Restrict embed scope, define migration checkpoint to native module |
| Arete integration underestimates composition effort | Medium | Medium | Start adapter spikes early using libs/arete/* capability audit |
Compliance and Security#
- Shell continues to enforce least-privilege domain data access through BFF and adapter boundaries.
- Shared auth/session handling remains centralized in shell-level auth layer.
- Adapter telemetry must avoid leaking sensitive domain payloads.
Monitoring and Observability#
Track at minimum:
- adapter call success/error rates per domain
- launch latency by domain and surface
- fallback activation counts by error category
- domain outage impact on shell render success
- contract validation failures in CI
Related Decisions#
- Builds on shell-first direction documented in
docs/releases/v1/specs/product-brief.md. - Aligns with MVP constraints in
docs/releases/v1/scope/mvp-scope.md. - Complements cross-domain metrics in
docs/releases/v1/reports/metrics.md. - Supports future ADRs for web strategy, deep linking, auth, offline, and analytics.
References#
apps/tara/mobile/README.mdapps/veritas/mobile/app/_layout.tsxapps/nyx/mobile/project.jsonlibs/arete/*docs/adr/ADR-0011-api-contract-approach.md