Skip to content

Auth & Rate Limiting

API key management, JWT sessions, audit logging, IP filtering, and multi-backend rate limiting for production deployments.

Nella includes a complete authentication and rate limiting system for production deployments. Manage API keys, issue JWT tokens, audit every action, filter by IP, and enforce rate limits with multiple storage backends.

Authentication

API Key Management

Create, validate, rotate, and revoke API keys with granular permissions.

import { Authenticator } from '@getnella/mcp';

const auth = await Authenticator.create({
  storagePath: '.nella/auth',
  encryptionKey: process.env.NELLA_AUTH_ENCRYPTION_KEY,
});

// Set up a workspace with default keys
const { agent, agentKey, adminKey } = await auth.setupWorkspace('my-workspace');

// Authenticate a request
const result = await auth.authenticate({
  apiKey: 'nella_key_...',
  action: 'search',
  origin: 'cursor',
});

if (result.success) {
  // Proceed with the request
}

Permissions

Each API key has granular permissions:

PermissionDescription
searchSearch the indexed codebase
verifyVerify generated code
indexTrigger workspace indexing
readContextRead session context
writeContextModify session context
manageSessionsCreate/delete sessions
adminFull access including key management

Supported Agent Types

Keys can be scoped to specific agent types: copilot, cursor, cline, aider, continue, or custom.

Key Encryption

API keys are encrypted at rest using AES-256-GCM with a 12-byte IV and 16-byte authentication tag. Set the encryption key via the NELLA_AUTH_ENCRYPTION_KEY environment variable (must be 32 bytes).

Key Rotation

Automatic key rotation is supported via rotation policies. When a key is rotated, the old key remains valid for a grace period before revocation.

JWT Sessions

Issue short-lived JWT tokens for session-based authentication.

import { TokenManager } from '@getnella/mcp';

const tokens = new TokenManager({
  secret: process.env.NELLA_JWT_SECRET,
});

// Issue a token from a valid API key
const { token, expiresAt } = tokens.issueToken(apiKey, {
  sessionId: 'sess_123',
});

// Issue a short-lived token (default: 5 minutes)
const shortToken = tokens.issueShortLivedToken(apiKey, 300);

// Validate
const validation = tokens.validateToken(token);
if (validation.valid) {
  console.log(validation.payload.permissions);
}

JWT payload includes: subject (key ID), issuer, audience, expiry, workspace ID, agent ID, permissions, and session info.

Validation error codes: INVALID_TOKEN, EXPIRED_TOKEN, REVOKED_TOKEN, INVALID_SIGNATURE.

Set the signing secret via NELLA_JWT_SECRET environment variable.

Audit Logging

Every authentication and authorization event is logged to an append-only audit log with automatic file rotation.

import { AuditLogManager } from '@getnella/mcp';

const audit = await AuditLogManager.create({
  storagePath: '.nella/audit',
});

// Logs are written automatically by the Authenticator
// You can also log manually:
await audit.logAuth(true, 'agent-1', 'search', { query: 'handleAuth' });
await audit.logKeyOp('create', 'admin', 'key_abc', 'Agent Key');

Log Categories

CategoryActions
authenticationLogin, validate, reject
authorizationPermission check, file access
key_managementCreate, rotate, revoke, expire

IP Filtering

Restrict access by IP address with CIDR range support.

import { IPFilter } from '@getnella/mcp';

const filter = new IPFilter({
  allowedIPs: ['10.0.0.0/8', '192.168.1.0/24'],
  enabled: true,
});

const result = filter.isAllowed('10.0.1.50');
// { allowed: true }

// Also supports X-Forwarded-For chains
const chainResult = filter.isAllowedChain(['203.0.113.1', '10.0.1.50']);

Rate Limiting

Enforce request rate limits with multiple algorithms and storage backends.

Quick Start

import { RateLimiter } from '@getnella/mcp';

const limiter = new RateLimiter({
  requestsPerMinute: 60,
  requestsPerHour: 1000,
  requestsPerDay: 10000,
  maxTokensPerRequest: 100000,
  maxConcurrent: 5,
});

// Check without consuming
const check = limiter.check({ entityId: 'agent-1', action: 'search' });

// Check and consume
const result = limiter.consume({ entityId: 'agent-1', action: 'search' });
if (!result.allowed) {
  // result.retryAfter tells the client when to retry
}

Algorithms

AlgorithmDescription
sliding-window (default)Tracks requests in minute/hour/day windows
token-bucketConfigurable refill rate and bucket size

Storage Backends

BackendDescription
memory (default)In-process Map — fast, resets on restart
redisRedis with TLS, Sentinel, and Cluster support
sqlitePersistent SQLite database
autoTries Redis → SQLite → memory

Priority Levels

LevelMultiplierBehavior
criticalBypassExempt from rate limits
high2.0xDouble the allowed rate
normal1.0xDefault limits
low0.5xHalf the allowed rate

Dynamic Limits

Rate limits can adjust automatically based on system load:

{
  dynamicLimits: {
    enabled: true,
    loadFunction: () => getCurrentCPUUsage(),  // returns 0-1
    minMultiplier: 0.5,                         // reduce to 50% under load
    maxMultiplier: 1.5,                         // increase to 150% when idle
    evaluationInterval: 30000                   // check every 30 seconds
  }
}

Graceful Degradation

When gracefulDegradation is configured, a warning event is emitted when usage hits the soft limit threshold (default: 80%) before hard blocking occurs. This gives clients time to back off.

HTTP Headers

Rate limit responses include standard headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1706140800
X-RateLimit-Policy: sliding-window
Retry-After: 30