@highflame/policy 2.2.35 → 2.2.37

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 (78) hide show
  1. package/_schemas/agent_ops/context.json +822 -0
  2. package/_schemas/agent_ops/schema.cedarschema +134 -109
  3. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_a2a_cross_origin.cedar +6 -4
  4. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_a2a_escalation.cedar +5 -4
  5. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_a2a_inter_agent_injection.cedar +9 -8
  6. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_claude_block_injection.cedar +2 -2
  7. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_defaults.cedar +3 -3
  8. package/_schemas/agent_ops/templates/ported/agent-security/agent_identity_multi_agent_trust.cedar +6 -6
  9. package/_schemas/agent_ops/templates/ported/content-safety/trust_safety_chat_assistant.cedar +5 -4
  10. package/_schemas/agent_ops/templates/ported/content-safety/trust_safety_defaults.cedar +18 -12
  11. package/_schemas/agent_ops/templates/ported/content-safety/trust_safety_semantic.cedar +6 -6
  12. package/_schemas/agent_ops/templates/ported/content-safety/trust_safety_toxicity.cedar +4 -4
  13. package/_schemas/agent_ops/templates/ported/data-protection/data_protection_advanced_secrets.cedar +4 -2
  14. package/_schemas/agent_ops/templates/ported/data-protection/data_protection_data_pipeline.cedar +2 -1
  15. package/_schemas/agent_ops/templates/ported/data-protection/data_protection_defaults.cedar +4 -2
  16. package/_schemas/agent_ops/templates/ported/data-protection/privacy_advanced_pii.cedar +42 -21
  17. package/_schemas/agent_ops/templates/ported/data-protection/privacy_defaults.cedar +14 -7
  18. package/_schemas/agent_ops/templates/ported/data-protection/privacy_pii_model.cedar +10 -5
  19. package/_schemas/agent_ops/templates/ported/organization/organization_team_permissions.cedar +3 -2
  20. package/_schemas/agent_ops/templates/ported/threat-detection/security_advanced_block_critical_severity.cedar +3 -3
  21. package/_schemas/agent_ops/templates/ported/threat-detection/security_chat_assistant.cedar +5 -4
  22. package/_schemas/agent_ops/templates/ported/threat-detection/security_data_pipeline_block_injection.cedar +3 -2
  23. package/_schemas/agent_ops/templates/ported/threat-detection/security_injection.cedar +9 -8
  24. package/_schemas/agent_ops/templates/ported/threat-detection/security_patterns.cedar +5 -3
  25. package/_schemas/agent_ops/templates/ported/threat-detection/semantic_defaults.cedar +9 -7
  26. package/_schemas/ai_gateway/context.json +308 -0
  27. package/_schemas/ai_gateway/schema.cedarschema +44 -7
  28. package/_schemas/ai_gateway/templates/defaults/agent_security.cedar +5 -16
  29. package/_schemas/ai_gateway/templates/defaults/pii.cedar +14 -7
  30. package/_schemas/ai_gateway/templates/defaults/pii_advanced.cedar +42 -21
  31. package/_schemas/ai_gateway/templates/defaults/pii_model.cedar +10 -5
  32. package/_schemas/ai_gateway/templates/defaults/semantic.cedar +9 -74
  33. package/_schemas/ai_gateway/templates/defaults/tools.cedar +7 -38
  34. package/_schemas/ai_gateway/templates/secrets.cedar +3 -3
  35. package/_schemas/guardrails/context.json +701 -0
  36. package/_schemas/guardrails/schema.cedarschema +30 -2
  37. package/_schemas/guardrails/templates/defaults/agent_identity.cedar +3 -3
  38. package/_schemas/guardrails/templates/defaults/injection.cedar +9 -8
  39. package/_schemas/guardrails/templates/defaults/pii.cedar +14 -7
  40. package/_schemas/guardrails/templates/defaults/pii_model.cedar +10 -5
  41. package/_schemas/guardrails/templates/defaults/secrets.cedar +4 -2
  42. package/_schemas/guardrails/templates/defaults/security_patterns.cedar +5 -3
  43. package/_schemas/guardrails/templates/defaults/semantic.cedar +6 -6
  44. package/_schemas/guardrails/templates/defaults/toxicity.cedar +6 -6
  45. package/_schemas/guardrails/templates/profiles/a2a_security/cross_origin.cedar +6 -4
  46. package/_schemas/guardrails/templates/profiles/a2a_security/escalation_detection.cedar +5 -4
  47. package/_schemas/guardrails/templates/profiles/a2a_security/inter_agent_injection.cedar +9 -8
  48. package/_schemas/guardrails/templates/profiles/advanced_detection/pii.cedar +42 -21
  49. package/_schemas/guardrails/templates/profiles/advanced_detection/secrets.cedar +4 -2
  50. package/_schemas/guardrails/templates/profiles/chat_assistant/security.cedar +5 -4
  51. package/_schemas/guardrails/templates/profiles/chat_assistant/trust_safety.cedar +5 -4
  52. package/_schemas/guardrails/templates/profiles/data_pipeline/data_protection.cedar +2 -1
  53. package/_schemas/guardrails/templates/profiles/data_pipeline/security.cedar +3 -2
  54. package/_schemas/guardrails/templates/profiles/multi_agent/agent_trust.cedar +6 -6
  55. package/_schemas/guardrails/templates/templates.json +0 -9
  56. package/_schemas/overwatch/context.json +30 -0
  57. package/_schemas/overwatch/schema.cedarschema +7 -0
  58. package/dist/agent_ops-context.gen.d.ts +6 -1
  59. package/dist/agent_ops-context.gen.js +10 -0
  60. package/dist/agent_ops-defaults.gen.js +177 -120
  61. package/dist/agent_ops-entities.gen.js +5 -1
  62. package/dist/ai_gateway-context.gen.d.ts +6 -1
  63. package/dist/ai_gateway-context.gen.js +10 -0
  64. package/dist/ai_gateway-defaults.gen.js +90 -164
  65. package/dist/ai_gateway-detectors.gen.js +6 -1
  66. package/dist/ai_gateway-entities.gen.js +6 -2
  67. package/dist/guardrails-context.gen.d.ts +6 -1
  68. package/dist/guardrails-context.gen.js +10 -0
  69. package/dist/guardrails-defaults.gen.js +144 -145
  70. package/dist/guardrails-detectors.gen.js +6 -1
  71. package/dist/guardrails-entities.gen.js +5 -1
  72. package/dist/overwatch-context.gen.d.ts +6 -1
  73. package/dist/overwatch-context.gen.js +10 -0
  74. package/dist/overwatch-detectors.gen.js +6 -1
  75. package/dist/service-schemas.gen.d.ts +4 -4
  76. package/dist/service-schemas.gen.js +528 -118
  77. package/package.json +1 -1
  78. package/_schemas/guardrails/templates/profiles/advanced_detection/threat_severity.cedar +0 -30
@@ -78,13 +78,23 @@ namespace AgentOps {
78
78
  // Actions
79
79
  // =========================================================================
80
80
 
81
- /// Process user prompts and AI responses for security threats and content violations
81
+ /// Process user prompts for security threats and content violations
82
82
  action "process_prompt" appliesTo {
83
83
  principal: [User, Agent],
84
84
  resource: [App, Agent, Session],
85
85
  context: ProcessPromptContext
86
86
  };
87
87
 
88
+ /// Process model responses for security threats and content violations.
89
+ /// Distinct trigger from process_prompt (ADR 0031). Declared ahead of a
90
+ /// caller: no AgentOps producer emits model responses today, so this is
91
+ /// namespace symmetry with ai_gateway/guardrails until one does.
92
+ action "process_response" appliesTo {
93
+ principal: [User, Agent],
94
+ resource: [App, Agent, Session],
95
+ context: ProcessResponseContext
96
+ };
97
+
88
98
  /// Execute tool calls (shell, file operations, MCP tools)
89
99
  action "call_tool" appliesTo {
90
100
  principal: [User, Agent],
@@ -130,7 +140,15 @@ namespace AgentOps {
130
140
  // Context Types (Action-Specific)
131
141
  // =========================================================================
132
142
 
133
- /// Context for process_prompt action (user prompts & AI responses)
143
+ /// Context for the process_response action.
144
+ ///
145
+ /// An alias, not a copy: prompts and responses are inspected by the same
146
+ /// detector pipeline and carry the same keys — only the trigger differs
147
+ /// (ADR 0031). Aliasing means a new detector key cannot land on one
148
+ /// direction and go missing on the other.
149
+ type ProcessResponseContext = ProcessPromptContext;
150
+
151
+ /// Context for process_prompt action (user prompts)
134
152
  type ProcessPromptContext = {
135
153
  // Identity (AARM R6 / CAP-IDN-011) — projected from the principal's token; optional.
136
154
  "role"?: String,
@@ -166,12 +184,12 @@ namespace AgentOps {
166
184
  "indirect_injection_score"?: Long, // Indirect injection via tool outputs (0-100)
167
185
 
168
186
  // Privacy - Secrets (optional)
169
- "secrets_detected"?: Boolean,
187
+ "secrets_detected"?: Bool,
170
188
  "secret_count"?: Long,
171
189
  "secret_types"?: Set<String>, // ["aws_access_key", "github_token", ...]
172
190
 
173
191
  // Privacy - PII (optional)
174
- "pii_detected"?: Boolean,
192
+ "pii_detected"?: Bool,
175
193
  "pii_count"?: Long,
176
194
  "pii_types"?: Set<String>, // ["email", "phone", "ssn", "credit_card", ...]
177
195
  "pii_score"?: Long, // PII ML classifier confidence (0-100)
@@ -195,65 +213,65 @@ namespace AgentOps {
195
213
  "topic_confidence"?: Long, // 0-100
196
214
 
197
215
  // Security - Invisible Character Detection (optional)
198
- "invisible_chars_detected"?: Boolean,
216
+ "invisible_chars_detected"?: Bool,
199
217
  "invisible_chars_score"?: Long, // 0-100
200
218
 
201
219
  // Security - Pattern Detection (optional)
202
- "command_injection_detected"?: Boolean,
220
+ "command_injection_detected"?: Bool,
203
221
  "command_injection_type"?: String, // "reverse_shell" | "privilege_escalation" | ...
204
222
  "command_injection_score"?: Long, // 0-100
205
- "path_traversal_detected"?: Boolean,
223
+ "path_traversal_detected"?: Bool,
206
224
  "path_traversal_severity"?: String, // "critical" | "high" | "medium" | "low" | "none"
207
225
  "path_traversal_type"?: String,
208
- "sql_injection_detected"?: Boolean,
226
+ "sql_injection_detected"?: Bool,
209
227
  "sql_injection_type"?: String, // "tautology" | "union_based" | "destructive" | ...
210
228
  "sql_injection_score"?: Long, // 0-100
211
229
 
212
230
  // Security - Cross-Origin Escalation (optional)
213
- "cross_origin_detected"?: Boolean,
231
+ "cross_origin_detected"?: Bool,
214
232
  "cross_origin_type"?: String, // "cross_origin_tool" | "cross_origin_server" | "none"
215
233
  "cross_origin_score"?: Long, // 0-100
216
234
 
217
235
  // Security - Encoded Injection (optional)
218
- "encoded_content_detected"?: Boolean,
236
+ "encoded_content_detected"?: Bool,
219
237
  "encoded_types"?: Set<String>, // ["base64", "hex", "unicode", "url", ...]
220
238
  "encoded_count"?: Long,
221
239
  "encoded_score"?: Long, // 0-100
222
240
 
223
241
  // Language & Script Detection (optional)
224
242
  "detected_language"?: String, // ISO language code
225
- "is_english"?: Boolean,
243
+ "is_english"?: Bool,
226
244
  "language_confidence"?: Long, // 0-100
227
245
  "detected_script"?: String, // "latin" | "cyrillic" | "arabic" | "unknown" | ...
228
- "is_latin_script"?: Boolean,
246
+ "is_latin_script"?: Bool,
229
247
  "script_confidence"?: Long, // 0-100
230
248
 
231
249
  // Content Analysis (optional)
232
250
  "hallucination_score"?: Long,
233
251
  "factuality_score"?: Long, // 0-100
234
252
  "sentiment_score"?: Long,
235
- "contains_code"?: Boolean,
253
+ "contains_code"?: Bool,
236
254
  "code_languages"?: Set<String>,
237
255
  "code_ratio"?: Long, // 0-100
238
- "keyword_matched"?: Boolean,
256
+ "keyword_matched"?: Bool,
239
257
  "keyword_categories"?: Set<String>,
240
258
  "keyword_count"?: Long,
241
- "contains_non_ascii"?: Boolean,
242
- "phishing_detected"?: Boolean,
259
+ "contains_non_ascii"?: Bool,
260
+ "phishing_detected"?: Bool,
243
261
  "content_safety_score"?: Long, // 0-100
244
- "content_safety_blocked"?: Boolean,
262
+ "content_safety_blocked"?: Bool,
245
263
 
246
264
  // Agentic - Multi-Turn Context (optional)
247
265
  "conversation_turn"?: Long,
248
- "multi_turn_detection"?: Boolean,
266
+ "multi_turn_detection"?: Bool,
249
267
 
250
268
  // Session Detection History — cross-turn sticky flags (optional)
251
- "session_pii_detected"?: Boolean,
269
+ "session_pii_detected"?: Bool,
252
270
  "session_pii_types"?: Set<String>,
253
- "session_secrets_detected"?: Boolean,
271
+ "session_secrets_detected"?: Bool,
254
272
  "session_secret_types"?: Set<String>,
255
- "session_injection_detected"?: Boolean,
256
- "session_command_injection"?: Boolean,
273
+ "session_injection_detected"?: Bool,
274
+ "session_command_injection"?: Bool,
257
275
  "session_threat_turns"?: Long,
258
276
  "session_max_injection_score"?: Long,
259
277
  "session_max_jailbreak_score"?: Long,
@@ -283,14 +301,14 @@ namespace AgentOps {
283
301
  "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
284
302
  "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
285
303
  "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
286
- "flow_sink_is_external"?: Boolean,
304
+ "flow_sink_is_external"?: Bool,
287
305
  "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
288
306
  "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
289
307
  "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
290
308
 
291
309
  // Usage Budget — multi-window token & cost enforcement (optional)
292
310
  "budget_remaining_pct"?: Long,
293
- "budget_exceeded"?: Boolean,
311
+ "budget_exceeded"?: Bool,
294
312
  "budget_cost_micros_this_turn"?: Long,
295
313
  "budget_model"?: String,
296
314
  "budget_tokens_pct_session"?: Long,
@@ -298,15 +316,15 @@ namespace AgentOps {
298
316
  "budget_tokens_pct_monthly"?: Long,
299
317
  "budget_cost_pct_daily"?: Long,
300
318
  "budget_cost_pct_monthly"?: Long,
301
- "budget_exceeded_session"?: Boolean,
302
- "budget_exceeded_daily"?: Boolean,
303
- "budget_exceeded_monthly"?: Boolean,
319
+ "budget_exceeded_session"?: Bool,
320
+ "budget_exceeded_daily"?: Bool,
321
+ "budget_exceeded_monthly"?: Bool,
304
322
 
305
323
  // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
306
324
  "rpm_remaining_pct"?: Long,
307
- "rpm_exceeded"?: Boolean,
325
+ "rpm_exceeded"?: Bool,
308
326
  "tpm_remaining_pct"?: Long,
309
- "tpm_exceeded"?: Boolean,
327
+ "tpm_exceeded"?: Bool,
310
328
 
311
329
  // Agent Identity — authenticated agent principal metadata (optional)
312
330
  "agent_id"?: String,
@@ -318,8 +336,8 @@ namespace AgentOps {
318
336
  // Supply-chain / package safety + aggregate threat severity (optional —
319
337
  // ADR 0012 unified port). Projected by Shield's malicious-package and
320
338
  // threat-severity detectors; every read is \`has\`-guarded in policy.
321
- "malicious_package_detected"?: Boolean,
322
- "package_install_detected"?: Boolean,
339
+ "malicious_package_detected"?: Bool,
340
+ "package_install_detected"?: Bool,
323
341
  "package_check_status"?: String,
324
342
  "max_threat_severity"?: Long,
325
343
 
@@ -346,9 +364,9 @@ namespace AgentOps {
346
364
  // Tool Risk (optional)
347
365
  "tool_name"?: String,
348
366
  "tool_risk_score"?: Long, // 0-100
349
- "tool_is_sensitive"?: Boolean,
367
+ "tool_is_sensitive"?: Bool,
350
368
  "tool_category"?: String, // "safe" | "sensitive" | "dangerous"
351
- "tool_is_builtin"?: Boolean,
369
+ "tool_is_builtin"?: Bool,
352
370
 
353
371
  // AARM R3 (CAP-ENF-007) — Action Parameter Validation
354
372
  "action_params"?: {
@@ -361,29 +379,29 @@ namespace AgentOps {
361
379
  "target"?: String,
362
380
  "query"?: String,
363
381
  },
364
- "param_type_violation"?: Boolean,
382
+ "param_type_violation"?: Bool,
365
383
  "param_type_violations"?: Set<String>,
366
384
 
367
385
  // MCP context (optional)
368
386
  "mcp_server"?: String,
369
387
  "mcp_tool"?: String,
370
- "mcp_server_verified"?: Boolean,
388
+ "mcp_server_verified"?: Bool,
371
389
 
372
390
  // Agentic - Behavioral Patterns (optional)
373
- "suspicious_pattern"?: Boolean,
391
+ "suspicious_pattern"?: Bool,
374
392
  "pattern_type"?: String, // "data_exfiltration" | "secret_exfiltration" | ...
375
393
  "sequence_risk"?: Long, // 0-100
376
394
 
377
395
  // Agentic - Loop Detection (optional)
378
- "loop_detected"?: Boolean,
396
+ "loop_detected"?: Bool,
379
397
  "loop_count"?: Long,
380
398
  "loop_tool"?: String,
381
399
 
382
400
  // Security checks on tool arguments (optional)
383
- "secrets_detected"?: Boolean,
401
+ "secrets_detected"?: Bool,
384
402
  "secret_count"?: Long,
385
403
  "secret_types"?: Set<String>,
386
- "pii_detected"?: Boolean,
404
+ "pii_detected"?: Bool,
387
405
  "pii_types"?: Set<String>,
388
406
  "pii_count"?: Long,
389
407
  "pii_score"?: Long,
@@ -398,58 +416,65 @@ namespace AgentOps {
398
416
  "topic_confidence"?: Long, // 0-100
399
417
 
400
418
  // Security - Pattern Detection (optional)
401
- "command_injection_detected"?: Boolean,
419
+ "command_injection_detected"?: Bool,
402
420
  "command_injection_type"?: String,
403
421
  "command_injection_score"?: Long,
404
- "path_traversal_detected"?: Boolean,
422
+ "path_traversal_detected"?: Bool,
405
423
  "path_traversal_severity"?: String,
406
424
  "path_traversal_type"?: String,
407
- "sql_injection_detected"?: Boolean,
425
+ "sql_injection_detected"?: Bool,
408
426
  "sql_injection_type"?: String,
409
427
  "sql_injection_score"?: Long,
410
428
 
411
429
  // Security - Cross-Origin Escalation (optional)
412
- "cross_origin_detected"?: Boolean,
430
+ "cross_origin_detected"?: Bool,
413
431
  "cross_origin_type"?: String,
414
432
  "cross_origin_score"?: Long,
415
433
 
416
434
  // Security - Invisible Character Detection (optional)
417
- "invisible_chars_detected"?: Boolean,
435
+ "invisible_chars_detected"?: Bool,
418
436
  "invisible_chars_score"?: Long,
419
437
 
420
438
  // Security - Encoded Injection (optional)
421
- "encoded_content_detected"?: Boolean,
439
+ "encoded_content_detected"?: Bool,
422
440
  "encoded_types"?: Set<String>,
423
441
  "encoded_count"?: Long,
424
442
  "encoded_score"?: Long,
425
443
 
426
444
  // Agentic - Agent Security (optional)
427
- "tool_poisoning_detected"?: Boolean,
445
+ "tool_poisoning_detected"?: Bool,
428
446
  "tool_poisoning_score"?: Long,
429
447
  "tool_poisoning_type"?: String,
430
- "rug_pull_detected"?: Boolean,
448
+ "rug_pull_detected"?: Bool,
431
449
  "rug_pull_score"?: Long,
432
450
  "rug_pull_type"?: String,
433
451
 
434
452
  // Agentic - MCP Risk (optional)
435
- "mcp_config_risk"?: Boolean,
453
+ "mcp_config_risk"?: Bool,
436
454
  "mcp_risk_type"?: String,
437
455
  "mcp_risk_score"?: Long,
438
456
 
439
457
  // Tool Operation Classifier (optional)
440
458
  "tool_operation_classes"?: Set<String>,
441
459
 
460
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \\n); Cedar \`like\` is anchored so patterns start with "*": sub-tree "*\\n/etc/*", bare dir "*\\n/etc\\n*", exact "*\\n/etc/passwd\\n*" ---
461
+ "resolved_target_paths"?: String, // union of resolved absolute target paths, any capability
462
+ "read_target_paths"?: String, // paths the command reads or enumerates
463
+ "write_target_paths"?: String, // paths the command writes, creates, or destroys
464
+ "exec_target_paths"?: String, // paths executed as a script
465
+ "unresolved_target"?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated
466
+
442
467
  // Agentic - Multi-Turn Context (optional)
443
468
  "conversation_turn"?: Long,
444
- "multi_turn_detection"?: Boolean,
469
+ "multi_turn_detection"?: Bool,
445
470
 
446
471
  // Session Detection History — cross-turn sticky flags (optional)
447
- "session_pii_detected"?: Boolean,
472
+ "session_pii_detected"?: Bool,
448
473
  "session_pii_types"?: Set<String>,
449
- "session_secrets_detected"?: Boolean,
474
+ "session_secrets_detected"?: Bool,
450
475
  "session_secret_types"?: Set<String>,
451
- "session_injection_detected"?: Boolean,
452
- "session_command_injection"?: Boolean,
476
+ "session_injection_detected"?: Bool,
477
+ "session_command_injection"?: Bool,
453
478
  "session_threat_turns"?: Long,
454
479
  "session_max_injection_score"?: Long,
455
480
  "session_max_jailbreak_score"?: Long,
@@ -479,14 +504,14 @@ namespace AgentOps {
479
504
  "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
480
505
  "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
481
506
  "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
482
- "flow_sink_is_external"?: Boolean,
507
+ "flow_sink_is_external"?: Bool,
483
508
  "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
484
509
  "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
485
510
  "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
486
511
 
487
512
  // Usage Budget (optional)
488
513
  "budget_remaining_pct"?: Long,
489
- "budget_exceeded"?: Boolean,
514
+ "budget_exceeded"?: Bool,
490
515
  "budget_cost_micros_this_turn"?: Long,
491
516
  "budget_model"?: String,
492
517
  "budget_tokens_pct_session"?: Long,
@@ -494,15 +519,15 @@ namespace AgentOps {
494
519
  "budget_tokens_pct_monthly"?: Long,
495
520
  "budget_cost_pct_daily"?: Long,
496
521
  "budget_cost_pct_monthly"?: Long,
497
- "budget_exceeded_session"?: Boolean,
498
- "budget_exceeded_daily"?: Boolean,
499
- "budget_exceeded_monthly"?: Boolean,
522
+ "budget_exceeded_session"?: Bool,
523
+ "budget_exceeded_daily"?: Bool,
524
+ "budget_exceeded_monthly"?: Bool,
500
525
 
501
526
  // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
502
527
  "rpm_remaining_pct"?: Long,
503
- "rpm_exceeded"?: Boolean,
528
+ "rpm_exceeded"?: Bool,
504
529
  "tpm_remaining_pct"?: Long,
505
- "tpm_exceeded"?: Boolean,
530
+ "tpm_exceeded"?: Bool,
506
531
 
507
532
  // Aggregated threat summary (optional)
508
533
  "highest_severity"?: String,
@@ -522,8 +547,8 @@ namespace AgentOps {
522
547
  // Supply-chain / package safety + aggregate threat severity (optional —
523
548
  // ADR 0012 unified port). Projected by Shield's malicious-package and
524
549
  // threat-severity detectors; every read is \`has\`-guarded in policy.
525
- "malicious_package_detected"?: Boolean,
526
- "package_install_detected"?: Boolean,
550
+ "malicious_package_detected"?: Bool,
551
+ "package_install_detected"?: Bool,
527
552
  "package_check_status"?: String,
528
553
  "max_threat_severity"?: Long,
529
554
 
@@ -551,14 +576,14 @@ namespace AgentOps {
551
576
  "path"?: String,
552
577
 
553
578
  // Security checks on file content (optional)
554
- "secrets_detected"?: Boolean,
579
+ "secrets_detected"?: Bool,
555
580
  "secret_count"?: Long,
556
581
  "secret_types"?: Set<String>,
557
- "pii_detected"?: Boolean,
582
+ "pii_detected"?: Bool,
558
583
  "pii_types"?: Set<String>,
559
584
 
560
585
  // Security - Path Traversal (optional)
561
- "path_traversal_detected"?: Boolean,
586
+ "path_traversal_detected"?: Bool,
562
587
  "path_traversal_severity"?: String,
563
588
  "path_traversal_type"?: String,
564
589
 
@@ -568,12 +593,12 @@ namespace AgentOps {
568
593
  "detected_threats"?: Set<String>,
569
594
 
570
595
  // Session Detection History (optional)
571
- "session_pii_detected"?: Boolean,
596
+ "session_pii_detected"?: Bool,
572
597
  "session_pii_types"?: Set<String>,
573
- "session_secrets_detected"?: Boolean,
598
+ "session_secrets_detected"?: Bool,
574
599
  "session_secret_types"?: Set<String>,
575
- "session_injection_detected"?: Boolean,
576
- "session_command_injection"?: Boolean,
600
+ "session_injection_detected"?: Bool,
601
+ "session_command_injection"?: Bool,
577
602
  "session_threat_turns"?: Long,
578
603
  "session_max_injection_score"?: Long,
579
604
  "session_max_jailbreak_score"?: Long,
@@ -603,14 +628,14 @@ namespace AgentOps {
603
628
  "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
604
629
  "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
605
630
  "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
606
- "flow_sink_is_external"?: Boolean,
631
+ "flow_sink_is_external"?: Bool,
607
632
  "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
608
633
  "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
609
634
  "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
610
635
 
611
636
  // Usage Budget (optional)
612
637
  "budget_remaining_pct"?: Long,
613
- "budget_exceeded"?: Boolean,
638
+ "budget_exceeded"?: Bool,
614
639
  "budget_cost_micros_this_turn"?: Long,
615
640
  "budget_model"?: String,
616
641
  "budget_tokens_pct_session"?: Long,
@@ -618,15 +643,15 @@ namespace AgentOps {
618
643
  "budget_tokens_pct_monthly"?: Long,
619
644
  "budget_cost_pct_daily"?: Long,
620
645
  "budget_cost_pct_monthly"?: Long,
621
- "budget_exceeded_session"?: Boolean,
622
- "budget_exceeded_daily"?: Boolean,
623
- "budget_exceeded_monthly"?: Boolean,
646
+ "budget_exceeded_session"?: Bool,
647
+ "budget_exceeded_daily"?: Bool,
648
+ "budget_exceeded_monthly"?: Bool,
624
649
 
625
650
  // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
626
651
  "rpm_remaining_pct"?: Long,
627
- "rpm_exceeded"?: Boolean,
652
+ "rpm_exceeded"?: Bool,
628
653
  "tpm_remaining_pct"?: Long,
629
- "tpm_exceeded"?: Boolean,
654
+ "tpm_exceeded"?: Bool,
630
655
 
631
656
  // Agent Identity (optional)
632
657
  "agent_id"?: String,
@@ -659,18 +684,18 @@ namespace AgentOps {
659
684
  "path"?: String,
660
685
 
661
686
  // Security - Invisible Character Detection in write content (optional)
662
- "invisible_chars_detected"?: Boolean,
687
+ "invisible_chars_detected"?: Bool,
663
688
  "invisible_chars_score"?: Long,
664
689
 
665
690
  // Security checks on content being written (optional)
666
- "secrets_detected"?: Boolean,
691
+ "secrets_detected"?: Bool,
667
692
  "secret_count"?: Long,
668
693
  "secret_types"?: Set<String>,
669
- "pii_detected"?: Boolean,
694
+ "pii_detected"?: Bool,
670
695
  "pii_types"?: Set<String>,
671
696
 
672
697
  // Security - Path Traversal (optional)
673
- "path_traversal_detected"?: Boolean,
698
+ "path_traversal_detected"?: Bool,
674
699
  "path_traversal_severity"?: String,
675
700
  "path_traversal_type"?: String,
676
701
 
@@ -680,12 +705,12 @@ namespace AgentOps {
680
705
  "detected_threats"?: Set<String>,
681
706
 
682
707
  // Session Detection History (optional)
683
- "session_pii_detected"?: Boolean,
708
+ "session_pii_detected"?: Bool,
684
709
  "session_pii_types"?: Set<String>,
685
- "session_secrets_detected"?: Boolean,
710
+ "session_secrets_detected"?: Bool,
686
711
  "session_secret_types"?: Set<String>,
687
- "session_injection_detected"?: Boolean,
688
- "session_command_injection"?: Boolean,
712
+ "session_injection_detected"?: Bool,
713
+ "session_command_injection"?: Bool,
689
714
  "session_threat_turns"?: Long,
690
715
  "session_max_injection_score"?: Long,
691
716
  "session_max_jailbreak_score"?: Long,
@@ -715,14 +740,14 @@ namespace AgentOps {
715
740
  "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
716
741
  "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
717
742
  "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
718
- "flow_sink_is_external"?: Boolean,
743
+ "flow_sink_is_external"?: Bool,
719
744
  "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
720
745
  "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
721
746
  "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
722
747
 
723
748
  // Usage Budget (optional)
724
749
  "budget_remaining_pct"?: Long,
725
- "budget_exceeded"?: Boolean,
750
+ "budget_exceeded"?: Bool,
726
751
  "budget_cost_micros_this_turn"?: Long,
727
752
  "budget_model"?: String,
728
753
  "budget_tokens_pct_session"?: Long,
@@ -730,15 +755,15 @@ namespace AgentOps {
730
755
  "budget_tokens_pct_monthly"?: Long,
731
756
  "budget_cost_pct_daily"?: Long,
732
757
  "budget_cost_pct_monthly"?: Long,
733
- "budget_exceeded_session"?: Boolean,
734
- "budget_exceeded_daily"?: Boolean,
735
- "budget_exceeded_monthly"?: Boolean,
758
+ "budget_exceeded_session"?: Bool,
759
+ "budget_exceeded_daily"?: Bool,
760
+ "budget_exceeded_monthly"?: Bool,
736
761
 
737
762
  // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
738
763
  "rpm_remaining_pct"?: Long,
739
- "rpm_exceeded"?: Boolean,
764
+ "rpm_exceeded"?: Bool,
740
765
  "tpm_remaining_pct"?: Long,
741
- "tpm_exceeded"?: Boolean,
766
+ "tpm_exceeded"?: Bool,
742
767
 
743
768
  // Agent Identity (optional)
744
769
  "agent_id"?: String,
@@ -769,20 +794,20 @@ namespace AgentOps {
769
794
 
770
795
  // MCP context (optional)
771
796
  "mcp_server"?: String,
772
- "mcp_server_verified"?: Boolean,
797
+ "mcp_server_verified"?: Bool,
773
798
 
774
799
  // Agentic - Agent Security (optional)
775
- "tool_poisoning_detected"?: Boolean,
800
+ "tool_poisoning_detected"?: Bool,
776
801
  "tool_poisoning_score"?: Long,
777
802
  "tool_poisoning_type"?: String,
778
803
 
779
804
  // Agentic - MCP Risk (optional)
780
- "mcp_config_risk"?: Boolean,
805
+ "mcp_config_risk"?: Bool,
781
806
  "mcp_risk_type"?: String,
782
807
  "mcp_risk_score"?: Long,
783
808
 
784
809
  // Security - Cross-Origin Escalation (optional)
785
- "cross_origin_detected"?: Boolean,
810
+ "cross_origin_detected"?: Bool,
786
811
  "cross_origin_type"?: String,
787
812
  "cross_origin_score"?: Long,
788
813
 
@@ -792,12 +817,12 @@ namespace AgentOps {
792
817
  "detected_threats"?: Set<String>,
793
818
 
794
819
  // Session Detection History (optional)
795
- "session_pii_detected"?: Boolean,
820
+ "session_pii_detected"?: Bool,
796
821
  "session_pii_types"?: Set<String>,
797
- "session_secrets_detected"?: Boolean,
822
+ "session_secrets_detected"?: Bool,
798
823
  "session_secret_types"?: Set<String>,
799
- "session_injection_detected"?: Boolean,
800
- "session_command_injection"?: Boolean,
824
+ "session_injection_detected"?: Bool,
825
+ "session_command_injection"?: Bool,
801
826
  "session_threat_turns"?: Long,
802
827
  "session_max_injection_score"?: Long,
803
828
  "session_max_jailbreak_score"?: Long,
@@ -827,14 +852,14 @@ namespace AgentOps {
827
852
  "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
828
853
  "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
829
854
  "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
830
- "flow_sink_is_external"?: Boolean,
855
+ "flow_sink_is_external"?: Bool,
831
856
  "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
832
857
  "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
833
858
  "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
834
859
 
835
860
  // Usage Budget (optional)
836
861
  "budget_remaining_pct"?: Long,
837
- "budget_exceeded"?: Boolean,
862
+ "budget_exceeded"?: Bool,
838
863
  "budget_cost_micros_this_turn"?: Long,
839
864
  "budget_model"?: String,
840
865
  "budget_tokens_pct_session"?: Long,
@@ -842,15 +867,15 @@ namespace AgentOps {
842
867
  "budget_tokens_pct_monthly"?: Long,
843
868
  "budget_cost_pct_daily"?: Long,
844
869
  "budget_cost_pct_monthly"?: Long,
845
- "budget_exceeded_session"?: Boolean,
846
- "budget_exceeded_daily"?: Boolean,
847
- "budget_exceeded_monthly"?: Boolean,
870
+ "budget_exceeded_session"?: Bool,
871
+ "budget_exceeded_daily"?: Bool,
872
+ "budget_exceeded_monthly"?: Bool,
848
873
 
849
874
  // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
850
875
  "rpm_remaining_pct"?: Long,
851
- "rpm_exceeded"?: Boolean,
876
+ "rpm_exceeded"?: Bool,
852
877
  "tpm_remaining_pct"?: Long,
853
- "tpm_exceeded"?: Boolean,
878
+ "tpm_exceeded"?: Bool,
854
879
 
855
880
  // Agent Identity (optional)
856
881
  "agent_id"?: String,
@@ -862,8 +887,8 @@ namespace AgentOps {
862
887
  // Supply-chain / package safety + aggregate threat severity (optional —
863
888
  // ADR 0012 unified port). Projected by Shield's malicious-package and
864
889
  // threat-severity detectors; every read is \`has\`-guarded in policy.
865
- "malicious_package_detected"?: Boolean,
866
- "package_install_detected"?: Boolean,
890
+ "malicious_package_detected"?: Bool,
891
+ "package_install_detected"?: Bool,
867
892
  "package_check_status"?: String,
868
893
  "max_threat_severity"?: Long,
869
894
 
@@ -909,7 +934,7 @@ namespace AgentOps {
909
934
  // requested (i.e. whenever egress_hosts is non-empty), so a "no network"
910
935
  // profile can gate on this single boolean. egress_hosts then narrows the
911
936
  // host allowlist for profiles that DO permit egress.
912
- "network_egress"?: Boolean,
937
+ "network_egress"?: Bool,
913
938
  "egress_hosts"?: Set<String>, // Host allowlist for egress, e.g. {"pypi.org"}
914
939
  "exec_allowlist"?: Set<String>, // Executables the sandbox may run, e.g. {"python", "python3"}
915
940
  // Curated mechanism toggles (ADR 0017 D1.3) — authorization facts only;
@@ -986,6 +1011,13 @@ entity Server in [Project];
986
1011
  /// MCP prompt -- resource for process_prompt action
987
1012
  entity LlmPrompt in [Project];
988
1013
 
1014
+ /// Model response -- resource for process_response action.
1015
+ /// Parented to Project like every other resource: Shield injects
1016
+ /// \`when { resource in <Ns>::Project::"<id>" }\` into every synced rule
1017
+ /// (shield#428), so a resource outside the project hierarchy would make
1018
+ /// every policy written against it unsatisfiable.
1019
+ entity LlmResponse in [Project];
1020
+
989
1021
  /// File/resource path -- resource for read_file/write_file actions
990
1022
  entity FilePath in [Project];
991
1023
 
@@ -1048,6 +1080,13 @@ action call_tool appliesTo {
1048
1080
  // --- Tool Operation Classifier ---
1049
1081
  tool_operation_classes?: Set<String>, // subset of {"readonly", "write_enabling", "execute_enabling", "network_access", "unknown"}
1050
1082
 
1083
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \\n); Cedar \`like\` is anchored so patterns start with "*": sub-tree "*\\n/etc/*", bare dir "*\\n/etc\\n*", exact "*\\n/etc/passwd\\n*" ---
1084
+ resolved_target_paths?: String, // union of resolved absolute target paths, any capability
1085
+ read_target_paths?: String, // paths the command reads or enumerates
1086
+ write_target_paths?: String, // paths the command writes, creates, or destroys
1087
+ exec_target_paths?: String, // paths executed as a script
1088
+ unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated
1089
+
1051
1090
  // --- MCP Trust ---
1052
1091
  mcp_server_verified?: Bool, // Whether server is from verified registry
1053
1092
 
@@ -1186,12 +1225,13 @@ action connect_server appliesTo {
1186
1225
  },
1187
1226
  };
1188
1227
 
1189
- // Process a prompt (MCP prompts/get or LLM chat completions)
1190
- // Threat focus: injection, jailbreak, secrets, PII, content safety
1191
- action process_prompt appliesTo {
1192
- principal: [User, MCP_Client],
1193
- resource: [LlmPrompt],
1194
- context: {
1228
+ // Shared content-inspection context.
1229
+ //
1230
+ // Prompts and responses are inspected by the same detector pipeline and so
1231
+ // carry the same context keys; only the TRIGGER differs (ADR 0031). Declaring
1232
+ // the shape once means a new detector key cannot land on one direction and go
1233
+ // missing on the other — the drift class shield#393 / shield#387 were about.
1234
+ type ContentInspectionContext = {
1195
1235
  // Identity (AARM R6 / CAP-IDN-011) — projected from the principal's token; optional.
1196
1236
  role?: String,
1197
1237
  privilege_scope?: Set<String>,
@@ -1270,7 +1310,29 @@ action process_prompt appliesTo {
1270
1310
  rpm_exceeded?: Bool,
1271
1311
  tpm_remaining_pct?: Long,
1272
1312
  tpm_exceeded?: Bool,
1273
- },
1313
+ };
1314
+
1315
+ // Process a prompt (MCP prompts/get or LLM chat completions)
1316
+ // Threat focus: injection, jailbreak, secrets, PII, content safety
1317
+ action process_prompt appliesTo {
1318
+ principal: [User, MCP_Client],
1319
+ resource: [LlmPrompt],
1320
+ context: ContentInspectionContext,
1321
+ };
1322
+
1323
+ // Process a model response (LLM chat completion output, streamed or buffered)
1324
+ // Threat focus: data leakage in output, harmful content, hallucination,
1325
+ // indirect injection carried back to the caller.
1326
+ //
1327
+ // Distinct from process_prompt so that (a) a policy can be scoped to one
1328
+ // direction from its head alone and (b) Shield's action-scoped detector
1329
+ // scheduling (INV-DET-001) can keep prompt-only detectors off the egress
1330
+ // path — before this action existed, a prompt-scoped dlp/model_armor/webhook
1331
+ // rule shipped response bodies downstream. See ADR 0031.
1332
+ action process_response appliesTo {
1333
+ principal: [User, MCP_Client],
1334
+ resource: [LlmResponse],
1335
+ context: ContentInspectionContext,
1274
1336
  };
1275
1337
 
1276
1338
  // Read an MCP resource (resources/read, resources/list)
@@ -1471,13 +1533,24 @@ namespace Guardrails {
1471
1533
  // Actions
1472
1534
  // =========================================================================
1473
1535
 
1474
- /// Process user prompts and AI responses for security threats and content violations
1536
+ /// Process user prompts for security threats and content violations
1475
1537
  action "process_prompt" appliesTo {
1476
1538
  principal: [User, Agent],
1477
1539
  resource: [App, Agent, Session],
1478
1540
  context: ProcessPromptContext
1479
1541
  };
1480
1542
 
1543
+ /// Process model responses for security threats and content violations.
1544
+ /// Distinct trigger from process_prompt (ADR 0031) so a policy can be
1545
+ /// scoped to one direction from its head, and so Shield's action-scoped
1546
+ /// detector scheduling (INV-DET-001) keeps prompt-only detectors off the
1547
+ /// egress path.
1548
+ action "process_response" appliesTo {
1549
+ principal: [User, Agent],
1550
+ resource: [App, Agent, Session],
1551
+ context: ProcessResponseContext
1552
+ };
1553
+
1481
1554
  /// Execute tool calls (shell, file operations, MCP tools)
1482
1555
  action "call_tool" appliesTo {
1483
1556
  principal: [User, Agent],
@@ -1510,7 +1583,17 @@ namespace Guardrails {
1510
1583
  // Context Types (Action-Specific)
1511
1584
  // =========================================================================
1512
1585
 
1513
- /// Context for process_prompt action (user prompts & AI responses)
1586
+ /// Context for the process_response action.
1587
+ ///
1588
+ /// An alias, not a copy: prompts and responses are inspected by the same
1589
+ /// detector pipeline and carry the same keys — only the trigger differs
1590
+ /// (ADR 0031). Aliasing means a new detector key cannot land on one
1591
+ /// direction and go missing on the other, and it guarantees no policy
1592
+ /// loses a context key at the cutover, since this is byte-for-byte the
1593
+ /// shape responses were already evaluated against under process_prompt.
1594
+ type ProcessResponseContext = ProcessPromptContext;
1595
+
1596
+ /// Context for process_prompt action (user prompts)
1514
1597
  type ProcessPromptContext = {
1515
1598
  // Identity (AARM R6 / CAP-IDN-011) — projected from the principal's token; optional.
1516
1599
  "role"?: String,
@@ -1821,6 +1904,13 @@ namespace Guardrails {
1821
1904
  // Tool Operation Classifier (optional) — populated by AST-based classifiers (bash, python, etc.)
1822
1905
  "tool_operation_classes"?: Set<String>, // subset of {"readonly", "write_enabling", "execute_enabling", "network_access", "unknown"}
1823
1906
 
1907
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \\n); Cedar \`like\` is anchored so patterns start with "*": sub-tree "*\\n/etc/*", bare dir "*\\n/etc\\n*", exact "*\\n/etc/passwd\\n*" ---
1908
+ "resolved_target_paths"?: String, // union of resolved absolute target paths, any capability
1909
+ "read_target_paths"?: String, // paths the command reads or enumerates
1910
+ "write_target_paths"?: String, // paths the command writes, creates, or destroys
1911
+ "exec_target_paths"?: String, // paths executed as a script
1912
+ "unresolved_target"?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated
1913
+
1824
1914
  // Agentic - Multi-Turn Context (optional)
1825
1915
  "conversation_turn"?: Long,
1826
1916
  "multi_turn_detection"?: Bool,
@@ -2332,6 +2422,13 @@ action call_tool appliesTo {
2332
2422
  // --- Tool Operation Classifier ---
2333
2423
  tool_operation_classes?: Set<String>, // subset of {"readonly", "write_enabling", "execute_enabling", "network_access", "unknown"}
2334
2424
 
2425
+ // --- Bash AST resolved target paths (#411 / CAP-DET-007) — newline-delimited (leading+trailing \\n); Cedar \`like\` is anchored so patterns start with "*": sub-tree "*\\n/etc/*", bare dir "*\\n/etc\\n*", exact "*\\n/etc/passwd\\n*" ---
2426
+ resolved_target_paths?: String, // union of resolved absolute target paths, any capability
2427
+ read_target_paths?: String, // paths the command reads or enumerates
2428
+ write_target_paths?: String, // paths the command writes, creates, or destroys
2429
+ exec_target_paths?: String, // paths executed as a script
2430
+ unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code
2431
+
2335
2432
  // --- Session Detection History (cross-turn sticky flags) ---
2336
2433
  session_pii_detected?: Bool,
2337
2434
  session_pii_types?: Set<String>,
@@ -3303,6 +3400,137 @@ export const AGENT_OPS_CONTEXT = {
3303
3400
  { "key": "max_threat_severity", "type": "number", "required": false, "description": "Aggregate max threat severity across detectors (0=none,1=low,2=medium,3=high,4=critical)." }
3304
3401
  ]
3305
3402
  },
3403
+ {
3404
+ "name": "process_response",
3405
+ "description": "Process a model response (LLM chat completion output) — threat focus: data leakage in output, harmful content, hallucination, indirect injection carried back to the caller. Distinct trigger from process_prompt (ADR 0031) so a policy can be scoped to one direction from its head and prompt-only detectors stay off the egress path.",
3406
+ "context_attributes": [
3407
+ { "key": "role", "type": "string", "required": false, "description": "Caller\'s RBAC role projected from the principal\'s token (AARM R6 / CAP-IDN-011)" },
3408
+ { "key": "privilege_scope", "type": "array", "required": false, "description": "Privilege-scope strings granted to the caller, projected from the token (AARM R6 / CAP-IDN-011)" },
3409
+ { "key": "identity_type", "type": "string", "required": false, "description": "Principal identity class projected from the token: \'human\', \'agent\', \'service\', or \'mcp_server\'" },
3410
+ { "key": "principal", "type": "string", "required": false, "description": "Stable principal identifier projected from the token (e.g. a ZeroID / WIMSE URI or user id)" },
3411
+ { "key": "request_id", "type": "string", "required": true, "description": "Unique identifier for this request, useful for audit trails and debugging" },
3412
+ { "key": "timestamp", "type": "number", "required": true, "description": "Unix timestamp in milliseconds when the request was processed" },
3413
+ { "key": "direction", "type": "string", "required": true, "description": "Content flow direction: \'input\' for user prompts, \'output\' for AI responses" },
3414
+ { "key": "content_type", "type": "string", "required": true, "description": "Type of content being analyzed: \'prompt\', \'response\', \'tool_call\', \'file\', or \'clipboard\'" },
3415
+ { "key": "detector_count", "type": "number", "required": true, "description": "Number of detectors that were executed for this request" },
3416
+ { "key": "source", "type": "string", "required": false, "description": "Traffic origin: \'ide\' | \'cli\' | \'api\' | \'browser\'. Present for Overwatch/code-agent traffic." },
3417
+ { "key": "event", "type": "string", "required": false, "description": "Event type: \'prompt\' | \'tool_call\' | \'file_read\' | \'file_write\' | \'connect_server\'. Present for Overwatch traffic." },
3418
+ { "key": "user_email", "type": "string", "required": false, "description": "Human operator email (IDE sessions)" },
3419
+ { "key": "cwd", "type": "string", "required": false, "description": "Current working directory (IDE sessions)" },
3420
+ { "key": "workspace_root", "type": "string", "required": false, "description": "IDE workspace root path" },
3421
+ { "key": "model_name", "type": "string", "required": false, "description": "LLM model name: \'claude-3-5-sonnet\', \'gpt-4o\', etc. Present for AI Gateway traffic." },
3422
+ { "key": "model_provider", "type": "string", "required": false, "description": "Model provider: \'anthropic\' | \'openai\' | \'google\' | \'meta\'. Present for AI Gateway traffic." },
3423
+ { "key": "injection_score", "type": "number", "required": false, "description": "Combined prompt injection confidence (0-100). MAX of all detector scores." },
3424
+ { "key": "jailbreak_score", "type": "number", "required": false, "description": "Combined jailbreak detection confidence (0-100). MAX of all detector scores." },
3425
+ { "key": "injection_pulse_score", "type": "number", "required": false, "description": "Highflame single-turn classifier score for prompt injection (0-100)." },
3426
+ { "key": "injection_deep_context_score", "type": "number", "required": false, "description": "DeepContext multi-turn analyzer score for prompt injection (0-100)." },
3427
+ { "key": "jailbreak_pulse_score", "type": "number", "required": false, "description": "Highflame single-turn classifier score for jailbreak attempts (0-100)." },
3428
+ { "key": "jailbreak_deep_context_score", "type": "number", "required": false, "description": "DeepContext multi-turn analyzer score for jailbreak attempts (0-100)." },
3429
+ { "key": "injection_type", "type": "string", "required": false, "description": "Type of injection detected: \'prompt\', \'sql\', \'command\', or \'none\'" },
3430
+ { "key": "indirect_injection_score", "type": "number", "required": false, "description": "Indirect prompt injection risk score (0-100) — injection via tool outputs, retrieved documents, or external content." },
3431
+ { "key": "indirect_injection_type", "type": "string", "required": false, "description": "Type of indirect injection detected in content (e.g., instruction override, authority hijack)" },
3432
+ { "key": "secrets_detected", "type": "boolean", "required": false, "description": "Whether any API keys, tokens, passwords, or credentials were detected" },
3433
+ { "key": "secret_count", "type": "number", "required": false, "description": "Total number of secret matches found" },
3434
+ { "key": "secret_types", "type": "array", "required": false, "description": "Array of secret types found (e.g., [\'aws_access_key\', \'github_token\'])" },
3435
+ { "key": "pii_detected", "type": "boolean", "required": false, "description": "Whether personally identifiable information (PII) was found" },
3436
+ { "key": "pii_count", "type": "number", "required": false, "description": "Total number of PII matches found" },
3437
+ { "key": "pii_types", "type": "array", "required": false, "description": "Array of PII types detected (e.g., [\'email\', \'phone\', \'ssn\', \'credit_card\'])" },
3438
+ { "key": "pii_score", "type": "number", "required": false, "description": "PII detection ML classifier confidence (0-100)." },
3439
+ { "key": "highest_severity", "type": "string", "required": false, "description": "Highest severity level: \'critical\', \'high\', \'medium\', \'low\', or \'none\'" },
3440
+ { "key": "threat_count", "type": "number", "required": false, "description": "Total number of threats detected across all detectors" },
3441
+ { "key": "threat_categories", "type": "array", "required": false, "description": "Array of threat category names detected (e.g., [\'injection\', \'pii\', \'secrets\'])" },
3442
+ { "key": "detected_threats", "type": "array", "required": false, "description": "Array of specific threat names detected" },
3443
+ { "key": "violence_score", "type": "number", "required": false, "description": "ML-based score for violent content references (0-100)." },
3444
+ { "key": "hate_speech_score", "type": "number", "required": false, "description": "ML-based score for hate speech or discriminatory language (0-100)." },
3445
+ { "key": "sexual_score", "type": "number", "required": false, "description": "ML-based score for sexual or adult content (0-100)." },
3446
+ { "key": "weapons_score", "type": "number", "required": false, "description": "ML-based score for weapons references (0-100)." },
3447
+ { "key": "crime_score", "type": "number", "required": false, "description": "ML-based score for criminal activity discussions (0-100)." },
3448
+ { "key": "profanity_score", "type": "number", "required": false, "description": "ML-based score for profanity and vulgar language (0-100)." },
3449
+ { "key": "content_topics", "type": "array", "required": false, "description": "Semantic topics detected in content (e.g., [\'controlled_substances\', \'weapons_manufacturing\'])" },
3450
+ { "key": "topic_confidence", "type": "number", "required": false, "description": "Confidence score from topic classifier (0-100)." },
3451
+ { "key": "invisible_chars_detected", "type": "boolean", "required": false, "description": "Whether invisible Unicode characters were detected in the content" },
3452
+ { "key": "invisible_chars_score", "type": "number", "required": false, "description": "Density score for invisible characters (0-100)." },
3453
+ { "key": "command_injection_detected", "type": "boolean", "required": false, "description": "Whether command injection patterns were detected" },
3454
+ { "key": "command_injection_type", "type": "string", "required": false, "description": "Type of command injection: \'reverse_shell\', \'privilege_escalation\', \'code_execution\', \'destructive_command\', or \'data_exfiltration\'" },
3455
+ { "key": "command_injection_score", "type": "number", "required": false, "description": "Confidence score for command injection detection (0-100)." },
3456
+ { "key": "path_traversal_detected", "type": "boolean", "required": false, "description": "Whether path traversal patterns were detected" },
3457
+ { "key": "path_traversal_severity", "type": "string", "required": false, "description": "Severity of path traversal: \'critical\', \'high\', \'medium\', \'low\', or \'none\'" },
3458
+ { "key": "path_traversal_type", "type": "string", "required": false, "description": "Type of path traversal detected" },
3459
+ { "key": "sql_injection_detected", "type": "boolean", "required": false, "description": "Whether SQL injection patterns were detected" },
3460
+ { "key": "sql_injection_type", "type": "string", "required": false, "description": "Type of SQL injection: \'tautology\', \'union_based\', \'destructive\', \'blind\', or \'error_based\'" },
3461
+ { "key": "sql_injection_score", "type": "number", "required": false, "description": "Confidence score for SQL injection detection (0-100)." },
3462
+ { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected" },
3463
+ { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation: \'cross_origin_tool\', \'cross_origin_server\', or \'none\'" },
3464
+ { "key": "cross_origin_score", "type": "number", "required": false, "description": "Risk score for cross-origin escalation (0-100)." },
3465
+ { "key": "encoded_content_detected", "type": "boolean", "required": false, "description": "Whether encoded content was detected (base64, hex, unicode, URL encoding)" },
3466
+ { "key": "encoded_types", "type": "array", "required": false, "description": "Array of encoding types detected (e.g., [\'base64\', \'hex\', \'unicode\', \'url\'])" },
3467
+ { "key": "encoded_count", "type": "number", "required": false, "description": "Number of encoded segments found" },
3468
+ { "key": "encoded_score", "type": "number", "required": false, "description": "Risk score for encoded injection attempts (0-100)." },
3469
+ { "key": "detected_language", "type": "string", "required": false, "description": "ISO language code of the detected language (e.g., \'en\', \'fr\', \'zh\')" },
3470
+ { "key": "is_english", "type": "boolean", "required": false, "description": "Whether the content is in English" },
3471
+ { "key": "language_confidence", "type": "number", "required": false, "description": "Confidence score for language detection (0-100)." },
3472
+ { "key": "detected_script", "type": "string", "required": false, "description": "Writing script detected: \'latin\', \'cyrillic\', \'arabic\', \'cjk\', \'unknown\', etc." },
3473
+ { "key": "is_latin_script", "type": "boolean", "required": false, "description": "Whether the content uses Latin script" },
3474
+ { "key": "script_confidence", "type": "number", "required": false, "description": "Confidence score for script detection (0-100)." },
3475
+ { "key": "hallucination_score", "type": "number", "required": false, "description": "ML-based score for hallucinated or fabricated content (0-100)." },
3476
+ { "key": "factuality_score", "type": "number", "required": false, "description": "ML-based factuality assessment score (0-100)." },
3477
+ { "key": "sentiment_score", "type": "number", "required": false, "description": "Sentiment analysis score." },
3478
+ { "key": "contains_code", "type": "boolean", "required": false, "description": "Whether code snippets were detected in the content" },
3479
+ { "key": "code_languages", "type": "array", "required": false, "description": "Array of programming languages detected in code snippets" },
3480
+ { "key": "code_ratio", "type": "number", "required": false, "description": "Percentage of content that consists of code (0-100)." },
3481
+ { "key": "keyword_matched", "type": "boolean", "required": false, "description": "Whether any configured keywords or phrases were matched" },
3482
+ { "key": "keyword_categories", "type": "array", "required": false, "description": "Array of keyword categories matched (e.g., [\'competitor_names\', \'restricted_topics\'])" },
3483
+ { "key": "keyword_count", "type": "number", "required": false, "description": "Number of keyword matches found" },
3484
+ { "key": "contains_non_ascii", "type": "boolean", "required": false, "description": "Whether non-ASCII characters were detected" },
3485
+ { "key": "phishing_detected", "type": "boolean", "required": false, "description": "Whether phishing patterns were detected" },
3486
+ { "key": "content_safety_score", "type": "number", "required": false, "description": "Aggregate content safety score (0-100)." },
3487
+ { "key": "content_safety_blocked", "type": "boolean", "required": false, "description": "Whether content was flagged for blocking by the content safety system" },
3488
+ { "key": "conversation_turn", "type": "number", "required": false, "description": "Current conversation turn number" },
3489
+ { "key": "multi_turn_detection", "type": "boolean", "required": false, "description": "Whether multi-turn injection patterns were detected" },
3490
+ { "key": "budget_remaining_pct", "type": "number", "required": false, "description": "Remaining token budget as percentage (0-100)." },
3491
+ { "key": "budget_exceeded", "type": "boolean", "required": false, "description": "Whether the token budget has been exceeded" },
3492
+ { "key": "rpm_remaining_pct", "type": "number", "required": false, "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)." },
3493
+ { "key": "rpm_exceeded", "type": "boolean", "required": false, "description": "Whether the RPM limit has been exceeded" },
3494
+ { "key": "tpm_remaining_pct", "type": "number", "required": false, "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)." },
3495
+ { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded" },
3496
+ { "key": "session_pii_detected", "type": "boolean", "required": false, "description": "Whether PII was detected in any previous turn of the session" },
3497
+ { "key": "session_pii_types", "type": "array", "required": false, "description": "PII types detected across the session (accumulated)" },
3498
+ { "key": "session_secrets_detected", "type": "boolean", "required": false, "description": "Whether secrets were detected in any previous turn of the session" },
3499
+ { "key": "session_secret_types", "type": "array", "required": false, "description": "Secret types detected across the session (accumulated)" },
3500
+ { "key": "session_injection_detected", "type": "boolean", "required": false, "description": "Whether prompt injection was detected in any previous turn of the session" },
3501
+ { "key": "session_command_injection", "type": "boolean", "required": false, "description": "Whether command injection was detected in any previous turn of the session" },
3502
+ { "key": "session_threat_turns", "type": "number", "required": false, "description": "Number of turns in the session where threats were detected" },
3503
+ { "key": "session_max_injection_score", "type": "number", "required": false, "description": "Highest prompt injection score seen in any turn of the session (0-100). Use for tiered responses: >75 hard block, >50 restrict permissions" },
3504
+ { "key": "session_max_jailbreak_score", "type": "number", "required": false, "description": "Highest jailbreak detection score seen in any turn of the session (0-100)" },
3505
+ { "key": "session_max_command_injection_score", "type": "number", "required": false, "description": "Highest command injection score seen in any turn of the session (0-100)" },
3506
+ { "key": "session_max_pii_score", "type": "number", "required": false, "description": "Highest PII risk score seen in any turn of the session (0-100)" },
3507
+ { "key": "session_max_secret_score", "type": "number", "required": false, "description": "Highest secret detection score seen in any turn of the session (0-100)" },
3508
+ { "key": "session_cumulative_risk_score", "type": "number", "required": false, "description": "Sum of per-turn risk scores across the session. Catches death-by-a-thousand-cuts where no single turn is high but cumulative risk is significant" },
3509
+ { "key": "session_max_sensitivity", "type": "string", "required": false, "description": "Highest data-sensitivity tier observed across the session (e.g. \'public\', \'internal\', \'confidential\', \'restricted\')" },
3510
+ { "key": "session_original_request", "type": "string", "required": false, "description": "The session\'s first user request, retained for drift / goal-hijack policies that compare later turns against the original intent" },
3511
+ { "key": "agent_id", "type": "string", "required": false, "description": "Unique identifier of the authenticated AI agent making this request. Empty string for human user requests." },
3512
+ { "key": "agent_type", "type": "string", "required": false, "description": "Type of the authenticated agent: \'orchestrator\', \'autonomous\', \'tool_agent\', or \'human_proxy\'. Empty string for human users." },
3513
+ { "key": "agent_trust_level", "type": "string", "required": false, "description": "Trust level of the authenticated agent: \'first_party\', \'verified_third_party\', or \'unverified\'." },
3514
+ { "key": "agent_framework", "type": "string", "required": false, "description": "Framework or SDK the agent is built with (e.g., \'claude-code\', \'langchain\', \'crewai\', \'autogen\')." },
3515
+ { "key": "agent_publisher", "type": "string", "required": false, "description": "Organization that published the agent (e.g., \'anthropic\', \'internal\', \'acme-corp\')." },
3516
+ { "key": "flow_confidentiality", "type": "string", "required": false, "description": "Confidentiality tier of the data this action carries or targets (ADR 0020): \'public\', \'internal\', \'confidential\', \'restricted\', or \'unknown\'. Shares the ladder with session_max_sensitivity but is a per-value fact, not a session scalar. \'unknown\' MUST NOT be treated as \'public\' — guard with has and let policy DENY/STEP_UP/DEFER per flow_resolution_status." },
3517
+ { "key": "flow_integrity", "type": "string", "required": false, "description": "Integrity/influence tier of the data this action carries (ADR 0020): \'trusted\', \'untrusted\', \'mixed\', or \'unknown\'. Orthogonal to confidentiality: untrusted content may inform a pure analysis but MUST NOT authorize a side-effecting sink. Least-trusted contributor wins on join." },
3518
+ { "key": "flow_data_types", "type": "array", "required": false, "description": "Sensitive data categories present in the value (ADR 0020), e.g. \'pii\', \'secrets\', \'source_code\', \'financial\', \'health\'. Union of all contributing inputs. Set<String>." },
3519
+ { "key": "flow_compartments", "type": "array", "required": false, "description": "Compartments the value belongs to (ADR 0020), e.g. \'tenant:acme\', \'customer:123\', \'project:x\'. Union of all contributing inputs — cross-compartment composition is expressible by cardinality. Set<String>." },
3520
+ { "key": "flow_resolution_status", "type": "string", "required": false, "description": "How the flow label was resolved (ADR 0020): \'known\', \'inferred\', \'unknown\', or \'conflicted\'. Policy authors choose the posture for \'unknown\' per sink (DENY external, STEP_UP, DEFER while a classifier runs, or allow-and-record). Never silently resolves to public." },
3521
+ { "key": "flow_origins", "type": "array", "required": false, "description": "Origin kinds that produced or influenced the value (ADR 0020): \'mcp_tool_result\', \'model\', \'file\', \'database\', \'user\'. Provenance fact for lineage-aware policy. Set<String>." },
3522
+ { "key": "flow_sink", "type": "string", "required": false, "description": "Logical destination this action releases the value to (ADR 0020), e.g. \'external_model\', \'local_model\', \'external_mcp\', \'trusted_mcp\', \'user_secure_output\', \'public_network\', \'file\'. The \'where\' half of a flow decision — pair with flow_confidentiality/flow_integrity." },
3523
+ { "key": "flow_sink_is_external", "type": "boolean", "required": false, "description": "Whether the destination is outside the tenant trust boundary (ADR 0020). Lets a single policy express \'confidential data MUST NOT leave to any external sink\' without enumerating sink ids." },
3524
+ { "key": "flow_sink_effects", "type": "array", "required": false, "description": "Side effects the destination can exercise (ADR 0020), e.g. \'network.send\', \'financial.transfer\', \'filesystem.write\'. Enables \'untrusted content MUST NOT reach a financial.transfer sink\'. Set<String>." },
3525
+ { "key": "principal_clearances", "type": "array", "required": false, "description": "Clearances AuthN/ZeroID mints for the principal (ADR 0020 D8), e.g. \'restricted\', \'pii\'. Coarse scopes gate the capability; clearances gate which protected data that capability may touch. Set<String>." },
3526
+ { "key": "principal_compartments", "type": "array", "required": false, "description": "Compartments the principal is admitted to (ADR 0020 D8), e.g. \'tenant:acme\', \'customer:123\'. A flow into a compartment the principal lacks is deniable independent of confidentiality tier. Set<String>." },
3527
+ { "key": "surface", "type": "string", "required": true, "description": "Origin surface of the request (ADR 0012 D14.2) — REQUIRED; projected by Shield from the ingress product, never user-supplied. Values are the product identifiers: \'guardrails\', \'overwatch\', \'ai_gateway\' (\'sentry\' joins at D17 phase 2). The \'Applies to\' narrowing target: test with an ordinary condition (context.surface == \'ai_gateway\'); no \'has\' guard needed because it is required. A policy with no surface condition applies to every surface, including ones added later." },
3528
+ { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "Whether a referenced package carries a known-malicious osv.dev (MAL-) advisory." },
3529
+ { "key": "package_install_detected", "type": "boolean", "required": false, "description": "Whether the request installs or downloads a package (pip/npm/cargo/etc.)." },
3530
+ { "key": "package_check_status", "type": "string", "required": false, "description": "Malicious-package lookup status: empty (ok) or degraded (OSV unavailable, fail-open)." },
3531
+ { "key": "max_threat_severity", "type": "number", "required": false, "description": "Aggregate max threat severity across detectors (0=none,1=low,2=medium,3=high,4=critical)." }
3532
+ ]
3533
+ },
3306
3534
  {
3307
3535
  "name": "call_tool",
3308
3536
  "description": "Execute agentic tool calls, including shell commands, file operations, and MCP tools",
@@ -3376,6 +3604,11 @@ export const AGENT_OPS_CONTEXT = {
3376
3604
  { "key": "encoded_count", "type": "number", "required": false, "description": "Number of encoded segments found in tool arguments" },
3377
3605
  { "key": "encoded_score", "type": "number", "required": false, "description": "Risk score for encoded injection in tool arguments (0-100)." },
3378
3606
  { "key": "tool_operation_classes", "type": "array", "required": false, "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: \'readonly\', \'write_enabling\', \'execute_enabling\', \'network_access\', \'unknown\'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). \'unknown\' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy." },
3607
+ { "key": "resolved_target_paths", "type": "string", "required": false, "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with \'*\': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated." },
3608
+ { "key": "read_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths)." },
3609
+ { "key": "write_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\"." },
3610
+ { "key": "exec_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths)." },
3611
+ { "key": "unresolved_target", "type": "boolean", "required": false, "description": "True when a shell command\'s target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments." },
3379
3612
  { "key": "path", "type": "string", "required": false, "description": "File path targeted by the tool call" },
3380
3613
  { "key": "conversation_turn", "type": "number", "required": false, "description": "Current conversation turn number" },
3381
3614
  { "key": "multi_turn_detection", "type": "boolean", "required": false, "description": "Whether multi-turn injection patterns were detected across tool calls" },
@@ -3698,6 +3931,11 @@ export const AI_GATEWAY_CONTEXT = {
3698
3931
  { "key": "tool_is_sensitive", "type": "boolean", "required": false, "description": "Tool sensitivity flag" },
3699
3932
  { "key": "tool_is_builtin", "type": "boolean", "required": false, "description": "Built-in tool flag" },
3700
3933
  { "key": "tool_operation_classes", "type": "array", "required": false, "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: \'readonly\', \'write_enabling\', \'execute_enabling\', \'network_access\', \'unknown\'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). \'unknown\' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy." },
3934
+ { "key": "resolved_target_paths", "type": "string", "required": false, "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with \'*\': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated. NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim." },
3935
+ { "key": "read_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths). NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim." },
3936
+ { "key": "write_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\". NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim." },
3937
+ { "key": "exec_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths). NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim." },
3938
+ { "key": "unresolved_target", "type": "boolean", "required": false, "description": "True when a shell command\'s target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments. NOTE (AI Gateway): declared ahead of runtime emission — the gateway does not populate this until the bash classifier is wired (#173); policies validate now but will not match in the interim." },
3701
3939
  { "key": "mcp_server_verified", "type": "boolean", "required": false, "description": "Whether server is from verified registry" },
3702
3940
  { "key": "violence_score", "type": "number", "required": false, "description": "Violence content score (0-100)" },
3703
3941
  { "key": "weapons_score", "type": "number", "required": false, "description": "Weapons content score (0-100)" },
@@ -3848,6 +4086,57 @@ export const AI_GATEWAY_CONTEXT = {
3848
4086
  { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" }
3849
4087
  ]
3850
4088
  },
4089
+ {
4090
+ "name": "process_response",
4091
+ "description": "Process a model response (LLM chat completion output) — threat focus: data leakage in output, harmful content, hallucination, indirect injection carried back to the caller. Distinct trigger from process_prompt (ADR 0031) so a policy can be scoped to one direction from its head and prompt-only detectors stay off the egress path.",
4092
+ "context_attributes": [
4093
+ { "key": "role", "type": "string", "required": false, "description": "Caller\'s RBAC role projected from the principal\'s token (AARM R6 / CAP-IDN-011), e.g. finance_lead. Absent when the token carries no role claim." },
4094
+ { "key": "privilege_scope", "type": "array", "required": false, "description": "Privilege-scope strings granted to the caller, projected from the token (AARM R6 / CAP-IDN-011), e.g. transfer:approve. Absent when the token carries no claim." },
4095
+ { "key": "content", "type": "string", "required": true, "description": "Raw content being scanned" },
4096
+ { "key": "mcp_server", "type": "string", "required": false, "description": "MCP server name" },
4097
+ { "key": "threat_count", "type": "number", "required": false, "description": "Total threats detected" },
4098
+ { "key": "highest_severity", "type": "string", "required": false, "description": "Highest threat severity" },
4099
+ { "key": "threat_categories", "type": "array", "required": false, "description": "Threat category names" },
4100
+ { "key": "detected_threats", "type": "array", "required": false, "description": "Detection rule names that matched" },
4101
+ { "key": "max_threat_severity", "type": "number", "required": false, "description": "Numeric severity (0-4)" },
4102
+ { "key": "secrets_detected", "type": "boolean", "required": false, "description": "Whether secrets/credentials detected" },
4103
+ { "key": "secret_types", "type": "array", "required": false, "description": "Types of secrets found" },
4104
+ { "key": "secret_count", "type": "number", "required": false, "description": "Number of distinct secrets" },
4105
+ { "key": "pii_detected", "type": "boolean", "required": false, "description": "Whether PII detected" },
4106
+ { "key": "pii_types", "type": "array", "required": false, "description": "Types of PII detected" },
4107
+ { "key": "pii_count", "type": "number", "required": false, "description": "Number of PII matches" },
4108
+ { "key": "pii_score", "type": "number", "required": false, "description": "PII classifier confidence (0-100)" },
4109
+ { "key": "injection_score", "type": "number", "required": false, "description": "Injection classifier confidence (0-100)" },
4110
+ { "key": "jailbreak_score", "type": "number", "required": false, "description": "Jailbreak classifier confidence (0-100)" },
4111
+ { "key": "violence_score", "type": "number", "required": false, "description": "Violence content score (0-100)" },
4112
+ { "key": "weapons_score", "type": "number", "required": false, "description": "Weapons content score (0-100)" },
4113
+ { "key": "hate_speech_score", "type": "number", "required": false, "description": "Hate speech score (0-100)" },
4114
+ { "key": "crime_score", "type": "number", "required": false, "description": "Crime content score (0-100)" },
4115
+ { "key": "sexual_score", "type": "number", "required": false, "description": "Sexual content score (0-100)" },
4116
+ { "key": "profanity_score", "type": "number", "required": false, "description": "Profanity score (0-100)" },
4117
+ { "key": "invisible_chars_detected", "type": "boolean", "required": false, "description": "Invisible Unicode chars detected" },
4118
+ { "key": "invisible_chars_score", "type": "number", "required": false, "description": "Unicode attack severity (0-100)" },
4119
+ { "key": "model_name", "type": "string", "required": false, "description": "Target model name (e.g., gpt-4, claude-3-opus)" },
4120
+ { "key": "model_provider", "type": "string", "required": false, "description": "Provider name (e.g., openai, anthropic, bedrock)" },
4121
+ { "key": "session_threat_turns", "type": "number", "required": false, "description": "Count of turns with detected threats in this session" },
4122
+ { "key": "session_cumulative_risk_score", "type": "number", "required": false, "description": "Cumulative risk score across session turns" },
4123
+ { "key": "session_injection_detected", "type": "boolean", "required": false, "description": "Injection seen in any prior turn of this session" },
4124
+ { "key": "session_command_injection", "type": "boolean", "required": false, "description": "Command injection seen in any prior turn of this session" },
4125
+ { "key": "session_pii_detected", "type": "boolean", "required": false, "description": "PII seen in any prior turn of this session" },
4126
+ { "key": "session_pii_types", "type": "array", "required": false, "description": "PII types accumulated across session" },
4127
+ { "key": "session_secrets_detected", "type": "boolean", "required": false, "description": "Secrets seen in any prior turn of this session" },
4128
+ { "key": "session_secret_types", "type": "array", "required": false, "description": "Secret types accumulated across session" },
4129
+ { "key": "session_max_injection_score", "type": "number", "required": false, "description": "Max injection score across session turns" },
4130
+ { "key": "session_max_jailbreak_score", "type": "number", "required": false, "description": "Max jailbreak score across session turns" },
4131
+ { "key": "session_max_command_injection_score", "type": "number", "required": false, "description": "Max command-injection score across session turns" },
4132
+ { "key": "session_max_pii_score", "type": "number", "required": false, "description": "Max pii score across session turns" },
4133
+ { "key": "session_max_secret_score", "type": "number", "required": false, "description": "Max secret score across session turns" },
4134
+ { "key": "rpm_remaining_pct", "type": "number", "required": false, "description": "Remaining RPM (requests per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
4135
+ { "key": "rpm_exceeded", "type": "boolean", "required": false, "description": "Whether the RPM limit has been exceeded. Use this to enforce rate limits via Cedar policy" },
4136
+ { "key": "tpm_remaining_pct", "type": "number", "required": false, "description": "Remaining TPM (tokens per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
4137
+ { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" }
4138
+ ]
4139
+ },
3851
4140
  {
3852
4141
  "name": "read_file",
3853
4142
  "description": "Read an MCP resource — threat focus: secrets exposure, PII exposure",
@@ -4047,6 +4336,117 @@ export const GUARDRAILS_CONTEXT = {
4047
4336
  { "key": "agent_publisher", "type": "string", "required": false, "description": "Organization that published the agent (e.g., \'anthropic\', \'internal\', \'acme-corp\'). Use this for organization-level trust policies" }
4048
4337
  ]
4049
4338
  },
4339
+ {
4340
+ "name": "process_response",
4341
+ "description": "Process a model response (LLM chat completion output) — threat focus: data leakage in output, harmful content, hallucination, indirect injection carried back to the caller. Distinct trigger from process_prompt (ADR 0031) so a policy can be scoped to one direction from its head and prompt-only detectors stay off the egress path.",
4342
+ "context_attributes": [
4343
+ { "key": "role", "type": "string", "required": false, "description": "Caller\'s RBAC role projected from the principal\'s token (AARM R6 / CAP-IDN-011), e.g. finance_lead. Absent when the token carries no role claim." },
4344
+ { "key": "privilege_scope", "type": "array", "required": false, "description": "Privilege-scope strings granted to the caller, projected from the token (AARM R6 / CAP-IDN-011), e.g. transfer:approve. Absent when the token carries no claim." },
4345
+ { "key": "identity_type", "type": "string", "required": false, "description": "Principal identity class projected from the token: \'human\', \'agent\', or \'service\'. Use to apply identity-class-specific policies" },
4346
+ { "key": "principal", "type": "string", "required": false, "description": "Stable principal identifier projected from the token (e.g. a ZeroID / WIMSE URI or user id). Absent when the token carries no principal claim" },
4347
+ { "key": "request_id", "type": "string", "required": true, "description": "Unique identifier for this request, useful for audit trails and debugging" },
4348
+ { "key": "timestamp", "type": "number", "required": true, "description": "Unix timestamp in milliseconds when the request was processed" },
4349
+ { "key": "direction", "type": "string", "required": true, "description": "Content flow direction: \'input\' for user prompts, \'output\' for AI responses. Use this to apply different policies to inputs vs outputs (e.g., block PII only in outputs)" },
4350
+ { "key": "content_type", "type": "string", "required": true, "description": "Type of content being analyzed: \'prompt\', \'response\', \'tool_call\', \'file\', or \'clipboard\'" },
4351
+ { "key": "detector_count", "type": "number", "required": true, "description": "Number of detectors that were executed for this request" },
4352
+ { "key": "injection_score", "type": "number", "required": false, "description": "Combined prompt injection confidence (0-100). MAX of all detector scores (Pulse + DeepContext). Use injection_pulse_score / injection_deep_context_score for individual detector control" },
4353
+ { "key": "jailbreak_score", "type": "number", "required": false, "description": "Combined jailbreak detection confidence (0-100). MAX of all detector scores (Pulse + DeepContext). Use jailbreak_pulse_score / jailbreak_deep_context_score for individual detector control" },
4354
+ { "key": "injection_pulse_score", "type": "number", "required": false, "description": "Highflame single-turn classifier score for prompt injection (0-100). Raw score from Pulse detector before combination with deep-context. Use for per-detector policy control" },
4355
+ { "key": "injection_deep_context_score", "type": "number", "required": false, "description": "DeepContext multi-turn analyzer score for prompt injection (0-100). Tracks injection patterns across conversation history. Generally higher confidence than single-turn" },
4356
+ { "key": "jailbreak_pulse_score", "type": "number", "required": false, "description": "Highflame single-turn classifier score for jailbreak attempts (0-100). Raw score from Pulse detector before combination with deep-context" },
4357
+ { "key": "jailbreak_deep_context_score", "type": "number", "required": false, "description": "DeepContext multi-turn analyzer score for jailbreak attempts (0-100). Detects jailbreak escalation patterns across conversation turns" },
4358
+ { "key": "injection_type", "type": "string", "required": false, "description": "Type of injection detected: \'prompt\', \'sql\', \'command\', or \'none\'. Use this to apply different policies per injection type" },
4359
+ { "key": "secrets_detected", "type": "boolean", "required": false, "description": "Whether any API keys, tokens, passwords, or credentials were detected in the content. True indicates presence of secrets" },
4360
+ { "key": "secret_count", "type": "number", "required": false, "description": "Total number of secret matches found. Multiple matches may indicate data dumps or accidental credential exposure" },
4361
+ { "key": "secret_types", "type": "array", "required": false, "description": "Array of secret types found (e.g., [\'aws_access_key\', \'github_token\']). Use set operations like .contains() to check for specific types" },
4362
+ { "key": "pii_detected", "type": "boolean", "required": false, "description": "Whether personally identifiable information (PII) was found in the content. Commonly used to block PII in outputs to prevent data leakage" },
4363
+ { "key": "pii_count", "type": "number", "required": false, "description": "Total number of PII matches found (emails, phone numbers, SSNs, etc.)" },
4364
+ { "key": "pii_types", "type": "array", "required": false, "description": "Array of PII types detected (e.g., [\'email\', \'phone\', \'ssn\', \'credit_card\']). Use .contains() to block specific sensitive types" },
4365
+ { "key": "pii_score", "type": "number", "required": false, "description": "PII detection ML classifier confidence (0-100). Catches novel PII patterns including names, addresses, and identifiers that regex rules may miss. Typical threshold: >=80 for high-confidence blocking" },
4366
+ { "key": "highest_severity", "type": "string", "required": false, "description": "Highest severity level across all detection engines: \'critical\', \'high\', \'medium\', \'low\', or \'none\'. Use for severity-based catch-all policies (e.g., block any content flagged as critical)" },
4367
+ { "key": "violence_score", "type": "number", "required": false, "description": "ML-based score for violent content references (0-100). Typical threshold: >90 for critical blocks, >60 for warnings" },
4368
+ { "key": "hate_speech_score", "type": "number", "required": false, "description": "ML-based score for hate speech, discriminatory language, or targeted harassment (0-100). Typical threshold: >75 for blocks" },
4369
+ { "key": "sexual_score", "type": "number", "required": false, "description": "ML-based score for sexual or adult content (0-100). Adjust thresholds based on your application\'s audience" },
4370
+ { "key": "weapons_score", "type": "number", "required": false, "description": "ML-based score for weapons references or violent imagery (0-100)" },
4371
+ { "key": "crime_score", "type": "number", "required": false, "description": "ML-based score for criminal activity discussions (0-100)" },
4372
+ { "key": "profanity_score", "type": "number", "required": false, "description": "ML-based score for profanity and vulgar language (0-100)" },
4373
+ { "key": "content_topics", "type": "array", "required": false, "description": "Semantic topics detected in content (e.g., [\'controlled_substances\', \'weapons_manufacturing\']). Use .contains() to block specific topics per application" },
4374
+ { "key": "topic_confidence", "type": "number", "required": false, "description": "Confidence score from topic classifier (0-100). Use with content_topics to tune sensitivity — higher thresholds reduce false positives" },
4375
+ { "key": "invisible_chars_detected", "type": "boolean", "required": false, "description": "Whether invisible Unicode characters (zero-width joiners, RTL marks, etc.) were detected in the content. Commonly used for prompt injection evasion" },
4376
+ { "key": "invisible_chars_score", "type": "number", "required": false, "description": "Density score for invisible characters in the content (0-100). Higher scores indicate more invisible characters, suggesting evasion attempts" },
4377
+ { "key": "command_injection_detected", "type": "boolean", "required": false, "description": "Whether command injection patterns were detected in the content (reverse shells, privilege escalation, destructive commands)" },
4378
+ { "key": "command_injection_type", "type": "string", "required": false, "description": "Type of command injection: \'reverse_shell\', \'privilege_escalation\', \'code_execution\', \'destructive_command\', or \'data_exfiltration\'" },
4379
+ { "key": "command_injection_score", "type": "number", "required": false, "description": "Confidence score for command injection detection (0-100). Higher scores indicate stronger pattern matches" },
4380
+ { "key": "path_traversal_detected", "type": "boolean", "required": false, "description": "Whether path traversal patterns were detected (e.g., ../../../etc/passwd, URL-encoded variants)" },
4381
+ { "key": "path_traversal_severity", "type": "string", "required": false, "description": "Severity of path traversal: \'critical\' (sensitive system files), \'high\' (deep traversal), \'medium\' (moderate traversal), \'low\', or \'none\'" },
4382
+ { "key": "path_traversal_type", "type": "string", "required": false, "description": "Type of path traversal detected (e.g., \'sensitive_file\', \'deep_traversal\', \'encoded_traversal\')" },
4383
+ { "key": "sql_injection_detected", "type": "boolean", "required": false, "description": "Whether SQL injection patterns were detected (tautologies, UNION-based, destructive queries)" },
4384
+ { "key": "sql_injection_type", "type": "string", "required": false, "description": "Type of SQL injection: \'tautology\', \'union_based\', \'destructive\', \'blind\', or \'error_based\'" },
4385
+ { "key": "sql_injection_score", "type": "number", "required": false, "description": "Confidence score for SQL injection detection (0-100). Typical threshold: >=75 for blocks" },
4386
+ { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected (tool calls or references crossing trust boundaries)" },
4387
+ { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation: \'cross_origin_tool\', \'cross_origin_server\', or \'none\'" },
4388
+ { "key": "cross_origin_score", "type": "number", "required": false, "description": "Risk score for cross-origin escalation (0-100). Higher scores indicate more suspicious cross-boundary activity" },
4389
+ { "key": "package_install_detected", "type": "boolean", "required": false, "description": "Whether the event contains a recognized package install/download command (pip, npm, yarn, pnpm, bun, uv, gem, cargo, go, composer)" },
4390
+ { "key": "packages_checked", "type": "number", "required": false, "description": "Number of unique packages checked against the osv.dev database for this event" },
4391
+ { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "Whether any referenced package has a known-malicious OSV advisory (OpenSSF MAL- ID). Use to block supply-chain attacks at install time" },
4392
+ { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise" },
4393
+ { "key": "malicious_packages", "type": "array", "required": false, "description": "Malicious packages as ecosystem/name[@version] strings (e.g. \'PyPI/evil-pkg@1.0.0\')" },
4394
+ { "key": "package_names", "type": "array", "required": false, "description": "Names of all packages parsed from the install command (without ecosystem prefix), e.g. [\'requests\', \'left-pad\']. Available even when the osv.dev lookup fails." },
4395
+ { "key": "package_ecosystems", "type": "array", "required": false, "description": "Unique package ecosystems seen in this event, e.g. [\'PyPI\', \'npm\']. Useful for policy rules that restrict which ecosystems are permitted." },
4396
+ { "key": "package_advisory_count", "type": "number", "required": false, "description": "Total number of non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." },
4397
+ { "key": "package_risk_score", "type": "number", "required": false, "description": "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." },
4398
+ { "key": "package_check_status", "type": "string", "required": false, "description": "Set to \'degraded\' when the osv.dev lookup failed and packages could not be verified (fail-open). Combine with package_install_detected to fail closed" },
4399
+ { "key": "encoded_content_detected", "type": "boolean", "required": false, "description": "Whether encoded content was detected (base64, hex, unicode, URL encoding) that may hide malicious payloads" },
4400
+ { "key": "encoded_types", "type": "array", "required": false, "description": "Array of encoding types detected (e.g., [\'base64\', \'hex\', \'unicode\', \'url\']). Use .contains() to check for specific encoding types" },
4401
+ { "key": "encoded_count", "type": "number", "required": false, "description": "Number of encoded segments found in the content" },
4402
+ { "key": "encoded_score", "type": "number", "required": false, "description": "Risk score for encoded injection attempts (0-100). Considers encoding density and decoded content patterns" },
4403
+ { "key": "detected_language", "type": "string", "required": false, "description": "ISO language code of the detected language (e.g., \'en\', \'fr\', \'zh\'). Use this for language-specific policy enforcement" },
4404
+ { "key": "is_english", "type": "boolean", "required": false, "description": "Whether the content is in English. Useful for applying English-only policies or flagging non-English content" },
4405
+ { "key": "language_confidence", "type": "number", "required": false, "description": "Confidence score for language detection (0-100). Use with detected_language to tune sensitivity" },
4406
+ { "key": "detected_script", "type": "string", "required": false, "description": "Writing script detected in content: \'latin\', \'cyrillic\', \'arabic\', \'cjk\', \'unknown\', etc. Use to detect script-switching attacks" },
4407
+ { "key": "is_latin_script", "type": "boolean", "required": false, "description": "Whether the content uses Latin script. Useful for detecting non-Latin script injection attempts" },
4408
+ { "key": "script_confidence", "type": "number", "required": false, "description": "Confidence score for script detection (0-100)" },
4409
+ { "key": "hallucination_score", "type": "number", "required": false, "description": "ML-based score for hallucinated or fabricated content (0-100). Higher scores indicate higher likelihood of non-factual claims" },
4410
+ { "key": "factuality_score", "type": "number", "required": false, "description": "ML-based factuality assessment score (0-100). Higher scores indicate more factually grounded content" },
4411
+ { "key": "sentiment_score", "type": "number", "required": false, "description": "Sentiment analysis score. Use to detect overly negative or manipulative tone in prompts or responses" },
4412
+ { "key": "contains_code", "type": "boolean", "required": false, "description": "Whether code snippets were detected in the content" },
4413
+ { "key": "code_languages", "type": "array", "required": false, "description": "Array of programming languages detected in code snippets (e.g., [\'python\', \'javascript\'])" },
4414
+ { "key": "code_ratio", "type": "number", "required": false, "description": "Percentage of content that consists of code (0-100). High values may indicate code dumps or automated content" },
4415
+ { "key": "keyword_matched", "type": "boolean", "required": false, "description": "Whether any configured keywords or phrases were matched in the content" },
4416
+ { "key": "keyword_categories", "type": "array", "required": false, "description": "Array of keyword categories matched (e.g., [\'competitor_names\', \'restricted_topics\']). Use .contains() for category-specific policies" },
4417
+ { "key": "keyword_count", "type": "number", "required": false, "description": "Number of keyword matches found in the content" },
4418
+ { "key": "contains_non_ascii", "type": "boolean", "required": false, "description": "Whether non-ASCII characters were detected. May indicate obfuscation or encoding-based evasion attempts" },
4419
+ { "key": "phishing_detected", "type": "boolean", "required": false, "description": "Whether phishing patterns were detected in the content (suspicious URLs, impersonation, credential requests)" },
4420
+ { "key": "content_safety_score", "type": "number", "required": false, "description": "Aggregate content safety score (0-100). Combines multiple safety signals into a single risk indicator" },
4421
+ { "key": "content_safety_blocked", "type": "boolean", "required": false, "description": "Whether content was flagged for blocking by the content safety system" },
4422
+ { "key": "conversation_turn", "type": "number", "required": false, "description": "Current conversation turn number. Use for policies that escalate strictness over long conversations" },
4423
+ { "key": "multi_turn_detection", "type": "boolean", "required": false, "description": "Whether multi-turn injection patterns were detected (attack spread across multiple conversation turns)" },
4424
+ { "key": "rpm_remaining_pct", "type": "number", "required": false, "description": "Remaining RPM (requests per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
4425
+ { "key": "rpm_exceeded", "type": "boolean", "required": false, "description": "Whether the RPM limit has been exceeded. Use this to enforce rate limits via Cedar policy" },
4426
+ { "key": "tpm_remaining_pct", "type": "number", "required": false, "description": "Remaining TPM (tokens per minute) as percentage (0-100). Gateway-metered, Shield-decided (ADR 0014)" },
4427
+ { "key": "tpm_exceeded", "type": "boolean", "required": false, "description": "Whether the TPM limit has been exceeded. Use this to enforce token rate limits via Cedar policy" },
4428
+ { "key": "session_pii_detected", "type": "boolean", "required": false, "description": "Whether PII was detected in any previous turn of the session" },
4429
+ { "key": "session_pii_types", "type": "array", "required": false, "description": "PII types detected across the session (accumulated)" },
4430
+ { "key": "session_secrets_detected", "type": "boolean", "required": false, "description": "Whether secrets were detected in any previous turn of the session" },
4431
+ { "key": "session_secret_types", "type": "array", "required": false, "description": "Secret types detected across the session (accumulated)" },
4432
+ { "key": "session_injection_detected", "type": "boolean", "required": false, "description": "Whether prompt injection was detected in any previous turn of the session" },
4433
+ { "key": "session_command_injection", "type": "boolean", "required": false, "description": "Whether command injection was detected in any previous turn of the session" },
4434
+ { "key": "session_threat_turns", "type": "number", "required": false, "description": "Number of turns in the session where threats were detected" },
4435
+ { "key": "session_max_injection_score", "type": "number", "required": false, "description": "Highest prompt injection score seen in any turn of the session (0-100). Use for tiered responses: >75 hard block, >50 restrict permissions" },
4436
+ { "key": "session_max_jailbreak_score", "type": "number", "required": false, "description": "Highest jailbreak detection score seen in any turn of the session (0-100)" },
4437
+ { "key": "session_max_command_injection_score", "type": "number", "required": false, "description": "Highest command injection score seen in any turn of the session (0-100)" },
4438
+ { "key": "session_max_pii_score", "type": "number", "required": false, "description": "Highest PII risk score seen in any turn of the session (0-100)" },
4439
+ { "key": "session_max_secret_score", "type": "number", "required": false, "description": "Highest secret detection score seen in any turn of the session (0-100)" },
4440
+ { "key": "session_cumulative_risk_score", "type": "number", "required": false, "description": "Sum of per-turn risk scores across the session. Catches death-by-a-thousand-cuts where no single turn is high but cumulative risk is significant" },
4441
+ { "key": "session_max_sensitivity", "type": "string", "required": false, "description": "Highest data-sensitivity tier observed across the session (e.g. \'public\', \'internal\', \'confidential\', \'restricted\'). Use for session-level escalation policies" },
4442
+ { "key": "session_original_request", "type": "string", "required": false, "description": "The session\'s first user request, retained for drift / goal-hijack policies that compare later turns against the original intent" },
4443
+ { "key": "agent_id", "type": "string", "required": false, "description": "Unique identifier of the authenticated AI agent making this request (e.g., \'agent_research_v3\'). Empty string for human user requests. Use this to write agent-specific policies" },
4444
+ { "key": "agent_type", "type": "string", "required": false, "description": "Type of the authenticated agent: \'orchestrator\' (coordinates sub-agents), \'autonomous\' (self-directed), \'tool_agent\' (single-purpose tool), or \'human_proxy\' (acts on behalf of a human). Empty string for human users" },
4445
+ { "key": "agent_trust_level", "type": "string", "required": false, "description": "Trust level of the authenticated agent: \'first_party\' (your own agents), \'verified_third_party\' (audited external agents), or \'unverified\' (unknown agents). Use this for tiered access control — e.g., only first_party agents can call dangerous tools" },
4446
+ { "key": "agent_framework", "type": "string", "required": false, "description": "Framework or SDK the agent is built with (e.g., \'claude-code\', \'langchain\', \'crewai\', \'autogen\'). Use this to apply framework-specific policies" },
4447
+ { "key": "agent_publisher", "type": "string", "required": false, "description": "Organization that published the agent (e.g., \'anthropic\', \'internal\', \'acme-corp\'). Use this for organization-level trust policies" }
4448
+ ]
4449
+ },
4050
4450
  {
4051
4451
  "name": "call_tool",
4052
4452
  "description": "Execute agentic tool calls, including shell commands, file operations, and MCP tools",
@@ -4113,6 +4513,11 @@ export const GUARDRAILS_CONTEXT = {
4113
4513
  { "key": "mcp_input_request_types", "type": "array", "required": false, "description": "Threat shapes found in the input request (e.g. [\'credential_elicitation\', \'sampling_injection\', \'root_probe\']). Use .contains() to block a specific shape" },
4114
4514
  { "key": "mcp_input_request_methods", "type": "array", "required": false, "description": "MCP methods the server asked the client to perform (e.g. [\'elicitation/create\', \'sampling/createMessage\', \'roots/list\']). Independent of content, so a policy can refuse a capability outright — e.g. mcp_input_request_methods.contains(\"sampling/createMessage\") on an unverified server — rather than only reacting to a payload that was successfully classified" },
4115
4515
  { "key": "tool_operation_classes", "type": "array", "required": false, "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: \'readonly\', \'write_enabling\', \'execute_enabling\', \'network_access\', \'unknown\'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). \'unknown\' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy." },
4516
+ { "key": "resolved_target_paths", "type": "string", "required": false, "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with \'*\': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated." },
4517
+ { "key": "read_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths)." },
4518
+ { "key": "write_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\"." },
4519
+ { "key": "exec_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths)." },
4520
+ { "key": "unresolved_target", "type": "boolean", "required": false, "description": "True when a shell command\'s target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments." },
4116
4521
  { "key": "cross_origin_detected", "type": "boolean", "required": false, "description": "Whether cross-origin escalation patterns were detected in tool calls crossing trust boundaries" },
4117
4522
  { "key": "cross_origin_type", "type": "string", "required": false, "description": "Type of cross-origin escalation detected in tool call" },
4118
4523
  { "key": "cross_origin_score", "type": "number", "required": false, "description": "Risk score for cross-origin escalation in tool calls (0-100)" },
@@ -4432,6 +4837,11 @@ export const OVERWATCH_CONTEXT = {
4432
4837
  { "key": "sequence_risk", "type": "number", "required": false, "description": "Behavioral sequence risk score (0-100)" },
4433
4838
  { "key": "mcp_server_verified", "type": "boolean", "required": false, "description": "Whether the MCP server is from a verified registry" },
4434
4839
  { "key": "tool_operation_classes", "type": "array", "required": false, "description": "All operation classes observed in the tool call, emitted by the AST command classifiers. Subset of: \'readonly\', \'write_enabling\', \'execute_enabling\', \'network_access\', \'unknown\'. A single command can carry several classes; combine with contains() to match shapes — e.g. tool_operation_classes.contains(\"network_access\") && tool_operation_classes.contains(\"execute_enabling\") catches download-and-run (curl | sh). Used by the Bash Operation Classes template. \'unknown\' appears when any unrecognized or variable-expanded command was seen and should be treated as deny-worthy." },
4840
+ { "key": "resolved_target_paths", "type": "string", "required": false, "description": "Newline-delimited (leading+trailing \\n) union of the statically-resolved absolute target paths a shell command touches, any capability, emitted by the bash AST detector. Cedar like is full-string anchored and every value starts with the \\n delimiter, so patterns must begin with \'*\': anchored sub-tree \"*\\n/etc/*\" (matches only paths under /etc, unlike the loose \"*/etc/*\" which also hits a project etc/ dir at any depth), bare directory \"*\\n/etc\\n*\" (e.g. rm -rf /etc, no trailing slash), exact file \"*\\n/etc/passwd\\n*\". Resolution is purely lexical (cwd-join + path.Clean; quoting, escapes, wrappers, cd/VAR/bash -c normalized); remote endpoints and dynamic operands are never fabricated." },
4841
+ { "key": "read_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command reads or enumerates, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths)." },
4842
+ { "key": "write_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command writes, creates, or destroys (redirects, cp/mv/dd, curl/wget -o, scp/rsync local dest, tar/unzip/cpio extraction, yq -i), emitted by the bash AST detector. \\n-anchored: e.g. write_target_paths like \"*\\n/etc/cron.d/*\"." },
4843
+ { "key": "exec_target_paths", "type": "string", "required": false, "description": "Newline-delimited resolved absolute paths a shell command executes as a script, emitted by the bash AST detector. \\n-anchored: match with like patterns that begin with \'*\' (see resolved_target_paths)." },
4844
+ { "key": "unresolved_target", "type": "boolean", "required": false, "description": "True when a shell command\'s target hid behind a variable, glob, command substitution, or inline shell code that static analysis could not resolve, or when the 64-path / 4096-byte path-list cap truncated the results. Benign dev traffic sets this frequently (variables, globs, and command substitution are everywhere, and the truncation cap trips it too), so it is NOT a deny signal on its own — combine it with a path or operation match, and reserve a blanket deny-on-unresolved rule for high-assurance or allowlisted environments." },
4435
4845
  { "key": "package_install_detected", "type": "boolean", "required": false, "description": "True iff a package install/download command was recognized in the tool call arguments." },
4436
4846
  { "key": "malicious_package_detected", "type": "boolean", "required": false, "description": "True iff any referenced package has a known-malicious (MAL-) OSV advisory." },
4437
4847
  { "key": "malicious_package_score", "type": "number", "required": false, "description": "100 when a malicious package was detected, 0 otherwise." },