Quickstart
Rails quickstart
Package camada, on RubyGems.
1. Install
bundle add camada2. Environment
The key is printed once when you create a project in the app. Set these as environment variables: export them in the shell that starts your app, or add them in your host's settings. Rack and Rails read no .env file (Rails needs the dotenv-rails gem for that).
export CAMADA_KEY=<ingest_token>.<snap_token>
export CAMADA_INGEST_URL=http://localhost:8787 # dev only; defaults to production ingest3. Wire it in
# config.ru — Sinatra, Hanami, or any Rack app
require "camada"
use Camada::Rack # first, so camada answers before routing
run App
# Rails — nothing to add: the Railtie inserts Camada::Rack at the top of the middleware stack- One gem, one Rack middleware; the Railtie mounts it for Rails.
- Never request.ip: the middleware reads REMOTE_ADDR and applies your trusted-proxy rules itself.
4. Add the beacon to HTML pages
Optional but recommended. The beacon cuts false positives by showing which sessions are real browsers. Use the helper.
"<html><head>#{Camada.script_tag(env)}</head>…" # Sinatra: env; Rails: request.env5. Send app outcomes
Login failures, signups and checkout declines are the signals no edge position sees. The identifier is HMAC-hashed in your process. How they catch credential stuffing.
Camada.track(env, "login_failed", user: email) # Sinatra: env; Rails: request.envRuntime
What it does per request
- Refreshes the snapshot off-path on a thread at the cadence your tenant config sets (ETag/304, gzip on the wire). A cold start fails open.
- Resolves the client IP from REMOTE_ADDR per your trusted-proxy setting — never request.ip, which trusts X-Forwarded-For from anyone.
- Your ordered custom rules first, then allow, block, challenge. A block gets a 403 with x-block-reason before your app runs; a challenge serves the proof-of-work page on a page load, and an API call reaches your app with an x-camada-challenge: 1 response header. The event still ships.
- Serves /_cam/b.js (the beacon, first-party) and relays /_cam/fp posts onto the event batch with the resolved client IP.
- Sets x-rid and the _sfp session cookie, and when the server closes the body ships one batched, redacted event carrying the matched route pattern (sinatra.route, Rails route_uri_pattern).
Limits
Caveats at this position
- Enforcement at this position covers IP, path, user-agent and request-header conditions. ASN, country and TLS-fingerprint entries fail open in-app.
- The Rack env carries no wire header order, so the analyst reads no HEADER_ORDER signal from this tap and never scores its absence.
- The request that builds the engine is answered cold. Warm it in an initializer by waiting for the boot poll (the README shows the bounded loop).
- Threads do not survive a fork: the SDK compares Process.pid on every call and starts over in a forked worker. Puma cluster mode, Unicorn and Passenger need nothing added.
- CAMADA_SERVERLESS=1 switches to a per-request staleness check with no poll thread.
Kill switch: CAMADA_DISABLED=1, checked per request. All other variables are listed in the docs index; the package's options and deployment notes are on the Ruby page.