Security
Production-grade defaults built in. Harden your app using examples/todo as the reference implementation.
Built in (no setup)
- CSRF —
X-Resuma-CSRFon actions and submits - Headers — CSP nonces, HSTS, X-Frame-Options, COOP, CORP
- Rate limiting — per-IP on
/_resuma/action/* - Origin check — blocks cross-origin POST abuse
- SSR safety — escaped HTML + sanitized JSON state + JSON-LD
- Client bundles —
script-src 'self'; TypeScript viaClientComponent
Trust boundaries
| API | Escaping | Notes |
|---|---|---|
view! text/attrs | Auto | Default for UI |
View::raw() | None | Trusted static HTML only |
with_head() | Partial | Inline <style> / <script> get CSP nonces; external src scripts use 'self' |
ClientComponent | Attrs escaped | Ids restricted to [a-zA-Z0-9_-] |
| Resumability payload | Sanitized | Blocks </script> breakouts |
Rate limiting
Per-IP sliding window in memory (resets on process restart). Defaults: 120 action RPC/min, 60 submits/min. Tune with RESUMA_RATE_ACTIONS / RESUMA_RATE_SUBMITS. For multi-instance deployments, add edge rate limiting (Fly, Cloudflare, nginx) in front of Resuma.
Guides
Todo exampleStart here — full backend reference (main + security + todo_store)Configure serverSecurityConfig · env vars · Fly/DockerSecure #[server] actionsValidation · Result errors · action middlewareAuth middlewareFlow #[middleware] vs ResumaApp action pipelineBackend patternsPattern mapping tableAuthorization & RLSRow-level checks · Postgres RLS
Quick start (ResumaApp)
mod security;
#[tokio::main]
async fn main() -> std::io::Result<()> {
security::install();
ResumaApp::new()
.page("/", || Home::render(HomeProps::default()))
.serve(security::serve_options())
.await
}