Security & Operations
Production-ready security, observability, and operational tooling for Kernova deployments.
Rate Limiting
Protect your system from abuse and runaway costs with token-bucket rate limiting.
// Per-user: 30 requests per minutekernel.rateLimiter.addRule({ id: 'user-limit', scope: 'identity', key: '*', maxRequests: 30, windowMs: 60_000, burstAllowance: 5, // Allow short bursts of 35});
// Per-provider: protect API quotaskernel.rateLimiter.addRule({ id: 'openai-quota', scope: 'provider', key: 'openai', maxRequests: 200, windowMs: 60_000,});
// Global: system-wide safety netkernel.rateLimiter.addRule({ id: 'global-safety', scope: 'global', key: '*', maxRequests: 1000, windowMs: 60_000,});Rate limits are automatically enforced on every kernel.submit() call. When exceeded:
Error: Rate limit exceeded. Try again later.Manual Checks
const check = kernel.rateLimiter.check('identity', 'user_abc');// { allowed: true, remaining: 25, resetAt: 1720000060000 }
// Or if rate limited:// { allowed: false, remaining: 0, resetAt: ..., retryAfterMs: 23000 }Sandbox Manager
Restrict what agents can do during tool execution — filesystem access, network, and tool permissions.
// Create a restricted sandbox for untrusted agentsconst ctx = kernel.sandbox.createContext('agent_untrusted', { allowedPaths: ['./workspace', './uploads'], deniedPaths: ['../', '/etc', 'C:\\Windows'], allowedTools: ['read_file', 'search', 'write_file'], deniedTools: ['exec', 'shell', 'rm', 'delete'], timeoutMs: 10_000, // 10s max per tool call allowNetwork: false, // No outbound requests allowWrite: true, // Can create/modify files (within allowed paths)});
// Before tool execution, check permissions:kernel.sandbox.isPathAllowed(ctx.id, './workspace/report.md'); // truekernel.sandbox.isPathAllowed(ctx.id, '../../etc/passwd'); // false ← BLOCKEDkernel.sandbox.isToolAllowed(ctx.id, 'search'); // truekernel.sandbox.isToolAllowed(ctx.id, 'exec'); // false ← BLOCKED
// Clean upkernel.sandbox.destroy(ctx.id);What Gets Blocked
- Path traversal — Any path resolving outside the workspace directory
- System directories —
/etc,/usr,C:\Windows, etc. - Denied tools — Tools explicitly listed in
deniedTools - Unlisted tools — If
allowedToolsis set, anything not in the list is blocked
Auth Profile Manager
Manage multiple API keys per provider with automatic rotation and rate-limit recovery.
// Add multiple keys for the same providerkernel.authProfiles.add('openai', 'Primary', process.env.OPENAI_KEY_1!, 10); // priority 10kernel.authProfiles.add('openai', 'Backup', process.env.OPENAI_KEY_2!, 5); // priority 5kernel.authProfiles.add('openai', 'Free Tier', process.env.OPENAI_KEY_3!, 1); // priority 1
// Get a key (highest-priority available, round-robin)const key = kernel.authProfiles.getKey('openai');// Returns the Primary key first
// When a key hits a rate limit:kernel.authProfiles.markRateLimited(profileId);// Next getKey() call will return the Backup key// Primary goes on 60s cooldown (doubles on consecutive failures)
// After successful use:kernel.authProfiles.markSuccess(profileId);// Resets failure counterWhy This Matters
Without key rotation:
- One rate limit = entire system stops
- One expired key = downtime
With auth profiles:
- Rate limit on key A → instantly switch to key B
- Key A cools down → auto-returns to rotation
- All keys exhausted → errors propagate (circuit breaker)
Config Manager
Layered configuration with environment variable support, hot reload, and change watching.
Layer Precedence
defaults (lowest) → file config → env variables → runtime overrides (highest)// Read configconst provider = kernel.configManager.get('models.default.provider'); // 'openai'const timeout = kernel.configManager.getOrDefault('tools.timeout', 30000); // 30000
// Override at runtime (highest priority)kernel.configManager.set('models.default.provider', 'anthropic');
// Environment variables auto-loaded with KERNOVA_ prefix:// KERNOVA_MODELS__DEFAULT__PROVIDER=openai → models.default.providerHot Reload
import { readFileSync, watchFile } from 'fs';
// Watch config file for changeswatchFile('./kernova.config.json', () => { const config = JSON.parse(readFileSync('./kernova.config.json', 'utf-8')); kernel.configManager.reload(config); // Emits config.changed events for each modified path});Watching for Changes
// React when a specific config changesconst unwatch = kernel.configManager.watch('models.default.provider', (newProvider) => { console.log(`Provider changed to: ${newProvider}`);});
// Stop watchingunwatch();Metrics Collector
Automatic performance tracking from all kernel events.
// Metrics are collected automatically. Get a snapshot anytime:const m = kernel.metrics.snapshot();
console.log(`Intents: ${m.intents.total} total, ${m.intents.active} active`);console.log(`Success rate: ${(m.intents.succeeded / m.intents.total * 100).toFixed(1)}%`);console.log(`Avg latency: ${m.intents.avgDurationMs}ms, p95: ${m.intents.p95DurationMs}ms`);console.log(`Tokens: ${m.tokens.total} total, ${m.tokens.last5min} last 5 min`);console.log(`Model errors: ${(m.models.errorRate * 100).toFixed(1)}%`);Expose as Prometheus Metrics
import { createServer } from 'http';
createServer((req, res) => { if (req.url === '/metrics') { const s = kernel.metrics.snapshot(); res.end([ `kernova_intents_total ${s.intents.total}`, `kernova_intents_active ${s.intents.active}`, `kernova_intent_duration_p95_ms ${s.intents.p95DurationMs}`, `kernova_tokens_total ${s.tokens.total}`, `kernova_model_error_rate ${s.models.errorRate}`, ].join('\n')); }}).listen(9090);Health Monitor
Probe-based health checking with state change detection.
// Add custom health probeskernel.health.addCheck({ id: 'database', name: 'Database', check: async () => { const start = Date.now(); try { await db.query('SELECT 1'); return { state: 'healthy', latencyMs: Date.now() - start }; } catch (e) { return { state: 'unhealthy', message: e.message }; } },});
// Run all checksconst status = await kernel.health.check();console.log(`Overall: ${status.overall}`); // 'healthy' | 'degraded' | 'unhealthy'for (const c of status.checks) { console.log(` ${c.name}: ${c.state} (${c.latencyMs}ms)`);}Security Auditor
Automated security scanning to catch misconfigurations.
const audit = kernel.securityAuditor.audit(kernel);
console.log(`Security Score: ${audit.score}/100`);for (const finding of audit.findings) { console.log(`[${finding.severity}] ${finding.message}`); console.log(` Fix: ${finding.recommendation}`);}Built-in Checks
| Check | What It Catches |
|---|---|
| Anonymous access in production | Gateway has no auth configured |
| Missing rate limits | No custom rate limit rules |
| No model provider | Agents can’t generate responses |
| Debug mode in production | Trajectory may leak data |
| No agents registered | System can’t handle intents |
Add Custom Checks
kernel.securityAuditor.addCheck({ id: 'env-secrets', name: 'Secrets in Environment', description: 'Checks that API keys are properly scoped', category: 'secrets', check: (kernel) => { // Your custom logic return null; // null = passed },});Complete Production Setup
import { KernovaKernel, defineAgent } from '@kernova/core';
const kernel = new KernovaKernel({ environment: 'production', dataDir: '/data/kernova' });await kernel.start();
// 1. Register agentskernel.agentRegistry.register(assistantAgent.definition, assistantAgent.executor);
// 2. Security: rate limits + authkernel.rateLimiter.addRule({ id: 'user', scope: 'identity', key: '*', maxRequests: 30, windowMs: 60_000 });kernel.authProfiles.add('openai', 'Primary', process.env.OPENAI_KEY_1!, 10);kernel.authProfiles.add('openai', 'Backup', process.env.OPENAI_KEY_2!, 5);
// 3. Start gateway with authawait kernel.gateway.start(); // Token from KERNOVA_API_KEY or KernelConfig.gateway.auth.tokens
// 4. Health monitoringkernel.health.addCheck({ id: 'db', name: 'DB', check: checkDatabase });
// 5. Security auditconst audit = kernel.securityAuditor.audit(kernel);if (audit.score < 70) console.warn(`⚠️ Security score: ${audit.score}/100`);
// 6. Graceful shutdownprocess.on('SIGTERM', async () => { await kernel.stop(); process.exit(0);});