@beingmartinbmc/ojas 0.2.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/LICENSE +21 -0
- package/README.md +308 -0
- package/dist/aahar/index.d.ts +179 -0
- package/dist/aahar/index.d.ts.map +1 -0
- package/dist/aahar/index.js +657 -0
- package/dist/aahar/index.js.map +1 -0
- package/dist/aahar/scoring.d.ts +85 -0
- package/dist/aahar/scoring.d.ts.map +1 -0
- package/dist/aahar/scoring.js +268 -0
- package/dist/aahar/scoring.js.map +1 -0
- package/dist/agni/index.d.ts +113 -0
- package/dist/agni/index.d.ts.map +1 -0
- package/dist/agni/index.js +328 -0
- package/dist/agni/index.js.map +1 -0
- package/dist/agni/model-router.d.ts +77 -0
- package/dist/agni/model-router.d.ts.map +1 -0
- package/dist/agni/model-router.js +163 -0
- package/dist/agni/model-router.js.map +1 -0
- package/dist/agni/response-distiller.d.ts +37 -0
- package/dist/agni/response-distiller.d.ts.map +1 -0
- package/dist/agni/response-distiller.js +193 -0
- package/dist/agni/response-distiller.js.map +1 -0
- package/dist/agni/tiktoken-adapter.d.ts +55 -0
- package/dist/agni/tiktoken-adapter.d.ts.map +1 -0
- package/dist/agni/tiktoken-adapter.js +113 -0
- package/dist/agni/tiktoken-adapter.js.map +1 -0
- package/dist/chikitsa/index.d.ts +130 -0
- package/dist/chikitsa/index.d.ts.map +1 -0
- package/dist/chikitsa/index.js +565 -0
- package/dist/chikitsa/index.js.map +1 -0
- package/dist/demo.d.ts +15 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +278 -0
- package/dist/demo.js.map +1 -0
- package/dist/index.d.ts +201 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +588 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/audit.d.ts +39 -0
- package/dist/mcp/audit.d.ts.map +1 -0
- package/dist/mcp/audit.js +73 -0
- package/dist/mcp/audit.js.map +1 -0
- package/dist/mcp/contracts.d.ts +76 -0
- package/dist/mcp/contracts.d.ts.map +1 -0
- package/dist/mcp/contracts.js +44 -0
- package/dist/mcp/contracts.js.map +1 -0
- package/dist/mcp/envelope.d.ts +107 -0
- package/dist/mcp/envelope.d.ts.map +1 -0
- package/dist/mcp/envelope.js +162 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/registry.d.ts +110 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +258 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/server.d.ts +26 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +107 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/agent.d.ts +4 -0
- package/dist/mcp/tools/agent.d.ts.map +1 -0
- package/dist/mcp/tools/agent.js +300 -0
- package/dist/mcp/tools/agent.js.map +1 -0
- package/dist/mcp/tools/context.d.ts +4 -0
- package/dist/mcp/tools/context.d.ts.map +1 -0
- package/dist/mcp/tools/context.js +261 -0
- package/dist/mcp/tools/context.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +5 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +20 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/memory.d.ts +4 -0
- package/dist/mcp/tools/memory.d.ts.map +1 -0
- package/dist/mcp/tools/memory.js +220 -0
- package/dist/mcp/tools/memory.js.map +1 -0
- package/dist/mcp/tools/output.d.ts +4 -0
- package/dist/mcp/tools/output.d.ts.map +1 -0
- package/dist/mcp/tools/output.js +206 -0
- package/dist/mcp/tools/output.js.map +1 -0
- package/dist/mcp/tools/recovery.d.ts +4 -0
- package/dist/mcp/tools/recovery.d.ts.map +1 -0
- package/dist/mcp/tools/recovery.js +165 -0
- package/dist/mcp/tools/recovery.js.map +1 -0
- package/dist/mcp/tools/registrar.d.ts +4 -0
- package/dist/mcp/tools/registrar.d.ts.map +1 -0
- package/dist/mcp/tools/registrar.js +17 -0
- package/dist/mcp/tools/registrar.js.map +1 -0
- package/dist/mcp/tools/report.d.ts +4 -0
- package/dist/mcp/tools/report.d.ts.map +1 -0
- package/dist/mcp/tools/report.js +68 -0
- package/dist/mcp/tools/report.js.map +1 -0
- package/dist/mcp/tools/shared.d.ts +37 -0
- package/dist/mcp/tools/shared.d.ts.map +1 -0
- package/dist/mcp/tools/shared.js +214 -0
- package/dist/mcp/tools/shared.js.map +1 -0
- package/dist/mcp/trace.d.ts +47 -0
- package/dist/mcp/trace.d.ts.map +1 -0
- package/dist/mcp/trace.js +216 -0
- package/dist/mcp/trace.js.map +1 -0
- package/dist/nidra/index.d.ts +275 -0
- package/dist/nidra/index.d.ts.map +1 -0
- package/dist/nidra/index.js +889 -0
- package/dist/nidra/index.js.map +1 -0
- package/dist/persistence/migrations.d.ts +10 -0
- package/dist/persistence/migrations.d.ts.map +1 -0
- package/dist/persistence/migrations.js +77 -0
- package/dist/persistence/migrations.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +30 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +209 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +104 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +5 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/pulse/index.d.ts +144 -0
- package/dist/pulse/index.d.ts.map +1 -0
- package/dist/pulse/index.js +453 -0
- package/dist/pulse/index.js.map +1 -0
- package/dist/raksha/classifiers/http-classifier.d.ts +26 -0
- package/dist/raksha/classifiers/http-classifier.d.ts.map +1 -0
- package/dist/raksha/classifiers/http-classifier.js +62 -0
- package/dist/raksha/classifiers/http-classifier.js.map +1 -0
- package/dist/raksha/classifiers/index.d.ts +5 -0
- package/dist/raksha/classifiers/index.d.ts.map +1 -0
- package/dist/raksha/classifiers/index.js +8 -0
- package/dist/raksha/classifiers/index.js.map +1 -0
- package/dist/raksha/classifiers/onnx-classifier.d.ts +41 -0
- package/dist/raksha/classifiers/onnx-classifier.d.ts.map +1 -0
- package/dist/raksha/classifiers/onnx-classifier.js +99 -0
- package/dist/raksha/classifiers/onnx-classifier.js.map +1 -0
- package/dist/raksha/hallucination-detectors.d.ts +106 -0
- package/dist/raksha/hallucination-detectors.d.ts.map +1 -0
- package/dist/raksha/hallucination-detectors.js +327 -0
- package/dist/raksha/hallucination-detectors.js.map +1 -0
- package/dist/raksha/index.d.ts +168 -0
- package/dist/raksha/index.d.ts.map +1 -0
- package/dist/raksha/index.js +597 -0
- package/dist/raksha/index.js.map +1 -0
- package/dist/raksha/prompt-injection-detectors.d.ts +30 -0
- package/dist/raksha/prompt-injection-detectors.d.ts.map +1 -0
- package/dist/raksha/prompt-injection-detectors.js +153 -0
- package/dist/raksha/prompt-injection-detectors.js.map +1 -0
- package/dist/types.d.ts +1115 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +71 -0
- package/dist/types.js.map +1 -0
- package/dist/util/calibration.d.ts +32 -0
- package/dist/util/calibration.d.ts.map +1 -0
- package/dist/util/calibration.js +108 -0
- package/dist/util/calibration.js.map +1 -0
- package/dist/util/id.d.ts +2 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +9 -0
- package/dist/util/id.js.map +1 -0
- package/dist/vyayam/index.d.ts +76 -0
- package/dist/vyayam/index.d.ts.map +1 -0
- package/dist/vyayam/index.js +528 -0
- package/dist/vyayam/index.js.map +1 -0
- package/dist/vyayam/tool-fault-proxy.d.ts +95 -0
- package/dist/vyayam/tool-fault-proxy.d.ts.map +1 -0
- package/dist/vyayam/tool-fault-proxy.js +170 -0
- package/dist/vyayam/tool-fault-proxy.js.map +1 -0
- package/docs/ARCHITECTURE.md +162 -0
- package/docs/BACKLOG.md +342 -0
- package/docs/CONFIGURATION.md +305 -0
- package/docs/EVIDENCE.md +232 -0
- package/docs/EVIDENCE_MATRIX.md +293 -0
- package/docs/KNOWN_FAILURES.md +367 -0
- package/docs/MCP.md +614 -0
- package/docs/MODULES.md +368 -0
- package/docs/SECURITY.md +251 -0
- package/docs/TRUST.md +88 -0
- package/docs/assets/ojas-hero.png +0 -0
- package/package.json +101 -0
package/docs/MODULES.md
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Module Reference
|
|
2
|
+
|
|
3
|
+
Seven specialised modules. Each maps to an analogue of a human-health system. Each exposes a 0–100 health score plus lower-level dimensions surfaced through `healthCheck()` and the MCP `ojas_get_health` / `ojas_generate_health_report` tools.
|
|
4
|
+
|
|
5
|
+
| Section | Role |
|
|
6
|
+
|---|---|
|
|
7
|
+
| [🥗 Aahar — Cognitive Nutrition](#aahar) | What the agent reads |
|
|
8
|
+
| [😴 Nidra — Recovery & Consolidation](#nidra) | How the agent learns from experience |
|
|
9
|
+
| [💪 Vyayam — Resilience & Stress](#vyayam) | How the agent holds up under pressure |
|
|
10
|
+
| [🛡️ Raksha — Immune Defense](#raksha) | What threats the agent rejects |
|
|
11
|
+
| [🔥 Agni — Cognitive Metabolism](#agni) | How efficiently the agent burns tokens / latency / tools |
|
|
12
|
+
| [📈 Pulse — Health Telemetry](#pulse) | Continuous vital-signs bus |
|
|
13
|
+
| [🩺 Chikitsa — Repair & Rehabilitation](#chikitsa) | What to do when something breaks |
|
|
14
|
+
| [Unified Health Report](#report) | Aggregate score + per-module dimensions |
|
|
15
|
+
| [Health Events](#events) | Canonical event payloads emitted by Pulse |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<a id="aahar"></a>
|
|
20
|
+
## 🥗 1. Aahar (आहार) — Cognitive Nutrition
|
|
21
|
+
|
|
22
|
+
Aahar controls what an AI agent cognitively consumes.
|
|
23
|
+
|
|
24
|
+
Agents consume context, retrieval results, memory, instructions, tool outputs, and prior reasoning traces. Poor intake leads to hallucination, instability, wasted tokens, and planning errors.
|
|
25
|
+
|
|
26
|
+
Aahar helps by:
|
|
27
|
+
|
|
28
|
+
- filtering irrelevant, stale, redundant, or noisy context
|
|
29
|
+
- ranking context by relevance, freshness, trust, and risk
|
|
30
|
+
- reducing cognitive load and attention fragmentation
|
|
31
|
+
- improving signal-to-noise ratio per token
|
|
32
|
+
- keeping the agent focused on the current objective
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const healthy = ojas.feed(rawContextItems);
|
|
36
|
+
|
|
37
|
+
const result = await ojas.feedAndProcess(
|
|
38
|
+
'Design an API',
|
|
39
|
+
rawContextItems
|
|
40
|
+
);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Under the hood, `feed()` runs Raksha first, then Aahar:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
raw context → immune defense → nutrition scoring → healthy context
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
<a id="nidra"></a>
|
|
52
|
+
## 😴 2. Nidra (निद्रा) — Recovery and Consolidation
|
|
53
|
+
|
|
54
|
+
Nidra controls how agents recover, stabilize, and learn from experience.
|
|
55
|
+
|
|
56
|
+
Human sleep consolidates memory, removes noise, and restores cognition. Nidra brings the same idea to agent runtimes by turning execution traces into reusable intelligence.
|
|
57
|
+
|
|
58
|
+
Nidra helps by:
|
|
59
|
+
|
|
60
|
+
- consolidating traces into memories and heuristics
|
|
61
|
+
- detecting repeated failures and drift patterns
|
|
62
|
+
- compressing experience into reusable summaries
|
|
63
|
+
- reducing memory noise and cognitive instability
|
|
64
|
+
- extracting lessons from completed tasks
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
ojas.recordTrace({
|
|
68
|
+
id: 'trace-1',
|
|
69
|
+
agentId: 'research-agent',
|
|
70
|
+
action: 'search',
|
|
71
|
+
input: {},
|
|
72
|
+
output: {},
|
|
73
|
+
success: true,
|
|
74
|
+
durationMs: 120,
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const recovery = await ojas.recover();
|
|
79
|
+
|
|
80
|
+
console.log(recovery.recovered);
|
|
81
|
+
console.log(recovery.memoriesCreated);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Consolidated memories can be injected back into the bound agent through the `AgentAdapter` interface.
|
|
85
|
+
|
|
86
|
+
> **Transactionality:** `Ojas.recover()` is two-phase — `Nidra.analyseUnprocessed()` produces candidate memories without mutating, each is injected into the agent via `injectMemory()`, then `Nidra.commitAnalysis()` commits. If any injection throws, no traces are marked processed and no memories are persisted; a `recovery_injection_failed` pulse event explains the abort. See [`docs/CONFIGURATION.md`](./CONFIGURATION.md#adapter) for the adapter contract.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
<a id="vyayam"></a>
|
|
91
|
+
## 💪 3. Vyayam (व्यायाम) — Resilience and Stress Engineering
|
|
92
|
+
|
|
93
|
+
Vyayam controls how agents become stronger under pressure.
|
|
94
|
+
|
|
95
|
+
Agents should not only be tested in clean, ideal conditions. They must be tested against ambiguity, hostile inputs, tool failures, memory corruption, and unstable environments.
|
|
96
|
+
|
|
97
|
+
Vyayam helps by:
|
|
98
|
+
|
|
99
|
+
- generating controlled stress scenarios
|
|
100
|
+
- testing prompt-injection resistance
|
|
101
|
+
- simulating tool failure, latency, and conflicting instructions
|
|
102
|
+
- measuring hallucination resistance and recovery ability
|
|
103
|
+
- identifying fragile workflows and weak reasoning patterns
|
|
104
|
+
|
|
105
|
+
Supported stress types include:
|
|
106
|
+
|
|
107
|
+
- adversarial input
|
|
108
|
+
- prompt injection
|
|
109
|
+
- memory corruption
|
|
110
|
+
- tool failure
|
|
111
|
+
- latency spike
|
|
112
|
+
- conflicting instructions
|
|
113
|
+
- context overflow
|
|
114
|
+
- ambiguous goal
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const results = await ojas.stressTest();
|
|
118
|
+
|
|
119
|
+
console.log(results.passed);
|
|
120
|
+
console.log(results.failed);
|
|
121
|
+
console.log(results.hallucinationsDetected);
|
|
122
|
+
|
|
123
|
+
const scenario = ojas.vyayam.generateScenario('prompt_injection', 0.8);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
> Each scenario runs against the bound agent within `policy.maxScenarioDurationMs` (default 30s). Agents that exceed the budget are recorded as failed scenarios rather than hanging the harness.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
<a id="raksha"></a>
|
|
131
|
+
## 🛡️ 4. Raksha (रक्षा) — Immune Defense (heuristic tripwire)
|
|
132
|
+
|
|
133
|
+
Raksha is a **regex-based prompt-injection tripwire**. It catches canonical attempts to override instructions, exfiltrate secrets, or confuse the agent's role, and it now reduces several common obfuscation bypasses (Cyrillic/Greek homoglyphs, zero-width insertions, full-width Latin, and one-shot printable base64). It still misses recursive obfuscation, non-covered homoglyphs, indirect/multi-document injection, policy laundering, and roleplay attacks — see [`KNOWN_FAILURES.md` → Raksha](./KNOWN_FAILURES.md#raksha-heuristic-regex-tripwire-with-a-bypass-reduction-pipeline). Treat it as one layer in defence-in-depth, not as a security boundary.
|
|
134
|
+
|
|
135
|
+
As agents consume web pages, documents, tool outputs, code, emails, and memories, they become vulnerable to malicious instructions and memory poisoning.
|
|
136
|
+
|
|
137
|
+
Raksha helps by:
|
|
138
|
+
|
|
139
|
+
- flagging canonical prompt-injection and instruction-override phrasings
|
|
140
|
+
- flagging canonical role-confusion and data-exfiltration phrasings
|
|
141
|
+
- quarantining risky context before it reaches the agent (heuristic; bypassable)
|
|
142
|
+
- preserving the system / developer / user instruction hierarchy by routing flagged items into quarantine
|
|
143
|
+
- downgrading or rejecting unsafe / low-confidence long-term memory writes
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const { safe, quarantined, assessments } = ojas.raksha.defendContext(items);
|
|
147
|
+
|
|
148
|
+
console.log(safe);
|
|
149
|
+
console.log(quarantined);
|
|
150
|
+
console.log(assessments);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Example assessment:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
{
|
|
157
|
+
itemId: 'ctx-12',
|
|
158
|
+
threatType: 'prompt_injection',
|
|
159
|
+
riskScore: 0.72,
|
|
160
|
+
quarantined: true,
|
|
161
|
+
reasons: ['Attempts to override higher-priority instructions.']
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
> Raksha is a regex-based tripwire today, not a learned classifier. Do **not** rely on it as a sole defence. Read [`SECURITY.md`](./SECURITY.md) and [`KNOWN_FAILURES.md`](./KNOWN_FAILURES.md) before deploying.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
<a id="agni"></a>
|
|
170
|
+
## 🔥 5. Agni (अग्नि) — Cognitive Metabolism
|
|
171
|
+
|
|
172
|
+
Agni manages how efficiently the agent converts cognitive intake into useful action.
|
|
173
|
+
|
|
174
|
+
Agent cost is not only model cost. It also includes token waste, unnecessary retrieval, repeated tool calls, long latency, excessive reasoning, and failed retries.
|
|
175
|
+
|
|
176
|
+
Agni helps by:
|
|
177
|
+
|
|
178
|
+
- estimating reasoning depth from task risk and ambiguity
|
|
179
|
+
- optimizing token budgets and retrieval volume
|
|
180
|
+
- tracking latency and cost pressure
|
|
181
|
+
- detecting wasteful tool usage
|
|
182
|
+
- balancing deep reasoning with fast execution
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
const effort = ojas.agni.estimateReasoningEffort(0.9, 0.7);
|
|
186
|
+
// → 'deep'
|
|
187
|
+
|
|
188
|
+
const metabolism = ojas.agni.assess();
|
|
189
|
+
|
|
190
|
+
console.log(metabolism.tokenEfficiency);
|
|
191
|
+
console.log(metabolism.toolEconomy);
|
|
192
|
+
console.log(metabolism.costPressure);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
> **Token accounting falls back through three tiers:** explicit `trace.tokensUsed` → `trace.inputTokens + trace.outputTokens` → payload-length estimate. Failed tool calls still count against the average, because failed tokens still cost money.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
<a id="pulse"></a>
|
|
200
|
+
## 📈 6. Pulse — Health Telemetry
|
|
201
|
+
|
|
202
|
+
Pulse continuously monitors the agent's cognitive vital signs.
|
|
203
|
+
|
|
204
|
+
Traditional telemetry tracks latency, logs, and errors. Pulse tracks agent health: clarity, context quality, memory health, drift, recovery, resilience, trust, and stability.
|
|
205
|
+
|
|
206
|
+
Pulse helps by:
|
|
207
|
+
|
|
208
|
+
- emitting structured health events
|
|
209
|
+
- detecting degradation before complete failure
|
|
210
|
+
- tracking repeated loops, fallback overuse, and contradiction
|
|
211
|
+
- routing health triggers to the correct Ojas module
|
|
212
|
+
- supporting dashboards and alerting systems
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const telemetry = ojas.pulse.assess();
|
|
216
|
+
|
|
217
|
+
console.log(telemetry.vitalSigns);
|
|
218
|
+
console.log(telemetry.degradationRisk);
|
|
219
|
+
console.log(telemetry.activeAlerts);
|
|
220
|
+
|
|
221
|
+
const events = ojas.pulse.getEvents();
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
<a id="chikitsa"></a>
|
|
227
|
+
## 🩺 7. Chikitsa (चिकित्सा) — Repair and Rehabilitation
|
|
228
|
+
|
|
229
|
+
Chikitsa diagnoses failures and generates structured repair protocols.
|
|
230
|
+
|
|
231
|
+
When an agent fails, the cause may be bad context, weak planning, unsafe memory, retrieval error, tool failure, instruction conflict, prompt injection, or model limitation. Chikitsa classifies the failure and recommends recovery actions.
|
|
232
|
+
|
|
233
|
+
Chikitsa helps by:
|
|
234
|
+
|
|
235
|
+
- identifying the likely failure cause
|
|
236
|
+
- generating repair protocols
|
|
237
|
+
- recommending rollback, reset, retry, or escalation
|
|
238
|
+
- preparing agents for rehabilitation through Vyayam
|
|
239
|
+
- recommending recovery so repeated failures don't become permanent behaviour *(advisory; correctness of the recommendation is not measured — see [`KNOWN_FAILURES.md` → Chikitsa](./KNOWN_FAILURES.md#chikitsa-recommendations-are-pattern-lookups))*
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
const protocols = ojas.chikitsa.diagnose([
|
|
243
|
+
{
|
|
244
|
+
type: 'tool_error',
|
|
245
|
+
message: 'Search API returned 503',
|
|
246
|
+
severity: 'high',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
type: 'prompt_injection',
|
|
250
|
+
message: 'Instruction override attempt detected',
|
|
251
|
+
severity: 'critical',
|
|
252
|
+
},
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
console.log(protocols);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Example protocol actions:
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
context_reset
|
|
262
|
+
memory_rollback
|
|
263
|
+
tool_retry
|
|
264
|
+
plan_regeneration
|
|
265
|
+
retrieval_refresh
|
|
266
|
+
instruction_regrounding
|
|
267
|
+
safe_mode_activation
|
|
268
|
+
human_escalation
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
> **Preview vs commit:** `previewDiagnose()` returns the same protocols `diagnose()` would emit but without recording them. Useful inside `healthCheck()`, which is intentionally read-only and surfaces would-be repairs via the `previewRepairProtocols` field.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
<a id="report"></a>
|
|
276
|
+
## Unified Health Report
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const report = ojas.healthCheck(activeContext);
|
|
280
|
+
|
|
281
|
+
console.log(`Overall: ${Math.round(report.overall.value * 100)} / 100`);
|
|
282
|
+
console.log(report.moduleScores);
|
|
283
|
+
console.log(report.recommendations);
|
|
284
|
+
console.log(report.events);
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Example `moduleScores`:
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
{
|
|
291
|
+
aahar: 91,
|
|
292
|
+
nidra: 78,
|
|
293
|
+
vyayam: 97,
|
|
294
|
+
raksha: 93,
|
|
295
|
+
agni: 96,
|
|
296
|
+
pulse: 68,
|
|
297
|
+
chikitsa: 72
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Each module exposes a 0–100 health score plus lower-level dimensions:
|
|
302
|
+
|
|
303
|
+
| Module | Dimensions |
|
|
304
|
+
|---|---|
|
|
305
|
+
| `aahar` | `contextQuality`, `cognitiveLoad`, `attentionFocus`, `signalToNoise`, `tokenEfficiency` |
|
|
306
|
+
| `nidra` | `memoryConsolidation`, `cognitiveStability`, `learningRate`, `driftScore` |
|
|
307
|
+
| `vyayam` | `overallResilience`, `hallucinationResistance`, `recoveryAbility`, `planningStability`, `weaknesses[]` |
|
|
308
|
+
| `raksha` | `threatResistance`, `instructionIntegrity`, `quarantineEffectiveness`, `threatsDetected`, `quarantinedItems` |
|
|
309
|
+
| `agni` | `tokenEfficiency`, `toolEconomy`, `reasoningEfficiency`, `latencyEfficiency`, `costPressure` |
|
|
310
|
+
| `pulse` | `vitalSigns`, `degradationRisk`, `observabilityCoverage`, `eventsEmitted`, `activeAlerts` |
|
|
311
|
+
| `chikitsa` | `repairReadiness`, `rollbackSafety`, `recoveryPlaybooks`, `protocolsAvailable` |
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
<a id="events"></a>
|
|
316
|
+
## Health Events
|
|
317
|
+
|
|
318
|
+
Ojas emits canonical health events that can be consumed by dashboards, logs, alerting systems, or MCP clients.
|
|
319
|
+
|
|
320
|
+
### Context overload
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
{
|
|
324
|
+
eventType: 'context_overload_detected',
|
|
325
|
+
detectedBy: 'aahar',
|
|
326
|
+
severity: 'medium',
|
|
327
|
+
details: {
|
|
328
|
+
contextTokens: 128000,
|
|
329
|
+
relevanceScore: 0.52,
|
|
330
|
+
duplicateContextRatio: 0.31,
|
|
331
|
+
},
|
|
332
|
+
recommendedAction: 'compress_context_and_rerank_memory',
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Recovery completed
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
{
|
|
340
|
+
eventType: 'recovery_cycle_completed',
|
|
341
|
+
detectedBy: 'nidra',
|
|
342
|
+
details: {
|
|
343
|
+
rawTracesProcessed: 42,
|
|
344
|
+
memoriesCreated: 5,
|
|
345
|
+
memoriesPruned: 11,
|
|
346
|
+
heuristicsUpdated: 3,
|
|
347
|
+
driftReduction: 0.18,
|
|
348
|
+
},
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Prompt injection quarantined
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
{
|
|
356
|
+
eventType: 'prompt_injection_quarantined',
|
|
357
|
+
detectedBy: 'raksha',
|
|
358
|
+
severity: 'critical',
|
|
359
|
+
details: {
|
|
360
|
+
source: 'retrieved_webpage',
|
|
361
|
+
attackType: 'instruction_override',
|
|
362
|
+
riskScore: 0.72,
|
|
363
|
+
actionTaken: 'quarantined_from_agent_context',
|
|
364
|
+
},
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
See `KnownHealthEventType` and the `*Details` interfaces in `src/types.ts` for the full event schema.
|
package/docs/SECURITY.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Security policy for Ojas
|
|
2
|
+
|
|
3
|
+
> **Trust model in one sentence:** Ojas v0.3 is **stdio-only, single
|
|
4
|
+
> trusted tenant**. The MCP host that launches the process is trusted;
|
|
5
|
+
> agent IDs are *routing identifiers, not credentials*. The security
|
|
6
|
+
> boundary is the OS / process boundary, not a per-call authentication
|
|
7
|
+
> layer. Acknowledge the model by setting `OJAS_TRUSTED_SINGLE_TENANT=1`
|
|
8
|
+
> (otherwise the server emits a loud stderr warning at startup). Do
|
|
9
|
+
> **not** expose the MCP server to untrusted callers, multiple tenants,
|
|
10
|
+
> or the network without an external authenticated gateway.
|
|
11
|
+
|
|
12
|
+
## MCP authentication
|
|
13
|
+
|
|
14
|
+
Ojas MCP v0.3 is **stdio-only**. Stdio MCP does not provide a portable
|
|
15
|
+
caller identity, bearer-token channel, or per-request auth context —
|
|
16
|
+
the host that launches the process *is* the caller. Therefore Ojas does
|
|
17
|
+
not implement in-process MCP authentication in this version, and that
|
|
18
|
+
is **a scope decision, not a missing feature**.
|
|
19
|
+
|
|
20
|
+
The security boundary is the local OS / process boundary. Use:
|
|
21
|
+
|
|
22
|
+
- one process per trusted user / workspace
|
|
23
|
+
- OS user isolation
|
|
24
|
+
- workspace-specific configuration
|
|
25
|
+
- `OJAS_DISABLE_AUTO_REGISTER=1`
|
|
26
|
+
- `OJAS_ALLOWED_AGENT_IDS=<agent>`
|
|
27
|
+
- `OJAS_MAX_AGENTS=1` where appropriate
|
|
28
|
+
|
|
29
|
+
Network transports (HTTP, SSE, streamable-HTTP) are **out of scope**
|
|
30
|
+
unless protected by an external authentication and authorization layer.
|
|
31
|
+
If Ojas ever ships a non-stdio transport, that transport will fail
|
|
32
|
+
closed unless auth is configured.
|
|
33
|
+
|
|
34
|
+
## MCP audit logging
|
|
35
|
+
|
|
36
|
+
When `OJAS_AUDIT=1` is set, the MCP server emits structured JSONL audit
|
|
37
|
+
entries to stderr for critical operations: agent registration, policy
|
|
38
|
+
changes, safe-mode toggles, health checks, and quarantine events. Each
|
|
39
|
+
entry contains `timestamp`, `operation`, `agentId`, `sessionId`,
|
|
40
|
+
`args_summary`, `result_summary`, and `durationMs`.
|
|
41
|
+
|
|
42
|
+
This is a local audit trail, not a centralized log pipeline. For
|
|
43
|
+
production multi-tenant deployments, feed stderr into your SIEM or log
|
|
44
|
+
aggregator.
|
|
45
|
+
|
|
46
|
+
## Recommended network deployment architecture
|
|
47
|
+
|
|
48
|
+
Ojas itself does **not** implement HTTP transport, TLS termination, or
|
|
49
|
+
per-request authentication. For network-facing or multi-user deployments,
|
|
50
|
+
front the Ojas MCP server with an authenticated gateway:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
┌─────────────┐ stdio ┌────────────────┐
|
|
54
|
+
│ nginx / │ ───────────→ │ Ojas MCP │
|
|
55
|
+
│ Caddy + │ │ (stdio server) │
|
|
56
|
+
│ OAuth2 │ └────────────────┘
|
|
57
|
+
│ Proxy │
|
|
58
|
+
└─────────────┘
|
|
59
|
+
↑ HTTPS + OAuth2 / mTLS
|
|
60
|
+
│
|
|
61
|
+
Clients (IDEs, agents, CI)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The gateway should provide:
|
|
65
|
+
- TLS termination
|
|
66
|
+
- OAuth2 / mTLS client authentication
|
|
67
|
+
- Tenant-ID header propagation (Ojas uses `agent_id` as a routing
|
|
68
|
+
identifier; the gateway maps authenticated users to allowed agent IDs)
|
|
69
|
+
- Rate limiting per tenant
|
|
70
|
+
- Request/response logging
|
|
71
|
+
|
|
72
|
+
## Security non-goals for v0.3
|
|
73
|
+
|
|
74
|
+
To prevent recurring review churn, this version explicitly does **not**
|
|
75
|
+
implement:
|
|
76
|
+
|
|
77
|
+
- multi-user authentication on the MCP boundary
|
|
78
|
+
- per-client authorization or capability scoping
|
|
79
|
+
- network-facing access control
|
|
80
|
+
- tenant isolation between agents on the same process
|
|
81
|
+
- secret / token management
|
|
82
|
+
|
|
83
|
+
If you need any of those, run Ojas behind an authenticated MCP gateway
|
|
84
|
+
or use one Ojas process per trusted user / workspace.
|
|
85
|
+
|
|
86
|
+
## Persistence encryption and backup
|
|
87
|
+
|
|
88
|
+
### Encryption-at-rest
|
|
89
|
+
|
|
90
|
+
`SQLitePersistenceStore` supports encryption-at-rest via SQLCipher. Pass
|
|
91
|
+
`encryptionKey` in the options:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const store = new SQLitePersistenceStore({
|
|
95
|
+
dbPath: './ojas-data.db',
|
|
96
|
+
encryptionKey: process.env.OJAS_DB_KEY, // 256-bit key recommended
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This issues `PRAGMA key = '<key>'` at database open. Requires a
|
|
101
|
+
SQLCipher-compatible build of `better-sqlite3` (e.g., build with
|
|
102
|
+
`--build-from-source` against `sqlcipher`).
|
|
103
|
+
|
|
104
|
+
### Backup and restore
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Hot backup (safe while server is running):
|
|
108
|
+
await store.backup('/backups/ojas-2026-05-14.db');
|
|
109
|
+
|
|
110
|
+
// Restore (closes current DB, copies, reopens):
|
|
111
|
+
await store.restore('/backups/ojas-2026-05-14.db');
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Backup cadence recommendation**: daily for development, hourly for
|
|
115
|
+
production single-node deployments. The backup API uses `better-sqlite3`'s
|
|
116
|
+
native `.backup()` which is safe during concurrent reads.
|
|
117
|
+
|
|
118
|
+
### Multi-host architecture pattern
|
|
119
|
+
|
|
120
|
+
For multi-host / multi-tenant / HA production, Ojas's SQLite store is not
|
|
121
|
+
sufficient. Instead:
|
|
122
|
+
|
|
123
|
+
1. Implement `PersistenceStore` against your chosen backend
|
|
124
|
+
(Postgres, Turso, CockroachDB).
|
|
125
|
+
2. Use the `PersistenceStore` interface — it requires `loadSessions`,
|
|
126
|
+
`saveSession`, `deleteSession`, and optionally `backup`/`restore`.
|
|
127
|
+
3. Run one Ojas instance per host, each connected to the shared backend.
|
|
128
|
+
4. Use the external database's own replication, encryption, and backup
|
|
129
|
+
facilities.
|
|
130
|
+
|
|
131
|
+
## Production hardening checklist
|
|
132
|
+
|
|
133
|
+
The Ojas MCP server is designed for local IDE use. Before deploying to
|
|
134
|
+
anything else, at minimum:
|
|
135
|
+
|
|
136
|
+
| Setting | Recommended value | Why |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| `OJAS_TRUSTED_SINGLE_TENANT` | `1` | Acknowledge the trust model. Suppresses the startup warning but does **not** add auth. |
|
|
139
|
+
| `OJAS_DISABLE_AUTO_REGISTER` | `1` | Reject MCP calls for unknown `agent_id`s. Prevents an attacker who knows the schema from spinning up arbitrary agents. |
|
|
140
|
+
| `OJAS_ALLOWED_AGENT_IDS` | `a,b,c` | Hard allowlist of `agent_id`s the server will accept. |
|
|
141
|
+
| `OJAS_MAX_AGENTS` | small number | Bound registry growth. |
|
|
142
|
+
| `OJAS_ALLOW_REPLACE_EXISTING` | unset | Leave OFF in production. Replacement wipes accumulated Ojas state; default is to reject the request. |
|
|
143
|
+
|
|
144
|
+
A defence-in-depth deployment also wraps the MCP server with an
|
|
145
|
+
auth-aware MCP gateway, runs it in a process that cannot reach
|
|
146
|
+
production secrets, and treats every Ojas health score as advisory
|
|
147
|
+
rather than authoritative.
|
|
148
|
+
|
|
149
|
+
## What Ojas's "immune defense" actually is
|
|
150
|
+
|
|
151
|
+
Ojas's Raksha module is **a deterministic detector stack** with an
|
|
152
|
+
optional **async classifier plugin interface**. The rule-based core
|
|
153
|
+
combines patterns, Unicode/base64 bypass reduction, and a semantic-intent
|
|
154
|
+
detector. When `classifiers` are configured, Raksha merges ML
|
|
155
|
+
probabilities with rule-based scores (max wins). It catches forms of:
|
|
156
|
+
|
|
157
|
+
- direct instruction overrides (`ignore previous instructions`, etc.)
|
|
158
|
+
- system / developer / role boundary markup (`<system>...</system>`)
|
|
159
|
+
- exfiltration-shaped phrases (`reveal the api_key`, `print the system prompt`)
|
|
160
|
+
- a handful of role-confusion and memory-poisoning patterns
|
|
161
|
+
- common policy-laundering frames that demote system/developer policy
|
|
162
|
+
|
|
163
|
+
It is **explicitly not** a complete prompt-injection defense system. The
|
|
164
|
+
current bypass-reduction pipeline handles Cyrillic/Greek homoglyphs,
|
|
165
|
+
zero-width insertions, full-width Latin, one-shot printable base64 payloads,
|
|
166
|
+
and common policy-laundering frames, but Raksha will still likely miss:
|
|
167
|
+
|
|
168
|
+
- novel paraphrased attacks outside the semantic-intent rules
|
|
169
|
+
- recursive / nested obfuscation, including base64-inside-base64 payloads
|
|
170
|
+
- non-Cyrillic / non-Greek homoglyphs and other Unicode confusables
|
|
171
|
+
- multi-turn / multi-item attacks split across context entries
|
|
172
|
+
- indirect injection in retrieved documents
|
|
173
|
+
- tool-output injection that exploits formatting / serialization boundaries
|
|
174
|
+
- benign content that legitimately discusses credentials, system prompts, or
|
|
175
|
+
similar terms (false positives on security documentation)
|
|
176
|
+
- adversarially-crafted Unicode / RTL / control-character sequences
|
|
177
|
+
- prompts that combine task-completion with subtle policy violation
|
|
178
|
+
|
|
179
|
+
**Do not** rely on Raksha as a sole control for any decision that has real
|
|
180
|
+
security or compliance impact. Treat it as one layer in a defense-in-depth
|
|
181
|
+
strategy, alongside (at minimum):
|
|
182
|
+
|
|
183
|
+
- a dedicated prompt-injection classifier or model judge
|
|
184
|
+
- structured-document isolation (the agent never reads raw retrieval verbatim)
|
|
185
|
+
- least-privilege tool capabilities and signed retrieval sources
|
|
186
|
+
- explicit human-in-the-loop gates on irreversible actions
|
|
187
|
+
- secret-redaction at retrieval / tool-output boundaries
|
|
188
|
+
- output filtering for known-leak patterns
|
|
189
|
+
|
|
190
|
+
## What is in scope to harden
|
|
191
|
+
|
|
192
|
+
- Expanding obfuscation-resistant detection beyond the current one-shot normalization and decode pipeline
|
|
193
|
+
- ✅ **Done**: Pluggable `PromptInjectionClassifier` interface — callers can swap in a learned model
|
|
194
|
+
- ✅ **Done**: Bundled `OnnxPromptInjectionClassifier` (local ONNX inference) and `HttpPromptInjectionClassifier` (external API) shipped as reference implementations
|
|
195
|
+
- Source-trust policies (signed retrieval, allowlist by domain)
|
|
196
|
+
- Memory-write quarantine with reflection-only release
|
|
197
|
+
- Per-event-type retention and rate limiting on the MCP boundary
|
|
198
|
+
|
|
199
|
+
## Reporting a vulnerability
|
|
200
|
+
|
|
201
|
+
If you believe you've found a security-relevant bug — for example a payload
|
|
202
|
+
that bypasses Raksha and reaches the agent context, a way to escape MCP
|
|
203
|
+
isolation, or a behaviour that contradicts the safety defaults documented
|
|
204
|
+
here — please:
|
|
205
|
+
|
|
206
|
+
1. Open a private security advisory via GitHub's "Report a vulnerability"
|
|
207
|
+
workflow on the repository.
|
|
208
|
+
2. Or email the maintainer listed in `package.json`.
|
|
209
|
+
3. Please do **not** open a public issue first.
|
|
210
|
+
|
|
211
|
+
Include:
|
|
212
|
+
- a minimal reproduction (input / configuration / version)
|
|
213
|
+
- the observed vs expected behaviour
|
|
214
|
+
- impact (what an attacker could do)
|
|
215
|
+
|
|
216
|
+
We aim to acknowledge reports within a few days. As an early-stage project,
|
|
217
|
+
we make no formal time-to-fix guarantees.
|
|
218
|
+
|
|
219
|
+
## Defaults that prefer safety over convenience
|
|
220
|
+
|
|
221
|
+
The following defaults are intentional, not accidental:
|
|
222
|
+
|
|
223
|
+
- `ojas_consolidate_memory.allow_new_memories` defaults to `false`. Memory
|
|
224
|
+
writes are dangerous; an explicit opt-in is required to commit.
|
|
225
|
+
- `ojas_run_recovery.mode` defaults to `recommend`. Apply-mode is opt-in.
|
|
226
|
+
- `criticalRequiresHuman` is enforced via `human_escalation` appended to
|
|
227
|
+
every critical repair protocol's actions.
|
|
228
|
+
- `OJAS_DISABLE_AUTO_REGISTER=1` rejects MCP calls for unregistered agents.
|
|
229
|
+
Production deployments are encouraged to set this.
|
|
230
|
+
- `OJAS_MAX_AGENTS` (default 256) caps registry growth to prevent unbounded
|
|
231
|
+
state expansion from a malicious / buggy client.
|
|
232
|
+
- `Aahar.filter()` rejects malformed numeric inputs rather than silently
|
|
233
|
+
letting them bypass token budgets or dominate prioritization.
|
|
234
|
+
|
|
235
|
+
## Known limitations
|
|
236
|
+
|
|
237
|
+
These are not bugs, they are intentional v0.3 scope:
|
|
238
|
+
|
|
239
|
+
- The MCP server is stdio-only and assumes the launching host is trusted.
|
|
240
|
+
See the "MCP authentication" and "Security non-goals" sections above
|
|
241
|
+
— this is the intended trust boundary for v0.3, not a deferred fix.
|
|
242
|
+
For shared deployments, add an auth-aware MCP gateway in front or run
|
|
243
|
+
one process per trusted user / workspace.
|
|
244
|
+
- SQLite persistence is local single-node. For multi-host, implement
|
|
245
|
+
`PersistenceStore` against an external database (see "Multi-host
|
|
246
|
+
architecture pattern" above).
|
|
247
|
+
- Health scores are heuristic; treat them as observability signals, not
|
|
248
|
+
ground-truth quality metrics. Empirical calibration via L3 pipeline
|
|
249
|
+
is available but not yet validated against real agent populations.
|
|
250
|
+
- The `AbortSignal` cancellation mechanism is opt-in: agents that don't
|
|
251
|
+
check the signal parameter will still leak work after timeout.
|