sendmux-core 1.2.0 → 1.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: ff4ba7f22a000b14507a25981b13a01a670fb31e668df0557ebe9c2235250e70
4
- data.tar.gz: 40c0a5588f8dcccdad392eb4a5fd377787515af71de933406ab1da8ea118b9fd
3
+ metadata.gz: f39dc569a3376fb13568b300d2cf22819cf1815894fac4f749cd8b0cd5622100
4
+ data.tar.gz: bc14bfe99f7242ba965ff6f676d6fd2a4a7608b7530e0576ab4e3f7fce3fc29b
5
5
  SHA512:
6
- metadata.gz: 1845afef061ef4c6fd27a43a286007a0f628db39439c3d2a7bf0f813873345cac550f2c662a826a7a573c5ca7ffd1c39ac26e5508e8a88440799fe29a3a25e36
7
- data.tar.gz: 77b6fec300b2fdce52fa4c7f21bd1d5122d01f05db8e5c36cf5f90fbbf3877b43086cfa2ab4dbdd27ad33c6c7bf098c62bc27ada7ed5ee1677865e68b2b1d708
6
+ metadata.gz: a1976ba03f4693dee9b5b7a4dec6722a037d0ae2c170069bcda0e29d04a200ddcf399136bd2d3a3476c7c967d33e15ff2b71cb221adf5a3d59489e8d7a190a0d
7
+ data.tar.gz: 9915b261526d42672bb55ed28be7bc5fe3171093eedc04b0cb5819de3c0e2a83ee372e9e73e21b748baab38d3358462820c3d8eda8468343dde5c513c36d5b9b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.0](https://github.com/Sendmux/sendmux-sdk/compare/ruby-core/v1.2.0...ruby-core/v1.3.0) (2026-09-10)
4
+
5
+
6
+ ### Features
7
+
8
+ * add REST OAuth clients and CLI token lifecycle ([cc4a3aa](https://github.com/Sendmux/sendmux-sdk/commit/cc4a3aa6110378641418a94455ed5b9a986e65ff))
9
+
3
10
  ## [1.2.0](https://github.com/Sendmux/sendmux-sdk/compare/ruby-core/v1.1.0...ruby-core/v1.2.0) (2026-09-08)
4
11
 
5
12
 
data/README.md CHANGED
@@ -15,7 +15,7 @@ Shared authentication, retry, pagination, header, and error helpers for the Send
15
15
  ## Requirements
16
16
 
17
17
  - Ruby 3.1 or newer.
18
- - A Sendmux API key when using the helpers with a surface client.
18
+ - A Sendmux API key or REST OAuth access token when using a surface client.
19
19
 
20
20
  ## Installation
21
21
 
@@ -46,6 +46,8 @@ puts surface
46
46
 
47
47
  Use `Sendmux::Core::ApiKeySurface::ROOT` for root-key management clients, `Sendmux::Core::ApiKeySurface::SENDING` for send-capable `smx_mbx_` keys or owner-approved Sending-resource `smx_agent_` tokens, and `Sendmux::Core::ApiKeySurface::MAILBOX` for mailbox-compatible credentials. Mailbox-compatible credentials can start with `smx_mbx_` or `smx_agent_`.
48
48
 
49
+ Surface clients accept `access_token:` as a bare token or callable instead of `api_key:`. Token providers run before each request; the application owns token storage and refresh.
50
+
49
51
  ### Header helpers
50
52
 
51
53
  Generated Ruby operations accept option hashes. The header helpers return the option keys expected by those generated operations.
@@ -9,17 +9,41 @@ module Sendmux
9
9
  MAILBOX_PREFIX = 'smx_mbx_'
10
10
  AGENT_PREFIX = 'smx_agent_'
11
11
 
12
- def self.configure_bearer(configuration, api_key, expected_surface, base_url: nil)
13
- assert_api_key_surface(api_key, expected_surface)
12
+ def self.configure_bearer(configuration, api_key, expected_surface, base_url: nil, access_token: nil)
13
+ raise ArgumentError, 'Provide exactly one of api_key or access_token' if api_key.nil? == access_token.nil?
14
14
  unless configuration.respond_to?(:access_token=)
15
15
  raise ArgumentError, 'Generated configuration does not support bearer access tokens'
16
16
  end
17
17
 
18
- configuration.access_token = api_key
18
+ if api_key.nil?
19
+ configure_access_token(configuration, access_token)
20
+ else
21
+ assert_api_key_surface(api_key, expected_surface)
22
+ configuration.access_token = api_key
23
+ configuration.access_token_getter = nil if configuration.respond_to?(:access_token_getter=)
24
+ end
19
25
  configure_base_url(configuration, base_url) if base_url && !base_url.empty?
20
26
  configuration
21
27
  end
22
28
 
29
+ def self.configure_access_token(configuration, access_token)
30
+ if access_token.respond_to?(:call)
31
+ configuration.access_token = nil
32
+ configuration.access_token_getter = -> { validate_access_token(access_token.call) }
33
+ else
34
+ configuration.access_token = validate_access_token(access_token)
35
+ configuration.access_token_getter = nil if configuration.respond_to?(:access_token_getter=)
36
+ end
37
+ end
38
+
39
+ def self.validate_access_token(token)
40
+ unless token.is_a?(String) && token.match?(%r{\A[A-Za-z0-9._~+/-]+=*\z})
41
+ raise ArgumentError, 'Provide a valid bare access token'
42
+ end
43
+
44
+ token
45
+ end
46
+
23
47
  def self.assert_api_key_surface(api_key, expected_surface)
24
48
  actual = surface_for(api_key)
25
49
  unless actual
@@ -13,12 +13,20 @@ module Sendmux
13
13
  end
14
14
 
15
15
  def self.retryable_request?(env)
16
+ return false if explicitly_non_retryable?(env[:body])
17
+
16
18
  method = env[:method].to_s.upcase
17
19
  return true if SAFE_METHODS.include?(method)
18
20
 
19
21
  method == 'POST' && header(env[:request_headers] || {}, 'Idempotency-Key') && replayable_body?(env[:body])
20
22
  end
21
23
 
24
+ def self.explicitly_non_retryable?(body)
25
+ payload = ErrorMapper.payload_from(body)
26
+ detail = ErrorMapper.hash_at(payload, 'error')
27
+ payload.is_a?(Hash) && payload['ok'] == false && detail && detail['retryable'] == false
28
+ end
29
+
22
30
  def self.header(headers, name)
23
31
  headers.find { |key, _value| key.to_s.downcase == name.downcase }&.last
24
32
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sendmux
4
4
  module Core
5
- VERSION = '1.2.0'
5
+ VERSION = '1.3.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sendmux-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sendmux
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-09-08 00:00:00.000000000 Z
10
+ date: 2026-09-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: faraday