@sunaiva/gate 1.0.0 → 1.1.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 (76) hide show
  1. package/BUSINESS_LICENSE.md +70 -0
  2. package/CHANGELOG.md +148 -0
  3. package/LICENSE +0 -0
  4. package/README.md +411 -27
  5. package/dist/config/defaults.d.ts +22 -1
  6. package/dist/config/defaults.d.ts.map +1 -1
  7. package/dist/config/defaults.js +56 -8
  8. package/dist/config/defaults.js.map +1 -1
  9. package/dist/config/loader.d.ts +0 -0
  10. package/dist/config/loader.d.ts.map +1 -1
  11. package/dist/config/loader.js +24 -6
  12. package/dist/config/loader.js.map +1 -1
  13. package/dist/engine/backend-client.d.ts +58 -0
  14. package/dist/engine/backend-client.d.ts.map +1 -0
  15. package/dist/engine/backend-client.js +287 -0
  16. package/dist/engine/backend-client.js.map +1 -0
  17. package/dist/engine/hmac-verifier.d.ts +33 -0
  18. package/dist/engine/hmac-verifier.d.ts.map +1 -0
  19. package/dist/engine/hmac-verifier.js +161 -0
  20. package/dist/engine/hmac-verifier.js.map +1 -0
  21. package/dist/engine/immutability.d.ts +59 -0
  22. package/dist/engine/immutability.d.ts.map +1 -0
  23. package/dist/engine/immutability.js +129 -0
  24. package/dist/engine/immutability.js.map +1 -0
  25. package/dist/engine/pattern-matcher.d.ts +13 -0
  26. package/dist/engine/pattern-matcher.d.ts.map +1 -1
  27. package/dist/engine/pattern-matcher.js +85 -17
  28. package/dist/engine/pattern-matcher.js.map +1 -1
  29. package/dist/engine/rule-engine.d.ts +62 -1
  30. package/dist/engine/rule-engine.d.ts.map +1 -1
  31. package/dist/engine/rule-engine.js +222 -12
  32. package/dist/engine/rule-engine.js.map +1 -1
  33. package/dist/engine/session-state.d.ts +0 -0
  34. package/dist/engine/session-state.d.ts.map +1 -1
  35. package/dist/engine/session-state.js +8 -2
  36. package/dist/engine/session-state.js.map +1 -1
  37. package/dist/engine/ship-confidence-gate.d.ts +184 -0
  38. package/dist/engine/ship-confidence-gate.d.ts.map +1 -0
  39. package/dist/engine/ship-confidence-gate.js +768 -0
  40. package/dist/engine/ship-confidence-gate.js.map +1 -0
  41. package/dist/index.d.ts +0 -0
  42. package/dist/index.d.ts.map +0 -0
  43. package/dist/index.js +289 -2
  44. package/dist/index.js.map +1 -1
  45. package/dist/rules/categories.json +0 -0
  46. package/dist/rules/presets.json +0 -0
  47. package/dist/rules/rules.json +200 -100
  48. package/dist/tools/audit.d.ts +6 -0
  49. package/dist/tools/audit.d.ts.map +1 -1
  50. package/dist/tools/audit.js +43 -6
  51. package/dist/tools/audit.js.map +1 -1
  52. package/dist/tools/bypass.d.ts +0 -0
  53. package/dist/tools/bypass.d.ts.map +1 -1
  54. package/dist/tools/bypass.js +50 -6
  55. package/dist/tools/bypass.js.map +1 -1
  56. package/dist/tools/rules.d.ts +0 -0
  57. package/dist/tools/rules.d.ts.map +0 -0
  58. package/dist/tools/rules.js +0 -0
  59. package/dist/tools/rules.js.map +0 -0
  60. package/dist/tools/ship-confidence.d.ts +11 -0
  61. package/dist/tools/ship-confidence.d.ts.map +1 -0
  62. package/dist/tools/ship-confidence.js +42 -0
  63. package/dist/tools/ship-confidence.js.map +1 -0
  64. package/dist/tools/update.d.ts +0 -0
  65. package/dist/tools/update.d.ts.map +1 -1
  66. package/dist/tools/update.js +45 -9
  67. package/dist/tools/update.js.map +1 -1
  68. package/dist/tools/validate.d.ts +0 -0
  69. package/dist/tools/validate.d.ts.map +1 -1
  70. package/dist/tools/validate.js +56 -4
  71. package/dist/tools/validate.js.map +1 -1
  72. package/dist/types/backend.d.ts +69 -0
  73. package/dist/types/backend.d.ts.map +1 -0
  74. package/dist/types/backend.js +18 -0
  75. package/dist/types/backend.js.map +1 -0
  76. package/package.json +11 -3
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Async-style audit write. The file I/O is deferred to setImmediate so the hot
3
+ * path (the validate_action response) returns before the syscall. Errors are
4
+ * swallowed because the audit log is informational and must never break
5
+ * enforcement.
6
+ */
1
7
  export declare function appendAudit(entry: Record<string, unknown>): void;
2
8
  export declare function handleGetAuditLog(args: {
3
9
  limit?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/tools/audit.ts"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMhE;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GAejF"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/tools/audit.ts"],"names":[],"mappings":"AA+BA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAYhE;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GAejF"}
@@ -1,16 +1,53 @@
1
- import { readFileSync, appendFileSync, existsSync, mkdirSync } from "node:fs";
1
+ import { readFileSync, appendFileSync, existsSync, mkdirSync, statSync, renameSync } from "node:fs";
2
2
  import { dirname } from "node:path";
3
3
  import { getConfig } from "../config/loader.js";
4
+ // Rotate audit log when it crosses this size (bytes).
5
+ const AUDIT_ROTATE_BYTES = 10 * 1024 * 1024; // 10 MB
6
+ // Throttle rotation checks: only stat the file at most every 60s.
7
+ const ROTATE_CHECK_MS = 60_000;
8
+ let _lastRotateCheck = 0;
4
9
  function getLogPath() {
5
10
  return getConfig().audit_log_path;
6
11
  }
7
- export function appendAudit(entry) {
12
+ function maybeRotate(logPath) {
13
+ const now = Date.now();
14
+ if (now - _lastRotateCheck < ROTATE_CHECK_MS)
15
+ return;
16
+ _lastRotateCheck = now;
8
17
  try {
9
- const logPath = getLogPath();
10
- mkdirSync(dirname(logPath), { recursive: true });
11
- appendFileSync(logPath, JSON.stringify(entry) + "\n");
18
+ if (!existsSync(logPath))
19
+ return;
20
+ const size = statSync(logPath).size;
21
+ if (size < AUDIT_ROTATE_BYTES)
22
+ return;
23
+ // Rotate: audit.jsonl -> audit.jsonl.1 (best-effort). Single-slot rotation
24
+ // is acceptable for an informational audit ledger.
25
+ const rotated = `${logPath}.1`;
26
+ renameSync(logPath, rotated);
27
+ }
28
+ catch {
29
+ // Fail-OPEN: never let rotation block writes.
12
30
  }
13
- catch { }
31
+ }
32
+ /**
33
+ * Async-style audit write. The file I/O is deferred to setImmediate so the hot
34
+ * path (the validate_action response) returns before the syscall. Errors are
35
+ * swallowed because the audit log is informational and must never break
36
+ * enforcement.
37
+ */
38
+ export function appendAudit(entry) {
39
+ const stamped = { ...entry };
40
+ setImmediate(() => {
41
+ try {
42
+ const logPath = getLogPath();
43
+ mkdirSync(dirname(logPath), { recursive: true });
44
+ maybeRotate(logPath);
45
+ appendFileSync(logPath, JSON.stringify(stamped) + "\n");
46
+ }
47
+ catch {
48
+ // Fail-OPEN
49
+ }
50
+ });
14
51
  }
15
52
  export async function handleGetAuditLog(args) {
16
53
  const logPath = getLogPath();
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/tools/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,SAAS,UAAU;IACjB,OAAO,SAAS,EAAE,CAAC,cAAc,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAA8B;IACxD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAA0C;IAChF,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACnG,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChF,IAAI,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvG,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC;IAEvG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IAEhC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACrH,CAAC"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/tools/audit.ts"],"names":[],"mappings":"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"}
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"bypass.d.ts","sourceRoot":"","sources":["../../src/tools/bypass.ts"],"names":[],"mappings":"AAGA,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;;;GAe9E"}
1
+ {"version":3,"file":"bypass.d.ts","sourceRoot":"","sources":["../../src/tools/bypass.ts"],"names":[],"mappings":"AAgBA,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;;;GAiD9E"}
@@ -1,16 +1,60 @@
1
+ /**
2
+ * log_bypass MCP tool — record an intentional, justified rule bypass.
3
+ *
4
+ * Constitutional rules CANNOT be bypassed (Builder B4 — Finding C3).
5
+ * Backed by `src/engine/immutability.ts`. A rejected bypass writes
6
+ * NOTHING to the audit log (per B4 brief test #8) — the entire call
7
+ * fails before audit is touched. This is intentional: a constitutional
8
+ * bypass attempt is a misuse signal, not a logged business event.
9
+ */
1
10
  import { loadAllRules } from "../engine/rule-engine.js";
11
+ import { assertCanBypass, ConstitutionalImmutableError, } from "../engine/immutability.js";
2
12
  import { appendAudit } from "./audit.js";
3
13
  export async function handleLogBypass(args) {
4
14
  const rules = loadAllRules();
5
- const rule = rules.find(r => r.id === args.rule_id);
15
+ const rule = rules.find((r) => r.id === args.rule_id);
6
16
  if (!rule) {
7
- return { content: [{ type: "text", text: JSON.stringify({ error: `Rule not found: ${args.rule_id}` }) }] };
17
+ return {
18
+ content: [{
19
+ type: "text",
20
+ text: JSON.stringify({ error: `Rule not found: ${args.rule_id}` }),
21
+ }],
22
+ };
8
23
  }
9
- if (rule.enforcement === "constitutional") {
10
- return { content: [{ type: "text", text: JSON.stringify({ error: `Cannot bypass constitutional rule: ${args.rule_id}` }) }] };
24
+ try {
25
+ assertCanBypass(args.rule_id);
11
26
  }
12
- const entry = { timestamp: new Date().toISOString(), type: "bypass", rule_id: args.rule_id, reason: args.reason };
27
+ catch (err) {
28
+ if (err instanceof ConstitutionalImmutableError) {
29
+ return {
30
+ content: [{
31
+ type: "text",
32
+ text: JSON.stringify({
33
+ error: "CONSTITUTIONAL_RULE_CANNOT_BE_BYPASSED",
34
+ rule_id: err.rule_id,
35
+ message: "Constitutional rules cannot be bypassed via log_bypass",
36
+ }),
37
+ }],
38
+ };
39
+ }
40
+ throw err;
41
+ }
42
+ const entry = {
43
+ timestamp: new Date().toISOString(),
44
+ type: "bypass",
45
+ rule_id: args.rule_id,
46
+ reason: args.reason,
47
+ };
13
48
  appendAudit(entry);
14
- return { content: [{ type: "text", text: JSON.stringify({ logged: true, bypass_id: `byp_${Date.now()}`, rule_id: args.rule_id }) }] };
49
+ return {
50
+ content: [{
51
+ type: "text",
52
+ text: JSON.stringify({
53
+ logged: true,
54
+ bypass_id: `byp_${Date.now()}`,
55
+ rule_id: args.rule_id,
56
+ }),
57
+ }],
58
+ };
15
59
  }
16
60
  //# sourceMappingURL=bypass.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bypass.js","sourceRoot":"","sources":["../../src/tools/bypass.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAyC;IAC7E,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC;IAEpD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACtH,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,KAAK,gBAAgB,EAAE,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,sCAAsC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACzI,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAClH,WAAW,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACjJ,CAAC"}
1
+ {"version":3,"file":"bypass.js","sourceRoot":"","sources":["../../src/tools/bypass.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EACL,eAAe,EACf,4BAA4B,GAC7B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAyC;IAC7E,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC;IAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;iBACnE,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,4BAA4B,EAAE,CAAC;YAChD,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,wCAAwC;4BAC/C,OAAO,EAAE,GAAG,CAAC,OAAO;4BACpB,OAAO,EAAE,wDAAwD;yBAClE,CAAC;qBACH,CAAC;aACH,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;IACF,WAAW,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,MAAM,EAAE,IAAI;oBACZ,SAAS,EAAE,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE;oBAC9B,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC;aACH,CAAC;KACH,CAAC;AACJ,CAAC"}
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ export declare function handleShipConfidenceCheck(args: {
2
+ artifact_id: string;
3
+ command_preview?: string;
4
+ label?: string;
5
+ }): Promise<{
6
+ content: {
7
+ type: "text";
8
+ text: string;
9
+ }[];
10
+ }>;
11
+ //# sourceMappingURL=ship-confidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-confidence.d.ts","sourceRoot":"","sources":["../../src/tools/ship-confidence.ts"],"names":[],"mappings":"AAQA,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;GAmCA"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * MCP tool: ship_confidence_check
3
+ *
4
+ * Invokes the ShipConfidenceGate for a given artifact_id and returns a
5
+ * structured result. The audit ledger is written by the gate itself.
6
+ */
7
+ import { ShipConfidenceGate } from "../engine/ship-confidence-gate.js";
8
+ export async function handleShipConfidenceCheck(args) {
9
+ // Lazy single-instance — picks up env at call time (test-friendly).
10
+ const gate = new ShipConfidenceGate();
11
+ const result = await gate.check(args.artifact_id, {
12
+ commandPreview: args.command_preview,
13
+ label: args.label,
14
+ });
15
+ const responseBody = {
16
+ allowed: result.decision === "allow",
17
+ decision: result.decision,
18
+ tier: result.tier,
19
+ reason: result.reason,
20
+ evidence: result.evidence,
21
+ verdict_id: result.verdict_id,
22
+ level: result.level,
23
+ signed_at: result.signed_at,
24
+ age_minutes: result.age_minutes,
25
+ would_have_been: result.would_have_been,
26
+ bypassed: result.bypassed ?? false,
27
+ stamp: result.stamp,
28
+ hook_name: result.stamp.hook_name,
29
+ hook_version: result.stamp.hook_version,
30
+ rule_name: result.stamp.rule_name,
31
+ rule_version: result.stamp.rule_version,
32
+ };
33
+ return {
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: JSON.stringify(responseBody, null, 2),
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ //# sourceMappingURL=ship-confidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-confidence.js","sourceRoot":"","sources":["../../src/tools/ship-confidence.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,IAI/C;IACC,oEAAoE;IACpE,MAAM,IAAI,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE;QAChD,cAAc,EAAE,IAAI,CAAC,eAAe;QACpC,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG;QACnB,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,OAAO;QACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;QAClC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS;QACjC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY;QACvC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS;QACjC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY;KACxC,CAAC;IAEF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;aAC5C;SACF;KACF,CAAC;AACJ,CAAC"}
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/tools/update.ts"],"names":[],"mappings":"AAGA,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;GAqBtF"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/tools/update.ts"],"names":[],"mappings":"AAmBA,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;GA0CtF"}
@@ -1,24 +1,60 @@
1
+ /**
2
+ * update_rules MCP tool — enable/disable rules.
3
+ *
4
+ * Constitutional rules CANNOT be disabled (Builder B4 — Finding C2).
5
+ * Backed by `src/engine/immutability.ts` whose source of truth is the
6
+ * frozen CONSTITUTIONAL_RULE_IDS array in defaults.ts plus any rule
7
+ * with `enforcement === "constitutional"` in rules.json.
8
+ *
9
+ * Atomicity: if ANY disable target is constitutional, the WHOLE call
10
+ * rejects — no partial commits (per B4 brief test #5). This prevents
11
+ * a caller from sneaking a real disable past the guard by mixing
12
+ * constitutional and non-constitutional IDs.
13
+ */
1
14
  import { getConfig, saveConfig } from "../config/loader.js";
2
- import { loadAllRules } from "../engine/rule-engine.js";
15
+ import { assertCanDisable, ConstitutionalImmutableError, } from "../engine/immutability.js";
3
16
  export async function handleUpdateRules(args) {
4
- const cfg = getConfig();
5
- const allRules = loadAllRules();
6
- const constitutional = new Set(allRules.filter(r => r.enforcement === "constitutional").map(r => r.id));
7
- if (args.disable?.some(id => constitutional.has(id))) {
17
+ const blocked = [];
18
+ if (args.disable) {
19
+ for (const id of args.disable) {
20
+ try {
21
+ assertCanDisable(id);
22
+ }
23
+ catch (err) {
24
+ if (err instanceof ConstitutionalImmutableError) {
25
+ blocked.push(err.rule_id);
26
+ }
27
+ else {
28
+ throw err;
29
+ }
30
+ }
31
+ }
32
+ }
33
+ if (blocked.length > 0) {
8
34
  return {
9
35
  content: [{
10
36
  type: "text",
11
- text: JSON.stringify({ error: "Cannot disable constitutional rules", blocked: args.disable.filter(id => constitutional.has(id)) }),
37
+ text: JSON.stringify({
38
+ error: "CONSTITUTIONAL_RULE_IMMUTABLE",
39
+ rule_ids: blocked,
40
+ message: "Constitutional rules cannot be disabled via update_rules",
41
+ }),
12
42
  }],
13
43
  };
14
44
  }
45
+ const cfg = getConfig();
15
46
  const active = new Set(cfg.active_rules);
16
47
  if (args.enable)
17
- args.enable.forEach(id => active.add(id));
48
+ args.enable.forEach((id) => active.add(id));
18
49
  if (args.disable)
19
- args.disable.forEach(id => active.delete(id));
50
+ args.disable.forEach((id) => active.delete(id));
20
51
  cfg.active_rules = [...active];
21
52
  saveConfig(cfg);
22
- return { content: [{ type: "text", text: JSON.stringify({ updated: true, active_count: cfg.active_rules.length }) }] };
53
+ return {
54
+ content: [{
55
+ type: "text",
56
+ text: JSON.stringify({ updated: true, active_count: cfg.active_rules.length }),
57
+ }],
58
+ };
23
59
  }
24
60
  //# sourceMappingURL=update.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/tools/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAA+C;IACrF,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAExG,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,qCAAqC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;iBACpI,CAAC;SACH,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,MAAM;QAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,IAAI,IAAI,CAAC,OAAO;QAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,GAAG,CAAC,CAAC;IAEhB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClI,CAAC"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/tools/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAA+C;IACrF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,4BAA4B,EAAE,CAAC;oBAChD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5B,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,CAAC;gBACZ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,KAAK,EAAE,+BAA+B;wBACtC,QAAQ,EAAE,OAAO;wBACjB,OAAO,EAAE,0DAA0D;qBACpE,CAAC;iBACH,CAAC;SACH,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,MAAM;QAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,OAAO;QAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,GAAG,CAAC,CAAC;IAEhB,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;aAC/E,CAAC;KACH,CAAC;AACJ,CAAC"}
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAKA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GA0BpF"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAQA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GA4EpF"}
@@ -1,26 +1,78 @@
1
- import { evaluateAction } from "../engine/rule-engine.js";
1
+ import { evaluateActionAsync } from "../engine/rule-engine.js";
2
2
  import { getConfig } from "../config/loader.js";
3
3
  import { getWarningCounts, recordWarning } from "../engine/session-state.js";
4
4
  import { appendAudit } from "./audit.js";
5
+ const PKG_VERSION = "1.1.0";
6
+ const HOOK_NAME = "sunaiva-gate";
5
7
  export async function handleValidateAction(args) {
8
+ // Kill-switch: short-circuit everything if disabled.
9
+ if (process.env.DISABLE_SUNAIVA_GATE === "1") {
10
+ return {
11
+ content: [{
12
+ type: "text",
13
+ text: JSON.stringify({
14
+ allowed: true,
15
+ gate_version: PKG_VERSION,
16
+ hook_name: HOOK_NAME,
17
+ disabled: true,
18
+ message: `[${HOOK_NAME} v${PKG_VERSION}] DISABLED via DISABLE_SUNAIVA_GATE=1 — all actions allowed.`,
19
+ }, null, 2),
20
+ }],
21
+ };
22
+ }
23
+ const dryRun = process.env.SUNAIVA_GATE_DRY_RUN === "1";
6
24
  const cfg = getConfig();
7
25
  const counts = getWarningCounts();
8
- const result = evaluateAction(args.action, cfg, counts, args.context);
26
+ // Async path when SUNAIVA_GATE_API_TOKEN is set, premium rules are
27
+ // delegated to the BackendClient. Unset → premium rules return
28
+ // `skipped_no_token` and the once-per-process stderr notice fires.
29
+ const result = await evaluateActionAsync(args.action, cfg, counts, args.context);
9
30
  for (const w of result.warnings)
10
31
  recordWarning(w.id);
32
+ const decision = result.allowed ? "pass" : "block";
11
33
  const entry = {
12
34
  timestamp: new Date().toISOString(),
13
- type: result.allowed ? "pass" : "block",
35
+ gate_version: PKG_VERSION,
36
+ type: dryRun ? `dry_run_${decision}` : decision,
14
37
  action: args.action.slice(0, 200),
38
+ severity_tier: result.severity_tier,
15
39
  violations: result.violations.map(r => r.id),
16
40
  warnings: result.warnings.map(r => r.id),
41
+ skipped_premium: result.skipped_premium,
42
+ would_have_blocked: result.would_have_blocked,
17
43
  };
18
44
  appendAudit(entry);
45
+ // In dry-run, force allowed=true but expose what would have happened.
46
+ const finalAllowed = dryRun ? true : result.allowed;
47
+ // Self-stamping: every block/warn message identifies the gate + escape hatch.
48
+ let stamp = `[${HOOK_NAME} v${PKG_VERSION}]`;
49
+ if (!finalAllowed) {
50
+ const violationNames = result.violations.map(r => `${r.id} (${r.name})`).join(", ");
51
+ stamp += ` BLOCKED by ${violationNames}. Escape: export DISABLE_SUNAIVA_GATE=1`;
52
+ }
53
+ else if (dryRun && result.would_have_blocked.length > 0) {
54
+ stamp += ` DRY-RUN — would have blocked: ${result.would_have_blocked.join(", ")}`;
55
+ }
56
+ else if (result.warnings.length > 0) {
57
+ const warnNames = result.warnings.map(r => `${r.id} (${r.name})`).join(", ");
58
+ stamp += ` WARN ${warnNames}. Next match will block. Escape: export DISABLE_SUNAIVA_GATE=1`;
59
+ }
60
+ else {
61
+ stamp += " allow";
62
+ }
19
63
  return {
20
64
  content: [{
21
65
  type: "text",
22
66
  text: JSON.stringify({
23
- allowed: result.allowed,
67
+ allowed: finalAllowed,
68
+ gate_version: PKG_VERSION,
69
+ hook_name: HOOK_NAME,
70
+ escape_hatch: "DISABLE_SUNAIVA_GATE=1",
71
+ severity_tier: result.severity_tier,
72
+ dry_run: dryRun,
73
+ would_have_blocked: result.would_have_blocked,
74
+ skipped_premium: result.skipped_premium,
75
+ message: stamp,
24
76
  rule_violations: result.violations.map(r => ({ id: r.id, name: r.name, severity: r.severity })),
25
77
  warnings: result.warnings.map(r => ({ id: r.id, name: r.name })),
26
78
  }, null, 2),
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAA0C;IACnF,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAEtE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;QAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAErD,MAAM,KAAK,GAAG;QACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;QACvC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;QACjC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzC,CAAC;IACF,WAAW,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;oBAC/F,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;iBACjE,EAAE,IAAI,EAAE,CAAC,CAAC;aACZ,CAAC;KACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Shared types for the Sunaiva Gate premium backend integration.
3
+ *
4
+ * Exposed from `src/types/backend.ts` so other internal modules (e.g.,
5
+ * B2's ship-confidence flow) can import the same shapes without depending
6
+ * on the full backend-client implementation.
7
+ *
8
+ * API contract source: sunaiva-gate-backend/README.md §"API contract"
9
+ * POST /api/v1/match
10
+ * Request : { rule_id, input_text, context? }
11
+ * Response: { matched, severity, decision, reason? }
12
+ */
13
+ /** Severity tier returned by the backend for a matched rule. */
14
+ export type BackendSeverity = "block" | "warn" | "log";
15
+ /** Decision instruction the backend wants the client to enforce. */
16
+ export type BackendDecision = "deny" | "allow" | "ask";
17
+ /**
18
+ * Status of a per-rule backend evaluation. The client never blocks the
19
+ * customer on backend-side failures — those are treated as a skip so a
20
+ * Sunaiva outage cannot trigger a customer-side service outage.
21
+ */
22
+ export type BackendEvalStatus = "matched" | "no_match" | "skipped_no_token" | "skipped_auth" | "skipped_tier" | "skipped_quota" | "skipped_unknown" | "skipped_error" | "skipped_disabled";
23
+ /** Per-rule evaluation outcome. */
24
+ export interface BackendRuleResult {
25
+ rule_id: string;
26
+ status: BackendEvalStatus;
27
+ matched: boolean;
28
+ severity?: BackendSeverity;
29
+ decision?: BackendDecision;
30
+ reason?: string;
31
+ /** Set when status is `skipped_error` / `skipped_*` for operator visibility. */
32
+ error?: string;
33
+ /** HTTP status code returned by the backend, if any. */
34
+ http_status?: number;
35
+ /** Wall-clock latency for this rule's backend call (ms). */
36
+ latency_ms: number;
37
+ }
38
+ /** Aggregate of all rule evaluations in a single backend pass. */
39
+ export interface BackendEvalResult {
40
+ /** Rule IDs that were attempted. */
41
+ evaluated_rules: string[];
42
+ /** Per-rule results in input order. */
43
+ results: BackendRuleResult[];
44
+ /** Subset of evaluated_rules that matched (matched=true). */
45
+ matched_rule_ids: string[];
46
+ /** Subset of evaluated_rules that were skipped for any reason. */
47
+ skipped_rule_ids: string[];
48
+ /** Total wall-clock latency (ms) for all calls combined. */
49
+ latency_ms: number;
50
+ /** True iff no API token was configured (drives once-per-session stderr notice). */
51
+ premium_skipped_due_to_no_token: boolean;
52
+ }
53
+ /** Options for constructing a BackendClient. */
54
+ export interface BackendClientOptions {
55
+ /** Backend URL. Defaults to env SUNAIVA_GATE_BACKEND_URL or the production URL. */
56
+ url?: string;
57
+ /** Customer JWT. Defaults to env SUNAIVA_GATE_API_TOKEN. */
58
+ apiToken?: string;
59
+ /** Request timeout (ms). Defaults to env SUNAIVA_GATE_BACKEND_TIMEOUT_MS or 3000. */
60
+ timeoutMs?: number;
61
+ /** Injected fetch (for tests). Defaults to global fetch. */
62
+ fetchImpl?: typeof fetch;
63
+ }
64
+ /** Production backend URL. */
65
+ export declare const DEFAULT_BACKEND_URL = "https://gate.sunaiva.dev/api/v1/match";
66
+ export declare const DEFAULT_TIMEOUT_MS = 3000;
67
+ export declare const RETRY_BACKOFF_MS = 500;
68
+ export declare const MAX_RETRIES = 1;
69
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/types/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAEvD,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,UAAU,GACV,kBAAkB,GAClB,cAAc,GACd,cAAc,GACd,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,kBAAkB,CACnB;AAEH,mCAAmC;AACnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,uCAAuC;IACvC,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,+BAA+B,EAAE,OAAO,CAAC;CAC1C;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,8BAA8B;AAC9B,eAAO,MAAM,mBAAmB,0CAA0C,CAAC;AAC3E,eAAO,MAAM,kBAAkB,OAAO,CAAC;AACvC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,WAAW,IAAI,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Shared types for the Sunaiva Gate premium backend integration.
3
+ *
4
+ * Exposed from `src/types/backend.ts` so other internal modules (e.g.,
5
+ * B2's ship-confidence flow) can import the same shapes without depending
6
+ * on the full backend-client implementation.
7
+ *
8
+ * API contract source: sunaiva-gate-backend/README.md §"API contract"
9
+ * POST /api/v1/match
10
+ * Request : { rule_id, input_text, context? }
11
+ * Response: { matched, severity, decision, reason? }
12
+ */
13
+ /** Production backend URL. */
14
+ export const DEFAULT_BACKEND_URL = "https://gate.sunaiva.dev/api/v1/match";
15
+ export const DEFAULT_TIMEOUT_MS = 3000;
16
+ export const RETRY_BACKOFF_MS = 500;
17
+ export const MAX_RETRIES = 1;
18
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/types/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAqEH,8BAA8B;AAC9B,MAAM,CAAC,MAAM,mBAAmB,GAAG,uCAAuC,CAAC;AAC3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AACpC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunaiva/gate",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Sunaiva Gate MCP — enforcement layer for AI agent rules. Stop documenting rules your agents ignore. Start enforcing them.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -9,15 +9,23 @@
9
9
  },
10
10
  "files": [
11
11
  "dist/",
12
+ "dist/rules/",
13
+ "dist/rules/rules.json",
14
+ "dist/rules/presets.json",
15
+ "dist/rules/categories.json",
12
16
  "README.md",
17
+ "CHANGELOG.md",
18
+ "BUSINESS_LICENSE.md",
19
+ "LICENSE",
13
20
  "package.json"
14
21
  ],
15
22
  "scripts": {
16
23
  "build": "tsc && node scripts/strip-patterns.js",
17
24
  "start": "node dist/index.js",
18
25
  "dev": "tsx src/index.ts",
19
- "setup": "tsx src/setup.ts",
20
- "prepublishOnly": "npm run build",
26
+ "verify-bundle": "node scripts/verify-bundle.js",
27
+ "prepack": "node scripts/verify-bundle.js",
28
+ "prepublishOnly": "npm run build && node scripts/verify-bundle.js",
21
29
  "test": "node --experimental-vm-modules node_modules/.bin/jest --passWithNoTests"
22
30
  },
23
31
  "keywords": [