@kya-os/checkpoint-express
v1.6.0
Published
Express.js middleware for Checkpoint — engine-backed AI agent detection and MCP-I verification
Readme
@kya-os/checkpoint-express
Express.js middleware for Checkpoint — engine-backed AI agent
detection and KYA-OS verification. Every verification decision flows
through the Rust kya-os-engine via WASM; this package is plumbing
only (translate request → call engine → apply verdict to response).
Renamed from
@kya-os/agentshield-express. See migration below.
Installation
npm install @kya-os/checkpoint-expressBundler compatibility
checkpoint-express depends on @kya-os/checkpoint-wasm-runtime,
which ships the WASM verification engine as a wasm-bindgen
--target bundler artifact (SDK-Next.js-Integration-Audit-1 / #2618).
For an Express app deployed to Node directly, no bundler is involved
at consume-time — the published bundle leaves the wasm-runtime import
external and Node resolves it via node_modules at startup. Install,
import, done.
If you're building your Express app with a bundler (esbuild via
@vercel/node, Webpack via custom build, Bun/Deno), the canonical
bundler-target artifact loads natively without configuration.
Quick Start
import express from 'express';
import { withCheckpoint } from '@kya-os/checkpoint-express';
const app = express();
app.use(express.json()); // body-parser — required for MCP-I envelope parsing
app.use(
withCheckpoint({
tenantHost: 'your.tenant.example',
})
);
app.get('/', (_req, res) => res.json({ ok: true }));
app.listen(3000);That's the whole API. The engine handles UA pattern detection, KYA-OS signature verification, scope evaluation, delegation chain verification, status-list lookups, and policy evaluation. The wrapper translates Express requests, calls the engine, and applies the verdict.
Config
interface CheckpointConfig {
tenantHost: string; // your dashboard hostname (drives PolicyEvaluator lookup)
enforcementMode?: 'enforce' | 'observe'; // default 'enforce'
argusUrl?: string; // reputation oracle (omit → trust-by-default)
dashboardUrl?: string; // tenant-policy source (omit → open-by-default)
reputationBaseline?: number; // anonymous-request baseline; default 1.0
adapters?: Partial<{
didResolver;
statusListCache;
reputationOracle;
policyEvaluator;
}>; // override factory defaults (tests)
onResult?: (result, req) => void | Promise<void>; // observability hook
}Observability with storage adapters
The session-tracking + Redis/Memory event storage from the legacy
createEnhancedAgentShieldMiddleware are now composable primitives.
Wire them into withCheckpoint via the onResult callback:
import { withCheckpoint, createStorageAdapter } from '@kya-os/checkpoint-express';
const storage = createStorageAdapter({ type: 'redis', ...redisConfig });
app.use(
withCheckpoint({
tenantHost: 'your.tenant.example',
onResult: async (result, req) => {
await storage.recordEvent({
verdict: result.decision.kind,
agentDid: result.agentDid,
ts: Date.now(),
});
},
})
);Errors thrown inside onResult are swallowed so observability
failures can't break the verdict path.
Response shape
The middleware adapts the engine's Decision to four response shapes:
| Verdict | Action |
| ---------------- | -------------------------------------------------------------------------------- |
| Permit / Observe | next() — pass through, set verdict cookie + X-Checkpoint-* headers |
| Redirect | res.redirect(302, target) |
| Block + HTML | res.redirect(302, '/blocked') — your /blocked route reads the verdict cookie |
| Block + non-HTML | res.status(<engine-status>).json(body) (4xx, JSON-API clients) |
The __checkpoint_verdict cookie is byte-equal to the Next.js
sibling package (@kya-os/checkpoint-nextjs); cross-runtime
parity at the cookie layer is guaranteed by the shared
encodeVerdictCookie primitive in @kya-os/checkpoint-shared.
Migration
Coming from @kya-os/agentshield-express? Three swaps:
- "@kya-os/agentshield-express": "^0.2.1"
+ "@kya-os/checkpoint-express": "^1.0.0"- import { agentShield } from '@kya-os/agentshield-express';
+ import { withCheckpoint } from '@kya-os/checkpoint-express';
- app.use(agentShield({ apiKey: process.env.AGENTSHIELD_API_KEY }));
+ app.use(withCheckpoint({ tenantHost: 'your.tenant.example' }));// Legacy enhanced middleware
- import { createEnhancedAgentShieldMiddleware } from '@kya-os/agentshield-express';
- app.use(createEnhancedAgentShieldMiddleware({ storage: { type: 'redis', ... }, ... }));
+ // See "Observability with storage adapters" above.The legacy local-detection chain (agentShield,
createAgentShieldMiddleware, createEnhancedAgentShieldMiddleware,
applyPolicy, and the rest of policy.ts's enforcement helpers)
was retired as throw-stubs in 1.0.0 and fully deleted in 1.3.0
(Phase-E.7). Importing those names from @kya-os/checkpoint-express
will fail at type-check today. Storage adapters and session helpers
are preserved as the composable observability surface — wire them
into withCheckpoint via the onResult callback (see above).
Customers still on the legacy package name should install the final
deprecation stub at
@kya-os/[email protected],
which throws a migration message at import time.
License
MIT OR Apache-2.0
