# QNE Contact Node NAT And Mobile Backup Doctrine V1

Status: current planning doctrine

Date: 2026-06-23

Scope: QNE node WAN/LAN reachability, contact-node NAT traversal, DHT endpoint
presence, mobile recovery vaults, companion-node encrypted backup continuity,
and fixed-node lifetime storage policy.

## Purpose

QNE development networking now includes WAN and LAN devices. The base node is
the first minimal version of the permanent node runtime, not disposable
bootstrap scaffolding. A node cannot be treated as fully reachable merely
because a local service is running. The network layer must distinguish service
health, contact acknowledgement, observed endpoint state, DHT presence, and
actual peer reachability.

QNE backups also need a layered model. Fixed nodes may hold full lifetime data,
but a user's mobile device is a better first recovery authority than an
always-on network node. Companion nodes should help cover backup gaps while the
mobile is asleep or offline, without being asked to hold or decrypt another
user's full backup.

## Contact-Node NAT Traversal

Every capable QNE node may act as a contact node for hole punching and endpoint
presence. This avoids treating one seed as the only STUN/rendezvous authority.
Presence and liveness are handled by the current
`qneskill-node-presence-v00604` skill. That skill must be carried over the
black-box `qne-p2p` dependency. Node code must not create a separate p2p
transport, raw UDP session layer, custom handshake, or custom framing outside
the qne-p2p crate.

If NAT traversal, contact-node behavior, DHT publication, or liveness needs a
qne-p2p feature that is not currently exposed, the needed qne-p2p crate change
must be referred to the founder before any qne-p2p crate modification is made.

The basic model:

1. Node A wants to be reachable.
2. A chooses one or more contact nodes from seed, DHT, LAN discovery, or known
   peers.
3. A sends a contact request to a selected contact node B.
4. B observes A's source UDP endpoint.
5. B acknowledges the request and records or confirms A's observed endpoint.
6. A keeps the NAT mapping open with normal qneskill traffic where possible.
7. If no data moves during the liveness interval, A sends a node-presence
   liveness message.
8. B refreshes A's endpoint record while traffic or liveness messages continue.
9. If B misses enough liveness, B retires A's endpoint record.
10. A detects missed contact acknowledgements and selects another contact.
11. Callers that fail to reach A go back to the DHT/contact layer for fresh
    endpoint information.

A node should normally maintain more than one contact node when possible. Two or
three contacts gives better resilience across sleeping devices, NAT instability,
and contact-node failures.

## Endpoint Change Handling

If a node knows its observed WAN endpoint changed, it should notify its contact
nodes immediately. The system must not depend on this notification being
delivered.

Reachability is both proactive and reactive:

- proactive: the node announces changed observed endpoints to contacts;
- reactive: callers that fail to reach the node retry with fresh DHT/contact
  data.

DHT endpoint records are leases, not permanent facts. They must include expiry
metadata and must be refreshed by contact acknowledgements.

Initial timing assumptions:

```text
heartbeat interval: 20-30 seconds
endpoint stale after: 60-90 seconds
endpoint expired after: 120 seconds
contact failover after: 2-3 missed acknowledgements
```

Actual production timing can be adjusted after WAN/LAN device testing.

## NAT Reality

QNE should assume:

- home/laptop nodes can usually send outbound UDP to a seed/contact node;
- inbound direct UDP may or may not work;
- WAN endpoints can change after router reboot, sleep/wake, Wi-Fi changes, VPN
  changes, ISP reconnect, mobile hotspot change, or carrier NAT behavior;
- UDP mappings often expire quickly without traffic;
- mobile and carrier-grade NAT may require relay or push/wake support later;
- symmetric NAT may produce different observed endpoints per destination.

The installer or status report must not claim "connected to network" unless the
node has received at least one contact acknowledgement. Before that, it may
claim only that the service is running and a node-presence message was sent.

## Presence Record Shape

A contact-backed presence record should include at least:

```text
node_uuid
node_role
platform
qne_node_version
claimed_lan_endpoints[]
observed_wan_endpoints[]
contact_nodes[]
last_contact_ack
nat_confidence
capabilities[]
expires_at
signature
```

Presence is the evolved, safer form of the older "known nodes" idea. A normal
node should not store the whole network. It stores its own current presence,
active/recent contacts, records relevant to its users or communities, and a
bounded cache learned through DHT/contact/gossip paths.

Presence is node-level and temporary. It must not store user nicknames or
contact aliases. Human names belong in user/contact data:

```text
nickname/contact alias -> user_id
user_id -> active device/node ids
node_id -> current signed presence/endpoints
```

The DHT provides address hints. Presence provides fresh node state. Actual trust
comes from signature verification, revocation checks, and successful qne-p2p
session authentication. Cached presence endpoint candidates may include LAN
addresses, observed WAN addresses from hole punching, relay/contact hints, and
last successful session routes, but every candidate is only a hint until qne-p2p
proves the peer identity.

Normal nodes must bound presence storage. Initial defaults:

```text
max_presence_records = 5000
max_presence_age = 24h
max_presence_bytes = 32MB
presence_ttl = 15m
```

Larger seed/master/skill-repo nodes may retain more because that is their role,
but user nodes must remain resource-bounded.

For the development network, `development-seed-master-0001` may be the first
stable contact/rendezvous node, but the design should not make it the only
possible contact node.

## Gossip Record Sync

Gossip means exchanging small signed facts over existing qne-p2p sessions using
qneskills. It is not a separate raw protocol. The minimal current skill shape is:

```text
qneskill-gossip-v00616
actions:
  announce_inventory
  request_records
  send_records
```

Initial record types:

```text
presence
role_manifest
revocation
network_epoch
artifact_manifest
```

Nodes exchange compact inventories first, request only missing/newer records,
verify signatures before storing, and relay only records within their relevant
scope. The DHT helps find nodes; gossip spreads verified network facts once
nodes are already talking.

The qne-p2p static public key is the intended node identity key. Presence and
revocation records should be signed by the corresponding static private key
once qne-p2p exposes the necessary stable identity/signature API. Until then,
development versions may persist session-observed unsigned records, clearly
marked as not yet cryptographically authoritative.

## Bootstrap Download Observations

The master node should coordinate installer downloads before the user is sent to
Bunny for the large static file. This lets the master create a temporary
download session, observe the requester IP, attach MaxMind ASN/ISP/GeoNames
hints, choose the current correct artifact, and create one bootstrap UUID.

The bootstrap UUID becomes the qne-node UUID when the installer successfully
claims the record. Base node installation does not create a user. Users are
created later by node/user-onboarding flows, and some qne-nodes will never have
users.

The browser header platform guess is not authority. When the installer runs, it
detects the actual local platform and claims the short-lived session with its
nonce. If the downloaded installer/runtime is wrong or stale, the installer can
request the correct runtime from the master and fetch it from Bunny.

ASN/ISP and GeoNames values are valuable for resilient peer discovery because
they can help select nearby or same-provider peers. They must remain bounded
routing hints, not identity facts. Raw IP addresses should stay in the master
bootstrap record or local diagnostics unless there is a clear operational need
to share them.

## Installer Status Language

Without GUI, installers must write and open a text status report. The report
should distinguish:

```text
Service: running / not running
Network: qne-development-network
Seed/contact heartbeat: sent / failed
Seed/contact acknowledgement: received / not implemented / missing
Observed endpoint: known / unknown
DHT presence: recorded / pending / not implemented
Connection: awaiting seed acknowledgement support / contact-backed / relay-needed
```

The user should not need shell commands to know whether the service is running
and what network state is actually known.

## Mobile Recovery Vault

A mobile device is better used first as the user's trusted portable persist
backup and recovery authority than as an always-on node. It may later become an
opportunistic network node, but its first durable role is backup and restore.

The mobile app should naturally combine:

```text
QNE UI
mobile intents/actions
personal recovery vault
encrypted persist backup manager
restore/migration approval device
```

Mobile is less exposed than a general-purpose laptop to broad ransomware because
of app sandboxing, hardware-backed key storage, and fewer arbitrary executable
workflows. It is still not immune to theft, account compromise, malicious apps,
OS bugs, or user-approved destructive actions.

Therefore mobile backups must be encrypted, versioned, append-oriented, and
protected from unilateral deletion by a compromised laptop.

## Companion Backup Continuity

The mobile may be asleep or offline, so it cannot by itself guarantee that it
has the latest complete backup. Companion nodes fill this gap by holding
encrypted backup deltas or checkpoints.

The roles are:

```text
fixed node = current working persist owner and full lifetime storage holder
mobile = recovery authority / user-held vault
companion nodes = encrypted continuity backup holders
```

Companion nodes should not be expected to hold another user's full backup. They
hold encrypted continuity pieces sufficient to cover gaps since the mobile last
synced. They must not be able to decrypt those pieces.

Restore can then combine:

1. mobile-held recovery authority and latest known manifest;
2. mobile-held backup pieces;
3. companion-held encrypted deltas/checkpoints;
4. fixed-node or online/offline archive tiers when available.

## Backup Manifest

Backup sets need a signed manifest that spans mobile, fixed-node, companion,
online, and offline storage tiers.

The manifest should record:

```text
backup_set_id
user_id / node_id
base_checkpoint_hash
delta_sequence_numbers
content_hashes
created_by_device
held_by_mobile
held_by_companions[]
latest_complete_sequence
retention_class
restore_policy
signature
```

The mobile should know what the latest complete backup sequence should be, where
missing encrypted chunks are held, and whether each chunk verifies by hash and
signature.

## Fixed-Node Storage Policy

Fixed nodes may hold full lifetime data locally, online, or offline according to
storage policy. Mobile is not expected to carry the full lifetime archive.

Storage classes:

```text
current: hot, local/online, fast restore
recent-month: rollback window
medium-2y: medium-term retention
archive-lifetime: lifetime history
mobile-critical: latest complete recovery set and recovery authority
companion-continuity: encrypted deltas/checkpoints while mobile is unavailable
```

The policy should allow:

- fixed node local disk: current, recent, selected medium;
- fixed node online storage: current, recent, medium, archive index;
- offline archive: lifetime immutable snapshots;
- mobile: latest complete recovery set, manifest, keys/approvals;
- companions: encrypted continuity pieces since mobile last synced.

## Doctrine Rule Summary

Fixed nodes may hold full lifetime data. Mobile is the user's recovery
authority. Companion nodes hold only encrypted continuity backup pieces. QNE
reachability is contact-backed and lease-based; any node may serve as a contact
node for another node's observed endpoint and hole-punching flow.
