offline_protocol 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ # Commercial License
2
+
3
+ Copyright © 2025-2026 Offline Protocol, Inc.
4
+
5
+ The Offline Protocol SDK is **dual-licensed**. You may use it under **either** of the
6
+ following licenses, at your option:
7
+
8
+ 1. **GNU Affero General Public License v3.0 (AGPL-3.0-only)** — the full text is in
9
+ [`LICENSE`](LICENSE). This option is free of charge but carries strong copyleft
10
+ obligations: software that incorporates this SDK is generally a covered work
11
+ under the AGPL-3.0 (per section 5) and must be distributed under the same
12
+ license with corresponding source made available to recipients (per section 6).
13
+ If you operate a modified version that interacts with users over a network, you
14
+ must additionally offer those users the corresponding source — this is the
15
+ network-use clause specific to AGPL (section 13).
16
+
17
+ 2. **Commercial License** — for organizations that cannot or do not wish to comply
18
+ with the AGPL-3.0 (for example, shipping the SDK inside a proprietary mobile
19
+ application, embedding it in closed-source firmware, or operating a SaaS without
20
+ releasing source). A separate commercial license from **Offline Protocol, Inc.**
21
+ grants the right to use, modify, and distribute the SDK without the AGPL-3.0
22
+ obligations, subject to the applicable commercial agreement, including the
23
+ telemetry term below.
24
+
25
+ You only need **one** of the two licenses, not both.
26
+
27
+ One distribution channel deserves a specific call-out: Apple's standard App
28
+ Store terms are widely regarded as incompatible with the AGPL-3.0's
29
+ prohibition on further restrictions, so the commercial license is the
30
+ supported option for apps distributed through the Apple App Store — the
31
+ reasoning is laid out in the
32
+ [Licensing FAQ](https://github.com/Offline-Protocol/offline-protocol-sdk/blob/main/docs/licensing-faq.md).
33
+
34
+ ## Telemetry under the Commercial License
35
+
36
+ The SDK includes an optional telemetry client that, once an application
37
+ enables it with a telemetry API key and application identifier issued by
38
+ Offline Protocol, Inc., collects, batches, and uploads supported operational
39
+ events to Offline Protocol's hosted telemetry service. Service access, usage
40
+ allowances, and metered charges are set out in the applicable commercial
41
+ agreement. The following telemetry term applies to every commercial license,
42
+ as set out in that agreement.
43
+
44
+ A commercial licensee may leave hosted telemetry off, never supply telemetry
45
+ credentials, or switch it off using the SDK's documented controls. Until it is
46
+ explicitly enabled, the hosted telemetry client does not collect, buffer,
47
+ persist, or upload telemetry. The controls stop new collection; handling of
48
+ previously queued records, final flushes, and in-flight uploads is described
49
+ in the telemetry documentation.
50
+
51
+ Except as expressly authorized in writing by Offline Protocol, Inc., a
52
+ commercial licensee may not modify, configure, or build the SDK so that its
53
+ bundled telemetry client uploads to an unauthorized endpoint, redirects or
54
+ duplicates its uploads to another telemetry service, or alters the event
55
+ schema or serialized payload format it uploads. Security updates that preserve
56
+ the authorized destination and payload format are permitted. Network proxies
57
+ and gateways that forward uploads unaltered to an authorized endpoint, and
58
+ local test captures in builds that are not shipped, are permitted.
59
+
60
+ These telemetry restrictions do not limit the licensee's use of information
61
+ received through the SDK's public APIs. Receiving events and diagnostics,
62
+ storing or analyzing them, and forwarding them to the licensee's own systems
63
+ or third-party observability providers are ordinary uses of the SDK.
64
+ Independently implementing telemetry collection and export using those APIs is
65
+ also permitted.
66
+
67
+ This term applies to the Commercial License only. It does not modify or impose
68
+ additional restrictions on the AGPL-3.0 option, under which the telemetry
69
+ client may be modified, removed, or replaced in accordance with that license.
70
+ Under either option, the SDK performs no commercial-license entitlement
71
+ checks, and core SDK functionality does not require hosted telemetry.
72
+
73
+ ## Obtaining a Commercial License
74
+
75
+ Commercial licenses are offered by **Offline Protocol, Inc.** To request a quote
76
+ or discuss commercial terms, contact:
77
+
78
+ - **Email:** legal@offlineprotocol.com
79
+
80
+ Please include a brief description of your intended use (product, distribution
81
+ model, expected scale) so we can scope the license appropriately.
82
+
83
+ ## Contributions
84
+
85
+ Contributors grant **Offline Protocol, Inc.** the right to sublicense their
86
+ contributions under this Commercial License alongside the AGPL-3.0. The full terms are in
87
+ [`CLA.md`](https://github.com/Offline-Protocol/offline-protocol-sdk/blob/main/CLA.md);
88
+ see [`CONTRIBUTING.md`](https://github.com/Offline-Protocol/offline-protocol-sdk/blob/main/CONTRIBUTING.md)
89
+ for the signing flow.
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # The Offline Protocol SDK from Ruby
2
+
3
+ A typed Ruby API for scripts, tooling and servers, generated from the same
4
+ interface definition as the Swift, Kotlin, Python and Java bindings by UniFFI's
5
+ own Ruby generator. It calls the native library directly through the
6
+ [`ffi`](https://github.com/ffi/ffi) gem: there is no native glue of its own and
7
+ it does not go through the C API.
8
+
9
+ The whole binding is one file, [`lib/offline_protocol.rb`](lib/offline_protocol.rb).
10
+ The module is `OfflineProtocol` and the engine inside it is
11
+ `OfflineProtocol::OfflineProtocol`. `MeshServices` and `DataStore` hang off the
12
+ engine, every record and enum of the definition is a class, and the things a
13
+ host implements are plain objects that respond to the interface's methods. An
14
+ engine refusal is an exception named for the variant
15
+ (`OfflineProtocol::ProtocolError::EncryptFailed`).
16
+
17
+ The contract is [docs/bridges/ruby.md](../../docs/bridges/ruby.md), on top of
18
+ the [shared one](../../docs/bridges/README.md). Read it before writing a
19
+ callback or a storage provider.
20
+
21
+ ## What you need
22
+
23
+ | What | Where it comes from |
24
+ |---|---|
25
+ | Ruby 3.3 or later and the `ffi` gem, `~> 1.17` | Yours; `bundle install` in this directory installs the gem |
26
+ | This binding | The [`offline_protocol`](https://rubygems.org/gems/offline_protocol) gem once a release publishes it (R7), or [`lib/offline_protocol.rb`](lib/offline_protocol.rb) on your load path |
27
+ | `liboffline_protocol_uniffi.so` / `.dylib`, `offline_protocol_uniffi.dll` | The release's desktop archives, or `cargo build --release -p offline-protocol-uniffi` |
28
+
29
+ The library is found on the loader's search path, and the loader reads the
30
+ variable when the process starts, so set it before Ruby launches:
31
+
32
+ ```sh
33
+ # Linux
34
+ LD_LIBRARY_PATH=/path/to/dir ruby -Ilib your_script.rb
35
+ # macOS
36
+ DYLD_LIBRARY_PATH=/path/to/dir ruby -Ilib your_script.rb
37
+ # Windows (RubyInstaller reads RUBY_DLL_PATH, not PATH)
38
+ $env:RUBY_DLL_PATH = "C:\path\to\dir"; ruby -Ilib your_script.rb
39
+ ```
40
+
41
+ A protected system Ruby on macOS (`/usr/bin/ruby`) drops `DYLD_LIBRARY_PATH`;
42
+ use a Ruby you installed.
43
+
44
+ ## Quick start
45
+
46
+ ```ruby
47
+ require "offline_protocol"
48
+
49
+ Sdk = OfflineProtocol
50
+
51
+ # An instance-less function needs no engine.
52
+ puts Sdk.derive_address([0] * 32)
53
+
54
+ # Name the fields the definition leaves without a default; the rest take it.
55
+ config = Sdk::ProtocolConfig.new(
56
+ app_id: "com.example.ruby", profile: "ruby-example",
57
+ ble_enabled: false, wifi_direct_enabled: false, internet_enabled: true,
58
+ reticulum_enabled: false, nostr_enabled: false, prefer_online: false,
59
+ initial_ttl: 8, encryption_enabled: true, auto_key_exchange: true,
60
+ # The pending queue: per peer, global, the SDK's 24 h lifetime, overflow.
61
+ store_pending: true, max_pending_per_peer: 64, max_pending_global: 4096,
62
+ pending_ttl_ms: 86_400_000, overflow_policy: Sdk::OverflowPolicy::DROP_OLDEST
63
+ )
64
+
65
+ engine = Sdk::OfflineProtocol.new(config)
66
+
67
+ # Any object that responds to on_event. It runs inside the engine call.
68
+ listener = Object.new
69
+ def listener.on_event(json) = puts(json)
70
+ engine.set_event_callback(listener)
71
+
72
+ engine.emit_test_event
73
+ ```
74
+
75
+ Keep the engine reachable for as long as the process runs. See R3 in the
76
+ contract for what a collected engine costs.
77
+
78
+ A byte array the engine returns comes back signed, -128 to 127, and has to be
79
+ masked with `map { |b| b & 0xFF }` before it goes back in (R8).
80
+
81
+ A complete, runnable program is in [examples/ruby-app](../../examples/ruby-app/README.md).
82
+
83
+ ## Storage
84
+
85
+ The engine needs somewhere to keep key material and protocol state. Either hand
86
+ it the built-in file stores:
87
+
88
+ ```ruby
89
+ engine.initialize_mls_with_file_stores(mls_dir, state_dir, store_key_32_bytes)
90
+ ```
91
+
92
+ or write two providers and pass them to `initialize_mls`. They carry bytes
93
+ differently (R5 in the contract), and a provider you write should pass
94
+ `OfflineProtocol.run_storage_conformance`. [`test/memory_storage.rb`](test/memory_storage.rb)
95
+ is a complete in-memory pair.
96
+
97
+ ## Tests
98
+
99
+ ```sh
100
+ cargo build -p offline-protocol-uniffi
101
+ cd bindings/ruby
102
+ bundle install
103
+ bundle exec rake test
104
+ ```
105
+
106
+ `rake test` puts `../../target/debug` on the loader's search path (set
107
+ `OFFLINE_PROTOCOL_LIBRARY_DIR` for another build) and runs
108
+ [`test/consumer_check_test.rb`](test/consumer_check_test.rb) against the real
109
+ library. The generated code does not compare the library's FFI checksums, so
110
+ these tests are what show that the binding and the library came from the same
111
+ definition. Outside this repository nothing checks it: take the library from
112
+ the same release as the gem (R1).
113
+
114
+ `bundle exec rake build` writes the gem to `pkg/`, at the version in
115
+ `OFFLINE_PROTOCOL_VERSION` (default `0.0.0`). Use the task, not `gem build`: it
116
+ stages the license notices from the repository root, which the gemspec names
117
+ and `gem build` cannot reach.
118
+
119
+ ## Regenerating
120
+
121
+ Never edit `lib/offline_protocol.rb`. It is regenerated with the other four
122
+ bindings, which are one artifact set:
123
+
124
+ ```sh
125
+ ./scripts/generate-bindings.sh
126
+ ```
127
+
128
+ The Ruby generator is part of `uniffi-bindgen`, so there is nothing more to
129
+ install than the other bindings need. [`uniffi.toml`](uniffi.toml) names the
130
+ library; see R1 in the contract.