@arelis-ai/ai-governance-sdk 1.0.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/dist/index.cjs +4079 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2248 -0
- package/dist/index.d.ts +2248 -0
- package/dist/index.js +3607 -0
- package/dist/index.js.map +1 -0
- package/package.json +95 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,4079 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var governanceCore = require('@arelis-ai/governance-core');
|
|
4
|
+
var governancePolicy = require('@arelis-ai/governance-policy');
|
|
5
|
+
var governanceAudit = require('@arelis-ai/governance-audit');
|
|
6
|
+
var crypto = require('crypto');
|
|
7
|
+
var governanceModels = require('@arelis-ai/governance-models');
|
|
8
|
+
var governanceTelemetryOtel = require('@arelis-ai/governance-telemetry-otel');
|
|
9
|
+
var governanceMcp = require('@arelis-ai/governance-mcp');
|
|
10
|
+
var governanceKnowledge = require('@arelis-ai/governance-knowledge');
|
|
11
|
+
var governancePrompts = require('@arelis-ai/governance-prompts');
|
|
12
|
+
var governanceMemory = require('@arelis-ai/governance-memory');
|
|
13
|
+
var governanceDataSources = require('@arelis-ai/governance-data-sources');
|
|
14
|
+
var governanceEvaluations = require('@arelis-ai/governance-evaluations');
|
|
15
|
+
var governanceSecrets = require('@arelis-ai/governance-secrets');
|
|
16
|
+
var governanceAgents = require('@arelis-ai/governance-agents');
|
|
17
|
+
var governanceTools = require('@arelis-ai/governance-tools');
|
|
18
|
+
var governanceQuotas = require('@arelis-ai/governance-quotas');
|
|
19
|
+
|
|
20
|
+
// src/client.ts
|
|
21
|
+
var CAUSAL_GRAPH_SCHEMA_VERSION = "1.0";
|
|
22
|
+
function normalizeValue(value) {
|
|
23
|
+
if (value instanceof Date) {
|
|
24
|
+
return value.toISOString();
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "bigint") {
|
|
27
|
+
return value.toString();
|
|
28
|
+
}
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
return value.map((entry) => normalizeValue(entry));
|
|
31
|
+
}
|
|
32
|
+
if (value && typeof value === "object") {
|
|
33
|
+
const record = value;
|
|
34
|
+
const sortedKeys = Object.keys(record).sort();
|
|
35
|
+
const result = {};
|
|
36
|
+
for (const key of sortedKeys) {
|
|
37
|
+
result[key] = normalizeValue(record[key]);
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
function canonicalizePayload(value) {
|
|
44
|
+
return JSON.stringify(normalizeValue(value));
|
|
45
|
+
}
|
|
46
|
+
function hashPayload(payload) {
|
|
47
|
+
return crypto.createHash("sha256").update(payload).digest("hex");
|
|
48
|
+
}
|
|
49
|
+
function hashObject(value) {
|
|
50
|
+
return hashPayload(canonicalizePayload(value));
|
|
51
|
+
}
|
|
52
|
+
function computeMerkleRoot(hashes) {
|
|
53
|
+
if (hashes.length === 0) {
|
|
54
|
+
return hashPayload("");
|
|
55
|
+
}
|
|
56
|
+
let level = [...hashes];
|
|
57
|
+
while (level.length > 1) {
|
|
58
|
+
const nextLevel = [];
|
|
59
|
+
for (let i = 0; i < level.length; i += 2) {
|
|
60
|
+
const left = level[i];
|
|
61
|
+
const right = level[i + 1] ?? left;
|
|
62
|
+
nextLevel.push(hashPayload(`${left}${right}`));
|
|
63
|
+
}
|
|
64
|
+
level = nextLevel;
|
|
65
|
+
}
|
|
66
|
+
return level[0];
|
|
67
|
+
}
|
|
68
|
+
var LocalCausalGraphBuilder = class {
|
|
69
|
+
runId;
|
|
70
|
+
nodes = /* @__PURE__ */ new Map();
|
|
71
|
+
edges = /* @__PURE__ */ new Map();
|
|
72
|
+
lastEventByRun = /* @__PURE__ */ new Map();
|
|
73
|
+
constructor(runId) {
|
|
74
|
+
this.runId = runId;
|
|
75
|
+
}
|
|
76
|
+
recordEvent(event) {
|
|
77
|
+
const runNodeId = `run:${event.runId}`;
|
|
78
|
+
if (!this.nodes.has(runNodeId)) {
|
|
79
|
+
this.nodes.set(runNodeId, {
|
|
80
|
+
id: runNodeId,
|
|
81
|
+
kind: "run",
|
|
82
|
+
runId: event.runId,
|
|
83
|
+
digest: hashObject({ runId: event.runId, kind: "run" })
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const eventNodeId = `evt:${event.eventId}`;
|
|
87
|
+
if (!this.nodes.has(eventNodeId)) {
|
|
88
|
+
this.nodes.set(eventNodeId, {
|
|
89
|
+
id: eventNodeId,
|
|
90
|
+
kind: "event",
|
|
91
|
+
runId: event.runId,
|
|
92
|
+
eventId: event.eventId,
|
|
93
|
+
eventType: event.type,
|
|
94
|
+
time: event.time,
|
|
95
|
+
event,
|
|
96
|
+
digest: hashObject({
|
|
97
|
+
eventId: event.eventId,
|
|
98
|
+
runId: event.runId,
|
|
99
|
+
type: event.type,
|
|
100
|
+
time: event.time
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const containsId = `${runNodeId}:contains:${eventNodeId}`;
|
|
105
|
+
this.edges.set(containsId, {
|
|
106
|
+
id: containsId,
|
|
107
|
+
from: runNodeId,
|
|
108
|
+
to: eventNodeId,
|
|
109
|
+
kind: "contains"
|
|
110
|
+
});
|
|
111
|
+
const lastEvent = this.lastEventByRun.get(event.runId);
|
|
112
|
+
if (lastEvent && lastEvent !== eventNodeId) {
|
|
113
|
+
const sequenceId = `${lastEvent}:sequence:${eventNodeId}`;
|
|
114
|
+
this.edges.set(sequenceId, {
|
|
115
|
+
id: sequenceId,
|
|
116
|
+
from: lastEvent,
|
|
117
|
+
to: eventNodeId,
|
|
118
|
+
kind: "sequence"
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
this.lastEventByRun.set(event.runId, eventNodeId);
|
|
122
|
+
if (event.parentRunId) {
|
|
123
|
+
const parentRunId = `run:${event.parentRunId}`;
|
|
124
|
+
if (!this.nodes.has(parentRunId)) {
|
|
125
|
+
this.nodes.set(parentRunId, {
|
|
126
|
+
id: parentRunId,
|
|
127
|
+
kind: "run",
|
|
128
|
+
runId: event.parentRunId,
|
|
129
|
+
digest: hashObject({ runId: event.parentRunId, kind: "run" })
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const parentEdgeId = `${parentRunId}:parent:${runNodeId}`;
|
|
133
|
+
this.edges.set(parentEdgeId, {
|
|
134
|
+
id: parentEdgeId,
|
|
135
|
+
from: parentRunId,
|
|
136
|
+
to: runNodeId,
|
|
137
|
+
kind: "parent"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
build() {
|
|
142
|
+
return {
|
|
143
|
+
runId: this.runId,
|
|
144
|
+
schemaVersion: CAUSAL_GRAPH_SCHEMA_VERSION,
|
|
145
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
146
|
+
nodes: Array.from(this.nodes.values()),
|
|
147
|
+
edges: Array.from(this.edges.values())
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
var LocalCausalGraphAuditSink = class {
|
|
152
|
+
baseSink;
|
|
153
|
+
store;
|
|
154
|
+
builders = /* @__PURE__ */ new Map();
|
|
155
|
+
constructor(baseSink, store) {
|
|
156
|
+
this.baseSink = baseSink;
|
|
157
|
+
this.store = store;
|
|
158
|
+
}
|
|
159
|
+
async write(event) {
|
|
160
|
+
await this.baseSink.write(event);
|
|
161
|
+
this.record(event);
|
|
162
|
+
await this.persistIfComplete(event);
|
|
163
|
+
}
|
|
164
|
+
async writeBatch(events) {
|
|
165
|
+
if (this.baseSink.writeBatch) {
|
|
166
|
+
await this.baseSink.writeBatch(events);
|
|
167
|
+
} else {
|
|
168
|
+
for (const event of events) {
|
|
169
|
+
await this.baseSink.write(event);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
for (const event of events) {
|
|
173
|
+
this.record(event);
|
|
174
|
+
await this.persistIfComplete(event);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async flush() {
|
|
178
|
+
if (this.baseSink.flush) {
|
|
179
|
+
await this.baseSink.flush();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async close() {
|
|
183
|
+
for (const builder of this.builders.values()) {
|
|
184
|
+
await this.store.save(builder.build());
|
|
185
|
+
}
|
|
186
|
+
this.builders.clear();
|
|
187
|
+
if (this.baseSink.close) {
|
|
188
|
+
await this.baseSink.close();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
record(event) {
|
|
192
|
+
const builder = this.builders.get(event.runId) ?? new LocalCausalGraphBuilder(event.runId);
|
|
193
|
+
builder.recordEvent(event);
|
|
194
|
+
this.builders.set(event.runId, builder);
|
|
195
|
+
}
|
|
196
|
+
async persistIfComplete(event) {
|
|
197
|
+
if (event.type !== "run.ended" && event.type !== "run.error") {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const builder = this.builders.get(event.runId);
|
|
201
|
+
if (!builder) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
await this.store.save(builder.build());
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
function createCausalGraphAuditSink(baseSink, store) {
|
|
208
|
+
return new LocalCausalGraphAuditSink(baseSink, store);
|
|
209
|
+
}
|
|
210
|
+
function createCausalGraphCommitment(graph, signer) {
|
|
211
|
+
const nodeDigests = graph.nodes.map((node) => node.digest).sort();
|
|
212
|
+
const root = computeMerkleRoot(nodeDigests);
|
|
213
|
+
const commitment = {
|
|
214
|
+
runId: graph.runId,
|
|
215
|
+
root,
|
|
216
|
+
algorithm: "sha256",
|
|
217
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
218
|
+
nodeCount: graph.nodes.length,
|
|
219
|
+
edgeCount: graph.edges.length
|
|
220
|
+
};
|
|
221
|
+
if (signer) {
|
|
222
|
+
const payload = `${commitment.runId}:${commitment.root}:${commitment.createdAt}`;
|
|
223
|
+
commitment.signerId = signer.id;
|
|
224
|
+
commitment.signature = signer.sign(payload);
|
|
225
|
+
}
|
|
226
|
+
return commitment;
|
|
227
|
+
}
|
|
228
|
+
var HashProofProvider = class extends governanceAudit.HashProofProvider {
|
|
229
|
+
};
|
|
230
|
+
var InMemoryComplianceArtifactStore = class {
|
|
231
|
+
artifactsByRun = /* @__PURE__ */ new Map();
|
|
232
|
+
async save(artifact) {
|
|
233
|
+
const existing = this.artifactsByRun.get(artifact.runId) ?? [];
|
|
234
|
+
existing.push(artifact);
|
|
235
|
+
this.artifactsByRun.set(artifact.runId, existing);
|
|
236
|
+
}
|
|
237
|
+
async get(runId, artifactId) {
|
|
238
|
+
const list = this.artifactsByRun.get(runId) ?? [];
|
|
239
|
+
return list.find((artifact) => artifact.id === artifactId);
|
|
240
|
+
}
|
|
241
|
+
async list(runId) {
|
|
242
|
+
return this.artifactsByRun.get(runId) ?? [];
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
function resolveDisclosureRules(baseRules, allowedRuleIds) {
|
|
246
|
+
if (!allowedRuleIds || allowedRuleIds.length === 0) {
|
|
247
|
+
return baseRules;
|
|
248
|
+
}
|
|
249
|
+
const allowed = new Set(allowedRuleIds);
|
|
250
|
+
return baseRules.filter((rule) => allowed.has(rule.id));
|
|
251
|
+
}
|
|
252
|
+
function toAuditDecisions(decisions) {
|
|
253
|
+
return decisions.map((d) => {
|
|
254
|
+
if (d.effect === "block") {
|
|
255
|
+
return {
|
|
256
|
+
effect: "block",
|
|
257
|
+
reason: d.reason,
|
|
258
|
+
code: d.code
|
|
259
|
+
};
|
|
260
|
+
} else if (d.effect === "transform") {
|
|
261
|
+
return {
|
|
262
|
+
effect: "transform",
|
|
263
|
+
reason: d.reason
|
|
264
|
+
};
|
|
265
|
+
} else if (d.effect === "require_approval") {
|
|
266
|
+
return {
|
|
267
|
+
effect: "require_approval",
|
|
268
|
+
reason: d.reason
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return { effect: "allow" };
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function toPolicySummary(result) {
|
|
275
|
+
const summary = {
|
|
276
|
+
evaluated: result.decisions.length,
|
|
277
|
+
allowed: result.decisions.filter((d) => d.effect === "allow").length,
|
|
278
|
+
blocked: result.decisions.filter((d) => d.effect === "block").length,
|
|
279
|
+
transformed: result.decisions.filter((d) => d.effect === "transform").length
|
|
280
|
+
};
|
|
281
|
+
const reasons = result.decisions.filter((d) => d.effect !== "allow").map((d) => {
|
|
282
|
+
if (d.effect === "block") return d.reason;
|
|
283
|
+
if (d.effect === "transform") return d.reason;
|
|
284
|
+
if (d.effect === "require_approval") return d.reason;
|
|
285
|
+
return void 0;
|
|
286
|
+
}).filter((r) => r !== void 0);
|
|
287
|
+
if (reasons.length > 0) {
|
|
288
|
+
summary.reasons = reasons;
|
|
289
|
+
}
|
|
290
|
+
return summary;
|
|
291
|
+
}
|
|
292
|
+
var ArelisClient = class {
|
|
293
|
+
modelRegistry;
|
|
294
|
+
policyEngine;
|
|
295
|
+
auditSink;
|
|
296
|
+
telemetry;
|
|
297
|
+
contextResolver;
|
|
298
|
+
toolRegistry;
|
|
299
|
+
mcpRegistry;
|
|
300
|
+
kbRegistry;
|
|
301
|
+
promptRegistry;
|
|
302
|
+
memoryRegistry;
|
|
303
|
+
dataSourceRegistry;
|
|
304
|
+
quotaManager;
|
|
305
|
+
evaluators;
|
|
306
|
+
approvalStore;
|
|
307
|
+
secretResolver;
|
|
308
|
+
redactor;
|
|
309
|
+
compiledPolicy;
|
|
310
|
+
complianceGraphStore;
|
|
311
|
+
complianceArtifactStore;
|
|
312
|
+
complianceProofProvider;
|
|
313
|
+
complianceProofJobQueue;
|
|
314
|
+
complianceDisclosureRules;
|
|
315
|
+
complianceSigner;
|
|
316
|
+
complianceProofCache = /* @__PURE__ */ new Map();
|
|
317
|
+
complianceProofTimeoutMs;
|
|
318
|
+
extensions;
|
|
319
|
+
riskRouterConfig;
|
|
320
|
+
runSnapshots = /* @__PURE__ */ new Map();
|
|
321
|
+
/**
|
|
322
|
+
* Models namespace for model operations
|
|
323
|
+
*/
|
|
324
|
+
models;
|
|
325
|
+
/**
|
|
326
|
+
* Agents namespace for agent operations
|
|
327
|
+
*/
|
|
328
|
+
agents;
|
|
329
|
+
/**
|
|
330
|
+
* MCP namespace for MCP server operations
|
|
331
|
+
*/
|
|
332
|
+
mcp;
|
|
333
|
+
/**
|
|
334
|
+
* Knowledge namespace for knowledge base operations
|
|
335
|
+
*/
|
|
336
|
+
knowledge;
|
|
337
|
+
prompts;
|
|
338
|
+
memory;
|
|
339
|
+
dataSources;
|
|
340
|
+
approvals;
|
|
341
|
+
evaluations;
|
|
342
|
+
quotas;
|
|
343
|
+
secrets;
|
|
344
|
+
compliance;
|
|
345
|
+
governance;
|
|
346
|
+
constructor(config) {
|
|
347
|
+
this.modelRegistry = config.modelRegistry;
|
|
348
|
+
this.policyEngine = config.policyEngine;
|
|
349
|
+
const compiledPolicy = config.policyCompilation ? config.policyCompilation.compiler.compile(config.policyCompilation.source) : void 0;
|
|
350
|
+
this.compiledPolicy = compiledPolicy;
|
|
351
|
+
this.complianceGraphStore = config.compliance?.causalGraphStore;
|
|
352
|
+
this.complianceArtifactStore = config.compliance?.artifactStore ?? (config.compliance ? new InMemoryComplianceArtifactStore() : void 0);
|
|
353
|
+
this.complianceProofProvider = config.compliance?.proofProvider ?? (config.compliance ? new HashProofProvider() : void 0);
|
|
354
|
+
this.complianceProofJobQueue = config.compliance?.proofJobQueue;
|
|
355
|
+
this.complianceDisclosureRules = config.compliance?.disclosureRules ?? compiledPolicy?.disclosureRules;
|
|
356
|
+
this.complianceSigner = config.compliance?.commitmentSigner;
|
|
357
|
+
this.complianceProofTimeoutMs = config.compliance?.proofTimeoutMs;
|
|
358
|
+
this.extensions = config.extensions;
|
|
359
|
+
this.riskRouterConfig = {
|
|
360
|
+
mode: config.extensions?.riskRouting?.mode ?? "off",
|
|
361
|
+
defaultAction: config.extensions?.riskRouting?.defaultAction
|
|
362
|
+
};
|
|
363
|
+
this.auditSink = this.complianceGraphStore ? createCausalGraphAuditSink(config.auditSink, this.complianceGraphStore) : config.auditSink;
|
|
364
|
+
this.telemetry = config.telemetry ?? governanceTelemetryOtel.createNoOpTelemetry();
|
|
365
|
+
this.contextResolver = config.contextResolver ?? governanceCore.defaultContextResolver;
|
|
366
|
+
this.toolRegistry = config.toolRegistry;
|
|
367
|
+
this.mcpRegistry = config.mcpRegistry ?? governanceMcp.createMCPRegistry();
|
|
368
|
+
this.kbRegistry = config.kbRegistry ?? governanceKnowledge.createKBRegistry();
|
|
369
|
+
this.promptRegistry = config.promptRegistry ?? governancePrompts.createTemplateRegistry();
|
|
370
|
+
this.memoryRegistry = config.memoryRegistry ?? governanceMemory.createMemoryRegistry();
|
|
371
|
+
if (this.memoryRegistry.list().length === 0) {
|
|
372
|
+
this.memoryRegistry.register(governanceMemory.createInMemoryMemoryProvider());
|
|
373
|
+
}
|
|
374
|
+
this.dataSourceRegistry = config.dataSourceRegistry ?? governanceDataSources.createDataSourceRegistry();
|
|
375
|
+
this.quotaManager = config.quotaManager;
|
|
376
|
+
this.evaluators = config.evaluators ?? [];
|
|
377
|
+
this.approvalStore = config.approvalStore ?? governanceCore.createInMemoryApprovalStore();
|
|
378
|
+
this.secretResolver = config.secretResolver ?? governanceSecrets.createEnvSecretResolver();
|
|
379
|
+
this.redactor = config.redactor ?? governancePolicy.createRedactor({ secretPatterns: governanceSecrets.getSecretRedactionPatterns() });
|
|
380
|
+
this.models = {
|
|
381
|
+
generate: this.generate.bind(this),
|
|
382
|
+
generateStream: this.generateStream.bind(this)
|
|
383
|
+
};
|
|
384
|
+
this.agents = {
|
|
385
|
+
run: this.runAgent.bind(this)
|
|
386
|
+
};
|
|
387
|
+
this.mcp = {
|
|
388
|
+
registerServer: this.registerMCPServer.bind(this),
|
|
389
|
+
discoverTools: this.discoverMCPTools.bind(this),
|
|
390
|
+
getRegistry: () => this.mcpRegistry
|
|
391
|
+
};
|
|
392
|
+
this.knowledge = {
|
|
393
|
+
registerKB: this.registerKB.bind(this),
|
|
394
|
+
retrieve: this.retrieve.bind(this),
|
|
395
|
+
getRegistry: () => this.kbRegistry
|
|
396
|
+
};
|
|
397
|
+
this.prompts = {
|
|
398
|
+
register: this.registerPromptTemplate.bind(this),
|
|
399
|
+
get: (query) => this.promptRegistry.get(query),
|
|
400
|
+
list: (id) => this.promptRegistry.list(id)
|
|
401
|
+
};
|
|
402
|
+
this.memory = {
|
|
403
|
+
read: this.readMemory.bind(this),
|
|
404
|
+
write: this.writeMemory.bind(this),
|
|
405
|
+
delete: this.deleteMemory.bind(this),
|
|
406
|
+
list: async (scope, contextInput) => {
|
|
407
|
+
const provider = this.getDefaultMemoryProvider();
|
|
408
|
+
const context = await this.contextResolver(contextInput);
|
|
409
|
+
return provider.list(scope, { runId: governanceCore.generateRunId(), governance: context });
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
this.dataSources = {
|
|
413
|
+
register: this.registerDataSource.bind(this),
|
|
414
|
+
read: this.readDataSource.bind(this),
|
|
415
|
+
getRegistry: () => this.dataSourceRegistry
|
|
416
|
+
};
|
|
417
|
+
this.approvals = {
|
|
418
|
+
approve: this.approveRequest.bind(this),
|
|
419
|
+
reject: this.rejectRequest.bind(this),
|
|
420
|
+
list: (status) => this.approvalStore.list(status),
|
|
421
|
+
get: (approvalId) => this.approvalStore.get(approvalId)
|
|
422
|
+
};
|
|
423
|
+
this.evaluations = {
|
|
424
|
+
run: async (input, evaluators) => this.runEvaluations(input, evaluators)
|
|
425
|
+
};
|
|
426
|
+
this.quotas = {
|
|
427
|
+
check: async (key, proposed) => {
|
|
428
|
+
if (!this.quotaManager) {
|
|
429
|
+
throw new Error("Quota manager not configured");
|
|
430
|
+
}
|
|
431
|
+
return this.quotaManager.check(key, proposed);
|
|
432
|
+
},
|
|
433
|
+
commit: async (key, actual) => {
|
|
434
|
+
if (!this.quotaManager) {
|
|
435
|
+
throw new Error("Quota manager not configured");
|
|
436
|
+
}
|
|
437
|
+
return this.quotaManager.commit(key, actual);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
this.secrets = {
|
|
441
|
+
resolve: async (ref, contextInput) => {
|
|
442
|
+
const runId = governanceCore.generateRunId();
|
|
443
|
+
const context = contextInput ? await this.contextResolver(contextInput) : void 0;
|
|
444
|
+
const resolved = await governanceSecrets.resolveSecretValue(this.secretResolver, ref, {
|
|
445
|
+
context,
|
|
446
|
+
runId
|
|
447
|
+
});
|
|
448
|
+
if (context) {
|
|
449
|
+
await this.auditSink.write(
|
|
450
|
+
governanceAudit.createSecretResolvedEvent({
|
|
451
|
+
runId,
|
|
452
|
+
context,
|
|
453
|
+
ref,
|
|
454
|
+
resolverId: resolved.resolution.resolverId
|
|
455
|
+
})
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
return resolved.value;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
this.compliance = {
|
|
462
|
+
requestArtifact: this.requestComplianceArtifact.bind(this),
|
|
463
|
+
getArtifacts: async (runId) => this.complianceArtifactStore ? this.complianceArtifactStore.list(runId) : [],
|
|
464
|
+
verifyArtifact: this.verifyComplianceArtifact.bind(this),
|
|
465
|
+
replayRun: this.replayComplianceRun.bind(this)
|
|
466
|
+
};
|
|
467
|
+
this.governance = {
|
|
468
|
+
createGateEvaluator: () => ({
|
|
469
|
+
resolveContext: (partial) => this.contextResolver(partial),
|
|
470
|
+
evaluatePolicy: (input) => this.evaluatePolicy(input.checkpoint, input.runId, input.context, input.data),
|
|
471
|
+
getPolicyMetadata: () => this.getPolicyAuditMetadata()
|
|
472
|
+
})
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Generate a response from a model
|
|
477
|
+
*/
|
|
478
|
+
async generate(input) {
|
|
479
|
+
const runId = governanceCore.generateRunId();
|
|
480
|
+
const context = await this.contextResolver(input.context);
|
|
481
|
+
const startTime = Date.now();
|
|
482
|
+
const resolveSpan = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.MODEL_RESOLVE, {
|
|
483
|
+
"arelis.run.id": runId,
|
|
484
|
+
"arelis.model.requested": input.model,
|
|
485
|
+
...this.telemetry.contextAttributes(context)
|
|
486
|
+
});
|
|
487
|
+
let resolved;
|
|
488
|
+
try {
|
|
489
|
+
resolved = this.modelRegistry.resolveRouteOrModel({
|
|
490
|
+
routeOrModelId: input.model,
|
|
491
|
+
context,
|
|
492
|
+
dataClass: input.dataClass,
|
|
493
|
+
requiredResidency: input.requiredResidency
|
|
494
|
+
});
|
|
495
|
+
resolveSpan.setAttribute("arelis.model.id", resolved.descriptor.id);
|
|
496
|
+
if (resolved.routeId) {
|
|
497
|
+
resolveSpan.setAttribute("arelis.model.route.id", resolved.routeId);
|
|
498
|
+
}
|
|
499
|
+
} catch (error) {
|
|
500
|
+
resolveSpan.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
501
|
+
resolveSpan.setStatus(
|
|
502
|
+
"error",
|
|
503
|
+
error instanceof Error ? error.message : "Model resolution failed"
|
|
504
|
+
);
|
|
505
|
+
resolveSpan.end();
|
|
506
|
+
throw error;
|
|
507
|
+
}
|
|
508
|
+
const modelId = resolved.descriptor.id;
|
|
509
|
+
const provider = this.modelRegistry.resolve(resolved.descriptor.providerId);
|
|
510
|
+
let requestToSend = { ...input.request, model: modelId, context };
|
|
511
|
+
const promptTemplate = this.resolvePromptTemplate(input.promptTemplate);
|
|
512
|
+
if (promptTemplate) {
|
|
513
|
+
requestToSend = this.applyPromptTemplate(promptTemplate, requestToSend);
|
|
514
|
+
}
|
|
515
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.MODEL_GENERATE, {
|
|
516
|
+
"arelis.run.id": runId,
|
|
517
|
+
"arelis.model.id": modelId,
|
|
518
|
+
...this.telemetry.contextAttributes(context)
|
|
519
|
+
});
|
|
520
|
+
let policySummary;
|
|
521
|
+
const warnings = [];
|
|
522
|
+
try {
|
|
523
|
+
await this.auditSink.write(
|
|
524
|
+
governanceAudit.createRunStartedEvent({
|
|
525
|
+
runId,
|
|
526
|
+
context,
|
|
527
|
+
operation: "models.generate"
|
|
528
|
+
})
|
|
529
|
+
);
|
|
530
|
+
try {
|
|
531
|
+
await this.emitModelResolutionEvents(runId, context, resolved);
|
|
532
|
+
await this.captureSnapshot({
|
|
533
|
+
runId,
|
|
534
|
+
context,
|
|
535
|
+
modelRouteId: resolved.routeId
|
|
536
|
+
});
|
|
537
|
+
resolveSpan.setStatus("ok");
|
|
538
|
+
} catch (error) {
|
|
539
|
+
resolveSpan.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
540
|
+
resolveSpan.setStatus(
|
|
541
|
+
"error",
|
|
542
|
+
error instanceof Error ? error.message : "Model resolution failed"
|
|
543
|
+
);
|
|
544
|
+
throw error;
|
|
545
|
+
} finally {
|
|
546
|
+
resolveSpan.end();
|
|
547
|
+
}
|
|
548
|
+
const quotaDecision = await this.preflightQuota(
|
|
549
|
+
runId,
|
|
550
|
+
context,
|
|
551
|
+
provider,
|
|
552
|
+
requestToSend,
|
|
553
|
+
input.options
|
|
554
|
+
);
|
|
555
|
+
let generationOptions = input.options;
|
|
556
|
+
if (quotaDecision?.effect === "limit" && quotaDecision.applied.tokensOut !== void 0) {
|
|
557
|
+
const currentMax = generationOptions?.maxTokens;
|
|
558
|
+
const limited = quotaDecision.applied.tokensOut;
|
|
559
|
+
generationOptions = {
|
|
560
|
+
...generationOptions ?? {},
|
|
561
|
+
maxTokens: currentMax ? Math.min(currentMax, limited) : limited
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
if (promptTemplate) {
|
|
565
|
+
await this.auditSink.write(
|
|
566
|
+
governanceAudit.createPromptTemplateUsedEvent({
|
|
567
|
+
runId,
|
|
568
|
+
context,
|
|
569
|
+
template: {
|
|
570
|
+
id: promptTemplate.id,
|
|
571
|
+
version: promptTemplate.version,
|
|
572
|
+
hash: promptTemplate.hash
|
|
573
|
+
}
|
|
574
|
+
})
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
const beforePromptResult = await this.evaluatePolicy("BeforePrompt", runId, context, {
|
|
578
|
+
modelId,
|
|
579
|
+
input: requestToSend.messages
|
|
580
|
+
});
|
|
581
|
+
if (!beforePromptResult.summary.allowed) {
|
|
582
|
+
throw await this.createPolicyError(beforePromptResult, runId, context);
|
|
583
|
+
}
|
|
584
|
+
await this.auditSink.write(
|
|
585
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
586
|
+
runId,
|
|
587
|
+
context,
|
|
588
|
+
checkpoint: "BeforePrompt",
|
|
589
|
+
decisions: toAuditDecisions(beforePromptResult.decisions),
|
|
590
|
+
allowed: true,
|
|
591
|
+
policyVersion: beforePromptResult.policyVersion
|
|
592
|
+
})
|
|
593
|
+
);
|
|
594
|
+
const riskRouteMode = await this.enforceRuntimeRiskRoute({
|
|
595
|
+
runId,
|
|
596
|
+
context,
|
|
597
|
+
operation: "models.generate",
|
|
598
|
+
policyDecisions: beforePromptResult.decisions,
|
|
599
|
+
quotaEffect: quotaDecision?.effect
|
|
600
|
+
});
|
|
601
|
+
if (riskRouteMode === "sandbox") {
|
|
602
|
+
warnings.push({
|
|
603
|
+
code: "risk.sandbox",
|
|
604
|
+
message: "Execution proceeded in sandbox mode"
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
if (input.grounding) {
|
|
608
|
+
const grounded = await this.applyGrounding(input.grounding, requestToSend, runId, context);
|
|
609
|
+
requestToSend = grounded.request;
|
|
610
|
+
}
|
|
611
|
+
await this.auditSink.write(
|
|
612
|
+
governanceAudit.createModelRequestEvent({
|
|
613
|
+
runId,
|
|
614
|
+
context,
|
|
615
|
+
model: {
|
|
616
|
+
id: modelId,
|
|
617
|
+
provider: provider.id,
|
|
618
|
+
version: resolved.descriptor.version,
|
|
619
|
+
lifecycleState: resolved.descriptor.lifecycleState
|
|
620
|
+
},
|
|
621
|
+
inputRef: governanceAudit.createInlineRef(JSON.stringify(requestToSend.messages)),
|
|
622
|
+
promptTemplate: promptTemplate ? { id: promptTemplate.id, version: promptTemplate.version, hash: promptTemplate.hash } : void 0
|
|
623
|
+
})
|
|
624
|
+
);
|
|
625
|
+
const response = await provider.generate(requestToSend, generationOptions);
|
|
626
|
+
const afterOutputResult = await this.evaluatePolicy("AfterModelOutput", runId, context, {
|
|
627
|
+
modelId,
|
|
628
|
+
input: requestToSend.messages,
|
|
629
|
+
output: response.content
|
|
630
|
+
});
|
|
631
|
+
if (!afterOutputResult.summary.allowed) {
|
|
632
|
+
throw await this.createPolicyError(afterOutputResult, runId, context);
|
|
633
|
+
}
|
|
634
|
+
await this.auditSink.write(
|
|
635
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
636
|
+
runId,
|
|
637
|
+
context,
|
|
638
|
+
checkpoint: "AfterModelOutput",
|
|
639
|
+
decisions: toAuditDecisions(afterOutputResult.decisions),
|
|
640
|
+
allowed: true,
|
|
641
|
+
policyVersion: afterOutputResult.policyVersion
|
|
642
|
+
})
|
|
643
|
+
);
|
|
644
|
+
const outputContent = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
645
|
+
const evaluationResult = await this.evaluateOutput(
|
|
646
|
+
runId,
|
|
647
|
+
context,
|
|
648
|
+
outputContent,
|
|
649
|
+
input.evaluators
|
|
650
|
+
);
|
|
651
|
+
if (evaluationResult?.effect === "warn") {
|
|
652
|
+
warnings.push({ code: "evaluation.warn", message: "Evaluation warnings" });
|
|
653
|
+
}
|
|
654
|
+
const validation = await this.validateOutputSchema(
|
|
655
|
+
input.outputSchema,
|
|
656
|
+
outputContent,
|
|
657
|
+
input.outputValidationMode ?? "block",
|
|
658
|
+
runId,
|
|
659
|
+
context
|
|
660
|
+
);
|
|
661
|
+
if (validation?.warning) {
|
|
662
|
+
warnings.push({ code: "output.validation", message: validation.warning });
|
|
663
|
+
}
|
|
664
|
+
await this.auditSink.write(
|
|
665
|
+
governanceAudit.createModelResponseEvent({
|
|
666
|
+
runId,
|
|
667
|
+
context,
|
|
668
|
+
model: { id: modelId, provider: provider.id },
|
|
669
|
+
outputRef: governanceAudit.createInlineRef(outputContent),
|
|
670
|
+
usage: response.usage
|
|
671
|
+
})
|
|
672
|
+
);
|
|
673
|
+
if (this.quotaManager && response.usage) {
|
|
674
|
+
await this.commitQuota(runId, context, response.usage);
|
|
675
|
+
}
|
|
676
|
+
policySummary = this.mergePolicySummaries([
|
|
677
|
+
toPolicySummary(beforePromptResult),
|
|
678
|
+
toPolicySummary(afterOutputResult)
|
|
679
|
+
]);
|
|
680
|
+
const durationMs = Date.now() - startTime;
|
|
681
|
+
await this.auditSink.write(
|
|
682
|
+
governanceAudit.createRunEndedEvent({
|
|
683
|
+
runId,
|
|
684
|
+
context,
|
|
685
|
+
success: true,
|
|
686
|
+
durationMs
|
|
687
|
+
})
|
|
688
|
+
);
|
|
689
|
+
span.setStatus("ok");
|
|
690
|
+
span.end();
|
|
691
|
+
return {
|
|
692
|
+
runId,
|
|
693
|
+
output: response,
|
|
694
|
+
usage: response.usage,
|
|
695
|
+
policy: policySummary,
|
|
696
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
697
|
+
};
|
|
698
|
+
} catch (error) {
|
|
699
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
700
|
+
span.setStatus("error", error instanceof Error ? error.message : "Unknown error");
|
|
701
|
+
span.end();
|
|
702
|
+
const durationMs = Date.now() - startTime;
|
|
703
|
+
await this.auditSink.write(
|
|
704
|
+
governanceAudit.createRunEndedEvent({
|
|
705
|
+
runId,
|
|
706
|
+
context,
|
|
707
|
+
success: false,
|
|
708
|
+
durationMs
|
|
709
|
+
})
|
|
710
|
+
);
|
|
711
|
+
throw error;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
async generateStream(input) {
|
|
715
|
+
const runId = governanceCore.generateRunId();
|
|
716
|
+
const context = await this.contextResolver(input.context);
|
|
717
|
+
const startTime = Date.now();
|
|
718
|
+
const resolveSpan = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.MODEL_RESOLVE, {
|
|
719
|
+
"arelis.run.id": runId,
|
|
720
|
+
"arelis.model.requested": input.model,
|
|
721
|
+
...this.telemetry.contextAttributes(context)
|
|
722
|
+
});
|
|
723
|
+
let resolved;
|
|
724
|
+
try {
|
|
725
|
+
resolved = this.modelRegistry.resolveRouteOrModel({
|
|
726
|
+
routeOrModelId: input.model,
|
|
727
|
+
context,
|
|
728
|
+
dataClass: input.dataClass,
|
|
729
|
+
requiredResidency: input.requiredResidency
|
|
730
|
+
});
|
|
731
|
+
resolveSpan.setAttribute("arelis.model.id", resolved.descriptor.id);
|
|
732
|
+
if (resolved.routeId) {
|
|
733
|
+
resolveSpan.setAttribute("arelis.model.route.id", resolved.routeId);
|
|
734
|
+
}
|
|
735
|
+
} catch (error) {
|
|
736
|
+
resolveSpan.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
737
|
+
resolveSpan.setStatus(
|
|
738
|
+
"error",
|
|
739
|
+
error instanceof Error ? error.message : "Model resolution failed"
|
|
740
|
+
);
|
|
741
|
+
resolveSpan.end();
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
744
|
+
const modelId = resolved.descriptor.id;
|
|
745
|
+
const provider = this.modelRegistry.resolve(resolved.descriptor.providerId);
|
|
746
|
+
if (!governanceModels.supportsStreaming(provider)) {
|
|
747
|
+
throw new Error(`Model provider "${provider.id}" does not support streaming`);
|
|
748
|
+
}
|
|
749
|
+
let requestToSend = { ...input.request, model: modelId, context };
|
|
750
|
+
const promptTemplate = this.resolvePromptTemplate(input.promptTemplate);
|
|
751
|
+
if (promptTemplate) {
|
|
752
|
+
requestToSend = this.applyPromptTemplate(promptTemplate, requestToSend);
|
|
753
|
+
}
|
|
754
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.MODEL_STREAM, {
|
|
755
|
+
"arelis.run.id": runId,
|
|
756
|
+
"arelis.model.id": modelId,
|
|
757
|
+
...this.telemetry.contextAttributes(context)
|
|
758
|
+
});
|
|
759
|
+
await this.auditSink.write(
|
|
760
|
+
governanceAudit.createRunStartedEvent({
|
|
761
|
+
runId,
|
|
762
|
+
context,
|
|
763
|
+
operation: "models.generateStream"
|
|
764
|
+
})
|
|
765
|
+
);
|
|
766
|
+
try {
|
|
767
|
+
await this.emitModelResolutionEvents(runId, context, resolved);
|
|
768
|
+
await this.captureSnapshot({
|
|
769
|
+
runId,
|
|
770
|
+
context,
|
|
771
|
+
modelRouteId: resolved.routeId
|
|
772
|
+
});
|
|
773
|
+
resolveSpan.setStatus("ok");
|
|
774
|
+
} catch (error) {
|
|
775
|
+
resolveSpan.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
776
|
+
resolveSpan.setStatus(
|
|
777
|
+
"error",
|
|
778
|
+
error instanceof Error ? error.message : "Model resolution failed"
|
|
779
|
+
);
|
|
780
|
+
throw error;
|
|
781
|
+
} finally {
|
|
782
|
+
resolveSpan.end();
|
|
783
|
+
}
|
|
784
|
+
const quotaDecision = await this.preflightQuota(
|
|
785
|
+
runId,
|
|
786
|
+
context,
|
|
787
|
+
provider,
|
|
788
|
+
requestToSend,
|
|
789
|
+
input.options
|
|
790
|
+
);
|
|
791
|
+
let generationOptions = input.options;
|
|
792
|
+
if (quotaDecision?.effect === "limit" && quotaDecision.applied.tokensOut !== void 0) {
|
|
793
|
+
const currentMax = generationOptions?.maxTokens;
|
|
794
|
+
const limited = quotaDecision.applied.tokensOut;
|
|
795
|
+
generationOptions = {
|
|
796
|
+
...generationOptions ?? {},
|
|
797
|
+
maxTokens: currentMax ? Math.min(currentMax, limited) : limited
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
if (promptTemplate) {
|
|
801
|
+
await this.auditSink.write(
|
|
802
|
+
governanceAudit.createPromptTemplateUsedEvent({
|
|
803
|
+
runId,
|
|
804
|
+
context,
|
|
805
|
+
template: {
|
|
806
|
+
id: promptTemplate.id,
|
|
807
|
+
version: promptTemplate.version,
|
|
808
|
+
hash: promptTemplate.hash
|
|
809
|
+
}
|
|
810
|
+
})
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
const beforePromptResult = await this.evaluatePolicy("BeforePrompt", runId, context, {
|
|
814
|
+
modelId,
|
|
815
|
+
input: requestToSend.messages
|
|
816
|
+
});
|
|
817
|
+
if (!beforePromptResult.summary.allowed) {
|
|
818
|
+
throw await this.createPolicyError(beforePromptResult, runId, context);
|
|
819
|
+
}
|
|
820
|
+
await this.auditSink.write(
|
|
821
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
822
|
+
runId,
|
|
823
|
+
context,
|
|
824
|
+
checkpoint: "BeforePrompt",
|
|
825
|
+
decisions: toAuditDecisions(beforePromptResult.decisions),
|
|
826
|
+
allowed: true,
|
|
827
|
+
policyVersion: beforePromptResult.policyVersion
|
|
828
|
+
})
|
|
829
|
+
);
|
|
830
|
+
await this.enforceRuntimeRiskRoute({
|
|
831
|
+
runId,
|
|
832
|
+
context,
|
|
833
|
+
operation: "models.generateStream",
|
|
834
|
+
policyDecisions: beforePromptResult.decisions,
|
|
835
|
+
quotaEffect: quotaDecision?.effect
|
|
836
|
+
});
|
|
837
|
+
if (input.grounding) {
|
|
838
|
+
const grounded = await this.applyGrounding(input.grounding, requestToSend, runId, context);
|
|
839
|
+
requestToSend = grounded.request;
|
|
840
|
+
}
|
|
841
|
+
await this.auditSink.write(
|
|
842
|
+
governanceAudit.createModelRequestEvent({
|
|
843
|
+
runId,
|
|
844
|
+
context,
|
|
845
|
+
model: { id: modelId, provider: provider.id, version: resolved.descriptor.version },
|
|
846
|
+
inputRef: governanceAudit.createInlineRef(JSON.stringify(requestToSend.messages)),
|
|
847
|
+
promptTemplate: promptTemplate ? { id: promptTemplate.id, version: promptTemplate.version, hash: promptTemplate.hash } : void 0
|
|
848
|
+
})
|
|
849
|
+
);
|
|
850
|
+
await this.auditSink.write(
|
|
851
|
+
governanceAudit.createModelStreamStartedEvent({
|
|
852
|
+
runId,
|
|
853
|
+
context,
|
|
854
|
+
model: { id: modelId, provider: provider.id }
|
|
855
|
+
})
|
|
856
|
+
);
|
|
857
|
+
const emitChunks = input.streamOptions?.emitChunks ?? true;
|
|
858
|
+
const abortOnSensitive = input.streamOptions?.abortOnSensitive ?? false;
|
|
859
|
+
const baseStream = provider.stream(requestToSend, generationOptions);
|
|
860
|
+
const auditSink = this.auditSink;
|
|
861
|
+
const redactor = this.redactor;
|
|
862
|
+
const evaluatePolicy = this.evaluatePolicy.bind(this);
|
|
863
|
+
const createPolicyError = this.createPolicyError.bind(this);
|
|
864
|
+
const evaluateOutput = this.evaluateOutput.bind(this);
|
|
865
|
+
const validateOutputSchema = this.validateOutputSchema.bind(this);
|
|
866
|
+
const commitQuota = this.commitQuota.bind(this);
|
|
867
|
+
const createPolicyEvaluatedEventWithMetadata = this.createPolicyEvaluatedEventWithMetadata.bind(this);
|
|
868
|
+
const quotaManager = this.quotaManager;
|
|
869
|
+
let completed = false;
|
|
870
|
+
let outputContent = "";
|
|
871
|
+
let usage;
|
|
872
|
+
async function* wrappedStream() {
|
|
873
|
+
try {
|
|
874
|
+
for await (const chunk of baseStream) {
|
|
875
|
+
if (chunk.type === "content" && chunk.content) {
|
|
876
|
+
outputContent += chunk.content;
|
|
877
|
+
if (abortOnSensitive && redactor.containsSensitiveData(chunk.content)) {
|
|
878
|
+
await auditSink.write(
|
|
879
|
+
governanceAudit.createSecretDetectedBlockedEvent({
|
|
880
|
+
runId,
|
|
881
|
+
context,
|
|
882
|
+
reason: "Sensitive content detected in stream chunk"
|
|
883
|
+
})
|
|
884
|
+
);
|
|
885
|
+
await auditSink.write(
|
|
886
|
+
governanceAudit.createModelStreamAbortedEvent({
|
|
887
|
+
runId,
|
|
888
|
+
context,
|
|
889
|
+
model: { id: modelId, provider: provider.id },
|
|
890
|
+
reason: "Sensitive content detected"
|
|
891
|
+
})
|
|
892
|
+
);
|
|
893
|
+
throw new Error("Sensitive content detected during streaming");
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if (chunk.type === "usage") {
|
|
897
|
+
usage = chunk.usage;
|
|
898
|
+
}
|
|
899
|
+
if (emitChunks) {
|
|
900
|
+
await auditSink.write(
|
|
901
|
+
governanceAudit.createModelStreamChunkEvent({
|
|
902
|
+
runId,
|
|
903
|
+
context,
|
|
904
|
+
model: { id: modelId, provider: provider.id },
|
|
905
|
+
chunkType: chunk.type,
|
|
906
|
+
size: chunk.content ? chunk.content.length : void 0
|
|
907
|
+
})
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
if (chunk.type === "done") {
|
|
911
|
+
const afterOutputResult = await evaluatePolicy("AfterModelOutput", runId, context, {
|
|
912
|
+
modelId,
|
|
913
|
+
input: requestToSend.messages,
|
|
914
|
+
output: outputContent
|
|
915
|
+
});
|
|
916
|
+
if (!afterOutputResult.summary.allowed) {
|
|
917
|
+
throw await createPolicyError(afterOutputResult, runId, context);
|
|
918
|
+
}
|
|
919
|
+
await auditSink.write(
|
|
920
|
+
createPolicyEvaluatedEventWithMetadata({
|
|
921
|
+
runId,
|
|
922
|
+
context,
|
|
923
|
+
checkpoint: "AfterModelOutput",
|
|
924
|
+
decisions: toAuditDecisions(afterOutputResult.decisions),
|
|
925
|
+
allowed: true,
|
|
926
|
+
policyVersion: afterOutputResult.policyVersion
|
|
927
|
+
})
|
|
928
|
+
);
|
|
929
|
+
await evaluateOutput(runId, context, outputContent, input.evaluators);
|
|
930
|
+
await validateOutputSchema(
|
|
931
|
+
input.outputSchema,
|
|
932
|
+
outputContent,
|
|
933
|
+
input.outputValidationMode ?? "block",
|
|
934
|
+
runId,
|
|
935
|
+
context
|
|
936
|
+
);
|
|
937
|
+
await auditSink.write(
|
|
938
|
+
governanceAudit.createModelResponseEvent({
|
|
939
|
+
runId,
|
|
940
|
+
context,
|
|
941
|
+
model: { id: modelId, provider: provider.id },
|
|
942
|
+
outputRef: governanceAudit.createInlineRef(outputContent),
|
|
943
|
+
usage
|
|
944
|
+
})
|
|
945
|
+
);
|
|
946
|
+
if (quotaManager && usage) {
|
|
947
|
+
await commitQuota(runId, context, usage);
|
|
948
|
+
}
|
|
949
|
+
await auditSink.write(
|
|
950
|
+
governanceAudit.createModelStreamEndedEvent({
|
|
951
|
+
runId,
|
|
952
|
+
context,
|
|
953
|
+
model: { id: modelId, provider: provider.id },
|
|
954
|
+
finishReason: chunk.finishReason
|
|
955
|
+
})
|
|
956
|
+
);
|
|
957
|
+
await auditSink.write(
|
|
958
|
+
governanceAudit.createRunEndedEvent({
|
|
959
|
+
runId,
|
|
960
|
+
context,
|
|
961
|
+
success: true,
|
|
962
|
+
durationMs: Date.now() - startTime
|
|
963
|
+
})
|
|
964
|
+
);
|
|
965
|
+
completed = true;
|
|
966
|
+
}
|
|
967
|
+
yield chunk;
|
|
968
|
+
}
|
|
969
|
+
} catch (error) {
|
|
970
|
+
if (!completed) {
|
|
971
|
+
await auditSink.write(
|
|
972
|
+
governanceAudit.createModelStreamAbortedEvent({
|
|
973
|
+
runId,
|
|
974
|
+
context,
|
|
975
|
+
model: { id: modelId, provider: provider.id },
|
|
976
|
+
reason: error instanceof Error ? error.message : "Stream aborted"
|
|
977
|
+
})
|
|
978
|
+
);
|
|
979
|
+
await auditSink.write(
|
|
980
|
+
governanceAudit.createRunEndedEvent({
|
|
981
|
+
runId,
|
|
982
|
+
context,
|
|
983
|
+
success: false,
|
|
984
|
+
durationMs: Date.now() - startTime
|
|
985
|
+
})
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
989
|
+
span.setStatus("error", error instanceof Error ? error.message : "Unknown error");
|
|
990
|
+
span.end();
|
|
991
|
+
throw error;
|
|
992
|
+
} finally {
|
|
993
|
+
if (completed) {
|
|
994
|
+
span.setStatus("ok");
|
|
995
|
+
span.end();
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
return { runId, stream: wrappedStream() };
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Run an agent with limits and governance
|
|
1003
|
+
*/
|
|
1004
|
+
async runAgent(input) {
|
|
1005
|
+
const runId = governanceCore.generateRunId();
|
|
1006
|
+
const context = await this.contextResolver(input.context);
|
|
1007
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.RUN, {
|
|
1008
|
+
"arelis.run.id": runId,
|
|
1009
|
+
"arelis.agent.id": input.agent.getConfig().agentId,
|
|
1010
|
+
...this.telemetry.contextAttributes(context)
|
|
1011
|
+
});
|
|
1012
|
+
try {
|
|
1013
|
+
let adjustedLimits = input.limits;
|
|
1014
|
+
let quotaEffect;
|
|
1015
|
+
if (this.quotaManager) {
|
|
1016
|
+
const key = this.toQuotaKey(context);
|
|
1017
|
+
const proposed = {
|
|
1018
|
+
agentSteps: input.limits?.maxSteps ?? input.agent.getConfig().limits.maxSteps,
|
|
1019
|
+
wallTimeMs: input.limits?.maxTimeMs ?? input.agent.getConfig().limits.maxTimeMs
|
|
1020
|
+
};
|
|
1021
|
+
const decision = await this.quotaManager.check(key, proposed);
|
|
1022
|
+
quotaEffect = decision.effect;
|
|
1023
|
+
await this.auditSink.write(governanceAudit.createQuotaCheckedEvent({ runId, context, key }));
|
|
1024
|
+
if (decision.effect === "limit") {
|
|
1025
|
+
await this.auditSink.write(
|
|
1026
|
+
governanceAudit.createQuotaLimitedEvent({ runId, context, key, reason: decision.reason })
|
|
1027
|
+
);
|
|
1028
|
+
adjustedLimits = {
|
|
1029
|
+
...adjustedLimits,
|
|
1030
|
+
maxSteps: decision.applied.agentSteps ?? adjustedLimits?.maxSteps,
|
|
1031
|
+
maxTimeMs: decision.applied.wallTimeMs ?? adjustedLimits?.maxTimeMs
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
if (decision.effect === "block") {
|
|
1035
|
+
await this.auditSink.write(
|
|
1036
|
+
governanceAudit.createQuotaExceededEvent({ runId, context, key, reason: decision.reason })
|
|
1037
|
+
);
|
|
1038
|
+
throw new governanceCore.PolicyBlockedError({
|
|
1039
|
+
runId,
|
|
1040
|
+
context,
|
|
1041
|
+
reason: decision.reason,
|
|
1042
|
+
policyCode: decision.code
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
await this.auditSink.write(
|
|
1047
|
+
governanceAudit.createRunStartedEvent({
|
|
1048
|
+
runId,
|
|
1049
|
+
context,
|
|
1050
|
+
operation: "agents.run"
|
|
1051
|
+
})
|
|
1052
|
+
);
|
|
1053
|
+
await this.captureSnapshot({
|
|
1054
|
+
runId,
|
|
1055
|
+
context
|
|
1056
|
+
});
|
|
1057
|
+
await this.enforceRuntimeRiskRoute({
|
|
1058
|
+
runId,
|
|
1059
|
+
context,
|
|
1060
|
+
operation: "agents.run",
|
|
1061
|
+
policyDecisions: [],
|
|
1062
|
+
quotaEffect
|
|
1063
|
+
});
|
|
1064
|
+
const runtimeAgent = input.agent;
|
|
1065
|
+
const runtimeCanSelfGovern = typeof runtimeAgent.configureRuntimeGovernance === "function";
|
|
1066
|
+
if (runtimeCanSelfGovern) {
|
|
1067
|
+
runtimeAgent.configureRuntimeGovernance?.({
|
|
1068
|
+
policyEngine: this.policyEngine,
|
|
1069
|
+
auditSink: this.auditSink,
|
|
1070
|
+
compiledPolicy: this.compiledPolicy ? {
|
|
1071
|
+
snapshotHash: this.compiledPolicy.snapshot.hash,
|
|
1072
|
+
compilerId: this.compiledPolicy.engineId,
|
|
1073
|
+
constraints: this.compiledPolicy.constraints,
|
|
1074
|
+
disclosureRules: this.compiledPolicy.disclosureRules,
|
|
1075
|
+
policyVersion: this.compiledPolicy.policyVersion
|
|
1076
|
+
} : void 0
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
const result = await runtimeAgent.run({
|
|
1080
|
+
input: input.input,
|
|
1081
|
+
runId,
|
|
1082
|
+
limits: adjustedLimits,
|
|
1083
|
+
onStep: runtimeCanSelfGovern ? void 0 : async (step) => {
|
|
1084
|
+
const toolCalls = step.execution?.toolName && step.execution.toolName.length > 0 ? [
|
|
1085
|
+
{
|
|
1086
|
+
toolName: step.execution.toolName,
|
|
1087
|
+
argsRef: step.execution.toolInput ? governanceAudit.createHashRef(JSON.stringify(step.execution.toolInput)) : void 0,
|
|
1088
|
+
resultRef: step.execution.toolOutput !== void 0 ? governanceAudit.createHashRef(JSON.stringify(step.execution.toolOutput)) : void 0,
|
|
1089
|
+
success: !step.execution.error
|
|
1090
|
+
}
|
|
1091
|
+
] : void 0;
|
|
1092
|
+
await this.auditSink.write(
|
|
1093
|
+
governanceAudit.createAgentStepEvent({
|
|
1094
|
+
runId,
|
|
1095
|
+
context,
|
|
1096
|
+
stepNumber: step.stepNumber,
|
|
1097
|
+
stepType: "plan"
|
|
1098
|
+
})
|
|
1099
|
+
);
|
|
1100
|
+
await this.auditSink.write(
|
|
1101
|
+
governanceAudit.createAgentStepEvent({
|
|
1102
|
+
runId,
|
|
1103
|
+
context,
|
|
1104
|
+
stepNumber: step.stepNumber,
|
|
1105
|
+
stepType: "execute",
|
|
1106
|
+
toolCalls
|
|
1107
|
+
})
|
|
1108
|
+
);
|
|
1109
|
+
await this.auditSink.write(
|
|
1110
|
+
governanceAudit.createAgentStepEvent({
|
|
1111
|
+
runId,
|
|
1112
|
+
context,
|
|
1113
|
+
stepNumber: step.stepNumber,
|
|
1114
|
+
stepType: "observe"
|
|
1115
|
+
})
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
});
|
|
1119
|
+
if (result.status === "completed" && result.output !== null) {
|
|
1120
|
+
const outputContent = typeof result.output === "string" ? result.output : JSON.stringify(result.output);
|
|
1121
|
+
await this.evaluateOutput(runId, context, outputContent, void 0, "agent");
|
|
1122
|
+
}
|
|
1123
|
+
if (this.quotaManager) {
|
|
1124
|
+
const key = this.toQuotaKey(context);
|
|
1125
|
+
await this.quotaManager.commit(key, {
|
|
1126
|
+
agentSteps: result.totalSteps,
|
|
1127
|
+
wallTimeMs: result.totalDurationMs
|
|
1128
|
+
});
|
|
1129
|
+
await this.auditSink.write(governanceAudit.createQuotaCommittedEvent({ runId, context, key }));
|
|
1130
|
+
}
|
|
1131
|
+
await this.auditSink.write(
|
|
1132
|
+
governanceAudit.createRunEndedEvent({
|
|
1133
|
+
runId,
|
|
1134
|
+
context,
|
|
1135
|
+
success: result.status === "completed",
|
|
1136
|
+
durationMs: result.totalDurationMs
|
|
1137
|
+
})
|
|
1138
|
+
);
|
|
1139
|
+
span.setStatus(result.status === "completed" ? "ok" : "error", result.error);
|
|
1140
|
+
span.end();
|
|
1141
|
+
return result;
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
1144
|
+
span.setStatus("error", error instanceof Error ? error.message : "Unknown error");
|
|
1145
|
+
span.end();
|
|
1146
|
+
throw error;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Evaluate a policy checkpoint
|
|
1151
|
+
*/
|
|
1152
|
+
async evaluatePolicy(checkpoint, runId, context, data) {
|
|
1153
|
+
const compiled = this.compiledPolicy ? {
|
|
1154
|
+
compilerId: this.compiledPolicy.engineId,
|
|
1155
|
+
snapshotHash: this.compiledPolicy.snapshot.hash,
|
|
1156
|
+
constraints: this.compiledPolicy.constraints,
|
|
1157
|
+
disclosureRules: this.compiledPolicy.disclosureRules
|
|
1158
|
+
} : void 0;
|
|
1159
|
+
const input = {
|
|
1160
|
+
checkpoint,
|
|
1161
|
+
context,
|
|
1162
|
+
runId,
|
|
1163
|
+
compiled,
|
|
1164
|
+
data
|
|
1165
|
+
};
|
|
1166
|
+
if (compiled && this.policyEngine.evaluateCompiled) {
|
|
1167
|
+
return this.policyEngine.evaluateCompiled(input);
|
|
1168
|
+
}
|
|
1169
|
+
return this.policyEngine.evaluate(input);
|
|
1170
|
+
}
|
|
1171
|
+
resolveRuntimeRiskRoute(input) {
|
|
1172
|
+
return governancePolicy.resolveRiskRoute(
|
|
1173
|
+
{
|
|
1174
|
+
operation: input.operation,
|
|
1175
|
+
context: input.context,
|
|
1176
|
+
policyDecisions: input.policyDecisions,
|
|
1177
|
+
quotaEffect: input.quotaEffect,
|
|
1178
|
+
evaluationEffect: input.evaluationEffect,
|
|
1179
|
+
explicitSignals: input.explicitSignals
|
|
1180
|
+
},
|
|
1181
|
+
this.riskRouterConfig
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
async enforceRuntimeRiskRoute(input) {
|
|
1185
|
+
const decision = this.resolveRuntimeRiskRoute({
|
|
1186
|
+
operation: input.operation,
|
|
1187
|
+
context: input.context,
|
|
1188
|
+
policyDecisions: input.policyDecisions,
|
|
1189
|
+
quotaEffect: input.quotaEffect,
|
|
1190
|
+
evaluationEffect: input.evaluationEffect,
|
|
1191
|
+
explicitSignals: input.explicitSignals
|
|
1192
|
+
});
|
|
1193
|
+
await this.auditSink.write(
|
|
1194
|
+
governanceAudit.createRiskRouteDecidedEvent({
|
|
1195
|
+
runId: input.runId,
|
|
1196
|
+
context: input.context,
|
|
1197
|
+
route: decision.action,
|
|
1198
|
+
score: decision.score,
|
|
1199
|
+
factors: decision.factors,
|
|
1200
|
+
deterministicInputsHash: decision.deterministicInputsHash
|
|
1201
|
+
})
|
|
1202
|
+
);
|
|
1203
|
+
if (decision.action === "block") {
|
|
1204
|
+
throw new governanceCore.PolicyBlockedError({
|
|
1205
|
+
runId: input.runId,
|
|
1206
|
+
context: input.context,
|
|
1207
|
+
reason: "Risk router blocked execution",
|
|
1208
|
+
policyCode: "RISK_ROUTE_BLOCKED"
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
if (decision.action === "require_approval") {
|
|
1212
|
+
throw await this.createPolicyError(
|
|
1213
|
+
{
|
|
1214
|
+
decisions: [
|
|
1215
|
+
{
|
|
1216
|
+
effect: "require_approval",
|
|
1217
|
+
approvers: [input.context.actor.id],
|
|
1218
|
+
reason: "Risk router requires approval"
|
|
1219
|
+
}
|
|
1220
|
+
],
|
|
1221
|
+
summary: {
|
|
1222
|
+
allowed: false,
|
|
1223
|
+
blockReason: "Risk router requires approval",
|
|
1224
|
+
approvers: [input.context.actor.id]
|
|
1225
|
+
}
|
|
1226
|
+
},
|
|
1227
|
+
input.runId,
|
|
1228
|
+
input.context
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1231
|
+
return decision.action === "sandbox" ? "sandbox" : void 0;
|
|
1232
|
+
}
|
|
1233
|
+
computeDeterministicHash(value) {
|
|
1234
|
+
return governanceAudit.hashObject(value);
|
|
1235
|
+
}
|
|
1236
|
+
async captureSnapshot(input) {
|
|
1237
|
+
const toolRegistryHash = this.toolRegistry ? this.computeDeterministicHash(
|
|
1238
|
+
this.toolRegistry.list().map((tool) => tool.name).sort()
|
|
1239
|
+
) : void 0;
|
|
1240
|
+
const configStateHash = this.computeDeterministicHash({
|
|
1241
|
+
extensions: this.extensions,
|
|
1242
|
+
policyCompilerId: this.compiledPolicy?.engineId,
|
|
1243
|
+
policyVersion: this.compiledPolicy?.policyVersion
|
|
1244
|
+
});
|
|
1245
|
+
const snapshot = {
|
|
1246
|
+
schema: "arelis.audit.snapshot.bundle.v1",
|
|
1247
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1248
|
+
policySnapshotHash: this.compiledPolicy?.snapshot.hash,
|
|
1249
|
+
modelRouteId: input.modelRouteId,
|
|
1250
|
+
toolRegistryHash,
|
|
1251
|
+
configStateHash
|
|
1252
|
+
};
|
|
1253
|
+
const snapshotHash = this.computeDeterministicHash(snapshot);
|
|
1254
|
+
this.runSnapshots.set(input.runId, snapshot);
|
|
1255
|
+
await this.auditSink.write(
|
|
1256
|
+
governanceAudit.createSnapshotCapturedEvent({
|
|
1257
|
+
runId: input.runId,
|
|
1258
|
+
context: input.context,
|
|
1259
|
+
snapshotSchema: snapshot.schema,
|
|
1260
|
+
snapshotHash,
|
|
1261
|
+
policySnapshotHash: snapshot.policySnapshotHash,
|
|
1262
|
+
modelRouteId: snapshot.modelRouteId,
|
|
1263
|
+
toolRegistryHash: snapshot.toolRegistryHash,
|
|
1264
|
+
configStateHash: snapshot.configStateHash
|
|
1265
|
+
})
|
|
1266
|
+
);
|
|
1267
|
+
return snapshot;
|
|
1268
|
+
}
|
|
1269
|
+
getPolicyAuditMetadata() {
|
|
1270
|
+
return {
|
|
1271
|
+
policySnapshotHash: this.compiledPolicy?.snapshot.hash,
|
|
1272
|
+
policyCompilerId: this.compiledPolicy?.engineId
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
createPolicyEvaluatedEventWithMetadata(options) {
|
|
1276
|
+
const event = governanceAudit.createPolicyEvaluatedEvent(options);
|
|
1277
|
+
const metadata = this.getPolicyAuditMetadata();
|
|
1278
|
+
if (metadata.policySnapshotHash) {
|
|
1279
|
+
event.policySnapshotHash = metadata.policySnapshotHash;
|
|
1280
|
+
}
|
|
1281
|
+
if (metadata.policyCompilerId) {
|
|
1282
|
+
event.policyCompilerId = metadata.policyCompilerId;
|
|
1283
|
+
}
|
|
1284
|
+
return event;
|
|
1285
|
+
}
|
|
1286
|
+
extractAuditContextFromGraph(graph) {
|
|
1287
|
+
for (const node of graph.nodes) {
|
|
1288
|
+
if (node.kind === "event" && node.event) {
|
|
1289
|
+
return node.event.context;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return void 0;
|
|
1293
|
+
}
|
|
1294
|
+
extractPolicySnapshotHashFromGraph(graph) {
|
|
1295
|
+
for (const node of graph.nodes) {
|
|
1296
|
+
if (node.kind === "event" && node.event && node.event.type === "policy.evaluated" && node.event.policySnapshotHash) {
|
|
1297
|
+
return node.event.policySnapshotHash;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return void 0;
|
|
1301
|
+
}
|
|
1302
|
+
isComposedProofCapabilityEnabled() {
|
|
1303
|
+
return this.extensions?.capabilities?.["multiLayerComposedComplianceProofs"]?.enabled === true || this.extensions?.composedProofs?.profile === "hash_and_zk";
|
|
1304
|
+
}
|
|
1305
|
+
buildComposedProofLayers(graph) {
|
|
1306
|
+
const eventNodes = graph.nodes.filter((node) => node.kind === "event" && node.eventType);
|
|
1307
|
+
const idsByPrefix = (prefixes) => eventNodes.filter((node) => prefixes.some((prefix) => node.eventType?.startsWith(prefix))).map((node) => node.id);
|
|
1308
|
+
return [
|
|
1309
|
+
{
|
|
1310
|
+
layer: "infra",
|
|
1311
|
+
payload: idsByPrefix(["infra.", "resource."])
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
layer: "config",
|
|
1315
|
+
payload: idsByPrefix(["config.change."])
|
|
1316
|
+
},
|
|
1317
|
+
{
|
|
1318
|
+
layer: "auth",
|
|
1319
|
+
payload: idsByPrefix(["auth."])
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
layer: "inference",
|
|
1323
|
+
payload: idsByPrefix(["model.", "output.validation."])
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
layer: "agent",
|
|
1327
|
+
payload: idsByPrefix(["agent."])
|
|
1328
|
+
},
|
|
1329
|
+
{
|
|
1330
|
+
layer: "tools",
|
|
1331
|
+
payload: idsByPrefix(["tool.", "mcp.tools."])
|
|
1332
|
+
}
|
|
1333
|
+
];
|
|
1334
|
+
}
|
|
1335
|
+
async requestComplianceArtifact(input) {
|
|
1336
|
+
if (!this.complianceGraphStore) {
|
|
1337
|
+
throw new Error("Compliance graph store not configured");
|
|
1338
|
+
}
|
|
1339
|
+
const graph = await this.complianceGraphStore.get(input.runId);
|
|
1340
|
+
if (!graph) {
|
|
1341
|
+
throw new Error(`No causal graph found for run ${input.runId}`);
|
|
1342
|
+
}
|
|
1343
|
+
const disclosureRules = resolveDisclosureRules(
|
|
1344
|
+
input.disclosureRules ?? this.complianceDisclosureRules ?? [],
|
|
1345
|
+
input.disclosureRuleIds
|
|
1346
|
+
);
|
|
1347
|
+
const usingDerivedDisclosure = !input.disclosureRules && this.compiledPolicy?.disclosureDerivation?.strategy === "policy-derived";
|
|
1348
|
+
const policySnapshotHash = this.extractPolicySnapshotHashFromGraph(graph) ?? this.compiledPolicy?.snapshot.hash;
|
|
1349
|
+
const commitment = createCausalGraphCommitment(graph, this.complianceSigner);
|
|
1350
|
+
const composedEnabled = input.composed !== void 0 || this.isComposedProofCapabilityEnabled();
|
|
1351
|
+
const composedInput = composedEnabled ? {
|
|
1352
|
+
layers: this.buildComposedProofLayers(graph),
|
|
1353
|
+
includeNarrowingProof: input.composed?.includeNarrowingProof ?? true,
|
|
1354
|
+
includeLineageProof: input.composed?.includeLineageProof ?? true,
|
|
1355
|
+
enableZk: input.composed?.enableZk ?? this.extensions?.composedProofs?.enableZkMode ?? false
|
|
1356
|
+
} : void 0;
|
|
1357
|
+
const proofInput = {
|
|
1358
|
+
graph,
|
|
1359
|
+
commitment,
|
|
1360
|
+
disclosureRules,
|
|
1361
|
+
policySnapshotHash,
|
|
1362
|
+
composed: composedInput
|
|
1363
|
+
};
|
|
1364
|
+
const provider = this.complianceProofProvider ?? new HashProofProvider();
|
|
1365
|
+
const cacheKey = `${input.runId}:${disclosureRules.map((rule) => rule.id).sort().join("|")}:${composedEnabled ? "composed" : "legacy"}`;
|
|
1366
|
+
if (input.async && this.complianceProofJobQueue) {
|
|
1367
|
+
return this.complianceProofJobQueue.submit(proofInput, provider);
|
|
1368
|
+
}
|
|
1369
|
+
let proof = this.complianceProofCache.get(cacheKey);
|
|
1370
|
+
if (!proof) {
|
|
1371
|
+
const proofPromise = provider.createProof(proofInput);
|
|
1372
|
+
if (this.complianceProofTimeoutMs && this.complianceProofTimeoutMs > 0) {
|
|
1373
|
+
proof = await Promise.race([
|
|
1374
|
+
proofPromise,
|
|
1375
|
+
new Promise((_, reject) => {
|
|
1376
|
+
setTimeout(() => {
|
|
1377
|
+
reject(new Error("Compliance proof generation timed out"));
|
|
1378
|
+
}, this.complianceProofTimeoutMs);
|
|
1379
|
+
})
|
|
1380
|
+
]);
|
|
1381
|
+
} else {
|
|
1382
|
+
proof = await proofPromise;
|
|
1383
|
+
}
|
|
1384
|
+
this.complianceProofCache.set(cacheKey, proof);
|
|
1385
|
+
}
|
|
1386
|
+
if (usingDerivedDisclosure) {
|
|
1387
|
+
const eventContext = this.extractAuditContextFromGraph(graph);
|
|
1388
|
+
const derivation = this.compiledPolicy?.disclosureDerivation;
|
|
1389
|
+
if (eventContext && derivation) {
|
|
1390
|
+
await this.auditSink.write(
|
|
1391
|
+
governanceAudit.createDisclosureDerivedGeneratedEvent({
|
|
1392
|
+
runId: input.runId,
|
|
1393
|
+
context: eventContext,
|
|
1394
|
+
policySnapshotHash,
|
|
1395
|
+
derivedRuleSetId: derivation.ruleSetId,
|
|
1396
|
+
derivedRuleCount: disclosureRules.length,
|
|
1397
|
+
derivationHash: derivation.ruleSetHash
|
|
1398
|
+
})
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
this.telemetry.addEvent(governanceTelemetryOtel.EventNames.COMPLIANCE_PROOF_GENERATED, {
|
|
1403
|
+
"arelis.run.id": input.runId,
|
|
1404
|
+
"arelis.compliance.rules": disclosureRules.length
|
|
1405
|
+
});
|
|
1406
|
+
const artifact = {
|
|
1407
|
+
id: `artifact_${input.runId}_${Date.now()}`,
|
|
1408
|
+
runId: input.runId,
|
|
1409
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1410
|
+
artifactSchema: proof.schemaVersion === governanceAudit.COMPLIANCE_PROOF_SCHEMA_V2 ? governanceAudit.COMPLIANCE_ARTIFACT_SCHEMA_V2 : governanceAudit.COMPLIANCE_ARTIFACT_SCHEMA_V1,
|
|
1411
|
+
context: this.extractAuditContextFromGraph(graph),
|
|
1412
|
+
policySnapshotHash,
|
|
1413
|
+
commitment,
|
|
1414
|
+
proof,
|
|
1415
|
+
disclosureRuleIds: disclosureRules.map((rule) => rule.id)
|
|
1416
|
+
};
|
|
1417
|
+
if (this.complianceArtifactStore) {
|
|
1418
|
+
await this.complianceArtifactStore.save(artifact);
|
|
1419
|
+
}
|
|
1420
|
+
if (proof.schemaVersion === governanceAudit.COMPLIANCE_PROOF_SCHEMA_V2 && artifact.context) {
|
|
1421
|
+
await this.auditSink.write(
|
|
1422
|
+
governanceAudit.createComplianceProofComposedEvent({
|
|
1423
|
+
runId: artifact.runId,
|
|
1424
|
+
context: artifact.context,
|
|
1425
|
+
artifactId: artifact.id,
|
|
1426
|
+
artifactSchema: governanceAudit.COMPLIANCE_ARTIFACT_SCHEMA_V2,
|
|
1427
|
+
layerCount: proof.layers?.length ?? 0,
|
|
1428
|
+
layerKinds: proof.layers?.map((layer) => layer.layer) ?? [],
|
|
1429
|
+
includesNarrowingProof: proof.narrowingProof !== void 0,
|
|
1430
|
+
includesLineageProof: proof.lineageProof !== void 0
|
|
1431
|
+
})
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
return artifact;
|
|
1435
|
+
}
|
|
1436
|
+
async verifyComplianceArtifact(input) {
|
|
1437
|
+
const provider = this.complianceProofProvider ?? new HashProofProvider();
|
|
1438
|
+
const disclosureRules = input.disclosureRules ?? this.complianceDisclosureRules ?? [];
|
|
1439
|
+
const expectComposed = input.expectComposed === true || input.artifact.artifactSchema === governanceAudit.COMPLIANCE_ARTIFACT_SCHEMA_V2 || input.artifact.proof.schemaVersion === governanceAudit.COMPLIANCE_PROOF_SCHEMA_V2;
|
|
1440
|
+
const result = await provider.verifyProof({
|
|
1441
|
+
commitment: input.artifact.commitment,
|
|
1442
|
+
proof: input.artifact.proof,
|
|
1443
|
+
disclosureRules,
|
|
1444
|
+
policySnapshotHash: input.policySnapshotHash ?? input.artifact.policySnapshotHash,
|
|
1445
|
+
expectComposed
|
|
1446
|
+
});
|
|
1447
|
+
if (result.valid && this.compiledPolicy?.disclosureDerivation?.strategy === "policy-derived" && !input.disclosureRules) {
|
|
1448
|
+
const expectedRuleIds = [...this.compiledPolicy.disclosureRules.map((rule) => rule.id)].sort();
|
|
1449
|
+
const artifactRuleIds = [...input.artifact.disclosureRuleIds ?? []].sort();
|
|
1450
|
+
if (JSON.stringify(expectedRuleIds) !== JSON.stringify(artifactRuleIds)) {
|
|
1451
|
+
return {
|
|
1452
|
+
valid: false,
|
|
1453
|
+
reason: "Derived disclosure scope does not match policy-derived rule set",
|
|
1454
|
+
reasonCode: "derived.scope_mismatch",
|
|
1455
|
+
reasonCodes: ["derived.scope_mismatch"]
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
if (input.artifact.policySnapshotHash && input.artifact.policySnapshotHash !== this.compiledPolicy.snapshot.hash) {
|
|
1459
|
+
return {
|
|
1460
|
+
valid: false,
|
|
1461
|
+
reason: "Policy snapshot hash does not match derived disclosure proof scope",
|
|
1462
|
+
reasonCode: "derived.snapshot_mismatch",
|
|
1463
|
+
reasonCodes: ["derived.snapshot_mismatch"]
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
this.telemetry.addEvent(governanceTelemetryOtel.EventNames.COMPLIANCE_PROOF_VERIFIED, {
|
|
1468
|
+
"arelis.run.id": input.artifact.runId,
|
|
1469
|
+
"arelis.compliance.valid": result.valid
|
|
1470
|
+
});
|
|
1471
|
+
return result;
|
|
1472
|
+
}
|
|
1473
|
+
async replayComplianceRun(input) {
|
|
1474
|
+
if (!this.complianceGraphStore) {
|
|
1475
|
+
throw new Error("Compliance graph store not configured");
|
|
1476
|
+
}
|
|
1477
|
+
const graph = await this.complianceGraphStore.get(input.runId);
|
|
1478
|
+
if (!graph) {
|
|
1479
|
+
throw new Error(`No causal graph found for run ${input.runId}`);
|
|
1480
|
+
}
|
|
1481
|
+
const recordedSnapshot = this.runSnapshots.get(input.runId);
|
|
1482
|
+
const replay = await governanceAudit.replayCausalGraph(graph, void 0, {
|
|
1483
|
+
recordedSnapshot,
|
|
1484
|
+
replaySnapshot: input.replaySnapshot
|
|
1485
|
+
});
|
|
1486
|
+
const driftFields = replay.driftDiagnostics?.filter((entry) => !entry.compatible).map((entry) => entry.field);
|
|
1487
|
+
const replayContext = this.extractAuditContextFromGraph(graph);
|
|
1488
|
+
if (driftFields && driftFields.length > 0 && replayContext) {
|
|
1489
|
+
await this.auditSink.write(
|
|
1490
|
+
governanceAudit.createReplayDriftDetectedEvent({
|
|
1491
|
+
runId: input.runId,
|
|
1492
|
+
context: replayContext,
|
|
1493
|
+
snapshotSchema: recordedSnapshot?.schema ?? "arelis.audit.snapshot.bundle.v1",
|
|
1494
|
+
driftFields,
|
|
1495
|
+
compatible: false
|
|
1496
|
+
})
|
|
1497
|
+
);
|
|
1498
|
+
}
|
|
1499
|
+
return replay;
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Create appropriate error from policy result
|
|
1503
|
+
*/
|
|
1504
|
+
async createPolicyError(result, runId, context) {
|
|
1505
|
+
if (result.summary.approvers && result.summary.approvers.length > 0) {
|
|
1506
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.APPROVAL_REQUEST, {
|
|
1507
|
+
"arelis.run.id": runId,
|
|
1508
|
+
...this.telemetry.contextAttributes(context)
|
|
1509
|
+
});
|
|
1510
|
+
try {
|
|
1511
|
+
const approval = await this.approvalStore.create({
|
|
1512
|
+
runId,
|
|
1513
|
+
context,
|
|
1514
|
+
operation: "policy",
|
|
1515
|
+
reason: result.summary.blockReason ?? "Approval required",
|
|
1516
|
+
approvers: result.summary.approvers
|
|
1517
|
+
});
|
|
1518
|
+
await this.auditSink.write(
|
|
1519
|
+
governanceAudit.createApprovalRequestedEvent({
|
|
1520
|
+
runId,
|
|
1521
|
+
context,
|
|
1522
|
+
approvalId: approval.id,
|
|
1523
|
+
approvers: approval.approvers,
|
|
1524
|
+
reason: approval.reason
|
|
1525
|
+
})
|
|
1526
|
+
);
|
|
1527
|
+
span.setStatus("ok");
|
|
1528
|
+
return new governanceCore.PolicyApprovalRequiredError({
|
|
1529
|
+
runId,
|
|
1530
|
+
context,
|
|
1531
|
+
reason: result.summary.blockReason ?? "Approval required",
|
|
1532
|
+
approvers: result.summary.approvers,
|
|
1533
|
+
approvalId: approval.id
|
|
1534
|
+
});
|
|
1535
|
+
} catch (error) {
|
|
1536
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
1537
|
+
span.setStatus("error", error instanceof Error ? error.message : "Approval request failed");
|
|
1538
|
+
throw error;
|
|
1539
|
+
} finally {
|
|
1540
|
+
span.end();
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
return new governanceCore.PolicyBlockedError({
|
|
1544
|
+
runId,
|
|
1545
|
+
context,
|
|
1546
|
+
reason: result.summary.blockReason ?? "Policy blocked request",
|
|
1547
|
+
policyCode: result.summary.blockCode
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Register an MCP server and discover its tools
|
|
1552
|
+
*/
|
|
1553
|
+
async registerMCPServer(input) {
|
|
1554
|
+
const context = await this.contextResolver(input.context);
|
|
1555
|
+
const runId = governanceCore.generateRunId();
|
|
1556
|
+
const policyResult = await this.evaluatePolicy("BeforeOperation", runId, context, {
|
|
1557
|
+
input: {
|
|
1558
|
+
operation: "mcp.register",
|
|
1559
|
+
server: {
|
|
1560
|
+
id: input.server.id,
|
|
1561
|
+
transport: input.server.transport.type,
|
|
1562
|
+
auth: input.server.auth?.type,
|
|
1563
|
+
governance: input.server.governance
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
await this.auditSink.write(
|
|
1568
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
1569
|
+
runId,
|
|
1570
|
+
context,
|
|
1571
|
+
checkpoint: "BeforeOperation",
|
|
1572
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
1573
|
+
allowed: policyResult.summary.allowed,
|
|
1574
|
+
policyVersion: policyResult.policyVersion
|
|
1575
|
+
})
|
|
1576
|
+
);
|
|
1577
|
+
if (!policyResult.summary.allowed) {
|
|
1578
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
1579
|
+
}
|
|
1580
|
+
this.mcpRegistry.registerServer(input.server);
|
|
1581
|
+
await this.ensureMCPTransport(input.server, context, runId);
|
|
1582
|
+
await this.auditSink.write(
|
|
1583
|
+
governanceAudit.createMCPServerRegisteredEvent({
|
|
1584
|
+
runId,
|
|
1585
|
+
context,
|
|
1586
|
+
serverId: input.server.id,
|
|
1587
|
+
transport: input.server.transport.type
|
|
1588
|
+
})
|
|
1589
|
+
);
|
|
1590
|
+
await this.auditSink.write(
|
|
1591
|
+
governanceAudit.createResourceCreatedEvent({
|
|
1592
|
+
runId,
|
|
1593
|
+
context,
|
|
1594
|
+
operation: "mcp.register",
|
|
1595
|
+
resource: {
|
|
1596
|
+
type: "mcp.server",
|
|
1597
|
+
id: input.server.id,
|
|
1598
|
+
provider: input.server.transport.type,
|
|
1599
|
+
metadata: {
|
|
1600
|
+
governance: input.server.governance
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
})
|
|
1604
|
+
);
|
|
1605
|
+
if (this.toolRegistry) {
|
|
1606
|
+
const discovery = await governanceMcp.discoverTools(
|
|
1607
|
+
this.mcpRegistry,
|
|
1608
|
+
this.toolRegistry,
|
|
1609
|
+
input.server.id,
|
|
1610
|
+
input.discoveryOptions
|
|
1611
|
+
);
|
|
1612
|
+
await this.auditSink.write(
|
|
1613
|
+
governanceAudit.createMCPServerConnectedEvent({
|
|
1614
|
+
runId,
|
|
1615
|
+
context,
|
|
1616
|
+
serverId: input.server.id
|
|
1617
|
+
})
|
|
1618
|
+
);
|
|
1619
|
+
await this.auditSink.write(
|
|
1620
|
+
governanceAudit.createMCPToolsDiscoveredEvent({
|
|
1621
|
+
runId,
|
|
1622
|
+
context,
|
|
1623
|
+
serverId: input.server.id,
|
|
1624
|
+
totalDiscovered: discovery.totalDiscovered,
|
|
1625
|
+
registeredCount: discovery.registeredCount,
|
|
1626
|
+
skippedCount: discovery.skippedCount,
|
|
1627
|
+
toolNames: discovery.tools.map((tool) => tool.originalName)
|
|
1628
|
+
})
|
|
1629
|
+
);
|
|
1630
|
+
return discovery;
|
|
1631
|
+
}
|
|
1632
|
+
const emptyResult = {
|
|
1633
|
+
serverId: input.server.id,
|
|
1634
|
+
totalDiscovered: 0,
|
|
1635
|
+
registeredCount: 0,
|
|
1636
|
+
skippedCount: 0,
|
|
1637
|
+
tools: [],
|
|
1638
|
+
discoveredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1639
|
+
};
|
|
1640
|
+
await this.auditSink.write(
|
|
1641
|
+
governanceAudit.createMCPToolsDiscoveredEvent({
|
|
1642
|
+
runId,
|
|
1643
|
+
context,
|
|
1644
|
+
serverId: input.server.id,
|
|
1645
|
+
totalDiscovered: 0,
|
|
1646
|
+
registeredCount: 0,
|
|
1647
|
+
skippedCount: 0,
|
|
1648
|
+
toolNames: []
|
|
1649
|
+
})
|
|
1650
|
+
);
|
|
1651
|
+
return emptyResult;
|
|
1652
|
+
}
|
|
1653
|
+
/**
|
|
1654
|
+
* Discover tools from an MCP server
|
|
1655
|
+
*/
|
|
1656
|
+
async discoverMCPTools(input) {
|
|
1657
|
+
if (!this.toolRegistry) {
|
|
1658
|
+
throw new Error("Tool registry is required for tool discovery");
|
|
1659
|
+
}
|
|
1660
|
+
const runId = governanceCore.generateRunId();
|
|
1661
|
+
const context = await this.contextResolver(input.context);
|
|
1662
|
+
const server = this.mcpRegistry.getServer(input.serverId);
|
|
1663
|
+
if (!server) {
|
|
1664
|
+
throw new Error(`MCP server "${input.serverId}" not found`);
|
|
1665
|
+
}
|
|
1666
|
+
const policyResult = await this.evaluatePolicy("BeforeOperation", runId, context, {
|
|
1667
|
+
input: {
|
|
1668
|
+
operation: "mcp.discover",
|
|
1669
|
+
serverId: input.serverId
|
|
1670
|
+
}
|
|
1671
|
+
});
|
|
1672
|
+
await this.auditSink.write(
|
|
1673
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
1674
|
+
runId,
|
|
1675
|
+
context,
|
|
1676
|
+
checkpoint: "BeforeOperation",
|
|
1677
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
1678
|
+
allowed: policyResult.summary.allowed,
|
|
1679
|
+
policyVersion: policyResult.policyVersion
|
|
1680
|
+
})
|
|
1681
|
+
);
|
|
1682
|
+
if (!policyResult.summary.allowed) {
|
|
1683
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
1684
|
+
}
|
|
1685
|
+
await this.ensureMCPTransport(server.descriptor, context, runId);
|
|
1686
|
+
const discovery = await governanceMcp.discoverTools(
|
|
1687
|
+
this.mcpRegistry,
|
|
1688
|
+
this.toolRegistry,
|
|
1689
|
+
input.serverId,
|
|
1690
|
+
input.options
|
|
1691
|
+
);
|
|
1692
|
+
await this.auditSink.write(
|
|
1693
|
+
governanceAudit.createMCPServerConnectedEvent({
|
|
1694
|
+
runId,
|
|
1695
|
+
context,
|
|
1696
|
+
serverId: input.serverId
|
|
1697
|
+
})
|
|
1698
|
+
);
|
|
1699
|
+
await this.auditSink.write(
|
|
1700
|
+
governanceAudit.createMCPToolsDiscoveredEvent({
|
|
1701
|
+
runId,
|
|
1702
|
+
context,
|
|
1703
|
+
serverId: input.serverId,
|
|
1704
|
+
totalDiscovered: discovery.totalDiscovered,
|
|
1705
|
+
registeredCount: discovery.registeredCount,
|
|
1706
|
+
skippedCount: discovery.skippedCount,
|
|
1707
|
+
toolNames: discovery.tools.map((tool) => tool.originalName)
|
|
1708
|
+
})
|
|
1709
|
+
);
|
|
1710
|
+
return discovery;
|
|
1711
|
+
}
|
|
1712
|
+
/**
|
|
1713
|
+
* Register a knowledge base
|
|
1714
|
+
*/
|
|
1715
|
+
async registerKB(input) {
|
|
1716
|
+
const runId = governanceCore.generateRunId();
|
|
1717
|
+
const context = await this.contextResolver(input.context);
|
|
1718
|
+
const policyResult = await this.evaluatePolicy("BeforeOperation", runId, context, {
|
|
1719
|
+
input: {
|
|
1720
|
+
operation: "knowledge.register",
|
|
1721
|
+
kb: {
|
|
1722
|
+
id: input.kb.id,
|
|
1723
|
+
provider: input.kb.provider,
|
|
1724
|
+
region: input.kb.region,
|
|
1725
|
+
governance: input.kb.governance
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
});
|
|
1729
|
+
await this.auditSink.write(
|
|
1730
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
1731
|
+
runId,
|
|
1732
|
+
context,
|
|
1733
|
+
checkpoint: "BeforeOperation",
|
|
1734
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
1735
|
+
allowed: policyResult.summary.allowed,
|
|
1736
|
+
policyVersion: policyResult.policyVersion
|
|
1737
|
+
})
|
|
1738
|
+
);
|
|
1739
|
+
if (!policyResult.summary.allowed) {
|
|
1740
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
1741
|
+
}
|
|
1742
|
+
this.kbRegistry.registerKB(input.kb);
|
|
1743
|
+
await this.auditSink.write(
|
|
1744
|
+
governanceAudit.createResourceCreatedEvent({
|
|
1745
|
+
runId,
|
|
1746
|
+
context,
|
|
1747
|
+
operation: "knowledge.register",
|
|
1748
|
+
resource: {
|
|
1749
|
+
type: "knowledge.base",
|
|
1750
|
+
id: input.kb.id,
|
|
1751
|
+
provider: input.kb.provider,
|
|
1752
|
+
region: input.kb.region,
|
|
1753
|
+
metadata: {
|
|
1754
|
+
governance: input.kb.governance
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
})
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
async registerPromptTemplate(input, contextInput) {
|
|
1761
|
+
const runId = governanceCore.generateRunId();
|
|
1762
|
+
const context = await this.contextResolver(contextInput);
|
|
1763
|
+
const policyResult = await this.evaluatePolicy("BeforeOperation", runId, context, {
|
|
1764
|
+
input: {
|
|
1765
|
+
operation: "prompts.register",
|
|
1766
|
+
template: {
|
|
1767
|
+
id: input.id,
|
|
1768
|
+
version: input.version,
|
|
1769
|
+
metadata: input.metadata
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
await this.auditSink.write(
|
|
1774
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
1775
|
+
runId,
|
|
1776
|
+
context,
|
|
1777
|
+
checkpoint: "BeforeOperation",
|
|
1778
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
1779
|
+
allowed: policyResult.summary.allowed,
|
|
1780
|
+
policyVersion: policyResult.policyVersion
|
|
1781
|
+
})
|
|
1782
|
+
);
|
|
1783
|
+
if (!policyResult.summary.allowed) {
|
|
1784
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
1785
|
+
}
|
|
1786
|
+
const template = this.promptRegistry.register(input);
|
|
1787
|
+
await this.auditSink.write(
|
|
1788
|
+
governanceAudit.createResourceCreatedEvent({
|
|
1789
|
+
runId,
|
|
1790
|
+
context,
|
|
1791
|
+
operation: "prompts.register",
|
|
1792
|
+
resource: {
|
|
1793
|
+
type: "prompt.template",
|
|
1794
|
+
id: template.id,
|
|
1795
|
+
name: template.version,
|
|
1796
|
+
metadata: {
|
|
1797
|
+
hash: template.hash,
|
|
1798
|
+
tags: template.metadata?.tags
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
})
|
|
1802
|
+
);
|
|
1803
|
+
return template;
|
|
1804
|
+
}
|
|
1805
|
+
async registerDataSource(input) {
|
|
1806
|
+
const runId = governanceCore.generateRunId();
|
|
1807
|
+
const context = await this.contextResolver(input.context);
|
|
1808
|
+
const policyResult = await this.evaluatePolicy("BeforeOperation", runId, context, {
|
|
1809
|
+
input: {
|
|
1810
|
+
operation: "dataSources.register",
|
|
1811
|
+
source: {
|
|
1812
|
+
id: input.descriptor.id,
|
|
1813
|
+
provider: input.descriptor.provider,
|
|
1814
|
+
region: input.descriptor.region,
|
|
1815
|
+
governance: input.descriptor.governance,
|
|
1816
|
+
access: input.descriptor.access
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
await this.auditSink.write(
|
|
1821
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
1822
|
+
runId,
|
|
1823
|
+
context,
|
|
1824
|
+
checkpoint: "BeforeOperation",
|
|
1825
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
1826
|
+
allowed: policyResult.summary.allowed,
|
|
1827
|
+
policyVersion: policyResult.policyVersion
|
|
1828
|
+
})
|
|
1829
|
+
);
|
|
1830
|
+
if (!policyResult.summary.allowed) {
|
|
1831
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
1832
|
+
}
|
|
1833
|
+
this.dataSourceRegistry.register(input.descriptor, input.provider);
|
|
1834
|
+
await this.auditSink.write(
|
|
1835
|
+
governanceAudit.createResourceCreatedEvent({
|
|
1836
|
+
runId,
|
|
1837
|
+
context,
|
|
1838
|
+
operation: "dataSources.register",
|
|
1839
|
+
resource: {
|
|
1840
|
+
type: "data.source",
|
|
1841
|
+
id: input.descriptor.id,
|
|
1842
|
+
provider: input.descriptor.provider,
|
|
1843
|
+
region: input.descriptor.region,
|
|
1844
|
+
metadata: {
|
|
1845
|
+
governance: input.descriptor.governance
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
})
|
|
1849
|
+
);
|
|
1850
|
+
}
|
|
1851
|
+
/**
|
|
1852
|
+
* Retrieve chunks from a knowledge base
|
|
1853
|
+
*/
|
|
1854
|
+
async retrieve(input) {
|
|
1855
|
+
const runId = governanceCore.generateRunId();
|
|
1856
|
+
const context = await this.contextResolver(input.context);
|
|
1857
|
+
const registeredKB = this.kbRegistry.getKB(input.kbId);
|
|
1858
|
+
if (!registeredKB) {
|
|
1859
|
+
throw new Error(`Knowledge base not found: ${input.kbId}`);
|
|
1860
|
+
}
|
|
1861
|
+
await this.auditSink.write(
|
|
1862
|
+
governanceAudit.createKBQueryEvent({
|
|
1863
|
+
runId,
|
|
1864
|
+
context,
|
|
1865
|
+
kb: { id: input.kbId, provider: registeredKB.descriptor.provider },
|
|
1866
|
+
queryId: runId,
|
|
1867
|
+
topK: input.query.topK
|
|
1868
|
+
})
|
|
1869
|
+
);
|
|
1870
|
+
const retriever = governanceKnowledge.createKBRetriever(this.kbRegistry);
|
|
1871
|
+
const kbContext = { runId, governance: context };
|
|
1872
|
+
const result = await retriever.retrieve(input.query, kbContext, input.options);
|
|
1873
|
+
await this.auditSink.write(
|
|
1874
|
+
governanceAudit.createKBResultsEvent({
|
|
1875
|
+
runId,
|
|
1876
|
+
context,
|
|
1877
|
+
kb: { id: input.kbId, provider: registeredKB.descriptor.provider },
|
|
1878
|
+
queryId: result.queryId,
|
|
1879
|
+
chunkCount: result.chunks.length,
|
|
1880
|
+
totalFound: result.totalFound
|
|
1881
|
+
})
|
|
1882
|
+
);
|
|
1883
|
+
return result;
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Apply grounding to a model request (internal helper)
|
|
1887
|
+
*/
|
|
1888
|
+
async applyGrounding(grounding, request, runId, context) {
|
|
1889
|
+
const groundingHelper = governanceKnowledge.createGroundingHelper();
|
|
1890
|
+
const queryText = grounding.query ?? this.extractLastUserMessage(request) ?? "No query provided";
|
|
1891
|
+
const retriever = governanceKnowledge.createKBRetriever(this.kbRegistry);
|
|
1892
|
+
const kbContext = { runId, governance: context };
|
|
1893
|
+
const retrievalResults = [];
|
|
1894
|
+
const kbInfos = [];
|
|
1895
|
+
const queryIds = [];
|
|
1896
|
+
for (const kbId of grounding.kbIds) {
|
|
1897
|
+
const registeredKB = this.kbRegistry.getKB(kbId);
|
|
1898
|
+
if (!registeredKB) {
|
|
1899
|
+
continue;
|
|
1900
|
+
}
|
|
1901
|
+
kbInfos.push({ id: kbId, provider: registeredKB.descriptor.provider });
|
|
1902
|
+
await this.auditSink.write(
|
|
1903
|
+
governanceAudit.createKBQueryEvent({
|
|
1904
|
+
runId,
|
|
1905
|
+
context,
|
|
1906
|
+
kb: { id: kbId, provider: registeredKB.descriptor.provider },
|
|
1907
|
+
queryId: `${runId}-${kbId}`,
|
|
1908
|
+
topK: grounding.topK
|
|
1909
|
+
})
|
|
1910
|
+
);
|
|
1911
|
+
const result = await retriever.retrieve(
|
|
1912
|
+
{ query: queryText, kb: kbId, topK: grounding.topK },
|
|
1913
|
+
kbContext
|
|
1914
|
+
);
|
|
1915
|
+
queryIds.push(result.queryId);
|
|
1916
|
+
retrievalResults.push(result);
|
|
1917
|
+
await this.auditSink.write(
|
|
1918
|
+
governanceAudit.createKBResultsEvent({
|
|
1919
|
+
runId,
|
|
1920
|
+
context,
|
|
1921
|
+
kb: { id: kbId, provider: registeredKB.descriptor.provider },
|
|
1922
|
+
queryId: result.queryId,
|
|
1923
|
+
chunkCount: result.chunks.length,
|
|
1924
|
+
totalFound: result.totalFound
|
|
1925
|
+
})
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
const mergedResults = governanceKnowledge.mergeRetrievalResults(retrievalResults);
|
|
1929
|
+
const queryIdByKbId = new Map(retrievalResults.map((result) => [result.kbId, result.queryId]));
|
|
1930
|
+
const kbInfoById = new Map(kbInfos.map((info) => [info.id, info]));
|
|
1931
|
+
const policyFilteredChunks = [];
|
|
1932
|
+
const allowedChunks = [];
|
|
1933
|
+
let policyFilteredCount = 0;
|
|
1934
|
+
for (const chunk of mergedResults.chunks) {
|
|
1935
|
+
const policyResult = await this.evaluatePolicy("BeforePrompt", runId, context, {
|
|
1936
|
+
input: {
|
|
1937
|
+
kbId: chunk.source.kbId,
|
|
1938
|
+
text: chunk.text,
|
|
1939
|
+
metadata: chunk.metadata,
|
|
1940
|
+
source: chunk.source,
|
|
1941
|
+
score: chunk.score
|
|
1942
|
+
}
|
|
1943
|
+
});
|
|
1944
|
+
await this.auditSink.write(
|
|
1945
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
1946
|
+
runId,
|
|
1947
|
+
context,
|
|
1948
|
+
checkpoint: "BeforePrompt",
|
|
1949
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
1950
|
+
allowed: policyResult.summary.allowed,
|
|
1951
|
+
policyVersion: policyResult.policyVersion
|
|
1952
|
+
})
|
|
1953
|
+
);
|
|
1954
|
+
if (!policyResult.summary.allowed) {
|
|
1955
|
+
policyFilteredCount += 1;
|
|
1956
|
+
const reason = policyResult.summary.blockReason ?? "Filtered by policy";
|
|
1957
|
+
policyFilteredChunks.push({ chunk, reason });
|
|
1958
|
+
const kbInfo = kbInfoById.get(chunk.source.kbId);
|
|
1959
|
+
const policyDecision = toAuditDecisions(policyResult.decisions).find(
|
|
1960
|
+
(decision) => decision.effect !== "allow"
|
|
1961
|
+
);
|
|
1962
|
+
await this.auditSink.write(
|
|
1963
|
+
governanceAudit.createKBChunkFilteredEvent({
|
|
1964
|
+
runId,
|
|
1965
|
+
context,
|
|
1966
|
+
kb: { id: chunk.source.kbId, provider: kbInfo?.provider },
|
|
1967
|
+
queryId: queryIdByKbId.get(chunk.source.kbId) ?? mergedResults.queryId,
|
|
1968
|
+
chunkRef: governanceAudit.createHashRef(chunk.text),
|
|
1969
|
+
reason,
|
|
1970
|
+
policy: policyDecision
|
|
1971
|
+
})
|
|
1972
|
+
);
|
|
1973
|
+
continue;
|
|
1974
|
+
}
|
|
1975
|
+
const patches = policyResult.decisions.flatMap(
|
|
1976
|
+
(decision) => decision.effect === "transform" ? decision.patches : []
|
|
1977
|
+
);
|
|
1978
|
+
if (patches.length > 0) {
|
|
1979
|
+
const transformed = governancePolicy.applyPatches(
|
|
1980
|
+
{
|
|
1981
|
+
text: chunk.text,
|
|
1982
|
+
metadata: chunk.metadata,
|
|
1983
|
+
source: chunk.source,
|
|
1984
|
+
score: chunk.score
|
|
1985
|
+
},
|
|
1986
|
+
patches
|
|
1987
|
+
);
|
|
1988
|
+
allowedChunks.push({
|
|
1989
|
+
...chunk,
|
|
1990
|
+
text: typeof transformed.text === "string" ? transformed.text : chunk.text,
|
|
1991
|
+
metadata: transformed.metadata && typeof transformed.metadata === "object" ? transformed.metadata : chunk.metadata,
|
|
1992
|
+
source: transformed.source && typeof transformed.source === "object" ? transformed.source : chunk.source,
|
|
1993
|
+
score: typeof transformed.score === "number" ? transformed.score : chunk.score
|
|
1994
|
+
});
|
|
1995
|
+
} else {
|
|
1996
|
+
allowedChunks.push(chunk);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
const policyFilteredResults = {
|
|
2000
|
+
...mergedResults,
|
|
2001
|
+
chunks: allowedChunks,
|
|
2002
|
+
filteredCount: (mergedResults.filteredCount ?? 0) + policyFilteredCount
|
|
2003
|
+
};
|
|
2004
|
+
const groundingResult = groundingHelper.applyGrounding(
|
|
2005
|
+
policyFilteredResults,
|
|
2006
|
+
kbContext,
|
|
2007
|
+
grounding.options
|
|
2008
|
+
);
|
|
2009
|
+
if (policyFilteredChunks.length > 0) {
|
|
2010
|
+
groundingResult.filteredChunks.unshift(...policyFilteredChunks);
|
|
2011
|
+
}
|
|
2012
|
+
await this.auditSink.write(
|
|
2013
|
+
governanceAudit.createKBGroundingAppliedEvent({
|
|
2014
|
+
runId,
|
|
2015
|
+
context,
|
|
2016
|
+
kbs: kbInfos,
|
|
2017
|
+
queryIds,
|
|
2018
|
+
chunksUsed: groundingResult.usedChunks.length,
|
|
2019
|
+
chunksFiltered: groundingResult.filteredChunks.length
|
|
2020
|
+
})
|
|
2021
|
+
);
|
|
2022
|
+
const augmentedRequest = this.augmentRequestWithGrounding(request, groundingResult);
|
|
2023
|
+
return {
|
|
2024
|
+
request: augmentedRequest,
|
|
2025
|
+
result: groundingResult
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
2028
|
+
/**
|
|
2029
|
+
* Augment a model request with grounding context
|
|
2030
|
+
*/
|
|
2031
|
+
augmentRequestWithGrounding(request, groundingResult) {
|
|
2032
|
+
if (!groundingResult.augmentedPrompt || groundingResult.usedChunks.length === 0) {
|
|
2033
|
+
return request;
|
|
2034
|
+
}
|
|
2035
|
+
const groundingMessage = {
|
|
2036
|
+
role: "system",
|
|
2037
|
+
content: groundingResult.augmentedPrompt
|
|
2038
|
+
};
|
|
2039
|
+
return {
|
|
2040
|
+
...request,
|
|
2041
|
+
messages: [groundingMessage, ...request.messages]
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* Extract the last user message from a request
|
|
2046
|
+
*/
|
|
2047
|
+
extractLastUserMessage(request) {
|
|
2048
|
+
const messages = request.messages;
|
|
2049
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2050
|
+
const msg = messages[i];
|
|
2051
|
+
if (msg && msg.role === "user") {
|
|
2052
|
+
return typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
return void 0;
|
|
2056
|
+
}
|
|
2057
|
+
resolvePromptTemplate(input) {
|
|
2058
|
+
if (!input) {
|
|
2059
|
+
return void 0;
|
|
2060
|
+
}
|
|
2061
|
+
if ("content" in input && "hash" in input) {
|
|
2062
|
+
return input;
|
|
2063
|
+
}
|
|
2064
|
+
const query = {
|
|
2065
|
+
id: input.id,
|
|
2066
|
+
version: input.version
|
|
2067
|
+
};
|
|
2068
|
+
const template = this.promptRegistry.get(query);
|
|
2069
|
+
if (!template) {
|
|
2070
|
+
throw new Error(`Prompt template not found: ${input.id}`);
|
|
2071
|
+
}
|
|
2072
|
+
return template;
|
|
2073
|
+
}
|
|
2074
|
+
applyPromptTemplate(template, request) {
|
|
2075
|
+
const systemMessage = {
|
|
2076
|
+
role: "system",
|
|
2077
|
+
content: template.content
|
|
2078
|
+
};
|
|
2079
|
+
return {
|
|
2080
|
+
...request,
|
|
2081
|
+
systemPrompt: request.systemPrompt ?? template.content,
|
|
2082
|
+
messages: [systemMessage, ...request.messages]
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
async emitModelResolutionEvents(runId, context, resolved) {
|
|
2086
|
+
const descriptor = resolved.descriptor;
|
|
2087
|
+
if (descriptor.lifecycleState === "disabled") {
|
|
2088
|
+
await this.auditSink.write(
|
|
2089
|
+
governanceAudit.createModelDisabledBlockedEvent({
|
|
2090
|
+
runId,
|
|
2091
|
+
context,
|
|
2092
|
+
model: {
|
|
2093
|
+
id: descriptor.id,
|
|
2094
|
+
provider: descriptor.providerId,
|
|
2095
|
+
version: descriptor.version
|
|
2096
|
+
},
|
|
2097
|
+
reason: "Model disabled"
|
|
2098
|
+
})
|
|
2099
|
+
);
|
|
2100
|
+
throw new Error(`Model "${descriptor.id}" is disabled`);
|
|
2101
|
+
}
|
|
2102
|
+
await this.auditSink.write(
|
|
2103
|
+
governanceAudit.createModelResolvedEvent({
|
|
2104
|
+
runId,
|
|
2105
|
+
context,
|
|
2106
|
+
routeId: resolved.routeId,
|
|
2107
|
+
model: {
|
|
2108
|
+
id: descriptor.id,
|
|
2109
|
+
provider: descriptor.providerId,
|
|
2110
|
+
version: descriptor.version,
|
|
2111
|
+
lifecycleState: descriptor.lifecycleState
|
|
2112
|
+
},
|
|
2113
|
+
fallbackUsed: resolved.fallbackUsed
|
|
2114
|
+
})
|
|
2115
|
+
);
|
|
2116
|
+
if (resolved.fallbackUsed) {
|
|
2117
|
+
await this.auditSink.write(
|
|
2118
|
+
governanceAudit.createModelFallbackUsedEvent({
|
|
2119
|
+
runId,
|
|
2120
|
+
context,
|
|
2121
|
+
routeId: resolved.routeId,
|
|
2122
|
+
model: {
|
|
2123
|
+
id: descriptor.id,
|
|
2124
|
+
provider: descriptor.providerId,
|
|
2125
|
+
version: descriptor.version
|
|
2126
|
+
},
|
|
2127
|
+
reason: "Fallback candidate selected"
|
|
2128
|
+
})
|
|
2129
|
+
);
|
|
2130
|
+
}
|
|
2131
|
+
if (descriptor.lifecycleState === "deprecated") {
|
|
2132
|
+
await this.auditSink.write(
|
|
2133
|
+
governanceAudit.createModelDeprecatedUsedEvent({
|
|
2134
|
+
runId,
|
|
2135
|
+
context,
|
|
2136
|
+
model: {
|
|
2137
|
+
id: descriptor.id,
|
|
2138
|
+
provider: descriptor.providerId,
|
|
2139
|
+
version: descriptor.version
|
|
2140
|
+
},
|
|
2141
|
+
reason: "Deprecated model used"
|
|
2142
|
+
})
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
toQuotaKey(context) {
|
|
2147
|
+
return {
|
|
2148
|
+
orgId: context.org.id,
|
|
2149
|
+
teamId: context.team?.id,
|
|
2150
|
+
actorId: context.actor.id,
|
|
2151
|
+
purpose: context.purpose,
|
|
2152
|
+
environment: context.environment
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
async preflightQuota(runId, context, provider, request, options) {
|
|
2156
|
+
if (!this.quotaManager) {
|
|
2157
|
+
return void 0;
|
|
2158
|
+
}
|
|
2159
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.QUOTA_CHECK, {
|
|
2160
|
+
"arelis.run.id": runId,
|
|
2161
|
+
"arelis.model.id": request.model,
|
|
2162
|
+
...this.telemetry.contextAttributes(context)
|
|
2163
|
+
});
|
|
2164
|
+
const key = this.toQuotaKey(context);
|
|
2165
|
+
const proposed = {};
|
|
2166
|
+
if (governanceModels.supportsTokenEstimation(provider)) {
|
|
2167
|
+
proposed.tokensIn = await provider.estimateTokens(request);
|
|
2168
|
+
}
|
|
2169
|
+
if (options?.maxTokens) {
|
|
2170
|
+
proposed.tokensOut = options.maxTokens;
|
|
2171
|
+
}
|
|
2172
|
+
try {
|
|
2173
|
+
const decision = await this.quotaManager.check(key, proposed);
|
|
2174
|
+
await this.auditSink.write(governanceAudit.createQuotaCheckedEvent({ runId, context, key }));
|
|
2175
|
+
if (decision.effect === "limit") {
|
|
2176
|
+
await this.auditSink.write(
|
|
2177
|
+
governanceAudit.createQuotaLimitedEvent({ runId, context, key, reason: decision.reason })
|
|
2178
|
+
);
|
|
2179
|
+
}
|
|
2180
|
+
if (decision.effect === "block") {
|
|
2181
|
+
await this.auditSink.write(
|
|
2182
|
+
governanceAudit.createQuotaExceededEvent({ runId, context, key, reason: decision.reason })
|
|
2183
|
+
);
|
|
2184
|
+
throw new governanceCore.PolicyBlockedError({
|
|
2185
|
+
runId,
|
|
2186
|
+
context,
|
|
2187
|
+
reason: decision.reason,
|
|
2188
|
+
policyCode: decision.code
|
|
2189
|
+
});
|
|
2190
|
+
}
|
|
2191
|
+
span.setStatus("ok");
|
|
2192
|
+
return decision;
|
|
2193
|
+
} catch (error) {
|
|
2194
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
2195
|
+
span.setStatus("error", error instanceof Error ? error.message : "Quota check failed");
|
|
2196
|
+
throw error;
|
|
2197
|
+
} finally {
|
|
2198
|
+
span.end();
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
async commitQuota(runId, context, usage) {
|
|
2202
|
+
if (!this.quotaManager) {
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
const key = this.toQuotaKey(context);
|
|
2206
|
+
await this.quotaManager.commit(key, {
|
|
2207
|
+
tokensIn: usage.inputTokens ?? usage.promptTokens,
|
|
2208
|
+
tokensOut: usage.outputTokens ?? usage.completionTokens,
|
|
2209
|
+
usd: usage.costUsd
|
|
2210
|
+
});
|
|
2211
|
+
await this.auditSink.write(governanceAudit.createQuotaCommittedEvent({ runId, context, key }));
|
|
2212
|
+
}
|
|
2213
|
+
async evaluateOutput(runId, context, outputContent, evaluatorsOverride, surface = "model") {
|
|
2214
|
+
const evaluators = evaluatorsOverride ?? this.evaluators;
|
|
2215
|
+
if (!evaluators || evaluators.length === 0) {
|
|
2216
|
+
return void 0;
|
|
2217
|
+
}
|
|
2218
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.EVALUATION_RUN, {
|
|
2219
|
+
"arelis.run.id": runId,
|
|
2220
|
+
"arelis.evaluation.surface": surface,
|
|
2221
|
+
...this.telemetry.contextAttributes(context)
|
|
2222
|
+
});
|
|
2223
|
+
const evaluationInput = {
|
|
2224
|
+
runId,
|
|
2225
|
+
context,
|
|
2226
|
+
surface,
|
|
2227
|
+
outputRef: governanceAudit.createInlineRef(outputContent)
|
|
2228
|
+
};
|
|
2229
|
+
try {
|
|
2230
|
+
const results = await governanceEvaluations.runEvaluations(evaluators, evaluationInput);
|
|
2231
|
+
for (const result of results.results) {
|
|
2232
|
+
const maxSeverity = result.findings.reduce((acc, finding) => {
|
|
2233
|
+
const order = {
|
|
2234
|
+
info: 0,
|
|
2235
|
+
low: 1,
|
|
2236
|
+
medium: 2,
|
|
2237
|
+
high: 3,
|
|
2238
|
+
critical: 4
|
|
2239
|
+
};
|
|
2240
|
+
const currentRank = order[finding.severity] ?? 0;
|
|
2241
|
+
const accRank = acc ? order[acc] ?? 0 : -1;
|
|
2242
|
+
return currentRank > accRank ? finding.severity : acc;
|
|
2243
|
+
}, void 0);
|
|
2244
|
+
await this.auditSink.write(
|
|
2245
|
+
governanceAudit.createEvaluationRunEvent({
|
|
2246
|
+
runId,
|
|
2247
|
+
context,
|
|
2248
|
+
evaluatorId: result.evaluatorId,
|
|
2249
|
+
version: result.version
|
|
2250
|
+
})
|
|
2251
|
+
);
|
|
2252
|
+
await this.auditSink.write(
|
|
2253
|
+
governanceAudit.createEvaluationResultEvent({
|
|
2254
|
+
runId,
|
|
2255
|
+
context,
|
|
2256
|
+
evaluatorId: result.evaluatorId,
|
|
2257
|
+
version: result.version,
|
|
2258
|
+
effect: result.effect,
|
|
2259
|
+
findingCount: result.findings.length,
|
|
2260
|
+
maxSeverity
|
|
2261
|
+
})
|
|
2262
|
+
);
|
|
2263
|
+
if (result.effect === "warn") {
|
|
2264
|
+
await this.auditSink.write(
|
|
2265
|
+
governanceAudit.createEvaluationWarningEvent({
|
|
2266
|
+
runId,
|
|
2267
|
+
context,
|
|
2268
|
+
evaluatorId: result.evaluatorId,
|
|
2269
|
+
message: "Evaluation produced warnings"
|
|
2270
|
+
})
|
|
2271
|
+
);
|
|
2272
|
+
}
|
|
2273
|
+
if (result.effect === "block") {
|
|
2274
|
+
await this.auditSink.write(
|
|
2275
|
+
governanceAudit.createEvaluationBlockedEvent({
|
|
2276
|
+
runId,
|
|
2277
|
+
context,
|
|
2278
|
+
evaluatorId: result.evaluatorId,
|
|
2279
|
+
reason: "Evaluation blocked"
|
|
2280
|
+
})
|
|
2281
|
+
);
|
|
2282
|
+
throw new governanceCore.EvaluationBlockedError({
|
|
2283
|
+
runId,
|
|
2284
|
+
context,
|
|
2285
|
+
evaluatorId: result.evaluatorId,
|
|
2286
|
+
reason: "Evaluation blocked output"
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
span.setStatus("ok");
|
|
2291
|
+
return results;
|
|
2292
|
+
} catch (error) {
|
|
2293
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
2294
|
+
span.setStatus("error", error instanceof Error ? error.message : "Evaluation failed");
|
|
2295
|
+
throw error;
|
|
2296
|
+
} finally {
|
|
2297
|
+
span.end();
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
async validateOutputSchema(schema, outputContent, mode, runId, context) {
|
|
2301
|
+
if (!schema) {
|
|
2302
|
+
return void 0;
|
|
2303
|
+
}
|
|
2304
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.OUTPUT_VALIDATE, {
|
|
2305
|
+
"arelis.run.id": runId,
|
|
2306
|
+
"arelis.schema.type": schema.type,
|
|
2307
|
+
...this.telemetry.contextAttributes(context)
|
|
2308
|
+
});
|
|
2309
|
+
await this.auditSink.write(
|
|
2310
|
+
governanceAudit.createOutputValidationStartedEvent({
|
|
2311
|
+
runId,
|
|
2312
|
+
context,
|
|
2313
|
+
schemaType: schema.type
|
|
2314
|
+
})
|
|
2315
|
+
);
|
|
2316
|
+
let valid = false;
|
|
2317
|
+
let error;
|
|
2318
|
+
try {
|
|
2319
|
+
let data = outputContent;
|
|
2320
|
+
if (schema.type === "jsonSchema" || schema.type === "zod") {
|
|
2321
|
+
data = typeof outputContent === "string" ? JSON.parse(outputContent) : outputContent;
|
|
2322
|
+
}
|
|
2323
|
+
if (schema.type === "jsonSchema") {
|
|
2324
|
+
error = this.validateJsonSchema(schema.schema, data);
|
|
2325
|
+
valid = !error;
|
|
2326
|
+
} else if (schema.type === "zod") {
|
|
2327
|
+
const result = schema.schema.safeParse(data);
|
|
2328
|
+
valid = result.success;
|
|
2329
|
+
if (!result.success) {
|
|
2330
|
+
error = result.error?.message ?? "Zod validation failed";
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
} catch (err) {
|
|
2334
|
+
error = err instanceof Error ? err.message : "Invalid JSON output";
|
|
2335
|
+
valid = false;
|
|
2336
|
+
}
|
|
2337
|
+
if (valid) {
|
|
2338
|
+
await this.auditSink.write(
|
|
2339
|
+
governanceAudit.createOutputValidationPassedEvent({
|
|
2340
|
+
runId,
|
|
2341
|
+
context,
|
|
2342
|
+
schemaType: schema.type
|
|
2343
|
+
})
|
|
2344
|
+
);
|
|
2345
|
+
span.setStatus("ok");
|
|
2346
|
+
span.end();
|
|
2347
|
+
return void 0;
|
|
2348
|
+
}
|
|
2349
|
+
await this.auditSink.write(
|
|
2350
|
+
governanceAudit.createOutputValidationFailedEvent({
|
|
2351
|
+
runId,
|
|
2352
|
+
context,
|
|
2353
|
+
schemaType: schema.type,
|
|
2354
|
+
error: error ?? "Validation failed"
|
|
2355
|
+
})
|
|
2356
|
+
);
|
|
2357
|
+
span.setStatus("error", error ?? "Validation failed");
|
|
2358
|
+
span.end();
|
|
2359
|
+
if (mode === "block") {
|
|
2360
|
+
throw new Error(`Output validation failed: ${error ?? "Invalid output"}`);
|
|
2361
|
+
}
|
|
2362
|
+
return { warning: `Output validation failed: ${error ?? "Invalid output"}` };
|
|
2363
|
+
}
|
|
2364
|
+
validateJsonSchema(schema, data) {
|
|
2365
|
+
const schemaType = schema["type"];
|
|
2366
|
+
if (!schemaType) {
|
|
2367
|
+
return void 0;
|
|
2368
|
+
}
|
|
2369
|
+
if (schemaType === "object") {
|
|
2370
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
2371
|
+
return "Expected object";
|
|
2372
|
+
}
|
|
2373
|
+
const required = schema["required"] ?? [];
|
|
2374
|
+
for (const key of required) {
|
|
2375
|
+
if (!(key in data)) {
|
|
2376
|
+
return `Missing required property: ${key}`;
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
const properties = schema["properties"];
|
|
2380
|
+
if (properties) {
|
|
2381
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
2382
|
+
if (propSchema?.type && key in data) {
|
|
2383
|
+
const value = data[key];
|
|
2384
|
+
if (!this.matchesType(propSchema.type, value)) {
|
|
2385
|
+
return `Invalid type for ${key}`;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
return void 0;
|
|
2391
|
+
}
|
|
2392
|
+
if (!this.matchesType(schemaType, data)) {
|
|
2393
|
+
return `Expected ${schemaType}`;
|
|
2394
|
+
}
|
|
2395
|
+
return void 0;
|
|
2396
|
+
}
|
|
2397
|
+
matchesType(type, value) {
|
|
2398
|
+
switch (type) {
|
|
2399
|
+
case "string":
|
|
2400
|
+
return typeof value === "string";
|
|
2401
|
+
case "number":
|
|
2402
|
+
return typeof value === "number";
|
|
2403
|
+
case "boolean":
|
|
2404
|
+
return typeof value === "boolean";
|
|
2405
|
+
case "array":
|
|
2406
|
+
return Array.isArray(value);
|
|
2407
|
+
case "object":
|
|
2408
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2409
|
+
default:
|
|
2410
|
+
return true;
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
getDefaultMemoryProvider() {
|
|
2414
|
+
const providers = this.memoryRegistry.list();
|
|
2415
|
+
if (providers.length === 0) {
|
|
2416
|
+
throw new Error("No memory providers registered");
|
|
2417
|
+
}
|
|
2418
|
+
return providers[0];
|
|
2419
|
+
}
|
|
2420
|
+
async readMemory(input) {
|
|
2421
|
+
const runId = governanceCore.generateRunId();
|
|
2422
|
+
const context = await this.contextResolver(input.context);
|
|
2423
|
+
const provider = input.providerId ? this.memoryRegistry.get(input.providerId) ?? this.getDefaultMemoryProvider() : this.getDefaultMemoryProvider();
|
|
2424
|
+
const policyResult = await this.evaluatePolicy("BeforePrompt", runId, context, {
|
|
2425
|
+
input: {
|
|
2426
|
+
memory: {
|
|
2427
|
+
providerId: provider.id,
|
|
2428
|
+
scope: input.scope,
|
|
2429
|
+
key: input.key
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
});
|
|
2433
|
+
await this.auditSink.write(
|
|
2434
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
2435
|
+
runId,
|
|
2436
|
+
context,
|
|
2437
|
+
checkpoint: "BeforePrompt",
|
|
2438
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
2439
|
+
allowed: policyResult.summary.allowed,
|
|
2440
|
+
policyVersion: policyResult.policyVersion
|
|
2441
|
+
})
|
|
2442
|
+
);
|
|
2443
|
+
if (!policyResult.summary.allowed) {
|
|
2444
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
2445
|
+
}
|
|
2446
|
+
const entry = await provider.read(input.scope, input.key, { runId, governance: context });
|
|
2447
|
+
await this.auditSink.write(
|
|
2448
|
+
governanceAudit.createMemoryReadEvent({
|
|
2449
|
+
runId,
|
|
2450
|
+
context,
|
|
2451
|
+
memory: { providerId: provider.id, scope: input.scope, key: input.key }
|
|
2452
|
+
})
|
|
2453
|
+
);
|
|
2454
|
+
return entry;
|
|
2455
|
+
}
|
|
2456
|
+
async writeMemory(input) {
|
|
2457
|
+
const runId = governanceCore.generateRunId();
|
|
2458
|
+
const context = await this.contextResolver(input.context);
|
|
2459
|
+
const provider = input.providerId ? this.memoryRegistry.get(input.providerId) ?? this.getDefaultMemoryProvider() : this.getDefaultMemoryProvider();
|
|
2460
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.MEMORY_WRITE, {
|
|
2461
|
+
"arelis.run.id": runId,
|
|
2462
|
+
"arelis.memory.provider": provider.id,
|
|
2463
|
+
"arelis.memory.scope": input.scope,
|
|
2464
|
+
"arelis.memory.key": input.key,
|
|
2465
|
+
...this.telemetry.contextAttributes(context)
|
|
2466
|
+
});
|
|
2467
|
+
try {
|
|
2468
|
+
const policyResult = await this.evaluatePolicy("BeforePersist", runId, context, {
|
|
2469
|
+
input: input.value
|
|
2470
|
+
});
|
|
2471
|
+
if (!policyResult.summary.allowed) {
|
|
2472
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
2473
|
+
}
|
|
2474
|
+
await this.auditSink.write(
|
|
2475
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
2476
|
+
runId,
|
|
2477
|
+
context,
|
|
2478
|
+
checkpoint: "BeforePersist",
|
|
2479
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
2480
|
+
allowed: true,
|
|
2481
|
+
policyVersion: policyResult.policyVersion
|
|
2482
|
+
})
|
|
2483
|
+
);
|
|
2484
|
+
const entry = await provider.write(
|
|
2485
|
+
input.scope,
|
|
2486
|
+
input.key,
|
|
2487
|
+
input.value,
|
|
2488
|
+
{ runId, governance: context },
|
|
2489
|
+
input.metadata
|
|
2490
|
+
);
|
|
2491
|
+
await this.auditSink.write(
|
|
2492
|
+
governanceAudit.createMemoryWriteEvent({
|
|
2493
|
+
runId,
|
|
2494
|
+
context,
|
|
2495
|
+
memory: { providerId: provider.id, scope: input.scope, key: input.key },
|
|
2496
|
+
valueRef: governanceAudit.createHashRef(JSON.stringify(input.value ?? ""))
|
|
2497
|
+
})
|
|
2498
|
+
);
|
|
2499
|
+
span.setStatus("ok");
|
|
2500
|
+
return entry;
|
|
2501
|
+
} catch (error) {
|
|
2502
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
2503
|
+
span.setStatus("error", error instanceof Error ? error.message : "Memory write failed");
|
|
2504
|
+
throw error;
|
|
2505
|
+
} finally {
|
|
2506
|
+
span.end();
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
async deleteMemory(input) {
|
|
2510
|
+
const runId = governanceCore.generateRunId();
|
|
2511
|
+
const context = await this.contextResolver(input.context);
|
|
2512
|
+
const provider = input.providerId ? this.memoryRegistry.get(input.providerId) ?? this.getDefaultMemoryProvider() : this.getDefaultMemoryProvider();
|
|
2513
|
+
const policyResult = await this.evaluatePolicy("BeforePersist", runId, context, {
|
|
2514
|
+
input: {
|
|
2515
|
+
memory: {
|
|
2516
|
+
providerId: provider.id,
|
|
2517
|
+
scope: input.scope,
|
|
2518
|
+
key: input.key
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
});
|
|
2522
|
+
await this.auditSink.write(
|
|
2523
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
2524
|
+
runId,
|
|
2525
|
+
context,
|
|
2526
|
+
checkpoint: "BeforePersist",
|
|
2527
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
2528
|
+
allowed: policyResult.summary.allowed,
|
|
2529
|
+
policyVersion: policyResult.policyVersion
|
|
2530
|
+
})
|
|
2531
|
+
);
|
|
2532
|
+
if (!policyResult.summary.allowed) {
|
|
2533
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
2534
|
+
}
|
|
2535
|
+
const result = await provider.delete(input.scope, input.key, { runId, governance: context });
|
|
2536
|
+
await this.auditSink.write(
|
|
2537
|
+
governanceAudit.createMemoryDeleteEvent({
|
|
2538
|
+
runId,
|
|
2539
|
+
context,
|
|
2540
|
+
memory: { providerId: provider.id, scope: input.scope, key: input.key }
|
|
2541
|
+
})
|
|
2542
|
+
);
|
|
2543
|
+
return result;
|
|
2544
|
+
}
|
|
2545
|
+
async readDataSource(input) {
|
|
2546
|
+
const runId = governanceCore.generateRunId();
|
|
2547
|
+
const context = await this.contextResolver(input.context);
|
|
2548
|
+
const entry = this.dataSourceRegistry.get(input.sourceId);
|
|
2549
|
+
if (!entry) {
|
|
2550
|
+
throw new Error(`Data source not found: ${input.sourceId}`);
|
|
2551
|
+
}
|
|
2552
|
+
const span = this.telemetry.startSpan(governanceTelemetryOtel.SpanNames.DATA_READ, {
|
|
2553
|
+
"arelis.run.id": runId,
|
|
2554
|
+
"arelis.data.source": entry.descriptor.id,
|
|
2555
|
+
...this.telemetry.contextAttributes(context)
|
|
2556
|
+
});
|
|
2557
|
+
try {
|
|
2558
|
+
await this.auditSink.write(
|
|
2559
|
+
governanceAudit.createDataReadEvent({
|
|
2560
|
+
runId,
|
|
2561
|
+
context,
|
|
2562
|
+
source: {
|
|
2563
|
+
id: entry.descriptor.id,
|
|
2564
|
+
provider: entry.descriptor.provider,
|
|
2565
|
+
region: entry.descriptor.region
|
|
2566
|
+
},
|
|
2567
|
+
queryRef: governanceAudit.createHashRef(input.query)
|
|
2568
|
+
})
|
|
2569
|
+
);
|
|
2570
|
+
const policyResult = await this.evaluatePolicy("BeforePrompt", runId, context, {
|
|
2571
|
+
input: input.query
|
|
2572
|
+
});
|
|
2573
|
+
if (!policyResult.summary.allowed) {
|
|
2574
|
+
await this.auditSink.write(
|
|
2575
|
+
governanceAudit.createDataBlockedEvent({
|
|
2576
|
+
runId,
|
|
2577
|
+
context,
|
|
2578
|
+
source: {
|
|
2579
|
+
id: entry.descriptor.id,
|
|
2580
|
+
provider: entry.descriptor.provider,
|
|
2581
|
+
region: entry.descriptor.region
|
|
2582
|
+
},
|
|
2583
|
+
reason: policyResult.summary.blockReason ?? "Data blocked"
|
|
2584
|
+
})
|
|
2585
|
+
);
|
|
2586
|
+
throw await this.createPolicyError(policyResult, runId, context);
|
|
2587
|
+
}
|
|
2588
|
+
await this.auditSink.write(
|
|
2589
|
+
this.createPolicyEvaluatedEventWithMetadata({
|
|
2590
|
+
runId,
|
|
2591
|
+
context,
|
|
2592
|
+
checkpoint: "BeforePrompt",
|
|
2593
|
+
decisions: toAuditDecisions(policyResult.decisions),
|
|
2594
|
+
allowed: true,
|
|
2595
|
+
policyVersion: policyResult.policyVersion
|
|
2596
|
+
})
|
|
2597
|
+
);
|
|
2598
|
+
const transformed = policyResult.decisions.find((d) => d.effect === "transform");
|
|
2599
|
+
if (transformed) {
|
|
2600
|
+
await this.auditSink.write(
|
|
2601
|
+
governanceAudit.createDataFilteredEvent({
|
|
2602
|
+
runId,
|
|
2603
|
+
context,
|
|
2604
|
+
source: {
|
|
2605
|
+
id: entry.descriptor.id,
|
|
2606
|
+
provider: entry.descriptor.provider,
|
|
2607
|
+
region: entry.descriptor.region
|
|
2608
|
+
},
|
|
2609
|
+
reason: transformed.reason ?? "Data filtered by policy"
|
|
2610
|
+
})
|
|
2611
|
+
);
|
|
2612
|
+
}
|
|
2613
|
+
const result = await entry.provider.read(
|
|
2614
|
+
{ sourceId: input.sourceId, query: input.query, metadata: input.metadata },
|
|
2615
|
+
{ runId, governance: context }
|
|
2616
|
+
);
|
|
2617
|
+
span.setStatus("ok");
|
|
2618
|
+
return result;
|
|
2619
|
+
} catch (error) {
|
|
2620
|
+
span.recordError(error instanceof Error ? error : new Error(String(error)));
|
|
2621
|
+
span.setStatus("error", error instanceof Error ? error.message : "Data read failed");
|
|
2622
|
+
throw error;
|
|
2623
|
+
} finally {
|
|
2624
|
+
span.end();
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
async approveRequest(input) {
|
|
2628
|
+
const context = await this.contextResolver(input.context);
|
|
2629
|
+
await this.approvalStore.approve(input.approvalId, input.resolvedBy, input.reason);
|
|
2630
|
+
await this.auditSink.write(
|
|
2631
|
+
governanceAudit.createApprovalGrantedEvent({
|
|
2632
|
+
runId: governanceCore.generateRunId(),
|
|
2633
|
+
context,
|
|
2634
|
+
approvalId: input.approvalId,
|
|
2635
|
+
resolvedBy: input.resolvedBy,
|
|
2636
|
+
reason: input.reason
|
|
2637
|
+
})
|
|
2638
|
+
);
|
|
2639
|
+
}
|
|
2640
|
+
async rejectRequest(input) {
|
|
2641
|
+
const context = await this.contextResolver(input.context);
|
|
2642
|
+
await this.approvalStore.reject(input.approvalId, input.resolvedBy, input.reason);
|
|
2643
|
+
await this.auditSink.write(
|
|
2644
|
+
governanceAudit.createApprovalRejectedEvent({
|
|
2645
|
+
runId: governanceCore.generateRunId(),
|
|
2646
|
+
context,
|
|
2647
|
+
approvalId: input.approvalId,
|
|
2648
|
+
resolvedBy: input.resolvedBy,
|
|
2649
|
+
reason: input.reason
|
|
2650
|
+
})
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
2653
|
+
async runEvaluations(input, evaluatorsOverride) {
|
|
2654
|
+
const evaluators = evaluatorsOverride ?? this.evaluators;
|
|
2655
|
+
return governanceEvaluations.runEvaluations(evaluators, input);
|
|
2656
|
+
}
|
|
2657
|
+
async ensureMCPTransport(server, context, runId) {
|
|
2658
|
+
if (this.mcpRegistry.getTransport(server.id)) {
|
|
2659
|
+
return;
|
|
2660
|
+
}
|
|
2661
|
+
if (server.transport.type === "stdio") {
|
|
2662
|
+
const env = { ...server.transport.env ?? {} };
|
|
2663
|
+
if (server.auth && server.auth.type !== "none") {
|
|
2664
|
+
const resolved = await governanceSecrets.resolveSecretValue(this.secretResolver, server.auth.valueRef, {
|
|
2665
|
+
context,
|
|
2666
|
+
runId
|
|
2667
|
+
});
|
|
2668
|
+
env["ARELIS_MCP_AUTH"] = resolved.value;
|
|
2669
|
+
await this.auditSink.write(
|
|
2670
|
+
governanceAudit.createSecretResolvedEvent({
|
|
2671
|
+
runId,
|
|
2672
|
+
context,
|
|
2673
|
+
ref: server.auth.valueRef,
|
|
2674
|
+
resolverId: resolved.resolution.resolverId
|
|
2675
|
+
})
|
|
2676
|
+
);
|
|
2677
|
+
}
|
|
2678
|
+
const transport = governanceMcp.createStdioMCPTransport({
|
|
2679
|
+
...server.transport,
|
|
2680
|
+
env
|
|
2681
|
+
});
|
|
2682
|
+
this.mcpRegistry.setTransport(server.id, transport);
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
if (server.transport.type === "http") {
|
|
2686
|
+
const headers = { ...server.transport.headers ?? {} };
|
|
2687
|
+
if (server.auth && server.auth.type !== "none") {
|
|
2688
|
+
const resolved = await governanceSecrets.resolveSecretValue(this.secretResolver, server.auth.valueRef, {
|
|
2689
|
+
context,
|
|
2690
|
+
runId
|
|
2691
|
+
});
|
|
2692
|
+
if (server.auth.type === "bearer") {
|
|
2693
|
+
headers["Authorization"] = `Bearer ${resolved.value}`;
|
|
2694
|
+
} else if (server.auth.type === "apiKey") {
|
|
2695
|
+
headers[server.auth.headerName ?? "x-api-key"] = resolved.value;
|
|
2696
|
+
}
|
|
2697
|
+
await this.auditSink.write(
|
|
2698
|
+
governanceAudit.createSecretResolvedEvent({
|
|
2699
|
+
runId,
|
|
2700
|
+
context,
|
|
2701
|
+
ref: server.auth.valueRef,
|
|
2702
|
+
resolverId: resolved.resolution.resolverId
|
|
2703
|
+
})
|
|
2704
|
+
);
|
|
2705
|
+
}
|
|
2706
|
+
const transport = governanceMcp.createHttpMCPTransport({
|
|
2707
|
+
...server.transport,
|
|
2708
|
+
headers
|
|
2709
|
+
});
|
|
2710
|
+
this.mcpRegistry.setTransport(server.id, transport);
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
/**
|
|
2714
|
+
* Merge multiple policy summaries
|
|
2715
|
+
*/
|
|
2716
|
+
mergePolicySummaries(summaries) {
|
|
2717
|
+
const merged = {
|
|
2718
|
+
evaluated: 0,
|
|
2719
|
+
allowed: 0,
|
|
2720
|
+
blocked: 0,
|
|
2721
|
+
transformed: 0
|
|
2722
|
+
};
|
|
2723
|
+
const allReasons = [];
|
|
2724
|
+
for (const summary of summaries) {
|
|
2725
|
+
merged.evaluated += summary.evaluated;
|
|
2726
|
+
merged.allowed += summary.allowed;
|
|
2727
|
+
merged.blocked += summary.blocked;
|
|
2728
|
+
merged.transformed += summary.transformed;
|
|
2729
|
+
if (summary.reasons) {
|
|
2730
|
+
allReasons.push(...summary.reasons);
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
if (allReasons.length > 0) {
|
|
2734
|
+
merged.reasons = allReasons;
|
|
2735
|
+
}
|
|
2736
|
+
return merged;
|
|
2737
|
+
}
|
|
2738
|
+
};
|
|
2739
|
+
function createArelisClient(config) {
|
|
2740
|
+
return new ArelisClient(config);
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
// src/platform/platform-client.ts
|
|
2744
|
+
var ArelisApiError = class extends Error {
|
|
2745
|
+
type;
|
|
2746
|
+
title;
|
|
2747
|
+
status;
|
|
2748
|
+
detail;
|
|
2749
|
+
instance;
|
|
2750
|
+
constructor(opts) {
|
|
2751
|
+
super(opts.detail);
|
|
2752
|
+
this.name = "ArelisApiError";
|
|
2753
|
+
this.type = opts.type;
|
|
2754
|
+
this.title = opts.title;
|
|
2755
|
+
this.status = opts.status;
|
|
2756
|
+
this.detail = opts.detail;
|
|
2757
|
+
this.instance = opts.instance;
|
|
2758
|
+
}
|
|
2759
|
+
};
|
|
2760
|
+
var INITIAL_BACKOFF_MS = 500;
|
|
2761
|
+
var MAX_BACKOFF_MS = 3e4;
|
|
2762
|
+
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
2763
|
+
function isRetryableError(error) {
|
|
2764
|
+
if (error instanceof ArelisApiError) {
|
|
2765
|
+
return RETRYABLE_STATUS_CODES.has(error.status);
|
|
2766
|
+
}
|
|
2767
|
+
return error instanceof TypeError;
|
|
2768
|
+
}
|
|
2769
|
+
function buildQueryString(params) {
|
|
2770
|
+
const entries = [];
|
|
2771
|
+
for (const [key, value] of Object.entries(params)) {
|
|
2772
|
+
if (value !== void 0 && value !== null) {
|
|
2773
|
+
entries.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
return entries.length > 0 ? `?${entries.join("&")}` : "";
|
|
2777
|
+
}
|
|
2778
|
+
var ArelisPlatform = class {
|
|
2779
|
+
baseUrl;
|
|
2780
|
+
apiKey;
|
|
2781
|
+
token;
|
|
2782
|
+
maxRetries;
|
|
2783
|
+
timeout;
|
|
2784
|
+
events;
|
|
2785
|
+
proofs;
|
|
2786
|
+
risk;
|
|
2787
|
+
replay;
|
|
2788
|
+
graphs;
|
|
2789
|
+
governance;
|
|
2790
|
+
apiKeys;
|
|
2791
|
+
usage;
|
|
2792
|
+
jobs;
|
|
2793
|
+
organization;
|
|
2794
|
+
quotas;
|
|
2795
|
+
billing;
|
|
2796
|
+
metering;
|
|
2797
|
+
telemetry;
|
|
2798
|
+
exports;
|
|
2799
|
+
namespaces;
|
|
2800
|
+
approvals;
|
|
2801
|
+
aiSystems;
|
|
2802
|
+
mcpServers;
|
|
2803
|
+
constructor(config) {
|
|
2804
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
2805
|
+
this.apiKey = config.apiKey;
|
|
2806
|
+
this.token = config.token;
|
|
2807
|
+
this.maxRetries = config.maxRetries ?? 3;
|
|
2808
|
+
this.timeout = config.timeout ?? 3e4;
|
|
2809
|
+
this.events = {
|
|
2810
|
+
create: (event) => this.request("POST", "/api/v1/events", event),
|
|
2811
|
+
createBatch: (input) => this.request("POST", "/api/v1/events/batch", input),
|
|
2812
|
+
list: (params) => {
|
|
2813
|
+
const qs = buildQueryString(params);
|
|
2814
|
+
return this.request("GET", `/api/v1/events${qs}`);
|
|
2815
|
+
},
|
|
2816
|
+
get: (eventId) => this.request("GET", `/api/v1/events/${eventId}`),
|
|
2817
|
+
count: (params) => {
|
|
2818
|
+
const qs = buildQueryString(params ?? {});
|
|
2819
|
+
return this.request("GET", `/api/v1/events/count${qs}`);
|
|
2820
|
+
}
|
|
2821
|
+
};
|
|
2822
|
+
this.proofs = {
|
|
2823
|
+
create: (req) => this.request("POST", "/api/v1/proofs", req),
|
|
2824
|
+
get: (proofId) => this.request("GET", `/api/v1/proofs/${proofId}`),
|
|
2825
|
+
verify: (input) => this.request("POST", "/api/v1/proofs/verify", input),
|
|
2826
|
+
list: (params) => {
|
|
2827
|
+
const qs = buildQueryString(params ?? {});
|
|
2828
|
+
return this.request("GET", `/api/v1/proofs${qs}`);
|
|
2829
|
+
}
|
|
2830
|
+
};
|
|
2831
|
+
this.risk = {
|
|
2832
|
+
evaluate: (input) => this.request("POST", "/api/v1/risk/evaluate", input),
|
|
2833
|
+
getConfig: () => this.request("GET", "/api/v1/risk/config"),
|
|
2834
|
+
updateConfig: (config2) => this.request("PUT", "/api/v1/risk/config", config2),
|
|
2835
|
+
listDecisions: (params) => {
|
|
2836
|
+
const qs = buildQueryString(params ?? {});
|
|
2837
|
+
return this.request("GET", `/api/v1/risk/decisions${qs}`);
|
|
2838
|
+
},
|
|
2839
|
+
simulate: (input) => this.request("POST", "/api/v1/risk/simulate", input),
|
|
2840
|
+
getConfigVersions: () => this.request(
|
|
2841
|
+
"GET",
|
|
2842
|
+
"/api/v1/risk/config/versions"
|
|
2843
|
+
),
|
|
2844
|
+
saveDraft: (input) => this.request("POST", "/api/v1/risk/config/draft", input),
|
|
2845
|
+
clearDraft: () => this.request("DELETE", "/api/v1/risk/config/draft"),
|
|
2846
|
+
publishDraft: (input) => this.request("POST", "/api/v1/risk/config/publish", input),
|
|
2847
|
+
rollbackConfig: (input) => this.request(
|
|
2848
|
+
"POST",
|
|
2849
|
+
"/api/v1/risk/config/rollback",
|
|
2850
|
+
input
|
|
2851
|
+
)
|
|
2852
|
+
};
|
|
2853
|
+
this.replay = {
|
|
2854
|
+
start: (req) => this.request("POST", "/api/v1/replay", req),
|
|
2855
|
+
startCausalGraph: (req) => this.request("POST", "/api/v1/replay/causal-graph", req),
|
|
2856
|
+
get: (replayId) => this.request("GET", `/api/v1/replay/${replayId}`),
|
|
2857
|
+
list: (params) => {
|
|
2858
|
+
const qs = buildQueryString(params ?? {});
|
|
2859
|
+
return this.request("GET", `/api/v1/replay${qs}`);
|
|
2860
|
+
},
|
|
2861
|
+
createTemplate: (input) => this.request("POST", "/api/v1/replay/templates", input),
|
|
2862
|
+
listTemplates: (params) => {
|
|
2863
|
+
const qs = buildQueryString(params ?? {});
|
|
2864
|
+
return this.request("GET", `/api/v1/replay/templates${qs}`);
|
|
2865
|
+
},
|
|
2866
|
+
getTemplate: (templateId) => this.request("GET", `/api/v1/replay/templates/${templateId}`),
|
|
2867
|
+
updateTemplate: (templateId, input) => this.request("PUT", `/api/v1/replay/templates/${templateId}`, input),
|
|
2868
|
+
deleteTemplate: (templateId) => this.request("DELETE", `/api/v1/replay/templates/${templateId}`),
|
|
2869
|
+
compare: (input) => this.request("POST", "/api/v1/replay/compare", input)
|
|
2870
|
+
};
|
|
2871
|
+
this.graphs = {
|
|
2872
|
+
list: (params) => {
|
|
2873
|
+
const qs = buildQueryString(params ?? {});
|
|
2874
|
+
return this.request("GET", `/api/v1/graphs${qs}`);
|
|
2875
|
+
},
|
|
2876
|
+
get: (runId) => this.request("GET", `/api/v1/graphs/${runId}`),
|
|
2877
|
+
commit: (runId) => this.request("POST", `/api/v1/graphs/${runId}/commit`),
|
|
2878
|
+
lineage: (runId, nodeId) => {
|
|
2879
|
+
const qs = nodeId ? buildQueryString({ nodeId }) : "";
|
|
2880
|
+
return this.request("GET", `/api/v1/graphs/${runId}/lineage${qs}`);
|
|
2881
|
+
}
|
|
2882
|
+
};
|
|
2883
|
+
this.governance = {
|
|
2884
|
+
evaluatePolicy: (input) => this.request("POST", "/api/v1/governance/policy/evaluate", input),
|
|
2885
|
+
listPolicyEvaluations: (params) => {
|
|
2886
|
+
const qs = buildQueryString(params ?? {});
|
|
2887
|
+
return this.request(
|
|
2888
|
+
"GET",
|
|
2889
|
+
`/api/v1/governance/policy/evaluations${qs}`
|
|
2890
|
+
);
|
|
2891
|
+
},
|
|
2892
|
+
getSnapshot: (runId, params) => {
|
|
2893
|
+
const qs = params ? buildQueryString(params) : "";
|
|
2894
|
+
return this.request(
|
|
2895
|
+
"GET",
|
|
2896
|
+
`/api/v1/governance/snapshots/${runId}${qs}`
|
|
2897
|
+
);
|
|
2898
|
+
},
|
|
2899
|
+
policies: {
|
|
2900
|
+
create: (input) => this.request("POST", "/api/v1/governance/policies", input),
|
|
2901
|
+
list: (params) => {
|
|
2902
|
+
const qs = buildQueryString(params ?? {});
|
|
2903
|
+
return this.request("GET", `/api/v1/governance/policies${qs}`);
|
|
2904
|
+
},
|
|
2905
|
+
get: (policyId) => this.request("GET", `/api/v1/governance/policies/${policyId}`),
|
|
2906
|
+
update: (policyId, input) => this.request("PUT", `/api/v1/governance/policies/${policyId}`, input),
|
|
2907
|
+
delete: (policyId) => this.request("DELETE", `/api/v1/governance/policies/${policyId}`),
|
|
2908
|
+
restore: (policyId) => this.request("POST", `/api/v1/governance/policies/${policyId}/restore`),
|
|
2909
|
+
createVersion: (policyId, input) => this.request(
|
|
2910
|
+
"POST",
|
|
2911
|
+
`/api/v1/governance/policies/${policyId}/versions`,
|
|
2912
|
+
input
|
|
2913
|
+
),
|
|
2914
|
+
listVersions: (policyId) => this.request(
|
|
2915
|
+
"GET",
|
|
2916
|
+
`/api/v1/governance/policies/${policyId}/versions`
|
|
2917
|
+
),
|
|
2918
|
+
activateVersion: (policyId, input) => this.request(
|
|
2919
|
+
"POST",
|
|
2920
|
+
`/api/v1/governance/policies/${policyId}/activate-version`,
|
|
2921
|
+
input
|
|
2922
|
+
),
|
|
2923
|
+
transition: (policyId, input) => this.request(
|
|
2924
|
+
"POST",
|
|
2925
|
+
`/api/v1/governance/policies/${policyId}/transition`,
|
|
2926
|
+
input
|
|
2927
|
+
),
|
|
2928
|
+
rollback: (policyId, input) => this.request(
|
|
2929
|
+
"POST",
|
|
2930
|
+
`/api/v1/governance/policies/${policyId}/rollback`,
|
|
2931
|
+
input
|
|
2932
|
+
),
|
|
2933
|
+
simulate: (policyId, input) => this.request(
|
|
2934
|
+
"POST",
|
|
2935
|
+
`/api/v1/governance/policies/${policyId}/simulate`,
|
|
2936
|
+
input
|
|
2937
|
+
),
|
|
2938
|
+
bulkSimulate: (input) => this.request(
|
|
2939
|
+
"POST",
|
|
2940
|
+
"/api/v1/governance/policies/simulate",
|
|
2941
|
+
input
|
|
2942
|
+
),
|
|
2943
|
+
impact: (policyId, input) => this.request(
|
|
2944
|
+
"POST",
|
|
2945
|
+
`/api/v1/governance/policies/${policyId}/impact`,
|
|
2946
|
+
input
|
|
2947
|
+
)
|
|
2948
|
+
}
|
|
2949
|
+
};
|
|
2950
|
+
this.apiKeys = {
|
|
2951
|
+
create: (input) => this.request("POST", "/api/v1/api-keys", input),
|
|
2952
|
+
list: () => this.request("GET", "/api/v1/api-keys"),
|
|
2953
|
+
update: (keyId, input) => this.request("PUT", `/api/v1/api-keys/${keyId}`, input),
|
|
2954
|
+
revoke: (keyId) => this.request("DELETE", `/api/v1/api-keys/${keyId}`),
|
|
2955
|
+
rotate: (keyId) => this.request("POST", `/api/v1/api-keys/${keyId}/rotate`)
|
|
2956
|
+
};
|
|
2957
|
+
this.usage = {
|
|
2958
|
+
get: () => this.request("GET", "/api/v1/usage"),
|
|
2959
|
+
history: () => this.request("GET", "/api/v1/usage/history")
|
|
2960
|
+
};
|
|
2961
|
+
this.jobs = {
|
|
2962
|
+
list: (params) => {
|
|
2963
|
+
const qs = buildQueryString(params ?? {});
|
|
2964
|
+
return this.request("GET", `/api/v1/jobs${qs}`);
|
|
2965
|
+
},
|
|
2966
|
+
get: (jobId) => this.request("GET", `/api/v1/jobs/${jobId}`),
|
|
2967
|
+
retry: (jobId) => this.request("POST", `/api/v1/jobs/${jobId}/retry`)
|
|
2968
|
+
};
|
|
2969
|
+
this.organization = {
|
|
2970
|
+
get: () => this.request("GET", "/api/v1/organization")
|
|
2971
|
+
};
|
|
2972
|
+
this.quotas = {
|
|
2973
|
+
get: () => this.request("GET", "/api/v1/quotas")
|
|
2974
|
+
};
|
|
2975
|
+
this.billing = {
|
|
2976
|
+
summary: () => this.request("GET", "/api/v1/billing/summary")
|
|
2977
|
+
};
|
|
2978
|
+
this.metering = {
|
|
2979
|
+
getMilestones: () => this.request("GET", "/api/v1/metering/milestones"),
|
|
2980
|
+
updateMilestones: (input) => this.request("PUT", "/api/v1/metering/milestones", input),
|
|
2981
|
+
listMilestoneDeliveries: (params) => {
|
|
2982
|
+
const qs = buildQueryString(params ?? {});
|
|
2983
|
+
return this.request(
|
|
2984
|
+
"GET",
|
|
2985
|
+
`/api/v1/metering/milestones/deliveries${qs}`
|
|
2986
|
+
);
|
|
2987
|
+
}
|
|
2988
|
+
};
|
|
2989
|
+
this.telemetry = {
|
|
2990
|
+
reportUsage: (input) => this.request("POST", "/api/v1/telemetry/usage", input),
|
|
2991
|
+
submitAttestation: (challengeId, input) => this.request("POST", `/api/v1/telemetry/attestations/${challengeId}`, input),
|
|
2992
|
+
listReports: (params) => {
|
|
2993
|
+
const qs = buildQueryString(params ?? {});
|
|
2994
|
+
return this.request("GET", `/api/v1/telemetry/reports${qs}`);
|
|
2995
|
+
},
|
|
2996
|
+
listChallenges: (params) => {
|
|
2997
|
+
const qs = buildQueryString(params ?? {});
|
|
2998
|
+
return this.request(
|
|
2999
|
+
"GET",
|
|
3000
|
+
`/api/v1/telemetry/challenges${qs}`
|
|
3001
|
+
);
|
|
3002
|
+
}
|
|
3003
|
+
};
|
|
3004
|
+
this.exports = {
|
|
3005
|
+
create: (input) => this.request("POST", "/api/v1/exports", input),
|
|
3006
|
+
list: (params) => {
|
|
3007
|
+
const qs = buildQueryString(params ?? {});
|
|
3008
|
+
return this.request("GET", `/api/v1/exports${qs}`);
|
|
3009
|
+
},
|
|
3010
|
+
get: (exportId) => this.request("GET", `/api/v1/exports/${exportId}`),
|
|
3011
|
+
download: (exportId) => this.downloadExportArtifact(exportId)
|
|
3012
|
+
};
|
|
3013
|
+
this.namespaces = {
|
|
3014
|
+
agents: this.buildNamespaceCrud("/api/v1/namespaces/agents"),
|
|
3015
|
+
approvals: this.buildNamespaceCrud("/api/v1/namespaces/approvals"),
|
|
3016
|
+
complianceConfig: this.buildNamespaceCrud("/api/v1/namespaces/compliance-config"),
|
|
3017
|
+
dataSources: this.buildNamespaceCrud("/api/v1/namespaces/data-sources"),
|
|
3018
|
+
evaluations: this.buildNamespaceCrud("/api/v1/namespaces/evaluations"),
|
|
3019
|
+
governanceConfig: this.buildNamespaceCrud("/api/v1/namespaces/governance-config"),
|
|
3020
|
+
knowledge: this.buildNamespaceCrud("/api/v1/namespaces/knowledge"),
|
|
3021
|
+
mcp: {
|
|
3022
|
+
...this.buildNamespaceCrud("/api/v1/namespaces/mcp"),
|
|
3023
|
+
evaluateTool: (input) => this.request("POST", "/api/v1/mcp/tools/evaluate", input),
|
|
3024
|
+
governedInvoke: async (input) => {
|
|
3025
|
+
const { invoke, denyMode, ...evalInput } = input;
|
|
3026
|
+
const decision = await this.request(
|
|
3027
|
+
"POST",
|
|
3028
|
+
"/api/v1/mcp/tools/evaluate",
|
|
3029
|
+
evalInput
|
|
3030
|
+
);
|
|
3031
|
+
const isDenied = decision.decision === "deny" || decision.decision === "escalate";
|
|
3032
|
+
if (isDenied) {
|
|
3033
|
+
if (denyMode === "throw") {
|
|
3034
|
+
throw new ArelisApiError({
|
|
3035
|
+
type: "https://arelis.dev/errors/mcp-tool-denied",
|
|
3036
|
+
title: "MCP Tool Call Denied",
|
|
3037
|
+
status: 403,
|
|
3038
|
+
detail: decision.policy.summary.blockReason ?? "MCP tool call blocked by policy"
|
|
3039
|
+
});
|
|
3040
|
+
}
|
|
3041
|
+
return { runId: decision.runId, invoked: false, decision };
|
|
3042
|
+
}
|
|
3043
|
+
const result = await invoke();
|
|
3044
|
+
return { runId: decision.runId, invoked: true, decision, result };
|
|
3045
|
+
}
|
|
3046
|
+
},
|
|
3047
|
+
memory: this.buildNamespaceCrud("/api/v1/namespaces/memory"),
|
|
3048
|
+
prompts: this.buildNamespaceCrud("/api/v1/namespaces/prompts"),
|
|
3049
|
+
quotas: this.buildNamespaceCrud("/api/v1/namespaces/quotas/config"),
|
|
3050
|
+
secrets: this.buildNamespaceCrud("/api/v1/namespaces/secrets"),
|
|
3051
|
+
telemetry: this.buildNamespaceCrud("/api/v1/namespaces/telemetry"),
|
|
3052
|
+
tools: this.buildNamespaceCrud("/api/v1/namespaces/tools")
|
|
3053
|
+
};
|
|
3054
|
+
this.approvals = {
|
|
3055
|
+
list: (params) => {
|
|
3056
|
+
const qs = buildQueryString(params ?? {});
|
|
3057
|
+
return this.request(
|
|
3058
|
+
"GET",
|
|
3059
|
+
`/api/v1/namespaces/approvals${qs}`
|
|
3060
|
+
);
|
|
3061
|
+
},
|
|
3062
|
+
resolve: (approvalId, input) => this.request(
|
|
3063
|
+
"POST",
|
|
3064
|
+
`/api/v1/approvals/${approvalId}/resolve`,
|
|
3065
|
+
input
|
|
3066
|
+
),
|
|
3067
|
+
getConfig: () => this.request(
|
|
3068
|
+
"GET",
|
|
3069
|
+
"/api/v1/namespaces/approvals"
|
|
3070
|
+
),
|
|
3071
|
+
updateConfig: (input) => this.request(
|
|
3072
|
+
"POST",
|
|
3073
|
+
"/api/v1/namespaces/approvals",
|
|
3074
|
+
input
|
|
3075
|
+
)
|
|
3076
|
+
};
|
|
3077
|
+
this.aiSystems = {
|
|
3078
|
+
register: (input) => this.request("POST", "/api/v1/ai-systems", input),
|
|
3079
|
+
list: (params) => {
|
|
3080
|
+
const qs = buildQueryString(params ?? {});
|
|
3081
|
+
return this.request("GET", `/api/v1/ai-systems${qs}`);
|
|
3082
|
+
},
|
|
3083
|
+
get: (systemId) => this.request("GET", `/api/v1/ai-systems/${systemId}`),
|
|
3084
|
+
update: (systemId, input) => this.request("PUT", `/api/v1/ai-systems/${systemId}`, input),
|
|
3085
|
+
archive: (systemId) => this.request("DELETE", `/api/v1/ai-systems/${systemId}`),
|
|
3086
|
+
setDefault: (systemId) => this.request("POST", `/api/v1/ai-systems/${systemId}/set-default`),
|
|
3087
|
+
summary: (systemId, params) => {
|
|
3088
|
+
const qs = buildQueryString(params ?? {});
|
|
3089
|
+
return this.request(
|
|
3090
|
+
"GET",
|
|
3091
|
+
`/api/v1/ai-systems/${systemId}/summary${qs}`
|
|
3092
|
+
);
|
|
3093
|
+
}
|
|
3094
|
+
};
|
|
3095
|
+
this.mcpServers = {
|
|
3096
|
+
create: (input) => this.request("POST", "/api/v1/mcp-servers", input),
|
|
3097
|
+
list: (params) => {
|
|
3098
|
+
const qs = buildQueryString(params ?? {});
|
|
3099
|
+
return this.request("GET", `/api/v1/mcp-servers${qs}`);
|
|
3100
|
+
},
|
|
3101
|
+
get: (serverId) => this.request("GET", `/api/v1/mcp-servers/${serverId}`),
|
|
3102
|
+
update: (serverId, input) => this.request("PUT", `/api/v1/mcp-servers/${serverId}`, input),
|
|
3103
|
+
archive: (serverId) => this.request("DELETE", `/api/v1/mcp-servers/${serverId}`),
|
|
3104
|
+
createTool: (serverId, input) => this.request(
|
|
3105
|
+
"POST",
|
|
3106
|
+
`/api/v1/mcp-servers/${serverId}/tools`,
|
|
3107
|
+
input
|
|
3108
|
+
),
|
|
3109
|
+
listTools: (serverId, params) => {
|
|
3110
|
+
const qs = buildQueryString(params ?? {});
|
|
3111
|
+
return this.request(
|
|
3112
|
+
"GET",
|
|
3113
|
+
`/api/v1/mcp-servers/${serverId}/tools${qs}`
|
|
3114
|
+
);
|
|
3115
|
+
},
|
|
3116
|
+
updateTool: (serverId, toolName, input) => this.request(
|
|
3117
|
+
"PUT",
|
|
3118
|
+
`/api/v1/mcp-servers/${serverId}/tools/${encodeURIComponent(toolName)}`,
|
|
3119
|
+
input
|
|
3120
|
+
),
|
|
3121
|
+
refreshTools: (serverId) => this.request(
|
|
3122
|
+
"POST",
|
|
3123
|
+
`/api/v1/mcp-servers/${serverId}/refresh-tools`
|
|
3124
|
+
),
|
|
3125
|
+
healthCheck: (serverId) => this.request(
|
|
3126
|
+
"POST",
|
|
3127
|
+
`/api/v1/mcp-servers/${serverId}/health-check`
|
|
3128
|
+
),
|
|
3129
|
+
healthHistory: (serverId, params) => {
|
|
3130
|
+
const qs = buildQueryString(params ?? {});
|
|
3131
|
+
return this.request(
|
|
3132
|
+
"GET",
|
|
3133
|
+
`/api/v1/mcp-servers/${serverId}/health${qs}`
|
|
3134
|
+
);
|
|
3135
|
+
},
|
|
3136
|
+
linkSystem: (serverId, input) => this.request(
|
|
3137
|
+
"POST",
|
|
3138
|
+
`/api/v1/mcp-servers/${serverId}/link`,
|
|
3139
|
+
input
|
|
3140
|
+
),
|
|
3141
|
+
unlinkSystem: (serverId, systemId) => this.request(
|
|
3142
|
+
"DELETE",
|
|
3143
|
+
`/api/v1/mcp-servers/${serverId}/link/${systemId}`
|
|
3144
|
+
),
|
|
3145
|
+
linkedSystems: (serverId) => this.request(
|
|
3146
|
+
"GET",
|
|
3147
|
+
`/api/v1/mcp-servers/${serverId}/systems`
|
|
3148
|
+
)
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
// ---------- Core request with retry logic --------------------------------
|
|
3152
|
+
async request(method, path, body) {
|
|
3153
|
+
const url = `${this.baseUrl}${path}`;
|
|
3154
|
+
let lastError;
|
|
3155
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
3156
|
+
try {
|
|
3157
|
+
const response = await this.fetchWithTimeout(url, method, body);
|
|
3158
|
+
if (response.ok) {
|
|
3159
|
+
return await response.json();
|
|
3160
|
+
}
|
|
3161
|
+
const errorBody = await this.safeParseJson(response);
|
|
3162
|
+
const apiError = new ArelisApiError({
|
|
3163
|
+
type: (typeof errorBody?.["type"] === "string" ? errorBody["type"] : null) ?? `https://arelis.dev/errors/http-${response.status}`,
|
|
3164
|
+
title: (typeof errorBody?.["title"] === "string" ? errorBody["title"] : null) ?? response.statusText,
|
|
3165
|
+
status: response.status,
|
|
3166
|
+
detail: (typeof errorBody?.["detail"] === "string" ? errorBody["detail"] : null) ?? `Request failed with status ${response.status}`,
|
|
3167
|
+
instance: typeof errorBody?.["instance"] === "string" ? errorBody["instance"] : void 0
|
|
3168
|
+
});
|
|
3169
|
+
if (!RETRYABLE_STATUS_CODES.has(response.status) || attempt === this.maxRetries) {
|
|
3170
|
+
throw apiError;
|
|
3171
|
+
}
|
|
3172
|
+
lastError = apiError;
|
|
3173
|
+
const backoff = this.computeBackoff(attempt, response);
|
|
3174
|
+
await this.sleep(backoff);
|
|
3175
|
+
} catch (error) {
|
|
3176
|
+
if (error instanceof ArelisApiError) {
|
|
3177
|
+
if (!isRetryableError(error) || attempt === this.maxRetries) {
|
|
3178
|
+
throw error;
|
|
3179
|
+
}
|
|
3180
|
+
lastError = error;
|
|
3181
|
+
} else if (isRetryableError(error)) {
|
|
3182
|
+
if (attempt === this.maxRetries) {
|
|
3183
|
+
throw error;
|
|
3184
|
+
}
|
|
3185
|
+
lastError = error;
|
|
3186
|
+
} else {
|
|
3187
|
+
throw error;
|
|
3188
|
+
}
|
|
3189
|
+
const backoff = this.computeBackoff(attempt);
|
|
3190
|
+
await this.sleep(backoff);
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
throw lastError;
|
|
3194
|
+
}
|
|
3195
|
+
async fetchWithTimeout(url, method, body) {
|
|
3196
|
+
const controller = new AbortController();
|
|
3197
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
3198
|
+
try {
|
|
3199
|
+
const headers = {
|
|
3200
|
+
Accept: "application/json"
|
|
3201
|
+
};
|
|
3202
|
+
if (this.apiKey) {
|
|
3203
|
+
headers["x-api-key"] = this.apiKey;
|
|
3204
|
+
} else if (this.token) {
|
|
3205
|
+
headers["Authorization"] = `Bearer ${this.token}`;
|
|
3206
|
+
}
|
|
3207
|
+
if (body !== void 0) {
|
|
3208
|
+
headers["Content-Type"] = "application/json";
|
|
3209
|
+
}
|
|
3210
|
+
const response = await fetch(url, {
|
|
3211
|
+
method,
|
|
3212
|
+
headers,
|
|
3213
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
3214
|
+
signal: controller.signal
|
|
3215
|
+
});
|
|
3216
|
+
return response;
|
|
3217
|
+
} finally {
|
|
3218
|
+
clearTimeout(timeoutId);
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
async downloadExportArtifact(exportId) {
|
|
3222
|
+
const response = await this.fetchWithTimeout(
|
|
3223
|
+
`${this.baseUrl}/api/v1/exports/${encodeURIComponent(exportId)}/download`,
|
|
3224
|
+
"GET"
|
|
3225
|
+
);
|
|
3226
|
+
if (!response.ok) {
|
|
3227
|
+
const errorBody = await this.safeParseJson(response);
|
|
3228
|
+
throw new ArelisApiError({
|
|
3229
|
+
type: (typeof errorBody?.["type"] === "string" ? errorBody["type"] : null) ?? `https://arelis.dev/errors/http-${response.status}`,
|
|
3230
|
+
title: (typeof errorBody?.["title"] === "string" ? errorBody["title"] : null) ?? response.statusText,
|
|
3231
|
+
status: response.status,
|
|
3232
|
+
detail: (typeof errorBody?.["detail"] === "string" ? errorBody["detail"] : null) ?? `Request failed with status ${response.status}`,
|
|
3233
|
+
instance: typeof errorBody?.["instance"] === "string" ? errorBody["instance"] : void 0
|
|
3234
|
+
});
|
|
3235
|
+
}
|
|
3236
|
+
const content = await response.text();
|
|
3237
|
+
const disposition = response.headers.get("Content-Disposition");
|
|
3238
|
+
const fileNameMatch = disposition?.match(/filename="(.+?)"/);
|
|
3239
|
+
const fileName = fileNameMatch?.[1] ?? `export-${exportId}.dat`;
|
|
3240
|
+
const mimeType = response.headers.get("Content-Type") ?? "application/octet-stream";
|
|
3241
|
+
return {
|
|
3242
|
+
fileName,
|
|
3243
|
+
mimeType,
|
|
3244
|
+
content
|
|
3245
|
+
};
|
|
3246
|
+
}
|
|
3247
|
+
buildNamespaceCrud(routePath) {
|
|
3248
|
+
return {
|
|
3249
|
+
list: (params) => {
|
|
3250
|
+
const qs = buildQueryString(params ?? {});
|
|
3251
|
+
return this.request("GET", `${routePath}${qs}`);
|
|
3252
|
+
},
|
|
3253
|
+
create: (data) => this.request("POST", routePath, data),
|
|
3254
|
+
get: (id) => this.request("GET", `${routePath}/${id}`),
|
|
3255
|
+
update: (id, data) => this.request("PUT", `${routePath}/${id}`, data),
|
|
3256
|
+
archive: (id) => this.request("DELETE", `${routePath}/${id}`)
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
computeBackoff(attempt, response) {
|
|
3260
|
+
if (response) {
|
|
3261
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
3262
|
+
if (retryAfter) {
|
|
3263
|
+
const seconds = Number(retryAfter);
|
|
3264
|
+
if (!Number.isNaN(seconds)) {
|
|
3265
|
+
return Math.min(seconds * 1e3, MAX_BACKOFF_MS);
|
|
3266
|
+
}
|
|
3267
|
+
const date = new Date(retryAfter);
|
|
3268
|
+
if (!Number.isNaN(date.getTime())) {
|
|
3269
|
+
const delayMs = date.getTime() - Date.now();
|
|
3270
|
+
return Math.min(Math.max(delayMs, 0), MAX_BACKOFF_MS);
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
const base = INITIAL_BACKOFF_MS * Math.pow(2, attempt);
|
|
3275
|
+
const jitter = Math.random() * base * 0.5;
|
|
3276
|
+
return Math.min(base + jitter, MAX_BACKOFF_MS);
|
|
3277
|
+
}
|
|
3278
|
+
async safeParseJson(response) {
|
|
3279
|
+
try {
|
|
3280
|
+
return await response.json();
|
|
3281
|
+
} catch {
|
|
3282
|
+
return null;
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
sleep(ms) {
|
|
3286
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3287
|
+
}
|
|
3288
|
+
// ---------- SSE stream ----------------------------------------------------
|
|
3289
|
+
/**
|
|
3290
|
+
* Opens an SSE connection to the real-time event stream.
|
|
3291
|
+
* Requires browser `EventSource` API or a polyfill in Node.js
|
|
3292
|
+
* (e.g., the `eventsource` npm package assigned to `globalThis.EventSource`).
|
|
3293
|
+
*/
|
|
3294
|
+
stream(options) {
|
|
3295
|
+
const token = this.apiKey ?? this.token ?? "";
|
|
3296
|
+
const url = `${this.baseUrl}/api/v1/stream?token=${encodeURIComponent(token)}`;
|
|
3297
|
+
const ESConstructor = globalThis.EventSource;
|
|
3298
|
+
if (!ESConstructor) {
|
|
3299
|
+
throw new Error(
|
|
3300
|
+
"EventSource is not available. In Node.js, install an EventSource polyfill such as 'eventsource'."
|
|
3301
|
+
);
|
|
3302
|
+
}
|
|
3303
|
+
const eventSource = new ESConstructor(url);
|
|
3304
|
+
const types = options.eventTypes ?? [
|
|
3305
|
+
"event:created",
|
|
3306
|
+
"proof:created",
|
|
3307
|
+
"risk:evaluated",
|
|
3308
|
+
"replay:completed",
|
|
3309
|
+
"policy:updated",
|
|
3310
|
+
"usage:updated",
|
|
3311
|
+
"key:updated"
|
|
3312
|
+
];
|
|
3313
|
+
for (const type of types) {
|
|
3314
|
+
eventSource.addEventListener(type, (event) => {
|
|
3315
|
+
try {
|
|
3316
|
+
const data = JSON.parse(event.data);
|
|
3317
|
+
options.onEvent(type, data);
|
|
3318
|
+
} catch {
|
|
3319
|
+
}
|
|
3320
|
+
});
|
|
3321
|
+
}
|
|
3322
|
+
return {
|
|
3323
|
+
close() {
|
|
3324
|
+
eventSource.close();
|
|
3325
|
+
}
|
|
3326
|
+
};
|
|
3327
|
+
}
|
|
3328
|
+
};
|
|
3329
|
+
|
|
3330
|
+
// src/platform/index.ts
|
|
3331
|
+
function createArelisPlatform(config) {
|
|
3332
|
+
return new ArelisPlatform(config);
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
// src/unified.ts
|
|
3336
|
+
function createArelis(config) {
|
|
3337
|
+
const runtime = config.runtime ? createArelisClient(config.runtime) : void 0;
|
|
3338
|
+
const platform = config.platform ? createArelisPlatform(config.platform) : void 0;
|
|
3339
|
+
if (!runtime && !platform) {
|
|
3340
|
+
throw new Error("createArelis requires at least one configuration: runtime or platform");
|
|
3341
|
+
}
|
|
3342
|
+
return {
|
|
3343
|
+
runtime,
|
|
3344
|
+
platform
|
|
3345
|
+
};
|
|
3346
|
+
}
|
|
3347
|
+
|
|
3348
|
+
// src/extension-contracts.ts
|
|
3349
|
+
var EXTENSION_NAMESPACE_CONTRACTS = [
|
|
3350
|
+
{
|
|
3351
|
+
id: "foundation.policy_compiled_orchestration_cag_selective_disclosure",
|
|
3352
|
+
capabilityFlag: "foundationPolicyCompiledOrchestrationCagSelectiveDisclosure",
|
|
3353
|
+
configNamespace: "extensions.foundation",
|
|
3354
|
+
apiNamespace: "foundation",
|
|
3355
|
+
eventPrefixes: ["policy.", "model.", "tool.", "orchestration."],
|
|
3356
|
+
checkpointNamespaces: ["BeforeOperation", "BeforePrompt", "AfterModelOutput"],
|
|
3357
|
+
artifactSchemas: ["arelis.audit.compliance.v1"]
|
|
3358
|
+
},
|
|
3359
|
+
{
|
|
3360
|
+
id: "extension.full_lifecycle_governance_audit_trail",
|
|
3361
|
+
capabilityFlag: "fullLifecycleGovernanceAuditTrail",
|
|
3362
|
+
configNamespace: "extensions.fullLifecycleGovernanceAuditTrail",
|
|
3363
|
+
apiNamespace: "extensions.lifecycleAudit",
|
|
3364
|
+
eventPrefixes: ["cli.command.", "infra.", "config.", "auth.", "mcp.server.", "mcp.tools."],
|
|
3365
|
+
checkpointNamespaces: [
|
|
3366
|
+
"BeforeProvision",
|
|
3367
|
+
"BeforeDestroy",
|
|
3368
|
+
"BeforeConfigChange",
|
|
3369
|
+
"BeforeAuth"
|
|
3370
|
+
],
|
|
3371
|
+
artifactSchemas: ["arelis.audit.lifecycle.v1"]
|
|
3372
|
+
},
|
|
3373
|
+
{
|
|
3374
|
+
id: "extension.agent_operated_governed_self_service",
|
|
3375
|
+
capabilityFlag: "agentOperatedGovernedSelfService",
|
|
3376
|
+
configNamespace: "extensions.agentOperatedGovernedSelfService",
|
|
3377
|
+
apiNamespace: "extensions.agentGovernance",
|
|
3378
|
+
eventPrefixes: ["agent.step.", "agent.attestation.", "memory."],
|
|
3379
|
+
checkpointNamespaces: ["BeforeAgentStep"],
|
|
3380
|
+
artifactSchemas: ["arelis.audit.agent-attestation.v1"]
|
|
3381
|
+
},
|
|
3382
|
+
{
|
|
3383
|
+
id: "extension.multi_layer_composed_compliance_proofs",
|
|
3384
|
+
capabilityFlag: "multiLayerComposedComplianceProofs",
|
|
3385
|
+
configNamespace: "extensions.multiLayerComposedComplianceProofs",
|
|
3386
|
+
apiNamespace: "extensions.composedProofs",
|
|
3387
|
+
eventPrefixes: ["compliance.proof."],
|
|
3388
|
+
checkpointNamespaces: [],
|
|
3389
|
+
artifactSchemas: ["arelis.audit.compliance.composed.v2"]
|
|
3390
|
+
},
|
|
3391
|
+
{
|
|
3392
|
+
id: "extension.risk_adaptive_runtime_routing",
|
|
3393
|
+
capabilityFlag: "riskAdaptiveRuntimeRouting",
|
|
3394
|
+
configNamespace: "extensions.riskAdaptiveRuntimeRouting",
|
|
3395
|
+
apiNamespace: "extensions.riskRouting",
|
|
3396
|
+
eventPrefixes: ["risk.route."],
|
|
3397
|
+
checkpointNamespaces: [],
|
|
3398
|
+
artifactSchemas: ["arelis.audit.risk-routing.v1"]
|
|
3399
|
+
},
|
|
3400
|
+
{
|
|
3401
|
+
id: "extension.time_bound_snapshot_replay",
|
|
3402
|
+
capabilityFlag: "timeBoundSnapshotReplay",
|
|
3403
|
+
configNamespace: "extensions.timeBoundSnapshotReplay",
|
|
3404
|
+
apiNamespace: "extensions.snapshotReplay",
|
|
3405
|
+
eventPrefixes: ["snapshot.", "replay."],
|
|
3406
|
+
checkpointNamespaces: [],
|
|
3407
|
+
artifactSchemas: ["arelis.audit.snapshot.bundle.v1"]
|
|
3408
|
+
},
|
|
3409
|
+
{
|
|
3410
|
+
id: "extension.policy_derived_selective_disclosure",
|
|
3411
|
+
capabilityFlag: "policyDerivedSelectiveDisclosure",
|
|
3412
|
+
configNamespace: "extensions.policyDerivedSelectiveDisclosure",
|
|
3413
|
+
apiNamespace: "extensions.policyDisclosureSynthesis",
|
|
3414
|
+
eventPrefixes: ["disclosure.derived."],
|
|
3415
|
+
checkpointNamespaces: [],
|
|
3416
|
+
artifactSchemas: ["arelis.audit.disclosure.derived.v1"]
|
|
3417
|
+
}
|
|
3418
|
+
];
|
|
3419
|
+
function extensionContractById(id) {
|
|
3420
|
+
const contract = EXTENSION_NAMESPACE_CONTRACTS.find((entry) => entry.id === id);
|
|
3421
|
+
if (!contract) {
|
|
3422
|
+
throw new Error(`Unknown extension contract: ${id}`);
|
|
3423
|
+
}
|
|
3424
|
+
return contract;
|
|
3425
|
+
}
|
|
3426
|
+
function detectExtensionContractCollisions(contracts = EXTENSION_NAMESPACE_CONTRACTS) {
|
|
3427
|
+
const collisions = [];
|
|
3428
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3429
|
+
const recordCollision = (type, values, contractId) => {
|
|
3430
|
+
for (const value of values) {
|
|
3431
|
+
const key = `${type}:${value}`;
|
|
3432
|
+
const existing = seen.get(key);
|
|
3433
|
+
if (existing && existing !== contractId) {
|
|
3434
|
+
collisions.push({ type, value, leftId: existing, rightId: contractId });
|
|
3435
|
+
continue;
|
|
3436
|
+
}
|
|
3437
|
+
seen.set(key, contractId);
|
|
3438
|
+
}
|
|
3439
|
+
};
|
|
3440
|
+
for (const contract of contracts) {
|
|
3441
|
+
recordCollision("capabilityFlag", [contract.capabilityFlag], contract.id);
|
|
3442
|
+
recordCollision("configNamespace", [contract.configNamespace], contract.id);
|
|
3443
|
+
recordCollision("apiNamespace", [contract.apiNamespace], contract.id);
|
|
3444
|
+
recordCollision("artifactSchema", contract.artifactSchemas, contract.id);
|
|
3445
|
+
recordCollision("eventPrefix", contract.eventPrefixes, contract.id);
|
|
3446
|
+
}
|
|
3447
|
+
return collisions;
|
|
3448
|
+
}
|
|
3449
|
+
var GovernanceGateDeniedError = class extends Error {
|
|
3450
|
+
decision;
|
|
3451
|
+
constructor(decision) {
|
|
3452
|
+
super(`Governance gate denied invocation: ${decision.reasons.join("; ") || "Policy denied"}`);
|
|
3453
|
+
this.name = "GovernanceGateDeniedError";
|
|
3454
|
+
this.decision = decision;
|
|
3455
|
+
}
|
|
3456
|
+
};
|
|
3457
|
+
function createGovernanceGateEvaluator(options) {
|
|
3458
|
+
return {
|
|
3459
|
+
evaluatePolicy: options.evaluatePolicy,
|
|
3460
|
+
resolveContext: options.resolveContext ?? governanceCore.defaultContextResolver,
|
|
3461
|
+
getPolicyMetadata: options.getPolicyMetadata
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
function scanPromptForPii(prompt, options = {}) {
|
|
3465
|
+
const redactor = options.redactor ?? governancePolicy.createRedactor(options.redactorConfig);
|
|
3466
|
+
const redacted = redactor.redact(prompt);
|
|
3467
|
+
return {
|
|
3468
|
+
hasPii: redacted.findings.length > 0,
|
|
3469
|
+
findings: redacted.findings.map((finding) => ({
|
|
3470
|
+
type: finding.type,
|
|
3471
|
+
original: finding.original,
|
|
3472
|
+
start: finding.start,
|
|
3473
|
+
end: finding.end,
|
|
3474
|
+
pattern: finding.pattern
|
|
3475
|
+
}))
|
|
3476
|
+
};
|
|
3477
|
+
}
|
|
3478
|
+
async function evaluatePreInvocationGate(source, input, options = {}) {
|
|
3479
|
+
const evaluator = resolveEvaluator(source);
|
|
3480
|
+
const pii = scanPromptForPii(input.prompt, options);
|
|
3481
|
+
const runId = input.runId ?? governanceCore.generateRunId();
|
|
3482
|
+
const context = await evaluator.resolveContext({
|
|
3483
|
+
org: input.context?.org ?? { id: "sdk-governance-gate" },
|
|
3484
|
+
team: input.context?.team,
|
|
3485
|
+
actor: input.actor,
|
|
3486
|
+
purpose: input.context?.purpose ?? "pre-invocation-gate",
|
|
3487
|
+
environment: input.context?.environment ?? "dev",
|
|
3488
|
+
sessionId: input.context?.sessionId,
|
|
3489
|
+
requestId: input.context?.requestId,
|
|
3490
|
+
tags: input.context?.tags
|
|
3491
|
+
});
|
|
3492
|
+
const policyResult = await evaluator.evaluatePolicy({
|
|
3493
|
+
checkpoint: "BeforePrompt",
|
|
3494
|
+
runId,
|
|
3495
|
+
context,
|
|
3496
|
+
data: {
|
|
3497
|
+
modelId: input.model,
|
|
3498
|
+
input: [{ role: "user", content: input.prompt }]
|
|
3499
|
+
}
|
|
3500
|
+
});
|
|
3501
|
+
const reasons = collectReasons(policyResult);
|
|
3502
|
+
const codes = collectCodes(policyResult);
|
|
3503
|
+
const metadata = evaluator.getPolicyMetadata?.() ?? {};
|
|
3504
|
+
return {
|
|
3505
|
+
runId,
|
|
3506
|
+
decision: policyResult.summary.allowed ? "allow" : "deny",
|
|
3507
|
+
pii,
|
|
3508
|
+
policy: {
|
|
3509
|
+
allowed: policyResult.summary.allowed,
|
|
3510
|
+
decisions: policyResult.decisions,
|
|
3511
|
+
summary: policyResult.summary,
|
|
3512
|
+
policyVersion: policyResult.policyVersion
|
|
3513
|
+
},
|
|
3514
|
+
metadata: {
|
|
3515
|
+
policyIds: [...input.policyIds ?? []],
|
|
3516
|
+
policyIdsMode: "metadata_only",
|
|
3517
|
+
model: input.model,
|
|
3518
|
+
actor: {
|
|
3519
|
+
id: input.actor.id,
|
|
3520
|
+
type: input.actor.type
|
|
3521
|
+
},
|
|
3522
|
+
policySnapshotHash: metadata.policySnapshotHash,
|
|
3523
|
+
policyCompilerId: metadata.policyCompilerId
|
|
3524
|
+
},
|
|
3525
|
+
reasons,
|
|
3526
|
+
codes
|
|
3527
|
+
};
|
|
3528
|
+
}
|
|
3529
|
+
async function withGovernanceGate(source, input, invoke, options = {}) {
|
|
3530
|
+
const decision = await evaluatePreInvocationGate(source, input, options);
|
|
3531
|
+
if (decision.decision === "deny") {
|
|
3532
|
+
if (options.denyMode === "return") {
|
|
3533
|
+
return {
|
|
3534
|
+
runId: decision.runId,
|
|
3535
|
+
invoked: false,
|
|
3536
|
+
decision
|
|
3537
|
+
};
|
|
3538
|
+
}
|
|
3539
|
+
throw new GovernanceGateDeniedError(decision);
|
|
3540
|
+
}
|
|
3541
|
+
const result = await invoke();
|
|
3542
|
+
return {
|
|
3543
|
+
runId: decision.runId,
|
|
3544
|
+
invoked: true,
|
|
3545
|
+
decision,
|
|
3546
|
+
result
|
|
3547
|
+
};
|
|
3548
|
+
}
|
|
3549
|
+
function resolveEvaluator(source) {
|
|
3550
|
+
if ("governance" in source && source.governance?.createGateEvaluator) {
|
|
3551
|
+
return source.governance.createGateEvaluator();
|
|
3552
|
+
}
|
|
3553
|
+
if ("evaluatePolicy" in source && "resolveContext" in source) {
|
|
3554
|
+
return source;
|
|
3555
|
+
}
|
|
3556
|
+
throw new Error(
|
|
3557
|
+
"Unsupported governance gate source: expected ArelisClient.governance.createGateEvaluator() or GovernanceGateEvaluator"
|
|
3558
|
+
);
|
|
3559
|
+
}
|
|
3560
|
+
function collectReasons(result) {
|
|
3561
|
+
const reasons = /* @__PURE__ */ new Set();
|
|
3562
|
+
for (const decision of result.decisions) {
|
|
3563
|
+
if ((decision.effect === "block" || decision.effect === "transform" || decision.effect === "require_approval") && decision.reason) {
|
|
3564
|
+
reasons.add(decision.reason);
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3567
|
+
if (result.summary.blockReason) {
|
|
3568
|
+
reasons.add(result.summary.blockReason);
|
|
3569
|
+
}
|
|
3570
|
+
return [...reasons];
|
|
3571
|
+
}
|
|
3572
|
+
function collectCodes(result) {
|
|
3573
|
+
const codes = /* @__PURE__ */ new Set();
|
|
3574
|
+
for (const decision of result.decisions) {
|
|
3575
|
+
if (decision.effect === "block" && decision.code) {
|
|
3576
|
+
codes.add(decision.code);
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
if (result.summary.blockCode) {
|
|
3580
|
+
codes.add(result.summary.blockCode);
|
|
3581
|
+
}
|
|
3582
|
+
return [...codes];
|
|
3583
|
+
}
|
|
3584
|
+
async function verifyComplianceArtifact(artifact, options = {}) {
|
|
3585
|
+
const provider = options.provider ?? new governanceAudit.HashProofProvider();
|
|
3586
|
+
return provider.verifyProof({
|
|
3587
|
+
commitment: artifact.commitment,
|
|
3588
|
+
proof: artifact.proof,
|
|
3589
|
+
disclosureRules: options.disclosureRules ?? [],
|
|
3590
|
+
policySnapshotHash: options.policySnapshotHash ?? artifact.policySnapshotHash,
|
|
3591
|
+
expectComposed: artifact.artifactSchema === governanceAudit.COMPLIANCE_ARTIFACT_SCHEMA_V2 || artifact.proof.schemaVersion === governanceAudit.COMPLIANCE_PROOF_SCHEMA_V2
|
|
3592
|
+
});
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
Object.defineProperty(exports, "EvaluationBlockedError", {
|
|
3596
|
+
enumerable: true,
|
|
3597
|
+
get: function () { return governanceCore.EvaluationBlockedError; }
|
|
3598
|
+
});
|
|
3599
|
+
Object.defineProperty(exports, "PolicyApprovalRequiredError", {
|
|
3600
|
+
enumerable: true,
|
|
3601
|
+
get: function () { return governanceCore.PolicyApprovalRequiredError; }
|
|
3602
|
+
});
|
|
3603
|
+
Object.defineProperty(exports, "PolicyBlockedError", {
|
|
3604
|
+
enumerable: true,
|
|
3605
|
+
get: function () { return governanceCore.PolicyBlockedError; }
|
|
3606
|
+
});
|
|
3607
|
+
Object.defineProperty(exports, "generateRunId", {
|
|
3608
|
+
enumerable: true,
|
|
3609
|
+
get: function () { return governanceCore.generateRunId; }
|
|
3610
|
+
});
|
|
3611
|
+
Object.defineProperty(exports, "isEvaluationBlockedError", {
|
|
3612
|
+
enumerable: true,
|
|
3613
|
+
get: function () { return governanceCore.isEvaluationBlockedError; }
|
|
3614
|
+
});
|
|
3615
|
+
Object.defineProperty(exports, "isPolicyApprovalRequiredError", {
|
|
3616
|
+
enumerable: true,
|
|
3617
|
+
get: function () { return governanceCore.isPolicyApprovalRequiredError; }
|
|
3618
|
+
});
|
|
3619
|
+
Object.defineProperty(exports, "isPolicyBlockedError", {
|
|
3620
|
+
enumerable: true,
|
|
3621
|
+
get: function () { return governanceCore.isPolicyBlockedError; }
|
|
3622
|
+
});
|
|
3623
|
+
Object.defineProperty(exports, "allowDecision", {
|
|
3624
|
+
enumerable: true,
|
|
3625
|
+
get: function () { return governancePolicy.allowDecision; }
|
|
3626
|
+
});
|
|
3627
|
+
Object.defineProperty(exports, "blockDecision", {
|
|
3628
|
+
enumerable: true,
|
|
3629
|
+
get: function () { return governancePolicy.blockDecision; }
|
|
3630
|
+
});
|
|
3631
|
+
Object.defineProperty(exports, "compilePolicy", {
|
|
3632
|
+
enumerable: true,
|
|
3633
|
+
get: function () { return governancePolicy.compilePolicy; }
|
|
3634
|
+
});
|
|
3635
|
+
Object.defineProperty(exports, "createAllowAllEngine", {
|
|
3636
|
+
enumerable: true,
|
|
3637
|
+
get: function () { return governancePolicy.createAllowAllEngine; }
|
|
3638
|
+
});
|
|
3639
|
+
Object.defineProperty(exports, "createDenyAllEngine", {
|
|
3640
|
+
enumerable: true,
|
|
3641
|
+
get: function () { return governancePolicy.createDenyAllEngine; }
|
|
3642
|
+
});
|
|
3643
|
+
Object.defineProperty(exports, "createJsonPolicyCompiler", {
|
|
3644
|
+
enumerable: true,
|
|
3645
|
+
get: function () { return governancePolicy.createJsonPolicyCompiler; }
|
|
3646
|
+
});
|
|
3647
|
+
Object.defineProperty(exports, "createPolicyEngineFromConfig", {
|
|
3648
|
+
enumerable: true,
|
|
3649
|
+
get: function () { return governancePolicy.createPolicyEngineFromConfig; }
|
|
3650
|
+
});
|
|
3651
|
+
Object.defineProperty(exports, "createPolicyModeEngine", {
|
|
3652
|
+
enumerable: true,
|
|
3653
|
+
get: function () { return governancePolicy.createPolicyModeEngine; }
|
|
3654
|
+
});
|
|
3655
|
+
Object.defineProperty(exports, "loadPolicyConfigFile", {
|
|
3656
|
+
enumerable: true,
|
|
3657
|
+
get: function () { return governancePolicy.loadPolicyConfigFile; }
|
|
3658
|
+
});
|
|
3659
|
+
Object.defineProperty(exports, "loadPolicyEngineFromFile", {
|
|
3660
|
+
enumerable: true,
|
|
3661
|
+
get: function () { return governancePolicy.loadPolicyEngineFromFile; }
|
|
3662
|
+
});
|
|
3663
|
+
Object.defineProperty(exports, "parsePolicyConfig", {
|
|
3664
|
+
enumerable: true,
|
|
3665
|
+
get: function () { return governancePolicy.parsePolicyConfig; }
|
|
3666
|
+
});
|
|
3667
|
+
Object.defineProperty(exports, "requireApprovalDecision", {
|
|
3668
|
+
enumerable: true,
|
|
3669
|
+
get: function () { return governancePolicy.requireApprovalDecision; }
|
|
3670
|
+
});
|
|
3671
|
+
Object.defineProperty(exports, "transformDecision", {
|
|
3672
|
+
enumerable: true,
|
|
3673
|
+
get: function () { return governancePolicy.transformDecision; }
|
|
3674
|
+
});
|
|
3675
|
+
Object.defineProperty(exports, "HashProofProvider", {
|
|
3676
|
+
enumerable: true,
|
|
3677
|
+
get: function () { return governanceAudit.HashProofProvider; }
|
|
3678
|
+
});
|
|
3679
|
+
Object.defineProperty(exports, "SnarkjsProofProvider", {
|
|
3680
|
+
enumerable: true,
|
|
3681
|
+
get: function () { return governanceAudit.SnarkjsProofProvider; }
|
|
3682
|
+
});
|
|
3683
|
+
Object.defineProperty(exports, "assessPolicyRisk", {
|
|
3684
|
+
enumerable: true,
|
|
3685
|
+
get: function () { return governanceAudit.assessPolicyRisk; }
|
|
3686
|
+
});
|
|
3687
|
+
Object.defineProperty(exports, "createAgentAttestationCreatedEvent", {
|
|
3688
|
+
enumerable: true,
|
|
3689
|
+
get: function () { return governanceAudit.createAgentAttestationCreatedEvent; }
|
|
3690
|
+
});
|
|
3691
|
+
Object.defineProperty(exports, "createAuthFailedEvent", {
|
|
3692
|
+
enumerable: true,
|
|
3693
|
+
get: function () { return governanceAudit.createAuthFailedEvent; }
|
|
3694
|
+
});
|
|
3695
|
+
Object.defineProperty(exports, "createAuthStartedEvent", {
|
|
3696
|
+
enumerable: true,
|
|
3697
|
+
get: function () { return governanceAudit.createAuthStartedEvent; }
|
|
3698
|
+
});
|
|
3699
|
+
Object.defineProperty(exports, "createAuthSucceededEvent", {
|
|
3700
|
+
enumerable: true,
|
|
3701
|
+
get: function () { return governanceAudit.createAuthSucceededEvent; }
|
|
3702
|
+
});
|
|
3703
|
+
Object.defineProperty(exports, "createBlobRef", {
|
|
3704
|
+
enumerable: true,
|
|
3705
|
+
get: function () { return governanceAudit.createBlobRef; }
|
|
3706
|
+
});
|
|
3707
|
+
Object.defineProperty(exports, "createCausalGraphCommitment", {
|
|
3708
|
+
enumerable: true,
|
|
3709
|
+
get: function () { return governanceAudit.createCausalGraphCommitment; }
|
|
3710
|
+
});
|
|
3711
|
+
Object.defineProperty(exports, "createCliCommandCompletedEvent", {
|
|
3712
|
+
enumerable: true,
|
|
3713
|
+
get: function () { return governanceAudit.createCliCommandCompletedEvent; }
|
|
3714
|
+
});
|
|
3715
|
+
Object.defineProperty(exports, "createCliCommandFailedEvent", {
|
|
3716
|
+
enumerable: true,
|
|
3717
|
+
get: function () { return governanceAudit.createCliCommandFailedEvent; }
|
|
3718
|
+
});
|
|
3719
|
+
Object.defineProperty(exports, "createCliCommandStartedEvent", {
|
|
3720
|
+
enumerable: true,
|
|
3721
|
+
get: function () { return governanceAudit.createCliCommandStartedEvent; }
|
|
3722
|
+
});
|
|
3723
|
+
Object.defineProperty(exports, "createComplianceProofComposedEvent", {
|
|
3724
|
+
enumerable: true,
|
|
3725
|
+
get: function () { return governanceAudit.createComplianceProofComposedEvent; }
|
|
3726
|
+
});
|
|
3727
|
+
Object.defineProperty(exports, "createCompositeSink", {
|
|
3728
|
+
enumerable: true,
|
|
3729
|
+
get: function () { return governanceAudit.createCompositeSink; }
|
|
3730
|
+
});
|
|
3731
|
+
Object.defineProperty(exports, "createConfigChangeCompletedEvent", {
|
|
3732
|
+
enumerable: true,
|
|
3733
|
+
get: function () { return governanceAudit.createConfigChangeCompletedEvent; }
|
|
3734
|
+
});
|
|
3735
|
+
Object.defineProperty(exports, "createConfigChangeFailedEvent", {
|
|
3736
|
+
enumerable: true,
|
|
3737
|
+
get: function () { return governanceAudit.createConfigChangeFailedEvent; }
|
|
3738
|
+
});
|
|
3739
|
+
Object.defineProperty(exports, "createConfigChangeStartedEvent", {
|
|
3740
|
+
enumerable: true,
|
|
3741
|
+
get: function () { return governanceAudit.createConfigChangeStartedEvent; }
|
|
3742
|
+
});
|
|
3743
|
+
Object.defineProperty(exports, "createConsoleSink", {
|
|
3744
|
+
enumerable: true,
|
|
3745
|
+
get: function () { return governanceAudit.createConsoleSink; }
|
|
3746
|
+
});
|
|
3747
|
+
Object.defineProperty(exports, "createDisclosureDerivedGeneratedEvent", {
|
|
3748
|
+
enumerable: true,
|
|
3749
|
+
get: function () { return governanceAudit.createDisclosureDerivedGeneratedEvent; }
|
|
3750
|
+
});
|
|
3751
|
+
Object.defineProperty(exports, "createHashRef", {
|
|
3752
|
+
enumerable: true,
|
|
3753
|
+
get: function () { return governanceAudit.createHashRef; }
|
|
3754
|
+
});
|
|
3755
|
+
Object.defineProperty(exports, "createInfraDestroyCompletedEvent", {
|
|
3756
|
+
enumerable: true,
|
|
3757
|
+
get: function () { return governanceAudit.createInfraDestroyCompletedEvent; }
|
|
3758
|
+
});
|
|
3759
|
+
Object.defineProperty(exports, "createInfraDestroyFailedEvent", {
|
|
3760
|
+
enumerable: true,
|
|
3761
|
+
get: function () { return governanceAudit.createInfraDestroyFailedEvent; }
|
|
3762
|
+
});
|
|
3763
|
+
Object.defineProperty(exports, "createInfraDestroyStartedEvent", {
|
|
3764
|
+
enumerable: true,
|
|
3765
|
+
get: function () { return governanceAudit.createInfraDestroyStartedEvent; }
|
|
3766
|
+
});
|
|
3767
|
+
Object.defineProperty(exports, "createInfraProvisionCompletedEvent", {
|
|
3768
|
+
enumerable: true,
|
|
3769
|
+
get: function () { return governanceAudit.createInfraProvisionCompletedEvent; }
|
|
3770
|
+
});
|
|
3771
|
+
Object.defineProperty(exports, "createInfraProvisionFailedEvent", {
|
|
3772
|
+
enumerable: true,
|
|
3773
|
+
get: function () { return governanceAudit.createInfraProvisionFailedEvent; }
|
|
3774
|
+
});
|
|
3775
|
+
Object.defineProperty(exports, "createInfraProvisionStartedEvent", {
|
|
3776
|
+
enumerable: true,
|
|
3777
|
+
get: function () { return governanceAudit.createInfraProvisionStartedEvent; }
|
|
3778
|
+
});
|
|
3779
|
+
Object.defineProperty(exports, "createInlineRef", {
|
|
3780
|
+
enumerable: true,
|
|
3781
|
+
get: function () { return governanceAudit.createInlineRef; }
|
|
3782
|
+
});
|
|
3783
|
+
Object.defineProperty(exports, "createKBChunkFilteredEvent", {
|
|
3784
|
+
enumerable: true,
|
|
3785
|
+
get: function () { return governanceAudit.createKBChunkFilteredEvent; }
|
|
3786
|
+
});
|
|
3787
|
+
Object.defineProperty(exports, "createKBGroundingAppliedEvent", {
|
|
3788
|
+
enumerable: true,
|
|
3789
|
+
get: function () { return governanceAudit.createKBGroundingAppliedEvent; }
|
|
3790
|
+
});
|
|
3791
|
+
Object.defineProperty(exports, "createKBQueryEvent", {
|
|
3792
|
+
enumerable: true,
|
|
3793
|
+
get: function () { return governanceAudit.createKBQueryEvent; }
|
|
3794
|
+
});
|
|
3795
|
+
Object.defineProperty(exports, "createKBResultsEvent", {
|
|
3796
|
+
enumerable: true,
|
|
3797
|
+
get: function () { return governanceAudit.createKBResultsEvent; }
|
|
3798
|
+
});
|
|
3799
|
+
Object.defineProperty(exports, "createMCPServerConnectedEvent", {
|
|
3800
|
+
enumerable: true,
|
|
3801
|
+
get: function () { return governanceAudit.createMCPServerConnectedEvent; }
|
|
3802
|
+
});
|
|
3803
|
+
Object.defineProperty(exports, "createMCPServerDisconnectedEvent", {
|
|
3804
|
+
enumerable: true,
|
|
3805
|
+
get: function () { return governanceAudit.createMCPServerDisconnectedEvent; }
|
|
3806
|
+
});
|
|
3807
|
+
Object.defineProperty(exports, "createMCPServerRegisteredEvent", {
|
|
3808
|
+
enumerable: true,
|
|
3809
|
+
get: function () { return governanceAudit.createMCPServerRegisteredEvent; }
|
|
3810
|
+
});
|
|
3811
|
+
Object.defineProperty(exports, "createMCPToolsDiscoveredEvent", {
|
|
3812
|
+
enumerable: true,
|
|
3813
|
+
get: function () { return governanceAudit.createMCPToolsDiscoveredEvent; }
|
|
3814
|
+
});
|
|
3815
|
+
Object.defineProperty(exports, "createMemorySink", {
|
|
3816
|
+
enumerable: true,
|
|
3817
|
+
get: function () { return governanceAudit.createMemorySink; }
|
|
3818
|
+
});
|
|
3819
|
+
Object.defineProperty(exports, "createNoOpSink", {
|
|
3820
|
+
enumerable: true,
|
|
3821
|
+
get: function () { return governanceAudit.createNoOpSink; }
|
|
3822
|
+
});
|
|
3823
|
+
Object.defineProperty(exports, "createOrchestrationStepEvent", {
|
|
3824
|
+
enumerable: true,
|
|
3825
|
+
get: function () { return governanceAudit.createOrchestrationStepEvent; }
|
|
3826
|
+
});
|
|
3827
|
+
Object.defineProperty(exports, "createReplayDriftDetectedEvent", {
|
|
3828
|
+
enumerable: true,
|
|
3829
|
+
get: function () { return governanceAudit.createReplayDriftDetectedEvent; }
|
|
3830
|
+
});
|
|
3831
|
+
Object.defineProperty(exports, "createResourceCreatedEvent", {
|
|
3832
|
+
enumerable: true,
|
|
3833
|
+
get: function () { return governanceAudit.createResourceCreatedEvent; }
|
|
3834
|
+
});
|
|
3835
|
+
Object.defineProperty(exports, "createResourceDeletedEvent", {
|
|
3836
|
+
enumerable: true,
|
|
3837
|
+
get: function () { return governanceAudit.createResourceDeletedEvent; }
|
|
3838
|
+
});
|
|
3839
|
+
Object.defineProperty(exports, "createResourceUpdatedEvent", {
|
|
3840
|
+
enumerable: true,
|
|
3841
|
+
get: function () { return governanceAudit.createResourceUpdatedEvent; }
|
|
3842
|
+
});
|
|
3843
|
+
Object.defineProperty(exports, "createRiskRouteDecidedEvent", {
|
|
3844
|
+
enumerable: true,
|
|
3845
|
+
get: function () { return governanceAudit.createRiskRouteDecidedEvent; }
|
|
3846
|
+
});
|
|
3847
|
+
Object.defineProperty(exports, "createSnapshotCapturedEvent", {
|
|
3848
|
+
enumerable: true,
|
|
3849
|
+
get: function () { return governanceAudit.createSnapshotCapturedEvent; }
|
|
3850
|
+
});
|
|
3851
|
+
Object.defineProperty(exports, "findInferenceRunsFromLifecycle", {
|
|
3852
|
+
enumerable: true,
|
|
3853
|
+
get: function () { return governanceAudit.findInferenceRunsFromLifecycle; }
|
|
3854
|
+
});
|
|
3855
|
+
Object.defineProperty(exports, "replayAuditRun", {
|
|
3856
|
+
enumerable: true,
|
|
3857
|
+
get: function () { return governanceAudit.replayAuditRun; }
|
|
3858
|
+
});
|
|
3859
|
+
Object.defineProperty(exports, "replayCausalGraph", {
|
|
3860
|
+
enumerable: true,
|
|
3861
|
+
get: function () { return governanceAudit.replayCausalGraph; }
|
|
3862
|
+
});
|
|
3863
|
+
Object.defineProperty(exports, "traceLifecycleOriginsForOutput", {
|
|
3864
|
+
enumerable: true,
|
|
3865
|
+
get: function () { return governanceAudit.traceLifecycleOriginsForOutput; }
|
|
3866
|
+
});
|
|
3867
|
+
Object.defineProperty(exports, "traverseLineage", {
|
|
3868
|
+
enumerable: true,
|
|
3869
|
+
get: function () { return governanceAudit.traverseLineage; }
|
|
3870
|
+
});
|
|
3871
|
+
Object.defineProperty(exports, "BaseModelProvider", {
|
|
3872
|
+
enumerable: true,
|
|
3873
|
+
get: function () { return governanceModels.BaseModelProvider; }
|
|
3874
|
+
});
|
|
3875
|
+
Object.defineProperty(exports, "ProviderCapabilityNotSupportedError", {
|
|
3876
|
+
enumerable: true,
|
|
3877
|
+
get: function () { return governanceModels.ProviderCapabilityNotSupportedError; }
|
|
3878
|
+
});
|
|
3879
|
+
Object.defineProperty(exports, "createMockProvider", {
|
|
3880
|
+
enumerable: true,
|
|
3881
|
+
get: function () { return governanceModels.createMockProvider; }
|
|
3882
|
+
});
|
|
3883
|
+
Object.defineProperty(exports, "createModelRegistry", {
|
|
3884
|
+
enumerable: true,
|
|
3885
|
+
get: function () { return governanceModels.createModelRegistry; }
|
|
3886
|
+
});
|
|
3887
|
+
Object.defineProperty(exports, "supportsAudioGeneration", {
|
|
3888
|
+
enumerable: true,
|
|
3889
|
+
get: function () { return governanceModels.supportsAudioGeneration; }
|
|
3890
|
+
});
|
|
3891
|
+
Object.defineProperty(exports, "supportsAudioToImage", {
|
|
3892
|
+
enumerable: true,
|
|
3893
|
+
get: function () { return governanceModels.supportsAudioToImage; }
|
|
3894
|
+
});
|
|
3895
|
+
Object.defineProperty(exports, "supportsAudioToText", {
|
|
3896
|
+
enumerable: true,
|
|
3897
|
+
get: function () { return governanceModels.supportsAudioToText; }
|
|
3898
|
+
});
|
|
3899
|
+
Object.defineProperty(exports, "supportsAudioToVideo", {
|
|
3900
|
+
enumerable: true,
|
|
3901
|
+
get: function () { return governanceModels.supportsAudioToVideo; }
|
|
3902
|
+
});
|
|
3903
|
+
Object.defineProperty(exports, "supportsImageGeneration", {
|
|
3904
|
+
enumerable: true,
|
|
3905
|
+
get: function () { return governanceModels.supportsImageGeneration; }
|
|
3906
|
+
});
|
|
3907
|
+
Object.defineProperty(exports, "supportsImageToAudio", {
|
|
3908
|
+
enumerable: true,
|
|
3909
|
+
get: function () { return governanceModels.supportsImageToAudio; }
|
|
3910
|
+
});
|
|
3911
|
+
Object.defineProperty(exports, "supportsImageToText", {
|
|
3912
|
+
enumerable: true,
|
|
3913
|
+
get: function () { return governanceModels.supportsImageToText; }
|
|
3914
|
+
});
|
|
3915
|
+
Object.defineProperty(exports, "supportsImageToVideo", {
|
|
3916
|
+
enumerable: true,
|
|
3917
|
+
get: function () { return governanceModels.supportsImageToVideo; }
|
|
3918
|
+
});
|
|
3919
|
+
Object.defineProperty(exports, "supportsStreaming", {
|
|
3920
|
+
enumerable: true,
|
|
3921
|
+
get: function () { return governanceModels.supportsStreaming; }
|
|
3922
|
+
});
|
|
3923
|
+
Object.defineProperty(exports, "supportsTokenEstimation", {
|
|
3924
|
+
enumerable: true,
|
|
3925
|
+
get: function () { return governanceModels.supportsTokenEstimation; }
|
|
3926
|
+
});
|
|
3927
|
+
Object.defineProperty(exports, "supportsVideoGeneration", {
|
|
3928
|
+
enumerable: true,
|
|
3929
|
+
get: function () { return governanceModels.supportsVideoGeneration; }
|
|
3930
|
+
});
|
|
3931
|
+
Object.defineProperty(exports, "supportsVideoToAudio", {
|
|
3932
|
+
enumerable: true,
|
|
3933
|
+
get: function () { return governanceModels.supportsVideoToAudio; }
|
|
3934
|
+
});
|
|
3935
|
+
Object.defineProperty(exports, "supportsVideoToImage", {
|
|
3936
|
+
enumerable: true,
|
|
3937
|
+
get: function () { return governanceModels.supportsVideoToImage; }
|
|
3938
|
+
});
|
|
3939
|
+
Object.defineProperty(exports, "supportsVideoToText", {
|
|
3940
|
+
enumerable: true,
|
|
3941
|
+
get: function () { return governanceModels.supportsVideoToText; }
|
|
3942
|
+
});
|
|
3943
|
+
Object.defineProperty(exports, "createNoOpTelemetry", {
|
|
3944
|
+
enumerable: true,
|
|
3945
|
+
get: function () { return governanceTelemetryOtel.createNoOpTelemetry; }
|
|
3946
|
+
});
|
|
3947
|
+
Object.defineProperty(exports, "createOTelAdapter", {
|
|
3948
|
+
enumerable: true,
|
|
3949
|
+
get: function () { return governanceTelemetryOtel.createOTelAdapter; }
|
|
3950
|
+
});
|
|
3951
|
+
Object.defineProperty(exports, "createHttpMCPTransport", {
|
|
3952
|
+
enumerable: true,
|
|
3953
|
+
get: function () { return governanceMcp.createHttpMCPTransport; }
|
|
3954
|
+
});
|
|
3955
|
+
Object.defineProperty(exports, "createMCPRegistry", {
|
|
3956
|
+
enumerable: true,
|
|
3957
|
+
get: function () { return governanceMcp.createMCPRegistry; }
|
|
3958
|
+
});
|
|
3959
|
+
Object.defineProperty(exports, "createMockMCPTransport", {
|
|
3960
|
+
enumerable: true,
|
|
3961
|
+
get: function () { return governanceMcp.createMockMCPTransport; }
|
|
3962
|
+
});
|
|
3963
|
+
Object.defineProperty(exports, "createStdioMCPTransport", {
|
|
3964
|
+
enumerable: true,
|
|
3965
|
+
get: function () { return governanceMcp.createStdioMCPTransport; }
|
|
3966
|
+
});
|
|
3967
|
+
Object.defineProperty(exports, "discoverTools", {
|
|
3968
|
+
enumerable: true,
|
|
3969
|
+
get: function () { return governanceMcp.discoverTools; }
|
|
3970
|
+
});
|
|
3971
|
+
Object.defineProperty(exports, "getMCPToolName", {
|
|
3972
|
+
enumerable: true,
|
|
3973
|
+
get: function () { return governanceMcp.getMCPToolName; }
|
|
3974
|
+
});
|
|
3975
|
+
Object.defineProperty(exports, "parseMCPToolName", {
|
|
3976
|
+
enumerable: true,
|
|
3977
|
+
get: function () { return governanceMcp.parseMCPToolName; }
|
|
3978
|
+
});
|
|
3979
|
+
Object.defineProperty(exports, "HybridScorer", {
|
|
3980
|
+
enumerable: true,
|
|
3981
|
+
get: function () { return governanceKnowledge.HybridScorer; }
|
|
3982
|
+
});
|
|
3983
|
+
Object.defineProperty(exports, "applyGrounding", {
|
|
3984
|
+
enumerable: true,
|
|
3985
|
+
get: function () { return governanceKnowledge.applyGrounding; }
|
|
3986
|
+
});
|
|
3987
|
+
Object.defineProperty(exports, "createGroundingHelper", {
|
|
3988
|
+
enumerable: true,
|
|
3989
|
+
get: function () { return governanceKnowledge.createGroundingHelper; }
|
|
3990
|
+
});
|
|
3991
|
+
Object.defineProperty(exports, "createKBRegistry", {
|
|
3992
|
+
enumerable: true,
|
|
3993
|
+
get: function () { return governanceKnowledge.createKBRegistry; }
|
|
3994
|
+
});
|
|
3995
|
+
Object.defineProperty(exports, "createKBRetriever", {
|
|
3996
|
+
enumerable: true,
|
|
3997
|
+
get: function () { return governanceKnowledge.createKBRetriever; }
|
|
3998
|
+
});
|
|
3999
|
+
Object.defineProperty(exports, "createMemoryKBProvider", {
|
|
4000
|
+
enumerable: true,
|
|
4001
|
+
get: function () { return governanceKnowledge.createMemoryKBProvider; }
|
|
4002
|
+
});
|
|
4003
|
+
Object.defineProperty(exports, "mergeRetrievalResults", {
|
|
4004
|
+
enumerable: true,
|
|
4005
|
+
get: function () { return governanceKnowledge.mergeRetrievalResults; }
|
|
4006
|
+
});
|
|
4007
|
+
Object.defineProperty(exports, "computePromptHash", {
|
|
4008
|
+
enumerable: true,
|
|
4009
|
+
get: function () { return governancePrompts.computePromptHash; }
|
|
4010
|
+
});
|
|
4011
|
+
Object.defineProperty(exports, "createTemplateRegistry", {
|
|
4012
|
+
enumerable: true,
|
|
4013
|
+
get: function () { return governancePrompts.createTemplateRegistry; }
|
|
4014
|
+
});
|
|
4015
|
+
Object.defineProperty(exports, "createInMemoryMemoryProvider", {
|
|
4016
|
+
enumerable: true,
|
|
4017
|
+
get: function () { return governanceMemory.createInMemoryMemoryProvider; }
|
|
4018
|
+
});
|
|
4019
|
+
Object.defineProperty(exports, "createMemoryRegistry", {
|
|
4020
|
+
enumerable: true,
|
|
4021
|
+
get: function () { return governanceMemory.createMemoryRegistry; }
|
|
4022
|
+
});
|
|
4023
|
+
Object.defineProperty(exports, "createDataSourceRegistry", {
|
|
4024
|
+
enumerable: true,
|
|
4025
|
+
get: function () { return governanceDataSources.createDataSourceRegistry; }
|
|
4026
|
+
});
|
|
4027
|
+
Object.defineProperty(exports, "deriveEvaluationEffect", {
|
|
4028
|
+
enumerable: true,
|
|
4029
|
+
get: function () { return governanceEvaluations.deriveEvaluationEffect; }
|
|
4030
|
+
});
|
|
4031
|
+
Object.defineProperty(exports, "runEvaluations", {
|
|
4032
|
+
enumerable: true,
|
|
4033
|
+
get: function () { return governanceEvaluations.runEvaluations; }
|
|
4034
|
+
});
|
|
4035
|
+
Object.defineProperty(exports, "createEnvSecretResolver", {
|
|
4036
|
+
enumerable: true,
|
|
4037
|
+
get: function () { return governanceSecrets.createEnvSecretResolver; }
|
|
4038
|
+
});
|
|
4039
|
+
Object.defineProperty(exports, "getSecretRedactionPatterns", {
|
|
4040
|
+
enumerable: true,
|
|
4041
|
+
get: function () { return governanceSecrets.getSecretRedactionPatterns; }
|
|
4042
|
+
});
|
|
4043
|
+
Object.defineProperty(exports, "createAgentRuntime", {
|
|
4044
|
+
enumerable: true,
|
|
4045
|
+
get: function () { return governanceAgents.createAgentRuntime; }
|
|
4046
|
+
});
|
|
4047
|
+
Object.defineProperty(exports, "createInMemoryAgentMemory", {
|
|
4048
|
+
enumerable: true,
|
|
4049
|
+
get: function () { return governanceAgents.createInMemoryAgentMemory; }
|
|
4050
|
+
});
|
|
4051
|
+
Object.defineProperty(exports, "createToolRegistry", {
|
|
4052
|
+
enumerable: true,
|
|
4053
|
+
get: function () { return governanceTools.createToolRegistry; }
|
|
4054
|
+
});
|
|
4055
|
+
Object.defineProperty(exports, "createToolRunner", {
|
|
4056
|
+
enumerable: true,
|
|
4057
|
+
get: function () { return governanceTools.createToolRunner; }
|
|
4058
|
+
});
|
|
4059
|
+
Object.defineProperty(exports, "createInMemoryQuotaManager", {
|
|
4060
|
+
enumerable: true,
|
|
4061
|
+
get: function () { return governanceQuotas.createInMemoryQuotaManager; }
|
|
4062
|
+
});
|
|
4063
|
+
exports.ArelisApiError = ArelisApiError;
|
|
4064
|
+
exports.ArelisClient = ArelisClient;
|
|
4065
|
+
exports.ArelisPlatform = ArelisPlatform;
|
|
4066
|
+
exports.EXTENSION_NAMESPACE_CONTRACTS = EXTENSION_NAMESPACE_CONTRACTS;
|
|
4067
|
+
exports.GovernanceGateDeniedError = GovernanceGateDeniedError;
|
|
4068
|
+
exports.createArelis = createArelis;
|
|
4069
|
+
exports.createArelisClient = createArelisClient;
|
|
4070
|
+
exports.createArelisPlatform = createArelisPlatform;
|
|
4071
|
+
exports.createGovernanceGateEvaluator = createGovernanceGateEvaluator;
|
|
4072
|
+
exports.detectExtensionContractCollisions = detectExtensionContractCollisions;
|
|
4073
|
+
exports.evaluatePreInvocationGate = evaluatePreInvocationGate;
|
|
4074
|
+
exports.extensionContractById = extensionContractById;
|
|
4075
|
+
exports.scanPromptForPii = scanPromptForPii;
|
|
4076
|
+
exports.verifyComplianceArtifactOffline = verifyComplianceArtifact;
|
|
4077
|
+
exports.withGovernanceGate = withGovernanceGate;
|
|
4078
|
+
//# sourceMappingURL=index.cjs.map
|
|
4079
|
+
//# sourceMappingURL=index.cjs.map
|