minfraud 1.1.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop.yml +12 -0
  3. data/.github/workflows/test.yml +33 -0
  4. data/.rubocop.yml +108 -0
  5. data/CHANGELOG.md +57 -0
  6. data/Gemfile +4 -2
  7. data/README.dev.md +1 -1
  8. data/README.md +170 -55
  9. data/Rakefile +9 -3
  10. data/bin/console +4 -3
  11. data/lib/maxmind/geoip2/model/city.rb +3 -3
  12. data/lib/maxmind/geoip2/model/country.rb +5 -5
  13. data/lib/maxmind/geoip2/record/traits.rb +13 -4
  14. data/lib/minfraud.rb +44 -6
  15. data/lib/minfraud/assessments.rb +113 -53
  16. data/lib/minfraud/components/account.rb +31 -9
  17. data/lib/minfraud/components/addressable.rb +73 -26
  18. data/lib/minfraud/components/base.rb +26 -14
  19. data/lib/minfraud/components/billing.rb +5 -0
  20. data/lib/minfraud/components/credit_card.rb +64 -20
  21. data/lib/minfraud/components/custom_inputs.rb +14 -3
  22. data/lib/minfraud/components/device.rb +45 -15
  23. data/lib/minfraud/components/email.rb +120 -9
  24. data/lib/minfraud/components/event.rb +60 -24
  25. data/lib/minfraud/components/order.rb +59 -22
  26. data/lib/minfraud/components/payment.rb +44 -9
  27. data/lib/minfraud/components/report/transaction.rb +50 -39
  28. data/lib/minfraud/components/shipping.rb +14 -5
  29. data/lib/minfraud/components/shopping_cart.rb +19 -12
  30. data/lib/minfraud/components/shopping_cart_item.rb +42 -13
  31. data/lib/minfraud/enum.rb +22 -8
  32. data/lib/minfraud/error_handler.rb +32 -25
  33. data/lib/minfraud/errors.rb +22 -2
  34. data/lib/minfraud/http_service.rb +23 -8
  35. data/lib/minfraud/http_service/request.rb +19 -18
  36. data/lib/minfraud/http_service/response.rb +19 -14
  37. data/lib/minfraud/model/address.rb +4 -4
  38. data/lib/minfraud/model/credit_card.rb +7 -7
  39. data/lib/minfraud/model/device.rb +2 -2
  40. data/lib/minfraud/model/email.rb +4 -4
  41. data/lib/minfraud/model/error.rb +1 -1
  42. data/lib/minfraud/model/insights.rb +5 -5
  43. data/lib/minfraud/model/ip_address.rb +20 -1
  44. data/lib/minfraud/model/ip_risk_reason.rb +48 -0
  45. data/lib/minfraud/model/issuer.rb +3 -3
  46. data/lib/minfraud/model/score.rb +6 -6
  47. data/lib/minfraud/model/shipping_address.rb +1 -1
  48. data/lib/minfraud/model/subscores.rb +38 -16
  49. data/lib/minfraud/model/warning.rb +2 -2
  50. data/lib/minfraud/report.rb +33 -13
  51. data/lib/minfraud/resolver.rb +25 -17
  52. data/lib/minfraud/validates.rb +187 -0
  53. data/lib/minfraud/version.rb +4 -1
  54. data/minfraud.gemspec +8 -2
  55. metadata +77 -10
  56. data/.travis.yml +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 992486331731cfd910c7ae3da4039bfa3b776277ff3eb3fb44ae62816299d2cb
4
- data.tar.gz: db10a19261bdca8cb64df6f0992a2d102859c670fc47568cdc01e299c17318a6
3
+ metadata.gz: af8e0a313e978adbd8ccfdf6fccad4652ad0b5c4df5f7812da097f2be4d5390e
4
+ data.tar.gz: 8d766ee43c166bc26a8c8643cded1d7a43a27cf6cc531e9fddaf66028ab0ebde
5
5
  SHA512:
6
- metadata.gz: bd6e8c22d6557f26233b1f5c306ab3d358adb9f661f1452d02471ce0b705cd0037ecafc235af86646894bc4ab953c595989011148aa4f658132f6ec7c7218a4f
7
- data.tar.gz: f8e53c39ef6a07271297e8555808682b9cb662efe43057ea6da9ea9400418b7a59bd168051888e8c69ebda1d9ed6947729e48de5b3a61df25b26536f13589bef
6
+ metadata.gz: 497a1c19029b36879b1b2f1b42f7037cfa205b24b199d71c84564a1cf26136de41f6b7fc8fdb9c9ffa163d3f82b8283d159f017d887aaa9709dfd059f1333625
7
+ data.tar.gz: 72f3fd755450dd1f68b3f675fc181e3a326574bcde905ee7e1b3e64951c2c009788124b2e063e99ed6d080430d7f3d093bf64b8f8dfb78c452436de3937e5cbd
@@ -0,0 +1,12 @@
1
+ name: Run rubocop
2
+ on: [push, pull_request]
3
+ jobs:
4
+ rubocop:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v2
8
+ - uses: ruby/setup-ruby@v1
9
+ with:
10
+ ruby-version: '3.0'
11
+ - run: bundle install
12
+ - run: bundle exec rake -t rubocop
@@ -0,0 +1,33 @@
1
+ name: Run tests
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ${{ matrix.os }}
6
+ strategy:
7
+ fail-fast: false
8
+ matrix:
9
+ os: [ubuntu-latest, windows-latest, macos-latest]
10
+ version:
11
+ [
12
+ 2.1,
13
+ 2.2,
14
+ 2.3,
15
+ 2.4,
16
+ 2.5,
17
+ 2.6,
18
+ 2.7,
19
+ '3.0',
20
+ jruby,
21
+ ]
22
+ exclude:
23
+ - os: windows-latest
24
+ version: jruby
25
+ steps:
26
+ - uses: actions/checkout@v2
27
+ with:
28
+ submodules: true
29
+ - uses: ruby/setup-ruby@v1
30
+ with:
31
+ ruby-version: ${{ matrix.version }}
32
+ - run: bundle install
33
+ - run: bundle exec rake -t spec
data/.rubocop.yml ADDED
@@ -0,0 +1,108 @@
1
+ Gemspec/RequiredRubyVersion:
2
+ Enabled: false # We support 2.1+, but rubocop supports 2.4+.
3
+
4
+ # Metrics.
5
+
6
+ Metrics/BlockLength:
7
+ Enabled: false # Default is true, but mostly hit in tests.
8
+
9
+ Metrics/AbcSize:
10
+ Enabled: false # To allow for pre-existing code.
11
+
12
+ Metrics/ClassLength:
13
+ Enabled: false # To allow for pre-existing code.
14
+
15
+ Metrics/CyclomaticComplexity:
16
+ Enabled: false # To allow for pre-existing code.
17
+
18
+ Metrics/MethodLength:
19
+ Enabled: false # To allow for pre-existing code.
20
+
21
+ Metrics/PerceivedComplexity:
22
+ Enabled: false # To allow for pre-existing code.
23
+
24
+ # Layout.
25
+
26
+ Layout/LineLength:
27
+ Max: 150 # Default is 120.
28
+
29
+ Layout/HashAlignment:
30
+ EnforcedHashRocketStyle: table # Default is key.
31
+ EnforcedColonStyle: table # Default is key.
32
+
33
+ Layout/ExtraSpacing:
34
+ ForceEqualSignAlignment: true # Default is false.
35
+
36
+ Layout/IndentationStyle:
37
+ IndentationWidth: 2 # Default is <none>.
38
+
39
+ # Style.
40
+
41
+ Style/HashSyntax:
42
+ EnforcedStyle: ruby19_no_mixed_keys # Default is ruby19.
43
+
44
+ Style/CollectionMethods:
45
+ Enabled: true # Default is false.
46
+
47
+ Style/NumericLiterals:
48
+ MinDigits: 4 # Default is 5.
49
+
50
+ Style/NegatedIf: # I disagree with this.
51
+ Enabled: false
52
+
53
+ Style/IfUnlessModifier: # This doesn't always make sense.
54
+ Enabled: false
55
+
56
+ Style/SymbolArray:
57
+ EnforcedStyle: brackets # Default is percent, but 1.9 doesn't support that.
58
+
59
+ # Trailing commas are often good.
60
+ Style/TrailingCommaInArguments:
61
+ Enabled: false
62
+ Style/TrailingCommaInArrayLiteral:
63
+ Enabled: false
64
+ Style/TrailingCommaInHashLiteral:
65
+ Enabled: false
66
+
67
+ Style/SafeNavigation:
68
+ Enabled: false # Default is true, but this 1.9 doesn't support it.
69
+
70
+ # Default is both which is probably fine, but it changes code and I don't want
71
+ # to investigate any possible behavior change right now.
72
+ Style/EmptyElse:
73
+ EnforcedStyle: empty
74
+
75
+ Style/ConditionalAssignment:
76
+ Enabled: false # This produces kind of strange results.
77
+
78
+ Style/Dir:
79
+ Enabled: false # This is good, but not supported on 1.9.
80
+
81
+ Style/ExpandPathArguments:
82
+ Enabled: false # This causes us to use __dir__ which 1.9 doesn't support.
83
+
84
+ Style/GuardClause:
85
+ Enabled: false # Doesn't always make sense.
86
+
87
+ Style/Documentation:
88
+ Enabled: false # We should enable this, but allow for pre-existing code.
89
+
90
+ Style/FormatStringToken:
91
+ Enabled: false # Seems unnecessary.
92
+
93
+ # Asks to use x.negative? instead of x < 0. But this isn't available until 2.3.
94
+ Style/NumericPredicate:
95
+ Enabled: false
96
+
97
+ # Seems unnecessary. Asks us to call super in a bunch of places when there's no
98
+ # need.
99
+ Lint/MissingSuper:
100
+ Enabled: false
101
+
102
+ # Naming.
103
+
104
+ Naming/VariableNumber:
105
+ Enabled: false # Doesn't always make sense.
106
+
107
+ AllCops:
108
+ NewCops: enable
data/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # Minfraud Changelog
2
2
 
3
+ ## v1.5.0 (2021-02-02)
4
+
5
+ * Add the `hash_address` attribute to `Minfraud::Components::Email`. If
6
+ this is `true`, the MD5 hash of the `address` will be sent instead of the
7
+ plain text `address`. Use this if you prefer to send the hash of the
8
+ `address` rather than the plain text. Note that this normalizes the
9
+ `address`, so we recommend using it as opposed to hashing the `address`
10
+ manually.
11
+ * The email `domain` input is now automatically set if the email `address`
12
+ input is set but the `domain` is not.
13
+ * Adds new payment processors `:apple_pay` and `:aps_payments` to
14
+ `Minfraud::Components::Payment`.
15
+ * Added support for the IP address risk reasons in the minFraud Insights
16
+ and Factors responses. This is available at `.ip_address.risk_reasons`.
17
+ It is an array of `IPRiskReason` objects.
18
+
19
+ ## v1.4.1 (2020-12-01)
20
+
21
+ * Do not throw an exception if the response does not include IP address
22
+ information. Previously we would incorrectly try to retrieve fields from
23
+ `nil`, leading to a `NoMethodError`.
24
+
25
+ ## v1.4.0 (2020-10-13)
26
+
27
+ * IMPORTANT: Ruby 2.0 is no longer supported. If you're using Ruby 2.0,
28
+ please use version 1.3.0.
29
+ * Add handling for the `REQUEST_INVALID` error code.
30
+ * The IP address is no longer a required input.
31
+ * Adds new payment processor `:tsys` to `Minfraud::Components::Payment`.
32
+
33
+ ## v1.3.0 (2020-09-25)
34
+
35
+ * Adds support for persistent HTTP connections. Connections persist
36
+ automatically.
37
+ * IMPORTANT: Ruby 1.9 is no longer supported. If you're using Ruby 1.9,
38
+ please use version 1.2.0 or older.
39
+ * Adds support for client side validation of inputs. An `InvalidInputError`
40
+ exception will be raised if an input is invalid. This can be enabled by
41
+ setting `enable_validation` to `true` when configuring `Minfraud`. It is
42
+ disabled by default.
43
+ * Adds the `residential_proxy?` method to `MaxMind::GeoIP2::Record::Traits`
44
+ for use with minFraud Insights and Factors.
45
+
46
+ ## v1.2.0 (2020-07-15)
47
+
48
+ * Adds new processor types to `Minfraud::Components::Payment`: `:cashfree`,
49
+ `:first_atlantic_commerce`, `:komoju`, `:paytm`, `:razorpay`, and
50
+ `:systempay`.
51
+ * Adds support for three new Factors outputs: `/subscores/device` (the risk
52
+ associated with the device), `/subscores/email_local_part` (the risk
53
+ associated with the part of the email address before the @ symbol) and
54
+ `/subscores/shipping_address` (the risk associated with the shipping
55
+ address).
56
+ * Adds support for providing your MaxMind account ID using the `account_id`
57
+ attribute instead of the `user_id` attribute. In a future release,
58
+ support for the `user_id` attribute will be removed.
59
+
3
60
  ## v1.1.0 (2020-06-19)
4
61
 
5
62
  * Adds support for the minFraud Report Transaction API. Reporting
data/Gemfile CHANGED
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # coveralls fails on Ruby 1.9. My understanding is we don't need to run this on
4
6
  # more than one version anyway, so restrict to the current latest.
5
7
  version_pieces = RUBY_VERSION.split('.')
6
- major_version = version_pieces[0]
7
- minor_version = version_pieces[1]
8
+ major_version = version_pieces[0]
9
+ minor_version = version_pieces[1]
8
10
  if major_version == '2' && minor_version == '7'
9
11
  gem 'coveralls', require: false
10
12
  end
data/README.dev.md CHANGED
@@ -1,4 +1,4 @@
1
1
  # How to release
2
2
 
3
3
  See
4
- [here](https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/master/README.dev.md).
4
+ [here](https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/main/README.dev.md).
data/README.md CHANGED
@@ -10,10 +10,6 @@ API](https://dev.maxmind.com/minfraud/report-transaction/).
10
10
  The legacy minFraud Standard and Premium services are not supported by this
11
11
  API.
12
12
 
13
- ## Requirements
14
-
15
- This gem works with Ruby 1.9 and above.
16
-
17
13
  ## Installation
18
14
 
19
15
  Add this line to your application's Gemfile:
@@ -24,71 +20,171 @@ gem 'minfraud'
24
20
 
25
21
  And then execute:
26
22
 
27
- ```ruby
23
+ ```
28
24
  $ bundle
29
25
  ```
30
26
 
31
27
  Or install it yourself as:
28
+
32
29
  ```
33
30
  $ gem install minfraud
34
31
  ```
35
32
 
33
+ ## API Documentation
34
+
35
+ See the [API documentation](https://www.rubydoc.info/gems/minfraud) for
36
+ more details.
37
+
36
38
  ## Usage
37
39
 
38
40
  ### Configuration
39
41
 
40
42
  An account ID and license key are required to work with the web services.
43
+ Configure these before making a request:
41
44
 
42
45
  ```ruby
43
46
  Minfraud.configure do |c|
47
+ c.account_id = 12345
44
48
  c.license_key = 'your_license_key'
45
- c.user_id = 'your_user_id'
49
+ c.enable_validation = true
46
50
  end
47
51
  ````
48
52
 
49
53
  ### Making a minFraud Score, Insights, or Factors Request
50
54
 
55
+ To use the minFraud API, create a `Minfraud::Assessments` object. The
56
+ constructor takes a hash of symbols corresponding to each component of the
57
+ minFraud request. You can also set components by their attribute after
58
+ creating the object.
59
+
60
+ After populating the object, call the method for the minFraud endpoint you
61
+ want to use: `#score`, `#insights`, or `#factors`. The returned value is a
62
+ `MinFraud::Response` object. You can access the response model through its
63
+ `#body` attribute.
64
+
65
+ An exception will be thrown for critical errors. You should check for
66
+ `warnings` related to your inputs after a request.
67
+
51
68
  ```ruby
52
- # You can either provide a hash of parameters to the initializer
69
+ # Prepare the request.
53
70
  assessment = Minfraud::Assessments.new(
54
71
  device: {
55
- ip_address: '1.2.3.4.5'
56
- }
72
+ ip_address: '152.216.7.110',
73
+ accept_language: 'en-US,en;q=0.8',
74
+ session_age: 3600.5,
75
+ session_id: 'foo',
76
+ user_agent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36',
77
+ },
78
+ event: {
79
+ transaction_id: 'txn3134133',
80
+ shop_id: 's2123',
81
+ time: '2012-04-12T23:20:50+00:00',
82
+ type: :purchase,
83
+ },
84
+ account: {
85
+ user_id: '3132',
86
+ username_md5: '4f9726678c438914fa04bdb8c1a24088',
87
+ },
88
+ email: {
89
+ address: 'test@maxmind.com',
90
+ domain: 'maxmind.com',
91
+ },
92
+ billing: {
93
+ first_name: 'First',
94
+ last_name: 'Last',
95
+ company: 'Company',
96
+ address: '101 Address Rd.',
97
+ address_2: 'Unit 5',
98
+ city: 'New Haven',
99
+ region: 'CT',
100
+ country: 'US',
101
+ postal: '06510',
102
+ phone_number: '123-456-7890',
103
+ phone_country_code: '1',
104
+ },
105
+ shipping: {
106
+ first_name: 'ShipFirst',
107
+ last_name: 'ShipLast',
108
+ company: 'ShipCo',
109
+ address: '322 Ship Addr. Ln.',
110
+ address_2: 'St. 43',
111
+ city: 'Nowhere',
112
+ region: 'OK',
113
+ country: 'US',
114
+ postal: '73003',
115
+ phone_number: '123-456-0000',
116
+ phone_country_code: '1',
117
+ delivery_speed: :same_day,
118
+ },
119
+ payment: {
120
+ processor: :stripe,
121
+ was_authorized: false,
122
+ decline_code: 'invalid number',
123
+ },
124
+ credit_card: {
125
+ issuer_id_number: '411111',
126
+ last_4_digits: '7643',
127
+ bank_name: 'Bank of No Hope',
128
+ bank_phone_country_code: '1',
129
+ bank_phone_number: '123-456-1234',
130
+ token: 'abcd',
131
+ avs_result: 'Y',
132
+ cvv_result: 'N',
133
+ },
134
+ order: {
135
+ amount: 323.21,
136
+ currency: 'USD',
137
+ discount_code: 'FIRST',
138
+ is_gift: true,
139
+ has_gift_message: false,
140
+ affiliate_id: 'af12',
141
+ subaffiliate_id: 'saf42',
142
+ referrer_uri: 'http://www.amazon.com/',
143
+ },
144
+ shopping_cart: [
145
+ {
146
+ category: 'pets',
147
+ item_id: 'leash-0231',
148
+ quantity: 2,
149
+ price: 20.43,
150
+ },
151
+ {
152
+ category: 'beauty',
153
+ item_id: 'msc-1232',
154
+ quantity: 1,
155
+ price: 100.00,
156
+ },
157
+ ],
158
+ custom_inputs: {
159
+ section: 'news',
160
+ previous_purchases: 19,
161
+ discount: 3.2,
162
+ previous_user: true,
163
+ },
57
164
  )
58
- # or create a component and assign them to the assessments object directly
59
- device = Minfraud::Components::Device.new(ip_address: '1.2.3.4.5')
60
- assessment = Minfraud::Assessments.new(device: device)
61
- # or
62
- assessment = Minfraud::Assessments.new
63
- assessment.device = device
64
-
65
- # There are multiple components that reflect the minFraud request top level
66
- # keys.
67
-
68
- # Some components will raise an error if provided with the wrong values for
69
- # attributes, e.g
70
- event = Minfraud::Components::Event.new(type: 'foobar') # => Minfraud::NotEnumValueError
71
-
72
- # You can check the list of permitted values for the attribute by calling a
73
- # class method
74
- Minfraud::Components::Event.type_values # => ["account_creation", "account_login", ....]
75
-
76
- # You can now call 3 different minFraud endpoints: score, insights and factors
77
- assessment.score
78
- assessment.insights
79
- assessment.factors
80
-
81
- result = assessment.score # => Minfraud::Response instance
82
-
83
- result.status # => Response status code
84
- result.code # => minFraud-specific response code
85
- result.body # => Response body
86
- result.headers # => Response headers
87
-
88
- # You can change data between requests
89
- first_request = assessment.insights
90
- assessment.device.ip_address = '22.22.22.33'
91
- second_request = assessment.insights
165
+
166
+ # To get the Factors response model, use #factors.
167
+ factors_model = assessment.factors.body
168
+
169
+ factors_model.warnings.each { |w| puts w.warning }
170
+
171
+ p factors_model.subscores.email_address
172
+ p factors_model.risk_score
173
+
174
+ # To get the Insights response model, use #insights.
175
+ insights_model = assessment.insights.body
176
+
177
+ insights_model.warnings.each { |w| puts w.warning }
178
+
179
+ p insights_model.credit_card.issuer.name
180
+ p insights_model.risk_score
181
+
182
+ # To get the Score response model, use #score.
183
+ score_model = assessment.score.body
184
+
185
+ score_model.warnings.each { |w| puts w.warning }
186
+
187
+ p score_model.risk_score
92
188
  ```
93
189
 
94
190
  See the [API documentation](https://www.rubydoc.info/gems/minfraud) for
@@ -97,23 +193,21 @@ more details.
97
193
  ### Reporting a Transaction to MaxMind
98
194
 
99
195
  MaxMind encourages the use of this API, as data received through this
100
- channel is continually used to improve the accuracy of their fraud
101
- detection algorithms.
196
+ channel is used to improve the accuracy of their fraud detection
197
+ algorithms.
102
198
 
103
- To use the Report Transactions API, create a new
199
+ To use the Report Transaction API, create a
104
200
  `Minfraud::Components::Report::Transaction` object. An IP address and a
105
- valid tag are required arguments for this API. Additional params may also
106
- be set, as documented below.
201
+ valid tag are required arguments for this API. Additional parameters may be
202
+ set, as shown below.
107
203
 
108
204
  If the report is successful, nothing is returned. If the report fails, an
109
- exception with be thrown.
110
-
111
- See the API documentation for more details.
205
+ exception will be thrown.
112
206
 
113
207
  ```ruby
114
208
  # The report_transaction method only makes use of a transaction component:
115
209
  txn = Minfraud::Components::Report::Transaction.new(
116
- ip_address: '1.2.3.4',
210
+ ip_address: '152.216.7.110',
117
211
  tag: :suspected_fraud,
118
212
  maxmind_id: '12345678',
119
213
  minfraud_id: '58fa38d8-4b87-458b-a22b-f00eda1aa20d',
@@ -127,13 +221,20 @@ reporter.report_transaction
127
221
  See the [API documentation](https://www.rubydoc.info/gems/minfraud) for
128
222
  more details.
129
223
 
224
+ ### Persistent HTTP Connections
225
+
226
+ This gem supports persistent HTTP connections, allowing you to avoid the
227
+ overhead of creating a new HTTP connection for each minFraud request if you
228
+ plan to perform more than one. You do not need to do anything to enable
229
+ this functionality.
230
+
130
231
  ### Exceptions
131
232
 
132
233
  The gem supplies several distinct exception-types:
133
234
 
134
- * `RequestFormatError` - Raised if unpermitted key is provided to the
135
- `Minfraud::Assessments` initializer
136
- * `ClientError` - Raised if the IP address is absent, reserved or the JSON
235
+ * `RequestFormatError` - Raised if an unknown key is provided to the
236
+ `Minfraud::Assessments` constructor
237
+ * `ClientError` - Raised if the IP address is absent, reserved, or the JSON
137
238
  body cannot be decoded
138
239
  * `AuthorizationError` - Raised if there are problems with the account ID
139
240
  and/or license key
@@ -142,6 +243,16 @@ The gem supplies several distinct exception-types:
142
243
  * `NotEnumValueError` - Raised if an attribute value doesn't belong to the
143
244
  predefined set of values
144
245
 
246
+ ### Thread Safety
247
+
248
+ This gem is safe for use from multiple threads.
249
+
250
+ `Minfraud::Assessments` and `Minfraud::Report` objects must not be shared
251
+ across threads.
252
+
253
+ Please note that you must run `Minfraud.configure` before calling any
254
+ functionality using multiple threads.
255
+
145
256
  ## Support
146
257
 
147
258
  Please report all issues with this code using the
@@ -151,6 +262,10 @@ If you are having an issue with the minFraud service that is not specific
151
262
  to the client API, please see
152
263
  [our support page](https://www.maxmind.com/en/support).
153
264
 
265
+ ## Requirements
266
+
267
+ This gem works with Ruby 2.1 and above.
268
+
154
269
  ## Contributing
155
270
 
156
271
  Bug reports and pull requests are welcome on