Disciplines · Decisions (ADRs)

ADR-0007: OSHUN Shell Architecture and Domain Adapter Pattern

OSHUN must deliver one cohesive product surface that exposes Tara, Veritas, Nyx, and Arete across:

Accepted · 2026-02-16
12sections6 minread

On this page

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/mobile already uses Expo Router + React Native.
  • apps/veritas/mobile already uses Expo Router + React Native.
  • apps/nyx/mobile is 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#

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:

ts
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#

  1. Shell loads domain registry and shared session context.
  2. Shell requests cross-domain data (direct adapter call and/or BFF aggregate).
  3. Adapters map domain data to shell contracts.
  4. Shell renders consistent UI with domain-accented presentation.
  5. 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-registry with domain metadata contracts.
  • Define error/fallback states and telemetry requirements.

Phase 2: Shell Baseline#

  • Scaffold apps/oshun/mobile and 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
  • 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.md
  • apps/veritas/mobile/app/_layout.tsx
  • apps/nyx/mobile/project.json
  • libs/arete/*
  • docs/adr/ADR-0011-api-contract-approach.md