@cello-protocol/gateway 0.0.1

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 (105) hide show
  1. package/dist/bin/cello-gateway.d.ts +3 -0
  2. package/dist/bin/cello-gateway.d.ts.map +1 -0
  3. package/dist/bin/cello-gateway.js +174 -0
  4. package/dist/bin/cello-gateway.js.map +1 -0
  5. package/dist/client.d.ts +16 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +182 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/config/config-store.d.ts +42 -0
  10. package/dist/config/config-store.d.ts.map +1 -0
  11. package/dist/config/config-store.js +198 -0
  12. package/dist/config/config-store.js.map +1 -0
  13. package/dist/detect/deberta-model-manifest.d.ts +54 -0
  14. package/dist/detect/deberta-model-manifest.d.ts.map +1 -0
  15. package/dist/detect/deberta-model-manifest.js +17 -0
  16. package/dist/detect/deberta-model-manifest.js.map +1 -0
  17. package/dist/detect/exfil.d.ts +14 -0
  18. package/dist/detect/exfil.d.ts.map +1 -0
  19. package/dist/detect/exfil.js +69 -0
  20. package/dist/detect/exfil.js.map +1 -0
  21. package/dist/detect/gitleaks-rules.d.ts +18 -0
  22. package/dist/detect/gitleaks-rules.d.ts.map +1 -0
  23. package/dist/detect/gitleaks-rules.js +229 -0
  24. package/dist/detect/gitleaks-rules.js.map +1 -0
  25. package/dist/detect/injection-patterns.d.ts +10 -0
  26. package/dist/detect/injection-patterns.d.ts.map +1 -0
  27. package/dist/detect/injection-patterns.js +53 -0
  28. package/dist/detect/injection-patterns.js.map +1 -0
  29. package/dist/detect/injection-scanner.d.ts +44 -0
  30. package/dist/detect/injection-scanner.d.ts.map +1 -0
  31. package/dist/detect/injection-scanner.js +45 -0
  32. package/dist/detect/injection-scanner.js.map +1 -0
  33. package/dist/detect/language.d.ts +37 -0
  34. package/dist/detect/language.d.ts.map +1 -0
  35. package/dist/detect/language.js +85 -0
  36. package/dist/detect/language.js.map +1 -0
  37. package/dist/detect/linear-regex.d.ts +20 -0
  38. package/dist/detect/linear-regex.d.ts.map +1 -0
  39. package/dist/detect/linear-regex.js +70 -0
  40. package/dist/detect/linear-regex.js.map +1 -0
  41. package/dist/detect/model-installer.d.ts +32 -0
  42. package/dist/detect/model-installer.d.ts.map +1 -0
  43. package/dist/detect/model-installer.js +94 -0
  44. package/dist/detect/model-installer.js.map +1 -0
  45. package/dist/detect/pii.d.ts +27 -0
  46. package/dist/detect/pii.d.ts.map +1 -0
  47. package/dist/detect/pii.js +119 -0
  48. package/dist/detect/pii.js.map +1 -0
  49. package/dist/detect/rate-limit.d.ts +44 -0
  50. package/dist/detect/rate-limit.d.ts.map +1 -0
  51. package/dist/detect/rate-limit.js +56 -0
  52. package/dist/detect/rate-limit.js.map +1 -0
  53. package/dist/detect/sanitize.d.ts +50 -0
  54. package/dist/detect/sanitize.d.ts.map +1 -0
  55. package/dist/detect/sanitize.js +211 -0
  56. package/dist/detect/sanitize.js.map +1 -0
  57. package/dist/detect/secrets.d.ts +20 -0
  58. package/dist/detect/secrets.d.ts.map +1 -0
  59. package/dist/detect/secrets.js +104 -0
  60. package/dist/detect/secrets.js.map +1 -0
  61. package/dist/index.d.ts +38 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +25 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/passthrough.d.ts +18 -0
  66. package/dist/passthrough.d.ts.map +1 -0
  67. package/dist/passthrough.js +21 -0
  68. package/dist/passthrough.js.map +1 -0
  69. package/dist/protocol.d.ts +53 -0
  70. package/dist/protocol.d.ts.map +1 -0
  71. package/dist/protocol.js +52 -0
  72. package/dist/protocol.js.map +1 -0
  73. package/dist/records/record-store.d.ts +28 -0
  74. package/dist/records/record-store.d.ts.map +1 -0
  75. package/dist/records/record-store.js +134 -0
  76. package/dist/records/record-store.js.map +1 -0
  77. package/dist/screen/inbound.d.ts +29 -0
  78. package/dist/screen/inbound.d.ts.map +1 -0
  79. package/dist/screen/inbound.js +127 -0
  80. package/dist/screen/inbound.js.map +1 -0
  81. package/dist/screen/inbound.test.d.ts +2 -0
  82. package/dist/screen/inbound.test.d.ts.map +1 -0
  83. package/dist/screen/inbound.test.js +49 -0
  84. package/dist/screen/inbound.test.js.map +1 -0
  85. package/dist/screen/outbound.d.ts +57 -0
  86. package/dist/screen/outbound.d.ts.map +1 -0
  87. package/dist/screen/outbound.js +183 -0
  88. package/dist/screen/outbound.js.map +1 -0
  89. package/dist/screen/outbound.test.d.ts +2 -0
  90. package/dist/screen/outbound.test.d.ts.map +1 -0
  91. package/dist/screen/outbound.test.js +62 -0
  92. package/dist/screen/outbound.test.js.map +1 -0
  93. package/dist/server.d.ts +34 -0
  94. package/dist/server.d.ts.map +1 -0
  95. package/dist/server.js +129 -0
  96. package/dist/server.js.map +1 -0
  97. package/dist/spawn.d.ts +32 -0
  98. package/dist/spawn.d.ts.map +1 -0
  99. package/dist/spawn.js +84 -0
  100. package/dist/spawn.js.map +1 -0
  101. package/dist/types.d.ts +121 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +39 -0
  104. package/dist/types.js.map +1 -0
  105. package/package.json +42 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * M9-IN-001 — inbound Layer-1 deterministic sanitization.
3
+ *
4
+ * Pure function, no model, no network (INV-1). Runs the ordered steps from the attack-corpus §1
5
+ * pipeline that need no external engine: size cap (first — AC-005), invisible/smuggled-Unicode
6
+ * strip (AC-001 / SI-001), confusables normalization (NFKC + script-lookalike map), encoded-
7
+ * payload decode, Shannon-entropy scoring (AC-003), and chat-template/special-token strip (AC-004).
8
+ *
9
+ * The Step-9 injection-pattern match (AC-002) is a SEPARATE concern: it requires a linear-time
10
+ * RE2 engine (no native RegExp — ReDoS). The RE2 binding is a pending decision, so that step is
11
+ * not wired here yet; this module exposes the sanitized text + notes that the pattern matcher and
12
+ * the M9-IN-002 scanner will consume.
13
+ */
14
+ /** Default per-message byte cap — mirrors the daemon's 1 MB content cap. */
15
+ export declare const DEFAULT_MAX_BYTES = 1000000;
16
+ export interface SanitizationNote {
17
+ step: "invisible_strip" | "confusables" | "decode" | "entropy" | "special_tokens";
18
+ detail: string;
19
+ count?: number;
20
+ }
21
+ export interface SanitizeResult {
22
+ /** The DELIVERED text: invisible-strip + confusables + special-token strip. Empty on `blocked`. */
23
+ text: string;
24
+ /**
25
+ * The delivered text with encodings additionally decoded — for DETECTION ONLY (the pattern
26
+ * matcher / entropy). Never delivered to the agent: decoding %XX / &#..; / \x.. in a legitimate
27
+ * URL or code snippet would corrupt content the receiver needs (M1 review / decode-then-rescan).
28
+ */
29
+ decodedForScan: string;
30
+ /** Per-step detection notes (only steps that fired). */
31
+ notes: SanitizationNote[];
32
+ /** A suspicion signal for high-entropy (encoded-blob) content. 0 = nothing suspicious. */
33
+ entropySuspicion: number;
34
+ /** Set when the message is rejected outright (e.g. over the size cap) — text is empty. */
35
+ blocked?: {
36
+ reason: string;
37
+ guidance: string;
38
+ };
39
+ }
40
+ export interface SanitizeOptions {
41
+ maxBytes?: number;
42
+ }
43
+ export declare function stripInvisible(text: string): {
44
+ text: string;
45
+ removed: number;
46
+ };
47
+ /** The space-free, encoded-alphabet, high-entropy tokens (encoded-blob candidates) in `text`. */
48
+ export declare function highEntropyTokens(text: string): string[];
49
+ export declare function sanitizeInbound(content: Uint8Array, opts?: SanitizeOptions): SanitizeResult;
50
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/detect/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,iBAAiB,GAAG,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,mGAAmG;IACnG,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,0FAA0F;IAC1F,gBAAgB,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAQ9E;AAwED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQxD;AAwBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,GAAE,eAAoB,GAAG,cAAc,CA4C/F"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * M9-IN-001 — inbound Layer-1 deterministic sanitization.
3
+ *
4
+ * Pure function, no model, no network (INV-1). Runs the ordered steps from the attack-corpus §1
5
+ * pipeline that need no external engine: size cap (first — AC-005), invisible/smuggled-Unicode
6
+ * strip (AC-001 / SI-001), confusables normalization (NFKC + script-lookalike map), encoded-
7
+ * payload decode, Shannon-entropy scoring (AC-003), and chat-template/special-token strip (AC-004).
8
+ *
9
+ * The Step-9 injection-pattern match (AC-002) is a SEPARATE concern: it requires a linear-time
10
+ * RE2 engine (no native RegExp — ReDoS). The RE2 binding is a pending decision, so that step is
11
+ * not wired here yet; this module exposes the sanitized text + notes that the pattern matcher and
12
+ * the M9-IN-002 scanner will consume.
13
+ */
14
+ /** Default per-message byte cap — mirrors the daemon's 1 MB content cap. */
15
+ export const DEFAULT_MAX_BYTES = 1_000_000;
16
+ // ── Step 1: invisible / smuggled-Unicode strip ───────────────────────────────
17
+ // Codepoints that are invisible (or direction-altering) to a human but tokenize for an LLM.
18
+ const SINGLE_SMUGGLE = new Set([
19
+ 0x00ad, // soft hyphen
20
+ 0x200b, 0x200c, 0x200d, // zero-width space / non-joiner / joiner
21
+ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, // word joiner + invisible math operators
22
+ 0xfeff, // BOM / zero-width no-break space
23
+ 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, // bidi embeddings / overrides / pop
24
+ 0x2066, 0x2067, 0x2068, 0x2069, // bidi isolates
25
+ ]);
26
+ function isSmuggled(cp) {
27
+ if (SINGLE_SMUGGLE.has(cp))
28
+ return true;
29
+ if (cp >= 0xe0000 && cp <= 0xe007f)
30
+ return true; // Tags block
31
+ if (cp >= 0xfe00 && cp <= 0xfe0f)
32
+ return true; // variation selectors
33
+ if (cp >= 0xe0100 && cp <= 0xe01ef)
34
+ return true; // variation selectors supplement
35
+ return false;
36
+ }
37
+ export function stripInvisible(text) {
38
+ let out = "";
39
+ let removed = 0;
40
+ for (const ch of text) {
41
+ if (isSmuggled(ch.codePointAt(0))) {
42
+ removed++;
43
+ continue;
44
+ }
45
+ out += ch;
46
+ }
47
+ return { text: out, removed };
48
+ }
49
+ // ── Step 3: confusables normalization ────────────────────────────────────────
50
+ // NFKC folds full-width, mathematical-alphanumeric, enclosed, and other compatibility lookalikes
51
+ // to their base form. NFKC does NOT touch cross-script confusables (Cyrillic/Greek letters that
52
+ // merely LOOK Latin), so those get an explicit map. (A full Unicode confusables.txt integration —
53
+ // 6,800+ pairs — is a follow-up; this covers the common attack scripts.)
54
+ const CYRILLIC_GREEK_CONFUSABLES = {
55
+ // Cyrillic → Latin
56
+ "а": "a", "е": "e", "о": "o", "с": "c", "р": "p", "х": "x",
57
+ "у": "y", "к": "k", "м": "m", "т": "t", "н": "h", "в": "b",
58
+ "и": "u", "ѕ": "s", "і": "i", "ј": "j", "һ": "h", "ԁ": "d",
59
+ "А": "A", "В": "B", "Е": "E", "К": "K", "М": "M", "Н": "H",
60
+ "О": "O", "Р": "P", "С": "C", "Т": "T", "Х": "X", "Ѕ": "S",
61
+ "І": "I", "Ј": "J",
62
+ // Greek → Latin
63
+ "ο": "o", "ν": "v", "α": "a", "ρ": "p", "υ": "u", "κ": "k",
64
+ "Α": "A", "Β": "B", "Ε": "E", "Κ": "K", "Μ": "M", "Ν": "N",
65
+ "Ο": "O", "Ρ": "P", "Τ": "T", "Χ": "X",
66
+ };
67
+ function normalizeConfusables(text) {
68
+ const nfkc = text.normalize("NFKC");
69
+ let count = 0;
70
+ const mapped = [...nfkc].map((ch) => {
71
+ const r = CYRILLIC_GREEK_CONFUSABLES[ch];
72
+ if (r !== undefined) {
73
+ count++;
74
+ return r;
75
+ }
76
+ return ch;
77
+ }).join("");
78
+ return { text: mapped, changed: mapped !== text, count };
79
+ }
80
+ // ── Step 6: encoded-payload decode ───────────────────────────────────────────
81
+ // Decode HTML entities, percent-encoding, and \x / \u escapes so a word hidden behind an encoding
82
+ // surfaces for downstream pattern matching. (Base64/other-radix BLOCKS are handled by entropy
83
+ // scoring + the Step-7 hidden-instruction handling, not decoded blindly here.)
84
+ const NAMED_ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " };
85
+ function decodeEncoded(text) {
86
+ let count = 0;
87
+ let out = text;
88
+ out = out.replace(/&#x([0-9a-f]+);/gi, (_m, h) => { count++; return safeFromCodePoint(parseInt(h, 16)); });
89
+ out = out.replace(/&#(\d+);/g, (_m, d) => { count++; return safeFromCodePoint(parseInt(d, 10)); });
90
+ out = out.replace(/&([a-z]+);/gi, (m, name) => {
91
+ const v = NAMED_ENTITIES[name.toLowerCase()];
92
+ if (v === undefined)
93
+ return m;
94
+ count++;
95
+ return v;
96
+ });
97
+ out = out.replace(/%([0-9a-f]{2})/gi, (_m, h) => { count++; return safeFromCodePoint(parseInt(h, 16)); });
98
+ out = out.replace(/\\x([0-9a-f]{2})/gi, (_m, h) => { count++; return safeFromCodePoint(parseInt(h, 16)); });
99
+ out = out.replace(/\\u\{?([0-9a-f]{1,6})\}?/gi, (_m, h) => { count++; return safeFromCodePoint(parseInt(h, 16)); });
100
+ return { text: out, changed: out !== text, count };
101
+ }
102
+ function safeFromCodePoint(cp) {
103
+ if (!Number.isFinite(cp) || cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff))
104
+ return "";
105
+ try {
106
+ return String.fromCodePoint(cp);
107
+ }
108
+ catch {
109
+ return "";
110
+ }
111
+ }
112
+ // ── Step 8: Shannon-entropy scoring ──────────────────────────────────────────
113
+ // An encoded payload (base64/hex blob) is a long, space-free, high-entropy token; ordinary prose
114
+ // is short tokens with lower per-character entropy. Count the suspicious tokens.
115
+ const ENTROPY_MIN_TOKEN_LEN = 20;
116
+ const ENTROPY_BITS_THRESHOLD = 4.0;
117
+ function shannonBits(s) {
118
+ const freq = new Map();
119
+ for (const ch of s)
120
+ freq.set(ch, (freq.get(ch) ?? 0) + 1);
121
+ let h = 0;
122
+ for (const c of freq.values()) {
123
+ const p = c / s.length;
124
+ h -= p * Math.log2(p);
125
+ }
126
+ return h;
127
+ }
128
+ // An encoded-blob candidate is a long run drawn purely from a base64/base64url/hex alphabet —
129
+ // which excludes URLs, file paths, and prose (they carry `:` `/` `.` or whitespace). This keeps
130
+ // the entropy signal on actual encoded payloads, not legitimate long tokens like a URL.
131
+ const ENCODED_CHARSET = /^[A-Za-z0-9+/=_-]+$/;
132
+ /** The space-free, encoded-alphabet, high-entropy tokens (encoded-blob candidates) in `text`. */
133
+ export function highEntropyTokens(text) {
134
+ const found = [];
135
+ for (const token of text.split(/\s+/)) {
136
+ if (token.length < ENTROPY_MIN_TOKEN_LEN)
137
+ continue;
138
+ if (!ENCODED_CHARSET.test(token))
139
+ continue;
140
+ if (shannonBits(token) >= ENTROPY_BITS_THRESHOLD)
141
+ found.push(token);
142
+ }
143
+ return found;
144
+ }
145
+ function scoreEntropy(text) {
146
+ return highEntropyTokens(text).length;
147
+ }
148
+ // ── Step 9 (markers): chat-template / special-token strip ────────────────────
149
+ // Removes privileged-turn markers so they cannot be re-interpreted as a system/instruction turn.
150
+ // These are bounded literals/anchored patterns (no catastrophic backtracking) — distinct from the
151
+ // RE2 injection-pattern step (AC-002), which is parked on the RE2 binding decision.
152
+ const LITERAL_MARKERS = ["[SYSTEM]", "[/SYSTEM]", "<<SYS>>", "<</SYS>>", "[INST]", "[/INST]", "SYSTEM PROMPT:", "<system>", "</system>"];
153
+ function stripSpecialTokens(text) {
154
+ let out = text;
155
+ let removed = 0;
156
+ for (const lit of LITERAL_MARKERS) {
157
+ const parts = out.split(lit);
158
+ if (parts.length > 1) {
159
+ removed += parts.length - 1;
160
+ out = parts.join(" ");
161
+ }
162
+ }
163
+ out = out.replace(/<\|[a-z0-9_]+\|>/gi, () => { removed++; return " "; });
164
+ out = out.replace(/###\s*(instruction|response|system|human|assistant)\b:?/gi, () => { removed++; return " "; });
165
+ out = out.replace(/<\/?s>/gi, () => { removed++; return " "; });
166
+ return { text: out, removed };
167
+ }
168
+ // ── The pipeline ─────────────────────────────────────────────────────────────
169
+ export function sanitizeInbound(content, opts = {}) {
170
+ const maxBytes = opts.maxBytes ?? DEFAULT_MAX_BYTES;
171
+ const notes = [];
172
+ // AC-005: size cap FIRST — before any decode/normalize work.
173
+ if (content.length > maxBytes) {
174
+ return {
175
+ text: "",
176
+ decodedForScan: "",
177
+ notes: [],
178
+ entropySuspicion: 0,
179
+ blocked: {
180
+ reason: "content_too_large",
181
+ guidance: `Inbound message is ${content.length} bytes, over the ${maxBytes}-byte cap. ` +
182
+ "It was rejected before sanitization; the sender must split it into smaller messages.",
183
+ },
184
+ };
185
+ }
186
+ let text = new TextDecoder("utf-8", { fatal: false }).decode(content);
187
+ const inv = stripInvisible(text);
188
+ if (inv.removed > 0)
189
+ notes.push({ step: "invisible_strip", detail: "stripped invisible/smuggled-Unicode codepoints", count: inv.removed });
190
+ text = inv.text;
191
+ const conf = normalizeConfusables(text);
192
+ if (conf.changed)
193
+ notes.push({ step: "confusables", detail: "normalized lookalike characters to their base form", count: conf.count });
194
+ text = conf.text;
195
+ const tok = stripSpecialTokens(text);
196
+ if (tok.removed > 0)
197
+ notes.push({ step: "special_tokens", detail: "stripped chat-template / special-token markers", count: tok.removed });
198
+ text = tok.text;
199
+ // Decode is DETECTION-ONLY (decode-then-rescan): it feeds the pattern matcher + entropy, and is
200
+ // NOT applied to the delivered `text` — decoding %XX / &#..; / \x.. / \u.. in a legitimate URL,
201
+ // code snippet, or quoted entity would silently corrupt content the receiver needs (M1 review).
202
+ const dec = decodeEncoded(text);
203
+ if (dec.changed)
204
+ notes.push({ step: "decode", detail: "encoded payload detected (decoded for rescan; delivered form unchanged)", count: dec.count });
205
+ const decodedForScan = dec.text;
206
+ const entropySuspicion = scoreEntropy(decodedForScan);
207
+ if (entropySuspicion > 0)
208
+ notes.push({ step: "entropy", detail: "high-entropy encoded-blob segment(s) detected", count: entropySuspicion });
209
+ return { text, decodedForScan, notes, entropySuspicion };
210
+ }
211
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/detect/sanitize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /** Compile the rule set + the false-positive layer. Returns how many of the 222 rules compiled. */
2
+ export declare function compileSecretRules(): {
3
+ compiled: number;
4
+ total: number;
5
+ };
6
+ export declare function secretRulesReady(): boolean;
7
+ export interface SecretFinding {
8
+ ruleId: string;
9
+ }
10
+ export interface SecretScanResult {
11
+ text: string;
12
+ findings: SecretFinding[];
13
+ }
14
+ /**
15
+ * Redact every detected secret in `input` with a typed placeholder `[REDACTED:<rule-id>]`. The
16
+ * delivered text never contains a detected secret value (SI-001). Returns the redacted text + the
17
+ * rules that fired. Returns the input unchanged if the rules were never compiled.
18
+ */
19
+ export declare function redactSecrets(input: string): SecretScanResult;
20
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/detect/secrets.ts"],"names":[],"mappings":"AAuBA,mGAAmG;AACnG,wBAAgB,kBAAkB,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAexE;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,MAAM,WAAW,aAAa;IAAG,MAAM,EAAE,MAAM,CAAA;CAAE;AACjD,MAAM,WAAW,gBAAgB;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE;AAmB7E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CA6B7D"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * M9-OUT-001 — outbound secret detection + redaction.
3
+ *
4
+ * Adopts the FULL gitleaks dictionary (222 detectors, MIT — see ./gitleaks-rules.ts) plus the
5
+ * generic keyword-proximity + entropy catch-all (gitleaks' own `generic-api-key` rule, so coverage
6
+ * is not limited to enumerated formats), with gitleaks' value-level false-positive layer (stopwords
7
+ * + allow-regexes + per-rule entropy thresholds). Secrets redact by DEFAULT — leaking a credential is
8
+ * essentially never intended; the rare deliberate send goes through the M9-FEED-001 governance
9
+ * re-send.
10
+ *
11
+ * Every pattern runs on the RE2 engine (the rules are RE2-authored), so a crafted message can never
12
+ * cause catastrophic backtracking. The keyword pre-filter (run a rule only when one of its keywords
13
+ * appears) keeps the 222-rule scan fast. Compile once at gateway startup, after initLinearRegex().
14
+ */
15
+ import { LinearRegex } from "./linear-regex.js";
16
+ import { GITLEAKS_RULES, GITLEAKS_STOPWORDS, GITLEAKS_ALLOW_REGEXES } from "./gitleaks-rules.js";
17
+ let RULES = null;
18
+ let STOPWORDS = [];
19
+ let ALLOW = [];
20
+ /** Compile the rule set + the false-positive layer. Returns how many of the 222 rules compiled. */
21
+ export function compileSecretRules() {
22
+ const compiled = [];
23
+ for (const r of GITLEAKS_RULES) {
24
+ try {
25
+ compiled.push({ id: r.id, re: new LinearRegex(r.regex), keywords: r.keywords, entropy: r.entropy });
26
+ }
27
+ catch {
28
+ // A rule that does not compile under RE2 is skipped rather than crashing the gateway.
29
+ }
30
+ }
31
+ RULES = compiled;
32
+ STOPWORDS = GITLEAKS_STOPWORDS.map((s) => s.toLowerCase());
33
+ ALLOW = GITLEAKS_ALLOW_REGEXES.map((s) => {
34
+ try {
35
+ return new LinearRegex(s);
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }).filter((x) => x !== null);
41
+ return { compiled: compiled.length, total: GITLEAKS_RULES.length };
42
+ }
43
+ export function secretRulesReady() {
44
+ return RULES !== null;
45
+ }
46
+ function shannonBits(s) {
47
+ const freq = new Map();
48
+ for (const ch of s)
49
+ freq.set(ch, (freq.get(ch) ?? 0) + 1);
50
+ let h = 0;
51
+ for (const c of freq.values()) {
52
+ const p = c / s.length;
53
+ h -= p * Math.log2(p);
54
+ }
55
+ return h;
56
+ }
57
+ /** gitleaks' value-level false-positive layer: stopword substring, allow-regex, or below entropy. */
58
+ function isFalsePositive(value, ruleEntropy) {
59
+ const lower = value.toLowerCase();
60
+ if (STOPWORDS.some((sw) => lower.includes(sw)))
61
+ return true;
62
+ if (ALLOW.some((re) => re.test(value)))
63
+ return true;
64
+ if (ruleEntropy > 0 && shannonBits(value) < ruleEntropy)
65
+ return true;
66
+ return false;
67
+ }
68
+ /**
69
+ * Redact every detected secret in `input` with a typed placeholder `[REDACTED:<rule-id>]`. The
70
+ * delivered text never contains a detected secret value (SI-001). Returns the redacted text + the
71
+ * rules that fired. Returns the input unchanged if the rules were never compiled.
72
+ */
73
+ export function redactSecrets(input) {
74
+ if (!RULES)
75
+ return { text: input, findings: [] };
76
+ let text = input;
77
+ const findings = [];
78
+ const lowerContent = input.toLowerCase();
79
+ for (const rule of RULES) {
80
+ // Keyword pre-filter: skip a rule unless one of its keywords appears (gitleaks' fast path).
81
+ if (rule.keywords.length > 0 && !rule.keywords.some((k) => lowerContent.includes(k)))
82
+ continue;
83
+ // Collect every real-secret value this rule matches (scanning the whole text without a global
84
+ // flag, by advancing past each match).
85
+ const secrets = new Set();
86
+ let offset = 0;
87
+ let guard = 0;
88
+ while (offset < text.length && guard++ < 1000) {
89
+ const m = rule.re.exec(text.slice(offset));
90
+ if (!m || m.index === undefined)
91
+ break;
92
+ const value = (m[1] ?? m[0]) || "";
93
+ if (value && !isFalsePositive(value, rule.entropy))
94
+ secrets.add(value);
95
+ offset += m.index + Math.max(1, m[0].length);
96
+ }
97
+ for (const value of secrets) {
98
+ text = text.split(value).join(`[REDACTED:${rule.id}]`);
99
+ findings.push({ ruleId: rule.id });
100
+ }
101
+ }
102
+ return { text, findings };
103
+ }
104
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/detect/secrets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @cello-protocol/gateway — the CELLO security gateway.
3
+ *
4
+ * A separate program from the daemon. The daemon imports only the contract
5
+ * (`SecurityGatewayClient` + verdict types) and a client implementation; all detection lives
6
+ * here. M9-CORE-001 ships the seam with a pass-through; later stories add the pipeline.
7
+ */
8
+ export type { ScreenDirection, ScreenDisposition, GovernanceDisposition, GovernanceEvent, ScreenContext, ScreenVerdict, SecurityGatewayClient, } from "./types.js";
9
+ export { OutboundScreener } from "./screen/outbound.js";
10
+ export type { OutboundVerdict, OutboundScreenerOptions, OutboundScreenContext } from "./screen/outbound.js";
11
+ export { InboundScreener } from "./screen/inbound.js";
12
+ export type { InboundVerdict, InboundScreenerOptions } from "./screen/inbound.js";
13
+ export { initLinearRegex, linearRegexEngine, LinearRegex } from "./detect/linear-regex.js";
14
+ export { compileInjectionPatterns, scanInjectionPatterns, injectionPatternsReady } from "./detect/injection-patterns.js";
15
+ export { compileSecretRules, redactSecrets, secretRulesReady } from "./detect/secrets.js";
16
+ export type { SecretFinding, SecretScanResult } from "./detect/secrets.js";
17
+ export { screenInboundLanguage } from "./detect/language.js";
18
+ export type { LanguageVerdict, LanguageOptions, Script } from "./detect/language.js";
19
+ export { InjectionScanner, scoreToVerdict, BLOCK_THRESHOLD, FLAG_THRESHOLD } from "./detect/injection-scanner.js";
20
+ export type { InjectionClassifier, InjectionVerdict, ScanResult } from "./detect/injection-scanner.js";
21
+ export { isModelInstalled, installModel, verifyModel, sha256File } from "./detect/model-installer.js";
22
+ export type { InstallResult, InstallOptions } from "./detect/model-installer.js";
23
+ export { DEBERTA_MODEL } from "./detect/deberta-model-manifest.js";
24
+ export { GatewayConfigStore } from "./config/config-store.js";
25
+ export type { ConfigDirection, SetResult, ConfigVersionRow } from "./config/config-store.js";
26
+ export { GatewayRecordStore } from "./records/record-store.js";
27
+ export type { RecordDisposition, RecordDirection, RecordInput, SecurityRecord } from "./records/record-store.js";
28
+ export { GATEWAY_UNAVAILABLE, GOVERNANCE_TIMEOUT, failClosedVerdict } from "./types.js";
29
+ export { PassthroughGatewayClient } from "./passthrough.js";
30
+ export { SCREEN_OUTBOUND, SCREEN_INBOUND, encodeFrame, FrameDecoder, } from "./protocol.js";
31
+ export type { ScreenMethod, WireScreenRequest, WireScreenResponse } from "./protocol.js";
32
+ export { createGatewayServer } from "./server.js";
33
+ export type { GatewayScreenFn, GatewayServerOptions, GatewayServerHandle, GatewayLogger, } from "./server.js";
34
+ export { LocalSidecarGatewayClient } from "./client.js";
35
+ export type { LocalSidecarGatewayClientOptions } from "./client.js";
36
+ export { spawnGatewaySidecar, GATEWAY_READY_TOKEN } from "./spawn.js";
37
+ export type { SpawnGatewayOptions, SpawnedGateway } from "./spawn.js";
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,aAAa,EACb,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5G,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAIlF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACzH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAClH,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACtG,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACjH,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,EACL,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,GACd,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,gCAAgC,EAAE,MAAM,aAAa,CAAC;AAGpE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtE,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ // The composed inbound/outbound screens (the gateway runs these; M9-FEED-001 renders the verdict).
2
+ export { OutboundScreener } from "./screen/outbound.js";
3
+ export { InboundScreener } from "./screen/inbound.js";
4
+ // The RE2 linear-time regex engine (native re2 preferred, re2-wasm fallback) + the injection
5
+ // pattern scanner (M9-IN-001 Step-9). initLinearRegex() must be awaited once before use.
6
+ export { initLinearRegex, linearRegexEngine, LinearRegex } from "./detect/linear-regex.js";
7
+ export { compileInjectionPatterns, scanInjectionPatterns, injectionPatternsReady } from "./detect/injection-patterns.js";
8
+ export { compileSecretRules, redactSecrets, secretRulesReady } from "./detect/secrets.js";
9
+ export { screenInboundLanguage } from "./detect/language.js";
10
+ export { InjectionScanner, scoreToVerdict, BLOCK_THRESHOLD, FLAG_THRESHOLD } from "./detect/injection-scanner.js";
11
+ export { isModelInstalled, installModel, verifyModel, sha256File } from "./detect/model-installer.js";
12
+ export { DEBERTA_MODEL } from "./detect/deberta-model-manifest.js";
13
+ export { GatewayConfigStore } from "./config/config-store.js";
14
+ export { GatewayRecordStore } from "./records/record-store.js";
15
+ export { GATEWAY_UNAVAILABLE, GOVERNANCE_TIMEOUT, failClosedVerdict } from "./types.js";
16
+ export { PassthroughGatewayClient } from "./passthrough.js";
17
+ // Wire protocol (shared by the local sidecar; Phase 2's mTLS gateway reuses these shapes).
18
+ export { SCREEN_OUTBOUND, SCREEN_INBOUND, encodeFrame, FrameDecoder, } from "./protocol.js";
19
+ // The gateway server (the separate program) + the screen-function and logger seams.
20
+ export { createGatewayServer } from "./server.js";
21
+ // The daemon's local-sidecar adapter.
22
+ export { LocalSidecarGatewayClient } from "./client.js";
23
+ // Spawn the gateway as a child process (composition root + tests).
24
+ export { spawnGatewaySidecar, GATEWAY_READY_TOKEN } from "./spawn.js";
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,mGAAmG;AACnG,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,6FAA6F;AAC7F,yFAAyF;AACzF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACzH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAElH,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEtG,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,2FAA2F;AAC3F,OAAO,EACL,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,eAAe,CAAC;AAGvB,oFAAoF;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQlD,sCAAsC;AACtC,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAGxD,mEAAmE;AACnE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ScreenContext, ScreenVerdict, SecurityGatewayClient } from "./types.js";
2
+ /**
3
+ * The null-object gateway client: screens nothing, always allows.
4
+ *
5
+ * This is the daemon's default when no gateway is configured (backward compatibility for the
6
+ * many daemon/SNM tests written before M9, and for a deployment that has not enabled the
7
+ * security layer). It still RETURNS a verdict (`allow`) — so SI-001 ("never act on content
8
+ * without a verdict") holds even on the default path; "no gateway configured" means
9
+ * "always-allow verdict", not "no verdict".
10
+ *
11
+ * It contains no detection logic. Real screening lives in the gateway PROGRAM (the server +
12
+ * the local sidecar / remote client), never in the daemon.
13
+ */
14
+ export declare class PassthroughGatewayClient implements SecurityGatewayClient {
15
+ screenOutbound(content: Uint8Array, _ctx: ScreenContext): Promise<ScreenVerdict>;
16
+ screenInbound(content: Uint8Array, _ctx: ScreenContext): Promise<ScreenVerdict>;
17
+ }
18
+ //# sourceMappingURL=passthrough.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passthrough.d.ts","sourceRoot":"","sources":["../src/passthrough.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEtF;;;;;;;;;;;GAWG;AACH,qBAAa,wBAAyB,YAAW,qBAAqB;IAC9D,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAIhF,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;CAGtF"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The null-object gateway client: screens nothing, always allows.
3
+ *
4
+ * This is the daemon's default when no gateway is configured (backward compatibility for the
5
+ * many daemon/SNM tests written before M9, and for a deployment that has not enabled the
6
+ * security layer). It still RETURNS a verdict (`allow`) — so SI-001 ("never act on content
7
+ * without a verdict") holds even on the default path; "no gateway configured" means
8
+ * "always-allow verdict", not "no verdict".
9
+ *
10
+ * It contains no detection logic. Real screening lives in the gateway PROGRAM (the server +
11
+ * the local sidecar / remote client), never in the daemon.
12
+ */
13
+ export class PassthroughGatewayClient {
14
+ async screenOutbound(content, _ctx) {
15
+ return { disposition: "allow", content };
16
+ }
17
+ async screenInbound(content, _ctx) {
18
+ return { disposition: "allow", content };
19
+ }
20
+ }
21
+ //# sourceMappingURL=passthrough.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passthrough.js","sourceRoot":"","sources":["../src/passthrough.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,cAAc,CAAC,OAAmB,EAAE,IAAmB;QAC3D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAmB,EAAE,IAAmB;QAC1D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC3C,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The daemon ↔ gateway wire protocol.
3
+ *
4
+ * Framing: a 4-byte big-endian length prefix followed by a UTF-8 JSON payload. Content bytes
5
+ * ride as base64 inside the JSON (binary-safe over a text protocol). This is the local-sidecar
6
+ * transport (Unix domain socket); Phase 2 swaps the socket for mTLS but keeps these message
7
+ * shapes, so the remote gateway is a transport change, not a protocol change.
8
+ */
9
+ import type { ScreenDirection, ScreenDisposition, GovernanceEvent, GovernanceDecision } from "./types.js";
10
+ export declare const SCREEN_OUTBOUND = "screen_outbound";
11
+ export declare const SCREEN_INBOUND = "screen_inbound";
12
+ export type ScreenMethod = typeof SCREEN_OUTBOUND | typeof SCREEN_INBOUND;
13
+ /** A screen request on the wire. `content` is base64. */
14
+ export interface WireScreenRequest {
15
+ id: number;
16
+ method: ScreenMethod;
17
+ content: string;
18
+ ctx: {
19
+ direction: ScreenDirection;
20
+ agentName: string;
21
+ sessionId: string;
22
+ correlationId?: string;
23
+ /** The agent's governance re-send decisions, keyed by flagId (M9-FEED-001 §6). Outbound only. */
24
+ governanceDecisions?: Record<string, GovernanceDecision>;
25
+ };
26
+ }
27
+ /** A screen response on the wire. `content` is base64, present ONLY when the gateway transformed it. */
28
+ export interface WireScreenResponse {
29
+ id: number;
30
+ verdict: {
31
+ disposition: ScreenDisposition;
32
+ content?: string;
33
+ reason?: string;
34
+ guidance?: string;
35
+ /** Governance findings — plain JSON, carried verbatim (M9-FEED-001 renders them). */
36
+ events?: GovernanceEvent[];
37
+ /** A content-rejection block (vs a transient fail-closed one). See ScreenVerdict.terminal. */
38
+ terminal?: boolean;
39
+ };
40
+ }
41
+ /** Encode an object as a length-prefixed JSON frame. */
42
+ export declare function encodeFrame(obj: unknown): Buffer;
43
+ /**
44
+ * A stateful decoder for length-prefixed JSON frames arriving as arbitrary socket chunks.
45
+ * Feed it each chunk; it invokes `onFrame` for every complete frame. `onError` fires on a
46
+ * frame that exceeds MAX_FRAME_BYTES or fails to parse — the caller should drop the connection.
47
+ */
48
+ export declare class FrameDecoder {
49
+ #private;
50
+ constructor(onFrame: (obj: unknown) => void, onError: (err: Error) => void);
51
+ push(chunk: Buffer): void;
52
+ }
53
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE1G,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,MAAM,MAAM,YAAY,GAAG,OAAO,eAAe,GAAG,OAAO,cAAc,CAAC;AAE1E,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE;QACH,SAAS,EAAE,eAAe,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,iGAAiG;QACjG,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;KAC1D,CAAC;CACH;AAED,wGAAwG;AACxG,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE;QACP,WAAW,EAAE,iBAAiB,CAAC;QAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,qFAAqF;QACrF,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;QAC3B,8FAA8F;QAC9F,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;CACH;AAOD,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAMhD;AAED;;;;GAIG;AACH,qBAAa,YAAY;;gBAKX,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI;IAK1E,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAoB1B"}