xaq-cli 0.0.0 → 0.1.0-nightly.72
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.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/admin-5gThRwgj.js +162 -0
- package/dist/admin-5gThRwgj.js.map +1 -0
- package/dist/admin-Btrm8mCd.js +218 -0
- package/dist/admin-Btrm8mCd.js.map +1 -0
- package/dist/admin-CWofnT_Q.js +2 -0
- package/dist/api-BFpElwqK.js +89 -0
- package/dist/api-BFpElwqK.js.map +1 -0
- package/dist/audit-BB7jK9Z5.js +2 -0
- package/dist/audit-BVYknW2i.js +79 -0
- package/dist/audit-BVYknW2i.js.map +1 -0
- package/dist/auth-CXmBdMqw.js +2 -0
- package/dist/auth-D-GmwNv-.js +550 -0
- package/dist/auth-D-GmwNv-.js.map +1 -0
- package/dist/brand--ZB8jTn1.js +32 -0
- package/dist/brand--ZB8jTn1.js.map +1 -0
- package/dist/bus-Cz0flS37.js +12 -0
- package/dist/bus-Cz0flS37.js.map +1 -0
- package/dist/bus-OKIGut72.js +2 -0
- package/dist/cli.js +234 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands-BNVLjYXA.js +167 -0
- package/dist/commands-BNVLjYXA.js.map +1 -0
- package/dist/commands-CdA6-WE7.js +112 -0
- package/dist/commands-CdA6-WE7.js.map +1 -0
- package/dist/config-C9XmYZWO.js +94 -0
- package/dist/config-C9XmYZWO.js.map +1 -0
- package/dist/config-CNVi0v5t.js +2 -0
- package/dist/connect-TtJ9n0Rw.js +362 -0
- package/dist/connect-TtJ9n0Rw.js.map +1 -0
- package/dist/content-C1lKMxFS.js +1170 -0
- package/dist/content-C1lKMxFS.js.map +1 -0
- package/dist/content-worker.js +28 -0
- package/dist/content-worker.js.map +1 -0
- package/dist/crypto-fv2fj3S8.js +75 -0
- package/dist/crypto-fv2fj3S8.js.map +1 -0
- package/dist/db-BEUEUPyP.js +561 -0
- package/dist/db-BEUEUPyP.js.map +1 -0
- package/dist/db-Q5BQuwga.js +2 -0
- package/dist/errors-FbMS3QBo.js +39 -0
- package/dist/errors-FbMS3QBo.js.map +1 -0
- package/dist/filter-Ck6OMxvu.js +158 -0
- package/dist/filter-Ck6OMxvu.js.map +1 -0
- package/dist/hermes-CKyzt1mH.js +3 -0
- package/dist/hermes-DHnDTYJp.js +1023 -0
- package/dist/hermes-DHnDTYJp.js.map +1 -0
- package/dist/import-DsN5NZT3.js +910 -0
- package/dist/import-DsN5NZT3.js.map +1 -0
- package/dist/instance-CwWbFbJ8.js +2 -0
- package/dist/instance-Dj9TpJB2.js +195 -0
- package/dist/instance-Dj9TpJB2.js.map +1 -0
- package/dist/listen-B9iO7HgQ.js +1568 -0
- package/dist/listen-B9iO7HgQ.js.map +1 -0
- package/dist/listen-CXVKG9XD.js +2 -0
- package/dist/manage-Bo6COB4p.js +477 -0
- package/dist/manage-Bo6COB4p.js.map +1 -0
- package/dist/manage-DoXqvjnU.js +2 -0
- package/dist/mcpheader-B8c5YO1B.js +2 -0
- package/dist/mcpheader-C9H4vudu.js +185 -0
- package/dist/mcpheader-C9H4vudu.js.map +1 -0
- package/dist/mcpsetup-BnHudwpq.js +2 -0
- package/dist/mcpsetup-DXXo2qjf.js +1053 -0
- package/dist/mcpsetup-DXXo2qjf.js.map +1 -0
- package/dist/node-check-CjTk6VNL.js +24 -0
- package/dist/node-check-CjTk6VNL.js.map +1 -0
- package/dist/paths-d-C2kdjo.js +2 -0
- package/dist/paths-yzOKD6ow.js +46 -0
- package/dist/paths-yzOKD6ow.js.map +1 -0
- package/dist/profile-CcMZ4hn7.js +2 -0
- package/dist/profile-NmMKAczz.js +222 -0
- package/dist/profile-NmMKAczz.js.map +1 -0
- package/dist/prompt-CKMQx_MJ.js +114 -0
- package/dist/prompt-CKMQx_MJ.js.map +1 -0
- package/dist/recipes-C7TIDlRj.js +3 -0
- package/dist/recipes-DG_-doGq.js +314 -0
- package/dist/recipes-DG_-doGq.js.map +1 -0
- package/dist/send-Dk-t8ia-.js +108 -0
- package/dist/send-Dk-t8ia-.js.map +1 -0
- package/dist/server-CDqDp1q3.js +20640 -0
- package/dist/server-CDqDp1q3.js.map +1 -0
- package/dist/service-BVn3soZZ.js +766 -0
- package/dist/service-BVn3soZZ.js.map +1 -0
- package/dist/service-BaWGPmSd.js +2 -0
- package/dist/service-C7jfo-Ex.js +457 -0
- package/dist/service-C7jfo-Ex.js.map +1 -0
- package/dist/service-DxDyKDQ-.js +2 -0
- package/dist/settings-B5qSHxRM.js +134 -0
- package/dist/settings-B5qSHxRM.js.map +1 -0
- package/dist/settings-DQvZaMN1.js +2 -0
- package/dist/setup-token-CwuSzfLK.js +48 -0
- package/dist/setup-token-CwuSzfLK.js.map +1 -0
- package/dist/skill/SKILL.md +445 -0
- package/dist/skill-1UQj3qgW.js +69 -0
- package/dist/skill-1UQj3qgW.js.map +1 -0
- package/dist/skill-pelq18JQ.js +2 -0
- package/dist/ssrf-BlVpGZ7C.js +181 -0
- package/dist/ssrf-BlVpGZ7C.js.map +1 -0
- package/dist/types-BhJDbSzE.js +135 -0
- package/dist/types-BhJDbSzE.js.map +1 -0
- package/dist/ui-B8Sd4Y7Y.js +81 -0
- package/dist/ui-B8Sd4Y7Y.js.map +1 -0
- package/dist/urls-Dp8pBGMU.js +2 -0
- package/dist/urls-U_LfYV61.js +27 -0
- package/dist/urls-U_LfYV61.js.map +1 -0
- package/dist/version-BxH7OuWD.js +20 -0
- package/dist/version-BxH7OuWD.js.map +1 -0
- package/dist/web/assets/_agentId-DonOCOlC.js +1 -0
- package/dist/web/assets/_app-B7t5lEia.js +1 -0
- package/dist/web/assets/_app-DMTGqYpM.js +65 -0
- package/dist/web/assets/_connectionId-DR5vFXOg.js +1 -0
- package/dist/web/assets/_webhookId-LfUlsULp.js +1 -0
- package/dist/web/assets/account-status-CEszs13C.js +1 -0
- package/dist/web/assets/accounts-5m7aiXuZ.js +1 -0
- package/dist/web/assets/accounts-list-YfJzThZa.js +1 -0
- package/dist/web/assets/activity-DOIe7SAg.js +1 -0
- package/dist/web/assets/add-connection-C8JR-13R.js +1 -0
- package/dist/web/assets/agent-create-form-CPxnPYH4.js +1 -0
- package/dist/web/assets/agents-B2Qj5KxT.js +1 -0
- package/dist/web/assets/approvals-BGaVaoFy.js +1 -0
- package/dist/web/assets/approve._id-BLrQnzPM.js +1 -0
- package/dist/web/assets/arrow-left-DZVAXoKj.js +1 -0
- package/dist/web/assets/arrow-right-C2zcqRr2.js +1 -0
- package/dist/web/assets/attention-gO9Nw5uW.js +1 -0
- package/dist/web/assets/audit-BPXXre8S.js +1 -0
- package/dist/web/assets/audit-bits-CGyIprzK.js +1 -0
- package/dist/web/assets/bell-ring-ig3zn1iS.js +1 -0
- package/dist/web/assets/bot-Zk76q_39.js +1 -0
- package/dist/web/assets/calendar-notice-DsCfq3VJ.js +1 -0
- package/dist/web/assets/calendar-plus-Cycfkk0y.js +1 -0
- package/dist/web/assets/calendar-setup-Pn61Wj1n.js +2 -0
- package/dist/web/assets/card-GSO5o-Ug.js +1 -0
- package/dist/web/assets/check-check-Ds1bPIGv.js +1 -0
- package/dist/web/assets/checkbox-B937U-Fd.js +1 -0
- package/dist/web/assets/chevron-right-Cqh4mDk1.js +1 -0
- package/dist/web/assets/chips-input-2xWDofmE.js +1 -0
- package/dist/web/assets/choice-cards-CgAIqBGX.js +1 -0
- package/dist/web/assets/circle-x-DcU-0zVh.js +1 -0
- package/dist/web/assets/command-khhto70y.js +1 -0
- package/dist/web/assets/common-BPZV8TFb.js +1 -0
- package/dist/web/assets/connect-agent-guide-CJdw31p2.js +1 -0
- package/dist/web/assets/connect-host-lr2c3xWh.js +6 -0
- package/dist/web/assets/connection-row-DYx_5o0c.js +1 -0
- package/dist/web/assets/connections-C4NOFb5R.js +1 -0
- package/dist/web/assets/data-table-kW1pkRB5.js +1 -0
- package/dist/web/assets/empty-DzTDioBP.js +1 -0
- package/dist/web/assets/events-C9zJnPKK.js +1 -0
- package/dist/web/assets/eye-B9gT1QSq.js +1 -0
- package/dist/web/assets/eye-off-Diktqz_g.js +1 -0
- package/dist/web/assets/field-C6ejurju.js +1 -0
- package/dist/web/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/web/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/web/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/web/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/web/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/web/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/web/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/web/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/web/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/web/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/web/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/web/assets/get-started-C38bq1gZ.js +2 -0
- package/dist/web/assets/hidden-chars-Dr9TxfvF.js +1 -0
- package/dist/web/assets/index-DGzo3kGh.js +11 -0
- package/dist/web/assets/index-zKOCQLGX.css +2 -0
- package/dist/web/assets/input-CWwJgozn.js +1 -0
- package/dist/web/assets/input-group-HG8OXcJ4.js +1 -0
- package/dist/web/assets/label-multi-select-sH8mllw8.js +1 -0
- package/dist/web/assets/labels-B5UqVwFo.js +1 -0
- package/dist/web/assets/laptop-BxJ4Nbj7.js +1 -0
- package/dist/web/assets/last-call-D-O5O94z.js +1 -0
- package/dist/web/assets/listener-handled-HNCuVrQ7.js +1 -0
- package/dist/web/assets/login-DaeKclcf.js +1 -0
- package/dist/web/assets/mail-C5fm2pTC.js +1 -0
- package/dist/web/assets/mcp-call-UoOTPFyh.js +1 -0
- package/dist/web/assets/mcp-call-card-Cr-OEDX2.js +3 -0
- package/dist/web/assets/message-square-quote-se8Bf3RP.js +1 -0
- package/dist/web/assets/mutations-CLPqJ6cj.js +1 -0
- package/dist/web/assets/network-igNw0VVx.js +1 -0
- package/dist/web/assets/pairing-XjuaVr2u.js +1 -0
- package/dist/web/assets/pairing-notifier-KPzOEZSO.js +1 -0
- package/dist/web/assets/paperclip-znS4iTrg.js +1 -0
- package/dist/web/assets/password-input-DV3aqcNf.js +1 -0
- package/dist/web/assets/pause-o-dK3khK.js +1 -0
- package/dist/web/assets/pencil-DkPFAhEq.js +1 -0
- package/dist/web/assets/play-DvCHND93.js +1 -0
- package/dist/web/assets/plug-CXAniEiR.js +1 -0
- package/dist/web/assets/plug-zap-BwR-l5wb.js +1 -0
- package/dist/web/assets/plus-B_TUslu3.js +1 -0
- package/dist/web/assets/preload-helper-Cc_aKyUb.js +1 -0
- package/dist/web/assets/public-url-rF2Xjyel.js +1 -0
- package/dist/web/assets/queries-Cv3nXx0U.js +42 -0
- package/dist/web/assets/refresh-cw-Ch5FNrby.js +1 -0
- package/dist/web/assets/revealed-keys-C_9NtJPY.js +1 -0
- package/dist/web/assets/rolldown-runtime-XKyaHtl9.js +1 -0
- package/dist/web/assets/rotate-ccw-B-mzPDk0.js +1 -0
- package/dist/web/assets/search-CTVKGomS.js +1 -0
- package/dist/web/assets/select-Bb806bpq.js +1 -0
- package/dist/web/assets/send-DuMVuYs1.js +1 -0
- package/dist/web/assets/settings-BWauhfFf.js +1 -0
- package/dist/web/assets/setup-B7bNKQOp.js +1 -0
- package/dist/web/assets/sheet-CYPwpUsH.js +1 -0
- package/dist/web/assets/shield-alert-CSYB-ThV.js +1 -0
- package/dist/web/assets/shield-check-BulpsYqK.js +1 -0
- package/dist/web/assets/sparkles-CUTiob4K.js +1 -0
- package/dist/web/assets/stamp-BNXUGNa3.js +1 -0
- package/dist/web/assets/step-url-51aMNak-.js +1 -0
- package/dist/web/assets/stream-Du7fY5_Y.js +1 -0
- package/dist/web/assets/tag-I5_-1jFL.js +1 -0
- package/dist/web/assets/terminal-BvxDFTJc.js +1 -0
- package/dist/web/assets/test-email-button-DYi7V_6X.js +1 -0
- package/dist/web/assets/toggle-group-Bdo1gmQ1.js +1 -0
- package/dist/web/assets/trash-Ci0aICEl.js +1 -0
- package/dist/web/assets/use-delivery-speed-BBh7W2q6.js +1 -0
- package/dist/web/assets/use-label-names-BXicesnP.js +1 -0
- package/dist/web/assets/use-sign-out-CPrY_oVO.js +1 -0
- package/dist/web/assets/useInfiniteQuery-DJLIM8yJ.js +1 -0
- package/dist/web/assets/useQuery-MrTwwNy5.js +1 -0
- package/dist/web/assets/useRouterState-D4OBK8l5.js +1 -0
- package/dist/web/assets/webhook-DjeeZiNC.js +1 -0
- package/dist/web/assets/webhook-bits-jw-y2D3u.js +1 -0
- package/dist/web/assets/webhook-sheet-B8h0skDe.js +34 -0
- package/dist/web/assets/webhooks-Cfsdpoyd.js +1 -0
- package/dist/web/assets/x-MF2TZ9aG.js +1 -0
- package/dist/web/favicon.svg +1 -0
- package/dist/web/index.html +27 -0
- package/package.json +98 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-C1lKMxFS.js","names":[],"sources":["../server/mail/css.ts","../server/mail/content.ts"],"sourcesContent":["// Just enough CSS to decide what a human reader can see: inline declarations, colours and contrast,\n// font sizes, background images, and simple top-level <style> rules. Not a CSS engine.\n\n// ───────────── Minimal DOM typing (linkedom; the server tsconfig has no DOM lib) ─────────────\n\nexport interface DomNode {\n nodeType: number;\n nodeName: string;\n textContent: string | null;\n childNodes: ArrayLike<DomNode>;\n parentNode: DomNode | null;\n remove(): void;\n}\n\nexport interface DomElement extends DomNode {\n tagName: string;\n innerHTML: string;\n getAttribute(name: string): string | null;\n hasAttribute(name: string): boolean;\n querySelector(sel: string): DomElement | null;\n querySelectorAll(sel: string): ArrayLike<DomElement>;\n replaceWith(...nodes: (DomNode | string)[]): void;\n append(...nodes: (DomNode | string)[]): void;\n}\n\nexport interface DomDocument {\n body: DomElement | null;\n documentElement: DomElement;\n createElement(tag: string): DomElement;\n}\n\nexport type Style = Map<string, string>;\n\n/** Declaration values longer than this are ignored (no legitimate hiding needs them; bounds regex work). */\nconst MAX_VALUE_CHARS = 256;\n\n/** Parses declarations (\"a: b; c: d\") into lower-cased property → value. `!important` is dropped. */\nexport function parseStyle(style: string | null | undefined): Style {\n const out: Style = new Map();\n if (!style) return out;\n for (const decl of style.split(\";\")) {\n const i = decl.indexOf(\":\");\n if (i < 0) continue;\n if (decl.length - i > MAX_VALUE_CHARS + 16) continue;\n const prop = decl.slice(0, i).trim().toLowerCase();\n const value = decl\n .slice(i + 1)\n .replace(/!\\s*important/i, \"\")\n .trim()\n .toLowerCase();\n if (prop && value) out.set(prop, value);\n }\n return out;\n}\n\nexport const isZeroLength = (v: string | undefined) => v !== undefined && /^[+-]?(?:0+(?:\\.0*)?|\\.0+)(?:[a-z%]+)?$/.test(v.trim());\n\n// ───────────── Colours ─────────────\n\n// CSS named colours (CSS Color Module Level 4).\nconst NAMED_COLORS: Record<string, string> = Object.fromEntries(\n `aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 black 000000\n blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 chartreuse 7fff00\n chocolate d2691e coral ff7f50 cornflowerblue 6495ed cornsilk fff8dc crimson dc143c cyan 00ffff darkblue 00008b\n darkcyan 008b8b darkgoldenrod b8860b darkgray a9a9a9 darkgreen 006400 darkgrey a9a9a9 darkkhaki bdb76b darkmagenta 8b008b\n darkolivegreen 556b2f darkorange ff8c00 darkorchid 9932cc darkred 8b0000 darksalmon e9967a darkseagreen 8fbc8f\n darkslateblue 483d8b darkslategray 2f4f4f darkslategrey 2f4f4f darkturquoise 00ced1 darkviolet 9400d3 deeppink ff1493\n deepskyblue 00bfff dimgray 696969 dimgrey 696969 dodgerblue 1e90ff firebrick b22222 floralwhite fffaf0 forestgreen 228b22\n fuchsia ff00ff gainsboro dcdcdc ghostwhite f8f8ff gold ffd700 goldenrod daa520 gray 808080 green 008000 greenyellow adff2f\n grey 808080 honeydew f0fff0 hotpink ff69b4 indianred cd5c5c indigo 4b0082 ivory fffff0 khaki f0e68c lavender e6e6fa\n lavenderblush fff0f5 lawngreen 7cfc00 lemonchiffon fffacd lightblue add8e6 lightcoral f08080 lightcyan e0ffff\n lightgoldenrodyellow fafad2 lightgray d3d3d3 lightgreen 90ee90 lightgrey d3d3d3 lightpink ffb6c1 lightsalmon ffa07a\n lightseagreen 20b2aa lightskyblue 87cefa lightslategray 778899 lightslategrey 778899 lightsteelblue b0c4de lightyellow ffffe0\n lime 00ff00 limegreen 32cd32 linen faf0e6 magenta ff00ff maroon 800000 mediumaquamarine 66cdaa mediumblue 0000cd\n mediumorchid ba55d3 mediumpurple 9370db mediumseagreen 3cb371 mediumslateblue 7b68ee mediumspringgreen 00fa9a\n mediumturquoise 48d1cc mediumvioletred c71585 midnightblue 191970 mintcream f5fffa mistyrose ffe4e1 moccasin ffe4b5\n navajowhite ffdead navy 000080 oldlace fdf5e6 olive 808000 olivedrab 6b8e23 orange ffa500 orangered ff4500 orchid da70d6\n palegoldenrod eee8aa palegreen 98fb98 paleturquoise afeeee palevioletred db7093 papayawhip ffefd5 peachpuff ffdab9\n peru cd853f pink ffc0cb plum dda0dd powderblue b0e0e6 purple 800080 rebeccapurple 663399 red ff0000 rosybrown bc8f8f\n royalblue 4169e1 saddlebrown 8b4513 salmon fa8072 sandybrown f4a460 seagreen 2e8b57 seashell fff5ee sienna a0522d\n silver c0c0c0 skyblue 87ceeb slateblue 6a5acd slategray 708090 slategrey 708090 snow fffafa springgreen 00ff7f\n steelblue 4682b4 tan d2b48c teal 008080 thistle d8bfd8 tomato ff6347 turquoise 40e0d0 violet ee82ee wheat f5deb3\n white ffffff whitesmoke f5f5f5 yellow ffff00 yellowgreen 9acd32`\n .trim()\n .split(/\\s+/)\n .reduce<[string, string][]>((acc, tok, i, all) => (i % 2 ? acc : [...acc, [tok, `#${all[i + 1]}`]]), []),\n);\n\nconst hex2 = (n: number) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, \"0\");\nconst rgbHex = (r: number, g: number, b: number) => `#${hex2(r)}${hex2(g)}${hex2(b)}`;\n\n/** Alpha component: \"0.5\", \"50%\". */\nconst alpha = (s: string | undefined) => (s === undefined ? 1 : s.endsWith(\"%\") ? parseFloat(s) / 100 : parseFloat(s));\n\nfunction hue(s: string): number {\n const n = parseFloat(s);\n if (s.endsWith(\"turn\")) return n * 360;\n if (s.endsWith(\"grad\")) return n * 0.9;\n if (s.endsWith(\"rad\")) return (n * 180) / Math.PI;\n return n;\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n const k = (n: number) => (n + h / 30) % 12;\n const a = s * Math.min(l, 1 - l);\n const f = (n: number) => l - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));\n return [f(0) * 255, f(8) * 255, f(4) * 255];\n}\n\n/** Normalizes a CSS colour to \"#rrggbb\", \"transparent\" (alpha ≈ 0), or null when unknown. */\nexport function normalizeColor(value: string | null | undefined): string | null {\n if (!value) return null;\n const v = value.trim().toLowerCase();\n if (v === \"transparent\") return \"transparent\";\n if (NAMED_COLORS[v]) return NAMED_COLORS[v];\n let m = /^#([0-9a-f]{3,4})$/.exec(v);\n if (m) {\n const [r, g, b, a] = m[1]!.split(\"\");\n if (a === \"0\") return \"transparent\";\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n m = /^#([0-9a-f]{6})([0-9a-f]{2})?$/.exec(v);\n if (m) return m[2] !== undefined && parseInt(m[2], 16) < 13 ? \"transparent\" : `#${m[1]}`;\n const fn = /^(rgba?|hsla?|hwb)\\(\\s*([^)]*)\\)$/.exec(v);\n if (!fn) return null;\n const parts = fn[2]!.split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3) return null;\n if (alpha(parts[3]) < 0.05) return \"transparent\";\n const pct = (s: string, scale: number) => (s.endsWith(\"%\") ? (parseFloat(s) / 100) * scale : parseFloat(s));\n if (fn[1]!.startsWith(\"rgb\")) return rgbHex(pct(parts[0]!, 255), pct(parts[1]!, 255), pct(parts[2]!, 255));\n const h = hue(parts[0]!);\n const x = parseFloat(parts[1]!) / 100;\n const y = parseFloat(parts[2]!) / 100;\n if ([h, x, y].some(Number.isNaN)) return null;\n if (fn[1]!.startsWith(\"hsl\")) return rgbHex(...hslToRgb(h, x, y));\n // hwb: whiteness x, blackness y.\n if (x + y >= 1) return rgbHex(...([1, 1, 1].map(() => (x / (x + y)) * 255) as [number, number, number]));\n const [r, g, b] = hslToRgb(h, 1, 0.5).map((c) => (c / 255) * (1 - x - y) + x);\n return rgbHex(r! * 255, g! * 255, b! * 255);\n}\n\nfunction luminance(hex: string): number {\n const c = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255).map((s) => (s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4));\n return 0.2126 * c[0]! + 0.7152 * c[1]! + 0.0722 * c[2]!;\n}\n\n/** WCAG contrast ratio between two \"#rrggbb\" colours (1 = identical, 21 = black on white). */\nexport function contrastRatio(a: string, b: string): number {\n const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);\n return (hi! + 0.05) / (lo! + 0.05);\n}\n\n/** Images and gradients in a `background` shorthand (they paint over the colour). */\nconst BG_IMAGE = /url\\([^)]*\\)|(?:repeating-)?(?:linear|radial|conic)-gradient\\((?:[^()]|\\([^()]*\\))*\\)|(?:-webkit-)?image-set\\([^)]*\\)/g;\n\n/** The background colour an element sets, from `background-color`, the `background` shorthand or `bgcolor`. */\nexport function backgroundColor(style: Style, el: DomElement): string | null {\n const direct = normalizeColor(style.get(\"background-color\"));\n if (direct) return direct;\n const shorthand = style.get(\"background\")?.replace(BG_IMAGE, \" \");\n if (shorthand) {\n for (const token of shorthand.match(/#[0-9a-f]{3,8}\\b|(?:rgba?|hsla?|hwb)\\([^)]*\\)|[a-z]+/g) ?? []) {\n const c = normalizeColor(token);\n if (c) return c;\n }\n }\n return normalizeColor(el.getAttribute(\"bgcolor\"));\n}\n\n/** A background image or gradient, so the background colour may not be what's behind the text. */\nexport function hasBackgroundImage(style: Style, el: DomElement): boolean {\n const image = style.get(\"background-image\");\n BG_IMAGE.lastIndex = 0;\n return (!!image && image !== \"none\") || BG_IMAGE.test(style.get(\"background\") ?? \"\") || el.hasAttribute(\"background\");\n}\n\n// ───────────── Sizes ─────────────\n\nconst ROOT_FONT_PX = 16;\nconst ABSOLUTE_PX: Record<string, number> = { px: 1, pt: 4 / 3, pc: 16, in: 96, cm: 96 / 2.54, mm: 96 / 25.4, q: 96 / 101.6 };\nconst SIZE_KEYWORDS: Record<string, number> = {\n \"xx-small\": 9,\n \"x-small\": 10,\n small: 13,\n medium: 16,\n large: 18,\n \"x-large\": 24,\n \"xx-large\": 32,\n \"xxx-large\": 48,\n};\n\n/** A font-size value in px given the parent's size; null when it isn't a size. */\nfunction sizePx(raw: string, parent: number): number | null {\n const v = raw.trim();\n if (SIZE_KEYWORDS[v] !== undefined) return SIZE_KEYWORDS[v];\n if (v === \"smaller\") return parent / 1.2;\n if (v === \"larger\") return parent * 1.2;\n if (v === \"inherit\" || v === \"unset\") return parent;\n if (v === \"initial\") return ROOT_FONT_PX;\n const m = /^([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+))([a-z%]*)$/.exec(v);\n if (!m) return null;\n const n = parseFloat(m[1]!);\n const unit = m[2]!;\n if (!unit) return n === 0 ? 0 : null;\n if (ABSOLUTE_PX[unit] !== undefined) return n * ABSOLUTE_PX[unit];\n if (unit === \"em\") return n * parent;\n if (unit === \"%\") return (n / 100) * parent;\n if (unit === \"rem\") return n * ROOT_FONT_PX;\n if (unit === \"ex\" || unit === \"ch\") return (n * parent) / 2;\n // Viewport and container units: only zero is certain.\n return n === 0 ? 0 : parent;\n}\n\n/** Effective font size in px from `font-size` or the `font` shorthand (\"bold 0/0 a\", \"12px/1.4 Arial\"). */\nexport function fontSizePx(style: Style, parent: number): number {\n const explicit = style.get(\"font-size\");\n if (explicit !== undefined) return sizePx(explicit, parent) ?? parent;\n const shorthand = style.get(\"font\");\n if (shorthand) {\n for (const token of shorthand.split(/\\s+/)) {\n const size = sizePx(token.split(\"/\")[0]!, parent);\n if (size !== null) return size;\n }\n }\n return parent;\n}\n\nexport const DEFAULT_FONT_PX = ROOT_FONT_PX;\n\n// ───────────── Stylesheets ─────────────\n//\n// Mail clients honour <style> blocks, so hiding rules there matter. Any sender controls this input, so the\n// work is bounded: CSS over MAX_CSS_CHARS is ignored, at most MAX_RULES rules are read, selectors are\n// matched through an index built in one tree walk (never querySelectorAll per selector), and matching\n// stops after MAX_MATCH_OPS checks. When anything is skipped, colours are treated as uncertain (which only\n// ever keeps text) and the hiding found so far still applies.\n\n/** Properties taken from <style> rules: only the ones that can hide content. */\nconst SHEET_PROPS = new Set([\"display\", \"visibility\", \"opacity\", \"font-size\", \"font\", \"overflow\", \"height\", \"max-height\", \"width\", \"max-width\"]);\nconst COLOR_PROPS = /^(?:color|background(?:-color|-image)?)$/;\nconst MAX_CSS_CHARS = 64_000;\nconst MAX_RULES = 300;\nconst MAX_SELECTORS = 300;\nconst MAX_SELECTOR_CHARS = 200;\nconst MAX_COMBINATORS = 3;\nconst MAX_MATCH_OPS = 2_000_000;\n\ninterface Rule {\n selectors: string[];\n decls: Style;\n /** In @media/@supports (print-only media are dropped). */\n conditional: boolean;\n}\n\n/** Removes comments in one pass (a lazy regex rescans the rest of the input for every unclosed \"/*\"). */\nfunction stripCssComments(css: string): string {\n let out = \"\";\n let i = 0;\n while (i < css.length) {\n const start = css.indexOf(\"/*\", i);\n if (start < 0) return out + css.slice(i);\n out += css.slice(i, start) + \" \";\n const end = css.indexOf(\"*/\", start + 2);\n if (end < 0) return out;\n i = end + 2;\n }\n return out;\n}\n\n/**\n * Media that can apply to someone reading the mail on a screen: not print-only, and no width bound no real\n * viewport has (`max-width: 1px`, `min-width: 99999px`).\n */\nfunction plausibleMedia(prelude: string): boolean {\n if (!/^@media\\b/i.test(prelude)) return true;\n if (/^@media\\s+(?:only\\s+)?print\\b/i.test(prelude) && !/\\b(?:screen|all)\\b/i.test(prelude)) return false;\n for (const m of prelude.matchAll(/\\((min|max)-(?:device-)?width\\s*:\\s*(\\d+(?:\\.\\d+)?)(px|em|rem)?\\s*\\)/gi)) {\n const px = parseFloat(m[2]!) * (m[3] && m[3].toLowerCase() !== \"px\" ? 16 : 1);\n if (m[1]!.toLowerCase() === \"max\" ? px < 200 : px > 4000) return false;\n }\n return true;\n}\n\n/** Splits CSS (comments already stripped) into rules; rules inside conditional groups are marked. Linear. */\nfunction parseRules(css: string): { rules: Rule[]; truncated: boolean } {\n const rules: Rule[] = [];\n let truncated = false;\n const text = css;\n const block = (from: number): number => {\n // Index just past the \"}\" matching the \"{\" at `from`.\n let depth = 0;\n for (let i = from; i < text.length; i++) {\n if (text[i] === \"{\") depth++;\n else if (text[i] === \"}\" && --depth === 0) return i + 1;\n }\n return text.length;\n };\n const walk = (start: number, end: number, conditional: boolean) => {\n let i = start;\n while (i < end) {\n const open = text.indexOf(\"{\", i);\n if (open < 0 || open >= end) break;\n const prelude = text.slice(i, open).trim();\n const close = block(open);\n if (prelude.startsWith(\"@\")) {\n if (/^@(media|supports|document|container)\\b/i.test(prelude) && !conditional && plausibleMedia(prelude)) walk(open + 1, close - 1, true);\n } else if (rules.length >= MAX_RULES) {\n truncated = true;\n return;\n } else {\n rules.push({ selectors: prelude.split(\",\").map((x) => x.trim()).filter(Boolean), decls: parseStyle(text.slice(open + 1, close - 1)), conditional });\n }\n i = close;\n }\n };\n walk(0, text.length, false);\n return { rules, truncated };\n}\n\n/** tag#id.class.class (no combinators, attributes or pseudo-classes). */\ninterface Compound {\n tag: string | null;\n id: string | null;\n classes: string[];\n}\n\nfunction parseCompound(sel: string): Compound | null {\n const m = /^([a-z][a-z0-9-]*|\\*)?((?:[#.][\\w-]+)*)$/i.exec(sel.trim());\n if (!m || (!m[1] && !m[2])) return null;\n const parts = m[2]!.match(/[#.][\\w-]+/g) ?? [];\n const ids = parts.filter((x) => x.startsWith(\"#\")).map((x) => x.slice(1));\n if (ids.length > 1) return null;\n return {\n tag: m[1] && m[1] !== \"*\" ? m[1].toUpperCase() : null,\n id: ids[0] ?? null,\n classes: parts.filter((x) => x.startsWith(\".\")).map((x) => x.slice(1)),\n };\n}\n\n/** One step up from the subject: `child` for \">\", otherwise any ancestor (descendant combinator). */\ninterface AncestorStep {\n compound: Compound;\n child: boolean;\n}\n\n/** Compounds joined by descendant/child combinators, as subject + ancestor steps (right to left). */\nfunction parseChain(sel: string): { subject: Compound; ancestors: AncestorStep[] } | null {\n if (/[+~]/.test(sel)) return null;\n const tokens = sel.trim().replace(/\\s*>\\s*/g, \" > \").split(/\\s+/);\n const compounds: Compound[] = [];\n const childLinks: boolean[] = [];\n let child = false;\n for (const tok of tokens) {\n if (tok === \">\") {\n if (!compounds.length || child) return null;\n child = true;\n continue;\n }\n const c = parseCompound(tok);\n if (!c) return null;\n if (compounds.length) childLinks.push(child);\n compounds.push(c);\n child = false;\n }\n if (!compounds.length || child) return null;\n const subject = compounds.pop()!;\n const ancestors = compounds.reverse().map((compound, i) => ({ compound, child: childLinks[childLinks.length - 1 - i]! }));\n return { subject, ancestors };\n}\n\n/**\n * The element a complex selector applies to, over-approximated: its last compound with attribute and\n * pseudo parts dropped (`td > a.btn:hover` → `a.btn`). \"any\" when that leaves nothing specific.\n */\nfunction subjectOf(sel: string): Compound | \"any\" {\n const last = sel.trim().split(/[\\s>+~]+/).at(-1) ?? \"\";\n const bare = last.replace(/\\[[^\\]]*\\]/g, \"\").replace(/::?[\\w-]+(?:\\([^)]*\\))?/g, \"\");\n const c = parseCompound(bare);\n return !c || (!c.tag && !c.id && !c.classes.length) ? \"any\" : c;\n}\n\nconst indexKey = (c: Compound) => (c.id ? `#${c.id}` : c.classes.length ? `.${c.classes[0]}` : c.tag ? c.tag : \"*\");\n\ninterface Entry {\n compound: Compound;\n /** Ancestor steps that must also match for `hide` (greedy, nearest ancestor first). */\n ancestors: AncestorStep[];\n /** Apply these hiding declarations (top-level rules with tag/class/id selectors and ' '/'>' combinators). */\n hide: Style | null;\n /** Sets colour or background: the element's colours can't be known from inline styles. */\n colour: boolean;\n /** A conditional rule that makes hidden content visible again on some device (subject over-approximated). */\n reveal: boolean;\n order: number;\n}\n\nconst VISIBLE_VALUES: Record<string, (v: string) => boolean> = {\n display: (v) => v !== \"none\",\n visibility: (v) => v === \"visible\",\n opacity: (v) => parseFloat(v) >= 0.1,\n \"font-size\": (v) => !isZeroLength(v),\n overflow: (v) => v === \"visible\" || v === \"auto\" || v === \"scroll\",\n height: (v) => !isZeroLength(v),\n \"max-height\": (v) => !isZeroLength(v),\n width: (v) => !isZeroLength(v),\n \"max-width\": (v) => !isZeroLength(v),\n};\n\nconst reveals = (decls: Style) => [...decls].some(([p, v]) => VISIBLE_VALUES[p]?.(v));\n\nexport interface SheetEffects {\n /** Hiding declarations per element, from top-level rules. */\n hiding: Map<DomElement, Style>;\n /** Elements whose colour/background a rule may set. */\n colourStyled: Set<DomElement>;\n /** A colour rule targets anything: treat every background as uncertain. */\n allColourUncertain: boolean;\n /** Some rules were not read (size/count/work limits): backgrounds of class/id elements are uncertain. */\n classedColourUncertain: boolean;\n}\n\ninterface ElementKey {\n tag: string;\n id: string | null;\n classes: string[];\n}\n\nfunction keyOf(el: DomElement): ElementKey {\n return {\n tag: el.tagName.toUpperCase(),\n id: el.getAttribute(\"id\"),\n classes: (el.getAttribute(\"class\") ?? \"\").split(/\\s+/).filter(Boolean).slice(0, 50),\n };\n}\n\nconst compoundMatches = (c: Compound, k: ElementKey) =>\n (!c.tag || c.tag === k.tag) && (!c.id || c.id === k.id) && c.classes.every((x) => k.classes.includes(x));\n\n/** Greedy right-to-left ancestor check; counts every step against the shared budget. */\nfunction ancestorsMatch(el: DomElement, steps: AncestorStep[], budget: { ops: number }): boolean {\n let node = el.parentNode as DomElement | null;\n for (const step of steps) {\n if (step.child) {\n budget.ops++;\n if (!node || node.nodeType !== 1 || !compoundMatches(step.compound, keyOf(node))) return false;\n } else {\n while (node && node.nodeType === 1 && !compoundMatches(step.compound, keyOf(node))) {\n if (++budget.ops > MAX_MATCH_OPS) return false;\n node = node.parentNode as DomElement | null;\n }\n if (!node || node.nodeType !== 1) return false;\n }\n node = node.parentNode as DomElement | null;\n }\n return true;\n}\n\nexport function stylesheetEffects(doc: DomDocument): SheetEffects {\n const out: SheetEffects = { hiding: new Map(), colourStyled: new Set(), allColourUncertain: false, classedColourUncertain: false };\n const root = doc.documentElement;\n let css = stripCssComments(\n Array.from(root.querySelectorAll(\"style\"))\n .map((s) => s.textContent ?? \"\")\n .join(\"\\n\"),\n ).replace(/<!--|-->/g, \" \");\n if (!css.trim()) return out;\n if (css.length > MAX_CSS_CHARS) {\n // Read the rules that fit; whatever was cut may style classed elements.\n css = css.slice(0, css.lastIndexOf(\"}\", MAX_CSS_CHARS) + 1);\n out.classedColourUncertain = true;\n }\n const { rules, truncated } = parseRules(css);\n if (truncated) out.classedColourUncertain = true;\n\n const index = new Map<string, Entry[]>();\n let selectors = 0;\n let order = 0;\n for (const rule of rules) {\n const hide = new Map([...rule.decls].filter(([p]) => SHEET_PROPS.has(p)));\n const colour = [...rule.decls.keys()].some((p) => COLOR_PROPS.test(p));\n const reveal = rule.conditional && reveals(hide);\n if (!colour && !reveal && (rule.conditional || !hide.size)) continue;\n for (const sel of rule.selectors) {\n if (++selectors > MAX_SELECTORS) {\n out.classedColourUncertain = true;\n break;\n }\n // Long or deeply combined selectors are skipped outright (bounded work, and never hiding rules).\n if (sel.length > MAX_SELECTOR_CHARS || (sel.match(/[\\s>+~]+/g)?.length ?? 0) > MAX_COMBINATORS) {\n if (colour) out.classedColourUncertain = true;\n continue;\n }\n const chain = parseChain(sel);\n const subject = chain?.subject ?? subjectOf(sel);\n if (subject === \"any\") {\n // Over-approximation is only safe for \"keep visible\" effects.\n if (colour) out.allColourUncertain = true;\n if (!reveal) continue;\n }\n const compound = subject === \"any\" ? { tag: null, id: null, classes: [] } : subject;\n const entry: Entry = {\n compound,\n ancestors: chain?.ancestors ?? [],\n hide: !rule.conditional && chain && hide.size ? hide : null,\n colour,\n reveal,\n order: order++,\n };\n if (!entry.hide && !entry.colour && !entry.reveal) continue;\n const key = indexKey(compound);\n const list = index.get(key);\n if (list) list.push(entry);\n else index.set(key, [entry]);\n }\n }\n if (!index.size) return out;\n\n // One walk: each element only checks the rules indexed under its id, classes, tag and \"*\".\n const budget = { ops: 0 };\n for (const el of Array.from(root.querySelectorAll(\"*\"))) {\n const k = keyOf(el);\n const keys = [...(k.id ? [`#${k.id}`] : []), ...k.classes.map((c) => `.${c}`), k.tag, \"*\"];\n const matched: Entry[] = [];\n for (const key of keys) {\n for (const e of index.get(key) ?? []) {\n if (++budget.ops > MAX_MATCH_OPS) {\n out.classedColourUncertain = true;\n return out;\n }\n if (!compoundMatches(e.compound, k)) continue;\n // Ancestors only gate hiding; a rule's colour effect stays over-approximated by its subject.\n if (e.hide && e.ancestors.length && !ancestorsMatch(el, e.ancestors, budget)) {\n if (e.colour) matched.push({ ...e, hide: null });\n continue;\n }\n matched.push(e);\n }\n }\n if (!matched.length) continue;\n if (matched.some((e) => e.colour)) out.colourStyled.add(el);\n if (matched.some((e) => e.reveal)) continue;\n const hiding = matched.filter((e) => e.hide).sort((a, b) => a.order - b.order);\n if (!hiding.length) continue;\n const style: Style = new Map();\n for (const e of hiding) for (const [p, v] of e.hide!) style.set(p, v);\n out.hiding.set(el, style);\n }\n return out;\n}\n","// Content guardrails: clean, don't censor. Removes only what a human reader would never see\n// (hidden HTML, invisible/smuggling unicode), converts HTML to markdown, and attaches informational\n// signals. Content is never altered because of a signal.\n\nimport { parseHTML } from \"linkedom\";\nimport TurndownService from \"turndown\";\nimport { gfm } from \"turndown-plugin-gfm\";\nimport type { Address, ContentSignals, GmailLabel, MessageContent, MessageSummary } from \"../../shared/types.ts\";\nimport type { ParsedMessage } from \"../google/types.ts\";\nimport {\n backgroundColor,\n contrastRatio,\n DEFAULT_FONT_PX,\n type DomDocument,\n type DomElement,\n type DomNode,\n fontSizePx,\n hasBackgroundImage,\n isZeroLength,\n normalizeColor,\n parseStyle,\n type Style,\n type SheetEffects,\n stylesheetEffects,\n} from \"./css.ts\";\n\nexport { normalizeColor } from \"./css.ts\";\n\n// ───────────── Invisible unicode ─────────────\n\n// Flagged and stripped: zero-width space/non-joiner/joiner (outside the contexts below), word joiner and\n// invisible operators (U+2060–U+2064), BOM (except a leading one), bidi overrides LRO/RLO (U+202D/E),\n// tag characters (U+E0000–U+E007F, \"ASCII smuggling\") and variation selectors that don't follow a base\n// character (\"emoji smuggling\" hides bytes in runs of them).\n// Stripped silently: soft hyphens (U+00AD, invisible line-break hints), bidi embeddings LRE/RLE, PDF\n// (U+202A–U+202C) and isolates (U+2066–U+2069). These only change visual order, never the logical text an\n// agent reads, and are common in legitimate RTL text; unbalanced ones are flagged.\n// Kept: LRM/RLM/ALM (never matched); ZWNJ/ZWJ between characters of joining scripts (Persian, Indic, …),\n// where they change spelling; ZWJ inside emoji sequences; one variation selector after its base character;\n// tag characters forming an emoji flag tag sequence (U+1F3F4 + tag letters/digits + CANCEL TAG).\nconst JOINING_SCRIPTS = [\n \"Arabic\", \"Syriac\", \"Nko\", \"Mongolian\", \"Thaana\", \"Devanagari\", \"Bengali\", \"Gurmukhi\", \"Gujarati\", \"Oriya\",\n \"Tamil\", \"Telugu\", \"Kannada\", \"Malayalam\", \"Sinhala\", \"Myanmar\", \"Khmer\", \"Tibetan\",\n].map((s) => `\\\\p{Script_Extensions=${s}}`).join(\"\");\nconst PICTO = \"\\\\p{Extended_Pictographic}\";\nconst VS = \"\\\\uFE00-\\\\uFE0F\\\\u{E0100}-\\\\u{E01EF}\";\nconst KEEP_FLAG = \"\\\\u{1F3F4}[\\\\u{E0030}-\\\\u{E0039}\\\\u{E0061}-\\\\u{E007A}]{2,7}\\\\u{E007F}\";\n// Also a ZWJ after a virama at the end of a word (Malayalam chillu forms such as \"ന്\\u200D\").\nconst KEEP_JOINER = `(?<=[${JOINING_SCRIPTS}])[\\\\u200C\\\\u200D](?=[${JOINING_SCRIPTS}])|(?<=[${JOINING_SCRIPTS}])(?<=\\\\p{M})\\\\u200D`;\nconst KEEP_EMOJI_ZWJ = `(?<=${PICTO}(?:\\\\uFE0F|\\\\p{Emoji_Modifier})?)\\\\u200D(?=${PICTO})`;\nconst KEEP_VS = `(?<=[^${VS}])[\\\\uFE00-\\\\uFE0F](?![${VS}])|(?<=\\\\p{Ideographic})[\\\\u{E0100}-\\\\u{E01EF}](?![${VS}])`;\nconst SILENT = \"[\\\\u00AD\\\\u202A-\\\\u202C\\\\u2066-\\\\u2069]\";\nconst FLAGGED = `[\\\\u200B-\\\\u200D\\\\u2060-\\\\u2064\\\\uFEFF\\\\u202D\\\\u202E\\\\u{E0000}-\\\\u{E007F}${VS}]`;\nconst INVISIBLE = new RegExp(`(${KEEP_FLAG})|(${KEEP_JOINER})|(${KEEP_EMOJI_ZWJ})|(${KEEP_VS})|(${SILENT})|${FLAGGED}`, \"gu\");\n\nconst BIDI_OPEN_EMBED = new Set([0x202a, 0x202b]);\nconst BIDI_OPEN_OVERRIDE = new Set([0x202d, 0x202e]);\nconst BIDI_OPEN_ISOLATE = new Set([0x2066, 0x2067, 0x2068]);\n\n/**\n * Bidi embeddings/isolates without their matching PDF/PDI (per paragraph): these can reorder what follows.\n * Overrides are always flagged on their own, so they never count here.\n */\nfunction unbalancedBidi(text: string): number {\n if (!/[\\u202A-\\u202E\\u2066-\\u2069]/.test(text)) return 0;\n // Linear: the stack is capped at UAX #9's max depth (125), so every pop/scan is O(1); openers beyond it\n // overflow and count as unmatched (no legitimate text nests that deep).\n const MAX_DEPTH = 125;\n let unmatched = 0;\n const stack: (\"e\" | \"o\" | \"i\")[] = [];\n const counted = (from: number) => stack.slice(from).filter((x) => x !== \"o\").length;\n for (const c of text) {\n const cp = c.codePointAt(0)!;\n const opener = BIDI_OPEN_EMBED.has(cp) ? \"e\" : BIDI_OPEN_OVERRIDE.has(cp) ? \"o\" : BIDI_OPEN_ISOLATE.has(cp) ? \"i\" : null;\n if (opener) {\n if (stack.length < MAX_DEPTH) stack.push(opener);\n else if (opener !== \"o\") unmatched++;\n } else if (cp === 0x202c) {\n if (stack.at(-1) === \"e\" || stack.at(-1) === \"o\") stack.pop();\n else unmatched++;\n } else if (cp === 0x2069) {\n const at = stack.lastIndexOf(\"i\");\n if (at < 0) unmatched++;\n else {\n unmatched += counted(at + 1);\n stack.length = at;\n }\n } else if (c === \"\\n\" || c === \"\\u2029\") {\n unmatched += counted(0);\n stack.length = 0;\n }\n }\n return unmatched + counted(0);\n}\n\n/** Removes invisible/smuggling characters. `removed` counts only the ones that can hide or disguise text. */\nexport function stripInvisible(text: string): { text: string; removed: number } {\n let removed = unbalancedBidi(text);\n const out = text.replace(\n INVISIBLE,\n (m: string, flag?: string, joiner?: string, zwj?: string, vs?: string, silent?: string, offset?: number) => {\n if (flag || joiner || zwj || vs) return m;\n if (!silent && !(m === \"\\uFEFF\" && offset === 0)) removed++;\n return \"\";\n },\n );\n return { text: out, removed };\n}\n\nconst visibleText = (s: string | null) => stripInvisible(s ?? \"\").text.trim();\n\n/** Tags delimiting untrusted third-party content in tool results: mail bodies and calendar event descriptions. */\nexport type UntrustedTag = \"email_content\" | \"calendar_content\";\n\n/**\n * Every delimiter xaq wraps untrusted text in: mail bodies, calendar descriptions and upstream MCP\n * tool output (server/broker/policy/output.ts). escapeDelimiters neutralizes all of them everywhere.\n */\nexport const DELIMITER_TAGS = [\"email_content\", \"calendar_content\", \"tool_output\"] as const;\n\n/**\n * Neutralizes our delimiters and look-alikes (`</ email_content >`, turndown's `calendar\\_content`) in\n * untrusted text. Every tag is escaped everywhere: an event description or a tool's output must not close\n * a mail wrapper either.\n */\nexport const escapeDelimiters = (s: string) => s.replace(/<(?=\\s{0,16}\\/?\\s{0,16}(?:email\\\\?_content|calendar\\\\?_content|tool\\\\?_output))/gi, \"<\");\n\n// ───────────── HTML cleaning ─────────────\n\nconst ELEMENT = 1;\nconst TEXT = 3;\nconst COMMENT = 8;\n\n/** Never rendered. Removed; text inside counts as hidden content only for the ones listed in HIDDEN_TEXT_TAGS. */\nconst NON_RENDERED = new Set([\"SCRIPT\", \"STYLE\", \"HEAD\", \"TITLE\", \"META\", \"LINK\", \"TEMPLATE\", \"NOSCRIPT\", \"OBJECT\", \"EMBED\", \"IFRAME\", \"SVG\"]);\nconst HIDDEN_TEXT_TAGS = new Set([\"SCRIPT\", \"TEMPLATE\", \"NOSCRIPT\"]);\n\n/** Hidden in a way no descendant can undo: the element and its subtree are removed. */\nfunction isCollapsed(style: Style): boolean {\n if (style.get(\"display\") === \"none\") return true;\n const overflow = style.get(\"overflow\");\n if (overflow !== \"hidden\" && overflow !== \"clip\") return false;\n return [\"max-height\", \"height\", \"max-width\", \"width\"].some((p) => isZeroLength(style.get(p)));\n}\n\nfunction parseOpacity(v: string | undefined): number {\n if (v === undefined) return 1;\n const n = v.endsWith(\"%\") ? parseFloat(v) / 100 : parseFloat(v);\n return Number.isNaN(n) ? 1 : Math.max(0, Math.min(1, n));\n}\n\n/** Text an element would show (also for <template>, whose content linkedom keeps out of textContent). */\nfunction elementText(el: DomElement): string {\n return visibleText(el.textContent || el.innerHTML.replace(/<[^<>]*>/g, \" \"));\n}\n\nconst hasText = (n: DomNode) => visibleText(n.textContent).length > 0;\n\nfunction isTrackingPixel(el: DomElement, style: Style): boolean {\n const small = (v: string | null | undefined) => v != null && /^\\s*[01](?:px)?\\s*$/.test(v);\n return (small(el.getAttribute(\"width\")) && small(el.getAttribute(\"height\"))) || (small(style.get(\"width\")) && small(style.get(\"height\")));\n}\n\n/** Rendering context inherited down the tree (inline styles plus hiding rules from top-level <style>). */\ninterface Inherited {\n color: string | null;\n bg: string | null;\n /** The real background may differ from `bg`: a background image, or a stylesheet rule setting colours. */\n bgUncertain: boolean;\n /** `background-clip: text` (gradient text): transparent text colour is still visible. */\n clipText: boolean;\n fontPx: number;\n /** Product of ancestor opacities. */\n opacity: number;\n /** visibility:hidden, which a descendant can undo with visibility:visible. */\n invisible: boolean;\n}\n\ninterface CleanState {\n /** Hidden elements/text that carried readable text. */\n removed: number;\n /** What the document's <style> blocks do: hiding rules and which elements' colours they may change. */\n sheet: SheetEffects;\n}\n\n/** Opacity below this, or text smaller than 1px, is invisible to a reader. */\nconst MIN_OPACITY = 0.1;\n/** Text/background contrast below this is unreadable (#eeeeee on white is ~1.16 and stays). */\nconst MIN_CONTRAST = 1.1;\n\nfunction textHidden(ctx: Inherited): boolean {\n if (ctx.invisible || ctx.fontPx < 1 || ctx.opacity < MIN_OPACITY) return true;\n if (ctx.color === \"transparent\") return !ctx.clipText;\n return !!ctx.color && !!ctx.bg && !ctx.bgUncertain && contrastRatio(ctx.color, ctx.bg) < MIN_CONTRAST;\n}\n\nfunction styleOf(el: DomElement, state: CleanState): Style {\n const inline = parseStyle(el.getAttribute(\"style\"));\n const sheet = state.sheet.hiding.get(el);\n return sheet ? new Map([...sheet, ...inline]) : inline;\n}\n\nfunction childContext(el: DomElement, style: Style, parent: Inherited, state: CleanState): Inherited {\n const tag = el.tagName.toUpperCase();\n const visibility = style.get(\"visibility\");\n const ownBg = backgroundColor(style, el);\n const bg = ownBg && ownBg !== \"transparent\" ? ownBg : null;\n const sheetColour =\n state.sheet.allColourUncertain ||\n state.sheet.colourStyled.has(el) ||\n (state.sheet.classedColourUncertain && (el.hasAttribute(\"class\") || el.hasAttribute(\"id\")));\n const clip = style.get(\"background-clip\") ?? style.get(\"-webkit-background-clip\");\n return {\n color: normalizeColor(style.get(\"color\")) ?? (tag === \"FONT\" ? normalizeColor(el.getAttribute(\"color\")) : null) ?? parent.color,\n bg: bg ?? parent.bg,\n bgUncertain: (bg ? false : parent.bgUncertain) || hasBackgroundImage(style, el) || sheetColour,\n clipText: parent.clipText || clip === \"text\",\n fontPx: fontSizePx(style, parent.fontPx),\n opacity: parent.opacity * parseOpacity(style.get(\"opacity\")),\n invisible: visibility === \"hidden\" || visibility === \"collapse\" ? true : visibility === \"visible\" ? false : parent.invisible,\n };\n}\n\n/** Comment text a human could read if a client rendered it (conditional comments are rendered by Outlook). */\nfunction commentText(text: string): string {\n return visibleText(text.replace(/^\\s*\\[if[^\\]]*\\]>?|<!\\[endif\\]\\s*$|\\[endif\\]\\s*$/gi, \"\").replace(/<[^<>]*>/g, \" \"));\n}\n\nconst MAX_WHITESPACE_RUN = 64;\nconst LONG_WHITESPACE = /\\s{65}/;\nconst LONG_WHITESPACE_G = /\\s{65,}/g;\n\n/** Iterative (deeply nested mail must not overflow the stack). */\nfunction cleanTree(root: DomElement, rootCtx: Inherited, state: CleanState): void {\n const stack: [DomNode, Inherited][] = [[root, rootCtx]];\n while (stack.length) {\n const [node, ctx] = stack.pop()!;\n for (const child of Array.from(node.childNodes)) {\n if (child.nodeType === COMMENT) {\n if (commentText(child.textContent ?? \"\")) state.removed++;\n child.remove();\n continue;\n }\n if (child.nodeType === TEXT) {\n if (hasText(child) && textHidden(ctx)) {\n state.removed++;\n child.remove();\n continue;\n }\n // Whitespace runs are capped: nobody reads 64+ blanks, and turndown's end-anchored whitespace\n // regexes are quadratic in run length.\n const text = child.textContent ?? \"\";\n if (text.length > MAX_WHITESPACE_RUN && LONG_WHITESPACE.test(text)) {\n child.textContent = text.replace(LONG_WHITESPACE_G, (m) => m.slice(0, MAX_WHITESPACE_RUN));\n }\n continue;\n }\n if (child.nodeType !== ELEMENT) continue;\n const el = child as DomElement;\n const tag = el.tagName.toUpperCase();\n if (NON_RENDERED.has(tag)) {\n const jsonLd = tag === \"SCRIPT\" && /ld\\+json/i.test(el.getAttribute(\"type\") ?? \"\");\n if (HIDDEN_TEXT_TAGS.has(tag) && !jsonLd && elementText(el)) state.removed++;\n el.remove();\n continue;\n }\n const style = styleOf(el, state);\n const inner = childContext(el, style, ctx, state);\n if (el.hasAttribute(\"hidden\") || isCollapsed(style) || inner.opacity < MIN_OPACITY) {\n if (hasText(el)) state.removed++;\n el.remove();\n continue;\n }\n if (tag === \"IMG\") {\n // Images are never dropped for font-size; only when truly invisible or a tracking pixel.\n if (isTrackingPixel(el, style) || inner.invisible) el.remove();\n continue;\n }\n stack.push([el, inner]);\n }\n }\n}\n\n/** Deeper than this, elements are unwrapped (pathological nesting would overflow turndown's recursion). */\nconst MAX_DEPTH = 80;\nconst BLOCK_TAGS = new Set([\"DIV\", \"P\", \"TABLE\", \"TBODY\", \"THEAD\", \"TFOOT\", \"TR\", \"TD\", \"TH\", \"LI\", \"UL\", \"OL\", \"SECTION\", \"ARTICLE\", \"BLOCKQUOTE\", \"CENTER\", \"H1\", \"H2\", \"H3\", \"H4\", \"H5\", \"H6\"]);\n\n/**\n * Replaces everything below MAX_DEPTH with its leaves (text, images, line breaks) in document order.\n * Linear: leaves are collected in one walk and moved individually (moving whole subtrees per level, as\n * unwrapping does, is quadratic in linkedom).\n */\nfunction flattenDeepNesting(root: DomElement): void {\n const stack: [DomElement, number][] = [[root, 0]];\n while (stack.length) {\n const [el, depth] = stack.pop()!;\n if (depth < MAX_DEPTH) {\n for (const c of Array.from(el.childNodes)) if (c.nodeType === ELEMENT) stack.push([c as DomElement, depth + 1]);\n continue;\n }\n const leaves: (DomNode | string)[] = [];\n const walk: (DomNode | string)[] = Array.from(el.childNodes).reverse();\n while (walk.length) {\n const n = walk.pop()!;\n if (typeof n === \"string\") {\n leaves.push(n);\n } else if (n.nodeType === TEXT || n.nodeName === \"IMG\" || n.nodeName === \"BR\") {\n leaves.push(n);\n } else if (n.nodeType === ELEMENT) {\n // A block ends with a space so words from adjacent blocks don't run together.\n if (BLOCK_TAGS.has(n.nodeName)) walk.push(\" \");\n walk.push(...Array.from(n.childNodes).reverse());\n }\n }\n for (const c of Array.from(el.childNodes)) c.remove();\n el.append(...leaves);\n }\n}\n\n/** Elements beyond this make a message too complex to convert (checked on the raw HTML before parsing). */\nexport const MAX_ELEMENTS = 20_000;\n\nexport class ContentTooComplexError extends Error {}\n\n/** Counts start tags without building anything; stops at the cap. */\nfunction tooManyElements(html: string): boolean {\n const re = /<[a-zA-Z]/g;\n let n = 0;\n while (re.exec(html)) if (++n > MAX_ELEMENTS) return true;\n return false;\n}\n\n// ───────────── HTML → markdown ─────────────\n\nconst BLOCK_IN_CELL = \"div,p,table,ul,ol,h1,h2,h3,h4,h5,h6,blockquote,pre,hr\";\n/** Browsers ignore tabs/newlines/controls inside URL schemes (\"java	script:\"). */\n// oxlint-disable-next-line no-control-regex -- matching control characters is the point here\nconst schemeOf = (url: string) => url.replace(/[\\x00-\\x20\\x7f]/g, \"\").toLowerCase();\nconst UNSAFE_SCHEME = /^(?:javascript|data|vbscript|file):/;\n\nfunction createTurndown(): TurndownService {\n const td = new TurndownService({\n headingStyle: \"atx\",\n codeBlockStyle: \"fenced\",\n bulletListMarker: \"-\",\n emDelimiter: \"_\",\n hr: \"---\",\n });\n td.use(gfm);\n td.addRule(\"images\", {\n filter: \"img\",\n replacement: (_content, node) => {\n const el = node as unknown as DomElement;\n const alt = (el.getAttribute(\"alt\") ?? \"\").replace(/\\s+/g, \" \").trim();\n const src = (el.getAttribute(\"src\") ?? \"\").trim();\n const scheme = schemeOf(src);\n if (!src || UNSAFE_SCHEME.test(scheme) || scheme.startsWith(\"cid:\")) return alt ? `[image: ${alt}]` : \"\";\n return `![${alt.replace(/[[\\]]/g, \"\")}](${src.replace(/[()\\s]/g, encodeURIComponent)})`;\n },\n });\n td.addRule(\"unsafeLinks\", {\n filter: (node) => {\n if (node.nodeName !== \"A\") return false;\n const href = (node as unknown as DomElement).getAttribute(\"href\") ?? \"\";\n return !href.trim() || UNSAFE_SCHEME.test(schemeOf(href));\n },\n replacement: (content) => content,\n });\n return td;\n}\n\nlet turndownInstance: TurndownService | undefined;\nconst turndown = () => (turndownInstance ??= createTurndown());\n\n/** A table holding data (rendered as a GFM table) rather than email layout (unwrapped into blocks). */\nfunction isDataTable(table: DomElement): boolean {\n const role = (table.getAttribute(\"role\") ?? \"\").toLowerCase();\n if (role === \"presentation\" || role === \"none\") return false;\n if (table.querySelector(\"table\")) return false;\n const rows = Array.from(table.querySelectorAll(\"tr\"));\n if (rows.length < 2) return false;\n const widths = rows.map((r) => cellsOf(r).length);\n if (Math.max(...widths) < 2) return false;\n if (table.querySelector(\"th\")) return true;\n return !table.querySelector(BLOCK_IN_CELL);\n}\n\nconst cellsOf = (row: DomElement) => Array.from(row.childNodes).filter((n): n is DomElement => n.nodeName === \"TD\" || n.nodeName === \"TH\");\n\n/** Data-table cells with markup converted through turndown per document; later ones keep only their text. */\nconst MAX_CONVERTED_CELLS = 2_000;\n\nfunction cellMarkdown(cell: DomElement, budget: { cells: number }): string {\n // Plain-text cells (most of them) skip the full conversion.\n const plain = Array.from(cell.childNodes).every((n) => n.nodeType === TEXT);\n const md = plain || budget.cells-- <= 0 ? turndown().escape(cell.textContent ?? \"\") : turndown().turndown(cell.innerHTML);\n return md.replace(/\\s+/g, \" \").replace(/\\|/g, \"\\\\|\").trim();\n}\n\nfunction tableToMarkdown(table: DomElement, budget: { cells: number }): string {\n const rows = Array.from(table.querySelectorAll(\"tr\")).map((r) =>\n cellsOf(r).flatMap((c) => {\n const text = cellMarkdown(c, budget);\n // A spanned cell keeps its columns: the content, then empty cells.\n const span = Math.min(Math.max(parseInt(c.getAttribute(\"colspan\") ?? \"1\", 10) || 1, 1), 20);\n return [text, ...Array<string>(span - 1).fill(\"\")];\n }),\n );\n const width = Math.max(...rows.map((r) => r.length));\n const line = (cells: string[]) => `| ${Array.from({ length: width }, (_, i) => cells[i] ?? \"\").join(\" | \")} |`;\n const [head = [], ...body] = rows;\n return [line(head), line(Array(width).fill(\"---\")), ...body.map(line)].join(\"\\n\");\n}\n\n/** Converts tables in place: data tables become placeholders (filled after turndown), layout tables become blocks. */\nfunction prepareTables(doc: DomDocument, root: DomElement): Map<string, string> {\n const placeholders = new Map<string, string>();\n const tables = Array.from(root.querySelectorAll(\"table\"));\n const data = new Set(tables.filter(isDataTable));\n const budget = { cells: MAX_CONVERTED_CELLS };\n for (const table of data) {\n const key = `AIBTABLE${placeholders.size}X`;\n placeholders.set(key, tableToMarkdown(table, budget));\n const p = doc.createElement(\"p\");\n p.append(key);\n table.replaceWith(p);\n }\n for (const el of Array.from(root.querySelectorAll(\"table,thead,tbody,tfoot,tr,td,th,caption\"))) {\n const div = doc.createElement(\"div\");\n div.append(...Array.from(el.childNodes));\n el.replaceWith(div);\n }\n return placeholders;\n}\n\nfunction tidyMarkdown(md: string): string {\n return md\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(/\\u00A0/g, \" \")\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n}\n\n/**\n * Rebuilds a well-formed document (linkedom misplaces head content that isn't inside <head>): everything\n * before <body> goes into <head>, the rest (including stray content after </body>) into <body>.\n */\nfunction normalizeDocument(html: string): string {\n const open = /<body\\b([^<>]{0,4000})>/i.exec(html);\n if (!open) return `<!DOCTYPE html><html><head></head><body>${html}</body></html>`;\n const strip = (x: string) => x.replace(/<!DOCTYPE[^<>]{0,4000}>|<\\/?(?:html|head|body)\\b[^<>]{0,4000}>/gi, \"\");\n const head = strip(html.slice(0, open.index));\n const body = strip(html.slice(open.index + open[0].length));\n return `<!DOCTYPE html><html><head>${head}</head><body${open[1]}>${body}</body></html>`;\n}\n\n/** Cleans hidden content out of an HTML body and converts it to markdown. */\nexport function htmlToMarkdown(html: string): { markdown: string; removed: number } {\n if (tooManyElements(html)) throw new ContentTooComplexError(`more than ${MAX_ELEMENTS} elements`);\n const doc = parseHTML(normalizeDocument(html)).document as unknown as DomDocument;\n const root = doc.body ?? doc.documentElement;\n const state: CleanState = { removed: 0, sheet: stylesheetEffects(doc) };\n const rootStyle = styleOf(root, state);\n const base: Inherited = { color: null, bg: null, bgUncertain: false, clipText: false, fontPx: DEFAULT_FONT_PX, opacity: 1, invisible: false };\n const rootCtx = childContext(root, rootStyle, base, state);\n if (root.hasAttribute(\"hidden\") || isCollapsed(rootStyle) || rootCtx.opacity < MIN_OPACITY) {\n return { markdown: \"\", removed: hasText(root) ? 1 : 0 };\n }\n if (!rootCtx.color) rootCtx.color = normalizeColor(root.getAttribute(\"text\"));\n cleanTree(root, rootCtx, state);\n flattenDeepNesting(root);\n const tables = prepareTables(doc, root);\n let md = turndown().turndown(root.innerHTML);\n for (const [key, table] of tables) md = md.replace(key, `\\n\\n${table}\\n\\n`);\n const stripped = stripInvisible(md);\n return { markdown: tidyMarkdown(stripped.text), removed: state.removed + stripped.removed };\n}\n\n/** Cleans a text/plain body. */\nexport function cleanPlainText(text: string): { text: string; removed: number } {\n const stripped = stripInvisible(text);\n return { text: tidyMarkdown(stripped.text), removed: stripped.removed };\n}\n\n// ───────────── Signals ─────────────\n\n/** Drops RFC 5322 comments (nested parentheses) and the contents of quoted strings, in one pass. */\nfunction withoutCommentsAndQuotes(s: string): string {\n let out = \"\";\n let depth = 0;\n let quoted = false;\n for (let i = 0; i < s.length; i++) {\n const c = s[i]!;\n if (c === \"\\\\\") {\n i++;\n continue;\n }\n if (quoted) {\n if (c === '\"') {\n quoted = false;\n out += '\"';\n }\n } else if (c === '\"' && depth === 0) {\n quoted = true;\n out += '\"';\n } else if (c === \"(\") {\n depth++;\n } else if (c === \")\" && depth > 0) {\n if (--depth === 0) out += \" \";\n } else if (depth === 0) {\n out += c;\n }\n }\n return out;\n}\n\n/**\n * SPF/DKIM/DMARC from the topmost Authentication-Results header only, which Gmail adds on receipt\n * (authserv-id mx.google.com). Lower headers can be supplied by the sender and never fill gaps. Comments\n * and quoted strings are removed first, and results are read only at the start of each resinfo.\n */\nexport function parseAuthResults(header: string | null): ContentSignals[\"auth\"] {\n if (!header) return null;\n // Unfold continuation lines, then take the first header (several are joined with \"\\n\").\n const top = header.slice(0, 8192).replace(/\\r?\\n[ \\t]+/g, \" \").split(/\\r?\\n/)[0] ?? \"\";\n const s = withoutCommentsAndQuotes(top);\n const [servId = \"\", ...resinfo] = s.split(\";\");\n if (!/^(?:[a-z0-9-]+\\.)*google\\.com$/i.test(servId.trim().split(/\\s+/)[0] ?? \"\")) return null;\n const result = (method: string) => {\n for (const r of resinfo) {\n const m = new RegExp(`^\\\\s*${method}\\\\s*=\\\\s*([a-z]+)`, \"i\").exec(r);\n if (m) return m[1]!.toLowerCase();\n }\n return null;\n };\n return { spf: result(\"spf\"), dkim: result(\"dkim\"), dmarc: result(\"dmarc\") };\n}\n\n/** Consumer mailbox domains: senders on the same domain are still other people. */\nconst CONSUMER_DOMAINS = new Set([\"gmail.com\", \"googlemail.com\"]);\n\n/** Lower-cased address; Gmail addresses ignore dots and +tags in the local part, googlemail.com ≡ gmail.com. */\nfunction canonicalAddress(email: string): { local: string; domain: string } {\n const e = email.trim().toLowerCase();\n const at = e.lastIndexOf(\"@\");\n let local = e.slice(0, at);\n let domain = e.slice(at + 1);\n if (CONSUMER_DOMAINS.has(domain)) {\n domain = \"gmail.com\";\n local = local.replace(/\\+.*$/, \"\").replace(/\\./g, \"\");\n }\n return { local, domain };\n}\n\n/** Sender outside the account's organization (subdomains count as inside); for consumer Gmail, anyone but the account itself. */\nexport function isExternal(sender: string | null | undefined, accountEmail: string): boolean {\n if (!sender) return false;\n const s = canonicalAddress(sender);\n const own = canonicalAddress(accountEmail);\n if (own.domain === \"gmail.com\") return s.local !== own.local || s.domain !== own.domain;\n return !(s.domain === own.domain || s.domain.endsWith(`.${own.domain}`));\n}\n\ninterface Pattern {\n re: RegExp;\n /** Skip the hit when its clause is negated (\"we will never ask you to share your password\"). */\n negatable?: boolean;\n}\n\nconst SUSPICIOUS: Pattern[] = [\n {\n re: /\\b(?:ignore|disregard|forget|override)\\s+(?:all\\s+|any\\s+|the\\s+|your\\s+)*(?:previous|prior|above|earlier|preceding|existing)\\s+(?:instructions?|prompts?|directions|rules|guidelines|messages)\\b/i,\n negatable: true,\n },\n // Persona switches, not \"you are now a member/subscribed\".\n { re: /\\byou\\s+are\\s+now\\s+(?:an?\\s+(?:ai|assistant|agent|chatbot|language\\s+model|llm)\\b|acting\\s+as\\b|in\\s+(?:developer|god|admin|debug|dan|jailbreak)\\s+mode\\b|dan\\b|(?:the|my)\\s+(?:assistant|agent)\\b)/i },\n // Requests about a system prompt, not mentions of the term.\n {\n re: /\\b(?:reveal|print|show|repeat|output|paste|share|send|leak|ignore|disregard|override|bypass)\\s+(?:me\\s+)?(?:your|the|this)\\s+(?:system\\s+prompt|hidden\\s+instructions|initial\\s+instructions)\\b|\\bnew\\s+system\\s+prompt\\b/i,\n negatable: true,\n },\n { re: /\\bnew\\s+instructions\\s*:/i },\n { re: /\\bforward\\s+(?:all|every|each)\\s+(?:of\\s+(?:the|your|my)\\s+)?(?:e-?mails?|messages|mail|correspondence)\\b/i, negatable: true },\n { re: /\\b(?:do\\s+not|don't|never)\\s+(?:tell|inform|notify|alert|mention\\s+(?:this\\s+)?to)\\s+(?:the\\s+)?(?:user|owner|human|recipient)\\b/i },\n { re: /\\bBEGIN\\s+SYSTEM\\b|\\bEND\\s+SYSTEM\\b|<\\/?system>|\\[\\/?system\\]|<\\|im_start\\|>/i },\n // Transcript role spoofing (\"Assistant: Sure, …\"), not \"System: macOS 15.1\" or a job title.\n { re: /^[ \\t]*(?:assistant|system|ai)[ \\t]*:[ \\t]*(?:you\\b|ignore\\b|disregard\\b|from\\s+now\\b|new\\s+instructions\\b|sure\\b|okay\\b|ok\\b|i\\s+will\\b|i'll\\b|understood\\b)/im },\n { re: /\\b(?:reveal|send|share|leak|exfiltrate|give)\\s+(?:me\\s+)?(?:your|the)\\s+(?:api\\s+keys?|credentials|passwords?|secrets?|tokens?|instructions)\\b/i, negatable: true },\n // Imperatives, not retention notices (\"we will delete all messages older than 90 days\").\n {\n re: /\\b(?:delete|trash|purge)\\s+(?:all|every)\\s+(?:e-?mails?|messages)\\b(?!\\s+(?:and\\s+\\w+\\s+)?(?:older|after|before|from\\s+before|that\\s+are|which\\s+are)\\b)/i,\n negatable: true,\n },\n { re: /\\bnote\\s+to\\s+(?:the\\s+)?(?:ai|assistant|agent|llm)\\b/i },\n];\n\nconst NEGATION = /\\b(?:never|not|no\\s+one|nobody|cannot|won't|don't|doesn't|didn't|isn't|aren't)\\b|n't\\b/i;\n\n/** True when the clause before `index` (back to the sentence start) contains a negation. */\nfunction negated(text: string, index: number): boolean {\n const before = text.slice(Math.max(0, index - 80), index);\n const clause = before.split(/[.!?\\n;:]/).at(-1) ?? \"\";\n return NEGATION.test(clause);\n}\n\n/** Phrases common in prompt-injection attempts. Informational only. */\nexport function suspiciousPhrases(text: string): string[] {\n const hits = new Set<string>();\n for (const { re, negatable } of SUSPICIOUS) {\n const g = new RegExp(re.source, re.flags.includes(\"g\") ? re.flags : re.flags + \"g\");\n for (const m of text.matchAll(g)) {\n if (negatable && negated(text, m.index)) continue;\n hits.add(m[0].replace(/\\s+/g, \" \").trim());\n break;\n }\n }\n return [...hits].slice(0, 5);\n}\n\n// ───────────── Truncation ─────────────\n\n/** Truncates to `max` chars (0 = unlimited) at a paragraph, line or word boundary when one is close. */\nexport function truncateText(text: string, max: number): { text: string; truncated: boolean } {\n if (!max || text.length <= max) return { text, truncated: false };\n let cut = max;\n // Never split a surrogate pair.\n if (/[\\uD800-\\uDBFF]/.test(text[cut - 1] ?? \"\")) cut--;\n const window = text.slice(0, cut);\n const floor = Math.floor(cut * 0.8);\n for (const sep of [\"\\n\\n\", \"\\n\", \" \"]) {\n const i = window.lastIndexOf(sep);\n if (i >= floor) return { text: window.slice(0, i).trimEnd(), truncated: true };\n }\n return { text: window, truncated: true };\n}\n\n// ───────────── Message content ─────────────\n\nexport interface BuiltContent extends MessageContent {\n /** Untruncated length, for the \"truncated\" note. */\n totalChars: number;\n}\n\nconst UNCONVERTIBLE = \"[The HTML body of this message could not be converted to text.]\";\nconst TOO_COMPLEX_NOTE = \"[The HTML version of this message is too complex to display safely; showing the plain-text version.]\";\n/** Larger HTML bodies are not converted (bounded work per message); the text/plain part is used instead. */\nexport const MAX_HTML_CHARS = 500_000;\n\n/**\n * Cleaned, markdown-converted content with signals. Prefers HTML (more faithful), else text/plain. The\n * text/plain part is not used when the HTML's text was all hidden: the human reading HTML never sees it.\n */\nexport function buildContent(parsed: ParsedMessage, opts: { accountEmail: string; maxChars: number }): BuiltContent {\n let body = \"\";\n let removed = 0;\n let allHidden = false;\n let failed = false;\n let note = \"\";\n if (parsed.html && parsed.html.length > MAX_HTML_CHARS) {\n failed = true;\n note = `[The HTML version of this message is too large to convert (${Math.round(parsed.html.length / 1024)} KB); showing the plain-text version.]`;\n } else if (parsed.html && parsed.html.trim()) {\n try {\n const r = htmlToMarkdown(parsed.html);\n body = r.markdown;\n removed = r.removed;\n allHidden = !body && r.removed > 0;\n } catch (err) {\n failed = true;\n if (err instanceof ContentTooComplexError) note = TOO_COMPLEX_NOTE;\n }\n }\n if (!body && !allHidden && parsed.text) {\n const r = cleanPlainText(parsed.text);\n body = r.text;\n removed += r.removed;\n }\n if (!body && failed) body = note ? note.replace(/; showing the plain-text version/, \"\") : UNCONVERTIBLE;\n else if (note) body = `${note}\\n\\n${body}`;\n body = escapeDelimiters(body);\n const subject = stripInvisible(parsed.summary.subject ?? \"\");\n removed += subject.removed;\n const t = truncateText(body, opts.maxChars);\n return {\n body: t.text,\n truncated: t.truncated,\n totalChars: body.length,\n attachments: parsed.attachments,\n signals: {\n hiddenContentRemoved: removed > 0,\n suspiciousInstructions: suspiciousPhrases(`${subject.text}\\n${body}`),\n auth: parseAuthResults(parsed.authenticationResults),\n external: isExternal(parsed.summary.from?.email, opts.accountEmail),\n },\n };\n}\n\n// ───────────── Rendering for agents ─────────────\n\nconst escapeAttr = (s: string) => s.replace(/&/g, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\").replace(/>/g, \">\");\n\n/**\n * Wraps untrusted content in the delimiter: `<email_content from=\"…\" untrusted>` for mail,\n * `<calendar_content organizer=\"…\" untrusted>` for event descriptions. Delimiter tags and look-alikes inside\n * the content are escaped.\n */\nexport function wrapUntrusted(from: string | null | undefined, body: string, tag: UntrustedTag = \"email_content\"): string {\n const attr = tag === \"calendar_content\" ? \"organizer\" : \"from\";\n return `<${tag} ${attr}=\"${escapeAttr(cleanLine(from ?? \"unknown\", 320))}\" untrusted>\\n${escapeDelimiters(body)}\\n</${tag}>`;\n}\n\nconst MAX_LINE_INPUT = 4096;\n\n/** Untrusted header-ish text (subjects, names, snippets) on one line: cleaned, delimiter-escaped, optionally clipped. */\nexport function cleanLine(s: string, max = 0): string {\n // Clip first: header-ish values can be huge, and nothing past the clip is shown anyway.\n const one = escapeDelimiters(stripInvisible(s.slice(0, max ? max * 4 : MAX_LINE_INPUT)).text.replace(/\\s+/g, \" \").trim());\n return max && one.length > max ? one.slice(0, max - 1) + \"…\" : one;\n}\n\nexport function formatAddress(a: Address | null | undefined): string {\n if (!a) return \"(unknown)\";\n const name = a.name ? cleanLine(a.name, 100) : \"\";\n if (!name || name.toLowerCase() === a.email.toLowerCase()) return cleanLine(a.email);\n // A display name that looks like an address (\"<ceo@acme.com>\") must not read as the real sender.\n return /[<>@\"]/.test(name) ? `\"${name.replace(/[<>\"]/g, \"\")}\" <${cleanLine(a.email)}>` : `${name} <${cleanLine(a.email)}>`;\n}\n\nexport const formatAddresses = (list: Address[]) => list.map(formatAddress).join(\", \");\n\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nexport function labelNames(ids: string[], labels: GmailLabel[] | null): string[] {\n const byId = new Map((labels ?? []).map((l) => [l.id, l.name]));\n return ids.map((id) => cleanLine(byId.get(id) ?? id));\n}\n\n/** Only noteworthy signals, on one short line; null when there is nothing to say. */\nexport function signalLine(s: ContentSignals): string | null {\n const parts: string[] = [];\n if (s.auth) {\n const failed = ([\"spf\", \"dkim\", \"dmarc\"] as const).filter((k) => {\n const v = s.auth![k];\n return v !== null && ![\"pass\", \"none\", \"neutral\", \"bestguesspass\"].includes(v);\n });\n if (failed.length) parts.push(`sender authentication failed (${failed.map((k) => `${k.toUpperCase()}=${s.auth![k]}`).join(\", \")})`);\n }\n if (s.external) parts.push(\"external sender\");\n if (s.hiddenContentRemoved) parts.push(\"hidden content removed\");\n if (s.suspiciousInstructions.length) {\n parts.push(`contains instruction-like text (${s.suspiciousInstructions.map((p) => `\"${cleanLine(p, 60)}\"`).join(\", \")})`);\n }\n return parts.length ? `Signals: ${parts.join(\"; \")}` : null;\n}\n\n/** Compact header block + one wrapped body. Every header value is untrusted and goes through cleanLine. */\nexport function renderMessage(summary: MessageSummary, content: BuiltContent, labels: GmailLabel[] | null, maxChars: number): string {\n const lines = [`Message ${cleanLine(summary.id)} (thread ${cleanLine(summary.threadId)})`, `From: ${formatAddress(summary.from)}`];\n if (summary.to.length) lines.push(`To: ${formatAddresses(summary.to)}`);\n if (summary.cc.length) lines.push(`Cc: ${formatAddresses(summary.cc)}`);\n lines.push(`Date: ${cleanLine(summary.date)}`, `Subject: ${cleanLine(summary.subject) || \"(no subject)\"}`);\n if (summary.labelIds.length) lines.push(`Labels: ${labelNames(summary.labelIds, labels).join(\", \")}`);\n if (content.attachments.length) {\n lines.push(\n `Attachments: ${content.attachments\n .map((a) => `${cleanLine(a.filename) || \"(unnamed)\"} (${cleanLine(a.mimeType)}, ${formatSize(a.size)}, attachment_id: ${cleanLine(a.id)})`)\n .join(\"; \")}`,\n );\n }\n const signals = signalLine(content.signals);\n if (signals) lines.push(signals);\n lines.push(wrapUntrusted(summary.from?.email, content.body || \"(empty body)\"));\n if (content.truncated) {\n lines.push(`[Body truncated at ${maxChars} of ${content.totalChars} characters (operator setting maxBodyChars).]`);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Content when cleaning didn't finish in time (see server/mail/pool.ts): the cleaned text/plain part, or a\n * notice. Never the unconverted HTML. Marked truncated, with a note saying why.\n */\nexport function fallbackContent(parsed: ParsedMessage, opts: { accountEmail: string; maxChars: number }): BuiltContent {\n const text = parsed.text ? cleanPlainText(parsed.text.slice(0, MAX_HTML_CHARS)).text : \"\";\n const body = escapeDelimiters(\n text\n ? `[This message is too complex to display safely; showing its plain-text version.]\\n\\n${text}`\n : \"[This message is too complex to display safely. Ask a human to read it in Gmail.]\",\n );\n const subject = stripInvisible(parsed.summary.subject ?? \"\");\n const t = truncateText(body, opts.maxChars);\n return {\n body: t.text,\n truncated: true,\n totalChars: body.length,\n attachments: parsed.attachments,\n signals: {\n hiddenContentRemoved: false,\n suspiciousInstructions: suspiciousPhrases(`${subject.text}\\n${body}`),\n auth: parseAuthResults(parsed.authenticationResults),\n external: isExternal(parsed.summary.from?.email, opts.accountEmail),\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { h as stripInvisible, n as buildContent, u as htmlToMarkdown } from "./content-C1lKMxFS.js";
|
|
3
|
+
import { parentPort } from "node:worker_threads";
|
|
4
|
+
//#region server/mail/content-worker.ts
|
|
5
|
+
const port = parentPort;
|
|
6
|
+
if (port) {
|
|
7
|
+
port.on("message", (task) => {
|
|
8
|
+
try {
|
|
9
|
+
const result = task.kind === "content" ? buildContent(task.parsed, task.opts) : task.kind === "html" ? htmlToMarkdown(task.html) : stripInvisible(task.text).text;
|
|
10
|
+
port.postMessage({
|
|
11
|
+
id: task.id,
|
|
12
|
+
ok: true,
|
|
13
|
+
result
|
|
14
|
+
});
|
|
15
|
+
} catch (err) {
|
|
16
|
+
port.postMessage({
|
|
17
|
+
id: task.id,
|
|
18
|
+
ok: false,
|
|
19
|
+
error: err instanceof Error ? err.message : String(err)
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
port.postMessage({ ready: true });
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export {};
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=content-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-worker.js","names":[],"sources":["../server/mail/content-worker.ts"],"sourcesContent":["// Worker thread for content cleaning (see server/mail/pool.ts). Built as its own entry\n// (dist/content-worker.js); in source mode Node loads this .ts file directly.\n\nimport { parentPort } from \"node:worker_threads\";\nimport type { ParsedMessage } from \"../google/types.ts\";\nimport { buildContent, htmlToMarkdown, stripInvisible } from \"./content.ts\";\n\nexport type ContentTask =\n | { id: number; kind: \"content\"; parsed: ParsedMessage; opts: { accountEmail: string; maxChars: number } }\n | { id: number; kind: \"html\"; html: string }\n | { id: number; kind: \"text\"; text: string };\n\nexport type ContentReply = { ready: true } | { id: number; ok: true; result: unknown } | { id: number; ok: false; error: string };\n\nconst port = parentPort;\nif (port) {\n port.on(\"message\", (task: ContentTask) => {\n try {\n const result =\n task.kind === \"content\" ? buildContent(task.parsed, task.opts) : task.kind === \"html\" ? htmlToMarkdown(task.html) : stripInvisible(task.text).text;\n port.postMessage({ id: task.id, ok: true, result } satisfies ContentReply);\n } catch (err) {\n port.postMessage({ id: task.id, ok: false, error: err instanceof Error ? err.message : String(err) } satisfies ContentReply);\n }\n });\n port.postMessage({ ready: true } satisfies ContentReply);\n}\n"],"mappings":";;;;AAcA,MAAM,OAAO;AACb,IAAI,MAAM;CACR,KAAK,GAAG,YAAY,SAAsB;EACxC,IAAI;GACF,MAAM,SACJ,KAAK,SAAS,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI,IAAI,KAAK,SAAS,SAAS,eAAe,KAAK,IAAI,IAAI,eAAe,KAAK,IAAI,CAAC,CAAC;GAChJ,KAAK,YAAY;IAAE,IAAI,KAAK;IAAI,IAAI;IAAM;GAAO,CAAwB;EAC3E,SAAS,KAAK;GACZ,KAAK,YAAY;IAAE,IAAI,KAAK;IAAI,IAAI;IAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAAE,CAAwB;EAC7H;CACF,CAAC;CACD,KAAK,YAAY,EAAE,OAAO,KAAK,CAAwB;AACzD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as envVar } from "./brand--ZB8jTn1.js";
|
|
3
|
+
import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes, scrypt, timingSafeEqual } from "node:crypto";
|
|
5
|
+
//#region server/crypto.ts
|
|
6
|
+
/**
|
|
7
|
+
* Secrets at rest (refresh tokens, webhook secrets, Google client secret) are AES-256-GCM encrypted.
|
|
8
|
+
* Key source: XAQ_MASTER_KEY (AGENTINBOX_MASTER_KEY before the rename; base64, 32 bytes) or `<dataDir>/master.key` (generated, mode 0600).
|
|
9
|
+
* Ciphertext format: "v1:" + base64(iv[12] | tag[16] | ciphertext).
|
|
10
|
+
*/
|
|
11
|
+
var Crypto = class Crypto {
|
|
12
|
+
key;
|
|
13
|
+
constructor(key) {
|
|
14
|
+
if (key.length !== 32) throw new Error("master key must be 32 bytes");
|
|
15
|
+
this.key = key;
|
|
16
|
+
}
|
|
17
|
+
static load(keyFile) {
|
|
18
|
+
const fromEnv = envVar("MASTER_KEY");
|
|
19
|
+
if (fromEnv) return new Crypto(Buffer.from(fromEnv, "base64"));
|
|
20
|
+
if (!existsSync(keyFile)) writeFileSync(keyFile, randomBytes(32).toString("base64") + "\n", { mode: 384 });
|
|
21
|
+
chmodSync(keyFile, 384);
|
|
22
|
+
return new Crypto(Buffer.from(readFileSync(keyFile, "utf8").trim(), "base64"));
|
|
23
|
+
}
|
|
24
|
+
encrypt(plain) {
|
|
25
|
+
const iv = randomBytes(12);
|
|
26
|
+
const cipher = createCipheriv("aes-256-gcm", this.key, iv);
|
|
27
|
+
const ct = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
|
|
28
|
+
return "v1:" + Buffer.concat([
|
|
29
|
+
iv,
|
|
30
|
+
cipher.getAuthTag(),
|
|
31
|
+
ct
|
|
32
|
+
]).toString("base64");
|
|
33
|
+
}
|
|
34
|
+
decrypt(enc) {
|
|
35
|
+
if (!enc.startsWith("v1:")) throw new Error("unknown ciphertext version");
|
|
36
|
+
const buf = Buffer.from(enc.slice(3), "base64");
|
|
37
|
+
const decipher = createDecipheriv("aes-256-gcm", this.key, buf.subarray(0, 12));
|
|
38
|
+
decipher.setAuthTag(buf.subarray(12, 28));
|
|
39
|
+
return Buffer.concat([decipher.update(buf.subarray(28)), decipher.final()]).toString("utf8");
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
/** Fast hash for high-entropy tokens (API keys, session tokens). */
|
|
43
|
+
const sha256 = (s) => createHash("sha256").update(s).digest("hex");
|
|
44
|
+
const scryptAsync = (password, salt, length, opts) => new Promise((resolve, reject) => scrypt(password, salt, length, opts, (err, key) => err ? reject(err) : resolve(key)));
|
|
45
|
+
/** Like hashPassword, but runs scrypt on the thread pool instead of blocking the event loop. */
|
|
46
|
+
async function hashPasswordAsync(password) {
|
|
47
|
+
const salt = randomBytes(16);
|
|
48
|
+
const hash = await scryptAsync(password, salt, 32, {
|
|
49
|
+
N: 16384,
|
|
50
|
+
r: 8,
|
|
51
|
+
p: 1
|
|
52
|
+
});
|
|
53
|
+
return `scrypt$16384$8$1$${salt.toString("base64")}$${hash.toString("base64")}`;
|
|
54
|
+
}
|
|
55
|
+
/** Like verifyPassword, but runs scrypt on the thread pool instead of blocking the event loop. */
|
|
56
|
+
async function verifyPasswordAsync(password, stored) {
|
|
57
|
+
const [alg, n, r, p, salt, hash] = stored.split("$");
|
|
58
|
+
if (alg !== "scrypt" || !salt || !hash) return false;
|
|
59
|
+
const expected = Buffer.from(hash, "base64");
|
|
60
|
+
const actual = await scryptAsync(password, Buffer.from(salt, "base64"), expected.length, {
|
|
61
|
+
N: Number(n),
|
|
62
|
+
r: Number(r),
|
|
63
|
+
p: Number(p)
|
|
64
|
+
});
|
|
65
|
+
return timingSafeEqual(actual, expected);
|
|
66
|
+
}
|
|
67
|
+
function safeEqual(a, b) {
|
|
68
|
+
const ab = Buffer.from(a);
|
|
69
|
+
const bb = Buffer.from(b);
|
|
70
|
+
return ab.length === bb.length && timingSafeEqual(ab, bb);
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { verifyPasswordAsync as a, sha256 as i, hashPasswordAsync as n, safeEqual as r, Crypto as t };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=crypto-fv2fj3S8.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-fv2fj3S8.js","names":[],"sources":["../server/crypto.ts"],"sourcesContent":["import { createCipheriv, createDecipheriv, createHash, randomBytes, type ScryptOptions, scrypt, scryptSync, timingSafeEqual } from \"node:crypto\";\nimport { chmodSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { envVar } from \"./brand.ts\";\n\n/**\n * Secrets at rest (refresh tokens, webhook secrets, Google client secret) are AES-256-GCM encrypted.\n * Key source: XAQ_MASTER_KEY (AGENTINBOX_MASTER_KEY before the rename; base64, 32 bytes) or `<dataDir>/master.key` (generated, mode 0600).\n * Ciphertext format: \"v1:\" + base64(iv[12] | tag[16] | ciphertext).\n */\nexport class Crypto {\n private readonly key: Buffer;\n\n constructor(key: Buffer) {\n if (key.length !== 32) throw new Error(\"master key must be 32 bytes\");\n this.key = key;\n }\n\n static load(keyFile: string): Crypto {\n const fromEnv = envVar(\"MASTER_KEY\");\n if (fromEnv) return new Crypto(Buffer.from(fromEnv, \"base64\"));\n if (!existsSync(keyFile)) {\n writeFileSync(keyFile, randomBytes(32).toString(\"base64\") + \"\\n\", { mode: 0o600 });\n }\n chmodSync(keyFile, 0o600);\n return new Crypto(Buffer.from(readFileSync(keyFile, \"utf8\").trim(), \"base64\"));\n }\n\n encrypt(plain: string): string {\n const iv = randomBytes(12);\n const cipher = createCipheriv(\"aes-256-gcm\", this.key, iv);\n const ct = Buffer.concat([cipher.update(plain, \"utf8\"), cipher.final()]);\n return \"v1:\" + Buffer.concat([iv, cipher.getAuthTag(), ct]).toString(\"base64\");\n }\n\n decrypt(enc: string): string {\n if (!enc.startsWith(\"v1:\")) throw new Error(\"unknown ciphertext version\");\n const buf = Buffer.from(enc.slice(3), \"base64\");\n const decipher = createDecipheriv(\"aes-256-gcm\", this.key, buf.subarray(0, 12));\n decipher.setAuthTag(buf.subarray(12, 28));\n return Buffer.concat([decipher.update(buf.subarray(28)), decipher.final()]).toString(\"utf8\");\n }\n}\n\n/** Fast hash for high-entropy tokens (API keys, session tokens). */\nexport const sha256 = (s: string): string => createHash(\"sha256\").update(s).digest(\"hex\");\n\n/** Password hashing for the admin password. Format: \"scrypt$N$r$p$salt$hash\". */\nexport function hashPassword(password: string): string {\n const salt = randomBytes(16);\n const hash = scryptSync(password, salt, 32, { N: 16384, r: 8, p: 1 });\n return `scrypt$16384$8$1$${salt.toString(\"base64\")}$${hash.toString(\"base64\")}`;\n}\n\nexport function verifyPassword(password: string, stored: string): boolean {\n const [alg, n, r, p, salt, hash] = stored.split(\"$\");\n if (alg !== \"scrypt\" || !salt || !hash) return false;\n const expected = Buffer.from(hash, \"base64\");\n const actual = scryptSync(password, Buffer.from(salt, \"base64\"), expected.length, {\n N: Number(n),\n r: Number(r),\n p: Number(p),\n });\n return timingSafeEqual(actual, expected);\n}\n\nconst scryptAsync = (password: string, salt: Buffer, length: number, opts: ScryptOptions) =>\n new Promise<Buffer>((resolve, reject) => scrypt(password, salt, length, opts, (err, key) => (err ? reject(err) : resolve(key))));\n\n/** Like hashPassword, but runs scrypt on the thread pool instead of blocking the event loop. */\nexport async function hashPasswordAsync(password: string): Promise<string> {\n const salt = randomBytes(16);\n const hash = await scryptAsync(password, salt, 32, { N: 16384, r: 8, p: 1 });\n return `scrypt$16384$8$1$${salt.toString(\"base64\")}$${hash.toString(\"base64\")}`;\n}\n\n/** Like verifyPassword, but runs scrypt on the thread pool instead of blocking the event loop. */\nexport async function verifyPasswordAsync(password: string, stored: string): Promise<boolean> {\n const [alg, n, r, p, salt, hash] = stored.split(\"$\");\n if (alg !== \"scrypt\" || !salt || !hash) return false;\n const expected = Buffer.from(hash, \"base64\");\n const actual = await scryptAsync(password, Buffer.from(salt, \"base64\"), expected.length, { N: Number(n), r: Number(r), p: Number(p) });\n return timingSafeEqual(actual, expected);\n}\n\nexport function safeEqual(a: string, b: string): boolean {\n const ab = Buffer.from(a);\n const bb = Buffer.from(b);\n return ab.length === bb.length && timingSafeEqual(ab, bb);\n}\n"],"mappings":";;;;;;;;;;AASA,IAAa,SAAb,MAAa,OAAO;CAClB;CAEA,YAAY,KAAa;EACvB,IAAI,IAAI,WAAW,IAAI,MAAM,IAAI,MAAM,6BAA6B;EACpE,KAAK,MAAM;CACb;CAEA,OAAO,KAAK,SAAyB;EACnC,MAAM,UAAU,OAAO,YAAY;EACnC,IAAI,SAAS,OAAO,IAAI,OAAO,OAAO,KAAK,SAAS,QAAQ,CAAC;EAC7D,IAAI,CAAC,WAAW,OAAO,GACrB,cAAc,SAAS,YAAY,EAAE,CAAC,CAAC,SAAS,QAAQ,IAAI,MAAM,EAAE,MAAM,IAAM,CAAC;EAEnF,UAAU,SAAS,GAAK;EACxB,OAAO,IAAI,OAAO,OAAO,KAAK,aAAa,SAAS,MAAM,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC;CAC/E;CAEA,QAAQ,OAAuB;EAC7B,MAAM,KAAK,YAAY,EAAE;EACzB,MAAM,SAAS,eAAe,eAAe,KAAK,KAAK,EAAE;EACzD,MAAM,KAAK,OAAO,OAAO,CAAC,OAAO,OAAO,OAAO,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;EACvE,OAAO,QAAQ,OAAO,OAAO;GAAC;GAAI,OAAO,WAAW;GAAG;EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ;CAC/E;CAEA,QAAQ,KAAqB;EAC3B,IAAI,CAAC,IAAI,WAAW,KAAK,GAAG,MAAM,IAAI,MAAM,4BAA4B;EACxE,MAAM,MAAM,OAAO,KAAK,IAAI,MAAM,CAAC,GAAG,QAAQ;EAC9C,MAAM,WAAW,iBAAiB,eAAe,KAAK,KAAK,IAAI,SAAS,GAAG,EAAE,CAAC;EAC9E,SAAS,WAAW,IAAI,SAAS,IAAI,EAAE,CAAC;EACxC,OAAO,OAAO,OAAO,CAAC,SAAS,OAAO,IAAI,SAAS,EAAE,CAAC,GAAG,SAAS,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM;CAC7F;AACF;;AAGA,MAAa,UAAU,MAAsB,WAAW,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK;AAqBxF,MAAM,eAAe,UAAkB,MAAc,QAAgB,SACnE,IAAI,SAAiB,SAAS,WAAW,OAAO,UAAU,MAAM,QAAQ,OAAO,KAAK,QAAS,MAAM,OAAO,GAAG,IAAI,QAAQ,GAAG,CAAE,CAAC;;AAGjI,eAAsB,kBAAkB,UAAmC;CACzE,MAAM,OAAO,YAAY,EAAE;CAC3B,MAAM,OAAO,MAAM,YAAY,UAAU,MAAM,IAAI;EAAE,GAAG;EAAO,GAAG;EAAG,GAAG;CAAE,CAAC;CAC3E,OAAO,oBAAoB,KAAK,SAAS,QAAQ,EAAE,GAAG,KAAK,SAAS,QAAQ;AAC9E;;AAGA,eAAsB,oBAAoB,UAAkB,QAAkC;CAC5F,MAAM,CAAC,KAAK,GAAG,GAAG,GAAG,MAAM,QAAQ,OAAO,MAAM,GAAG;CACnD,IAAI,QAAQ,YAAY,CAAC,QAAQ,CAAC,MAAM,OAAO;CAC/C,MAAM,WAAW,OAAO,KAAK,MAAM,QAAQ;CAC3C,MAAM,SAAS,MAAM,YAAY,UAAU,OAAO,KAAK,MAAM,QAAQ,GAAG,SAAS,QAAQ;EAAE,GAAG,OAAO,CAAC;EAAG,GAAG,OAAO,CAAC;EAAG,GAAG,OAAO,CAAC;CAAE,CAAC;CACrI,OAAO,gBAAgB,QAAQ,QAAQ;AACzC;AAEA,SAAgB,UAAU,GAAW,GAAoB;CACvD,MAAM,KAAK,OAAO,KAAK,CAAC;CACxB,MAAM,KAAK,OAAO,KAAK,CAAC;CACxB,OAAO,GAAG,WAAW,GAAG,UAAU,gBAAgB,IAAI,EAAE;AAC1D"}
|