@aimarket/warden 0.21.0 → 0.22.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 (212) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README-es.md +24 -7
  3. package/README-fr.md +24 -7
  4. package/README-ru.md +24 -7
  5. package/README-zh.md +24 -7
  6. package/README.md +24 -7
  7. package/dist/annotation-review.d.ts +10 -0
  8. package/dist/annotation-review.d.ts.map +1 -0
  9. package/dist/annotation-review.js +36 -0
  10. package/dist/annotation-review.js.map +1 -0
  11. package/dist/answer-gate.d.ts +94 -0
  12. package/dist/answer-gate.d.ts.map +1 -0
  13. package/dist/answer-gate.js +234 -0
  14. package/dist/answer-gate.js.map +1 -0
  15. package/dist/atomic-screen.d.ts.map +1 -1
  16. package/dist/classifier.d.ts +2 -2
  17. package/dist/classifier.d.ts.map +1 -1
  18. package/dist/claude-hook.js.map +1 -1
  19. package/dist/declare.d.ts.map +1 -1
  20. package/dist/declare.js.map +1 -1
  21. package/dist/flow-guard-answer.d.ts +30 -0
  22. package/dist/flow-guard-answer.d.ts.map +1 -0
  23. package/dist/flow-guard-answer.js +228 -0
  24. package/dist/flow-guard-answer.js.map +1 -0
  25. package/dist/flow-guard-classify.d.ts +14 -0
  26. package/dist/flow-guard-classify.d.ts.map +1 -0
  27. package/dist/flow-guard-classify.js +224 -0
  28. package/dist/flow-guard-classify.js.map +1 -0
  29. package/dist/flow-guard-constraints.d.ts +43 -0
  30. package/dist/flow-guard-constraints.d.ts.map +1 -0
  31. package/dist/flow-guard-constraints.js +69 -0
  32. package/dist/flow-guard-constraints.js.map +1 -0
  33. package/dist/flow-guard-decode.d.ts +17 -0
  34. package/dist/flow-guard-decode.d.ts.map +1 -0
  35. package/dist/flow-guard-decode.js +149 -0
  36. package/dist/flow-guard-decode.js.map +1 -0
  37. package/dist/flow-guard-destinations.d.ts +23 -0
  38. package/dist/flow-guard-destinations.d.ts.map +1 -0
  39. package/dist/flow-guard-destinations.js +158 -0
  40. package/dist/flow-guard-destinations.js.map +1 -0
  41. package/dist/flow-guard-fingerprints.d.ts +27 -0
  42. package/dist/flow-guard-fingerprints.d.ts.map +1 -0
  43. package/dist/flow-guard-fingerprints.js +164 -0
  44. package/dist/flow-guard-fingerprints.js.map +1 -0
  45. package/dist/flow-guard-fragments.d.ts +17 -0
  46. package/dist/flow-guard-fragments.d.ts.map +1 -0
  47. package/dist/flow-guard-fragments.js +122 -0
  48. package/dist/flow-guard-fragments.js.map +1 -0
  49. package/dist/flow-guard-instructions.d.ts +12 -0
  50. package/dist/flow-guard-instructions.d.ts.map +1 -0
  51. package/dist/flow-guard-instructions.js +36 -0
  52. package/dist/flow-guard-instructions.js.map +1 -0
  53. package/dist/flow-guard-labels.d.ts +10 -0
  54. package/dist/flow-guard-labels.d.ts.map +1 -0
  55. package/dist/flow-guard-labels.js +55 -0
  56. package/dist/flow-guard-labels.js.map +1 -0
  57. package/dist/flow-guard-leak.d.ts +29 -0
  58. package/dist/flow-guard-leak.d.ts.map +1 -0
  59. package/dist/flow-guard-leak.js +135 -0
  60. package/dist/flow-guard-leak.js.map +1 -0
  61. package/dist/flow-guard-paths.d.ts +21 -0
  62. package/dist/flow-guard-paths.d.ts.map +1 -0
  63. package/dist/flow-guard-paths.js +72 -0
  64. package/dist/flow-guard-paths.js.map +1 -0
  65. package/dist/flow-guard-policy.d.ts +15 -0
  66. package/dist/flow-guard-policy.d.ts.map +1 -0
  67. package/dist/flow-guard-policy.js +179 -0
  68. package/dist/flow-guard-policy.js.map +1 -0
  69. package/dist/flow-guard-post.d.ts +6 -0
  70. package/dist/flow-guard-post.d.ts.map +1 -0
  71. package/dist/flow-guard-post.js +131 -0
  72. package/dist/flow-guard-post.js.map +1 -0
  73. package/dist/flow-guard-pre.d.ts +13 -0
  74. package/dist/flow-guard-pre.d.ts.map +1 -0
  75. package/dist/flow-guard-pre.js +335 -0
  76. package/dist/flow-guard-pre.js.map +1 -0
  77. package/dist/flow-guard-screen.d.ts +85 -0
  78. package/dist/flow-guard-screen.d.ts.map +1 -0
  79. package/dist/flow-guard-screen.js +558 -0
  80. package/dist/flow-guard-screen.js.map +1 -0
  81. package/dist/flow-guard-state.d.ts +12 -0
  82. package/dist/flow-guard-state.d.ts.map +1 -0
  83. package/dist/flow-guard-state.js +129 -0
  84. package/dist/flow-guard-state.js.map +1 -0
  85. package/dist/flow-guard-text.d.ts +9 -0
  86. package/dist/flow-guard-text.d.ts.map +1 -0
  87. package/dist/flow-guard-text.js +46 -0
  88. package/dist/flow-guard-text.js.map +1 -0
  89. package/dist/flow-guard-types.d.ts +162 -0
  90. package/dist/flow-guard-types.d.ts.map +1 -0
  91. package/dist/flow-guard-types.js +2 -0
  92. package/dist/flow-guard-types.js.map +1 -0
  93. package/dist/flow-guard.d.ts +22 -394
  94. package/dist/flow-guard.d.ts.map +1 -1
  95. package/dist/flow-guard.js +27 -2522
  96. package/dist/flow-guard.js.map +1 -1
  97. package/dist/histor.js.map +1 -1
  98. package/dist/index.d.ts +4 -0
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +2 -0
  101. package/dist/index.js.map +1 -1
  102. package/dist/jcs.d.ts.map +1 -1
  103. package/dist/jcs.js.map +1 -1
  104. package/dist/mcp-client.d.ts +1 -2
  105. package/dist/mcp-client.d.ts.map +1 -1
  106. package/dist/mcp-client.js +2 -19
  107. package/dist/mcp-client.js.map +1 -1
  108. package/dist/mcp-rpc.js.map +1 -1
  109. package/dist/mcp-tools.d.ts.map +1 -1
  110. package/dist/mcp-tools.js.map +1 -1
  111. package/dist/mtl.d.ts +1 -1
  112. package/dist/mtl.d.ts.map +1 -1
  113. package/dist/mtl.js.map +1 -1
  114. package/dist/origin.d.ts.map +1 -1
  115. package/dist/pin-store.d.ts.map +1 -1
  116. package/dist/pin-store.js.map +1 -1
  117. package/dist/pinning.d.ts.map +1 -1
  118. package/dist/pinning.js.map +1 -1
  119. package/dist/public-address.d.ts +3 -0
  120. package/dist/public-address.d.ts.map +1 -0
  121. package/dist/public-address.js +58 -0
  122. package/dist/public-address.js.map +1 -0
  123. package/dist/review-diff.d.ts +3 -3
  124. package/dist/review-diff.d.ts.map +1 -1
  125. package/dist/review-diff.js +3 -5
  126. package/dist/review-diff.js.map +1 -1
  127. package/dist/sandbox.d.ts.map +1 -1
  128. package/dist/sanitize.js.map +1 -1
  129. package/dist/scan-lock.d.ts.map +1 -1
  130. package/dist/scan-lock.js.map +1 -1
  131. package/dist/scan.d.ts.map +1 -1
  132. package/dist/scan.js.map +1 -1
  133. package/dist/static-scan.d.ts.map +1 -1
  134. package/dist/static-scan.js.map +1 -1
  135. package/dist/task-adapter.d.ts.map +1 -1
  136. package/dist/task-adapter.js.map +1 -1
  137. package/dist/threat-feed.d.ts.map +1 -1
  138. package/dist/threat-feed.js.map +1 -1
  139. package/dist/tool-list.js.map +1 -1
  140. package/dist/toxic-flow.js.map +1 -1
  141. package/dist/wrap-cli.d.ts +1 -1
  142. package/dist/wrap-cli.d.ts.map +1 -1
  143. package/dist/wrap-cli.js +2 -1
  144. package/dist/wrap-cli.js.map +1 -1
  145. package/dist/wrap-screen.js.map +1 -1
  146. package/dist/wrap-state.d.ts +3 -1
  147. package/dist/wrap-state.d.ts.map +1 -1
  148. package/dist/wrap-state.js +18 -3
  149. package/dist/wrap-state.js.map +1 -1
  150. package/dist/wrap-wire.d.ts.map +1 -1
  151. package/dist/wrap-wire.js.map +1 -1
  152. package/dist/wrap.d.ts.map +1 -1
  153. package/dist/wrap.js +45 -7
  154. package/dist/wrap.js.map +1 -1
  155. package/docs/flow-guard-answer-gate.es.md +53 -0
  156. package/docs/flow-guard-answer-gate.fr.md +53 -0
  157. package/docs/flow-guard-answer-gate.md +86 -0
  158. package/docs/flow-guard-answer-gate.ru.md +53 -0
  159. package/docs/flow-guard-answer-gate.zh.md +53 -0
  160. package/docs/flow-guard-constraint-evidence.es.md +76 -0
  161. package/docs/flow-guard-constraint-evidence.fr.md +76 -0
  162. package/docs/flow-guard-constraint-evidence.md +78 -0
  163. package/docs/flow-guard-constraint-evidence.ru.md +78 -0
  164. package/docs/flow-guard-constraint-evidence.zh.md +76 -0
  165. package/docs/flow-guard-final-witness-2026-10-26.es.md +24 -0
  166. package/docs/flow-guard-final-witness-2026-10-26.fr.md +24 -0
  167. package/docs/flow-guard-final-witness-2026-10-26.md +24 -0
  168. package/docs/flow-guard-final-witness-2026-10-26.ru.md +24 -0
  169. package/docs/flow-guard-final-witness-2026-10-26.zh.md +24 -0
  170. package/docs/flow-guard-fresh-rechecks-2026-10-26.es.md +39 -0
  171. package/docs/flow-guard-fresh-rechecks-2026-10-26.fr.md +39 -0
  172. package/docs/flow-guard-fresh-rechecks-2026-10-26.md +39 -0
  173. package/docs/flow-guard-fresh-rechecks-2026-10-26.ru.md +39 -0
  174. package/docs/flow-guard-fresh-rechecks-2026-10-26.zh.md +39 -0
  175. package/docs/flow-guard-model-comparison-2026-10-25.es.md +109 -0
  176. package/docs/flow-guard-model-comparison-2026-10-25.fr.md +109 -0
  177. package/docs/flow-guard-model-comparison-2026-10-25.md +109 -0
  178. package/docs/flow-guard-model-comparison-2026-10-25.ru.md +109 -0
  179. package/docs/flow-guard-model-comparison-2026-10-25.zh.md +109 -0
  180. package/docs/flow-guard-prospective-holdout-2026-10-26.es.md +30 -0
  181. package/docs/flow-guard-prospective-holdout-2026-10-26.fr.md +30 -0
  182. package/docs/flow-guard-prospective-holdout-2026-10-26.md +44 -0
  183. package/docs/flow-guard-prospective-holdout-2026-10-26.ru.md +44 -0
  184. package/docs/flow-guard-prospective-holdout-2026-10-26.zh.md +30 -0
  185. package/docs/flow-guard-review-factors-2026-10-26.es.md +41 -0
  186. package/docs/flow-guard-review-factors-2026-10-26.fr.md +41 -0
  187. package/docs/flow-guard-review-factors-2026-10-26.md +45 -0
  188. package/docs/flow-guard-review-factors-2026-10-26.ru.md +45 -0
  189. package/docs/flow-guard-review-factors-2026-10-26.zh.md +41 -0
  190. package/docs/flow-guard-structured-model-2026-10-26.es.md +35 -0
  191. package/docs/flow-guard-structured-model-2026-10-26.fr.md +35 -0
  192. package/docs/flow-guard-structured-model-2026-10-26.md +44 -0
  193. package/docs/flow-guard-structured-model-2026-10-26.ru.md +46 -0
  194. package/docs/flow-guard-structured-model-2026-10-26.zh.md +35 -0
  195. package/docs/flow-guard.es.md +54 -4
  196. package/docs/flow-guard.fr.md +54 -4
  197. package/docs/flow-guard.md +61 -4
  198. package/docs/flow-guard.ru.md +60 -4
  199. package/docs/flow-guard.zh.md +54 -4
  200. package/docs/scan-limits.es.md +39 -0
  201. package/docs/scan-limits.fr.md +39 -0
  202. package/docs/scan-limits.md +39 -0
  203. package/docs/scan-limits.ru.md +39 -0
  204. package/docs/scan-limits.zh.md +39 -0
  205. package/docs/scan.es.md +2 -0
  206. package/docs/scan.fr.md +2 -0
  207. package/docs/scan.md +2 -0
  208. package/docs/scan.ru.md +2 -0
  209. package/docs/scan.zh.md +2 -0
  210. package/examples/answer-gate-host.mjs +33 -0
  211. package/native/macos/Sources/WardenDesktop/NativeSurface.swift +1 -1
  212. package/package.json +6 -5
@@ -0,0 +1,69 @@
1
+ /** Optional host-supplied constraint evidence. No natural-language inference or permission grants. */
2
+ import { createHash } from 'node:crypto';
3
+ const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
4
+ const exact = (value, keys) => Object.keys(value).length === keys.length && keys.every(key => Object.hasOwn(value, key));
5
+ const scalar = (value) => typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value) && Math.abs(value) <= 1e12;
6
+ const id = (value) => typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/.test(value);
7
+ const field = (value) => typeof value === 'string' && /^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(value) && !['constructor', 'prototype'].includes(value);
8
+ const hash = (text) => createHash('sha256').update(text).digest('hex');
9
+ const same = (a, b) => typeof a === typeof b && a === b;
10
+ /** Fixed templates + finite scalars/positions only. No names, quotes, URLs or source-authored field labels. */
11
+ export function checkAnswerConstraints(value, answer, sessionId, turn) {
12
+ const empty = (status) => ({ status, violations: [], unknownReferences: 0, text: status === 'invalid' ? 'WARDEN: constraint evidence is unavailable because the host check did not validate. This is not a passed check.' : '' });
13
+ if (value === undefined)
14
+ return empty('absent');
15
+ if (!object(value) || !exact(value, ['schema', 'sessionId', 'turn', 'answerSha256', 'rules', 'records', 'claims']) || value.schema !== 'warden-answer-check/1' ||
16
+ value.sessionId !== sessionId || !Number.isSafeInteger(value.turn) || value.turn < 1 || value.turn !== turn || value.answerSha256 !== hash(answer) ||
17
+ !Array.isArray(value.rules) || !value.rules.length || value.rules.length > 16 || !Array.isArray(value.records) || !value.records.length || value.records.length > 256 || !object(value.claims))
18
+ return empty('invalid');
19
+ const rules = [];
20
+ for (const candidate of value.rules) {
21
+ if (!object(candidate) || !exact(candidate, ['field', 'op', 'value']) || !field(candidate.field) || typeof candidate.op !== 'string' || !['lte', 'gte', 'eq'].includes(candidate.op) || !scalar(candidate.value) || candidate.op !== 'eq' && typeof candidate.value !== 'number')
22
+ return empty('invalid');
23
+ rules.push(candidate);
24
+ }
25
+ const records = [];
26
+ const seen = new Set();
27
+ for (const candidate of value.records) {
28
+ if (!object(candidate) || !exact(candidate, ['id', 'attributes']) || !id(candidate.id) || seen.has(candidate.id) || !object(candidate.attributes) || Object.keys(candidate.attributes).length > 32 ||
29
+ !Object.entries(candidate.attributes).every(([key, entry]) => field(key) && scalar(entry)))
30
+ return empty('invalid');
31
+ records.push(candidate);
32
+ seen.add(candidate.id);
33
+ }
34
+ const claims = value.claims;
35
+ if (!exact(claims, ['selectedId', 'eligibleIds']) || !id(claims.selectedId) || !Array.isArray(claims.eligibleIds) || claims.eligibleIds.length > 128 || !claims.eligibleIds.every(id) || new Set(claims.eligibleIds).size !== claims.eligibleIds.length)
36
+ return empty('invalid');
37
+ // Stable facts identity is independent of selected claims and the generated answer.
38
+ const factsSha256 = hash(JSON.stringify({ rules, records: records.map(record => ({ id: record.id, attributes: Object.fromEntries(Object.entries(record.attributes).sort(([a], [b]) => a.localeCompare(b))) })) }));
39
+ const map = new Map(records.map(record => [record.id, record]));
40
+ const referenced = [...new Set([claims.selectedId, ...claims.eligibleIds])];
41
+ const violations = [];
42
+ let unknownReferences = 0;
43
+ for (const itemId of referenced) {
44
+ const record = map.get(itemId);
45
+ if (!record) {
46
+ unknownReferences++;
47
+ continue;
48
+ }
49
+ for (const [index, rule] of rules.entries()) {
50
+ if (!Object.hasOwn(record.attributes, rule.field)) {
51
+ unknownReferences++;
52
+ continue;
53
+ }
54
+ const actual = record.attributes[rule.field];
55
+ if (rule.op !== 'eq' && typeof actual !== 'number') {
56
+ unknownReferences++;
57
+ continue;
58
+ }
59
+ const passes = rule.op === 'eq' ? same(actual, rule.value) : rule.op === 'lte' ? actual <= rule.value : actual >= rule.value;
60
+ if (!passes)
61
+ violations.push({ item: records.indexOf(record) + 1, rule: index + 1, op: rule.op, limit: rule.value, actual });
62
+ }
63
+ }
64
+ const snippets = violations.slice(0, 8).map(v => `Source snapshot record #${v.item} (1-based source-record order, not claim-list order) violates rule #${v.rule}: actual ${v.actual}; required ${v.op === 'lte' ? '<=' : v.op === 'gte' ? '>=' : '==='} ${v.limit}.`);
65
+ const status = unknownReferences ? 'partial' : 'checked';
66
+ const text = snippets.length ? 'WARDEN constraint evidence (conditional on the host record snapshot): ' + snippets.join(' ') + (violations.length > 8 ? ` ${violations.length - 8} more contradictions recorded.` : '') + (unknownReferences ? ' Some references or fields are unknown; this is not a complete check.' : '') : unknownReferences ? 'WARDEN: some claimed items or rule fields are unknown. Constraint checking is incomplete, not passed.' : '';
67
+ return { status, factsSha256, violations, unknownReferences, text };
68
+ }
69
+ //# sourceMappingURL=flow-guard-constraints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-constraints.js","sourceRoot":"","sources":["../src/flow-guard-constraints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Flow guard: reversible spellings a value can hide in (URL, base64, hex, escapes, character lists, NATO), decoded into candidates. */
2
+ /** Only explicit character lists are decoded, never arbitrary prose. Unknown items end a run.
3
+ * English digit names and case markers cover the recorded attack, not arbitrary verbal encodings. */
4
+ export declare function spelledCandidates(text: string): string[];
5
+ /** Decimal scalar codes, in a contiguous explicit list. Unknown/invalid items terminate a run.
6
+ * Merely decoding public numbers does not block anything: existing secret/private fingerprints still decide. */
7
+ export declare function characterCodeCandidates(text: string): string[];
8
+ /** A small explicit spelling grammar, not a language model. Preserve explicit case for nested base64. */
9
+ export declare function natoCandidates(text: string): string[];
10
+ /** Reversible text encodings only: bounded breadth/depth, no eval or decompression. Exhaustion is explicit. */
11
+ export declare function scanCandidates(texts: readonly string[]): {
12
+ values: string[];
13
+ incomplete: boolean;
14
+ };
15
+ /** Compatibility helper: enforcement uses scanCandidates() so truncation is never mistaken for a clean scan. */
16
+ export declare function candidates(texts: readonly string[]): string[];
17
+ //# sourceMappingURL=flow-guard-decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-decode.d.ts","sourceRoot":"","sources":["../src/flow-guard-decode.ts"],"names":[],"mappings":"AAAA,wIAAwI;AAIxI;qGACqG;AACrG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAYxD;AAED;gHACgH;AAChH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAW9D;AASD,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAcrD;AAED,+GAA+G;AAC/G,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CA0ClG;AAED,gHAAgH;AAChH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAAyC"}
@@ -0,0 +1,149 @@
1
+ /** Flow guard: reversible spellings a value can hide in (URL, base64, hex, escapes, character lists, NATO), decoded into candidates. */
2
+ const MAX_CANDIDATE = 524_288;
3
+ /** Only explicit character lists are decoded, never arbitrary prose. Unknown items end a run.
4
+ * English digit names and case markers cover the recorded attack, not arbitrary verbal encodings. */
5
+ export function spelledCandidates(text) {
6
+ const digits = { zero: '0', one: '1', two: '2', three: '3', four: '4', five: '5', six: '6', seven: '7', eight: '8', nine: '9' };
7
+ const out = [];
8
+ let run = '';
9
+ const flush = () => { if (run.length >= 5)
10
+ out.push(run); run = ''; };
11
+ for (const item of text.slice(0, MAX_CANDIDATE).normalize('NFKC').split(/[,;|\r\n]+/)) {
12
+ const unit = item.trim().toLowerCase();
13
+ const ch = /^[a-z0-9]$/.test(unit) ? unit : (Object.hasOwn(digits, unit) ? digits[unit] : undefined) ?? /^(?:capital|uppercase|lowercase|letter) ([a-z])$/.exec(unit)?.[1];
14
+ if (ch)
15
+ run += ch;
16
+ else
17
+ flush();
18
+ }
19
+ flush();
20
+ return out;
21
+ }
22
+ /** Decimal scalar codes, in a contiguous explicit list. Unknown/invalid items terminate a run.
23
+ * Merely decoding public numbers does not block anything: existing secret/private fingerprints still decide. */
24
+ export function characterCodeCandidates(text) {
25
+ const out = [];
26
+ let run = '', count = 0;
27
+ const flush = () => { if (count >= 5)
28
+ out.push(run); run = ''; count = 0; };
29
+ for (const item of text.slice(0, MAX_CANDIDATE).normalize('NFKC').split(/[\s,;|[\]]+/)) {
30
+ if (!item)
31
+ continue;
32
+ const code = /^\d{1,7}$/.test(item) ? Number(item) : -1;
33
+ if (code >= 32 && code <= 0x10ffff && !(code >= 0x7f && code <= 0x9f) && !(code >= 0xd800 && code <= 0xdfff) || [9, 10, 13].includes(code)) {
34
+ run += String.fromCodePoint(code);
35
+ count++;
36
+ }
37
+ else
38
+ flush();
39
+ }
40
+ flush();
41
+ return out;
42
+ }
43
+ const NATO = Object.freeze(Object.fromEntries([
44
+ ...'alfa bravo charlie delta echo foxtrot golf hotel india juliett kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu'.split(' ').map((word, i) => [word, String.fromCharCode(97 + i)]),
45
+ ['alpha', 'a'], ['juliet', 'j'], ['x-ray', 'x'],
46
+ ['niner', '9'],
47
+ ...'zero one two three four five six seven eight nine'.split(' ').map((word, i) => [word, String(i)]),
48
+ ['underscore', '_'], ['hyphen', '-'], ['dash', '-'], ['slash', '/'], ['plus', '+'], ['equals', '='], ['dot', '.'],
49
+ ]));
50
+ /** A small explicit spelling grammar, not a language model. Preserve explicit case for nested base64. */
51
+ export function natoCandidates(text) {
52
+ const out = [];
53
+ let run = '', count = 0, marker = '';
54
+ const flush = () => { if (count >= 5)
55
+ out.push(run); run = ''; count = 0; marker = ''; };
56
+ for (const item of text.slice(0, MAX_CANDIDATE).normalize('NFKC').split(/[\s,;|]+/)) {
57
+ if (!item)
58
+ continue;
59
+ const unit = item.toLowerCase();
60
+ if (['capital', 'uppercase', 'lowercase', 'letter'].includes(unit)) {
61
+ if (marker)
62
+ flush();
63
+ marker = unit;
64
+ continue;
65
+ }
66
+ const ch = Object.hasOwn(NATO, unit) ? NATO[unit] : /^\d$/.test(unit) ? unit : undefined;
67
+ if (!ch || marker && !/^[a-z]$/.test(ch)) {
68
+ flush();
69
+ continue;
70
+ }
71
+ run += ['capital', 'uppercase'].includes(marker) ? ch.toUpperCase() : ch;
72
+ count++;
73
+ marker = '';
74
+ }
75
+ flush();
76
+ return out;
77
+ }
78
+ /** Reversible text encodings only: bounded breadth/depth, no eval or decompression. Exhaustion is explicit. */
79
+ export function scanCandidates(texts) {
80
+ const values = [], queue = [];
81
+ const seen = new Set();
82
+ let left = MAX_CANDIDATE, incomplete = false;
83
+ const push = (text, depth) => {
84
+ if (!text || seen.has(text))
85
+ return;
86
+ if (depth > 4 || values.length >= 64 || text.length > left) {
87
+ incomplete = true;
88
+ return;
89
+ }
90
+ seen.add(text);
91
+ left -= text.length;
92
+ values.push(text);
93
+ queue.push({ text, depth });
94
+ };
95
+ for (const text of texts) {
96
+ if (text.length > left) {
97
+ incomplete = true;
98
+ if (left)
99
+ push(text.slice(0, left), 0);
100
+ }
101
+ else
102
+ push(text, 0);
103
+ }
104
+ const utf8 = (bytes) => {
105
+ try {
106
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
107
+ return text && !/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(text) ? text : undefined;
108
+ }
109
+ catch {
110
+ return undefined;
111
+ }
112
+ };
113
+ for (let index = 0; index < queue.length; index++) {
114
+ const { text, depth } = queue[index];
115
+ const add = (value) => { if (value && value !== text)
116
+ push(value, depth + 1); };
117
+ if (/%[0-9a-f]{2}/i.test(text)) {
118
+ try {
119
+ add(decodeURIComponent(text.replace(/\+/g, ' ')));
120
+ }
121
+ catch { /* malformed literal, never executable */ }
122
+ }
123
+ for (const value of spelledCandidates(text))
124
+ add(value);
125
+ for (const value of characterCodeCandidates(text))
126
+ add(value);
127
+ for (const value of natoCandidates(text))
128
+ add(value);
129
+ const escaped = text.replace(/\\u\{([0-9a-f]{1,6})\}|\\u([0-9a-f]{4})|\\x([0-9a-f]{2})|&#(?:x([0-9a-f]+)|([0-9]+));/gi, (whole, a, b, c, d, e) => {
130
+ const code = Number.parseInt(a ?? b ?? c ?? d ?? e, e === undefined ? 16 : 10);
131
+ return code <= 0x10ffff && !(code >= 0xd800 && code <= 0xdfff) ? String.fromCodePoint(code) : whole;
132
+ });
133
+ add(escaped);
134
+ for (const m of text.matchAll(/[A-Za-z0-9+/_-]{8,}={0,2}/g)) {
135
+ const normalized = m[0].replace(/-/g, '+').replace(/_/g, '/').replace(/=+$/, '');
136
+ if (normalized.length % 4 === 1)
137
+ continue;
138
+ const bytes = Buffer.from(normalized, 'base64');
139
+ if (bytes.toString('base64').replace(/=+$/, '') === normalized)
140
+ add(utf8(bytes));
141
+ }
142
+ for (const m of text.matchAll(/\b(?:[0-9a-f]{2}){3,}\b/gi))
143
+ add(utf8(Buffer.from(m[0], 'hex')));
144
+ }
145
+ return { values, incomplete };
146
+ }
147
+ /** Compatibility helper: enforcement uses scanCandidates() so truncation is never mistaken for a clean scan. */
148
+ export function candidates(texts) { return scanCandidates(texts).values; }
149
+ //# sourceMappingURL=flow-guard-decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-decode.js","sourceRoot":"","sources":["../src/flow-guard-decode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /** Flow guard: who or what a call is aimed at, and whether the user named it. */
2
+ import type { FlowPolicy, FlowState } from './flow-guard-types.js';
3
+ export declare const MAX_RESOLVED = 200;
4
+ export declare const DEST_ARG_NAMES: Set<string>;
5
+ export declare function namesParty(input: Record<string, unknown>, texts: readonly string[]): boolean;
6
+ export declare function destinations(toolName: string, input: Record<string, unknown>, policy: FlowPolicy, hosts: readonly string[]): string[];
7
+ /**
8
+ * The operator named this tool's destination arguments and the call sets none of them: it acts on an
9
+ * existing relationship (change the amount of a standing order, not its payee), so no new party is reached.
10
+ * Unconfigured tools never qualify: without the operator's word, an absent argument proves nothing.
11
+ */
12
+ export declare function keepsDestination(toolName: string, input: Record<string, unknown>, policy: FlowPolicy): boolean;
13
+ /** Only structured records from explicitly configured contact tools may resolve a full display name.
14
+ * Arbitrary prose, YAML, capitalized words and local file reads cannot create authority. */
15
+ export declare function resolvedContacts(value: unknown, depth?: number): Array<{
16
+ v: string;
17
+ names: string[];
18
+ }>;
19
+ /** A URL mentioned in prose cannot stand in for an actual target argument. */
20
+ export declare function hasDestinationArgument(tool: string, input: Record<string, unknown>, policy: FlowPolicy): boolean;
21
+ export declare function allowedDestination(destination: string, patterns: readonly string[]): boolean;
22
+ export declare function namedByUser(dests: readonly string[], intent: readonly string[] | undefined, intentRaw?: readonly string[], resolved?: FlowState['resolved']): boolean;
23
+ //# sourceMappingURL=flow-guard-destinations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-destinations.d.ts","sourceRoot":"","sources":["../src/flow-guard-destinations.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKnE,eAAO,MAAM,YAAY,MAAM,CAAC;AAGhC,eAAO,MAAM,cAAc,aAGQ,CAAC;AAYpC,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI5F;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAmBrI;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAO9G;AASD;4FAC4F;AAC5F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiBjG;AASD,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAKhH;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAO5F;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,GAAG,OAAO,CAoBrK"}
@@ -0,0 +1,158 @@
1
+ import { globMatch, hostMatches } from './flow-guard-policy.js';
2
+ import { MAX_TEXT, hostsIn, strings } from './flow-guard-text.js';
3
+ import { normalizeText } from './flow-guard-fingerprints.js';
4
+ export const MAX_RESOLVED = 200;
5
+ // Who or what a call is aimed at. A destination the user named in their own words is the user's choice.
6
+ export const DEST_ARG_NAMES = new Set(['to', 'recipient', 'recipients', 'cc', 'bcc', 'email', 'emails', 'participants', 'user', 'users',
7
+ 'channel', 'url', 'urls', 'iban', 'account', 'address', 'phone', 'host', 'hostname', 'domain', 'webhook', 'endpoint',
8
+ 'attendee', 'attendees', 'invitee', 'invitees', 'assignee', 'assignees', 'reviewer', 'reviewers', 'collaborator', 'collaborators',
9
+ 'member', 'members', 'username']);
10
+ // The subset that names a party without doubt. On an unlabeled MCP tool one of these makes the call outbound;
11
+ // "user", "channel", "account" or "host" also name what a read looks at, so they do not.
12
+ const PARTY_ARG_NAMES = new Set(['to', 'recipient', 'recipients', 'cc', 'bcc', 'email', 'emails', 'participants', 'iban', 'phone',
13
+ 'webhook', 'endpoint', 'attendee', 'attendees', 'invitee', 'invitees', 'assignee', 'assignees', 'reviewer', 'reviewers',
14
+ 'collaborator', 'collaborators', 'member', 'members', 'username']);
15
+ // Bounded address parts and a fixed start prevent quadratic scans of long non-address payloads.
16
+ const EMAIL_RE = /(?<![a-z0-9._%+-])[a-z0-9._%+-]{1,64}@[a-z0-9.-]{1,253}\.[a-z]{2,63}\b/gi;
17
+ // A bare domain in text ("www.example.com/x"), limited to common TLDs so "file.txt" or "v1.2" do not count.
18
+ const BARE_DOMAIN_RE = /\b(?:www\.)?(?:[a-z0-9-]+\.)+(?:com|net|org|io|dev|ai|co|app|info|biz|xyz|me|us|uk|de|fr|es|it|nl|ru|cn|jp|in|br|eu|ch|se|no|fi|pl|cz|at|be|ca|au|nz|online|site|top|link|click|live|shop|store|tech|cloud|pro|tk|gq|ml|ga|cf|ly|gg|to|so|sh|cc|tv|ws)\b(?:\/[^\s"'<>)]*)?/gi;
19
+ const IBAN_RE = /\b[A-Z]{2}\d{2}(?:\s?[A-Z0-9]){10,30}\b/g;
20
+ export function namesParty(input, texts) {
21
+ const named = Object.entries(input).some(([k, v]) => PARTY_ARG_NAMES.has(k.toLowerCase()) &&
22
+ ((typeof v === 'string' && !!v.trim()) || typeof v === 'number' || (Array.isArray(v) && v.length > 0)));
23
+ return named || texts.some(t => new RegExp(EMAIL_RE.source, 'i').test(t) || new RegExp(IBAN_RE.source).test(t));
24
+ }
25
+ export function destinations(toolName, input, policy, hosts) {
26
+ const out = new Set(hosts);
27
+ const configured = Object.entries(policy.destinationArgs).find(([glob]) => globMatch(glob, toolName))?.[1];
28
+ const names = configured ? new Set(configured.map(n => n.toLowerCase())) : DEST_ARG_NAMES;
29
+ const add = (v) => {
30
+ if (typeof v === 'string' || typeof v === 'number') {
31
+ const t = String(v).trim();
32
+ if (t)
33
+ out.add(t);
34
+ }
35
+ else if (Array.isArray(v))
36
+ v.forEach(add);
37
+ else if (v && typeof v === 'object')
38
+ Object.values(v).forEach(add);
39
+ };
40
+ for (const [k, v] of Object.entries(input))
41
+ if (names.has(k.toLowerCase()))
42
+ add(v);
43
+ // Anything that names a place to reach, wherever it sits (a link in a message body is where the reader goes).
44
+ for (const t of strings(input)) {
45
+ for (const m of t.matchAll(EMAIL_RE))
46
+ out.add(m[0]);
47
+ for (const m of t.matchAll(IBAN_RE))
48
+ out.add(m[0]);
49
+ // A mailbox is one destination, not a separate grant to its provider's web host.
50
+ for (const m of t.matchAll(BARE_DOMAIN_RE))
51
+ if (t[(m.index ?? 0) - 1] !== '@')
52
+ out.add(m[0]);
53
+ }
54
+ for (const h of hostsIn(strings(input)))
55
+ out.add(h);
56
+ return [...new Set([...out].map(d => d.toLowerCase().replace(/^[a-z]+:\/\//, '').replace(/^www\./, '').replace(/\/+$/, '')))].filter(d => d.length >= 1);
57
+ }
58
+ /**
59
+ * The operator named this tool's destination arguments and the call sets none of them: it acts on an
60
+ * existing relationship (change the amount of a standing order, not its payee), so no new party is reached.
61
+ * Unconfigured tools never qualify: without the operator's word, an absent argument proves nothing.
62
+ */
63
+ export function keepsDestination(toolName, input, policy) {
64
+ const configured = Object.entries(policy.destinationArgs).find(([glob]) => globMatch(glob, toolName))?.[1];
65
+ if (!configured?.length)
66
+ return false;
67
+ // It must act on something that already exists, named by id: creating a new thing is not "keeping" a party.
68
+ const existing = Object.entries(input).some(([k, v]) => /(^|_)id$/i.test(k) && v !== undefined && v !== null && v !== '' && !configured.includes(k));
69
+ if (!existing)
70
+ return false;
71
+ return configured.every(name => { const v = input[name]; return v === undefined || v === null || v === '' || (Array.isArray(v) && v.length === 0); });
72
+ }
73
+ /** Every destination appears in what the user typed this session. Hosts match on the bare name too. */
74
+ /** A whole-word, case-insensitive match of `token` (length >= 3) in the user's raw prompt. */
75
+ function typedWord(token, raw) {
76
+ if (token.length < 3)
77
+ return false;
78
+ return new RegExp(`(^|[^\\p{L}\\p{N}])${token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}($|[^\\p{L}\\p{N}])`, 'iu').test(raw);
79
+ }
80
+ /** Only structured records from explicitly configured contact tools may resolve a full display name.
81
+ * Arbitrary prose, YAML, capitalized words and local file reads cannot create authority. */
82
+ export function resolvedContacts(value, depth = 0) {
83
+ if (depth > 8)
84
+ return [];
85
+ if (typeof value === 'string') {
86
+ if (value.length > MAX_TEXT)
87
+ return [];
88
+ try {
89
+ return resolvedContacts(JSON.parse(value), depth + 1);
90
+ }
91
+ catch {
92
+ return [];
93
+ }
94
+ }
95
+ if (Array.isArray(value))
96
+ return value.slice(0, MAX_RESOLVED).flatMap(v => resolvedContacts(v, depth + 1));
97
+ if (!value || typeof value !== 'object')
98
+ return [];
99
+ const record = value;
100
+ if (typeof record.name === 'string' && typeof record.email === 'string') {
101
+ const name = record.name.normalize('NFKC').trim().replace(/\s+/g, ' ').toLowerCase();
102
+ const email = record.email.trim().toLowerCase();
103
+ if (name.length >= 3 && name.length <= 200 && /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/.test(email))
104
+ return [{ v: email, names: [name] }];
105
+ return [];
106
+ }
107
+ // Common MCP envelopes only, not arbitrary nested notes or metadata.
108
+ return ['content', 'structuredContent', 'contacts', 'text'].flatMap(k => resolvedContacts(record[k], depth + 1));
109
+ }
110
+ function exactNamed(value, text) {
111
+ const escaped = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
112
+ // A full stop or comma that ends the sentence ends the value too ("send it to bob@corp.com."); one that goes on
113
+ // into more letters ("bob@corp.com.evil") does not.
114
+ return new RegExp(`(^|[^\\p{L}\\p{N}._%+@-])${escaped}($|[^\\p{L}\\p{N}._%+@-]|[.,](?=$|\\s))`, 'iu').test(text);
115
+ }
116
+ /** A URL mentioned in prose cannot stand in for an actual target argument. */
117
+ export function hasDestinationArgument(tool, input, policy) {
118
+ const configured = Object.entries(policy.destinationArgs).find(([glob]) => globMatch(glob, tool))?.[1];
119
+ const names = configured ? new Set(configured.map(n => n.toLowerCase())) : DEST_ARG_NAMES;
120
+ return Object.entries(input).some(([k, v]) => names.has(k.toLowerCase()) &&
121
+ ((typeof v === 'string' && !!v.trim()) || typeof v === 'number' || (Array.isArray(v) && v.length > 0)));
122
+ }
123
+ export function allowedDestination(destination, patterns) {
124
+ // Exact mailbox entries are possible; a host entry never authorizes every mailbox at that host.
125
+ if (destination.includes('@'))
126
+ return patterns.some(p => p.toLowerCase() === destination);
127
+ try {
128
+ const url = new URL(`https://${destination}`);
129
+ return !url.username && !url.password && hostMatches(url.hostname, patterns);
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ }
135
+ export function namedByUser(dests, intent, intentRaw, resolved) {
136
+ if (!dests.length || !intent?.length)
137
+ return false;
138
+ const raw = (intentRaw ?? []).join('\n');
139
+ // Contact authority applies to the exact mailbox, never to its provider's web host.
140
+ const viaContacts = dests.filter(d => d.includes('@') && (exactNamed(d, raw) || !!resolved?.some(r => r.v === d && r.names.some(n => typedWord(n, raw) && new Set(resolved.filter(other => other.names.includes(n)).map(other => other.v)).size === 1))));
141
+ return dests.every(d => {
142
+ if (viaContacts.includes(d))
143
+ return true;
144
+ // A bare number names an id only next to a word that says so ("file 13", "ID '13'", "#13"): in
145
+ // "June 13" it is a date. Short names ("Bob") must match a whole word.
146
+ if (/^\d+$/.test(d)) {
147
+ const re = new RegExp(`(\\bid\\b|\\bids\\b|\\bfile\\b|\\bnumber\\b|\\bno\\.|#|№)\\s*[:'"\\s]*${d}(?!\\d)`, 'iu');
148
+ return re.test(raw);
149
+ }
150
+ if (d.length < 6) {
151
+ const re = new RegExp(`(^|[^\\p{L}\\p{N}])${d.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}($|[^\\p{L}\\p{N}])`, 'iu');
152
+ return re.test(raw);
153
+ }
154
+ return exactNamed(d, raw) || (/^[a-z]{2}\d{2}[a-z0-9]{10,30}$/i.test(d) &&
155
+ [...raw.toUpperCase().matchAll(IBAN_RE)].some(m => normalizeText(m[0]) === d));
156
+ });
157
+ }
158
+ //# sourceMappingURL=flow-guard-destinations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-destinations.js","sourceRoot":"","sources":["../src/flow-guard-destinations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export declare const WINDOW = 20;
2
+ export declare const TOKEN_WINDOWS: readonly [8, 10];
3
+ export declare const KEY_STRUCTURE: string[];
4
+ export declare function normalizeText(s: string): string;
5
+ export declare function fpHash(window: string): string;
6
+ /** Windows of the private text at every STRIDE-th position: any leaked run of WINDOW+STRIDE-1 normalized chars hits one. */
7
+ export declare function fingerprints(text: string): string[];
8
+ export declare function piiTokens(text: string): string[];
9
+ export declare function secretPattern(texts: readonly string[]): string | undefined;
10
+ export declare const CONFUSABLE: Record<string, string>;
11
+ /** Letters and digits only, lower-cased: separators, case, spacing and look-alike letters do not hide a key. */
12
+ export declare function alnum(s: string): string;
13
+ /** Key-like values in private text: every random-looking run of a credential file, and every well-known
14
+ * secret format wherever it was read. Words, paths and host names are not random enough to count. */
15
+ export declare function secretValues(text: string, credentialFile: boolean): string[];
16
+ /** Normalized credentials for the original strong-window check. Raw values exist only transiently. */
17
+ export declare function secretTokens(text: string, credentialFile: boolean): string[];
18
+ /** Known providers' alphabetic payload prefixes are still secret: do not skip them merely because the first
19
+ * digit comes late. Keep every previously indexed window. Generic values retain the old conservative start:
20
+ * public word-based environment values ending in a year must not gain new hard-denial substrings. */
21
+ export declare function tokenFingerprintStart(a: string): number;
22
+ /** Windows hold both a letter and a digit; alphabetic-only words are not strong credential evidence.
23
+ * Public format/DER structure is excluded. The 8/10-character thresholds and stored hash format are unchanged. */
24
+ export declare function tokenFingerprints(tokens: readonly string[]): string[];
25
+ /** Every window of letters and digits of both token sizes, forwards and backwards: what a call is checked by. */
26
+ export declare function tokenWindows(text: string): string[];
27
+ //# sourceMappingURL=flow-guard-fingerprints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-fingerprints.d.ts","sourceRoot":"","sources":["../src/flow-guard-fingerprints.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,KAAK,CAAC;AASzB,eAAO,MAAM,aAAa,kBAA4C,CAAC;AAIvE,eAAO,MAAM,aAAa,UAAuJ,CAAC;AAElL,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,4HAA4H;AAC5H,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CASnD;AAMD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBhD;AAaD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAG1E;AAGD,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG7C,CAAC;AACF,gHAAgH;AAChH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvC;AAWD;qGACqG;AACrG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,EAAE,CAa5E;AAED,sGAAsG;AACtG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,EAAE,CAE5E;AAED;;qGAEqG;AACrG,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;kHACkH;AAClH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAWrE;AAED,iHAAiH;AACjH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnD"}