@sunaiva/gate 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +10 -0
  2. package/README.md +67 -0
  3. package/dist/config/defaults.d.ts +23 -0
  4. package/dist/config/defaults.d.ts.map +1 -0
  5. package/dist/config/defaults.js +26 -0
  6. package/dist/config/defaults.js.map +1 -0
  7. package/dist/config/loader.d.ts +5 -0
  8. package/dist/config/loader.d.ts.map +1 -0
  9. package/dist/config/loader.js +19 -0
  10. package/dist/config/loader.js.map +1 -0
  11. package/dist/engine/pattern-matcher.d.ts +32 -0
  12. package/dist/engine/pattern-matcher.d.ts.map +1 -0
  13. package/dist/engine/pattern-matcher.js +75 -0
  14. package/dist/engine/pattern-matcher.js.map +1 -0
  15. package/dist/engine/rule-engine.d.ts +25 -0
  16. package/dist/engine/rule-engine.d.ts.map +1 -0
  17. package/dist/engine/rule-engine.js +56 -0
  18. package/dist/engine/rule-engine.js.map +1 -0
  19. package/dist/engine/session-state.d.ts +14 -0
  20. package/dist/engine/session-state.d.ts.map +1 -0
  21. package/dist/engine/session-state.js +38 -0
  22. package/dist/engine/session-state.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +61 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/rules/categories.json +83 -0
  28. package/dist/rules/presets.json +163 -0
  29. package/dist/rules/rules.json +2119 -0
  30. package/dist/tools/audit.d.ts +11 -0
  31. package/dist/tools/audit.d.ts.map +1 -0
  32. package/dist/tools/audit.js +33 -0
  33. package/dist/tools/audit.js.map +1 -0
  34. package/dist/tools/bypass.d.ts +10 -0
  35. package/dist/tools/bypass.d.ts.map +1 -0
  36. package/dist/tools/bypass.js +16 -0
  37. package/dist/tools/bypass.js.map +1 -0
  38. package/dist/tools/rules.d.ts +10 -0
  39. package/dist/tools/rules.d.ts.map +1 -0
  40. package/dist/tools/rules.js +31 -0
  41. package/dist/tools/rules.js.map +1 -0
  42. package/dist/tools/update.d.ts +10 -0
  43. package/dist/tools/update.d.ts.map +1 -0
  44. package/dist/tools/update.js +24 -0
  45. package/dist/tools/update.js.map +1 -0
  46. package/dist/tools/validate.d.ts +10 -0
  47. package/dist/tools/validate.d.ts.map +1 -0
  48. package/dist/tools/validate.js +30 -0
  49. package/dist/tools/validate.js.map +1 -0
  50. package/package.json +65 -0
package/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Business Source License 1.1
2
+
3
+ Licensor: Sunaiva Digital
4
+ Licensed Work: @sunaiva/gate
5
+ Change Date: 2030-05-09 (4 years from publication)
6
+ Change License: Apache License, Version 2.0
7
+
8
+ Full BUSL 1.1 text: https://mariadb.com/bsl11/
9
+
10
+ Until the Change Date, use is permitted for non-commercial purposes and internal evaluation. Production use requires a commercial license from Sunaiva Digital.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @sunaiva/gate
2
+
3
+ **Stop documenting rules your agents ignore. Start enforcing them.**
4
+
5
+ Sunaiva Gate is an MCP server that enforces validation rules on AI agent actions. 100 battle-tested rules across 9 categories. Constitutional rules that never bend. Audit trail for every decision.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npx @sunaiva/gate
11
+ ```
12
+
13
+ ## MCP Configuration
14
+
15
+ Add to your Claude Code or Cursor MCP settings:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "sunaiva-gate": {
21
+ "command": "npx",
22
+ "args": ["@sunaiva/gate"]
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## Tools
29
+
30
+ | Tool | Description |
31
+ |------|-------------|
32
+ | `validate_action` | Check if a proposed action passes all active rules |
33
+ | `log_bypass` | Record an intentional rule bypass (non-constitutional only) |
34
+ | `get_rules` | List active rules, filter by category or preset |
35
+ | `update_rules` | Enable/disable rules (constitutional rules cannot be disabled) |
36
+ | `get_audit_log` | View recent gate decisions |
37
+
38
+ ## Presets
39
+
40
+ - **minimal** (5 rules) — absolute non-negotiables
41
+ - **essential** (15 rules) — recommended starting point
42
+ - **developer-safety** (25 rules) — for AI coding agents
43
+ - **financial-protection** (24 rules) — all financial + resource rules
44
+ - **full-suite** (100 rules) — everything
45
+
46
+ ## Privacy
47
+
48
+ Your data stays where you choose:
49
+ - **Managed** — zero config, Gemini Flash included
50
+ - **BYOK** — bring your own API key (Gemini, Claude, OpenRouter)
51
+ - **Local** — Ollama/LM Studio, nothing leaves your machine
52
+
53
+ ## License
54
+
55
+ **Business Source License 1.1 (BUSL-1.1)**
56
+
57
+ - Licensor: Sunaiva Digital
58
+ - Change Date: 2030-05-09 (4 years from publication)
59
+ - Change License: Apache License, Version 2.0
60
+
61
+ Until the Change Date, use is permitted for non-commercial purposes and internal evaluation. Production use requires a commercial license from Sunaiva Digital.
62
+
63
+ Full BUSL 1.1 text: https://mariadb.com/bsl11/
64
+
65
+ ---
66
+
67
+ Built by [Sunaiva Digital](https://sunaivadigital.com). Patent-protected validation infrastructure.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Default configuration values for @sunaiva/gate
3
+ */
4
+ export declare const CONFIG_DIR: string;
5
+ export declare const CONFIG_PATH: string;
6
+ export declare const AUDIT_LOG_PATH: string;
7
+ export declare const DEFAULT_CONFIG: GateConfig;
8
+ export declare const MANAGED_API_BASE = "https://api.sunaiva.ai/v1/gate";
9
+ export interface ModelConfig {
10
+ provider: "managed" | "gemini" | "anthropic" | "openrouter" | "local";
11
+ api_key?: string;
12
+ model_name?: string;
13
+ endpoint?: string;
14
+ }
15
+ export interface GateConfig {
16
+ api_key: string;
17
+ active_rules: string[];
18
+ active_preset?: string;
19
+ enforcement_mode: "enforce" | "warn-only" | "audit";
20
+ model: ModelConfig;
21
+ audit_log_path: string;
22
+ }
23
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,eAAO,MAAM,UAAU,QAA8B,CAAC;AACtD,eAAO,MAAM,WAAW,QAAuC,CAAC;AAChE,eAAO,MAAM,cAAc,QAAkC,CAAC;AAE9D,eAAO,MAAM,cAAc,EAAE,UAe5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,mCAAmC,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACpD,KAAK,EAAE,WAAW,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Default configuration values for @sunaiva/gate
3
+ */
4
+ import { homedir } from "os";
5
+ import { join } from "path";
6
+ export const CONFIG_DIR = join(homedir(), ".sunaiva");
7
+ export const CONFIG_PATH = join(CONFIG_DIR, "gate-config.json");
8
+ export const AUDIT_LOG_PATH = join(CONFIG_DIR, "audit.jsonl");
9
+ export const DEFAULT_CONFIG = {
10
+ api_key: "",
11
+ active_rules: [
12
+ "fin-001",
13
+ "gov-001",
14
+ "gov-002",
15
+ "dat-001",
16
+ "gov-008",
17
+ ],
18
+ active_preset: "minimal",
19
+ enforcement_mode: "enforce",
20
+ model: {
21
+ provider: "managed",
22
+ },
23
+ audit_log_path: AUDIT_LOG_PATH,
24
+ };
25
+ export const MANAGED_API_BASE = "https://api.sunaiva.ai/v1/gate";
26
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAE9D,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,OAAO,EAAE,EAAE;IACX,YAAY,EAAE;QACZ,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,aAAa,EAAE,SAAS;IACxB,gBAAgB,EAAE,SAAS;IAC3B,KAAK,EAAE;QACL,QAAQ,EAAE,SAAS;KACpB;IACD,cAAc,EAAE,cAAc;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,gCAAgC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type GateConfig } from "./defaults.js";
2
+ export declare function getConfig(): GateConfig;
3
+ export declare function saveConfig(cfg: GateConfig): void;
4
+ export declare function getActiveRuleIds(): string[];
5
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAA2C,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzF,wBAAgB,SAAS,IAAI,UAAU,CAMtC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAGhD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C"}
@@ -0,0 +1,19 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
2
+ import { CONFIG_DIR, CONFIG_PATH, DEFAULT_CONFIG } from "./defaults.js";
3
+ export function getConfig() {
4
+ try {
5
+ if (existsSync(CONFIG_PATH))
6
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
7
+ }
8
+ catch { }
9
+ saveConfig(DEFAULT_CONFIG);
10
+ return { ...DEFAULT_CONFIG };
11
+ }
12
+ export function saveConfig(cfg) {
13
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
14
+ writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2), { mode: 0o600 });
15
+ }
16
+ export function getActiveRuleIds() {
17
+ return getConfig().active_rules;
18
+ }
19
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAmB,MAAM,eAAe,CAAC;AAEzF,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,UAAU,CAAC,cAAc,CAAC,CAAC;IAC3B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAe;IACxC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,SAAS,EAAE,CAAC,YAAY,CAAC;AAClC,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Pattern Matcher — local regex/keyword matching for rule detection_pattern fields.
3
+ * No API call. Runs entirely in-process.
4
+ */
5
+ export interface MatchResult {
6
+ matched: boolean;
7
+ matched_keywords: string[];
8
+ confidence: "high" | "medium" | "low";
9
+ }
10
+ /**
11
+ * Extract keyword phrases from a human-readable detection_pattern string.
12
+ * The pattern field is prose like:
13
+ * "Detects: Stripe charges, PayPal payments, checkout URLs, credit card forms..."
14
+ */
15
+ export declare function parseDetectionPattern(detectionPattern: string): string[];
16
+ /**
17
+ * Match an action description against a rule's detection_pattern string.
18
+ *
19
+ * @param action The proposed action text from the agent
20
+ * @param detectionPattern The rule's detection_pattern field
21
+ * @returns MatchResult
22
+ */
23
+ export declare function matchAction(action: string, detectionPattern: string): MatchResult;
24
+ /**
25
+ * Match an action against multiple rules' detection patterns in one pass.
26
+ * Returns a map of ruleId -> MatchResult.
27
+ */
28
+ export declare function matchAgainstRules(action: string, rules: Array<{
29
+ id: string;
30
+ detection_pattern: string;
31
+ }>): Map<string, MatchResult>;
32
+ //# sourceMappingURL=pattern-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-matcher.d.ts","sourceRoot":"","sources":["../../src/engine/pattern-matcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAexE;AAeD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,GACvB,WAAW,CAwBb;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,GACtD,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAM1B"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Pattern Matcher — local regex/keyword matching for rule detection_pattern fields.
3
+ * No API call. Runs entirely in-process.
4
+ */
5
+ /**
6
+ * Extract keyword phrases from a human-readable detection_pattern string.
7
+ * The pattern field is prose like:
8
+ * "Detects: Stripe charges, PayPal payments, checkout URLs, credit card forms..."
9
+ */
10
+ export function parseDetectionPattern(detectionPattern) {
11
+ // Strip "Detects:" prefix if present
12
+ const cleaned = detectionPattern.replace(/^Detects:\s*/i, "");
13
+ // Split on commas, newlines, semicolons
14
+ const fragments = cleaned.split(/[,;\n]+/);
15
+ const keywords = [];
16
+ for (const fragment of fragments) {
17
+ const trimmed = fragment.trim().toLowerCase();
18
+ if (trimmed.length > 2) {
19
+ keywords.push(trimmed);
20
+ }
21
+ }
22
+ return keywords;
23
+ }
24
+ /**
25
+ * Build regex patterns from a list of keyword phrases.
26
+ * Each phrase becomes a word-boundary regex.
27
+ */
28
+ function buildPatterns(keywords) {
29
+ return keywords.map((kw) => {
30
+ // Escape special regex characters
31
+ const escaped = kw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32
+ // Allow word boundary or start/end of string matching
33
+ return new RegExp(escaped, "i");
34
+ });
35
+ }
36
+ /**
37
+ * Match an action description against a rule's detection_pattern string.
38
+ *
39
+ * @param action The proposed action text from the agent
40
+ * @param detectionPattern The rule's detection_pattern field
41
+ * @returns MatchResult
42
+ */
43
+ export function matchAction(action, detectionPattern) {
44
+ const keywords = parseDetectionPattern(detectionPattern);
45
+ const patterns = buildPatterns(keywords);
46
+ const actionLower = action.toLowerCase();
47
+ const matchedKeywords = [];
48
+ for (let i = 0; i < patterns.length; i++) {
49
+ if (patterns[i].test(actionLower)) {
50
+ matchedKeywords.push(keywords[i]);
51
+ }
52
+ }
53
+ const matched = matchedKeywords.length > 0;
54
+ // Confidence based on how many distinct signals match
55
+ let confidence = "low";
56
+ if (matchedKeywords.length >= 3) {
57
+ confidence = "high";
58
+ }
59
+ else if (matchedKeywords.length >= 1) {
60
+ confidence = "medium";
61
+ }
62
+ return { matched, matched_keywords: matchedKeywords, confidence };
63
+ }
64
+ /**
65
+ * Match an action against multiple rules' detection patterns in one pass.
66
+ * Returns a map of ruleId -> MatchResult.
67
+ */
68
+ export function matchAgainstRules(action, rules) {
69
+ const results = new Map();
70
+ for (const rule of rules) {
71
+ results.set(rule.id, matchAction(action, rule.detection_pattern));
72
+ }
73
+ return results;
74
+ }
75
+ //# sourceMappingURL=pattern-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-matcher.js","sourceRoot":"","sources":["../../src/engine/pattern-matcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,gBAAwB;IAC5D,qCAAqC;IACrC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAE9D,wCAAwC;IACxC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC9C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,QAAkB;IACvC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACzB,kCAAkC;QAClC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAC1D,sDAAsD;QACtD,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,gBAAwB;IAExB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEzC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAE3C,sDAAsD;IACtD,IAAI,UAAU,GAA8B,KAAK,CAAC;IAClD,IAAI,eAAe,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAChC,UAAU,GAAG,MAAM,CAAC;IACtB,CAAC;SAAM,IAAI,eAAe,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvC,UAAU,GAAG,QAAQ,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,KAAuD;IAEvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Rule Engine — loads rules.json, filters active rules, evaluates actions.
3
+ */
4
+ import type { GateConfig } from "../config/defaults.js";
5
+ export interface Rule {
6
+ id: string;
7
+ name: string;
8
+ description: string;
9
+ category: string;
10
+ enforcement: "constitutional" | "standard";
11
+ gate_type: string;
12
+ severity: "block" | "warn";
13
+ detection_pattern: string;
14
+ tags: string[];
15
+ preset_groups: string[];
16
+ }
17
+ export interface EvaluationResult {
18
+ allowed: boolean;
19
+ violations: Rule[];
20
+ warnings: Rule[];
21
+ }
22
+ export declare function loadAllRules(): Rule[];
23
+ export declare function getActiveRules(config: GateConfig): Rule[];
24
+ export declare function evaluateAction(action: string, config: GateConfig, warningCounts: Map<string, number>, context?: string): EvaluationResult;
25
+ //# sourceMappingURL=rule-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.d.ts","sourceRoot":"","sources":["../../src/engine/rule-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAMxD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,gBAAgB,GAAG,UAAU,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,IAAI,EAAE,CAAC;IACnB,QAAQ,EAAE,IAAI,EAAE,CAAC;CAClB;AAID,wBAAgB,YAAY,IAAI,IAAI,EAAE,CAKrC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,CAGzD;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,MAAM,GACf,gBAAgB,CA+BlB"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Rule Engine — loads rules.json, filters active rules, evaluates actions.
3
+ */
4
+ import { readFileSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { matchAction } from "./pattern-matcher.js";
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ // In dist, rules are in ../rules/ (relative to dist/engine/). In dev, ../../rules/.
10
+ const RULES_PATH = join(__dirname, "../rules/rules.json");
11
+ let _rules = null;
12
+ export function loadAllRules() {
13
+ if (_rules)
14
+ return _rules;
15
+ const raw = readFileSync(RULES_PATH, "utf-8");
16
+ _rules = JSON.parse(raw);
17
+ return _rules;
18
+ }
19
+ export function getActiveRules(config) {
20
+ const all = loadAllRules();
21
+ return all.filter((r) => config.active_rules.includes(r.id));
22
+ }
23
+ export function evaluateAction(action, config, warningCounts, context) {
24
+ const activeRules = getActiveRules(config);
25
+ const combined = context ? `${action} ${context}` : action;
26
+ const violations = [];
27
+ const warnings = [];
28
+ for (const rule of activeRules) {
29
+ const result = matchAction(combined, rule.detection_pattern);
30
+ if (!result.matched)
31
+ continue;
32
+ if (rule.enforcement === "constitutional") {
33
+ // Constitutional rules always block
34
+ violations.push(rule);
35
+ }
36
+ else {
37
+ // Standard rules: warn first time, block on repeat
38
+ const count = warningCounts.get(rule.id) ?? 0;
39
+ if (config.enforcement_mode === "warn-only") {
40
+ warnings.push(rule);
41
+ }
42
+ else if (config.enforcement_mode === "audit") {
43
+ warnings.push(rule);
44
+ }
45
+ else if (count === 0) {
46
+ warnings.push(rule);
47
+ }
48
+ else {
49
+ violations.push(rule);
50
+ }
51
+ }
52
+ }
53
+ const allowed = violations.length === 0;
54
+ return { allowed, violations, warnings };
55
+ }
56
+ //# sourceMappingURL=rule-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.js","sourceRoot":"","sources":["../../src/engine/rule-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,oFAAoF;AACpF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;AAqB1D,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC,MAAM,UAAU,YAAY;IAC1B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAW,CAAC;IACnC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,MAAkB,EAClB,aAAkC,EAClC,OAAgB;IAEhB,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAE3D,MAAM,UAAU,GAAW,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAW,EAAE,CAAC;IAE5B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,SAAS;QAE9B,IAAI,IAAI,CAAC,WAAW,KAAK,gBAAgB,EAAE,CAAC;YAC1C,oCAAoC;YACpC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,mDAAmD;YACnD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,MAAM,CAAC,gBAAgB,KAAK,WAAW,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;iBAAM,IAAI,MAAM,CAAC,gBAAgB,KAAK,OAAO,EAAE,CAAC;gBAC/C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;iBAAM,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;IACxC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,14 @@
1
+ interface SessionState {
2
+ session_start: string;
3
+ action_count: number;
4
+ warnings_issued: Record<string, number>;
5
+ }
6
+ export declare function getState(): SessionState;
7
+ export declare function saveState(s: SessionState): void;
8
+ export declare function recordWarning(ruleId: string): number;
9
+ export declare function getWarningCount(ruleId: string): number;
10
+ export declare function getWarningCounts(): Map<string, number>;
11
+ export declare function incrementAction(): void;
12
+ export declare function resetState(): void;
13
+ export {};
14
+ //# sourceMappingURL=session-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/engine/session-state.ts"],"names":[],"mappings":"AAIA,UAAU,YAAY;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAMD,wBAAgB,QAAQ,IAAI,YAAY,CAGvC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAE/C;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAGtD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
@@ -0,0 +1,38 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ const STATE_FILE = "/tmp/sunaiva_gate_session.json";
3
+ function defaultState() {
4
+ return { session_start: new Date().toISOString(), action_count: 0, warnings_issued: {} };
5
+ }
6
+ export function getState() {
7
+ try {
8
+ return JSON.parse(readFileSync(STATE_FILE, "utf-8"));
9
+ }
10
+ catch {
11
+ return defaultState();
12
+ }
13
+ }
14
+ export function saveState(s) {
15
+ writeFileSync(STATE_FILE, JSON.stringify(s, null, 2));
16
+ }
17
+ export function recordWarning(ruleId) {
18
+ const s = getState();
19
+ s.warnings_issued[ruleId] = (s.warnings_issued[ruleId] || 0) + 1;
20
+ saveState(s);
21
+ return s.warnings_issued[ruleId];
22
+ }
23
+ export function getWarningCount(ruleId) {
24
+ return getState().warnings_issued[ruleId] || 0;
25
+ }
26
+ export function getWarningCounts() {
27
+ const s = getState();
28
+ return new Map(Object.entries(s.warnings_issued));
29
+ }
30
+ export function incrementAction() {
31
+ const s = getState();
32
+ s.action_count++;
33
+ saveState(s);
34
+ }
35
+ export function resetState() {
36
+ saveState(defaultState());
37
+ }
38
+ //# sourceMappingURL=session-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-state.js","sourceRoot":"","sources":["../../src/engine/session-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEtD,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAQpD,SAAS,YAAY;IACnB,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,CAAC;IAC7D,MAAM,CAAC;QAAC,OAAO,YAAY,EAAE,CAAC;IAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAe;IACvC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,SAAS,CAAC,CAAC,CAAC,CAAC;IACb,OAAO,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,QAAQ,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,YAAY,EAAE,CAAC;IACjB,SAAS,CAAC,CAAC,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
5
+ import { handleValidateAction } from "./tools/validate.js";
6
+ import { handleLogBypass } from "./tools/bypass.js";
7
+ import { handleGetRules } from "./tools/rules.js";
8
+ import { handleUpdateRules } from "./tools/update.js";
9
+ import { handleGetAuditLog } from "./tools/audit.js";
10
+ const server = new Server({ name: "sunaiva-gate", version: "1.0.0" }, { capabilities: { tools: {} } });
11
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
12
+ tools: [
13
+ {
14
+ name: "validate_action",
15
+ description: "Check if a proposed action passes all active validation rules. Returns allowed/blocked with rule violations.",
16
+ inputSchema: { type: "object", properties: { action: { type: "string", description: "The action to validate" }, context: { type: "string", description: "Optional additional context" } }, required: ["action"] },
17
+ },
18
+ {
19
+ name: "log_bypass",
20
+ description: "Record an intentional rule bypass with justification. Cannot bypass constitutional rules.",
21
+ inputSchema: { type: "object", properties: { rule_id: { type: "string", description: "ID of the rule to bypass" }, reason: { type: "string", description: "Justification for the bypass" } }, required: ["rule_id", "reason"] },
22
+ },
23
+ {
24
+ name: "get_rules",
25
+ description: "List active validation rules, optionally filtered by category or preset.",
26
+ inputSchema: { type: "object", properties: { category: { type: "string", description: "Filter by category" }, preset: { type: "string", description: "Filter by preset name" } } },
27
+ },
28
+ {
29
+ name: "update_rules",
30
+ description: "Enable or disable validation rules. Constitutional rules cannot be disabled.",
31
+ inputSchema: { type: "object", properties: { enable: { type: "array", items: { type: "string" }, description: "Rule IDs to enable" }, disable: { type: "array", items: { type: "string" }, description: "Rule IDs to disable" } } },
32
+ },
33
+ {
34
+ name: "get_audit_log",
35
+ description: "View recent gate decisions — blocks, warnings, passes, and bypasses.",
36
+ inputSchema: { type: "object", properties: { limit: { type: "number", description: "Max entries to return (default 50)" }, rule_id: { type: "string", description: "Filter by rule ID" } } },
37
+ },
38
+ ],
39
+ }));
40
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
41
+ const { name, arguments: args } = req.params;
42
+ try {
43
+ switch (name) {
44
+ case "validate_action": return await handleValidateAction(args);
45
+ case "log_bypass": return await handleLogBypass(args);
46
+ case "get_rules": return await handleGetRules(args);
47
+ case "update_rules": return await handleUpdateRules(args);
48
+ case "get_audit_log": return await handleGetAuditLog(args);
49
+ default: return { content: [{ type: "text", text: `Unknown tool: ${name}` }] };
50
+ }
51
+ }
52
+ catch (err) {
53
+ return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }] };
54
+ }
55
+ });
56
+ async function main() {
57
+ const transport = new StdioServerTransport();
58
+ await server.connect(transport);
59
+ }
60
+ main().catch(console.error);
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ [
2
+ {
3
+ "id": "financial-safety",
4
+ "name": "Financial Safety",
5
+ "icon": "💰",
6
+ "description": "Prevent unauthorized spending, subscriptions, wire transfers, and financial actions. The category that pays for itself immediately.",
7
+ "rule_count": 12,
8
+ "risk_if_skipped": "Unauthorized charges, runaway API costs, accidental subscriptions, fraudulent transfers",
9
+ "example_incident": "gemini_credit_blaster.py ran 8 days, 35 workers, ~$800 charged — no billing cap"
10
+ },
11
+ {
12
+ "id": "data-protection",
13
+ "name": "Data Protection",
14
+ "icon": "🔐",
15
+ "description": "Prevent credential exposure, PII mishandling, unauthorized data exports, and privacy violations.",
16
+ "rule_count": 12,
17
+ "risk_if_skipped": "API key leaks, GDPR violations, customer data exposure, audit trail destruction",
18
+ "example_incident": "Agent commits .env.production to GitHub — 12 API keys exposed publicly"
19
+ },
20
+ {
21
+ "id": "action-governance",
22
+ "name": "Action Governance",
23
+ "icon": "🔒",
24
+ "description": "Gate destructive, irreversible, and high-impact actions — deployments, deletions, DNS changes, permission changes.",
25
+ "rule_count": 12,
26
+ "risk_if_skipped": "Production outages, accidental data deletion, broken infrastructure, unauthorized access grants",
27
+ "example_incident": "Agent deletes MX record while reconfiguring email routing — all inbound email down for 4 hours"
28
+ },
29
+ {
30
+ "id": "quality-gates",
31
+ "name": "Quality Gates",
32
+ "icon": "✅",
33
+ "description": "Enforce check-before-build, verify-before-claiming-done, test-before-shipping, and scope discipline.",
34
+ "rule_count": 12,
35
+ "risk_if_skipped": "Rebuilt code that already existed, unverified claims of completion, ships with failing tests, scope creep",
36
+ "example_incident": "Agent marks API endpoint 'deployed and working' based on deploy log without calling the live endpoint"
37
+ },
38
+ {
39
+ "id": "communication-safety",
40
+ "name": "Communication Safety",
41
+ "icon": "📢",
42
+ "description": "Gate email sends, social media posts, customer communications, outreach campaigns, and public content.",
43
+ "rule_count": 12,
44
+ "risk_if_skipped": "Mass emails with wrong content, brand-damaging social posts, GDPR violations, accidental campaign launches",
45
+ "example_incident": "Agent activates cold email campaign to 15,000 contacts without go-ahead after completing sequence setup"
46
+ },
47
+ {
48
+ "id": "knowledge-protocol",
49
+ "name": "Knowledge Protocol",
50
+ "icon": "📚",
51
+ "description": "Enforce knowledge-base-first lookups, source attribution, fact verification, and no fabricated statistics.",
52
+ "rule_count": 12,
53
+ "risk_if_skipped": "Invented statistics in reports, duplicate builds, outdated data used for decisions, title-only research",
54
+ "example_incident": "Agent states competitor pricing as fact from training data without checking competitor's current website"
55
+ },
56
+ {
57
+ "id": "resource-protection",
58
+ "name": "Resource Protection",
59
+ "icon": "⚡",
60
+ "description": "Enforce API rate limits, token budgets, storage quotas, concurrency caps, and service usage monitoring.",
61
+ "rule_count": 12,
62
+ "risk_if_skipped": "API key suspension, storage overflow, memory leaks, exceeded plan limits with overage charges",
63
+ "example_incident": "Agent fires 200 parallel Gemini workers against 60 RPM limit — 429 storm, key suspension"
64
+ },
65
+ {
66
+ "id": "security",
67
+ "name": "Security",
68
+ "icon": "🛡️",
69
+ "description": "Prevent secret exposure in logs, privilege escalation, dependency injection, SSRF, and banned provider routing.",
70
+ "rule_count": 12,
71
+ "risk_if_skipped": "Credential theft, supply chain compromise, auth bypass, proprietary code leaked to banned AI providers",
72
+ "example_incident": "Agent routes prompt containing proprietary IP to a DeepSeek endpoint to save costs"
73
+ },
74
+ {
75
+ "id": "compliance",
76
+ "name": "Compliance",
77
+ "icon": "⚖️",
78
+ "description": "EU AI Act Article 15 awareness, GDPR data handling, SOC2 controls, and audit trail maintenance.",
79
+ "rule_count": 4,
80
+ "risk_if_skipped": "EU AI Act fines (up to 3% global revenue), GDPR penalties, SOC2 audit failures",
81
+ "example_incident": "AI-powered CV screening deployed without bias assessment or human review — EU AI Act high-risk violation"
82
+ }
83
+ ]