@tenova/swt3-ai 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -240
- package/dist/demo.js +85 -0
- package/dist/demo.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
Witness your AI. Prove it followed the rules. Cryptographic accountability for every inference, tool call, and resource access.
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@tenova/swt3-ai)
|
|
4
4
|
[](https://www.npmjs.com/package/@tenova/swt3-ai)
|
|
@@ -6,26 +6,22 @@ Deterministic AI Governance for production agents. Zero latency. Zero data reten
|
|
|
6
6
|
|
|
7
7
|
# @tenova/swt3-ai
|
|
8
8
|
|
|
9
|
-
**SWT3 AI Witness SDK for TypeScript**:
|
|
9
|
+
**SWT3 AI Witness SDK for TypeScript**: tamper-proof evidence that your AI is doing what you say it does. Every inference hashed. Every tool call recorded. Every resource access checked against scope. No prompts or responses ever leave your infrastructure.
|
|
10
10
|
|
|
11
11
|
Works with OpenAI, Anthropic, Vercel AI SDK, and any OpenAI-compatible endpoint (vLLM, Ollama, Azure, Llama.cpp).
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The EU AI Act takes effect **August 2, 2026**. When regulators ask "prove your AI followed the rules," you need more than logs. You need cryptographic proof.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## See It Work in 10 Seconds
|
|
18
|
-
|
|
19
|
-
No API keys. No account. No network calls.
|
|
15
|
+
## See It Work (No Account Needed)
|
|
20
16
|
|
|
21
17
|
```bash
|
|
22
18
|
npm install @tenova/swt3-ai
|
|
23
19
|
npx swt3-demo
|
|
24
20
|
```
|
|
25
21
|
|
|
26
|
-
|
|
22
|
+
The demo runs the full pipeline locally: hash, extract, clear, anchor, verify. It shows a Regulatory Coverage Summary mapping each check to EU AI Act articles, with gaps highlighted. No API keys, no network calls.
|
|
27
23
|
|
|
28
|
-
## Three Lines
|
|
24
|
+
## Three Lines to Start Witnessing
|
|
29
25
|
|
|
30
26
|
### OpenAI
|
|
31
27
|
|
|
@@ -34,21 +30,21 @@ import { Witness } from "@tenova/swt3-ai";
|
|
|
34
30
|
import OpenAI from "openai";
|
|
35
31
|
|
|
36
32
|
const witness = new Witness({
|
|
37
|
-
endpoint: "https://
|
|
33
|
+
endpoint: "https://your-witness-endpoint.example.com",
|
|
38
34
|
apiKey: "axm_live_...",
|
|
39
|
-
tenantId: "
|
|
35
|
+
tenantId: "YOUR_TENANT",
|
|
40
36
|
});
|
|
41
37
|
|
|
42
38
|
const client = witness.wrap(new OpenAI()) as OpenAI;
|
|
43
39
|
|
|
44
|
-
// Non-streaming
|
|
40
|
+
// Non-streaming
|
|
45
41
|
const response = await client.chat.completions.create({
|
|
46
42
|
model: "gpt-4o",
|
|
47
43
|
messages: [{ role: "user", content: "Summarize this contract..." }],
|
|
48
44
|
});
|
|
49
45
|
console.log(response.choices[0].message.content);
|
|
50
46
|
|
|
51
|
-
// Streaming
|
|
47
|
+
// Streaming works too. Chunks arrive in real-time, witnessing happens after.
|
|
52
48
|
const stream = await client.chat.completions.create({
|
|
53
49
|
model: "gpt-4o",
|
|
54
50
|
messages: [{ role: "user", content: "Explain quantum computing" }],
|
|
@@ -66,9 +62,9 @@ import { Witness } from "@tenova/swt3-ai";
|
|
|
66
62
|
import Anthropic from "@anthropic-ai/sdk";
|
|
67
63
|
|
|
68
64
|
const witness = new Witness({
|
|
69
|
-
endpoint: "https://
|
|
65
|
+
endpoint: "https://your-witness-endpoint.example.com",
|
|
70
66
|
apiKey: "axm_live_...",
|
|
71
|
-
tenantId: "
|
|
67
|
+
tenantId: "YOUR_TENANT",
|
|
72
68
|
});
|
|
73
69
|
|
|
74
70
|
const client = witness.wrap(new Anthropic()) as Anthropic;
|
|
@@ -78,17 +74,6 @@ const message = await client.messages.create({
|
|
|
78
74
|
max_tokens: 1024,
|
|
79
75
|
messages: [{ role: "user", content: "Draft a compliance memo" }],
|
|
80
76
|
});
|
|
81
|
-
|
|
82
|
-
// Streaming with Anthropic
|
|
83
|
-
const stream = await client.messages.create({
|
|
84
|
-
model: "claude-sonnet-4-20250514",
|
|
85
|
-
max_tokens: 1024,
|
|
86
|
-
messages: [{ role: "user", content: "Analyze this dataset" }],
|
|
87
|
-
stream: true,
|
|
88
|
-
});
|
|
89
|
-
for await (const event of stream) {
|
|
90
|
-
// events arrive in real-time, witnessing happens after stream ends
|
|
91
|
-
}
|
|
92
77
|
```
|
|
93
78
|
|
|
94
79
|
### Vercel AI SDK (Next.js / React)
|
|
@@ -99,9 +84,9 @@ import { streamText } from "ai";
|
|
|
99
84
|
import { openai } from "@ai-sdk/openai";
|
|
100
85
|
|
|
101
86
|
const witness = new Witness({
|
|
102
|
-
endpoint: "https://
|
|
87
|
+
endpoint: "https://your-witness-endpoint.example.com",
|
|
103
88
|
apiKey: "axm_live_...",
|
|
104
|
-
tenantId: "
|
|
89
|
+
tenantId: "YOUR_TENANT",
|
|
105
90
|
});
|
|
106
91
|
|
|
107
92
|
const prompt = "Summarize this contract for the board";
|
|
@@ -111,299 +96,315 @@ const result = await streamText({
|
|
|
111
96
|
prompt,
|
|
112
97
|
onFinish: witness.vercelOnFinish({ promptText: prompt }),
|
|
113
98
|
});
|
|
114
|
-
|
|
115
|
-
// Works with any Vercel AI SDK provider:OpenAI, Anthropic, Google, Mistral, custom
|
|
116
99
|
```
|
|
117
100
|
|
|
118
|
-
The `onFinish` hook is framework-
|
|
101
|
+
The `onFinish` hook is framework-native. No wrapping, no proxying. It fires after the stream completes and works with any Vercel AI SDK provider.
|
|
119
102
|
|
|
120
|
-
##
|
|
103
|
+
## What the SDK Does
|
|
121
104
|
|
|
122
|
-
|
|
105
|
+
When your AI makes a call, the SDK:
|
|
123
106
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
107
|
+
1. **Hashes** the prompt and response locally using SHA-256 (raw text never leaves your machine)
|
|
108
|
+
2. **Extracts** numeric factors: model version, latency, token count, guardrail status
|
|
109
|
+
3. **Clears** sensitive metadata based on your clearing level (you control what goes on the wire)
|
|
110
|
+
4. **Anchors** the factors into a cryptographic fingerprint anyone can independently verify
|
|
111
|
+
5. **Buffers** and flushes anchors in the background (median overhead: under 1ms)
|
|
112
|
+
6. **Returns** your original response completely untouched
|
|
129
113
|
|
|
130
|
-
|
|
131
|
-
model: "meta-llama/Meta-Llama-3-70B-Instruct",
|
|
132
|
-
messages: [{ role: "user", content: "Classify this threat indicator" }],
|
|
133
|
-
});
|
|
134
|
-
// Same SWT3 anchor, same ledger, same audit trail:regardless of where the model runs
|
|
114
|
+
For streaming: chunks arrive to the developer in real-time. The SDK accumulates content in the background and witnesses after the stream completes.
|
|
135
115
|
|
|
136
|
-
|
|
137
|
-
const localClient = witness.wrap(
|
|
138
|
-
new OpenAI({ baseURL: "http://localhost:11434/v1" }),
|
|
139
|
-
) as OpenAI;
|
|
116
|
+
## Witness Agent Tool Calls
|
|
140
117
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
)
|
|
118
|
+
If your AI agent calls tools or functions, wrap them to create a record of every invocation:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const search = witness.wrapTool(
|
|
122
|
+
(query: string) => db.execute(query),
|
|
123
|
+
"search_database"
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const results = await search("SELECT * FROM transactions WHERE amount > 10000");
|
|
127
|
+
// An AI-TOOL.1 anchor is minted recording: tool name, latency, success/failure
|
|
148
128
|
```
|
|
149
129
|
|
|
150
|
-
|
|
130
|
+
When an auditor asks "what tools did your agent use?" you have the cryptographic record.
|
|
151
131
|
|
|
152
|
-
|
|
132
|
+
## Witness Agent Resource Access
|
|
133
|
+
|
|
134
|
+
New in v0.2.10. Wrap any function your agent uses to access external resources. The SDK records what was accessed and whether it was within the agent's declared scope:
|
|
153
135
|
|
|
154
136
|
```typescript
|
|
155
|
-
|
|
156
|
-
|
|
137
|
+
const queryCustomers = witness.wrapAccess(
|
|
138
|
+
(sql: string) => db.execute(sql),
|
|
139
|
+
"customer-database", // resource name
|
|
140
|
+
"read-only analytics" // declared authorization scope
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const results = await queryCustomers("SELECT name FROM customers");
|
|
144
|
+
// An AI-ACC.1 anchor is minted recording:
|
|
145
|
+
// - Was it accessed? (yes)
|
|
146
|
+
// - Was it within scope? (yes)
|
|
147
|
+
// - Was access granted? (yes)
|
|
148
|
+
```
|
|
157
149
|
|
|
158
|
-
|
|
159
|
-
endpoint: "https://sovereign.tenova.io",
|
|
160
|
-
apiKey: "test", // any string, handoff runs before network flush
|
|
161
|
-
tenantId: "LOCAL_TEST",
|
|
162
|
-
factorHandoff: "file", // write anchors to ./swt3-handoff/ as JSON
|
|
163
|
-
});
|
|
150
|
+
If the agent tries to access something outside its declared scope, the anchor records a FAIL verdict. When a CISO asks "can you prove your AI agent only accessed what it was authorized to access?" this is the answer.
|
|
164
151
|
|
|
165
|
-
|
|
152
|
+
## Detect Instruction Drift
|
|
166
153
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
154
|
+
New in v0.2.10. The SDK separately hashes the system prompt (base instructions) for each inference. If your agent's instructions change between audit periods, the hash changes and the platform flags it as instruction drift.
|
|
155
|
+
|
|
156
|
+
This happens automatically. No configuration needed. The system prompt hash is extracted from:
|
|
157
|
+
- OpenAI: messages where `role === "system"`
|
|
158
|
+
- Anthropic: the `system` parameter
|
|
159
|
+
|
|
160
|
+
The hash is included at clearing levels 0 and 1, stripped at levels 2 and 3.
|
|
161
|
+
|
|
162
|
+
## Agent Identity
|
|
172
163
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
164
|
+
Bind a unique identity to every anchor your agent produces:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const witness = new Witness({
|
|
168
|
+
endpoint: "...",
|
|
169
|
+
apiKey: "axm_...",
|
|
170
|
+
tenantId: "...",
|
|
171
|
+
agentId: "fraud-detector-prod",
|
|
172
|
+
signingKey: "swt3_sk_...", // HMAC-SHA256 signing for non-repudiation
|
|
173
|
+
});
|
|
178
174
|
```
|
|
179
175
|
|
|
180
|
-
|
|
176
|
+
The `agentId` survives all clearing levels. The `signingKey` produces a cryptographic signature on every anchor, proving which agent instance created it. This enables:
|
|
177
|
+
- Per-agent compliance passports
|
|
178
|
+
- Fleet-wide governance dashboards
|
|
179
|
+
- Agent-scoped evidence packages for auditors
|
|
181
180
|
|
|
182
|
-
##
|
|
181
|
+
## What Gets Witnessed
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
|---|---|---|
|
|
186
|
-
| Mint anchors | ✓ | ✓ |
|
|
187
|
-
| Verify one anchor | ✓ | ✓ |
|
|
188
|
-
| Evidence retention | 0 (files on disk) | 7 days (free) / 90 days (Pro) |
|
|
189
|
-
| Compliance dashboard | — | ✓ |
|
|
190
|
-
| Auditor share links | — | ✓ (Pro) |
|
|
191
|
-
| EU AI Act conformity | — | ✓ (Pro) |
|
|
192
|
-
| Compliance Passport | — | ✓ (Pro) |
|
|
193
|
-
| Enclave integrity proof | — | ✓ (Enclave) |
|
|
194
|
-
| **Survives an audit** | **No** | **Yes** |
|
|
183
|
+
Each inference produces anchors for these checks. Every check maps to a regulation.
|
|
195
184
|
|
|
196
|
-
|
|
197
|
-
|
|
185
|
+
| Check | What It Proves | Plain English | Regulation |
|
|
186
|
+
|-------|---------------|---------------|------------|
|
|
187
|
+
| AI-INF.1 | Prompt and response were captured | "Was the inference logged?" | EU AI Act Art. 12 |
|
|
188
|
+
| AI-INF.2 | Latency was within threshold | "Was response time acceptable?" | NIST AI RMF MEASURE 2.6 |
|
|
189
|
+
| AI-MDL.1 | Deployed model matches approved hash | "Is this the right model?" | EU AI Act Art. 9 |
|
|
190
|
+
| AI-MDL.2 | Model version was recorded | "Is the model version tracked?" | EU AI Act Art. 72 |
|
|
191
|
+
| AI-GRD.1 | Required safety guardrails were active | "Are enough guardrails running?" | NIST AI RMF MANAGE 4.1 |
|
|
192
|
+
| AI-GRD.2 | No refusal or content filter triggered | "Did a safety filter trigger?" | EU AI Act Art. 9 |
|
|
193
|
+
| AI-TOOL.1 | Tool/function call was recorded | "Did the tool call succeed?" | NIST AI RMF MANAGE 4.1 |
|
|
194
|
+
| AI-ACC.1 | Resource access was within scope | "Was the access authorized?" | EU AI Act Art. 14 |
|
|
195
|
+
| AI-ID.1 | Agent identity was attested | "Is the agent identified?" | EU AI Act Art. 13 |
|
|
198
196
|
|
|
199
|
-
##
|
|
197
|
+
## How Verdicts Work
|
|
200
198
|
|
|
201
|
-
|
|
202
|
-
2. **Hash**: Prompts and responses are SHA-256 hashed in-process
|
|
203
|
-
3. **Extract**: Model hash, latency, token count, refusal status as numeric factors
|
|
204
|
-
4. **Clear**: Raw text is purged from the wire payload (configurable clearing level)
|
|
205
|
-
5. **Buffer**: Factors queued in background, flushed to the SWT3 ledger asynchronously
|
|
206
|
-
6. **Return**: Your original response returns untouched, zero added latency
|
|
199
|
+
Every anchor carries three numbers:
|
|
207
200
|
|
|
208
|
-
|
|
201
|
+
- **factor_a** = the threshold (what should happen)
|
|
202
|
+
- **factor_b** = the observation (what actually happened)
|
|
203
|
+
- **factor_c** = context (extra detail)
|
|
209
204
|
|
|
210
|
-
|
|
205
|
+
The verdict is a simple comparison. No AI, no probability. Just math.
|
|
211
206
|
|
|
212
|
-
|
|
213
|
-
|-------|------|------------|----------|
|
|
214
|
-
| 0 | Analytics | Hashes + factors + model + provider + guardrails | Internal analytics |
|
|
215
|
-
| 1 | Standard | Hashes + factors + model + provider | **Default.** Production apps |
|
|
216
|
-
| 2 | Sensitive | Hashes + factors + model only | Healthcare, legal, PII |
|
|
217
|
-
| 3 | Classified | Numeric factors only. Model ID hashed. | Defense, air-gapped |
|
|
207
|
+
### Reading an Anchor
|
|
218
208
|
|
|
219
|
-
|
|
209
|
+
```
|
|
210
|
+
Check: AI-GRD.1 factor_a: 2 factor_b: 3 factor_c: 1 Verdict: PASS
|
|
220
211
|
|
|
221
|
-
|
|
222
|
-
// Healthcare deployment: Level 2
|
|
223
|
-
const witness = new Witness({
|
|
224
|
-
endpoint: "https://sovereign.tenova.io",
|
|
225
|
-
apiKey: "axm_live_...",
|
|
226
|
-
tenantId: "HOSPITAL_ENCLAVE",
|
|
227
|
-
clearingLevel: 2,
|
|
228
|
-
});
|
|
212
|
+
Translation: "We required 2 guardrails. 3 were active. All passed."
|
|
229
213
|
```
|
|
230
214
|
|
|
231
|
-
|
|
215
|
+
```
|
|
216
|
+
Check: AI-ACC.1 factor_a: 1 factor_b: 0 factor_c: 0 Verdict: FAIL
|
|
232
217
|
|
|
233
|
-
|
|
234
|
-
|-----------|---------------|-------------------|
|
|
235
|
-
| AI-INF.1 | Inference provenance (prompt + response hashed) | EU AI Act Art. 12 |
|
|
236
|
-
| AI-INF.2 | Latency within threshold (detects model swaps) | NIST AI RMF MEASURE 2.6 |
|
|
237
|
-
| AI-MDL.1 | Model hash matches approved version | EU AI Act Art. 9 |
|
|
238
|
-
| AI-MDL.2 | Model version identifier recorded | EU AI Act Art. 72 |
|
|
239
|
-
| AI-GRD.1 | Required guardrails were active | NIST AI RMF MANAGE 4.1 |
|
|
240
|
-
| AI-GRD.2 | No content filter / refusal triggered | EU AI Act Art. 9 |
|
|
241
|
-
| AI-TOOL.1 | Agent tool/function call recorded (latency, success) | NIST AI RMF MANAGE 4.1 |
|
|
242
|
-
| AI-ID.1 | Witness instance identity attested (agent accountability) | EU AI Act Art. 13 |
|
|
243
|
-
|
|
244
|
-
## View an Anchor
|
|
245
|
-
|
|
246
|
-
A Level 1 anchor for AI-INF.1 (Inference Provenance). This is what reaches the witness ledger. No prompts, no responses, just cryptographic proof.
|
|
247
|
-
|
|
248
|
-
```json
|
|
249
|
-
{
|
|
250
|
-
"procedure_id": "AI-INF.1",
|
|
251
|
-
"factor_a": 1,
|
|
252
|
-
"factor_b": 1,
|
|
253
|
-
"factor_c": 0,
|
|
254
|
-
"clearing_level": 1,
|
|
255
|
-
"anchor_fingerprint": "c059eb5938c0",
|
|
256
|
-
"anchor_epoch": 1774800000,
|
|
257
|
-
"fingerprint_timestamp_ms": 1774800000000,
|
|
258
|
-
"ai_prompt_hash": "315f5bdb76d078c4",
|
|
259
|
-
"ai_response_hash": "a1b2c3d4e5f60718",
|
|
260
|
-
"ai_latency_ms": 842,
|
|
261
|
-
"ai_model_id": "gpt-4o",
|
|
262
|
-
"ai_context": {
|
|
263
|
-
"provider": "openai",
|
|
264
|
-
"guardrails": ["content-filter", "pii-redaction"]
|
|
265
|
-
}
|
|
266
|
-
}
|
|
218
|
+
Translation: "Access attempt occurred. Target was outside declared scope. Access denied."
|
|
267
219
|
```
|
|
268
220
|
|
|
269
|
-
|
|
221
|
+
### Factor Reference
|
|
270
222
|
|
|
271
|
-
|
|
223
|
+
| Check | factor_a | factor_b | factor_c | Verdict Rule |
|
|
224
|
+
|-------|----------|----------|----------|-------------|
|
|
225
|
+
| AI-INF.1 | 1 (required) | 1 if hashes present | 0 | PASS if b >= a |
|
|
226
|
+
| AI-INF.2 | Latency limit (ms) | Actual latency (ms) | 1 if over limit | PASS if b <= a |
|
|
227
|
+
| AI-MDL.1 | 1 (required) | 1 if hash present | 0 | PASS if b >= a |
|
|
228
|
+
| AI-MDL.2 | 1 (required) | 1 if version recorded | 0 | PASS if b >= a |
|
|
229
|
+
| AI-GRD.1 | Required count | Active count | 1 if all passed | PASS if b >= a |
|
|
230
|
+
| AI-GRD.2 | 1 (clean expected) | 0 if refusal | 0 | PASS if b >= a |
|
|
231
|
+
| AI-TOOL.1 | 1 (called) | Latency (ms) | 1=success, 0=error | PASS if b >= a |
|
|
232
|
+
| AI-ACC.1 | 1 (accessed) | 1=in scope, 0=out | 1=granted, 0=denied | PASS if b >= a |
|
|
233
|
+
| AI-ID.1 | 1 (required) | 1 if identity present | 0 | PASS if b >= a |
|
|
272
234
|
|
|
273
|
-
|
|
235
|
+
### Verify Any Anchor From Your Terminal
|
|
274
236
|
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
apiKey: "axm_...",
|
|
279
|
-
tenantId: "...",
|
|
280
|
-
bufferSize: 50, // flush every 50 anchors
|
|
281
|
-
flushInterval: 10, // or every 10 seconds
|
|
282
|
-
maxRetries: 5, // retry before dead-lettering
|
|
283
|
-
});
|
|
237
|
+
```bash
|
|
238
|
+
echo -n "WITNESS:DEMO_TENANT:AI-INF.1:1:1:0:1774800000000" | sha256sum | cut -c1-12
|
|
239
|
+
# Produces a 12-character fingerprint. Compare it to the anchor. If it matches, the anchor is real.
|
|
284
240
|
```
|
|
285
241
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
This SDK produces **identical SWT3 fingerprints** to the Python SDK (`swt3-ai`) and the Axiom ingestion endpoint. A unified audit trail across your entire stack:
|
|
242
|
+
No SDK needed. Works on any machine, any language.
|
|
289
243
|
|
|
290
|
-
|
|
291
|
-
|-------|----------|---------|
|
|
292
|
-
| Backend services | Python | `swt3-ai` |
|
|
293
|
-
| API routes / Edge | TypeScript | `@tenova/swt3-ai` |
|
|
294
|
-
| Frontend (Next.js) | TypeScript | `@tenova/swt3-ai` + Vercel AI SDK |
|
|
295
|
-
| CLI / scripts | Python | `swt3-ai` |
|
|
244
|
+
## Sovereign Cloud Support
|
|
296
245
|
|
|
297
|
-
|
|
246
|
+
The SDK works with any OpenAI-compatible endpoint. Run models on your own infrastructure and witness every inference identically:
|
|
298
247
|
|
|
299
|
-
|
|
248
|
+
```typescript
|
|
249
|
+
// vLLM with Llama 3 on your hardware
|
|
250
|
+
const client = witness.wrap(
|
|
251
|
+
new OpenAI({ baseURL: "http://gpu-cluster.internal:8000/v1" }),
|
|
252
|
+
) as OpenAI;
|
|
300
253
|
|
|
301
|
-
|
|
302
|
-
|
|
254
|
+
// Ollama for local development
|
|
255
|
+
const localClient = witness.wrap(
|
|
256
|
+
new OpenAI({ baseURL: "http://localhost:11434/v1" }),
|
|
257
|
+
) as OpenAI;
|
|
303
258
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
259
|
+
// Azure OpenAI
|
|
260
|
+
const azureClient = witness.wrap(
|
|
261
|
+
new OpenAI({
|
|
262
|
+
apiKey: process.env.AZURE_OPENAI_KEY,
|
|
263
|
+
baseURL: "https://your-resource.openai.azure.com/openai/deployments/gpt-4o",
|
|
264
|
+
}),
|
|
265
|
+
) as OpenAI;
|
|
307
266
|
```
|
|
308
267
|
|
|
309
|
-
|
|
268
|
+
Same anchors, same ledger, same audit trail. Regardless of where the model runs.
|
|
310
269
|
|
|
311
|
-
|
|
270
|
+
## Clearing Levels (Privacy Control)
|
|
312
271
|
|
|
313
|
-
|
|
314
|
-
|--------|---------|-------------|
|
|
315
|
-
| `endpoint` | *required* | Witness endpoint URL |
|
|
316
|
-
| `apiKey` | *required* | API key (`axm_*`) |
|
|
317
|
-
| `tenantId` | *required* | Enclave identifier |
|
|
318
|
-
| `clearingLevel` | `1` | Clearing level (0-3) |
|
|
319
|
-
| `bufferSize` | `10` | Flush after N anchors |
|
|
320
|
-
| `flushInterval` | `5` | Flush after N seconds |
|
|
321
|
-
| `timeout` | `10000` | HTTP timeout (ms) |
|
|
322
|
-
| `maxRetries` | `3` | Retries before dead-letter |
|
|
323
|
-
| `guardrailNames` | `[]` | Active guardrail names |
|
|
324
|
-
| `factorHandoff` | - | `"file"` to enable local factor export |
|
|
325
|
-
| `factorHandoffPath` | - | Directory for factor handoff files |
|
|
272
|
+
You control what leaves your infrastructure. The SDK always returns the full response to your code. Clearing only affects the witness payload.
|
|
326
273
|
|
|
327
|
-
|
|
274
|
+
| Level | Name | What Goes on the Wire | Use Case |
|
|
275
|
+
|-------|------|-----------------------|----------|
|
|
276
|
+
| 0 | Analytics | Everything: hashes, factors, model, provider, guardrails, prompt hash | Internal analytics |
|
|
277
|
+
| 1 | Standard | Hashes, factors, model, provider (no raw text ever) | **Default.** Production apps |
|
|
278
|
+
| 2 | Sensitive | Hashes, factors, model only. No provider, no guardrail names | Healthcare, legal, PII |
|
|
279
|
+
| 3 | Classified | Numeric factors only. Model name hashed. Zero metadata | Defense, air-gapped |
|
|
328
280
|
|
|
329
|
-
|
|
281
|
+
```typescript
|
|
282
|
+
const witness = new Witness({
|
|
283
|
+
endpoint: "...",
|
|
284
|
+
apiKey: "axm_...",
|
|
285
|
+
tenantId: "...",
|
|
286
|
+
clearingLevel: 2, // Sensitive: strips provider and guardrail names
|
|
287
|
+
});
|
|
288
|
+
```
|
|
330
289
|
|
|
331
|
-
|
|
290
|
+
At every level, raw prompts and responses **never leave your infrastructure**. Only SHA-256 hashes and numeric factors travel on the wire.
|
|
332
291
|
|
|
333
|
-
|
|
292
|
+
## Local Mode (No Account Needed)
|
|
334
293
|
|
|
335
|
-
|
|
294
|
+
Try the SDK locally before connecting to a live endpoint:
|
|
336
295
|
|
|
337
|
-
|
|
296
|
+
```typescript
|
|
297
|
+
const witness = new Witness({
|
|
298
|
+
endpoint: "https://your-witness-endpoint.example.com",
|
|
299
|
+
apiKey: "test",
|
|
300
|
+
tenantId: "LOCAL_TEST",
|
|
301
|
+
factorHandoff: "file", // Writes anchors to ./swt3-handoff/ as JSON
|
|
302
|
+
});
|
|
303
|
+
```
|
|
338
304
|
|
|
339
|
-
|
|
305
|
+
## Local SDK vs Connected
|
|
340
306
|
|
|
341
|
-
|
|
307
|
+
| Capability | Local SDK | Connected (free tier) |
|
|
308
|
+
|---|---|---|
|
|
309
|
+
| Mint anchors | Yes | Yes |
|
|
310
|
+
| Verify one anchor | Yes | Yes |
|
|
311
|
+
| Evidence retention | Files on disk | 7 days (free) / 90 days (Pro) |
|
|
312
|
+
| Compliance dashboard | No | Yes |
|
|
313
|
+
| Agent Passport | No | Yes (Pro) |
|
|
314
|
+
| Fleet dashboard | No | Yes (Pro) |
|
|
315
|
+
| EU AI Act conformity | No | Yes (Pro) |
|
|
316
|
+
| Auditor evidence packages | No | Yes (Pro) |
|
|
317
|
+
| Access violation tracking | No | Yes (Pro) |
|
|
318
|
+
| **Survives an audit** | **No** | **Yes** |
|
|
319
|
+
|
|
320
|
+
> Local anchors prove it to you. A connected engine proves it to your auditor.
|
|
342
321
|
|
|
343
|
-
##
|
|
322
|
+
## Resilience (Flight Recorder)
|
|
344
323
|
|
|
345
|
-
|
|
324
|
+
The SDK never blocks your inference. If the witness endpoint is unreachable, payloads move to a dead-letter queue. When connectivity returns, the backlog drains automatically. Your production system is never affected.
|
|
346
325
|
|
|
347
326
|
```typescript
|
|
348
327
|
const witness = new Witness({
|
|
349
|
-
endpoint: "
|
|
350
|
-
apiKey: "
|
|
351
|
-
tenantId: "
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
328
|
+
endpoint: "...",
|
|
329
|
+
apiKey: "axm_...",
|
|
330
|
+
tenantId: "...",
|
|
331
|
+
bufferSize: 50, // flush every 50 anchors
|
|
332
|
+
flushInterval: 10, // or every 10 seconds
|
|
333
|
+
maxRetries: 5, // retry before dead-lettering
|
|
355
334
|
});
|
|
356
335
|
```
|
|
357
336
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
For the full protocol specification, see the [Factor Handoff Protocol](https://sovereign.tenova.io/docs/factor-handoff-protocol.html).
|
|
337
|
+
## API Reference
|
|
361
338
|
|
|
362
|
-
|
|
339
|
+
### `new Witness(options)`
|
|
363
340
|
|
|
364
|
-
|
|
341
|
+
| Option | Default | Description |
|
|
342
|
+
|--------|---------|-------------|
|
|
343
|
+
| `endpoint` | required | Witness endpoint URL |
|
|
344
|
+
| `apiKey` | required | API key (axm_ prefix) |
|
|
345
|
+
| `tenantId` | required | Your tenant identifier |
|
|
346
|
+
| `clearingLevel` | 1 | Privacy level (0-3) |
|
|
347
|
+
| `bufferSize` | 10 | Flush after N anchors |
|
|
348
|
+
| `flushInterval` | 5 | Flush after N seconds |
|
|
349
|
+
| `timeout` | 10000 | HTTP timeout (ms) |
|
|
350
|
+
| `maxRetries` | 3 | Retries before dead-letter |
|
|
351
|
+
| `guardrailNames` | [] | Active guardrail names |
|
|
352
|
+
| `agentId` | - | Agent identity (survives all clearing levels) |
|
|
353
|
+
| `signingKey` | - | HMAC-SHA256 key for payload signing |
|
|
354
|
+
| `factorHandoff` | - | "file" for local factor export |
|
|
355
|
+
| `factorHandoffPath` | - | Directory for handoff files |
|
|
356
|
+
|
|
357
|
+
### Methods
|
|
358
|
+
|
|
359
|
+
| Method | Description |
|
|
360
|
+
|--------|-------------|
|
|
361
|
+
| `witness.wrap(client)` | Returns a Proxy that behaves identically to the original client. Supports OpenAI and Anthropic. |
|
|
362
|
+
| `witness.wrapTool(fn, name?)` | Wraps a function for tool call witnessing (AI-TOOL.1). |
|
|
363
|
+
| `witness.wrapAccess(fn, resource?, scope?)` | Wraps a function for resource access witnessing (AI-ACC.1). |
|
|
364
|
+
| `witness.vercelOnFinish(opts?)` | Returns an onFinish callback for Vercel AI SDK streamText/generateText. |
|
|
365
|
+
| `witness.flush()` | Force-flush all buffered payloads. Returns receipts. |
|
|
366
|
+
| `witness.stop()` | Stop the witness and flush remaining payloads. |
|
|
365
367
|
|
|
366
|
-
|
|
367
|
-
|------|-----------|-------------|-------|
|
|
368
|
-
| **Open** | 7 days | SDK, dashboard, public verify | Free |
|
|
369
|
-
| **Pro** | 90 days | + AI conformity exports, regulatory reports | $499/mo |
|
|
370
|
-
| **Enclave** | 1 year | + OSCAL, Gate API, attestations, webhook feeds | $9,500/mo |
|
|
371
|
-
| **Sovereign** | Custom | + White-glove ATO sprint, mock assessment, on-prem | [Book Assessment](https://calendly.com/tenova-axiom/30min) |
|
|
368
|
+
## Installation
|
|
372
369
|
|
|
373
|
-
|
|
370
|
+
```bash
|
|
371
|
+
npm install @tenova/swt3-ai
|
|
374
372
|
|
|
375
|
-
|
|
373
|
+
# Peer dependencies (install whichever you use)
|
|
374
|
+
npm install openai # for OpenAI adapter
|
|
375
|
+
npm install @anthropic-ai/sdk # for Anthropic adapter
|
|
376
|
+
```
|
|
376
377
|
|
|
377
|
-
|
|
378
|
+
## Regulatory Coverage
|
|
378
379
|
|
|
379
|
-
|
|
380
|
-
- [Quickstart Guide](https://sovereign.tenova.io/guides/ai-witness-quickstart.html) - 10-minute integration walkthrough
|
|
381
|
-
- [Book a Strategy Call](https://calendly.com/tenova-axiom/30min) - enterprise, on-prem, or Sovereign tier
|
|
380
|
+
The SWT3 AI Witnessing Profile maps to:
|
|
382
381
|
|
|
383
|
-
|
|
382
|
+
- **EU AI Act**: Articles 9, 10, 12, 13, 14, 53, 72
|
|
383
|
+
- **NIST AI RMF**: GOVERN, MAP, MEASURE, MANAGE functions
|
|
384
|
+
- **ISO 42001**: Annex A AI management controls
|
|
385
|
+
- **NIST 800-53**: SI-7 (integrity), AU-2/AU-3 (audit), AC controls
|
|
386
|
+
- **SR 11-7**: Model risk management (financial services)
|
|
384
387
|
|
|
385
|
-
|
|
388
|
+
## Zero Lock-in
|
|
386
389
|
|
|
387
|
-
|
|
388
|
-
- [Clearing & Data Sovereignty Addendum](https://sovereign.tenova.io/terms/clearing-addendum) - Shared responsibility, incident response SLA, regulatory applicability
|
|
389
|
-
- [Air-Gap Deployment Guide](https://github.com/tenova-labs/swt3-ai/blob/main/docs/sovereign-sync.md) - Zero-egress operation, sneakernet sync, offline verification
|
|
390
|
+
Remove the `witness.wrap()` call. Your code works exactly as before. Anchors already minted stay in the ledger. There is nothing to undo.
|
|
390
391
|
|
|
391
|
-
##
|
|
392
|
+
## Cross-Language Parity
|
|
392
393
|
|
|
393
|
-
|
|
394
|
-
- [Factor Handoff Protocol](https://sovereign.tenova.io/docs/factor-handoff-protocol.html) - How factors are securely transferred to your custody
|
|
395
|
-
- [CMMC Compliance Overlay](https://sovereign.tenova.io/guides/cmmc-overlay.html) - Control mappings for defense industrial base
|
|
394
|
+
This SDK produces identical fingerprints to the Python SDK (`swt3-ai`). A unified audit trail across your entire stack, verified by shared test vectors at build time.
|
|
396
395
|
|
|
397
|
-
|
|
396
|
+
| Layer | Language | Package |
|
|
397
|
+
|-------|----------|---------|
|
|
398
|
+
| Backend services | Python | swt3-ai |
|
|
399
|
+
| API routes / Edge | TypeScript | @tenova/swt3-ai |
|
|
400
|
+
| Frontend (Next.js) | TypeScript | @tenova/swt3-ai + Vercel AI SDK |
|
|
398
401
|
|
|
399
|
-
##
|
|
402
|
+
## Privacy
|
|
400
403
|
|
|
401
|
-
|
|
404
|
+
Your prompts and responses **never leave your infrastructure**. The SDK computes SHA-256 hashes locally and transmits only irreversible hashes and numeric factors. At Clearing Level 3, even the model name is hashed. The witness endpoint is a blind registrar: it stores cryptographic proofs, not your data.
|
|
402
405
|
|
|
403
406
|
---
|
|
404
407
|
|
|
405
408
|
*SWT3: Sovereign Witness Traceability. We don't run your models. We witness them.*
|
|
406
409
|
|
|
407
|
-
*TeNova: Defining the AI Accountability Standard. One protocol. Zero Integrity Debt. Total Sovereignty.*
|
|
408
|
-
|
|
409
410
|
SWT3 and Sovereign Witness Traceability are trademarks of Tenable Nova LLC. Patent pending. Apache 2.0 licensed.
|
package/dist/demo.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* No API keys. No account. No network calls.
|
|
9
9
|
*/
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
|
+
import { writeFileSync } from "node:fs";
|
|
11
12
|
const isColor = process.stdout.isTTY;
|
|
12
13
|
const B = isColor ? "\x1b[1m" : "";
|
|
13
14
|
const D = isColor ? "\x1b[2m" : "";
|
|
@@ -78,9 +79,11 @@ async function main() {
|
|
|
78
79
|
console.log();
|
|
79
80
|
console.log(`${C}5. Minting SWT3 Witness Anchors...${R}`);
|
|
80
81
|
console.log();
|
|
82
|
+
const anchors = [];
|
|
81
83
|
for (const [procId, fa, fb, fc, verdict, desc] of procedures) {
|
|
82
84
|
const fp = mintFingerprint(tenant, procId, fa, fb, fc, tsMs);
|
|
83
85
|
const anchor = `SWT3-E-${provider}-AI-${procId}-${verdict}-${epoch}-${fp}`;
|
|
86
|
+
anchors.push(anchor);
|
|
84
87
|
const color = verdict === "PASS" ? G : A;
|
|
85
88
|
console.log(` ${color}■ ${verdict}${R} ${W}${procId}${R} ${D}${desc}${R}`);
|
|
86
89
|
console.log(` ${D}${anchor}${R}`);
|
|
@@ -140,6 +143,88 @@ async function main() {
|
|
|
140
143
|
console.log(` ${D}Book a pilot: ${C}https://calendly.com/tenova-axiom/30min${R}`);
|
|
141
144
|
console.log(` ${D}GitHub: ${C}https://github.com/tenova-labs/swt3-ai${R}`);
|
|
142
145
|
console.log();
|
|
146
|
+
// ── Write HTML coverage report (best-effort) ──
|
|
147
|
+
try {
|
|
148
|
+
const html = generateHtmlReport(coverageMap, uncovered, anchors, daysLeft);
|
|
149
|
+
writeFileSync("swt3-coverage-report.html", html, "utf-8");
|
|
150
|
+
console.log(` ${G}[SWT3] Coverage report saved \u2192 swt3-coverage-report.html${R}`);
|
|
151
|
+
console.log();
|
|
152
|
+
}
|
|
153
|
+
catch { /* best-effort — never fail the demo */ }
|
|
154
|
+
}
|
|
155
|
+
function generateHtmlReport(coverageMap, uncoveredList, anchorList, daysLeft) {
|
|
156
|
+
const ts = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
157
|
+
const coveredRows = coverageMap.map(([p, a, d, v]) => `<tr><td style="font-family:monospace">${p}</td><td>${a}</td><td>${d}</td><td style="color:#4ADE80;font-weight:700">[${v}]</td></tr>`).join("\n");
|
|
158
|
+
const uncoveredRows = uncoveredList.map(([p, a, d]) => `<tr><td style="font-family:monospace;color:#FBBF24">${p}</td><td>${a}</td><td>${d}</td></tr>`).join("\n");
|
|
159
|
+
const anchorText = anchorList.join("\n");
|
|
160
|
+
const countdown = daysLeft > 0
|
|
161
|
+
? `EU AI Act enforcement in ${daysLeft} days (August 2, 2026)`
|
|
162
|
+
: "EU AI Act enforcement has begun.";
|
|
163
|
+
return `<!DOCTYPE html>
|
|
164
|
+
<html lang="en">
|
|
165
|
+
<head>
|
|
166
|
+
<meta charset="UTF-8">
|
|
167
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
168
|
+
<title>SWT3 AI Witness \u2014 Coverage Report</title>
|
|
169
|
+
<style>
|
|
170
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
171
|
+
body{background:#070504;color:#E0D9D1;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:2.5rem;line-height:1.6}
|
|
172
|
+
.c{max-width:800px;margin:0 auto}
|
|
173
|
+
h1{color:#E8A87C;font-size:1.5rem;margin-bottom:.25rem}
|
|
174
|
+
h2{color:#E8A87C;font-size:1.1rem;margin:1.5rem 0 .75rem}
|
|
175
|
+
.meta{color:#6B7280;font-size:.8rem;margin-bottom:1.5rem}
|
|
176
|
+
.score{font-size:2.5rem;font-weight:800;margin:1rem 0}
|
|
177
|
+
.score .pass{color:#4ADE80}
|
|
178
|
+
.score .total{color:#6B7280}
|
|
179
|
+
table{width:100%;border-collapse:collapse;margin:.75rem 0;font-size:.9rem}
|
|
180
|
+
th{text-align:left;padding:.5rem .75rem;color:#E8A87C;border-bottom:1px solid #222;font-size:.75rem;text-transform:uppercase;letter-spacing:.1em}
|
|
181
|
+
td{padding:.5rem .75rem;border-bottom:1px solid #151312}
|
|
182
|
+
pre{background:#111;padding:1rem;border-radius:8px;overflow-x:auto;font-size:.8rem;color:#9CA3AF;margin:.75rem 0;border:1px solid #222}
|
|
183
|
+
.countdown{font-size:1rem;font-weight:600;color:#FBBF24;margin:1.5rem 0}
|
|
184
|
+
.cta{display:inline-block;margin-top:1.25rem;padding:.75rem 2rem;background:#E8A87C;color:#070504;font-weight:700;text-decoration:none;border-radius:6px;font-size:.9rem;letter-spacing:.03em}
|
|
185
|
+
.cta:hover{opacity:.9}
|
|
186
|
+
.footer{color:#6B7280;font-size:.75rem;margin-top:2.5rem;padding-top:1.5rem;border-top:1px solid #222}
|
|
187
|
+
.warn{color:#FBBF24}
|
|
188
|
+
.sep{border:none;border-top:1px solid #222;margin:1.5rem 0}
|
|
189
|
+
</style>
|
|
190
|
+
</head>
|
|
191
|
+
<body>
|
|
192
|
+
<div class="c">
|
|
193
|
+
<h1>SWT3 AI Witness \u2014 Coverage Report</h1>
|
|
194
|
+
<p class="meta">Generated ${ts} UTC | SWT3 Protocol v0.2.9 | Demo Environment</p>
|
|
195
|
+
|
|
196
|
+
<div class="score"><span class="pass">3</span><span class="total"> / 12 obligations covered</span></div>
|
|
197
|
+
|
|
198
|
+
<h2>Covered \u2014 EU AI Act Article Mapping</h2>
|
|
199
|
+
<table>
|
|
200
|
+
<tr><th>Procedure</th><th>EU AI Act</th><th>Obligation</th><th>Status</th></tr>
|
|
201
|
+
${coveredRows}
|
|
202
|
+
</table>
|
|
203
|
+
|
|
204
|
+
<h2 class="warn">Uncovered Obligations (${uncoveredList.length})</h2>
|
|
205
|
+
<table>
|
|
206
|
+
<tr><th>Procedure</th><th>EU AI Act</th><th>Obligation</th></tr>
|
|
207
|
+
${uncoveredRows}
|
|
208
|
+
</table>
|
|
209
|
+
|
|
210
|
+
<hr class="sep">
|
|
211
|
+
|
|
212
|
+
<p class="countdown">${countdown}</p>
|
|
213
|
+
|
|
214
|
+
<h2>Anchor Evidence (Demo)</h2>
|
|
215
|
+
<pre>${anchorText}</pre>
|
|
216
|
+
|
|
217
|
+
<p>Full conformity requires all 12 procedures across inference, model governance, guardrails, and explainability domains.</p>
|
|
218
|
+
<a class="cta" href="https://sovereign.tenova.io/signup?ref=sdk_demo">Close the Gap \u2014 Free Account</a>
|
|
219
|
+
|
|
220
|
+
<div class="footer">
|
|
221
|
+
<p>SWT3 Protocol \u2014 Patent Pending \u2014 Apache 2.0</p>
|
|
222
|
+
<p>TeNova: Defining the AI Accountability Standard.</p>
|
|
223
|
+
<p style="margin-top:.5rem">This report was generated locally by the SWT3 AI Witness SDK demo. No data was transmitted.</p>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</body>
|
|
227
|
+
</html>`;
|
|
143
228
|
}
|
|
144
229
|
main();
|
|
145
230
|
//# sourceMappingURL=demo.js.map
|
package/dist/demo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"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"}
|