@ai-pip/csl 0.1.1 → 0.1.4
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/package.json +10 -28
- package/src/index.test.ts +429 -0
- package/{index.ts → src/index.ts} +53 -50
- package/src/test-external.js +547 -0
- package/layers/csl/adapters/index.ts +0 -9
- package/layers/csl/adapters/input/DOMAdapter.ts +0 -236
- package/layers/csl/adapters/input/UIAdapter.ts +0 -0
- package/layers/csl/adapters/output/ConsoleLogger.ts +0 -34
- package/layers/csl/adapters/output/CryptoHashGenerator.ts +0 -29
- package/layers/csl/adapters/output/FilePolicyRepository.ts +0 -0
- package/layers/csl/adapters/output/InMemoryPolicyRepository.ts +0 -135
- package/layers/csl/adapters/output/SystemTimestampProvider.ts +0 -9
- package/layers/csl/domain/entities/CSLResult.ts +0 -309
- package/layers/csl/domain/entities/Segment.ts +0 -338
- package/layers/csl/domain/entities/index.ts +0 -2
- package/layers/csl/domain/exceptions/ClassificationError.ts +0 -26
- package/layers/csl/domain/exceptions/SegmentationError.ts +0 -30
- package/layers/csl/domain/exceptions/index.ts +0 -2
- package/layers/csl/domain/index.ts +0 -4
- package/layers/csl/domain/services/AnomalyService.ts +0 -255
- package/layers/csl/domain/services/LineageService.ts +0 -224
- package/layers/csl/domain/services/NormalizationService.ts +0 -392
- package/layers/csl/domain/services/OriginClassificationService.ts +0 -69
- package/layers/csl/domain/services/PiDetectionService.ts +0 -475
- package/layers/csl/domain/services/PolicyService.ts +0 -296
- package/layers/csl/domain/services/SegmentClassificationService.ts +0 -105
- package/layers/csl/domain/services/SerializationService.ts +0 -229
- package/layers/csl/domain/services/index.ts +0 -7
- package/layers/csl/domain/value-objects/AnomalyScore.ts +0 -23
- package/layers/csl/domain/value-objects/ContentHash.ts +0 -54
- package/layers/csl/domain/value-objects/LineageEntry.ts +0 -42
- package/layers/csl/domain/value-objects/Origin-map.ts +0 -67
- package/layers/csl/domain/value-objects/Origin.ts +0 -99
- package/layers/csl/domain/value-objects/Pattern.ts +0 -221
- package/layers/csl/domain/value-objects/PiDetection.ts +0 -140
- package/layers/csl/domain/value-objects/PiDetectionResult.ts +0 -275
- package/layers/csl/domain/value-objects/PolicyRule.ts +0 -151
- package/layers/csl/domain/value-objects/TrustLevel.ts +0 -34
- package/layers/csl/domain/value-objects/index.ts +0 -10
- package/layers/csl/index.ts +0 -3
- package/layers/csl/ports/index.ts +0 -10
- package/layers/csl/ports/input/ClassificationPort.ts +0 -76
- package/layers/csl/ports/input/SegmentationPort.ts +0 -81
- package/layers/csl/ports/output/DOMAdapter.ts +0 -14
- package/layers/csl/ports/output/HashGenerator.ts +0 -18
- package/layers/csl/ports/output/Logger.ts +0 -17
- package/layers/csl/ports/output/PolicyRepository.ts +0 -29
- package/layers/csl/ports/output/SegmentClassified.ts +0 -8
- package/layers/csl/ports/output/TimeStampProvider.ts +0 -5
- package/layers/csl/services/CSLService.ts +0 -393
- package/layers/csl/services/index.ts +0 -1
- package/layers/csl/types/entities-types.ts +0 -37
- package/layers/csl/types/index.ts +0 -4
- package/layers/csl/types/pi-types.ts +0 -111
- package/layers/csl/types/port-output-types.ts +0 -17
- package/layers/csl/types/value-objects-types.ts +0 -213
- package/layers/csl/utils/colors.ts +0 -25
- package/layers/csl/utils/pattern-helpers.ts +0 -174
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import type { Segment } from './Segment'
|
|
2
|
-
import type { LineageEntry } from '../value-objects'
|
|
3
|
-
import { TrustLevelType } from '../../types'
|
|
4
|
-
import { TrustLevel } from '../value-objects'
|
|
5
|
-
import type { CSLResultMetadata } from '../../types'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* CSLResult entity represents the complete result of the CSL (Context Segmentation Layer) processing.
|
|
10
|
-
*
|
|
11
|
-
* @remarks
|
|
12
|
-
* CSLResult is the output entity of the CSL layer. It aggregates all processed segments
|
|
13
|
-
* along with metadata about the segmentation process. This entity is required as input
|
|
14
|
-
* for the ISL (Instruction Sanitization Layer), which is the next layer in the AI-PIP pipeline.
|
|
15
|
-
*
|
|
16
|
-
* **Purpose:**
|
|
17
|
-
* - Aggregates all segments processed by CSL
|
|
18
|
-
* - Provides metadata for analysis and auditing
|
|
19
|
-
* - Maintains complete lineage for traceability
|
|
20
|
-
* - Serves as input for downstream layers (ISL, CPE, AAL)
|
|
21
|
-
*
|
|
22
|
-
* **Usage Flow:**
|
|
23
|
-
* 1. CSL processes DOM/user input → creates Segment[]
|
|
24
|
-
* 2. Segments are analyzed and classified
|
|
25
|
-
* 3. CSLResult aggregates all segments with metadata
|
|
26
|
-
* 4. CSLResult is passed to ISL layer for further processing
|
|
27
|
-
*
|
|
28
|
-
* @property segments - Array of all processed segments with their classifications and scores
|
|
29
|
-
* @property metadata - Aggregated statistics about the segmentation process
|
|
30
|
-
* @property lineage - Complete lineage entries tracking the processing history
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```typescript
|
|
34
|
-
* // After CSL processing - all metadata is calculated automatically
|
|
35
|
-
* const cslResult = new CSLResult({
|
|
36
|
-
* segments: processedSegments, // Each segment has trustLevel and anomalyScore assigned
|
|
37
|
-
* metadata: {
|
|
38
|
-
* // trust_distribution is calculated automatically from segments' TrustLevel values
|
|
39
|
-
* // total_segments is calculated automatically from segments.length
|
|
40
|
-
* // anomaly_score is calculated automatically as average of segments' AnomalyScore.score
|
|
41
|
-
* blocked_segments: ['seg-003'],
|
|
42
|
-
* processing_time_ms: 150
|
|
43
|
-
* },
|
|
44
|
-
* lineage: allLineageEntries
|
|
45
|
-
* })
|
|
46
|
-
*
|
|
47
|
-
* // Access calculated values
|
|
48
|
-
* console.log(`Total segments: ${cslResult.metadata.total_segments}`)
|
|
49
|
-
* console.log(`Average anomaly score: ${cslResult.metadata.anomaly_score}`)
|
|
50
|
-
* console.log(`TC: ${cslResult.metadata.trust_distribution.TC}`)
|
|
51
|
-
* console.log(`STC: ${cslResult.metadata.trust_distribution.STC}`)
|
|
52
|
-
* console.log(`UC: ${cslResult.metadata.trust_distribution.UC}`)
|
|
53
|
-
*
|
|
54
|
-
* // Pass to ISL layer
|
|
55
|
-
* const islResult = islLayer.process(cslResult)
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export class CSLResult {
|
|
59
|
-
readonly segments: readonly Segment[]
|
|
60
|
-
readonly metadata: CSLResultMetadata
|
|
61
|
-
readonly lineage: readonly LineageEntry[]
|
|
62
|
-
|
|
63
|
-
constructor(props: {
|
|
64
|
-
segments: Segment[]
|
|
65
|
-
metadata: Omit<CSLResultMetadata, 'trust_distribution' | 'total_segments' | 'anomaly_score'> & {
|
|
66
|
-
trust_distribution?: CSLResultMetadata['trust_distribution']
|
|
67
|
-
}
|
|
68
|
-
lineage: LineageEntry[]
|
|
69
|
-
}) {
|
|
70
|
-
if (!Array.isArray(props.segments)) {
|
|
71
|
-
throw new TypeError('CSLResult segments must be an array')
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!props.metadata || typeof props.metadata !== 'object') {
|
|
75
|
-
throw new Error('CSLResult metadata must be an object')
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (!Array.isArray(props.lineage)) {
|
|
79
|
-
throw new TypeError('CSLResult lineage must be an array')
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.segments = Object.freeze([...props.segments])
|
|
83
|
-
|
|
84
|
-
// Calculate trust_distribution from segments' TrustLevel values
|
|
85
|
-
const trustDistribution = this.calculateTrustDistribution(props.segments)
|
|
86
|
-
|
|
87
|
-
// Validate or use provided trust_distribution
|
|
88
|
-
if (props.metadata.trust_distribution) {
|
|
89
|
-
const provided = props.metadata.trust_distribution
|
|
90
|
-
if (
|
|
91
|
-
provided.TC !== trustDistribution.TC ||
|
|
92
|
-
provided.STC !== trustDistribution.STC ||
|
|
93
|
-
provided.UC !== trustDistribution.UC
|
|
94
|
-
) {
|
|
95
|
-
throw new Error(
|
|
96
|
-
`CSLResult trust_distribution mismatch. Expected ${JSON.stringify(trustDistribution)}, got ${JSON.stringify(provided)}`
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Calculate total_segments automatically from segments.length
|
|
102
|
-
const totalSegments = props.segments.length
|
|
103
|
-
|
|
104
|
-
// Calculate average anomaly_score from segments' AnomalyScore values
|
|
105
|
-
const averageAnomalyScore = this.calculateAverageAnomalyScore(props.segments)
|
|
106
|
-
|
|
107
|
-
this.metadata = Object.freeze({
|
|
108
|
-
...props.metadata,
|
|
109
|
-
total_segments: totalSegments,
|
|
110
|
-
trust_distribution: trustDistribution,
|
|
111
|
-
anomaly_score: averageAnomalyScore
|
|
112
|
-
})
|
|
113
|
-
this.lineage = Object.freeze([...props.lineage])
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Calculates trust distribution from segments' TrustLevel values
|
|
118
|
-
*
|
|
119
|
-
* @param segments - Array of segments to analyze
|
|
120
|
-
* @returns Trust distribution object with counts for TC, STC, and UC
|
|
121
|
-
*
|
|
122
|
-
* @private
|
|
123
|
-
*/
|
|
124
|
-
private calculateTrustDistribution(segments: Segment[]): {
|
|
125
|
-
TC: number
|
|
126
|
-
STC: number
|
|
127
|
-
UC: number
|
|
128
|
-
} {
|
|
129
|
-
const distribution = {
|
|
130
|
-
TC: 0,
|
|
131
|
-
STC: 0,
|
|
132
|
-
UC: 0
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
for (const segment of segments) {
|
|
136
|
-
if (!segment.trustLevel) {
|
|
137
|
-
// If segment doesn't have trustLevel assigned, count as UC (untrusted)
|
|
138
|
-
distribution.UC++
|
|
139
|
-
continue
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const trustLevel = segment.trustLevel.value
|
|
143
|
-
if (trustLevel === TrustLevelType.TC) {
|
|
144
|
-
distribution.TC++
|
|
145
|
-
} else if (trustLevel === TrustLevelType.STC) {
|
|
146
|
-
distribution.STC++
|
|
147
|
-
} else if (trustLevel === TrustLevelType.UC) {
|
|
148
|
-
distribution.UC++
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return distribution
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Calculates the average anomaly score across all segments
|
|
157
|
-
*
|
|
158
|
-
* @remarks
|
|
159
|
-
* Formula: sum(segment.anomalyScore.score) / total_segments
|
|
160
|
-
* If a segment doesn't have anomalyScore, it counts as 0
|
|
161
|
-
*
|
|
162
|
-
* @param segments - Array of segments to analyze
|
|
163
|
-
* @returns Average anomaly score (0-1)
|
|
164
|
-
*
|
|
165
|
-
* @private
|
|
166
|
-
*/
|
|
167
|
-
private calculateAverageAnomalyScore(segments: Segment[]): number {
|
|
168
|
-
if (segments.length === 0) {
|
|
169
|
-
return 0
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
let totalScore = 0
|
|
173
|
-
for (const segment of segments) {
|
|
174
|
-
if (segment.anomalyScore) {
|
|
175
|
-
totalScore += segment.anomalyScore.score
|
|
176
|
-
}
|
|
177
|
-
// If segment doesn't have anomalyScore, it contributes 0 to the sum
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return totalScore / segments.length
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Returns the number of segments that should be blocked
|
|
185
|
-
*
|
|
186
|
-
* @returns Number of blocked segments
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* ```typescript
|
|
190
|
-
* const blockedCount = cslResult.getBlockedCount()
|
|
191
|
-
* if (blockedCount > 0) {
|
|
192
|
-
* console.warn(`${blockedCount} segments were blocked`)
|
|
193
|
-
* }
|
|
194
|
-
* ```
|
|
195
|
-
*/
|
|
196
|
-
getBlockedCount(): number {
|
|
197
|
-
return this.metadata.blocked_segments.length
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Returns the number of trusted (TC) segments
|
|
202
|
-
*
|
|
203
|
-
* @returns Number of TC segments
|
|
204
|
-
*
|
|
205
|
-
* @example
|
|
206
|
-
* ```typescript
|
|
207
|
-
* const trustedCount = cslResult.getTrustedCount()
|
|
208
|
-
* console.log(`${trustedCount} segments are fully trusted`)
|
|
209
|
-
* ```
|
|
210
|
-
*/
|
|
211
|
-
getTrustedCount(): number {
|
|
212
|
-
return this.metadata.trust_distribution.TC
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Returns true if any segments were blocked
|
|
217
|
-
*
|
|
218
|
-
* @returns true if there are blocked segments, false otherwise
|
|
219
|
-
*
|
|
220
|
-
* @example
|
|
221
|
-
* ```typescript
|
|
222
|
-
* if (cslResult.hasBlockedSegments()) {
|
|
223
|
-
* // Handle security concerns
|
|
224
|
-
* }
|
|
225
|
-
* ```
|
|
226
|
-
*/
|
|
227
|
-
hasBlockedSegments(): boolean {
|
|
228
|
-
return this.metadata.blocked_segments.length > 0
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Returns the average anomaly score across all segments
|
|
233
|
-
*
|
|
234
|
-
* @returns Average anomaly score (0-1)
|
|
235
|
-
*
|
|
236
|
-
* @example
|
|
237
|
-
* ```typescript
|
|
238
|
-
* const avgScore = cslResult.getAverageAnomalyScore()
|
|
239
|
-
* if (avgScore > 0.7) {
|
|
240
|
-
* console.warn('High average anomaly score detected')
|
|
241
|
-
* }
|
|
242
|
-
* ```
|
|
243
|
-
*/
|
|
244
|
-
getAverageAnomalyScore(): number {
|
|
245
|
-
return this.metadata.anomaly_score
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Returns the processing time in milliseconds
|
|
250
|
-
*
|
|
251
|
-
* @returns Processing time in milliseconds
|
|
252
|
-
*
|
|
253
|
-
* @example
|
|
254
|
-
* ```typescript
|
|
255
|
-
* const processingTime = cslResult.getProcessingTime()
|
|
256
|
-
* console.log(`CSL processing took ${processingTime}ms`)
|
|
257
|
-
* ```
|
|
258
|
-
*/
|
|
259
|
-
getProcessingTime(): number {
|
|
260
|
-
return this.metadata.processing_time_ms
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Returns all segments that match the specified trust level
|
|
265
|
-
*
|
|
266
|
-
* @remarks
|
|
267
|
-
* This method is particularly useful for:
|
|
268
|
-
* - **ISL Layer**: Process only trusted (TC) or semi-trusted (STC) segments
|
|
269
|
-
* - **CPE Layer**: Apply different cryptographic protections based on trust level
|
|
270
|
-
* - **Auditing**: Generate reports filtered by trust level
|
|
271
|
-
* - **Logging**: Log segments by trust level for debugging
|
|
272
|
-
* - **Debugging**: Inspect segments of a specific trust level
|
|
273
|
-
*
|
|
274
|
-
* @param level - The trust level to filter by (TC, STC, or UC)
|
|
275
|
-
* @returns Array of segments that have the specified trust level
|
|
276
|
-
*
|
|
277
|
-
* @example
|
|
278
|
-
* ```typescript
|
|
279
|
-
* // Get only trusted segments for ISL processing
|
|
280
|
-
* const trustedSegments = cslResult.getSegmentsByTrustLevel(TrustLevelType.TC)
|
|
281
|
-
* const islResult = islLayer.process(trustedSegments)
|
|
282
|
-
*
|
|
283
|
-
* // Get untrusted segments for auditing
|
|
284
|
-
* const untrustedSegments = cslResult.getSegmentsByTrustLevel(TrustLevelType.UC)
|
|
285
|
-
* console.log(`Found ${untrustedSegments.length} untrusted segments`)
|
|
286
|
-
*
|
|
287
|
-
* // Log segments by trust level for debugging
|
|
288
|
-
* for (const level of [TrustLevelType.TC, TrustLevelType.STC, TrustLevelType.UC]) {
|
|
289
|
-
* const segments = cslResult.getSegmentsByTrustLevel(level)
|
|
290
|
-
* console.log(`${level}: ${segments.length} segments`)
|
|
291
|
-
* }
|
|
292
|
-
*
|
|
293
|
-
* // CPE layer: Apply different protections based on trust level
|
|
294
|
-
* const semiTrustedSegments = cslResult.getSegmentsByTrustLevel(TrustLevelType.STC)
|
|
295
|
-
* for (const segment of semiTrustedSegments) {
|
|
296
|
-
* // Apply additional validation
|
|
297
|
-
* }
|
|
298
|
-
* ```
|
|
299
|
-
*/
|
|
300
|
-
getSegmentsByTrustLevel(level: TrustLevelType): readonly Segment[] {
|
|
301
|
-
return this.segments.filter(segment => {
|
|
302
|
-
if (!segment.trustLevel) {
|
|
303
|
-
// Segments without trustLevel are considered UC (untrusted)
|
|
304
|
-
return level === TrustLevelType.UC
|
|
305
|
-
}
|
|
306
|
-
return segment.trustLevel.value === level
|
|
307
|
-
})
|
|
308
|
-
}
|
|
309
|
-
}
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Origin,
|
|
3
|
-
TrustLevel,
|
|
4
|
-
AnomalyScore,
|
|
5
|
-
ContentHash,
|
|
6
|
-
PiDetectionResult,
|
|
7
|
-
} from "../value-objects"
|
|
8
|
-
|
|
9
|
-
import type { LineageEntry } from "../value-objects"
|
|
10
|
-
import type { SegmentMetadata } from "../../types"
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Segment entity represents a content segment extracted from the DOM or user input.
|
|
14
|
-
*
|
|
15
|
-
* @remarks
|
|
16
|
-
* A Segment is the core entity in the CSL layer. It represents a piece of content
|
|
17
|
-
* that goes through the processing pipeline. The segment starts with basic information
|
|
18
|
-
* (origin, content, mime type) and accumulates additional metadata as it's processed:
|
|
19
|
-
* trust level, hash, anomaly scores, prompt injection detection results, and lineage.
|
|
20
|
-
*
|
|
21
|
-
* **Lifecycle:**
|
|
22
|
-
* 1. Created with basic properties (id, origin, content, mime, timestamp, source)
|
|
23
|
-
* 2. Trust level is assigned by OriginClassificationService
|
|
24
|
-
* 3. Hash is generated by HashGenerator
|
|
25
|
-
* 4. Prompt injection detection is performed by PiDetectionService
|
|
26
|
-
* 5. Anomaly score is calculated by AnomalyService
|
|
27
|
-
* 6. Lineage entries are added by LineageService
|
|
28
|
-
*
|
|
29
|
-
* @property id - Unique identifier for this segment
|
|
30
|
-
* @property origin - Origin of the content (user input, DOM visible, DOM hidden, etc.)
|
|
31
|
-
* @property content - The actual text content of the segment
|
|
32
|
-
* @property mime - MIME type of the content (e.g., 'text/plain', 'text/html')
|
|
33
|
-
* @property timestamp - Unix timestamp in milliseconds when the segment was created
|
|
34
|
-
* @property source - Source identifier (e.g., DOM element ID, input field name)
|
|
35
|
-
* @property metadata - Optional metadata about the segment (DOM path, visibility, etc.)
|
|
36
|
-
* @property trustLevel - Trust level assigned during classification (TC, STC, UC) - assigned after creation
|
|
37
|
-
* @property hash - Cryptographic hash of the content - generated after creation
|
|
38
|
-
* @property anomalyScore - Risk score and action recommendation - calculated after creation
|
|
39
|
-
* @property piDetection - Prompt injection detection results - detected after creation
|
|
40
|
-
* @property lineage - Array of lineage entries tracking the processing history - added during processing
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* // Create a segment from user input
|
|
45
|
-
* const segment = new Segment({
|
|
46
|
-
* id: 'seg-123',
|
|
47
|
-
* origin: new Origin(OriginType.USER_INPUT),
|
|
48
|
-
* content: 'Hello, how can I help you?',
|
|
49
|
-
* mime: 'text/plain',
|
|
50
|
-
* timestamp: Date.now(),
|
|
51
|
-
* source: 'user-input-field',
|
|
52
|
-
* metadata: { isVisible: true }
|
|
53
|
-
* })
|
|
54
|
-
*
|
|
55
|
-
* // After processing pipeline - use protected setters
|
|
56
|
-
* segment.assignTrustLevel(new TrustLevel(TrustLevelType.TC))
|
|
57
|
-
* segment.assignHash(new ContentHash('abc123...', 'sha256'))
|
|
58
|
-
* segment.assignPiDetection(new PiDetectionResult(0.1, [], 'ALLOW'))
|
|
59
|
-
* segment.assignAnomalyScore(new AnomalyScore(0.2, 'ALLOW'))
|
|
60
|
-
* segment.addLineageEntry(new LineageEntry('classification', Date.now(), 'Classified as TC'))
|
|
61
|
-
*
|
|
62
|
-
* // Check if segment should be blocked
|
|
63
|
-
* if (segment.shouldBlock()) {
|
|
64
|
-
* // Handle blocking logic
|
|
65
|
-
* }
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
|
|
69
|
-
export class Segment {
|
|
70
|
-
|
|
71
|
-
readonly id: string;
|
|
72
|
-
|
|
73
|
-
// Immutable state
|
|
74
|
-
readonly origin: Origin;
|
|
75
|
-
readonly content: string;
|
|
76
|
-
readonly mime: string;
|
|
77
|
-
readonly timestamp: number;
|
|
78
|
-
readonly source: string;
|
|
79
|
-
readonly metadata?: SegmentMetadata | undefined;
|
|
80
|
-
|
|
81
|
-
// Mutable state (assigned during processing pipeline)
|
|
82
|
-
private _trustLevel?: TrustLevel;
|
|
83
|
-
private _hash?: ContentHash;
|
|
84
|
-
private _anomalyScore?: AnomalyScore;
|
|
85
|
-
private _piDetection?: PiDetectionResult;
|
|
86
|
-
private _lineage?: LineageEntry[];
|
|
87
|
-
|
|
88
|
-
constructor(props: {
|
|
89
|
-
id: string;
|
|
90
|
-
origin: Origin
|
|
91
|
-
content: string
|
|
92
|
-
mime: string
|
|
93
|
-
timestamp: number
|
|
94
|
-
source: string
|
|
95
|
-
metadata?: SegmentMetadata | undefined
|
|
96
|
-
|
|
97
|
-
}) {
|
|
98
|
-
if (!props.id || typeof props.id !== 'string' || props.id.trim().length === 0) {
|
|
99
|
-
throw new TypeError('Segment id must be a non-empty string')
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (!props.content || typeof props.content !== 'string') {
|
|
103
|
-
throw new TypeError('Segment content must be a non-empty string')
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (!props.mime || typeof props.mime !== 'string' || props.mime.trim().length === 0) {
|
|
107
|
-
throw new TypeError('Segment mime must be a non-empty string')
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (typeof props.timestamp !== 'number' || props.timestamp < 0 || !Number.isFinite(props.timestamp)) {
|
|
111
|
-
throw new TypeError('Segment timestamp must be a valid positive number')
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (!props.source || typeof props.source !== 'string' || props.source.trim().length === 0) {
|
|
115
|
-
throw new TypeError('Segment source must be a non-empty string')
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
this.id = props.id.trim()
|
|
119
|
-
this.origin = props.origin
|
|
120
|
-
this.content = props.content
|
|
121
|
-
this.mime = props.mime.trim()
|
|
122
|
-
this.timestamp = props.timestamp
|
|
123
|
-
this.source = props.source.trim()
|
|
124
|
-
this.metadata = props.metadata
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Gets the trust level assigned to this segment
|
|
129
|
-
*
|
|
130
|
-
* @returns The trust level if assigned, undefined otherwise
|
|
131
|
-
*/
|
|
132
|
-
get trustLevel(): TrustLevel | undefined {
|
|
133
|
-
return this._trustLevel
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Gets the cryptographic hash of this segment
|
|
138
|
-
*
|
|
139
|
-
* @returns The content hash if generated, undefined otherwise
|
|
140
|
-
*/
|
|
141
|
-
get hash(): ContentHash | undefined {
|
|
142
|
-
return this._hash
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Gets the anomaly score calculated for this segment
|
|
147
|
-
*
|
|
148
|
-
* @returns The anomaly score if calculated, undefined otherwise
|
|
149
|
-
*/
|
|
150
|
-
get anomalyScore(): AnomalyScore | undefined {
|
|
151
|
-
return this._anomalyScore
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Gets the prompt injection detection results
|
|
156
|
-
*
|
|
157
|
-
* @returns The PI detection result if detected, undefined otherwise
|
|
158
|
-
*/
|
|
159
|
-
get piDetection(): PiDetectionResult | undefined {
|
|
160
|
-
return this._piDetection
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Gets the lineage entries for this segment
|
|
165
|
-
*
|
|
166
|
-
* @returns The lineage entries if any, undefined otherwise
|
|
167
|
-
*/
|
|
168
|
-
get lineage(): LineageEntry[] | undefined {
|
|
169
|
-
return this._lineage ? [...this._lineage] : undefined
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Assigns a trust level to this segment
|
|
174
|
-
*
|
|
175
|
-
* @remarks
|
|
176
|
-
* This method can only be called once. Subsequent calls will throw an error.
|
|
177
|
-
* Typically called by OriginClassificationService during the processing pipeline.
|
|
178
|
-
*
|
|
179
|
-
* @param trustLevel - The trust level to assign
|
|
180
|
-
* @throws Error if trust level has already been assigned
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* ```typescript
|
|
184
|
-
* segment.assignTrustLevel(new TrustLevel(TrustLevelType.TC))
|
|
185
|
-
* ```
|
|
186
|
-
*/
|
|
187
|
-
assignTrustLevel(trustLevel: TrustLevel): void {
|
|
188
|
-
if (this._trustLevel !== undefined) {
|
|
189
|
-
throw new Error('TrustLevel has already been assigned to this segment')
|
|
190
|
-
}
|
|
191
|
-
this._trustLevel = trustLevel
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Assigns a cryptographic hash to this segment
|
|
196
|
-
*
|
|
197
|
-
* @remarks
|
|
198
|
-
* This method can only be called once. Subsequent calls will throw an error.
|
|
199
|
-
* Typically called by HashGenerator during the processing pipeline.
|
|
200
|
-
*
|
|
201
|
-
* @param hash - The content hash to assign
|
|
202
|
-
* @throws Error if hash has already been assigned
|
|
203
|
-
*
|
|
204
|
-
* @example
|
|
205
|
-
* ```typescript
|
|
206
|
-
* segment.assignHash(new ContentHash('abc123...', 'sha256'))
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
assignHash(hash: ContentHash): void {
|
|
210
|
-
if (this._hash !== undefined) {
|
|
211
|
-
throw new Error('ContentHash has already been assigned to this segment')
|
|
212
|
-
}
|
|
213
|
-
this._hash = hash
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Assigns an anomaly score to this segment
|
|
218
|
-
*
|
|
219
|
-
* @remarks
|
|
220
|
-
* This method can only be called once. Subsequent calls will throw an error.
|
|
221
|
-
* Typically called by AnomalyService during the processing pipeline.
|
|
222
|
-
*
|
|
223
|
-
* @param anomalyScore - The anomaly score to assign
|
|
224
|
-
* @throws Error if anomaly score has already been assigned
|
|
225
|
-
*
|
|
226
|
-
* @example
|
|
227
|
-
* ```typescript
|
|
228
|
-
* segment.assignAnomalyScore(new AnomalyScore(0.5, 'WARN'))
|
|
229
|
-
* ```
|
|
230
|
-
*/
|
|
231
|
-
assignAnomalyScore(anomalyScore: AnomalyScore): void {
|
|
232
|
-
if (this._anomalyScore !== undefined) {
|
|
233
|
-
throw new Error('AnomalyScore has already been assigned to this segment')
|
|
234
|
-
}
|
|
235
|
-
this._anomalyScore = anomalyScore
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Assigns prompt injection detection results to this segment
|
|
240
|
-
*
|
|
241
|
-
* @remarks
|
|
242
|
-
* This method can only be called once. Subsequent calls will throw an error.
|
|
243
|
-
* Typically called by PiDetectionService during the processing pipeline.
|
|
244
|
-
*
|
|
245
|
-
* @param piDetection - The PI detection result to assign
|
|
246
|
-
* @throws Error if PI detection has already been assigned
|
|
247
|
-
*
|
|
248
|
-
* @example
|
|
249
|
-
* ```typescript
|
|
250
|
-
* segment.assignPiDetection(new PiDetectionResult(0.95, ['role_swapping'], 'BLOCK'))
|
|
251
|
-
* ```
|
|
252
|
-
*/
|
|
253
|
-
assignPiDetection(piDetection: PiDetectionResult): void {
|
|
254
|
-
if (this._piDetection !== undefined) {
|
|
255
|
-
throw new Error('PiDetectionResult has already been assigned to this segment')
|
|
256
|
-
}
|
|
257
|
-
this._piDetection = piDetection
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Adds a lineage entry to this segment
|
|
262
|
-
*
|
|
263
|
-
* @remarks
|
|
264
|
-
* Unlike other assignment methods, this allows multiple entries to be added.
|
|
265
|
-
* Typically called by LineageService during the processing pipeline.
|
|
266
|
-
*
|
|
267
|
-
* @param entry - The lineage entry to add
|
|
268
|
-
*
|
|
269
|
-
* @example
|
|
270
|
-
* ```typescript
|
|
271
|
-
* segment.addLineageEntry(new LineageEntry('normalization', Date.now(), 'Unicode normalization applied'))
|
|
272
|
-
* segment.addLineageEntry(new LineageEntry('classification', Date.now(), 'Classified as TC'))
|
|
273
|
-
* ```
|
|
274
|
-
*/
|
|
275
|
-
addLineageEntry(entry: LineageEntry): void {
|
|
276
|
-
this._lineage = [... (this._lineage ?? []), entry]
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Returns true if the segment has a trusted content level (TC)
|
|
281
|
-
*
|
|
282
|
-
* @returns true if trustLevel is TC, false otherwise
|
|
283
|
-
*
|
|
284
|
-
* @example
|
|
285
|
-
* ```typescript
|
|
286
|
-
* if (segment.isTrusted()) {
|
|
287
|
-
* // Process trusted content
|
|
288
|
-
* }
|
|
289
|
-
* ```
|
|
290
|
-
*/
|
|
291
|
-
isTrusted(): boolean {
|
|
292
|
-
return this._trustLevel?.isTrusted() ?? false
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Returns true if prompt injection patterns were detected in this segment
|
|
297
|
-
*
|
|
298
|
-
* @returns true if piDetection has detected patterns, false otherwise
|
|
299
|
-
*
|
|
300
|
-
* @example
|
|
301
|
-
* ```typescript
|
|
302
|
-
* if (segment.hasDetections()) {
|
|
303
|
-
* console.log('Prompt injection detected!')
|
|
304
|
-
* }
|
|
305
|
-
* ```
|
|
306
|
-
*/
|
|
307
|
-
hasDetections(): boolean {
|
|
308
|
-
return this._piDetection?.hasDetections() ?? false
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Determines if this segment should be blocked based on security analysis.
|
|
313
|
-
*
|
|
314
|
-
* @remarks
|
|
315
|
-
* Priority order:
|
|
316
|
-
* 1. Prompt injection detection (piDetection) - highest priority
|
|
317
|
-
* 2. Anomaly score (anomalyScore) - secondary check
|
|
318
|
-
*
|
|
319
|
-
* A segment is blocked if:
|
|
320
|
-
* - Prompt injection is detected with BLOCK action, OR
|
|
321
|
-
* - Anomaly score indicates high risk (BLOCK action)
|
|
322
|
-
*
|
|
323
|
-
* @returns true if the segment should be blocked, false otherwise
|
|
324
|
-
*
|
|
325
|
-
* @example
|
|
326
|
-
* ```typescript
|
|
327
|
-
* if (segment.shouldBlock()) {
|
|
328
|
-
* throw new SecurityError('Segment blocked due to security concerns')
|
|
329
|
-
* }
|
|
330
|
-
* ```
|
|
331
|
-
*/
|
|
332
|
-
shouldBlock(): boolean {
|
|
333
|
-
if (this._piDetection?.shouldBlock()) return true
|
|
334
|
-
if (this._anomalyScore?.isHighRisk()) return true
|
|
335
|
-
return false
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ClassificationError is thrown when classification fails.
|
|
3
|
-
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* This error is thrown by OriginClassificationService when:
|
|
6
|
-
* - An origin type is not mapped in originMap
|
|
7
|
-
* - Classification cannot be determined
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* try {
|
|
12
|
-
* const trustLevel = OriginClassificationService.classify(origin)
|
|
13
|
-
* } catch (error) {
|
|
14
|
-
* if (error instanceof ClassificationError) {
|
|
15
|
-
* // Handle classification error
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
export class ClassificationError extends Error {
|
|
21
|
-
constructor(message: string) {
|
|
22
|
-
super(message);
|
|
23
|
-
this.name = 'ClassificationError';
|
|
24
|
-
Object.setPrototypeOf(this, ClassificationError.prototype);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SegmentationError is thrown when the segmentation process fails.
|
|
3
|
-
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* This error is thrown by CSLService when:
|
|
6
|
-
* - DOM adaptation fails
|
|
7
|
-
* - Segment processing fails
|
|
8
|
-
* - Critical pipeline steps fail
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* try {
|
|
13
|
-
* const result = await cslService.segment(document.body)
|
|
14
|
-
* } catch (error) {
|
|
15
|
-
* if (error instanceof SegmentationError) {
|
|
16
|
-
* console.error('Segmentation failed:', error.message)
|
|
17
|
-
* }
|
|
18
|
-
* }
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export class SegmentationError extends Error {
|
|
22
|
-
constructor(
|
|
23
|
-
message: string,
|
|
24
|
-
public readonly cause?: unknown
|
|
25
|
-
) {
|
|
26
|
-
super(message)
|
|
27
|
-
this.name = 'SegmentationError'
|
|
28
|
-
Object.setPrototypeOf(this, SegmentationError.prototype)
|
|
29
|
-
}
|
|
30
|
-
}
|