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.
- checksums.yaml +7 -0
- data/EXPORT.md +68 -0
- data/LICENSE +661 -0
- data/LICENSE-COMMERCIAL.md +89 -0
- data/README.md +130 -0
- data/THIRD-PARTY-NOTICES.md +6992 -0
- data/lib/offline_protocol.rb +12623 -0
- metadata +64 -0
|
@@ -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.
|