Express Observability & Storage
Session tracking and Redis event storage for the Express middleware
Overview
There is no separate "enhanced" Express middleware. The legacy createEnhancedAgentShieldMiddleware was removed from @kya-os/checkpoint-express in 1.3.0. Session tracking and event storage are now composable primitives you wire into the one middleware factory, withCheckpoint, through its onResult callback.
This page covers the Express-specific storage and session-tracking exports. For the full middleware reference (config options, response headers, response shape) covering Next.js, Express, and .NET, see Middleware Enforcement.
Setup
Record detection events from onResult. Construct a storage adapter with the async createStorageAdapter factory (Upstash Redis for production):
import express from 'express';
import { randomUUID } from 'node:crypto';
import { withCheckpoint, createStorageAdapter } from '@kya-os/checkpoint-express';
const app = express();
app.use(express.json());
const storage = await createStorageAdapter({
type: 'redis',
ttl: 86400, // 24 hours (default)
redis: {
url: process.env.REDIS_URL!,
token: process.env.REDIS_TOKEN!,
},
});
app.use(
withCheckpoint({
tenantHost: 'your.tenant.example',
apiKey: process.env.CHECKPOINT_API_KEY,
onResult: async (result, req) => {
await storage.storeEvent({
eventId: randomUUID(),
sessionId: req.headers['x-request-id']?.toString() ?? randomUUID(),
timestamp: new Date().toISOString(),
agentType: result.detectionDetail.detectionClass.type,
agentName: result.detectionDetail.detectedAgent?.name ?? 'unknown',
confidence: result.detectionDetail.confidence,
path: req.path,
method: req.method,
userAgent: req.headers['user-agent'],
detectionReasons: result.detectionDetail.reasons,
verificationMethod: result.detectionDetail.verificationMethod,
});
},
})
);
app.listen(3000);Errors thrown inside onResult are swallowed so an observability failure can't break the verdict path.
Storage Adapters
@kya-os/checkpoint-express exports MemoryStorageAdapter, RedisStorageAdapter, and the async createStorageAdapter factory.
Memory
For development and single-instance deployments. Data is lost on restart. This is the default — createStorageAdapter() with no argument (or { type: 'memory' }) returns a MemoryStorageAdapter.
import { createStorageAdapter } from '@kya-os/checkpoint-express';
const storage = await createStorageAdapter(); // in-memoryRedis
For production. Persists events and sessions across restarts and instances via Upstash Redis.
import { createStorageAdapter } from '@kya-os/checkpoint-express';
const storage = await createStorageAdapter({
type: 'redis',
ttl: 86400, // 24 hours (default)
redis: {
url: process.env.REDIS_URL!,
token: process.env.REDIS_TOKEN!,
},
});Memory storage is not suitable for production — data is lost on restart and not shared across instances. Use Redis for production deployments.
Custom Adapter
Implement the StorageAdapter interface and pass it as { type: 'custom', custom: myAdapter }:
import type { StorageAdapter } from '@kya-os/checkpoint-express';
const myAdapter: StorageAdapter = {
storeEvent: async (event) => {
/* persist an AgentDetectionEvent */
},
storeSession: async (session) => {
/* upsert an AgentSession */
},
getEvents: async (sessionId, limit) => {
return [];
},
getSession: async (sessionId) => {
return null;
},
getRecentEvents: async (limit) => {
return [];
},
getActiveSessions: async (limit) => {
return [];
},
cleanup: async (before) => {
/* optional */
},
};Session Tracking
For cookie/header-based session continuity, wrap the middleware with withSessionTracking. When enabled, a returning agent's session is attached to req.agentShield on subsequent requests:
import { withCheckpoint, withSessionTracking } from '@kya-os/checkpoint-express';
const checkpoint = withCheckpoint({ tenantHost: 'your.tenant.example' });
app.use(withSessionTracking(checkpoint, { enabled: true }));The package also exports the ExpressSessionTracker class directly if you need finer control over check / track.
req.agentShield is populated only when session tracking is wired via withSessionTracking.
Plain withCheckpoint attaches nothing to req — read the verdict from the onResult callback.
Response Headers
The engine path sets X-Checkpoint-* headers and a __checkpoint_verdict cookie (byte-identical to the Next.js sibling package). In observe mode it adds X-Checkpoint-Would-Have-Been.
When session tracking is wired, ExpressSessionTracker additionally emits kya-session, kya-session-agent, and kya-session-id (and withSessionTracking sets kya-detected / kya-agent on a continued session).
Next Steps
- Middleware Enforcement — Full config reference for Next.js, Express, and .NET
- Express Integration — Basic Express middleware setup
- Policies — Configure enforcement rules