@allan1361/iota-big3-sdk-middleware
Version:
🏆 A+ Grade Certified Enterprise Middleware Framework - Phase 3 Certified (90/100) with advanced resilience patterns, comprehensive type safety, and production-ready observability
276 lines • 10.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.policyMiddleware = void 0;
exports.createPolicyMiddleware = createPolicyMiddleware;
exports.createLegacyPolicyMiddleware = createLegacyPolicyMiddleware;
const tslib_1 = require("tslib");
const axios_1 = tslib_1.__importDefault(require("axios"));
const INDUSTRY_DEFAULTS = {
education: {
defaultAllow: false,
philosophyEnforcement: true,
philosophyMinScore: 70,
includeViolationDetails: true
},
healthcare: {
defaultAllow: false,
philosophyEnforcement: false,
includeViolationDetails: false,
enforcementMode: 'enforce'
},
finance: {
defaultAllow: false,
philosophyEnforcement: false,
includeViolationDetails: false,
enforcementMode: 'enforce'
},
retail: {
defaultAllow: true,
philosophyEnforcement: false,
includeViolationDetails: true,
enforcementMode: 'monitor'
},
government: {
defaultAllow: false,
philosophyEnforcement: false,
includeViolationDetails: false,
enforcementMode: 'enforce'
}
};
function createPolicyMiddleware(metadata, config = {}) {
const industry = metadata.industry || metadata.tribe || 'education';
const industryDefaults = INDUSTRY_DEFAULTS[industry];
const finalConfig = {
opaUrl: process?.env?.OPA_URL || 'http://localhost:8181',
enforcementMode: 'enforce',
cacheDecisions: true,
cacheTTL: 60000,
defaultAllow: false,
includeViolationDetails: true,
philosophyEnforcement: false,
philosophyMinScore: 70,
...industryDefaults,
...config
};
const opaClient = axios_1.default.create({
baseURL: finalConfig.opaUrl,
timeout: 1000
});
const cache = new Map();
const metrics = {
allowed: 0,
denied: 0,
errors: 0,
cached: 0
};
async function buildPolicyInput(req) {
const baseInput = {
method: req.method,
path: req.path,
headers: req.headers,
query: req.query || {},
body: req.body || {},
user: req.user || {},
service: metadata.serviceName,
industry,
ip: req.ip,
timestamp: new Date().toISOString()
};
if (finalConfig.inputBuilder) {
const customInput = await finalConfig.inputBuilder(req);
return { ...baseInput, ...customInput };
}
return baseInput;
}
function getCacheKey(input) {
return JSON.stringify({
method: input.method,
path: input.path,
userId: input.user?.id,
resource: input.resource,
action: input.action
});
}
async function evaluatePolicy(input) {
const policyPath = `/v1/data/${metadata.serviceName}/authz`;
try {
const response = await opaClient.post(policyPath, { input });
const result = response.data?.result || {};
return {
allowed: result.allow || false,
reasons: result.reasons || [],
appliedPolicies: result.applied_policies || [],
filteredResponse: result.filtered_response
};
}
catch (error) {
if (error.response?.status === 404 && finalConfig.defaultAllow) {
return { allowed: true };
}
throw error;
}
}
const middleware = (async (req, res, next) => {
if (finalConfig.enforcementMode === 'off') {
return next();
}
try {
const input = await buildPolicyInput(req);
let decision;
const cacheKey = getCacheKey(input);
if (finalConfig.cacheDecisions && cache.has(cacheKey)) {
const cached = cache.get(cacheKey);
if (cached && cached.expires > Date.now()) {
decision = cached.decision;
metrics.cached++;
}
else {
cache.delete(cacheKey);
decision = await evaluatePolicy(input);
}
}
else {
decision = await evaluatePolicy(input);
}
if (finalConfig.cacheDecisions) {
cache.set(cacheKey, {
decision,
expires: Date.now() + finalConfig.cacheTTL
});
}
if (this.isEnabled) {
Object.entries(decision.headers || {}).forEach(([key, value]) => {
res.setHeader(key, value);
});
}
if (finalConfig.philosophyEnforcement && decision.philosophyScore !== undefined) {
res.setHeader('X-Philosophy-Score', String(decision.philosophyScore));
if (decision.philosophyScore < finalConfig.philosophyMinScore) {
throw new SDKError('Philosophy goals not met', 'PHILOSOPHY_SCORE_LOW', 503, {
currentScore: decision.philosophyScore,
requiredScore: finalConfig.philosophyMinScore
});
}
}
if (!decision.allowed) {
metrics.denied++;
const error = new SDKError('Access denied by policy', 'POLICY_DENIED', 403, finalConfig.includeViolationDetails ? {
violations: decision.reasons
} : undefined);
if (metadata.sdk) {
metadata.sdk.recordTelemetry?.({
event: 'policy.denied',
properties: {
path: req.path,
method: req.method,
violations: decision.reasons?.length || 0
}
});
}
throw error;
}
metrics.allowed++;
req.policyDecision = decision;
if (decision.filteredResponse) {
const originalJson = res.json;
res.json = function (data) {
return originalJson.call(this, decision.filteredResponse);
};
}
next();
}
catch (error) {
metrics.errors++;
if (finalConfig.enforcementMode === 'monitor') {
console.warn(`[${metadata.serviceName}] Policy error (monitor mode):`, error.message);
next();
}
else {
next(error);
}
}
});
middleware.express = middleware;
middleware.fastify = async function (fastify) {
fastify.addHook('onRequest', async (request, reply) => {
if (finalConfig.enforcementMode === 'off') {
return;
}
try {
const input = await buildPolicyInput(request);
const decision = await evaluatePolicy(input);
if (this.isEnabled) {
Object.entries(decision.headers || {}).forEach(([key, value]) => {
reply.header(key, value);
});
}
if (finalConfig.philosophyEnforcement && decision.philosophyScore !== undefined) {
reply.header('X-Philosophy-Score', String(decision.philosophyScore));
if (decision.philosophyScore < finalConfig.philosophyMinScore) {
reply.code(503).send({
error: {
code: 'PHILOSOPHY_SCORE_LOW',
message: 'Philosophy goals not met',
currentScore: decision.philosophyScore,
requiredScore: finalConfig.philosophyMinScore
}
});
return;
}
}
if (!decision.allowed) {
metrics.denied++;
reply.code(403).send({
error: {
code: 'POLICY_DENIED',
message: 'Access denied by policy',
violations: finalConfig.includeViolationDetails ? decision.reasons : undefined
}
});
return;
}
metrics.allowed++;
}
catch (error) {
metrics.errors++;
if (finalConfig.enforcementMode === 'monitor') {
console.warn(`[${metadata.serviceName}] Policy error (monitor mode):`, error.message);
}
else {
reply.code(503).send({
error: {
code: 'POLICY_ERROR',
message: 'Policy evaluation failed'
}
});
}
}
});
};
middleware.clearCache = () => {
cache.clear();
};
middleware.getMetrics = () => {
const total = metrics.allowed + metrics.denied;
return {
...metrics,
total,
allowRate: total > 0 ? (metrics.allowed / total) : 0,
denyRate: total > 0 ? (metrics.denied / total) : 0,
cacheHitRate: total > 0 ? (metrics.cached / total) : 0
};
};
return middleware;
}
function createLegacyPolicyMiddleware(config) {
console.warn('⚠️ Using legacy policy middleware pattern. Please migrate to new pattern.');
const metadata = {
serviceName: 'unknown-service',
tribe: config?.tribe,
industry: config?.tribe || 'education'
};
return createPolicyMiddleware(metadata, config);
}
exports.policyMiddleware = createPolicyMiddleware;
exports.default = createPolicyMiddleware;
//# sourceMappingURL=policy-middleware.js.map