Quickstart
ASP.NET Core quickstart
Installed from GitHub (camada-app/camada-dotnet).
1. Install
Not on NuGet yet. From the folder that holds your .csproj: clone it next to the project, then reference it.
git clone https://github.com/camada-app/camada-dotnet ../camada-dotnet
dotnet add reference ../camada-dotnet/src/Camada/Camada.csproj2. 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 runs dotnet run, add them to "environmentVariables" in Properties/launchSettings.json, or set them in your host's settings. camada reads only the environment, and ASP.NET does not pass appsettings.json, user-secrets or a .env file to it.
export CAMADA_KEY=<ingest_token>.<snap_token>
export CAMADA_INGEST_URL=http://localhost:8787 # dev only; defaults to production ingest3. Wire it in
// Program.cs
using Camada.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCamada(); // one engine from the environment, drained on shutdown
var app = builder.Build();
app.UseCamada(); // FIRST: camada answers before routing, static files, anything
// your routes go here, the beacon one below included: app.Run() blocks, so nothing after it is mapped
app.Run();- Put UseCamada() before UseForwardedHeaders(), if you use it, so camada judges the raw header itself.
- .NET 8; nothing beyond the ASP.NET Core shared framework.
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.
// Program.cs, above app.Run(): the tag goes in the <head> of the pages you render
app.MapGet("/", (HttpContext ctx) => Results.Content($"<html><head>{ctx.CamadaScriptTag()}</head><body>…</body></html>", "text/html"));5. 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.
// in a handler that takes HttpContext ctx, once your own sign-in check fails (email: the account it was for)
ctx.CamadaTrack("login_failed", user: email);Runtime
What it does per request
- Refreshes the snapshot off-path on a background PeriodicTimer task at the cadence your tenant config sets (ETag/304, gzip on the wire). A cold start fails open.
- Resolves the client IP from Connection.RemoteIpAddress per your trusted-proxy setting. Raw X-Forwarded-For is never trusted without it.
- 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 from Response.OnStarting, puts the context in HttpContext.Items["camada"], and when the response is done ships one batched, redacted event carrying the matched route 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 header order is what IHeaderDictionary reports, not the wire's under Kestrel; the analyst knows and never scores its absence.
- The request that builds the engine is answered cold. Resolve CamadaEngine from app.Services at startup and wait for the boot poll (the README shows the bounded loop).
- Keep UseCamada() before UseForwardedHeaders() so camada judges the raw header itself.
- Pending events drain on ApplicationStopping and ProcessExit. CAMADA_SERVERLESS=1 switches to a per-request staleness check with no timer.
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 .NET page.