@devilsdev/rag-pipeline-utils 2.2.0 → 2.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/README.md +323 -722
- package/contracts/contract-schema.json +189 -0
- package/contracts/reranker-contract.json +69 -0
- package/dist/index.cjs +19 -0
- package/dist/index.mjs +15 -1
- package/package.json +4 -2
- package/src/cli/commands/wizard.js +627 -0
- package/src/cli/input-sanitization-middleware.js +356 -0
- package/src/cli/templates/development.template.json +64 -0
- package/src/cli/templates/minimal.template.json +33 -0
- package/src/cli/templates/production.template.json +104 -0
- package/src/cli/templates/testing.template.json +45 -0
- package/src/config/connection-pool-config.json +259 -0
- package/src/config/memory-optimization.js +414 -0
- package/src/config/redaction-patterns.json +150 -0
- package/src/config/sanitization-rules.json +323 -0
- package/src/core/performance/streaming-safeguards.js +10 -1
- package/src/core/plugin-registry.js +275 -0
- package/src/dag/core/error-context.js +391 -0
- package/src/dag/core/execution-scheduler.js +350 -0
- package/src/dag/core/topology-validation.js +415 -0
- package/src/dag/dag-engine.js +26 -424
- package/src/dev/README.md +126 -0
- package/src/dev/dev-server.js +356 -0
- package/src/dev/examples/hot-reload-usage.js +355 -0
- package/src/dev/hot-reload.js +807 -0
- package/src/enterprise/sso-integration.js +184 -15
- package/src/index.js +19 -0
- package/src/observability/event-logger.js +62 -2
- package/src/plugins/optimized-openai-embedder.js +169 -0
- package/src/reranker/llm-reranker.js +30 -4
- package/src/security/jwt-config.js +431 -0
- package/src/security/jwt-validator.js +701 -0
- package/src/utils/api-client-pool-integration.js +436 -0
- package/src/utils/batch-processor.js +710 -0
- package/src/utils/connection-pool.js +605 -0
- package/src/utils/contract-validator.js +460 -0
- package/src/utils/error-formatter.js +603 -0
- package/src/utils/examples/error-formatter-usage.js +351 -0
- package/src/utils/input-sanitizer.js +967 -0
- package/src/utils/memory-monitor.js +800 -0
- package/src/utils/rate-limiter.js +244 -0
- package/src/utils/secure-logger-config.js +352 -0
- package/src/utils/secure-logger.js +576 -0
- package/src/utils/secure-logging.js +338 -0
- package/src/utils/structured-logger.js +32 -5
package/README.md
CHANGED
|
@@ -1,918 +1,519 @@
|
|
|
1
|
-
#
|
|
1
|
+
# rag-pipeline-utils
|
|
2
|
+
|
|
3
|
+
**Modular toolkit for building production-ready RAG pipelines in Node.js**
|
|
2
4
|
|
|
3
5
|
[](https://github.com/DevilsDev/rag-pipeline-utils/actions)
|
|
4
|
-
[](https://
|
|
6
|
+
[](https://www.npmjs.com/package/@devilsdev/rag-pipeline-utils)
|
|
7
|
+
[](https://codecov.io/gh/DevilsDev/rag-pipeline-utils)
|
|
8
|
+
[](https://opensource.org/licenses/GPL-3.0)
|
|
5
9
|
[](https://nodejs.org/)
|
|
6
|
-
[](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/LICENSE)
|
|
7
10
|
[](https://www.npmjs.com/package/@devilsdev/rag-pipeline-utils)
|
|
8
|
-
|
|
9
|
-
Enterprise-grade toolkit for building Retrieval-Augmented Generation (RAG) pipelines in Node.js with modular plugin architecture, streaming support, and observability.
|
|
10
|
-
|
|
11
|
-
## 🎉 What's New in v2.2.0
|
|
12
|
-
|
|
13
|
-
### Major Improvements
|
|
14
|
-
|
|
15
|
-
**✅ Fixed ESM Build (Critical)**
|
|
16
|
-
|
|
17
|
-
- Implemented CJS→ESM interop pattern for proper module compatibility
|
|
18
|
-
- All 15 exports now working correctly in both CommonJS and ES Modules
|
|
19
|
-
- Verified compatibility with Node.js 18.x, 20.x, and 22.x
|
|
20
|
-
|
|
21
|
-
**📦 50% Smaller Install Size**
|
|
22
|
-
|
|
23
|
-
- Reduced from ~30MB to ~15MB by optimizing dependencies
|
|
24
|
-
- Moved CLI-only tools to devDependencies
|
|
25
|
-
- Zero production vulnerabilities (npm audit clean)
|
|
26
|
-
|
|
27
|
-
**📝 Enhanced TypeScript Support**
|
|
28
|
-
|
|
29
|
-
- Added 5 complete plugin contract interfaces:
|
|
30
|
-
- `LoaderPlugin` - Document loading interface
|
|
31
|
-
- `EmbedderPlugin` - Text embedding interface
|
|
32
|
-
- `RetrieverPlugin` - Vector search interface
|
|
33
|
-
- `LLMPlugin` - Language model interface
|
|
34
|
-
- `RerankerPlugin` - Result reranking interface
|
|
35
|
-
- Added 4 helper types: `Document`, `SearchResult`, `RetrieveOptions`, `LLMResponse`
|
|
36
|
-
- 236 lines of comprehensive type definitions
|
|
37
|
-
- Full IDE autocomplete and type checking support
|
|
38
|
-
|
|
39
|
-
**🔧 Real-World Example**
|
|
40
|
-
|
|
41
|
-
- Complete OpenAI + Pinecone integration example in `examples/openai-pinecone/`
|
|
42
|
-
- Mock mode for testing without API keys
|
|
43
|
-
- Production-ready error handling and cost estimation guidance
|
|
44
|
-
- See [OpenAI + Pinecone Example](#openai--pinecone-example) below
|
|
45
|
-
|
|
46
|
-
**📚 Documentation Enhancements**
|
|
47
|
-
|
|
48
|
-
- Platform compatibility matrix (Linux, macOS, Windows, Docker)
|
|
49
|
-
- Module system examples (CommonJS + ES Modules)
|
|
50
|
-
- Docker usage examples
|
|
51
|
-
- Troubleshooting guides
|
|
52
|
-
|
|
53
|
-
### Migration from v2.1.x
|
|
54
|
-
|
|
55
|
-
**No breaking changes!** v2.2.0 is fully backward compatible. Simply update:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
npm install @devilsdev/rag-pipeline-utils@latest
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
All existing code will continue to work without modifications.
|
|
11
|
+
[](https://github.com/DevilsDev/rag-pipeline-utils/discussions)
|
|
62
12
|
|
|
63
13
|
---
|
|
64
14
|
|
|
65
|
-
##
|
|
15
|
+
## Why This Exists
|
|
66
16
|
|
|
67
|
-
|
|
68
|
-
npm install @devilsdev/rag-pipeline-utils
|
|
69
|
-
```
|
|
17
|
+
Building Retrieval-Augmented Generation (RAG) systems is harder than it should be. Most solutions lock you into specific vendors, force opinionated architectures, or sacrifice observability for simplicity.
|
|
70
18
|
|
|
71
|
-
**
|
|
19
|
+
**rag-pipeline-utils** takes a different approach: it provides the building blocks—loaders, embedders, retrievers, LLM connectors, and rerankers—that you compose into pipelines that fit your needs. Every component follows clear contracts. Every integration is optional. Every decision is yours.
|
|
72
20
|
|
|
73
|
-
|
|
21
|
+
We built this toolkit because we believe infrastructure should be:
|
|
74
22
|
|
|
75
|
-
|
|
23
|
+
- **Modular** – swap any component without rewriting your pipeline
|
|
24
|
+
- **Observable** – metrics, tracing, and audit logs built in from day one
|
|
25
|
+
- **Secure** – hardened JWT validation with replay protection, multi-layer path traversal defense, and enterprise-grade defaults
|
|
26
|
+
- **Open** – no vendor lock-in, no proprietary APIs, just JavaScript
|
|
76
27
|
|
|
77
|
-
|
|
78
|
-
| ----------- | ------------------ | ------------------------------------------------------------- |
|
|
79
|
-
| **Linux** | ✅ Fully Supported | Tested on Ubuntu 20.04+, Debian 11+, RHEL 8+ |
|
|
80
|
-
| **macOS** | ✅ Fully Supported | Tested on macOS 12+ (Intel & Apple Silicon) |
|
|
81
|
-
| **Windows** | ✅ Fully Supported | Tested on Windows 10/11, WSL2 recommended for best experience |
|
|
82
|
-
| **Docker** | ✅ Fully Supported | Alpine & Debian-based images available |
|
|
28
|
+
Whether you're prototyping a document Q&A system or scaling a production knowledge base, this toolkit grows with you.
|
|
83
29
|
|
|
84
|
-
|
|
30
|
+
---
|
|
85
31
|
|
|
86
|
-
|
|
32
|
+
## Quick Start
|
|
87
33
|
|
|
88
|
-
|
|
34
|
+
Here's a complete RAG pipeline in 15 lines:
|
|
89
35
|
|
|
90
36
|
```javascript
|
|
91
|
-
const {
|
|
92
|
-
createRagPipeline,
|
|
93
|
-
DAGEngine,
|
|
94
|
-
} = require("@devilsdev/rag-pipeline-utils");
|
|
37
|
+
const { createRagPipeline } = require("@devilsdev/rag-pipeline-utils");
|
|
95
38
|
|
|
39
|
+
// Implement your plugins (or use existing ones)
|
|
96
40
|
const pipeline = createRagPipeline({
|
|
97
|
-
|
|
41
|
+
loader: new MyPDFLoader(),
|
|
42
|
+
embedder: new MyOpenAIEmbedder({ apiKey: process.env.OPENAI_API_KEY }),
|
|
43
|
+
retriever: new MyVectorDBRetriever({ url: "http://localhost:8000" }),
|
|
44
|
+
llm: new MyLLMConnector({ model: "gpt-4" }),
|
|
98
45
|
});
|
|
99
|
-
|
|
46
|
+
|
|
47
|
+
// Ingest documents
|
|
48
|
+
await pipeline.ingest("./company-docs.pdf");
|
|
49
|
+
|
|
50
|
+
// Query with natural language
|
|
51
|
+
const answer = await pipeline.query("What is the vacation policy?");
|
|
52
|
+
console.log(answer.text);
|
|
53
|
+
// Output: "Based on the company handbook, employees receive 20 days of vacation per year..."
|
|
100
54
|
```
|
|
101
55
|
|
|
102
|
-
**
|
|
56
|
+
**Requirements:** Node.js >= 18.0.0
|
|
103
57
|
|
|
104
|
-
|
|
105
|
-
import { createRagPipeline, DAGEngine } from "@devilsdev/rag-pipeline-utils";
|
|
58
|
+
Install with:
|
|
106
59
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
110
|
-
const dag = new DAGEngine();
|
|
60
|
+
```bash
|
|
61
|
+
npm install @devilsdev/rag-pipeline-utils
|
|
111
62
|
```
|
|
112
63
|
|
|
113
|
-
###
|
|
114
|
-
|
|
115
|
-
**New in v2.2.0:** Complete plugin contract interfaces with 236 lines of type definitions:
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
import {
|
|
119
|
-
createRagPipeline,
|
|
120
|
-
DAGEngine,
|
|
121
|
-
RagPipelineConfig,
|
|
122
|
-
// Plugin contract interfaces (NEW in v2.2.0)
|
|
123
|
-
LoaderPlugin,
|
|
124
|
-
EmbedderPlugin,
|
|
125
|
-
RetrieverPlugin,
|
|
126
|
-
LLMPlugin,
|
|
127
|
-
RerankerPlugin,
|
|
128
|
-
// Helper types (NEW in v2.2.0)
|
|
129
|
-
Document,
|
|
130
|
-
SearchResult,
|
|
131
|
-
RetrieveOptions,
|
|
132
|
-
LLMResponse,
|
|
133
|
-
} from "@devilsdev/rag-pipeline-utils";
|
|
134
|
-
|
|
135
|
-
// Type-safe plugin implementation
|
|
136
|
-
class MyLoader implements LoaderPlugin {
|
|
137
|
-
async load(source: string, options?: any): Promise<Document[]> {
|
|
138
|
-
// Your implementation with full type checking
|
|
139
|
-
return [
|
|
140
|
-
{
|
|
141
|
-
id: "doc-1",
|
|
142
|
-
content: "Document content",
|
|
143
|
-
metadata: { source },
|
|
144
|
-
},
|
|
145
|
-
];
|
|
146
|
-
}
|
|
147
|
-
}
|
|
64
|
+
### What's New in v2.3.0 (Released November 7, 2025)
|
|
148
65
|
|
|
149
|
-
|
|
150
|
-
loader: new MyLoader(),
|
|
151
|
-
embedder: "my-embedder",
|
|
152
|
-
};
|
|
66
|
+
**Major Security Enhancements:**
|
|
153
67
|
|
|
154
|
-
|
|
155
|
-
|
|
68
|
+
- **Advanced JWT replay protection** with self-signed token reusability
|
|
69
|
+
- **Hardened path traversal defense** with iterative URL decoding
|
|
70
|
+
- **Consistent validation behavior** eliminating duplicate checks
|
|
71
|
+
- **Race condition mitigation** in concurrent token verification
|
|
156
72
|
|
|
157
|
-
|
|
73
|
+
**All security tests passing:** 113 security-focused tests with 100% coverage on critical paths.
|
|
158
74
|
|
|
159
|
-
|
|
160
|
-
- **Runtime dependencies**: Only 11 production dependencies
|
|
161
|
-
- **Total install size**: ~15MB (including dependencies) - **50% smaller than v2.1.x**
|
|
162
|
-
- **Tree-shakeable**: ES module exports support tree-shaking
|
|
163
|
-
- **Zero vulnerabilities**: npm audit clean (production dependencies)
|
|
75
|
+
[See full security details below](#security-and-quality) | [Migration guide](#upgrading-from-v22x)
|
|
164
76
|
|
|
165
|
-
|
|
77
|
+
---
|
|
166
78
|
|
|
167
|
-
|
|
79
|
+
## How It Works
|
|
168
80
|
|
|
169
|
-
|
|
170
|
-
FROM node:18-alpine
|
|
81
|
+
**rag-pipeline-utils** orchestrates data through a clear, predictable flow:
|
|
171
82
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
83
|
+
```mermaid
|
|
84
|
+
graph LR
|
|
85
|
+
A[Documents] --> B[Loader]
|
|
86
|
+
B --> C[Embedder]
|
|
87
|
+
C --> D[Vector Store]
|
|
88
|
+
D --> E[Retriever]
|
|
89
|
+
F[User Query] --> C
|
|
90
|
+
F --> E
|
|
91
|
+
E --> G[Reranker]
|
|
92
|
+
G --> H[LLM]
|
|
93
|
+
H --> I[Response]
|
|
176
94
|
|
|
177
|
-
|
|
95
|
+
style B fill:#e1f5e1
|
|
96
|
+
style C fill:#e1f5e1
|
|
97
|
+
style E fill:#e1f5e1
|
|
98
|
+
style G fill:#fff4e1
|
|
99
|
+
style H fill:#e1f5e1
|
|
100
|
+
style I fill:#e3f2fd
|
|
178
101
|
```
|
|
179
102
|
|
|
180
|
-
**
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
image: node:18-alpine
|
|
187
|
-
working_dir: /app
|
|
188
|
-
volumes:
|
|
189
|
-
- ./:/app
|
|
190
|
-
environment:
|
|
191
|
-
- NODE_ENV=production
|
|
192
|
-
command: npm start
|
|
193
|
-
```
|
|
103
|
+
1. **Loader** – Parse documents (PDF, HTML, Markdown, etc.)
|
|
104
|
+
2. **Embedder** – Convert text to vector embeddings
|
|
105
|
+
3. **Vector Store** – Index and persist embeddings
|
|
106
|
+
4. **Retriever** – Find semantically similar content
|
|
107
|
+
5. **Reranker** (optional) – Refine retrieval results
|
|
108
|
+
6. **LLM** – Generate contextual responses
|
|
194
109
|
|
|
195
|
-
|
|
110
|
+
Every component is replaceable. Every step is observable.
|
|
196
111
|
|
|
197
|
-
|
|
112
|
+
---
|
|
198
113
|
|
|
199
|
-
|
|
200
|
-
const { createRagPipeline } = require("@devilsdev/rag-pipeline-utils");
|
|
114
|
+
## Features
|
|
201
115
|
|
|
202
|
-
|
|
203
|
-
const pipeline = createRagPipeline({
|
|
204
|
-
loader: yourLoaderPlugin,
|
|
205
|
-
embedder: yourEmbedderPlugin,
|
|
206
|
-
retriever: yourRetrieverPlugin,
|
|
207
|
-
llm: yourLLMPlugin,
|
|
208
|
-
});
|
|
116
|
+
### Modular Plugin Architecture
|
|
209
117
|
|
|
210
|
-
|
|
211
|
-
await pipeline.ingest("./document.pdf");
|
|
212
|
-
const result = await pipeline.query("What is this document about?");
|
|
213
|
-
console.log(result);
|
|
214
|
-
```
|
|
118
|
+
Swap any component without rewriting your pipeline. Use OpenAI embeddings with Pinecone storage, or mix Hugging Face models with PostgreSQL—your choice.
|
|
215
119
|
|
|
216
|
-
###
|
|
217
|
-
|
|
218
|
-
Create `.ragrc.json`:
|
|
219
|
-
|
|
220
|
-
```json
|
|
221
|
-
{
|
|
222
|
-
"loader": {
|
|
223
|
-
"pdf": "your-pdf-loader-plugin"
|
|
224
|
-
},
|
|
225
|
-
"embedder": {
|
|
226
|
-
"default": "your-embedder-plugin"
|
|
227
|
-
},
|
|
228
|
-
"retriever": {
|
|
229
|
-
"default": "your-vector-db-plugin"
|
|
230
|
-
},
|
|
231
|
-
"llm": {
|
|
232
|
-
"default": "your-llm-plugin"
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
```
|
|
120
|
+
### Enterprise Observability
|
|
236
121
|
|
|
237
|
-
|
|
122
|
+
Built-in structured logging, Prometheus metrics, OpenTelemetry tracing, and audit logs for compliance-grade transparency.
|
|
238
123
|
|
|
239
|
-
|
|
240
|
-
const {
|
|
241
|
-
loadConfig,
|
|
242
|
-
createRagPipeline,
|
|
243
|
-
} = require("@devilsdev/rag-pipeline-utils");
|
|
124
|
+
### DAG Workflow Engine
|
|
244
125
|
|
|
245
|
-
|
|
246
|
-
const pipeline = createRagPipeline(config);
|
|
247
|
-
```
|
|
126
|
+
Chain complex multi-step operations with retry logic, parallel execution, and graceful error handling. Perfect for batch ingestion or multi-stage transformations.
|
|
248
127
|
|
|
249
|
-
|
|
128
|
+
### Type-Safe Contracts
|
|
250
129
|
|
|
251
|
-
|
|
130
|
+
Complete TypeScript interfaces for all plugin types. Full IDE autocomplete and compile-time validation.
|
|
252
131
|
|
|
253
|
-
|
|
254
|
-
const {
|
|
255
|
-
// Core pipeline
|
|
256
|
-
createRagPipeline,
|
|
132
|
+
### Production-Ready Security
|
|
257
133
|
|
|
258
|
-
|
|
259
|
-
loadConfig,
|
|
260
|
-
validateRagrc,
|
|
261
|
-
normalizeConfig,
|
|
134
|
+
Hardened security with defense-in-depth: JWT replay protection with race condition mitigation, multi-layer path traversal defense with iterative URL decoding, validated JSON parsing, algorithm whitelisting, automatic secret redaction, and comprehensive audit logging.
|
|
262
135
|
|
|
263
|
-
|
|
264
|
-
pluginRegistry,
|
|
136
|
+
### Streaming & Batching
|
|
265
137
|
|
|
266
|
-
|
|
267
|
-
DAGEngine,
|
|
138
|
+
Stream LLM responses in real-time. Batch embed thousands of documents efficiently with parallel processing and backpressure control.
|
|
268
139
|
|
|
269
|
-
|
|
270
|
-
eventLogger,
|
|
271
|
-
metrics,
|
|
140
|
+
### Framework Agnostic
|
|
272
141
|
|
|
273
|
-
|
|
274
|
-
ParallelProcessor,
|
|
142
|
+
Works with Express, Fastify, Next.js, or any Node.js runtime. Deploy to AWS Lambda, Vercel, Docker, or bare metal.
|
|
275
143
|
|
|
276
|
-
|
|
277
|
-
MultiModalProcessor,
|
|
278
|
-
AdaptiveRetrievalEngine,
|
|
144
|
+
---
|
|
279
145
|
|
|
280
|
-
|
|
281
|
-
AuditLogger,
|
|
282
|
-
DataGovernance,
|
|
146
|
+
## Join the Community
|
|
283
147
|
|
|
284
|
-
|
|
285
|
-
logger,
|
|
286
|
-
} = require("@devilsdev/rag-pipeline-utils");
|
|
287
|
-
```
|
|
148
|
+
We're building this together.
|
|
288
149
|
|
|
289
|
-
|
|
150
|
+
Whether you're implementing a new retriever, writing documentation, reporting bugs, or sharing ideas—every contribution makes this toolkit better for everyone.
|
|
290
151
|
|
|
291
|
-
|
|
152
|
+
**Getting Started:**
|
|
292
153
|
|
|
293
|
-
|
|
154
|
+
- [GitHub Discussions](https://github.com/DevilsDev/rag-pipeline-utils/discussions) – Ask questions, share use cases, propose features
|
|
155
|
+
- [Issue Tracker](https://github.com/DevilsDev/rag-pipeline-utils/issues) – Report bugs or request features
|
|
156
|
+
- [Contributing Guide](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/docs/CONTRIBUTING.md) – Learn how to submit pull requests
|
|
157
|
+
- [Code of Conduct](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/CODE_OF_CONDUCT.md) – Our community standards
|
|
294
158
|
|
|
295
|
-
|
|
296
|
-
- `config.embedder` - Text embedding plugin
|
|
297
|
-
- `config.retriever` - Vector storage and retrieval plugin
|
|
298
|
-
- `config.llm` - Language model plugin
|
|
299
|
-
- `config.reranker` (optional) - Result reranking plugin
|
|
159
|
+
**Good First Issues:** Look for issues tagged `good first issue` to find beginner-friendly contributions.
|
|
300
160
|
|
|
301
|
-
**
|
|
161
|
+
**Office Hours:** Join our monthly community calls to discuss roadmap priorities and architectural decisions.
|
|
302
162
|
|
|
303
|
-
|
|
163
|
+
---
|
|
304
164
|
|
|
305
|
-
|
|
306
|
-
// Load configuration from file
|
|
307
|
-
const config = await loadConfig(".ragrc.json");
|
|
165
|
+
## Security and Quality
|
|
308
166
|
|
|
309
|
-
|
|
310
|
-
const isValid = validateRagrc(config);
|
|
167
|
+
Security isn't optional. This toolkit is built with defense in depth:
|
|
311
168
|
|
|
312
|
-
|
|
313
|
-
const normalized = normalizeConfig(config);
|
|
314
|
-
```
|
|
169
|
+
### Core Security Features
|
|
315
170
|
|
|
316
|
-
|
|
171
|
+
- **Validated Inputs** – All JSON parsed through schema validation (AJV)
|
|
172
|
+
- **Secure Logging** – Automatic redaction of 36 sensitive field patterns (API keys, JWTs, tokens)
|
|
173
|
+
- **JWT Best Practices** – Algorithm whitelisting, issuer/audience validation, expiration enforcement
|
|
174
|
+
- **Dependency Scanning** – Weekly Dependabot updates, CI blocks on critical vulnerabilities
|
|
175
|
+
- **Audit Trail** – Immutable compliance-grade logs for all security-sensitive operations
|
|
176
|
+
- **Plugin Sandboxing** – Third-party plugins run with declared permissions and resource limits
|
|
177
|
+
- **Supply Chain Security** – All GitHub Actions pinned to commit SHAs, SBOM generation available
|
|
317
178
|
|
|
318
|
-
|
|
319
|
-
const { pluginRegistry } = require("@devilsdev/rag-pipeline-utils");
|
|
179
|
+
### Recent Security Enhancements (v2.3.0)
|
|
320
180
|
|
|
321
|
-
|
|
322
|
-
pluginRegistry.register("my-plugin", MyPluginClass);
|
|
181
|
+
#### Hardened JWT Validation
|
|
323
182
|
|
|
324
|
-
|
|
325
|
-
const Plugin = pluginRegistry.get("my-plugin");
|
|
183
|
+
**Advanced Replay Protection:**
|
|
326
184
|
|
|
327
|
-
|
|
328
|
-
|
|
185
|
+
- Self-signed tokens can be verified multiple times (essential for refresh flows and load balancer retries)
|
|
186
|
+
- External tokens are tracked and blocked on replay attempts
|
|
187
|
+
- Race condition mitigation with optimized check-then-set pattern
|
|
188
|
+
- Separate tracking for reusable vs. single-use tokens
|
|
329
189
|
|
|
330
|
-
|
|
331
|
-
const exists = pluginRegistry.has("my-plugin");
|
|
332
|
-
```
|
|
190
|
+
**Consistent Validation Behavior:**
|
|
333
191
|
|
|
334
|
-
|
|
192
|
+
- `strictValidation` flag now consistently controls issuer/audience validation
|
|
193
|
+
- Eliminated duplicate validation logic to prevent configuration confusion
|
|
194
|
+
- Clear separation of concerns: jsonwebtoken handles cryptographic validation, custom logic handles business rules
|
|
335
195
|
|
|
336
|
-
|
|
196
|
+
**Example:**
|
|
337
197
|
|
|
338
198
|
```javascript
|
|
339
|
-
const {
|
|
340
|
-
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
id: "embed",
|
|
352
|
-
type: "embedder",
|
|
353
|
-
dependencies: ["load"],
|
|
354
|
-
config: {
|
|
355
|
-
/* embedder config */
|
|
356
|
-
},
|
|
357
|
-
},
|
|
358
|
-
{
|
|
359
|
-
id: "store",
|
|
360
|
-
type: "retriever",
|
|
361
|
-
dependencies: ["embed"],
|
|
362
|
-
config: {
|
|
363
|
-
/* retriever config */
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
],
|
|
199
|
+
const { JWTValidator } = require("@devilsdev/rag-pipeline-utils");
|
|
200
|
+
|
|
201
|
+
const validator = new JWTValidator({
|
|
202
|
+
secret: process.env.JWT_SECRET,
|
|
203
|
+
algorithm: "HS256",
|
|
204
|
+
issuer: "my-app",
|
|
205
|
+
audience: "api-users",
|
|
206
|
+
strictValidation: true, // Enforces iss/aud validation
|
|
207
|
+
enableJtiTracking: true, // Prevents replay attacks
|
|
367
208
|
});
|
|
368
209
|
|
|
369
|
-
|
|
210
|
+
// Self-signed tokens can be verified multiple times
|
|
211
|
+
const token = validator.sign({ sub: "user-123" });
|
|
212
|
+
validator.verify(token); // First verification
|
|
213
|
+
validator.verify(token); // Still works (refresh flow)
|
|
214
|
+
|
|
215
|
+
// External tokens are blocked on replay
|
|
216
|
+
const externalToken = getTokenFromThirdParty();
|
|
217
|
+
validator.verify(externalToken); // First use
|
|
218
|
+
validator.verify(externalToken); // Throws "Token replay detected"
|
|
370
219
|
```
|
|
371
220
|
|
|
372
|
-
|
|
221
|
+
#### Path Traversal Defense
|
|
373
222
|
|
|
374
|
-
|
|
375
|
-
const { eventLogger, metrics } = require("@devilsdev/rag-pipeline-utils");
|
|
223
|
+
**Multi-Layer Protection:**
|
|
376
224
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
});
|
|
225
|
+
- Iterative URL decoding (up to 5 passes) to catch sophisticated encoding attacks
|
|
226
|
+
- Detects double-encoded paths: `%252e%252e%252f` → `%2e%2e%2f` → `../`
|
|
227
|
+
- Malformed encoding treated as attack indicator (throws error)
|
|
228
|
+
- Critical security violations always throw, regardless of configuration
|
|
382
229
|
|
|
383
|
-
|
|
384
|
-
eventLogger.log("info", "Pipeline started", { pipelineId: "abc123" });
|
|
230
|
+
**Attack Vectors Blocked:**
|
|
385
231
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
232
|
+
- Standard traversal: `../../../etc/passwd`
|
|
233
|
+
- Windows paths: `..\..\windows\system32`
|
|
234
|
+
- URL encoded: `%2e%2e%2f`, `%2e%2e%5c`
|
|
235
|
+
- Double encoded: `%252e%252e%252f`
|
|
236
|
+
- Mixed encoding: combinations of above
|
|
390
237
|
|
|
391
|
-
|
|
238
|
+
**Example:**
|
|
392
239
|
|
|
393
240
|
```javascript
|
|
394
|
-
const {
|
|
241
|
+
const { sanitizePath } = require("@devilsdev/rag-pipeline-utils");
|
|
395
242
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
});
|
|
243
|
+
// Safe paths are normalized
|
|
244
|
+
sanitizePath("docs/README.md"); // Returns: "docs/README.md"
|
|
399
245
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
246
|
+
// Dangerous paths throw errors
|
|
247
|
+
sanitizePath("../../../etc/passwd"); // Throws
|
|
248
|
+
sanitizePath("%2e%2e%2f%2e%2e%2fpasswd"); // Throws
|
|
249
|
+
sanitizePath("%252e%252e%252fconfig"); // Throws (double-encoded)
|
|
404
250
|
```
|
|
405
251
|
|
|
406
|
-
|
|
252
|
+
#### Defense-in-Depth Architecture
|
|
407
253
|
|
|
408
|
-
|
|
254
|
+
**Critical Security Errors:**
|
|
409
255
|
|
|
410
|
-
|
|
256
|
+
- Path traversal violations **always throw**, even if `throwOnInvalid=false`
|
|
257
|
+
- Object depth limit violations **always throw** to prevent DoS
|
|
258
|
+
- Security-critical operations are prioritized over configuration flexibility
|
|
411
259
|
|
|
412
|
-
**
|
|
260
|
+
**Security Monitoring:**
|
|
413
261
|
|
|
414
|
-
|
|
262
|
+
- All blocked attempts tracked in `stats.blocked` counter
|
|
263
|
+
- Audit events emitted for replay detection, algorithm mismatches, and validation failures
|
|
264
|
+
- Structured logging with security event correlation
|
|
415
265
|
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Loader plugin interface (NEW TypeScript interface in v2.2.0)
|
|
419
|
-
* Implements: LoaderPlugin
|
|
420
|
-
*/
|
|
421
|
-
class MyLoader {
|
|
422
|
-
async load(source, options) {
|
|
423
|
-
// Load and parse document
|
|
424
|
-
// Return array of Document objects
|
|
425
|
-
return [
|
|
426
|
-
{
|
|
427
|
-
id: "doc-1",
|
|
428
|
-
content: "Document text...",
|
|
429
|
-
metadata: { page: 1, source },
|
|
430
|
-
// embedding: optional pre-computed embedding
|
|
431
|
-
},
|
|
432
|
-
];
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
```
|
|
266
|
+
### Quality Metrics
|
|
436
267
|
|
|
437
|
-
|
|
268
|
+
**Zero Production Vulnerabilities:** `npm audit --production` returns clean on every release.
|
|
438
269
|
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Embedder plugin interface (NEW TypeScript interface in v2.2.0)
|
|
442
|
-
* Implements: EmbedderPlugin
|
|
443
|
-
*/
|
|
444
|
-
class MyEmbedder {
|
|
445
|
-
async embed(text, options) {
|
|
446
|
-
// Generate embedding for a single text string
|
|
447
|
-
// Return: Promise<number[]> - embedding vector
|
|
448
|
-
return [0.1, 0.2, 0.3 /* ... 1536 dimensions for OpenAI */];
|
|
449
|
-
}
|
|
270
|
+
**Test Coverage:** 113 security-focused tests across 2 dedicated security suites:
|
|
450
271
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
// Generate embeddings for multiple texts
|
|
454
|
-
return texts.map((text) => this.embed(text));
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
```
|
|
272
|
+
- JWT Validator: 44 tests covering algorithm confusion, replay attacks, and validation edge cases
|
|
273
|
+
- Input Sanitizer: 69 tests covering XSS, SQL injection, command injection, and path traversal
|
|
458
274
|
|
|
459
|
-
|
|
275
|
+
**Supported Node Versions:** 18.x, 20.x, 22.x (tested in CI)
|
|
460
276
|
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Retriever plugin interface (NEW TypeScript interface in v2.2.0)
|
|
464
|
-
* Implements: RetrieverPlugin
|
|
465
|
-
*/
|
|
466
|
-
class MyRetriever {
|
|
467
|
-
async retrieve(query, options) {
|
|
468
|
-
// query can be:
|
|
469
|
-
// - string: search by text
|
|
470
|
-
// - { embedding: number[] }: search by vector
|
|
471
|
-
const { topK = 5, minScore = 0.7, filter } = options || {};
|
|
472
|
-
|
|
473
|
-
// Search for similar vectors
|
|
474
|
-
// Return: Promise<SearchResult[]>
|
|
475
|
-
return [
|
|
476
|
-
{
|
|
477
|
-
id: "result-1",
|
|
478
|
-
score: 0.95,
|
|
479
|
-
document: {
|
|
480
|
-
id: "doc-1",
|
|
481
|
-
content: "Document text...",
|
|
482
|
-
metadata: { source: "file.pdf" },
|
|
483
|
-
},
|
|
484
|
-
metadata: {
|
|
485
|
-
/* additional search metadata */
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
];
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
#### LLM Plugin
|
|
494
|
-
|
|
495
|
-
```javascript
|
|
496
|
-
/**
|
|
497
|
-
* LLM plugin interface (NEW TypeScript interface in v2.2.0)
|
|
498
|
-
* Implements: LLMPlugin
|
|
499
|
-
*/
|
|
500
|
-
class MyLLM {
|
|
501
|
-
async generate(prompt, options) {
|
|
502
|
-
// Generate text from prompt
|
|
503
|
-
// Return: Promise<LLMResponse>
|
|
504
|
-
return {
|
|
505
|
-
text: "Generated response...",
|
|
506
|
-
usage: {
|
|
507
|
-
promptTokens: 100,
|
|
508
|
-
completionTokens: 50,
|
|
509
|
-
totalTokens: 150,
|
|
510
|
-
},
|
|
511
|
-
metadata: {
|
|
512
|
-
model: "gpt-4",
|
|
513
|
-
finishReason: "stop",
|
|
514
|
-
},
|
|
515
|
-
};
|
|
516
|
-
}
|
|
277
|
+
---
|
|
517
278
|
|
|
518
|
-
|
|
519
|
-
async *stream(prompt, options) {
|
|
520
|
-
// Stream response chunks
|
|
521
|
-
yield "Generated ";
|
|
522
|
-
yield "response ";
|
|
523
|
-
yield "chunks...";
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
```
|
|
279
|
+
## Installation & Development
|
|
527
280
|
|
|
528
|
-
|
|
281
|
+
### Install
|
|
529
282
|
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
* Reranker plugin interface (NEW TypeScript interface in v2.2.0)
|
|
533
|
-
* Implements: RerankerPlugin
|
|
534
|
-
*/
|
|
535
|
-
class MyReranker {
|
|
536
|
-
async rerank(results, query, options) {
|
|
537
|
-
// Rerank search results based on relevance to query
|
|
538
|
-
// Return: Promise<SearchResult[]> - reranked results
|
|
539
|
-
return results
|
|
540
|
-
.map((result) => ({
|
|
541
|
-
...result,
|
|
542
|
-
score: calculateRelevanceScore(query, result),
|
|
543
|
-
}))
|
|
544
|
-
.sort((a, b) => b.score - a.score);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
283
|
+
```bash
|
|
284
|
+
npm install @devilsdev/rag-pipeline-utils
|
|
547
285
|
```
|
|
548
286
|
|
|
549
|
-
|
|
287
|
+
### Development Setup
|
|
550
288
|
|
|
551
289
|
```bash
|
|
552
|
-
#
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
PINECONE_ENVIRONMENT=us-east-1
|
|
556
|
-
CHROMA_URL=http://localhost:8000
|
|
557
|
-
|
|
558
|
-
# Performance settings
|
|
559
|
-
RAG_MAX_CONCURRENCY=5
|
|
560
|
-
RAG_BATCH_SIZE=10
|
|
561
|
-
```
|
|
290
|
+
# Clone the repository
|
|
291
|
+
git clone https://github.com/DevilsDev/rag-pipeline-utils.git
|
|
292
|
+
cd rag-pipeline-utils
|
|
562
293
|
|
|
563
|
-
|
|
294
|
+
# Install dependencies
|
|
295
|
+
npm install
|
|
564
296
|
|
|
565
|
-
|
|
297
|
+
# Run tests
|
|
298
|
+
npm test
|
|
566
299
|
|
|
567
|
-
|
|
568
|
-
|
|
300
|
+
# Run linter
|
|
301
|
+
npm run lint
|
|
569
302
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
});
|
|
303
|
+
# Build distribution
|
|
304
|
+
npm run build
|
|
573
305
|
|
|
574
|
-
|
|
306
|
+
# Run development tools
|
|
307
|
+
npm run dev
|
|
575
308
|
```
|
|
576
309
|
|
|
577
|
-
###
|
|
578
|
-
|
|
579
|
-
```javascript
|
|
580
|
-
const { AdaptiveRetrievalEngine } = require("@devilsdev/rag-pipeline-utils");
|
|
581
|
-
|
|
582
|
-
const retriever = new AdaptiveRetrievalEngine({
|
|
583
|
-
// Configuration for adaptive retrieval strategies
|
|
584
|
-
});
|
|
310
|
+
### Common Commands
|
|
585
311
|
|
|
586
|
-
|
|
312
|
+
```bash
|
|
313
|
+
npm test # Run test suite
|
|
314
|
+
npm run test:watch # Watch mode for TDD
|
|
315
|
+
npm run lint # Check code style
|
|
316
|
+
npm run lint:fix # Auto-fix linting issues
|
|
317
|
+
npm run security:audit # Scan dependencies
|
|
318
|
+
npm run docs:api # Generate API documentation
|
|
319
|
+
npm run benchmark # Performance benchmarks
|
|
587
320
|
```
|
|
588
321
|
|
|
589
|
-
|
|
322
|
+
---
|
|
590
323
|
|
|
591
|
-
|
|
592
|
-
const { AuditLogger } = require("@devilsdev/rag-pipeline-utils");
|
|
324
|
+
## Roadmap
|
|
593
325
|
|
|
594
|
-
|
|
595
|
-
destination: "./audit-logs",
|
|
596
|
-
});
|
|
326
|
+
### v2.3.0 (Q2 2025)
|
|
597
327
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
});
|
|
603
|
-
```
|
|
328
|
+
- **Enhanced CLI** – Interactive wizard for pipeline setup, validation commands, and migration tools
|
|
329
|
+
- **Plugin Marketplace** – Curated registry of community-contributed plugins with ratings and verification
|
|
330
|
+
- **Streaming Embeddings** – Real-time embedding generation with backpressure control
|
|
331
|
+
- **Multi-Tenant Support** – Workspace isolation, resource quotas, and tenant-specific configurations
|
|
604
332
|
|
|
605
|
-
###
|
|
333
|
+
### v2.4.0 (Q3 2025)
|
|
606
334
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
policies: {
|
|
612
|
-
retention: "90d",
|
|
613
|
-
encryption: true,
|
|
614
|
-
},
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
await governance.enforce(data);
|
|
618
|
-
```
|
|
335
|
+
- **GraphRAG Support** – Native knowledge graph integration for entity-relationship retrieval
|
|
336
|
+
- **Federated Learning** – Privacy-preserving model training across distributed datasets
|
|
337
|
+
- **Advanced Reranking** – Cross-encoder models and learned ranking functions
|
|
338
|
+
- **Performance Dashboard** – Web UI for monitoring pipeline health and cost metrics
|
|
619
339
|
|
|
620
|
-
|
|
340
|
+
### Beyond
|
|
621
341
|
|
|
622
|
-
|
|
342
|
+
- Native Rust bindings for performance-critical paths
|
|
343
|
+
- Kubernetes operator for production deployments
|
|
344
|
+
- Real-time collaboration features for team-based pipelines
|
|
623
345
|
|
|
624
|
-
|
|
625
|
-
# Initialize configuration
|
|
626
|
-
npx rag-pipeline init
|
|
346
|
+
**Vote on features:** Share your priorities in [GitHub Discussions](https://github.com/DevilsDev/rag-pipeline-utils/discussions/categories/roadmap).
|
|
627
347
|
|
|
628
|
-
|
|
629
|
-
npx rag-pipeline ingest ./documents
|
|
630
|
-
npx rag-pipeline query "Your question"
|
|
348
|
+
---
|
|
631
349
|
|
|
632
|
-
|
|
633
|
-
npx rag-pipeline doctor
|
|
634
|
-
```
|
|
350
|
+
## Upgrading from v2.2.x
|
|
635
351
|
|
|
636
|
-
|
|
352
|
+
The v2.3.0 release includes important security enhancements that are **100% backward compatible** for most use cases. However, there are a few behavioral changes to be aware of:
|
|
637
353
|
|
|
638
|
-
|
|
639
|
-
try {
|
|
640
|
-
const result = await pipeline.query("What is AI?");
|
|
641
|
-
} catch (error) {
|
|
642
|
-
if (error.code === "PLUGIN_NOT_FOUND") {
|
|
643
|
-
console.error("Required plugin not found:", error.message);
|
|
644
|
-
} else if (error.code === "INVALID_CONFIG") {
|
|
645
|
-
console.error("Invalid configuration:", error.message);
|
|
646
|
-
} else {
|
|
647
|
-
console.error("Pipeline error:", error.message);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
```
|
|
354
|
+
### JWT Validator Changes
|
|
651
355
|
|
|
652
|
-
|
|
356
|
+
#### No Action Required (Recommended Use Case)
|
|
653
357
|
|
|
654
|
-
|
|
358
|
+
If you're using the default configuration with `strictValidation: true` (the default), everything works the same:
|
|
655
359
|
|
|
656
360
|
```javascript
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
const llm = new OpenAILLMPlugin({ model: "gpt-4" });
|
|
664
|
-
|
|
665
|
-
// Create pipeline
|
|
666
|
-
const pipeline = createRagPipeline({
|
|
667
|
-
loader,
|
|
668
|
-
embedder,
|
|
669
|
-
retriever,
|
|
670
|
-
llm,
|
|
361
|
+
const validator = new JWTValidator({
|
|
362
|
+
secret: process.env.JWT_SECRET,
|
|
363
|
+
algorithm: "HS256",
|
|
364
|
+
issuer: "my-app",
|
|
365
|
+
audience: "api-users",
|
|
366
|
+
// strictValidation defaults to true
|
|
671
367
|
});
|
|
672
368
|
|
|
673
|
-
//
|
|
674
|
-
await pipeline.ingest("./company-handbook.pdf");
|
|
675
|
-
|
|
676
|
-
// Query
|
|
677
|
-
const answer = await pipeline.query("What is the vacation policy?");
|
|
678
|
-
console.log(answer);
|
|
369
|
+
// Behavior unchanged - tokens validated correctly
|
|
679
370
|
```
|
|
680
371
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
```javascript
|
|
684
|
-
// Use your custom database retriever
|
|
685
|
-
class PostgresRetriever {
|
|
686
|
-
constructor(connectionString) {
|
|
687
|
-
this.db = new PostgresClient(connectionString);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
async retrieve(queryVector, options) {
|
|
691
|
-
const results = await this.db.query(
|
|
692
|
-
"SELECT content, metadata, vector <-> $1 as score FROM embeddings ORDER BY score LIMIT $2",
|
|
693
|
-
[queryVector, options.topK],
|
|
694
|
-
);
|
|
695
|
-
return results.rows;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
const pipeline = createRagPipeline({
|
|
700
|
-
loader: yourLoader,
|
|
701
|
-
embedder: yourEmbedder,
|
|
702
|
-
retriever: new PostgresRetriever("postgresql://localhost/kb"),
|
|
703
|
-
llm: yourLLM,
|
|
704
|
-
});
|
|
705
|
-
```
|
|
372
|
+
#### Behavior Change (Advanced Use Case)
|
|
706
373
|
|
|
707
|
-
|
|
374
|
+
If you explicitly set `strictValidation: false`, the behavior has changed for consistency:
|
|
708
375
|
|
|
709
|
-
|
|
376
|
+
**Before v2.3.0:**
|
|
710
377
|
|
|
711
378
|
```javascript
|
|
712
|
-
const
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
});
|
|
718
|
-
|
|
719
|
-
// Process documents in parallel
|
|
720
|
-
await processor.process(documents, async (doc) => {
|
|
721
|
-
return await pipeline.ingest(doc);
|
|
379
|
+
const validator = new JWTValidator({
|
|
380
|
+
secret: process.env.JWT_SECRET,
|
|
381
|
+
strictValidation: false,
|
|
382
|
+
issuer: "my-app", // These were still validated
|
|
383
|
+
audience: "api-users", // even with strictValidation=false
|
|
722
384
|
});
|
|
723
385
|
```
|
|
724
386
|
|
|
725
|
-
|
|
387
|
+
**After v2.3.0:**
|
|
726
388
|
|
|
727
389
|
```javascript
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
console.log("Total queries:", stats.queries?.total || 0);
|
|
736
|
-
console.log("Average latency:", stats.queries?.avgLatency || 0);
|
|
390
|
+
const validator = new JWTValidator({
|
|
391
|
+
secret: process.env.JWT_SECRET,
|
|
392
|
+
strictValidation: false,
|
|
393
|
+
issuer: "my-app", // Now properly ignored
|
|
394
|
+
audience: "api-users", // when strictValidation=false
|
|
395
|
+
});
|
|
396
|
+
// issuer/audience validation is now truly disabled
|
|
737
397
|
```
|
|
738
398
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
### OpenAI + Pinecone Example
|
|
399
|
+
**Migration:** If you were relying on the old inconsistent behavior, set `strictValidation: true` explicitly.
|
|
742
400
|
|
|
743
|
-
|
|
401
|
+
#### Enhanced Behavior (Self-Signed Tokens)
|
|
744
402
|
|
|
745
|
-
|
|
403
|
+
Self-signed tokens can now be verified multiple times, which is essential for:
|
|
746
404
|
|
|
747
|
-
-
|
|
748
|
-
-
|
|
749
|
-
-
|
|
750
|
-
- ✅ Real Pinecone integration
|
|
751
|
-
- ✅ Error handling and cost estimation
|
|
752
|
-
- ✅ Comprehensive documentation
|
|
405
|
+
- Refresh token flows
|
|
406
|
+
- Load balancer retries
|
|
407
|
+
- Distributed systems with eventual consistency
|
|
753
408
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
```bash
|
|
757
|
-
cd examples/openai-pinecone
|
|
758
|
-
npm install
|
|
759
|
-
|
|
760
|
-
# Test with mock mode (no API keys needed)
|
|
761
|
-
USE_MOCK_MODE=true npm start
|
|
409
|
+
```javascript
|
|
410
|
+
const token = validator.sign({ sub: "user-123" });
|
|
762
411
|
|
|
763
|
-
|
|
764
|
-
|
|
412
|
+
// Before v2.3.0: Second verification would throw "replay detected"
|
|
413
|
+
// After v2.3.0: Works correctly for self-signed tokens
|
|
414
|
+
validator.verify(token); // Works
|
|
415
|
+
validator.verify(token); // Now works!
|
|
765
416
|
```
|
|
766
417
|
|
|
767
|
-
|
|
418
|
+
External tokens (not signed by your validator) are still correctly blocked on replay.
|
|
768
419
|
|
|
769
|
-
|
|
420
|
+
### Input Sanitizer Changes
|
|
770
421
|
|
|
771
|
-
|
|
772
|
-
class OpenAIEmbedder {
|
|
773
|
-
constructor({ apiKey, model = "text-embedding-ada-002" }) {
|
|
774
|
-
this.client = new OpenAI({ apiKey });
|
|
775
|
-
this.model = model;
|
|
776
|
-
}
|
|
422
|
+
#### Path Traversal Now Always Throws
|
|
777
423
|
|
|
778
|
-
|
|
779
|
-
const response = await this.client.embeddings.create({
|
|
780
|
-
model: this.model,
|
|
781
|
-
input: texts,
|
|
782
|
-
});
|
|
783
|
-
return response.data.map((d) => d.embedding);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
424
|
+
Path traversal attempts now **always throw errors**, even with `throwOnInvalid: false`:
|
|
786
425
|
|
|
787
|
-
|
|
788
|
-
constructor({ apiKey, model = "gpt-4" }) {
|
|
789
|
-
this.client = new OpenAI({ apiKey });
|
|
790
|
-
this.model = model;
|
|
791
|
-
}
|
|
426
|
+
**Before v2.3.0:**
|
|
792
427
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
});
|
|
798
|
-
return { text: response.choices[0].message.content };
|
|
799
|
-
}
|
|
800
|
-
}
|
|
428
|
+
```javascript
|
|
429
|
+
const sanitizer = new InputSanitizer({ throwOnInvalid: false });
|
|
430
|
+
const result = sanitizePath("../../../etc/passwd");
|
|
431
|
+
// Returned: null (silent failure)
|
|
801
432
|
```
|
|
802
433
|
|
|
803
|
-
|
|
434
|
+
**After v2.3.0:**
|
|
804
435
|
|
|
805
436
|
```javascript
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
}
|
|
437
|
+
const sanitizer = new InputSanitizer({ throwOnInvalid: false });
|
|
438
|
+
const result = sanitizePath("../../../etc/passwd");
|
|
439
|
+
// Throws: "Potential path traversal detected"
|
|
440
|
+
```
|
|
811
441
|
|
|
812
|
-
|
|
813
|
-
const collection = await this.client.getOrCreateCollection({
|
|
814
|
-
name: this.collectionName,
|
|
815
|
-
});
|
|
442
|
+
**Rationale:** Path traversal is a critical security violation that should never be silently ignored.
|
|
816
443
|
|
|
817
|
-
|
|
818
|
-
embeddings: vectors,
|
|
819
|
-
metadatas: metadata,
|
|
820
|
-
ids: metadata.map((_, i) => `doc_${i}`),
|
|
821
|
-
});
|
|
822
|
-
}
|
|
444
|
+
**Migration:** Wrap path sanitization in try-catch if you need to handle errors gracefully:
|
|
823
445
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
});
|
|
833
|
-
|
|
834
|
-
return results.metadatas[0].map((meta, i) => ({
|
|
835
|
-
content: results.documents[0][i],
|
|
836
|
-
metadata: meta,
|
|
837
|
-
score: 1 - results.distances[0][i],
|
|
838
|
-
}));
|
|
446
|
+
```javascript
|
|
447
|
+
try {
|
|
448
|
+
const safePath = sanitizePath(userInput);
|
|
449
|
+
// Use safePath
|
|
450
|
+
} catch (error) {
|
|
451
|
+
if (error.message.includes("path traversal")) {
|
|
452
|
+
// Handle attack attempt
|
|
453
|
+
logger.warn("Path traversal blocked", { input: userInput });
|
|
454
|
+
return res.status(400).json({ error: "Invalid path" });
|
|
839
455
|
}
|
|
456
|
+
throw error;
|
|
840
457
|
}
|
|
841
458
|
```
|
|
842
459
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
### Common Issues
|
|
460
|
+
### Breaking Changes
|
|
846
461
|
|
|
847
|
-
**
|
|
462
|
+
**None.** All changes are security enhancements that improve correctness without breaking existing valid use cases.
|
|
848
463
|
|
|
849
|
-
|
|
850
|
-
npm install @devilsdev/rag-pipeline-utils
|
|
851
|
-
```
|
|
464
|
+
### Testing Your Upgrade
|
|
852
465
|
|
|
853
|
-
|
|
466
|
+
Run your test suite after upgrading:
|
|
854
467
|
|
|
855
|
-
```
|
|
856
|
-
|
|
857
|
-
pluginRegistry.register("my-embedder", MyEmbedderClass);
|
|
468
|
+
```bash
|
|
469
|
+
npm test
|
|
858
470
|
```
|
|
859
471
|
|
|
860
|
-
|
|
472
|
+
If you encounter issues, please [open an issue](https://github.com/DevilsDev/rag-pipeline-utils/issues) with details about your configuration.
|
|
861
473
|
|
|
862
|
-
|
|
863
|
-
// Validate your configuration
|
|
864
|
-
const { validateRagrc } = require("@devilsdev/rag-pipeline-utils");
|
|
865
|
-
const isValid = validateRagrc(config);
|
|
866
|
-
if (!isValid) {
|
|
867
|
-
console.error("Configuration is invalid");
|
|
868
|
-
}
|
|
869
|
-
```
|
|
474
|
+
---
|
|
870
475
|
|
|
871
|
-
|
|
476
|
+
## Contributing
|
|
872
477
|
|
|
873
|
-
|
|
874
|
-
const { logger } = require("@devilsdev/rag-pipeline-utils");
|
|
478
|
+
We welcome contributions of all kinds:
|
|
875
479
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
480
|
+
- **Code** – Fix bugs, add features, improve performance
|
|
481
|
+
- **Documentation** – Write guides, improve examples, clarify concepts
|
|
482
|
+
- **Testing** – Expand test coverage, add integration tests, report edge cases
|
|
483
|
+
- **Design** – Propose API improvements, suggest architectural patterns
|
|
484
|
+
- **Community** – Answer questions, review pull requests, mentor new contributors
|
|
879
485
|
|
|
880
|
-
|
|
486
|
+
**Before You Start:**
|
|
881
487
|
|
|
882
|
-
|
|
488
|
+
1. Read the [Contributing Guide](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/docs/CONTRIBUTING.md)
|
|
489
|
+
2. Check existing [Issues](https://github.com/DevilsDev/rag-pipeline-utils/issues) and [Discussions](https://github.com/DevilsDev/rag-pipeline-utils/discussions)
|
|
490
|
+
3. Open an issue to discuss major changes before coding
|
|
491
|
+
4. Follow our [Code of Conduct](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/CODE_OF_CONDUCT.md)
|
|
883
492
|
|
|
884
|
-
**
|
|
493
|
+
**Pull Request Checklist:**
|
|
885
494
|
|
|
886
|
-
-
|
|
887
|
-
-
|
|
888
|
-
-
|
|
889
|
-
-
|
|
890
|
-
-
|
|
495
|
+
- [ ] Tests pass (`npm test`)
|
|
496
|
+
- [ ] Linter passes (`npm run lint`)
|
|
497
|
+
- [ ] Documentation updated
|
|
498
|
+
- [ ] Changelog entry added
|
|
499
|
+
- [ ] Type definitions updated (if applicable)
|
|
891
500
|
|
|
892
|
-
|
|
501
|
+
---
|
|
893
502
|
|
|
894
|
-
|
|
895
|
-
- Simple in-memory implementation
|
|
896
|
-
- Perfect for learning and prototyping
|
|
503
|
+
## License
|
|
897
504
|
|
|
898
|
-
|
|
505
|
+
**GPL-3.0** – See [LICENSE](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/LICENSE) for full terms.
|
|
899
506
|
|
|
900
|
-
|
|
901
|
-
- [Issue Tracker](https://github.com/DevilsDev/rag-pipeline-utils/issues)
|
|
902
|
-
- [Discussions](https://github.com/DevilsDev/rag-pipeline-utils/discussions)
|
|
903
|
-
- [OpenAI + Pinecone Example](examples/openai-pinecone/) (NEW)
|
|
904
|
-
- [Release Notes](https://github.com/DevilsDev/rag-pipeline-utils/releases)
|
|
905
|
-
- [CHANGELOG](CHANGELOG.md)
|
|
507
|
+
This is free software: you are free to change and redistribute it under the terms of the GNU General Public License version 3.
|
|
906
508
|
|
|
907
|
-
|
|
509
|
+
---
|
|
908
510
|
|
|
909
|
-
|
|
511
|
+
## What's Next?
|
|
910
512
|
|
|
911
|
-
|
|
513
|
+
**Star this repository** if you find it useful—it helps others discover the project.
|
|
912
514
|
|
|
913
|
-
|
|
515
|
+
**Share your use case** in [Discussions](https://github.com/DevilsDev/rag-pipeline-utils/discussions/categories/show-and-tell) to inspire the community.
|
|
914
516
|
|
|
915
|
-
|
|
517
|
+
**Contribute** your first pull request—check out issues tagged [good first issue](https://github.com/DevilsDev/rag-pipeline-utils/labels/good%20first%20issue).
|
|
916
518
|
|
|
917
|
-
|
|
918
|
-
- Discussions: https://github.com/DevilsDev/rag-pipeline-utils/discussions
|
|
519
|
+
Happy building.
|