pubnub 6.1.0 → 6.2.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/.pubnub.yml +18 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -0
- data/VERSION +1 -1
- data/features/support/hooks.rb +1 -1
- data/lib/pubnub/cbor.rb +50 -20
- data/lib/pubnub/constants.rb +1 -1
- data/lib/pubnub/event.rb +1 -1
- data/lib/pubnub/events/grant.rb +18 -4
- data/lib/pubnub/events/grant_token.rb +16 -1
- data/lib/pubnub/validators/grant.rb +22 -0
- data/lib/pubnub/validators/grant_token.rb +22 -0
- data/lib/pubnub/version.rb +1 -1
- data/pubnub.gemspec +4 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 376093de161830660661ecd60b0eb9a7f38e06096efad64a5588d5b00aaaa554
|
|
4
|
+
data.tar.gz: 8409b67c533fc6d079d230eb0bea64eddbbdc40ddb48ff95bb48be116aa5be16
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6df8f51d9465cfdf3f9c4cc14ae0afb83e43cc4d83d20c78ae8e9fb7fb9eed99f83f9879e29a334dfbae52d8a39a084c8903b433c4248ae49d51f9cfe58fb766
|
|
7
|
+
data.tar.gz: e6e014c7736f84bcab8eab9b464f1622051372c99097750b5745942e0a153b84dd3fb4a9469516194238d84ae31d03444a9501fc45d2ab61d2573ff40a507377
|
data/.pubnub.yml
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
---
|
|
2
|
-
version: "6.
|
|
2
|
+
version: "6.2.0"
|
|
3
3
|
changelog:
|
|
4
|
+
- date: 2026-10-21
|
|
5
|
+
version: v6.2.0
|
|
6
|
+
changes:
|
|
7
|
+
- type: feature
|
|
8
|
+
text: "Add `categories` support to `grant` and `grant_token` for granting enumeration (`get`) permission on all `channels` and `uuids` metadata."
|
|
9
|
+
- date: 2026-07-21
|
|
10
|
+
version: v6.1.1
|
|
11
|
+
changes:
|
|
12
|
+
- type: bug
|
|
13
|
+
text: "`Pubnub::Cbor` now enforces a recursion-depth cap, a per-container length cap, and a total input size cap. Malformed or attacker-crafted tokens reaching `Pubnub::Client#parse_token` raise `Pubnub::Cbor::DecodeError` instead of hanging the caller or triggering `SystemStackError`."
|
|
14
|
+
- type: bug
|
|
15
|
+
text: "`Pubnub::Constants::DEFAULT_SSL` flipped from `false` to `true`. Integrators must now opt out explicitly to send traffic in cleartext."
|
|
16
|
+
- type: bug
|
|
17
|
+
text: "The Requested URI debug entry in `Pubnub::Event#uri` now masks the `signature` and `pnsig` query parameter values."
|
|
4
18
|
- date: 2026-06-15
|
|
5
19
|
version: v6.1.0
|
|
6
20
|
changes:
|
|
@@ -647,7 +661,7 @@ sdks:
|
|
|
647
661
|
- x86-64
|
|
648
662
|
- distribution-type: package
|
|
649
663
|
distribution-repository: RubyGems
|
|
650
|
-
package-name: pubnub-6.
|
|
664
|
+
package-name: pubnub-6.2.0.gem
|
|
651
665
|
location: https://rubygems.org/gems/pubnub
|
|
652
666
|
requires:
|
|
653
667
|
- name: addressable
|
|
@@ -752,8 +766,8 @@ sdks:
|
|
|
752
766
|
- x86-64
|
|
753
767
|
- distribution-type: library
|
|
754
768
|
distribution-repository: GitHub release
|
|
755
|
-
package-name: pubnub-6.
|
|
756
|
-
location: https://github.com/pubnub/ruby/releases/download/v6.
|
|
769
|
+
package-name: pubnub-6.2.0.gem
|
|
770
|
+
location: https://github.com/pubnub/ruby/releases/download/v6.2.0/pubnub-6.2.0.gem
|
|
757
771
|
requires:
|
|
758
772
|
- name: addressable
|
|
759
773
|
min-version: 2.0.0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## v6.2.0
|
|
2
|
+
October 21 2026
|
|
3
|
+
|
|
4
|
+
#### Added
|
|
5
|
+
- Add `categories` support to `grant` and `grant_token` for granting enumeration (`get`) permission on all `channels` and `uuids` metadata.
|
|
6
|
+
|
|
7
|
+
## v6.1.1
|
|
8
|
+
July 21 2026
|
|
9
|
+
|
|
10
|
+
#### Fixed
|
|
11
|
+
- `Pubnub::Cbor` now enforces a recursion-depth cap, a per-container length cap, and a total input size cap. Malformed or attacker-crafted tokens reaching `Pubnub::Client#parse_token` raise `Pubnub::Cbor::DecodeError` instead of hanging the caller or triggering `SystemStackError`.
|
|
12
|
+
- `Pubnub::Constants::DEFAULT_SSL` flipped from `false` to `true`. Integrators must now opt out explicitly to send traffic in cleartext.
|
|
13
|
+
- The Requested URI debug entry in `Pubnub::Event#uri` now masks the `signature` and `pnsig` query parameter values, per the SDK log practices ADR. `auth` and `token` remain visible at DEBUG since they are permitted URL parameters.
|
|
14
|
+
|
|
1
15
|
## v6.1.0
|
|
2
16
|
June 15 2026
|
|
3
17
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.
|
|
1
|
+
6.2.0
|
data/features/support/hooks.rb
CHANGED
data/lib/pubnub/cbor.rb
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
module Pubnub
|
|
2
2
|
class Cbor
|
|
3
|
+
class DecodeError < StandardError; end
|
|
4
|
+
|
|
5
|
+
MAX_DEPTH = 32
|
|
6
|
+
MAX_CONTAINER_LENGTH = 65_536
|
|
7
|
+
MAX_INPUT_SIZE = 1_048_576
|
|
3
8
|
|
|
4
9
|
private
|
|
5
10
|
|
|
@@ -43,9 +48,14 @@ module Pubnub
|
|
|
43
48
|
end
|
|
44
49
|
end
|
|
45
50
|
|
|
51
|
+
def take_bytes(data, count)
|
|
52
|
+
raise DecodeError, "Truncated CBOR input" if data.size < count
|
|
53
|
+
data.shift(count)
|
|
54
|
+
end
|
|
55
|
+
|
|
46
56
|
def decode_integer(data, additional)
|
|
47
57
|
if ADDITIONAL_LENGTH_BYTES.member?(additional)
|
|
48
|
-
bytearray_to_i(data
|
|
58
|
+
bytearray_to_i(take_bytes(data, ADDITIONAL_LENGTH_BYTES[additional]))
|
|
49
59
|
else
|
|
50
60
|
additional
|
|
51
61
|
end
|
|
@@ -55,7 +65,10 @@ module Pubnub
|
|
|
55
65
|
if additional <= 23
|
|
56
66
|
additional
|
|
57
67
|
else
|
|
58
|
-
|
|
68
|
+
raise DecodeError, "Invalid float additional value" unless ADDITIONAL_LENGTH_BYTES.member?(additional)
|
|
69
|
+
|
|
70
|
+
bytes = bytearray_to_i(take_bytes(data, ADDITIONAL_LENGTH_BYTES[additional]))
|
|
71
|
+
|
|
59
72
|
case (additional)
|
|
60
73
|
when ADDITIONAL_LENGTH_1B
|
|
61
74
|
bytes
|
|
@@ -98,44 +111,57 @@ module Pubnub
|
|
|
98
111
|
result = []
|
|
99
112
|
|
|
100
113
|
loop do
|
|
114
|
+
raise DecodeError, "Truncated CBOR input" if data.empty?
|
|
101
115
|
byte = data.shift
|
|
102
116
|
break if byte == INDEFINITE_BREAK
|
|
103
117
|
result.append(byte)
|
|
104
|
-
break if data.empty?
|
|
105
118
|
end
|
|
106
119
|
result
|
|
107
120
|
end
|
|
108
121
|
|
|
109
|
-
def
|
|
110
|
-
if ADDITIONAL_LENGTH_BYTES.member?(additional)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
122
|
+
def compute_container_length(data, additional, min_element_bytes)
|
|
123
|
+
length = if ADDITIONAL_LENGTH_BYTES.member?(additional)
|
|
124
|
+
bytearray_to_i(take_bytes(data, ADDITIONAL_LENGTH_BYTES[additional]))
|
|
125
|
+
else
|
|
126
|
+
additional
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
if length > MAX_CONTAINER_LENGTH
|
|
130
|
+
raise DecodeError, "CBOR container length #{length} exceeds maximum #{MAX_CONTAINER_LENGTH}"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
if length * min_element_bytes > data.size
|
|
134
|
+
raise DecodeError, "CBOR container length #{length} exceeds remaining input"
|
|
114
135
|
end
|
|
136
|
+
|
|
137
|
+
length
|
|
115
138
|
end
|
|
116
139
|
|
|
117
140
|
def decode_string(data, additional)
|
|
118
141
|
if additional == ADDITIONAL_TYPE_INDEFINITE
|
|
119
142
|
indefinite_data(data).pack('C*').force_encoding('UTF-8')
|
|
120
143
|
else
|
|
121
|
-
length =
|
|
122
|
-
data
|
|
144
|
+
length = compute_container_length(data, additional, 1)
|
|
145
|
+
take_bytes(data, length).pack('C*').force_encoding('UTF-8')
|
|
123
146
|
end
|
|
124
147
|
end
|
|
125
148
|
|
|
126
|
-
def decode_map(data, additional)
|
|
127
|
-
length =
|
|
149
|
+
def decode_map(data, additional, depth)
|
|
150
|
+
length = compute_container_length(data, additional, 2)
|
|
128
151
|
result = Hash.new
|
|
129
|
-
|
|
152
|
+
length.times { result.store(parse_data(data, depth), parse_data(data, depth)) }
|
|
130
153
|
result
|
|
131
154
|
end
|
|
132
155
|
|
|
133
|
-
def decode_array(data, additional)
|
|
134
|
-
length =
|
|
135
|
-
(
|
|
156
|
+
def decode_array(data, additional, depth)
|
|
157
|
+
length = compute_container_length(data, additional, 1)
|
|
158
|
+
Array.new(length) { parse_data(data, depth) }
|
|
136
159
|
end
|
|
137
160
|
|
|
138
|
-
def parse_data(data)
|
|
161
|
+
def parse_data(data, depth = 0)
|
|
162
|
+
raise DecodeError, "CBOR nesting depth exceeds #{MAX_DEPTH}" if depth > MAX_DEPTH
|
|
163
|
+
raise DecodeError, "Truncated CBOR input" if data.empty?
|
|
164
|
+
|
|
139
165
|
byte = data.shift
|
|
140
166
|
|
|
141
167
|
case (byte)
|
|
@@ -163,9 +189,9 @@ module Pubnub
|
|
|
163
189
|
when TYPE_TEXT_STRING
|
|
164
190
|
decode_string(data, additional)
|
|
165
191
|
when TYPE_ARRAY
|
|
166
|
-
decode_array(data, additional)
|
|
192
|
+
decode_array(data, additional, depth + 1)
|
|
167
193
|
when TYPE_HASHMAP
|
|
168
|
-
decode_map(data, additional)
|
|
194
|
+
decode_map(data, additional, depth + 1)
|
|
169
195
|
else
|
|
170
196
|
nil
|
|
171
197
|
end
|
|
@@ -175,7 +201,11 @@ module Pubnub
|
|
|
175
201
|
public
|
|
176
202
|
|
|
177
203
|
def decode(value)
|
|
178
|
-
|
|
204
|
+
if value.size > MAX_INPUT_SIZE
|
|
205
|
+
raise DecodeError, "CBOR input size #{value.size} exceeds maximum #{MAX_INPUT_SIZE}"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
parse_data(value.dup)
|
|
179
209
|
end
|
|
180
210
|
end
|
|
181
211
|
|
data/lib/pubnub/constants.rb
CHANGED
data/lib/pubnub/event.rb
CHANGED
|
@@ -88,7 +88,7 @@ module Pubnub
|
|
|
88
88
|
uri += path
|
|
89
89
|
uri += '?' + Formatter.params_hash_to_url_params(parameters)
|
|
90
90
|
uri += "&signature=#{sa_signature}" if sa_signature
|
|
91
|
-
Pubnub.logger.debug('Pubnub::Event') { "Requested URI: #{uri}" }
|
|
91
|
+
Pubnub.logger.debug('Pubnub::Event') { "Requested URI: #{uri.gsub(/([?&](?:signature|pnsig)=)[^&#]*/i, '\1***')}" }
|
|
92
92
|
URI uri
|
|
93
93
|
end
|
|
94
94
|
|
data/lib/pubnub/events/grant.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Pubnub
|
|
|
7
7
|
|
|
8
8
|
def initialize(options, app)
|
|
9
9
|
@event = current_operation
|
|
10
|
+
@categories = format_categories(options[:categories])
|
|
10
11
|
super
|
|
11
12
|
@uuids = Formatter::format_uuid(options[:uuids]) unless options[:uuids].nil?
|
|
12
13
|
@ttl ||= Pubnub::Constants::DEFAULT_TTL
|
|
@@ -18,10 +19,22 @@ module Pubnub
|
|
|
18
19
|
Pubnub::Constants::OPERATION_GRANT
|
|
19
20
|
end
|
|
20
21
|
|
|
22
|
+
def format_categories(categories)
|
|
23
|
+
formatted = case categories
|
|
24
|
+
when NilClass then return nil
|
|
25
|
+
when Array then categories.map { |category| category.to_s.strip }
|
|
26
|
+
when String, Symbol then categories.to_s.split(',').map(&:strip)
|
|
27
|
+
else return categories
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
formatted.empty? ? nil : formatted
|
|
31
|
+
end
|
|
32
|
+
|
|
21
33
|
def parameters(signature = false)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
category_grant = !@categories.nil?
|
|
35
|
+
write = (category_grant && @write.nil?) || [0, '0', false].include?(@write) ? 0 : 1
|
|
36
|
+
read = (category_grant && @read.nil?) || [0, '0', false].include?(@read) ? 0 : 1
|
|
37
|
+
manage = (category_grant && @manage.nil?) || [0, '0', false].include?(@manage) ? 0 : 1 # unless @group.blank?
|
|
25
38
|
delete = [0, '0', false].include?(@delete) ? 0 : 1 unless @delete.nil?
|
|
26
39
|
get = [0, '0', false].include?(@get) ? 0 : 1 unless @get.nil?
|
|
27
40
|
update = [0, '0', false].include?(@update) ? 0 : 1 unless @update.nil?
|
|
@@ -35,7 +48,8 @@ module Pubnub
|
|
|
35
48
|
g: get,
|
|
36
49
|
u: update,
|
|
37
50
|
j: join,
|
|
38
|
-
ttl: @ttl
|
|
51
|
+
ttl: @ttl,
|
|
52
|
+
category: (@categories.join(',') unless @categories.nil?) }.delete_if { |_k, v| v.nil? }.merge(super(signature))
|
|
39
53
|
end
|
|
40
54
|
|
|
41
55
|
def path
|
|
@@ -12,6 +12,7 @@ module Pubnub
|
|
|
12
12
|
options[:channel_groups] = options[:channel_groups] || {}
|
|
13
13
|
@spaces_permissions = options[:spaces_permissions] || {}
|
|
14
14
|
@users_permissions = options[:users_permissions] || {}
|
|
15
|
+
@categories = options[:categories] || {}
|
|
15
16
|
super
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -31,7 +32,8 @@ module Pubnub
|
|
|
31
32
|
meta: @meta,
|
|
32
33
|
uuid: uuid,
|
|
33
34
|
resources: prepare_permissions(:resource, @channels, @channel_groups, @uuids, @spaces_permissions, @users_permissions),
|
|
34
|
-
patterns: prepare_permissions(:pattern, @channels, @channel_groups, @uuids, @spaces_permissions, @users_permissions)
|
|
35
|
+
patterns: prepare_permissions(:pattern, @channels, @channel_groups, @uuids, @spaces_permissions, @users_permissions),
|
|
36
|
+
categories: prepare_categories(@categories)
|
|
35
37
|
}.select { |_, v| v }
|
|
36
38
|
}
|
|
37
39
|
body = Formatter.format_message(raw_body, nil, false)
|
|
@@ -70,6 +72,12 @@ module Pubnub
|
|
|
70
72
|
.to_h { |k, v| [k, v.calculate_bitmask] }
|
|
71
73
|
end
|
|
72
74
|
|
|
75
|
+
def prepare_categories(categories)
|
|
76
|
+
return nil if categories.empty?
|
|
77
|
+
|
|
78
|
+
categories.to_h { |k, v| [k.to_s, v.calculate_bitmask] }
|
|
79
|
+
end
|
|
80
|
+
|
|
73
81
|
def valid_envelope(parsed_response, req_res_objects)
|
|
74
82
|
Pubnub::Envelope.new(
|
|
75
83
|
event: @event,
|
|
@@ -146,6 +154,13 @@ module Pubnub
|
|
|
146
154
|
join: join
|
|
147
155
|
)
|
|
148
156
|
end
|
|
157
|
+
|
|
158
|
+
def cat(get: false)
|
|
159
|
+
Permissions.new(
|
|
160
|
+
type: :category,
|
|
161
|
+
get: get
|
|
162
|
+
)
|
|
163
|
+
end
|
|
149
164
|
end
|
|
150
165
|
|
|
151
166
|
def initialize(options)
|
|
@@ -12,6 +12,7 @@ module Pubnub
|
|
|
12
12
|
validate_keys!
|
|
13
13
|
validate_ttl!
|
|
14
14
|
validate_uuids!
|
|
15
|
+
validate_categories!
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
private
|
|
@@ -37,6 +38,27 @@ module Pubnub
|
|
|
37
38
|
)
|
|
38
39
|
end
|
|
39
40
|
|
|
41
|
+
def validate_categories!
|
|
42
|
+
return if @categories.nil?
|
|
43
|
+
|
|
44
|
+
raise(
|
|
45
|
+
ArgumentError.new(object: self, message: ':categories has to be kind of String, Symbol or Array for grant event.'),
|
|
46
|
+
':categories has to be kind of String, Symbol or Array for grant event.'
|
|
47
|
+
) unless @categories.is_a?(Array)
|
|
48
|
+
|
|
49
|
+
raise(
|
|
50
|
+
ArgumentError.new(object: self, message: ':categories supports only channels and uuids for grant event.'),
|
|
51
|
+
':categories supports only channels and uuids for grant event.'
|
|
52
|
+
) unless (@categories - %w[channels uuids]).empty?
|
|
53
|
+
|
|
54
|
+
# Use the per-call option: PAM#initialize resets @auth_key to options[:auth_key], so a client-level
|
|
55
|
+
# auth_key is never sent as the grant target `auth`.
|
|
56
|
+
raise(
|
|
57
|
+
ArgumentError.new(object: self, message: ':auth_key is required for grant event on categories.'),
|
|
58
|
+
':auth_key is required for grant event on categories.'
|
|
59
|
+
) if @given_options[:auth_key].nil? || @given_options[:auth_key].to_s.empty?
|
|
60
|
+
end
|
|
61
|
+
|
|
40
62
|
def validate_uuids!
|
|
41
63
|
return if @uuids.nil?
|
|
42
64
|
|
|
@@ -12,6 +12,7 @@ module Pubnub
|
|
|
12
12
|
validate_permissions!(@uuids, ":uuids")
|
|
13
13
|
validate_permissions!(@channels, ":channels")
|
|
14
14
|
validate_permissions!(@channel_groups, ":uuids")
|
|
15
|
+
validate_categories!
|
|
15
16
|
validate_objects_entities_separation!
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -47,6 +48,27 @@ module Pubnub
|
|
|
47
48
|
) unless arg.is_a?(Hash)
|
|
48
49
|
end
|
|
49
50
|
|
|
51
|
+
def validate_categories!
|
|
52
|
+
return if @categories.nil?
|
|
53
|
+
|
|
54
|
+
raise(
|
|
55
|
+
ArgumentError.new(object: self, message: ':categories has to be kind of Hash for grant token event.'),
|
|
56
|
+
':categories has to be kind of Hash for grant token event.'
|
|
57
|
+
) unless @categories.is_a?(Hash)
|
|
58
|
+
|
|
59
|
+
@categories.each do |key, value|
|
|
60
|
+
raise(
|
|
61
|
+
ArgumentError.new(object: self, message: ':categories supports only :channels and :uuids keys for grant token event.'),
|
|
62
|
+
':categories supports only :channels and :uuids keys for grant token event.'
|
|
63
|
+
) unless %w[channels uuids].include?(key.to_s)
|
|
64
|
+
|
|
65
|
+
raise(
|
|
66
|
+
ArgumentError.new(object: self, message: ':categories values have to be created with Pubnub::Permissions.cat for grant token event.'),
|
|
67
|
+
':categories values have to be created with Pubnub::Permissions.cat for grant token event.'
|
|
68
|
+
) unless value.is_a?(Pubnub::Permissions) && value.type == :category
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
50
72
|
def validate_objects_entities_separation!
|
|
51
73
|
entities_set = !@spaces_permissions.empty? ||
|
|
52
74
|
!@users_permissions.empty?
|
data/lib/pubnub/version.rb
CHANGED
data/pubnub.gemspec
CHANGED
|
@@ -11,6 +11,10 @@ Gem::Specification.new do |spec|
|
|
|
11
11
|
spec.description = 'Ruby anywhere in the world in 250ms with PubNub!'
|
|
12
12
|
spec.homepage = 'https://github.com/pubnub/ruby'
|
|
13
13
|
spec.licenses = ['LicenseRef-LICENSE.txt']
|
|
14
|
+
spec.metadata = {
|
|
15
|
+
"changelog_uri" => "https://www.pubnub.com/docs/sdks/ruby/changelog",
|
|
16
|
+
"documentation_uri" => "https://www.pubnub.com/docs/sdks/ruby",
|
|
17
|
+
}
|
|
14
18
|
|
|
15
19
|
spec.files = `git ls-files -z`.split("\x0").grep_v(/^(test|spec|fixtures)/)
|
|
16
20
|
spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pubnub
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
4
|
+
version: 6.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- PubNub
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: addressable
|
|
@@ -332,7 +332,9 @@ files:
|
|
|
332
332
|
homepage: https://github.com/pubnub/ruby
|
|
333
333
|
licenses:
|
|
334
334
|
- LicenseRef-LICENSE.txt
|
|
335
|
-
metadata:
|
|
335
|
+
metadata:
|
|
336
|
+
changelog_uri: https://www.pubnub.com/docs/sdks/ruby/changelog
|
|
337
|
+
documentation_uri: https://www.pubnub.com/docs/sdks/ruby
|
|
336
338
|
post_install_message:
|
|
337
339
|
rdoc_options: []
|
|
338
340
|
require_paths:
|