@ai-pip/core 0.1.4 → 0.1.5
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 +91 -30
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
- package/src/cpe/envelope.ts +0 -115
- package/src/cpe/exceptions/EnvelopeError.ts +0 -11
- package/src/cpe/exceptions/index.ts +0 -6
- package/src/cpe/index.ts +0 -44
- package/src/cpe/types.ts +0 -68
- package/src/cpe/utils.ts +0 -65
- package/src/cpe/value-objects/Metadata.ts +0 -78
- package/src/cpe/value-objects/Nonce.ts +0 -57
- package/src/cpe/value-objects/Signature.ts +0 -83
- package/src/cpe/value-objects/index.ts +0 -10
- package/src/csl/classify.ts +0 -77
- package/src/csl/exceptions/ClassificationError.ts +0 -16
- package/src/csl/exceptions/SegmentationError.ts +0 -19
- package/src/csl/exceptions/index.ts +0 -3
- package/src/csl/index.ts +0 -55
- package/src/csl/lineage.ts +0 -40
- package/src/csl/segment.ts +0 -100
- package/src/csl/types.ts +0 -113
- package/src/csl/utils.ts +0 -30
- package/src/csl/value-objects/ContentHash.ts +0 -48
- package/src/csl/value-objects/LineageEntry.ts +0 -33
- package/src/csl/value-objects/Origin-map.ts +0 -51
- package/src/csl/value-objects/Origin.ts +0 -52
- package/src/csl/value-objects/TrustLevel.ts +0 -33
- package/src/csl/value-objects/index.ts +0 -14
- package/src/index.ts +0 -94
- package/src/isl/exceptions/SanitizationError.ts +0 -14
- package/src/isl/exceptions/index.ts +0 -2
- package/src/isl/index.ts +0 -53
- package/src/isl/sanitize.ts +0 -93
- package/src/isl/types.ts +0 -87
- package/src/isl/value-objects/AnomalyScore.ts +0 -40
- package/src/isl/value-objects/Pattern.ts +0 -158
- package/src/isl/value-objects/PiDetection.ts +0 -92
- package/src/isl/value-objects/PiDetectionResult.ts +0 -129
- package/src/isl/value-objects/PolicyRule.ts +0 -117
- package/src/isl/value-objects/index.ts +0 -41
- package/src/shared/index.ts +0 -18
- package/src/shared/lineage.ts +0 -53
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Nonce - Valor único para prevenir ataques de replay
|
|
3
|
-
* Value Object puro e inmutable
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { randomBytes } from 'node:crypto'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Nonce - Valor único generado aleatoriamente
|
|
10
|
-
*/
|
|
11
|
-
export type Nonce = {
|
|
12
|
-
readonly value: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Genera un nonce único
|
|
17
|
-
*
|
|
18
|
-
* @param length - Longitud del nonce en bytes (default: 16)
|
|
19
|
-
* @returns Nonce único
|
|
20
|
-
*/
|
|
21
|
-
export function createNonce(length: number = 16): Nonce {
|
|
22
|
-
if (length < 8) {
|
|
23
|
-
throw new Error('Nonce length must be at least 8 bytes')
|
|
24
|
-
}
|
|
25
|
-
if (length > 64) {
|
|
26
|
-
throw new Error('Nonce length must be at most 64 bytes')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const bytes = randomBytes(length)
|
|
30
|
-
const value = bytes.toString('hex')
|
|
31
|
-
|
|
32
|
-
return Object.freeze({
|
|
33
|
-
value,
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Valida que un string sea un nonce válido
|
|
39
|
-
*
|
|
40
|
-
* @param value - String a validar
|
|
41
|
-
* @returns true si es un nonce válido
|
|
42
|
-
*/
|
|
43
|
-
export function isValidNonce(value: string): boolean {
|
|
44
|
-
return /^[a-f0-9]{16,128}$/i.test(value)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Compara dos nonces
|
|
49
|
-
*
|
|
50
|
-
* @param nonce1 - Primer nonce
|
|
51
|
-
* @param nonce2 - Segundo nonce
|
|
52
|
-
* @returns true si son iguales
|
|
53
|
-
*/
|
|
54
|
-
export function equalsNonce(nonce1: Nonce, nonce2: Nonce): boolean {
|
|
55
|
-
return nonce1.value === nonce2.value
|
|
56
|
-
}
|
|
57
|
-
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Signature - Firma criptográfica HMAC-SHA256
|
|
3
|
-
* Value Object puro e inmutable
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { createHmac } from 'node:crypto'
|
|
7
|
-
import type { SignatureAlgorithm } from '../types'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Signature - Firma criptográfica
|
|
11
|
-
*/
|
|
12
|
-
export type SignatureVO = {
|
|
13
|
-
readonly value: string
|
|
14
|
-
readonly algorithm: SignatureAlgorithm
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Genera una firma HMAC-SHA256 del contenido
|
|
19
|
-
*
|
|
20
|
-
* @param content - Contenido a firmar
|
|
21
|
-
* @param secretKey - Clave secreta para HMAC
|
|
22
|
-
* @returns Signature inmutable
|
|
23
|
-
*
|
|
24
|
-
* @throws {Error} Si la clave secreta está vacía
|
|
25
|
-
*/
|
|
26
|
-
export function createSignature(
|
|
27
|
-
content: string,
|
|
28
|
-
secretKey: string
|
|
29
|
-
): SignatureVO {
|
|
30
|
-
if (!secretKey || secretKey.length === 0) {
|
|
31
|
-
throw new Error('Secret key is required for signature generation')
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (typeof content !== 'string') {
|
|
35
|
-
throw new TypeError('Content must be a string')
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const hmac = createHmac('sha256', secretKey)
|
|
39
|
-
hmac.update(content)
|
|
40
|
-
const signature = hmac.digest('hex')
|
|
41
|
-
|
|
42
|
-
return Object.freeze({
|
|
43
|
-
value: signature,
|
|
44
|
-
algorithm: 'HMAC-SHA256',
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Verifica una firma HMAC-SHA256
|
|
50
|
-
*
|
|
51
|
-
* @param content - Contenido original
|
|
52
|
-
* @param signature - Firma a verificar
|
|
53
|
-
* @param secretKey - Clave secreta para HMAC
|
|
54
|
-
* @returns true si la firma es válida
|
|
55
|
-
*/
|
|
56
|
-
export function verifySignature(
|
|
57
|
-
content: string,
|
|
58
|
-
signature: string,
|
|
59
|
-
secretKey: string
|
|
60
|
-
): boolean {
|
|
61
|
-
if (!secretKey || secretKey.length === 0) {
|
|
62
|
-
return false
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const expectedSignature = createSignature(content, secretKey)
|
|
67
|
-
return expectedSignature.value === signature
|
|
68
|
-
} catch {
|
|
69
|
-
return false
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Valida el formato de una firma
|
|
75
|
-
*
|
|
76
|
-
* @param signature - Firma a validar
|
|
77
|
-
* @returns true si el formato es válido
|
|
78
|
-
*/
|
|
79
|
-
export function isValidSignatureFormat(signature: string): boolean {
|
|
80
|
-
// HMAC-SHA256 produce un hash hexadecimal de 64 caracteres
|
|
81
|
-
return /^[a-f0-9]{64}$/i.test(signature)
|
|
82
|
-
}
|
|
83
|
-
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CPE Value Objects - Exports
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export type { Nonce } from './Nonce'
|
|
6
|
-
export { createNonce, isValidNonce, equalsNonce } from './Nonce'
|
|
7
|
-
export { createMetadata, isValidMetadata } from './Metadata'
|
|
8
|
-
export type { SignatureVO } from './Signature'
|
|
9
|
-
export { createSignature, verifySignature, isValidSignatureFormat } from './Signature'
|
|
10
|
-
|
package/src/csl/classify.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { createTrustLevel } from './value-objects/TrustLevel'
|
|
2
|
-
import type { Origin } from './value-objects/Origin'
|
|
3
|
-
import { originMap } from './value-objects/Origin-map'
|
|
4
|
-
import { ClassificationError } from './exceptions'
|
|
5
|
-
import { OriginType } from './types'
|
|
6
|
-
import type { Source } from './types'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Clasifica un source y retorna su TrustLevel - función pura determinista
|
|
10
|
-
*
|
|
11
|
-
* @remarks
|
|
12
|
-
* - 100% determinista: mismo source → mismo trust level, siempre
|
|
13
|
-
* - Sin efectos secundarios: función pura
|
|
14
|
-
* - Sin análisis de contenido: solo el source importa
|
|
15
|
-
*
|
|
16
|
-
* @param source - El source del contenido ('DOM' | 'UI' | 'SYSTEM' | 'API')
|
|
17
|
-
* @returns TrustLevel determinado por el source
|
|
18
|
-
*
|
|
19
|
-
* @throws {ClassificationError} Si el source no puede ser clasificado
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* const trust = classifySource('UI')
|
|
24
|
-
* // Returns: { value: 'TC' }
|
|
25
|
-
*
|
|
26
|
-
* const trust2 = classifySource('DOM')
|
|
27
|
-
* // Returns: { value: 'STC' }
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
export function classifySource(source: Source) {
|
|
31
|
-
// Mapeo simple: Source → OriginType → TrustLevel
|
|
32
|
-
const sourceToOriginType: Record<Source, OriginType> = {
|
|
33
|
-
'UI': OriginType.SYSTEM_GENERATED, // UI directa → TC
|
|
34
|
-
'SYSTEM': OriginType.SYSTEM_GENERATED, // System → TC
|
|
35
|
-
'DOM': OriginType.DOM_VISIBLE, // DOM → STC
|
|
36
|
-
'API': OriginType.NETWORK_FETCHED // API → UC
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const originType = sourceToOriginType[source]
|
|
40
|
-
|
|
41
|
-
if (!originType) {
|
|
42
|
-
throw new ClassificationError(`Source '${source}' cannot be classified`)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const trustLevelType = originMap.get(originType)
|
|
46
|
-
|
|
47
|
-
if (!trustLevelType) {
|
|
48
|
-
throw new ClassificationError(
|
|
49
|
-
`Origin type '${originType}' is not mapped in originMap. ` +
|
|
50
|
-
`All OriginType values must have a corresponding TrustLevel mapping.`
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return createTrustLevel(trustLevelType)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Clasifica un Origin y retorna su TrustLevel - función pura determinista
|
|
59
|
-
*
|
|
60
|
-
* @param origin - El Origin value object
|
|
61
|
-
* @returns TrustLevel determinado por el origin
|
|
62
|
-
*
|
|
63
|
-
* @throws {ClassificationError} Si el origin no está mapeado
|
|
64
|
-
*/
|
|
65
|
-
export function classifyOrigin(origin: Origin) {
|
|
66
|
-
const trustLevelType = originMap.get(origin.type)
|
|
67
|
-
|
|
68
|
-
if (!trustLevelType) {
|
|
69
|
-
throw new ClassificationError(
|
|
70
|
-
`Origin type '${origin.type}' is not mapped in originMap. ` +
|
|
71
|
-
`All OriginType values must have a corresponding TrustLevel mapping.`
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return createTrustLevel(trustLevelType)
|
|
76
|
-
}
|
|
77
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ClassificationError is thrown when classification fails.
|
|
3
|
-
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* This error is thrown when:
|
|
6
|
-
* - An origin type is not mapped in originMap
|
|
7
|
-
* - Classification cannot be determined
|
|
8
|
-
*/
|
|
9
|
-
export class ClassificationError extends Error {
|
|
10
|
-
constructor(message: string) {
|
|
11
|
-
super(message)
|
|
12
|
-
this.name = 'ClassificationError'
|
|
13
|
-
Object.setPrototypeOf(this, ClassificationError.prototype)
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SegmentationError is thrown when the segmentation process fails.
|
|
3
|
-
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* This error is thrown when:
|
|
6
|
-
* - Content segmentation fails
|
|
7
|
-
* - Critical pipeline steps fail
|
|
8
|
-
*/
|
|
9
|
-
export class SegmentationError extends Error {
|
|
10
|
-
constructor(
|
|
11
|
-
message: string,
|
|
12
|
-
public readonly cause?: unknown
|
|
13
|
-
) {
|
|
14
|
-
super(message)
|
|
15
|
-
this.name = 'SegmentationError'
|
|
16
|
-
Object.setPrototypeOf(this, SegmentationError.prototype)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
package/src/csl/index.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CSL (Context Segmentation Layer) - Core Semántico
|
|
3
|
-
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* Este es el core semántico de CSL. Solo contiene:
|
|
6
|
-
* - Funciones puras (sin estado)
|
|
7
|
-
* - Value objects inmutables
|
|
8
|
-
* - Tipos y excepciones
|
|
9
|
-
*
|
|
10
|
-
* **NO contiene:**
|
|
11
|
-
* - Detección de prompt injection (va a ISL)
|
|
12
|
-
* - Políticas (van a ISL)
|
|
13
|
-
* - Anomaly scores (van a ISL)
|
|
14
|
-
* - Normalización agresiva (va a ISL)
|
|
15
|
-
* - Servicios con estado (van al SDK)
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
// Funciones puras principales
|
|
19
|
-
export { segment } from './segment'
|
|
20
|
-
export { classifySource, classifyOrigin } from './classify'
|
|
21
|
-
export { initLineage, createLineageEntry } from './lineage'
|
|
22
|
-
|
|
23
|
-
// Value objects
|
|
24
|
-
export type { TrustLevel, Origin, LineageEntry, ContentHash } from './value-objects'
|
|
25
|
-
export {
|
|
26
|
-
createTrustLevel,
|
|
27
|
-
isTrusted,
|
|
28
|
-
isSemiTrusted,
|
|
29
|
-
isUntrusted,
|
|
30
|
-
createOrigin,
|
|
31
|
-
isDom,
|
|
32
|
-
isUser,
|
|
33
|
-
isSystem,
|
|
34
|
-
isInjected,
|
|
35
|
-
isUnknown,
|
|
36
|
-
isNetworkFetched,
|
|
37
|
-
isExternal,
|
|
38
|
-
isSha256,
|
|
39
|
-
isSha512,
|
|
40
|
-
originMap,
|
|
41
|
-
createContentHash,
|
|
42
|
-
validateOriginMap
|
|
43
|
-
} from './value-objects'
|
|
44
|
-
|
|
45
|
-
// Exceptions
|
|
46
|
-
export { ClassificationError } from './exceptions/ClassificationError'
|
|
47
|
-
export { SegmentationError } from './exceptions/SegmentationError'
|
|
48
|
-
|
|
49
|
-
// Types
|
|
50
|
-
export { OriginType, TrustLevelType } from './types'
|
|
51
|
-
export type { HashAlgorithm, Source, CSLInput, CSLSegment, CSLResult } from './types'
|
|
52
|
-
|
|
53
|
-
// Utils
|
|
54
|
-
export { generateId, splitByContextRules } from './utils'
|
|
55
|
-
|
package/src/csl/lineage.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { createLineageEntry as createEntry } from './value-objects/LineageEntry'
|
|
2
|
-
import type { LineageEntry } from './value-objects/LineageEntry'
|
|
3
|
-
import type { CSLSegment } from './types'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Inicializa el linaje para un segmento - función pura
|
|
7
|
-
*
|
|
8
|
-
* @remarks
|
|
9
|
-
* Crea la entrada inicial de linaje cuando se crea un segmento en CSL.
|
|
10
|
-
* El core solo registra step y timestamp, sin notes.
|
|
11
|
-
*
|
|
12
|
-
* @param segment - El segmento para el cual inicializar el linaje
|
|
13
|
-
* @returns Array con la entrada inicial de linaje
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* const lineage = initLineage(segment)
|
|
18
|
-
* // Returns: [{ step: 'CSL', timestamp: ... }]
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export function initLineage(_segment: CSLSegment): LineageEntry[] {
|
|
22
|
-
return [
|
|
23
|
-
createEntry('CSL', Date.now())
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Crea una entrada de linaje - función pura
|
|
29
|
-
*
|
|
30
|
-
* @remarks
|
|
31
|
-
* El core solo registra step y timestamp.
|
|
32
|
-
* Notes y metadata van en el SDK para observabilidad.
|
|
33
|
-
*
|
|
34
|
-
* @param step - Nombre del paso de procesamiento
|
|
35
|
-
* @returns Nueva entrada de linaje
|
|
36
|
-
*/
|
|
37
|
-
export function createLineageEntry(step: string): LineageEntry {
|
|
38
|
-
return createEntry(step, Date.now())
|
|
39
|
-
}
|
|
40
|
-
|
package/src/csl/segment.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import type { CSLInput, CSLResult, CSLSegment } from './types'
|
|
2
|
-
import { classifySource } from './classify'
|
|
3
|
-
import { initLineage } from './lineage'
|
|
4
|
-
import { generateId, splitByContextRules } from './utils'
|
|
5
|
-
import { SegmentationError } from './exceptions'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Segmenta input en segmentos semánticos - función pura principal de CSL
|
|
9
|
-
*
|
|
10
|
-
* @remarks
|
|
11
|
-
* Esta es la función principal de CSL. Segmenta el contenido, clasifica
|
|
12
|
-
* por origen, e inicializa el linaje. Todo de forma pura y determinista.
|
|
13
|
-
*
|
|
14
|
-
* **Invariantes preservados:**
|
|
15
|
-
* - El contenido original nunca se pierde
|
|
16
|
-
* - El orden de segmentos es estable
|
|
17
|
-
* - Todo segmento tiene linaje inicial
|
|
18
|
-
* - CSL es determinista
|
|
19
|
-
*
|
|
20
|
-
* @param input - Input con contenido y source
|
|
21
|
-
* @returns CSLResult con segmentos clasificados y linaje inicializado
|
|
22
|
-
*
|
|
23
|
-
* @throws {SegmentationError} Si la segmentación falla
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* const result = segment({
|
|
28
|
-
* content: 'Hello\nWorld',
|
|
29
|
-
* source: 'UI',
|
|
30
|
-
* metadata: {}
|
|
31
|
-
* })
|
|
32
|
-
*
|
|
33
|
-
* // result.segments contiene 2 segmentos, cada uno con:
|
|
34
|
-
* // - content original
|
|
35
|
-
* // - trust level clasificado
|
|
36
|
-
* // - lineage inicializado
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
export function segment(input: CSLInput): CSLResult {
|
|
40
|
-
try {
|
|
41
|
-
// 1. Validar input
|
|
42
|
-
if (!input.content || typeof input.content !== 'string') {
|
|
43
|
-
throw new SegmentationError('CSLInput content must be a non-empty string')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!input.source) {
|
|
47
|
-
throw new SegmentationError('CSLInput source is required')
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// 2. Dividir contenido en segmentos estructurales (función pura)
|
|
51
|
-
// CSL solo segmenta por estructura, no por intención semántica
|
|
52
|
-
const contentSegments = splitByContextRules(input.content)
|
|
53
|
-
|
|
54
|
-
// 3. Si no hay contenido, retornar resultado vacío
|
|
55
|
-
if (contentSegments.length === 0) {
|
|
56
|
-
return {
|
|
57
|
-
segments: Object.freeze([]),
|
|
58
|
-
lineage: Object.freeze([])
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 4. Clasificar source una vez (determinista)
|
|
63
|
-
const trust = classifySource(input.source)
|
|
64
|
-
|
|
65
|
-
// 5. Crear segmentos con clasificación y linaje
|
|
66
|
-
const segments: CSLSegment[] = contentSegments.map((content) => {
|
|
67
|
-
// Crear segmento temporal para inicializar linaje
|
|
68
|
-
const tempSegment: CSLSegment = {
|
|
69
|
-
id: generateId(),
|
|
70
|
-
content, // ✅ Original preservado
|
|
71
|
-
source: input.source, // ✅ Origen preservado
|
|
72
|
-
trust, // ✅ Clasificación determinista
|
|
73
|
-
lineage: [], // Se inicializa después
|
|
74
|
-
...(input.metadata && { metadata: input.metadata })
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Inicializar linaje
|
|
78
|
-
const lineage = initLineage(tempSegment)
|
|
79
|
-
|
|
80
|
-
// Retornar segmento completo
|
|
81
|
-
return {
|
|
82
|
-
...tempSegment,
|
|
83
|
-
lineage // ✅ Linaje inicializado
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
// 6. Recolectar todo el linaje
|
|
88
|
-
const allLineage = segments.flatMap(s => s.lineage)
|
|
89
|
-
|
|
90
|
-
// 7. Retornar resultado puro
|
|
91
|
-
return {
|
|
92
|
-
segments: Object.freeze(segments),
|
|
93
|
-
lineage: Object.freeze(allLineage)
|
|
94
|
-
}
|
|
95
|
-
} catch (error) {
|
|
96
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error during segmentation'
|
|
97
|
-
throw new SegmentationError(`Failed to segment content: ${errorMessage}`, error)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
package/src/csl/types.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types for CSL (Context Segmentation Layer) - Core Semántico
|
|
3
|
-
*
|
|
4
|
-
* Solo tipos esenciales para CSL. Tipos relacionados con detección,
|
|
5
|
-
* anomalías y políticas van a ISL.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* OriginType represents the deterministic source of a content segment.
|
|
10
|
-
*/
|
|
11
|
-
export enum OriginType {
|
|
12
|
-
/**
|
|
13
|
-
* Direct user input from UI controls
|
|
14
|
-
* Always classified as UC (Untrusted Content) for security.
|
|
15
|
-
*/
|
|
16
|
-
USER = 'USER',
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Content from visible DOM elements
|
|
20
|
-
* Classified as STC (Semi-Trusted Content) because user can verify it.
|
|
21
|
-
*/
|
|
22
|
-
DOM_VISIBLE = 'DOM_VISIBLE',
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Content from hidden DOM elements
|
|
26
|
-
* Classified as UC (Untrusted Content) - potential attack vector.
|
|
27
|
-
*/
|
|
28
|
-
DOM_HIDDEN = 'DOM_HIDDEN',
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Content from DOM attributes (data-*, aria-*, etc.)
|
|
32
|
-
* Classified as STC (Semi-Trusted Content) - visible in source.
|
|
33
|
-
*/
|
|
34
|
-
DOM_ATTRIBUTE = 'DOM_ATTRIBUTE',
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Content injected by scripts (dynamically generated)
|
|
38
|
-
* Classified as UC (Untrusted Content) - can be manipulated.
|
|
39
|
-
*/
|
|
40
|
-
SCRIPT_INJECTED = 'SCRIPT_INJECTED',
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Content fetched from network (API calls, external resources)
|
|
44
|
-
* Classified as UC (Untrusted Content) - external source, not verified.
|
|
45
|
-
*/
|
|
46
|
-
NETWORK_FETCHED = 'NETWORK_FETCHED',
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* System-generated content (instructions, system prompts, etc.)
|
|
50
|
-
* Classified as TC (Trusted Content) - system controls this content.
|
|
51
|
-
*/
|
|
52
|
-
SYSTEM_GENERATED = 'SYSTEM_GENERATED',
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Origin cannot be determined
|
|
56
|
-
* Classified as UC (Untrusted Content) - unknown is untrusted by default.
|
|
57
|
-
*/
|
|
58
|
-
UNKNOWN = 'UNKNOWN',
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* TrustLevelType represents the trust level of content
|
|
63
|
-
*/
|
|
64
|
-
export enum TrustLevelType {
|
|
65
|
-
TC = 'TC', // Trusted Content
|
|
66
|
-
STC = 'STC', // Semi-Trusted Content
|
|
67
|
-
UC = 'UC', // Untrusted Content
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* HashAlgorithm for ContentHash (opcional, para trazabilidad)
|
|
72
|
-
*/
|
|
73
|
-
export type HashAlgorithm = 'sha256' | 'sha512'
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Source type for CSL input
|
|
77
|
-
*/
|
|
78
|
-
export type Source = 'DOM' | 'UI' | 'SYSTEM' | 'API'
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* CSLInput - Input para la función segment()
|
|
82
|
-
*/
|
|
83
|
-
export interface CSLInput {
|
|
84
|
-
readonly content: string
|
|
85
|
-
readonly source: Source
|
|
86
|
-
readonly metadata?: Record<string, unknown>
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Importar tipos de value objects para usar en interfaces
|
|
90
|
-
import type { ContentHash, LineageEntry, TrustLevel } from './value-objects'
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* CSLSegment - Segmento puro, solo datos semánticos
|
|
94
|
-
*/
|
|
95
|
-
export interface CSLSegment {
|
|
96
|
-
readonly id: string
|
|
97
|
-
readonly content: string // Original, sin modificar
|
|
98
|
-
readonly source: Source
|
|
99
|
-
readonly trust: TrustLevel // Clasificado por origen
|
|
100
|
-
readonly lineage: LineageEntry[] // Inicializado en CSL
|
|
101
|
-
readonly hash?: ContentHash // Opcional, para trazabilidad
|
|
102
|
-
readonly metadata?: Record<string, unknown>
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* CSLResult - Resultado puro, solo datos
|
|
107
|
-
*/
|
|
108
|
-
export interface CSLResult {
|
|
109
|
-
readonly segments: readonly CSLSegment[]
|
|
110
|
-
readonly lineage: readonly LineageEntry[]
|
|
111
|
-
readonly processingTimeMs?: number // Opcional, para métricas
|
|
112
|
-
}
|
|
113
|
-
|
package/src/csl/utils.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility functions for CSL - funciones puras
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Generates a unique ID for a segment
|
|
7
|
-
*/
|
|
8
|
-
export function generateId(): string {
|
|
9
|
-
return `seg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Splits content by context rules - función pura de segmentación
|
|
14
|
-
*
|
|
15
|
-
* @remarks
|
|
16
|
-
* Segmentación básica por líneas. Sin normalización agresiva
|
|
17
|
-
* (la normalización va a ISL).
|
|
18
|
-
*/
|
|
19
|
-
export function splitByContextRules(content: string): string[] {
|
|
20
|
-
if (content.length === 0) {
|
|
21
|
-
return []
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Segmentación básica por líneas
|
|
25
|
-
return content
|
|
26
|
-
.split(/\n+/)
|
|
27
|
-
.map(line => line.trim())
|
|
28
|
-
.filter(line => line.length > 0)
|
|
29
|
-
}
|
|
30
|
-
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { HashAlgorithm } from '../types'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ContentHash - tipo puro
|
|
5
|
-
*/
|
|
6
|
-
export type ContentHash = {
|
|
7
|
-
readonly value: string
|
|
8
|
-
readonly algorithm: HashAlgorithm
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Crea un ContentHash - función pura
|
|
13
|
-
*/
|
|
14
|
-
export function createContentHash(value: string, algorithm: HashAlgorithm = 'sha256'): ContentHash {
|
|
15
|
-
if (!value || typeof value !== 'string') {
|
|
16
|
-
throw new Error('ContentHash value must be a non-empty string')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!['sha256', 'sha512'].includes(algorithm)) {
|
|
20
|
-
throw new Error(`Invalid HashAlgorithm: ${algorithm}. Must be 'sha256' or 'sha512'`)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const hexPattern = /^[a-f0-9]+$/i
|
|
24
|
-
if (!hexPattern.test(value)) {
|
|
25
|
-
throw new Error('ContentHash value must be a valid hexadecimal string')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const expectedLength = algorithm === 'sha256' ? 64 : 128
|
|
29
|
-
if (value.length !== expectedLength) {
|
|
30
|
-
throw new Error(`ContentHash value length must be ${expectedLength} characters for ${algorithm}`)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
value: value.toLowerCase(),
|
|
35
|
-
algorithm
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Funciones puras para ContentHash
|
|
41
|
-
*/
|
|
42
|
-
export function isSha256(hash: ContentHash): boolean {
|
|
43
|
-
return hash.algorithm === 'sha256'
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function isSha512(hash: ContentHash): boolean {
|
|
47
|
-
return hash.algorithm === 'sha512'
|
|
48
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LineageEntry - tipo puro
|
|
3
|
-
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* El core semántico solo preserva linaje estructural.
|
|
6
|
-
* Notes libres son para observabilidad (SDK), no core.
|
|
7
|
-
*/
|
|
8
|
-
export type LineageEntry = {
|
|
9
|
-
readonly step: string
|
|
10
|
-
readonly timestamp: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Crea un LineageEntry - función pura
|
|
15
|
-
*
|
|
16
|
-
* @remarks
|
|
17
|
-
* El core solo registra step y timestamp.
|
|
18
|
-
* Notes y metadata van en el SDK para observabilidad.
|
|
19
|
-
*/
|
|
20
|
-
export function createLineageEntry(step: string, timestamp: number): LineageEntry {
|
|
21
|
-
if (!step || typeof step !== 'string' || step.trim().length === 0) {
|
|
22
|
-
throw new Error('LineageEntry step must be a non-empty string')
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (typeof timestamp !== 'number' || timestamp < 0 || !Number.isFinite(timestamp)) {
|
|
26
|
-
throw new Error('LineageEntry timestamp must be a valid positive number')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
step: step.trim(),
|
|
31
|
-
timestamp
|
|
32
|
-
}
|
|
33
|
-
}
|