didww-v3 6.1.0 → 6.1.1

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: 9cdeedbb317141c84de28bbedb4f652b858793e257d8d84f70155b08fc54623c
4
- data.tar.gz: c48319beb5292ef53595e7905d4ac62ff0e59685bcb57eb48c2f7e6efbb7bd3e
3
+ metadata.gz: d834eeacdcc690b1b19e390a31730342681b1efe94d1e5f124d9b8c82d9ba5ca
4
+ data.tar.gz: 694e8a57d08a8cd646d715d424a1824aff726b3af40190db4749417de158c3ca
5
5
  SHA512:
6
- metadata.gz: 42be04280b6673a827de5f4bc680f032f28d72437137d081455f2168aa02e92d3861b7fc842e6c70406e6495d1f377745f90a23ead254fdf0a5a6caf40417d63
7
- data.tar.gz: e6aeccf261500d0307c5cbc7eae427880a853d008ce28639ff2512daa1ea1cb40c54962b3d0f972f7e3ea0a73274bc40a6a8a57b9df45689b9c0ddfb83987acb
6
+ metadata.gz: 0565f13367337588e62fadcc5464a3aaea268567b8b7af51e1c0f1b221027be039f242d1fae74e3a1b8980edff2add2cd394055b7e4c30a4bc453c0e39e15288
7
+ data.tar.gz: 44ceb7b1488be5a77b1d1b15a3ed45fd963a09e280941a5a14a7476fa331355ac81768974149aab51d44a38fe1d0f2717fb8fd38fd456704e6e9ccbe505d9879
data/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [6.1.1] - 2026-05-04
8
+ ### Fixed
9
+ - `SipConfiguration#enabled_sip_registration = true` now always emits `host: null` and `port: null` on the wire, not only when the local attribute hash already had them set. The previous conditional cascade (introduced in 6.1.0) silently no-op'd when re-enabling SIP registration on an existing trunk through a fresh `SipConfiguration` instance: the PATCH body carried only `enabled_sip_registration: true`, the server merged it with the trunk's persisted host, and rejected with 422 (`host must be blank when the SIP registration is enabled`). Verified end-to-end against the live sandbox via the new `examples/voice_in_trunk_sip_registration.rb`.
10
+
11
+ ### Added
12
+ - `examples/voice_in_trunk_sip_registration.rb` — end-to-end create / rename / disable / re-enable flow demonstrating every cascade rule against the sandbox API.
13
+
7
14
  ## [6.1.0] - 2026-05-04
8
15
  ### Added
9
16
  - Complete the 2026-04-16 `SipConfiguration` attribute set that was missed during the 2026-04-16 rollout (and is not present in the public Postman collection — server form is the source of truth):
data/didww-v3.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ['alex.k@didww.com']
12
12
 
13
13
  spec.summary = %q{Ruby client for DIDWW API v3}
14
- spec.description = %q{Ruby client for DIDWW API v3}
14
+ spec.description = %q{Ruby client for the DIDWW JSON:API v3, covering DID inventory, voice in/out trunks, regulatory documents, exports, and emergency calling services.}
15
15
  spec.homepage = 'https://github.com/didww/didww-v3-ruby'
16
16
  spec.license = 'MIT'
17
17
 
@@ -24,11 +24,16 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.required_ruby_version = '>= 3.3'
26
26
 
27
- spec.add_dependency 'activesupport'
28
- spec.add_dependency 'faraday'
29
- spec.add_dependency 'faraday-multipart'
30
- spec.add_dependency 'json_api_client', '1.23.0'
31
- spec.add_dependency 'http'
32
- spec.add_dependency 'down'
33
- spec.add_dependency 'openssl-oaep'
27
+ # Lower bounds match the oldest version verified by CI; upper bounds
28
+ # cap on the next known-incompatible major so consumers get a clear
29
+ # constraint failure rather than a runtime surprise. The CI matrix in
30
+ # .github/workflows/tests.yml exercises activesupport ~> 7.2 / 8.0 /
31
+ # 8.1 — declaring a wider lower bound than that would be aspirational.
32
+ spec.add_dependency 'activesupport', '>= 7.2', '< 9'
33
+ spec.add_dependency 'faraday', '~> 2.0'
34
+ spec.add_dependency 'faraday-multipart', '~> 1.0'
35
+ spec.add_dependency 'json_api_client', '1.23.0'
36
+ spec.add_dependency 'http', '~> 5.0'
37
+ spec.add_dependency 'down', '~> 5.0'
38
+ spec.add_dependency 'openssl-oaep', '~> 0.1'
34
39
  end
data/examples/README.md CHANGED
@@ -41,6 +41,7 @@ DIDWW_API_KEY=your_api_key ruby examples/orders_nanpa.rb
41
41
  | Script | Description |
42
42
  |---|---|
43
43
  | [`voice_in_trunks.rb`](voice_in_trunks.rb) | Lists voice in trunks and their configurations. |
44
+ | [`voice_in_trunk_sip_registration.rb`](voice_in_trunk_sip_registration.rb) | End-to-end SIP registration flow: create with `enabled_sip_registration: true`, rename, disable by setting `host`, re-enable by toggling the flag. The SDK keeps the dependent fields (`host`, `port`, `use_did_in_ruri`) aligned with the server's validation rules automatically. |
44
45
  | [`voice_in_trunk_groups.rb`](voice_in_trunk_groups.rb) | CRUD for trunk groups with trunk relationships. |
45
46
 
46
47
  ### Voice Out (Outbound)
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # End-to-end SIP registration flow on /voice_in_trunks (API 2026-04-16):
4
+ # create with sip_registration enabled → rename → disable by setting
5
+ # `host` → re-enable by toggling the flag. The SDK keeps the
6
+ # dependent fields (`host`, `port`, `use_did_in_ruri`) aligned with
7
+ # the server's validation rules automatically. The sandbox trunk is
8
+ # left in place after the script completes so it can be inspected
9
+ # afterwards.
10
+ #
11
+ # Usage: DIDWW_API_KEY=your_sandbox_key ruby examples/voice_in_trunk_sip_registration.rb
12
+
13
+ require 'bundler/setup'
14
+ require 'didww'
15
+
16
+ DIDWW::Client.configure do |client|
17
+ client.api_key = ENV.fetch('DIDWW_API_KEY') { abort 'Please set DIDWW_API_KEY' }
18
+ client.api_mode = :sandbox
19
+ end
20
+
21
+ puts "=== Ruby SDK v#{DIDWW::VERSION} — SIP registration flow ==="
22
+
23
+ # 1) Create a SIP trunk with sip_registration enabled. The server
24
+ # generates `incoming_auth_*` credentials and returns them in the
25
+ # response — they are read-only and stripped from any subsequent
26
+ # write payload by the SDK.
27
+ puts "\n[1/4] Create with sip_registration enabled..."
28
+ trunk = DIDWW::Client.voice_in_trunks.new(
29
+ name: "sip-registration-example-#{Time.now.to_i}",
30
+ priority: 1,
31
+ weight: 100,
32
+ cli_format: 'e164',
33
+ ringing_timeout: 30,
34
+ configuration: DIDWW::ComplexObject::SipConfiguration.new.tap do |c|
35
+ c.enabled_sip_registration = true
36
+ c.use_did_in_ruri = true
37
+ c.cnam_lookup = false
38
+ c.codec_ids = [9, 7]
39
+ c.transport_protocol_id = 1
40
+ end
41
+ )
42
+ abort "create failed: #{trunk.errors.full_messages.join('; ')}" unless trunk.save
43
+ puts " id=#{trunk.id}"
44
+ puts " incoming_auth_username=#{trunk.configuration.incoming_auth_username.inspect}"
45
+ puts " incoming_auth_password=#{trunk.configuration.incoming_auth_password.inspect}"
46
+ trunk_id = trunk.id
47
+
48
+ # 2) Rename — a single-field PATCH that doesn't touch SIP-registration state.
49
+ puts "\n[2/4] Rename trunk..."
50
+ trunk.name = "sip-registration-renamed-#{Time.now.to_i}"
51
+ abort "rename failed: #{trunk.errors.full_messages.join('; ')}" unless trunk.save
52
+ puts " name=#{trunk.name}"
53
+
54
+ # 3) Disable sip_registration by setting `host`. The SDK flips
55
+ # `enabled_sip_registration` and `use_did_in_ruri` to false in the
56
+ # same PATCH so the server-side validators accept the change.
57
+ puts "\n[3/4] Disable by setting host..."
58
+ trunk.configuration = DIDWW::ComplexObject::SipConfiguration.new.tap do |c|
59
+ c.host = '203.0.113.10'
60
+ end
61
+ abort "disable failed: #{trunk.errors.full_messages.join('; ')}" unless trunk.save
62
+ fresh = DIDWW::Client.voice_in_trunks.find(trunk_id).first
63
+ puts " enabled_sip_registration=#{fresh.configuration.enabled_sip_registration.inspect}"
64
+ puts " use_did_in_ruri=#{fresh.configuration.use_did_in_ruri.inspect}"
65
+ puts " host=#{fresh.configuration.host.inspect}"
66
+ puts " incoming_auth_username=#{fresh.configuration.incoming_auth_username.inspect}"
67
+
68
+ # 4) Re-enable sip_registration. Setting `enabled_sip_registration = true`
69
+ # sends host=nil / port=nil on the wire so the server (which still has
70
+ # the host from step 3) is told to clear them.
71
+ puts "\n[4/4] Re-enable by toggling enabled_sip_registration..."
72
+ trunk = DIDWW::Client.voice_in_trunks.find(trunk_id).first
73
+ trunk.configuration = DIDWW::ComplexObject::SipConfiguration.new.tap do |c|
74
+ c.enabled_sip_registration = true
75
+ c.use_did_in_ruri = true
76
+ end
77
+ abort "re-enable failed: #{trunk.errors.full_messages.join('; ')}" unless trunk.save
78
+ fresh = DIDWW::Client.voice_in_trunks.find(trunk_id).first
79
+ puts " enabled_sip_registration=#{fresh.configuration.enabled_sip_registration.inspect}"
80
+ puts " host=#{fresh.configuration.host.inspect}"
81
+ puts " incoming_auth_username=#{fresh.configuration.incoming_auth_username.inspect}"
82
+
83
+ puts "\n=== PASS — trunk #{trunk_id} left in sandbox ==="
@@ -350,12 +350,14 @@ module DIDWW
350
350
  def enabled_sip_registration=(val)
351
351
  case val
352
352
  when true
353
- # Clear host/port only if they were already set never emit a
354
- # spurious `host: null` on a fresh config, which would otherwise
355
- # widen every PATCH/POST body. If the trunk had a host, we have
356
- # to send `host: null` explicitly so the server clears it.
357
- self[:host] = nil if attributes.key?('host') && !self[:host].nil?
358
- self[:port] = nil if attributes.key?('port') && !self[:port].nil?
353
+ # Always emit host: null and port: null on the wire when
354
+ # enabling sip_registration. The server requires both blank
355
+ # (returns 422 otherwise) AND a PATCH against an existing
356
+ # trunk that already has host/port set on the server side
357
+ # MUST explicitly nullify them — the SDK's local attributes
358
+ # hash starts empty, so there's nothing to "preserve".
359
+ self[:host] = nil
360
+ self[:port] = nil
359
361
  when false
360
362
  # Server requires use_did_in_ruri = false whenever sip_registration
361
363
  # is disabled. Always emit it on the wire so the server's check
data/lib/didww/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module DIDWW
3
- VERSION = '6.1.0'.freeze
3
+ VERSION = '6.1.1'.freeze
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: didww-v3
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0
4
+ version: 6.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Korobeinikov
@@ -15,42 +15,48 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
18
+ version: '7.2'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
26
  - - ">="
24
27
  - !ruby/object:Gem::Version
25
- version: '0'
28
+ version: '7.2'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: faraday
28
34
  requirement: !ruby/object:Gem::Requirement
29
35
  requirements:
30
- - - ">="
36
+ - - "~>"
31
37
  - !ruby/object:Gem::Version
32
- version: '0'
38
+ version: '2.0'
33
39
  type: :runtime
34
40
  prerelease: false
35
41
  version_requirements: !ruby/object:Gem::Requirement
36
42
  requirements:
37
- - - ">="
43
+ - - "~>"
38
44
  - !ruby/object:Gem::Version
39
- version: '0'
45
+ version: '2.0'
40
46
  - !ruby/object:Gem::Dependency
41
47
  name: faraday-multipart
42
48
  requirement: !ruby/object:Gem::Requirement
43
49
  requirements:
44
- - - ">="
50
+ - - "~>"
45
51
  - !ruby/object:Gem::Version
46
- version: '0'
52
+ version: '1.0'
47
53
  type: :runtime
48
54
  prerelease: false
49
55
  version_requirements: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - ">="
57
+ - - "~>"
52
58
  - !ruby/object:Gem::Version
53
- version: '0'
59
+ version: '1.0'
54
60
  - !ruby/object:Gem::Dependency
55
61
  name: json_api_client
56
62
  requirement: !ruby/object:Gem::Requirement
@@ -69,45 +75,46 @@ dependencies:
69
75
  name: http
70
76
  requirement: !ruby/object:Gem::Requirement
71
77
  requirements:
72
- - - ">="
78
+ - - "~>"
73
79
  - !ruby/object:Gem::Version
74
- version: '0'
80
+ version: '5.0'
75
81
  type: :runtime
76
82
  prerelease: false
77
83
  version_requirements: !ruby/object:Gem::Requirement
78
84
  requirements:
79
- - - ">="
85
+ - - "~>"
80
86
  - !ruby/object:Gem::Version
81
- version: '0'
87
+ version: '5.0'
82
88
  - !ruby/object:Gem::Dependency
83
89
  name: down
84
90
  requirement: !ruby/object:Gem::Requirement
85
91
  requirements:
86
- - - ">="
92
+ - - "~>"
87
93
  - !ruby/object:Gem::Version
88
- version: '0'
94
+ version: '5.0'
89
95
  type: :runtime
90
96
  prerelease: false
91
97
  version_requirements: !ruby/object:Gem::Requirement
92
98
  requirements:
93
- - - ">="
99
+ - - "~>"
94
100
  - !ruby/object:Gem::Version
95
- version: '0'
101
+ version: '5.0'
96
102
  - !ruby/object:Gem::Dependency
97
103
  name: openssl-oaep
98
104
  requirement: !ruby/object:Gem::Requirement
99
105
  requirements:
100
- - - ">="
106
+ - - "~>"
101
107
  - !ruby/object:Gem::Version
102
- version: '0'
108
+ version: '0.1'
103
109
  type: :runtime
104
110
  prerelease: false
105
111
  version_requirements: !ruby/object:Gem::Requirement
106
112
  requirements:
107
- - - ">="
113
+ - - "~>"
108
114
  - !ruby/object:Gem::Version
109
- version: '0'
110
- description: Ruby client for DIDWW API v3
115
+ version: '0.1'
116
+ description: Ruby client for the DIDWW JSON:API v3, covering DID inventory, voice
117
+ in/out trunks, regulatory documents, exports, and emergency calling services.
111
118
  email:
112
119
  - alex.k@didww.com
113
120
  executables: []
@@ -158,6 +165,7 @@ files:
158
165
  - examples/regions.rb
159
166
  - examples/shared_capacity_groups.rb
160
167
  - examples/voice_in_trunk_groups.rb
168
+ - examples/voice_in_trunk_sip_registration.rb
161
169
  - examples/voice_in_trunks.rb
162
170
  - examples/voice_out_trunks.rb
163
171
  - lib/didww.rb