# ADR-0009: Deep-Linking and Cross-Domain Routing Model

**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 to `https://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:

- `tara`
- `veritas`
- `nyx`
- `arete`

Shell surface format:

- `oshun://home`
- `oshun://explore`
- `oshun://activity`
- `oshun://profile`
- `oshun://search`

HTTPS equivalent formats:

- Shell routes: `https://oshun.app/app/{surface}`
- Domain routes: `https://oshun.app/d/{domain}/{path}`

### Canonical Examples

- `oshun://tara/meditation/abc123`
- `oshun://veritas/article/claim-42`
- `oshun://nyx/events/meteor-shower-2026`
- `oshun://arete/check-in/today`
- `https://oshun.app/d/tara/meditation/abc123`
- `https://oshun.app/app/home`

### Route Resolution Model

1. Parse and validate URI/URL against OSHUN allowlist.
2. Normalize to canonical route descriptor.
3. Resolve descriptor through `@oshun/navigation` route registry.
4. Dispatch to shell surface or domain adapter launch contract.
5. If unavailable/fails, route to safe fallback with user-visible recovery.

### Normative Route Descriptor

```ts
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://...` and `https://tara.app/...` -> `oshun://tara/...`
- `veritas://...` and `https://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/home` equivalent)
- present contextual message (`content moved`, `content unavailable`, or
  `login 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_received`
- `oshun.link_normalized`
- `oshun.link_resolved`
- `oshun.link_failed`
- `oshun.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.md`
- `docs/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.ts`
- `apps/tara/mobile/app.json`
- `apps/veritas/mobile/src/services/widget.ts`
- `apps/veritas/mobile/src/services/oauth.ts`
- `apps/veritas/mobile/app.json`
