Status: Accepted Date: 2026-02-16 Authors: OSHUN Mobile Engineering, OSHUN Web Engineering, OSHUN Platform Engineering Reviewers: Domain Mobile/Web Leads Supersedes: N/A Superseded by: N/A
Context and Problem Statement#
OSHUN must support reliable, shareable, and measurable navigation across:
- mobile app (
apps/oshun/mobile) - web/PWA (
apps/oshun/web) - domain-specific entry points (Tara, Veritas, Nyx, Arete)
Current domain implementations use domain-specific schemes and routes:
- Tara:
tara://...+https://tara.app/...with custom parser/route mapping. - Veritas:
veritas://...+ app links tohttps://www.veritas.news/.... - Nyx: web/PWA route model (Vite) with installable behavior.
Without a unified route contract, OSHUN risks:
- inconsistent deep-link behavior across platforms
- broken cross-domain navigation semantics
- difficult analytics attribution and debugging
- brittle migration from domain-specific links to shell links
Decision Drivers#
- Single routing language across shell and domains.
- Cross-platform parity between mobile app links and HTTPS links.
- Backward compatibility with existing Tara/Veritas links.
- Safety: strict validation and predictable fallback behavior.
- Observability: consistent link lifecycle telemetry.
- Extensibility for future domains and route expansions.
Considered Options#
Option 1: Keep Domain-Specific Links and Pass Through#
Description: OSHUN accepts only existing domain link formats and forwards to per-domain handlers.
Pros:
- ✅ Minimal migration effort initially
- ✅ Reuses existing domain handlers directly
Cons:
- ❌ No canonical OSHUN link format
- ❌ Inconsistent analytics and routing behavior
- ❌ Hard to enforce shared security and fallback rules
Option 2: HTTPS-Only Routing, No Custom Scheme#
Description: all links use HTTPS and rely on universal/app links only.
Pros:
- ✅ Simpler link shape for sharing
- ✅ Browser-friendly by default
Cons:
- ❌ Less reliable in app-to-app and native-only contexts
- ❌ Harder local/dev linking and push/deep navigation ergonomics
- ❌ Requires perfect associated-domain support from day one
Option 3: Canonical OSHUN Scheme + HTTPS Equivalents (Chosen)#
Description: define one canonical OSHUN deep-link contract with deterministic HTTPS equivalents and resolver rules.
Pros:
- ✅ Explicit, versionable route contract
- ✅ Strong mobile and web parity
- ✅ Cleaner analytics and debugging
- ✅ Supports legacy link migration path
Cons:
- ❌ Requires route registry and resolver implementation discipline
- ❌ Requires migration bridge for old domain links
Decision Outcome#
Chosen option: Option 3 - canonical oshun:// links with HTTPS equivalents.
Canonical Link Formats#
Primary deep-link format:
oshun://{target}
Domain-specific target format:
oshun://{domain}/{path}
where domain is one of:
taraveritasnyxarete
Shell surface format:
oshun://homeoshun://exploreoshun://activityoshun://profileoshun://search
HTTPS equivalent formats:
- Shell routes:
https://oshun.app/app/{surface} - Domain routes:
https://oshun.app/d/{domain}/{path}
Canonical Examples#
oshun://tara/meditation/abc123oshun://veritas/article/claim-42oshun://nyx/events/meteor-shower-2026oshun://arete/check-in/todayhttps://oshun.app/d/tara/meditation/abc123https://oshun.app/app/home
Route Resolution Model#
- Parse and validate URI/URL against OSHUN allowlist.
- Normalize to canonical route descriptor.
- Resolve descriptor through
@oshun/navigationroute registry. - Dispatch to shell surface or domain adapter launch contract.
- If unavailable/fails, route to safe fallback with user-visible recovery.
Normative Route Descriptor#
export type OshunDomain = 'tara' | 'veritas' | 'nyx' | 'arete';
export interface OshunRouteDescriptor {
kind: 'shell' | 'domain';
surface?: 'home' | 'explore' | 'activity' | 'profile' | 'search';
domain?: OshunDomain;
pathSegments: string[];
query: Record<string, string>;
sourceUrl: string;
}
Backward Compatibility Rules#
OSHUN link resolver must support legacy links and normalize them:
tara://...andhttps://tara.app/...->oshun://tara/...veritas://...andhttps://www.veritas.news/...->oshun://veritas/...
Legacy support is mandatory for migration period and should emit
legacy_link_redirected telemetry.
Query and Attribution Rules#
- Preserve
utm_*,ref, campaign, and invite metadata through normalization. - Reject or sanitize unknown dangerous parameters.
- Normalize key casing to lowercase for canonical internal handling.
Fallback Behavior (Mandatory)#
If route cannot be resolved:
- open shell-safe fallback (
/app/homeequivalent) - present contextual message (
content moved,content unavailable, orlogin required) - log structured failure event with error category
Security and Validation Rules#
- Accept only allowlisted schemes (
oshun,https) and known domains. - Reject unknown hosts for HTTPS deep links unless explicitly mapped.
- Block executable/script payloads in path/query fields.
- Gate sensitive routes behind auth and entitlement checks.
- Never execute navigation side-effects before route validation completes.
Implementation Plan#
Phase 1: Contracts#
- Define route contracts in
libs/oshun/navigation. - Define route registry and canonical path builders/parsers.
- Define canonical redirect map for legacy domain links.
Phase 2: Platform Integration#
- Configure Expo linking for
oshun://scheme and associated domains. - Configure web middleware/handlers for
/app/*and/d/*URL forms. - Implement resolver shared logic for mobile and web.
Phase 3: Domain Adapter Binding#
- Bind canonical domain descriptors to adapter
launch()actions. - Add typed fallbacks for unavailable domain/module/content states.
Phase 4: Migration and Hardening#
- Add legacy link normalization tests.
- Add push-notification and shared-link E2E coverage.
- Add telemetry dashboards for resolution success/failure and latency.
Success Metrics#
- Deep-link resolution success rate >= 99.5% for valid links.
- p95 route resolution time <= 150ms before first navigation dispatch.
- 100% canonicalization coverage for known legacy Tara/Veritas links.
- No unresolved-link crash in production sessions.
Consequences#
Positive Consequences#
- ✅ One understandable route contract across mobile/web/PWA.
- ✅ Cleaner analytics for attribution and funnel analysis.
- ✅ Safer validation and fallback handling.
- ✅ Easier onboarding for new domain adapters.
Negative Consequences#
- ❌ Adds central governance burden to route contract changes.
- ❌ Requires migration work for legacy domain URL ecosystems.
- ❌ Requires close coordination with auth/entitlement checks.
Risks and Mitigations#
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| Legacy links missed during normalization | Medium | High | Maintain explicit mapping table + production error sampling |
| Domain adapter rejects canonical route shape | Medium | Medium | Contract tests between resolver and each adapter |
| Route contract drift between mobile and web | Medium | High | Shared parser/builder package in libs/oshun/navigation |
| Open redirect/security gaps | Low | High | Strict allowlist, validation, and security tests |
Monitoring and Observability#
Track:
oshun.link_receivedoshun.link_normalizedoshun.link_resolvedoshun.link_failedoshun.legacy_link_redirected
Each event must include platform, source, route kind, domain (if present), and error category (if failed).
Related Decisions#
docs/adr/ADR-0013-oshun-shell-architecture-and-domain-adapters.mddocs/adr/ADR-0014-oshun-web-and-pwa-strategy.md- Future ADR dependencies: auth model, offline strategy, analytics taxonomy
References#
apps/tara/mobile/src/services/deepLinks.tsapps/tara/mobile/app.jsonapps/veritas/mobile/src/services/widget.tsapps/veritas/mobile/src/services/oauth.tsapps/veritas/mobile/app.json