Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,28 @@ archived by series under [docs/changelog/](docs/changelog/); see the

### Added

- **Python has a gateway-daemon client.** `GatewayManager`, as
`ProtocolManager.gateway` when `reticulum_enabled=True`, speaks the
[gateway-daemon contract](docs/spec/gateway-contract.md) over TCP to a
daemon on local IP: it attaches with the core-built address declaration,
offers the carrier to the core only once the gateway has bound the session
to this device's address (its capabilities are handed to the core on their
own frame, which the contract puts before the announcement), settles every
send on the gateway's verdict rather than on the socket write, fails what a
dead or silent connection owes (sixty seconds, under the core's own expiry),
and asks about the core's presence watchlist. It is the first client on this
carrier to read the `stored` and `pushed` verdict flags, reported as
`relay_stored`, `relay_pushed` and `relay_pushed_stored`, the relay client's
mapping. The stub callback the manager used to install for this slot is
gone; an application that drives the slot itself still replaces the callback
the same way. `configure(daemon_address=...)` and `start()` it after
`ProtocolManager.start()`; `stop()` stops it with the rest. The decisions
live in `gateway_attach_policy.py`, `gateway_verdict_tracker.py` and
`presence_watch_policy.py`, ports of the Swift files, with their
hand-mirrored constants pinned as literals and read by the Rust guards
beside the Swift and Kotlin copies (P11 in `docs/bridges/python.md`). No
daemon has been run against it.

- **A local API guide and two client examples.** `docs/local-api.md` is
the guide to running the SDK as a service several local applications
share; `bindings/python/examples/local_api_client.py` (Python) and
Expand Down
5 changes: 4 additions & 1 deletion bindings/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ offline_protocol_sdk/
├── protocol_manager.py # High-level wrapper (processing loop, lifecycle)
├── internet_manager.py # WebSocket transport (websockets library)
├── peer_stream_manager.py # TCP peer streams + DNS-SD (the wifi_direct slot)
├── gateway_manager.py # Gateway-daemon client over TCP (the reticulum slot)
├── gateway_attach_policy.py # Its decisions and frame shapes, socket-free
├── gateway_verdict_tracker.py, presence_watch_policy.py
├── services.py # Service registry wrappers with the copy the engine lacks
├── dnssd_bridge.py # Services on the LAN: publish own, import neighbours' (optional extra `lan`)
├── ble_manager.py # BLE transport (bleak library)
Expand All @@ -151,7 +154,7 @@ offline_protocol_sdk/
| Internet/WebSocket | `websockets` | All | Primary transport for desktop |
| BLE | `bleak` | All | Central (scanner) role only; peripheral/GATT server requires `bless` |
| Peer stream (the `wifi_direct` slot) | `asyncio` sockets; `zeroconf` for LAN discovery (optional extra `lan`) | All | `PeerStreamManager`: TCP streams to configured `host:port` peers or hosts found over DNS-SD, each proved by the identity-assertion preamble ([spec](../../docs/spec/stream-framing.md)). Start it after `ProtocolManager.start()`; binds every interface unless `listen_host` narrows it |
| Reticulum | Built-in | All | Handled in Rust core; `ProtocolManager` wires a stub callback when `reticulum_enabled=True` — apps driving Reticulum themselves replace it via `protocol.set_reticulum_transport_callback(...)` |
| Reticulum (a gateway daemon) | `asyncio` sockets | All | `GatewayManager` as `pm.gateway` when `reticulum_enabled=True`: the [gateway-daemon contract](../../docs/spec/gateway-contract.md) over TCP to a daemon on local IP (`configure(daemon_address="localhost:4242")`, then `await pm.gateway.start()` after `pm.start()`). Attaches with a signed address declaration, settles each send on the gateway's verdict, watches presence. What answers is a daemon built to the contract; this package ships the device half. Apps driving the slot themselves replace the callback via `protocol.set_reticulum_transport_callback(...)` |
| Nostr | Built-in | All | Handled in Rust core (BIP-340 signing); `ProtocolManager` wires a stub callback when `nostr_enabled=True` — apps driving Nostr themselves replace it via `protocol.set_nostr_transport_callback(...)` |

### Secure Storage
Expand Down
Loading
Loading