@sandrobuilds/tracerney 0.9.6
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/README.md +702 -0
- package/dist/application/ShieldApplicationService.d.ts +94 -0
- package/dist/application/ShieldApplicationService.d.ts.map +1 -0
- package/dist/application/ShieldApplicationService.js +223 -0
- package/dist/application/ShieldApplicationService.js.map +1 -0
- package/dist/application/ShieldBlockError.d.ts +10 -0
- package/dist/application/ShieldBlockError.d.ts.map +1 -0
- package/dist/application/ShieldBlockError.js +13 -0
- package/dist/application/ShieldBlockError.js.map +1 -0
- package/dist/application/index.d.ts +9 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +8 -0
- package/dist/application/index.js.map +1 -0
- package/dist/application/ports/ILLMProvider.d.ts +71 -0
- package/dist/application/ports/ILLMProvider.d.ts.map +1 -0
- package/dist/application/ports/ILLMProvider.js +15 -0
- package/dist/application/ports/ILLMProvider.js.map +1 -0
- package/dist/application/ports/IPatternRepository.d.ts +20 -0
- package/dist/application/ports/IPatternRepository.d.ts.map +1 -0
- package/dist/application/ports/IPatternRepository.js +7 -0
- package/dist/application/ports/IPatternRepository.js.map +1 -0
- package/dist/application/ports/ISentinel.d.ts +22 -0
- package/dist/application/ports/ISentinel.d.ts.map +1 -0
- package/dist/application/ports/ISentinel.js +8 -0
- package/dist/application/ports/ISentinel.js.map +1 -0
- package/dist/application/ports/ITelemetrySink.d.ts +35 -0
- package/dist/application/ports/ITelemetrySink.d.ts.map +1 -0
- package/dist/application/ports/ITelemetrySink.js +7 -0
- package/dist/application/ports/ITelemetrySink.js.map +1 -0
- package/dist/application/ports/index.d.ts +10 -0
- package/dist/application/ports/index.d.ts.map +1 -0
- package/dist/application/ports/index.js +7 -0
- package/dist/application/ports/index.js.map +1 -0
- package/dist/application/utils/index.d.ts +6 -0
- package/dist/application/utils/index.d.ts.map +1 -0
- package/dist/application/utils/index.js +6 -0
- package/dist/application/utils/index.js.map +1 -0
- package/dist/application/utils/jitter.d.ts +10 -0
- package/dist/application/utils/jitter.d.ts.map +1 -0
- package/dist/application/utils/jitter.js +13 -0
- package/dist/application/utils/jitter.js.map +1 -0
- package/dist/application/utils/normalizePrompt.d.ts +18 -0
- package/dist/application/utils/normalizePrompt.d.ts.map +1 -0
- package/dist/application/utils/normalizePrompt.js +36 -0
- package/dist/application/utils/normalizePrompt.js.map +1 -0
- package/dist/domain/detection/InjectionThreat.d.ts +19 -0
- package/dist/domain/detection/InjectionThreat.d.ts.map +1 -0
- package/dist/domain/detection/InjectionThreat.js +18 -0
- package/dist/domain/detection/InjectionThreat.js.map +1 -0
- package/dist/domain/detection/PatternMatcher.d.ts +36 -0
- package/dist/domain/detection/PatternMatcher.d.ts.map +1 -0
- package/dist/domain/detection/PatternMatcher.js +65 -0
- package/dist/domain/detection/PatternMatcher.js.map +1 -0
- package/dist/domain/detection/VanguardPattern.d.ts +19 -0
- package/dist/domain/detection/VanguardPattern.d.ts.map +1 -0
- package/dist/domain/detection/VanguardPattern.js +21 -0
- package/dist/domain/detection/VanguardPattern.js.map +1 -0
- package/dist/domain/detection/index.d.ts +11 -0
- package/dist/domain/detection/index.d.ts.map +1 -0
- package/dist/domain/detection/index.js +8 -0
- package/dist/domain/detection/index.js.map +1 -0
- package/dist/domain/events/SecurityEvent.d.ts +30 -0
- package/dist/domain/events/SecurityEvent.d.ts.map +1 -0
- package/dist/domain/events/SecurityEvent.js +21 -0
- package/dist/domain/events/SecurityEvent.js.map +1 -0
- package/dist/domain/events/SecurityEventType.d.ts +13 -0
- package/dist/domain/events/SecurityEventType.d.ts.map +1 -0
- package/dist/domain/events/SecurityEventType.js +15 -0
- package/dist/domain/events/SecurityEventType.js.map +1 -0
- package/dist/domain/events/ThreatSeverity.d.ts +13 -0
- package/dist/domain/events/ThreatSeverity.d.ts.map +1 -0
- package/dist/domain/events/ThreatSeverity.js +15 -0
- package/dist/domain/events/ThreatSeverity.js.map +1 -0
- package/dist/domain/events/index.d.ts +11 -0
- package/dist/domain/events/index.d.ts.map +1 -0
- package/dist/domain/events/index.js +8 -0
- package/dist/domain/events/index.js.map +1 -0
- package/dist/domain/guard/ToolGuard.d.ts +35 -0
- package/dist/domain/guard/ToolGuard.d.ts.map +1 -0
- package/dist/domain/guard/ToolGuard.js +49 -0
- package/dist/domain/guard/ToolGuard.js.map +1 -0
- package/dist/domain/guard/ToolPolicy.d.ts +16 -0
- package/dist/domain/guard/ToolPolicy.d.ts.map +1 -0
- package/dist/domain/guard/ToolPolicy.js +19 -0
- package/dist/domain/guard/ToolPolicy.js.map +1 -0
- package/dist/domain/guard/ToolViolation.d.ts +14 -0
- package/dist/domain/guard/ToolViolation.d.ts.map +1 -0
- package/dist/domain/guard/ToolViolation.js +15 -0
- package/dist/domain/guard/ToolViolation.js.map +1 -0
- package/dist/domain/guard/index.d.ts +11 -0
- package/dist/domain/guard/index.d.ts.map +1 -0
- package/dist/domain/guard/index.js +8 -0
- package/dist/domain/guard/index.js.map +1 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +173 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/llm/OpenRouterProvider.d.ts +32 -0
- package/dist/infrastructure/llm/OpenRouterProvider.d.ts.map +1 -0
- package/dist/infrastructure/llm/OpenRouterProvider.js +119 -0
- package/dist/infrastructure/llm/OpenRouterProvider.js.map +1 -0
- package/dist/infrastructure/llm/index.d.ts +7 -0
- package/dist/infrastructure/llm/index.d.ts.map +1 -0
- package/dist/infrastructure/llm/index.js +6 -0
- package/dist/infrastructure/llm/index.js.map +1 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.d.ts +16 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.d.ts.map +1 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.js +19 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.js.map +1 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.d.ts +77 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.d.ts.map +1 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.js +176 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.js.map +1 -0
- package/dist/infrastructure/patterns/bundled-patterns.d.ts +9 -0
- package/dist/infrastructure/patterns/bundled-patterns.d.ts.map +1 -0
- package/dist/infrastructure/patterns/bundled-patterns.js +2082 -0
- package/dist/infrastructure/patterns/bundled-patterns.js.map +1 -0
- package/dist/infrastructure/patterns/index.d.ts +9 -0
- package/dist/infrastructure/patterns/index.d.ts.map +1 -0
- package/dist/infrastructure/patterns/index.js +8 -0
- package/dist/infrastructure/patterns/index.js.map +1 -0
- package/dist/infrastructure/sentinel/LLMSentinel.d.ts +48 -0
- package/dist/infrastructure/sentinel/LLMSentinel.d.ts.map +1 -0
- package/dist/infrastructure/sentinel/LLMSentinel.js +142 -0
- package/dist/infrastructure/sentinel/LLMSentinel.js.map +1 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.d.ts +30 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.js +40 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.js.map +1 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.d.ts +51 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.js +134 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.js.map +1 -0
- package/dist/infrastructure/telemetry/index.d.ts +9 -0
- package/dist/infrastructure/telemetry/index.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/index.js +7 -0
- package/dist/infrastructure/telemetry/index.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shield Application Service
|
|
3
|
+
* Core orchestrator: wires domain services + infrastructure adapters
|
|
4
|
+
* Fixes all 5 integration gaps from the original design
|
|
5
|
+
*/
|
|
6
|
+
import { type ToolPolicy } from "../domain/guard/ToolPolicy";
|
|
7
|
+
import { ILLMProvider, type LLMResponse } from "./ports/ILLMProvider";
|
|
8
|
+
import { ISentinel } from "./ports/ISentinel";
|
|
9
|
+
import { ITelemetrySink } from "./ports/ITelemetrySink";
|
|
10
|
+
import { IPatternRepository } from "./ports/IPatternRepository";
|
|
11
|
+
import { HttpShadowLogSink } from "../infrastructure/telemetry";
|
|
12
|
+
export interface ShieldApplicationServiceConfig {
|
|
13
|
+
patternRepository: IPatternRepository;
|
|
14
|
+
telemetrySink?: ITelemetrySink;
|
|
15
|
+
toolPolicy: ToolPolicy;
|
|
16
|
+
sdkVersion?: string;
|
|
17
|
+
llmProvider?: ILLMProvider;
|
|
18
|
+
sentinel?: ISentinel;
|
|
19
|
+
shadowLogSink?: HttpShadowLogSink;
|
|
20
|
+
}
|
|
21
|
+
export interface WrapOptions {
|
|
22
|
+
prompt?: string;
|
|
23
|
+
requestId?: string;
|
|
24
|
+
modelName?: string;
|
|
25
|
+
provider?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ServiceStatus {
|
|
28
|
+
patternMatcher: {
|
|
29
|
+
ready: boolean;
|
|
30
|
+
stats?: unknown;
|
|
31
|
+
};
|
|
32
|
+
toolGuard: {
|
|
33
|
+
allowedTools: readonly string[];
|
|
34
|
+
};
|
|
35
|
+
telemetry: {
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
status?: unknown;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export declare class ShieldApplicationService {
|
|
41
|
+
private readonly config;
|
|
42
|
+
private patternMatcher;
|
|
43
|
+
private toolGuard;
|
|
44
|
+
private telemetrySink?;
|
|
45
|
+
private llmProvider?;
|
|
46
|
+
private sentinel?;
|
|
47
|
+
private readonly sdkVersion;
|
|
48
|
+
constructor(config: ShieldApplicationServiceConfig);
|
|
49
|
+
/**
|
|
50
|
+
* Update patterns from remote repository in background.
|
|
51
|
+
* Non-blocking; fails gracefully, falling back to bundled patterns.
|
|
52
|
+
*/
|
|
53
|
+
private updateRemotePatterns;
|
|
54
|
+
/**
|
|
55
|
+
* Main wrapper method for LLM calls.
|
|
56
|
+
* Fixes Gap 2 (latencyMs now stored) and Gap 3 (prompt parameter for pre-LLM scan)
|
|
57
|
+
*
|
|
58
|
+
* @param llmCall - The LLM function to execute
|
|
59
|
+
* @param options - Optional: prompt for pre-LLM scan, request context
|
|
60
|
+
*/
|
|
61
|
+
wrap<T extends LLMResponse>(llmCall: () => Promise<T>, options?: WrapOptions): Promise<T>;
|
|
62
|
+
/**
|
|
63
|
+
* Scan a raw prompt pre-LLM for inline use.
|
|
64
|
+
* Throws if injection is detected.
|
|
65
|
+
*
|
|
66
|
+
* Hardened Middleware:
|
|
67
|
+
* - Normalize: Collapse homoglyphs and whitespace tricks
|
|
68
|
+
* - Layer 1 (Regex): Fast, pattern-based detection
|
|
69
|
+
* - Layer 2 (LLM Sentinel): If Layer 1 misses, use LLM to verify
|
|
70
|
+
* - Jitter: Add random delay to mask which layer blocked (if any)
|
|
71
|
+
*/
|
|
72
|
+
scanPrompt(prompt: string, requestId?: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Update tool policy at runtime
|
|
75
|
+
*/
|
|
76
|
+
setAllowedTools(tools: readonly string[]): void;
|
|
77
|
+
/**
|
|
78
|
+
* Get service status for diagnostics
|
|
79
|
+
*/
|
|
80
|
+
getStatus(): ServiceStatus;
|
|
81
|
+
/**
|
|
82
|
+
* Report a security event (non-blocking)
|
|
83
|
+
*/
|
|
84
|
+
private report;
|
|
85
|
+
/**
|
|
86
|
+
* Graceful shutdown: flush telemetry, release resources
|
|
87
|
+
*/
|
|
88
|
+
destroy(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Generate a unique request ID
|
|
91
|
+
*/
|
|
92
|
+
private generateRequestId;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=ShieldApplicationService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShieldApplicationService.d.ts","sourceRoot":"","sources":["../../src/application/ShieldApplicationService.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAO/E,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE,OAAO,EAAE,iBAAiB,EAAyB,MAAM,6BAA6B,CAAC;AAIvF,MAAM,WAAW,8BAA8B;IAC7C,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE;QACd,KAAK,EAAE,OAAO,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACT,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;KACjC,CAAC;IACF,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAED,qBAAa,wBAAwB;IASvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IARnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,aAAa,CAAC,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,CAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAEP,MAAM,EAAE,8BAA8B;IAgBnE;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;OAMG;IACG,IAAI,CAAC,CAAC,SAAS,WAAW,EAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,CAAC,CAAC;IAuDb;;;;;;;;;OASG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFnE;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAK/C;;OAEG;IACH,SAAS,IAAI,aAAa;IAgB1B;;OAEG;IACH,OAAO,CAAC,MAAM;IAMd;;OAEG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAG1B"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shield Application Service
|
|
3
|
+
* Core orchestrator: wires domain services + infrastructure adapters
|
|
4
|
+
* Fixes all 5 integration gaps from the original design
|
|
5
|
+
*/
|
|
6
|
+
import { PatternMatcher } from '../domain/detection/PatternMatcher.js';
|
|
7
|
+
import { ToolGuard } from '../domain/guard/ToolGuard.js';
|
|
8
|
+
import { createToolPolicy } from '../domain/guard/ToolPolicy.js';
|
|
9
|
+
import { createSecurityEvent, SecurityEventType, ThreatSeverity, } from '../domain/events/index.js';
|
|
10
|
+
import { ShieldBlockError } from './ShieldBlockError.js';
|
|
11
|
+
import { normalizePrompt, jitter } from './utils/index.js';
|
|
12
|
+
import { BUNDLED_PATTERNS } from '../infrastructure/patterns/bundled-patterns.js';
|
|
13
|
+
import { BundledPatternRepository } from '../infrastructure/patterns/BundledPatternRepository.js';
|
|
14
|
+
export class ShieldApplicationService {
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.toolGuard = new ToolGuard(config.toolPolicy);
|
|
18
|
+
this.telemetrySink = config.telemetrySink;
|
|
19
|
+
this.llmProvider = config.llmProvider;
|
|
20
|
+
this.sentinel = config.sentinel; // Layer 2
|
|
21
|
+
// this.shadowLogSink = config.shadowLogSink; // Disabled for now
|
|
22
|
+
this.sdkVersion = config.sdkVersion ?? "0.2.0";
|
|
23
|
+
// Initialize patterns synchronously (bundled patterns always available)
|
|
24
|
+
this.patternMatcher = new PatternMatcher(BUNDLED_PATTERNS);
|
|
25
|
+
console.log(`[Tracerny] Layer 1 ready immediately with ${BUNDLED_PATTERNS.length} bundled patterns`);
|
|
26
|
+
// Load remote patterns in background if configured (zero-day updates)
|
|
27
|
+
this.updateRemotePatterns();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Update patterns from remote repository in background.
|
|
31
|
+
* Non-blocking; fails gracefully, falling back to bundled patterns.
|
|
32
|
+
*/
|
|
33
|
+
updateRemotePatterns() {
|
|
34
|
+
// Only load remote if not using bundled repository
|
|
35
|
+
if (this.config.patternRepository instanceof BundledPatternRepository === false) {
|
|
36
|
+
this.config.patternRepository
|
|
37
|
+
.getPatterns()
|
|
38
|
+
.then((patterns) => {
|
|
39
|
+
if (patterns && patterns.length > 0) {
|
|
40
|
+
this.patternMatcher = new PatternMatcher(patterns);
|
|
41
|
+
console.log(`[Tracerny] Layer 1 updated with ${patterns.length} remote patterns`);
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
.catch((err) => {
|
|
45
|
+
console.warn("[Tracerny] Remote pattern load failed, using bundled patterns:", err);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Main wrapper method for LLM calls.
|
|
51
|
+
* Fixes Gap 2 (latencyMs now stored) and Gap 3 (prompt parameter for pre-LLM scan)
|
|
52
|
+
*
|
|
53
|
+
* @param llmCall - The LLM function to execute
|
|
54
|
+
* @param options - Optional: prompt for pre-LLM scan, request context
|
|
55
|
+
*/
|
|
56
|
+
async wrap(llmCall, options) {
|
|
57
|
+
const requestId = options?.requestId ?? this.generateRequestId();
|
|
58
|
+
const startTime = Date.now();
|
|
59
|
+
try {
|
|
60
|
+
// FIX GAP 3: Pre-LLM scan if prompt is provided
|
|
61
|
+
// Uses both Layer 1 (Regex) and Layer 2 (LLM) to make decision
|
|
62
|
+
if (options?.prompt) {
|
|
63
|
+
await this.scanPrompt(options.prompt, requestId);
|
|
64
|
+
// scanPrompt throws ShieldBlockError if blocked by Layer 2
|
|
65
|
+
// Layer 1 just flags suspicious, doesn't block
|
|
66
|
+
}
|
|
67
|
+
// Execute the LLM call
|
|
68
|
+
const response = await llmCall();
|
|
69
|
+
// FIX GAP 2: Compute and store latencyMs in event metadata
|
|
70
|
+
const latencyMs = Date.now() - startTime;
|
|
71
|
+
// Validate tool calls against policy
|
|
72
|
+
const toolCalls = response.choices?.[0]?.message?.tool_calls;
|
|
73
|
+
const violation = this.toolGuard.validate(toolCalls, requestId);
|
|
74
|
+
if (violation) {
|
|
75
|
+
const event = createSecurityEvent(requestId, SecurityEventType.UNAUTHORIZED_TOOL, ThreatSeverity.CRITICAL, `Tool '${violation.toolName}' is not in allow list`, {
|
|
76
|
+
toolName: violation.toolName,
|
|
77
|
+
blockLatencyMs: latencyMs, // FIX GAP 2: now included
|
|
78
|
+
modelName: options?.modelName,
|
|
79
|
+
provider: options?.provider,
|
|
80
|
+
}, startTime);
|
|
81
|
+
this.report(event);
|
|
82
|
+
throw new ShieldBlockError(`Tracerny Block: Unauthorized tool '${violation.toolName}'`, event);
|
|
83
|
+
}
|
|
84
|
+
return response;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
// Re-throw our blocks as-is
|
|
88
|
+
if (error instanceof ShieldBlockError) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
// Let other errors (LLM failures, network issues) propagate
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Scan a raw prompt pre-LLM for inline use.
|
|
97
|
+
* Throws if injection is detected.
|
|
98
|
+
*
|
|
99
|
+
* Hardened Middleware:
|
|
100
|
+
* - Normalize: Collapse homoglyphs and whitespace tricks
|
|
101
|
+
* - Layer 1 (Regex): Fast, pattern-based detection
|
|
102
|
+
* - Layer 2 (LLM Sentinel): If Layer 1 misses, use LLM to verify
|
|
103
|
+
* - Jitter: Add random delay to mask which layer blocked (if any)
|
|
104
|
+
*/
|
|
105
|
+
async scanPrompt(prompt, requestId) {
|
|
106
|
+
if (!prompt) {
|
|
107
|
+
return; // No-op for empty prompt
|
|
108
|
+
}
|
|
109
|
+
const rid = requestId ?? this.generateRequestId();
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
try {
|
|
112
|
+
// Normalize prompt to prevent Unicode/whitespace evasion
|
|
113
|
+
const normalizedPrompt = normalizePrompt(prompt);
|
|
114
|
+
console.log(`[Tracerny] Scanning prompt (${normalizedPrompt.length} chars), sentinel=${!!this.sentinel}`);
|
|
115
|
+
// Layer 1: Regex patterns (detection, NOT blocking)
|
|
116
|
+
// Flags suspicious content but doesn't block - Layer 2 makes the final decision
|
|
117
|
+
const threat = this.patternMatcher.match(normalizedPrompt);
|
|
118
|
+
const isSuspicious = !!threat;
|
|
119
|
+
console.log(`[Tracerny] Layer 1 result: ${isSuspicious ? 'SUSPICIOUS' : 'CLEAN'}`);
|
|
120
|
+
if (isSuspicious && threat) {
|
|
121
|
+
console.log(`[Tracerny] Layer 1 flagged: ${threat.patternName}`);
|
|
122
|
+
}
|
|
123
|
+
// Layer 2: LLM Sentinel ALWAYS called (makes final decision)
|
|
124
|
+
// Even if Layer 1 is clean, Layer 2 can catch subtle attacks
|
|
125
|
+
// If Layer 1 is suspicious, Layer 2 verifies context (allows educational content)
|
|
126
|
+
console.log(`[Tracerny] Layer 2 check: sentinel=${!!this.sentinel}`);
|
|
127
|
+
if (this.sentinel) {
|
|
128
|
+
console.log('[Tracerny] Layer 2: Calling Sentinel...');
|
|
129
|
+
try {
|
|
130
|
+
const result = await this.sentinel.check(normalizedPrompt, rid);
|
|
131
|
+
console.log(`[Tracerny] Layer 2 result: blocked=${result.blocked}`);
|
|
132
|
+
if (result.blocked) {
|
|
133
|
+
// Log to shadow_log for analysis
|
|
134
|
+
// Disabled for now - will re-enable after fixing endpoint
|
|
135
|
+
// if (this.shadowLogSink) {
|
|
136
|
+
// const shadowPayload: ShadowLogPayload = {
|
|
137
|
+
// id: rid,
|
|
138
|
+
// prompt: prompt.substring(0, 500),
|
|
139
|
+
// keywords: result.keywords,
|
|
140
|
+
// verdict: 'YES', // Detected as attack by LLM
|
|
141
|
+
// latencyMs: result.latencyMs || 0,
|
|
142
|
+
// model: result.llmModel || 'unknown',
|
|
143
|
+
// timestamp: new Date().toISOString(),
|
|
144
|
+
// };
|
|
145
|
+
// this.shadowLogSink.log(shadowPayload).catch(err => {
|
|
146
|
+
// console.warn("[Tracerny] Shadow log send failed:", err);
|
|
147
|
+
// });
|
|
148
|
+
// }
|
|
149
|
+
const event = createSecurityEvent(rid, SecurityEventType.PROMPT_INJECTION, ThreatSeverity.HIGH, `LLM Sentinel detected: ${result.keywords.join(", ")} (confidence: ${result.confidence})`, {
|
|
150
|
+
patternName: "LLM Sentinel",
|
|
151
|
+
requestSnippet: prompt.substring(0, 100),
|
|
152
|
+
blockLatencyMs: (result.latencyMs || 0) + (Date.now() - startTime),
|
|
153
|
+
modelName: result.llmModel,
|
|
154
|
+
});
|
|
155
|
+
this.report(event);
|
|
156
|
+
throw new ShieldBlockError("Tracerny Block: LLM Sentinel", event);
|
|
157
|
+
}
|
|
158
|
+
// Layer 2 passed - no shadow log entry
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
// If sentinel throws (network error, etc), check if it's our block or a system error
|
|
162
|
+
if (error instanceof ShieldBlockError) {
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
// Other errors are silently caught - Layer 2 is non-blocking fallback
|
|
166
|
+
console.warn("[Tracerny] Layer 2 sentinel error:", error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Both layers passed - prompt is safe
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
// Jitter: Add random delay to obfuscate timing (always runs, masked from caller)
|
|
174
|
+
await jitter();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Update tool policy at runtime
|
|
179
|
+
*/
|
|
180
|
+
setAllowedTools(tools) {
|
|
181
|
+
const policy = createToolPolicy(tools);
|
|
182
|
+
this.toolGuard.updatePolicy(policy);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get service status for diagnostics
|
|
186
|
+
*/
|
|
187
|
+
getStatus() {
|
|
188
|
+
return {
|
|
189
|
+
patternMatcher: {
|
|
190
|
+
ready: this.patternMatcher !== null,
|
|
191
|
+
stats: this.patternMatcher?.stats(),
|
|
192
|
+
},
|
|
193
|
+
toolGuard: {
|
|
194
|
+
allowedTools: this.toolGuard.getAllowedTools(),
|
|
195
|
+
},
|
|
196
|
+
telemetry: {
|
|
197
|
+
enabled: this.telemetrySink !== undefined,
|
|
198
|
+
status: this.telemetrySink?.getStatus(),
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Report a security event (non-blocking)
|
|
204
|
+
*/
|
|
205
|
+
report(event) {
|
|
206
|
+
if (this.telemetrySink) {
|
|
207
|
+
this.telemetrySink.queue(event);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Graceful shutdown: flush telemetry, release resources
|
|
212
|
+
*/
|
|
213
|
+
destroy() {
|
|
214
|
+
this.telemetrySink?.destroy();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Generate a unique request ID
|
|
218
|
+
*/
|
|
219
|
+
generateRequestId() {
|
|
220
|
+
return `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=ShieldApplicationService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShieldApplicationService.js","sourceRoot":"","sources":["../../src/application/ShieldApplicationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShieldBlockError
|
|
3
|
+
* Application exception: thrown when a security block occurs
|
|
4
|
+
*/
|
|
5
|
+
import { SecurityEvent } from "../domain/events/SecurityEvent";
|
|
6
|
+
export declare class ShieldBlockError extends Error {
|
|
7
|
+
readonly event: SecurityEvent;
|
|
8
|
+
constructor(message: string, event: SecurityEvent);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=ShieldBlockError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShieldBlockError.d.ts","sourceRoot":"","sources":["../../src/application/ShieldBlockError.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,qBAAa,gBAAiB,SAAQ,KAAK;aAGvB,KAAK,EAAE,aAAa;gBADpC,OAAO,EAAE,MAAM,EACC,KAAK,EAAE,aAAa;CAMvC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShieldBlockError
|
|
3
|
+
* Application exception: thrown when a security block occurs
|
|
4
|
+
*/
|
|
5
|
+
export class ShieldBlockError extends Error {
|
|
6
|
+
constructor(message, event) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.event = event;
|
|
9
|
+
this.name = "ShieldBlockError";
|
|
10
|
+
Object.setPrototypeOf(this, ShieldBlockError.prototype);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=ShieldBlockError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShieldBlockError.js","sourceRoot":"","sources":["../../src/application/ShieldBlockError.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YACE,OAAe,EACC,KAAoB;QAEpC,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,UAAK,GAAL,KAAK,CAAe;QAGpC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC1D,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application Layer
|
|
3
|
+
* Barrel export
|
|
4
|
+
*/
|
|
5
|
+
export { ShieldApplicationService } from "./ShieldApplicationService";
|
|
6
|
+
export type { ShieldApplicationServiceConfig, WrapOptions, ServiceStatus } from "./ShieldApplicationService";
|
|
7
|
+
export { ShieldBlockError } from "./ShieldBlockError";
|
|
8
|
+
export * from "./ports";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EAAE,8BAA8B,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE7G,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ILLMProvider
|
|
3
|
+
* Outbound port: defines the contract for LLM calls
|
|
4
|
+
* Implemented by: OpenRouterProvider, OpenAI, Anthropic adapters, etc.
|
|
5
|
+
*/
|
|
6
|
+
export interface LLMMessage {
|
|
7
|
+
readonly role: "user" | "assistant" | "system";
|
|
8
|
+
readonly content: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LLMTool {
|
|
11
|
+
readonly type: "function";
|
|
12
|
+
readonly function: {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly description?: string;
|
|
15
|
+
readonly parameters?: Record<string, unknown>;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface ToolCall {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly function: {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly arguments?: string | Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
readonly type?: "function";
|
|
25
|
+
}
|
|
26
|
+
export interface LLMChoice {
|
|
27
|
+
readonly message: {
|
|
28
|
+
readonly content: string | null;
|
|
29
|
+
readonly role: "assistant";
|
|
30
|
+
readonly tool_calls?: readonly ToolCall[];
|
|
31
|
+
};
|
|
32
|
+
readonly finish_reason: "stop" | "tool_calls" | "length" | "content_filter" | null;
|
|
33
|
+
readonly index: number;
|
|
34
|
+
}
|
|
35
|
+
export interface TokenUsage {
|
|
36
|
+
readonly prompt_tokens: number;
|
|
37
|
+
readonly completion_tokens: number;
|
|
38
|
+
readonly total_tokens: number;
|
|
39
|
+
}
|
|
40
|
+
export interface LLMResponse {
|
|
41
|
+
readonly id?: string;
|
|
42
|
+
readonly choices: readonly LLMChoice[];
|
|
43
|
+
readonly usage?: TokenUsage;
|
|
44
|
+
readonly model?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface LLMRequest {
|
|
47
|
+
readonly messages: readonly LLMMessage[];
|
|
48
|
+
readonly model: string;
|
|
49
|
+
readonly tools?: readonly LLMTool[];
|
|
50
|
+
readonly temperature?: number;
|
|
51
|
+
readonly maxTokens?: number;
|
|
52
|
+
readonly [key: string]: unknown;
|
|
53
|
+
}
|
|
54
|
+
export declare class ProviderError extends Error {
|
|
55
|
+
readonly providerName: string;
|
|
56
|
+
readonly statusCode?: number | undefined;
|
|
57
|
+
readonly cause?: unknown | undefined;
|
|
58
|
+
constructor(message: string, providerName: string, statusCode?: number | undefined, cause?: unknown | undefined);
|
|
59
|
+
}
|
|
60
|
+
export interface ILLMProvider {
|
|
61
|
+
/**
|
|
62
|
+
* The name of this provider (for telemetry)
|
|
63
|
+
*/
|
|
64
|
+
readonly providerName: string;
|
|
65
|
+
/**
|
|
66
|
+
* Execute an LLM call
|
|
67
|
+
* Throws ProviderError on failure
|
|
68
|
+
*/
|
|
69
|
+
complete(request: LLMRequest): Promise<LLMResponse>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=ILLMProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ILLMProvider.d.ts","sourceRoot":"","sources":["../../../src/application/ports/ILLMProvider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/C,CAAC;CACH;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvD,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;KAC3C,CAAC;IACF,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,qBAAa,aAAc,SAAQ,KAAK;aAGpB,YAAY,EAAE,MAAM;aACpB,UAAU,CAAC,EAAE,MAAM;aACnB,KAAK,CAAC,EAAE,OAAO;gBAH/B,OAAO,EAAE,MAAM,EACC,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACrD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ILLMProvider
|
|
3
|
+
* Outbound port: defines the contract for LLM calls
|
|
4
|
+
* Implemented by: OpenRouterProvider, OpenAI, Anthropic adapters, etc.
|
|
5
|
+
*/
|
|
6
|
+
export class ProviderError extends Error {
|
|
7
|
+
constructor(message, providerName, statusCode, cause) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.providerName = providerName;
|
|
10
|
+
this.statusCode = statusCode;
|
|
11
|
+
this.cause = cause;
|
|
12
|
+
this.name = "ProviderError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ILLMProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ILLMProvider.js","sourceRoot":"","sources":["../../../src/application/ports/ILLMProvider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyDH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YACE,OAAe,EACC,YAAoB,EACpB,UAAmB,EACnB,KAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,iBAAY,GAAZ,YAAY,CAAQ;QACpB,eAAU,GAAV,UAAU,CAAS;QACnB,UAAK,GAAL,KAAK,CAAU;QAG/B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPatternRepository
|
|
3
|
+
* Outbound port: defines the contract for loading detection patterns
|
|
4
|
+
* Implemented by: BundledPatternRepository, RemotePatternRepository
|
|
5
|
+
*/
|
|
6
|
+
import { VanguardPattern } from "../../domain/detection/VanguardPattern";
|
|
7
|
+
export interface IPatternRepository {
|
|
8
|
+
/**
|
|
9
|
+
* Load patterns.
|
|
10
|
+
* May be synchronous (bundled) or asynchronous (remote).
|
|
11
|
+
* Returns readonly array for immutability.
|
|
12
|
+
*/
|
|
13
|
+
getPatterns(): Promise<readonly VanguardPattern[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Source identifier for diagnostics.
|
|
16
|
+
* Examples: "bundled@0.1.0", "remote:https://api.tracerney.dev/manifest.json"
|
|
17
|
+
*/
|
|
18
|
+
readonly sourceIdentifier: string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=IPatternRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPatternRepository.d.ts","sourceRoot":"","sources":["../../../src/application/ports/IPatternRepository.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,WAAW,IAAI,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAC;IAEnD;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IPatternRepository.js","sourceRoot":"","sources":["../../../src/application/ports/IPatternRepository.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ISentinel - Port for Layer 2 LLM-based attack detection
|
|
3
|
+
*
|
|
4
|
+
* Called when Layer 1 (regex) finds no match.
|
|
5
|
+
* Provides a second opinion via fast LLM model.
|
|
6
|
+
*/
|
|
7
|
+
export interface ISentinel {
|
|
8
|
+
/**
|
|
9
|
+
* Check if a prompt contains a prompt injection attack
|
|
10
|
+
* @param prompt The user input to evaluate
|
|
11
|
+
* @param requestId Optional request ID for logging
|
|
12
|
+
* @returns Result with blocked flag, confidence score, and triggered keywords
|
|
13
|
+
*/
|
|
14
|
+
check(prompt: string, requestId?: string): Promise<{
|
|
15
|
+
blocked: boolean;
|
|
16
|
+
confidence: number;
|
|
17
|
+
keywords: string[];
|
|
18
|
+
llmModel?: string;
|
|
19
|
+
latencyMs?: number;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=ISentinel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISentinel.d.ts","sourceRoot":"","sources":["../../../src/application/ports/ISentinel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,KAAK,CACH,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISentinel.js","sourceRoot":"","sources":["../../../src/application/ports/ISentinel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ITelemetrySink
|
|
3
|
+
* Outbound port: defines the contract for reporting security events
|
|
4
|
+
* Implemented by: HttpSignalSink, NoOpSink, etc.
|
|
5
|
+
*/
|
|
6
|
+
import { SecurityEvent } from "../../domain/events/SecurityEvent";
|
|
7
|
+
export interface TelemetrySinkStatus {
|
|
8
|
+
readonly enabled: boolean;
|
|
9
|
+
readonly queuedEvents: number;
|
|
10
|
+
readonly isPosting: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ITelemetrySink {
|
|
13
|
+
/**
|
|
14
|
+
* Queue a security event for async delivery.
|
|
15
|
+
* Returns immediately — never throws.
|
|
16
|
+
* Fire-and-forget pattern.
|
|
17
|
+
*/
|
|
18
|
+
queue(event: SecurityEvent): void;
|
|
19
|
+
/**
|
|
20
|
+
* Flush all queued events to the sink.
|
|
21
|
+
* Awaitable for graceful shutdown.
|
|
22
|
+
* Throws on persistent send failure (after retries).
|
|
23
|
+
*/
|
|
24
|
+
flush(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Destroy the sink and release resources.
|
|
27
|
+
* Should attempt a final flush if possible.
|
|
28
|
+
*/
|
|
29
|
+
destroy(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Get sink status (for diagnostics).
|
|
32
|
+
*/
|
|
33
|
+
getStatus(): TelemetrySinkStatus;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=ITelemetrySink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITelemetrySink.d.ts","sourceRoot":"","sources":["../../../src/application/ports/ITelemetrySink.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IAElC;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;OAGG;IACH,OAAO,IAAI,IAAI,CAAC;IAEhB;;OAEG;IACH,SAAS,IAAI,mBAAmB,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITelemetrySink.js","sourceRoot":"","sources":["../../../src/application/ports/ITelemetrySink.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application Ports
|
|
3
|
+
* Outbound port interfaces for dependency injection
|
|
4
|
+
* Barrel export
|
|
5
|
+
*/
|
|
6
|
+
export { ProviderError } from "./ILLMProvider";
|
|
7
|
+
export type { ILLMProvider, LLMRequest, LLMResponse, LLMMessage, LLMChoice, ToolCall, LLMTool, TokenUsage, } from "./ILLMProvider";
|
|
8
|
+
export type { ITelemetrySink, TelemetrySinkStatus } from "./ITelemetrySink";
|
|
9
|
+
export type { IPatternRepository } from "./IPatternRepository";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/application/ports/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,OAAO,EACP,UAAU,GACX,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|