broadcast-ruby 0.1.4 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3bd138dfa8311b17c14ef537073cdf62406503d605b83f3d49b96659e28cda9
4
- data.tar.gz: 6d7f2dccd5e01060b566bcd35a65a74349a078b9ed68348a4d510a98a8faf219
3
+ metadata.gz: fec10ff364f7b63e728e1da143f2e0ff4445e2466f8a9e1a307370142d4c8666
4
+ data.tar.gz: efce695852b7774e6e40f1f91a93ee2487e8d635a579ab0fe20505a9fe4a9efe
5
5
  SHA512:
6
- metadata.gz: '0164853b6f09a1f00227adf8201e0cd53a6ff84ece799471f839994e8b2dae6cc65486e08bc3877b9640056eabf9bba8b9659fc2c8a2a4172117b5b1fbc482cf'
7
- data.tar.gz: b31dfa8c5e5f6ebcf6cb3861e92e82fe3b13f66e60d163da7dfbdc5d80abbd669f3a066259aa6316aaa3a1a5017ade083f12a67d82acb84299e1cb271f87b680
6
+ metadata.gz: b72667f6f90ecb99ec60d0d9c905f529fbf0f78e30386e78ca93aeb1ac783e2a923750b76a41b73f2da771be67b3bfca012749066614a2ddb99c6cebb093924c
7
+ data.tar.gz: ff0b6ba2de7606b7dbc1fab2c552f6947158cd69ad28ae328d3b23f1d52b8878700802a08d108841e7453b5495398258c70e2e287bbc5ac76e1a908baedab1c1
data/CHANGELOG.md CHANGED
@@ -2,6 +2,119 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.3.0] - 2026-07-26
6
+
7
+ Catches the gem up to the Broadcast v2.19 API. The API gained a response-warnings
8
+ contract, idempotency keys, and several discovery endpoints since 0.2.0; none of
9
+ them were represented here.
10
+
11
+ ### Breaking
12
+ - **`host` is now required.** It previously defaulted to `https://sendbroadcast.com`,
13
+ which 301-redirects to `sendbroadcast.net` — and since the client did not follow
14
+ redirects, the default failed every request with
15
+ `APIError: Unexpected response: 301`. Broadcast is self-hosted-first, so there is
16
+ no URL the gem can guess. Pass `host:` explicitly or set `BROADCAST_HOST`.
17
+ A host without a scheme is now rejected at construction rather than at request time.
18
+
19
+ ### Added
20
+ - **`client.autopilots`** — the Autopilot API (AI-generated newsletters): CRUD,
21
+ activate / pause / deactivate, trigger_run, and runs. The `autopilot_read` /
22
+ `autopilot_write` token permissions existed since 2026-01-30 but had no
23
+ endpoints behind them until Broadcast v2.19.1. `update` strips a bullet-masked
24
+ `openrouter_api_key` so a fetch-modify-save cannot destroy the stored key.
25
+ - **API warnings.** Successful writes can carry a `warnings` array describing what
26
+ the server ignored (`unrecognized_parameter`, `parameter_ignored`,
27
+ `parameter_overridden`, `double_opt_in_skipped`). Exposed as `result.warnings`
28
+ and controlled by `warnings_mode:` — `:log` (default), `:raise`, or `:ignore`.
29
+ - **`Broadcast::Response`.** All JSON calls now return a Hash subclass carrying
30
+ `#warnings`, `#rate_limit`, `#status`, `#headers`, and `#idempotent_replay?`.
31
+ Existing Hash-based code is unaffected.
32
+ - **Idempotent transactional sends.** `transactionals.create(..., idempotency_key:)`
33
+ sends the `Idempotency-Key` header; `Broadcast::ConflictError` maps 409 (previously
34
+ a generic `APIError`).
35
+ - **Rate-limit awareness.** `result.rate_limit` exposes the `X-RateLimit-*` headers,
36
+ `RateLimitError#retry_after` exposes `Retry-After`, and 429s are now retried
37
+ honouring it, bounded by the new `max_retry_delay` setting (default 30s).
38
+ - **Discovery endpoints:** `client.whoami`, `client.status`, `client.prime`, and
39
+ `client.skill` (plain text).
40
+ - **Migration/export namespace:** `client.migration.*` covers all 19 read-only
41
+ endpoints under `/api/migration/v1`, plus `each_record` for automatic paging and
42
+ `download_file_asset` for binary assets. Requires an admin token.
43
+ - **`Broadcast::Webhook::EVENT_TYPES`** and per-category constants (`EMAIL_EVENTS`,
44
+ `SUBSCRIBER_EVENTS`, `BROADCAST_EVENTS`, `SEQUENCE_EVENTS`, `SYSTEM_EVENTS`).
45
+ - `BROADCAST_HOST` / `BROADCAST_API_TOKEN` environment fallbacks, matching the
46
+ Broadcast CLI's config keys.
47
+ - Redirect handling: same-host GETs follow up to 3 hops. Writes, and any redirect
48
+ that changes host, fail with an error naming the target — every request carries
49
+ the bearer token, so following a cross-host redirect would leak it.
50
+ - Documented attributes added to the API after 0.2.0 — template
51
+ `template_purpose` / `confirmation_text` / `default_confirmation` /
52
+ `confirmation_page_settings`; opt-in form `confirmation_email_template_id` /
53
+ `welcome_email_template_id` / `confirmation_redirect_url` /
54
+ `include_unsubscribe_link_in_confirmation`; admin-only `confirmed_at` on
55
+ subscriber create; and the full subscriber list filter set.
56
+
57
+ ### Fixed
58
+ - Debug logging redacted: SMTP passwords and provider API keys are no longer written
59
+ to the log when `debug: true`.
60
+ - 2xx responses other than 200/201 (e.g. 204) no longer raise.
61
+ - A 2xx response with a non-JSON body no longer raises `JSON::ParserError`.
62
+ - Error messages now include ActiveModel-style `errors` hashes, not just `error` strings.
63
+ - Binary responses keep binary encoding instead of being tagged UTF-8.
64
+ - The ActionMailer delivery method no longer wraps `WarningError` in `DeliveryError` —
65
+ the email was sent, so reporting a delivery failure would be wrong.
66
+ - **Packaging:** the gemspec shipped this repo's internal planning documents
67
+ (`TODO.md`, `SDK-TODO.md`, `.api-coverage.yml`) and the committed `.gem`
68
+ artifacts at the repo root to every install. The file list now excludes them,
69
+ along with `.github/` and `pkg/`. `SDK-COVERAGE.md` is kept deliberately —
70
+ "what does this gem support" is a user's question.
71
+
72
+ ### Internal
73
+ - HTTP transport extracted from `Client` into `Broadcast::Connection`, and debug
74
+ logging into `Broadcast::DebugLogger`.
75
+ - Test coverage for the gemspec's file list, since a wrong package fails
76
+ silently: nothing breaks, the download is just wrong.
77
+
78
+ ### Verification
79
+ - 292 tests, rubocop clean.
80
+ - Coverage against the generated OpenAPI document: 104/104 operations
81
+ (`rake "openapi:coverage[../broadcast-ruby]"` in the `broadcast` repo).
82
+ - The built `.gem` was installed into an isolated `GEM_HOME` and exercised.
83
+ - `rake test_live` run against a real self-hosted instance: 14 tests, 52
84
+ assertions, 0 failures. Covers the discovery endpoints, the `X-RateLimit-*`
85
+ headers, and full create/read/update/delete round-trips for subscribers,
86
+ sequences, segments, templates, and webhook endpoints.
87
+ - Two gaps in that run, both deliberate: the transactional **send** test is
88
+ skipped unless `BROADCAST_TEST_EMAIL` is set, so no mail was delivered; and
89
+ the target was a local development instance over plain HTTP, so TLS and
90
+ real-world latency and rate limiting are still unexercised.
91
+
92
+ ## [0.2.0] - 2026-04-28
93
+
94
+ ### Added
95
+ - `client.opt_in_forms` resource: list, get, create, update, delete, analytics, create_variant, duplicate
96
+ - `client.email_servers` resource: list, get, create, update, delete, test_connection, copy_to_channel
97
+ - `client.transactionals` resource with full create surface (`template_id`, `preheader`, `include_unsubscribe_link`, `subscriber:` attrs); `client.send_email` and `client.get_email` are now thin shims that delegate
98
+ - Double opt-in support: pass `double_opt_in: true` (or a hash with `reply_to:` / `confirmation_template_id:` / `include_unsubscribe_link:`) to `transactionals.create` and `subscribers.create`. Optional top-level `confirmation_template_id:` is also accepted
99
+ - `Configuration#broadcast_channel_id` plus `client.with_channel(id) { ... }` block API for admin/system tokens — auto-includes the channel on every request inside the block (or globally when set on config), without overriding callers that pass it explicitly
100
+ - `Broadcast::AuthorizationError` for 403 responses (previously fell through to a generic `APIError`)
101
+ - Credential redaction scrubber on `email_servers.update`: values matching the API's bullet-redaction shape on known credential fields are stripped from the payload (with a logger warning) so callers can't accidentally round-trip a redacted response back into the model
102
+
103
+ ### Notes
104
+ - `opt_in_forms.list` returns up to 250 results per page with `pagination` metadata; only main forms are returned (variants are excluded)
105
+ - `opt_in_forms` `index`/`show` JSON shape (rendered via JBuilder views) differs slightly from `create`/`update` (rendered via the controller's inline serializer)
106
+ - `email_servers.copy_to_channel` requires an admin token and is account-scoped in SaaS mode
107
+
108
+ ## [0.1.4] - 2026-03-18
109
+
110
+ ### Fixed
111
+ - Register delivery method at class load time instead of in an initializer. ActionMailer's railtie applies config settings (including `broadcast_settings`) inside `on_load(:action_mailer)`, which ran before our initializer-based registration. This caused `undefined method broadcast_settings=` on boot in Rails 8.1.
112
+
113
+ ## [0.1.3] - 2026-03-18
114
+
115
+ ### Fixed
116
+ - Attempted fix for Railtie timing: use `before: :load_config_initializers`. Did not fully resolve the issue — superseded by 0.1.4.
117
+
5
118
  ## [0.1.2] - 2026-03-18
6
119
 
7
120
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- broadcast-ruby (0.1.4)
4
+ broadcast-ruby (0.3.0)
5
5
  base64
6
6
 
7
7
  GEM
@@ -155,6 +155,7 @@ GEM
155
155
 
156
156
  PLATFORMS
157
157
  arm64-darwin-24
158
+ arm64-darwin-25
158
159
  x86_64-linux
159
160
 
160
161
  DEPENDENCIES
@@ -176,7 +177,7 @@ CHECKSUMS
176
177
  ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
177
178
  base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
178
179
  bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
179
- broadcast-ruby (0.1.4)
180
+ broadcast-ruby (0.3.0)
180
181
  builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
181
182
  concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
182
183
  connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a