@ai-pip/core 0.2.0 → 0.3.0
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/CHANGELOG.md +66 -2
- package/README.md +107 -18
- package/dist/AAL/constants.d.ts +15 -0
- package/dist/AAL/constants.d.ts.map +1 -0
- package/dist/AAL/constants.js +20 -0
- package/dist/AAL/constants.js.map +1 -0
- package/dist/AAL/index.d.ts +2 -1
- package/dist/AAL/index.d.ts.map +1 -1
- package/dist/AAL/index.js +3 -1
- package/dist/AAL/index.js.map +1 -1
- package/dist/AAL/process/applyRemovalPlan.d.ts +21 -0
- package/dist/AAL/process/applyRemovalPlan.d.ts.map +1 -0
- package/dist/AAL/process/applyRemovalPlan.js +150 -0
- package/dist/AAL/process/applyRemovalPlan.js.map +1 -0
- package/dist/AAL/process/buildDecisionReason.d.ts.map +1 -1
- package/dist/AAL/process/buildDecisionReason.js +26 -4
- package/dist/AAL/process/buildDecisionReason.js.map +1 -1
- package/dist/AAL/process/buildRemovalPlan.d.ts +17 -10
- package/dist/AAL/process/buildRemovalPlan.d.ts.map +1 -1
- package/dist/AAL/process/buildRemovalPlan.js +84 -30
- package/dist/AAL/process/buildRemovalPlan.js.map +1 -1
- package/dist/AAL/process/index.d.ts +2 -1
- package/dist/AAL/process/index.d.ts.map +1 -1
- package/dist/AAL/process/index.js +2 -1
- package/dist/AAL/process/index.js.map +1 -1
- package/dist/AAL/process/resolveAgentAction.d.ts.map +1 -1
- package/dist/AAL/process/resolveAgentAction.js +24 -0
- package/dist/AAL/process/resolveAgentAction.js.map +1 -1
- package/dist/AAL/types.d.ts +11 -7
- package/dist/AAL/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/isl/detect/detect.d.ts +39 -0
- package/dist/isl/detect/detect.d.ts.map +1 -0
- package/dist/isl/detect/detect.js +369 -0
- package/dist/isl/detect/detect.js.map +1 -0
- package/dist/isl/detect/index.d.ts +6 -0
- package/dist/isl/detect/index.d.ts.map +1 -0
- package/dist/isl/detect/index.js +5 -0
- package/dist/isl/detect/index.js.map +1 -0
- package/dist/isl/index.d.ts +8 -1
- package/dist/isl/index.d.ts.map +1 -1
- package/dist/isl/index.js +5 -0
- package/dist/isl/index.js.map +1 -1
- package/dist/isl/process/emitSignal.d.ts +19 -10
- package/dist/isl/process/emitSignal.d.ts.map +1 -1
- package/dist/isl/process/emitSignal.js +25 -23
- package/dist/isl/process/emitSignal.js.map +1 -1
- package/dist/isl/process/index.d.ts +1 -0
- package/dist/isl/process/index.d.ts.map +1 -1
- package/dist/isl/riskScore/calculators.d.ts +19 -0
- package/dist/isl/riskScore/calculators.d.ts.map +1 -0
- package/dist/isl/riskScore/calculators.js +50 -0
- package/dist/isl/riskScore/calculators.js.map +1 -0
- package/dist/isl/riskScore/index.d.ts +14 -0
- package/dist/isl/riskScore/index.d.ts.map +1 -0
- package/dist/isl/riskScore/index.js +26 -0
- package/dist/isl/riskScore/index.js.map +1 -0
- package/dist/isl/riskScore/types.d.ts +20 -0
- package/dist/isl/riskScore/types.d.ts.map +1 -0
- package/dist/isl/riskScore/types.js +12 -0
- package/dist/isl/riskScore/types.js.map +1 -0
- package/dist/isl/sanitize.d.ts +8 -1
- package/dist/isl/sanitize.d.ts.map +1 -1
- package/dist/isl/sanitize.js +13 -5
- package/dist/isl/sanitize.js.map +1 -1
- package/dist/isl/signals.d.ts +16 -1
- package/dist/isl/signals.d.ts.map +1 -1
- package/dist/isl/signals.js +4 -2
- package/dist/isl/signals.js.map +1 -1
- package/dist/isl/value-objects/Pattern.d.ts +21 -0
- package/dist/isl/value-objects/Pattern.d.ts.map +1 -1
- package/dist/isl/value-objects/Pattern.js +36 -0
- package/dist/isl/value-objects/Pattern.js.map +1 -1
- package/dist/isl/value-objects/index.d.ts +2 -2
- package/dist/isl/value-objects/index.d.ts.map +1 -1
- package/dist/isl/value-objects/index.js +1 -1
- package/dist/isl/value-objects/index.js.map +1 -1
- package/dist/shared/audit.d.ts +116 -16
- package/dist/shared/audit.d.ts.map +1 -1
- package/dist/shared/audit.js +314 -32
- package/dist/shared/audit.js.map +1 -1
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,70 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - (unreleased)
|
|
11
|
+
|
|
12
|
+
### ✨ Added
|
|
13
|
+
|
|
14
|
+
- **ISL – Threat detection**
|
|
15
|
+
- `detectThreats(content, options?)`: pure, deterministic function returning `readonly PiDetection[]`.
|
|
16
|
+
- Default patterns for known attack surfaces (prompt-injection, jailbreak, role hijacking, script_like, hidden_text); expanded set (~287 patterns).
|
|
17
|
+
- Integration in `sanitize`: each segment may carry `piDetection` (`PiDetectionResult`).
|
|
18
|
+
- Option `SanitizeOptions.detectThreatsOptions` for custom patterns or limits (`patterns`, `maxTotal`, `maxPerPattern`).
|
|
19
|
+
- `getDefaultThreatPatterns()`: returns the default set (cached, frozen).
|
|
20
|
+
- `THREAT_TYPES` and type `ThreatType` for deterministic taxonomy.
|
|
21
|
+
|
|
22
|
+
- **ISL – Risk score strategies**
|
|
23
|
+
- Enum `RiskScoreStrategy`: `MAX_CONFIDENCE`, `SEVERITY_PLUS_VOLUME`, `WEIGHTED_BY_TYPE`.
|
|
24
|
+
- Pure calculators: `maxConfidenceCalculator`, `severityPlusVolumeCalculator`, `weightedByTypeCalculator`, `defaultWeightedByTypeCalculator`.
|
|
25
|
+
- `getCalculator(strategy, typeWeights?)`: returns the registered calculator for the strategy.
|
|
26
|
+
- Strategy fixed at `emitSignal`; reflected in `ISLSignal.metadata.strategy` for audit.
|
|
27
|
+
|
|
28
|
+
- **emitSignal – Risk score options**
|
|
29
|
+
- `EmitSignalOptions`: `timestamp?`, `riskScore?: { strategy, typeWeights? }`.
|
|
30
|
+
- Default: `RiskScoreStrategy.MAX_CONFIDENCE`.
|
|
31
|
+
- Backward compatibility: `emitSignal(islResult, timestamp)` still supported.
|
|
32
|
+
|
|
33
|
+
- **ISLSignal – Strategy metadata**
|
|
34
|
+
- `ISLSignal.metadata?: { strategy: RiskScoreStrategy }` for traceability.
|
|
35
|
+
- `createISLSignal(..., metadata?)` accepts optional fourth argument `metadata`.
|
|
36
|
+
|
|
37
|
+
- **AAL – Actionable removal plan**
|
|
38
|
+
- `buildRemovalPlanFromResult(islResult, policy)`: builds `RemovalPlan` from `ISLResult` with `segmentId` per instruction.
|
|
39
|
+
- `applyRemovalPlan(islResult, plan)`: pure function that removes malicious ranges from each segment's `sanitizedContent`; clamps ranges to content; merges overlapping and adjacent ranges (gap only punctuation/whitespace); returns new `ISLResult`.
|
|
40
|
+
- `RemovedInstruction.segmentId?`: optional, present when the plan is built from `ISLResult`.
|
|
41
|
+
- Guards in `resolveAgentAction`, `resolveAgentActionWithScore`, `buildDecisionReason`, `buildRemovalPlan`, and `buildRemovalPlanFromResult` for safe handling of detections and signals.
|
|
42
|
+
|
|
43
|
+
- **AAL – Resolve action with score**
|
|
44
|
+
- `resolveAgentActionWithScore(islSignal, policy)`: returns `{ action, anomalyScore }` for SDK/audit use.
|
|
45
|
+
|
|
46
|
+
- **AAL – Colors for UI/audit**
|
|
47
|
+
- `ACTION_DISPLAY_COLORS` and `getActionDisplayColor(action)` for ALLOW/WARN/BLOCK.
|
|
48
|
+
|
|
49
|
+
- **Shared – Audit improvements (run id, JSON, logs, full pipeline)**
|
|
50
|
+
- **Run identifier**: `createAuditRunId()` generates a unique run id; full-pipeline formatters accept `options.runId` and `options.generatedAt` for correlation across reports and logs.
|
|
51
|
+
- **Full pipeline audit**: `formatPipelineAuditFull(csl, isl, signal, aalReason, removalPlan?, cpe?, options?)` builds a single report (CSL → ISL → Signal → AAL → optional CPE) with run id and generated-at timestamp; lineage preserved in each section.
|
|
52
|
+
- **formatPipelineAudit** extended: `options.includeSignalAndAAL`, `options.signal`, `options.aalReason`, `options.removalPlan` to include ISL Signal and AAL sections in the pipeline report.
|
|
53
|
+
- **JSON variant**: `buildFullAuditPayload(csl, isl, signal, reason, options?)` returns a JSON-serializable object (runId, generatedAt, summary, sections with lineage). `formatPipelineAuditAsJson(...)` returns the JSON string; `options.compact: true` for one-line output (logs, SIEM).
|
|
54
|
+
- **Audit for logs**: `buildAuditLogEntry(signal, reason, options?)` returns a compact summary (runId, generatedAtIso, action, riskScore, hasThreats, detectionCount) for one-line logging.
|
|
55
|
+
- Types: `AuditRunInfo`, `AuditLogSummary`, `FullPipelineAuditOptions`, `PipelineAuditJsonOptions`.
|
|
56
|
+
|
|
57
|
+
### 🔄 Changed
|
|
58
|
+
|
|
59
|
+
- **sanitize (ISL)**: optional second argument `SanitizeOptions`; uses `detectThreats` per segment and assigns `piDetection` when detections exist; option `detectThreatsOptions` for patterns or limits.
|
|
60
|
+
- **emitSignal (ISL)**: second argument may be `EmitSignalOptions` (object) or `number` (timestamp); computes risk score with configured strategy; includes `metadata.strategy` on the signal.
|
|
61
|
+
- **RemovedInstruction (AAL)**: `type` is now `string` (any `pattern_type`); added `segmentId?: string`.
|
|
62
|
+
|
|
63
|
+
### 📚 Documentation
|
|
64
|
+
|
|
65
|
+
- **FEATURE.md**: per-version detail of new and modified features; table of methods/APIs changed in 0.3.0 with description of each change.
|
|
66
|
+
- **README.md**: audit section updated with run id, full pipeline (formatPipelineAuditFull), JSON variant (buildFullAuditPayload, formatPipelineAuditAsJson), and audit for logs (buildAuditLogEntry); examples for full report and compact log entry.
|
|
67
|
+
|
|
68
|
+
### 📎 More information
|
|
69
|
+
|
|
70
|
+
For specific method signatures and API changes in 0.3.0, see **[FEATURE.md](./FEATURE.md)**.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
10
74
|
## [0.2.0] - 2026-01-26
|
|
11
75
|
|
|
12
76
|
### ♻️ Architectural Refactor - ISL / AAL Separation
|
|
@@ -161,7 +225,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
161
225
|
|
|
162
226
|
**Problem**: When importing types from `@ai-pip/core` in SDK projects, TypeScript could not resolve nested type properties:
|
|
163
227
|
- `this.data.trust.value` appeared as `any` instead of `TrustLevelType`
|
|
164
|
-
- No
|
|
228
|
+
- No autocomplete for nested properties
|
|
165
229
|
- Type inference failed for complex types
|
|
166
230
|
|
|
167
231
|
**Root Cause**: Incompatibility between `moduleResolution: "bundler"` (used in `@ai-pip-core`) and `moduleResolution: "nodenext"` (used in SDK projects). TypeScript couldn't follow the chain of type imports correctly.
|
|
@@ -173,7 +237,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
173
237
|
|
|
174
238
|
**Impact**:
|
|
175
239
|
- ✅ Nested types now resolve correctly
|
|
176
|
-
- ✅
|
|
240
|
+
- ✅ Autocomplete works for all type properties
|
|
177
241
|
- ✅ Type inference works correctly in consuming projects
|
|
178
242
|
- ✅ Better compatibility with Node.js ESM module resolution
|
|
179
243
|
|
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ This package contains the **core** implementation of the protocol, which include
|
|
|
44
44
|
- [Import Strategies](#import-strategies)
|
|
45
45
|
- [Official SDK](#official-sdk)
|
|
46
46
|
- [CHANGELOG](#changelog)
|
|
47
|
-
|
|
47
|
+
- [FEATURES](#features)
|
|
48
48
|
<a id="architecture"></a>
|
|
49
49
|
## 🏗️ Architecture
|
|
50
50
|
|
|
@@ -53,7 +53,7 @@ The AI-PIP protocol is composed of the following layers with clear separation of
|
|
|
53
53
|
### ✅ Implemented Layers
|
|
54
54
|
|
|
55
55
|
- **CSL (Context Segmentation Layer)**: Segments and classifies content according to its origin
|
|
56
|
-
- **ISL (Instruction Sanitization Layer)**: Detects malicious patterns, scores risk, and sanitizes content. Emits signals (ISLSignal) for other layers to consume.
|
|
56
|
+
- **ISL (Instruction Sanitization Layer)**: Detects malicious patterns (`detectThreats`, ~287 default patterns), scores risk (configurable strategies), and sanitizes content. Each segment may carry `piDetection` (`PiDetectionResult`). Optional `SanitizeOptions.detectThreatsOptions` for custom patterns or limits. Emits signals (ISLSignal) for other layers to consume.
|
|
57
57
|
- **AAL (Agent Action Lock)**: Hybrid layer that consumes ISL signals and applies configurable policies (ALLOW/WARN/BLOCK). Core-defined contract, SDK-implemented.
|
|
58
58
|
- **CPE (Cryptographic Prompt Envelope)**: Generates cryptographic envelope with HMAC-SHA256 signature
|
|
59
59
|
|
|
@@ -153,11 +153,11 @@ import { segment, classifySource, createTrustLevel } from '@ai-pip/core/csl'
|
|
|
153
153
|
import type { CSLResult, CSLSegment, TrustLevel } from '@ai-pip/core/csl'
|
|
154
154
|
|
|
155
155
|
// Import from ISL (Instruction Sanitization Layer)
|
|
156
|
-
import { sanitize, createISLSignal } from '@ai-pip/core/isl'
|
|
157
|
-
import type { ISLResult, ISLSegment, ISLSignal } from '@ai-pip/core/isl'
|
|
156
|
+
import { sanitize, createISLSignal, detectThreats, getDefaultThreatPatterns } from '@ai-pip/core/isl'
|
|
157
|
+
import type { ISLResult, ISLSegment, ISLSignal, DetectThreatsOptions } from '@ai-pip/core/isl'
|
|
158
158
|
|
|
159
159
|
// Import from AAL (Agent Action Lock)
|
|
160
|
-
import { createAnomalyScore, resolveAgentAction } from '@ai-pip/core/aal'
|
|
160
|
+
import { createAnomalyScore, resolveAgentAction, resolveAgentActionWithScore, buildRemovalPlanFromResult, applyRemovalPlan } from '@ai-pip/core/aal'
|
|
161
161
|
import type { AnomalyScore, AgentPolicy } from '@ai-pip/core/aal'
|
|
162
162
|
|
|
163
163
|
// Import from CPE (Cryptographic Prompt Envelope)
|
|
@@ -199,7 +199,7 @@ This example demonstrates the complete AI-PIP processing pipeline:
|
|
|
199
199
|
|
|
200
200
|
1. **CSL (Context Segmentation Layer)**: The `segment()` function takes user input and segments it into semantic chunks. Each segment is classified by its origin (`source: 'UI'`), which determines its trust level. The result contains multiple segments, each with its own trust classification and lineage tracking.
|
|
201
201
|
|
|
202
|
-
2. **ISL (Instruction Sanitization Layer)**: The `sanitize()` function processes the segmented content and applies sanitization based on each segment's trust level. Trusted content (TC) receives minimal sanitization, semi-trusted (STC) gets moderate sanitization, and untrusted content (UC) receives aggressive sanitization to remove potential prompt injection attempts. ISL
|
|
202
|
+
2. **ISL (Instruction Sanitization Layer)**: The `sanitize()` function processes the segmented content and applies sanitization based on each segment's trust level. Trusted content (TC) receives minimal sanitization, semi-trusted (STC) gets moderate sanitization, and untrusted content (UC) receives aggressive sanitization to remove potential prompt injection attempts. ISL runs `detectThreats` per segment (default ~287 patterns; optional `SanitizeOptions.detectThreatsOptions` for custom patterns or limits) and attaches `piDetection` (`PiDetectionResult`) to segments with detections. It emits signals (ISLSignal) that can be consumed by AAL for policy-based decisions.
|
|
203
203
|
|
|
204
204
|
3. **CPE (Cryptographic Prompt Envelope)**: The `envelope()` function creates a cryptographic wrapper around the sanitized content. It generates a unique nonce, timestamp, and HMAC-SHA256 signature to ensure the integrity and authenticity of the processed prompt. The resulting envelope can be safely sent to an AI model with cryptographic proof that the content hasn't been tampered with.
|
|
205
205
|
|
|
@@ -254,7 +254,7 @@ This example shows the same processing pipeline but using layer-specific imports
|
|
|
254
254
|
|
|
255
255
|
2. **Content Segmentation**: The `segment()` function breaks down the input into semantic segments. Each segment inherits the trust classification from its source, allowing different parts of the content to be processed according to their trustworthiness.
|
|
256
256
|
|
|
257
|
-
3. **Content Sanitization**: The `sanitize()` function applies security measures based on each segment's trust level. This step removes or neutralizes potential prompt injection attempts, especially in untrusted content segments.
|
|
257
|
+
3. **Content Sanitization**: The `sanitize()` function applies security measures based on each segment's trust level and runs threat detection per segment (each segment may have `piDetection`). This step removes or neutralizes potential prompt injection attempts, especially in untrusted content segments.
|
|
258
258
|
|
|
259
259
|
4. **Nonce Generation**: `createNonce()` generates a unique random value that prevents replay attacks. This nonce is included in the cryptographic envelope to ensure each processed prompt is unique.
|
|
260
260
|
|
|
@@ -612,7 +612,9 @@ import {
|
|
|
612
612
|
emitSignal,
|
|
613
613
|
resolveAgentAction,
|
|
614
614
|
buildDecisionReason,
|
|
615
|
-
buildRemovalPlan
|
|
615
|
+
buildRemovalPlan,
|
|
616
|
+
buildRemovalPlanFromResult,
|
|
617
|
+
applyRemovalPlan
|
|
616
618
|
} from '@ai-pip/core'
|
|
617
619
|
import type { ISLSignal, AgentPolicy } from '@ai-pip/core'
|
|
618
620
|
|
|
@@ -623,7 +625,7 @@ const cslResult = segment({
|
|
|
623
625
|
metadata: {}
|
|
624
626
|
})
|
|
625
627
|
|
|
626
|
-
// 2. Sanitize content (ISL) - produces internal result
|
|
628
|
+
// 2. Sanitize content (ISL) - produces internal result; segments may have piDetection
|
|
627
629
|
const islResult = sanitize(cslResult)
|
|
628
630
|
|
|
629
631
|
// 3. Emit signal from ISL result - external contract
|
|
@@ -649,10 +651,12 @@ console.log('Agent action:', action) // 'ALLOW', 'WARN', or 'BLOCK'
|
|
|
649
651
|
const reason = buildDecisionReason(action, islSignal, policy)
|
|
650
652
|
console.log('Decision reason:', reason.reason)
|
|
651
653
|
|
|
652
|
-
// 7. Build removal plan
|
|
654
|
+
// 7. Build removal plan from signal (descriptive) or from result (actionable)
|
|
653
655
|
const removalPlan = buildRemovalPlan(islSignal, policy)
|
|
654
656
|
if (removalPlan.shouldRemove) {
|
|
655
|
-
|
|
657
|
+
const planFromResult = buildRemovalPlanFromResult(islResult, policy)
|
|
658
|
+
const cleanedResult = applyRemovalPlan(islResult, planFromResult)
|
|
659
|
+
console.log(`Removed ${planFromResult.instructionsToRemove.length} instruction(s); use cleanedResult for LLM`)
|
|
656
660
|
}
|
|
657
661
|
```
|
|
658
662
|
|
|
@@ -675,6 +679,38 @@ if (removalPlan.shouldRemove) {
|
|
|
675
679
|
|
|
676
680
|
**Key Principle**: A layer should never consume the internal "result" of another layer. It consumes a signal.
|
|
677
681
|
|
|
682
|
+
#### Risk score strategies (ISL)
|
|
683
|
+
|
|
684
|
+
The risk score on the signal is derived from aggregated detections using a **strategy** chosen at emit time. Only registered strategies are allowed (auditability and reproducibility).
|
|
685
|
+
|
|
686
|
+
| Strategy | Description | When to use |
|
|
687
|
+
|----------|-------------|-------------|
|
|
688
|
+
| **MAX_CONFIDENCE** (default) | Single highest confidence among detections. | Simple, conservative; good default. |
|
|
689
|
+
| **SEVERITY_PLUS_VOLUME** | Highest confidence plus a small bump per extra detection (volume). | When multiple detections should raise risk. |
|
|
690
|
+
| **WEIGHTED_BY_TYPE** | Weight by pattern type (e.g. jailbreak vs prompt-injection). | When some threat types should count more. |
|
|
691
|
+
|
|
692
|
+
```typescript
|
|
693
|
+
import { emitSignal, RiskScoreStrategy } from '@ai-pip/core/isl'
|
|
694
|
+
|
|
695
|
+
// Default: MAX_CONFIDENCE
|
|
696
|
+
const signal = emitSignal(islResult)
|
|
697
|
+
|
|
698
|
+
// Explicit strategy
|
|
699
|
+
const signalSev = emitSignal(islResult, {
|
|
700
|
+
riskScore: { strategy: RiskScoreStrategy.SEVERITY_PLUS_VOLUME }
|
|
701
|
+
})
|
|
702
|
+
|
|
703
|
+
// WEIGHTED_BY_TYPE with custom weights
|
|
704
|
+
const signalWeighted = emitSignal(islResult, {
|
|
705
|
+
riskScore: {
|
|
706
|
+
strategy: RiskScoreStrategy.WEIGHTED_BY_TYPE,
|
|
707
|
+
typeWeights: { 'prompt-injection': 1.2, jailbreak: 1 }
|
|
708
|
+
}
|
|
709
|
+
})
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
The strategy used is stored in **`signal.metadata.strategy`** for auditability. For full API and formulas, see the [ISL layer documentation](https://github.com/AI-PIP/ai-pip-docs/blob/main/docs/core/layers/ISL.md) in the protocol docs.
|
|
713
|
+
|
|
678
714
|
---
|
|
679
715
|
|
|
680
716
|
<a id="example-audit-utilities"></a>
|
|
@@ -696,7 +732,12 @@ import {
|
|
|
696
732
|
formatISLSignalForAudit,
|
|
697
733
|
formatAALForAudit,
|
|
698
734
|
formatCPEForAudit,
|
|
699
|
-
formatPipelineAudit
|
|
735
|
+
formatPipelineAudit,
|
|
736
|
+
formatPipelineAuditFull,
|
|
737
|
+
formatPipelineAuditAsJson,
|
|
738
|
+
createAuditRunId,
|
|
739
|
+
buildAuditLogEntry,
|
|
740
|
+
buildFullAuditPayload
|
|
700
741
|
} from '@ai-pip/core'
|
|
701
742
|
import type { AgentPolicy } from '@ai-pip/core'
|
|
702
743
|
|
|
@@ -721,12 +762,32 @@ console.log(formatISLSignalForAudit(islSignal))
|
|
|
721
762
|
console.log(formatAALForAudit(reason, removalPlan))
|
|
722
763
|
console.log(formatCPEForAudit(cpeResult))
|
|
723
764
|
|
|
724
|
-
// Full pipeline audit report
|
|
765
|
+
// Full pipeline audit report (CSL → ISL → CPE)
|
|
725
766
|
const fullAudit = formatPipelineAudit(cslResult, islResult, cpeResult, {
|
|
726
767
|
title: 'AI-PIP Pipeline Audit',
|
|
727
768
|
sectionSeparator: '\n\n'
|
|
728
769
|
})
|
|
729
770
|
console.log(fullAudit)
|
|
771
|
+
|
|
772
|
+
// Full pipeline with run id and Signal + AAL (CSL → ISL → Signal → AAL → optional CPE)
|
|
773
|
+
const runId = createAuditRunId()
|
|
774
|
+
const generatedAt = Date.now()
|
|
775
|
+
const fullReport = formatPipelineAuditFull(cslResult, islResult, islSignal, reason, removalPlan, cpeResult, {
|
|
776
|
+
runId,
|
|
777
|
+
generatedAt,
|
|
778
|
+
includeCpe: true,
|
|
779
|
+
title: 'AI-PIP Pipeline Audit (full)'
|
|
780
|
+
})
|
|
781
|
+
console.log(fullReport)
|
|
782
|
+
|
|
783
|
+
// JSON for logs / SIEM / machine consumption
|
|
784
|
+
const payload = buildFullAuditPayload(cslResult, islResult, islSignal, reason, { runId, generatedAt, removalPlan, cpe: cpeResult })
|
|
785
|
+
const jsonReport = formatPipelineAuditAsJson(cslResult, islResult, islSignal, reason, { runId, generatedAt, removalPlan, compact: true })
|
|
786
|
+
logger.info(jsonReport)
|
|
787
|
+
|
|
788
|
+
// Compact log entry (one line per request)
|
|
789
|
+
const logEntry = buildAuditLogEntry(islSignal, reason, { runId, generatedAt })
|
|
790
|
+
logger.info(JSON.stringify(logEntry))
|
|
730
791
|
```
|
|
731
792
|
|
|
732
793
|
**What this example demonstrates:**
|
|
@@ -736,9 +797,13 @@ console.log(fullAudit)
|
|
|
736
797
|
- **`formatISLSignalForAudit(signal)`**: Formats ISL signal (risk score, threats, detections) for audit.
|
|
737
798
|
- **`formatAALForAudit(reason, removalPlan?)`**: Formats AAL decision reason and optional removal plan.
|
|
738
799
|
- **`formatCPEForAudit(result)`**: Formats CPE result (metadata, signature, lineage).
|
|
739
|
-
- **`formatPipelineAudit(csl, isl, cpe, options?)`**: Builds a single full pipeline audit string.
|
|
800
|
+
- **`formatPipelineAudit(csl, isl, cpe, options?)`**: Builds a single full pipeline audit string (CSL → ISL → CPE). Use **`options.includeSignalAndAAL`** with **`options.signal`** and **`options.aalReason`** to include ISL Signal and AAL sections.
|
|
801
|
+
- **`formatPipelineAuditFull(csl, isl, signal, aalReason, removalPlan?, cpe?, options?)`**: Full pipeline report (CSL → ISL → Signal → AAL → optional CPE) with **run id** and **generated at** timestamp; lineage in each section.
|
|
802
|
+
- **Run identifier**: **`createAuditRunId()`** generates a unique run id; pass **`options.runId`** and **`options.generatedAt`** to formatters for correlation across reports and logs.
|
|
803
|
+
- **JSON variant**: **`buildFullAuditPayload(csl, isl, signal, reason, options?)`** returns a JSON-serializable object (runId, generatedAt, summary, sections with lineage). **`formatPipelineAuditAsJson(...)`** returns the JSON string; use **`options.compact: true`** for one-line output (logs, SIEM).
|
|
804
|
+
- **Audit for logs**: **`buildAuditLogEntry(signal, reason, options?)`** returns a compact summary (`runId`, `generatedAtIso`, `action`, `riskScore`, `hasThreats`, `detectionCount`) for one-line logging (e.g. `logger.info(JSON.stringify(entry))`).
|
|
740
805
|
|
|
741
|
-
All formatters accept minimal shapes (layer-agnostic) so you can pass any compatible object. Output is ordered and consistent for compliance and debugging.
|
|
806
|
+
All formatters accept minimal shapes (layer-agnostic) so you can pass any compatible object. Output is ordered and consistent for compliance and debugging. Lineage is preserved in every section for traceability.
|
|
742
807
|
|
|
743
808
|
<a id="use-cases"></a>
|
|
744
809
|
### Use cases
|
|
@@ -748,8 +813,8 @@ Typical scenarios where AI-PIP core is used:
|
|
|
748
813
|
| Use case | Layers involved | Goal |
|
|
749
814
|
|----------|-----------------|------|
|
|
750
815
|
| **Secure user chat** | CSL → ISL → CPE | Segment UI input, sanitize, wrap in envelope before sending to the model. |
|
|
751
|
-
| **Policy-based moderation** | CSL → ISL → emitSignal → AAL | Get risk signal from ISL, resolve ALLOW/WARN/BLOCK
|
|
752
|
-
| **Audit and compliance** | Shared audit formatters | Pretty-print CSL/ISL/AAL/CPE results
|
|
816
|
+
| **Policy-based moderation** | CSL → ISL → emitSignal → AAL | Get risk signal from ISL, resolve ALLOW/WARN/BLOCK; use `buildRemovalPlanFromResult` + `applyRemovalPlan` to get cleaned content for the LLM. |
|
|
817
|
+
| **Audit and compliance** | Shared audit formatters | Pretty-print CSL/ISL/AAL/CPE results; full pipeline with run id (`formatPipelineAuditFull`); JSON variant (`buildFullAuditPayload`, `formatPipelineAuditAsJson`) for SIEM; compact log entry (`buildAuditLogEntry`) for one-line logging. |
|
|
753
818
|
| **DOM / scraped content** | CSL (source: DOM) → ISL → CPE | Treat web content as untrusted (UC), apply aggressive sanitization. |
|
|
754
819
|
| **System instructions** | CSL (source: SYSTEM) → ISL → CPE | Trusted content (TC), minimal sanitization. |
|
|
755
820
|
| **Lineage and forensics** | All layers | Use lineage from results and `filterLineageByStep` / `getLastLineageEntry` for tracing. |
|
|
@@ -763,17 +828,35 @@ const signal = emitSignal(islResult)
|
|
|
763
828
|
const action = resolveAgentAction(signal, policy)
|
|
764
829
|
const reason = buildDecisionReason(action, signal, policy)
|
|
765
830
|
const plan = buildRemovalPlan(signal, policy)
|
|
766
|
-
|
|
831
|
+
const planFromResult = buildRemovalPlanFromResult(islResult, policy)
|
|
832
|
+
const cleanedResult = applyRemovalPlan(islResult, planFromResult)
|
|
833
|
+
// Use action, reason, plan; send cleanedResult.segments to the LLM when removal is enabled.
|
|
767
834
|
```
|
|
768
835
|
|
|
769
836
|
**Example: audit report**
|
|
770
837
|
|
|
771
838
|
```typescript
|
|
839
|
+
// Text report (CSL → ISL → CPE)
|
|
772
840
|
const report = formatPipelineAudit(cslResult, islResult, cpeResult, {
|
|
773
841
|
title: 'Request Audit',
|
|
774
842
|
sectionSeparator: '\n---\n'
|
|
775
843
|
})
|
|
776
844
|
logger.info(report)
|
|
845
|
+
|
|
846
|
+
// Full report with run id and Signal + AAL
|
|
847
|
+
const runId = createAuditRunId()
|
|
848
|
+
const fullReport = formatPipelineAuditFull(cslResult, islResult, signal, reason, removalPlan, cpeResult, {
|
|
849
|
+
runId, generatedAt: Date.now(), includeCpe: true
|
|
850
|
+
})
|
|
851
|
+
logger.info(fullReport)
|
|
852
|
+
|
|
853
|
+
// JSON for SIEM / machine consumption
|
|
854
|
+
const jsonReport = formatPipelineAuditAsJson(cslResult, islResult, signal, reason, { runId, generatedAt: Date.now(), removalPlan, compact: true })
|
|
855
|
+
logger.info(jsonReport)
|
|
856
|
+
|
|
857
|
+
// One-line log entry per request
|
|
858
|
+
const logEntry = buildAuditLogEntry(signal, reason, { runId, generatedAt: Date.now() })
|
|
859
|
+
logger.info(JSON.stringify(logEntry))
|
|
777
860
|
```
|
|
778
861
|
|
|
779
862
|
<a id="documentation"></a>
|
|
@@ -804,6 +887,7 @@ All AI-PIP protocol documentation is centralized in the [documentation repositor
|
|
|
804
887
|
### Code-Specific Documentation
|
|
805
888
|
|
|
806
889
|
- **[CHANGELOG](./CHANGELOG.md)** - Package version history
|
|
890
|
+
- **[FEATURE](./FEATURE.md)** - New and modified features by version
|
|
807
891
|
- **[API Reference](#-basic-usage)** - Usage examples in this README
|
|
808
892
|
|
|
809
893
|
<a id="testing"></a>
|
|
@@ -1000,6 +1084,11 @@ For SDK development updates and roadmap, see the [AI-PIP Documentation Repositor
|
|
|
1000
1084
|
|
|
1001
1085
|
For complete details and all version history, see [CHANGELOG.md](./CHANGELOG.md).
|
|
1002
1086
|
|
|
1087
|
+
<a id="features"></a>
|
|
1088
|
+
## 📋 Features
|
|
1089
|
+
|
|
1090
|
+
Summary of new and modified features per version (aligned with the changelog): **[FEATURE.md](./FEATURE.md)**.
|
|
1091
|
+
|
|
1003
1092
|
---
|
|
1004
1093
|
|
|
1005
1094
|
**Current Version**: 0.2.0
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AAL display constants - semantic mapping for SDK/UI.
|
|
3
|
+
* Used for consistent display of AAL decisions (e.g. colors).
|
|
4
|
+
*/
|
|
5
|
+
import type { AnomalyAction } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Display color for each AAL action.
|
|
8
|
+
* SDK/UI can use this for consistent styling (e.g. green = allow, yellow = warn, red = block).
|
|
9
|
+
*/
|
|
10
|
+
export declare const ACTION_DISPLAY_COLORS: Record<AnomalyAction, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Returns the display color for an AAL action.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getActionDisplayColor(action: AnomalyAction): string;
|
|
15
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/AAL/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAI9D,CAAA;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEnE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AAL display constants - semantic mapping for SDK/UI.
|
|
3
|
+
* Used for consistent display of AAL decisions (e.g. colors).
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Display color for each AAL action.
|
|
7
|
+
* SDK/UI can use this for consistent styling (e.g. green = allow, yellow = warn, red = block).
|
|
8
|
+
*/
|
|
9
|
+
export const ACTION_DISPLAY_COLORS = Object.freeze({
|
|
10
|
+
ALLOW: 'green',
|
|
11
|
+
WARN: 'yellow',
|
|
12
|
+
BLOCK: 'red'
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Returns the display color for an AAL action.
|
|
16
|
+
*/
|
|
17
|
+
export function getActionDisplayColor(action) {
|
|
18
|
+
return ACTION_DISPLAY_COLORS[action];
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/AAL/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAkC,MAAM,CAAC,MAAM,CAAC;IAChF,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,KAAK;CACb,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IACzD,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAA;AACtC,CAAC"}
|
package/dist/AAL/index.d.ts
CHANGED
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
*/
|
|
22
22
|
export { createAnomalyScore, isHighRisk, isLowRisk, isWarnRisk, isRoleProtected, isContextLeakPreventionEnabled, isInstructionImmutable, isIntentBlocked, isScopeSensitive } from './value-objects/index.js';
|
|
23
23
|
export type { AnomalyScore, PolicyRule } from './value-objects/index.js';
|
|
24
|
-
export { resolveAgentAction, resolveAgentActionWithScore, buildDecisionReason, buildRemovalPlan } from './process/index.js';
|
|
24
|
+
export { resolveAgentAction, resolveAgentActionWithScore, buildDecisionReason, buildRemovalPlan, buildRemovalPlanFromResult, applyRemovalPlan } from './process/index.js';
|
|
25
25
|
export type { DecisionReason, RemovalPlan } from './process/index.js';
|
|
26
26
|
export { buildAALLineage } from './lineage/index.js';
|
|
27
|
+
export { ACTION_DISPLAY_COLORS, getActionDisplayColor } from './constants.js';
|
|
27
28
|
export type { AnomalyAction, RemovedInstruction, BlockedIntent, SensitiveScope, ProtectedRole, ImmutableInstruction, AgentPolicy, } from './types.js';
|
|
28
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/AAL/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AAL/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EACH,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,8BAA8B,EAC9B,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,YAAY,EACR,YAAY,EACZ,UAAU,EACb,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACH,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EACnB,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EACR,cAAc,EACd,WAAW,EACd,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGpD,YAAY,EACR,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,WAAW,GACd,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AAL/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EACH,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,8BAA8B,EAC9B,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,YAAY,EACR,YAAY,EACZ,UAAU,EACb,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACH,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,0BAA0B,EAC1B,gBAAgB,EACnB,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EACR,cAAc,EACd,WAAW,EACd,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAG7E,YAAY,EACR,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,WAAW,GACd,MAAM,YAAY,CAAA"}
|
package/dist/AAL/index.js
CHANGED
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
// Value objects
|
|
23
23
|
export { createAnomalyScore, isHighRisk, isLowRisk, isWarnRisk, isRoleProtected, isContextLeakPreventionEnabled, isInstructionImmutable, isIntentBlocked, isScopeSensitive } from './value-objects/index.js';
|
|
24
24
|
// Process functions
|
|
25
|
-
export { resolveAgentAction, resolveAgentActionWithScore, buildDecisionReason, buildRemovalPlan } from './process/index.js';
|
|
25
|
+
export { resolveAgentAction, resolveAgentActionWithScore, buildDecisionReason, buildRemovalPlan, buildRemovalPlanFromResult, applyRemovalPlan } from './process/index.js';
|
|
26
26
|
// Lineage
|
|
27
27
|
export { buildAALLineage } from './lineage/index.js';
|
|
28
|
+
// Display constants (for SDK/UI)
|
|
29
|
+
export { ACTION_DISPLAY_COLORS, getActionDisplayColor } from './constants.js';
|
|
28
30
|
//# sourceMappingURL=index.js.map
|
package/dist/AAL/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/AAL/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gBAAgB;AAChB,OAAO,EACH,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,8BAA8B,EAC9B,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAOjC,oBAAoB;AACpB,OAAO,EACH,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EACnB,MAAM,oBAAoB,CAAA;AAO3B,UAAU;AACV,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/AAL/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gBAAgB;AAChB,OAAO,EACH,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,8BAA8B,EAC9B,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAOjC,oBAAoB;AACpB,OAAO,EACH,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,0BAA0B,EAC1B,gBAAgB,EACnB,MAAM,oBAAoB,CAAA;AAO3B,UAAU;AACV,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEpD,iCAAiC;AACjC,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* applyRemovalPlan - Applies a removal plan to ISL result (pure, deterministic).
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Removes malicious ranges from each segment's sanitizedContent according to the plan.
|
|
6
|
+
* Only instructions with segmentId are applied; others are skipped.
|
|
7
|
+
* Overlapping ranges per segment are merged before removal.
|
|
8
|
+
*/
|
|
9
|
+
import type { RemovalPlan } from './buildRemovalPlan.js';
|
|
10
|
+
import type { ISLResult } from '../../isl/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Applies a removal plan to an ISL result.
|
|
13
|
+
* Produces a new ISLResult with segment sanitizedContent updated (malicious ranges removed).
|
|
14
|
+
* Instructions without segmentId are ignored. Positions are clamped to [0, content.length] per segment; invalid or empty ranges are dropped. Lineage and metadata are preserved.
|
|
15
|
+
*
|
|
16
|
+
* @param islResult - ISL result (segments with sanitizedContent and optional piDetection)
|
|
17
|
+
* @param plan - Removal plan from buildRemovalPlanFromResult (must include segmentIds for removal)
|
|
18
|
+
* @returns New ISLResult with sanitizedContent updated per segment
|
|
19
|
+
*/
|
|
20
|
+
export declare function applyRemovalPlan(islResult: ISLResult, plan: RemovalPlan): ISLResult;
|
|
21
|
+
//# sourceMappingURL=applyRemovalPlan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyRemovalPlan.d.ts","sourceRoot":"","sources":["../../../src/AAL/process/applyRemovalPlan.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,oBAAoB,CAAA;AAwG/D;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,CAmCnF"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* applyRemovalPlan - Applies a removal plan to ISL result (pure, deterministic).
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Removes malicious ranges from each segment's sanitizedContent according to the plan.
|
|
6
|
+
* Only instructions with segmentId are applied; others are skipped.
|
|
7
|
+
* Overlapping ranges per segment are merged before removal.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Clamps position ranges to valid [0, contentLength) and drops empty or invalid ranges.
|
|
11
|
+
* Ensures 0 <= start <= end <= contentLength and start < end.
|
|
12
|
+
*/
|
|
13
|
+
function clampRangesToContent(ranges, contentLength) {
|
|
14
|
+
if (contentLength <= 0 || ranges.length === 0)
|
|
15
|
+
return [];
|
|
16
|
+
const result = [];
|
|
17
|
+
for (const r of ranges) {
|
|
18
|
+
const start = Math.max(0, Math.min(Number(r.start), contentLength));
|
|
19
|
+
const end = Math.max(0, Math.min(Number(r.end), contentLength));
|
|
20
|
+
if (start < end)
|
|
21
|
+
result.push({ start, end });
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Merges overlapping ranges (start inclusive, end exclusive). Sorted by start.
|
|
27
|
+
*/
|
|
28
|
+
function mergeRanges(ranges) {
|
|
29
|
+
if (ranges.length === 0)
|
|
30
|
+
return [];
|
|
31
|
+
const sorted = [...ranges].sort((a, b) => a.start - b.start);
|
|
32
|
+
const merged = [{ start: sorted[0].start, end: sorted[0].end }];
|
|
33
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
34
|
+
const r = sorted[i];
|
|
35
|
+
const last = merged.at(-1);
|
|
36
|
+
if (r.start <= last.end) {
|
|
37
|
+
merged[merged.length - 1] = { start: last.start, end: Math.max(last.end, r.end) };
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
merged.push({ start: r.start, end: r.end });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return merged;
|
|
44
|
+
}
|
|
45
|
+
/** Max gap (chars) between ranges to consider for merging when gap is only punctuation/whitespace */
|
|
46
|
+
const MAX_PUNCTUATION_GAP = 10;
|
|
47
|
+
/** True if the substring is only whitespace and/or common punctuation (no words). */
|
|
48
|
+
function isOnlyPunctuationOrWhitespace(s) {
|
|
49
|
+
return /^[\s.,;:!?'"-]*$/.test(s);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Merges consecutive ranges when the gap between them is only punctuation/whitespace,
|
|
53
|
+
* so we remove one contiguous block instead of leaving fragments like ", . ".
|
|
54
|
+
*/
|
|
55
|
+
function mergeAdjacentByPunctuation(ranges, content) {
|
|
56
|
+
if (ranges.length <= 1)
|
|
57
|
+
return [...ranges];
|
|
58
|
+
const result = [{ ...ranges[0] }];
|
|
59
|
+
for (let i = 1; i < ranges.length; i++) {
|
|
60
|
+
const r = ranges[i];
|
|
61
|
+
const last = result.at(-1);
|
|
62
|
+
const gapStart = last.end;
|
|
63
|
+
const gapEnd = r.start;
|
|
64
|
+
if (gapEnd > gapStart && gapEnd - gapStart <= MAX_PUNCTUATION_GAP) {
|
|
65
|
+
const gap = content.slice(gapStart, gapEnd);
|
|
66
|
+
if (isOnlyPunctuationOrWhitespace(gap)) {
|
|
67
|
+
result[result.length - 1] = { start: last.start, end: r.end };
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
result.push({ ...r });
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Removes given ranges from content. Ranges must be non-overlapping and sorted by start.
|
|
77
|
+
*/
|
|
78
|
+
function removeRanges(content, ranges) {
|
|
79
|
+
if (ranges.length === 0)
|
|
80
|
+
return content;
|
|
81
|
+
let result = '';
|
|
82
|
+
let pos = 0;
|
|
83
|
+
for (const r of ranges) {
|
|
84
|
+
if (r.start > pos)
|
|
85
|
+
result += content.slice(pos, r.start);
|
|
86
|
+
pos = Math.max(pos, r.end);
|
|
87
|
+
}
|
|
88
|
+
if (pos < content.length)
|
|
89
|
+
result += content.slice(pos);
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
function assertApplyRemovalPlanArgs(islResult, plan) {
|
|
93
|
+
if (islResult == null || typeof islResult !== 'object') {
|
|
94
|
+
throw new TypeError('AAL applyRemovalPlan: islResult must be a non-null object');
|
|
95
|
+
}
|
|
96
|
+
if (!Array.isArray(islResult.segments)) {
|
|
97
|
+
throw new TypeError('AAL applyRemovalPlan: islResult.segments must be an array');
|
|
98
|
+
}
|
|
99
|
+
if (plan == null || typeof plan !== 'object') {
|
|
100
|
+
throw new TypeError('AAL applyRemovalPlan: plan must be a non-null object');
|
|
101
|
+
}
|
|
102
|
+
if (!Array.isArray(plan.instructionsToRemove)) {
|
|
103
|
+
throw new TypeError('AAL applyRemovalPlan: plan.instructionsToRemove must be an array');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Applies a removal plan to an ISL result.
|
|
108
|
+
* Produces a new ISLResult with segment sanitizedContent updated (malicious ranges removed).
|
|
109
|
+
* Instructions without segmentId are ignored. Positions are clamped to [0, content.length] per segment; invalid or empty ranges are dropped. Lineage and metadata are preserved.
|
|
110
|
+
*
|
|
111
|
+
* @param islResult - ISL result (segments with sanitizedContent and optional piDetection)
|
|
112
|
+
* @param plan - Removal plan from buildRemovalPlanFromResult (must include segmentIds for removal)
|
|
113
|
+
* @returns New ISLResult with sanitizedContent updated per segment
|
|
114
|
+
*/
|
|
115
|
+
export function applyRemovalPlan(islResult, plan) {
|
|
116
|
+
assertApplyRemovalPlanArgs(islResult, plan);
|
|
117
|
+
if (!plan.shouldRemove || plan.instructionsToRemove.length === 0) {
|
|
118
|
+
return islResult;
|
|
119
|
+
}
|
|
120
|
+
const bySegmentId = new Map();
|
|
121
|
+
for (const inst of plan.instructionsToRemove) {
|
|
122
|
+
if (inst.segmentId == null)
|
|
123
|
+
continue;
|
|
124
|
+
const list = bySegmentId.get(inst.segmentId) ?? [];
|
|
125
|
+
list.push(inst.position);
|
|
126
|
+
bySegmentId.set(inst.segmentId, list);
|
|
127
|
+
}
|
|
128
|
+
if (bySegmentId.size === 0)
|
|
129
|
+
return islResult;
|
|
130
|
+
const newSegments = islResult.segments.map((seg) => {
|
|
131
|
+
const ranges = bySegmentId.get(seg.id);
|
|
132
|
+
if (ranges == null || ranges.length === 0)
|
|
133
|
+
return seg;
|
|
134
|
+
const content = seg.sanitizedContent ?? '';
|
|
135
|
+
const len = typeof content === 'string' ? content.length : 0;
|
|
136
|
+
const clamped = clampRangesToContent(ranges, len);
|
|
137
|
+
if (clamped.length === 0)
|
|
138
|
+
return seg;
|
|
139
|
+
const merged = mergeRanges(clamped);
|
|
140
|
+
const mergedAdjacent = mergeAdjacentByPunctuation(merged, content);
|
|
141
|
+
const newContent = removeRanges(content, mergedAdjacent);
|
|
142
|
+
return { ...seg, sanitizedContent: newContent };
|
|
143
|
+
});
|
|
144
|
+
return {
|
|
145
|
+
segments: Object.freeze(newSegments),
|
|
146
|
+
lineage: islResult.lineage,
|
|
147
|
+
metadata: islResult.metadata
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=applyRemovalPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyRemovalPlan.js","sourceRoot":"","sources":["../../../src/AAL/process/applyRemovalPlan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildDecisionReason.d.ts","sourceRoot":"","sources":["../../../src/AAL/process/buildDecisionReason.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;
|
|
1
|
+
{"version":3,"file":"buildDecisionReason.d.ts","sourceRoot":"","sources":["../../../src/AAL/process/buildDecisionReason.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AA2BD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,WAAW,GAClB,cAAc,CAgChB"}
|