@nest-yalc-2/sentinel 2.2.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/package.json +24 -7
- package/dist/__tests__/sentinel.spec.d.ts +0 -5
- package/dist/__tests__/sentinel.spec.js +0 -75
- package/dist/algorithms/ai-guardrails.d.ts +0 -26
- package/dist/algorithms/ai-guardrails.js +0 -64
- package/dist/algorithms/lsass-guard.d.ts +0 -20
- package/dist/algorithms/lsass-guard.js +0 -28
- package/dist/algorithms/markov-sequence.d.ts +0 -22
- package/dist/algorithms/markov-sequence.js +0 -52
- package/dist/algorithms/polymorphic-routes.d.ts +0 -29
- package/dist/algorithms/polymorphic-routes.js +0 -100
- package/dist/algorithms/polymorphic_routes.d.ts +0 -29
- package/dist/algorithms/polymorphic_routes.js +0 -100
- package/dist/algorithms/rag-groundedness.d.ts +0 -17
- package/dist/algorithms/rag-groundedness.js +0 -62
- package/dist/algorithms/sbom-verifier.d.ts +0 -24
- package/dist/algorithms/sbom-verifier.js +0 -80
- package/dist/algorithms/shannon-entropy.d.ts +0 -16
- package/dist/algorithms/shannon-entropy.js +0 -39
- package/dist/index.d.ts +0 -14
- package/dist/index.js +0 -30
- package/dist/sentinel.guard.d.ts +0 -8
- package/dist/sentinel.guard.js +0 -38
- package/dist/sentinel.interceptor.d.ts +0 -11
- package/dist/sentinel.interceptor.js +0 -43
- package/dist/sentinel.module.d.ts +0 -12
- package/dist/sentinel.module.js +0 -35
- package/tsconfig.json +0 -18
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # RAG Groundedness & Hallucination Guardrail Engine (`rag-groundedness.ts`)
|
|
4
|
-
* RAG factual claim overlap ratio scoring engine
|
|
5
|
-
* (Academic Ref: *Building LLM-Powered Applications* & *Mastering LLM Applications*).
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.RagHallucinationGroundednessEngine = void 0;
|
|
9
|
-
class RagHallucinationGroundednessEngine {
|
|
10
|
-
/**
|
|
11
|
-
* Computes factual groundedness score as the ratio of generated response claims supported by retrieved context chunks
|
|
12
|
-
*/
|
|
13
|
-
static evaluateGroundedness(generatedResponse, retrievedContexts, groundednessThreshold = 0.70) {
|
|
14
|
-
const claims = generatedResponse
|
|
15
|
-
.split(/[.!?]/)
|
|
16
|
-
.map((s) => s.trim())
|
|
17
|
-
.filter((s) => s.length > 0);
|
|
18
|
-
if (claims.length === 0) {
|
|
19
|
-
return {
|
|
20
|
-
groundednessScore: 1.0,
|
|
21
|
-
isGrounded: true,
|
|
22
|
-
unsupportedClaims: [],
|
|
23
|
-
matchedContextFacts: [],
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
const combinedContext = retrievedContexts.join(' ').toLowerCase();
|
|
27
|
-
const contextWords = new Set(combinedContext
|
|
28
|
-
.split(/[^a-zA-Z0-9]+/)
|
|
29
|
-
.filter((w) => w.length > 0));
|
|
30
|
-
let matchedClaimsCount = 0;
|
|
31
|
-
const unsupportedClaims = [];
|
|
32
|
-
const matchedContextFacts = [];
|
|
33
|
-
for (const claim of claims) {
|
|
34
|
-
const claimWords = claim
|
|
35
|
-
.toLowerCase()
|
|
36
|
-
.split(/[^a-zA-Z0-9]+/)
|
|
37
|
-
.filter((w) => w.length > 3);
|
|
38
|
-
if (claimWords.length === 0) {
|
|
39
|
-
matchedClaimsCount++;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
const matches = claimWords.filter((w) => contextWords.has(w)).length;
|
|
43
|
-
const matchRatio = matches / claimWords.length;
|
|
44
|
-
if (matchRatio >= 0.4) {
|
|
45
|
-
matchedClaimsCount++;
|
|
46
|
-
matchedContextFacts.push(claim);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
unsupportedClaims.push(claim);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const groundednessScore = matchedClaimsCount / claims.length;
|
|
53
|
-
const isGrounded = groundednessScore >= groundednessThreshold;
|
|
54
|
-
return {
|
|
55
|
-
groundednessScore,
|
|
56
|
-
isGrounded,
|
|
57
|
-
unsupportedClaims,
|
|
58
|
-
matchedContextFacts,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
exports.RagHallucinationGroundednessEngine = RagHallucinationGroundednessEngine;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # SBOM & Supply Chain Dependency Integrity Guard (`sbom-verifier.ts`)
|
|
3
|
-
* Package SHA-256 cryptographic hash & dependency integrity validator
|
|
4
|
-
* (Academic Ref: *Intelligent Continuous Security*, O'Reilly - Ch. 7).
|
|
5
|
-
*/
|
|
6
|
-
export interface SbomComponentRecord {
|
|
7
|
-
name: string;
|
|
8
|
-
version: string;
|
|
9
|
-
expectedSha256: string;
|
|
10
|
-
isRevoked: boolean;
|
|
11
|
-
}
|
|
12
|
-
export interface SupplyChainIntegrityReport {
|
|
13
|
-
isValid: boolean;
|
|
14
|
-
tamperedComponents: string[];
|
|
15
|
-
revokedComponents: string[];
|
|
16
|
-
totalVerified: number;
|
|
17
|
-
}
|
|
18
|
-
export declare class SbomSupplyChainVerifierEngine {
|
|
19
|
-
static verifyComponent(record: SbomComponentRecord, actualContent: string | Buffer): {
|
|
20
|
-
matches: boolean;
|
|
21
|
-
actualHash: string;
|
|
22
|
-
};
|
|
23
|
-
static auditSupplyChain(manifest: SbomComponentRecord[], actualComponents: Map<string, string | Buffer>): SupplyChainIntegrityReport;
|
|
24
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # SBOM & Supply Chain Dependency Integrity Guard (`sbom-verifier.ts`)
|
|
4
|
-
* Package SHA-256 cryptographic hash & dependency integrity validator
|
|
5
|
-
* (Academic Ref: *Intelligent Continuous Security*, O'Reilly - Ch. 7).
|
|
6
|
-
*/
|
|
7
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
-
if (k2 === undefined) k2 = k;
|
|
9
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
-
}
|
|
13
|
-
Object.defineProperty(o, k2, desc);
|
|
14
|
-
}) : (function(o, m, k, k2) {
|
|
15
|
-
if (k2 === undefined) k2 = k;
|
|
16
|
-
o[k2] = m[k];
|
|
17
|
-
}));
|
|
18
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
-
}) : function(o, v) {
|
|
21
|
-
o["default"] = v;
|
|
22
|
-
});
|
|
23
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
-
var ownKeys = function(o) {
|
|
25
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
-
var ar = [];
|
|
27
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
-
return ar;
|
|
29
|
-
};
|
|
30
|
-
return ownKeys(o);
|
|
31
|
-
};
|
|
32
|
-
return function (mod) {
|
|
33
|
-
if (mod && mod.__esModule) return mod;
|
|
34
|
-
var result = {};
|
|
35
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
-
__setModuleDefault(result, mod);
|
|
37
|
-
return result;
|
|
38
|
-
};
|
|
39
|
-
})();
|
|
40
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.SbomSupplyChainVerifierEngine = void 0;
|
|
42
|
-
const crypto = __importStar(require("crypto"));
|
|
43
|
-
class SbomSupplyChainVerifierEngine {
|
|
44
|
-
static verifyComponent(record, actualContent) {
|
|
45
|
-
const bytes = typeof actualContent === 'string' ? Buffer.from(actualContent) : actualContent;
|
|
46
|
-
const actualHash = crypto.createHash('sha256').update(bytes).digest('hex');
|
|
47
|
-
const matches = actualHash.toLowerCase() === record.expectedSha256.toLowerCase();
|
|
48
|
-
return { matches, actualHash };
|
|
49
|
-
}
|
|
50
|
-
static auditSupplyChain(manifest, actualComponents) {
|
|
51
|
-
const tamperedComponents = [];
|
|
52
|
-
const revokedComponents = [];
|
|
53
|
-
let totalVerified = 0;
|
|
54
|
-
for (const record of manifest) {
|
|
55
|
-
if (record.isRevoked) {
|
|
56
|
-
revokedComponents.push(`${record.name}@${record.version}`);
|
|
57
|
-
}
|
|
58
|
-
const content = actualComponents.get(record.name);
|
|
59
|
-
if (content) {
|
|
60
|
-
const { matches } = this.verifyComponent(record, content);
|
|
61
|
-
if (!matches) {
|
|
62
|
-
tamperedComponents.push(`${record.name}@${record.version} (Hash mismatch)`);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
totalVerified++;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
tamperedComponents.push(`${record.name}@${record.version} (Missing component)`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
isValid: tamperedComponents.length === 0 && revokedComponents.length === 0,
|
|
74
|
-
tamperedComponents,
|
|
75
|
-
revokedComponents,
|
|
76
|
-
totalVerified,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
exports.SbomSupplyChainVerifierEngine = SbomSupplyChainVerifierEngine;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # Shannon Payload Entropy Evaluator (`shannon-entropy.ts`)
|
|
3
|
-
* Calculates payload information entropy to detect obfuscated, packed, or encrypted payloads
|
|
4
|
-
* (Academic Ref: *Malware Data Science*, No Starch Press).
|
|
5
|
-
*/
|
|
6
|
-
export interface EntropyAssessment {
|
|
7
|
-
entropyScore: number;
|
|
8
|
-
isSuspicious: boolean;
|
|
9
|
-
byteLength: number;
|
|
10
|
-
}
|
|
11
|
-
export declare class ShannonEntropyEngine {
|
|
12
|
-
/**
|
|
13
|
-
* Calculates Shannon Entropy H(X) = -sum(P(x) * log2(P(x))) for string/buffer payload
|
|
14
|
-
*/
|
|
15
|
-
static calculateEntropy(payload: string | Buffer): EntropyAssessment;
|
|
16
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # Shannon Payload Entropy Evaluator (`shannon-entropy.ts`)
|
|
4
|
-
* Calculates payload information entropy to detect obfuscated, packed, or encrypted payloads
|
|
5
|
-
* (Academic Ref: *Malware Data Science*, No Starch Press).
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.ShannonEntropyEngine = void 0;
|
|
9
|
-
class ShannonEntropyEngine {
|
|
10
|
-
/**
|
|
11
|
-
* Calculates Shannon Entropy H(X) = -sum(P(x) * log2(P(x))) for string/buffer payload
|
|
12
|
-
*/
|
|
13
|
-
static calculateEntropy(payload) {
|
|
14
|
-
const bytes = typeof payload === 'string' ? Buffer.from(payload) : payload;
|
|
15
|
-
if (bytes.length === 0) {
|
|
16
|
-
return { entropyScore: 0.0, isSuspicious: false, byteLength: 0 };
|
|
17
|
-
}
|
|
18
|
-
const counts = new Array(256).fill(0);
|
|
19
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
20
|
-
counts[bytes[i]]++;
|
|
21
|
-
}
|
|
22
|
-
let entropy = 0.0;
|
|
23
|
-
const len = bytes.length;
|
|
24
|
-
for (let i = 0; i < 256; i++) {
|
|
25
|
-
if (counts[i] > 0) {
|
|
26
|
-
const p = counts[i] / len;
|
|
27
|
-
entropy -= p * Math.log2(p);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
// High entropy threshold > 7.2 indicates packed/encrypted payload
|
|
31
|
-
const isSuspicious = entropy > 7.2 && bytes.length > 64;
|
|
32
|
-
return {
|
|
33
|
-
entropyScore: Math.round(entropy * 1000) / 1000,
|
|
34
|
-
isSuspicious,
|
|
35
|
-
byteLength: bytes.length,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
exports.ShannonEntropyEngine = ShannonEntropyEngine;
|
package/dist/index.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # Ferrox-Node Sentinel (`@nest-yalc-2/sentinel` / `@ferrox/node-sentinel`)
|
|
3
|
-
* Enterprise AI/ML Security Analytics & 35 SOTA Innovations for NestJS
|
|
4
|
-
*/
|
|
5
|
-
export * from './algorithms/ai-guardrails';
|
|
6
|
-
export * from './algorithms/rag-groundedness';
|
|
7
|
-
export * from './algorithms/shannon-entropy';
|
|
8
|
-
export * from './algorithms/polymorphic-routes';
|
|
9
|
-
export * from './algorithms/markov-sequence';
|
|
10
|
-
export * from './algorithms/lsass-guard';
|
|
11
|
-
export * from './algorithms/sbom-verifier';
|
|
12
|
-
export * from './sentinel.guard';
|
|
13
|
-
export * from './sentinel.interceptor';
|
|
14
|
-
export * from './sentinel.module';
|
package/dist/index.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # Ferrox-Node Sentinel (`@nest-yalc-2/sentinel` / `@ferrox/node-sentinel`)
|
|
4
|
-
* Enterprise AI/ML Security Analytics & 35 SOTA Innovations for NestJS
|
|
5
|
-
*/
|
|
6
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
-
if (k2 === undefined) k2 = k;
|
|
8
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
-
}
|
|
12
|
-
Object.defineProperty(o, k2, desc);
|
|
13
|
-
}) : (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
o[k2] = m[k];
|
|
16
|
-
}));
|
|
17
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
-
};
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
__exportStar(require("./algorithms/ai-guardrails"), exports);
|
|
22
|
-
__exportStar(require("./algorithms/rag-groundedness"), exports);
|
|
23
|
-
__exportStar(require("./algorithms/shannon-entropy"), exports);
|
|
24
|
-
__exportStar(require("./algorithms/polymorphic-routes"), exports);
|
|
25
|
-
__exportStar(require("./algorithms/markov-sequence"), exports);
|
|
26
|
-
__exportStar(require("./algorithms/lsass-guard"), exports);
|
|
27
|
-
__exportStar(require("./algorithms/sbom-verifier"), exports);
|
|
28
|
-
__exportStar(require("./sentinel.guard"), exports);
|
|
29
|
-
__exportStar(require("./sentinel.interceptor"), exports);
|
|
30
|
-
__exportStar(require("./sentinel.module"), exports);
|
package/dist/sentinel.guard.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # NestJS Ferrox-Node Sentinel Guard (`sentinel.guard.ts`)
|
|
3
|
-
* CanActivate Guard evaluating entropy, prompt injection, and velocity anomalies
|
|
4
|
-
*/
|
|
5
|
-
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
6
|
-
export declare class FerroxSentinelGuard implements CanActivate {
|
|
7
|
-
canActivate(context: ExecutionContext): boolean;
|
|
8
|
-
}
|
package/dist/sentinel.guard.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # NestJS Ferrox-Node Sentinel Guard (`sentinel.guard.ts`)
|
|
4
|
-
* CanActivate Guard evaluating entropy, prompt injection, and velocity anomalies
|
|
5
|
-
*/
|
|
6
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
9
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
10
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.FerroxSentinelGuard = void 0;
|
|
14
|
-
const common_1 = require("@nestjs/common");
|
|
15
|
-
const ai_guardrails_js_1 = require("./algorithms/ai-guardrails.js");
|
|
16
|
-
const shannon_entropy_js_1 = require("./algorithms/shannon-entropy.js");
|
|
17
|
-
let FerroxSentinelGuard = class FerroxSentinelGuard {
|
|
18
|
-
canActivate(context) {
|
|
19
|
-
const request = context.switchToHttp().getRequest();
|
|
20
|
-
const bodyStr = request.body ? JSON.stringify(request.body) : '';
|
|
21
|
-
// 1. Evaluate Payload Shannon Entropy
|
|
22
|
-
const entropyResult = shannon_entropy_js_1.ShannonEntropyEngine.calculateEntropy(bodyStr);
|
|
23
|
-
if (entropyResult.isSuspicious) {
|
|
24
|
-
throw new common_1.ForbiddenException(`[FerroxSentinel] Blocked high-entropy payload (Score: ${entropyResult.entropyScore})`);
|
|
25
|
-
}
|
|
26
|
-
// 2. Evaluate Prompt Injection Patterns if string present in query or body
|
|
27
|
-
const promptSample = `${request.url} ${bodyStr}`;
|
|
28
|
-
const aiAssessment = ai_guardrails_js_1.AiPromptGuardrailEngine.evaluatePrompt(promptSample);
|
|
29
|
-
if (aiAssessment.isThreatDetected && aiAssessment.threatScore >= 0.7) {
|
|
30
|
-
throw new common_1.ForbiddenException(`[FerroxSentinel] Blocked Prompt Injection / DAN Jailbreak attempt. Matched: ${aiAssessment.matchedKeywords.join(', ')}`);
|
|
31
|
-
}
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
exports.FerroxSentinelGuard = FerroxSentinelGuard;
|
|
36
|
-
exports.FerroxSentinelGuard = FerroxSentinelGuard = __decorate([
|
|
37
|
-
(0, common_1.Injectable)()
|
|
38
|
-
], FerroxSentinelGuard);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # NestJS Ferrox-Node RAG Groundedness & Response Interceptor (`sentinel.interceptor.ts`)
|
|
3
|
-
* Evaluates LLM generated response groundedness against retrieved context
|
|
4
|
-
*/
|
|
5
|
-
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
6
|
-
import { Observable } from 'rxjs';
|
|
7
|
-
export declare class RagGroundednessInterceptor implements NestInterceptor {
|
|
8
|
-
private readonly minGroundednessScore;
|
|
9
|
-
constructor(minGroundednessScore?: number);
|
|
10
|
-
intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
11
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # NestJS Ferrox-Node RAG Groundedness & Response Interceptor (`sentinel.interceptor.ts`)
|
|
4
|
-
* Evaluates LLM generated response groundedness against retrieved context
|
|
5
|
-
*/
|
|
6
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
9
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
10
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
11
|
-
};
|
|
12
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
13
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
14
|
-
};
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.RagGroundednessInterceptor = void 0;
|
|
17
|
-
const common_1 = require("@nestjs/common");
|
|
18
|
-
const operators_1 = require("rxjs/operators");
|
|
19
|
-
const rag_groundedness_js_1 = require("./algorithms/rag-groundedness.js");
|
|
20
|
-
let RagGroundednessInterceptor = class RagGroundednessInterceptor {
|
|
21
|
-
minGroundednessScore;
|
|
22
|
-
constructor(minGroundednessScore = 0.70) {
|
|
23
|
-
this.minGroundednessScore = minGroundednessScore;
|
|
24
|
-
}
|
|
25
|
-
intercept(context, next) {
|
|
26
|
-
const request = context.switchToHttp().getRequest();
|
|
27
|
-
const retrievedContexts = request.ragContexts || [];
|
|
28
|
-
return next.handle().pipe((0, operators_1.map)((response) => {
|
|
29
|
-
if (typeof response === 'string' && retrievedContexts.length > 0) {
|
|
30
|
-
const assessment = rag_groundedness_js_1.RagHallucinationGroundednessEngine.evaluateGroundedness(response, retrievedContexts, this.minGroundednessScore);
|
|
31
|
-
if (!assessment.isGrounded) {
|
|
32
|
-
throw new common_1.BadGatewayException(`[FerroxSentinel] LLM response failed groundedness check (Score: ${assessment.groundednessScore.toFixed(2)} < ${this.minGroundednessScore})`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return response;
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
exports.RagGroundednessInterceptor = RagGroundednessInterceptor;
|
|
40
|
-
exports.RagGroundednessInterceptor = RagGroundednessInterceptor = __decorate([
|
|
41
|
-
(0, common_1.Injectable)(),
|
|
42
|
-
__metadata("design:paramtypes", [Number])
|
|
43
|
-
], RagGroundednessInterceptor);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # NestJS Ferrox-Node Sentinel Module (`sentinel.module.ts`)
|
|
3
|
-
*/
|
|
4
|
-
import { DynamicModule } from '@nestjs/common';
|
|
5
|
-
export interface SentinelModuleOptions {
|
|
6
|
-
enablePromptSanitizer?: boolean;
|
|
7
|
-
enableEntropyCheck?: boolean;
|
|
8
|
-
minGroundednessScore?: number;
|
|
9
|
-
}
|
|
10
|
-
export declare class FerroxSentinelModule {
|
|
11
|
-
static register(options?: SentinelModuleOptions): DynamicModule;
|
|
12
|
-
}
|
package/dist/sentinel.module.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* # NestJS Ferrox-Node Sentinel Module (`sentinel.module.ts`)
|
|
4
|
-
*/
|
|
5
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
6
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
7
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
8
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
9
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
10
|
-
};
|
|
11
|
-
var FerroxSentinelModule_1;
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.FerroxSentinelModule = void 0;
|
|
14
|
-
const common_1 = require("@nestjs/common");
|
|
15
|
-
const sentinel_guard_js_1 = require("./sentinel.guard.js");
|
|
16
|
-
const sentinel_interceptor_js_1 = require("./sentinel.interceptor.js");
|
|
17
|
-
let FerroxSentinelModule = FerroxSentinelModule_1 = class FerroxSentinelModule {
|
|
18
|
-
static register(options = {}) {
|
|
19
|
-
return {
|
|
20
|
-
module: FerroxSentinelModule_1,
|
|
21
|
-
providers: [
|
|
22
|
-
sentinel_guard_js_1.FerroxSentinelGuard,
|
|
23
|
-
{
|
|
24
|
-
provide: sentinel_interceptor_js_1.RagGroundednessInterceptor,
|
|
25
|
-
useValue: new sentinel_interceptor_js_1.RagGroundednessInterceptor(options.minGroundednessScore ?? 0.70),
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
exports: [sentinel_guard_js_1.FerroxSentinelGuard, sentinel_interceptor_js_1.RagGroundednessInterceptor],
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
exports.FerroxSentinelModule = FerroxSentinelModule;
|
|
33
|
-
exports.FerroxSentinelModule = FerroxSentinelModule = FerroxSentinelModule_1 = __decorate([
|
|
34
|
-
(0, common_1.Module)({})
|
|
35
|
-
], FerroxSentinelModule);
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "NodeNext",
|
|
4
|
-
"moduleResolution": "NodeNext",
|
|
5
|
-
"target": "ES2022",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"rootDir": "./src",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"experimentalDecorators": true,
|
|
11
|
-
"emitDecoratorMetadata": true,
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"esModuleInterop": true,
|
|
14
|
-
"types": ["node", "jest"]
|
|
15
|
-
},
|
|
16
|
-
"include": ["src/**/*"],
|
|
17
|
-
"exclude": ["src/__tests__"]
|
|
18
|
-
}
|