MainSDK
Search⌘K
How-to

Watch for security events

Write the app's own security events, listen for the ones the SDK writes, detect brute force and probing, and send them to your own SIEM.

Building for 0.3

Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.

Stability The promise an interface ships with.

  • Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
  • Beta Usable in production; may change before it becomes stable.
  • Experimental May change or go away; needs an explicit opt-in in main.yaml.
Stability levels
Updated 2026-10-28

You will turn on the detectors, send events to your collector and add one event of your own. It takes about 15 minutes.

You need

  • A MainSDK app with auth set up.
  • An OpenTelemetry collector, if you want events outside the app.

1. Choose where events go and what detects

main.yaml
security:
  events:
    to: [log, otel]
    min: low
  detect:
    brute-force: { failures: 10, window: 5m }
    stuffing: { accounts: 20, window: 5m }
    probing: { denials: 20, window: 1m }

log is always on. Read it with mainsdk logs --security. The detectors report and never block.

2. Add an event of your own

app/refunds.ts
import { security } from "mainsdk";

security.emit({ type: "app.refund_spike", severity: "medium", message: "Refunds above the daily norm", attrs: { count: 41 } });

The type must start with app., or the call is refused with MAIN-SECURITY-0005. The SDK writes the catalogue events itself.

3. Listen

app/alerts.ts
import { security } from "mainsdk";

const stop = security.on("auth.*", (e) => console.log(e.type, e.severity));

Check that it works

  • Fail a sign-in ten times: mainsdk logs --security shows auth.brute_force.
  • Every event holds a keyed user hash and a trimmed address, never the raw values.

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet