@ethicalzen/sdk
Version:
Official EthicalZen SDK for Node.js - AI safety guardrails made simple
170 lines (169 loc) • 6.59 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EthicalZenMiddleware = EthicalZenMiddleware;
exports.enforceRoute = enforceRoute;
const client_1 = require("./client");
/**
* Express middleware for automatic EthicalZen enforcement
*
* @param config - Middleware configuration
* @returns Express middleware function
*
* @example
* ```typescript
* import { EthicalZenMiddleware } from '@ethicalzen/sdk';
*
* app.use(EthicalZenMiddleware({
* apiKey: process.env.ETHICALZEN_API_KEY,
* contractId: 'chatbot/general/us/v1.0',
* enforceOn: 'response'
* }));
*
* app.post('/chat', async (req, res) => {
* const response = await generateAIResponse(req.body);
* res.json({ message: response }); // Automatically validated!
* });
* ```
*/
function EthicalZenMiddleware(config) {
const client = new client_1.EthicalZenClient({
apiKey: config.apiKey,
tenantId: config.tenantId,
baseURL: config.baseURL,
timeout: config.timeout
});
const enforceOn = config.enforceOn || 'response';
const failureMode = config.failureMode || 'block';
return async (req, res, next) => {
// Enforce on request (validate input)
if (enforceOn === 'request' || enforceOn === 'both') {
try {
const payload = config.extractPayload
? config.extractPayload(req, res)
: { input: req.body };
const result = await client.enforce({
contractId: config.contractId,
payload,
metadata: {
method: req.method,
path: req.path,
timestamp: new Date().toISOString()
}
});
if (!result.passed) {
// Handle violation
if (config.onViolation) {
config.onViolation(result, req, res);
return;
}
if (failureMode === 'block') {
return res.status(400).json({
error: 'Safety violation detected',
violations: result.violations,
contractId: result.contractId
});
}
else if (failureMode === 'log') {
console.warn('[EthicalZen] Request violations detected:', result.violations);
// Continue to next middleware
}
}
}
catch (error) {
console.error('[EthicalZen] Request enforcement error:', error);
if (failureMode === 'block') {
return res.status(500).json({
error: 'Safety check failed',
message: 'Unable to validate request safety'
});
}
}
}
// Enforce on response (validate output)
if (enforceOn === 'response' || enforceOn === 'both') {
// Intercept res.json to validate AI output
const originalJson = res.json.bind(res);
res.json = function (body) {
(async () => {
try {
const payload = config.extractPayload
? config.extractPayload(req, res)
: { output: body };
const result = await client.enforce({
contractId: config.contractId,
payload,
metadata: {
method: req.method,
path: req.path,
statusCode: res.statusCode,
timestamp: new Date().toISOString()
}
});
if (!result.passed) {
// Handle violation
if (config.onViolation) {
config.onViolation(result, req, res);
return;
}
if (failureMode === 'block') {
res.status(400);
originalJson.call(res, {
error: 'Safety violation detected',
violations: result.violations,
contractId: result.contractId
});
return;
}
else if (failureMode === 'log') {
console.warn('[EthicalZen] Response violations detected:', result.violations);
// Return original response
}
}
// No violations or failureMode=pass, return original response
originalJson.call(res, body);
}
catch (error) {
console.error('[EthicalZen] Response enforcement error:', error);
if (failureMode === 'block') {
res.status(500);
originalJson.call(res, {
error: 'Safety check failed',
message: 'Unable to validate response safety'
});
return;
}
// If log or pass mode, return original response
originalJson.call(res, body);
}
})();
return res;
};
}
next();
};
}
/**
* Route-specific middleware for selective enforcement
*
* @param config - Middleware configuration
* @returns Express middleware function
*
* @example
* ```typescript
* import { enforceRoute } from '@ethicalzen/sdk';
*
* app.post('/chat',
* enforceRoute({
* apiKey: process.env.ETHICALZEN_API_KEY,
* contractId: 'chatbot/general/us/v1.0'
* }),
* async (req, res) => {
* const response = await generateAIResponse(req.body);
* res.json({ message: response });
* }
* );
* ```
*/
function enforceRoute(config) {
return EthicalZenMiddleware(config);
}