Reputable Ruby Client
Ruby gem for integrating with Reputable - bot detection and reputation scoring for Rails applications.
Resilience First: This gem is designed to never break your application. All operations fail silently with safe defaults.
Release notes and version bumps: see clients/ruby/RELEASING.md.
Installation
Add to your Gemfile:
gem 'reputable'
Then run:
bundle install
Rails Quick Start
1. Create Initializer
# config/initializers/reputable.rb
Reputable.configure do |config|
# Required: Redis/Dragonfly URL (TLS supported via rediss://)
config.redis_url = ENV['REPUTABLE_REDIS_URL']
# Optional: Verbose logging (logs every middleware decision)
# config.verbose = true
end
# Optional: Enable logging
Reputable.logger = Rails.logger
2. Add Middleware
# config/application.rb
module YourApp
class Application < Rails::Application
# Add Reputable middleware (recommended: async mode, non-blocking)
config.middleware.use Reputable::Middleware, async: true
end
end
3. Use Controller Helpers
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Reputable::Rails::ControllerHelpers
end
# app/controllers/payments_controller.rb
class PaymentsController < ApplicationController
def create
@order = Order.create!(order_params)
if @order.payment_successful?
# Trust this IP after successful payment (forever)
trust_current_ip(reason: 'payment_completed', order_id: @order.id)
end
end
end
That's it! Reputable will now track all requests and you can query/apply reputations.
Configuration Reference
Environment Variables
All configuration can be set via environment variables:
# Required
REPUTABLE_REDIS_URL=rediss://user:password@your-dragonfly.example.com:6379
# Optional: Base URL for verification and API endpoints (domain only)
REPUTABLE_BASE_URL=https://api.reputable.click
# Optional: Blocked page branding/support info
REPUTABLE_SITE_NAME="Example Store"
REPUTABLE_SUPPORT_EMAIL=support@example.com
REPUTABLE_SUPPORT_URL=https://example.com/support
# Optional: Disable entirely (useful for test environments)
REPUTABLE_ENABLED=false
# Optional: Connection tuning
REPUTABLE_CONNECT_TIMEOUT=0.5 # Redis connect timeout (seconds)
REPUTABLE_READ_TIMEOUT=0.5 # Redis read timeout (seconds)
REPUTABLE_WRITE_TIMEOUT=0.5 # Redis write timeout (seconds)
REPUTABLE_POOL_SIZE=5 # Connection pool size
REPUTABLE_POOL_TIMEOUT=1.0 # Pool checkout timeout (seconds)
# Optional: Verbose logging (logs every middleware decision at info level)
REPUTABLE_VERBOSE=true
# Optional: SSL (for custom certificates)
REPUTABLE_SSL_VERIFY=false # Disable SSL verification (NOT recommended for production)
Full Configuration Options
Reputable.configure do |config|
# Redis connection (supports redis:// and rediss:// for TLS)
config.redis_url = ENV['REPUTABLE_REDIS_URL']
# Connection pool settings
config.pool_size = 5 # Number of Redis connections
config.pool_timeout = 1.0 # Max wait for connection (seconds)
# Redis operation timeouts
config.connect_timeout = 0.5 # Connection timeout
config.read_timeout = 0.5 # Read timeout
config.write_timeout = 0.5 # Write timeout
# Custom SSL parameters (for self-signed certs, etc.)
config.ssl_params = {
ca_file: '/path/to/ca.crt',
verify_mode: OpenSSL::SSL::VERIFY_PEER
}
# Customize TTLs (in seconds, 0 = forever)
config.default_ttls = {
trusted_verified: 0, # Forever
trusted_behavior: 365 * 24 * 3600, # 1 year
untrusted_challenge: 7 * 24 * 3600,
untrusted_block: 7 * 24 * 3600,
untrusted_ignore: 7 * 24 * 3600
}
# IP header priority (for proxy environments)
# Default covers Heroku, Cloudflare, AWS ALB, nginx, HAProxy
config.ip_header_priority = %w[
HTTP_CF_CONNECTING_IP
HTTP_X_FORWARDED_FOR
HTTP_X_REAL_IP
HTTP_TRUE_CLIENT_IP
REMOTE_ADDR
]
# Verification Configuration
# Supports comma-separated list in REPUTABLE_TRUSTED_KEYS or single key in REPUTABLE_TRUSTED_KEY
config.trusted_keys = ENV['REPUTABLE_TRUSTED_KEYS']&.split(',') || ENV['REPUTABLE_TRUSTED_KEY']
config.base_url = ENV['REPUTABLE_BASE_URL'] # Domain only
# Optional: blocked page branding/support info
config.site_name = ENV['REPUTABLE_SITE_NAME']
config.support_email = ENV['REPUTABLE_SUPPORT_EMAIL']
config.support_url = ENV['REPUTABLE_SUPPORT_URL']
# Verbose logging — logs every middleware decision at info level
# Also available via REPUTABLE_VERBOSE=true
config.verbose = true
# Error callback (optional)
config.on_error = ->(error, context) {
# Report to your error tracking service
Sentry.capture_exception(error, extra: { context: context })
}
end
# Enable logging (required for verbose output)
Reputable.logger = Rails.logger
Proxy & Load Balancer Support
The gem automatically handles IP extraction in proxy environments including:
- Heroku - Uses
X-Forwarded-For - Cloudflare - Uses
CF-Connecting-IP(highest priority by default) - AWS ALB/ELB - Uses
X-Forwarded-For - nginx - Uses
X-Real-IPorX-Forwarded-For - HAProxy - Uses
X-Forwarded-For - Google Cloud Load Balancer - Uses
X-Forwarded-For
How IP Extraction Works
- Headers are checked in priority order (configurable via
ip_header_priority) - For
X-Forwarded-For, we parse the leftmost public IP (skipping private ranges) - Private IP ranges (10.x, 172.16.x, 192.168.x, etc.) are automatically filtered
Custom Proxy Configuration
# If your proxy uses a non-standard header
config.ip_header_priority = %w[
HTTP_X_MY_CUSTOM_IP
HTTP_X_FORWARDED_FOR
REMOTE_ADDR
]
TLS/SSL Support
The gem fully supports TLS connections to Redis/Dragonfly:
# Use rediss:// scheme for TLS
config.redis_url = "rediss://user:password@your-server:6379"
SSL Error Handling
All SSL errors are caught and logged, never breaking your application:
- Certificate verification failures
- Handshake timeouts
- Protocol errors
- Self-signed certificate issues
Custom Certificates
config.ssl_params = {
ca_file: '/path/to/custom-ca.crt',
cert: OpenSSL::X509::Certificate.new(File.read('/path/to/client.crt')),
key: OpenSSL::PKey::RSA.new(File.read('/path/to/client.key'))
}
Disable SSL Verification (Development Only)
# NOT recommended for production
REPUTABLE_SSL_VERIFY=false
Hosted Measurement
Hosted measurement is the shared cloud.reputable.click path for per-request
proxy, bot, timing, ASN, geo, and anomaly checks. It does not require Redis and
does not replace the dedicated Reputable middleware path above.
Configure the customer credentials issued from the Reputable /measure page:
Reputable.configure do |config|
config.measurement_base_url = ENV["REPUTABLE_MEASURE_BASE_URL"] # e.g. https://cloud.reputable.click
config.measurement_customer_id = ENV["REPUTABLE_MEASURE_CUSTOMER_ID"]
config.measurement_capability = ENV["REPUTABLE_MEASURE_CAPABILITY"]
config.measurement_private_jwk = JSON.parse(ENV.fetch("REPUTABLE_MEASURE_PRIVATE_JWK"))
end
Mint a short-lived token for the browser to send to the hosted collect endpoint:
token = Reputable.measurement_token(
mode: "collect",
session_ref: session.id,
request_id: request.request_id,
origin: request.base_url,
request_context: {
scheme: request.scheme,
host: request.host,
method: request.request_method,
path: request.path,
query: request.query_string,
page_type: "product",
action_type: "view"
}
)
collect_url = Reputable.measurement_collect_url(token)
After the browser returns the signed resultToken, verify it server-side before
allowing an expensive or abuse-sensitive action:
result = Reputable.verify_measurement_result(result_token)
if result && result["outcome"] != "deny"
# Continue with the protected action.
else
# Review, challenge, or block according to your app policy.
end
For offline verification without fetching JWKS from the measurement fleet, set:
config.measurement_result_jwks = JSON.parse(ENV.fetch("REPUTABLE_MEASURE_RESULT_JWKS"))
Relevant environment variables:
REPUTABLE_MEASURE_BASE_URL=https://cloud.reputable.click
REPUTABLE_MEASURE_CUSTOMER_ID=cus_...
REPUTABLE_MEASURE_CAPABILITY=eyJ...
REPUTABLE_MEASURE_PRIVATE_JWK='{"kty":"EC","crv":"P-256",...}'
REPUTABLE_MEASURE_RESULT_JWKS='{"keys":[...]}'
REPUTABLE_MEASURE_TOKEN_TTL=120
Middleware Configuration
Basic Usage
# config/application.rb
config.middleware.use Reputable::Middleware
With Options
config.middleware.use Reputable::Middleware,
# Skip certain paths (health checks, assets, etc.)
skip_paths: ['/health', '/healthz', '/assets', '/packs'],
# Skip all requests under a path prefix
# Example: /bot_verifications/new, /bot_verifications/123, etc.
skip_path_prefixes: ['/bot_verifications'],
# Skip by file extension
skip_extensions: ['.js', '.css', '.png', '.jpg', '.svg'],
# Custom skip logic
skip_if: ->(env) {
env['HTTP_X_INTERNAL'] == 'true' ||
env['PATH_INFO'].start_with?('/admin')
},
# Add custom tags based on request
tag_builder: ->(env) {
= []
<< "env:#{Rails.env}"
<< "mobile:true" if env['HTTP_USER_AGENT']&.include?('Mobile')
},
# Async mode (default: true) - tracking runs in background thread
async: true,
# Request tracking (default: false) - push request context to Redis
# Falls back to ENV REPUTABLE_TRACK_REQUEST if not set
track_request: true,
# Ignore XHR requests (default: false)
# Useful for suppressing tracking of background widgets or polling
ignore_xhr: true,
# Expose reputation flags in request env for views/controllers (default: true)
# Sets request.env['reputable.ignore_analytics'] for any untrusted_* status
expose_reputation: true
Optional Reputation Gate
If you want the middleware to enforce IP reputation decisions, enable the gate:
config.middleware.use Reputable::Middleware,
reputation_gate: true,
challenge_action: :verify, # Redirect to verification for untrusted_challenge
block_action: :blocked_page_remote, # Redirect to hosted blocked page (uses app UI settings)
blocked_page_path: "/_reputable/blocked" # Only used for local blocked page
Notes:
- For
untrusted_challenge, the middleware redirects to the Reputable verification URL. - For
untrusted_block, the default is to redirect to the hosted blocked page (/_reputable/verify/blocked). - The hosted blocked page uses the same app UI settings as the verify/failure pages (
siteName,supportEmail). - To render a local blocked page instead, set
block_action: :blocked_pageand passblocked_pageoptions. - To use a custom hosted page, set
blocked_redirect_url: "https://example.com/blocked". - Use
blocked_page_pathonly for local blocked pages (or to build a customfailure_url). - Override
challenge_redirect_status(default302) orverification_force_challengeif needed.
Server/JS Request Reconciliation
When using both server-side tracking (Rack middleware) and client-side JavaScript tracking, requests can be double-counted. The reconciliation system prevents this by correlating requests using a unique request_id.
Automatic Request ID: The middleware automatically generates a UUID for each request and stores it in env['reputable.request_id']. This ID is included when pushing to the Redis buffer.
Exposing to JavaScript: To enable reconciliation, expose the request_id in your views:
<%# In your layout (app/views/layouts/application.html.erb) %>
<meta name="reputable-request-id" content="<%= request.env['reputable.request_id'] %>">
<%# Or via JavaScript variable %>
<script>
window.reputableConfig = {
requestId: '<%= request.env['reputable.request_id'] %>'
};
</script>
The JavaScript snippet will automatically read the request_id from:
data-reputable-request-idattribute on the script tagwindow.reputableConfig.requestId<meta name="reputable-request-id">tag
Bot Detection Signal: If the middleware tracks a request but JavaScript never fires (after a 10-second grace period), the request is flagged with risk:no_js. This is a strong bot signal—bots and crawlers typically don't render JavaScript.
Default Skipped Paths
The middleware automatically skips:
/health,/healthz,/ready,/readyz,/live,/livez/metrics,/favicon.ico- Static assets (
.js,.css,.png,.jpg,.svg,.woff, etc.)
Controller Helpers (Rails)
class ApplicationController < ActionController::Base
include Reputable::Rails::ControllerHelpers
end
Available Methods
# Track current request manually (if not using middleware)
track_reputable_request(tags: ['custom:tag'])
# Trust methods (after successful actions)
trust_current_ip(reason: 'payment_completed', order_id: '123')
# Challenge/Block methods
challenge_current_ip(reason: 'suspicious_activity')
block_current_ip(reason: 'abuse_detected')
# Lookup methods
if current_ip_trusted?
# Skip CAPTCHA, higher rate limits
end
# View/helper flag for untrusted_ignore
if reputable_ignore_analytics?
# Skip analytics / tracking in views
end
if current_ip_blocked?
render status: 403
return
end
# Get full reputation data
rep = current_ip_reputation
# => { status: 'trusted_verified', reason: 'payment', ... }
Verification Redirect Helpers
class SessionsController < ApplicationController
def new
require_reputable_verification!
# If verified, continue
end
end
Optional args:
return_url(default:request.original_url)failure_url(default: API/verify/failurepage)session_id(default:session.id)force_challenge(default:false)session_key(default::reputable_verified_at)
You can check or clear the session flag:
reputable_verified?
clear_reputable_verification!
Reputation Gate Helpers
class SessionsController < ApplicationController
def new
require_reputable_reputation!
# If not blocked/challenged, continue
end
end
require_reputable_reputation! will:
- Render a blocked page for
untrusted_block - Run verification flow for
untrusted_challenge
You can also render the blocked page directly:
render_reputable_blocked_page(
site_name: "Example Store",
support_email: "support@example.com",
support_url: "https://example.com/support"
)
Manual API Usage
Request Tracking
# Synchronous (blocks until complete)
Reputable.track_request(
ip: request.ip,
path: request.path,
query: request.query_string,
method: request.request_method,
user_agent: request.user_agent,
referer: request.referer,
tags: ['view:page:product']
)
# Asynchronous (fire-and-forget, recommended)
Reputable.track_request_async(
ip: request.ip,
path: request.path
)
Trusted Security Events
For the full cross-service contract and Go API behavior, see docs/SECURITY_EVENTS.md.
Reputable.track_security_event(
event_type: "login_failed",
ip: request.ip,
account_id: current_account.id,
user_id: current_user.id,
session_id: session.id.to_s,
request_id: request.request_id,
reason_code: "invalid_password",
context: {
country: "US",
proxy_class: "none",
ja4: request.headers["X-JA4"],
ua_family: "chrome"
},
resource: {
type: "account",
id: current_account.id,
action: "login"
},
metadata: { auth_method: "password" }
)
# Async (recommended)
Reputable.track_security_event_async(
event_type: "permission_denied",
ip: request.ip,
account_id: current_account.id,
user_id: current_user.id,
reason_code: "missing_scope"
)
Reputation Management
# Trust IP (behavioral by default, uses default TTL)
Reputable.trust_ip(request.ip, reason: 'behavior_trust', order_id: order.id)
# Trust IP as verified (forever, explicitly)
Reputable.trust_ip(
request.ip,
reason: 'payment_completed',
status: :trusted_verified,
ttl: 0,
order_id: order.id
)
# Challenge (require CAPTCHA, etc.)
Reputable.challenge_ip(request.ip, reason: 'unusual_activity')
# Block (with custom TTL)
Reputable.block_ip(request.ip, reason: 'abuse', ttl: 7.days.to_i)
# Ignore in analytics (internal monitoring, etc.)
Reputable.ignore_ip(request.ip, reason: 'internal_monitoring')
Reputation Lookup (O(1) Redis)
# Quick boolean checks
Reputable.trusted_ip?(request.ip) # => true/false
Reputable.blocked_ip?(request.ip) # => true/false
Reputable.challenged_ip?(request.ip) # => true/false
# Get status string
Reputable.lookup_ip(request.ip)
# => "trusted_verified" or "untrusted_block" or nil
# Full lookup with metadata
Reputable.lookup_reputation(:ip, request.ip)
# => { status: "trusted_verified", reason: "payment_completed",
# source: "app_server", updated_at: 1703123456789,
# expires_at: 0, metadata: { order_id: "123" } }
ASN Reputation
Apply and lookup reputations for entire ASNs (Autonomous System Numbers). Useful for blocking datacenter traffic or known-bad networks.
# Apply reputation to an ASN
Reputable.block_asn("15169", reason: "datacenter_abuse")
Reputable.challenge_asn("7922", reason: "suspicious_traffic")
Reputable.trust_asn("16509", reason: "known_partner")
Reputable.ignore_asn("32934", reason: "internal_monitoring")
# Quick boolean checks
Reputable.blocked_asn?("15169") # => true/false
Reputable.challenged_asn?("7922") # => true/false
Reputable.trusted_asn?("16509") # => true/false
# Get status string
Reputable.lookup_asn("15169")
# => "untrusted_block" or nil
# Full lookup with metadata
Reputable.lookup_reputation(:asn, "15169")
# => { status: "untrusted_block", reason: "datacenter_abuse", ... }
Note: ASNs are normalized automatically - both "15169" and "AS15169" work.
Enforcing ASN Reputation in Controllers
If you want to challenge or block requests based on ASN reputation (independent of the middleware's IP-based gate), add a controller filter:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :enforce_asn_reputation
private
def enforce_asn_reputation
return if reputable_verified?
asn = request_asn
return unless asn
if Reputable.challenged_asn?(asn)
redirect_to Reputable.verification_url(
return_url: request.original_url,
session_id: session.id.to_s
), status: 302, allow_other_host: true
elsif Reputable.blocked_asn?(asn)
redirect_to Reputable.blocked_page_url, status: 302, allow_other_host: true
end
end
def reputable_verified?
session[:reputable_verified] || session[:reputable_verified_at].present?
end
def request_asn
# Option 1: From a header (if HAProxy/Cloudflare provides it)
# request.headers["X-ASN"]&.sub(/^AS/i, "")
# Option 2: From your own GeoIP lookup
# GeoIP.lookup(request.remote_ip)&.asn
# Option 3: Stored in request.env from earlier middleware
# request.env["app.asn"]
end
end
To apply only to specific controllers or actions:
class CheckoutController < ApplicationController
before_action :enforce_asn_reputation, only: [:create]
end
User Verification & Trust Flow
When you identify a suspicious user (e.g., high risk score or specific tag), you can redirect them to the Reputable verification page. This page performs advanced browser checks and challenges (CAPTCHA) if necessary.
1. Generating a Signed Redirect URL
To effectively hand off verification handling to Reputable, generate a signed verification URL:
# In your controller
if suspicious_activity_detected?
redirect_url = Reputable.verification_url(
return_url: request.original_url, # Where to send them back after verification
failure_url: root_url, # Optional: where to send if they fail/garbage token
session_id: session.id, # Optional: link specific session
force_challenge: false # Optional: if true, always show CAPTCHA (for testing)
)
redirect_to redirect_url
end
Options:
return_url(required): Where to redirect after successful verificationfailure_url(optional): Where to redirect on failure (defaults to API/verify/failurepage)session_id(optional): Bind verification to a specific sessionforce_challenge(optional): Iftrue, always show CAPTCHA even for trusted users. Useful for testing the challenge flow.
2. Handling the Return Redirect
When the user passes verification (or is determined to be already trusted/clean), they are immediately redirected back to your return_url with signed parameters.
Middleware (Automatic Handling):
If you are using Reputable::Middleware (recommended), this is handled automatically. The middleware detects the return parameters, verifies the signature, and sets env['reputable.verified'] = true.
# In your controller
if request.env['reputable.verified']
# User just passed verification!
# You might want to graduate them to trusted status locally
trust_current_ip(reason: 'interactive_verification')
end
Manual Verification: If you need to verify manually (e.g., custom controller logic):
# In your controller action (the return_url target)
if params[:reputable_s] || params[:reputable_signature]
if Reputable.verify_redirect_return(params)
# Signature is VALID. Meaning Reputable actually sent this user back.
decoded = Reputable.decode_reputable_response(params)
status = decoded&.dig("status") || params[:reputable_status]
outcome = decoded&.dig("outcome") || params[:reputable_outcome]
country = decoded&.dig("country") || params[:reputable_country]
if status == 'pass'
# Grant access
end
else
# Invalid signature - potential tampering attempt!
render plain: "Verification failed", status: 403
end
end
Return Parameters: The current Go API returns compact signed parameters:
reputable_r: Base64url-encoded response payloadreputable_s: HMAC-SHA256 signature of the decoded payload
Decode reputable_r with Reputable.decode_reputable_response(params) to read:
status:passorfailsession_id: The session ID you providedoutcome: The specific reputation outcome (e.g.,trusted_verified)ignore_analytics:true/falseflagcountry: ISO country codechallenge_passed:truewhen an interactive challenge was completed
The Ruby client still accepts the legacy expanded parameters (reputable_status, reputable_session_id, reputable_outcome, reputable_ignore_analytics, reputable_country, reputable_challenge_passed, reputable_signature) for backward compatibility.
Resilience & Failsafe Features
Never Breaks Your App
The gem is designed with resilience as the top priority:
- All operations fail silently - Returns
false/nilon any error - No exceptions propagate - Everything is wrapped in rescue blocks
- Circuit breaker - After 5 failures, stops trying for 30 seconds
Disable via Environment
# Completely disable (useful for test/CI environments)
REPUTABLE_ENABLED=false
# Enable request tracking (push request context to Redis)
REPUTABLE_TRACK_REQUEST=true
# Check in code
if Reputable.enabled?
# Only when enabled
end
Safe Return Values
| Operation | Returns on Failure |
|---|---|
track_request |
false |
trust_ip, block_ip, etc. |
false |
lookup_ip, lookup_reputation |
nil |
trusted_ip?, blocked_ip? |
false |
| Middleware tracking | silently skipped |
Circuit Breaker
- Opens after 5 consecutive failures
- While open, returns defaults immediately (no Redis calls)
- Resets after 30 seconds
Error Callback
config.on_error = ->(error, context) {
# Log to your error service
Rails.logger.warn("Reputable error: #{error.class} in #{context}")
Sentry.capture_exception(error)
}
Verbose Logging / Debugging
When troubleshooting middleware behavior (e.g., unexpected redirects or blocked requests), enable verbose mode to see every decision the gem makes:
# config/initializers/reputable.rb
Reputable.configure do |config|
config.verbose = true
# ...
end
Reputable.logger = Rails.logger
Or via environment variable:
REPUTABLE_VERBOSE=true
When enabled, the middleware logs at info level with a [Reputable] prefix. Example output for a challenged request:
[Reputable] request: GET / ip=68.6.118.12 rid=abc-123
[Reputable] state: enabled=true operational=true gate=true track=false
[Reputable] extract_ip: 68.6.118.12 (from HTTP_X_FORWARDED_FOR: 68.6.118.12, 10.0.0.1)
[Reputable] lookup: reputation:ip:68.6.118.12 → status=untrusted_challenge reason=inherited:asn:7922 source=inherited
[Reputable] gate: ip=68.6.118.12 status="untrusted_challenge"
[Reputable] verified_session?: false (reputable_verified_at= reputable_verified=)
[Reputable] gate: CHALLENGING ip=68.6.118.12 action=verify
[Reputable] challenge: REDIRECTING 302 → https://api.reputable.click/_reputable/verify?token=...
When verbose is false (the default), none of these logs are emitted.
Tags for Classification
Use tags to classify requests for behavioral analysis:
# Page context
tags: ['view:page:product']
tags: ['view:page:checkout']
tags: ['view:page:cart']
tags: ['view:page:login']
# Traffic source
tags: ['trust:channel:email']
tags: ['trust:channel:ad']
tags: ['trust:channel:organic']
# Trust signals (from verified actions)
tags: ['trust:financial:payment']
tags: ['trust:auth:login']
tags: ['trust:identity:verified']
tags: ['trust:interactive:captcha']
Testing
Disable in Test Environment
# config/environments/test.rb
ENV['REPUTABLE_ENABLED'] = 'false'
# Or in spec_helper.rb
RSpec.configure do |config|
config.before(:suite) do
ENV['REPUTABLE_ENABLED'] = 'false'
end
end
Mock Lookups
# In tests, lookups return nil when disabled
expect(Reputable.trusted_ip?('1.2.3.4')).to eq(false)
expect(Reputable.lookup_ip('1.2.3.4')).to be_nil
How It Works
- Request Tracking: Your Rails app pushes request data to Redis buffers (enable with
track_request: trueorREPUTABLE_TRACK_REQUEST=true) - Async Processing: Reputable API processes buffers asynchronously
- Behavioral Analysis: Requests go through classification and pattern analysis
- Reputation Storage: Scores stored in Redis for O(1) lookups
What's Available from Rails
- IP reputation and history
- Request classification
- UA churn detection
- Cross-request pattern analysis
- Manual reputation overrides
What Requires Edge Deployment
- JA4/JA3 TLS fingerprints
- HAProxy timing analysis
- Geo-latency heuristics
License
MIT