# Architecture

## Scope

O20010.06 is the HT Portal smartphone companion, distributed as HT Portal VPN,
not a second portal. The native app opens the dedicated `o20010.01` mobile VPN
login and device picker in a system in-app browser. `o20010.03` authorizes the
selected device and creates a short-lived handoff; the native app then asks the
operating system for VPN permission and starts the existing n3n-based device VPN
flow.

The first release deliberately supports only:

- authenticated device VPN sessions;
- standard runtime devices using `n3n-v3`;
- runtime version 2.2.0 or newer;
- IPv4 split tunnelling;
- Android 10+ and an internally distributed iOS 16+ preview.

Fast Connection is outside this scope.

## Handoff sequence

1. The app opens `https://portal.hivetechnology.net/mobile-vpn` in an Android
   Custom Tab or iOS Safari View Controller; login and device selection use the
   portal's existing authentication session.
2. The portal calls `POST /mobile-vpn/handoffs` with the device and platform.
3. The API checks user/device ownership and runtime compatibility.
4. The API stores only a SHA-256 ticket digest and an AES-256-GCM encrypted
   request payload. The clear ticket is returned once in a URL fragment.
5. The in-app browser opens `https://connect.portal.hivetechnology.net/vpn/#handoff=<ticket>`.
6. An installed app receives the Universal/App Link directly. The fallback page
   removes the fragment from browser history before trying the custom scheme.
7. The app presents its VPN data disclosure. Cancelling at this point does not
   redeem the ticket or create a mobile VPN session.
8. After confirmation, the app redeems the ticket once. The API atomically consumes it and issues a
   separate, scoped mobile-session bearer token.
9. After OS VPN consent, the app starts the session. The API creates the normal
   `connections` request consumed by `o20010.04`.
10. When the runtime reports `vpn-created`, the app receives the n3n and runtime
   endpoint configuration through the bearer-protected config endpoint.
11. The native tunnel connects by UDP first and then TCP relay if necessary.
12. A pinned/CA-validated WebSocket through the overlay proves runtime reachability.

The portal and app both receive sanitized session events. Stopping either the
handoff from the portal or the session from the app deletes the underlying
connection request.

## Native data plane

`core/` embeds the pinned n3n 3.4.6 edge. Mobile operating systems expose an IP
TUN, while n3n expects Ethernet frames. `htp_packet_bridge` provides the narrow
TUN-to-TAP adapter:

- outbound IPv4 packets receive an Ethernet header;
- inbound Ethernet IPv4 payloads are returned to the OS packet API;
- ARP is answered locally and peer MAC information is learned;
- no DNS proxy, full-tunnel route, or packet logging is implemented.

Android uses `VpnService` and protects each n3n supernode socket from the VPN.
iOS uses a Packet Tunnel Network Extension and excludes resolved supernode IPs
from included routes. The runtime WebSocket is intentionally not excluded: it
must traverse the overlay.

## Ownership boundaries

- `o20010.01`: app launch UX and session status only.
- `o20010.03`: authorization, one-time handoff, mobile session, revocation,
  audit, and existing runtime connection orchestration.
- `o20010.04`: unchanged runtime VPN producer.
- `o20010.06`: native consent, secure local credentials, packet tunnel,
  route-conflict protection, reconnect, and background lifecycle.
