kavachOS

Configuration

All createKavach() options explained.

createKavach() accepts a KavachConfig object. The only required field is database. Everything else is optional and enables features incrementally.

import { createKavach } from 'kavachos';

const kavach = await createKavach({
  database: { provider: 'sqlite', url: 'kavach.db' },
});

Common development setup

A minimal config for local development with email/password auth and no email sending:

import { createKavach } from 'kavachos';
import { emailPassword } from 'kavachos/auth';

const kavach = await createKavach({
  database: { provider: 'sqlite', url: './kavach.db' },
  plugins: [
    emailPassword({
      requireVerification: false, // skip in dev
      onSendVerification: async (email, token) => {
        console.log(`Verify: http://localhost:3000/verify?token=${token}`);
      },
    }),
  ],
});

Top-level options

Prop

Type

Database config

Prop

Type

// Cloudflare D1 (edge)
const kavach = await createKavach({
  database: {
    provider: 'd1',
    binding: env.KAVACH_DB,  // D1Database from Worker env
  },
});

// SQLite (Node.js)
const kavach = await createKavach({
  database: { provider: 'sqlite', url: './kavach.db' },
});

// PostgreSQL
const kavach = await createKavach({
  database: { provider: 'postgres', url: process.env.DATABASE_URL },
});

// MySQL
database: { provider: 'mysql', url: process.env.DATABASE_URL }

// In-memory SQLite (tests)
database: { provider: 'sqlite', url: ':memory:' }

Agent config

Controls the agent identity lifecycle.

Prop

Type

agents: {
  enabled: true,
  maxPerUser: 10,
  defaultPermissions: [],
  auditAll: true,
  tokenExpiry: '30d',
},

MCP config

Enables the OAuth 2.1 authorization server for MCP-compliant tool access.

Prop

Type

mcp: {
  enabled: true,
  issuer: 'https://auth.example.com',
  baseUrl: 'https://auth.example.com',
  accessTokenTtl: 3600,
  refreshTokenTtl: 604800,
  enforceAuth: true,
  loginPage: 'https://example.com/login',
  consentPage: 'https://example.com/consent',
},

Auth config

Connects KavachOS to your existing auth provider so it can resolve the human user behind incoming requests.

auth: {
  adapter: betterAuthAdapter(auth),   // resolves user from request
  session: {                          // optional: KavachOS-managed sessions
    secret: process.env.SESSION_SECRET,
    maxAge: 60 * 60 * 24 * 30,       // 30 days in seconds
  },
},

When auth is omitted, kavach.auth.resolveUser() always returns null (manual user management mode).

See Auth adapters for all adapter options.

Session config

Prop

Type

Password reset config

Requires auth.session to be configured. The caller provides an email-sending callback.

Prop

Type

Always use an HTTPS URL for resetUrl in production. Reset tokens in plain HTTP links can be intercepted in transit or leaked via Referer headers.

auth: {
  adapter: betterAuthAdapter(auth),
  session: {
    secret: process.env.SESSION_SECRET!,
    maxAge: 60 * 60 * 24 * 7, // 7 days
  },
  passwordReset: {
    resetUrl: 'https://example.com/reset-password',
    tokenTtlSeconds: 3600,
    revokeSessionsOnReset: true,
    minPasswordLength: 10,
    sendResetEmail: async (email, token, url) => {
      await mailer.send({
        to: email,
        subject: 'Reset your password',
        html: `<a href="${url}">Reset password</a>`,
      });
    },
  },
},

Session freshness config

Controls when sessions are considered "fresh" for sensitive operations like password changes and passkey registration.

Prop

Type

Plugins

KavachOS features are composable. Enable what you need:

PluginImportWhat it does
emailPasswordkavachos/authEmail + password with verification and reset
passkeykavachos/authWebAuthn/FIDO2 biometric auth
magicLinkkavachos/authPasswordless email links
emailOtpkavachos/authOne-time password codes via email
twoFactorkavachos/authTOTP 2FA with backup codes
multiSessionkavachos/authSession limits and device management
organizationkavachos/authOrganizations with RBAC
apiKeyskavachos/authStatic API key management
adminkavachos/authUser management, banning, impersonation
stripekavachos/authStripe billing integration
polarkavachos/authPolar payment integration

Anomaly config

Prop

Type

anomaly: {
  highFrequencyThreshold: 200,
  highDenialRateThreshold: 30,
  expectedHours: { start: 8, end: 20 },
},

Environment variables pattern

Never hardcode secrets in config. Pass them through environment variables:

const kavach = await createKavach({
  database: {
    provider: 'postgres',
    url: process.env.DATABASE_URL!,
  },
  secret: process.env.KAVACH_SECRET!,
  mcp: {
    enabled: true,
    issuer: process.env.KAVACH_ISSUER!,
    signingSecret: process.env.KAVACH_SIGNING_SECRET,
  },
});

Dev vs production example

// config/kavach.ts
const isDev = process.env.NODE_ENV !== 'production';

export const kavach = await createKavach({
  database: isDev
    ? { provider: 'sqlite', url: './kavach-dev.db' }
    : { provider: 'postgres', url: process.env.DATABASE_URL! },

  secret: process.env.KAVACH_SECRET!,
  baseUrl: process.env.KAVACH_BASE_URL ?? 'http://localhost:3000',

  agents: {
    enabled: true,
    maxPerUser: isDev ? 100 : 25,
    auditAll: true,
    tokenExpiry: '30d',
  },

  mcp: {
    enabled: true,
    issuer: process.env.KAVACH_BASE_URL ?? 'http://localhost:3000',
    accessTokenTtl: isDev ? 86400 : 3600,
    enforceAuth: !isDev,
    loginPage: '/login',
    consentPage: '/consent',
  },

  anomaly: {
    highFrequencyThreshold: 500,
    highDenialRateThreshold: 50,
  },
});

secret and mcp.signingSecret must be at least 32 characters. In production, generate them with openssl rand -base64 32.

Next steps

On this page