@agent-native/core 0.78.8 → 0.79.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 (181) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +25 -0
  3. package/corpus/core/docs/content/actions.md +4 -2
  4. package/corpus/core/docs/content/agent-surfaces.md +9 -0
  5. package/corpus/core/docs/content/extensions.md +10 -0
  6. package/corpus/core/docs/content/generative-ui.md +217 -0
  7. package/corpus/core/docs/content/key-concepts.md +2 -2
  8. package/corpus/core/docs/content/mcp-apps.md +3 -5
  9. package/corpus/core/docs/content/native-chat-ui.md +9 -5
  10. package/corpus/core/docs/content/tracking.md +9 -3
  11. package/corpus/core/package.json +1 -1
  12. package/corpus/core/src/action-ui.ts +1 -0
  13. package/corpus/core/src/client/analytics.ts +195 -12
  14. package/corpus/core/src/client/chat/index.ts +1 -0
  15. package/corpus/core/src/client/chat/tool-call-display.tsx +5 -2
  16. package/corpus/core/src/client/chat/widgets/InlineExtensionWidget.tsx +139 -0
  17. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +27 -1
  18. package/corpus/core/src/client/conversation/AgentConversation.tsx +38 -0
  19. package/corpus/core/src/client/conversation/code-agent-transcript.ts +9 -0
  20. package/corpus/core/src/client/conversation/types.ts +4 -0
  21. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +27 -5
  22. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +26 -5
  23. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +654 -0
  24. package/corpus/core/src/client/extensions/iframe-bridge.ts +30 -0
  25. package/corpus/core/src/client/extensions/index.ts +5 -0
  26. package/corpus/core/src/client/index.ts +1 -0
  27. package/corpus/core/src/client/session-replay.ts +89 -14
  28. package/corpus/core/src/code-agents/transcript-normalizer.ts +14 -0
  29. package/corpus/core/src/extensions/actions.ts +218 -1
  30. package/corpus/core/src/extensions/html-shell.ts +70 -3
  31. package/corpus/core/src/extensions/routes.ts +12 -4
  32. package/corpus/core/src/index.browser.ts +1 -0
  33. package/corpus/core/src/index.ts +1 -0
  34. package/corpus/core/src/mcp/build-server.ts +1 -1
  35. package/corpus/core/src/mcp/embed-app.ts +11 -1
  36. package/corpus/core/src/server/agent-chat-plugin.ts +21 -9
  37. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
  40. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +198 -59
  41. package/corpus/templates/analytics/AGENTS.md +12 -0
  42. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +1105 -0
  43. package/corpus/templates/analytics/actions/dashboard-panel-order.ts +169 -0
  44. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +89 -6
  45. package/corpus/templates/analytics/actions/mutate-dashboard.ts +333 -0
  46. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +214 -0
  47. package/corpus/templates/analytics/actions/send-dashboard-report-now.ts +48 -21
  48. package/corpus/templates/analytics/actions/update-dashboard.ts +193 -100
  49. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +11 -0
  50. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -1
  51. package/corpus/templates/analytics/app/global.css +81 -10
  52. package/corpus/templates/analytics/app/i18n-data.ts +249 -4
  53. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +3 -3
  54. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +41 -1
  55. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +1 -1
  56. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +4 -4
  57. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +48 -18
  58. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +32 -0
  59. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +204 -70
  60. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +1101 -227
  61. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +160 -133
  62. package/corpus/templates/analytics/changelog/2026-06-26-agents-can-now-edit-dashboards-through-a-typed-mutation-scri.md +6 -0
  63. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-bar-chart-hovers-stay-subtle-in-dark-mode.md +6 -0
  64. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-chart-moves-are-now-handled-by-panel-id-making-sim.md +6 -0
  65. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-charts-drag-smoothly-with-stable-cards-inactive-ch.md +6 -0
  66. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-charts-show-a-refresh-spinner-while-keeping-existi.md +6 -0
  67. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-edits-stay-stable-while-chart-order-and-deletions-.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-email-reports-queue-immediate-sends.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-06-26-explorer-dashboards-now-drag-charts-with-a-stable-preview-an.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-06-26-session-replay-playback-can-now-be-toggled-by-clicking-the-r.md +6 -0
  71. package/corpus/templates/analytics/changelog/2026-06-26-session-replays-now-open-from-the-full-row-and-play-with-tim.md +6 -0
  72. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +21 -0
  73. package/corpus/templates/analytics/server/lib/dashboard-report.ts +41 -17
  74. package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
  75. package/dist/action-ui.d.ts +1 -0
  76. package/dist/action-ui.d.ts.map +1 -1
  77. package/dist/action-ui.js +1 -0
  78. package/dist/action-ui.js.map +1 -1
  79. package/dist/client/analytics.d.ts.map +1 -1
  80. package/dist/client/analytics.js +173 -12
  81. package/dist/client/analytics.js.map +1 -1
  82. package/dist/client/chat/index.d.ts +1 -1
  83. package/dist/client/chat/index.d.ts.map +1 -1
  84. package/dist/client/chat/index.js +1 -1
  85. package/dist/client/chat/index.js.map +1 -1
  86. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  87. package/dist/client/chat/tool-call-display.js +3 -1
  88. package/dist/client/chat/tool-call-display.js.map +1 -1
  89. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts +17 -0
  90. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts.map +1 -0
  91. package/dist/client/chat/widgets/InlineExtensionWidget.js +85 -0
  92. package/dist/client/chat/widgets/InlineExtensionWidget.js.map +1 -0
  93. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  94. package/dist/client/chat/widgets/builtin-tool-renderers.js +15 -2
  95. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  96. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  97. package/dist/client/conversation/AgentConversation.js +33 -0
  98. package/dist/client/conversation/AgentConversation.js.map +1 -1
  99. package/dist/client/conversation/code-agent-transcript.js +8 -0
  100. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  101. package/dist/client/conversation/types.d.ts +4 -0
  102. package/dist/client/conversation/types.d.ts.map +1 -1
  103. package/dist/client/conversation/types.js.map +1 -1
  104. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  105. package/dist/client/extensions/EmbeddedExtension.js +29 -1
  106. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  107. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  108. package/dist/client/extensions/ExtensionViewer.js +28 -1
  109. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  110. package/dist/client/extensions/InlineExtensionFrame.d.ts +25 -0
  111. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -0
  112. package/dist/client/extensions/InlineExtensionFrame.js +488 -0
  113. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -0
  114. package/dist/client/extensions/iframe-bridge.d.ts +2 -0
  115. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  116. package/dist/client/extensions/iframe-bridge.js +23 -0
  117. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  118. package/dist/client/extensions/index.d.ts +1 -0
  119. package/dist/client/extensions/index.d.ts.map +1 -1
  120. package/dist/client/extensions/index.js +1 -0
  121. package/dist/client/extensions/index.js.map +1 -1
  122. package/dist/client/index.d.ts +1 -1
  123. package/dist/client/index.d.ts.map +1 -1
  124. package/dist/client/index.js +1 -1
  125. package/dist/client/index.js.map +1 -1
  126. package/dist/client/session-replay.d.ts +11 -1
  127. package/dist/client/session-replay.d.ts.map +1 -1
  128. package/dist/client/session-replay.js +74 -14
  129. package/dist/client/session-replay.js.map +1 -1
  130. package/dist/code-agents/transcript-normalizer.d.ts +2 -0
  131. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  132. package/dist/code-agents/transcript-normalizer.js +8 -0
  133. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  134. package/dist/collab/awareness.d.ts +2 -2
  135. package/dist/collab/awareness.d.ts.map +1 -1
  136. package/dist/collab/routes.d.ts +2 -2
  137. package/dist/extensions/actions.d.ts.map +1 -1
  138. package/dist/extensions/actions.js +200 -1
  139. package/dist/extensions/actions.js.map +1 -1
  140. package/dist/extensions/html-shell.d.ts.map +1 -1
  141. package/dist/extensions/html-shell.js +70 -3
  142. package/dist/extensions/html-shell.js.map +1 -1
  143. package/dist/extensions/routes.d.ts.map +1 -1
  144. package/dist/extensions/routes.js +11 -4
  145. package/dist/extensions/routes.js.map +1 -1
  146. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  147. package/dist/index.browser.d.ts +1 -1
  148. package/dist/index.browser.d.ts.map +1 -1
  149. package/dist/index.browser.js +1 -1
  150. package/dist/index.browser.js.map +1 -1
  151. package/dist/index.d.ts +1 -1
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js +1 -1
  154. package/dist/index.js.map +1 -1
  155. package/dist/mcp/build-server.js +1 -1
  156. package/dist/mcp/build-server.js.map +1 -1
  157. package/dist/mcp/embed-app.d.ts.map +1 -1
  158. package/dist/mcp/embed-app.js +11 -1
  159. package/dist/mcp/embed-app.js.map +1 -1
  160. package/dist/observability/routes.d.ts +7 -7
  161. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  162. package/dist/resources/handlers.d.ts +2 -2
  163. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  164. package/dist/server/agent-chat-plugin.js +21 -9
  165. package/dist/server/agent-chat-plugin.js.map +1 -1
  166. package/dist/server/agent-engine-api-key-route.d.ts +2 -2
  167. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  168. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  169. package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
  170. package/docs/content/actions.md +4 -2
  171. package/docs/content/agent-surfaces.md +9 -0
  172. package/docs/content/extensions.md +10 -0
  173. package/docs/content/generative-ui.md +217 -0
  174. package/docs/content/key-concepts.md +2 -2
  175. package/docs/content/mcp-apps.md +3 -5
  176. package/docs/content/native-chat-ui.md +9 -5
  177. package/docs/content/tracking.md +9 -3
  178. package/package.json +1 -1
  179. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  180. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  181. package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
@@ -1 +1 @@
1
- {"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAAA,MAAM,yBAAyB,GAC7B,mXAAmX,CAAC;AAEtX,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,QAAQ;IACR,0BAA0B;IAC1B,4BAA4B;IAC5B,oBAAoB;IACpB,oBAAoB;IACpB,gCAAgC;IAChC,0CAA0C;CAC3C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,yBAAyB,oBAAoB,yBAAyB,GAAG,CAAC;AAEjH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAoEnE,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,SAAiB,EACjB,MAAe,EACf,WAAoB,EACpB,OAAgC;IAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,mBAAmB,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAChC,OAAO,IAAI;QACT,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,OAAO;KACd,CACF,CAAC;IAEF,OAAO;iBACQ,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;;;;wDAIU,yBAAyB;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,uDAAuD,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmFlI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA+PK,eAAe;8BACV,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2NjC,WAAW,CAAC,CAAC,CAAC,uBAAuB,eAAe,mBAAmB,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE;GACnG,OAAO;;;;;;;;;;SAUD,CAAC;AACV,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["const EXTENSION_IFRAME_CSP_BASE =\n \"default-src 'none'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data: blob:; media-src 'self' data: blob:; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none';\";\n\nexport const EXTENSION_FRAME_ANCESTORS = [\n \"'self'\",\n \"https://agent-native.com\",\n \"https://*.agent-native.com\",\n \"http://localhost:*\",\n \"http://127.0.0.1:*\",\n \"https://*.claudemcpcontent.com\",\n \"https://*.web-sandbox.oaiusercontent.com\",\n].join(\" \");\n\nexport const EXTENSION_IFRAME_CSP = `${EXTENSION_IFRAME_CSP_BASE} frame-ancestors ${EXTENSION_FRAME_ANCESTORS};`;\n\nexport const EXTENSION_IFRAME_META_CSP = EXTENSION_IFRAME_CSP_BASE;\n\n/**\n * SECURITY — EXTENSION CONTENT IS UNTRUSTED.\n *\n * `${content}` (line ~Body) interpolates raw HTML/JS authored by a user. This\n * file is the boundary between framework-controlled HTML and user-controlled\n * HTML. Two non-negotiable invariants for every change here:\n *\n * 1. The iframe MUST be rendered with a `sandbox` attribute that does NOT\n * include `allow-same-origin`. The viewer (`ExtensionViewer.tsx`,\n * `EmbeddedExtension.tsx`) sets `sandbox=\"allow-scripts allow-forms\"` —\n * and that is the only acceptable shape. Adding `allow-same-origin`\n * would give the extension full DOM access to the parent window via\n * cross-frame script.\n *\n * 2. Every reachable parent action must treat the postMessage payload as\n * hostile. The bridge in `iframe-bridge.ts` enforces a path allowlist,\n * header sanitization, and method allowlist; do not relax those gates\n * for \"convenience\" in this file or any caller.\n *\n * For the trust model rationale, see audit 05-tools-sandbox.md (C1) and the\n * `extensions` skill. When in doubt, fail closed.\n *\n * BACKWARDS COMPAT — the iframe injects helpers under both their canonical\n * `extension*` names (`extensionFetch`, `extensionData`, `extensionId`,\n * `extensionBinding`) AND legacy `tool*` aliases (`toolFetch`, `toolData`,\n * `toolId`, `toolBinding`) so existing user-authored extension bodies that\n * pre-date the rename keep working. Same for layout opt-ins:\n * `data-extension-layout=\"full-bleed\"` / `data-extension-padding=\"none\"` /\n * class `agent-native-extension-bleed` / CSS var\n * `--agent-native-extension-padding` are canonical; the `data-tool-*`,\n * `agent-native-tool-bleed`, and `--agent-native-tool-padding` variants are\n * accepted as aliases.\n */\n\nexport interface ExtensionRenderBinding {\n /** Email of the user who authored / owns the extension. */\n authorEmail: string;\n /** Email of the user currently viewing/running the extension. */\n viewerEmail: string;\n /** True when viewer === author. */\n isAuthor: boolean;\n /**\n * Resolved role for the viewer (\"owner\" | \"admin\" | \"editor\" | \"viewer\").\n *\n * TODO(security, audit H4): the host-side bridge does not yet gate any\n * helper based on this value — every viewer gets the same powers as the\n * author. The role is plumbed through so a follow-up PR can constrain\n * `appAction` / `dbExec` / `extensionFetch` for non-author viewers (and\n * eventually require an explicit consent step before running a shared\n * extension, audit C1). For now this is metadata only.\n */\n role: \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n /** Where the extension definition came from. Database extensions are the default. */\n source?: \"database\" | \"local-files\";\n /**\n * Fine-grained helper permissions for local file extensions. Database-backed\n * extensions keep using the role table in the parent bridge.\n */\n permissions?: {\n appActions?: string[];\n extensionData?: boolean;\n sql?: boolean;\n externalFetch?: boolean;\n };\n}\n\nexport function buildExtensionHtml(\n content: string,\n themeVars: string,\n isDark: boolean,\n extensionId?: string,\n binding?: ExtensionRenderBinding,\n): string {\n const extensionIdJson = JSON.stringify(extensionId ?? \"\");\n const extensionIdAttr = escapeHtmlAttribute(extensionId ?? \"\");\n const bindingJson = JSON.stringify(\n binding ?? {\n authorEmail: \"\",\n viewerEmail: \"\",\n isAuthor: true,\n role: \"owner\",\n },\n );\n\n return `<!DOCTYPE html>\n<html lang=\"en\"${isDark ? ' class=\"dark\"' : \"\"}>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Security-Policy\" content=\"${EXTENSION_IFRAME_META_CSP}\" />\n ${binding && !binding.isAuthor ? `<meta name=\"agent-native-extension-author\" content=\"${escapeHtmlAttribute(binding.authorEmail)}\" />` : \"\"}\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300..700&display=swap\" rel=\"stylesheet\" />\n <script>\n var _extensionErrors = [];\n var _extensionErrorDetails = [];\n var _consoleLogs = [];\n var _networkLogs = [];\n\n var _origConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info };\n function _wrapConsole(level, orig) {\n return function() {\n var args = Array.prototype.slice.call(arguments);\n var msg = args.map(function(a) {\n try { return typeof a === 'object' ? JSON.stringify(a) : String(a); }\n catch(e) { return String(a); }\n }).join(' ');\n if (_consoleLogs.length >= 50) _consoleLogs.shift();\n _consoleLogs.push({ level: level, message: msg });\n orig.apply(console, arguments);\n };\n }\n console.log = _wrapConsole('log', _origConsole.log);\n console.warn = _wrapConsole('warn', _origConsole.warn);\n console.error = _wrapConsole('error', _origConsole.error);\n console.info = _wrapConsole('info', _origConsole.info);\n\n function _collectError(message, stack) {\n if (!message) return;\n if (message === 'Script error.' || message === 'Script error') message = 'Runtime error';\n if (_extensionErrors.indexOf(message) !== -1) return;\n _extensionErrors.push(message);\n _extensionErrorDetails.push({ message: message, stack: stack || '' });\n _renderErrorToast();\n }\n\n function _renderErrorToast() {\n var toast = document.getElementById('__extension-error-toast');\n if (!toast) return;\n var msg = document.getElementById('__extension-error-msg');\n if (!msg || _extensionErrors.length === 0) return;\n if (_extensionErrors.length === 1) {\n msg.textContent = _extensionErrors[0];\n } else {\n msg.textContent = _extensionErrors.length + ' errors — ' + _extensionErrors[_extensionErrors.length - 1];\n }\n toast.style.display = 'block';\n }\n\n window.addEventListener('error', function(event) {\n var msg = event.message || '';\n if (msg.indexOf('Alpine Expression Error') === 0) return;\n var stack = event.error && event.error.stack ? event.error.stack : '';\n _collectError(msg, stack);\n });\n\n window.addEventListener('unhandledrejection', function(event) {\n var msg = event.reason && event.reason.message ? event.reason.message : String(event.reason);\n var stack = event.reason && event.reason.stack ? event.reason.stack : '';\n _collectError(msg, stack);\n });\n </script>\n <!--\n SECURITY: pinned to exact patch versions + SRI integrity hashes. A\n malicious republish of @tailwindcss/browser@4.x or alpinejs@3.x would\n otherwise inject code into every extension. To bump these versions:\n 1. npm view @tailwindcss/browser version (or alpinejs)\n 2. curl -sL https://cdn.jsdelivr.net/npm/@tailwindcss/browser@<v> \\\\\n | openssl dgst -sha384 -binary | openssl base64 -A\n 3. Update the URL + integrity hash below in lockstep.\n -->\n <script\n src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4\"\n integrity=\"sha384-yNSZBFvuOWcmww494a9+1zNuvgUGEXoWkein7cxP8wHUTi3iXCU4vJ7hr3tzBCml\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n defer\n src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.15.11/dist/cdn.min.js\"\n integrity=\"sha384-WPtu0YHhJ3arcykfnv1JgUffWDSKRnqnDeTpJUbOc2os2moEmLkIdaeR0trPN4be\"\n crossorigin=\"anonymous\"\n ></script>\n <style>${themeVars}</style>\n <style type=\"text/tailwindcss\">\n @custom-variant dark (&:where(.dark, .dark *));\n @theme {\n --color-border: hsl(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n --color-sidebar: hsl(var(--sidebar-background));\n --color-sidebar-foreground: hsl(var(--sidebar-foreground));\n --color-sidebar-primary: hsl(var(--sidebar-primary));\n --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));\n --color-sidebar-accent: hsl(var(--sidebar-accent));\n --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));\n --color-sidebar-border: hsl(var(--sidebar-border));\n --color-sidebar-ring: hsl(var(--sidebar-ring));\n --radius-lg: var(--radius);\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n }\n </style>\n\t <style>\n\t *, *::before, *::after { border-color: hsl(var(--border)); }\n\t body {\n\t --agent-native-extension-padding: clamp(16px, 2vw, 24px);\n\t /* Legacy alias for pre-rename extension content (do not remove). */\n\t --agent-native-tool-padding: var(--agent-native-extension-padding);\n\t box-sizing: border-box;\n\t font-family: 'Inter', sans-serif;\n\t margin: 0;\n\t min-height: 100vh;\n\t padding: var(--agent-native-extension-padding);\n\t }\n\t body:has(> [data-extension-layout=\"full-bleed\"]),\n\t body:has(> [data-extension-padding=\"none\"]),\n\t body:has(> .agent-native-extension-bleed),\n\t /* Legacy aliases (do not remove). */\n\t body:has(> [data-tool-layout=\"full-bleed\"]),\n\t body:has(> [data-tool-padding=\"none\"]),\n\t body:has(> .agent-native-tool-bleed) {\n\t padding: 0;\n\t }\n\t </style>\n\t <script>\n\t var _extensionRequestSeq = 0;\n\t var _extensionPendingRequests = {};\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var message = event.data || {};\n\t if (\n\t message.type !== 'agent-native-extension-response' &&\n\t message.type !== 'agent-native-tool-response'\n\t ) return;\n\t var pending = _extensionPendingRequests[message.requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[message.requestId];\n\t if (message.error) {\n\t pending.reject(new Error(message.error));\n\t } else {\n\t pending.resolve(message.response);\n\t }\n\t });\n\n\t function hostRequest(path, options) {\n\t options = options || {};\n\t return new Promise(function(resolve, reject) {\n\t var requestId = 'extension-req-' + (++_extensionRequestSeq);\n\t _extensionPendingRequests[requestId] = { resolve: resolve, reject: reject };\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-request',\n\t requestId: requestId,\n\t path: path,\n\t options: {\n\t method: options.method || 'GET',\n\t headers: options.headers || {},\n\t body: options.body,\n\t },\n\t }, '*');\n\t setTimeout(function() {\n\t var pending = _extensionPendingRequests[requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[requestId];\n\t pending.reject(new Error('Extension host request timed out'));\n\t }, 30000);\n\t });\n\t }\n\n\t var _origHostRequest = hostRequest;\n\t hostRequest = function(path, options) {\n\t var entry = { path: path, method: (options && options.method) || 'GET' };\n\t return _origHostRequest(path, options).then(function(res) {\n\t entry.ok = res.ok;\n\t entry.status = res.status;\n\t if (!res.ok && res.body) {\n\t try { entry.error = typeof res.body === 'string' ? res.body.slice(0, 200) : JSON.stringify(res.body).slice(0, 200); } catch(e) {}\n\t }\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t return res;\n\t }, function(err) {\n\t entry.ok = false;\n\t entry.error = err.message;\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t throw err;\n\t });\n\t };\n\n\t function extensionFetch(url, options) {\n\t var opts = options || {};\n\t return hostRequest('/_agent-native/extensions/proxy', {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({\n\t url: url,\n method: opts.method || 'GET',\n headers: opts.headers,\n body: opts.body,\n }),\n\t }).then(function(res) {\n\t var data = res.body;\n\t if (data.error && data.status === undefined) {\n\t throw new Error(data.error);\n\t }\n return {\n ok: data.status >= 200 && data.status < 300,\n status: data.status,\n\t json: function() { return Promise.resolve(data.body); },\n\t text: function() { return Promise.resolve(typeof data.body === 'string' ? data.body : JSON.stringify(data.body)); },\n\t };\n\t });\n\t }\n\n\t function _appendActionQuery(path, params) {\n\t var search = new URLSearchParams();\n\t params = params || {};\n\t Object.keys(params).forEach(function(key) {\n\t var value = params[key];\n\t if (value === undefined || value === null) return;\n\t if (Array.isArray(value)) {\n\t value.forEach(function(item) {\n\t if (item !== undefined && item !== null) {\n\t search.append(key, String(item));\n\t }\n\t });\n\t return;\n\t }\n\t search.set(key, String(value));\n\t });\n\t var qs = search.toString();\n\t return qs ? path + '?' + qs : path;\n\t }\n\n\t function _methodHintFromActionResponse(res) {\n\t if (!res || res.status !== 405) return null;\n\t var body = res.body || {};\n\t var message = typeof body === 'string' ? body : body.error;\n\t if (!message) return null;\n\t var match = String(message).match(/Use (GET|POST|PUT|PATCH|DELETE|HEAD)\\\\.?/i);\n\t return match ? match[1].toUpperCase() : null;\n\t }\n\n\t async function appAction(name, params) {\n\t params = params || {};\n\t if (name === 'navigate') {\n\t var navRes = await hostRequest('/_agent-native/application-state/navigate', {\n\t method: 'PUT',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\t if (!navRes.ok) {\n\t var navErr = navRes.body || { error: navRes.statusText };\n\t throw new Error(navErr.error || 'Navigation failed: ' + navRes.status);\n\t }\n\t return navRes.body;\n\t }\n\t var path = '/_agent-native/actions/' + encodeURIComponent(name);\n\t var res = await hostRequest(path, {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\n\t var retryMethod = _methodHintFromActionResponse(res);\n\t if (!res.ok && retryMethod && retryMethod !== 'POST') {\n\t var retryPath = path;\n\t var retryOptions = {\n\t method: retryMethod,\n\t headers: { 'Content-Type': 'application/json' },\n\t };\n\t if (retryMethod === 'GET' || retryMethod === 'HEAD') {\n\t retryPath = _appendActionQuery(path, params);\n\t } else {\n\t retryOptions.body = JSON.stringify(params);\n\t }\n\t res = await hostRequest(retryPath, retryOptions);\n\t }\n\n\t if (!res.ok) {\n\t var err = res.body || { error: res.statusText };\n\t throw new Error(err.error || 'Action failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n\t async function appFetch(path, options) {\n\t options = options || {};\n\t var res = await hostRequest(path, {\n\t ...options,\n\t headers: {\n\t 'Content-Type': 'application/json',\n\t ...(options.headers || {}),\n\t },\n\t });\n\t if (!res.ok) {\n\t var err = typeof res.body === 'object' && res.body ? res.body : { error: res.statusText };\n\t throw new Error(err.error || 'Request failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n async function dbQuery(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/query', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n async function dbExec(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/exec', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n var _extensionId = ${extensionIdJson};\n var _extensionBinding = ${bindingJson};\n window.extensionBinding = _extensionBinding;\n // Legacy alias for extension bodies authored before the rename.\n window.toolBinding = _extensionBinding;\n // SECURITY (audit H4): announce the resolved binding to the parent so the\n // host bridge can gate dangerous helpers based on viewer role. Sent\n // BEFORE the user-authored content has a chance to run, so a malicious\n // extension body cannot suppress or rewrite the announcement. The parent\n // ignores subsequent announcements for the same iframe; see\n // ExtensionViewer.tsx / EmbeddedExtension.tsx.\n try {\n window.parent.postMessage(\n {\n type: 'agent-native-extension-binding',\n extensionId: _extensionId,\n binding: _extensionBinding,\n },\n '*',\n );\n } catch (_) {}\n // SECURITY: when the viewer is not the author of this extension, emit a\n // clear console warning. The bridge currently runs every helper with the\n // viewer's session — a malicious shared extension can call any action,\n // read any owned table row in scope, and resolve any user-scope secret.\n // A full consent step is tracked as TODO C1 in audit 05-tools-sandbox.md.\n if (_extensionBinding && !_extensionBinding.isAuthor) {\n try {\n console.warn(\n '[agent-native] Shared extension — running with viewer\\\\'s session. ' +\n 'Author: ' + (_extensionBinding.authorEmail || '<unknown>') + '. ' +\n 'Bridge calls (appAction, dbExec, extensionFetch) execute under ' +\n 'your account; they are gated by your permissions, not the ' +\n 'author\\\\'s. Do not run untrusted shared extensions.',\n );\n } catch (_) {}\n }\n\n var extensionData = {\n\t async list(collection, opts) {\n\t var limit = (opts && opts.limit) || 100;\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '?limit=' + limit + '&scope=' + scope);\n\t if (!res.ok) throw new Error('Failed to list extension data');\n\t return res.body;\n\t },\n async get(collection, id, opts) {\n var scope = (opts && opts.scope) || 'user';\n var items = await this.list(collection, { scope: scope });\n return (items || []).find(function(item) { return item.id === id; }) || null;\n },\n async set(collection, id, data, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection), {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({ id: id, data: data, scope: scope }),\n\t });\n\t if (!res.ok) throw new Error('Failed to save extension data');\n\t return res.body;\n\t },\n\t async remove(collection, id, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '/' + encodeURIComponent(id) + '?scope=' + scope, {\n\t method: 'DELETE',\n\t });\n\t if (!res.ok) throw new Error('Failed to delete extension data');\n\t return res.body;\n\t },\n\t };\n\n\t // Legacy aliases — extension bodies authored before the rename use\n\t // toolFetch, toolData, toolId. Keep these working forever.\n\t var toolFetch = extensionFetch;\n\t var toolData = extensionData;\n\t var _toolId = _extensionId;\n\t </script>\n\t <style>\n\t #__extension-error-toast {\n\t display: none;\n\t position: fixed;\n\t bottom: 16px;\n\t right: 16px;\n\t max-width: 420px;\n\t background: hsl(var(--destructive));\n\t color: hsl(var(--destructive-foreground));\n\t border: 1px solid hsl(var(--destructive) / .6);\n\t border-radius: calc(var(--radius, .5rem) + 2px);\n\t padding: 12px 16px;\n\t font-size: 13px;\n\t line-height: 1.4;\n\t font-family: 'Inter', sans-serif;\n\t z-index: 9999;\n\t box-shadow: 0 4px 12px rgba(0,0,0,.15), 0 1px 3px rgba(0,0,0,.1);\n\t animation: __toast-in 0.2s ease-out;\n\t }\n\t @keyframes __toast-in {\n\t from { opacity: 0; transform: translateY(8px); }\n\t to { opacity: 1; transform: translateY(0); }\n\t }\n\t </style>\n\t <script>\n\t // Extension-point slot context: when an extension is rendered embedded\n\t // inside an ExtensionSlot, the host pushes a context object via\n\t // postMessage. Extensions read it synchronously via window.slotContext\n\t // or subscribe to changes via window.onSlotContext(fn). When rendered\n\t // full-page (no ?slot= param), slotContext stays null and extensions\n\t // branch on that.\n\t window.slotContext = null;\n\t var _slotContextSubscribers = [];\n\t window.onSlotContext = function(fn) {\n\t _slotContextSubscribers.push(fn);\n\t if (window.slotContext !== null) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t }\n\t return function() {\n\t _slotContextSubscribers = _slotContextSubscribers.filter(function(f) { return f !== fn; });\n\t };\n\t };\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-slot-context') return;\n\t window.slotContext = msg.context || {};\n\t _slotContextSubscribers.forEach(function(fn) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t });\n\t });\n\n\t // Auto-resize the iframe to its content when running in slot mode. The\n\t // host listens for agent-native-extension-resize and adjusts the iframe height.\n\t if (new URLSearchParams(location.search).get('slot')) {\n\t var _lastH = 0;\n\t var _reportHeight = function() {\n\t var h = Math.max(\n\t document.documentElement.scrollHeight,\n\t document.body ? document.body.scrollHeight : 0,\n\t );\n\t if (h !== _lastH) {\n\t _lastH = h;\n\t window.parent.postMessage({ type: 'agent-native-extension-resize', height: h }, '*');\n\t }\n\t };\n\t if (typeof ResizeObserver !== 'undefined') {\n\t var _ro = new ResizeObserver(_reportHeight);\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _ro.observe(document.documentElement);\n\t if (document.body) _ro.observe(document.body);\n\t });\n\t }\n\t // Initial reports — Alpine takes a tick to render after DOMContentLoaded.\n\t setTimeout(_reportHeight, 50);\n\t setTimeout(_reportHeight, 250);\n\t }\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-theme-update') return;\n\t var root = document.documentElement;\n\t if (msg.isDark !== undefined) {\n\t if (msg.isDark) root.classList.add('dark');\n\t else root.classList.remove('dark');\n\t }\n\t var vars = msg.vars || {};\n\t for (var key in vars) {\n\t if (vars.hasOwnProperty(key)) {\n\t root.style.setProperty(key, vars[key]);\n\t }\n\t }\n\t });\n\n\t document.addEventListener('keydown', function(e) {\n\t if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n\t var key = (e.key || '').toLowerCase();\n\t if (key === 'c' || key === 'v' || key === 'x' || key === 'a' || key === 'z' || key === 'y') return;\n\t e.preventDefault();\n\t e.stopPropagation();\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: e.metaKey, ctrlKey: e.ctrlKey,\n\t shiftKey: e.shiftKey, altKey: e.altKey,\n\t }, '*');\n\t return;\n\t }\n\t if (e.key === 'Escape') {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: false, ctrlKey: false,\n\t shiftKey: false, altKey: false,\n\t }, '*');\n\t }\n\t });\n\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _renderErrorToast();\n\t var fixBtn = document.getElementById('__extension-error-fix');\n\t if (fixBtn) {\n\t fixBtn.addEventListener('click', function() {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-error-fix',\n\t errors: _extensionErrors,\n\t errorDetails: _extensionErrorDetails,\n\t consoleLogs: _consoleLogs.slice(-30),\n\t networkLogs: _networkLogs.slice(-15)\n\t }, '*');\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t var dismissBtn = document.getElementById('__extension-error-dismiss');\n\t if (dismissBtn) {\n\t dismissBtn.addEventListener('click', function() {\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t });\n\t </script>\n\t</head>\n\t<body${extensionId ? ` data-extension-id=\"${extensionIdAttr}\" data-tool-id=\"${extensionIdAttr}\"` : \"\"} class=\"bg-background text-foreground\">\n\t${content}\n\t<div id=\"__extension-error-toast\">\n\t <div style=\"display:flex;align-items:flex-start;gap:8px;\">\n\t <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0;margin-top:1px;\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>\n\t <span id=\"__extension-error-msg\" style=\"flex:1;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;\"></span>\n\t <button id=\"__extension-error-fix\" style=\"cursor:pointer;border:none;background:rgba(255,255,255,.9);color:hsl(0 84.2% 40%);font-size:12px;font-weight:500;padding:4px 12px;border-radius:4px;flex-shrink:0;\">Fix</button>\n\t <button id=\"__extension-error-dismiss\" style=\"cursor:pointer;border:none;background:transparent;color:inherit;font-size:16px;padding:2px 6px;opacity:0.7;flex-shrink:0;\">&#215;</button>\n\t </div>\n\t</div>\n\t</body>\n\t</html>`;\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n"]}
1
+ {"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAAA,MAAM,yBAAyB,GAC7B,mXAAmX,CAAC;AAEtX,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,QAAQ;IACR,0BAA0B;IAC1B,4BAA4B;IAC5B,oBAAoB;IACpB,oBAAoB;IACpB,gCAAgC;IAChC,0CAA0C;CAC3C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,yBAAyB,oBAAoB,yBAAyB,GAAG,CAAC;AAEjH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAoEnE,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,SAAiB,EACjB,MAAe,EACf,WAAoB,EACpB,OAAgC;IAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,mBAAmB,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAChC,OAAO,IAAI;QACT,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,OAAO;KACd,CACF,CAAC;IAEF,OAAO;iBACQ,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;;;;wDAIU,yBAAyB;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,uDAAuD,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmFlI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA8SK,eAAe;8BACV,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+OjC,WAAW,CAAC,CAAC,CAAC,uBAAuB,eAAe,mBAAmB,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE;GACnG,OAAO;;;;;;;;;;SAUD,CAAC;AACV,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["const EXTENSION_IFRAME_CSP_BASE =\n \"default-src 'none'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data: blob:; media-src 'self' data: blob:; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none';\";\n\nexport const EXTENSION_FRAME_ANCESTORS = [\n \"'self'\",\n \"https://agent-native.com\",\n \"https://*.agent-native.com\",\n \"http://localhost:*\",\n \"http://127.0.0.1:*\",\n \"https://*.claudemcpcontent.com\",\n \"https://*.web-sandbox.oaiusercontent.com\",\n].join(\" \");\n\nexport const EXTENSION_IFRAME_CSP = `${EXTENSION_IFRAME_CSP_BASE} frame-ancestors ${EXTENSION_FRAME_ANCESTORS};`;\n\nexport const EXTENSION_IFRAME_META_CSP = EXTENSION_IFRAME_CSP_BASE;\n\n/**\n * SECURITY — EXTENSION CONTENT IS UNTRUSTED.\n *\n * `${content}` (line ~Body) interpolates raw HTML/JS authored by a user. This\n * file is the boundary between framework-controlled HTML and user-controlled\n * HTML. Two non-negotiable invariants for every change here:\n *\n * 1. The iframe MUST be rendered with a `sandbox` attribute that does NOT\n * include `allow-same-origin`. The viewer (`ExtensionViewer.tsx`,\n * `EmbeddedExtension.tsx`) sets `sandbox=\"allow-scripts allow-forms\"` —\n * and that is the only acceptable shape. Adding `allow-same-origin`\n * would give the extension full DOM access to the parent window via\n * cross-frame script.\n *\n * 2. Every reachable parent action must treat the postMessage payload as\n * hostile. The bridge in `iframe-bridge.ts` enforces a path allowlist,\n * header sanitization, and method allowlist; do not relax those gates\n * for \"convenience\" in this file or any caller.\n *\n * For the trust model rationale, see audit 05-tools-sandbox.md (C1) and the\n * `extensions` skill. When in doubt, fail closed.\n *\n * BACKWARDS COMPAT — the iframe injects helpers under both their canonical\n * `extension*` names (`extensionFetch`, `extensionData`, `extensionId`,\n * `extensionBinding`) AND legacy `tool*` aliases (`toolFetch`, `toolData`,\n * `toolId`, `toolBinding`) so existing user-authored extension bodies that\n * pre-date the rename keep working. Same for layout opt-ins:\n * `data-extension-layout=\"full-bleed\"` / `data-extension-padding=\"none\"` /\n * class `agent-native-extension-bleed` / CSS var\n * `--agent-native-extension-padding` are canonical; the `data-tool-*`,\n * `agent-native-tool-bleed`, and `--agent-native-tool-padding` variants are\n * accepted as aliases.\n */\n\nexport interface ExtensionRenderBinding {\n /** Email of the user who authored / owns the extension. */\n authorEmail: string;\n /** Email of the user currently viewing/running the extension. */\n viewerEmail: string;\n /** True when viewer === author. */\n isAuthor: boolean;\n /**\n * Resolved role for the viewer (\"owner\" | \"admin\" | \"editor\" | \"viewer\").\n *\n * TODO(security, audit H4): the host-side bridge does not yet gate any\n * helper based on this value — every viewer gets the same powers as the\n * author. The role is plumbed through so a follow-up PR can constrain\n * `appAction` / `dbExec` / `extensionFetch` for non-author viewers (and\n * eventually require an explicit consent step before running a shared\n * extension, audit C1). For now this is metadata only.\n */\n role: \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n /** Where the extension definition came from. Database extensions are the default. */\n source?: \"database\" | \"local-files\";\n /**\n * Fine-grained helper permissions for local file extensions. Database-backed\n * extensions keep using the role table in the parent bridge.\n */\n permissions?: {\n appActions?: string[];\n extensionData?: boolean;\n sql?: boolean;\n externalFetch?: boolean;\n };\n}\n\nexport function buildExtensionHtml(\n content: string,\n themeVars: string,\n isDark: boolean,\n extensionId?: string,\n binding?: ExtensionRenderBinding,\n): string {\n const extensionIdJson = JSON.stringify(extensionId ?? \"\");\n const extensionIdAttr = escapeHtmlAttribute(extensionId ?? \"\");\n const bindingJson = JSON.stringify(\n binding ?? {\n authorEmail: \"\",\n viewerEmail: \"\",\n isAuthor: true,\n role: \"owner\",\n },\n );\n\n return `<!DOCTYPE html>\n<html lang=\"en\"${isDark ? ' class=\"dark\"' : \"\"}>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Security-Policy\" content=\"${EXTENSION_IFRAME_META_CSP}\" />\n ${binding && !binding.isAuthor ? `<meta name=\"agent-native-extension-author\" content=\"${escapeHtmlAttribute(binding.authorEmail)}\" />` : \"\"}\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300..700&display=swap\" rel=\"stylesheet\" />\n <script>\n var _extensionErrors = [];\n var _extensionErrorDetails = [];\n var _consoleLogs = [];\n var _networkLogs = [];\n\n var _origConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info };\n function _wrapConsole(level, orig) {\n return function() {\n var args = Array.prototype.slice.call(arguments);\n var msg = args.map(function(a) {\n try { return typeof a === 'object' ? JSON.stringify(a) : String(a); }\n catch(e) { return String(a); }\n }).join(' ');\n if (_consoleLogs.length >= 50) _consoleLogs.shift();\n _consoleLogs.push({ level: level, message: msg });\n orig.apply(console, arguments);\n };\n }\n console.log = _wrapConsole('log', _origConsole.log);\n console.warn = _wrapConsole('warn', _origConsole.warn);\n console.error = _wrapConsole('error', _origConsole.error);\n console.info = _wrapConsole('info', _origConsole.info);\n\n function _collectError(message, stack) {\n if (!message) return;\n if (message === 'Script error.' || message === 'Script error') message = 'Runtime error';\n if (_extensionErrors.indexOf(message) !== -1) return;\n _extensionErrors.push(message);\n _extensionErrorDetails.push({ message: message, stack: stack || '' });\n _renderErrorToast();\n }\n\n function _renderErrorToast() {\n var toast = document.getElementById('__extension-error-toast');\n if (!toast) return;\n var msg = document.getElementById('__extension-error-msg');\n if (!msg || _extensionErrors.length === 0) return;\n if (_extensionErrors.length === 1) {\n msg.textContent = _extensionErrors[0];\n } else {\n msg.textContent = _extensionErrors.length + ' errors — ' + _extensionErrors[_extensionErrors.length - 1];\n }\n toast.style.display = 'block';\n }\n\n window.addEventListener('error', function(event) {\n var msg = event.message || '';\n if (msg.indexOf('Alpine Expression Error') === 0) return;\n var stack = event.error && event.error.stack ? event.error.stack : '';\n _collectError(msg, stack);\n });\n\n window.addEventListener('unhandledrejection', function(event) {\n var msg = event.reason && event.reason.message ? event.reason.message : String(event.reason);\n var stack = event.reason && event.reason.stack ? event.reason.stack : '';\n _collectError(msg, stack);\n });\n </script>\n <!--\n SECURITY: pinned to exact patch versions + SRI integrity hashes. A\n malicious republish of @tailwindcss/browser@4.x or alpinejs@3.x would\n otherwise inject code into every extension. To bump these versions:\n 1. npm view @tailwindcss/browser version (or alpinejs)\n 2. curl -sL https://cdn.jsdelivr.net/npm/@tailwindcss/browser@<v> \\\\\n | openssl dgst -sha384 -binary | openssl base64 -A\n 3. Update the URL + integrity hash below in lockstep.\n -->\n <script\n src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4\"\n integrity=\"sha384-yNSZBFvuOWcmww494a9+1zNuvgUGEXoWkein7cxP8wHUTi3iXCU4vJ7hr3tzBCml\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n defer\n src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.15.11/dist/cdn.min.js\"\n integrity=\"sha384-WPtu0YHhJ3arcykfnv1JgUffWDSKRnqnDeTpJUbOc2os2moEmLkIdaeR0trPN4be\"\n crossorigin=\"anonymous\"\n ></script>\n <style>${themeVars}</style>\n <style type=\"text/tailwindcss\">\n @custom-variant dark (&:where(.dark, .dark *));\n @theme {\n --color-border: hsl(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n --color-sidebar: hsl(var(--sidebar-background));\n --color-sidebar-foreground: hsl(var(--sidebar-foreground));\n --color-sidebar-primary: hsl(var(--sidebar-primary));\n --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));\n --color-sidebar-accent: hsl(var(--sidebar-accent));\n --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));\n --color-sidebar-border: hsl(var(--sidebar-border));\n --color-sidebar-ring: hsl(var(--sidebar-ring));\n --radius-lg: var(--radius);\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n }\n </style>\n\t <style>\n\t *, *::before, *::after { border-color: hsl(var(--border)); }\n\t body {\n\t --agent-native-extension-padding: clamp(16px, 2vw, 24px);\n\t /* Legacy alias for pre-rename extension content (do not remove). */\n\t --agent-native-tool-padding: var(--agent-native-extension-padding);\n\t box-sizing: border-box;\n\t font-family: 'Inter', sans-serif;\n\t margin: 0;\n\t min-height: 100vh;\n\t padding: var(--agent-native-extension-padding);\n\t }\n\t body:has(> [data-extension-layout=\"full-bleed\"]),\n\t body:has(> [data-extension-padding=\"none\"]),\n\t body:has(> .agent-native-extension-bleed),\n\t /* Legacy aliases (do not remove). */\n\t body:has(> [data-tool-layout=\"full-bleed\"]),\n\t body:has(> [data-tool-padding=\"none\"]),\n\t body:has(> .agent-native-tool-bleed) {\n\t padding: 0;\n\t }\n\t </style>\n\t <script>\n\t var _extensionRequestSeq = 0;\n\t var _extensionPendingRequests = {};\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var message = event.data || {};\n\t if (\n\t message.type !== 'agent-native-extension-response' &&\n\t message.type !== 'agent-native-tool-response'\n\t ) return;\n\t var pending = _extensionPendingRequests[message.requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[message.requestId];\n\t if (message.error) {\n\t pending.reject(new Error(message.error));\n\t } else {\n\t pending.resolve(message.response);\n\t }\n\t });\n\n\t function hostRequest(path, options) {\n\t options = options || {};\n\t return new Promise(function(resolve, reject) {\n\t var requestId = 'extension-req-' + (++_extensionRequestSeq);\n\t _extensionPendingRequests[requestId] = { resolve: resolve, reject: reject };\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-request',\n\t requestId: requestId,\n\t path: path,\n\t options: {\n\t method: options.method || 'GET',\n\t headers: options.headers || {},\n\t body: options.body,\n\t },\n\t }, '*');\n\t setTimeout(function() {\n\t var pending = _extensionPendingRequests[requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[requestId];\n\t pending.reject(new Error('Extension host request timed out'));\n\t }, 30000);\n\t });\n\t }\n\n\t var _origHostRequest = hostRequest;\n\t hostRequest = function(path, options) {\n\t var entry = { path: path, method: (options && options.method) || 'GET' };\n\t return _origHostRequest(path, options).then(function(res) {\n\t entry.ok = res.ok;\n\t entry.status = res.status;\n\t if (!res.ok && res.body) {\n\t try { entry.error = typeof res.body === 'string' ? res.body.slice(0, 200) : JSON.stringify(res.body).slice(0, 200); } catch(e) {}\n\t }\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t return res;\n\t }, function(err) {\n\t entry.ok = false;\n\t entry.error = err.message;\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t throw err;\n\t });\n\t };\n\n\t function extensionFetch(url, options) {\n\t var opts = options || {};\n\t return hostRequest('/_agent-native/extensions/proxy', {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({\n\t url: url,\n method: opts.method || 'GET',\n headers: opts.headers,\n body: opts.body,\n }),\n\t }).then(function(res) {\n\t var data = res.body;\n\t if (data.error && data.status === undefined) {\n\t throw new Error(data.error);\n\t }\n return {\n ok: data.status >= 200 && data.status < 300,\n status: data.status,\n\t json: function() { return Promise.resolve(data.body); },\n\t text: function() { return Promise.resolve(typeof data.body === 'string' ? data.body : JSON.stringify(data.body)); },\n\t };\n\t });\n\t }\n\n\t function _appendActionQuery(path, params) {\n\t var search = new URLSearchParams();\n\t params = params || {};\n\t Object.keys(params).forEach(function(key) {\n\t var value = params[key];\n\t if (value === undefined || value === null) return;\n\t if (Array.isArray(value)) {\n\t value.forEach(function(item) {\n\t if (item !== undefined && item !== null) {\n\t search.append(key, String(item));\n\t }\n\t });\n\t return;\n\t }\n\t search.set(key, String(value));\n\t });\n\t var qs = search.toString();\n\t return qs ? path + '?' + qs : path;\n\t }\n\n\t function _methodHintFromActionResponse(res) {\n\t if (!res || res.status !== 405) return null;\n\t var body = res.body || {};\n\t var message = typeof body === 'string' ? body : body.error;\n\t if (!message) return null;\n\t var match = String(message).match(/Use (GET|POST|PUT|PATCH|DELETE|HEAD)\\\\.?/i);\n\t return match ? match[1].toUpperCase() : null;\n\t }\n\n\t async function appAction(name, params) {\n\t params = params || {};\n\t if (name === 'navigate') {\n\t var navRes = await hostRequest('/_agent-native/application-state/navigate', {\n\t method: 'PUT',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\t if (!navRes.ok) {\n\t var navErr = navRes.body || { error: navRes.statusText };\n\t throw new Error(navErr.error || 'Navigation failed: ' + navRes.status);\n\t }\n\t return navRes.body;\n\t }\n\t var path = '/_agent-native/actions/' + encodeURIComponent(name);\n\t var res = await hostRequest(path, {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\n\t var retryMethod = _methodHintFromActionResponse(res);\n\t if (!res.ok && retryMethod && retryMethod !== 'POST') {\n\t var retryPath = path;\n\t var retryOptions = {\n\t method: retryMethod,\n\t headers: { 'Content-Type': 'application/json' },\n\t };\n\t if (retryMethod === 'GET' || retryMethod === 'HEAD') {\n\t retryPath = _appendActionQuery(path, params);\n\t } else {\n\t retryOptions.body = JSON.stringify(params);\n\t }\n\t res = await hostRequest(retryPath, retryOptions);\n\t }\n\n\t if (!res.ok) {\n\t var err = res.body || { error: res.statusText };\n\t throw new Error(err.error || 'Action failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n\t async function appFetch(path, options) {\n\t options = options || {};\n\t var res = await hostRequest(path, {\n\t ...options,\n\t headers: {\n\t 'Content-Type': 'application/json',\n\t ...(options.headers || {}),\n\t },\n\t });\n\t if (!res.ok) {\n\t var err = typeof res.body === 'object' && res.body ? res.body : { error: res.statusText };\n\t throw new Error(err.error || 'Request failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n\t function sendToChat(message, options) {\n\t options = options || {};\n\t var text = typeof message === 'string' ? message : JSON.stringify(message);\n\t window.parent.postMessage({\n\t type: 'agent-native-send-to-chat',\n\t message: text,\n\t context: options.context,\n\t submit: options.submit !== false,\n\t openSidebar: options.openSidebar !== false,\n\t }, '*');\n\t return { ok: true };\n\t }\n\n\t function inlineUiOutputKey() {\n\t var safeId = String(_extensionId || 'unknown').replace(/[^A-Za-z0-9_:-]/g, '') || 'unknown';\n\t return 'inline-ui:' + safeId + ':output';\n\t }\n\n\t async function outputToUi(value, options) {\n\t options = options || {};\n\t var key = inlineUiOutputKey();\n\t var payload = {\n\t value: value,\n\t updatedAt: new Date().toISOString(),\n\t extensionId: _extensionId,\n\t source: 'inline-ui',\n\t };\n\t if (options.label !== undefined) payload.label = options.label;\n\t if (options.context !== undefined) payload.context = options.context;\n\t if (options.meta !== undefined) payload.meta = options.meta;\n\t var output = await appFetch('/_agent-native/application-state/' + key, {\n\t method: 'PUT',\n\t headers: { 'X-Request-Source': 'inline-ui' },\n\t body: JSON.stringify(payload),\n\t });\n\t try {\n\t window.parent.postMessage({\n\t type: 'agent-native-ui-output',\n\t extensionId: _extensionId,\n\t key: key,\n\t value: value,\n\t output: output,\n\t }, '*');\n\t } catch (_) {}\n\t return { ok: true, key: key, output: output };\n\t }\n\n async function dbQuery(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/query', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n async function dbExec(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/exec', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n var _extensionId = ${extensionIdJson};\n var _extensionBinding = ${bindingJson};\n window.extensionBinding = _extensionBinding;\n // Legacy alias for extension bodies authored before the rename.\n window.toolBinding = _extensionBinding;\n // SECURITY (audit H4): announce the resolved binding to the parent so the\n // host bridge can gate dangerous helpers based on viewer role. Sent\n // BEFORE the user-authored content has a chance to run, so a malicious\n // extension body cannot suppress or rewrite the announcement. The parent\n // ignores subsequent announcements for the same iframe; see\n // ExtensionViewer.tsx / EmbeddedExtension.tsx.\n try {\n window.parent.postMessage(\n {\n type: 'agent-native-extension-binding',\n extensionId: _extensionId,\n binding: _extensionBinding,\n },\n '*',\n );\n } catch (_) {}\n // SECURITY: when the viewer is not the author of this extension, emit a\n // clear console warning. The bridge currently runs every helper with the\n // viewer's session — a malicious shared extension can call any action,\n // read any owned table row in scope, and resolve any user-scope secret.\n // A full consent step is tracked as TODO C1 in audit 05-tools-sandbox.md.\n if (_extensionBinding && !_extensionBinding.isAuthor) {\n try {\n console.warn(\n '[agent-native] Shared extension — running with viewer\\\\'s session. ' +\n 'Author: ' + (_extensionBinding.authorEmail || '<unknown>') + '. ' +\n 'Bridge calls (appAction, dbExec, extensionFetch) execute under ' +\n 'your account; they are gated by your permissions, not the ' +\n 'author\\\\'s. Do not run untrusted shared extensions.',\n );\n } catch (_) {}\n }\n\n var extensionData = {\n\t async list(collection, opts) {\n\t var limit = (opts && opts.limit) || 100;\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '?limit=' + limit + '&scope=' + scope);\n\t if (!res.ok) throw new Error('Failed to list extension data');\n\t return res.body;\n\t },\n async get(collection, id, opts) {\n var scope = (opts && opts.scope) || 'user';\n var items = await this.list(collection, { scope: scope });\n return (items || []).find(function(item) { return item.id === id; }) || null;\n },\n async set(collection, id, data, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection), {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({ id: id, data: data, scope: scope }),\n\t });\n\t if (!res.ok) throw new Error('Failed to save extension data');\n\t return res.body;\n\t },\n\t async remove(collection, id, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '/' + encodeURIComponent(id) + '?scope=' + scope, {\n\t method: 'DELETE',\n\t });\n\t if (!res.ok) throw new Error('Failed to delete extension data');\n\t return res.body;\n\t },\n\t };\n\n\t // Legacy aliases — extension bodies authored before the rename use\n\t // toolFetch, toolData, toolId. Keep these working forever.\n\t var toolFetch = extensionFetch;\n\t var toolData = extensionData;\n\t var _toolId = _extensionId;\n\t window.agentNative = Object.assign(window.agentNative || {}, {\n\t extensionId: _extensionId,\n\t extensionBinding: _extensionBinding,\n\t appAction: appAction,\n\t appFetch: appFetch,\n\t dbQuery: dbQuery,\n\t dbExec: dbExec,\n\t extensionFetch: extensionFetch,\n\t extensionData: extensionData,\n\t data: extensionData,\n\t sendToChat: sendToChat,\n\t chat: Object.assign({}, (window.agentNative && window.agentNative.chat) || {}, {\n\t send: sendToChat,\n\t }),\n\t ui: Object.assign({}, (window.agentNative && window.agentNative.ui) || {}, {\n\t output: outputToUi,\n\t }),\n\t });\n\t window.sendToAgentChat = sendToChat;\n\t </script>\n\t <style>\n\t #__extension-error-toast {\n\t display: none;\n\t position: fixed;\n\t bottom: 16px;\n\t right: 16px;\n\t max-width: 420px;\n\t background: hsl(var(--destructive));\n\t color: hsl(var(--destructive-foreground));\n\t border: 1px solid hsl(var(--destructive) / .6);\n\t border-radius: calc(var(--radius, .5rem) + 2px);\n\t padding: 12px 16px;\n\t font-size: 13px;\n\t line-height: 1.4;\n\t font-family: 'Inter', sans-serif;\n\t z-index: 9999;\n\t box-shadow: 0 4px 12px rgba(0,0,0,.15), 0 1px 3px rgba(0,0,0,.1);\n\t animation: __toast-in 0.2s ease-out;\n\t }\n\t @keyframes __toast-in {\n\t from { opacity: 0; transform: translateY(8px); }\n\t to { opacity: 1; transform: translateY(0); }\n\t }\n\t </style>\n\t <script>\n\t // Extension-point slot context: when an extension is rendered embedded\n\t // inside an ExtensionSlot, the host pushes a context object via\n\t // postMessage. Extensions read it synchronously via window.slotContext\n\t // or subscribe to changes via window.onSlotContext(fn). When rendered\n\t // full-page (no ?slot= param), slotContext stays null and extensions\n\t // branch on that.\n\t window.slotContext = null;\n\t var _slotContextSubscribers = [];\n\t window.onSlotContext = function(fn) {\n\t _slotContextSubscribers.push(fn);\n\t if (window.slotContext !== null) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t }\n\t return function() {\n\t _slotContextSubscribers = _slotContextSubscribers.filter(function(f) { return f !== fn; });\n\t };\n\t };\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-slot-context') return;\n\t window.slotContext = msg.context || {};\n\t _slotContextSubscribers.forEach(function(fn) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t });\n\t });\n\n\t // Auto-resize iframe renders. Persisted extension slots include ?slot=;\n\t // transient inline chat UI uses srcdoc, so detect that by parent frame.\n\t // The host listens for agent-native-extension-resize and adjusts height.\n\t if (new URLSearchParams(location.search).get('slot') || window.parent !== window) {\n\t var _lastH = 0;\n\t var _reportHeight = function() {\n\t var h = Math.max(\n\t document.documentElement.scrollHeight,\n\t document.body ? document.body.scrollHeight : 0,\n\t );\n\t if (h !== _lastH) {\n\t _lastH = h;\n\t window.parent.postMessage({ type: 'agent-native-extension-resize', height: h }, '*');\n\t }\n\t };\n\t if (typeof ResizeObserver !== 'undefined') {\n\t var _ro = new ResizeObserver(_reportHeight);\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _ro.observe(document.documentElement);\n\t if (document.body) _ro.observe(document.body);\n\t });\n\t }\n\t // Initial reports — Alpine takes a tick to render after DOMContentLoaded.\n\t setTimeout(_reportHeight, 50);\n\t setTimeout(_reportHeight, 250);\n\t }\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-theme-update') return;\n\t var root = document.documentElement;\n\t if (msg.isDark !== undefined) {\n\t if (msg.isDark) root.classList.add('dark');\n\t else root.classList.remove('dark');\n\t }\n\t var vars = msg.vars || {};\n\t for (var key in vars) {\n\t if (vars.hasOwnProperty(key)) {\n\t root.style.setProperty(key, vars[key]);\n\t }\n\t }\n\t });\n\n\t document.addEventListener('keydown', function(e) {\n\t if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n\t var key = (e.key || '').toLowerCase();\n\t if (key === 'c' || key === 'v' || key === 'x' || key === 'a' || key === 'z' || key === 'y') return;\n\t e.preventDefault();\n\t e.stopPropagation();\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: e.metaKey, ctrlKey: e.ctrlKey,\n\t shiftKey: e.shiftKey, altKey: e.altKey,\n\t }, '*');\n\t return;\n\t }\n\t if (e.key === 'Escape') {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: false, ctrlKey: false,\n\t shiftKey: false, altKey: false,\n\t }, '*');\n\t }\n\t });\n\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _renderErrorToast();\n\t var fixBtn = document.getElementById('__extension-error-fix');\n\t if (fixBtn) {\n\t fixBtn.addEventListener('click', function() {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-error-fix',\n\t errors: _extensionErrors,\n\t errorDetails: _extensionErrorDetails,\n\t consoleLogs: _consoleLogs.slice(-30),\n\t networkLogs: _networkLogs.slice(-15)\n\t }, '*');\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t var dismissBtn = document.getElementById('__extension-error-dismiss');\n\t if (dismissBtn) {\n\t dismissBtn.addEventListener('click', function() {\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t });\n\t </script>\n\t</head>\n\t<body${extensionId ? ` data-extension-id=\"${extensionIdAttr}\" data-tool-id=\"${extensionIdAttr}\"` : \"\"} class=\"bg-background text-foreground\">\n\t${content}\n\t<div id=\"__extension-error-toast\">\n\t <div style=\"display:flex;align-items:flex-start;gap:8px;\">\n\t <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0;margin-top:1px;\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>\n\t <span id=\"__extension-error-msg\" style=\"flex:1;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;\"></span>\n\t <button id=\"__extension-error-fix\" style=\"cursor:pointer;border:none;background:rgba(255,255,255,.9);color:hsl(0 84.2% 40%);font-size:12px;font-weight:500;padding:4px 12px;border-radius:4px;flex-shrink:0;\">Fix</button>\n\t <button id=\"__extension-error-dismiss\" style=\"cursor:pointer;border:none;background:transparent;color:inherit;font-size:16px;padding:2px 6px;opacity:0.7;flex-shrink:0;\">&#215;</button>\n\t </div>\n\t</div>\n\t</body>\n\t</html>`;\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"AAgEA,wBAAgB,uBAAuB,2FAuCtC;AAq0BD,eAAO,MAAM,kBAAkB,QACqa,CAAC;AAMrc,eAAO,MAAM,gBAAgB,QACwkB,CAAC;AAMtmB,eAAO,MAAM,oBAAoB,QACgB,CAAC;AAMlD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/D"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"AAgEA,wBAAgB,uBAAuB,2FA2CtC;AAy0BD,eAAO,MAAM,kBAAkB,QACqa,CAAC;AAMrc,eAAO,MAAM,gBAAgB,QACwkB,CAAC;AAMtmB,eAAO,MAAM,oBAAoB,QACgB,CAAC;AAMlD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/D"}
@@ -36,7 +36,11 @@ export function createExtensionsHandler() {
36
36
  return { error: "Authentication required" };
37
37
  }
38
38
  const orgCtx = await getOrgContext(event).catch(() => null);
39
- const userEmail = session.email;
39
+ const userEmail = normalizeExtensionUserEmail(session.email);
40
+ if (!userEmail) {
41
+ setResponseStatus(event, 401);
42
+ return { error: "Authentication required" };
43
+ }
40
44
  const orgId = orgCtx?.orgId ?? session.orgId ?? undefined;
41
45
  try {
42
46
  return await runWithRequestContext({ userEmail, orgId }, async () => {
@@ -53,6 +57,9 @@ export function createExtensionsHandler() {
53
57
  }
54
58
  });
55
59
  }
60
+ function normalizeExtensionUserEmail(email) {
61
+ return email.trim().toLowerCase();
62
+ }
56
63
  async function dispatch(event, method, parts, userEmail) {
57
64
  // POST /sql/query — read-only SQL for extension iframes
58
65
  if (method === "POST" &&
@@ -378,7 +385,7 @@ async function handleExtensionDataList(event, extensionId, collection, userEmail
378
385
  sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at
379
386
  FROM tool_data
380
387
  WHERE tool_id = ? AND collection = ?
381
- AND ((scope = 'user' AND owner_email = ?) OR (scope = 'org' AND org_id = ?))
388
+ AND ((scope = 'user' AND lower(owner_email) = ?) OR (scope = 'org' AND org_id = ?))
382
389
  ORDER BY created_at DESC
383
390
  LIMIT ?`,
384
391
  args: [extensionId, collection, userEmail, orgId ?? "", limit],
@@ -388,7 +395,7 @@ async function handleExtensionDataList(event, extensionId, collection, userEmail
388
395
  const result = await client.execute({
389
396
  sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at
390
397
  FROM tool_data
391
- WHERE tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?
398
+ WHERE tool_id = ? AND collection = ? AND scope = 'user' AND lower(owner_email) = ?
392
399
  ORDER BY updated_at DESC
393
400
  LIMIT ?`,
394
401
  args: [extensionId, collection, userEmail, limit],
@@ -473,7 +480,7 @@ async function handleExtensionDataDelete(event, extensionId, collection, itemId,
473
480
  return { ok: true };
474
481
  }
475
482
  await client.execute({
476
- sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?`,
483
+ sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND lower(owner_email) = ?`,
477
484
  args: [itemId, extensionId, collection, userEmail],
478
485
  });
479
486
  return { ok: true };
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n setResponseHeader,\n type H3Event,\n} from \"h3\";\n\nimport { getDbExec, isPostgres } from \"../db/client.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport {\n resolveKeyReferencesWithRequestScopes,\n validateUrlAllowlist,\n getResolvedKeyAllowlist,\n type ResolvedKeyReference,\n} from \"../secrets/substitution.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport {\n runWithRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { ForbiddenError, resolveAccess } from \"../sharing/access.js\";\nimport { ROLE_RANK, type ShareRole } from \"../sharing/schema.js\";\nimport { buildExtensionHtml, EXTENSION_IFRAME_CSP } from \"./html-shell.js\";\nimport {\n getLocalExtension,\n isLocalExtensionRow,\n listLocalExtensions,\n type LocalExtensionRow,\n} from \"./local.js\";\nimport {\n collectSecretValues,\n normalizeExtensionProxyMethod,\n readResponseTextWithLimit,\n redactSecrets,\n redactString,\n sanitizeOutboundHeaders,\n} from \"./proxy-security.js\";\nimport {\n listExtensions,\n getExtension,\n getExtensionHistoryVersion,\n listExtensionHistory,\n createExtension,\n updateExtension,\n updateExtensionContent,\n restoreExtensionHistoryVersion,\n deleteExtension,\n hideExtension,\n unhideExtension,\n globalHideExtension,\n globalUnhideExtension,\n ensureExtensionsTables,\n type ExtensionRow,\n} from \"./store.js\";\nimport { getThemeVars } from \"./theme.js\";\nimport {\n createSsrfSafeDispatcher,\n isBlockedExtensionUrlWithDns,\n} from \"./url-safety.js\";\n\nexport function createExtensionsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname\n ? pathname.split(\"/\").map((part) => {\n try {\n return decodeURIComponent(part);\n } catch {\n return part;\n }\n })\n : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = session.email;\n const orgId = orgCtx?.orgId ?? session.orgId ?? undefined;\n\n try {\n return await runWithRequestContext({ userEmail, orgId }, async () => {\n await ensureExtensionsTables();\n return dispatch(event, method, parts, userEmail);\n });\n } catch (err) {\n if (err instanceof ForbiddenError) {\n setResponseStatus(event, 403);\n return { error: err.message };\n }\n throw err;\n }\n });\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n userEmail: string,\n): Promise<unknown> {\n // POST /sql/query — read-only SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"query\"\n ) {\n return handleSqlQuery(event);\n }\n\n // POST /sql/exec — write SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"exec\"\n ) {\n return handleSqlExec(event);\n }\n\n // GET /data/:extensionId/:collection — list items in a collection\n if (method === \"GET\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataList(event, parts[1], parts[2], userEmail);\n }\n\n // POST /data/:extensionId/:collection — create/upsert an item\n if (method === \"POST\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataUpsert(event, parts[1], parts[2], userEmail);\n }\n\n // DELETE /data/:extensionId/:collection/:itemId — delete an item\n if (method === \"DELETE\" && parts.length === 4 && parts[0] === \"data\") {\n return handleExtensionDataDelete(\n event,\n parts[1],\n parts[2],\n parts[3],\n userEmail,\n );\n }\n\n // POST /proxy\n if (method === \"POST\" && parts.length === 1 && parts[0] === \"proxy\") {\n return handleProxy(event, userEmail);\n }\n\n // GET / — list. `?includeGloballyHidden=true` surfaces extensions an\n // admin/owner has globally hidden (so they can be unhidden for everyone).\n if (method === \"GET\" && parts.length === 0) {\n const includeGloballyHidden =\n event.url?.searchParams?.get(\"includeGloballyHidden\") === \"true\";\n const includeContent =\n event.url?.searchParams?.get(\"includeContent\") === \"true\";\n const rows = await listExtensions({ includeGloballyHidden });\n const localRows = includeGloballyHidden ? [] : await listLocalExtensions();\n return Promise.all(\n [...rows, ...localRows].map((row) =>\n extensionResponse(row, undefined, { includeContent }),\n ),\n );\n }\n\n // POST / — create\n if (method === \"POST\" && parts.length === 0) {\n const body = await readBody(event);\n if (!body.name) {\n setResponseStatus(event, 400);\n return { error: \"name is required\" };\n }\n const extension = await createExtension(body);\n setResponseStatus(event, 201);\n return extension;\n }\n\n // GET /:id/render\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"render\") {\n const localExtension = await getLocalExtension(parts[0]);\n if (localExtension) {\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n const html = buildExtensionHtml(\n localExtension.content,\n themeVars,\n isDark,\n parts[0],\n {\n authorEmail: localExtension.ownerEmail,\n viewerEmail: userEmail,\n isAuthor: false,\n role: \"viewer\",\n source: \"local-files\",\n permissions: localExtension.source.permissions,\n },\n );\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", EXTENSION_IFRAME_CSP);\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n const access = await resolveAccess(\"extension\", parts[0]);\n const extension = access?.resource;\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n // Compute viewer-vs-author binding so the iframe can warn when the\n // viewer is NOT the author. The role is plumbed through to gate\n // dangerous bridge helpers in iframe-bridge.ts (audit H4).\n const isAuthor = extension.ownerEmail === userEmail;\n\n const html = buildExtensionHtml(\n extension.content,\n themeVars,\n isDark,\n parts[0],\n {\n authorEmail: extension.ownerEmail,\n viewerEmail: userEmail,\n isAuthor,\n role: access.role,\n },\n );\n // Security headers per render. `frame-ancestors` in the CSP must be set as\n // an HTTP header to be enforced; meta-CSP can't set it per spec.\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", EXTENSION_IFRAME_CSP);\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n // GET /:id/history — list saved snapshots for an extension\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"history\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const limitParam = event.url?.searchParams?.get(\"limit\");\n const limit =\n limitParam === null || limitParam === undefined\n ? undefined\n : Number(limitParam);\n const includeContent =\n event.url?.searchParams?.get(\"includeContent\") === \"true\";\n return {\n history: await listExtensionHistory(parts[0], {\n limit,\n includeContent,\n }),\n };\n }\n\n // GET /:id/history/:version — fetch one snapshot plus its previous-version diff\n if (method === \"GET\" && parts.length === 3 && parts[1] === \"history\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const detail = await getExtensionHistoryVersion(parts[0], parts[2]);\n if (!detail) {\n setResponseStatus(event, 404);\n return { error: \"Extension history version not found\" };\n }\n return detail;\n }\n\n // POST /:id/history/:version/restore — restore display metadata + content\n if (\n method === \"POST\" &&\n parts.length === 4 &&\n parts[1] === \"history\" &&\n parts[3] === \"restore\"\n ) {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const restored = await restoreExtensionHistoryVersion(parts[0], parts[2]);\n if (!restored) {\n setResponseStatus(event, 404);\n return { error: \"Extension history version not found\" };\n }\n return extensionResponse(restored);\n }\n\n // GET /:id\n if (method === \"GET\" && parts.length === 1) {\n const localExtension = await getLocalExtension(parts[0]);\n if (localExtension) {\n return extensionResponse(localExtension, \"viewer\");\n }\n\n const access = await resolveAccess(\"extension\", parts[0]);\n if (!access) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return extensionResponse(access.resource as ExtensionRow, access.role);\n }\n\n // POST /:id/hide — remove from the current user's Extensions list/sidebar\n // without deleting the underlying extension for teammates or shared slots.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"hide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await hideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, hidden: true };\n }\n\n // POST /:id/unhide — restore an extension hidden by the current user.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"unhide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await unhideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, hidden: false };\n }\n\n // POST /:id/global-hide — admin/owner hides the extension from EVERYONE.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"global-hide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await globalHideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, globallyHidden: true };\n }\n\n // POST /:id/global-unhide — admin/owner reverses a global hide.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"global-unhide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await globalUnhideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, globallyHidden: false };\n }\n\n // PUT /:id\n if (method === \"PUT\" && parts.length === 1) {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const body = await readBody(event);\n const hasContentUpdate =\n body.content !== undefined ||\n body.patches !== undefined ||\n body.edits !== undefined ||\n body.format !== undefined;\n const hasMetaUpdate =\n body.name !== undefined ||\n body.description !== undefined ||\n body.icon !== undefined ||\n body.visibility !== undefined;\n\n let result = null;\n if (hasContentUpdate) {\n result = await updateExtensionContent(parts[0], {\n content: body.content,\n patches: body.patches,\n edits: body.edits,\n format: body.format === true || body.format === \"true\",\n });\n }\n if (hasMetaUpdate) {\n result = await updateExtension(parts[0], body);\n }\n if (!hasContentUpdate && !hasMetaUpdate) {\n result = await getExtension(parts[0]);\n }\n if (!result) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return result;\n }\n\n // DELETE /:id\n if (method === \"DELETE\" && parts.length === 1) {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await deleteExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n\nasync function extensionResponse(\n row: ExtensionRow | LocalExtensionRow,\n role?: \"owner\" | ShareRole | null,\n options: { includeContent?: boolean } = {},\n) {\n const local = isLocalExtensionRow(row);\n const resolvedRole = local\n ? \"viewer\"\n : (role ??\n (await resolveAccess(\"extension\", row.id)\n .then((access) => access?.role ?? null)\n .catch(() => null)));\n const responseRow =\n options.includeContent === false\n ? (({ content: _content, ...rest }) => rest)(row)\n : row;\n return {\n ...responseRow,\n role: resolvedRole,\n canEdit: local\n ? false\n : resolvedRole\n ? [\"owner\", \"admin\", \"editor\"].includes(resolvedRole)\n : false,\n canDelete: local\n ? false\n : resolvedRole\n ? [\"owner\", \"admin\"].includes(resolvedRole)\n : false,\n globallyHidden: row.hiddenAt != null,\n };\n}\n\nasync function localExtensionSqlOnlyResponse(\n event: H3Event,\n extensionId: string,\n): Promise<unknown | null> {\n const localExtension = await getLocalExtension(extensionId);\n if (!localExtension) return null;\n setResponseStatus(event, 400);\n return {\n error:\n \"This extension is backed by local files. Edit its extension.json or entry file in the workspace; SQL-backed extension history, sharing, hide, update, and delete operations do not apply.\",\n source: localExtension.source,\n };\n}\n\nasync function handleExtensionDataList(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const access = await requireExtensionDataAccess(event, extensionId, \"viewer\");\n if (!access.ok) return access.response;\n\n const client = getDbExec();\n const url = event.url;\n const limitParam = url?.searchParams?.get(\"limit\");\n const limit = limitParam\n ? Math.min(Math.max(1, Number(limitParam)), 1000)\n : 100;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, orgId, limit],\n });\n return result.rows ?? [];\n }\n\n if (scope === \"all\") {\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ?\n AND ((scope = 'user' AND owner_email = ?) OR (scope = 'org' AND org_id = ?))\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, orgId ?? \"\", limit],\n });\n return result.rows ?? [];\n }\n\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?\n ORDER BY updated_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, limit],\n });\n return result.rows ?? [];\n}\n\nasync function handleExtensionDataUpsert(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const access = await requireExtensionDataAccess(event, extensionId, \"editor\");\n if (!access.ok) return access.response;\n\n const body = await readBody(event);\n if (body.data === undefined) {\n setResponseStatus(event, 400);\n return { error: \"data is required\" };\n }\n const itemId = String(body.id || randomUUID());\n const data =\n typeof body.data === \"string\" ? body.data : JSON.stringify(body.data);\n const now = new Date().toISOString();\n const scope = body.scope === \"org\" ? \"org\" : \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\" && !orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n\n const scopeKey = scope === \"org\" ? `org:${orgId}` : userEmail;\n const client = getDbExec();\n const pg = isPostgres();\n const conflictClause = pg\n ? `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = EXCLUDED.data, updated_at = EXCLUDED.updated_at`\n : `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`;\n\n await client.execute({\n sql: `INSERT INTO tool_data (id, tool_id, collection, item_id, data, owner_email, scope, org_id, scope_key, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ${conflictClause}`,\n args: [\n randomUUID(),\n extensionId,\n collection,\n itemId,\n data,\n userEmail,\n scope,\n scope === \"org\" ? orgId! : null,\n scopeKey,\n now,\n now,\n ],\n });\n return {\n id: itemId,\n extensionId,\n collection,\n data,\n ownerEmail: userEmail,\n scope,\n orgId: scope === \"org\" ? orgId : null,\n createdAt: now,\n updatedAt: now,\n };\n}\n\nasync function handleExtensionDataDelete(\n event: H3Event,\n extensionId: string,\n collection: string,\n itemId: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const access = await requireExtensionDataAccess(event, extensionId, \"editor\");\n if (!access.ok) return access.response;\n\n const url = event.url;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n const client = getDbExec();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?`,\n args: [itemId, extensionId, collection, orgId],\n });\n return { ok: true };\n }\n\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?`,\n args: [itemId, extensionId, collection, userEmail],\n });\n return { ok: true };\n}\n\nasync function requireExtensionDataAccess(\n event: H3Event,\n extensionId: string,\n minRole: ShareRole,\n): Promise<{ ok: true } | { ok: false; response: unknown }> {\n const access = await resolveAccess(\"extension\", extensionId);\n if (access) {\n if (ROLE_RANK[access.role] < ROLE_RANK[minRole]) {\n setResponseStatus(event, 403);\n return {\n ok: false,\n response: {\n error: `Requires ${minRole} role on extension ${extensionId} (have ${access.role})`,\n },\n };\n }\n return { ok: true };\n }\n\n const localExtension = await getLocalExtension(extensionId);\n if (localExtension) {\n if (!localExtension.source.permissions.extensionData) {\n setResponseStatus(event, 403);\n return {\n ok: false,\n response: { error: \"extensionData is disabled for this extension\" },\n };\n }\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { ok: false, response: { error: \"Extension not found\" } };\n}\n\nasync function handleProxy(\n event: H3Event,\n userEmail: string,\n): Promise<unknown> {\n const body = await readBody(event);\n const rawUrl = body.url;\n if (!rawUrl || typeof rawUrl !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"url is required\" };\n }\n\n const method = normalizeExtensionProxyMethod(body.method || \"GET\");\n if (!method) {\n setResponseStatus(event, 405);\n return {\n error:\n \"Unsupported HTTP method. Allowed methods: GET, POST, PUT, PATCH, DELETE, HEAD.\",\n };\n }\n const rawHeaders: Record<string, string> = body.headers || {};\n const rawBody = body.body;\n\n let resolvedUrl = rawUrl;\n // Resolve secret references per header value rather than over a single\n // JSON.stringify(headers) blob. A secret value containing a double-quote\n // would corrupt that JSON, the later JSON.parse would throw, and the request\n // would silently fall back to the *unresolved* headers (placeholders intact).\n const parsedHeaders: Record<string, string> = {};\n let resolvedBody = rawBody;\n const allSecretValues: string[] = [];\n const allResolvedKeys: ResolvedKeyReference[] = [];\n\n try {\n const urlResult = await resolveKeyReferencesWithRequestScopes(\n rawUrl,\n userEmail,\n );\n resolvedUrl = urlResult.resolved;\n allSecretValues.push(...urlResult.secretValues);\n allResolvedKeys.push(...(urlResult.resolvedKeys ?? []));\n\n for (const [hk, hv] of Object.entries(rawHeaders)) {\n const headerResult = await resolveKeyReferencesWithRequestScopes(\n typeof hv === \"string\" ? hv : String(hv),\n userEmail,\n );\n parsedHeaders[hk] = headerResult.resolved;\n allSecretValues.push(...headerResult.secretValues);\n allResolvedKeys.push(...(headerResult.resolvedKeys ?? []));\n }\n\n if (rawBody) {\n const bodyResult = await resolveKeyReferencesWithRequestScopes(\n typeof rawBody === \"string\" ? rawBody : JSON.stringify(rawBody),\n userEmail,\n );\n resolvedBody = bodyResult.resolved;\n allSecretValues.push(...bodyResult.secretValues);\n allResolvedKeys.push(...(bodyResult.resolvedKeys ?? []));\n }\n } catch (err: any) {\n setResponseStatus(event, 400);\n return { error: `Key resolution failed: ${err?.message ?? err}` };\n }\n const secretValues = collectSecretValues(allSecretValues);\n\n if (await isBlockedExtensionUrlWithDns(resolvedUrl)) {\n setResponseStatus(event, 403);\n return { error: \"Requests to private/internal addresses are not allowed\" };\n }\n\n const uniqueResolvedKeys = new Map(\n allResolvedKeys.map((ref) => [\n `${ref.name}:${ref.scope}:${ref.scopeId}`,\n ref,\n ]),\n );\n for (const keyRef of uniqueResolvedKeys.values()) {\n const allowlist = await getResolvedKeyAllowlist(keyRef);\n if (!validateUrlAllowlist(resolvedUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Key \"${keyRef.name}\" is not allowed for this URL origin`,\n };\n }\n }\n\n const headers = sanitizeOutboundHeaders(parsedHeaders);\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n\n // Best-effort connect-time SSRF guard. When undici is available (it ships\n // with Node 18+ but is not always exposed as an importable module), the\n // dispatcher re-checks the resolved IP at TCP-connect time, closing the\n // TOCTOU between the pre-flight `isBlockedExtensionUrlWithDns` lookup and the\n // actual fetch lookup. If undici is not importable, fall through to plain\n // fetch — the pre-flight remains the primary protection.\n const dispatcher = (await createSsrfSafeDispatcher()) ?? undefined;\n\n try {\n const fetchOpts: RequestInit & { dispatcher?: unknown } = {\n method,\n headers,\n signal: controller.signal,\n redirect: \"manual\",\n };\n if (dispatcher) fetchOpts.dispatcher = dispatcher;\n if (resolvedBody && [\"POST\", \"PUT\", \"PATCH\"].includes(method)) {\n const isStringBody = typeof resolvedBody === \"string\";\n fetchOpts.body = isStringBody\n ? resolvedBody\n : JSON.stringify(resolvedBody);\n // Only inject Content-Type when (a) the caller didn't set one and\n // (b) the body is actually JSON-shaped (object or stringified JSON).\n // Otherwise leave it unset so the runtime fetch picks an appropriate\n // default and we don't misrepresent text/plain bodies as JSON.\n const hasContentType = Object.keys(headers).some(\n (k) => k.toLowerCase() === \"content-type\",\n );\n if (!hasContentType) {\n const isJsonShaped =\n !isStringBody ||\n (typeof resolvedBody === \"string\" &&\n /^\\s*[{[]/.test(resolvedBody) &&\n isLikelyJson(resolvedBody));\n if (isJsonShaped) headers[\"Content-Type\"] = \"application/json\";\n }\n }\n\n const response = await fetch(resolvedUrl, fetchOpts);\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get(\"location\");\n const redirectUrl = location ? new URL(location, resolvedUrl).href : null;\n if (redirectUrl && (await isBlockedExtensionUrlWithDns(redirectUrl))) {\n setResponseStatus(event, 403);\n return { error: \"Redirect to private/internal address blocked\" };\n }\n if (redirectUrl) {\n for (const keyRef of uniqueResolvedKeys.values()) {\n const allowlist = await getResolvedKeyAllowlist(keyRef);\n if (!validateUrlAllowlist(redirectUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Redirect URL is not allowed for key \"${keyRef.name}\"`,\n };\n }\n }\n }\n return {\n status: response.status,\n body: {\n redirect: redirectUrl\n ? redactString(redirectUrl, secretValues)\n : location,\n },\n };\n }\n\n const { text } = await readResponseTextWithLimit(response);\n let responseBody: unknown;\n try {\n responseBody = JSON.parse(text);\n } catch {\n responseBody = text;\n }\n\n return {\n status: response.status,\n body: redactSecrets(responseBody, secretValues),\n };\n } catch (err: any) {\n if (err?.name === \"AbortError\") {\n setResponseStatus(event, 504);\n return { error: \"Upstream request timed out\" };\n }\n setResponseStatus(event, 502);\n return {\n error: `Proxy request failed: ${redactSecrets(\n err?.message ?? String(err),\n secretValues,\n )}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Capture console output from a CLI script that uses console.log for results.\n * Same technique as wrapCliScript in agent-chat-plugin.ts.\n */\nlet captureCliOutputQueue: Promise<void> = Promise.resolve();\n\nasync function captureCliOutput(\n fn: (args: string[]) => Promise<void>,\n args: string[],\n): Promise<string> {\n const previousCapture = captureCliOutputQueue;\n let releaseCapture!: () => void;\n captureCliOutputQueue = new Promise<void>((resolve) => {\n releaseCapture = resolve;\n });\n await previousCapture;\n\n const logs: string[] = [];\n const origLog = console.log;\n const origError = console.error;\n const origStdoutWrite = process.stdout.write;\n console.log = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n console.error = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n process.stdout.write = ((chunk: any) => {\n if (typeof chunk === \"string\") logs.push(chunk);\n else if (Buffer.isBuffer(chunk)) logs.push(chunk.toString());\n return true;\n }) as any;\n try {\n await fn(args);\n } catch (err: any) {\n logs.push(`Error: ${err?.message ?? String(err)}`);\n } finally {\n console.log = origLog;\n console.error = origError;\n process.stdout.write = origStdoutWrite;\n releaseCapture();\n }\n return logs.join(\"\\n\") || \"(no output)\";\n}\n\nasync function handleSqlQuery(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (!/^\\s*(SELECT|WITH)\\b/i.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Only SELECT queries are allowed from extensions\" };\n }\n if (matchesSqlGate(SENSITIVE_SQL_RE, sql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not readable from extensions\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/query.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.limit) args.push(\"--limit\", String(body.limit));\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Query failed\" };\n }\n}\n\n// TODO(security): replace this regex blocklist with a SQL parser + an explicit\n// allowlist of tables a extension may read/write (e.g. only `tool_data`, plus a\n// per-template list). The current blocklist is best-effort defense in depth\n// and is by design bypassable via SQL constructions that don't include the\n// blocklisted token literally (string concat, dynamic SQL, etc). The temp-\n// view scoping in scripts/db/scoping.ts is the actual ownership boundary.\nexport const DESTRUCTIVE_SQL_RE =\n /\\b(CREATE\\s+(?:(?:LOCAL|GLOBAL)\\s+)?(?:TEMPORARY|TEMP)?\\s*(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE|TABLESPACE|PUBLICATION|SUBSCRIPTION)|DROP\\s+(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE)|TRUNCATE|DELETE\\s+FROM\\s+(?!tool_data\\b)|ALTER\\s+(TABLE|VIEW|SCHEMA|DATABASE|FUNCTION|ROLE|EXTENSION|PUBLICATION)\\s+(?!tool_data\\b)|ATTACH|DETACH|VACUUM|REINDEX|PRAGMA|GRANT|REVOKE|SET\\s+ROLE|RESET\\s+ROLE|COPY)\\b/i;\n\n// Sensitive tables that extensions must not touch directly. Includes Better Auth\n// identity tables, framework infrastructure (tracing, evals, automations,\n// integrations, notifications, scheduling, sharing/orgs), and Postgres\n// catalogs that would let a extension enumerate or read internals.\nexport const SENSITIVE_SQL_RE =\n /\\b(app_secrets|user|users|session|sessions|account|accounts|verification|oauth_tokens|tools|extensions|tool_shares|tool_slots|tool_slot_installs|tool_hidden_extensions|tool_history|member|organization|invitation|jwks|agent_trace_spans|agent_trace_summaries|agent_feedback|agent_satisfaction_scores|agent_evals|agent_runs|agent_run_events|notifications|progress_runs|integration_configs|integration_pending_tasks|integration_thread_mappings|resources|org_members|org_invitations|bigquery_cache|dashboard_views|pg_catalog|information_schema|pg_class|pg_proc|pg_namespace|pg_user|pg_roles|pg_authid|pg_shadow)\\b/i;\n\n// Refuses positional INSERTs (no column list). `INSERT INTO recordings VALUES\n// (...)` would let a extension stuff arbitrary owner_email values into a row.\n// `INSERT INTO recordings (col1, col2) VALUES (...)` is required so the\n// downstream injectOwnership helper can append owner_email.\nexport const POSITIONAL_INSERT_RE =\n /\\bINSERT\\s+INTO\\s+[\"'`]?\\w+[\"'`]?\\s+VALUES\\b/i;\n\nfunction stripSqlComments(sql: string): string {\n return sql.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/--[^\\n]*/g, \" \");\n}\n\n/**\n * Test a blocklist regex against the SQL with comments normalized two ways, so\n * a comment placed *inside* a keyword can't smuggle a blocked construct past a\n * literal-token match:\n * - comments → space catches `DROP /* x *​/ TABLE` (token boundaries kept)\n * - comments → empty catches `DR/**​/OP TABLE` (split keyword rejoined)\n *\n * A statement is refused if EITHER normalization trips the regex. This only\n * ever ADDS matches — it never newly-allows SQL — so it cannot loosen the gate\n * (real extension SQL doesn't embed comments inside keywords, so false-positive\n * risk is negligible). The authoritative ownership boundary remains the\n * fail-closed temp-view scoping in scripts/db/scoping.ts; this stays defense in\n * depth. See the TODO above re: replacing all of this with a real SQL parser.\n */\nexport function matchesSqlGate(re: RegExp, sql: string): boolean {\n const withSpace = sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \")\n .replace(/--[^\\n]*/g, \" \");\n const withNothing = sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/--[^\\n]*/g, \"\");\n return re.test(withSpace) || re.test(withNothing);\n}\n\nfunction isLikelyJson(text: string): boolean {\n try {\n const parsed = JSON.parse(text);\n return parsed !== null && typeof parsed === \"object\";\n } catch {\n return false;\n }\n}\n\nasync function handleSqlExec(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n if (matchesSqlGate(DESTRUCTIVE_SQL_RE, sql)) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Schema changes and destructive SQL are not allowed from extensions\",\n };\n }\n if (matchesSqlGate(SENSITIVE_SQL_RE, sql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not writable from extensions\",\n };\n }\n if (matchesSqlGate(POSITIONAL_INSERT_RE, sql)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"INSERT must specify an explicit column list (e.g. INSERT INTO t (col1, col2) VALUES (?, ?)) so ownership can be injected.\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/exec.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Exec failed\" };\n }\n}\n"]}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n setResponseHeader,\n type H3Event,\n} from \"h3\";\n\nimport { getDbExec, isPostgres } from \"../db/client.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport {\n resolveKeyReferencesWithRequestScopes,\n validateUrlAllowlist,\n getResolvedKeyAllowlist,\n type ResolvedKeyReference,\n} from \"../secrets/substitution.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport {\n runWithRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { ForbiddenError, resolveAccess } from \"../sharing/access.js\";\nimport { ROLE_RANK, type ShareRole } from \"../sharing/schema.js\";\nimport { buildExtensionHtml, EXTENSION_IFRAME_CSP } from \"./html-shell.js\";\nimport {\n getLocalExtension,\n isLocalExtensionRow,\n listLocalExtensions,\n type LocalExtensionRow,\n} from \"./local.js\";\nimport {\n collectSecretValues,\n normalizeExtensionProxyMethod,\n readResponseTextWithLimit,\n redactSecrets,\n redactString,\n sanitizeOutboundHeaders,\n} from \"./proxy-security.js\";\nimport {\n listExtensions,\n getExtension,\n getExtensionHistoryVersion,\n listExtensionHistory,\n createExtension,\n updateExtension,\n updateExtensionContent,\n restoreExtensionHistoryVersion,\n deleteExtension,\n hideExtension,\n unhideExtension,\n globalHideExtension,\n globalUnhideExtension,\n ensureExtensionsTables,\n type ExtensionRow,\n} from \"./store.js\";\nimport { getThemeVars } from \"./theme.js\";\nimport {\n createSsrfSafeDispatcher,\n isBlockedExtensionUrlWithDns,\n} from \"./url-safety.js\";\n\nexport function createExtensionsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname\n ? pathname.split(\"/\").map((part) => {\n try {\n return decodeURIComponent(part);\n } catch {\n return part;\n }\n })\n : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = normalizeExtensionUserEmail(session.email);\n if (!userEmail) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n const orgId = orgCtx?.orgId ?? session.orgId ?? undefined;\n\n try {\n return await runWithRequestContext({ userEmail, orgId }, async () => {\n await ensureExtensionsTables();\n return dispatch(event, method, parts, userEmail);\n });\n } catch (err) {\n if (err instanceof ForbiddenError) {\n setResponseStatus(event, 403);\n return { error: err.message };\n }\n throw err;\n }\n });\n}\n\nfunction normalizeExtensionUserEmail(email: string): string {\n return email.trim().toLowerCase();\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n userEmail: string,\n): Promise<unknown> {\n // POST /sql/query — read-only SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"query\"\n ) {\n return handleSqlQuery(event);\n }\n\n // POST /sql/exec — write SQL for extension iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"exec\"\n ) {\n return handleSqlExec(event);\n }\n\n // GET /data/:extensionId/:collection — list items in a collection\n if (method === \"GET\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataList(event, parts[1], parts[2], userEmail);\n }\n\n // POST /data/:extensionId/:collection — create/upsert an item\n if (method === \"POST\" && parts.length === 3 && parts[0] === \"data\") {\n return handleExtensionDataUpsert(event, parts[1], parts[2], userEmail);\n }\n\n // DELETE /data/:extensionId/:collection/:itemId — delete an item\n if (method === \"DELETE\" && parts.length === 4 && parts[0] === \"data\") {\n return handleExtensionDataDelete(\n event,\n parts[1],\n parts[2],\n parts[3],\n userEmail,\n );\n }\n\n // POST /proxy\n if (method === \"POST\" && parts.length === 1 && parts[0] === \"proxy\") {\n return handleProxy(event, userEmail);\n }\n\n // GET / — list. `?includeGloballyHidden=true` surfaces extensions an\n // admin/owner has globally hidden (so they can be unhidden for everyone).\n if (method === \"GET\" && parts.length === 0) {\n const includeGloballyHidden =\n event.url?.searchParams?.get(\"includeGloballyHidden\") === \"true\";\n const includeContent =\n event.url?.searchParams?.get(\"includeContent\") === \"true\";\n const rows = await listExtensions({ includeGloballyHidden });\n const localRows = includeGloballyHidden ? [] : await listLocalExtensions();\n return Promise.all(\n [...rows, ...localRows].map((row) =>\n extensionResponse(row, undefined, { includeContent }),\n ),\n );\n }\n\n // POST / — create\n if (method === \"POST\" && parts.length === 0) {\n const body = await readBody(event);\n if (!body.name) {\n setResponseStatus(event, 400);\n return { error: \"name is required\" };\n }\n const extension = await createExtension(body);\n setResponseStatus(event, 201);\n return extension;\n }\n\n // GET /:id/render\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"render\") {\n const localExtension = await getLocalExtension(parts[0]);\n if (localExtension) {\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n const html = buildExtensionHtml(\n localExtension.content,\n themeVars,\n isDark,\n parts[0],\n {\n authorEmail: localExtension.ownerEmail,\n viewerEmail: userEmail,\n isAuthor: false,\n role: \"viewer\",\n source: \"local-files\",\n permissions: localExtension.source.permissions,\n },\n );\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", EXTENSION_IFRAME_CSP);\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n const access = await resolveAccess(\"extension\", parts[0]);\n const extension = access?.resource;\n if (!extension) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n // Compute viewer-vs-author binding so the iframe can warn when the\n // viewer is NOT the author. The role is plumbed through to gate\n // dangerous bridge helpers in iframe-bridge.ts (audit H4).\n const isAuthor = extension.ownerEmail === userEmail;\n\n const html = buildExtensionHtml(\n extension.content,\n themeVars,\n isDark,\n parts[0],\n {\n authorEmail: extension.ownerEmail,\n viewerEmail: userEmail,\n isAuthor,\n role: access.role,\n },\n );\n // Security headers per render. `frame-ancestors` in the CSP must be set as\n // an HTTP header to be enforced; meta-CSP can't set it per spec.\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", EXTENSION_IFRAME_CSP);\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n // GET /:id/history — list saved snapshots for an extension\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"history\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const limitParam = event.url?.searchParams?.get(\"limit\");\n const limit =\n limitParam === null || limitParam === undefined\n ? undefined\n : Number(limitParam);\n const includeContent =\n event.url?.searchParams?.get(\"includeContent\") === \"true\";\n return {\n history: await listExtensionHistory(parts[0], {\n limit,\n includeContent,\n }),\n };\n }\n\n // GET /:id/history/:version — fetch one snapshot plus its previous-version diff\n if (method === \"GET\" && parts.length === 3 && parts[1] === \"history\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const detail = await getExtensionHistoryVersion(parts[0], parts[2]);\n if (!detail) {\n setResponseStatus(event, 404);\n return { error: \"Extension history version not found\" };\n }\n return detail;\n }\n\n // POST /:id/history/:version/restore — restore display metadata + content\n if (\n method === \"POST\" &&\n parts.length === 4 &&\n parts[1] === \"history\" &&\n parts[3] === \"restore\"\n ) {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const restored = await restoreExtensionHistoryVersion(parts[0], parts[2]);\n if (!restored) {\n setResponseStatus(event, 404);\n return { error: \"Extension history version not found\" };\n }\n return extensionResponse(restored);\n }\n\n // GET /:id\n if (method === \"GET\" && parts.length === 1) {\n const localExtension = await getLocalExtension(parts[0]);\n if (localExtension) {\n return extensionResponse(localExtension, \"viewer\");\n }\n\n const access = await resolveAccess(\"extension\", parts[0]);\n if (!access) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return extensionResponse(access.resource as ExtensionRow, access.role);\n }\n\n // POST /:id/hide — remove from the current user's Extensions list/sidebar\n // without deleting the underlying extension for teammates or shared slots.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"hide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await hideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, hidden: true };\n }\n\n // POST /:id/unhide — restore an extension hidden by the current user.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"unhide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await unhideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, hidden: false };\n }\n\n // POST /:id/global-hide — admin/owner hides the extension from EVERYONE.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"global-hide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await globalHideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, globallyHidden: true };\n }\n\n // POST /:id/global-unhide — admin/owner reverses a global hide.\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"global-unhide\") {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await globalUnhideExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true, globallyHidden: false };\n }\n\n // PUT /:id\n if (method === \"PUT\" && parts.length === 1) {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const body = await readBody(event);\n const hasContentUpdate =\n body.content !== undefined ||\n body.patches !== undefined ||\n body.edits !== undefined ||\n body.format !== undefined;\n const hasMetaUpdate =\n body.name !== undefined ||\n body.description !== undefined ||\n body.icon !== undefined ||\n body.visibility !== undefined;\n\n let result = null;\n if (hasContentUpdate) {\n result = await updateExtensionContent(parts[0], {\n content: body.content,\n patches: body.patches,\n edits: body.edits,\n format: body.format === true || body.format === \"true\",\n });\n }\n if (hasMetaUpdate) {\n result = await updateExtension(parts[0], body);\n }\n if (!hasContentUpdate && !hasMetaUpdate) {\n result = await getExtension(parts[0]);\n }\n if (!result) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return result;\n }\n\n // DELETE /:id\n if (method === \"DELETE\" && parts.length === 1) {\n const localResponse = await localExtensionSqlOnlyResponse(event, parts[0]);\n if (localResponse) return localResponse;\n const ok = await deleteExtension(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Extension not found\" };\n }\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n\nasync function extensionResponse(\n row: ExtensionRow | LocalExtensionRow,\n role?: \"owner\" | ShareRole | null,\n options: { includeContent?: boolean } = {},\n) {\n const local = isLocalExtensionRow(row);\n const resolvedRole = local\n ? \"viewer\"\n : (role ??\n (await resolveAccess(\"extension\", row.id)\n .then((access) => access?.role ?? null)\n .catch(() => null)));\n const responseRow =\n options.includeContent === false\n ? (({ content: _content, ...rest }) => rest)(row)\n : row;\n return {\n ...responseRow,\n role: resolvedRole,\n canEdit: local\n ? false\n : resolvedRole\n ? [\"owner\", \"admin\", \"editor\"].includes(resolvedRole)\n : false,\n canDelete: local\n ? false\n : resolvedRole\n ? [\"owner\", \"admin\"].includes(resolvedRole)\n : false,\n globallyHidden: row.hiddenAt != null,\n };\n}\n\nasync function localExtensionSqlOnlyResponse(\n event: H3Event,\n extensionId: string,\n): Promise<unknown | null> {\n const localExtension = await getLocalExtension(extensionId);\n if (!localExtension) return null;\n setResponseStatus(event, 400);\n return {\n error:\n \"This extension is backed by local files. Edit its extension.json or entry file in the workspace; SQL-backed extension history, sharing, hide, update, and delete operations do not apply.\",\n source: localExtension.source,\n };\n}\n\nasync function handleExtensionDataList(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const access = await requireExtensionDataAccess(event, extensionId, \"viewer\");\n if (!access.ok) return access.response;\n\n const client = getDbExec();\n const url = event.url;\n const limitParam = url?.searchParams?.get(\"limit\");\n const limit = limitParam\n ? Math.min(Math.max(1, Number(limitParam)), 1000)\n : 100;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, orgId, limit],\n });\n return result.rows ?? [];\n }\n\n if (scope === \"all\") {\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ?\n AND ((scope = 'user' AND lower(owner_email) = ?) OR (scope = 'org' AND org_id = ?))\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, orgId ?? \"\", limit],\n });\n return result.rows ?? [];\n }\n\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'user' AND lower(owner_email) = ?\n ORDER BY updated_at DESC\n LIMIT ?`,\n args: [extensionId, collection, userEmail, limit],\n });\n return result.rows ?? [];\n}\n\nasync function handleExtensionDataUpsert(\n event: H3Event,\n extensionId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const access = await requireExtensionDataAccess(event, extensionId, \"editor\");\n if (!access.ok) return access.response;\n\n const body = await readBody(event);\n if (body.data === undefined) {\n setResponseStatus(event, 400);\n return { error: \"data is required\" };\n }\n const itemId = String(body.id || randomUUID());\n const data =\n typeof body.data === \"string\" ? body.data : JSON.stringify(body.data);\n const now = new Date().toISOString();\n const scope = body.scope === \"org\" ? \"org\" : \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\" && !orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n\n const scopeKey = scope === \"org\" ? `org:${orgId}` : userEmail;\n const client = getDbExec();\n const pg = isPostgres();\n const conflictClause = pg\n ? `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = EXCLUDED.data, updated_at = EXCLUDED.updated_at`\n : `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`;\n\n await client.execute({\n sql: `INSERT INTO tool_data (id, tool_id, collection, item_id, data, owner_email, scope, org_id, scope_key, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ${conflictClause}`,\n args: [\n randomUUID(),\n extensionId,\n collection,\n itemId,\n data,\n userEmail,\n scope,\n scope === \"org\" ? orgId! : null,\n scopeKey,\n now,\n now,\n ],\n });\n return {\n id: itemId,\n extensionId,\n collection,\n data,\n ownerEmail: userEmail,\n scope,\n orgId: scope === \"org\" ? orgId : null,\n createdAt: now,\n updatedAt: now,\n };\n}\n\nasync function handleExtensionDataDelete(\n event: H3Event,\n extensionId: string,\n collection: string,\n itemId: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureExtensionsTables();\n const access = await requireExtensionDataAccess(event, extensionId, \"editor\");\n if (!access.ok) return access.response;\n\n const url = event.url;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n const client = getDbExec();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?`,\n args: [itemId, extensionId, collection, orgId],\n });\n return { ok: true };\n }\n\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND lower(owner_email) = ?`,\n args: [itemId, extensionId, collection, userEmail],\n });\n return { ok: true };\n}\n\nasync function requireExtensionDataAccess(\n event: H3Event,\n extensionId: string,\n minRole: ShareRole,\n): Promise<{ ok: true } | { ok: false; response: unknown }> {\n const access = await resolveAccess(\"extension\", extensionId);\n if (access) {\n if (ROLE_RANK[access.role] < ROLE_RANK[minRole]) {\n setResponseStatus(event, 403);\n return {\n ok: false,\n response: {\n error: `Requires ${minRole} role on extension ${extensionId} (have ${access.role})`,\n },\n };\n }\n return { ok: true };\n }\n\n const localExtension = await getLocalExtension(extensionId);\n if (localExtension) {\n if (!localExtension.source.permissions.extensionData) {\n setResponseStatus(event, 403);\n return {\n ok: false,\n response: { error: \"extensionData is disabled for this extension\" },\n };\n }\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { ok: false, response: { error: \"Extension not found\" } };\n}\n\nasync function handleProxy(\n event: H3Event,\n userEmail: string,\n): Promise<unknown> {\n const body = await readBody(event);\n const rawUrl = body.url;\n if (!rawUrl || typeof rawUrl !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"url is required\" };\n }\n\n const method = normalizeExtensionProxyMethod(body.method || \"GET\");\n if (!method) {\n setResponseStatus(event, 405);\n return {\n error:\n \"Unsupported HTTP method. Allowed methods: GET, POST, PUT, PATCH, DELETE, HEAD.\",\n };\n }\n const rawHeaders: Record<string, string> = body.headers || {};\n const rawBody = body.body;\n\n let resolvedUrl = rawUrl;\n // Resolve secret references per header value rather than over a single\n // JSON.stringify(headers) blob. A secret value containing a double-quote\n // would corrupt that JSON, the later JSON.parse would throw, and the request\n // would silently fall back to the *unresolved* headers (placeholders intact).\n const parsedHeaders: Record<string, string> = {};\n let resolvedBody = rawBody;\n const allSecretValues: string[] = [];\n const allResolvedKeys: ResolvedKeyReference[] = [];\n\n try {\n const urlResult = await resolveKeyReferencesWithRequestScopes(\n rawUrl,\n userEmail,\n );\n resolvedUrl = urlResult.resolved;\n allSecretValues.push(...urlResult.secretValues);\n allResolvedKeys.push(...(urlResult.resolvedKeys ?? []));\n\n for (const [hk, hv] of Object.entries(rawHeaders)) {\n const headerResult = await resolveKeyReferencesWithRequestScopes(\n typeof hv === \"string\" ? hv : String(hv),\n userEmail,\n );\n parsedHeaders[hk] = headerResult.resolved;\n allSecretValues.push(...headerResult.secretValues);\n allResolvedKeys.push(...(headerResult.resolvedKeys ?? []));\n }\n\n if (rawBody) {\n const bodyResult = await resolveKeyReferencesWithRequestScopes(\n typeof rawBody === \"string\" ? rawBody : JSON.stringify(rawBody),\n userEmail,\n );\n resolvedBody = bodyResult.resolved;\n allSecretValues.push(...bodyResult.secretValues);\n allResolvedKeys.push(...(bodyResult.resolvedKeys ?? []));\n }\n } catch (err: any) {\n setResponseStatus(event, 400);\n return { error: `Key resolution failed: ${err?.message ?? err}` };\n }\n const secretValues = collectSecretValues(allSecretValues);\n\n if (await isBlockedExtensionUrlWithDns(resolvedUrl)) {\n setResponseStatus(event, 403);\n return { error: \"Requests to private/internal addresses are not allowed\" };\n }\n\n const uniqueResolvedKeys = new Map(\n allResolvedKeys.map((ref) => [\n `${ref.name}:${ref.scope}:${ref.scopeId}`,\n ref,\n ]),\n );\n for (const keyRef of uniqueResolvedKeys.values()) {\n const allowlist = await getResolvedKeyAllowlist(keyRef);\n if (!validateUrlAllowlist(resolvedUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Key \"${keyRef.name}\" is not allowed for this URL origin`,\n };\n }\n }\n\n const headers = sanitizeOutboundHeaders(parsedHeaders);\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n\n // Best-effort connect-time SSRF guard. When undici is available (it ships\n // with Node 18+ but is not always exposed as an importable module), the\n // dispatcher re-checks the resolved IP at TCP-connect time, closing the\n // TOCTOU between the pre-flight `isBlockedExtensionUrlWithDns` lookup and the\n // actual fetch lookup. If undici is not importable, fall through to plain\n // fetch — the pre-flight remains the primary protection.\n const dispatcher = (await createSsrfSafeDispatcher()) ?? undefined;\n\n try {\n const fetchOpts: RequestInit & { dispatcher?: unknown } = {\n method,\n headers,\n signal: controller.signal,\n redirect: \"manual\",\n };\n if (dispatcher) fetchOpts.dispatcher = dispatcher;\n if (resolvedBody && [\"POST\", \"PUT\", \"PATCH\"].includes(method)) {\n const isStringBody = typeof resolvedBody === \"string\";\n fetchOpts.body = isStringBody\n ? resolvedBody\n : JSON.stringify(resolvedBody);\n // Only inject Content-Type when (a) the caller didn't set one and\n // (b) the body is actually JSON-shaped (object or stringified JSON).\n // Otherwise leave it unset so the runtime fetch picks an appropriate\n // default and we don't misrepresent text/plain bodies as JSON.\n const hasContentType = Object.keys(headers).some(\n (k) => k.toLowerCase() === \"content-type\",\n );\n if (!hasContentType) {\n const isJsonShaped =\n !isStringBody ||\n (typeof resolvedBody === \"string\" &&\n /^\\s*[{[]/.test(resolvedBody) &&\n isLikelyJson(resolvedBody));\n if (isJsonShaped) headers[\"Content-Type\"] = \"application/json\";\n }\n }\n\n const response = await fetch(resolvedUrl, fetchOpts);\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get(\"location\");\n const redirectUrl = location ? new URL(location, resolvedUrl).href : null;\n if (redirectUrl && (await isBlockedExtensionUrlWithDns(redirectUrl))) {\n setResponseStatus(event, 403);\n return { error: \"Redirect to private/internal address blocked\" };\n }\n if (redirectUrl) {\n for (const keyRef of uniqueResolvedKeys.values()) {\n const allowlist = await getResolvedKeyAllowlist(keyRef);\n if (!validateUrlAllowlist(redirectUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Redirect URL is not allowed for key \"${keyRef.name}\"`,\n };\n }\n }\n }\n return {\n status: response.status,\n body: {\n redirect: redirectUrl\n ? redactString(redirectUrl, secretValues)\n : location,\n },\n };\n }\n\n const { text } = await readResponseTextWithLimit(response);\n let responseBody: unknown;\n try {\n responseBody = JSON.parse(text);\n } catch {\n responseBody = text;\n }\n\n return {\n status: response.status,\n body: redactSecrets(responseBody, secretValues),\n };\n } catch (err: any) {\n if (err?.name === \"AbortError\") {\n setResponseStatus(event, 504);\n return { error: \"Upstream request timed out\" };\n }\n setResponseStatus(event, 502);\n return {\n error: `Proxy request failed: ${redactSecrets(\n err?.message ?? String(err),\n secretValues,\n )}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Capture console output from a CLI script that uses console.log for results.\n * Same technique as wrapCliScript in agent-chat-plugin.ts.\n */\nlet captureCliOutputQueue: Promise<void> = Promise.resolve();\n\nasync function captureCliOutput(\n fn: (args: string[]) => Promise<void>,\n args: string[],\n): Promise<string> {\n const previousCapture = captureCliOutputQueue;\n let releaseCapture!: () => void;\n captureCliOutputQueue = new Promise<void>((resolve) => {\n releaseCapture = resolve;\n });\n await previousCapture;\n\n const logs: string[] = [];\n const origLog = console.log;\n const origError = console.error;\n const origStdoutWrite = process.stdout.write;\n console.log = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n console.error = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n process.stdout.write = ((chunk: any) => {\n if (typeof chunk === \"string\") logs.push(chunk);\n else if (Buffer.isBuffer(chunk)) logs.push(chunk.toString());\n return true;\n }) as any;\n try {\n await fn(args);\n } catch (err: any) {\n logs.push(`Error: ${err?.message ?? String(err)}`);\n } finally {\n console.log = origLog;\n console.error = origError;\n process.stdout.write = origStdoutWrite;\n releaseCapture();\n }\n return logs.join(\"\\n\") || \"(no output)\";\n}\n\nasync function handleSqlQuery(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (!/^\\s*(SELECT|WITH)\\b/i.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Only SELECT queries are allowed from extensions\" };\n }\n if (matchesSqlGate(SENSITIVE_SQL_RE, sql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not readable from extensions\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/query.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.limit) args.push(\"--limit\", String(body.limit));\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Query failed\" };\n }\n}\n\n// TODO(security): replace this regex blocklist with a SQL parser + an explicit\n// allowlist of tables a extension may read/write (e.g. only `tool_data`, plus a\n// per-template list). The current blocklist is best-effort defense in depth\n// and is by design bypassable via SQL constructions that don't include the\n// blocklisted token literally (string concat, dynamic SQL, etc). The temp-\n// view scoping in scripts/db/scoping.ts is the actual ownership boundary.\nexport const DESTRUCTIVE_SQL_RE =\n /\\b(CREATE\\s+(?:(?:LOCAL|GLOBAL)\\s+)?(?:TEMPORARY|TEMP)?\\s*(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE|TABLESPACE|PUBLICATION|SUBSCRIPTION)|DROP\\s+(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE)|TRUNCATE|DELETE\\s+FROM\\s+(?!tool_data\\b)|ALTER\\s+(TABLE|VIEW|SCHEMA|DATABASE|FUNCTION|ROLE|EXTENSION|PUBLICATION)\\s+(?!tool_data\\b)|ATTACH|DETACH|VACUUM|REINDEX|PRAGMA|GRANT|REVOKE|SET\\s+ROLE|RESET\\s+ROLE|COPY)\\b/i;\n\n// Sensitive tables that extensions must not touch directly. Includes Better Auth\n// identity tables, framework infrastructure (tracing, evals, automations,\n// integrations, notifications, scheduling, sharing/orgs), and Postgres\n// catalogs that would let a extension enumerate or read internals.\nexport const SENSITIVE_SQL_RE =\n /\\b(app_secrets|user|users|session|sessions|account|accounts|verification|oauth_tokens|tools|extensions|tool_shares|tool_slots|tool_slot_installs|tool_hidden_extensions|tool_history|member|organization|invitation|jwks|agent_trace_spans|agent_trace_summaries|agent_feedback|agent_satisfaction_scores|agent_evals|agent_runs|agent_run_events|notifications|progress_runs|integration_configs|integration_pending_tasks|integration_thread_mappings|resources|org_members|org_invitations|bigquery_cache|dashboard_views|pg_catalog|information_schema|pg_class|pg_proc|pg_namespace|pg_user|pg_roles|pg_authid|pg_shadow)\\b/i;\n\n// Refuses positional INSERTs (no column list). `INSERT INTO recordings VALUES\n// (...)` would let a extension stuff arbitrary owner_email values into a row.\n// `INSERT INTO recordings (col1, col2) VALUES (...)` is required so the\n// downstream injectOwnership helper can append owner_email.\nexport const POSITIONAL_INSERT_RE =\n /\\bINSERT\\s+INTO\\s+[\"'`]?\\w+[\"'`]?\\s+VALUES\\b/i;\n\nfunction stripSqlComments(sql: string): string {\n return sql.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/--[^\\n]*/g, \" \");\n}\n\n/**\n * Test a blocklist regex against the SQL with comments normalized two ways, so\n * a comment placed *inside* a keyword can't smuggle a blocked construct past a\n * literal-token match:\n * - comments → space catches `DROP /* x *​/ TABLE` (token boundaries kept)\n * - comments → empty catches `DR/**​/OP TABLE` (split keyword rejoined)\n *\n * A statement is refused if EITHER normalization trips the regex. This only\n * ever ADDS matches — it never newly-allows SQL — so it cannot loosen the gate\n * (real extension SQL doesn't embed comments inside keywords, so false-positive\n * risk is negligible). The authoritative ownership boundary remains the\n * fail-closed temp-view scoping in scripts/db/scoping.ts; this stays defense in\n * depth. See the TODO above re: replacing all of this with a real SQL parser.\n */\nexport function matchesSqlGate(re: RegExp, sql: string): boolean {\n const withSpace = sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \")\n .replace(/--[^\\n]*/g, \" \");\n const withNothing = sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/--[^\\n]*/g, \"\");\n return re.test(withSpace) || re.test(withNothing);\n}\n\nfunction isLikelyJson(text: string): boolean {\n try {\n const parsed = JSON.parse(text);\n return parsed !== null && typeof parsed === \"object\";\n } catch {\n return false;\n }\n}\n\nasync function handleSqlExec(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n if (matchesSqlGate(DESTRUCTIVE_SQL_RE, sql)) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Schema changes and destructive SQL are not allowed from extensions\",\n };\n }\n if (matchesSqlGate(SENSITIVE_SQL_RE, sql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Sensitive framework tables are not writable from extensions\",\n };\n }\n if (matchesSqlGate(POSITIONAL_INSERT_RE, sql)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"INSERT must specify an explicit column list (e.g. INSERT INTO t (col1, col2) VALUES (?, ?)) so ownership can be injected.\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/exec.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Exec failed\" };\n }\n}\n"]}
@@ -3,18 +3,18 @@ declare const _default: import("../../action.js").ActionDefinition<{
3
3
  url?: string;
4
4
  filename?: string;
5
5
  }, {
6
- id?: undefined;
7
6
  error: string;
8
7
  configured?: undefined;
9
8
  connectPath?: undefined;
10
9
  url?: undefined;
10
+ id?: undefined;
11
11
  provider?: undefined;
12
12
  } | {
13
- id?: undefined;
14
13
  error: string;
15
14
  configured: boolean;
16
15
  connectPath: string;
17
16
  url?: undefined;
17
+ id?: undefined;
18
18
  provider?: undefined;
19
19
  } | {
20
20
  error?: undefined;
@@ -2,7 +2,7 @@ export { addContextToAgentChat, appendAgentChatContextToMessage, clearAgentChatC
2
2
  export { agentChat } from "./shared/index.js";
3
3
  export { parseArgs, camelCaseArgs } from "./scripts/parse-args.js";
4
4
  export { defineAction, AgentActionStopError, isAgentActionStopError, type ActionHttpConfig, type AgentActionStopOptions, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, type ActionMcpAppConfig, type ActionMcpAppCsp, type ActionMcpAppCspBuilder, type ActionMcpAppHtmlBuilder, type ActionMcpAppPermissions, type ActionMcpAppResourceConfig, type ActionMcpAppResourceMeta, } from "./action.js";
5
- export { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, type ActionChatUIConfig, } from "./action-ui.js";
5
+ export { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER, type ActionChatUIConfig, } from "./action-ui.js";
6
6
  export { DATA_CHART_WIDGET, DATA_INSIGHTS_WIDGET, DATA_TABLE_WIDGET, createDataChartWidgetResult, createDataInsightsWidgetResult, createDataTableWidgetResult, dataChartWidgetResultSchema, dataChartWidgetSchema, dataInsightsWidgetResultSchema, dataTableWidgetResultSchema, dataTableWidgetSchema, dataWidgetResultSchema, isDataChartWidget, isDataTableWidget, isDataWidgetResult, normalizeDataWidgetKind, normalizeDataWidgetResult, type DataChartSeriesDefinition, type DataChartWidget, type DataChartWidgetResult, type DataChartWidgetResultInput, type DataInsightsWidgetResult, type DataInsightsWidgetResultInput, type DataTableColumn, type DataTableWidget, type DataTableWidgetResult, type DataTableWidgetResultInput, type DataWidgetDisplay, type DataWidgetKind, type DataWidgetResult, type DataWidgetResultMetadata, } from "./data-widgets/index.js";
7
7
  export { embedApp, MCP_APP_REQUEST_ORIGIN_CSP_SOURCE, type EmbedAppOptions, } from "./mcp/embed-app.js";
8
8
  export { embedRoute, type EmbedRouteContext, type EmbedRouteOptions, type EmbedRoutePathBuilder, type EmbedRouteResult, } from "./mcp/embed-route.js";