Part 01 — Protocol Extension System Architecture
Reusable P2P Communication Platform
Status: Architecture specification
Part: 01 of 24
Primary language: Rust
Core transport: Iroh-first, transport-neutral architecture
Primary goals: extensibility, interoperability, safety, forward compatibility, modularity, zero unnecessary coupling
1. Purpose
The reusable communication platform must support future capabilities without turning the core protocol into a monolith.
The protocol extension system provides a controlled mechanism for adding new application-level protocols and features such as:
- messaging
- files
- group messaging
- presence
- receipts
- emergency communication
- device synchronization
- collaboration events
- ERP-specific payloads
- custom application features
- future experimental protocols
without requiring every node to implement every feature.
The extension system must preserve:
compatibility
security
resource limits
version negotiation
independent deployment
capability discovery
transport neutrality
The goal is not a dynamic-plugin system for arbitrary untrusted code.
The goal is a versioned protocol capability architecture.
2. Fundamental Principle
Do not design:
One giant protocol enum
├── Message
├── File
├── Presence
├── Emergency
├── Call
├── FutureFeature1
├── FutureFeature2
└── ...
That creates:
- central coupling
- large breaking changes
- forced feature support
- difficult third-party integration
- difficult protocol evolution
Instead:
Communication Session
│
├── Core Control Protocol
│
├── Messaging Extension
│
├── File Extension
│
├── Presence Extension
│
├── Emergency Extension
│
└── Application Extensions
Each extension is:
- independently identified
- independently versioned
- capability-negotiated
- size-limited
- authenticated
- transport-independent
- optional
3. Protocol Layers
Application
↓
Extension Protocol
↓
Session Multiplexer
↓
Core Protocol
↓
Transport
↓
Iroh / LAN / Bluetooth / Wi-Fi / DTN
Responsibilities:
Transport
Moves bytes.
Core protocol
Provides:
- connection/session bootstrap
- protocol negotiation
- capabilities
- authentication binding
- extension discovery
- error framing
- flow-control metadata
Extension protocol
Implements a reusable feature.
Examples:
messaging
files
presence
groups
emergency
Application protocol
Implements product-specific semantics on top of extension support.
4. Core Protocol Must Stay Small
The core protocol should know only what every peer needs.
Recommended responsibilities:
Hello
ProtocolVersion
PeerIdentityBinding
CapabilityAdvertisement
ExtensionAdvertisement
ExtensionOpen
ExtensionClose
Ping/Pong
Error
Shutdown
It should not know:
chat message format
file metadata
group membership
SOS payload
ERP business object
Those belong elsewhere.
5. Protocol Namespace
Every extension must have a stable identifier.
Recommended structure:
<organization>/<protocol>/<major-version>
Examples:
org.example.comm/messaging/1
org.example.comm/files/1
org.example.comm/presence/1
org.example.comm/emergency/1
Human-readable canonical names are useful for:
- documentation
- diagnostics
- interoperability
- test vectors
- configuration
A compact session-local numeric ID can be negotiated after handshake.
6. Strong Protocol Identifiers
Do not use arbitrary strings throughout the runtime.
#![allow(unused)] fn main() { pub struct ProtocolId { pub namespace: NamespaceId, pub protocol: ProtocolName, pub major: ProtocolMajor, } }
If hashes are later used for compact wire representation, collision handling must be explicit.
A safer initial design is:
bounded canonical string during negotiation
↓
session-local numeric identifier afterward
7. Major and Minor Versions
Use explicit compatibility semantics.
Major version
Wire-incompatible change.
messaging/1
messaging/2
Peers sharing no major version cannot use that extension together.
Minor version
Backward-compatible feature expansion within the same major version.
Messaging v1.4
may communicate with:
Messaging v1.2
using the common feature subset.
8. Capability Negotiation
Version alone is insufficient.
Messaging capabilities might include:
text
reply
edit
reaction
read_receipt
typing
group_message
custom_content
File capabilities might include:
range_resume
parallel_chunks
content_addressing
encrypted_blob
directory_manifest
The effective feature set is:
local capabilities ∩ remote capabilities
9. Capability Representation
Use strong compact identifiers.
#![allow(unused)] fn main() { pub struct CapabilityId(pub u32); pub struct CapabilitySet { pub values: Vec<CapabilityId>, } }
For very small capability sets, SmallVec may reduce allocation.
Avoid hot-path capability checks based on arbitrary strings.
Maintain a registry mapping IDs to human-readable names for diagnostics.
10. Negotiation Flow
Peer A
|
| HELLO
| core-version=1
| extensions:
| messaging/1 [text, reply, edit]
| files/1 [resume, chunking]
|
v
Peer B
|
| HELLO_ACK
| core-version=1
| negotiated:
| messaging/1 [text, reply]
| files/1 [resume]
|
v
Session Ready
Application traffic requiring an extension must not begin until that extension has been negotiated.
11. Mandatory and Optional Extensions
A consumer may declare:
#![allow(unused)] fn main() { pub enum ExtensionRequirement { Required, Optional, } }
Example file product:
files = required
messaging = absent
Example messenger:
messaging = required
files = optional
presence = optional
An unsupported optional extension must not tear down the whole session.
12. Extension Registry
#![allow(unused)] fn main() { pub trait ProtocolExtension: Send + Sync { fn descriptor(&self) -> ExtensionDescriptor; fn create_handler( &self, negotiated: NegotiatedExtension, ) -> Result<Box<dyn ExtensionHandler>, ExtensionError>; } }
Registry:
#![allow(unused)] fn main() { pub struct ExtensionRegistry { // protocol id -> implementation } }
Build the registry explicitly during runtime construction.
Avoid mandatory global static registries.
13. Runtime Construction
#![allow(unused)] fn main() { let runtime = CommunicationRuntime::builder() .register_extension(MessagingExtension::new(config)) .register_extension(FileExtension::new(file_config)) .build() .await?; }
A file-only application:
#![allow(unused)] fn main() { let runtime = CommunicationRuntime::builder() .register_extension(FileExtension::new(file_config)) .build() .await?; }
This is the intended reuse model.
14. Extension Isolation
Extensions must not reach directly into each other's private state.
Bad:
MessagingExtension
↓ direct internal access
FileExtension
Good:
MessagingExtension
↓
ContentReference API
↓
File capability
or application-level composition.
This prevents circular coupling.
15. Shared Services
Some infrastructure is legitimately shared:
identity
crypto
session
clock
scheduler
metrics
resource policy
Expose constrained handles, not the entire runtime.
#![allow(unused)] fn main() { pub struct ExtensionContext { pub identity: IdentityHandle, pub session: SessionHandle, pub scheduler: SchedulerHandle, pub resources: ResourcePolicy, } }
Avoid:
#![allow(unused)] fn main() { Arc<EntireRuntime> }
inside every extension.
16. Logical Channel Model
When transport supports multiplexing:
Session
├── Core control
├── Messaging
├── File control
├── File data stream(s)
├── Presence/datagram-like traffic
└── Calls/media
Large file traffic must not head-of-line-block control or messaging traffic.
17. Session-Local Extension IDs
After negotiation:
messaging/1 → 7
files/1 → 9
presence/1 → 12
The numeric mapping is session-local.
This reduces repeated framing overhead while retaining stable global protocol identities.
18. Framing
Every extension frame must be bounded.
Conceptually:
FrameLength
ExtensionSessionId
FrameType
Flags
Payload
Before allocation:
read bounded header
validate length
check extension limit
allocate/read safely
Never trust remote length fields.
19. Per-Extension Resource Limits
#![allow(unused)] fn main() { pub struct ExtensionLimits { pub max_frame_size: usize, pub max_in_flight_frames: usize, pub max_concurrent_streams: usize, pub max_buffered_bytes: usize, } }
Messaging:
small frames
moderate concurrency
Files:
streaming
bounded chunk buffers
possibly several streams
Presence:
very small frames
high discardability
20. Backpressure
Extension producer
↓
bounded queue
↓
session scheduler
↓
transport
A slow Bluetooth or DTN route must never produce:
unlimited queued file chunks
↓
out-of-memory
Backpressure is mandatory, not optional optimization.
21. Traffic Priority
#![allow(unused)] fn main() { pub enum TrafficPriority { Critical, Control, Interactive, Normal, Bulk, Background, } }
Examples:
SOS → Critical
Receipt → Control
Text → Interactive
Thumbnail → Normal
File chunk → Bulk
Background sync → Background
22. Fair Scheduling
Do not permanently starve bulk traffic.
Use:
weighted fair scheduling
+
strict bounded emergency override
rather than naive perpetual highest-priority-first scheduling.
23. Extension Lifecycle
Registered
↓
Advertised
↓
Negotiated
↓
Opening
↓
Active
↓
Closing
↓
Closed
Failures:
Rejected
Unsupported
VersionMismatch
ProtocolError
Lifecycle state must be explicit.
24. Lazy Extension Opening
Capability negotiation does not mean immediate heavy initialization.
Example:
files capability negotiated
↓
file extension dormant
↓
user sends first file
↓
OPEN_EXTENSION
↓
initialize transfer machinery
This saves CPU, memory, storage handles and battery on mobile.
25. Lazy Initialization Targets
Particularly suitable for:
calls
video
camera
file hashing
large media indexes
nearby radios
Do not initialize expensive subsystems merely because the binary contains them.
26. Extension Shutdown
Graceful close:
stop accepting new work
finish/persist critical state
send close when useful
release buffers
Abrupt close:
transport disappears
persist resumable state
mark recoverable work
Correctness must not depend on graceful shutdown.
27. Typed Extension Errors
#![allow(unused)] fn main() { pub enum ExtensionError { Unsupported, VersionMismatch, CapabilityMismatch, ResourceLimit, ProtocolViolation, Unauthorized, StorageFailure, Internal, } }
Wire errors should use stable codes.
Internal debug strings must not become protocol semantics.
28. Protocol Violation Classification
Classify violations as:
Recoverable
Extension-fatal
Session-fatal
Peer-abusive
Examples:
unknown optional frame → Recoverable
oversized malicious frame → Peer-abusive
authentication failure → Session-fatal
invalid file state → Extension-fatal
29. Unknown Extensions
If a peer advertises an unknown optional extension:
ignore or mark unsupported
Do not fail the entire connection.
This is fundamental for forward compatibility.
30. Unknown Capabilities
Within a known extension:
unknown optional capability
→ ignore
unknown required capability
→ reject extension operation/negotiation
The protocol must distinguish optional from required capability semantics.
31. Operation-Level Required Capabilities
An operation may require a specific capability.
Example:
EditMessage
requires messaging.edit
If the peer lacks it:
do not send unsupported wire operation
The application may:
disable the action
send a new message instead
show unsupported
32. Security Requirements Per Extension
#![allow(unused)] fn main() { pub struct SecurityRequirements { pub authenticated_peer: bool, pub e2ee_required: bool, pub authorization_required: bool, pub allow_anonymous: bool, } }
Messaging likely requires:
authenticated = true
E2EE = true
Public emergency broadcast can use different semantics but still needs explicit signature and authorization rules.
33. Authorization Hooks
Extensions should not invent product-specific authorization internally.
#![allow(unused)] fn main() { pub trait ExtensionAuthorization { async fn authorize( &self, peer: PeerIdentity, operation: OperationDescriptor, ) -> AuthorizationDecision; } }
Examples:
Messenger → block/contact policy
ERP → organization/role policy
Emergency → authority/priority policy
34. Namespaced Application Extensions
Examples:
com.schoolerp/document-alert/1
com.rescue/incident/1
org.example/messaging/1
Namespaces prevent accidental interpretation between unrelated products.
35. Extension Descriptor
#![allow(unused)] fn main() { pub struct ExtensionDescriptor { pub id: ProtocolId, pub version: ExtensionVersion, pub capabilities: CapabilitySet, pub requirements: ExtensionRequirements, pub limits: ExtensionLimits, } }
Used for:
- negotiation
- documentation
- diagnostics
- testing
- compatibility tooling
36. Generated Documentation
Typed descriptors allow tooling to generate:
supported extensions
version table
capabilities
resource limits
security requirements
This reduces documentation drift.
37. Wire Schema Ownership
Each extension owns its wire schema.
Example:
comm-messaging/protocol/v1/
comm-files/protocol/v1/
comm-emergency/protocol/v1/
Do not directly serialize application domain types.
38. Domain Types vs Wire Types
Bad:
one Message struct used by:
UI + DB + wire + domain
Good:
DomainMessage
↓ validated conversion
WireMessageV1
↓ serialization
bytes
This allows protocol evolution independently of UI/database evolution.
39. Serialization Discipline
Postcard is suitable for compact Rust-oriented binary payloads, but enforce:
- explicit size limits
- fixed-width protocol-relevant integers
- versioned enums
- bounded strings/vectors
- semantic validation after decode
- golden compatibility tests
Avoid usize as a wire-semantic field.
40. Low-Copy Strategy
Use low-copy types where large payloads justify them:
Bytes
Arc<[u8]>
borrowed slices
streamed file chunks
Do not overcomplicate tiny control frames solely to chase zero-copy.
The priority order is:
correctness
bounded memory
simple ownership
measured optimization
41. Extension Events
Prefer feature-specific event types.
Messaging:
MessageReceived
ReceiptReceived
TypingChanged
Files:
TransferStarted
TransferProgress
TransferCompleted
The high-level client may optionally aggregate them.
42. Avoid a Mandatory Giant Event Enum
If every feature must import every event variant, modularity is weakened.
Prefer:
CoreEvent
MessagingEvent
FileEvent
PresenceEvent
with optional aggregation for applications that want one stream.
43. Public SDK Surface
Applications should normally use:
CommunicationClient
MessagingClient
FileTransferClient
PresenceClient
not raw extension handlers.
Extension internals remain replaceable.
44. Peer Capability Query
#![allow(unused)] fn main() { let caps = client.peer_capabilities(peer).await?; if caps.supports(MESSAGING_V1) { // enable messaging UX } if caps.supports(FILES_V1) { // enable file-send UX } }
Consumers can adapt without hard-coding transport details.
45. Capability Cache
Persist a hint cache:
peer
protocol versions
capabilities
last observed
expiry/source
But authenticate and renegotiate on a fresh session.
Cached capabilities are hints, not security truth.
46. Capability Changes
Capabilities can change because of:
- application upgrade
- feature disablement
- permissions
- hardware availability
- platform changes
- policy changes
Therefore they are not immutable identity data.
47. Stability Classification
#![allow(unused)] fn main() { pub enum ExtensionStability { Stable, Experimental, Internal, } }
Experimental protocols should require explicit opt-in in production builds.
48. Private/Enterprise Extensions
Enterprise software may define:
com.company/internal-workflow/1
without modifying the core protocol.
That is a first-class design goal.
49. Third-Party Extension Loading
Initial recommendation:
compile-time Rust crate integration
not arbitrary runtime-loaded native plugins.
Benefits:
- stronger typing
- smaller attack surface
- mobile compatibility
- easier signing/auditing
- predictable lifecycle
Runtime plugin architecture belongs to a later dedicated part.
50. FFI Boundary
Do not design the internal extension API around C ABI limitations yet.
If external-language integration becomes required, expose a separate:
comm-ffi
with opaque handles and stable events.
Internal Rust APIs can remain ergonomic and strongly typed.
51. Transport Neutrality
Extension payloads must not require:
Iroh Endpoint IDs
Bluetooth MAC addresses
IP addresses
Wi-Fi handles
unless a specific protocol explicitly models transport metadata.
Use abstract peer/session identities.
52. Delivery Classes
#![allow(unused)] fn main() { pub enum DeliveryClass { Realtime, ReliableInteractive, Durable, DelayTolerant, } }
Examples:
Typing → Realtime
Text → Durable
SOS → DelayTolerant + Critical
Video frame → Realtime
File chunk → Durable/DelayTolerant depending policy
This informs routing.
53. Routing Requirements Per Operation
An operation can declare:
realtime requirement
maximum age
durability
forwarding permission
size class
priority
The routing engine, not the extension, chooses the concrete network path.
54. Resource Accounting
Track per extension:
memory
network bytes
stored bytes
queue depth
active streams
CPU-heavy operations
This supports:
- diagnostics
- quotas
- mobile battery policy
- abuse protection
55. Per-Peer Quotas
Limit:
frames/sec
bytes/sec
concurrent streams
queued operations
DTN storage
file transfers
Policies may vary by trust level.
56. Abuse Handling
The runtime needs escalating controls:
rate limit
pause extension
close extension
quarantine peer
close session
A malicious file stream should not corrupt or disable unrelated messaging state unless necessary for overall security.
57. Observability
Trace fields:
peer_id
extension_id
version
frame_type
operation_id
duration
bytes
result
Never log sensitive payload contents or keys.
58. Metrics
Useful extension metrics:
negotiation success
open latency
frames sent/received
protocol violations
queue depth
backpressure activations
unsupported capability count
version mismatch count
Local metrics should work without external telemetry.
59. Diagnostics
Example diagnostic view:
Active extensions:
messaging/1
text
reply
receipts
files/1
resume
chunking
Unsupported remote extensions:
com.example/custom/2
60. Compatibility Matrix
Each stable extension must test:
v1.0 ↔ v1.0
v1.0 ↔ v1.1
v1.1 ↔ v1.2
old subset ↔ new superset
Major incompatibility should fail cleanly and predictably.
61. Golden Wire Tests
Maintain test vectors:
Rust value
↓
expected exact stable bytes
↓
decode back to equivalent wire value
Unexpected stable-wire changes should fail CI.
62. Fuzzing
Fuzz:
core hello
extension advertisement
capabilities
extension open
frame parser
version parser
oversized lengths
invalid states
unknown fields
Each extension owns additional fuzz targets.
63. Property Tests
Important invariants:
encode/decode round trip
unknown optional extension does not kill session
required unknown capability is rejected
duplicate advertisement is deterministic
invalid length cannot trigger unbounded allocation
64. Simulated Peer Testing
Example:
Peer A:
messaging/1
files/1
Peer B:
messaging/1
Expected:
messaging works
files unsupported
session remains valid
65. Upgrade Example
Peer A:
files/1
files/2
Peer B:
files/1
Negotiate:
files/1
Peer C:
files/2
A ↔ C uses:
files/2
This enables gradual protocol migration.
66. Multiple Major Versions
An implementation may temporarily support several majors:
files/protocol/v1
files/protocol/v2
Convert into common domain models where semantics permit.
67. Deprecation Lifecycle
Supported
↓
Deprecated
↓
Disabled by default
↓
Removed
Publish timelines.
Do not suddenly remove compatible wire protocols unless security requires it.
68. Security Deprecation
If a protocol version becomes unsafe:
mark insecure
disable it
provide diagnostic
require upgrade where necessary
Security outranks backward compatibility.
69. Extension Persistence
Extensions may own durable state via dedicated repositories.
Messaging:
messages
outbox
receipts
Files:
transfer journal
verified chunks
Protocol handlers should not write arbitrary product database tables directly.
70. Wire vs Database Migration
These are separate concerns.
Example:
messaging wire protocol v1
can coexist with:
local database schema v7
Do not tie them together.
71. ERP Custom Extension Example
com.example.erp/approval/1
Can reuse:
identity
crypto
session
routing
DTN
without changing messaging or files.
72. Emergency Extension Design
Potential protocol families:
emergency-sos/1
emergency-alert/1
emergency-resource/1
Critical fields include:
priority
expiry
signature authenticity
DTN permission
location privacy semantics
73. File Extension Example
files/1
Capabilities:
manifest
range request
resume
parallel chunks
content addressing
encrypted metadata
Streams:
control
data-0
data-1
...
No messaging dependency.
74. Messaging Extension Example
messaging/1
Capabilities:
text
reply
edit
reaction
delivery receipt
read receipt
custom content reference
Attachments are represented as content/blob references.
Actual transfer belongs to files/1.
75. Presence Extension Example
presence/1
Properties:
small frames
short expiry
usually not DTN
loss tolerant
Possible capabilities:
basic presence
typing
activity hint
76. Calls and Media Extensions
Separate call control from media transport where useful:
calls/1
media/1
Capabilities may include:
audio codecs
video codecs
resolution
frame rate
hardware/software capability
Codec implementation remains outside the core protocol.
77. Protocol Composition
One product can negotiate:
messaging/1
files/1
presence/1
calls/1
emergency/1
custom-app/1
without creating a central monolith.
78. Core Handshake State Machine
Transport Connected
↓
Core Hello
↓
Identity Binding
↓
Core Version Agreement
↓
Extension Advertisement
↓
Capability Negotiation
↓
Session Established
↓
Lazy Extension Opens
Authentication failure stops application-level use.
79. Reconnection
Cached negotiation can speed reconnection, but peers must revalidate:
identity
protocol compatibility
capability validity
Never blindly trust stale session metadata.
80. Mobile Efficiency
On Android/iOS:
- lazy-open heavy extensions
- stop ephemeral services when backgrounded
- persist durable work
- reopen after resume
- use tight queues
- obey battery policy
- avoid starting media/files if unused
This architecture directly supports mobile efficiency.
81. Headless Nodes
A headless node can register:
files
DTN
relay
discovery
without:
Dioxus
messaging UI
calls
Useful for:
Raspberry Pi
NAS
server
emergency gateway
enterprise node
82. Compile-Time Features
Example:
[features]
default = ["core"]
messaging = ["dep:comm-messaging"]
files = ["dep:comm-files"]
presence = ["dep:comm-presence"]
dtn = ["dep:comm-dtn"]
calls = ["dep:comm-calls"]
Compile-time features choose which code is present.
Runtime negotiation chooses what peers actually use.
83. Binary Size
This prevents a file-only CLI from pulling in:
Dioxus
AV1
camera
messenger UI
unless requested.
This is a major benefit for reusable software.
84. Typed Extension Configuration
Messaging:
#![allow(unused)] fn main() { pub struct MessagingConfig { pub max_message_size: usize, pub receipts: bool, pub editing: bool, } }
Files:
#![allow(unused)] fn main() { pub struct FileConfig { pub chunk_size: usize, pub max_parallel_chunks: usize, pub max_file_size: u64, } }
Avoid untyped generic configuration maps for core behavior.
85. Configuration Validation
Validate before opening network listeners.
Example invalid configuration:
chunk size > extension maximum frame size
Fail fast during runtime construction.
86. Extension Dependencies
Represent dependencies explicitly:
required dependency
optional integration
Example:
messaging
optional integration → files
Messaging itself must continue working without files.
87. Integration Interfaces
Messaging can depend on an abstract resolver:
#![allow(unused)] fn main() { pub trait ContentResolver { async fn resolve( &self, reference: ContentReference, ) -> Result<ResolvedContent, ResolveError>; } }
The file subsystem can provide an implementation.
This preserves modularity.
88. Core vs First-Party Extensions
Classify protocols:
Core-maintained
First-party optional
Third-party
Experimental
Messaging should not be forced into the core merely because the flagship application uses it.
89. Extension Provenance
For compile-time extensions:
crate review
supply-chain controls
binary signing
release provenance
are sufficient initially.
Runtime-loaded plugin signing belongs to the later plugin/module architecture.
90. Interoperability Specification
Each stable extension must document:
protocol ID
versions
capabilities
wire schema
state machine
limits
security rules
error codes
test vectors
This allows non-Rust implementations later.
91. Rust Is the Reference, Not the Wire Format
Never depend on:
native enum layout
usize width
pointer size
native endian
Rust-only implementation details
All wire semantics must be explicit.
92. Postcard Rules
If Postcard is used:
- use fixed-width integers where semantics matter
- avoid
usizeon wire - version enum formats carefully
- bound collections
- keep golden test vectors
- validate decoded values
93. Error Code Strategy
Prefer extension-scoped stable codes.
Example:
core: 0x0000–0x00FF
messaging: 0x0100–0x01FF
files: 0x0200–0x02FF
or local error spaces scoped by negotiated extension ID.
Human-readable text is diagnostic only.
94. Extension Health
#![allow(unused)] fn main() { pub struct ExtensionHealth { pub state: ExtensionState, pub queue_depth: usize, pub active_operations: usize, pub last_error: Option<ExtensionErrorSummary>, } }
Useful for:
diagnostics
automated recovery
support bundles
UI health indicators
95. Recovery Semantics
Classify operations:
Retryable
Resumable
Discardable
Expired
Examples:
text message → Retryable
file transfer → Resumable
typing → Discardable
video frame → Discardable
expired SOS → Expired
96. Scheduler Contract
Extensions submit:
priority
deadline
payload size
delivery class
peer
durability
The central scheduler chooses:
transport
queue
retry policy
Extensions declare requirements; routing executes policy.
97. Storage Isolation
Use separate logical namespaces:
messaging/
files/
presence/
emergency/
custom/
A migration bug in one extension should not corrupt unrelated state.
98. Metrics Isolation
Examples:
comm_frames_sent{extension="messaging"}
comm_bytes_sent{extension="files"}
Avoid unbounded metric labels such as full peer IDs in aggregated telemetry.
99. Capability Isolation
Applications should receive only capability handles they are allowed to use.
Example:
ERP document module
can access files
cannot access messaging
This supports least privilege inside larger products.
100. Public API Example
#![allow(unused)] fn main() { let runtime = CommunicationRuntime::builder() .identity(identity) .transport(iroh) .register_extension( MessagingExtension::builder() .text(true) .receipts(true) .build()?, ) .register_extension( FileExtension::builder() .resume(true) .parallelism(4) .build()?, ) .build() .await?; let peer = runtime.connect(peer_addr).await?; let messaging = runtime.messaging()?; let files = runtime.files()?; }
The application does not manipulate low-level handshake internals.
101. File-Only Acceptance Test
#![allow(unused)] fn main() { let runtime = CommunicationRuntime::builder() .identity(identity) .transport(iroh) .register_extension(FileExtension::default()) .build() .await?; }
No messaging crate is required.
If this cannot compile cleanly, the architecture is still too coupled.
102. Custom ERP Extension
com.example.erp/approval/1
can reuse:
identity
crypto
transport
sessions
routing
DTN
without modifying the core protocol.
103. Anti-Patterns
Do not:
put every feature in one enum
make every extension mandatory
serialize domain structs directly
allow unbounded queues
use raw strings for hot capability checks
make Dioxus part of protocol handling
let Kotlin own protocol state
assume Iroh is the only possible transport forever
104. Recommended Crates for This Part
comm-types
comm-protocol-core
comm-extension-api
comm-session
comm-capability
Possible structure:
crates/comm-extension-api/
├── src/
│ ├── lib.rs
│ ├── descriptor.rs
│ ├── registry.rs
│ ├── handler.rs
│ ├── lifecycle.rs
│ ├── capability.rs
│ ├── limits.rs
│ ├── security.rs
│ └── error.rs
└── Cargo.toml
105. Implementation Sequence
Phase 1
Implement:
ProtocolId
ExtensionVersion
CapabilityId
ExtensionDescriptor
ExtensionRegistry
Phase 2
Implement:
Hello
VersionNegotiation
ExtensionAdvertisement
CapabilityNegotiation
Phase 3
Implement:
lazy extension open
lifecycle
bounded framing
Phase 4
Implement:
priority scheduling
backpressure
resource quotas
Phase 5
Convert:
messaging
files
into independent extensions.
Phase 6
Add:
compatibility tests
fuzzing
golden wire tests
diagnostics
106. Definition of Done
Part 01 is complete when:
- messaging and files register independently
- file-only peers work without messaging
- unknown optional extensions do not break sessions
- incompatible required extensions fail deterministically
- capability intersection is negotiated
- frame sizes are bounded
- queues are bounded
- traffic priority exists
- protocol IDs are stable
- wire and domain types are separate
- extensions cannot access unrestricted runtime state
- compatibility tests exist
- fuzz tests exist
- diagnostics show negotiated extensions
- reconnect behavior is deterministic
- heavy extensions can lazy-open on mobile
- custom application extensions can be added without changing core protocol
107. Relationship to the Remaining 23 Parts
This document is foundational.
The remaining architecture sequence is:
02 — Multi-Device Identity
03 — Transport & Routing Policy Engine
04 — Offline Event Log
05 — Robust File / Blob Subsystem
06 — DTN / Store-Carry-Forward
07 — Capability Negotiation Expansion
08 — Resource Limits & Backpressure
09 — Crash Recovery
10 — Protocol Fuzzing & Test Suite
11 — Relay / Self-Hosted Infrastructure
12 — Multipath Networking
13 — Battery-Aware Scheduling
14 — Proximity Abstraction
15 — QR / NFC Bootstrap Pairing
16 — Daemon & Headless Runtime
17 — Emergency Priority Architecture
18 — Network Diagnostics & Path Visualization
19 — C ABI / FFI
20 — Embedded Linux Node
21 — WASM-Compatible Components
22 — Third-Party Protocol Extensions
23 — External Interoperability Suite
24 — Plugin / Module Ecosystem
Later parts should build on the extension contracts rather than bypassing them.
108. Final Principle
The protocol should evolve through independently versioned, negotiated capabilities, not through an ever-growing central enum.
The architecture should allow:
old client
+
new client
+
file-only application
+
messenger
+
ERP
+
emergency node
all to participate in the same communication ecosystem while using only the capabilities they understand.
That is the foundation required to turn the project from one application's protocol into a reusable communication platform.