@highflame/policy 2.2.40 → 2.2.42

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 (33) hide show
  1. package/_schemas/agent_ops/templates/ported/organization/organization_deny_baseline.cedar +2 -2
  2. package/_schemas/agent_ops/templates/ported/tool-permissioning/tools_mcp_server_allowlist.cedar +24 -4
  3. package/_schemas/ai_gateway/context.json +300 -0
  4. package/_schemas/ai_gateway/detectors.json +928 -0
  5. package/_schemas/ai_gateway/schema.cedarschema +107 -3
  6. package/_schemas/ai_gateway/templates/mcp_server_allowlist.cedar +24 -4
  7. package/_schemas/guardrails/detectors.json +2193 -0
  8. package/_schemas/guardrails/templates/mcp_server_allowlist.cedar +24 -4
  9. package/_schemas/guardrails/templates/profiles/output_protection/credentials.cedar +35 -0
  10. package/_schemas/guardrails/templates/profiles/output_protection/data_leakage.cedar +63 -0
  11. package/_schemas/guardrails/templates/profiles/output_protection/harmful_content.cedar +58 -0
  12. package/_schemas/guardrails/templates/profiles/output_protection/injection_carried_back.cedar +39 -0
  13. package/_schemas/guardrails/templates/templates.json +107 -11
  14. package/_schemas/overwatch/context.json +65 -0
  15. package/_schemas/overwatch/detectors.json +1129 -0
  16. package/_schemas/overwatch/schema.cedarschema +90 -0
  17. package/_schemas/sentry/detectors.json +857 -0
  18. package/dist/agent_ops-defaults.gen.js +26 -6
  19. package/dist/ai_gateway-defaults.gen.js +24 -4
  20. package/dist/ai_gateway-detectors.gen.d.ts +1 -1
  21. package/dist/ai_gateway-detectors.gen.js +22 -8
  22. package/dist/ai_gateway-entities.gen.js +5 -1
  23. package/dist/guardrails-defaults.gen.js +366 -15
  24. package/dist/guardrails-detectors.gen.d.ts +1 -1
  25. package/dist/guardrails-detectors.gen.js +22 -8
  26. package/dist/overwatch-context.gen.d.ts +3 -1
  27. package/dist/overwatch-context.gen.js +4 -0
  28. package/dist/overwatch-defaults.gen.js +25 -5
  29. package/dist/overwatch-detectors.gen.d.ts +1 -1
  30. package/dist/overwatch-detectors.gen.js +38 -8
  31. package/dist/service-schemas.gen.d.ts +2 -2
  32. package/dist/service-schemas.gen.js +267 -8
  33. package/package.json +1 -1
@@ -1547,7 +1547,23 @@ const OVERWATCH_TOOLS_MCP_SERVER_ALLOWLIST_CEDAR = `// =========================
1547
1547
  // MCP Server Allowlist
1548
1548
  // =============================================================================
1549
1549
  // Restricts MCP server connections to a pre-approved list. Customize the
1550
- // \`context.mcp_server\` values in the permit rule to match allowed servers.
1550
+ // \`context.mcp_server\` values to match the allowed servers for your
1551
+ // environment — the SAME list appears in both rules and both must be edited.
1552
+ //
1553
+ // Both rules are conditional on the allowlist, and both are needed:
1554
+ //
1555
+ // permit ... when { allowlisted } grants access; Cedar is default-deny,
1556
+ // so without this nothing allows the
1557
+ // allowlisted servers either.
1558
+ // forbid ... unless { allowlisted } claws back everything else, including
1559
+ // when a broad Baseline Permit is loaded.
1560
+ //
1561
+ // The forbid MUST carry the negation. \`forbid\` always beats \`permit\` in Cedar,
1562
+ // so an UNCONDITIONAL forbid denies the allowlisted servers too — which is
1563
+ // what this template used to do (highflame-policy#186).
1564
+ //
1565
+ // The \`context has mcp_server\` guard stays inside both conditions: a request
1566
+ // naming no server cannot be on the allowlist, so it is denied.
1551
1567
  //
1552
1568
  // Context keys consumed:
1553
1569
  // - mcp_server: String
@@ -1573,7 +1589,7 @@ when {
1573
1589
 
1574
1590
  @id("tools.deny-non-allowlisted-mcp")
1575
1591
  @name("Block non-allowlisted MCP servers")
1576
- @description("Blocks connect_server unconditionally so only the allowlist permit applies.")
1592
+ @description("Blocks connect_server unless mcp_server is in the allowlist.")
1577
1593
  @severity("medium")
1578
1594
  @tags("category:tools,surface:connect-server,scope:org-wide,posture:deny-default")
1579
1595
  @reject_message("MCP server connection blocked: server is not on the allowlist.")
@@ -1581,7 +1597,11 @@ forbid (
1581
1597
  principal,
1582
1598
  action == Overwatch::Action::"connect_server",
1583
1599
  resource
1584
- );
1600
+ )
1601
+ unless {
1602
+ context has mcp_server &&
1603
+ (context.mcp_server == "filesystem" || context.mcp_server == "playwright")
1604
+ };
1585
1605
  `;
1586
1606
  const OVERWATCH_TOOLS_MCP_TOOL_PERMISSIONS_CEDAR = `// =============================================================================
1587
1607
  // MCP Tool Permissions
@@ -1652,8 +1672,8 @@ const OVERWATCH_ORGANIZATION_DENY_BASELINE_CEDAR = `// =========================
1652
1672
  // =============================================================================
1653
1673
 
1654
1674
  @id("organization.deny-baseline")
1655
- @name("Block all actions (deny baseline)")
1656
- @description("Blocks all actions; pair with scoped permit rules for a deny-by-default posture.")
1675
+ @name("Block all actions (kill switch)")
1676
+ @description("Blocks all actions unconditionally. A kill switch, not a baseline: forbid beats permit in Cedar, so this also disables every permit in the set.")
1657
1677
  @severity("high")
1658
1678
  @tags("category:organization,posture:deny-default,scope:org-wide")
1659
1679
  @reject_message("Request blocked: this organization uses a deny-by-default baseline — only explicitly permitted actions are allowed.")
@@ -1,5 +1,5 @@
1
1
  import type { DetectorCard } from './detector-card-types.gen';
2
- export declare const OVERWATCH_DETECTOR_SPEC_VERSION = "1.0.0";
2
+ export declare const OVERWATCH_DETECTOR_SPEC_VERSION = "1.1.0";
3
3
  export declare const OVERWATCH_DETECTORS: readonly DetectorCard[];
4
4
  export declare const OVERWATCH_FIELD_TO_DETECTORS: Readonly<Record<string, readonly string[]>>;
5
5
  export declare function overwatchDetectorById(id: string): DetectorCard | undefined;
@@ -1,4 +1,4 @@
1
- export const OVERWATCH_DETECTOR_SPEC_VERSION = "1.0.0";
1
+ export const OVERWATCH_DETECTOR_SPEC_VERSION = "1.1.0";
2
2
  export const OVERWATCH_DETECTORS = [
3
3
  {
4
4
  id: "injection",
@@ -84,6 +84,20 @@ export const OVERWATCH_DETECTORS = [
84
84
  defendsAgainst: ["unbounded_consumption", "excessive_agency"],
85
85
  exampleAttacks: [{ title: "Runaway tool loop", vulnerabilityId: "unbounded_consumption", snippet: "(agentic) the same shell command is invoked 30x in a row", expectedSignal: { "loop_detected": true } }],
86
86
  },
87
+ {
88
+ id: "budget_checker",
89
+ displayName: "Budget Checker",
90
+ category: "agent_behavior",
91
+ stability: "stable",
92
+ tier: "fast",
93
+ inhouse: false,
94
+ model: null,
95
+ latencyP50Ms: null,
96
+ emits: [{ name: "budget_remaining_pct", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Remaining session token budget (0-100). Default-filled to 100 when no metering ran." }, { name: "budget_exceeded", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff the session token budget has been exceeded. Absent when no metering ran, so policies must guard with `context has`." }],
97
+ supportedModes: ["enforce", "monitor", "alert"],
98
+ defendsAgainst: ["unbounded_consumption"],
99
+ exampleAttacks: [{ title: "Runaway autonomous session", vulnerabilityId: "unbounded_consumption", snippet: "(agentic) one prompt drives hundreds of tool calls, burning the session's token budget unattended", expectedSignal: { "budget_exceeded": true } }],
100
+ },
87
101
  {
88
102
  id: "tool_risk",
89
103
  displayName: "Tool Risk",
@@ -191,15 +205,31 @@ export const OVERWATCH_DETECTORS = [
191
205
  inhouse: false,
192
206
  model: null,
193
207
  latencyP50Ms: 250,
194
- emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the tool call." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "package_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories found across all checked packages." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Graduated supply-chain risk score (0-100)." }, { name: "package_check_status", type: "String", modifiable: false, semantic: "category_label", description: "Set to 'degraded' when the osv.dev lookup failed (fail-open); empty otherwise." }],
208
+ emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_check_status", type: "String", modifiable: false, semantic: "category_label", description: "Set to 'degraded' when the osv.dev lookup failed (fail-open); empty otherwise." }],
195
209
  supportedModes: ["enforce", "monitor", "alert"],
196
210
  defendsAgainst: ["supply_chain"],
197
211
  exampleAttacks: [{ title: "Typosquatted PyPI package install", vulnerabilityId: "supply_chain", snippet: "pip install reqeusts", expectedSignal: {} }, { title: "Malicious npm package install", vulnerabilityId: "supply_chain", snippet: "npm install event-stream@3.3.6", expectedSignal: {} }],
198
212
  },
213
+ {
214
+ id: "package_reputation",
215
+ displayName: "Package Reputation (OSV)",
216
+ category: "tool_safety",
217
+ stability: "preview",
218
+ tier: "slow",
219
+ inhouse: false,
220
+ model: null,
221
+ latencyP50Ms: 250,
222
+ emits: [{ name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands (without ecosystem prefix), e.g. 'requests', 'left-pad'. Available even when the osv.dev lookup fails." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'. Useful for policies that restrict which ecosystems are permitted." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", 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." }],
223
+ supportedModes: ["enforce", "monitor", "alert"],
224
+ defendsAgainst: ["supply_chain"],
225
+ exampleAttacks: [{ title: "Install of a package carrying a malicious advisory", vulnerabilityId: "supply_chain", snippet: "pip install evil-pkg", expectedSignal: { "malicious_package_detected": true } }],
226
+ },
199
227
  ];
200
228
  // Semantic field → contributing detector ids (producesAttrs + normalizationAliases,
201
229
  // resolved at codegen). Used by the client field→detector resolver — no Shield round-trip.
202
230
  export const OVERWATCH_FIELD_TO_DETECTORS = {
231
+ "budget_exceeded": ["budget_checker"],
232
+ "budget_remaining_pct": ["budget_checker"],
203
233
  "crime_score": ["toxicity"],
204
234
  "exec_target_paths": ["bash_ast_classifier"],
205
235
  "hate_speech_score": ["toxicity"],
@@ -215,20 +245,20 @@ export const OVERWATCH_FIELD_TO_DETECTORS = {
215
245
  "loop_count": ["loop_detector"],
216
246
  "loop_detected": ["loop_detector"],
217
247
  "loop_tool": ["loop_detector"],
218
- "malicious_package_detected": ["malicious_package"],
248
+ "malicious_package_detected": ["malicious_package", "package_reputation"],
219
249
  "malicious_package_score": ["malicious_package"],
220
- "malicious_packages": ["malicious_package"],
250
+ "malicious_packages": ["malicious_package", "package_reputation"],
221
251
  "mcp_config_risk": ["mcp_risk"],
222
252
  "mcp_risk_score": ["mcp_risk"],
223
253
  "mcp_server": ["mcp_risk"],
224
254
  "mcp_server_verified": ["mcp_risk"],
225
255
  "mcp_tool": ["mcp_risk"],
226
- "package_advisory_count": ["malicious_package"],
256
+ "package_advisory_count": ["package_reputation"],
227
257
  "package_check_status": ["malicious_package"],
228
- "package_ecosystems": ["malicious_package"],
258
+ "package_ecosystems": ["package_reputation"],
229
259
  "package_install_detected": ["malicious_package"],
230
- "package_names": ["malicious_package"],
231
- "package_risk_score": ["malicious_package"],
260
+ "package_names": ["package_reputation"],
261
+ "package_risk_score": ["package_reputation"],
232
262
  "packages_checked": ["malicious_package"],
233
263
  "pattern_type": ["action_pattern"],
234
264
  "pii_count": ["pii"],
@@ -9,7 +9,7 @@ export declare const AGENT_OPS_SCHEMA = "// ====================================
9
9
  *
10
10
  * Full Cedar schema for ai_gateway, embedded at codegen time.
11
11
  */
12
- export declare const AI_GATEWAY_SCHEMA = "// AIGateway Cedar Schema\n// ===================================\n// AI Gateway Security & Policy Enforcement\n//\n// AIGateway protects both MCP proxy operations (tool calls, server connections)\n// and LLM chat completions (prompt processing) by evaluating threats detected\n// by the Shield detection engine pipeline against Cedar policies.\n//\n// Architecture:\n// MCP/LLM Client -> Firehog Proxy -> Shield (detection + Cedar) -> Allow/Deny\n//\n// Threat Coverage:\n// - OWASP Top 10 for LLM Applications 2025 (LLM01, LLM06)\n// - OWASP Top 10 for Agentic Applications (ASI01, ASI02, ASI04)\n// - OWASP MCP Top 10 (MCP01-MCP05)\n\nnamespace AIGateway {\n\n// =============================================================================\n// ENTITIES - Tenant Hierarchy (ReBAC)\n// =============================================================================\n// AIGateway does not use App/Session hierarchy.\n//\n// Entity hierarchy:\n// Account (org root)\n// -> Project in [Account]\n// -> Tool/Server in [Project]\n//\n// Policy scoping examples:\n// resource == AIGateway::Tool::\"get_me\" -> specific tool\n// resource in AIGateway::Project::\"<uuid>\" -> project-wide\n// resource in AIGateway::Account::\"<uuid>\" -> org-wide\n\n/// Account represents an organization (top-level tenant)\nentity Account;\n\n/// Project represents a project within an account\nentity Project in [Account];\n\n// =============================================================================\n// ENTITIES - Principals\n// =============================================================================\n\n/// Human user authenticated via JWT or API key\nentity User;\n\n/// MCP client (default principal for unauthenticated requests)\nentity MCP_Client;\n\n// =============================================================================\n// ENTITIES - Resources (scoped under Project)\n// =============================================================================\n\n/// MCP tool -- resource for call_tool action\nentity Tool in [Project];\n\n/// MCP server -- resource for connect_server action\nentity Server in [Project];\n\n/// MCP prompt -- resource for process_prompt action\nentity LlmPrompt in [Project];\n\n/// Model response -- resource for process_response action.\n/// Parented to Project like every other resource: Shield injects\n/// `when { resource in <Ns>::Project::\"<id>\" }` into every synced rule\n/// (shield#428), so a resource outside the project hierarchy would make\n/// every policy written against it unsatisfiable.\nentity LlmResponse in [Project];\n\n/// File/resource path -- resource for read_file/write_file actions\nentity FilePath in [Project];\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\n// Call an MCP tool\n// Threat focus: command injection, tool poisoning, rug pull, secrets, PII\naction call_tool appliesTo {\n principal: [User, MCP_Client],\n resource: [Tool],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Content ---\n content: String, // Raw content being scanned\n\n // --- Tool & MCP ---\n tool_name?: String, // Tool name\n mcp_server?: String, // MCP server name\n mcp_tool?: String, // MCP tool name\n\n // --- Threat Detection (from Shield detection pipeline) ---\n threat_count?: Long, // Total threats detected\n highest_severity?: String, // \"critical\", \"high\", \"medium\", \"low\", \"none\"\n threat_categories?: Set<String>, // Threat category names\n detected_threats?: Set<String>, // Detection rule names that matched\n max_threat_severity?: Long, // Numeric severity (0=none, 1=low, 2=medium, 3=high, 4=critical)\n secrets_detected?: Bool, // Whether secrets/credentials detected\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n injection_score?: Long, // Prompt injection classifier confidence\n jailbreak_score?: Long, // Jailbreak detection classifier confidence\n\n // --- Agent Security (0-100) ---\n tool_poisoning_score?: Long, // Hidden instructions in tool description/args\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long, // Tool behavior drift after trust establishment\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long, // Indirect injection via tool output\n\n // --- Tool Risk Assessment ---\n tool_risk_score?: Long, // Computed tool risk (0-100)\n tool_category?: String, // \"safe\", \"sensitive\", \"dangerous\"\n tool_is_sensitive?: Bool,\n tool_is_builtin?: Bool,\n\n // --- Tool Operation Classifier ---\n tool_operation_classes?: Set<String>, // subset of {\"readonly\", \"write_enabling\", \"execute_enabling\", \"network_access\", \"unknown\"}\n\n // --- Bash AST resolved target paths (#411 / CAP-DET-007) \u2014 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*\" ---\n resolved_target_paths?: String, // union of resolved absolute target paths, any capability\n read_target_paths?: String, // paths the command reads or enumerates\n write_target_paths?: String, // paths the command writes, creates, or destroys\n exec_target_paths?: String, // paths executed as a script\n unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated\n\n // --- MCP Trust ---\n mcp_server_verified?: Bool, // Whether server is from verified registry\n\n // --- Content Safety Scores (0-100) ---\n violence_score?: Long,\n weapons_score?: Long,\n hate_speech_score?: Long,\n crime_score?: Long,\n sexual_score?: Long,\n profanity_score?: Long,\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- Behavioral Analysis ---\n loop_detected?: Bool,\n loop_count?: Long,\n loop_tool?: String,\n suspicious_pattern?: Bool,\n pattern_type?: String,\n sequence_risk?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Connect to an MCP server\n// Threat focus: supply chain, tool poisoning, rug pull, config risk\naction connect_server appliesTo {\n principal: [User, MCP_Client],\n resource: [Server],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content?: String, // Server config content (if available)\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Agent Security (0-100) ---\n tool_poisoning_score?: Long,\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long,\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long,\n\n // --- Secrets ---\n secrets_detected?: Bool,\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- MCP Trust & Config Risk ---\n mcp_server_verified?: Bool,\n mcp_config_risk?: Bool,\n mcp_risk_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Shared content-inspection context.\n//\n// Prompts and responses are inspected by the same detector pipeline and so\n// carry the same context keys; only the TRIGGER differs (ADR 0031). Declaring\n// the shape once means a new detector key cannot land on one direction and go\n// missing on the other \u2014 the drift class shield#393 / shield#387 were about.\ntype ContentInspectionContext = {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n injection_score?: Long,\n jailbreak_score?: Long,\n\n // --- Content Safety Scores (0-100) ---\n violence_score?: Long,\n weapons_score?: Long,\n hate_speech_score?: Long,\n crime_score?: Long,\n sexual_score?: Long,\n profanity_score?: Long,\n\n // --- Encoding ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- LLM-specific ---\n model_name?: String, // Target model name (e.g., \"gpt-4\", \"claude-3-opus\")\n model_provider?: String, // Provider name (e.g., \"openai\", \"anthropic\", \"bedrock\")\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n};\n\n// Process a prompt (MCP prompts/get or LLM chat completions)\n// Threat focus: injection, jailbreak, secrets, PII, content safety\naction process_prompt appliesTo {\n principal: [User, MCP_Client],\n resource: [LlmPrompt],\n context: ContentInspectionContext,\n};\n\n// Process a model response (LLM chat completion output, streamed or buffered)\n// Threat focus: data leakage in output, harmful content, hallucination,\n// indirect injection carried back to the caller.\n//\n// Distinct from process_prompt so that (a) a policy can be scoped to one\n// direction from its head alone and (b) Shield's action-scoped detector\n// scheduling (INV-DET-001) can keep prompt-only detectors off the egress\n// path \u2014 before this action existed, a prompt-scoped dlp/model_armor/webhook\n// rule shipped response bodies downstream. See ADR 0031.\naction process_response appliesTo {\n principal: [User, MCP_Client],\n resource: [LlmResponse],\n context: ContentInspectionContext,\n};\n\n// Read an MCP resource (resources/read, resources/list)\n// Threat focus: secrets exposure, PII exposure, sensitive paths\naction read_file appliesTo {\n principal: [User, MCP_Client],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Write an MCP resource (resources/write)\n// Threat focus: secrets in output, PII in output\naction write_file appliesTo {\n principal: [User, MCP_Client],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n}\n";
12
+ export declare const AI_GATEWAY_SCHEMA = "// AIGateway Cedar Schema\n// ===================================\n// AI Gateway Security & Policy Enforcement\n//\n// AIGateway protects both MCP proxy operations (tool calls, server connections)\n// and LLM chat completions (prompt processing) by evaluating threats detected\n// by the Shield detection engine pipeline against Cedar policies.\n//\n// Architecture:\n// MCP/LLM Client -> Firehog Proxy -> Shield (detection + Cedar) -> Allow/Deny\n//\n// Threat Coverage:\n// - OWASP Top 10 for LLM Applications 2025 (LLM01, LLM06)\n// - OWASP Top 10 for Agentic Applications (ASI01, ASI02, ASI04)\n// - OWASP MCP Top 10 (MCP01-MCP05)\n\nnamespace AIGateway {\n\n// =============================================================================\n// ENTITIES - Tenant Hierarchy (ReBAC)\n// =============================================================================\n// AIGateway does not use App/Session hierarchy.\n//\n// Entity hierarchy:\n// Account (org root)\n// -> Project in [Account]\n// -> Tool/Server in [Project]\n//\n// Policy scoping examples:\n// resource == AIGateway::Tool::\"get_me\" -> specific tool\n// resource in AIGateway::Project::\"<uuid>\" -> project-wide\n// resource in AIGateway::Account::\"<uuid>\" -> org-wide\n\n/// Account represents an organization (top-level tenant)\nentity Account;\n\n/// Project represents a project within an account\nentity Project in [Account];\n\n// =============================================================================\n// ENTITIES - Principals\n// =============================================================================\n\n/// Human user authenticated via JWT or API key\nentity User;\n\n/// MCP client (default principal for unauthenticated requests)\nentity MCP_Client;\n\n// =============================================================================\n// ENTITIES - Resources (scoped under Project)\n// =============================================================================\n\n/// MCP tool -- resource for call_tool action\nentity Tool in [Project];\n\n/// MCP server -- resource for connect_server action\nentity Server in [Project];\n\n/// MCP prompt -- resource for process_prompt action\nentity LlmPrompt in [Project];\n\n/// Model response -- resource for process_response action.\n/// Parented to Project like every other resource: Shield injects\n/// `when { resource in <Ns>::Project::\"<id>\" }` into every synced rule\n/// (shield#428), so a resource outside the project hierarchy would make\n/// every policy written against it unsatisfiable.\nentity LlmResponse in [Project];\n\n/// File/resource path -- resource for read_file/write_file actions\nentity FilePath in [Project];\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\n// Call an MCP tool (tools/call). Enumeration is the `list` action.\n// Threat focus: command injection, tool poisoning, rug pull, secrets, PII\naction call_tool appliesTo {\n principal: [User, MCP_Client],\n resource: [Tool],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Content ---\n content: String, // Raw content being scanned\n\n // --- Tool & MCP ---\n tool_name?: String, // Tool name\n mcp_server?: String, // MCP server name\n mcp_tool?: String, // MCP tool name\n\n // --- Threat Detection (from Shield detection pipeline) ---\n threat_count?: Long, // Total threats detected\n highest_severity?: String, // \"critical\", \"high\", \"medium\", \"low\", \"none\"\n threat_categories?: Set<String>, // Threat category names\n detected_threats?: Set<String>, // Detection rule names that matched\n max_threat_severity?: Long, // Numeric severity (0=none, 1=low, 2=medium, 3=high, 4=critical)\n secrets_detected?: Bool, // Whether secrets/credentials detected\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n injection_score?: Long, // Prompt injection classifier confidence\n jailbreak_score?: Long, // Jailbreak detection classifier confidence\n\n // --- Agent Security (0-100) ---\n tool_poisoning_score?: Long, // Hidden instructions in tool description/args\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long, // Tool behavior drift after trust establishment\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long, // Indirect injection via tool output\n\n // --- Tool Risk Assessment ---\n tool_risk_score?: Long, // Computed tool risk (0-100)\n tool_category?: String, // \"safe\", \"sensitive\", \"dangerous\"\n tool_is_sensitive?: Bool,\n tool_is_builtin?: Bool,\n\n // --- Tool Operation Classifier ---\n tool_operation_classes?: Set<String>, // subset of {\"readonly\", \"write_enabling\", \"execute_enabling\", \"network_access\", \"unknown\"}\n\n // --- Bash AST resolved target paths (#411 / CAP-DET-007) \u2014 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*\" ---\n resolved_target_paths?: String, // union of resolved absolute target paths, any capability\n read_target_paths?: String, // paths the command reads or enumerates\n write_target_paths?: String, // paths the command writes, creates, or destroys\n exec_target_paths?: String, // paths executed as a script\n unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code, or the path-list cap truncated\n\n // --- MCP Trust ---\n mcp_server_verified?: Bool, // Whether server is from verified registry\n\n // --- Content Safety Scores (0-100) ---\n violence_score?: Long,\n weapons_score?: Long,\n hate_speech_score?: Long,\n crime_score?: Long,\n sexual_score?: Long,\n profanity_score?: Long,\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- Behavioral Analysis ---\n loop_detected?: Bool,\n loop_count?: Long,\n loop_tool?: String,\n suspicious_pattern?: Bool,\n pattern_type?: String,\n sequence_risk?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Connect to an MCP server\n// Threat focus: supply chain, tool poisoning, rug pull, config risk\naction connect_server appliesTo {\n principal: [User, MCP_Client],\n resource: [Server],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content?: String, // Server config content (if available)\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Agent Security (0-100) ---\n tool_poisoning_score?: Long,\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long,\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long,\n\n // --- Secrets ---\n secrets_detected?: Bool,\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- MCP Trust & Config Risk ---\n mcp_server_verified?: Bool,\n mcp_config_risk?: Bool,\n mcp_risk_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Enumerate a server's tools, prompts, or resources\n// (tools/list, prompts/list, resources/list)\n//\n// Threat focus: tool poisoning and rug pull in the DESCRIPTIONS returned by\n// enumeration \u2014 the text a host feeds the model when it assembles the\n// session's tool schema, and the vector a rug-pull exploits between scans.\n//\n// Distinct from the actions it enumerates, and deliberately NOT default-locked\n// (highflame-shield#515 / INV-AUTHZ-003). Listing is host plumbing: the model\n// never decides to enumerate, the host does it to build the session. Folding\n// it into call_tool / process_prompt / read_file made enumeration inherit\n// their lock, and because a list names no tool, no conditioned grant\n// (`context has tool_name && ...`) can ever match it \u2014 so an agent holding a\n// correct grant for every tool it uses was still denied the enumeration step,\n// and without tools/list it cannot call anything at all. The only grant that\n// could match was an unconditioned one, which would have lifted the lock for\n// every call as well. There is no way to express \"may list, may not call\"\n// while a list and a call are the same action. See highflame-firehog#589.\n//\n// Authorization over WHAT may be enumerated is expressed through the list\n// CONTENTS (the grant-derived list filter), not by denying the request.\naction list appliesTo {\n principal: [User, MCP_Client],\n resource: [Server],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n\n // --- Content ---\n // The enumerated item's description. Optional: a tool may declare none,\n // and a policy must still evaluate when it does not.\n content?: String,\n mcp_server?: String,\n\n // --- Enumerated item identity ---\n // The list is scanned one item at a time, so the item being evaluated\n // rides here while the resource stays the server being enumerated.\n tool_name?: String,\n tool_risk_score?: Long,\n tool_category?: String, // \"safe\", \"sensitive\", \"dangerous\"\n tool_is_sensitive?: Bool,\n tool_is_builtin?: Bool,\n tool_operation_classes?: Set<String>,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Agent Security (0-100) \u2014 the reason this action scans at all ---\n tool_poisoning_score?: Long, // Hidden instructions in a tool description\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long, // Description drift after trust establishment\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n injection_score?: Long,\n jailbreak_score?: Long,\n\n // --- Secrets ---\n secrets_detected?: Bool,\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- MCP Trust & Config Risk ---\n mcp_server_verified?: Bool,\n mcp_config_risk?: Bool,\n mcp_risk_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long,\n session_cumulative_risk_score?: Long,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Shared content-inspection context.\n//\n// Prompts and responses are inspected by the same detector pipeline and so\n// carry the same context keys; only the TRIGGER differs (ADR 0031). Declaring\n// the shape once means a new detector key cannot land on one direction and go\n// missing on the other \u2014 the drift class shield#393 / shield#387 were about.\ntype ContentInspectionContext = {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n injection_score?: Long,\n jailbreak_score?: Long,\n\n // --- Content Safety Scores (0-100) ---\n violence_score?: Long,\n weapons_score?: Long,\n hate_speech_score?: Long,\n crime_score?: Long,\n sexual_score?: Long,\n profanity_score?: Long,\n\n // --- Encoding ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- LLM-specific ---\n model_name?: String, // Target model name (e.g., \"gpt-4\", \"claude-3-opus\")\n model_provider?: String, // Provider name (e.g., \"openai\", \"anthropic\", \"bedrock\")\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n};\n\n// Process a prompt (MCP prompts/get or LLM chat completions).\n// Enumeration (prompts/list) is the `list` action.\n// Threat focus: injection, jailbreak, secrets, PII, content safety\naction process_prompt appliesTo {\n principal: [User, MCP_Client],\n resource: [LlmPrompt],\n context: ContentInspectionContext,\n};\n\n// Process a model response (LLM chat completion output, streamed or buffered)\n// Threat focus: data leakage in output, harmful content, hallucination,\n// indirect injection carried back to the caller.\n//\n// Distinct from process_prompt so that (a) a policy can be scoped to one\n// direction from its head alone and (b) Shield's action-scoped detector\n// scheduling (INV-DET-001) can keep prompt-only detectors off the egress\n// path \u2014 before this action existed, a prompt-scoped dlp/model_armor/webhook\n// rule shipped response bodies downstream. See ADR 0031.\naction process_response appliesTo {\n principal: [User, MCP_Client],\n resource: [LlmResponse],\n context: ContentInspectionContext,\n};\n\n// Read an MCP resource (resources/read). Enumeration (resources/list)\n// is the `list` action.\n// Threat focus: secrets exposure, PII exposure, sensitive paths\naction read_file appliesTo {\n principal: [User, MCP_Client],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n// Write an MCP resource (resources/write)\n// Threat focus: secrets in output, PII in output\naction write_file appliesTo {\n principal: [User, MCP_Client],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- Session-Aware Threat Aggregation ---\n session_threat_turns?: Long, // Count of turns with detected threats\n session_cumulative_risk_score?: Long, // Accumulated risk across turns\n session_injection_detected?: Bool, // Injection seen in any prior turn\n session_command_injection?: Bool, // Command injection seen in any prior turn\n session_pii_detected?: Bool, // PII seen in any prior turn\n session_pii_types?: Set<String>, // PII types accumulated across session\n session_secrets_detected?: Bool, // Secrets seen in any prior turn\n session_secret_types?: Set<String>, // Secret types accumulated across session\n session_max_injection_score?: Long, // Max injection score across session turns\n session_max_jailbreak_score?: Long, // Max jailbreak score across session turns\n session_max_command_injection_score?: Long, // Max command-injection score across session turns\n session_max_pii_score?: Long, // Max pii score across session turns\n session_max_secret_score?: Long, // Max secret score across session turns\n\n // --- Usage Budget (multi-window, multi-dimension) ---\n budget_remaining_pct?: Long,\n budget_exceeded?: Bool,\n budget_cost_micros_this_turn?: Long,\n budget_model?: String,\n budget_tokens_pct_session?: Long,\n budget_tokens_pct_daily?: Long,\n budget_tokens_pct_monthly?: Long,\n budget_cost_pct_daily?: Long,\n budget_cost_pct_monthly?: Long,\n budget_exceeded_session?: Bool,\n budget_exceeded_daily?: Bool,\n budget_exceeded_monthly?: Bool,\n\n // Rate Limiting \u2014 gateway-metered, Shield-decided (ADR 0014)\n rpm_remaining_pct?: Long,\n rpm_exceeded?: Bool,\n tpm_remaining_pct?: Long,\n tpm_exceeded?: Bool,\n },\n};\n\n}\n";
13
13
  /**
14
14
  * Guardrails Cedar schema
15
15
  *
@@ -21,7 +21,7 @@ export declare const GUARDRAILS_SCHEMA = "// ===================================
21
21
  *
22
22
  * Full Cedar schema for overwatch, embedded at codegen time.
23
23
  */
24
- export declare const OVERWATCH_SCHEMA = "// Overwatch Cedar Schema\n// ===================================\n// IDE Agent Security & Policy Enforcement\n//\n// Overwatch protects IDE agent operations (prompts, tool calls, file access, MCP connections)\n// by evaluating threats detected by the detection engine pipeline against Cedar policies.\n//\n// Architecture:\n// User/Agent \u2192 IDE Hook \u2192 Detection Engine \u2192 Cedar Policy \u2192 Allow/Deny\n//\n// Supported IDEs:\n// - Cursor (beforeSubmitPrompt, beforeShellExecution, beforeMCPExecution, etc.)\n// - Claude Code (UserPromptSubmit, PreToolUse)\n// - GitHub Copilot (userPromptSubmitted, preToolUse)\n//\n// Threat Coverage:\n// - OWASP Top 10 for LLM Applications 2025 (LLM01-LLM10)\n// - OWASP Top 10 for Agentic Applications (ASI01-ASI10)\n// - OWASP MCP Top 10 (MCP01-MCP05)\n// - MITRE ATLAS Agent Techniques (AML.T0051, AML.T0080-T0082)\n\nnamespace Overwatch {\n\n// =============================================================================\n// ENTITIES - Tenant Hierarchy (ReBAC)\n// =============================================================================\n// Aligned with Guardrails entity hierarchy (Account \u2192 Project).\n// Overwatch does not have app-specific policies, so App is omitted.\n//\n// Entity hierarchy enables Cedar's `in` operator for policy scoping:\n// Account (org root)\n// \u2514\u2500\u2500 Project in [Account]\n// \u2514\u2500\u2500 Tool/Server/FilePath/LlmPrompt in [Project]\n//\n// Policy scoping examples:\n// resource == Overwatch::Tool::\"shell\" \u2192 specific tool\n// resource in Overwatch::Project::\"<uuid>\" \u2192 project-wide\n// resource in Overwatch::Account::\"<uuid>\" \u2192 org-wide\n\n/// Account represents an organization (top-level tenant)\nentity Account;\n\n/// Project represents a project within an account\nentity Project in [Account];\n\n// =============================================================================\n// ENTITIES - Principals\n// =============================================================================\n\n/// Human user or service account making requests to the IDE\nentity User;\n\n/// AI agent (Claude, GitHub Copilot, etc.)\nentity Agent;\n\n// =============================================================================\n// ENTITIES - Resources (scoped under Project)\n// =============================================================================\n\n/// LLM prompt or session \u2014 resource for process_prompt action\nentity LlmPrompt in [Project];\n\n/// MCP tool or native IDE tool \u2014 resource for call_tool action\nentity Tool in [Project];\n\n/// MCP server \u2014 resource for connect_server action\nentity Server in [Project];\n\n/// File system path \u2014 resource for read_file/write_file/call_tool actions\nentity FilePath in [Project];\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\n// User submits a prompt or receives AI response\n// Threat focus: injection, jailbreak, secrets, PII, content safety, invisible chars\naction process_prompt appliesTo {\n principal: [User, Agent],\n resource: [LlmPrompt],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Event & Source ---\n content: String, // Raw content being scanned\n source: String, // IDE source: \"cursor\", \"claudecode\", \"github_copilot\"\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // --- Workspace ---\n cwd?: String, // Current working directory\n workspace_root?: String, // Workspace/repository root\n\n // --- Threat Detection (from detection engine pipeline) ---\n threat_count: Long, // Total threats detected\n highest_severity: String, // \"critical\", \"high\", \"medium\", \"low\", \"none\"\n threat_categories: Set<String>, // Threat category names\n detected_threats: Set<String>, // Detection rule names that matched\n max_threat_severity: Long, // Numeric severity (0=none, 1=low, 2=medium, 3=high, 4=critical)\n secrets_detected: Bool, // Whether secrets/credentials detected\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>, // Types: \"aws_access_key\", \"github_token\", \"ssh_private_key\", etc.\n secret_count?: Long, // Number of distinct secrets found\n\n // --- PII Detection ---\n pii_detected?: Bool, // Whether any PII patterns matched\n pii_types?: Set<String>, // Types: \"ssn\", \"credit_card\", \"email\", \"phone\", etc.\n pii_count?: Long, // Number of PII matches\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool, // Zero-width chars, bidi overrides, tag chars detected\n invisible_chars_score?: Long, // Unicode attack severity (0-100)\n\n // --- Content Safety Scores (0-100, from ML classifiers) ---\n violence_score: Long,\n weapons_score: Long,\n hate_speech_score: Long,\n crime_score: Long,\n sexual_score: Long,\n profanity_score: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n pii_score: Long, // PII detection classifier confidence\n injection_score: Long, // Combined injection confidence: MAX(pulse, deep_context)\n jailbreak_score: Long, // Combined jailbreak confidence: MAX(pulse, deep_context)\n injection_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n injection_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n jailbreak_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n jailbreak_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n\n // --- Agent Security (0-100) ---\n indirect_injection_score: Long, // Indirect prompt injection risk (OWASP LLM01, ASI01)\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Legacy ---\n prompt_text?: String, // Same as content (backward compatibility)\n response_content?: String, // Response content (if available)\n },\n};\n\n// User calls a tool (native IDE tool or MCP tool)\n// Threat focus: command injection, tool poisoning, rug pull, data exfiltration, loops\naction call_tool appliesTo {\n principal: [User, Agent],\n resource: [Tool, FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Event & Source ---\n content: String, // Raw content being scanned (e.g., shell command, tool args)\n source: String, // IDE source\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // --- Tool & MCP ---\n tool_name?: String, // Normalized tool name (\"shell\", \"read_file\", etc.)\n mcp_server?: String, // MCP server name\n mcp_tool?: String, // MCP tool name\n\n // --- File & Path ---\n path?: String, // File path (if file operation)\n\n // --- Workspace ---\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- Content Safety Scores (0-100) ---\n violence_score?: Long,\n weapons_score?: Long,\n hate_speech_score?: Long,\n crime_score?: Long,\n sexual_score?: Long,\n profanity_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n pii_score?: Long,\n injection_score?: Long, // Combined injection confidence: MAX(pulse, deep_context)\n jailbreak_score?: Long, // Combined jailbreak confidence: MAX(pulse, deep_context)\n injection_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n injection_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n jailbreak_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n jailbreak_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n\n // --- Agent Security (0-100) --- (OWASP ASI01, ASI02, ASI04; MITRE AML.T0051)\n tool_poisoning_score?: Long, // Hidden instructions in tool description/args\n tool_poisoning_detected?: Bool, // Boolean flag for tool poisoning\n rug_pull_score?: Long, // Tool behavior drift after trust establishment\n rug_pull_detected?: Bool, // Boolean flag for rug pull\n indirect_injection_score?: Long, // Indirect injection via tool output\n\n // --- Tool Risk Assessment ---\n tool_risk_score?: Long, // Computed tool risk (0-100)\n tool_category?: String, // \"safe\", \"sensitive\", \"dangerous\"\n tool_is_sensitive?: Bool, // Sensitivity classification\n tool_is_builtin?: Bool, // Built-in IDE tool vs MCP tool\n\n // --- Behavioral Analysis --- (OWASP LLM10, ASI02, ASI08)\n loop_detected?: Bool, // Consecutive same-tool call loop\n loop_count?: Long, // Number of consecutive repeat calls\n loop_tool?: String, // Tool name in loop\n suspicious_pattern?: Bool, // Data exfiltration or attack sequence detected\n pattern_type?: String, // \"data_exfiltration\", \"secret_exfiltration\", \"credential_theft\", \"destructive_sequence\"\n sequence_risk?: Long, // Sequence risk score (0-100)\n\n // --- MCP Trust ---\n mcp_server_verified?: Bool, // Whether server is from verified registry\n\n // --- Tool Operation Classifier ---\n tool_operation_classes?: Set<String>, // subset of {\"readonly\", \"write_enabling\", \"execute_enabling\", \"network_access\", \"unknown\"}\n\n // --- Bash AST resolved target paths (#411 / CAP-DET-007) \u2014 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*\" ---\n resolved_target_paths?: String, // union of resolved absolute target paths, any capability\n read_target_paths?: String, // paths the command reads or enumerates\n write_target_paths?: String, // paths the command writes, creates, or destroys\n exec_target_paths?: String, // paths executed as a script\n unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Legacy ---\n response_content?: String,\n },\n};\n\n// Inspect the OUTPUT of a tool that has already run.\n// Threat focus: a credential or PII printed by a tool entering the agent's\n// context. The tool has run, so a permission verdict is meaningless here \u2014 the\n// only enforcement available is rewriting or withholding what the model sees,\n// which is why transform rules (@redaction_strategy) are the point of this\n// action. Context is deliberately narrower than call_tool: pre-execution\n// signals (tool risk, loop, sequence) belong to the call, not its result.\naction post_tool_call appliesTo {\n principal: [User, Agent],\n resource: [Tool, FilePath, LlmPrompt],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Event & Source ---\n content: String, // The tool's OUTPUT (stdout+stderr, or serialized response)\n source: String, // IDE source\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // --- Tool & MCP ---\n tool_name?: String,\n mcp_server?: String,\n mcp_tool?: String,\n\n // --- Result ---\n exit_code?: Long, // Absent when the IDE does not propagate it\n\n // --- File & Path ---\n path?: String,\n\n // --- Workspace ---\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Secrets --- the primary signal for this surface\n secrets_detected?: Bool,\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- Indirect injection via tool output --- (OWASP ASI01)\n indirect_injection_score?: Long,\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_threat_turns?: Long,\n session_max_secret_score?: Long,\n session_max_pii_score?: Long,\n session_cumulative_risk_score?: Long,\n },\n};\n\n// Connect to an MCP server\n// Threat focus: supply chain, tool poisoning, rug pull, config risk\naction connect_server appliesTo {\n principal: [User, Agent],\n resource: [Server],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content?: String, // Server config content (if available)\n source: String,\n event: String,\n user_email: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Agent Security (0-100) --- (OWASP ASI04, MCP01-MCP05)\n tool_poisoning_score?: Long, // Poisoned tool descriptions in server\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long, // Server behavior change after approval\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long, // Injection payloads in server responses\n\n // --- MCP Trust & Config Risk ---\n mcp_server_verified?: Bool, // Verified registry status\n mcp_config_risk?: Bool, // Risky server config detected (inline code exec, etc.)\n mcp_risk_score?: Long, // Config risk severity (0-100)\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n },\n};\n\n// Read a file from disk\n// Threat focus: secrets exposure, PII exposure, path traversal, sensitive paths\naction read_file appliesTo {\n principal: [User, Agent],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n source: String,\n event: String,\n user_email: String,\n path?: String,\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Agent Security ---\n indirect_injection_score?: Long, // Indirect injection via file content\n },\n};\n\n// Write a file to disk\n// Threat focus: secrets in output, PII in output, sensitive paths, malicious code\naction write_file appliesTo {\n principal: [User, Agent],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n source: String,\n event: String,\n user_email: String,\n path?: String,\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Agent Security ---\n indirect_injection_score?: Long, // Indirect injection via file content\n },\n};\n\n}\n";
24
+ export declare const OVERWATCH_SCHEMA = "// Overwatch Cedar Schema\n// ===================================\n// IDE Agent Security & Policy Enforcement\n//\n// Overwatch protects IDE agent operations (prompts, tool calls, file access, MCP connections)\n// by evaluating threats detected by the detection engine pipeline against Cedar policies.\n//\n// Architecture:\n// User/Agent \u2192 IDE Hook \u2192 Detection Engine \u2192 Cedar Policy \u2192 Allow/Deny\n//\n// Supported IDEs:\n// - Cursor (beforeSubmitPrompt, beforeShellExecution, beforeMCPExecution, etc.)\n// - Claude Code (UserPromptSubmit, PreToolUse)\n// - GitHub Copilot (userPromptSubmitted, preToolUse)\n//\n// Threat Coverage:\n// - OWASP Top 10 for LLM Applications 2025 (LLM01-LLM10)\n// - OWASP Top 10 for Agentic Applications (ASI01-ASI10)\n// - OWASP MCP Top 10 (MCP01-MCP05)\n// - MITRE ATLAS Agent Techniques (AML.T0051, AML.T0080-T0082)\n\nnamespace Overwatch {\n\n// =============================================================================\n// ENTITIES - Tenant Hierarchy (ReBAC)\n// =============================================================================\n// Aligned with Guardrails entity hierarchy (Account \u2192 Project).\n// Overwatch does not have app-specific policies, so App is omitted.\n//\n// Entity hierarchy enables Cedar's `in` operator for policy scoping:\n// Account (org root)\n// \u2514\u2500\u2500 Project in [Account]\n// \u2514\u2500\u2500 Tool/Server/FilePath/LlmPrompt in [Project]\n//\n// Policy scoping examples:\n// resource == Overwatch::Tool::\"shell\" \u2192 specific tool\n// resource in Overwatch::Project::\"<uuid>\" \u2192 project-wide\n// resource in Overwatch::Account::\"<uuid>\" \u2192 org-wide\n\n/// Account represents an organization (top-level tenant)\nentity Account;\n\n/// Project represents a project within an account\nentity Project in [Account];\n\n// =============================================================================\n// ENTITIES - Principals\n// =============================================================================\n\n/// Human user or service account making requests to the IDE\nentity User;\n\n/// AI agent (Claude, GitHub Copilot, etc.)\nentity Agent;\n\n// =============================================================================\n// ENTITIES - Resources (scoped under Project)\n// =============================================================================\n\n/// LLM prompt or session \u2014 resource for process_prompt action\nentity LlmPrompt in [Project];\n\n/// MCP tool or native IDE tool \u2014 resource for call_tool action\nentity Tool in [Project];\n\n/// MCP server \u2014 resource for connect_server action\nentity Server in [Project];\n\n/// File system path \u2014 resource for read_file/write_file/call_tool actions\nentity FilePath in [Project];\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\n// User submits a prompt or receives AI response\n// Threat focus: injection, jailbreak, secrets, PII, content safety, invisible chars\naction process_prompt appliesTo {\n principal: [User, Agent],\n resource: [LlmPrompt],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Event & Source ---\n content: String, // Raw content being scanned\n source: String, // IDE source: \"cursor\", \"claudecode\", \"github_copilot\"\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // --- Workspace ---\n cwd?: String, // Current working directory\n workspace_root?: String, // Workspace/repository root\n\n // --- Threat Detection (from detection engine pipeline) ---\n threat_count: Long, // Total threats detected\n highest_severity: String, // \"critical\", \"high\", \"medium\", \"low\", \"none\"\n threat_categories: Set<String>, // Threat category names\n detected_threats: Set<String>, // Detection rule names that matched\n max_threat_severity: Long, // Numeric severity (0=none, 1=low, 2=medium, 3=high, 4=critical)\n secrets_detected: Bool, // Whether secrets/credentials detected\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>, // Types: \"aws_access_key\", \"github_token\", \"ssh_private_key\", etc.\n secret_count?: Long, // Number of distinct secrets found\n\n // --- PII Detection ---\n pii_detected?: Bool, // Whether any PII patterns matched\n pii_types?: Set<String>, // Types: \"ssn\", \"credit_card\", \"email\", \"phone\", etc.\n pii_count?: Long, // Number of PII matches\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool, // Zero-width chars, bidi overrides, tag chars detected\n invisible_chars_score?: Long, // Unicode attack severity (0-100)\n\n // --- Content Safety Scores (0-100, from ML classifiers) ---\n violence_score: Long,\n weapons_score: Long,\n hate_speech_score: Long,\n crime_score: Long,\n sexual_score: Long,\n profanity_score: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n pii_score: Long, // PII detection classifier confidence\n injection_score: Long, // Combined injection confidence: MAX(pulse, deep_context)\n jailbreak_score: Long, // Combined jailbreak confidence: MAX(pulse, deep_context)\n injection_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n injection_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n jailbreak_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n jailbreak_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n\n // --- Agent Security (0-100) ---\n indirect_injection_score: Long, // Indirect prompt injection risk (OWASP LLM01, ASI01)\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Legacy ---\n prompt_text?: String, // Same as content (backward compatibility)\n response_content?: String, // Response content (if available)\n // --- Session Token Budget --- (OWASP LLM10; CAP-ENF-009, cerberus#147)\n // Fed by the cumulative session total the Overwatch daemon reports on the\n // prompt and before-tool events.\n //\n // BOTH are optional, so BOTH need a `has` guard \u2014 a bare\n // `context.budget_remaining_pct < 10` fails cedar validation with\n // \"unable to guarantee safety of access to optional attribute\".\n // Write: `context has budget_remaining_pct && context.budget_remaining_pct < 10`.\n //\n // The guard is a validation requirement, NOT a safety property. Whenever a\n // session loads, budget_checker emits both keys \u2014 including\n // budget_exceeded: false and budget_remaining_pct: 100 when no budget rule\n // is configured for the scope. So a grant conditioned on\n // `!context.budget_exceeded` fires on unbudgeted sessions, and a low\n // percentage is evidence of spend only when a budget rule exists. Absence\n // means the detector did not run at all (no session).\n budget_remaining_pct?: Long, // Remaining session token budget (0-100)\n budget_exceeded?: Bool, // Session token budget exceeded\n },\n};\n\n// User calls a tool (native IDE tool or MCP tool)\n// Threat focus: command injection, tool poisoning, rug pull, data exfiltration, loops\naction call_tool appliesTo {\n principal: [User, Agent],\n resource: [Tool, FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Event & Source ---\n content: String, // Raw content being scanned (e.g., shell command, tool args)\n source: String, // IDE source\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // --- Tool & MCP ---\n tool_name?: String, // Normalized tool name (\"shell\", \"read_file\", etc.)\n mcp_server?: String, // MCP server name\n mcp_tool?: String, // MCP tool name\n\n // --- File & Path ---\n path?: String, // File path (if file operation)\n\n // --- Workspace ---\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- Content Safety Scores (0-100) ---\n violence_score?: Long,\n weapons_score?: Long,\n hate_speech_score?: Long,\n crime_score?: Long,\n sexual_score?: Long,\n profanity_score?: Long,\n\n // --- ML Detector Confidence Scores (0-100) ---\n pii_score?: Long,\n injection_score?: Long, // Combined injection confidence: MAX(pulse, deep_context)\n jailbreak_score?: Long, // Combined jailbreak confidence: MAX(pulse, deep_context)\n injection_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n injection_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n jailbreak_pulse_score?: Long, // 0-100 Pulse single-turn classifier\n jailbreak_deep_context_score?: Long, // 0-100 DeepContext multi-turn\n\n // --- Agent Security (0-100) --- (OWASP ASI01, ASI02, ASI04; MITRE AML.T0051)\n tool_poisoning_score?: Long, // Hidden instructions in tool description/args\n tool_poisoning_detected?: Bool, // Boolean flag for tool poisoning\n rug_pull_score?: Long, // Tool behavior drift after trust establishment\n rug_pull_detected?: Bool, // Boolean flag for rug pull\n indirect_injection_score?: Long, // Indirect injection via tool output\n\n // --- Tool Risk Assessment ---\n tool_risk_score?: Long, // Computed tool risk (0-100)\n tool_category?: String, // \"safe\", \"sensitive\", \"dangerous\"\n tool_is_sensitive?: Bool, // Sensitivity classification\n tool_is_builtin?: Bool, // Built-in IDE tool vs MCP tool\n\n // --- Behavioral Analysis --- (OWASP LLM10, ASI02, ASI08)\n loop_detected?: Bool, // Consecutive same-tool call loop\n loop_count?: Long, // Number of consecutive repeat calls\n loop_tool?: String, // Tool name in loop\n suspicious_pattern?: Bool, // Data exfiltration or attack sequence detected\n pattern_type?: String, // \"data_exfiltration\", \"secret_exfiltration\", \"credential_theft\", \"destructive_sequence\"\n sequence_risk?: Long, // Sequence risk score (0-100)\n\n // --- MCP Trust ---\n mcp_server_verified?: Bool, // Whether server is from verified registry\n\n // --- Tool Operation Classifier ---\n tool_operation_classes?: Set<String>, // subset of {\"readonly\", \"write_enabling\", \"execute_enabling\", \"network_access\", \"unknown\"}\n\n // --- Bash AST resolved target paths (#411 / CAP-DET-007) \u2014 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*\" ---\n resolved_target_paths?: String, // union of resolved absolute target paths, any capability\n read_target_paths?: String, // paths the command reads or enumerates\n write_target_paths?: String, // paths the command writes, creates, or destroys\n exec_target_paths?: String, // paths executed as a script\n unresolved_target?: Bool, // a target hid behind a variable/glob/$()/inline code\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Legacy ---\n response_content?: String,\n // --- Session Token Budget --- (OWASP LLM10; CAP-ENF-009, cerberus#147)\n // Fed by the cumulative session total the Overwatch daemon reports on the\n // prompt and before-tool events.\n //\n // BOTH are optional, so BOTH need a `has` guard \u2014 a bare\n // `context.budget_remaining_pct < 10` fails cedar validation with\n // \"unable to guarantee safety of access to optional attribute\".\n // Write: `context has budget_remaining_pct && context.budget_remaining_pct < 10`.\n //\n // The guard is a validation requirement, NOT a safety property. Whenever a\n // session loads, budget_checker emits both keys \u2014 including\n // budget_exceeded: false and budget_remaining_pct: 100 when no budget rule\n // is configured for the scope. So a grant conditioned on\n // `!context.budget_exceeded` fires on unbudgeted sessions, and a low\n // percentage is evidence of spend only when a budget rule exists. Absence\n // means the detector did not run at all (no session).\n budget_remaining_pct?: Long, // Remaining session token budget (0-100)\n budget_exceeded?: Bool, // Session token budget exceeded\n },\n};\n\n// Inspect the OUTPUT of a tool that has already run.\n// Threat focus: a credential or PII printed by a tool entering the agent's\n// context. The tool has run, so a permission verdict is meaningless here \u2014 the\n// only enforcement available is rewriting or withholding what the model sees,\n// which is why transform rules (@redaction_strategy) are the point of this\n// action. Context is deliberately narrower than call_tool: pre-execution\n// signals (tool risk, loop, sequence) belong to the call, not its result.\naction post_tool_call appliesTo {\n principal: [User, Agent],\n resource: [Tool, FilePath, LlmPrompt],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n // --- Event & Source ---\n content: String, // The tool's OUTPUT (stdout+stderr, or serialized response)\n source: String, // IDE source\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // --- Tool & MCP ---\n tool_name?: String,\n mcp_server?: String,\n mcp_tool?: String,\n\n // --- Result ---\n exit_code?: Long, // Absent when the IDE does not propagate it\n\n // --- File & Path ---\n path?: String,\n\n // --- Workspace ---\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Secrets --- the primary signal for this surface\n secrets_detected?: Bool,\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n pii_score?: Long,\n\n // --- Indirect injection via tool output --- (OWASP ASI01)\n indirect_injection_score?: Long,\n\n // --- Encoding & Unicode Attacks ---\n invisible_chars_detected?: Bool,\n invisible_chars_score?: Long,\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_threat_turns?: Long,\n session_max_secret_score?: Long,\n session_max_pii_score?: Long,\n session_cumulative_risk_score?: Long,\n },\n};\n\n// Connect to an MCP server\n// Threat focus: supply chain, tool poisoning, rug pull, config risk\naction connect_server appliesTo {\n principal: [User, Agent],\n resource: [Server],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content?: String, // Server config content (if available)\n source: String,\n event: String,\n user_email: String,\n mcp_server?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n max_threat_severity?: Long,\n\n // --- Agent Security (0-100) --- (OWASP ASI04, MCP01-MCP05)\n tool_poisoning_score?: Long, // Poisoned tool descriptions in server\n tool_poisoning_detected?: Bool,\n rug_pull_score?: Long, // Server behavior change after approval\n rug_pull_detected?: Bool,\n indirect_injection_score?: Long, // Injection payloads in server responses\n\n // --- MCP Trust & Config Risk ---\n mcp_server_verified?: Bool, // Verified registry status\n mcp_config_risk?: Bool, // Risky server config detected (inline code exec, etc.)\n mcp_risk_score?: Long, // Config risk severity (0-100)\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n // --- Session Token Budget --- (OWASP LLM10; CAP-ENF-009, cerberus#147)\n // Fed by the cumulative session total the Overwatch daemon reports on the\n // prompt and before-tool events.\n //\n // BOTH are optional, so BOTH need a `has` guard \u2014 a bare\n // `context.budget_remaining_pct < 10` fails cedar validation with\n // \"unable to guarantee safety of access to optional attribute\".\n // Write: `context has budget_remaining_pct && context.budget_remaining_pct < 10`.\n //\n // The guard is a validation requirement, NOT a safety property. Whenever a\n // session loads, budget_checker emits both keys \u2014 including\n // budget_exceeded: false and budget_remaining_pct: 100 when no budget rule\n // is configured for the scope. So a grant conditioned on\n // `!context.budget_exceeded` fires on unbudgeted sessions, and a low\n // percentage is evidence of spend only when a budget rule exists. Absence\n // means the detector did not run at all (no session).\n budget_remaining_pct?: Long, // Remaining session token budget (0-100)\n budget_exceeded?: Bool, // Session token budget exceeded\n },\n};\n\n// Read a file from disk\n// Threat focus: secrets exposure, PII exposure, path traversal, sensitive paths\naction read_file appliesTo {\n principal: [User, Agent],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n source: String,\n event: String,\n user_email: String,\n path?: String,\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Agent Security ---\n indirect_injection_score?: Long, // Indirect injection via file content\n // --- Session Token Budget --- (OWASP LLM10; CAP-ENF-009, cerberus#147)\n // Fed by the cumulative session total the Overwatch daemon reports on the\n // prompt and before-tool events.\n //\n // BOTH are optional, so BOTH need a `has` guard \u2014 a bare\n // `context.budget_remaining_pct < 10` fails cedar validation with\n // \"unable to guarantee safety of access to optional attribute\".\n // Write: `context has budget_remaining_pct && context.budget_remaining_pct < 10`.\n //\n // The guard is a validation requirement, NOT a safety property. Whenever a\n // session loads, budget_checker emits both keys \u2014 including\n // budget_exceeded: false and budget_remaining_pct: 100 when no budget rule\n // is configured for the scope. So a grant conditioned on\n // `!context.budget_exceeded` fires on unbudgeted sessions, and a low\n // percentage is evidence of spend only when a budget rule exists. Absence\n // means the detector did not run at all (no session).\n budget_remaining_pct?: Long, // Remaining session token budget (0-100)\n budget_exceeded?: Bool, // Session token budget exceeded\n },\n};\n\n// Write a file to disk\n// Threat focus: secrets in output, PII in output, sensitive paths, malicious code\naction write_file appliesTo {\n principal: [User, Agent],\n resource: [FilePath],\n context: {\n // Identity (AARM R6 / CAP-IDN-011) \u2014 projected from the principal's token; optional.\n role?: String,\n privilege_scope?: Set<String>,\n content: String,\n source: String,\n event: String,\n user_email: String,\n path?: String,\n cwd?: String,\n workspace_root?: String,\n\n // --- Threat Detection ---\n threat_count?: Long,\n highest_severity?: String,\n threat_categories?: Set<String>,\n detected_threats?: Set<String>,\n max_threat_severity?: Long,\n secrets_detected?: Bool,\n\n // --- Secrets (granular) ---\n secret_types?: Set<String>,\n secret_count?: Long,\n\n // --- PII Detection ---\n pii_detected?: Bool,\n pii_types?: Set<String>,\n pii_count?: Long,\n\n // --- Session Detection History (cross-turn sticky flags) ---\n session_pii_detected?: Bool,\n session_pii_types?: Set<String>,\n session_secrets_detected?: Bool,\n session_secret_types?: Set<String>,\n session_injection_detected?: Bool,\n session_command_injection?: Bool,\n session_threat_turns?: Long,\n session_max_injection_score?: Long,\n session_max_jailbreak_score?: Long,\n session_max_command_injection_score?: Long,\n session_max_pii_score?: Long,\n session_max_secret_score?: Long,\n session_cumulative_risk_score?: Long,\n\n // --- Agent Security ---\n indirect_injection_score?: Long, // Indirect injection via file content\n // --- Session Token Budget --- (OWASP LLM10; CAP-ENF-009, cerberus#147)\n // Fed by the cumulative session total the Overwatch daemon reports on the\n // prompt and before-tool events.\n //\n // BOTH are optional, so BOTH need a `has` guard \u2014 a bare\n // `context.budget_remaining_pct < 10` fails cedar validation with\n // \"unable to guarantee safety of access to optional attribute\".\n // Write: `context has budget_remaining_pct && context.budget_remaining_pct < 10`.\n //\n // The guard is a validation requirement, NOT a safety property. Whenever a\n // session loads, budget_checker emits both keys \u2014 including\n // budget_exceeded: false and budget_remaining_pct: 100 when no budget rule\n // is configured for the scope. So a grant conditioned on\n // `!context.budget_exceeded` fires on unbudgeted sessions, and a low\n // percentage is evidence of spend only when a budget rule exists. Absence\n // means the detector did not run at all (no session).\n budget_remaining_pct?: Long, // Remaining session token budget (0-100)\n budget_exceeded?: Bool, // Session token budget exceeded\n },\n};\n\n}\n";
25
25
  /**
26
26
  * Palisade Cedar schema
27
27
  *