@muxoai/platform 1.3.0 → 1.3.2

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.
Files changed (51) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +19 -4
  3. package/.codex/config.toml +9 -2
  4. package/README.md +63 -20
  5. package/dist/clerk.d.ts +33 -0
  6. package/dist/clerk.js +198 -0
  7. package/dist/cli.js +1181 -99
  8. package/dist/engine.d.ts +22 -1
  9. package/dist/engine.js +284 -14
  10. package/dist/mcp.d.ts +6 -1
  11. package/dist/mcp.js +109 -22
  12. package/dist/nl.js +60 -36
  13. package/dist/policy.d.ts +9 -0
  14. package/dist/policy.js +73 -0
  15. package/dist/providers/composio-instant.d.ts +4 -0
  16. package/dist/providers/composio-instant.js +634 -534
  17. package/dist/providers/composio-sdk.d.ts +1 -0
  18. package/dist/providers/composio-sdk.js +6 -2
  19. package/dist/providers/microsoft-governance.d.ts +61 -2
  20. package/dist/providers/microsoft-governance.js +458 -24
  21. package/dist/providers/stripe-billing.js +14 -4
  22. package/dist/providers/stripe-projects.d.ts +4 -1
  23. package/dist/providers/stripe-projects.js +123 -12
  24. package/dist/providers/supermemory.d.ts +28 -5
  25. package/dist/providers/supermemory.js +183 -55
  26. package/dist/sdk.d.ts +167 -1
  27. package/dist/sdk.js +113 -2
  28. package/dist/server.js +258 -40
  29. package/dist/store.d.ts +26 -1
  30. package/dist/store.js +255 -6
  31. package/dist/types.d.ts +86 -0
  32. package/dist/ui/console-html.d.ts +16 -0
  33. package/dist/ui/console-html.js +2427 -2206
  34. package/dist/ui/design-tokens.d.ts +177 -0
  35. package/dist/ui/design-tokens.js +210 -0
  36. package/dist/version.d.ts +1 -0
  37. package/dist/version.js +1 -0
  38. package/package.json +2 -2
  39. package/plugins/muxo/.app.json +1 -1
  40. package/plugins/muxo/.claude-plugin/plugin.json +2 -2
  41. package/plugins/muxo/.codex-plugin/plugin.json +7 -5
  42. package/plugins/muxo/.mcp.json +1 -33
  43. package/plugins/muxo/assets/logo.png +0 -0
  44. package/plugins/muxo/hooks/session-start.sh +1 -1
  45. package/plugins/muxo/plugin.json +63 -6
  46. package/plugins/muxo/skills/muxo/SKILL.md +92 -14
  47. package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
  48. package/plugins/muxo/skills/muxo/references/cli.md +4 -2
  49. package/plugins/muxo/skills/muxo/references/mcp.md +15 -9
  50. package/plugins/muxo/skills/setup/SKILL.md +8 -2
  51. package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
@@ -1,7 +1,28 @@
1
1
  import crypto from "node:crypto";
2
- import { AgentIdentity, AuditLogger, McpSecurityScanner, PolicyEngine, } from "../../vendor/microsoft-governance/dist/index.js";
2
+ import { AgentIdentity, AuditLogger, ContextPoisoningDetector, ExecutionRing, FacetRegistry, KillSwitch, McpSecurityScanner, PolicyEngine, RingEnforcer, TrustManager, extractK8sFacets, extractProtocolFacets, extractSqlFacets, } from "../../vendor/microsoft-governance/dist/index.js";
3
3
  const SDK_VERSION = "5.0.0";
4
4
  const POLICY_ID = "muxo-microsoft-agent-governance-v5";
5
+ export const RING_LABELS = {
6
+ [ExecutionRing.Ring0]: "Ring 0 (Kernel / Destructive & Root Boundary)",
7
+ [ExecutionRing.Ring1]: "Ring 1 (Supervisor / Provisioning, Financial & Admin)",
8
+ [ExecutionRing.Ring2]: "Ring 2 (Standard Agent / Governed Write)",
9
+ [ExecutionRing.Ring3]: "Ring 3 (Unprivileged Sandbox / Read-Only)",
10
+ };
11
+ function requiredRingForRisk(riskLevel) {
12
+ switch (riskLevel) {
13
+ case "destructive":
14
+ return ExecutionRing.Ring0;
15
+ case "admin":
16
+ case "financial":
17
+ case "provisioning":
18
+ return ExecutionRing.Ring1;
19
+ case "write":
20
+ return ExecutionRing.Ring2;
21
+ case "read":
22
+ default:
23
+ return ExecutionRing.Ring3;
24
+ }
25
+ }
5
26
  // PKCS#8 DER prefix for a 32-byte Ed25519 private key seed (OID 1.3.101.112)
6
27
  const ED25519_PKCS8_PREFIX = Buffer.from([
7
28
  0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70,
@@ -39,12 +60,41 @@ function deriveDeterministicIdentity(seedMaterial, agentId, capabilities, opts)
39
60
  }
40
61
  export class MicrosoftGovernanceAdapter {
41
62
  scanner;
63
+ contextPoisoningDetector;
64
+ facetRegistry;
65
+ trustManager;
66
+ killSwitch;
67
+ activeKillSwitches = new Map();
42
68
  seedMaterial;
43
69
  auditLoggers = new Map();
44
70
  identities = new Map();
45
71
  defaultIdentity;
46
72
  constructor(seed) {
47
73
  this.scanner = new McpSecurityScanner();
74
+ this.contextPoisoningDetector = new ContextPoisoningDetector({
75
+ maxContextSizeBytes: 100_000,
76
+ maxEntriesPerSession: 250,
77
+ entropyThreshold: 5.5,
78
+ similarityThreshold: 0.92,
79
+ enableIsolation: true,
80
+ });
81
+ this.facetRegistry = new FacetRegistry();
82
+ this.facetRegistry.register("sql", extractSqlFacets);
83
+ this.facetRegistry.register("k8s", extractK8sFacets);
84
+ this.facetRegistry.register("infra", (sub) => ({
85
+ provider: String(sub.provider ?? "").toLowerCase(),
86
+ service: String(sub.service ?? "").toLowerCase(),
87
+ action: String(sub.action ?? "read").toLowerCase(),
88
+ destructive: Boolean(sub.destructive),
89
+ }));
90
+ this.trustManager = new TrustManager({
91
+ initialScore: 0.75,
92
+ decayFactor: 0.98,
93
+ });
94
+ this.killSwitch = new KillSwitch({
95
+ enabled: true,
96
+ defaultSubstituteAgentId: "muxo-safe-mode-guardian",
97
+ });
48
98
  this.seedMaterial = Buffer.isBuffer(seed)
49
99
  ? seed
50
100
  : Buffer.from(String(seed ||
@@ -94,12 +144,273 @@ export class MicrosoftGovernanceAdapter {
94
144
  }
95
145
  return logger;
96
146
  }
147
+ /**
148
+ * Scans memory or prompt context for OWASP ASI-06 Context Poisoning (prompt injection,
149
+ * roleplay overrides, delimiter injection, high-entropy exfiltration payloads, and session isolation).
150
+ */
151
+ scanMemoryContent(params) {
152
+ const safeAgentKey = params.workspaceId.replace(/[^a-zA-Z0-9_-]/g, "_");
153
+ const safeSessionKey = (params.sessionId || "default").replace(/[^a-zA-Z0-9_-]/g, "_");
154
+ const entryId = params.entryId || `mem_${crypto.randomBytes(6).toString("hex")}`;
155
+ const entry = {
156
+ id: entryId,
157
+ entryId,
158
+ agentId: safeAgentKey,
159
+ sessionId: safeSessionKey,
160
+ role: params.role || "user",
161
+ content: String(params.content || ""),
162
+ timestamp: new Date().toISOString(),
163
+ };
164
+ const findings = this.contextPoisoningDetector.scanEntry(entry);
165
+ // Augment with credential/secret exfiltration detection in memory content
166
+ if (/(cat|curl|wget)\s+.*(\/etc\/passwd|\.env|id_rsa|AWS_SECRET_ACCESS_KEY)/i.test(entry.content) ||
167
+ /send\s+(all\s+)?(api\s+keys|secrets|tokens|credentials)\s+to\s+https?:\/\//i.test(entry.content)) {
168
+ findings.push({
169
+ entryId: entry.id,
170
+ patternId: "MEMORY_EXFILTRATION_DIRECTIVE",
171
+ patternName: "Persistent Memory Credential Exfiltration Directive",
172
+ severity: "critical",
173
+ description: "Memory payload attempts to persist credential or file exfiltration instructions across agent runs",
174
+ matchedText: entry.content.slice(0, 100),
175
+ timestamp: Date.now(),
176
+ });
177
+ }
178
+ const hasCritical = findings.some((f) => f.severity === "critical");
179
+ const hasHigh = findings.some((f) => f.severity === "high");
180
+ const hasMedium = findings.some((f) => f.severity === "medium");
181
+ const riskLevel = hasCritical
182
+ ? "critical"
183
+ : hasHigh
184
+ ? "high"
185
+ : hasMedium
186
+ ? "medium"
187
+ : findings.length > 0
188
+ ? "low"
189
+ : "none";
190
+ const safe = !hasCritical && !hasHigh;
191
+ if (params.recordInDetector !== false && safe) {
192
+ try {
193
+ this.contextPoisoningDetector.addEntry(entry);
194
+ }
195
+ catch {
196
+ // Ignore session capacity overflow in long-running processes
197
+ }
198
+ }
199
+ const integrity = this.contextPoisoningDetector.verifyIntegrity(safeAgentKey, safeSessionKey);
200
+ const integrityValid = typeof integrity === "boolean" ? integrity : Boolean(integrity?.valid ?? true);
201
+ return {
202
+ safe,
203
+ riskLevel,
204
+ findingsCount: findings.length,
205
+ findings: findings.map((f) => ({
206
+ patternId: String(f.patternId || ""),
207
+ patternName: String(f.patternName || ""),
208
+ severity: String(f.severity || ""),
209
+ description: String(f.description || ""),
210
+ })),
211
+ integrityValid,
212
+ };
213
+ }
214
+ getContextPoisoningReport(workspaceId, sessionId = "default") {
215
+ const safeAgentKey = workspaceId.replace(/[^a-zA-Z0-9_-]/g, "_");
216
+ const safeSessionKey = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
217
+ return this.contextPoisoningDetector.scan(safeAgentKey, safeSessionKey);
218
+ }
219
+ /**
220
+ * Extracts structured SQL, Kubernetes, and Infrastructure protocol facets from tool input.
221
+ */
222
+ extractActionFacets(tool, input) {
223
+ const rawContext = {};
224
+ // Detect SQL payload in input
225
+ const candidateSql = typeof input.sql === "string"
226
+ ? input.sql
227
+ : typeof input.statement === "string"
228
+ ? input.statement
229
+ : typeof input.query === "string" &&
230
+ (tool.slug.includes("sql") ||
231
+ tool.slug.includes("postgres") ||
232
+ tool.slug.includes("neon") ||
233
+ tool.slug.includes("turso") ||
234
+ tool.slug.includes("supabase") ||
235
+ tool.slug.includes("db") ||
236
+ /^\s*(SELECT|INSERT|UPDATE|DELETE|DROP|TRUNCATE|ALTER|CREATE|WITH)\b/i.test(input.query))
237
+ ? input.query
238
+ : null;
239
+ if (candidateSql) {
240
+ rawContext.sql = { query: candidateSql };
241
+ }
242
+ // Detect Kubernetes payload in input
243
+ const candidateK8sPath = typeof input.k8s_path === "string"
244
+ ? input.k8s_path
245
+ : typeof input.path === "string" &&
246
+ (input.path.startsWith("/api/v1/") ||
247
+ input.path.startsWith("/apis/"))
248
+ ? input.path
249
+ : null;
250
+ if (candidateK8sPath) {
251
+ rawContext.k8s = {
252
+ method: typeof input.method === "string" ? input.method : "GET",
253
+ path: candidateK8sPath,
254
+ };
255
+ }
256
+ else if (input.k8s &&
257
+ typeof input.k8s === "object" &&
258
+ !Array.isArray(input.k8s)) {
259
+ rawContext.k8s = input.k8s;
260
+ }
261
+ // Detect Infrastructure / Resource provisioning facets
262
+ if (tool.lane === "stripe_projects" ||
263
+ tool.slug.startsWith("resource.") ||
264
+ tool.riskLevel === "provisioning" ||
265
+ tool.riskLevel === "destructive") {
266
+ rawContext.infra = {
267
+ provider: tool.providerSlug,
268
+ service: tool.upstreamSlug,
269
+ action: tool.riskLevel,
270
+ destructive: tool.riskLevel === "destructive" ||
271
+ tool.slug.includes("delete") ||
272
+ tool.slug.includes("destroy"),
273
+ };
274
+ }
275
+ const extracted = extractProtocolFacets(rawContext, this.facetRegistry);
276
+ const result = {};
277
+ if (extracted.sql) {
278
+ const sqlVerb = String(extracted.sql.verb || "UNKNOWN").toUpperCase();
279
+ const isDestructiveSql = sqlVerb === "DROP" ||
280
+ sqlVerb === "TRUNCATE" ||
281
+ (sqlVerb === "UNKNOWN" && Boolean(candidateSql?.includes(";"))) ||
282
+ (sqlVerb === "DELETE" &&
283
+ Boolean(candidateSql) &&
284
+ !/\bWHERE\b/i.test(candidateSql || ""));
285
+ result.sql = {
286
+ verb: sqlVerb,
287
+ target: String(extracted.sql.target || ""),
288
+ tables: String(extracted.sql.tables || ""),
289
+ functions: String(extracted.sql.functions || ""),
290
+ destructive: isDestructiveSql,
291
+ };
292
+ }
293
+ if (extracted.k8s) {
294
+ result.k8s = {
295
+ verb: String(extracted.k8s.verb || ""),
296
+ resource: String(extracted.k8s.resource || ""),
297
+ namespace: String(extracted.k8s.namespace || ""),
298
+ name: String(extracted.k8s.name || ""),
299
+ subresource: String(extracted.k8s.subresource || ""),
300
+ };
301
+ }
302
+ if (extracted.infra) {
303
+ result.infra = {
304
+ provider: String(extracted.infra.provider || tool.providerSlug),
305
+ service: String(extracted.infra.service || tool.upstreamSlug),
306
+ action: String(extracted.infra.action || tool.riskLevel),
307
+ destructive: Boolean(extracted.infra.destructive),
308
+ };
309
+ }
310
+ return result;
311
+ }
312
+ /**
313
+ * Evaluates hardware-style privilege rings (Ring 0..Ring 3) via Microsoft RingEnforcer.
314
+ */
315
+ evaluateRingEnforcement(workspace, tool, ownerApproved) {
316
+ const requiredRing = requiredRingForRisk(tool.riskLevel);
317
+ const policy = workspace.policy;
318
+ const requiresApproval = policy.mode === "enforce" &&
319
+ (policy.requireApprovalFor || []).includes(tool.riskLevel);
320
+ const agentRing = ownerApproved
321
+ ? ExecutionRing.Ring0
322
+ : policy.executionRing !== undefined
323
+ ? policy.executionRing
324
+ : requiresApproval
325
+ ? ExecutionRing.Ring2
326
+ : requiredRing;
327
+ const enforcer = new RingEnforcer({
328
+ agentRing,
329
+ defaultRing: ExecutionRing.Ring3,
330
+ actionRings: {
331
+ "read:*": ExecutionRing.Ring3,
332
+ "write:*": ExecutionRing.Ring2,
333
+ "admin:*": ExecutionRing.Ring1,
334
+ "financial:*": ExecutionRing.Ring1,
335
+ "provisioning:*": ExecutionRing.Ring1,
336
+ "destructive:*": ExecutionRing.Ring0,
337
+ },
338
+ });
339
+ const actionKey = `${tool.riskLevel}:${tool.slug}`;
340
+ const allowed = enforcer.canExecute(actionKey);
341
+ return {
342
+ agentRing,
343
+ requiredRing,
344
+ allowed,
345
+ ringLabel: RING_LABELS[requiredRing] || `Ring ${requiredRing}`,
346
+ };
347
+ }
348
+ /**
349
+ * Records an agent execution outcome in the Bayesian TrustManager and returns the updated TrustScore.
350
+ */
351
+ recordAgentOutcome(workspaceId, succeeded, weight = 0.05) {
352
+ if (succeeded) {
353
+ this.trustManager.recordSuccess(workspaceId, weight);
354
+ }
355
+ else {
356
+ this.trustManager.recordFailure(workspaceId, weight * 2);
357
+ }
358
+ return this.trustManager.getTrustScore(workspaceId);
359
+ }
360
+ /**
361
+ * Returns the current Bayesian TrustScore for a workspace agent boundary.
362
+ */
363
+ getWorkspaceTrustScore(workspaceId) {
364
+ const score = this.trustManager.getTrustScore(workspaceId);
365
+ return {
366
+ overall: Number(score.overall.toFixed(4)),
367
+ tier: score.tier,
368
+ reliability: Number(score.dimensions.reliability.toFixed(4)),
369
+ consistency: Number(score.dimensions.consistency.toFixed(4)),
370
+ };
371
+ }
372
+ /**
373
+ * Activates the emergency KillSwitch for a workspace agent boundary.
374
+ */
375
+ async activateKillSwitch(workspaceId, reason, action = "quarantine") {
376
+ const result = await this.killSwitch.kill(workspaceId, {
377
+ action,
378
+ reason: reason || "Emergency kill-switch activated by workspace operator",
379
+ });
380
+ this.activeKillSwitches.set(workspaceId, result);
381
+ this.trustManager.recordFailure(workspaceId, 0.25);
382
+ return result;
383
+ }
384
+ /**
385
+ * Resumes a workspace agent boundary after a KillSwitch quarantine/suspension.
386
+ */
387
+ resumeKillSwitch(workspaceId) {
388
+ const existed = this.activeKillSwitches.delete(workspaceId);
389
+ return {
390
+ resumed: existed,
391
+ workspaceId,
392
+ resumedAt: new Date().toISOString(),
393
+ };
394
+ }
395
+ isKillSwitchActive(workspaceId) {
396
+ return this.activeKillSwitches.get(workspaceId) || null;
397
+ }
97
398
  /**
98
399
  * Compiles the workspace's GovernancePolicy into a declarative Microsoft PolicyEngine instance.
99
400
  */
100
401
  createPolicyEngine(policy) {
101
402
  const engine = new PolicyEngine();
102
403
  const rules = [];
404
+ if (policy.killSwitchActive) {
405
+ rules.push({
406
+ name: "deny-kill-switch-active",
407
+ ruleAction: "deny",
408
+ priority: 200,
409
+ condition: {
410
+ workspace_active: true,
411
+ },
412
+ });
413
+ }
103
414
  for (const blockedSlug of policy.blockedToolSlugs || []) {
104
415
  const normalized = blockedSlug.trim();
105
416
  if (!normalized)
@@ -113,6 +424,44 @@ export class MicrosoftGovernanceAdapter {
113
424
  },
114
425
  });
115
426
  }
427
+ if (policy.mode === "enforce" && policy.blockDestructiveSql !== false) {
428
+ rules.push({
429
+ name: "deny-multi-statement-sql-injection",
430
+ ruleAction: "deny",
431
+ priority: 96,
432
+ condition: {
433
+ "sql.verb": "UNKNOWN",
434
+ "sql.destructive": true,
435
+ },
436
+ });
437
+ rules.push({
438
+ name: "require-approval-destructive-sql-drop",
439
+ ruleAction: "require_approval",
440
+ priority: 94,
441
+ condition: {
442
+ "sql.verb": "DROP",
443
+ owner_approved: false,
444
+ },
445
+ });
446
+ rules.push({
447
+ name: "require-approval-destructive-sql-truncate",
448
+ ruleAction: "require_approval",
449
+ priority: 94,
450
+ condition: {
451
+ "sql.verb": "TRUNCATE",
452
+ owner_approved: false,
453
+ },
454
+ });
455
+ rules.push({
456
+ name: "deny-k8s-delete-kube-system",
457
+ ruleAction: "deny",
458
+ priority: 95,
459
+ condition: {
460
+ "k8s.verb": "delete",
461
+ "k8s.namespace": "kube-system",
462
+ },
463
+ });
464
+ }
116
465
  if (policy.mode === "enforce") {
117
466
  for (const risk of policy.requireApprovalFor || []) {
118
467
  rules.push({
@@ -147,24 +496,38 @@ export class MicrosoftGovernanceAdapter {
147
496
  }
148
497
  /**
149
498
  * Runs the full Microsoft Agent Governance pipeline:
150
- * Agent ──► McpSecurityScanner ──► PolicyEngine ──► AgentIdentity (Ed25519 DID) ──► AuditLogger ──► DecisionRecord
499
+ * Agent ──► KillSwitch ──► McpSecurityScanner & ContextPoisoningDetector (ASI-06) ──► ProtocolFacets (SQL/K8s/Infra) ──► RingEnforcer ──► PolicyEngine ──► TrustManager ──► AgentIdentity (Ed25519 DID) ──► AuditLogger ──► DecisionRecord
151
500
  */
152
501
  evaluateAction(params) {
153
502
  const { workspace, actorId, tool, input, reason, stage } = params;
154
503
  const ownerApproved = Boolean(params.ownerApproved);
155
504
  const decidedAt = new Date().toISOString();
156
- // 1. McpSecurityScanner: inspect tool definition + input arguments for prompt injection / exfiltration
505
+ // 1. McpSecurityScanner + ContextPoisoningDetector (OWASP ASI-06): inspect tool definition + input arguments
157
506
  const serializedInput = JSON.stringify(input || {});
158
507
  const scanResult = this.scanner.scan({
159
508
  name: tool.slug,
160
509
  description: `${tool.description}\nReason: ${reason}\nArgs: ${serializedInput}`,
161
510
  parameters: tool.inputSchema,
162
511
  });
163
- const extraFindings = (scanResult.threats || []).map((t) => ({
164
- category: String(t.type || "mcp_scan"),
165
- severity: String(t.severity || "medium"),
166
- description: String(t.description || "Security scanner finding"),
167
- }));
512
+ const contextPoisoning = this.scanMemoryContent({
513
+ workspaceId: workspace.id,
514
+ sessionId: stage,
515
+ role: "user",
516
+ content: `${reason}\n${serializedInput}`,
517
+ recordInDetector: false,
518
+ });
519
+ const extraFindings = [
520
+ ...(scanResult.threats || []).map((t) => ({
521
+ category: String(t.type || "mcp_scan"),
522
+ severity: String(t.severity || "medium"),
523
+ description: String(t.description || "Security scanner finding"),
524
+ })),
525
+ ...contextPoisoning.findings.map((f) => ({
526
+ category: `asi06_${f.patternId.toLowerCase()}`,
527
+ severity: f.severity,
528
+ description: `${f.patternName}: ${f.description}`,
529
+ })),
530
+ ];
168
531
  // Additional argument-level prompt-injection / secret-exfiltration heuristics
169
532
  const suspiciousPatterns = [
170
533
  {
@@ -190,8 +553,15 @@ export class MicrosoftGovernanceAdapter {
190
553
  }
191
554
  }
192
555
  const highSeverityFinding = extraFindings.some((f) => f.severity === "high" || f.severity === "critical");
193
- // 2. PolicyEngine: evaluate declarative rules against tool slug, risk level, and approval state
556
+ // 2. Protocol Facets Extraction (SQL, Kubernetes, Infrastructure)
557
+ const protocolFacets = this.extractActionFacets(tool, input);
558
+ // 3. Hardware-style Execution Ring Enforcement (Ring 0..Ring 3)
559
+ const ringEnforcement = this.evaluateRingEnforcement(workspace, tool, ownerApproved);
560
+ // 4. PolicyEngine + KillSwitch evaluation
194
561
  const policy = workspace.policy;
562
+ const activeKill = this.isKillSwitchActive(workspace.id);
563
+ const killSwitchActive = Boolean(activeKill || policy.killSwitchActive);
564
+ const killSwitchReason = activeKill?.reason || policy.killSwitchReason || null;
195
565
  const policyEngine = this.createPolicyEngine(policy);
196
566
  const identity = this.getWorkspaceIdentity(workspace);
197
567
  const policyDecision = policyEngine.evaluatePolicy(identity.did, {
@@ -201,18 +571,36 @@ export class MicrosoftGovernanceAdapter {
201
571
  stage,
202
572
  owner_approved: ownerApproved,
203
573
  workspace_active: true,
574
+ ...(protocolFacets.sql ? { sql: protocolFacets.sql } : {}),
575
+ ...(protocolFacets.k8s ? { k8s: protocolFacets.k8s } : {}),
576
+ ...(protocolFacets.infra ? { infra: protocolFacets.infra } : {}),
204
577
  });
205
578
  let finalDecision = policyDecision.action === "deny"
206
579
  ? "deny"
207
580
  : policyDecision.action === "require_approval"
208
581
  ? "require_approval"
209
582
  : "allow";
210
- // Block explicitly blocked tools even in monitor mode, or high-severity injection findings in enforce mode
211
- if ((policy.blockedToolSlugs || []).includes(tool.slug) ||
212
- (highSeverityFinding && policy.mode === "enforce")) {
583
+ let matchedRule = policyDecision.matchedRule ?? null;
584
+ // Enforce KillSwitch, blocked tools, high-severity scanner/context-poisoning findings, or Ring breach
585
+ if (killSwitchActive) {
586
+ finalDecision = "deny";
587
+ matchedRule = "kill-switch-emergency-quarantine";
588
+ }
589
+ else if ((policy.blockedToolSlugs || []).includes(tool.slug)) {
213
590
  finalDecision = "deny";
591
+ matchedRule = matchedRule || `deny-blocked-tool-${tool.slug}`;
592
+ }
593
+ else if (highSeverityFinding && policy.mode === "enforce") {
594
+ finalDecision = "deny";
595
+ matchedRule = "mcp-security-scanner-high-severity";
596
+ this.trustManager.recordFailure(workspace.id, 0.1);
597
+ }
598
+ else if (!ringEnforcement.allowed && finalDecision === "allow" && policy.mode === "enforce") {
599
+ finalDecision = "require_approval";
600
+ matchedRule = `ring-enforcer-requires-ring-${ringEnforcement.requiredRing}`;
214
601
  }
215
- // 3. AuditLogger: append tamper-evident SHA-256 hash-chained log entry
602
+ const trustScore = this.getWorkspaceTrustScore(workspace.id);
603
+ // 5. AuditLogger: append tamper-evident SHA-256 hash-chained log entry
216
604
  const auditLogger = this.getWorkspaceAuditLogger(workspace.id);
217
605
  const auditDecision = finalDecision === "deny" ? "deny" : "allow";
218
606
  const auditEntry = auditLogger.log({
@@ -222,11 +610,13 @@ export class MicrosoftGovernanceAdapter {
222
610
  skillAuditMetadata: {
223
611
  skillName: tool.slug,
224
612
  skillOrigin: tool.lane,
225
- provenanceSourceTrust: "trusted",
613
+ provenanceSourceTrust: trustScore.tier === "Verified" || trustScore.tier === "Trusted"
614
+ ? "trusted"
615
+ : undefined,
226
616
  },
227
617
  });
228
618
  const chainVerified = auditLogger.verify();
229
- // 4. AgentIdentity (Ed25519 DID): cryptographically sign the decision record
619
+ // 6. AgentIdentity (Ed25519 DID): cryptographically sign the decision record
230
620
  const bindingHash = crypto
231
621
  .createHash("sha256")
232
622
  .update(JSON.stringify({
@@ -259,12 +649,14 @@ export class MicrosoftGovernanceAdapter {
259
649
  const publicKeyHex = Buffer.from(identity.publicKey).toString("hex");
260
650
  const verdict = finalDecision === "require_approval" ? "escalate" : finalDecision;
261
651
  const decisionReason = finalDecision === "deny"
262
- ? highSeverityFinding
263
- ? `Blocked by McpSecurityScanner: ${extraFindings.map((f) => f.description).join("; ")}`
264
- : `Denied by policy rule ${policyDecision.matchedRule || "default"}`
652
+ ? killSwitchActive
653
+ ? `Blocked by Emergency KillSwitch: ${killSwitchReason || "Workspace agent boundary is quarantined"}`
654
+ : highSeverityFinding
655
+ ? `Blocked by McpSecurityScanner / ContextPoisoningDetector: ${extraFindings.map((f) => f.description).join("; ")}`
656
+ : `Denied by policy rule ${matchedRule || "default"}`
265
657
  : finalDecision === "require_approval"
266
- ? `Escalated for human owner approval (${tool.riskLevel} risk lane)`
267
- : `Allowed by Microsoft Agent Governance (${policyDecision.matchedRule || "allow-governed-action"})`;
658
+ ? `Escalated for human owner approval (${tool.riskLevel} risk lane, ${ringEnforcement.ringLabel})`
659
+ : `Allowed by Microsoft Agent Governance (${matchedRule || "allow-governed-action"})`;
268
660
  return {
269
661
  id: `dec_${crypto.randomBytes(8).toString("hex")}`,
270
662
  sdk: "@microsoft/agent-governance-sdk",
@@ -280,12 +672,12 @@ export class MicrosoftGovernanceAdapter {
280
672
  decision: finalDecision,
281
673
  verdict,
282
674
  reason: decisionReason,
283
- matchedRule: policyDecision.matchedRule ?? null,
675
+ matchedRule,
284
676
  securityScan: {
285
- safe: scanResult.safe && !highSeverityFinding,
677
+ safe: scanResult.safe && !highSeverityFinding && contextPoisoning.safe,
286
678
  riskLevel: highSeverityFinding
287
679
  ? "high"
288
- : scanResult.risk_score > 50
680
+ : scanResult.risk_score > 50 || contextPoisoning.findingsCount > 0
289
681
  ? "medium"
290
682
  : "low",
291
683
  findingsCount: extraFindings.length,
@@ -300,6 +692,20 @@ export class MicrosoftGovernanceAdapter {
300
692
  previousHash: auditEntry.previousHash,
301
693
  chainVerified,
302
694
  },
695
+ protocolFacets,
696
+ ringEnforcement,
697
+ trustScore,
698
+ contextPoisoning: {
699
+ safe: contextPoisoning.safe,
700
+ riskLevel: contextPoisoning.riskLevel,
701
+ findingsCount: contextPoisoning.findingsCount,
702
+ findings: contextPoisoning.findings,
703
+ },
704
+ killSwitch: {
705
+ active: killSwitchActive,
706
+ killedAt: activeKill?.killedAt || null,
707
+ reason: killSwitchReason,
708
+ },
303
709
  ed25519Signature,
304
710
  signature: ed25519Signature,
305
711
  bindingHash,
@@ -398,13 +804,41 @@ export class MicrosoftGovernanceAdapter {
398
804
  const identity = this.getWorkspaceIdentity(workspace);
399
805
  const auditLogger = this.getWorkspaceAuditLogger(workspace.id);
400
806
  const entries = auditLogger.getEntries();
807
+ const activeKill = this.isKillSwitchActive(workspace.id);
808
+ const killSwitchActive = Boolean(activeKill || workspace.policy.killSwitchActive);
809
+ const contextPoisoningReport = this.getContextPoisoningReport(workspace.id, "default");
401
810
  return {
402
811
  sdk: "@microsoft/agent-governance-sdk",
403
812
  sdkVersion: SDK_VERSION,
404
813
  policyId: POLICY_ID,
405
- pipeline: "Agent ──► McpSecurityScanner ──► PolicyEngine ──► AgentIdentity (Ed25519 DID) ──► AuditLogger ──► DecisionRecord",
814
+ pipeline: "Agent ──► KillSwitch ──► McpSecurityScanner & ContextPoisoningDetector (ASI-06) ──► ProtocolFacets (SQL/K8s/Infra) ──► RingEnforcer ──► PolicyEngine ──► TrustManager ──► AgentIdentity (Ed25519 DID) ──► AuditLogger ──► DecisionRecord",
815
+ modules: [
816
+ "McpSecurityScanner",
817
+ "ContextPoisoningDetector",
818
+ "ProtocolFacets",
819
+ "RingEnforcer",
820
+ "PolicyEngine",
821
+ "TrustManager",
822
+ "KillSwitch",
823
+ "AgentIdentity",
824
+ "AuditLogger",
825
+ ],
406
826
  agentIdentity: identity.toJSON(),
407
827
  policy: workspace.policy,
828
+ trustScore: this.getWorkspaceTrustScore(workspace.id),
829
+ killSwitch: {
830
+ active: killSwitchActive,
831
+ killedAt: activeKill?.killedAt || null,
832
+ reason: activeKill?.reason || workspace.policy.killSwitchReason || null,
833
+ historyCount: this.killSwitch.getHistory().length,
834
+ },
835
+ contextPoisoning: {
836
+ poisoned: Boolean(contextPoisoningReport.poisoned ??
837
+ (contextPoisoningReport.findings?.length > 0)),
838
+ riskScore: Number(contextPoisoningReport.riskScore ?? 0),
839
+ findingsCount: contextPoisoningReport.findings.length,
840
+ findings: contextPoisoningReport.findings.slice(-10),
841
+ },
408
842
  auditChain: {
409
843
  entriesCount: entries.length,
410
844
  chainVerified: auditLogger.verify(),
@@ -192,10 +192,20 @@ export class StripeBillingAdapter {
192
192
  const prices = await this.ensurePrices(params.workspace.id);
193
193
  const form = new URLSearchParams();
194
194
  form.set("mode", params.kind === "starter_subscription" ? "subscription" : "payment");
195
- form.set("line_items[0][price]", params.kind === "starter_subscription"
196
- ? prices.starterPriceId
197
- : prices.creditsPriceId);
198
- form.set("line_items[0][quantity]", "1");
195
+ if (params.kind === "starter_subscription") {
196
+ form.set("line_items[0][price]", prices.starterPriceId);
197
+ form.set("line_items[0][quantity]", "1");
198
+ }
199
+ else if (creditsAmount === 1000) {
200
+ form.set("line_items[0][price]", prices.creditsPriceId);
201
+ form.set("line_items[0][quantity]", "1");
202
+ }
203
+ else {
204
+ form.set("line_items[0][price_data][currency]", "usd");
205
+ form.set("line_items[0][price_data][unit_amount]", String(Math.max(50, Math.round(creditsAmount))));
206
+ form.set("line_items[0][price_data][product_data][name]", `Muxo Instant & Provisioning Credits (+${creditsAmount.toLocaleString()} Credits)`);
207
+ form.set("line_items[0][quantity]", "1");
208
+ }
199
209
  form.set("client_reference_id", params.workspace.id);
200
210
  form.set("customer_email", params.customerEmail);
201
211
  form.set("metadata[workspace_id]", params.workspace.id);
@@ -1,5 +1,6 @@
1
1
  import { type MuxoConfig } from "../config.js";
2
2
  import type { MuxoTool } from "../types.js";
3
+ export declare function isPaidCloudProvisioning(tool: MuxoTool, input?: Record<string, unknown>): boolean;
3
4
  export declare class StripeProjectsAdapter {
4
5
  private readonly config;
5
6
  private readonly tools;
@@ -32,11 +33,13 @@ export declare class StripeProjectsAdapter {
32
33
  redirectUrl: string | null;
33
34
  message: string;
34
35
  }>;
35
- pullEnvVarsFromWorkdir(): Promise<Record<string, string>>;
36
+ pullEnvVarsFromWorkdir(syncFromCli?: boolean): Promise<Record<string, string>>;
36
37
  executeTool(params: {
37
38
  workspaceId: string;
38
39
  tool: MuxoTool;
39
40
  input: Record<string, unknown>;
41
+ stripeApiKey?: string | null;
42
+ masterWalletDepleted?: boolean;
40
43
  }): Promise<{
41
44
  output: Record<string, unknown>;
42
45
  provisionedResource?: {