durable_streams-rails 0.4.0 → 0.5.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 +4 -4
- data/README.md +48 -4
- data/app/models/concerns/durable_streams/rails/broadcastable.rb +1 -1
- data/lib/durable_streams/rails/engine.rb +2 -2
- data/lib/durable_streams/rails/version.rb +1 -1
- data/lib/durable_streams-rails.rb +3 -2
- data/lib/generators/durable_streams/install/templates/initializer.rb.tt +7 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf65130284ea6d82ba8c5a96a6140d8d90b2a85644150d95e4cccc254e166da4
|
|
4
|
+
data.tar.gz: a9351da1b24a5a717ad3717eed8faa19f6079c99ef3e9d8300214a1e31558e19
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48dce7b23beb7d4a5a8c7e37350d5790c25865f20cfebcd31bd80fad574c7179896fae4471289524556ea61836f739936c2e18fcc404fb7b810a4eee55a9f1c5
|
|
7
|
+
data.tar.gz: e1518c09eeaeaf28a6a92279bac1bc06b962aee73d89b8ead82b7651c7a6910f1a5eb9faa7210d3a4e3f97e2bf030c97df4c736a230e46d9dcf554c8ffc18375
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Durable Streams Rails
|
|
2
2
|
|
|
3
3
|
Durable Streams integration for Rails. Stream State Protocol events from your models to clients
|
|
4
|
-
over
|
|
4
|
+
over HTTP with the same developer experience as Turbo Broadcasts — but with offset-based
|
|
5
5
|
resumability, persistent event logs, and no WebSocket infrastructure.
|
|
6
6
|
|
|
7
7
|
```ruby
|
|
@@ -31,7 +31,7 @@ bin/rails generate durable_streams:install
|
|
|
31
31
|
|
|
32
32
|
This creates:
|
|
33
33
|
|
|
34
|
-
- `config/initializers/durable_streams.rb` — sets
|
|
34
|
+
- `config/initializers/durable_streams.rb` — sets `client_url` and `server_url`
|
|
35
35
|
- `config/durable_streams.yml` — server configuration (per environment)
|
|
36
36
|
- `bin/durable-streams` — binstub that auto-downloads and runs the server binary
|
|
37
37
|
- Updates `Procfile.dev` with a `streams:` entry
|
|
@@ -188,7 +188,7 @@ DurableStreams.broadcast_to(room, :presence,
|
|
|
188
188
|
|
|
189
189
|
### Signed stream URLs
|
|
190
190
|
|
|
191
|
-
Generate signed, expirable URLs for client
|
|
191
|
+
Generate signed, expirable URLs for client streaming connections:
|
|
192
192
|
|
|
193
193
|
```ruby
|
|
194
194
|
url = DurableStreams.signed_stream_url(room, :messages)
|
|
@@ -258,7 +258,7 @@ This gem mirrors `turbo-rails` 1:1 in structure and design:
|
|
|
258
258
|
| `Turbo::Broadcastable::TestHelper` | `DurableStreams::Rails::Broadcastable::TestHelper` | Test assertions |
|
|
259
259
|
|
|
260
260
|
The key architectural difference: Turbo broadcasts HTML fragments over WebSockets (Action Cable).
|
|
261
|
-
This gem broadcasts JSON State Protocol events over HTTP
|
|
261
|
+
This gem broadcasts JSON State Protocol events over HTTP (Durable Streams).
|
|
262
262
|
|
|
263
263
|
## Dependencies
|
|
264
264
|
|
|
@@ -324,6 +324,50 @@ requirement from application code:
|
|
|
324
324
|
Whichever path touches a stream first provisions it. The application developer never thinks
|
|
325
325
|
about stream creation.
|
|
326
326
|
|
|
327
|
+
## Security
|
|
328
|
+
|
|
329
|
+
### Two URLs, two authentication channels
|
|
330
|
+
|
|
331
|
+
The gem separates client-facing and server-to-server communication:
|
|
332
|
+
|
|
333
|
+
```ruby
|
|
334
|
+
# config/initializers/durable_streams.rb
|
|
335
|
+
|
|
336
|
+
# Client-facing — used by signed_stream_url to build URLs browsers connect to.
|
|
337
|
+
DurableStreams.client_url = ENV.fetch("DURABLE_STREAMS_CLIENT_URL", "http://localhost:4437/v1/streams")
|
|
338
|
+
|
|
339
|
+
# Server-to-server — used by Rails to POST broadcasts and PUT stream creation.
|
|
340
|
+
# Paired with server_api_key for authentication.
|
|
341
|
+
DurableStreams.server_url = ENV.fetch("DURABLE_STREAMS_SERVER_URL", "http://localhost:4437/v1/streams")
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
In single-server deployments both point to the same address. In multi-server deployments
|
|
345
|
+
they diverge: `client_url` is the public domain (behind a CDN), `server_url` is the internal
|
|
346
|
+
network address.
|
|
347
|
+
|
|
348
|
+
`server_url` is never exposed to clients. `client_url` is never used for server-to-server
|
|
349
|
+
communication.
|
|
350
|
+
|
|
351
|
+
### Client authentication — signed URLs
|
|
352
|
+
|
|
353
|
+
Browsers receive signed, expiring URLs via Inertia props (or any server-rendered response).
|
|
354
|
+
The token is generated by `MessageVerifier` and encodes the stream name, permissions
|
|
355
|
+
(`read`/`write`), and an expiration timestamp.
|
|
356
|
+
|
|
357
|
+
When a client connects, the Durable Streams server's `forward_auth` sends the request to
|
|
358
|
+
`AuthController#verify`, which validates the token's signature and expiration.
|
|
359
|
+
|
|
360
|
+
**The token is domain-agnostic.** It validates *what* (stream name + permissions + expiry),
|
|
361
|
+
not *where* (which host the request is hitting). Network-level controls (firewall/NSG rules)
|
|
362
|
+
must prevent clients from reaching `server_url` directly.
|
|
363
|
+
|
|
364
|
+
### Server authentication — API key
|
|
365
|
+
|
|
366
|
+
Rails authenticates to the Durable Streams server with a Bearer token (`server_api_key`)
|
|
367
|
+
sent in the `Authorization` header. The key is auto-derived from
|
|
368
|
+
`Rails.application.key_generator` — consistent across all instances of the same app
|
|
369
|
+
without manual configuration.
|
|
370
|
+
|
|
327
371
|
## Future
|
|
328
372
|
|
|
329
373
|
Brewing secretly — an async-backed durable streams server inside Rails.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# end
|
|
15
15
|
#
|
|
16
16
|
# This broadcasts a State Protocol insert event to the stream derived from the post association.
|
|
17
|
-
# All clients subscribed to that stream will receive the event
|
|
17
|
+
# All clients subscribed to that stream will receive the event.
|
|
18
18
|
#
|
|
19
19
|
# There are four basic operations you can broadcast: <tt>insert</tt>, <tt>update</tt>, <tt>upsert</tt>,
|
|
20
20
|
# and <tt>delete</tt>. As a rule, you should use the <tt>_later</tt> versions when broadcasting within
|
|
@@ -48,9 +48,9 @@ module DurableStreams
|
|
|
48
48
|
config.durable_streams.server_api_key ||
|
|
49
49
|
::Rails.application.key_generator.generate_key("durable_streams/server_api_key").unpack1("H*")
|
|
50
50
|
|
|
51
|
-
if DurableStreams.
|
|
51
|
+
if DurableStreams.server_url.present?
|
|
52
52
|
DurableStreams.configure do |c|
|
|
53
|
-
c.base_url = DurableStreams.
|
|
53
|
+
c.base_url = DurableStreams.server_url
|
|
54
54
|
c.default_headers = { "Authorization" => "Bearer #{DurableStreams.server_api_key}" }
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -12,7 +12,8 @@ module DurableStreams
|
|
|
12
12
|
extend DurableStreams::Rails::StreamProvisioner
|
|
13
13
|
extend DurableStreams::Rails::Broadcasts
|
|
14
14
|
|
|
15
|
-
mattr_accessor :
|
|
15
|
+
mattr_accessor :client_url
|
|
16
|
+
mattr_accessor :server_url
|
|
16
17
|
mattr_accessor :draw_routes, default: true
|
|
17
18
|
mattr_accessor :signed_stream_url_expires_in, default: 24.hours
|
|
18
19
|
|
|
@@ -38,7 +39,7 @@ module DurableStreams
|
|
|
38
39
|
{ "stream" => path, "permissions" => permissions.map(&:to_s) },
|
|
39
40
|
expires_in: expires_in
|
|
40
41
|
)
|
|
41
|
-
"#{
|
|
42
|
+
"#{client_url}/#{path}?token=#{token}"
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
# Verifies the signed token embedded in a stream URL. Used by the auth controller
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# Client-facing URL for signed stream URLs (what browsers connect to).
|
|
2
|
+
DurableStreams.client_url = ENV.fetch("DURABLE_STREAMS_CLIENT_URL", "http://localhost:4437/v1/streams")
|
|
3
|
+
|
|
4
|
+
# Server-to-server URL for broadcasts and stream provisioning.
|
|
5
|
+
# In single-server setups this matches client_url. In multi-server deployments
|
|
6
|
+
# this should point to the internal address of the Durable Streams server.
|
|
7
|
+
DurableStreams.server_url = ENV.fetch("DURABLE_STREAMS_SERVER_URL", "http://localhost:4437/v1/streams")
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: durable_streams-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- tokimonki
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
version: '8.0'
|
|
40
40
|
description: Stream State Protocol events from Active Record models with the same
|
|
41
41
|
DX as Turbo Broadcasts — declarative streaming, automatic callbacks, and async jobs
|
|
42
|
-
— but with offset-based resumability and persistent event logs over
|
|
42
|
+
— but with offset-based resumability and persistent event logs over HTTP.
|
|
43
43
|
email: opensource@tokimonki.com
|
|
44
44
|
executables: []
|
|
45
45
|
extensions: []
|