Guides
Roadmap
Milestones express dependency order, not a rule that all work in an earlier milestone must stop before a later foundation can land. M0–M3 are complete; M4, M5, and M6 each have shipped slices plus explicit remaining acceptance work. Build order details per crate: 09: Implementation Guide.
| Milestone | Status | Principal remaining gate |
|---|---|---|
| M0–M3 | Complete | Permanent regression and assurance work only |
| M4 | In progress | Stand up the physical two-radio nightly bench |
| M5 | In progress | Hands-on mobile qualification and installable distribution |
| M6 | In progress | Broader hardening, reproducibility, store delivery, and external audit |
M0: Design framework (done)
Deliverable: the documentation set in docs/: threat model, architecture, crypto
spec, transport spec, identity model, storage model, ADRs, implementation guide.
Acceptance: docs internally consistent; every architectural decision has an ADR; implementation guide sufficient for a competent Rust developer (or coding agent) to start M1 without design questions.
M1: Cryptographic core (kult-crypto) (done)
Workspace scaffolding + the full crypto layer: primitives wiring, hybrid PQXDH handshake, Double Ratchet with header encryption, fingerprints, key serialization.
Acceptance:
- All test obligations of 04: Cryptography §11 green in CI
(KATs, ratchet property tests, fuzz targets running,
cargo-denyclean). #![forbid(unsafe_code)]; every secret type zeroizes; API compiles asno_std+alloc.- Two in-memory parties complete handshake and exchange 10 000 messages under random
loss/reorder within
MAX_SKIP.
M2: Protocol & storage (kult-protocol, kult-store) (done)
Envelope codec, padding buckets, fragmentation/reassembly, delivery tokens, sealed sender; encrypted SQLite storage with the full key hierarchy; sneakernet bundle import/export (first working transport, needs no networking).
Acceptance:
- Two nodes exchange messages via bundle files end-to-end (write → export → import → read), surviving process restarts (queue persistence).
- Fragmentation round-trips at MTU 180 B with 30 % random fragment loss via NACK/retry.
- Fuzzers on envelope + bundle parsers; storage passes "copied DB file leaks nothing but sizes" review checklist.
M3: Internet transport & headless node (kult-transport, kult-node) (done)
The kult-node runtime is implemented per the build order in
09: Implementation Guide §2: delivery engine
(queued→sent→delivered on encrypted receipts, retry with backoff, dedup,
out-of-order stash), transport scheduler, session lifecycle, command/event API,
running over the sneakernet carrier. The libp2p carrier's first slice is also in:
QUIC (primary) and TCP+Noise+Yamux (fallback) with an envelope request-response
protocol reporting honest next-hop acks; two nodes exchange messages and receipts
over localhost, and the scheduler prefers it over slower carriers. The discovery
plane is in: a Kademlia DHT (bootstrap from any user-supplied peer, nothing
hardcoded) carrying whole-bundle-signed prekey records under the kult-address
digest, so a node adds a contact from the address string alone and the delivery
engine resolves missing return paths (sealed sender reveals none) from the
peer's record. Mailbox relays are in: any node can volunteer bounded
store-and-forward on /komms/mailbox/1; recipients register rotating
delivery tokens as accept-filters and collect on reconnect, senders deposit
sealed envelopes the scheduler ranks below direct paths, and the "relay stores
only sealed envelopes" acceptance criterion is pinned by an inspection test
(collection-deletes required making tokens recipient-scoped, ADR-0007).
NAT traversal is in as the pinned trio: AutoNAT dial-back probes report each
node's reachability (nat_status), a private node reserves a Circuit Relay v2
slot at any public peer (reserve_relay, every node volunteers bounded relay
service, and a fresh relay self-confirms its own address via AutoNAT seconds
after its first peer connects), the returned circuit address is handed out as
an ordinary multiaddr hint, and DCUtR upgrades relayed connections to direct
ones by hole punching. The headless daemon is in: kultd (its own crate,
application A3) runs the full node over the internet carrier: tick loop,
DHT bootstrap and bundle publication, automatic NAT probing with relay
reservation, mailbox check-ins, optional mailbox serving and sneakernet
spool, and exposes the node's command/event API as newline-delimited JSON
RPC on a mode-0600 local Unix socket, with kult as the matching CLI
client; the RPC acceptance test drives two daemons to verified delivery
through their sockets alone. mDNS LAN auto-discovery closes out M3: since
libp2p-mdns still pins the RUSTSEC-flagged hickory-proto 0.25 (and this
workspace ignores no vulnerabilities), the libp2p mDNS discovery profile is
implemented in-tree (ADR-0008), a strict, bounded DNS responder whose
discoveries seed the Kademlia routing table, so two nodes on one LAN
deliver messages and run the whole discovery plane (prekey
publish/lookup) with zero bootstrap configuration and no internet at all.
libp2p integration (QUIC, TCP fallback, Kademlia, relay v2, DCUtR), prekey bundles on DHT, mailbox relays, transport scheduler, headless daemon with local RPC.
Acceptance:
- Two nodes behind distinct NATs exchange messages with no manual configuration beyond sharing kult addresses.
- Recipient offline → message deposited at relay → delivered on reconnect; relay observably stores only sealed envelopes (verified by inspection test).
- LAN-only (no internet) delivery works via mDNS.
M4: Off-grid Meshtastic bridge (in progress)
USB-serial + TCP Meshtastic radio integration, private app port, runtime MTU computation, priority classes, selective retransmission, internet↔mesh bridging.
The carrier core is in: MeshtasticTransport (behind the meshtastic feature
of kult-transport) speaks the standard client protocol to a stock-firmware
radio over any byte stream (USB-serial, TCP, or an in-memory duplex in tests)
via the official meshtastic crate (the published protobuf definitions through
a generated client, per the implementation guide). Sealed envelopes ride the
private application port; the frame budget is the protobuf-pinned 233-byte
Data.payload cap, so the delivery engine's existing fragmentation path needs
no mesh-specific logic, and a ratcheted 192-bucket text message crosses the
mesh in ≤ 2 LoRa frames, pinned end-to-end (encrypt → fragment → framed
client protocol → fake radio → reassemble → decrypt) by an integration test.
Airtime is its own reviewed unit (airtime): the Semtech time-on-air formula
under known-answer tests, and a rolling one-hour duty-cycle budget sized from
the radio's reported region (EU868/EU433/UA433/UA868 → 10 %) that refuses
over-budget sends honestly with a retry hint instead of silently hogging the
mesh. The delivery engine's mesh policies are in (§4.2 rules 2–3 of the
transport spec): the outbound queue flushes in priority order (text >
receipts > handshakes), payloads over 4 KiB are held off airtime-budgeted
links with honest feedback (AwaitingFasterLink, "will send when a faster
link exists") and go out the first tick a faster carrier appears, and
selective retransmission works end to end: a receiver stuck missing
fragment indices NACKs them (inside an ordinary encrypted receipt, paced to
respect airtime), and the sender retransmits exactly the missing fragments,
never the whole message. The daemon is wired: kultd --meshtastic-serial /dev/ttyUSB0 (or --meshtastic-tcp host:4403) attaches a stock radio as a
carrier (an unreachable configured radio is a hard startup error), kult … --mesh broadcast sets mesh delivery hints, and an end-to-end test drives
two daemons (mDNS off, no bootstrap, mesh hints only) to verified
delivery through their RPC sockets with the (fake) radios as the sole
shared medium. Internet↔mesh bridging is in (§4.2 rule 5, mechanism in
ADR-0009): a node with both carriers forwards sealed envelopes it cannot
claim by delivery token: mesh-heard foreign traffic becomes mailbox
deposits at its configured relays (its own mailbox service deposited into
locally), internet-side deposits for unregistered tokens enter a bounded
transit buffer and are flooded over LoRa after the bridge's own traffic,
with content-id dedup, split horizon, and caps on every axis; kultd
bridges by default whenever a radio is attached (--no-bridge opts out),
and the acceptance test drives the full village topology (a mesh-only
node, an internet-only node, and a token-blind bridge between them) to
verified delivered states in both directions through RPC sockets alone.
The hardware-in-loop nightly is in as code: an #[ignore]d acceptance test
(crates/kultd/tests/hil.rs) drives two daemons attached to real
stock-firmware radios on USB-serial (mDNS off, no bootstrap, radios the
only shared medium) through handshake, delivery, receipts, and a ratcheted
reply, failing loudly (never green) on a misconfigured bench; a nightly
workflow runs it on a self-hosted bench runner, armed by the HIL_BENCH
repository variable so it skips cleanly until the bench exists. The bench
runbook (hardware, radio prep, runner registration, security posture) is
10: HIL Bench. Remaining: standing up the physical
two-radio bench and letting the nightly measure the on-air acceptance
criteria below.
Acceptance:
- Two phones/laptops with stock-firmware Meshtastic radios, all other networking disabled, exchange verified E2EE messages multi-hop.
- Text message in the 192 B bucket fits ≤ 2 LoRa frames (measured).
- A node with both mesh and internet bridges queued traffic in both directions.
- Duty-cycle accounting respects EU868 limits (logged and enforced).
M5: Applications (kult-ffi, desktop, mobile alpha) (in progress)
UniFFI bindings; Tauri desktop app; Android/iOS alpha shells. UX for verification (QR safety numbers), contact requests, delivery states, transport indicators, QR pairing and verification; animated message-bundle QR remains planned.
The bindings layer is in: kult-ffi exposes exactly the node's command/event
API (implementation guide §3.5) through UniFFI proc-macros: typed records and
enums for contacts, messages, delivery states, status, and events; blocking
methods a shell dispatches off its UI thread; events pushed to an
application-registered listener on a dedicated thread. Behind the surface sits
an embedded in-process runtime (ADR-0010): one constructor opens the encrypted
store and starts the same composition kultd runs (internet carrier with
mDNS, DHT bootstrap and bundle publication, NAT probing with relay
reservation, mailbox check-ins, optional sneakernet spool and (feature-gated)
Meshtastic radio with bridging) so iOS/Android, where no separate daemon can
run, get the full node from a library call. Ids cross the boundary as hex
strings, prekey bundles as bytes (QR payloads), and errors verbatim, never a
fake success. The crate's e2e test drives two nodes through the public FFI
surface alone: pairing by bundle exchange, verified delivered states via
listener events, history, safety numbers, restart persistence, honest
errors, and cargo run -p kult-ffi --features bindgen --bin uniffi-bindgen
generates the Kotlin/Swift sources. Backup/restore is in (ADR-0011/ADR-0012):
the current encrypted KKR4 file carries identity, contacts, history, group
state, user-authored sealed local metadata, note-to-self history, and
session-reset markers, sealed via Argon2id under a 24-word BIP-39 mnemonic (wordlist and
codec in-tree in kult-crypto, KAT-tested against the reference vectors);
ratchet sessions and prekey secrets are deliberately excluded, and a restored
node (fresh store, fresh vault, resumed identity) turns each reset marker
into a proactive OPK-less re-handshake on its first tick, so messaging
resumes in both directions without the user sending first. Exposed at every
front door: kult backup / Op::Backup (file written 0600, mnemonic shown
exactly once), kultd --restore on first run, and kult-ffi's
export_backup + restore constructor, each pinned by its own layer's
round-trip test (store, node, RPC, FFI). The desktop app is in
(application A1, apps/desktop): a Tauri shell over kult-ffi's embedded
runtime (the exact surface the mobile shells consume, dogfooded on
the desktop) with a dependency-free HTML/CSS/JS frontend (no bundler, no
npm) behind a strict CSP with zero plugins or webview capabilities. It
covers the M5 UX list end to end: create/unlock/restore at the gate,
out-of-band pairing by prekey-bundle QR or pasteable hex (interoperable
with kult bundle/kult add; large bundles ride the QR alphanumeric
mode) or by kult address via DHT lookup, conversations with the node's
honest delivery ladder rendered verbatim (queued → sent → delivered
plus the mesh "held, will send when a faster link exists" verdict),
safety-number verification with matching digits + QR on both ends and a
visible verified badge, key-change surfacing on session re-establishment,
transport indicators (NAT verdict, mDNS LAN peers, queue and
bridge-transit depths, live listen addresses), delivery-hint editing
(multiaddr/relay/spool/mesh-broadcast), and backup export with the
mnemonic shown exactly once. Network settings persist as secret-free
settings.json (the same knobs as kultd flags, radios included). The
app is its own cargo workspace so the GUI dependency tree stays out of
the core's lockfile and cargo-deny surface (it carries its own, equally
strict deny config, and its own CI job); all shell behavior lives in a
webview-agnostic layer pinned by a two-node end-to-end test: pairing by
scanned-style hex, events as the webview receives them, verification,
and the backup → mnemonic → restore flow. The Android alpha is in
(application A2, apps/android): a Kotlin shell over the same kult-ffi
runtime, generated bindings compiled fresh from the crate at build time
(never committed). Its structure mirrors the desktop split: every
behavior lives in a plain-JVM :core module (session layer + bindings)
pinned by JVM tests including a two-node e2e against the host-built
library (pairing by scanned bundle hex, verified delivered states via
listener events, safety numbers, backup → restore → automatic
re-handshake, no emulator involved); the :app module is UI only. It
covers the M5 UX list: create/unlock/restore gate, pairing by camera-
scanned QR (CameraX + pure-Java ZXing, no Google services, F-Droid
friendly), pasted hex, or kult address via DHT, conversations rendering
the node's honest delivery ladder (including the mesh "held" verdict),
safety-number verification with matching digits + QR across platforms,
key-change surfacing, transport indicators, hint editing, secret-free
settings.json (same file format as desktop), mnemonic-shown-once backup
export with OS cloud backup disabled, and a foreground service keeping
delivery alive in the background. Native libraries cross-compile via
cargo-ndk; CI runs the :core e2e and assembles the debug APK. Android
sender-key group UX is also shipped: a distinct group list/create flow,
dedicated history/chat/member surface, truthful per-recipient outbound
delivery rows, and a JVM acceptance scenario with a real offline member.
The iOS alpha is in (application A2, apps/ios): a Swift shell over the same
kult-ffi runtime, generated bindings compiled fresh from the crate at
build time (never committed). Its structure mirrors the other shells'
split: every behavior lives in the KommsCore Swift package (session
layer + bindings) pinned by tests that run on plain Linux or macOS with
no Xcode, including a two-node e2e against the host-built library
(pairing by scanned bundle hex, verified delivered states via listener
events, safety numbers, backup → restore → automatic re-handshake, no
simulator involved); the SwiftUI KommsApp is UI only. It covers the M5
UX list: create/unlock/restore gate, pairing by camera-scanned QR,
pasted hex, or kult address via DHT, conversations rendering the node's
honest delivery ladder (including the mesh "held" verdict),
safety-number verification with matching digits + QR across platforms,
key-change surfacing, transport indicators, hint editing, secret-free
settings.json (same file format as the other shells), and
mnemonic-shown-once backup export via the share sheet with the data
directory excluded from iCloud backup. The sender-key group front door is
also shipped: a distinct group list/create flow, dedicated history/chat and
member-management surfaces, truthful per-recipient outbound delivery rows,
and a host acceptance scenario with a real offline member. QR rendering is
CoreImage and scanning is AVFoundation. The app has zero third-party dependencies;
the only library it links is the workspace's own Rust core, built into
KultFFI.xcframework by a script for device/simulator targets. CI runs the
KommsCore e2e on every push. A macOS job gated by the IOS_APP_CI
repository variable assembles the xcframework and builds the app for a generic
iOS Simulator destination; full recent release-feature matrices have run that
job successfully. The app target's earlier SwiftUI initializer and
SystemConfiguration.framework linkage failures are fixed and guarded by that
build. Remaining: a full hands-on SwiftUI messaging pass and an on-device run;
background delivery and store distribution stay M6.
Acceptance: a non-technical user can install desktop + mobile builds, exchange QR verification with a friend, and message over internet, LAN, and mesh with truthful delivery/security indicators. Backup/restore round-trips.
M6: Hardening & reach (in progress)
Sender-key groups polish → OpenMLS for large groups; censorship-resistant transports
(obfuscation, arti/Tor); multi-device (Sesame-style); panic wipe; reproducible builds;
external security audit of kult-crypto + kult-protocol; F-Droid and store
distribution.
The optional Hybrid Infrastructure Layer is proposed as an independent M6 adoption track under ADR-0017 through ADR-0019: explicit Sovereign/Private/ Standard modes, rotating post-pairing rendezvous, and capability-gated content-free native wake. It is not implementation-ready until those ADRs are accepted. The track must preserve the Google-free Android artifact, keep DHT/ QR as first-contact discovery and volunteer mailboxes as durable delivery, and pass a blackhole test proving that loss of every optional service leaves the existing direct, LAN, mesh, mailbox, and sneakernet paths intact.
Sender-key groups v1 is in through the core stack (ADR-0012, construction pinned
in 04: Cryptography §6): per-member forward-ratcheting
chains in kult-crypto with the pairwise delay-tolerance bounds, group message
bodies whose only routing metadata (key_id ‖ iteration) is sealed under a
members-only header key so intermediaries see uniformly random bytes, and the
single ciphertext fanned out in ordinary per-member envelopes: relays,
mailboxes, receipts, NACKs, and bridging carry group traffic without knowing it
is group traffic. Membership is creator-managed with a monotonic generation
counter; every control message is one announce shape (group state + the
sender's chain snapshot frozen at entitlement time) that resends on a paced
timer until the ordinary encrypted receipt acknowledges it, so an envelope lost
on a lossy carrier never leaves a member permanently deaf to a sender. Removal
re-keys the group secret and rotates every remaining chain (the removed member
gets a notice that deliberately carries nothing else); rotation also triggers
on leave, on a message-count threshold (PCS), and on restore. Backups (KKR4;
older KKR1/KKR2/KKR3 files still restore) carry group identities and history but
never chains: a restored node announces a fresh chain, and co-members
redistribute theirs on the re-handshake, both directions pinned by the
kult-node e2e suite (groups_e2e.rs) alongside encrypt-once-on-the-wire,
per-member delivery ladders, newcomer-reads-no-history, and removed-member
exclusion. The shared front door is also in: kultd RPC, the kult CLI, and
kult-ffi expose group records, history, events, membership operations, and
honest per-member delivery state, pinned by rpc_e2e.rs and ffi_e2e.rs.
Desktop, Android, and iOS group UX are shipped, including truthful
per-recipient partial-delivery rows and shell-level acceptance coverage.
Remaining for groups is the M6 list above.
The versioned message-content foundation is shipped:
ADR-0014 is accepted and implemented
with a permanent legacy-text decode path, encrypted capability negotiation,
bounded typed Text frames, stable encrypted content ids, scoped deduplication,
and honest durable retention of unknown future kinds across the node, store,
RPC, UniFFI, and shells.
The Attachment core proposed by ADR-0015 is implemented: bounded manifests and bulk records, independently sealed resumable chunks, explicit consent/cancel/reject state, pairwise and encrypt-once group transfer, quota-bound sealed-file storage, KKR4 media exclusion, streamed export, and a hard no-airtime bulk class. The F4 application-facing carrier verdict is now shared across the node scheduler, RPC/CLI, and UniFFI as an expiring snapshot with change events; attachment activation consumes that same verdict. Bounded path-based attachment import/export, render-safe transfer records and events, and consent/reject/cancel/pause/resume now cross RPC/CLI and typed UniFFI with pairwise and encrypt-once group acceptance coverage. The desktop shell uses native caller-selected paths, Android uses Storage Access Framework streams, and iOS uses security-scoped document-provider URLs; both mobile shells stage only bounded app-private copies. All three expose pairwise/group send, per-object verified-byte progress and state, lifecycle controls, and protected caller-selected export. F3 shell delivery is complete: generic files use explicit local confirmation, older sealed previews remain renderable, and canonical edited PNG primaries are validated and rendered only through protected transient paths. Each shell exposes its actual interruption/resume policy. Restart acceptance proves verified progress survives node shutdown; Android's foreground service continues data-sync work while backgrounded, desktop continues while open or minimized, and iOS resumes on foreground without claiming unsupported continuous execution.
B2 recorded audio is shipped end to end on top of that unchanged F3/F4 path. Desktop, Android, and iOS record only while foregrounded, stop into a local review with no autoplay, show locally derived duration/waveform and the current carrier explanation, and require explicit send or discard. All three canonicalize to one metadata-free profile—mono signed 16-bit little-endian PCM WAV at 16 kHz, bounded to 60 seconds / 1,920,044 bytes—and deliver exact bytes pairwise or through the encrypt-once sender-key group flow. Protected playback and failure, interruption, lock, restart, and orphan cleanup are covered. The ADR-0015 invariant remains absolute: mesh-only recorded audio waits for a faster link and emits zero bulk airtime frames.
B16 still-image editing is shipped end to end without changing F3, F4, wire metadata, crypto, or transport behavior. One path-based Rust/UniFFI helper owns the 32 MiB / 4096-edge / 12-megapixel decode limits, EXIF-orientation normalization, integer crop/quarter-turn/region semantics, metadata-free RGBA PNG output, and create-new protection. Desktop, Android SAF, and iOS security-scoped pickers all stage protected app-private originals, show the exact final asset, support free/preset crop, rotation, and user-positioned blur or pixelation, and require explicit send or discard. Only the canonical final enters F3; cleanup covers denial, cancellation, failure, low storage, background/lock, shutdown, and restart orphans. Generic non-image files now show and atomically recheck the same authoritative F4 explanation. Pairwise and sender-key group acceptance proves exact bytes, metadata removal, wrapper determinism, protected receiver rendering/export, and zero manifest/chunk/range or other bulk mesh airtime. Video, cloud/generative editing, filters, face recognition, project files, and protocol changes remain out of scope.
B17 group mentions are shipped end to end under
ADR-0016. The immutable kind 0x0003
preserves exact fallback UTF-8 plus canonical sorted, non-overlapping UTF-8 byte
ranges targeting stable group peers; the whole shape remains authenticated,
encrypted, and padded inside ADR-0014 content. The node binds review to the exact
current roster and fresh per-peer capability intersection, so one sender-key
ciphertext is emitted only when every co-member supports Mention. Otherwise each
shell offers an explicit ordinary-text fallback with zero semantic signal.
RPC/CLI and UniFFI accept exact peer targets and ranges rather than display names.
Desktop, Android, and iOS provide accessible roster pickers, preserve readable
copy/search/history after roster or petname changes, and emit only a private
endpoint-local notification hint when the authenticated target is the local peer.
There is no server push or online-delivery guarantee, and no mention data was
added to envelopes, transports, DHT records, delivery tokens, or public OS
previews.
The F5 sealed local-metadata foundation is shipped in kult-store: typed and
bounded conversation, folder, pin, label, draft, preference, and custom-icon
records use an isolated storage key and reveal no local organization keys in a
copied database. User-authored metadata and sealed note-to-self history are
included in KKR4. Note-to-self text is shipped through every shell under one
reserved identity; the individual organization/theme/icon experiences remain
separate work.
B10 private local conversation folders are shipped end to end across the
unchanged F5 record contract, kult-node, RPC/CLI, UniFFI, desktop, Android,
and iOS. Cryptorandom stable IDs remain separate from exact duplicate-capable
UTF-8 names and durable manual order. Pairwise, group, and note-to-self targets
have at most one folder assignment; All and Unfiled are virtual views. Atomic
create, rename, complete-set reorder, move/unfile, delete cascade, stale cleanup,
and folder-first composition with independent B18 label filters create zero
network or transport work. Limits are 128 folders, 8,192 assignments, and 256
UTF-8 bytes per name. KKR4 preserves exact identity, order, membership, and
stale behavior; there is no remote or linked-device folder synchronization.
B18 private labels are shipped end to end across the unchanged F5 record
contract, kult-node, RPC/CLI, UniFFI, desktop, Android, and iOS. Labels target
stable pairwise, group, and note-to-self conversation IDs; message labels remain
deferred. Definitions use cryptorandom 16-byte IDs, exact bounded UTF-8 names,
and the canonical neutral, red, orange, yellow, green, teal, blue,
purple, and pink tokens. The shared limits are 128 live definitions, 8,192
live assignments, 32 labels per conversation, and 256 UTF-8 bytes per name.
Duplicate names are disambiguated by color and deterministic local order.
Atomic deletion, stale-record diagnostics, and deterministic match-any/match-all
filters remain local presentation behavior and create zero network or transport
work. KKR4 preserves exact identity, ordering, and membership; there is no
shared taxonomy, remote synchronization, or multi-device label sync.
Durable scheduled pairwise and group text is shipped end to end. The sealed scheduled outbox does not advance a ratchet or create transport work early; RPC/CLI, UniFFI, desktop, Android, and iOS expose create/list/edit/cancel and the activation lifecycle. Every shell renders scheduled rows separately from the ordinary queued, sent, and delivered ladder while converting only the display/editor to local time.
Acceptance: audit findings triaged with public report; reproducible-build attestation for all release artifacts.
Near horizon: real-time calls
Live voice and video calls are in scope as a near-horizon capability, strictly confined to high-bandwidth carriers (internet libp2p and LAN/mDNS) and disabled over any airtime-budgeted mesh link. The transport core already negotiates the direct connections a call needs (QUIC, DCUtR hole punching), and identity keys authenticate the peer with no central coordinator. Because this adds a real-time media path to the transports, it is pinned by ADR-0013 (Proposed) (media transport, metadata-blind call setup, carrier-gating rule) ahead of implementation. Recorded audio/video clips are already in scope as ordinary asynchronous payloads. Details and constraints: 11: Feature Scope.
Explicitly not scheduled
Cryptocurrency anything, federation with other networks, and any feature that requires mandatory project-operated infrastructure. Optional, replaceable, content-blind convenience services remain subject to ADR-0017 through ADR-0019. Each broader exception would need a compelling ADR.
For the wider product-feature triage (which messenger-app features fit the model and under what constraints, and where each maps onto these milestones), see 11: Feature Scope.