minfraud 1.1.0 → 1.5.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.
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