@aimarket/warden 0.21.0 → 0.22.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 (126) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README-es.md +8 -7
  3. package/README-fr.md +8 -7
  4. package/README-ru.md +8 -7
  5. package/README-zh.md +8 -7
  6. package/README.md +8 -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/flow-guard-answer.d.ts +29 -0
  12. package/dist/flow-guard-answer.d.ts.map +1 -0
  13. package/dist/flow-guard-answer.js +201 -0
  14. package/dist/flow-guard-answer.js.map +1 -0
  15. package/dist/flow-guard-classify.d.ts +14 -0
  16. package/dist/flow-guard-classify.d.ts.map +1 -0
  17. package/dist/flow-guard-classify.js +224 -0
  18. package/dist/flow-guard-classify.js.map +1 -0
  19. package/dist/flow-guard-decode.d.ts +17 -0
  20. package/dist/flow-guard-decode.d.ts.map +1 -0
  21. package/dist/flow-guard-decode.js +149 -0
  22. package/dist/flow-guard-decode.js.map +1 -0
  23. package/dist/flow-guard-destinations.d.ts +23 -0
  24. package/dist/flow-guard-destinations.d.ts.map +1 -0
  25. package/dist/flow-guard-destinations.js +158 -0
  26. package/dist/flow-guard-destinations.js.map +1 -0
  27. package/dist/flow-guard-fingerprints.d.ts +27 -0
  28. package/dist/flow-guard-fingerprints.d.ts.map +1 -0
  29. package/dist/flow-guard-fingerprints.js +164 -0
  30. package/dist/flow-guard-fingerprints.js.map +1 -0
  31. package/dist/flow-guard-fragments.d.ts +17 -0
  32. package/dist/flow-guard-fragments.d.ts.map +1 -0
  33. package/dist/flow-guard-fragments.js +122 -0
  34. package/dist/flow-guard-fragments.js.map +1 -0
  35. package/dist/flow-guard-instructions.d.ts +12 -0
  36. package/dist/flow-guard-instructions.d.ts.map +1 -0
  37. package/dist/flow-guard-instructions.js +36 -0
  38. package/dist/flow-guard-instructions.js.map +1 -0
  39. package/dist/flow-guard-labels.d.ts +10 -0
  40. package/dist/flow-guard-labels.d.ts.map +1 -0
  41. package/dist/flow-guard-labels.js +55 -0
  42. package/dist/flow-guard-labels.js.map +1 -0
  43. package/dist/flow-guard-leak.d.ts +29 -0
  44. package/dist/flow-guard-leak.d.ts.map +1 -0
  45. package/dist/flow-guard-leak.js +135 -0
  46. package/dist/flow-guard-leak.js.map +1 -0
  47. package/dist/flow-guard-paths.d.ts +21 -0
  48. package/dist/flow-guard-paths.d.ts.map +1 -0
  49. package/dist/flow-guard-paths.js +72 -0
  50. package/dist/flow-guard-paths.js.map +1 -0
  51. package/dist/flow-guard-policy.d.ts +15 -0
  52. package/dist/flow-guard-policy.d.ts.map +1 -0
  53. package/dist/flow-guard-policy.js +179 -0
  54. package/dist/flow-guard-policy.js.map +1 -0
  55. package/dist/flow-guard-post.d.ts +6 -0
  56. package/dist/flow-guard-post.d.ts.map +1 -0
  57. package/dist/flow-guard-post.js +131 -0
  58. package/dist/flow-guard-post.js.map +1 -0
  59. package/dist/flow-guard-pre.d.ts +13 -0
  60. package/dist/flow-guard-pre.d.ts.map +1 -0
  61. package/dist/flow-guard-pre.js +335 -0
  62. package/dist/flow-guard-pre.js.map +1 -0
  63. package/dist/flow-guard-screen.d.ts +85 -0
  64. package/dist/flow-guard-screen.d.ts.map +1 -0
  65. package/dist/flow-guard-screen.js +558 -0
  66. package/dist/flow-guard-screen.js.map +1 -0
  67. package/dist/flow-guard-state.d.ts +12 -0
  68. package/dist/flow-guard-state.d.ts.map +1 -0
  69. package/dist/flow-guard-state.js +121 -0
  70. package/dist/flow-guard-state.js.map +1 -0
  71. package/dist/flow-guard-text.d.ts +9 -0
  72. package/dist/flow-guard-text.d.ts.map +1 -0
  73. package/dist/flow-guard-text.js +46 -0
  74. package/dist/flow-guard-text.js.map +1 -0
  75. package/dist/flow-guard-types.d.ts +154 -0
  76. package/dist/flow-guard-types.d.ts.map +1 -0
  77. package/dist/flow-guard-types.js +2 -0
  78. package/dist/flow-guard-types.js.map +1 -0
  79. package/dist/flow-guard.d.ts +20 -394
  80. package/dist/flow-guard.d.ts.map +1 -1
  81. package/dist/flow-guard.js +26 -2522
  82. package/dist/flow-guard.js.map +1 -1
  83. package/dist/mcp-client.d.ts +1 -2
  84. package/dist/mcp-client.d.ts.map +1 -1
  85. package/dist/mcp-client.js +2 -19
  86. package/dist/mcp-client.js.map +1 -1
  87. package/dist/public-address.d.ts +3 -0
  88. package/dist/public-address.d.ts.map +1 -0
  89. package/dist/public-address.js +58 -0
  90. package/dist/public-address.js.map +1 -0
  91. package/dist/review-diff.d.ts +3 -3
  92. package/dist/review-diff.d.ts.map +1 -1
  93. package/dist/review-diff.js +3 -5
  94. package/dist/review-diff.js.map +1 -1
  95. package/dist/wrap-cli.d.ts.map +1 -1
  96. package/dist/wrap-cli.js +2 -1
  97. package/dist/wrap-cli.js.map +1 -1
  98. package/dist/wrap-state.d.ts +3 -1
  99. package/dist/wrap-state.d.ts.map +1 -1
  100. package/dist/wrap-state.js +18 -3
  101. package/dist/wrap-state.js.map +1 -1
  102. package/dist/wrap.d.ts.map +1 -1
  103. package/dist/wrap.js +45 -7
  104. package/dist/wrap.js.map +1 -1
  105. package/docs/flow-guard-model-comparison-2026-10-25.es.md +82 -0
  106. package/docs/flow-guard-model-comparison-2026-10-25.fr.md +82 -0
  107. package/docs/flow-guard-model-comparison-2026-10-25.md +82 -0
  108. package/docs/flow-guard-model-comparison-2026-10-25.ru.md +82 -0
  109. package/docs/flow-guard-model-comparison-2026-10-25.zh.md +82 -0
  110. package/docs/flow-guard.es.md +34 -4
  111. package/docs/flow-guard.fr.md +34 -4
  112. package/docs/flow-guard.md +41 -4
  113. package/docs/flow-guard.ru.md +40 -4
  114. package/docs/flow-guard.zh.md +34 -4
  115. package/docs/scan-limits.es.md +39 -0
  116. package/docs/scan-limits.fr.md +39 -0
  117. package/docs/scan-limits.md +39 -0
  118. package/docs/scan-limits.ru.md +39 -0
  119. package/docs/scan-limits.zh.md +39 -0
  120. package/docs/scan.es.md +2 -0
  121. package/docs/scan.fr.md +2 -0
  122. package/docs/scan.md +2 -0
  123. package/docs/scan.ru.md +2 -0
  124. package/docs/scan.zh.md +2 -0
  125. package/native/macos/Sources/WardenDesktop/NativeSurface.swift +1 -1
  126. package/package.json +4 -4
@@ -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"}
@@ -0,0 +1,164 @@
1
+ /** Flow guard: fingerprints of what the session read (private text, personal numbers, credentials) and the secret formats it knows. */
2
+ import { createHash } from 'node:crypto';
3
+ import { MAX_TEXT } from './flow-guard-text.js';
4
+ export const WINDOW = 20;
5
+ const STRIDE = 4;
6
+ // Credentials are fingerprinted again in short windows of their letters and digits only, so a piece of a key, or the
7
+ // key with separators between its characters, is still recognised. The sizes are the smallest at which none of 480
8
+ // made-up keys in eight formats matched anywhere in 100 million letters and digits of ordinary text
9
+ // (scripts/redteam/window-collisions.mjs): 8 for keys of letters and digits, 10 for hex keys, whose characters carry
10
+ // half the information and which share their alphabet with every hash and address in the text around them.
11
+ const TOKEN_WINDOW = 8;
12
+ const HEX_TOKEN_WINDOW = 10;
13
+ export const TOKEN_WINDOWS = [TOKEN_WINDOW, HEX_TOKEN_WINDOW];
14
+ const NORMALIZED_CREDENTIAL_PREFIX = /^(?:[rs]k(?:live|test)|skantapi[0-9]+|skant|skproj|sk|gh[pousr]|githubpat|glpat|npm|xox[abprs]|akia|asia|aiza)/;
15
+ // Text every key of a kind shares, so it is no piece of any one key: the RSA, EC and signature algorithm
16
+ // identifiers of DER keys and certificates, in letters and digits.
17
+ export const KEY_STRUCTURE = ['anbgkqhkig9w0baqefaa', 'a0gcsqgsib3dqebcwua', 'a0gcsqgsib3dqebbquaa', 'byqgsm49ageg', 'ccqgsm49aweh', 'bsubbaaiq', 'mcowbqydk2vw', 'mcowbqydk2vu'];
18
+ export function normalizeText(s) {
19
+ return s.normalize('NFKC').toLowerCase().replace(/\s+/g, '');
20
+ }
21
+ export function fpHash(window) {
22
+ return createHash('sha256').update(window).digest('hex').slice(0, 12);
23
+ }
24
+ /** Windows of the private text at every STRIDE-th position: any leaked run of WINDOW+STRIDE-1 normalized chars hits one. */
25
+ export function fingerprints(text) {
26
+ const n = normalizeText(text.slice(0, MAX_TEXT));
27
+ const out = new Set();
28
+ for (let i = 0; i + WINDOW <= n.length; i += STRIDE) {
29
+ const w = n.slice(i, i + WINDOW);
30
+ if (/^(.)\1+$/.test(w) || /^[0-9]+$/.test(w))
31
+ continue;
32
+ out.add(fpHash(w));
33
+ }
34
+ return [...out];
35
+ }
36
+ // Short structured values a 20-character window misses: card, passport, account and phone numbers.
37
+ // Words are split on whitespace; consecutive words that carry digits ("DE89 3704 0044", "+1 (555) 123-4567")
38
+ // join into one value, and a word without digits ends it.
39
+ const DATE_LIKE = /^(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{0,6}$/;
40
+ export function piiTokens(text) {
41
+ const out = new Set();
42
+ const flush = (group) => {
43
+ const t = group.join('').replace(/[^a-z0-9]/gi, '').toLowerCase();
44
+ const digits = (t.match(/\d/g) || []).length;
45
+ if (t.length < 8 || t.length > 34 || digits < 5 || DATE_LIKE.test(t))
46
+ return;
47
+ if (/^\d+$/.test(t) && t.length < 9)
48
+ return;
49
+ out.add(t);
50
+ };
51
+ let group = [];
52
+ for (const word of text.slice(0, MAX_TEXT).split(/\s+/)) {
53
+ const bare = word.replace(/^[^A-Za-z0-9+(]+|[^A-Za-z0-9)]+$/g, '');
54
+ if (/\d/.test(bare) && /^[A-Za-z0-9+()./-]+$/.test(bare)) {
55
+ group.push(bare);
56
+ continue;
57
+ }
58
+ if (group.length) {
59
+ flush(group);
60
+ group = [];
61
+ }
62
+ }
63
+ if (group.length)
64
+ flush(group);
65
+ return [...out];
66
+ }
67
+ const SECRET_PATTERNS = [
68
+ ['private key', /-----BEGIN [A-Z ]*PRIVATE KEY-----/],
69
+ ['AWS access key', /\b(AKIA|ASIA)[0-9A-Z]{16}\b/],
70
+ ['GitHub token', /\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,}\b|\bgithub_pat_[A-Za-z0-9_]{60,}/],
71
+ ['GitLab token', /\bglpat-[A-Za-z0-9_-]{20,}/],
72
+ ['Slack token', /\bxox[abprs]-[A-Za-z0-9-]{10,}/],
73
+ ['npm token', /\bnpm_[A-Za-z0-9]{36}\b/],
74
+ ['API key', /\bsk-(ant-)?[A-Za-z0-9_-]{20,}/],
75
+ ['Google API key', /\bAIza[0-9A-Za-z_-]{35}\b/],
76
+ ];
77
+ export function secretPattern(texts) {
78
+ for (const t of texts)
79
+ for (const [name, re] of SECRET_PATTERNS)
80
+ if (re.test(t))
81
+ return name;
82
+ return undefined;
83
+ }
84
+ // Cyrillic and Greek letters that look like Latin ones: a key retyped with them is the same key to a reader.
85
+ export const CONFUSABLE = {
86
+ а: 'a', в: 'b', е: 'e', ё: 'e', к: 'k', м: 'm', н: 'h', о: 'o', р: 'p', с: 'c', т: 't', у: 'y', х: 'x', і: 'i', ј: 'j', ѕ: 's', ԁ: 'd', ԛ: 'q', ԝ: 'w',
87
+ α: 'a', β: 'b', ε: 'e', η: 'n', ι: 'i', κ: 'k', ν: 'v', ο: 'o', ρ: 'p', τ: 't', υ: 'u', χ: 'x', γ: 'y', ζ: 'z',
88
+ };
89
+ /** Letters and digits only, lower-cased: separators, case, spacing and look-alike letters do not hide a key. */
90
+ export function alnum(s) {
91
+ return s.normalize('NFKC').toLowerCase().replace(/[^a-z0-9]/g, ch => CONFUSABLE[ch] ?? '');
92
+ }
93
+ function entropy(s) {
94
+ const counts = new Map();
95
+ for (const ch of s)
96
+ counts.set(ch, (counts.get(ch) ?? 0) + 1);
97
+ let h = 0;
98
+ for (const n of counts.values())
99
+ h -= (n / s.length) * Math.log2(n / s.length);
100
+ return h;
101
+ }
102
+ const TOKEN_RUN = /[A-Za-z0-9+/_-]{16,}={0,2}/g;
103
+ /** Key-like values in private text: every random-looking run of a credential file, and every well-known
104
+ * secret format wherever it was read. Words, paths and host names are not random enough to count. */
105
+ export function secretValues(text, credentialFile) {
106
+ const out = new Set();
107
+ const t = text.slice(0, MAX_TEXT);
108
+ const add = (raw) => {
109
+ // A base64 JSON object (a JWT's header or claims) is readable by anyone who holds the token; its signature,
110
+ // the run after the next dot, is the secret part and is kept.
111
+ if (raw.startsWith('eyJ'))
112
+ return;
113
+ const a = alnum(raw);
114
+ if (a.length >= 16 && /\d/.test(a) && /[a-z]/.test(a) && entropy(a) >= 3.5)
115
+ out.add(raw);
116
+ };
117
+ if (credentialFile)
118
+ for (const m of t.matchAll(TOKEN_RUN))
119
+ add(m[0]);
120
+ for (const [, re] of SECRET_PATTERNS)
121
+ for (const m of t.matchAll(new RegExp(re.source, 'g')))
122
+ add(m[0]);
123
+ return [...out];
124
+ }
125
+ /** Normalized credentials for the original strong-window check. Raw values exist only transiently. */
126
+ export function secretTokens(text, credentialFile) {
127
+ return [...new Set(secretValues(text, credentialFile).map(alnum))];
128
+ }
129
+ /** Known providers' alphabetic payload prefixes are still secret: do not skip them merely because the first
130
+ * digit comes late. Keep every previously indexed window. Generic values retain the old conservative start:
131
+ * public word-based environment values ending in a year must not gain new hard-denial substrings. */
132
+ export function tokenFingerprintStart(a) {
133
+ const leading = /^[a-z]*/.exec(a)[0].length;
134
+ if (/^(mii|mig|mhc|mc4|mco)/.test(a))
135
+ return Math.max(48, leading);
136
+ const prefix = NORMALIZED_CREDENTIAL_PREFIX.exec(a)?.[0];
137
+ return prefix ? Math.min(leading, prefix.length) : leading;
138
+ }
139
+ /** Windows hold both a letter and a digit; alphabetic-only words are not strong credential evidence.
140
+ * Public format/DER structure is excluded. The 8/10-character thresholds and stored hash format are unchanged. */
141
+ export function tokenFingerprints(tokens) {
142
+ const out = new Set();
143
+ for (const a of tokens) {
144
+ const size = /^[0-9a-f]+$/.test(a) ? HEX_TOKEN_WINDOW : TOKEN_WINDOW;
145
+ const start = tokenFingerprintStart(a);
146
+ for (let i = start; i + size <= a.length; i++) {
147
+ const w = a.slice(i, i + size);
148
+ if (/\d/.test(w) && /[a-z]/.test(w) && !KEY_STRUCTURE.some(k => k.includes(w)))
149
+ out.add(fpHash(w));
150
+ }
151
+ }
152
+ return [...out];
153
+ }
154
+ /** Every window of letters and digits of both token sizes, forwards and backwards: what a call is checked by. */
155
+ export function tokenWindows(text) {
156
+ const out = [];
157
+ for (const a of [alnum(text), alnum([...text].reverse().join(''))]) {
158
+ for (const size of TOKEN_WINDOWS)
159
+ for (let i = 0; i + size <= a.length; i++)
160
+ out.push(fpHash(a.slice(i, i + size)));
161
+ }
162
+ return out;
163
+ }
164
+ //# sourceMappingURL=flow-guard-fingerprints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-fingerprints.js","sourceRoot":"","sources":["../src/flow-guard-fingerprints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { FlowState, FragmentRecord } from './flow-guard-types.js';
2
+ export declare const MAX_FRAGMENT_INDEX = 16384;
3
+ export declare const MAX_FRAGMENT_SEEN = 256;
4
+ export declare const fragmentKey: (r: FragmentRecord) => string;
5
+ export declare const SHORT_SIZES: readonly [5, 6, 7];
6
+ /** Weak evidence asks before its first transmission, never silently learns by sending it.
7
+ * Five-char windows require upper/lower/digit classes in the source, while 6/7-char atoms may be words.
8
+ * Exact prefix-boundary slices cover chunks that already contain payload but no full six-char window.
9
+ * Only hash/offset/size metadata is persisted; public format and DER structure alone do not count. */
10
+ export declare function fragmentFingerprints(tokens: readonly string[], limit?: number): FragmentRecord[];
11
+ /** Must run under the session lock when remembering evidence. Audit never consumes or whitelists a match. */
12
+ export declare function checkFragments(input: Record<string, unknown>, state: FlowState, hasLegacyTokens: boolean, remember: boolean): {
13
+ secret?: string;
14
+ review?: boolean;
15
+ unavailable?: boolean;
16
+ };
17
+ //# sourceMappingURL=flow-guard-fragments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-guard-fragments.d.ts","sourceRoot":"","sources":["../src/flow-guard-fragments.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAMvE,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAGrC,eAAO,MAAM,WAAW,GAAI,GAAG,cAAc,WAA8F,CAAC;AAG5I,eAAO,MAAM,WAAW,oBAAqB,CAAC;AAE9C;;;sGAGsG;AACtG,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,SAAqB,GAAG,cAAc,EAAE,CA6B5G;AA+BD,6GAA6G;AAC7G,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAwB1L"}