The reactive, local-first stack that treats security as architecture, not an afterthought.

A TypeScript monorepo, published as @azmr/* on npm. The reactive core — signals, queries, UI — is an independent branch you can use on its own. Every persistence, policy, and AI package builds on @azmr/security instead of bolting compliance on afterward.

pnpm add @azmr/core

@azmr/ui

A design system on Base UI and Tailwind v4 tokens

30 components with live demos, every one checked with axe in CI. Theme it with CSS variables, copy a component into your app with the shadcn registry, or import it from the package. The preview on this page is the real package, rendered on the server.

  • Keyboard and screen reader behaviour built on Base UI primitives
  • Tokens for colour, spacing and density, with light and dark themes, no JavaScript
  • Server-safe entries cost no JavaScript in the browser

October invoices

Northline Electrical Ltd
  1. CompletedQuote
  2. 2Current stepInvoice
  3. 3Not startedPaid
InvoiceStatusAmount
INV-001Paid$250.00
INV-002Pending$1,250.00
INV-004Overdue$90.00

What ships by default

Reactivity and caching are a solved problem. Where the platform differs is what's already in the box when you also need auth, rate limiting, and an audit trail.

Azmara

  • RBAC via createAccessControl, fail-closed by default
  • SHA-256 hash-chained audit logging via createAuditLogger
  • Rate limiting and CORS composed declaratively via createPolicyEngine
  • All in the same monorepo as the reactive/data layer

TanStack Query

An excellent caching and sync layer for server state. It doesn't ship a first-party audit log, RBAC, or policy engine — those guarantees come from whatever backend or middleware you pair it with.

Convex

A strong reactive backend-as-a-service with built-in sync. Auth and access rules are handled through its own function-level checks; it doesn't provide a portable, standalone RBAC/audit-log/rate-limit primitive you can reuse outside its runtime.

The honest split

Every persistence, policy, and AI package (@azmr/db, @azmr/db-supabase, @azmr/policycore, @azmr/ai, @azmr/cli) depends on @azmr/security, directly or transitively. The reactive core (@azmr/core, @azmr/query, @azmr/ui) has zero dependency on it — use it standalone if that's all you need.

Rate limits, auth, and CORS as code

@azmr/policycore composes @azmr/security's primitives — rate limit, then auth, then CORS — declared once per route.

const engine = createPolicyEngine({
  policies: {
    "invoices.read": {
      rateLimit: { options: { maxRequests: 100, windowMs: 60_000 }, keyedBy: "subject" },
      auth: { resource: "invoice", action: "read" },
      cors: { allowedOrigins: ["https://app.example.com"] },
    },
  },
  accessControl,
});

FAQ

Does everything in Azmara depend on the security package?
No. Only the persistence, policy, and AI packages (@azmr/db, @azmr/db-supabase, @azmr/policycore, @azmr/ai, @azmr/cli) depend on @azmr/security. The reactive core (@azmr/core, @azmr/query, @azmr/ui) has zero dependency on it and works standalone.
Is the built-in rate limiter distributed-safe?
No — createRateLimiter is an in-memory sliding window, documented as such. For multi-instance deployments, pair it with an external store rather than relying on it alone across processes.
How complete is the OWASP Top 10 coverage?
Partial, honestly. @azmr/policycore's OWASP report currently evaluates 4 of the 10 2021 categories and ships its own disclaimer that it is not an audit, pentest, or certification. See the security overview for the full breakdown.
Why isolated-vm instead of vm2 for the AI sandbox?
vm2 has known sandbox-escape CVEs. @azmr/ai uses isolated-vm's real V8 isolate boundaries instead, with a 64MB memory limit and 5 second timeout per run. In production, if isolated-vm is unavailable it refuses to run rather than silently falling back to a weaker sandbox.

Start with the reactive core, or the full stack.

Every package installs independently. Bring in @azmr/security when you need the audit trail.