Part 03 — Transport & Routing Policy Engine Architecture
Reusable P2P Communication Platform
Status: Architecture specification
Part: 03 of 24
Primary language: Rust
Core transport: Iroh-first, transport-neutral
Primary goals: intelligent path selection, transport abstraction, failover, multipath readiness, battery awareness, DTN compatibility, predictable policy, reusable across messaging/files/calls/emergency/ERP products
1. Purpose
The communication platform must support multiple transport mechanisms without forcing each application feature to understand the differences between them.
Potential paths include:
Iroh direct
Iroh relay
local LAN
Wi-Fi Direct
Wi-Fi Aware
Bluetooth Classic
Bluetooth LE
application-level mesh
DTN/store-carry-forward
future transports
The transport/routing policy engine is responsible for deciding:
Which path should carry this operation?
When should the system retry?
When should it switch paths?
When should it use multiple paths?
When should it defer?
When should it fall back to DTN?
The application should express intent and constraints, not transport mechanics.
2. Fundamental Rule
Do not let feature code implement transport selection.
Bad:
Messaging:
try Iroh
if failed try LAN
if failed try Bluetooth
Bad:
File transfer:
if Wi-Fi then use Wi-Fi
else use Internet
Correct:
Application Operation
↓
Delivery Requirements
↓
Routing Policy Engine
↓
Path Candidates
↓
Scoring + Constraints
↓
Selected Route
↓
Transport Adapter
This separation is essential for reuse.
3. Architectural Position
Application
↓
Messaging / Files / Calls / Emergency
↓
Delivery Intent
↓
Routing Policy Engine
↓
Transport Manager
↓
Iroh / LAN / Wi-Fi / Bluetooth / DTN
Identity feeds destination resolution into routing.
Transport adapters feed measured path state into routing.
The routing engine sits between application semantics and transport mechanics.
4. Core Responsibilities
The routing engine owns:
- candidate path discovery
- route scoring
- policy validation
- fallback order
- path health tracking
- retry decisions
- transport switching
- path stickiness
- multipath planning
- bandwidth-aware selection
- latency-aware selection
- battery-aware selection
- metered-network awareness
- emergency priority handling
- DTN eligibility
- route diagnostics
- path history
- per-peer route memory
It does not own:
- message semantics
- file chunking
- codec negotiation
- cryptographic identity
- user interface
- transport implementation details
5. Main Abstractions
Recommended types:
#![allow(unused)] fn main() { pub struct RouteRequest; pub struct RouteDecision; pub struct PathCandidate; pub struct PathMetrics; pub struct DeliveryRequirements; pub struct RoutingPolicy; pub struct RoutePlan; pub struct RouteHealth; }
Transport identity and account/device identity remain separate types from Part 02.
6. Delivery Requirements
Feature layers describe what they need.
#![allow(unused)] fn main() { pub struct DeliveryRequirements { pub class: DeliveryClass, pub priority: Priority, pub max_latency: Option<Duration>, pub min_bandwidth: Option<Bitrate>, pub durable: bool, pub allow_metered: bool, pub allow_relay: bool, pub allow_bluetooth: bool, pub allow_dtn: bool, pub allow_multipath: bool, pub expiry: Option<Timestamp>, pub max_cost: Option<NetworkCost>, } }
These fields should be strongly typed where practical.
7. Delivery Classes
#![allow(unused)] fn main() { pub enum DeliveryClass { Realtime, Interactive, Reliable, Bulk, DelayTolerant, } }
Examples:
video call frame → Realtime
text message → Interactive/Reliable
receipt → Interactive
file transfer → Bulk/Reliable
SOS → Reliable/DelayTolerant
typing indicator → Realtime but non-durable
8. Priority
Use a small explicit scale.
#![allow(unused)] fn main() { pub enum Priority { Critical, High, Normal, Low, Background, } }
Priority affects scheduling but does not override hard constraints.
Example:
Critical SOS
can use Bluetooth/DTN if needed.
A Critical 4 GB video should still not be forced over BLE if impossible.
9. Path Candidate
Each possible route is normalized:
#![allow(unused)] fn main() { pub struct PathCandidate { pub path_id: PathId, pub transport: TransportKind, pub peer: DeviceId, pub endpoint: TransportEndpoint, pub metrics: PathMetrics, pub capabilities: PathCapabilities, pub health: RouteHealth, } }
Routing works on this generic representation.
10. Transport Kinds
#![allow(unused)] fn main() { pub enum TransportKind { IrohDirect, IrohRelay, LocalLan, WifiDirect, WifiAware, BluetoothClassic, BluetoothLe, MeshRelay, Dtn, } }
Future transports can be added without changing messaging/file APIs.
11. Path Capabilities
#![allow(unused)] fn main() { pub struct PathCapabilities { pub reliable_stream: bool, pub datagram: bool, pub large_files: bool, pub realtime_media: bool, pub peer_discovery: bool, pub store_and_forward: bool, pub metered: bool, } }
This prevents impossible route choices.
12. Path Metrics
Metrics should include:
#![allow(unused)] fn main() { pub struct PathMetrics { pub rtt: Option<Duration>, pub estimated_bandwidth: Option<Bitrate>, pub packet_loss: Option<Ratio>, pub jitter: Option<Duration>, pub stability: StabilityScore, pub energy_cost: EnergyCost, pub monetary_cost: NetworkCost, pub signal_quality: Option<SignalQuality>, pub last_success: Option<Timestamp>, } }
Not all transports expose all metrics.
Missing metrics must be represented explicitly.
13. Metrics Confidence
Every metric should have confidence/age metadata.
Example:
#![allow(unused)] fn main() { MeasuredValue<T> { value: T, observed_at: Timestamp, confidence: Confidence, } }
Routing must not treat a 20-minute-old bandwidth estimate as current truth.
14. Route Health
#![allow(unused)] fn main() { pub enum RouteHealth { Healthy, Degraded, Suspect, Unreachable, Unknown, } }
Health is derived from:
- recent failures
- timeouts
- connection churn
- path changes
- transport errors
15. Path Discovery Sources
Candidates may come from:
Iroh discovery
known endpoint cache
LAN discovery
Wi-Fi Direct/Aware discovery
Bluetooth discovery
recent peer encounter
DTN forwarding table
manual/QR endpoint
Discovery is separate from routing.
Routing consumes candidates.
16. Destination Resolution
Routing should accept logical targets:
#![allow(unused)] fn main() { pub enum Destination { Account(AccountId), Device(DeviceId), Group(GroupId), } }
Resolution flow:
AccountId
↓
Device Directory
↓
active devices
↓
known transport endpoints
↓
candidate paths
Part 02 provides device membership.
17. Account-Level Routing
A request to:
send to account
may produce a route plan to multiple devices.
Example:
Bob:
Phone reachable via Iroh direct
Laptop offline
Tablet reachable via LAN
Messaging may fan out.
File transfer may choose a specific target.
Routing must support both.
18. Route Plan
A route decision can be more than one path.
#![allow(unused)] fn main() { pub struct RoutePlan { pub primary: PathCandidate, pub fallbacks: Vec<PathCandidate>, pub replicas: Vec<PathCandidate>, pub strategy: RouteStrategy, } }
Strategies:
#![allow(unused)] fn main() { pub enum RouteStrategy { Single, Failover, Redundant, Multipath, DelayTolerant, } }
19. Single Route
For ordinary traffic:
one best path
Example:
small text message
→ Iroh direct
This avoids unnecessary duplication.
20. Failover Route
Plan:
Primary:
Iroh direct
Fallback:
Iroh relay
Fallback:
LAN
Fallback:
DTN
Failover does not send simultaneously.
It switches when policy or health dictates.
21. Redundant Route
For critical traffic:
send same logical operation
over more than one independent route
Example:
SOS
├── Internet
└── nearby mesh
Receiver deduplicates via stable operation/message ID.
Use redundancy sparingly.
22. Multipath Route
Multipath means splitting one operation across multiple paths.
Useful for:
large file
future live media
high-resilience transfer
Example:
Chunk ranges:
Wi-Fi → chunks 0–49
Internet → chunks 50–99
This should be a later optimization, not required for v1 routing.
23. Delay-Tolerant Route
If no continuous path exists:
persist operation
↓
select DTN bundle policy
↓
wait for peer encounter
↓
forward opportunistically
Routing should treat DTN as a legitimate delivery strategy, not merely an error fallback.
24. Route Scoring
A candidate route receives a score.
Conceptually:
score =
reachability
+ latency suitability
+ bandwidth suitability
+ stability
+ energy suitability
+ monetary-cost suitability
+ privacy policy
+ recent success
- congestion
- failure penalty
Do not hard-code one universal numeric formula.
Use typed weighted policy.
25. Hard Constraints vs Soft Preferences
Hard constraint:
realtime media requires realtime-capable path
Soft preference:
prefer direct over relay
Evaluation order:
1. eliminate paths violating hard constraints
2. score remaining paths
3. apply stickiness/hysteresis
4. produce route plan
26. Path Scoring Interface
#![allow(unused)] fn main() { pub trait PathScorer { fn score( &self, candidate: &PathCandidate, req: &DeliveryRequirements, context: &RoutingContext, ) -> RouteScore; } }
Allow product profiles to supply custom scorers.
27. Policy Profiles
Recommended defaults:
Balanced
LowLatency
LowPower
LowCost
HighReliability
Emergency
BulkTransfer
Applications can use:
#![allow(unused)] fn main() { RoutingPolicyProfile::Balanced }
instead of manually setting dozens of fields.
28. Balanced Policy
Typical:
prefer direct
prefer unmetered
avoid high battery cost
use relay if needed
use DTN for durable traffic only
Suitable for ordinary messenger usage.
29. Low-Latency Policy
For calls:
minimize RTT
penalize jitter/loss
avoid path switching
avoid DTN
avoid BLE
Bandwidth and stability matter more than monetary cost unless user policy forbids.
30. Low-Power Policy
For battery saver:
prefer existing connection
avoid active discovery
avoid Wi-Fi Direct setup
reduce multipath
avoid Bluetooth scanning escalation
The routing engine should understand setup cost, not just transmission cost.
31. Low-Cost Policy
For metered networks:
prefer LAN/Wi-Fi
delay bulk traffic
allow small control traffic
Useful for large files.
32. High-Reliability Policy
For important business data:
prefer proven paths
allow retry
possibly redundant control delivery
persist before send
33. Emergency Policy
Emergency mode may:
allow mesh
allow DTN
increase discovery
allow redundancy
prioritize critical payloads
ignore some cost preferences
but should still remain battery-aware.
34. Route Stickiness
Do not switch routes whenever a slightly better score appears.
Example:
Iroh direct stable
Wi-Fi briefly appears
Do not churn connection unnecessarily.
Use hysteresis:
switch only if:
new_score > current_score + threshold
or current route degraded
35. Path Hysteresis
#![allow(unused)] fn main() { pub struct HysteresisPolicy { pub switch_threshold: RouteScoreDelta, pub minimum_hold_time: Duration, pub degraded_override: bool, } }
This reduces:
- packet reordering
- reconnect overhead
- codec disruption
- battery use
36. Route Failure Classification
Classify failures:
Temporary
TransportUnavailable
AuthenticationFailure
PolicyDenied
RemoteRejected
Permanent
Unknown
Routing should retry only when appropriate.
37. Failure Examples
Timeout → Temporary
Bluetooth disabled → TransportUnavailable
Revoked device → AuthenticationFailure
Metered forbidden → PolicyDenied
Unsupported extension → RemoteRejected
Invalid destination → Permanent
Do not blindly retry all failures.
38. Retry Policy
#![allow(unused)] fn main() { pub struct RetryPolicy { pub max_attempts: Option<u32>, pub initial_backoff: Duration, pub max_backoff: Duration, pub jitter: Ratio, pub retry_on_network_change: bool, } }
Durable messages may retry indefinitely until expiry.
Typing indicators should not retry.
39. Retry on Connectivity Change
A connectivity event can bypass backoff.
Example:
message waiting
↓
Wi-Fi restored
↓
retry immediately
This improves perceived latency.
40. Path Memory
Maintain per-peer route history:
last successful path
recent RTT
recent failures
known local route
last Internet gateway
Use it as a hint.
Do not treat historical state as proof of current reachability.
41. Route Cache
Cache:
Destination
Best Known Path
Fallbacks
Observed At
TTL
Invalidate on:
- device directory update
- network transition
- transport shutdown
- authentication failure
42. Network Transition Events
Routing must react to:
Wi-Fi connected
Wi-Fi disconnected
cellular connected
Bluetooth enabled
Bluetooth disabled
LAN route discovered
Iroh path changed
app backgrounded
battery saver enabled
Events come from platform/transport layers.
43. Route Re-Evaluation
Do not recompute all routes on every small event.
Use targeted invalidation:
Wi-Fi changed
→ reevaluate Wi-Fi-related candidates
This preserves efficiency.
44. Transport Setup Cost
Some paths require setup.
Example:
existing Iroh session → cheap
Wi-Fi Direct group creation → expensive
Bluetooth pairing → expensive
Route scoring should include setup latency/cost.
For a 200-byte message, creating Wi-Fi Direct may be worse than using relay.
45. Existing Connection Preference
Prefer already-established healthy sessions.
This reduces:
- latency
- CPU
- radio activation
- battery
- handshake cost
unless another path clearly dominates.
46. Connection Pool Integration
Transport Manager should expose:
active connection
connecting
idle
unreachable
Routing can reuse pooled connections.
Do not create a connection per message.
47. Peer Session Abstraction
Routing should route through authenticated sessions, not raw transport addresses.
DeviceId
↓
Path
↓
Transport Connection
↓
Authenticated Session
This ties routing back to Part 02 identity.
48. Security Constraints
Routing cannot override:
identity trust
authorization
encryption requirements
revocation
A high-scoring path to a revoked device must never be selected.
49. Privacy Policy
Routing may consider privacy preferences:
PreferDirect
AvoidRelay
AllowRelay
AvoidMetered
NearbyOnly
InternetOnly
These are user/application policies.
Do not make privacy decisions implicit.
50. Direct vs Relay Preference
Default:
direct healthy path
>
relay path
But not absolutely.
A severely degraded direct path may be worse than a stable relay.
Scoring should reflect actual quality.
51. LAN Preference
For local same-router communication:
LAN direct
often provides:
- low latency
- high bandwidth
- no Internet dependency
It may outrank Internet relay when authenticated and available.
52. Wi-Fi Direct/Aware
Useful when:
no router
nearby devices
high bandwidth required
But setup overhead means it should not be created for every tiny message.
Use threshold policy:
large transfer
active call
explicit nearby session
53. Bluetooth Classic
Potentially useful for:
small/medium messages
fallback
local sync
but generally lower bandwidth than Wi-Fi.
Routing should understand its throughput class.
54. Bluetooth LE
BLE is suited for:
discovery
control
SOS
small messages
DTN handoff
Do not route:
large video
realtime AV1 calls
huge file
over BLE unless explicitly forced for tiny chunks/emergency policy.
55. Mesh Forwarding
Mesh path candidate represents:
next hop
estimated route utility
hop budget
relay trust policy
It is not the same as direct transport.
Routing decides whether to hand payload to mesh/DTN subsystem.
56. DTN Routing Boundary
The Routing Policy Engine decides:
DTN allowed?
priority?
expiry?
replication budget?
The DTN subsystem decides:
which encountered peer receives bundle?
Do not duplicate DTN algorithms inside general routing.
57. Delivery Semantics
Feature layers must label operations.
Examples:
typing:
non-durable
expires quickly
no DTN
message:
durable
retry
DTN allowed
file chunk:
resumable
bulk
DTN optional
call frame:
realtime
drop stale frames
This prevents incorrect route behavior.
58. Operation Descriptor
#![allow(unused)] fn main() { pub struct OperationDescriptor { pub operation_id: OperationId, pub destination: Destination, pub requirements: DeliveryRequirements, pub estimated_size: ByteCount, pub content_class: ContentClass, } }
Routing receives metadata, not application payload plaintext.
59. Content Class
#![allow(unused)] fn main() { pub enum ContentClass { Control, Text, Metadata, Thumbnail, Voice, Image, File, RealtimeAudio, RealtimeVideo, Emergency, } }
This helps policy without exposing private contents.
60. Size-Aware Routing
A path good for 1 KB may be poor for 1 GB.
Scoring must account for:
setup cost
transfer time
energy
reliability
Estimate:
completion_time ≈ setup + bytes / bandwidth
with uncertainty.
61. Deadline-Aware Routing
Realtime operations may have deadlines.
Example:
video frame useful for 100 ms
If estimated arrival exceeds deadline:
drop
rather than queue indefinitely.
62. Expiry-Aware Routing
Durable operations can have expiry.
Example:
SOS expires after 24h
typing after 5s
Routing should stop retrying after expiry.
63. Queue Architecture
Use per-class queues:
Critical
Control
Interactive
Bulk
Background
Each bounded.
Scheduler prevents bulk traffic from blocking interactive control.
64. Weighted Fair Scheduling
Example weights:
Critical: 10
Control: 8
Interactive: 6
Normal: 4
Bulk: 2
Background: 1
Actual values require testing.
Emergency critical traffic can temporarily preempt.
65. Backpressure
If transport cannot keep up:
producer
↓
bounded route queue
↓
backpressure
Feature receives:
QueueFull
Deferred
or async wait.
Never buffer unbounded data.
66. Per-Transport Queues
Maintain separate bounded queues per transport/session.
This prevents:
stalled Bluetooth
from blocking:
healthy Iroh
67. Per-Peer Fairness
One peer transferring a huge file must not starve messages to others.
Scheduler should include peer fairness.
68. Per-Extension Fairness
Files should not starve:
messaging
receipts
presence control
Use extension-aware quotas.
69. Route Planning for Messaging
Typical plan:
1. existing authenticated direct route
2. local LAN
3. Iroh relay
4. nearby transport
5. DTN
Actual ordering depends on policy and measured health.
70. Route Planning for Files
Typical:
1. high-bandwidth direct
2. LAN/Wi-Fi Direct
3. Iroh direct
4. relay
5. Bluetooth only if small/allowed
6. DTN if policy permits
71. Route Planning for Calls
Call path requirements:
low RTT
low jitter
sufficient bandwidth
stable
realtime
Fallback:
video
↓
lower bitrate
↓
audio
↓
call ends / switches to voice message
Routing supplies path quality signals to media adaptation.
72. Route Planning for Emergency
SOS may choose:
Internet direct
+
nearby mesh copy
or:
LAN
+
DTN
depending on connectivity.
Stable operation ID ensures deduplication.
73. Path Diversity
For redundant delivery, prefer independent failure domains.
Example:
Wi-Fi Internet
+
BLE mesh
is more diverse than:
two logical streams over same Wi-Fi path
Routing should understand shared-underlay relationships where possible.
74. Underlay Group
Add:
#![allow(unused)] fn main() { pub struct UnderlayId; }
Candidates sharing same underlay can be grouped.
Example:
Iroh direct over Wi-Fi
Iroh relay over Wi-Fi
share:
same Wi-Fi radio/network
This matters for redundancy.
75. Multipath Chunk Scheduler
For future large-file multipath:
file ranges
↓
path allocator
↓
per-path congestion/throughput
↓
dynamic chunk reassignment
Do not assign fixed 50/50 split.
Use measured throughput.
76. Path Collapse
If one multipath leg fails:
remaining chunks
→ reassigned
Transfer should continue.
77. Duplicate Chunk Handling
Content-addressed or range-based file transfer makes redundant/multipath delivery idempotent.
Receiver verifies and discards duplicate chunks.
78. Realtime Multipath
For calls, future options include:
redundant keyframes
audio on best path
video on high-bandwidth path
This is advanced and should be optional.
79. Congestion Signals
Transport adapters should report:
send queue
RTT trend
loss
throughput
connection congestion
Routing should not implement transport congestion control itself.
It uses transport-level signals.
80. Route Stability Score
Derive from:
connection lifetime
failure rate
path changes
packet loss
timeout history
A path with slightly worse RTT but much better stability may win.
81. Cold vs Warm Path
Path state:
Warm:
existing authenticated connection
Cold:
requires discovery/connection
Warm path gets a setup-cost advantage.
82. Metered Networks
Platform reports:
metered
unmetered
unknown
Application policy can:
block bulk
allow control
allow emergency
Do not use one global allow/deny.
83. Roaming
Represent separately if platform provides it.
A user may allow cellular but forbid roaming bulk transfer.
84. Battery Cost
Transport energy cost can be coarse:
#![allow(unused)] fn main() { pub enum EnergyCost { VeryLow, Low, Medium, High, VeryHigh, } }
No need for fake precision initially.
85. Battery-Aware Inputs
Routing context may include:
battery level class
charging state
battery saver
thermal state
foreground/background
Part 13 will deepen battery scheduling.
86. Background Restrictions
Mobile OS may disallow certain path setup in background.
Candidate path must include:
currently usable
requires foreground
Routing should not repeatedly attempt impossible background operations.
87. Platform Policy Integration
Android/iOS adapters expose:
network type
metered
roaming
power saver
background restrictions
radio availability
Rust routing policy remains authoritative.
88. Path Acquisition
Routing can request:
bring up Wi-Fi Direct
start BLE scan
establish Iroh session
through transport manager.
But active acquisition must be policy-limited because it costs power/time.
89. Passive vs Active Candidates
#![allow(unused)] fn main() { pub enum CandidateState { Active, PassiveKnown, RequiresDiscovery, RequiresSetup, } }
Scoring can penalize setup.
90. Discovery Budget
Routing should not trigger unlimited scans.
Use:
discovery budget
cooldown
priority-based escalation
Example:
normal message:
no aggressive BLE scan
SOS:
aggressive discovery allowed
91. Route Escalation Ladder
A practical model:
Stage 1:
use active connections
Stage 2:
use known endpoints
Stage 3:
perform lightweight discovery
Stage 4:
perform expensive proximity setup
Stage 5:
fall back to DTN
This controls resource cost.
92. Timeout by Stage
Each stage has bounded timeout.
Do not wait forever trying one path before considering alternatives.
93. Hedged Requests
For latency-sensitive small operations:
start primary
after short delay if no progress
start fallback
First success wins.
Useful for:
control
important text
Potentially expensive, so use selectively.
94. Deduplication Requirement
Hedged or redundant sends require stable:
OperationId
MessageId
BundleId
Receiver must be idempotent.
95. Route Diagnostics
Expose user/developer-readable plan:
Selected:
Iroh Direct
Reason:
Healthy existing session
RTT 42 ms
Unmetered Wi-Fi
Fallback:
Iroh Relay
Normal users do not need this.
Diagnostics do.
96. Path Visualization
Part 18 will expand this.
Routing should already preserve enough structured data to visualize:
Alice Phone
↓ Wi-Fi
Iroh Direct
↓
Bob Laptop
or:
Alice
↓ BLE
Relay Peer
↓ Internet
Bob
97. Route Decision Explainability
Each decision should include machine-readable reason codes:
#![allow(unused)] fn main() { pub enum RouteReason { ExistingHealthyConnection, LowestLatency, HighestBandwidth, PolicyPreferred, DirectPreferred, RelayFallback, EmergencyRedundancy, DtnOnlyAvailable, } }
This is excellent for debugging.
98. Metrics Collection
Useful routing metrics:
route selection count
failover count
path switch count
direct vs relay
DTN fallback count
average route setup latency
queue delay
retry count
99. Privacy of Metrics
Do not export:
peer identity
precise IP
contact graph
location
without explicit policy.
Local diagnostics can retain more detailed ephemeral information.
100. Routing State Store
Persist only useful durable routing hints:
last successful transport
recent gateway
known endpoint freshness
Do not persist every packet metric indefinitely.
101. Startup Behavior
At startup:
load route hints
↓
start core transport
↓
revalidate candidates
Never assume persisted route is still valid.
102. Suspend/Resume
On mobile resume:
invalidate stale metrics
refresh platform network state
reassess active sessions
retry durable operations
Do not immediately launch all discovery mechanisms.
103. Process Death
Routing correctness must not depend on in-memory plans.
Durable operations are persisted by message/file/outbox layers.
After restart:
reconstruct route
from current conditions.
104. Route Plan Lifetime
Plans are short-lived.
#![allow(unused)] fn main() { RoutePlan { created_at, valid_until, } }
Do not cache route decisions indefinitely.
105. Path Authorization
Transport availability is insufficient.
Candidate must pass:
device active
identity trusted enough
operation authorized
extension supported
before selection.
106. Extension Capability Integration
Part 01 supplies extension negotiation.
Routing can eliminate a path/session where remote does not support required protocol extension.
Example:
files/1 required
remote only supports messaging
→ path invalid for file operation
107. Device Capability Integration
Part 02 supplies device capabilities.
Example:
call to Bob
phone supports video
headless relay does not
Routing should target appropriate device subset.
108. Policy Layering
Use layered policy:
system hard safety policy
↓
application policy
↓
user preference
↓
operation requirements
↓
current network context
Hard safety constraints cannot be overridden by UI preference.
109. System Policy
Examples:
never send unencrypted private message
never route to revoked device
never exceed hard size limit
110. Application Policy
ERP example:
documents must not use unknown relay peers
Messenger:
normal messages may use relay
Emergency app:
SOS may use DTN
111. User Policy
Examples:
no mobile data for files
prefer local connections
disable Bluetooth relay
battery saver
112. Operation Policy
Specific operation may require:
deadline
minimum bandwidth
specific device
113. Policy Conflict
If constraints conflict:
large file
+
no metered
+
only metered path exists
Result:
DeferredByPolicy
not silent policy violation.
114. Policy Result Types
#![allow(unused)] fn main() { pub enum RouteDecisionResult { Routed(RoutePlan), Deferred(DeferredReason), Rejected(RejectReason), Unreachable, } }
This makes behavior explicit.
115. Deferred Reasons
WaitingForUnmetered
WaitingForPeer
WaitingForWifi
BatteryPolicy
BackgroundRestriction
NoSuitablePathYet
Useful for UI.
116. UI-Friendly State
Routing core can expose neutral state:
Sending
WaitingForConnection
WaitingForWiFi
CarriedByNearbyPeer
Delivered
Product UI maps it into wording.
Do not expose raw transport errors to normal users.
117. Route Policy Configuration
Use typed config:
#![allow(unused)] fn main() { RoutingConfig { direct_preference, relay_policy, bluetooth_policy, dtn_policy, multipath_policy, retry_policy, hysteresis, } }
Validate at startup.
118. No Global Singleton
Each CommunicationRuntime owns its routing engine.
This enables:
multiple identities
tests
embedded runtimes
tenant isolation
119. Routing Engine API
#![allow(unused)] fn main() { pub trait RoutingEngine { async fn plan( &self, request: RouteRequest, ) -> Result<RouteDecision, RoutingError>; async fn report_result( &self, report: RouteResultReport, ); } }
120. Transport Manager API
#![allow(unused)] fn main() { pub trait TransportManager { async fn candidates( &self, destination: &ResolvedDestination, ) -> Result<Vec<PathCandidate>, TransportError>; async fn acquire( &self, path: &PathCandidate, ) -> Result<TransportSession, TransportError>; } }
Routing does not own low-level sockets.
121. Feedback Loop
After each operation:
transport result
↓
routing feedback
↓
metrics update
↓
health update
The engine learns local path quality.
122. Avoid ML Initially
Do not start with a machine-learning route selector.
Deterministic policy is:
- easier to test
- explainable
- safer
- easier to debug
ML can be explored later if measurements justify it.
123. Deterministic Scoring
Given same:
policy
metrics
context
route decision should be reproducible.
This improves testing.
124. Simulated Routing Tests
Build fake paths:
Path A:
10 ms
1 Mbps
metered
Path B:
50 ms
100 Mbps
unmetered
Expected:
text → A or B depending policy
large file → B
125. Policy Property Tests
Examples:
revoked path never selected
forbidden metered path never selected
realtime operation never uses DTN
expired operation never routed
126. Chaos Tests
Simulate:
Wi-Fi flaps
relay latency spikes
BLE disappears
mobile data activates
battery saver enables
Assert:
no route storm
no infinite retry loop
bounded queues
127. Failover Test
primary healthy
↓
mid-transfer failure
↓
fallback acquired
↓
operation resumes if semantics allow
Message retry and file resume differ.
Routing only coordinates path change.
Feature layer owns semantic resume.
128. File Resume Integration
Routing says:
new path available
File engine says:
resume missing ranges
Do not make routing understand file chunk state.
129. Messaging Retry Integration
Routing says:
path failed
Messaging outbox decides:
retry same message ID
Routing does not create duplicate message semantics.
130. Call Path Change Integration
Routing reports:
new path
quality update
Call/media engine handles:
rebind
renegotiate
adapt bitrate
131. Security Event Integration
If routing gets:
authentication failure
revoked device
it must:
remove candidate
invalidate route cache
emit security-relevant event
Do not treat as ordinary transient failure.
132. Blacklisting
Temporary path blacklist can be used for repeated failure.
#![allow(unused)] fn main() { PathPenalty { until, reason, } }
Do not permanently blacklist transport based on one transient error.
133. Peer Abuse
If peer is abusive:
rate limit
quarantine
block
This is separate from path quality.
A high-bandwidth malicious peer must not win scoring.
134. Local-Only Mode
Application can enforce:
no Internet
Then routing considers only:
LAN
Wi-Fi Direct/Aware
Bluetooth
mesh
DTN
Useful for private/offline deployments.
135. Internet-Only Mode
Some enterprise policy may forbid proximity.
Then:
Iroh direct/relay
only.
136. Nearby-Only Mode
Useful for disaster/private transfer:
LAN
Wi-Fi Direct
Wi-Fi Aware
Bluetooth
mesh
No Internet paths.
137. Route Scope
#![allow(unused)] fn main() { pub enum RouteScope { Any, InternetOnly, LocalOnly, NearbyOnly, } }
Applications can request a scope.
138. Emergency Override
Emergency policy may override:
user preference to avoid relay
only if the user explicitly enabled such emergency behavior.
Do not silently violate user privacy choices.
139. User Consent
Policies involving:
cellular charges
relay usage
relay storage
nearby forwarding
should have explicit product-level consent settings.
Routing consumes the resulting policy.
140. Bandwidth Reservation
Future call + file coexistence:
reserve bandwidth for realtime audio/video
Bulk transfer yields.
Routing/scheduler can coordinate class-based quotas.
141. Traffic Shaping
Per-class rate caps:
Bulk max 5 Mbps while call active
Background max 1 Mbps
This avoids call degradation.
142. Connection Admission
Limit:
max simultaneous peer sessions
max expensive radio sessions
Routing may reject or defer low-priority new connections.
143. Thermal Awareness
On mobile/desktop:
thermal pressure
may reduce:
multipath
Wi-Fi Direct setup
background bulk
Media subsystem also adapts separately.
144. Memory Pressure
Under memory pressure:
reduce route queues
pause bulk acquisition
drop stale realtime packets
Durable operations remain persisted.
145. Transport Adapter Contract
Each adapter should report:
availability
capabilities
health
metrics
setup cost
current session state
and support:
connect/acquire
close
send/stream
146. Iroh Adapter
Reports:
direct vs relay path
RTT
session availability
address info
but routing API should not expose Iroh-specific types upward.
147. LAN Adapter
Reports:
local reachability
interface
estimated throughput class
Identity/authentication still applies.
148. Bluetooth Adapter
Reports:
BLE vs Classic
proximity
estimated bandwidth
paired/available state
Do not use Bluetooth MAC as identity.
149. Wi-Fi Direct/Aware Adapter
Reports:
support
current group/session
setup cost
available bandwidth class
background restrictions
150. DTN Adapter
General routing sees:
store-and-forward path available
with:
uncertain latency
delivery probability
replication policy
Detailed peer encounter logic remains in Part 06.
151. Route Probability
For DTN/mesh, exact RTT may be unknown.
Use:
delivery likelihood
expected delay class
instead of fake precise latency.
152. Metric Types Must Match Reality
Do not force:
Bluetooth RSSI
Iroh RTT
DTN encounter probability
into one misleading number.
Use typed metric categories, then derive normalized scoring.
153. Scoring Normalization
A scorer can normalize:
LatencyScore
BandwidthScore
EnergyScore
ReliabilityScore
CostScore
then combine with policy weights.
154. Policy Weight Example
#![allow(unused)] fn main() { RouteWeights { latency: 0.30, bandwidth: 0.20, reliability: 0.25, energy: 0.15, cost: 0.10, } }
Do not expose floating-point tuning directly to ordinary users.
Profiles configure these internally.
155. Integer Score Option
For deterministic portability, use fixed-point/integer score.
Example:
0..10_000
Avoid floating point if reproducibility matters.
156. Route Decision Logging
Log:
operation id
selected path
reason codes
candidate count
policy profile
not payload content.
157. Developer Diagnostics
Advanced screen can show:
Destination: Bob Phone
Selected: Iroh Direct
Score: 8240
Fallback: Iroh Relay
Reason: existing session + low RTT
Useful for field testing.
158. Route History
Keep bounded recent history:
last N decisions
for diagnostics.
Do not retain indefinitely.
159. Telemetry Export
If enabled:
aggregate route success
direct/relay ratio
failover rate
Redact peer identity.
160. API Example: Text Message
#![allow(unused)] fn main() { let req = RouteRequest::for_device(bob_phone) .class(DeliveryClass::Interactive) .priority(Priority::Normal) .estimated_size(512) .allow_dtn(true); let decision = router.plan(req).await?; }
161. API Example: Large File
#![allow(unused)] fn main() { let req = RouteRequest::for_device(bob_laptop) .class(DeliveryClass::Bulk) .priority(Priority::Low) .estimated_size(file_size) .allow_metered(false) .allow_multipath(true); }
162. API Example: SOS
#![allow(unused)] fn main() { let req = RouteRequest::for_account(target) .class(DeliveryClass::DelayTolerant) .priority(Priority::Critical) .allow_dtn(true) .allow_redundancy(true) .expiry(sos_expiry); }
163. API Example: Video Call
#![allow(unused)] fn main() { let req = RouteRequest::for_device(peer) .class(DeliveryClass::Realtime) .priority(Priority::High) .min_bandwidth(required_video_rate) .max_latency(Duration::from_millis(200)) .allow_dtn(false); }
164. Route Result Report
Transport/session reports:
#![allow(unused)] fn main() { pub struct RouteResultReport { pub path_id: PathId, pub operation_id: OperationId, pub outcome: RouteOutcome, pub observed_metrics: ObservedMetrics, } }
This closes feedback loop.
165. Route Outcome
Success
Timeout
ConnectionFailed
AuthenticationFailed
RemoteRejected
PolicyBlocked
Partial
Cancelled
166. Partial Outcome
Useful for:
file transfer
Routing can report:
bytes transferred before failure
Feature layer uses it for resume.
167. Cancellation
Route acquisition and send operations must support cancellation.
Example:
user cancels file
Stop:
path acquisition
queued operation
retry timer
where safe.
168. Graceful Path Switch
For long-lived sessions:
prepare new path
↓
authenticate
↓
transfer state
↓
switch
↓
close old path
Avoid dropping old route before new one is ready if seamless handoff is possible.
169. Make-Before-Break
Use when:
call
large transfer
and policy permits.
This reduces interruption.
170. Break-Before-Make
Use when:
resource constrained
security requires old path termination
Make strategy explicit.
171. Multi-Device Route Aggregation
Account target may use:
parallel routes to multiple devices
with per-device plan.
Do not flatten all devices into one route score.
172. Device Preference
Application may mark:
primary device
preferred file device
call-capable device
Routing uses as policy input, not immutable identity.
173. Group Routing
Group messaging does not mean:
one path to group
It may:
fan out to devices
or use group dissemination protocol
Routing provides per-destination transport choices.
174. Broadcast Routing
Emergency/local broadcast may use:
local dissemination
mesh
DTN
with separate duplication controls.
Do not reuse ordinary unicast blindly.
175. Route Constraints by Content Sensitivity
High-sensitivity content may forbid:
untrusted store-and-forward
even if encrypted, depending on application policy.
Represent:
forwarding_allowed
relay_allowed
explicitly.
176. Storage Cost
DTN route has storage cost.
Route policy can consider:
relay storage quota
local storage pressure
before accepting large bundles.
177. Route Planning Under Storage Pressure
If:
DTN store nearly full
prefer:
direct path
or reject/defer low-priority bulk traffic.
178. Emergency Storage Override
Critical SOS may evict:
expired
low-priority
bulk
DTN items according to Part 17/06 policy.
General routing marks priority.
179. Route Policy Persistence
Persist user/application settings.
Do not persist transient:
current best score
RTT samples
as authoritative policy.
180. Dynamic Policy Update
Policy can change at runtime:
user enables battery saver
emergency mode starts
call begins
Routing re-evaluates relevant active operations.
181. Call-Induced Policy Change
During call:
bulk file traffic throttled
realtime priority increased
path switching hysteresis increased
After call:
normal policy restored
182. Emergency-Induced Policy Change
Emergency mode may:
enable proximity
allow DTN
increase critical queue weight
while still honoring user opt-in and safety constraints.
183. Testing Matrix
Test combinations:
direct + relay
LAN + Internet
Wi-Fi + BLE
BLE only
DTN only
metered only
battery saver
background restricted
for each delivery class.
184. Route Selection Golden Tests
Example expected cases:
Existing direct healthy + text
→ direct
Direct degraded + relay stable + text
→ relay
Large file + unmetered LAN
→ LAN
Typing + only DTN
→ reject/drop
SOS + Internet unavailable + BLE mesh
→ DTN/mesh
185. Property Tests
Invariants:
revoked device never selected
forbidden transport never selected
expired operation never retried
realtime never routed through DTN
hard minimum bandwidth respected
186. Fuzzing
Fuzz:
route request parser if network-exposed
policy config parsing
metrics updates
candidate sets
state transitions
Routing is mostly internal, but malformed transport telemetry should not panic.
187. Benchmarking
Benchmark:
candidate scoring
route planning
cache lookup
path update
large peer sets
Target route decision should be very fast relative to network operations.
188. Scalability
Do not linearly rescore thousands of irrelevant candidates for every packet.
Cache per-peer candidates.
Route at:
operation/session level
not per small network packet.
189. Call Routing Frequency
For calls, quality metrics update frequently.
Do not rerun full planner every frame.
Use:
path monitor
and trigger reevaluation only when thresholds cross.
190. File Routing Frequency
For files:
reevaluate on:
path failure
significant quality change
new superior high-bandwidth path
policy change
not per chunk.
191. Message Routing Frequency
Each message can reuse:
healthy session route
until invalidated.
No need for expensive full scoring every time.
192. Architecture Modules
Recommended crate:
comm-routing/
├── src/
│ ├── lib.rs
│ ├── request.rs
│ ├── requirements.rs
│ ├── candidate.rs
│ ├── metrics.rs
│ ├── scorer.rs
│ ├── policy.rs
│ ├── planner.rs
│ ├── health.rs
│ ├── cache.rs
│ ├── scheduler.rs
│ ├── retry.rs
│ ├── diagnostics.rs
│ └── error.rs
193. Related Crates
comm-transport
comm-discovery
comm-session
comm-identity
comm-dtn
comm-types
The routing crate should not import:
Dioxus
Kotlin
Android APIs
messenger UI
194. Error Types
#![allow(unused)] fn main() { pub enum RoutingError { NoCandidate, PolicyConflict, IdentityResolution, TransportUnavailable, ResourceLimit, Cancelled, Internal, } }
195. No anyhow in Public Routing API
Use typed errors.
anyhow remains acceptable at top-level application bootstrap.
196. Initial Production Scope
Implement first:
candidate collection
hard constraints
weighted scoring
direct/relay/LAN/Bluetooth/DTN categories
failover
route cache
hysteresis
retry policy
bounded queues
diagnostics
Defer:
true multipath aggregation
advanced redundancy optimization
predictive route learning
ML
197. Implementation Phases
Phase 1 — Types and policy
Implement:
DeliveryRequirements
PathCandidate
PathMetrics
RoutingPolicy
RoutePlan
Phase 2 — Candidate collection
Integrate:
Iroh
LAN
Bluetooth
Wi-Fi
Phase 3 — Scoring
Implement:
hard constraints
weighted scores
existing-path preference
Phase 4 — Failover
Implement:
fallback plan
retry policy
hysteresis
Phase 5 — DTN
Integrate:
delay-tolerant route option
Phase 6 — Resource scheduling
Implement:
priority queues
fairness
backpressure
Phase 7 — Diagnostics/testing
Implement:
reason codes
route history
simulation
property tests
benchmarks
198. Definition of Done
Part 03 is complete when:
- applications submit delivery intent, not transport names
- account destinations resolve to device paths
- all path candidates are normalized
- hard constraints eliminate invalid paths
- remaining paths are scored deterministically
- existing healthy paths are reused
- direct/relay/LAN/Bluetooth/DTN can coexist
- failover works
- path switching uses hysteresis
- policy conflicts defer/reject explicitly
- routing honors metered/battery/background policy
- queues are bounded
- bulk traffic cannot starve control traffic
- DTN is supported for eligible durable traffic
- realtime traffic never routes through DTN
- routing provides reason codes/diagnostics
- route state survives process restart only as hints
- security/revocation always outrank route quality
- routing is reusable by messaging, files, calls, emergency, ERP
- simulated path tests cover failures and transitions
199. Relationship to Other Parts
Part 03 depends on:
01 — Protocol Extension System
02 — Multi-Device Identity
It feeds directly into:
04 — Offline Event Log
05 — Robust File / Blob Subsystem
06 — DTN / Store-Carry-Forward
07 — Capability Negotiation Expansion
08 — Resource Limits & Backpressure
11 — Relay / Self-Hosted Infrastructure
12 — Multipath Networking
13 — Battery-Aware Scheduling
14 — Proximity Abstraction
17 — Emergency Priority Architecture
18 — Network Diagnostics & Path Visualization
200. Final Principle
The transport/routing policy engine should make this application-level request possible:
"Deliver this securely to Bob.
It is a normal interactive message.
It may use DTN.
It should avoid metered data if possible."
without the messaging layer knowing whether delivery ultimately occurs through:
Iroh direct
Iroh relay
LAN
Wi-Fi Direct
Bluetooth
mesh
DTN
That separation is what makes the communication platform adaptable, reusable, power-aware, resilient, and capable of surviving both ordinary network changes and severe infrastructure failure.