DEVELOPER DOCUMENTATION

High-value routes

Start with one sensitive browser route, use server-issued browser credentials, and add hosted validation where replay sensitivity matters.

Start in Observe on one route. Use the deployment URL and installed package version supplied for your workspace. Historical host examples and source capabilities do not establish a live service or published release.

MANDATE's first production wedge is high-value action protection.

Use this guide for browser-originated routes such as:

  • login
  • signup
  • checkout or payment submit
  • invite redemption
  • account recovery
  • queue admission
  • API key creation
  • admin or security changes

Keep server-to-server APIs, webhooks, cron jobs, and CLI routes outside this flow unless you have a separate integration path.

Rollout model

  1. Serve the collector through a first-party origin so MANDATE can issue the HttpOnly Mndt-Sess credential.
  2. Put ordinary protected browser routes behind MANDATE gate middleware.
  3. Pick one high-value route.
  4. Add hosted validation for that route.
  5. Put it on login or checkout. Log the decision. Leave the request alone.
  6. Review Activity and false positives.
  7. Move that route to enforcement with a rollback path.

Local versus hosted

Production browser routes use the server-issued HttpOnly Mndt-Sess credential.

The browser should not read, store, or forward MANDATE token material. Protected

routes should sit behind the MANDATE gate or a first-party proxy path that

enforces the cookie credential.

Hosted validation is the normal authority for protected browser actions,

including ordinary actions. Local crypto is limited to the explicit DEADMAN

incident tier and bounded legacy compatibility. Use the real hosted adapters

below; never infer authenticated identity from a browser header.

The current deployed writer uses Mndt-Sess; the candidate reader prefers

_mndt and accepts unambiguous legacy input. Select the actual deployed name

explicitly for manual hosted integration and coordinate any writer migration.

These examples use the unpublished kit candidate; see SDK overview.

Route table

RouteDefault postureStronger proof
Loginobserve -> enforcehosted validation
Signupobserveroute pressure
Checkout submitenforce candidateroute proof + request proof
Queue admissionenforce candidateone-use queue token
Account recoveryenforce candidatefresh proof

Framework examples

Next.js App Router

ts
// app/api/checkout/route.ts
import { withMandateHosted } from "@mandate-security/node/next";

export const POST = withMandateHosted(
  async (_request, { mandate }) => {
    return Response.json({ ok: true, sessionId: mandate.sessionId });
  },
  {
    siteSecret: process.env.MANDATE_SITE_SECRET,
    siteKey: process.env.MANDATE_SITE_KEY,
    apiKey: process.env.MANDATE_API_KEY,
    gateUrl: process.env.MANDATE_GATE_URL,
    credentialMode: "cookie",
    credentialCookieName: "Mndt-Sess",
    highValue: true,
    origin: "https://app.example.com",
    resolveHostedOptions: (request) => ({
      // Resolve accountKey from your authenticated server session.
      queueToken: request.headers.get("X-Mandate-Queue-Token") ?? undefined,
    }),
  },
);

Express

ts
import { mandateHosted } from "@mandate-security/node/express";

app.post(
  "/api/checkout",
  mandateHosted({
    siteSecret: process.env.MANDATE_SITE_SECRET,
    siteKey: process.env.MANDATE_SITE_KEY,
    apiKey: process.env.MANDATE_API_KEY,
    gateUrl: process.env.MANDATE_GATE_URL,
    credentialMode: "cookie",
    credentialCookieName: "Mndt-Sess",
    highValue: true,
    origin: "https://app.example.com",
    resolveHostedOptions: (req) => ({
      accountKey: req.user?.id,
      queueToken: req.get("X-Mandate-Queue-Token"),
    }),
  }),
  checkoutHandler,
);

FastAPI

py
from mandate.fastapi import hosted_response, validate_mandate_hosted
from mandate.verify import HostedValidateOptions

hosted_options = HostedValidateOptions(
    site_secret=os.environ["MANDATE_SITE_SECRET"],
    site_key=os.environ.get("MANDATE_SITE_KEY"),
    api_key=os.environ["MANDATE_API_KEY"],
    gate_url=os.environ["MANDATE_GATE_URL"],
    credential_mode="cookie", credential_cookie_name="Mndt-Sess",
    high_value=True,
    origin="https://app.example.com",
)

@app.post("/api/checkout")
async def checkout(request: Request):
    result = await validate_mandate_hosted(request, hosted_options)
    if not result.success:
        return hosted_response(result)
    return {"ok": True, "sessionId": result.session_id}

Go net/http

go
highValue := true
middleware := mandate.HostedMiddleware{
    Options: mandate.HostedValidateOptions{
        SiteSecret: os.Getenv("MANDATE_SITE_SECRET"),
        SiteKey: os.Getenv("MANDATE_SITE_KEY"),
        APIKey: os.Getenv("MANDATE_API_KEY"),
        GateURL: os.Getenv("MANDATE_GATE_URL"),
        CredentialMode: "cookie", CredentialCookieName: "Mndt-Sess",
        HighValue: &highValue,
        Origin: "https://app.example.com",
    },
}
http.Handle("/api/checkout", middleware.Handler(checkoutHandler))

Escalation outcomes

Hosted validation can return route-level outcomes when abuse pressure is

configured:

OutcomeCustomer response
throttleReturn 429 and honor Retry-After.
fresh_proofReturn 401 and ask the browser to obtain fresh proof.
queueReturn 202 with opaque queueToken; retry with X-Mandate-Queue-Token.
step_upReturn the configured customer-owned step-up path.
blockReturn 403 and do not run the protected action.

The browser receives only the coarse public code. Keep the full hosted decision

server-side for logging and support; do not echo its diagnostic reason.

See examples/queue-wait-room/ for customer-owned wait room

examples for Next.js, Express, FastAPI, Flask, and Go.

Rollback

Every enforcement change needs a rollback path:

  • flip that path back to logging-only (mode: "observe"),
  • disable hosted validation enforcement for that route,
  • keep the gate cookie credential boundary active for ordinary protection,
  • review Activity for false-positive impact,
  • document the reason for rollback.

Do not publish claims about broad bot-management replacement, no false positives,

or emulator defeat from a single route rollout.

Require established trust on sensitive actions

The first browser request may carry a provisional session while behavior warms

up. Keep browsing routes available, and set requireTrust: "established" on

checkout, login, and account actions. In enforce mode the adapter returns

fresh_proof_required; in observe mode it records trust_below_required.

This follows Cloudflare's guidance not to require JavaScript detection on the

first request.