avantgate 1.7.0 β†’ 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -86,17 +86,12 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
86
86
 
87
87
  ## πŸš€ Key Security & Defense Features
88
88
 
89
- - πŸ›‘οΈ **Active Threat Defense & Prompt Guardrails**: Blocks prompt injections, DAN jailbreaks, adversarial noise, and system prompt exfiltration *before* external API invocation.
90
- - πŸ”’ **Zero-Egress Data Loss Prevention (DLP)**: Automated local redaction of emails, phone numbers, IBAN/BIC, and French/EU identifiers (NIR SSN, SPI tax ID) before network egress.
91
- - ⚑ **Deterministic Workflow Engine (`avantgate/workflow`)**: In-process sequential state machine for multi-step agent orchestrations. Features automatic reverse compensation (Saga Pattern), non-blocking Human-in-the-Loop checkpoints, and safe-by-default AI tool conversion (`asTool()`).
92
- - 🎭 **Dual-Channel Tool Isolation (`avantgate/agent`)**: Decouples sensitive database records (streamed out-of-band directly to client UIs) from minimal cognitive LLM context (`llmDto`), keeping confidential fields out of context windows.
93
- - πŸ›‘ **Anti-IDOR & Multi-Tenant Defense**: Strict Row-Level Security, compile-time tenant tool enforcement (`createTenantTool`), post-fetch runtime assertions (`assertTenant`, `assertOwnership`), and native RBAC authorization at the agent tool boundary. See the [Anti-IDOR Architecture Guide](docs/anti-idor.md).
94
- - πŸ’° **Denial-of-Wallet & Pre-Flight Budgeting**: Enforces strict token and cent-level USD budget limits, rejecting abusive requests before paying for upstream inference.
95
- - πŸ”€ **Zero-Downtime Multi-Model Failover**: Seamless client-side failover to fallback providers (or local zero-cost Ollama) when upstream APIs return HTTP 429/500 errors.
96
- - πŸ”§ **Self-Repairing Structured Outputs**: Strict Zod schema compliance with automated heuristic markdown/JSON repair if the model hallucinates formatting.
97
- - πŸ“‘ **Zero-Dependency Telemetry Bridge (`HttpTelemetryExporter`, `PlatformStorageAdapter`)**: Mirror execution audits and hierarchical tool traces asynchronously without adding heavy external dependencies.
98
- - 🌐 **Lightweight Front-End SDK & React Hook (`avantgate/client`)**: Micro-bundle (< 1.7 KB gzipped) for browser UIs. Captures client-side security alerts (blocked API keys, prompt injection attempts), UI render metrics, and user feedback, streaming them directly to gateWall via `fetch(keepalive)` without loading backend infrastructure.
99
- - πŸ“¦ **100% Framework Agnostic**: Works seamlessly in Next.js, Express, Fastify, NestJS, Cloudflare Workers, AWS Lambda, or CLI scripts.
89
+ | Pillar | Core Capabilities & Architecture |
90
+ |---|---|
91
+ | πŸ›‘οΈ **AI-WAF & Privacy** | β€’ **Prompt Guardrails**: Blocks prompt injections, jailbreaks & exfiltration *pre-flight*.<br/>β€’ **Zero-Egress DLP**: In-process redaction of emails, phone numbers, IBANs & EU tax IDs.<br/>β€’ **Self-Repairing Outputs**: Native Zod validation with automatic JSON heuristic repair. |
92
+ | πŸ›‘ **Agent Isolation & Anti-IDOR** | β€’ **Dual-Channel DTOs**: Streams full records to UI while injecting sanitized summaries into LLM.<br/>β€’ **Anti-IDOR Boundary**: Compile-time tenant scoping (`createTenantTool`) & runtime ownership checks.<br/>β€’ **Infinite Loop Shield**: Detects and breaks recursive agent tool execution loops. |
93
+ | πŸ’° **FinOps & Resilience** | β€’ **Denial-of-Wallet**: Enforces hard token & USD budgets *before* external inference spend.<br/>β€’ **Multi-Model Failover**: Instant client-side routing to fallback models or local Ollama on 429/500.<br/>β€’ **Live Cost Ledger**: Token burn calculation & pricing adapters with zero external DB. |
94
+ | ⚑ **Sagas & Telemetry** | β€’ **Deterministic Sagas (`avantgate/workflow`)**: In-process FSM with automatic reverse compensation ($k-1 \to 0$).<br/>β€’ **Human-in-the-Loop (HITL)**: Non-blocking suspension & approval queues for high-risk tools.<br/>β€’ **Lightweight Telemetry (`avantgate/client`)**: < 1.7 KB client SDK & async audit bridge to GateWall. |
100
95
 
101
96
  ---
102
97
 
@@ -153,19 +148,6 @@ yarn add avantgate zod
153
148
 
154
149
  ---
155
150
 
156
- ## πŸ“– Documentation & Guides
157
-
158
- Comprehensive guides, copy-pasteable integration recipes, and architectural references are available in the dedicated documentation:
159
-
160
- | Guide | Description |
161
- |---|---|
162
- | **[Deterministic Workflow Engine](docs/workflow.md)** | Zero-infra Saga orchestrator, linear FSM rationale, reverse compensation, HITL checkpoints & agent tool conversion. |
163
- | **[Code Examples & Recipes](docs/examples.md)** | End-to-end security guardrails, PII redaction, anti-IDOR tool boundaries, cost tracking, Zod self-repair, and multi-model failover. |
164
- | **[Decoupled Pricing & DB Adapters](docs/pricing.md)** | Dynamic token pricing, database integration (Prisma / PostgreSQL / Drizzle), in-memory TTL caching, and runtime overrides. |
165
- | **[Durable Agent Harness & Tool Isolation](docs/agent.md)** | Serverless durable step execution, Human-in-the-Loop suspension, dual-channel DTO tool isolation, and telemetry streaming. |
166
-
167
- ---
168
-
169
151
  ## πŸ—οΈ Architecture & Extensibility
170
152
 
171
153
  AvantGate is built around clean **Ports and Adapters**:
@@ -177,41 +159,7 @@ AvantGate is built around clean **Ports and Adapters**:
177
159
 
178
160
  ## πŸ—ΊοΈ Roadmap & Milestones
179
161
 
180
- ### 🎯 Core Control Plane (`avantgate`)
181
-
182
- 1. ⏱️ **In-Process Sliding-Window Rate Limiter & User Quotas**
183
- - In-memory token bucket per User ID, IP address, or session without Redis.
184
- - Per-user daily & hourly token budget limits with automatic graceful throttling.
185
-
186
- 2. πŸ”’ **Bidirectional Sanitizer & Secret Leak Prevention**
187
- - Extend PII protection from input queries to **model outputs and audit logs**.
188
- - Active inspection to prevent LLM hallucinations from leaking server credentials, environment variables (`sk-...`, JWTs), or raw system instructions to client frontends.
189
-
190
- 3. ⚑ **Spend Velocity Circuit Breaker & Exponential Backoff**
191
- - Real-time spend velocity detection (trips if spend exceeds $X within Y minutes).
192
- - Configurable exponential backoff retries before triggering provider failover.
193
- - Safe degradation returning user-friendly messages instead of raw provider crashes.
194
-
195
- 4. βš–οΈ **Real-Time Evaluation Quality Gates**
196
- - Replace gut-feel and vibe-based evaluations with in-process, measurable output quality gates.
197
- - Built-in sub-millisecond heuristic gates:
198
- - **Refusal & Boilerplate Gate**: Detects unwanted refusal phrasing (*"As an AI..."*) and triggers fallback.
199
- - **Context Grounding Gate**: Verifies factual entity containment against supplied reference text.
200
- - Automated corrective retry loop (`onFailure: "retry_with_feedback"`) or instant model failover.
201
-
202
- 5. πŸ”Œ **Lifecycle Middleware Hooks (`beforeRequest`, `afterResponse`)**
203
- - Extensible middleware pipeline to inspect, enrich, or modify prompts and completions without modifying core logic.
204
- - Universal hook allowing any external RAG system or context engine to compose with AvantGate seamlessly.
205
-
206
- 6. πŸš€ **One-Line Launch-Safe Presets (`PRESETS.LAUNCH_SAFE`)**
207
- - Zero-config hardened setup with sensible defaults for security, budgets, and failovers.
208
-
209
- ### πŸ“¦ Modular Ecosystem & Extensions
210
-
211
- - **`avantgate/workflow`**: Deterministic sequential state machine, automatic reverse Saga rollback ($k-1 \to 0$), and durable HITL checkpoints.
212
- - **`avantgate/agent`**: Zero-infra durable step orchestration, human-in-the-loop pauses, and dual-channel PII tool isolation.
213
- - **`avantgate/finance`**: Zero-overhead financial accounting normalizer across international jurisdictions (FR PCG, US GAAP, UK IFRS, Swiss CO).
214
- - **Launch Readiness Linter**: Standalone developer tool to audit codebases before launch for exposed keys, unbudgeted endpoints, and missing guards.
162
+ Interested in upcoming features (output DLP & secret leak guard, lifecycle hooks, launch-safe presets) or release history See [**ROADMAP.md**](ROADMAP.md).
215
163
 
216
164
  ---
217
165
 
@@ -8,6 +8,7 @@ export declare class AvantGateControlLayer {
8
8
  private findProviderConfig;
9
9
  private calculateCost;
10
10
  private applySecurityGuards;
11
+ private applyOutputSecurityGuards;
11
12
  private checkPreflightBudget;
12
13
  private checkPostExecutionBudget;
13
14
  private buildMessages;
@@ -18,18 +19,12 @@ export declare class AvantGateControlLayer {
18
19
  private executeProviderPipeline;
19
20
  private assembleResult;
20
21
  private notifyAuditSink;
21
- /**
22
- * ExΓ©cute une requΓͺte avec garde d'entrΓ©e, masquage PII, garde prΓ©-vol et calcul des coΓ»ts.
23
- */
24
22
  execute: (options: {
25
23
  userQuery: string;
26
24
  systemPrompt?: string;
27
25
  temperature?: number;
28
26
  providerOverride?: LLMProviderPort;
29
27
  }) => Promise<ExecutionResult>;
30
- /**
31
- * ExΓ©cute une requΓͺte et valide/rΓ©pare le rΓ©sultat selon un schΓ©ma Zod.
32
- */
33
28
  executeStructured: <T>(options: {
34
29
  userQuery: string;
35
30
  systemPrompt?: string;
@@ -37,10 +32,16 @@ export declare class AvantGateControlLayer {
37
32
  temperature?: number;
38
33
  providerOverride?: LLMProviderPort;
39
34
  }) => Promise<StructuredExecutionResult<T>>;
40
- /**
41
- * MΓ©thode unifiΓ©e de premier niveau pour l'extraction structurΓ©e sans code boilerplate.
42
- * Gère le failover multi-fournisseurs, les retries, la validation Zod et la normalisation financière.
43
- */
35
+ private sanitizeIncomingMessages;
36
+ private verifyPromptBudget;
37
+ private dispatchOverrideAttempt;
38
+ private dispatchSimulatedAttempt;
39
+ private dispatchPipelineAttempt;
40
+ private dispatchProviderAttempt;
41
+ private parseAndValidateStructuredResult;
42
+ private buildStructuredResult;
43
+ private notifyAuditSinkSafe;
44
+ private waitRetryBackoff;
44
45
  generateStructuredOutput: <T>(options: GenerateStructuredOutputOptions<T>) => Promise<StructuredExecutionResult<T>>;
45
46
  }
46
47
  export declare const createLLMControlLayer: (config: ControlLayerConfig) => AvantGateControlLayer;
@@ -1 +1 @@
1
- {"version":3,"file":"control-layer.d.ts","sourceRoot":"","sources":["../src/control-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,+BAA+B,EAC/B,eAAe,EAIhB,MAAM,SAAS,CAAC;AAgBjB,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,oBAAoB,CAAC,CAAuB;gBAExC,MAAM,EAAE,kBAAkB;IAgBtC,OAAO,CAAC,qBAAqB,CAU3B;IAEF,OAAO,CAAC,kBAAkB,CAaxB;IAEF,OAAO,CAAC,aAAa,CAcnB;IAEF,OAAO,CAAC,mBAAmB,CAezB;IAEF,OAAO,CAAC,oBAAoB,CAkC1B;IAEF,OAAO,CAAC,wBAAwB,CAW9B;IAEF,OAAO,CAAC,aAAa,CAOnB;IAEF,OAAO,CAAC,aAAa,CAUnB;IAEF,OAAO,CAAC,gBAAgB,CAMtB;IAEF,OAAO,CAAC,iBAAiB,CAiBvB;IAEF,OAAO,CAAC,uBAAuB,CAmB7B;IAEF,OAAO,CAAC,uBAAuB,CA+B7B;IAEF,OAAO,CAAC,cAAc,CAoBpB;IAEF,OAAO,CAAC,eAAe,CAarB;IAEF;;OAEG;IACH,OAAO,GAAU,SAAS;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,eAAe,CAAC,CA2B1B;IAEF;;OAEG;IACH,iBAAiB,GAAU,CAAC,EAAE,SAAS;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAyBvC;IAEF;;;OAGG;IACH,wBAAwB,GAAU,CAAC,EACjC,SAAS,+BAA+B,CAAC,CAAC,CAAC,KAC1C,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAqHtC;CACH;AAED,eAAO,MAAM,qBAAqB,GAAI,QAAQ,kBAAkB,KAAG,qBAElE,CAAC;AAEF,eAAO,MAAM,eAAe,WAJkB,kBAAkB,KAAG,qBAIf,CAAC;AACrD,OAAO,EAAE,qBAAqB,IAAI,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"control-layer.d.ts","sourceRoot":"","sources":["../src/control-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,+BAA+B,EAC/B,eAAe,EAIhB,MAAM,SAAS,CAAC;AAiBjB,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,oBAAoB,CAAC,CAAuB;gBAExC,MAAM,EAAE,kBAAkB;IAgBtC,OAAO,CAAC,qBAAqB,CAU3B;IAEF,OAAO,CAAC,kBAAkB,CAaxB;IAEF,OAAO,CAAC,aAAa,CAcnB;IAEF,OAAO,CAAC,mBAAmB,CAezB;IAEF,OAAO,CAAC,yBAAyB,CAe/B;IAEF,OAAO,CAAC,oBAAoB,CAkC1B;IAEF,OAAO,CAAC,wBAAwB,CAW9B;IAEF,OAAO,CAAC,aAAa,CAOnB;IAEF,OAAO,CAAC,aAAa,CAUnB;IAEF,OAAO,CAAC,gBAAgB,CAMtB;IAEF,OAAO,CAAC,iBAAiB,CAsBvB;IAEF,OAAO,CAAC,uBAAuB,CAmB7B;IAEF,OAAO,CAAC,uBAAuB,CA+B7B;IAEF,OAAO,CAAC,cAAc,CAqBpB;IAEF,OAAO,CAAC,eAAe,CAarB;IAEF,OAAO,GAAU,SAAS;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,eAAe,CAAC,CA2B1B;IAGF,iBAAiB,GAAU,CAAC,EAAE,SAAS;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAyBvC;IAEF,OAAO,CAAC,wBAAwB,CAO9B;IAEF,OAAO,CAAC,kBAAkB,CAIxB;IAEF,OAAO,CAAC,uBAAuB,CAe7B;IAEF,OAAO,CAAC,wBAAwB,CAqB9B;IAEF,OAAO,CAAC,uBAAuB,CAkB7B;IAEF,OAAO,CAAC,uBAAuB,CAY7B;IAEF,OAAO,CAAC,gCAAgC,CAiBtC;IAEF,OAAO,CAAC,qBAAqB,CAwB3B;IAEF,OAAO,CAAC,mBAAmB,CAazB;IAEF,OAAO,CAAC,gBAAgB,CAQtB;IAEF,wBAAwB,GAAU,CAAC,EACjC,SAAS,+BAA+B,CAAC,CAAC,CAAC,KAC1C,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAwCtC;CACH;AAED,eAAO,MAAM,qBAAqB,GAAI,QAAQ,kBAAkB,KAAG,qBAElE,CAAC;AAEF,eAAO,MAAM,eAAe,WAJkB,kBAAkB,KAAG,qBAIf,CAAC;AACrD,OAAO,EAAE,qBAAqB,IAAI,kBAAkB,EAAE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export * from "./control-layer";
8
8
  export * from "./prompts";
9
9
  export * from "./providers/http-client";
10
10
  export * from "./workflow";
11
+ export * from "./secret-guard";
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  AvantGateBudgetExceededError: () => BudgetExceededError,
34
34
  AvantGateConfigurationError: () => ConfigurationError,
35
35
  AvantGateControlLayer: () => AvantGateControlLayer,
36
+ AvantGateSecretLeakBlockedError: () => SecretLeakBlockedError,
36
37
  BudgetExceededError: () => BudgetExceededError,
37
38
  CachedPricingAdapter: () => CachedPricingAdapter,
38
39
  ConfigurationError: () => ConfigurationError,
@@ -43,11 +44,13 @@ __export(index_exports, {
43
44
  PromptRegistry: () => PromptRegistry,
44
45
  PromptTemplate: () => PromptTemplate,
45
46
  SEED_MODEL_PRICES: () => SEED_MODEL_PRICES,
47
+ SecretLeakBlockedError: () => SecretLeakBlockedError,
46
48
  SqlitePricingAdapter: () => SqlitePricingAdapter,
47
49
  WorkflowAbortSignal: () => WorkflowAbortSignal,
48
50
  WorkflowSagaRollbackError: () => WorkflowSagaRollbackError,
49
51
  WorkflowValidationError: () => WorkflowValidationError,
50
52
  ZenLLMControlLayer: () => AvantGateControlLayer,
53
+ applyOutputGuards: () => applyOutputGuards,
51
54
  calculateCostUSD: () => calculateCostUSD,
52
55
  createAvantGate: () => createAvantGate,
53
56
  createHttpProviderClient: () => createHttpProviderClient,
@@ -59,6 +62,7 @@ __export(index_exports, {
59
62
  resolveModelPrice: () => resolveModelPrice,
60
63
  resolveModelPriceAsync: () => resolveModelPriceAsync,
61
64
  sanitizePII: () => sanitizePII,
65
+ sanitizeSecrets: () => sanitizeSecrets,
62
66
  validateUserInput: () => validateUserInput,
63
67
  validateWithZod: () => validateWithZod
64
68
  });
@@ -77,6 +81,14 @@ var BudgetExceededError = class extends Error {
77
81
  this.name = "BudgetExceededError";
78
82
  }
79
83
  };
84
+ var SecretLeakBlockedError = class extends Error {
85
+ detections;
86
+ constructor(message, detections) {
87
+ super(message);
88
+ this.name = "SecretLeakBlockedError";
89
+ this.detections = detections;
90
+ }
91
+ };
80
92
 
81
93
  // src/sqlite-pricing-adapter.ts
82
94
  var import_fs = __toESM(require("fs"));
@@ -1160,6 +1172,109 @@ var createHttpProviderClient = (config) => {
1160
1172
  return new HttpProviderClient(config);
1161
1173
  };
1162
1174
 
1175
+ // src/secret-guard.ts
1176
+ var SECRET_PATTERNS = [
1177
+ // 1. ClΓ©s privΓ©es (RSA, OpenSSH, EC, DSA)
1178
+ {
1179
+ type: "PRIVATE_KEY",
1180
+ regex: /-----BEGIN (?:[A-Z0-9_-]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9_-]+ )?PRIVATE KEY-----/g,
1181
+ mask: "[REDACTED_PRIVATE_KEY]"
1182
+ },
1183
+ // 2. ClΓ©s Anthropic Claude (avant OpenAI pour Γ©viter collision sk-)
1184
+ {
1185
+ type: "ANTHROPIC_API_KEY",
1186
+ regex: /\bsk-ant-(?:api\d{2}-)?[A-Za-z0-9_-]{20,}\b/g,
1187
+ mask: "[REDACTED_ANTHROPIC_KEY]"
1188
+ },
1189
+ // 3. ClΓ©s OpenAI (standard, projet, admin) - exclut explicitement sk-ant-
1190
+ {
1191
+ type: "OPENAI_API_KEY",
1192
+ regex: /\bsk-(?!ant-)(?:proj-|admin-|org-)?[A-Za-z0-9_-]{20,}\b/g,
1193
+ mask: "[REDACTED_OPENAI_KEY]"
1194
+ },
1195
+ // 4. ClΓ©s AWS Access Key ID
1196
+ {
1197
+ type: "AWS_ACCESS_KEY",
1198
+ regex: /\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b/g,
1199
+ mask: "[REDACTED_AWS_KEY]"
1200
+ },
1201
+ // 5. Tokens GitHub (Personal, OAuth, User, Server)
1202
+ {
1203
+ type: "GITHUB_TOKEN",
1204
+ regex: /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,255}\b/g,
1205
+ mask: "[REDACTED_GITHUB_TOKEN]"
1206
+ },
1207
+ // 6. JSON Web Tokens (JWT)
1208
+ {
1209
+ type: "JWT_TOKEN",
1210
+ regex: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}\.[A-Za-z0-9._-]{10,}\b/g,
1211
+ mask: "[REDACTED_JWT]"
1212
+ },
1213
+ // 7. Tokens Slack
1214
+ {
1215
+ type: "SLACK_TOKEN",
1216
+ regex: /\bxox[baprs]-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24,}\b/g,
1217
+ mask: "[REDACTED_SLACK_TOKEN]"
1218
+ },
1219
+ // 8. Mots de passe dans URL de connexion (Postgres, Mongo, Redis, MySQL)
1220
+ {
1221
+ type: "DATABASE_CONNECTION_SECRET",
1222
+ regex: /(?:postgres|postgresql|mysql|mongodb(?:\+srv)?|redis|amqp):\/\/[^:\s\/@]+:([^@\s]+)@/gi,
1223
+ mask: "[REDACTED_DB_SECRET]"
1224
+ }
1225
+ ];
1226
+ var sanitizeSecrets = (input) => {
1227
+ let text = input;
1228
+ const detections = [];
1229
+ for (const pattern of SECRET_PATTERNS) {
1230
+ let matchCount = 0;
1231
+ if (pattern.type === "DATABASE_CONNECTION_SECRET") {
1232
+ text = text.replace(pattern.regex, (fullMatch, password) => {
1233
+ matchCount++;
1234
+ return fullMatch.replace(password, pattern.mask);
1235
+ });
1236
+ } else {
1237
+ text = text.replace(pattern.regex, () => {
1238
+ matchCount++;
1239
+ return pattern.mask;
1240
+ });
1241
+ }
1242
+ if (matchCount > 0) {
1243
+ detections.push({ type: pattern.type, matchedCount: matchCount });
1244
+ }
1245
+ }
1246
+ return {
1247
+ text,
1248
+ hasSecrets: detections.length > 0,
1249
+ detections
1250
+ };
1251
+ };
1252
+ var applyOutputGuards = (rawOutput, options) => {
1253
+ let currentText = rawOutput;
1254
+ let piiCount = 0;
1255
+ if (options?.maskPII) {
1256
+ const piiResult = sanitizePII(currentText);
1257
+ currentText = piiResult.text;
1258
+ piiCount = piiResult.maskedCount;
1259
+ }
1260
+ const secretResult = sanitizeSecrets(currentText);
1261
+ currentText = secretResult.text;
1262
+ if (secretResult.hasSecrets && options?.secretLeakAction === "BLOCK") {
1263
+ const types = secretResult.detections.map((d) => d.type).join(", ");
1264
+ throw new SecretLeakBlockedError(
1265
+ `[AvantGate Output Guard] Response blocked: detected potential secret leak (${types})`,
1266
+ secretResult.detections
1267
+ );
1268
+ }
1269
+ return {
1270
+ text: currentText,
1271
+ sanitized: piiCount > 0 || secretResult.hasSecrets,
1272
+ secretDetected: secretResult.hasSecrets,
1273
+ piiMaskedCount: piiCount,
1274
+ detections: secretResult.detections
1275
+ };
1276
+ };
1277
+
1163
1278
  // src/control-layer.ts
1164
1279
  var AvantGateControlLayer = class {
1165
1280
  config;
@@ -1225,6 +1340,19 @@ var AvantGateControlLayer = class {
1225
1340
  }
1226
1341
  return userQuery;
1227
1342
  };
1343
+ applyOutputSecurityGuards = (rawOutput) => {
1344
+ const isDlpEnabled = this.config.security?.outputDLP ?? this.config.security?.maskPII ?? false;
1345
+ const shouldCheckSecrets = this.config.security?.blockSecretLeaks ?? true;
1346
+ if (!isDlpEnabled && !shouldCheckSecrets) {
1347
+ return rawOutput;
1348
+ }
1349
+ const guardResult = applyOutputGuards(rawOutput, {
1350
+ maskPII: isDlpEnabled,
1351
+ blockSecretLeaks: shouldCheckSecrets,
1352
+ secretLeakAction: this.config.security?.secretLeakAction ?? "REDACT"
1353
+ });
1354
+ return guardResult.text;
1355
+ };
1228
1356
  checkPreflightBudget = async (estimatedPromptTokens, targetModel, provider) => {
1229
1357
  if (this.config.maxTokenBudget !== void 0 && estimatedPromptTokens > this.config.maxTokenBudget) {
1230
1358
  throw new BudgetExceededError(
@@ -1291,19 +1419,20 @@ var AvantGateControlLayer = class {
1291
1419
  this.config.emergencyFallback
1292
1420
  ].filter((provider) => Boolean(provider?.client));
1293
1421
  };
1294
- executeSimulation = (query, systemPrompt) => {
1422
+ executeSimulation = (query, systemPrompt, modelOverride) => {
1423
+ const targetModel = modelOverride ?? this.config.primary.model;
1295
1424
  const promptTokens = Math.ceil(((systemPrompt?.length ?? 0) + query.length) / 4);
1296
1425
  const completionTokens = 50;
1297
- const cost = this.calculateCost(this.config.primary.model, promptTokens, completionTokens);
1426
+ const cost = this.calculateCost(targetModel, promptTokens, completionTokens);
1298
1427
  return {
1299
- text: `[AvantGate In-Process Engine] Response simulation for model: ${this.config.primary.model}`,
1428
+ text: `[AvantGate In-Process Engine] Response simulation for model: ${targetModel}`,
1300
1429
  tokens: {
1301
1430
  prompt: promptTokens,
1302
1431
  completion: completionTokens,
1303
1432
  total: promptTokens + completionTokens
1304
1433
  },
1305
1434
  costUSD: cost,
1306
- modelUsed: this.config.primary.model,
1435
+ modelUsed: targetModel,
1307
1436
  failoverOccurred: false,
1308
1437
  attempts: 1
1309
1438
  };
@@ -1350,6 +1479,7 @@ var AvantGateControlLayer = class {
1350
1479
  throw lastError;
1351
1480
  };
1352
1481
  assembleResult = (output) => {
1482
+ const sanitizedText = this.applyOutputSecurityGuards(output.responseText);
1353
1483
  const costUSD = this.calculateCost(
1354
1484
  output.modelUsed,
1355
1485
  output.usage.promptTokens,
@@ -1357,7 +1487,7 @@ var AvantGateControlLayer = class {
1357
1487
  output.usage.promptCacheHitTokens ?? 0
1358
1488
  );
1359
1489
  return {
1360
- text: output.responseText,
1490
+ text: sanitizedText,
1361
1491
  tokens: {
1362
1492
  prompt: output.usage.promptTokens,
1363
1493
  completion: output.usage.completionTokens,
@@ -1382,9 +1512,6 @@ var AvantGateControlLayer = class {
1382
1512
  attempts: result.attempts
1383
1513
  });
1384
1514
  };
1385
- /**
1386
- * ExΓ©cute une requΓͺte avec garde d'entrΓ©e, masquage PII, garde prΓ©-vol et calcul des coΓ»ts.
1387
- */
1388
1515
  execute = async (options) => {
1389
1516
  const sanitizedQuery = this.applySecurityGuards(options.userQuery);
1390
1517
  const messages = this.buildMessages(options.systemPrompt, sanitizedQuery);
@@ -1407,9 +1534,6 @@ var AvantGateControlLayer = class {
1407
1534
  await this.notifyAuditSink(result);
1408
1535
  return result;
1409
1536
  };
1410
- /**
1411
- * ExΓ©cute une requΓͺte et valide/rΓ©pare le rΓ©sultat selon un schΓ©ma Zod.
1412
- */
1413
1537
  executeStructured = async (options) => {
1414
1538
  const rawResult = await this.execute({
1415
1539
  userQuery: options.userQuery,
@@ -1433,106 +1557,147 @@ var AvantGateControlLayer = class {
1433
1557
  failoverOccurred: rawResult.failoverOccurred
1434
1558
  };
1435
1559
  };
1436
- /**
1437
- * MΓ©thode unifiΓ©e de premier niveau pour l'extraction structurΓ©e sans code boilerplate.
1438
- * Gère le failover multi-fournisseurs, les retries, la validation Zod et la normalisation financière.
1439
- */
1440
- generateStructuredOutput = async (options) => {
1441
- const maxRetries = options.maxRetries ?? this.config.retryOptions?.maxRetries ?? 2;
1442
- const modelToUse = options.model ?? this.config.primary.model;
1443
- const processedMessages = options.messages.map((msg) => {
1560
+ sanitizeIncomingMessages = (messages) => {
1561
+ return messages.map((msg) => {
1444
1562
  if (msg.role === "user") {
1445
1563
  return { ...msg, content: this.applySecurityGuards(msg.content) };
1446
1564
  }
1447
1565
  return msg;
1448
1566
  });
1449
- const promptLength = processedMessages.reduce((sum, msg) => sum + msg.content.length, 0);
1567
+ };
1568
+ verifyPromptBudget = async (messages, model) => {
1569
+ const promptLength = messages.reduce((sum, msg) => sum + msg.content.length, 0);
1450
1570
  const estimatedPromptTokens = Math.ceil(promptLength / 4);
1451
- await this.checkPreflightBudget(estimatedPromptTokens, modelToUse);
1571
+ await this.checkPreflightBudget(estimatedPromptTokens, model);
1572
+ };
1573
+ dispatchOverrideAttempt = async (override, messages, model, temperature) => {
1574
+ const res = await override.complete({ model, messages, temperature: temperature ?? 0.1 });
1575
+ const usage = this.resolveTokens(res.usage, JSON.stringify(messages), res.text);
1576
+ return {
1577
+ responseText: res.text,
1578
+ promptTokens: usage.promptTokens,
1579
+ completionTokens: usage.completionTokens,
1580
+ modelUsed: model,
1581
+ failoverOccurred: false
1582
+ };
1583
+ };
1584
+ dispatchSimulatedAttempt = (messages, modelOverride) => {
1585
+ if (!this.config.mockSimulation) {
1586
+ throw new ConfigurationError(
1587
+ "[AvantGate Configuration Error] No active LLM provider configured. Provide a client implementing LLMProviderPort or configure credentials (apiKey / baseUrl)."
1588
+ );
1589
+ }
1590
+ const sim = this.executeSimulation(JSON.stringify(messages), void 0, modelOverride);
1591
+ const responseText = sim.text.includes("{") ? sim.text : JSON.stringify({ simulation: true, model: sim.modelUsed });
1592
+ return {
1593
+ responseText,
1594
+ promptTokens: sim.tokens.prompt,
1595
+ completionTokens: sim.tokens.completion,
1596
+ modelUsed: sim.modelUsed,
1597
+ failoverOccurred: false
1598
+ };
1599
+ };
1600
+ dispatchPipelineAttempt = async (messages, modelOverride, temperature) => {
1601
+ const output = await this.executeProviderPipeline(
1602
+ messages,
1603
+ JSON.stringify(messages),
1604
+ temperature ?? 0.1,
1605
+ modelOverride
1606
+ );
1607
+ return {
1608
+ responseText: output.responseText,
1609
+ promptTokens: output.usage.promptTokens,
1610
+ completionTokens: output.usage.completionTokens,
1611
+ modelUsed: output.modelUsed,
1612
+ failoverOccurred: output.failoverOccurred
1613
+ };
1614
+ };
1615
+ dispatchProviderAttempt = async (options, messages, targetModel) => {
1616
+ if (options.providerOverride) {
1617
+ return this.dispatchOverrideAttempt(options.providerOverride, messages, targetModel, options.temperature);
1618
+ }
1619
+ if (this.getProviderChain().length === 0) {
1620
+ return this.dispatchSimulatedAttempt(messages, options.model);
1621
+ }
1622
+ return this.dispatchPipelineAttempt(messages, options.model ?? targetModel, options.temperature);
1623
+ };
1624
+ parseAndValidateStructuredResult = (rawText, options) => {
1625
+ const sanitizedResponse = this.applyOutputSecurityGuards(rawText);
1626
+ const isFinancial = options.financialNormalizer ?? Boolean(
1627
+ this.config.features?.finance?.enableFrenchAccounting || this.config.features?.finance
1628
+ );
1629
+ const parsedData = validateWithZod(sanitizedResponse, options.schema, {
1630
+ financialNormalizer: isFinancial,
1631
+ jurisdiction: this.config.features?.finance?.jurisdiction
1632
+ });
1633
+ return { parsedData, sanitizedResponse };
1634
+ };
1635
+ buildStructuredResult = (params) => {
1636
+ const totalTokens = params.promptTokens + params.completionTokens;
1637
+ const costUSD = this.calculateCost(params.modelUsed, params.promptTokens, params.completionTokens);
1638
+ this.checkPostExecutionBudget(totalTokens, costUSD);
1639
+ return {
1640
+ data: params.data,
1641
+ rawText: params.rawText,
1642
+ tokens: {
1643
+ prompt: params.promptTokens,
1644
+ completion: params.completionTokens,
1645
+ total: totalTokens
1646
+ },
1647
+ costUSD,
1648
+ modelUsed: params.modelUsed,
1649
+ failoverOccurred: params.failoverOccurred
1650
+ };
1651
+ };
1652
+ notifyAuditSinkSafe = async (sanitizedText, result, attempts) => {
1653
+ await this.notifyAuditSink({
1654
+ text: sanitizedText,
1655
+ tokens: result.tokens,
1656
+ costUSD: result.costUSD,
1657
+ modelUsed: result.modelUsed,
1658
+ failoverOccurred: result.failoverOccurred,
1659
+ attempts
1660
+ });
1661
+ };
1662
+ waitRetryBackoff = async (attempt, maxRetries) => {
1663
+ if (attempt >= maxRetries) {
1664
+ return;
1665
+ }
1666
+ const initialDelay = this.config.retryOptions?.initialDelayMs ?? 200;
1667
+ const factor = this.config.retryOptions?.backoffFactor ?? 1.5;
1668
+ const delay = initialDelay * Math.pow(factor, attempt);
1669
+ await new Promise((resolve) => setTimeout(resolve, delay));
1670
+ };
1671
+ generateStructuredOutput = async (options) => {
1672
+ const maxRetries = options.maxRetries ?? this.config.retryOptions?.maxRetries ?? 2;
1673
+ const targetModel = options.model ?? this.config.primary.model;
1674
+ const processedMessages = this.sanitizeIncomingMessages(options.messages);
1675
+ await this.verifyPromptBudget(processedMessages, targetModel);
1452
1676
  let lastError;
1453
1677
  let accumulatedPromptTokens = 0;
1454
1678
  let accumulatedCompletionTokens = 0;
1455
- let failoverOccurred = false;
1456
- let modelUsed = modelToUse;
1457
1679
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
1458
1680
  try {
1459
- let responseText = "";
1460
- let attemptPromptTokens = 0;
1461
- let attemptCompletionTokens = 0;
1462
- if (options.providerOverride) {
1463
- const res = await options.providerOverride.complete({
1464
- model: modelToUse,
1465
- messages: processedMessages,
1466
- temperature: options.temperature ?? 0.1
1467
- });
1468
- responseText = res.text;
1469
- const usage = this.resolveTokens(res.usage, JSON.stringify(processedMessages), responseText);
1470
- attemptPromptTokens = usage.promptTokens;
1471
- attemptCompletionTokens = usage.completionTokens;
1472
- modelUsed = modelToUse;
1473
- } else if (this.getProviderChain().length === 0) {
1474
- if (this.config.mockSimulation) {
1475
- const sim = this.executeSimulation(JSON.stringify(processedMessages));
1476
- responseText = sim.text;
1477
- attemptPromptTokens = sim.tokens.prompt;
1478
- attemptCompletionTokens = sim.tokens.completion;
1479
- } else {
1480
- throw new ConfigurationError(
1481
- "[AvantGate Configuration Error] No active LLM provider configured. Provide a client implementing LLMProviderPort or configure credentials (apiKey / baseUrl)."
1482
- );
1483
- }
1484
- } else {
1485
- const output = await this.executeProviderPipeline(
1486
- processedMessages,
1487
- JSON.stringify(processedMessages),
1488
- options.temperature ?? 0.1,
1489
- options.model
1490
- );
1491
- responseText = output.responseText;
1492
- attemptPromptTokens = output.usage.promptTokens;
1493
- attemptCompletionTokens = output.usage.completionTokens;
1494
- modelUsed = output.modelUsed;
1495
- failoverOccurred = output.failoverOccurred;
1496
- }
1497
- accumulatedPromptTokens += attemptPromptTokens;
1498
- accumulatedCompletionTokens += attemptCompletionTokens;
1499
- const isFinancial = options.financialNormalizer ?? Boolean(
1500
- this.config.features?.finance?.enableFrenchAccounting || this.config.features?.finance
1681
+ const output = await this.dispatchProviderAttempt(options, processedMessages, targetModel);
1682
+ accumulatedPromptTokens += output.promptTokens;
1683
+ accumulatedCompletionTokens += output.completionTokens;
1684
+ const { parsedData, sanitizedResponse } = this.parseAndValidateStructuredResult(
1685
+ output.responseText,
1686
+ options
1501
1687
  );
1502
- const parsedData = validateWithZod(responseText, options.schema, {
1503
- financialNormalizer: isFinancial,
1504
- jurisdiction: this.config.features?.finance?.jurisdiction
1505
- });
1506
- const totalTokens = accumulatedPromptTokens + accumulatedCompletionTokens;
1507
- const costUSD = this.calculateCost(modelUsed, accumulatedPromptTokens, accumulatedCompletionTokens);
1508
- this.checkPostExecutionBudget(totalTokens, costUSD);
1509
- const result = {
1688
+ const result = this.buildStructuredResult({
1510
1689
  data: parsedData,
1511
- rawText: responseText,
1512
- tokens: {
1513
- prompt: accumulatedPromptTokens,
1514
- completion: accumulatedCompletionTokens,
1515
- total: totalTokens
1516
- },
1517
- costUSD,
1518
- modelUsed,
1519
- failoverOccurred
1520
- };
1521
- await this.notifyAuditSink({
1522
- text: responseText,
1523
- tokens: result.tokens,
1524
- costUSD: result.costUSD,
1525
- modelUsed: result.modelUsed,
1526
- failoverOccurred: result.failoverOccurred,
1527
- attempts: attempt + 1
1690
+ rawText: sanitizedResponse,
1691
+ promptTokens: accumulatedPromptTokens,
1692
+ completionTokens: accumulatedCompletionTokens,
1693
+ modelUsed: output.modelUsed,
1694
+ failoverOccurred: output.failoverOccurred
1528
1695
  });
1696
+ await this.notifyAuditSinkSafe(sanitizedResponse, result, attempt + 1);
1529
1697
  return result;
1530
1698
  } catch (err) {
1531
1699
  lastError = err;
1532
- if (attempt < maxRetries) {
1533
- const delay = (this.config.retryOptions?.initialDelayMs ?? 200) * Math.pow(this.config.retryOptions?.backoffFactor ?? 1.5, attempt);
1534
- await new Promise((resolve) => setTimeout(resolve, delay));
1535
- }
1700
+ await this.waitRetryBackoff(attempt, maxRetries);
1536
1701
  }
1537
1702
  }
1538
1703
  throw lastError;
@@ -2449,6 +2614,7 @@ var defineWorkflow = (config) => {
2449
2614
  AvantGateBudgetExceededError,
2450
2615
  AvantGateConfigurationError,
2451
2616
  AvantGateControlLayer,
2617
+ AvantGateSecretLeakBlockedError,
2452
2618
  BudgetExceededError,
2453
2619
  CachedPricingAdapter,
2454
2620
  ConfigurationError,
@@ -2459,11 +2625,13 @@ var defineWorkflow = (config) => {
2459
2625
  PromptRegistry,
2460
2626
  PromptTemplate,
2461
2627
  SEED_MODEL_PRICES,
2628
+ SecretLeakBlockedError,
2462
2629
  SqlitePricingAdapter,
2463
2630
  WorkflowAbortSignal,
2464
2631
  WorkflowSagaRollbackError,
2465
2632
  WorkflowValidationError,
2466
2633
  ZenLLMControlLayer,
2634
+ applyOutputGuards,
2467
2635
  calculateCostUSD,
2468
2636
  createAvantGate,
2469
2637
  createHttpProviderClient,
@@ -2475,6 +2643,7 @@ var defineWorkflow = (config) => {
2475
2643
  resolveModelPrice,
2476
2644
  resolveModelPriceAsync,
2477
2645
  sanitizePII,
2646
+ sanitizeSecrets,
2478
2647
  validateUserInput,
2479
2648
  validateWithZod
2480
2649
  });
package/dist/index.mjs CHANGED
@@ -30,6 +30,14 @@ var BudgetExceededError = class extends Error {
30
30
  this.name = "BudgetExceededError";
31
31
  }
32
32
  };
33
+ var SecretLeakBlockedError = class extends Error {
34
+ detections;
35
+ constructor(message, detections) {
36
+ super(message);
37
+ this.name = "SecretLeakBlockedError";
38
+ this.detections = detections;
39
+ }
40
+ };
33
41
 
34
42
  // src/sqlite-pricing-adapter.ts
35
43
  import fs from "fs";
@@ -554,6 +562,109 @@ var createHttpProviderClient = (config) => {
554
562
  return new HttpProviderClient(config);
555
563
  };
556
564
 
565
+ // src/secret-guard.ts
566
+ var SECRET_PATTERNS = [
567
+ // 1. ClΓ©s privΓ©es (RSA, OpenSSH, EC, DSA)
568
+ {
569
+ type: "PRIVATE_KEY",
570
+ regex: /-----BEGIN (?:[A-Z0-9_-]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9_-]+ )?PRIVATE KEY-----/g,
571
+ mask: "[REDACTED_PRIVATE_KEY]"
572
+ },
573
+ // 2. ClΓ©s Anthropic Claude (avant OpenAI pour Γ©viter collision sk-)
574
+ {
575
+ type: "ANTHROPIC_API_KEY",
576
+ regex: /\bsk-ant-(?:api\d{2}-)?[A-Za-z0-9_-]{20,}\b/g,
577
+ mask: "[REDACTED_ANTHROPIC_KEY]"
578
+ },
579
+ // 3. ClΓ©s OpenAI (standard, projet, admin) - exclut explicitement sk-ant-
580
+ {
581
+ type: "OPENAI_API_KEY",
582
+ regex: /\bsk-(?!ant-)(?:proj-|admin-|org-)?[A-Za-z0-9_-]{20,}\b/g,
583
+ mask: "[REDACTED_OPENAI_KEY]"
584
+ },
585
+ // 4. ClΓ©s AWS Access Key ID
586
+ {
587
+ type: "AWS_ACCESS_KEY",
588
+ regex: /\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b/g,
589
+ mask: "[REDACTED_AWS_KEY]"
590
+ },
591
+ // 5. Tokens GitHub (Personal, OAuth, User, Server)
592
+ {
593
+ type: "GITHUB_TOKEN",
594
+ regex: /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,255}\b/g,
595
+ mask: "[REDACTED_GITHUB_TOKEN]"
596
+ },
597
+ // 6. JSON Web Tokens (JWT)
598
+ {
599
+ type: "JWT_TOKEN",
600
+ regex: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}\.[A-Za-z0-9._-]{10,}\b/g,
601
+ mask: "[REDACTED_JWT]"
602
+ },
603
+ // 7. Tokens Slack
604
+ {
605
+ type: "SLACK_TOKEN",
606
+ regex: /\bxox[baprs]-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24,}\b/g,
607
+ mask: "[REDACTED_SLACK_TOKEN]"
608
+ },
609
+ // 8. Mots de passe dans URL de connexion (Postgres, Mongo, Redis, MySQL)
610
+ {
611
+ type: "DATABASE_CONNECTION_SECRET",
612
+ regex: /(?:postgres|postgresql|mysql|mongodb(?:\+srv)?|redis|amqp):\/\/[^:\s\/@]+:([^@\s]+)@/gi,
613
+ mask: "[REDACTED_DB_SECRET]"
614
+ }
615
+ ];
616
+ var sanitizeSecrets = (input) => {
617
+ let text = input;
618
+ const detections = [];
619
+ for (const pattern of SECRET_PATTERNS) {
620
+ let matchCount = 0;
621
+ if (pattern.type === "DATABASE_CONNECTION_SECRET") {
622
+ text = text.replace(pattern.regex, (fullMatch, password) => {
623
+ matchCount++;
624
+ return fullMatch.replace(password, pattern.mask);
625
+ });
626
+ } else {
627
+ text = text.replace(pattern.regex, () => {
628
+ matchCount++;
629
+ return pattern.mask;
630
+ });
631
+ }
632
+ if (matchCount > 0) {
633
+ detections.push({ type: pattern.type, matchedCount: matchCount });
634
+ }
635
+ }
636
+ return {
637
+ text,
638
+ hasSecrets: detections.length > 0,
639
+ detections
640
+ };
641
+ };
642
+ var applyOutputGuards = (rawOutput, options) => {
643
+ let currentText = rawOutput;
644
+ let piiCount = 0;
645
+ if (options?.maskPII) {
646
+ const piiResult = sanitizePII(currentText);
647
+ currentText = piiResult.text;
648
+ piiCount = piiResult.maskedCount;
649
+ }
650
+ const secretResult = sanitizeSecrets(currentText);
651
+ currentText = secretResult.text;
652
+ if (secretResult.hasSecrets && options?.secretLeakAction === "BLOCK") {
653
+ const types = secretResult.detections.map((d) => d.type).join(", ");
654
+ throw new SecretLeakBlockedError(
655
+ `[AvantGate Output Guard] Response blocked: detected potential secret leak (${types})`,
656
+ secretResult.detections
657
+ );
658
+ }
659
+ return {
660
+ text: currentText,
661
+ sanitized: piiCount > 0 || secretResult.hasSecrets,
662
+ secretDetected: secretResult.hasSecrets,
663
+ piiMaskedCount: piiCount,
664
+ detections: secretResult.detections
665
+ };
666
+ };
667
+
557
668
  // src/control-layer.ts
558
669
  var AvantGateControlLayer = class {
559
670
  config;
@@ -619,6 +730,19 @@ var AvantGateControlLayer = class {
619
730
  }
620
731
  return userQuery;
621
732
  };
733
+ applyOutputSecurityGuards = (rawOutput) => {
734
+ const isDlpEnabled = this.config.security?.outputDLP ?? this.config.security?.maskPII ?? false;
735
+ const shouldCheckSecrets = this.config.security?.blockSecretLeaks ?? true;
736
+ if (!isDlpEnabled && !shouldCheckSecrets) {
737
+ return rawOutput;
738
+ }
739
+ const guardResult = applyOutputGuards(rawOutput, {
740
+ maskPII: isDlpEnabled,
741
+ blockSecretLeaks: shouldCheckSecrets,
742
+ secretLeakAction: this.config.security?.secretLeakAction ?? "REDACT"
743
+ });
744
+ return guardResult.text;
745
+ };
622
746
  checkPreflightBudget = async (estimatedPromptTokens, targetModel, provider) => {
623
747
  if (this.config.maxTokenBudget !== void 0 && estimatedPromptTokens > this.config.maxTokenBudget) {
624
748
  throw new BudgetExceededError(
@@ -685,19 +809,20 @@ var AvantGateControlLayer = class {
685
809
  this.config.emergencyFallback
686
810
  ].filter((provider) => Boolean(provider?.client));
687
811
  };
688
- executeSimulation = (query, systemPrompt) => {
812
+ executeSimulation = (query, systemPrompt, modelOverride) => {
813
+ const targetModel = modelOverride ?? this.config.primary.model;
689
814
  const promptTokens = Math.ceil(((systemPrompt?.length ?? 0) + query.length) / 4);
690
815
  const completionTokens = 50;
691
- const cost = this.calculateCost(this.config.primary.model, promptTokens, completionTokens);
816
+ const cost = this.calculateCost(targetModel, promptTokens, completionTokens);
692
817
  return {
693
- text: `[AvantGate In-Process Engine] Response simulation for model: ${this.config.primary.model}`,
818
+ text: `[AvantGate In-Process Engine] Response simulation for model: ${targetModel}`,
694
819
  tokens: {
695
820
  prompt: promptTokens,
696
821
  completion: completionTokens,
697
822
  total: promptTokens + completionTokens
698
823
  },
699
824
  costUSD: cost,
700
- modelUsed: this.config.primary.model,
825
+ modelUsed: targetModel,
701
826
  failoverOccurred: false,
702
827
  attempts: 1
703
828
  };
@@ -744,6 +869,7 @@ var AvantGateControlLayer = class {
744
869
  throw lastError;
745
870
  };
746
871
  assembleResult = (output) => {
872
+ const sanitizedText = this.applyOutputSecurityGuards(output.responseText);
747
873
  const costUSD = this.calculateCost(
748
874
  output.modelUsed,
749
875
  output.usage.promptTokens,
@@ -751,7 +877,7 @@ var AvantGateControlLayer = class {
751
877
  output.usage.promptCacheHitTokens ?? 0
752
878
  );
753
879
  return {
754
- text: output.responseText,
880
+ text: sanitizedText,
755
881
  tokens: {
756
882
  prompt: output.usage.promptTokens,
757
883
  completion: output.usage.completionTokens,
@@ -776,9 +902,6 @@ var AvantGateControlLayer = class {
776
902
  attempts: result.attempts
777
903
  });
778
904
  };
779
- /**
780
- * ExΓ©cute une requΓͺte avec garde d'entrΓ©e, masquage PII, garde prΓ©-vol et calcul des coΓ»ts.
781
- */
782
905
  execute = async (options) => {
783
906
  const sanitizedQuery = this.applySecurityGuards(options.userQuery);
784
907
  const messages = this.buildMessages(options.systemPrompt, sanitizedQuery);
@@ -801,9 +924,6 @@ var AvantGateControlLayer = class {
801
924
  await this.notifyAuditSink(result);
802
925
  return result;
803
926
  };
804
- /**
805
- * ExΓ©cute une requΓͺte et valide/rΓ©pare le rΓ©sultat selon un schΓ©ma Zod.
806
- */
807
927
  executeStructured = async (options) => {
808
928
  const rawResult = await this.execute({
809
929
  userQuery: options.userQuery,
@@ -827,106 +947,147 @@ var AvantGateControlLayer = class {
827
947
  failoverOccurred: rawResult.failoverOccurred
828
948
  };
829
949
  };
830
- /**
831
- * MΓ©thode unifiΓ©e de premier niveau pour l'extraction structurΓ©e sans code boilerplate.
832
- * Gère le failover multi-fournisseurs, les retries, la validation Zod et la normalisation financière.
833
- */
834
- generateStructuredOutput = async (options) => {
835
- const maxRetries = options.maxRetries ?? this.config.retryOptions?.maxRetries ?? 2;
836
- const modelToUse = options.model ?? this.config.primary.model;
837
- const processedMessages = options.messages.map((msg) => {
950
+ sanitizeIncomingMessages = (messages) => {
951
+ return messages.map((msg) => {
838
952
  if (msg.role === "user") {
839
953
  return { ...msg, content: this.applySecurityGuards(msg.content) };
840
954
  }
841
955
  return msg;
842
956
  });
843
- const promptLength = processedMessages.reduce((sum, msg) => sum + msg.content.length, 0);
957
+ };
958
+ verifyPromptBudget = async (messages, model) => {
959
+ const promptLength = messages.reduce((sum, msg) => sum + msg.content.length, 0);
844
960
  const estimatedPromptTokens = Math.ceil(promptLength / 4);
845
- await this.checkPreflightBudget(estimatedPromptTokens, modelToUse);
961
+ await this.checkPreflightBudget(estimatedPromptTokens, model);
962
+ };
963
+ dispatchOverrideAttempt = async (override, messages, model, temperature) => {
964
+ const res = await override.complete({ model, messages, temperature: temperature ?? 0.1 });
965
+ const usage = this.resolveTokens(res.usage, JSON.stringify(messages), res.text);
966
+ return {
967
+ responseText: res.text,
968
+ promptTokens: usage.promptTokens,
969
+ completionTokens: usage.completionTokens,
970
+ modelUsed: model,
971
+ failoverOccurred: false
972
+ };
973
+ };
974
+ dispatchSimulatedAttempt = (messages, modelOverride) => {
975
+ if (!this.config.mockSimulation) {
976
+ throw new ConfigurationError(
977
+ "[AvantGate Configuration Error] No active LLM provider configured. Provide a client implementing LLMProviderPort or configure credentials (apiKey / baseUrl)."
978
+ );
979
+ }
980
+ const sim = this.executeSimulation(JSON.stringify(messages), void 0, modelOverride);
981
+ const responseText = sim.text.includes("{") ? sim.text : JSON.stringify({ simulation: true, model: sim.modelUsed });
982
+ return {
983
+ responseText,
984
+ promptTokens: sim.tokens.prompt,
985
+ completionTokens: sim.tokens.completion,
986
+ modelUsed: sim.modelUsed,
987
+ failoverOccurred: false
988
+ };
989
+ };
990
+ dispatchPipelineAttempt = async (messages, modelOverride, temperature) => {
991
+ const output = await this.executeProviderPipeline(
992
+ messages,
993
+ JSON.stringify(messages),
994
+ temperature ?? 0.1,
995
+ modelOverride
996
+ );
997
+ return {
998
+ responseText: output.responseText,
999
+ promptTokens: output.usage.promptTokens,
1000
+ completionTokens: output.usage.completionTokens,
1001
+ modelUsed: output.modelUsed,
1002
+ failoverOccurred: output.failoverOccurred
1003
+ };
1004
+ };
1005
+ dispatchProviderAttempt = async (options, messages, targetModel) => {
1006
+ if (options.providerOverride) {
1007
+ return this.dispatchOverrideAttempt(options.providerOverride, messages, targetModel, options.temperature);
1008
+ }
1009
+ if (this.getProviderChain().length === 0) {
1010
+ return this.dispatchSimulatedAttempt(messages, options.model);
1011
+ }
1012
+ return this.dispatchPipelineAttempt(messages, options.model ?? targetModel, options.temperature);
1013
+ };
1014
+ parseAndValidateStructuredResult = (rawText, options) => {
1015
+ const sanitizedResponse = this.applyOutputSecurityGuards(rawText);
1016
+ const isFinancial = options.financialNormalizer ?? Boolean(
1017
+ this.config.features?.finance?.enableFrenchAccounting || this.config.features?.finance
1018
+ );
1019
+ const parsedData = validateWithZod(sanitizedResponse, options.schema, {
1020
+ financialNormalizer: isFinancial,
1021
+ jurisdiction: this.config.features?.finance?.jurisdiction
1022
+ });
1023
+ return { parsedData, sanitizedResponse };
1024
+ };
1025
+ buildStructuredResult = (params) => {
1026
+ const totalTokens = params.promptTokens + params.completionTokens;
1027
+ const costUSD = this.calculateCost(params.modelUsed, params.promptTokens, params.completionTokens);
1028
+ this.checkPostExecutionBudget(totalTokens, costUSD);
1029
+ return {
1030
+ data: params.data,
1031
+ rawText: params.rawText,
1032
+ tokens: {
1033
+ prompt: params.promptTokens,
1034
+ completion: params.completionTokens,
1035
+ total: totalTokens
1036
+ },
1037
+ costUSD,
1038
+ modelUsed: params.modelUsed,
1039
+ failoverOccurred: params.failoverOccurred
1040
+ };
1041
+ };
1042
+ notifyAuditSinkSafe = async (sanitizedText, result, attempts) => {
1043
+ await this.notifyAuditSink({
1044
+ text: sanitizedText,
1045
+ tokens: result.tokens,
1046
+ costUSD: result.costUSD,
1047
+ modelUsed: result.modelUsed,
1048
+ failoverOccurred: result.failoverOccurred,
1049
+ attempts
1050
+ });
1051
+ };
1052
+ waitRetryBackoff = async (attempt, maxRetries) => {
1053
+ if (attempt >= maxRetries) {
1054
+ return;
1055
+ }
1056
+ const initialDelay = this.config.retryOptions?.initialDelayMs ?? 200;
1057
+ const factor = this.config.retryOptions?.backoffFactor ?? 1.5;
1058
+ const delay = initialDelay * Math.pow(factor, attempt);
1059
+ await new Promise((resolve) => setTimeout(resolve, delay));
1060
+ };
1061
+ generateStructuredOutput = async (options) => {
1062
+ const maxRetries = options.maxRetries ?? this.config.retryOptions?.maxRetries ?? 2;
1063
+ const targetModel = options.model ?? this.config.primary.model;
1064
+ const processedMessages = this.sanitizeIncomingMessages(options.messages);
1065
+ await this.verifyPromptBudget(processedMessages, targetModel);
846
1066
  let lastError;
847
1067
  let accumulatedPromptTokens = 0;
848
1068
  let accumulatedCompletionTokens = 0;
849
- let failoverOccurred = false;
850
- let modelUsed = modelToUse;
851
1069
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
852
1070
  try {
853
- let responseText = "";
854
- let attemptPromptTokens = 0;
855
- let attemptCompletionTokens = 0;
856
- if (options.providerOverride) {
857
- const res = await options.providerOverride.complete({
858
- model: modelToUse,
859
- messages: processedMessages,
860
- temperature: options.temperature ?? 0.1
861
- });
862
- responseText = res.text;
863
- const usage = this.resolveTokens(res.usage, JSON.stringify(processedMessages), responseText);
864
- attemptPromptTokens = usage.promptTokens;
865
- attemptCompletionTokens = usage.completionTokens;
866
- modelUsed = modelToUse;
867
- } else if (this.getProviderChain().length === 0) {
868
- if (this.config.mockSimulation) {
869
- const sim = this.executeSimulation(JSON.stringify(processedMessages));
870
- responseText = sim.text;
871
- attemptPromptTokens = sim.tokens.prompt;
872
- attemptCompletionTokens = sim.tokens.completion;
873
- } else {
874
- throw new ConfigurationError(
875
- "[AvantGate Configuration Error] No active LLM provider configured. Provide a client implementing LLMProviderPort or configure credentials (apiKey / baseUrl)."
876
- );
877
- }
878
- } else {
879
- const output = await this.executeProviderPipeline(
880
- processedMessages,
881
- JSON.stringify(processedMessages),
882
- options.temperature ?? 0.1,
883
- options.model
884
- );
885
- responseText = output.responseText;
886
- attemptPromptTokens = output.usage.promptTokens;
887
- attemptCompletionTokens = output.usage.completionTokens;
888
- modelUsed = output.modelUsed;
889
- failoverOccurred = output.failoverOccurred;
890
- }
891
- accumulatedPromptTokens += attemptPromptTokens;
892
- accumulatedCompletionTokens += attemptCompletionTokens;
893
- const isFinancial = options.financialNormalizer ?? Boolean(
894
- this.config.features?.finance?.enableFrenchAccounting || this.config.features?.finance
1071
+ const output = await this.dispatchProviderAttempt(options, processedMessages, targetModel);
1072
+ accumulatedPromptTokens += output.promptTokens;
1073
+ accumulatedCompletionTokens += output.completionTokens;
1074
+ const { parsedData, sanitizedResponse } = this.parseAndValidateStructuredResult(
1075
+ output.responseText,
1076
+ options
895
1077
  );
896
- const parsedData = validateWithZod(responseText, options.schema, {
897
- financialNormalizer: isFinancial,
898
- jurisdiction: this.config.features?.finance?.jurisdiction
899
- });
900
- const totalTokens = accumulatedPromptTokens + accumulatedCompletionTokens;
901
- const costUSD = this.calculateCost(modelUsed, accumulatedPromptTokens, accumulatedCompletionTokens);
902
- this.checkPostExecutionBudget(totalTokens, costUSD);
903
- const result = {
1078
+ const result = this.buildStructuredResult({
904
1079
  data: parsedData,
905
- rawText: responseText,
906
- tokens: {
907
- prompt: accumulatedPromptTokens,
908
- completion: accumulatedCompletionTokens,
909
- total: totalTokens
910
- },
911
- costUSD,
912
- modelUsed,
913
- failoverOccurred
914
- };
915
- await this.notifyAuditSink({
916
- text: responseText,
917
- tokens: result.tokens,
918
- costUSD: result.costUSD,
919
- modelUsed: result.modelUsed,
920
- failoverOccurred: result.failoverOccurred,
921
- attempts: attempt + 1
1080
+ rawText: sanitizedResponse,
1081
+ promptTokens: accumulatedPromptTokens,
1082
+ completionTokens: accumulatedCompletionTokens,
1083
+ modelUsed: output.modelUsed,
1084
+ failoverOccurred: output.failoverOccurred
922
1085
  });
1086
+ await this.notifyAuditSinkSafe(sanitizedResponse, result, attempt + 1);
923
1087
  return result;
924
1088
  } catch (err) {
925
1089
  lastError = err;
926
- if (attempt < maxRetries) {
927
- const delay = (this.config.retryOptions?.initialDelayMs ?? 200) * Math.pow(this.config.retryOptions?.backoffFactor ?? 1.5, attempt);
928
- await new Promise((resolve) => setTimeout(resolve, delay));
929
- }
1090
+ await this.waitRetryBackoff(attempt, maxRetries);
930
1091
  }
931
1092
  }
932
1093
  throw lastError;
@@ -1255,6 +1416,7 @@ export {
1255
1416
  BudgetExceededError as AvantGateBudgetExceededError,
1256
1417
  ConfigurationError as AvantGateConfigurationError,
1257
1418
  AvantGateControlLayer,
1419
+ SecretLeakBlockedError as AvantGateSecretLeakBlockedError,
1258
1420
  BudgetExceededError,
1259
1421
  CachedPricingAdapter,
1260
1422
  ConfigurationError,
@@ -1265,11 +1427,13 @@ export {
1265
1427
  PromptRegistry,
1266
1428
  PromptTemplate,
1267
1429
  SEED_MODEL_PRICES,
1430
+ SecretLeakBlockedError,
1268
1431
  SqlitePricingAdapter,
1269
1432
  WorkflowAbortSignal,
1270
1433
  WorkflowSagaRollbackError,
1271
1434
  WorkflowValidationError,
1272
1435
  AvantGateControlLayer as ZenLLMControlLayer,
1436
+ applyOutputGuards,
1273
1437
  calculateCostUSD,
1274
1438
  createAvantGate,
1275
1439
  createHttpProviderClient,
@@ -1281,6 +1445,7 @@ export {
1281
1445
  resolveModelPrice,
1282
1446
  resolveModelPriceAsync,
1283
1447
  sanitizePII,
1448
+ sanitizeSecrets,
1284
1449
  validateUserInput,
1285
1450
  validateWithZod
1286
1451
  };
@@ -0,0 +1,29 @@
1
+ export interface SecretPatternDef {
2
+ type: string;
3
+ regex: RegExp;
4
+ mask: string;
5
+ }
6
+ export interface SecretDetection {
7
+ type: string;
8
+ matchedCount: number;
9
+ }
10
+ export interface SanitizeSecretsResult {
11
+ text: string;
12
+ hasSecrets: boolean;
13
+ detections: SecretDetection[];
14
+ }
15
+ export declare const sanitizeSecrets: (input: string) => SanitizeSecretsResult;
16
+ export interface OutputGuardOptions {
17
+ maskPII?: boolean;
18
+ blockSecretLeaks?: boolean;
19
+ secretLeakAction?: "REDACT" | "BLOCK";
20
+ }
21
+ export interface OutputGuardResult {
22
+ text: string;
23
+ sanitized: boolean;
24
+ secretDetected: boolean;
25
+ piiMaskedCount: number;
26
+ detections: SecretDetection[];
27
+ }
28
+ export declare const applyOutputGuards: (rawOutput: string, options?: OutputGuardOptions) => OutputGuardResult;
29
+ //# sourceMappingURL=secret-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-guard.d.ts","sourceRoot":"","sources":["../src/secret-guard.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAqDD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,qBA4B/C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,UAAU,kBAAkB,KAC3B,iBA+BF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -46,8 +46,19 @@ export declare class ConfigurationError extends Error {
46
46
  export declare class BudgetExceededError extends Error {
47
47
  constructor(message: string);
48
48
  }
49
+ export declare class SecretLeakBlockedError extends Error {
50
+ readonly detections?: Array<{
51
+ type: string;
52
+ matchedCount: number;
53
+ }>;
54
+ constructor(message: string, detections?: Array<{
55
+ type: string;
56
+ matchedCount: number;
57
+ }>);
58
+ }
49
59
  export { ConfigurationError as AvantGateConfigurationError };
50
60
  export { BudgetExceededError as AvantGateBudgetExceededError };
61
+ export { SecretLeakBlockedError as AvantGateSecretLeakBlockedError };
51
62
  export interface ProviderConfig {
52
63
  provider: "deepseek" | "mistral" | "openai" | "ollama" | "openrouter" | "custom";
53
64
  model: string;
@@ -60,6 +71,9 @@ export interface SecurityConfig {
60
71
  detectPromptInjection?: boolean;
61
72
  maskPII?: boolean;
62
73
  maxInputLength?: number;
74
+ outputDLP?: boolean;
75
+ blockSecretLeaks?: boolean;
76
+ secretLeakAction?: "REDACT" | "BLOCK";
63
77
  }
64
78
  export interface RetryConfig {
65
79
  maxRetries?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "avantgate",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Zero-infrastructure, in-process AI Application Firewall (AI-WAF) & privacy control plane for TypeScript: real-time prompt guardrails, zero-egress PII redaction, agent tool isolation, anti-IDOR defense, pre-flight token budgets, and multi-model failover.",
5
5
  "author": "Gatewall Team",
6
6
  "license": "MIT",
@@ -82,7 +82,8 @@
82
82
  ],
83
83
  "scripts": {
84
84
  "build": "tsup src/index.ts src/finance/index.ts src/agent/index.ts src/workflow/index.ts src/client/index.ts --format cjs --format esm --clean && tsc --emitDeclarationOnly --outDir dist",
85
- "test": "tsx tests/avantgate.test.ts && tsx tests/preflight-budget.test.ts && tsx tests/sqlite-pricing-adapter.test.ts && tsx tests/financial-normalizer.test.ts && tsx tests/prompt-builder.test.ts && tsx tests/pii-extended.test.ts && npm run test:agent && npm run test:workflow && npm run test:client",
85
+ "test": "tsx tests/avantgate.test.ts && tsx tests/preflight-budget.test.ts && tsx tests/sqlite-pricing-adapter.test.ts && tsx tests/financial-normalizer.test.ts && tsx tests/prompt-builder.test.ts && tsx tests/pii-extended.test.ts && tsx tests/output-dlp-secret-guard.test.ts && npm run test:agent && npm run test:workflow && npm run test:client",
86
+ "test:secrets": "tsx tests/output-dlp-secret-guard.test.ts",
86
87
  "test:pricing": "tsx tests/sqlite-pricing-adapter.test.ts",
87
88
  "test:finance": "tsx tests/financial-normalizer.test.ts",
88
89
  "test:prompts": "tsx tests/prompt-builder.test.ts",