diff --git a/docs/app-developers/gallery.md b/docs/app-developers/gallery.md index 7929c73..ba93a0c 100644 --- a/docs/app-developers/gallery.md +++ b/docs/app-developers/gallery.md @@ -133,7 +133,7 @@ Open `index.html` directly from disk; no static server needed. The app speaks MQ **What this glosses over**: - The `seen` set is in-memory; if you reload the receive tab while a message is unacked, you'll see it again. A real app would persist `seen` (e.g. IndexedDB). -- No app-layer chunking / progressive UX. F2 fragments under the hood and reassembles before delivery, so the receiver gets the whole file in one event - no "I've got 30% of it" intermediate state. If you wanted progressive render, you'd split the source into N independent DAPPS messages at the app layer. +- No app-layer chunking / progressive UX. DAPPS fragments under the hood and reassembles before delivery, so the receiver gets the whole file in one event - no "I've got 30% of it" intermediate state. If you wanted progressive render, you'd split the source into N independent DAPPS messages at the app layer. - Auth-required mode is supported by pasting a token into the form, but there's no operator-friendly first-run flow for minting / sharing the token. ## Long-form messenger (browser) - `examples/letters/` diff --git a/docs/audit.md b/docs/audit.md index 77d9545..5b053c3 100644 --- a/docs/audit.md +++ b/docs/audit.md @@ -9,10 +9,10 @@ Every site where the daemon puts bytes on a bearer: | Kind | What it covers | |---------------------|-------------------------------------------------------------------------------------------| | `beacon` | Discovery channel beacon broadcasts. | -| `solicit` | B6.2 solicit transmissions (scheduled or operator-triggered). | +| `solicit` | Solicit transmissions (scheduled or operator-triggered). | | `solicit-reply` | Replying to a solicit we received. | -| `probe` | Connected-mode probe sessions (Phase 1, Phase 2 transitive). | -| `probe-nodeprompt` | Probe via node prompt (Phase 2b). | +| `probe` | Connected-mode probe sessions (direct or transitive). | +| `probe-nodeprompt` | Probe via node prompt. | | `forward` | Outbound forwarder shipping a message to a neighbour. | | `forward-flood` | Per-recipient transmission of a flood-routed message. | | `poll` | Reverse-poll request to a peer (scheduled or operator-triggered). | diff --git a/docs/configure.md b/docs/configure.md index 6f9efd6..41af3b5 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -71,7 +71,7 @@ The admin password (for the dashboard cookie) is set on `/Setup` first-run flow, | Poll interval (hours) | `DAPPS_POLL_INTERVAL_HOURS` | `6` | Sweep cadence when scheduled polling is on. | | Opportunistic poll enabled | `DAPPS_OPPORTUNISTIC_POLL_ENABLED` | `true` | Drains a peer's queued mail at the end of every push session. | -### Multi-part messages (F2) +### Multi-part messages | Name | Env var | Default | What it does | |-----------------------------------|------------------------------------------|-------------|-----------------------------------------------------------------------------------------| diff --git a/docs/connect/meshcore.md b/docs/connect/meshcore.md index c71dc86..15b3636 100644 --- a/docs/connect/meshcore.md +++ b/docs/connect/meshcore.md @@ -1,6 +1,6 @@ # Connect via MeshCore -**Status: planned.** MeshCore as a backhaul bearer for DAPPS is in the [Phase H roadmap](https://github.com/M0LTE/dapps/blob/master/plan.md#phase-h--concrete-bearer-integrations) and not yet implemented in shipping code. This page exists so you can see the shape of the integration and plan around it. +**Status: planned.** MeshCore as a backhaul bearer for DAPPS is on the roadmap but not yet implemented in shipping code. This page exists so you can see the shape of the integration and plan around it. ## Why MeshCore @@ -55,6 +55,6 @@ A separate design note covering the MeshCore-as-a-bearer trade-offs is in [docs/ ## When? -Tracking issue: see [Phase H in plan.md](https://github.com/M0LTE/dapps/blob/master/plan.md#phase-h--concrete-bearer-integrations). It's blocked on hardware availability for testing - we want a real two-radio setup in the loop before declaring it shippable rather than relying on emulation. +Currently blocked on hardware availability for testing - we want a real two-radio setup in the loop before declaring it shippable rather than relying on emulation. If you've got a MeshCore radio and want to be a tester, [open an issue](https://github.com/M0LTE/dapps/issues). diff --git a/docs/discovery-and-routing.md b/docs/discovery-and-routing.md index 261806c..95ca0cf 100644 --- a/docs/discovery-and-routing.md +++ b/docs/discovery-and-routing.md @@ -12,7 +12,7 @@ Three tables, each with a single job: Plus two derived stores: -4. **Probed nodes** - per-callsign liveness state from connected-mode probes (Phase B6.1). Tracks success/failure history, source (`neighbour` for direct, `via:CALL` for transitive, `node-prompt:CALL` for node-prompt-discovered). +4. **Probed nodes** - per-callsign liveness state from connected-mode probes. Tracks success/failure history, source (`neighbour` for direct, `via:CALL` for transitive, `node-prompt:CALL` for node-prompt-discovered). 5. **Learned routes** - for the `passive-flood` algorithm, observed forwards build up an internal "I know how to reach X via Y" map. ## Discovery channels @@ -34,25 +34,25 @@ When you enable a discovery channel, the beaconer sends a small frame on its cad A beacon is one packet, not a session - it's stateless. The advertised TTL is how long the receiver should remember the row before it ages out. -## Solicits (B6.2) +## Solicits Beacons are push: I send mine, you happen to be listening. Solicits are pull: I ask "is anyone out there?" and listen for replies for a window. Useful on **HF NVIS** where the round-trip cost of a beacon (and the airtime budget you'd have to give it) makes "transmit and hope" expensive. Solicits are operator-triggered (via the dashboard) or scheduled per-channel. -## Probes (B6.1) +## Probes A probe is a connected-mode session - DAPPS opens a real DAPPS session to a peer's callsign and confirms the round-trip works. Probing is **off by default**; turn on with `DAPPS_PROBING_ENABLED=true`. Three flavours: -| Flavour | What it does | Source flag | -|------------------------|---------------------------------------------------------------------------------------------------------------------------------------|-------------------------| -| **Phase 1** | Direct probe: open a DAPPSv1 session, confirm prompt, hang up. Records success/failure. | `neighbour` | -| **Phase 2 - `peers`** | After a successful Phase 1 probe, ask the peer "who do you know?" via the `peers` command. Seed each unknown callsign as a candidate. | `via:` | -| **Phase 2b - node-prompt** | For peers that aren't (yet) DAPPS - connect to the BPQ node prompt, type the application command (`DAPPS` by default), and probe from there. | `node-prompt:` | +| Flavour | What it does | Source flag | +|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|-------------------------| +| **Direct** | Open a DAPPSv1 session, confirm prompt, hang up. Records success/failure. | `neighbour` | +| **Transitive** | After a successful direct probe, ask the peer "who do you know?" via the `peers` command. Seed each unknown callsign as a candidate. | `via:` | +| **Node-prompt** | For peers that aren't (yet) DAPPS - connect to the BPQ node prompt, type the application command (`DAPPS` by default), and probe from there. | `node-prompt:` | -Phase 2b auto-discovery is gated on `DAPPS_AUTO_DISCOVER_VIA_NODE_CALL=true`. When on, every AGW DAPPS beacon also seeds a node-prompt-probe candidate for the source's base callsign. +Node-prompt auto-discovery is gated on `DAPPS_AUTO_DISCOVER_VIA_NODE_CALL=true`. When on, every AGW DAPPS beacon also seeds a node-prompt-probe candidate for the source's base callsign. ## Neighbours diff --git a/docs/glossary.md b/docs/glossary.md index ba2ab65..427213a 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -36,7 +36,7 @@ Terms used throughout this manual. **dapps-id** - User property on MQTT publishes / REST submits that DAPPS uses for idempotent at-least-once delivery. Same `dapps-id` twice → second submit is a no-op. -**dapps-source** - User property carrying the originating callsign. Set by DAPPS at the source node, propagated end-to-end with F1 source tracking. +**dapps-source** - User property carrying the originating callsign. Set by DAPPS at the source node and propagated end-to-end across forwarding hops. **dapps-ttl** - User property carrying the residual TTL in seconds. Decremented on each forwarding hop; messages are dropped on zero. @@ -44,15 +44,7 @@ Terms used throughout this manual. **DSR** - Dynamic Source Routing - a routing class where the sender stamps the path on the message. The `meshcore` algorithm is DSR-flavoured. -**F1** - End-to-end source tracking. The originating callsign is preserved on the message all the way to the destination, even across multiple forwarding hops. - -**F2** - Multi-part messages. Payloads larger than the fragment threshold are split into N fragments at submit, each delivered independently and reassembled at the receiver. - -**F3** - Reverse polling. A peer can ask another peer for queued messages, instead of waiting for them to be pushed. Two flavours: opportunistic (free, at the end of every push session) and scheduled (periodic). - -**F4** - Versioning policy. How DAPPS manages compatibility on the wire - forward-compatible additions stay on the current version, breaking changes bump the prompt. - -**fragment** - A piece of a multi-part message. Each fragment carries its master ID, fragment index, fragment total, and is forwarded / acked independently. +**fragment** - A piece of a multi-part message. Payloads larger than the fragment threshold are split into N fragments at submit, each forwarded / acked independently and reassembled at the destination. Each carries its master ID, fragment index, and fragment total. **forwarder** - The background loop that walks the messages table and dispatches outbound forwards over the bearer. Ticks every 5 s. @@ -76,17 +68,17 @@ Terms used throughout this manual. **neighbour** - A callsign DAPPS will actually forward to. May be hand-added or auto-promoted from a successful probe. -**node-prompt** - The text prompt presented when an L2 connect lands on a packet node (BPQ et al). Phase 2b discovery uses this to probe peers that aren't directly DAPPS - connect, type the application command (`DAPPS` by default), then run a normal probe from the resulting prompt. +**node-prompt** - The text prompt presented when an L2 connect lands on a packet node (BPQ et al). DAPPS uses this to probe peers that aren't directly DAPPS - connect, type the application command (`DAPPS` by default), then run a normal probe from the resulting prompt. **NODECALL** - A callsign assigned to a packet node itself (as distinct from the operator's own callsign). For example, `GB7XYZ` might be the node call and `M0LTE` the operator's call. -**NVIS** - Near-Vertical Incidence Skywave. An HF propagation mode used for short-to-medium-range communication when ground-wave doesn't reach. DAPPS's B6.2 solicit-and-listen is shaped around its asymmetric-coverage characteristics. +**NVIS** - Near-Vertical Incidence Skywave. An HF propagation mode used for short-to-medium-range communication when ground-wave doesn't reach. DAPPS's solicit-and-listen discovery is shaped around its asymmetric-coverage characteristics. -**`peers`** - A DAPPSv1 command added in Phase 2 of the probe work. After a successful probe, the prober asks "who do you know?" and seeds each unknown callsign as a candidate to probe later. +**`peers`** - A DAPPSv1 command for transitive discovery. After a successful probe, the prober asks "who do you know?" and seeds each unknown callsign as a candidate to probe later. -**probe** - A connected-mode session opened to a peer to confirm reachability. Three flavours: direct (Phase 1), transitive via the peer's `peers` response (Phase 2), and node-prompt-discovered (Phase 2b). +**probe** - A connected-mode session opened to a peer to confirm reachability. Three flavours: direct, transitive (via the peer's `peers` response), and node-prompt-discovered (via the BPQ node prompt for peers that aren't directly DAPPS). -**`rev`** - A DAPPSv1 command added in Phase F3: "send me anything you're holding for me." Used by both opportunistic and scheduled polling. +**`rev`** - A DAPPSv1 command meaning "send me anything you're holding for me." Used by both opportunistic and scheduled polling. **REST** - DAPPS's HTTP-based app interface, alongside MQTT. Same submit shape; different protocol. diff --git a/docs/implement.md b/docs/implement.md index c9846d1..1d09489 100644 --- a/docs/implement.md +++ b/docs/implement.md @@ -7,7 +7,7 @@ The reference implementation in this repo is the canonical source of truth. Wher The page is in two parts: - [**Bare essentials**](#bare-essentials) - the smallest set of behaviours that lets two implementations exchange a message and not deadlock. If you implement only this, you get a node that pushes messages, accepts inbound messages, and is invisible to discovery / routing optimisations. -- [**Full interoperability**](#full-interoperability) - feature by feature, what to add to that minimum to be fully indistinguishable from the reference daemon: source tracking, fragmentation, ordering, polling, peer exchange, discovery beacons, and the datagram codec. +- [**Full interoperability**](#full-interoperability) - feature by feature, what to add to that minimum to be fully indistinguishable from the reference daemon: end-to-end source tracking, multi-part fragmentation, opt-in ordering, polling, peer exchange, discovery beacons, and the datagram codec. ## Bare essentials @@ -118,7 +118,7 @@ A node that does only: The features below are individually optional. The reference daemon implements all of them; pick the ones your scope needs. Each one is wire-additive: a daemon that doesn't understand `src=` will just ignore it, and the message still delivers. -### F1: end-to-end source tracking (`src=`) +### End-to-end source tracking (`src=`) Add to `ihave`: @@ -128,11 +128,11 @@ ihave 7e1f3a2 len=5 fmt=p s=1714982400000 src=G0ORIG dst=mail@G0RCV chk=a31f `src=` is the *originator* of the message - the callsign of the node whose app submitted it. Distinct from the *link source* (the immediate sender, derived from the bearer's session metadata). On a multi-hop relay path, every forwarder preserves `src=` verbatim; only the originator stamps it. -Why have it: without `src=`, a receiver three hops down can't tell whether a message originated at G0FIRST or just transited through G0FIRST. With `src=`, the receiver's app sees the originator (exposed as the `dapps-origin` MQTT user property) and can route replies back to the right source. Forwarders that don't speak F1 omit `src=`; receivers treat absent `src=` as "originator unknown". +Why have it: without `src=`, a receiver three hops down can't tell whether a message originated at G0FIRST or just transited through G0FIRST. With `src=`, the receiver's app sees the originator (exposed as the `dapps-origin` MQTT user property) and can route replies back to the right source. Forwarders that don't propagate it omit `src=`; receivers treat absent `src=` as "originator unknown". Reference: [DappsProtocolClient.cs:122-128](https://github.com/M0LTE/dapps/blob/master/src/dapps/dapps.client/DappsProtocolClient.cs#L122-L128), [IHaveValidator.cs:144-152](https://github.com/M0LTE/dapps/blob/master/src/dapps/dapps.core/Services/IHaveValidator.cs#L144-L152). -### F2: multi-part fragmentation (`mid=` + `frag=`) +### Multi-part fragmentation (`mid=` + `frag=`) A payload that exceeds the operator's fragment threshold (default 4 KB) is split into N chunks at the originator, sent as N independent `ihave` exchanges, and reassembled at the destination. @@ -148,7 +148,7 @@ ihave 33eeefe len=512 fmt=p s=1714982400003 mid=4cf02b1 frag=3/3 dst=mail@G0RCV - Each fragment has its own id (hash of its own chunk + its own salt). Intermediate hops forward fragments as opaque messages. - Only the final destination groups by `mid`, holds fragments in a reassembly buffer, and delivers the assembled payload to the app once all M arrive. -Why two-id'd: each fragment is independently content-addressed so it can be deduplicated, retried, and routed like any other message. The master id only matters at the destination; relays don't care. A pre-F2 receiver that doesn't know `mid`/`frag` will deliver each fragment to the app as a separate message, which is wrong but not corrupt. +Why two-id'd: each fragment is independently content-addressed so it can be deduplicated, retried, and routed like any other message. The master id only matters at the destination; relays don't care. A receiver that doesn't know `mid`/`frag` will deliver each fragment to the app as a separate message, which is wrong but not corrupt. Reassembly buffer entries time out after `FragmentReassemblyTimeoutSeconds` (default 7 days) - long because HF / mesh propagation gaps legitimately last days, and we'd rather hold the partial bytes than throw away most of a near-complete message. diff --git a/docs/index.md b/docs/index.md index 08cad4a..ffae162 100644 --- a/docs/index.md +++ b/docs/index.md @@ -27,6 +27,6 @@ DAPPS does **not** require BPQ. The default setup guide is BPQ because that's wh - **Protocol**: DAPPSv1 specified end-to-end. App authors want [the protocol reference](app-developers/reference.md); second-source implementers want [Implement DAPPS](implement.md). - **Implementation**: in active development. The [versioning policy](configure.md#versioning) describes where breaking changes are still fair game versus where compatibility is preserved. -- **Bearers**: AGW (BPQ today, any AGW host in principle) and RHPv2 (XRouter today; mainline BPQ when it ships RHPv2) are production-quality. MeshCore Companion + KISS are in the [Phase H roadmap](https://github.com/M0LTE/dapps/blob/master/plan.md#phase-h--concrete-bearer-integrations). +- **Bearers**: AGW (BPQ today, any AGW host in principle) and RHPv2 (XRouter today; mainline BPQ when it ships RHPv2) are production-quality. [MeshCore](connect/meshcore.md) Companion + KISS are planned, not yet shipped. If you've never heard of DAPPS before, [start here](getting-started.md).