zyphr 0.1.50 → 0.1.51

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: a4fd52fa232b4a334d6ea406412fa92ee9d076583b6038b8e9d0231b5c77c016
4
- data.tar.gz: 2f2e95c64d51dc3f4c48309a580d7e21960fc5a3665359b5986431e1f833c6b5
3
+ metadata.gz: f7ec40b14a9b8a2ce14cff88cdb6d2e4cdebd6b1c324a65a8f8c4f1b551f1688
4
+ data.tar.gz: dd884a0621a0a3243a6b1ffa98e6acc8821f1b4efaaf841f12df6307fba729cb
5
5
  SHA512:
6
- metadata.gz: 48bdb019fd49d35023234cc46edb30ed3aa0716a267aefa6fbfb8c3147be8e3cde1bf60bd01f0c12e1e443111fd5bb58f49a853d2c09e1c28b91040103c1f0fe
7
- data.tar.gz: fc7da20a4d8529d1a12e120bf0ffcf30588f26cc4abbfe8c0ea386c21d3435eac9aca82229a96f416d8d5826542881ec71c62f47c453b75179bdd9fd9f94e734
6
+ metadata.gz: 799f68978d7a8ea632126b16f2addb82b7e16f41e75c23f12abe809c5465ac74a7046276d371720f90472b4f0228353a3ccb9d48fbbf50ed443da2f9cf565a52
7
+ data.tar.gz: c17b1bdd2725d25d2c117ca6460e306ab1fe2cf96fddbcb43624f52f9dffa4546abd24ef2f13c66eb9c699e21ece24ef7e92f3d52f714ae712380fb09dcc21f6
@@ -11,6 +11,7 @@
11
11
  | **require_numbers** | **Boolean** | Whether at least one number (0-9) is required. | |
12
12
  | **require_special** | **Boolean** | Whether at least one special character is required. | |
13
13
  | **disallow_common** | **Boolean** | Whether commonly used passwords are rejected. | |
14
+ | **disallow_breached** | **Boolean** | Whether passwords found in the HaveIBeenPwned breach corpus are rejected at registration/reset. Checked via k-anonymity (only a 5-char SHA-1 prefix leaves our infrastructure) and fail-open: if the breach source is unavailable the password is allowed. Default false (advisory only — the breach signal is returned but does not gate acceptance unless enabled). | |
14
15
 
15
16
  ## Example
16
17
 
@@ -24,7 +25,8 @@ instance = Zyphr::PasswordPolicy.new(
24
25
  require_lowercase: null,
25
26
  require_numbers: null,
26
27
  require_special: null,
27
- disallow_common: null
28
+ disallow_common: null,
29
+ disallow_breached: null
28
30
  )
29
31
  ```
30
32
 
@@ -4,8 +4,10 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **valid** | **Boolean** | Whether the password would be accepted by the server's enforcement path. A password that is valid here is accepted by registration. | |
8
- | **score** | **Integer** | Strength score, 0-100. | |
7
+ | **valid** | **Boolean** | Whether the password would be accepted by the server's enforcement path. A password that is valid here is accepted by registration. When the application enables `disallow_breached`, a breached password is `valid: false` here AND rejected by register/reset (no drift). | |
8
+ | **breached** | **Boolean** | Whether the password appears in the HaveIBeenPwned breach corpus. This is a distinct signal from `valid` and is always returned regardless of the app's `disallow_breached` setting. Fail-open: if the breach source is unavailable this is `false`. | |
9
+ | **breach_count** | **Integer** | HIBP occurrence count for the password (0 if not breached or if the breach lookup failed/was unavailable). | |
10
+ | **score** | **Integer** | Strength score, 0-100. A pure composition measure — independent of the breach signal. | |
9
11
  | **label** | **String** | Strength label derived from the score. | |
10
12
  | **feedback** | **Array<String>** | Actionable feedback — policy errors plus strength-improvement suggestions. | |
11
13
 
@@ -16,6 +18,8 @@ require 'zyphr'
16
18
 
17
19
  instance = Zyphr::PasswordStrength.new(
18
20
  valid: null,
21
+ breached: null,
22
+ breach_count: null,
19
23
  score: null,
20
24
  label: null,
21
25
  feedback: null
@@ -37,6 +37,9 @@ module Zyphr
37
37
  # Whether commonly used passwords are rejected.
38
38
  attr_accessor :disallow_common
39
39
 
40
+ # Whether passwords found in the HaveIBeenPwned breach corpus are rejected at registration/reset. Checked via k-anonymity (only a 5-char SHA-1 prefix leaves our infrastructure) and fail-open: if the breach source is unavailable the password is allowed. Default false (advisory only — the breach signal is returned but does not gate acceptance unless enabled).
41
+ attr_accessor :disallow_breached
42
+
40
43
  # Attribute mapping from ruby-style variable name to JSON key.
41
44
  def self.attribute_map
42
45
  {
@@ -46,7 +49,8 @@ module Zyphr
46
49
  :'require_lowercase' => :'require_lowercase',
47
50
  :'require_numbers' => :'require_numbers',
48
51
  :'require_special' => :'require_special',
49
- :'disallow_common' => :'disallow_common'
52
+ :'disallow_common' => :'disallow_common',
53
+ :'disallow_breached' => :'disallow_breached'
50
54
  }
51
55
  end
52
56
 
@@ -69,7 +73,8 @@ module Zyphr
69
73
  :'require_lowercase' => :'Boolean',
70
74
  :'require_numbers' => :'Boolean',
71
75
  :'require_special' => :'Boolean',
72
- :'disallow_common' => :'Boolean'
76
+ :'disallow_common' => :'Boolean',
77
+ :'disallow_breached' => :'Boolean'
73
78
  }
74
79
  end
75
80
 
@@ -136,6 +141,12 @@ module Zyphr
136
141
  else
137
142
  self.disallow_common = nil
138
143
  end
144
+
145
+ if attributes.key?(:'disallow_breached')
146
+ self.disallow_breached = attributes[:'disallow_breached']
147
+ else
148
+ self.disallow_breached = nil
149
+ end
139
150
  end
140
151
 
141
152
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -171,6 +182,10 @@ module Zyphr
171
182
  invalid_properties.push('invalid value for "disallow_common", disallow_common cannot be nil.')
172
183
  end
173
184
 
185
+ if @disallow_breached.nil?
186
+ invalid_properties.push('invalid value for "disallow_breached", disallow_breached cannot be nil.')
187
+ end
188
+
174
189
  invalid_properties
175
190
  end
176
191
 
@@ -185,6 +200,7 @@ module Zyphr
185
200
  return false if @require_numbers.nil?
186
201
  return false if @require_special.nil?
187
202
  return false if @disallow_common.nil?
203
+ return false if @disallow_breached.nil?
188
204
  true
189
205
  end
190
206
 
@@ -258,6 +274,16 @@ module Zyphr
258
274
  @disallow_common = disallow_common
259
275
  end
260
276
 
277
+ # Custom attribute writer method with validation
278
+ # @param [Object] disallow_breached Value to be assigned
279
+ def disallow_breached=(disallow_breached)
280
+ if disallow_breached.nil?
281
+ fail ArgumentError, 'disallow_breached cannot be nil'
282
+ end
283
+
284
+ @disallow_breached = disallow_breached
285
+ end
286
+
261
287
  # Checks equality by comparing each attribute.
262
288
  # @param [Object] Object to be compared
263
289
  def ==(o)
@@ -269,7 +295,8 @@ module Zyphr
269
295
  require_lowercase == o.require_lowercase &&
270
296
  require_numbers == o.require_numbers &&
271
297
  require_special == o.require_special &&
272
- disallow_common == o.disallow_common
298
+ disallow_common == o.disallow_common &&
299
+ disallow_breached == o.disallow_breached
273
300
  end
274
301
 
275
302
  # @see the `==` method
@@ -281,7 +308,7 @@ module Zyphr
281
308
  # Calculates hash code according to all attributes.
282
309
  # @return [Integer] Hash code
283
310
  def hash
284
- [min_length, max_length, require_uppercase, require_lowercase, require_numbers, require_special, disallow_common].hash
311
+ [min_length, max_length, require_uppercase, require_lowercase, require_numbers, require_special, disallow_common, disallow_breached].hash
285
312
  end
286
313
 
287
314
  # Builds the object from hash
@@ -15,10 +15,16 @@ require 'time'
15
15
 
16
16
  module Zyphr
17
17
  class PasswordStrength
18
- # Whether the password would be accepted by the server's enforcement path. A password that is valid here is accepted by registration.
18
+ # Whether the password would be accepted by the server's enforcement path. A password that is valid here is accepted by registration. When the application enables `disallow_breached`, a breached password is `valid: false` here AND rejected by register/reset (no drift).
19
19
  attr_accessor :valid
20
20
 
21
- # Strength score, 0-100.
21
+ # Whether the password appears in the HaveIBeenPwned breach corpus. This is a distinct signal from `valid` and is always returned regardless of the app's `disallow_breached` setting. Fail-open: if the breach source is unavailable this is `false`.
22
+ attr_accessor :breached
23
+
24
+ # HIBP occurrence count for the password (0 if not breached or if the breach lookup failed/was unavailable).
25
+ attr_accessor :breach_count
26
+
27
+ # Strength score, 0-100. A pure composition measure — independent of the breach signal.
22
28
  attr_accessor :score
23
29
 
24
30
  # Strength label derived from the score.
@@ -53,6 +59,8 @@ module Zyphr
53
59
  def self.attribute_map
54
60
  {
55
61
  :'valid' => :'valid',
62
+ :'breached' => :'breached',
63
+ :'breach_count' => :'breach_count',
56
64
  :'score' => :'score',
57
65
  :'label' => :'label',
58
66
  :'feedback' => :'feedback'
@@ -73,6 +81,8 @@ module Zyphr
73
81
  def self.openapi_types
74
82
  {
75
83
  :'valid' => :'Boolean',
84
+ :'breached' => :'Boolean',
85
+ :'breach_count' => :'Integer',
76
86
  :'score' => :'Integer',
77
87
  :'label' => :'String',
78
88
  :'feedback' => :'Array<String>'
@@ -107,6 +117,18 @@ module Zyphr
107
117
  self.valid = nil
108
118
  end
109
119
 
120
+ if attributes.key?(:'breached')
121
+ self.breached = attributes[:'breached']
122
+ else
123
+ self.breached = nil
124
+ end
125
+
126
+ if attributes.key?(:'breach_count')
127
+ self.breach_count = attributes[:'breach_count']
128
+ else
129
+ self.breach_count = nil
130
+ end
131
+
110
132
  if attributes.key?(:'score')
111
133
  self.score = attributes[:'score']
112
134
  else
@@ -137,6 +159,18 @@ module Zyphr
137
159
  invalid_properties.push('invalid value for "valid", valid cannot be nil.')
138
160
  end
139
161
 
162
+ if @breached.nil?
163
+ invalid_properties.push('invalid value for "breached", breached cannot be nil.')
164
+ end
165
+
166
+ if @breach_count.nil?
167
+ invalid_properties.push('invalid value for "breach_count", breach_count cannot be nil.')
168
+ end
169
+
170
+ if @breach_count < 0
171
+ invalid_properties.push('invalid value for "breach_count", must be greater than or equal to 0.')
172
+ end
173
+
140
174
  if @score.nil?
141
175
  invalid_properties.push('invalid value for "score", score cannot be nil.')
142
176
  end
@@ -165,6 +199,9 @@ module Zyphr
165
199
  def valid?
166
200
  warn '[DEPRECATED] the `valid?` method is obsolete'
167
201
  return false if @valid.nil?
202
+ return false if @breached.nil?
203
+ return false if @breach_count.nil?
204
+ return false if @breach_count < 0
168
205
  return false if @score.nil?
169
206
  return false if @score > 100
170
207
  return false if @score < 0
@@ -185,6 +222,30 @@ module Zyphr
185
222
  @valid = valid
186
223
  end
187
224
 
225
+ # Custom attribute writer method with validation
226
+ # @param [Object] breached Value to be assigned
227
+ def breached=(breached)
228
+ if breached.nil?
229
+ fail ArgumentError, 'breached cannot be nil'
230
+ end
231
+
232
+ @breached = breached
233
+ end
234
+
235
+ # Custom attribute writer method with validation
236
+ # @param [Object] breach_count Value to be assigned
237
+ def breach_count=(breach_count)
238
+ if breach_count.nil?
239
+ fail ArgumentError, 'breach_count cannot be nil'
240
+ end
241
+
242
+ if breach_count < 0
243
+ fail ArgumentError, 'invalid value for "breach_count", must be greater than or equal to 0.'
244
+ end
245
+
246
+ @breach_count = breach_count
247
+ end
248
+
188
249
  # Custom attribute writer method with validation
189
250
  # @param [Object] score Value to be assigned
190
251
  def score=(score)
@@ -229,6 +290,8 @@ module Zyphr
229
290
  return true if self.equal?(o)
230
291
  self.class == o.class &&
231
292
  valid == o.valid &&
293
+ breached == o.breached &&
294
+ breach_count == o.breach_count &&
232
295
  score == o.score &&
233
296
  label == o.label &&
234
297
  feedback == o.feedback
@@ -243,7 +306,7 @@ module Zyphr
243
306
  # Calculates hash code according to all attributes.
244
307
  # @return [Integer] Hash code
245
308
  def hash
246
- [valid, score, label, feedback].hash
309
+ [valid, breached, breach_count, score, label, feedback].hash
247
310
  end
248
311
 
249
312
  # Builds the object from hash
@@ -69,4 +69,10 @@ describe Zyphr::PasswordPolicy do
69
69
  end
70
70
  end
71
71
 
72
+ describe 'test attribute "disallow_breached"' do
73
+ it 'should work' do
74
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
75
+ end
76
+ end
77
+
72
78
  end
@@ -33,6 +33,18 @@ describe Zyphr::PasswordStrength do
33
33
  end
34
34
  end
35
35
 
36
+ describe 'test attribute "breached"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ end
40
+ end
41
+
42
+ describe 'test attribute "breach_count"' do
43
+ it 'should work' do
44
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
45
+ end
46
+ end
47
+
36
48
  describe 'test attribute "score"' do
37
49
  it 'should work' do
38
50
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
data/zyphr.gemspec CHANGED
@@ -17,7 +17,7 @@ require "zyphr/version"
17
17
 
18
18
  Gem::Specification.new do |s|
19
19
  s.name = "zyphr"
20
- s.version = '0.1.50'
20
+ s.version = '0.1.51'
21
21
  s.platform = Gem::Platform::RUBY
22
22
  s.authors = ["Zyphr"]
23
23
  s.email = ["support@zyphr.dev"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zyphr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.50
4
+ version: 0.1.51
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zyphr