@agent-native/core 0.95.1 → 0.97.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 (655) hide show
  1. package/README.md +6 -0
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +64 -0
  4. package/corpus/core/docs/content/audit-log.mdx +2 -1
  5. package/corpus/core/docs/content/automations.mdx +7 -7
  6. package/corpus/core/docs/content/creating-templates.mdx +1 -1
  7. package/corpus/core/docs/content/internationalization.mdx +2 -1
  8. package/corpus/core/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  9. package/corpus/core/docs/content/locales/ar-SA/automations.mdx +7 -7
  10. package/corpus/core/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  11. package/corpus/core/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  12. package/corpus/core/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  13. package/corpus/core/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  14. package/corpus/core/docs/content/locales/ar-SA/security.mdx +8 -0
  15. package/corpus/core/docs/content/locales/de-DE/audit-log.mdx +2 -1
  16. package/corpus/core/docs/content/locales/de-DE/automations.mdx +7 -7
  17. package/corpus/core/docs/content/locales/de-DE/getting-started.mdx +7 -1
  18. package/corpus/core/docs/content/locales/de-DE/internationalization.mdx +1 -1
  19. package/corpus/core/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  20. package/corpus/core/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  21. package/corpus/core/docs/content/locales/de-DE/security.mdx +8 -0
  22. package/corpus/core/docs/content/locales/es-ES/audit-log.mdx +2 -1
  23. package/corpus/core/docs/content/locales/es-ES/automations.mdx +7 -7
  24. package/corpus/core/docs/content/locales/es-ES/getting-started.mdx +7 -1
  25. package/corpus/core/docs/content/locales/es-ES/internationalization.mdx +1 -1
  26. package/corpus/core/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  27. package/corpus/core/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  28. package/corpus/core/docs/content/locales/es-ES/security.mdx +8 -0
  29. package/corpus/core/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  30. package/corpus/core/docs/content/locales/fr-FR/automations.mdx +7 -7
  31. package/corpus/core/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  32. package/corpus/core/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  33. package/corpus/core/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  34. package/corpus/core/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  35. package/corpus/core/docs/content/locales/fr-FR/security.mdx +8 -0
  36. package/corpus/core/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  37. package/corpus/core/docs/content/locales/hi-IN/automations.mdx +7 -7
  38. package/corpus/core/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  39. package/corpus/core/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  40. package/corpus/core/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  41. package/corpus/core/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  42. package/corpus/core/docs/content/locales/hi-IN/security.mdx +8 -0
  43. package/corpus/core/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  44. package/corpus/core/docs/content/locales/ja-JP/automations.mdx +7 -7
  45. package/corpus/core/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  46. package/corpus/core/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  47. package/corpus/core/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  48. package/corpus/core/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  49. package/corpus/core/docs/content/locales/ja-JP/security.mdx +8 -0
  50. package/corpus/core/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  51. package/corpus/core/docs/content/locales/ko-KR/automations.mdx +7 -7
  52. package/corpus/core/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  53. package/corpus/core/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  54. package/corpus/core/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  55. package/corpus/core/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  56. package/corpus/core/docs/content/locales/ko-KR/security.mdx +8 -0
  57. package/corpus/core/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  58. package/corpus/core/docs/content/locales/pt-BR/automations.mdx +7 -7
  59. package/corpus/core/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  60. package/corpus/core/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  61. package/corpus/core/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  62. package/corpus/core/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  63. package/corpus/core/docs/content/locales/pt-BR/security.mdx +8 -0
  64. package/corpus/core/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  65. package/corpus/core/docs/content/locales/zh-CN/automations.mdx +7 -7
  66. package/corpus/core/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  67. package/corpus/core/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  68. package/corpus/core/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  69. package/corpus/core/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  70. package/corpus/core/docs/content/locales/zh-CN/security.mdx +8 -0
  71. package/corpus/core/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  72. package/corpus/core/docs/content/locales/zh-TW/automations.mdx +7 -7
  73. package/corpus/core/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  74. package/corpus/core/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  75. package/corpus/core/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  76. package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  77. package/corpus/core/docs/content/locales/zh-TW/security.mdx +8 -0
  78. package/corpus/core/docs/content/package-lifecycle.mdx +51 -0
  79. package/corpus/core/docs/content/sandbox-adapters.mdx +16 -5
  80. package/corpus/core/package.json +11 -2
  81. package/corpus/core/src/a2a/auth-policy.ts +33 -0
  82. package/corpus/core/src/a2a/client.ts +11 -1
  83. package/corpus/core/src/agent/durable-background.ts +15 -7
  84. package/corpus/core/src/agent/production-agent.ts +87 -27
  85. package/corpus/core/src/agent/run-store.ts +13 -4
  86. package/corpus/core/src/agent/thread-data-builder.ts +7 -5
  87. package/corpus/core/src/audit/actions/export-audit-events.ts +162 -0
  88. package/corpus/core/src/audit/store.ts +8 -3
  89. package/corpus/core/src/audit/types.ts +3 -0
  90. package/corpus/core/src/chat-threads/store.ts +20 -1
  91. package/corpus/core/src/cli/code-agent-executor.ts +1 -0
  92. package/corpus/core/src/cli/code-agent-runs.ts +14 -0
  93. package/corpus/core/src/cli/doctor.ts +396 -0
  94. package/corpus/core/src/cli/index.ts +56 -0
  95. package/corpus/core/src/cli/info.ts +3 -3
  96. package/corpus/core/src/cli/package-lifecycle.ts +821 -0
  97. package/corpus/core/src/client/AgentPanel.tsx +32 -25
  98. package/corpus/core/src/client/AssistantChat.tsx +36 -20
  99. package/corpus/core/src/client/MultiTabAssistantChat.tsx +141 -90
  100. package/corpus/core/src/client/agent-chat-adapter.ts +9 -9
  101. package/corpus/core/src/client/chat/ChatHistoryList.tsx +404 -0
  102. package/corpus/core/src/client/chat/index.ts +6 -0
  103. package/corpus/core/src/client/chat/tool-call-display.tsx +37 -3
  104. package/corpus/core/src/client/code-agent-chat-adapter.ts +72 -4
  105. package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +52 -11
  106. package/corpus/core/src/client/composer/TiptapComposer.tsx +157 -20
  107. package/corpus/core/src/client/composer/VoiceButton.tsx +28 -0
  108. package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +5 -0
  109. package/corpus/core/src/client/conversation/code-agent-transcript.ts +4 -5
  110. package/corpus/core/src/client/guided-questions.tsx +2 -1
  111. package/corpus/core/src/client/index.ts +11 -0
  112. package/corpus/core/src/client/use-chat-threads.ts +10 -1
  113. package/corpus/core/src/client/voice-provider-status.ts +44 -0
  114. package/corpus/core/src/code-agents/transcript-normalizer.ts +76 -0
  115. package/corpus/core/src/deploy/build.ts +12 -11
  116. package/corpus/core/src/guards/db-tool-scoping.ts +129 -0
  117. package/corpus/core/src/guards/index.ts +23 -0
  118. package/corpus/core/src/guards/no-drizzle-push.ts +116 -0
  119. package/corpus/core/src/guards/no-env-credentials.ts +229 -0
  120. package/corpus/core/src/guards/no-env-mutation.ts +114 -0
  121. package/corpus/core/src/guards/no-localhost-fallback.ts +124 -0
  122. package/corpus/core/src/guards/no-unscoped-credentials.ts +227 -0
  123. package/corpus/core/src/guards/no-unscoped-queries.ts +834 -0
  124. package/corpus/core/src/guards/scan-utils.ts +105 -0
  125. package/corpus/core/src/guards/types.ts +30 -0
  126. package/corpus/core/src/integrations/a2a-continuation-processor.ts +35 -5
  127. package/corpus/core/src/integrations/adapters/slack.ts +74 -21
  128. package/corpus/core/src/integrations/webhook-handler.ts +14 -0
  129. package/corpus/core/src/localization/default-messages.ts +6 -0
  130. package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
  131. package/corpus/core/src/observability/routes.ts +17 -0
  132. package/corpus/core/src/observability/store.ts +4 -1
  133. package/corpus/core/src/observability/traces.ts +41 -2
  134. package/corpus/core/src/org/accept-pending.ts +9 -1
  135. package/corpus/core/src/org/migrations.ts +41 -0
  136. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  137. package/corpus/core/src/package-lifecycle/manifest.ts +120 -0
  138. package/corpus/core/src/provider-api/custom-registry.ts +56 -0
  139. package/corpus/core/src/provider-api/index.ts +2 -0
  140. package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +19 -1
  141. package/corpus/core/src/scripts/call-agent.ts +53 -3
  142. package/corpus/core/src/scripts/chat/search-chats.ts +11 -8
  143. package/corpus/core/src/secrets/register-framework-secrets.ts +1 -1
  144. package/corpus/core/src/secrets/storage.ts +47 -27
  145. package/corpus/core/src/server/action-discovery.ts +4 -0
  146. package/corpus/core/src/server/agent-chat-plugin.ts +95 -18
  147. package/corpus/core/src/server/core-routes-plugin.ts +45 -14
  148. package/corpus/core/src/server/csrf.ts +24 -5
  149. package/corpus/core/src/server/framework-request-handler.ts +34 -0
  150. package/corpus/core/src/server/google-realtime-session.ts +1 -36
  151. package/corpus/core/src/server/poll.ts +24 -2
  152. package/corpus/core/src/server/realtime-voice.ts +80 -24
  153. package/corpus/core/src/server/request-origin.ts +63 -0
  154. package/corpus/core/src/server/transcribe-voice.ts +1 -50
  155. package/corpus/core/src/server/voice-providers-status.ts +4 -3
  156. package/corpus/core/src/shared/cache-control.ts +2 -8
  157. package/corpus/core/src/styles/agent-native.css +1 -0
  158. package/corpus/core/src/styles/chat-history-list.css +313 -0
  159. package/corpus/core/src/templates/default/package.json +2 -2
  160. package/corpus/core/src/templates/headless/package.json +0 -1
  161. package/corpus/core/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  162. package/corpus/core/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  163. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  164. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
  165. package/corpus/core/src/templates/workspace-core/package.json +0 -1
  166. package/corpus/core/src/templates/workspace-root/package.json +0 -1
  167. package/corpus/core/src/triggers/actions.ts +11 -3
  168. package/corpus/core/src/triggers/types.ts +7 -1
  169. package/corpus/core/src/vite/client.ts +1 -0
  170. package/corpus/templates/analytics/AGENTS.md +7 -0
  171. package/corpus/templates/analytics/actions/bigquery.ts +26 -2
  172. package/corpus/templates/analytics/actions/compose-dashboard.ts +65 -37
  173. package/corpus/templates/analytics/actions/data-source-status.ts +18 -0
  174. package/corpus/templates/analytics/actions/mutate-dashboard.ts +73 -24
  175. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +16 -13
  176. package/corpus/templates/analytics/actions/update-dashboard.ts +53 -42
  177. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +5 -4
  178. package/corpus/templates/analytics/app/global.css +10 -0
  179. package/corpus/templates/analytics/app/pages/Ask.tsx +25 -2
  180. package/corpus/templates/analytics/changelog/2026-07-10-analytics-answers-simple-time-bounded-metrics-without-unnece.md +6 -0
  181. package/corpus/templates/analytics/changelog/2026-07-10-analytics-chat-reliably-uses-connected-data-sources-across-s.md +6 -0
  182. package/corpus/templates/analytics/changelog/2026-07-10-chat-threads-now-stay-clear-of-top-actions-and-fade-smoothly.md +6 -0
  183. package/corpus/templates/analytics/changelog/2026-07-10-context-chips-can-now-be-selected-and-removed-one-at-a-time-.md +6 -0
  184. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-edits-from-the-agent-and-the-ui-at-the-same-time-n.md +6 -0
  185. package/corpus/templates/analytics/changelog/2026-07-10-the-ask-composer-no-longer-carries-dashboard-or-panel-contex.md +6 -0
  186. package/corpus/templates/analytics/changelog/2026-07-10-the-ask-section-stays-highlighted-while-its-chat-history-is-.md +6 -0
  187. package/corpus/templates/analytics/changelog/2026-07-10-timed-out-bigquery-jobs-are-now-cancelled-so-they-stop-consu.md +6 -0
  188. package/corpus/templates/analytics/package.json +1 -2
  189. package/corpus/templates/analytics/server/lib/bigquery.ts +91 -14
  190. package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
  191. package/corpus/templates/analytics/server/plugins/agent-chat.ts +82 -7
  192. package/corpus/templates/assets/package.json +1 -2
  193. package/corpus/templates/brain/package.json +1 -2
  194. package/corpus/templates/calendar/package.json +1 -2
  195. package/corpus/templates/chat/package.json +1 -2
  196. package/corpus/templates/clips/changelog/2026-07-10-atomic-view-tracking.md +6 -0
  197. package/corpus/templates/clips/chrome-extension/package.json +3 -2
  198. package/corpus/templates/clips/desktop/package.json +6 -4
  199. package/corpus/templates/clips/desktop/src/lib/recorder.ts +26 -13
  200. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +4 -1
  201. package/corpus/templates/clips/package.json +1 -2
  202. package/corpus/templates/clips/server/db/schema.ts +29 -17
  203. package/corpus/templates/clips/server/plugins/db.ts +8 -0
  204. package/corpus/templates/clips/server/routes/api/view-event.post.ts +260 -105
  205. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +16 -0
  206. package/corpus/templates/content/AGENTS.md +72 -62
  207. package/corpus/templates/content/actions/_content-database-source-adapters.ts +84 -0
  208. package/corpus/templates/content/actions/_database-source-utils.ts +206 -96
  209. package/corpus/templates/content/actions/_notion-database-source-adapter.ts +216 -0
  210. package/corpus/templates/content/actions/_position-utils.ts +76 -0
  211. package/corpus/templates/content/actions/_property-utils.ts +31 -20
  212. package/corpus/templates/content/actions/add-database-item.ts +52 -39
  213. package/corpus/templates/content/actions/attach-content-database-source.ts +95 -11
  214. package/corpus/templates/content/actions/change-content-database-source-role.ts +24 -1
  215. package/corpus/templates/content/actions/configure-document-property.ts +36 -27
  216. package/corpus/templates/content/actions/create-content-database.ts +40 -30
  217. package/corpus/templates/content/actions/create-document.ts +39 -32
  218. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -28
  219. package/corpus/templates/content/actions/list-notion-database-sources.ts +80 -0
  220. package/corpus/templates/content/actions/move-document.ts +64 -48
  221. package/corpus/templates/content/actions/refresh-content-database-source.ts +42 -3
  222. package/corpus/templates/content/actions/share-local-file-document.ts +36 -27
  223. package/corpus/templates/content/actions/suggest-source-join-key.ts +39 -16
  224. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +89 -23
  225. package/corpus/templates/content/app/components/editor/database/settings.tsx +1 -1
  226. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -1
  227. package/corpus/templates/content/app/i18n/zh-TW.ts +4 -0
  228. package/corpus/templates/content/app/i18n-data.ts +40 -0
  229. package/corpus/templates/content/changelog/2026-07-10-failed-row-creation-and-source-attach-now-show-an-error-inst.md +6 -0
  230. package/corpus/templates/content/changelog/2026-07-10-items-added-at-the-same-time-no-longer-end-up-with-identical.md +6 -0
  231. package/corpus/templates/content/changelog/2026-07-10-notion-databases-can-add-read-only-details-to-content-tables.md +6 -0
  232. package/corpus/templates/content/package.json +1 -2
  233. package/corpus/templates/content/parity/matrix.md +25 -25
  234. package/corpus/templates/content/parity/matrix.ts +1 -0
  235. package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +43 -26
  236. package/corpus/templates/content/shared/api.ts +16 -1
  237. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +8 -4
  238. package/corpus/templates/design/AGENTS.md +12 -2
  239. package/corpus/templates/design/DEVELOPING.md +10 -6
  240. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -6
  241. package/corpus/templates/design/actions/duplicate-design.ts +31 -25
  242. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +5 -1
  243. package/corpus/templates/design/changelog/2026-07-10-duplicating-a-design-can-no-longer-produce-a-copy-with-missi.md +6 -0
  244. package/corpus/templates/design/changelog/2026-07-10-local-visual-edits-can-now-save-safe-leaf-text-class-and.md +6 -0
  245. package/corpus/templates/design/package.json +1 -1
  246. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +388 -0
  247. package/corpus/templates/dispatch/package.json +1 -2
  248. package/corpus/templates/forms/actions/patch-form-fields.ts +82 -44
  249. package/corpus/templates/forms/changelog/2026-07-10-simultaneous-edits-to-different-form-fields-no-longer-overwr.md +6 -0
  250. package/corpus/templates/forms/package.json +1 -2
  251. package/corpus/templates/macros/package.json +1 -2
  252. package/corpus/templates/mail/app/components/email/EmailThread.tsx +3 -1
  253. package/corpus/templates/mail/changelog/2026-07-10-fixed-calendar-rsvp-buttons-in-emails-firing-duplicate-respo.md +6 -0
  254. package/corpus/templates/mail/package.json +1 -2
  255. package/corpus/templates/plan/actions/restore-plan-version.ts +126 -96
  256. package/corpus/templates/plan/changelog/2026-07-10-restoring-a-plan-version-can-no-longer-leave-a-plan-half-res.md +6 -0
  257. package/corpus/templates/plan/package.json +1 -2
  258. package/corpus/templates/plan/server/plans.ts +9 -2
  259. package/corpus/templates/slides/actions/list-decks.ts +28 -0
  260. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +41 -26
  261. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +4 -8
  262. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -4
  263. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -8
  264. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -12
  265. package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +3 -6
  266. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +3 -6
  267. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -5
  268. package/corpus/templates/slides/app/context/DeckContext.tsx +47 -4
  269. package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -30
  270. package/corpus/templates/slides/app/pages/Index.tsx +2 -3
  271. package/corpus/templates/slides/app/root.tsx +0 -5
  272. package/corpus/templates/slides/changelog/2026-07-10-deck-lists-load-much-faster-and-no-longer-re-download-slide-.md +6 -0
  273. package/corpus/templates/slides/package.json +1 -2
  274. package/dist/a2a/auth-policy.d.ts +19 -0
  275. package/dist/a2a/auth-policy.d.ts.map +1 -1
  276. package/dist/a2a/auth-policy.js +32 -0
  277. package/dist/a2a/auth-policy.js.map +1 -1
  278. package/dist/a2a/client.d.ts +7 -0
  279. package/dist/a2a/client.d.ts.map +1 -1
  280. package/dist/a2a/client.js +2 -1
  281. package/dist/a2a/client.js.map +1 -1
  282. package/dist/agent/durable-background.d.ts +8 -5
  283. package/dist/agent/durable-background.d.ts.map +1 -1
  284. package/dist/agent/durable-background.js +15 -8
  285. package/dist/agent/durable-background.js.map +1 -1
  286. package/dist/agent/production-agent.d.ts +6 -0
  287. package/dist/agent/production-agent.d.ts.map +1 -1
  288. package/dist/agent/production-agent.js +63 -26
  289. package/dist/agent/production-agent.js.map +1 -1
  290. package/dist/agent/run-store.d.ts.map +1 -1
  291. package/dist/agent/run-store.js +9 -4
  292. package/dist/agent/run-store.js.map +1 -1
  293. package/dist/agent/thread-data-builder.d.ts +1 -0
  294. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  295. package/dist/agent/thread-data-builder.js +6 -5
  296. package/dist/agent/thread-data-builder.js.map +1 -1
  297. package/dist/audit/actions/export-audit-events.d.ts +27 -0
  298. package/dist/audit/actions/export-audit-events.d.ts.map +1 -0
  299. package/dist/audit/actions/export-audit-events.js +144 -0
  300. package/dist/audit/actions/export-audit-events.js.map +1 -0
  301. package/dist/audit/store.d.ts +1 -0
  302. package/dist/audit/store.d.ts.map +1 -1
  303. package/dist/audit/store.js +8 -3
  304. package/dist/audit/store.js.map +1 -1
  305. package/dist/audit/types.d.ts +3 -0
  306. package/dist/audit/types.d.ts.map +1 -1
  307. package/dist/audit/types.js.map +1 -1
  308. package/dist/chat-threads/store.d.ts +10 -0
  309. package/dist/chat-threads/store.d.ts.map +1 -1
  310. package/dist/chat-threads/store.js +6 -0
  311. package/dist/chat-threads/store.js.map +1 -1
  312. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  313. package/dist/cli/code-agent-executor.js +1 -0
  314. package/dist/cli/code-agent-executor.js.map +1 -1
  315. package/dist/cli/code-agent-runs.d.ts +12 -0
  316. package/dist/cli/code-agent-runs.d.ts.map +1 -1
  317. package/dist/cli/code-agent-runs.js +1 -0
  318. package/dist/cli/code-agent-runs.js.map +1 -1
  319. package/dist/cli/doctor.d.ts +83 -0
  320. package/dist/cli/doctor.d.ts.map +1 -0
  321. package/dist/cli/doctor.js +277 -0
  322. package/dist/cli/doctor.js.map +1 -0
  323. package/dist/cli/index.js +50 -0
  324. package/dist/cli/index.js.map +1 -1
  325. package/dist/cli/info.js +3 -3
  326. package/dist/cli/info.js.map +1 -1
  327. package/dist/cli/package-lifecycle.d.ts +50 -0
  328. package/dist/cli/package-lifecycle.d.ts.map +1 -0
  329. package/dist/cli/package-lifecycle.js +560 -0
  330. package/dist/cli/package-lifecycle.js.map +1 -0
  331. package/dist/client/AgentPanel.d.ts.map +1 -1
  332. package/dist/client/AgentPanel.js +3 -3
  333. package/dist/client/AgentPanel.js.map +1 -1
  334. package/dist/client/AssistantChat.d.ts +11 -0
  335. package/dist/client/AssistantChat.d.ts.map +1 -1
  336. package/dist/client/AssistantChat.js +7 -4
  337. package/dist/client/AssistantChat.js.map +1 -1
  338. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  339. package/dist/client/MultiTabAssistantChat.js +83 -10
  340. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  341. package/dist/client/agent-chat-adapter.js +7 -3
  342. package/dist/client/agent-chat-adapter.js.map +1 -1
  343. package/dist/client/chat/ChatHistoryList.d.ts +88 -0
  344. package/dist/client/chat/ChatHistoryList.d.ts.map +1 -0
  345. package/dist/client/chat/ChatHistoryList.js +83 -0
  346. package/dist/client/chat/ChatHistoryList.js.map +1 -0
  347. package/dist/client/chat/index.d.ts +1 -0
  348. package/dist/client/chat/index.d.ts.map +1 -1
  349. package/dist/client/chat/index.js +1 -0
  350. package/dist/client/chat/index.js.map +1 -1
  351. package/dist/client/chat/tool-call-display.d.ts +13 -1
  352. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  353. package/dist/client/chat/tool-call-display.js +10 -2
  354. package/dist/client/chat/tool-call-display.js.map +1 -1
  355. package/dist/client/code-agent-chat-adapter.d.ts +17 -1
  356. package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
  357. package/dist/client/code-agent-chat-adapter.js +47 -3
  358. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  359. package/dist/client/composer/RealtimeVoiceMode.d.ts +11 -1
  360. package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
  361. package/dist/client/composer/RealtimeVoiceMode.js +5 -3
  362. package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
  363. package/dist/client/composer/TiptapComposer.d.ts +25 -2
  364. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  365. package/dist/client/composer/TiptapComposer.js +96 -5
  366. package/dist/client/composer/TiptapComposer.js.map +1 -1
  367. package/dist/client/composer/VoiceButton.d.ts.map +1 -1
  368. package/dist/client/composer/VoiceButton.js +21 -1
  369. package/dist/client/composer/VoiceButton.js.map +1 -1
  370. package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
  371. package/dist/client/composer/useRealtimeVoiceMode.js +5 -0
  372. package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
  373. package/dist/client/conversation/code-agent-transcript.d.ts +2 -0
  374. package/dist/client/conversation/code-agent-transcript.d.ts.map +1 -1
  375. package/dist/client/conversation/code-agent-transcript.js +3 -5
  376. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  377. package/dist/client/guided-questions.d.ts.map +1 -1
  378. package/dist/client/guided-questions.js +2 -1
  379. package/dist/client/guided-questions.js.map +1 -1
  380. package/dist/client/index.d.ts +3 -1
  381. package/dist/client/index.d.ts.map +1 -1
  382. package/dist/client/index.js +3 -1
  383. package/dist/client/index.js.map +1 -1
  384. package/dist/client/use-chat-threads.d.ts.map +1 -1
  385. package/dist/client/use-chat-threads.js +9 -1
  386. package/dist/client/use-chat-threads.js.map +1 -1
  387. package/dist/client/voice-provider-status.d.ts +10 -0
  388. package/dist/client/voice-provider-status.d.ts.map +1 -0
  389. package/dist/client/voice-provider-status.js +32 -0
  390. package/dist/client/voice-provider-status.js.map +1 -0
  391. package/dist/code-agents/transcript-normalizer.d.ts +29 -0
  392. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  393. package/dist/code-agents/transcript-normalizer.js +55 -0
  394. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  395. package/dist/collab/routes.d.ts +1 -1
  396. package/dist/deploy/build.d.ts.map +1 -1
  397. package/dist/deploy/build.js +13 -11
  398. package/dist/deploy/build.js.map +1 -1
  399. package/dist/guards/db-tool-scoping.d.ts +38 -0
  400. package/dist/guards/db-tool-scoping.d.ts.map +1 -0
  401. package/dist/guards/db-tool-scoping.js +114 -0
  402. package/dist/guards/db-tool-scoping.js.map +1 -0
  403. package/dist/guards/index.d.ts +23 -0
  404. package/dist/guards/index.d.ts.map +1 -0
  405. package/dist/guards/index.js +19 -0
  406. package/dist/guards/index.js.map +1 -0
  407. package/dist/guards/no-drizzle-push.d.ts +14 -0
  408. package/dist/guards/no-drizzle-push.d.ts.map +1 -0
  409. package/dist/guards/no-drizzle-push.js +97 -0
  410. package/dist/guards/no-drizzle-push.js.map +1 -0
  411. package/dist/guards/no-env-credentials.d.ts +36 -0
  412. package/dist/guards/no-env-credentials.d.ts.map +1 -0
  413. package/dist/guards/no-env-credentials.js +204 -0
  414. package/dist/guards/no-env-credentials.js.map +1 -0
  415. package/dist/guards/no-env-mutation.d.ts +23 -0
  416. package/dist/guards/no-env-mutation.d.ts.map +1 -0
  417. package/dist/guards/no-env-mutation.js +90 -0
  418. package/dist/guards/no-env-mutation.js.map +1 -0
  419. package/dist/guards/no-localhost-fallback.d.ts +30 -0
  420. package/dist/guards/no-localhost-fallback.d.ts.map +1 -0
  421. package/dist/guards/no-localhost-fallback.js +105 -0
  422. package/dist/guards/no-localhost-fallback.js.map +1 -0
  423. package/dist/guards/no-unscoped-credentials.d.ts +28 -0
  424. package/dist/guards/no-unscoped-credentials.d.ts.map +1 -0
  425. package/dist/guards/no-unscoped-credentials.js +199 -0
  426. package/dist/guards/no-unscoped-credentials.js.map +1 -0
  427. package/dist/guards/no-unscoped-queries.d.ts +32 -0
  428. package/dist/guards/no-unscoped-queries.d.ts.map +1 -0
  429. package/dist/guards/no-unscoped-queries.js +720 -0
  430. package/dist/guards/no-unscoped-queries.js.map +1 -0
  431. package/dist/guards/scan-utils.d.ts +28 -0
  432. package/dist/guards/scan-utils.d.ts.map +1 -0
  433. package/dist/guards/scan-utils.js +92 -0
  434. package/dist/guards/scan-utils.js.map +1 -0
  435. package/dist/guards/types.d.ts +28 -0
  436. package/dist/guards/types.d.ts.map +1 -0
  437. package/dist/guards/types.js +11 -0
  438. package/dist/guards/types.js.map +1 -0
  439. package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
  440. package/dist/integrations/a2a-continuation-processor.js +25 -5
  441. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  442. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  443. package/dist/integrations/adapters/slack.js +55 -21
  444. package/dist/integrations/adapters/slack.js.map +1 -1
  445. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  446. package/dist/integrations/webhook-handler.js +11 -0
  447. package/dist/integrations/webhook-handler.js.map +1 -1
  448. package/dist/localization/default-messages.d.ts +5 -0
  449. package/dist/localization/default-messages.d.ts.map +1 -1
  450. package/dist/localization/default-messages.js +5 -0
  451. package/dist/localization/default-messages.js.map +1 -1
  452. package/dist/notifications/routes.d.ts +2 -2
  453. package/dist/observability/hosted-model-experiment.d.ts +39 -0
  454. package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
  455. package/dist/observability/hosted-model-experiment.js +90 -0
  456. package/dist/observability/hosted-model-experiment.js.map +1 -0
  457. package/dist/observability/routes.d.ts +1 -1
  458. package/dist/observability/routes.d.ts.map +1 -1
  459. package/dist/observability/routes.js +16 -0
  460. package/dist/observability/routes.js.map +1 -1
  461. package/dist/observability/store.d.ts.map +1 -1
  462. package/dist/observability/store.js +4 -1
  463. package/dist/observability/store.js.map +1 -1
  464. package/dist/observability/traces.d.ts +6 -0
  465. package/dist/observability/traces.d.ts.map +1 -1
  466. package/dist/observability/traces.js +28 -2
  467. package/dist/observability/traces.js.map +1 -1
  468. package/dist/org/accept-pending.d.ts.map +1 -1
  469. package/dist/org/accept-pending.js +9 -1
  470. package/dist/org/accept-pending.js.map +1 -1
  471. package/dist/org/migrations.d.ts +7 -2
  472. package/dist/org/migrations.d.ts.map +1 -1
  473. package/dist/org/migrations.js +41 -0
  474. package/dist/org/migrations.js.map +1 -1
  475. package/dist/package-lifecycle/index.d.ts +2 -0
  476. package/dist/package-lifecycle/index.d.ts.map +1 -0
  477. package/dist/package-lifecycle/index.js +2 -0
  478. package/dist/package-lifecycle/index.js.map +1 -0
  479. package/dist/package-lifecycle/manifest.d.ts +24 -0
  480. package/dist/package-lifecycle/manifest.d.ts.map +1 -0
  481. package/dist/package-lifecycle/manifest.js +81 -0
  482. package/dist/package-lifecycle/manifest.js.map +1 -0
  483. package/dist/progress/routes.d.ts +1 -1
  484. package/dist/provider-api/custom-registry.d.ts +32 -1
  485. package/dist/provider-api/custom-registry.d.ts.map +1 -1
  486. package/dist/provider-api/custom-registry.js +41 -1
  487. package/dist/provider-api/custom-registry.js.map +1 -1
  488. package/dist/provider-api/index.d.ts +1 -1
  489. package/dist/provider-api/index.d.ts.map +1 -1
  490. package/dist/provider-api/index.js +1 -1
  491. package/dist/provider-api/index.js.map +1 -1
  492. package/dist/resources/handlers.d.ts +1 -1
  493. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  494. package/dist/scripts/agent-engines/list-agent-engines.js +19 -1
  495. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  496. package/dist/scripts/call-agent.d.ts.map +1 -1
  497. package/dist/scripts/call-agent.js +43 -3
  498. package/dist/scripts/call-agent.js.map +1 -1
  499. package/dist/scripts/chat/search-chats.d.ts +1 -1
  500. package/dist/scripts/chat/search-chats.d.ts.map +1 -1
  501. package/dist/scripts/chat/search-chats.js +11 -8
  502. package/dist/scripts/chat/search-chats.js.map +1 -1
  503. package/dist/secrets/register-framework-secrets.js +1 -1
  504. package/dist/secrets/register-framework-secrets.js.map +1 -1
  505. package/dist/secrets/storage.d.ts.map +1 -1
  506. package/dist/secrets/storage.js +45 -27
  507. package/dist/secrets/storage.js.map +1 -1
  508. package/dist/server/action-discovery.d.ts.map +1 -1
  509. package/dist/server/action-discovery.js +4 -0
  510. package/dist/server/action-discovery.js.map +1 -1
  511. package/dist/server/agent-chat-plugin.d.ts +11 -0
  512. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  513. package/dist/server/agent-chat-plugin.js +74 -19
  514. package/dist/server/agent-chat-plugin.js.map +1 -1
  515. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  516. package/dist/server/core-routes-plugin.d.ts +3 -0
  517. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  518. package/dist/server/core-routes-plugin.js +36 -12
  519. package/dist/server/core-routes-plugin.js.map +1 -1
  520. package/dist/server/csrf.d.ts.map +1 -1
  521. package/dist/server/csrf.js +18 -5
  522. package/dist/server/csrf.js.map +1 -1
  523. package/dist/server/framework-request-handler.d.ts.map +1 -1
  524. package/dist/server/framework-request-handler.js +34 -0
  525. package/dist/server/framework-request-handler.js.map +1 -1
  526. package/dist/server/google-realtime-session.d.ts.map +1 -1
  527. package/dist/server/google-realtime-session.js +2 -34
  528. package/dist/server/google-realtime-session.js.map +1 -1
  529. package/dist/server/poll.d.ts.map +1 -1
  530. package/dist/server/poll.js +24 -2
  531. package/dist/server/poll.js.map +1 -1
  532. package/dist/server/realtime-voice.d.ts.map +1 -1
  533. package/dist/server/realtime-voice.js +64 -21
  534. package/dist/server/realtime-voice.js.map +1 -1
  535. package/dist/server/request-origin.d.ts +10 -0
  536. package/dist/server/request-origin.d.ts.map +1 -0
  537. package/dist/server/request-origin.js +60 -0
  538. package/dist/server/request-origin.js.map +1 -0
  539. package/dist/server/transcribe-voice.d.ts.map +1 -1
  540. package/dist/server/transcribe-voice.js +2 -48
  541. package/dist/server/transcribe-voice.js.map +1 -1
  542. package/dist/server/voice-providers-status.d.ts.map +1 -1
  543. package/dist/server/voice-providers-status.js +2 -3
  544. package/dist/server/voice-providers-status.js.map +1 -1
  545. package/dist/shared/cache-control.d.ts +4 -6
  546. package/dist/shared/cache-control.d.ts.map +1 -1
  547. package/dist/shared/cache-control.js +2 -7
  548. package/dist/shared/cache-control.js.map +1 -1
  549. package/dist/styles/agent-native.css +1 -0
  550. package/dist/styles/chat-history-list.css +313 -0
  551. package/dist/templates/default/package.json +2 -2
  552. package/dist/templates/headless/package.json +0 -1
  553. package/dist/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  554. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  555. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  556. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
  557. package/dist/templates/workspace-core/package.json +0 -1
  558. package/dist/templates/workspace-root/package.json +0 -1
  559. package/dist/triggers/actions.d.ts.map +1 -1
  560. package/dist/triggers/actions.js +8 -3
  561. package/dist/triggers/actions.js.map +1 -1
  562. package/dist/triggers/types.d.ts +7 -1
  563. package/dist/triggers/types.d.ts.map +1 -1
  564. package/dist/triggers/types.js.map +1 -1
  565. package/dist/vite/client.d.ts.map +1 -1
  566. package/dist/vite/client.js +1 -0
  567. package/dist/vite/client.js.map +1 -1
  568. package/docs/content/audit-log.mdx +2 -1
  569. package/docs/content/automations.mdx +7 -7
  570. package/docs/content/creating-templates.mdx +1 -1
  571. package/docs/content/internationalization.mdx +2 -1
  572. package/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  573. package/docs/content/locales/ar-SA/automations.mdx +7 -7
  574. package/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  575. package/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  576. package/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  577. package/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  578. package/docs/content/locales/ar-SA/security.mdx +8 -0
  579. package/docs/content/locales/de-DE/audit-log.mdx +2 -1
  580. package/docs/content/locales/de-DE/automations.mdx +7 -7
  581. package/docs/content/locales/de-DE/getting-started.mdx +7 -1
  582. package/docs/content/locales/de-DE/internationalization.mdx +1 -1
  583. package/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  584. package/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  585. package/docs/content/locales/de-DE/security.mdx +8 -0
  586. package/docs/content/locales/es-ES/audit-log.mdx +2 -1
  587. package/docs/content/locales/es-ES/automations.mdx +7 -7
  588. package/docs/content/locales/es-ES/getting-started.mdx +7 -1
  589. package/docs/content/locales/es-ES/internationalization.mdx +1 -1
  590. package/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  591. package/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  592. package/docs/content/locales/es-ES/security.mdx +8 -0
  593. package/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  594. package/docs/content/locales/fr-FR/automations.mdx +7 -7
  595. package/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  596. package/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  597. package/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  598. package/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  599. package/docs/content/locales/fr-FR/security.mdx +8 -0
  600. package/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  601. package/docs/content/locales/hi-IN/automations.mdx +7 -7
  602. package/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  603. package/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  604. package/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  605. package/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  606. package/docs/content/locales/hi-IN/security.mdx +8 -0
  607. package/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  608. package/docs/content/locales/ja-JP/automations.mdx +7 -7
  609. package/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  610. package/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  611. package/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  612. package/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  613. package/docs/content/locales/ja-JP/security.mdx +8 -0
  614. package/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  615. package/docs/content/locales/ko-KR/automations.mdx +7 -7
  616. package/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  617. package/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  618. package/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  619. package/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  620. package/docs/content/locales/ko-KR/security.mdx +8 -0
  621. package/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  622. package/docs/content/locales/pt-BR/automations.mdx +7 -7
  623. package/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  624. package/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  625. package/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  626. package/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  627. package/docs/content/locales/pt-BR/security.mdx +8 -0
  628. package/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  629. package/docs/content/locales/zh-CN/automations.mdx +7 -7
  630. package/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  631. package/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  632. package/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  633. package/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  634. package/docs/content/locales/zh-CN/security.mdx +8 -0
  635. package/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  636. package/docs/content/locales/zh-TW/automations.mdx +7 -7
  637. package/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  638. package/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  639. package/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  640. package/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  641. package/docs/content/locales/zh-TW/security.mdx +8 -0
  642. package/docs/content/package-lifecycle.mdx +51 -0
  643. package/docs/content/sandbox-adapters.mdx +16 -5
  644. package/package.json +12 -3
  645. package/src/templates/default/package.json +2 -2
  646. package/src/templates/headless/package.json +0 -1
  647. package/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  648. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  649. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  650. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
  651. package/src/templates/workspace-core/package.json +0 -1
  652. package/src/templates/workspace-root/package.json +0 -1
  653. package/corpus/templates/slides/app/components/ui/toast.tsx +0 -1
  654. package/corpus/templates/slides/app/components/ui/toaster.tsx +0 -1
  655. package/corpus/templates/slides/app/hooks/use-toast.ts +0 -1
@@ -0,0 +1,834 @@
1
+ /**
2
+ * scanUnscopedQueries — ported from `scripts/guard-no-unscoped-queries.mjs`.
3
+ *
4
+ * Refuse to let any code query an "ownable" resource table (one that
5
+ * spreads `...ownableColumns()`) without going through framework access
6
+ * control: `accessFilter` / `resolveAccess` / `assertAccess`, or an
7
+ * explicit `ownerEmail` / `userEmail` / `orgId` filter. The check is
8
+ * per-STATEMENT, scoped to the enclosing block, so a sibling `if` branch
9
+ * that correctly scopes its query does not defuse an unscoped sibling.
10
+ *
11
+ * Conditional guard — per report 005's V1 guard set table: the original
12
+ * restricts scanning to `templates/[^/]+/(server|actions)/` and
13
+ * `packages/[^/]+/src/`, and hardcodes a `FILE_ALLOWLIST` of this
14
+ * framework's own sharing-primitive implementation files. For a generated
15
+ * app (no `templates/`/`packages/` wrapper — source lives at `actions/`
16
+ * and `server/` under the app root), this port scans `actions/` and
17
+ * `server/` directly and drops the hardcoded allowlist in favor of an
18
+ * optional `extraExemptPaths` param (default `[]`).
19
+ *
20
+ * Opt-out (within the enclosing block, or as a file header for whole-file
21
+ * opt-outs):
22
+ * // guard:allow-unscoped — short reason
23
+ */
24
+
25
+ import { readFileSafe, relPosix, walk } from "./scan-utils.js";
26
+ import type { GuardFinding, GuardResult, GuardScanOptions } from "./types.js";
27
+
28
+ export interface UnscopedQueriesOptions extends GuardScanOptions {
29
+ /** Exact repo-relative paths to exempt from the per-statement scan
30
+ * (e.g. this app's own sharing-primitive implementation, if any).
31
+ * Default `[]`. */
32
+ extraExemptPaths?: string[];
33
+ }
34
+
35
+ const ACCESS_CONTROL_HELPERS = [
36
+ /\baccessFilter\s*\(/,
37
+ /\bresolveAccess\s*\(/,
38
+ /\bassertAccess\s*\(/,
39
+ /\bgetShareableResource\s*\(/,
40
+ /\baccessFilterForShares\s*\(/,
41
+ ];
42
+
43
+ const EXPLICIT_OWNER_FILTERS = [
44
+ /\.\s*ownerEmail\b\s*[,)]/,
45
+ /\.\s*userEmail\b\s*[,)]/,
46
+ /\.\s*orgId\b\s*[,)]/,
47
+ /WHERE[\s\S]*?\bowner_email\b/i,
48
+ /WHERE[\s\S]*?\buser_email\b/i,
49
+ /WHERE[\s\S]*?\borg_id\b/i,
50
+ ];
51
+
52
+ const INSERT_OWNER_PATTERNS = [
53
+ /\bownerEmail\s*:/,
54
+ /\bownerEmail\s*[,}]/,
55
+ /\buserEmail\s*[:,}]/,
56
+ /\borgId\s*[:,}]/,
57
+ ];
58
+
59
+ const OPT_OUT_MARKER = /\/\/\s*guard:allow-unscoped\b/;
60
+
61
+ const BLOCK_OWNERSHIP_SIGNALS = [
62
+ /\bgetRequestUserEmail\s*\(/,
63
+ /\bgetRequestOrgId\s*\(/,
64
+ /\bgetCurrentUserEmail\s*\(/,
65
+ /\bgetCurrentOwnerEmail\s*\(/,
66
+ /\brunWithRequestContext\s*\(/,
67
+ ];
68
+
69
+ interface TableCall {
70
+ exportName: string;
71
+ sqlName: string;
72
+ body: string;
73
+ }
74
+
75
+ function extractTableCalls(contents: string): TableCall[] {
76
+ const out: TableCall[] = [];
77
+ const headerRegex =
78
+ /export\s+const\s+([a-zA-Z_$][\w$]*)\s*=\s*(?:[a-zA-Z_$][\w$]*Table|table)\s*\(\s*"([^"]+)"\s*,\s*\{/gm;
79
+ let m: RegExpExecArray | null;
80
+ while ((m = headerRegex.exec(contents)) !== null) {
81
+ const exportName = m[1];
82
+ const sqlName = m[2];
83
+ const start = headerRegex.lastIndex - 1;
84
+ let depth = 0;
85
+ let inStr: string | null = null;
86
+ let i = start;
87
+ let bodyEnd = -1;
88
+ for (; i < contents.length; i++) {
89
+ const c = contents[i];
90
+ const prev = contents[i - 1];
91
+ if (inStr) {
92
+ if (c === inStr && prev !== "\\") inStr = null;
93
+ continue;
94
+ }
95
+ if (c === '"' || c === "'" || c === "`") {
96
+ inStr = c;
97
+ continue;
98
+ }
99
+ if (c === "{") depth++;
100
+ else if (c === "}") {
101
+ depth--;
102
+ if (depth === 0) {
103
+ bodyEnd = i;
104
+ break;
105
+ }
106
+ }
107
+ }
108
+ if (bodyEnd === -1) continue;
109
+ const body = contents.slice(start + 1, bodyEnd);
110
+ out.push({ exportName, sqlName, body });
111
+ }
112
+ return out;
113
+ }
114
+
115
+ function extractOwnableExports(contents: string): Set<string> {
116
+ const exports = new Set<string>();
117
+ for (const { exportName, sqlName, body } of extractTableCalls(contents)) {
118
+ if (/\.\.\.ownableColumns\s*\(/.test(body)) {
119
+ exports.add(exportName);
120
+ exports.add(`__sql__${sqlName}`);
121
+ }
122
+ }
123
+ return exports;
124
+ }
125
+
126
+ function collectOwnableTables(root: string): Map<string, Set<string>> {
127
+ const byDir = new Map<string, Set<string>>();
128
+ for (const file of walk(root)) {
129
+ if (!file.endsWith("/db/schema.ts")) continue;
130
+ const contents = readFileSafe(file);
131
+ if (contents === null || !/ownableColumns\s*\(/.test(contents)) continue;
132
+ const ownables = extractOwnableExports(contents);
133
+ if (ownables.size > 0) {
134
+ byDir.set(relPosix(root, file), ownables);
135
+ }
136
+ }
137
+ return byDir;
138
+ }
139
+
140
+ interface Block {
141
+ open: number;
142
+ close: number;
143
+ }
144
+
145
+ function buildBlockTree(contents: string): Block[] {
146
+ const blocks: Block[] = [];
147
+ const stack: number[] = [];
148
+ let i = 0;
149
+ const n = contents.length;
150
+ let inStr: string | null = null;
151
+ const templateStack: string[] = [];
152
+
153
+ while (i < n) {
154
+ const c = contents[i];
155
+ const next = contents[i + 1];
156
+
157
+ if (inStr) {
158
+ if (c === "\\") {
159
+ i += 2;
160
+ continue;
161
+ }
162
+ if (inStr === "`") {
163
+ if (c === "`") {
164
+ inStr = null;
165
+ i++;
166
+ continue;
167
+ }
168
+ if (c === "$" && next === "{") {
169
+ templateStack.push("`");
170
+ inStr = null;
171
+ stack.push(-1 - templateStack.length);
172
+ i += 2;
173
+ continue;
174
+ }
175
+ } else if (c === inStr) {
176
+ inStr = null;
177
+ i++;
178
+ continue;
179
+ }
180
+ i++;
181
+ continue;
182
+ }
183
+
184
+ if (c === "/" && next === "/") {
185
+ while (i < n && contents[i] !== "\n") i++;
186
+ continue;
187
+ }
188
+ if (c === "/" && next === "*") {
189
+ i += 2;
190
+ while (i < n - 1 && !(contents[i] === "*" && contents[i + 1] === "/"))
191
+ i++;
192
+ i += 2;
193
+ continue;
194
+ }
195
+
196
+ if (c === '"' || c === "'" || c === "`") {
197
+ inStr = c;
198
+ i++;
199
+ continue;
200
+ }
201
+
202
+ if (c === "{") {
203
+ stack.push(i);
204
+ i++;
205
+ continue;
206
+ }
207
+ if (c === "}") {
208
+ const open = stack.pop();
209
+ if (open !== undefined && open >= 0) {
210
+ blocks.push({ open, close: i });
211
+ } else if (open !== undefined && open < 0) {
212
+ const kind = templateStack.pop();
213
+ inStr = kind ?? null;
214
+ }
215
+ i++;
216
+ continue;
217
+ }
218
+ i++;
219
+ }
220
+ blocks.sort((a, b) => a.open - b.open);
221
+ return blocks;
222
+ }
223
+
224
+ function innermostBlock(
225
+ blocks: Block[],
226
+ offset: number,
227
+ fileLen: number,
228
+ ): Block {
229
+ let best: Block | null = null;
230
+ for (const b of blocks) {
231
+ if (b.open <= offset && b.close >= offset) {
232
+ if (!best || b.open > best.open) best = b;
233
+ }
234
+ }
235
+ return best || { open: 0, close: fileLen };
236
+ }
237
+
238
+ function computeLineOffsets(contents: string): number[] {
239
+ const offsets = [0];
240
+ for (let i = 0; i < contents.length; i++) {
241
+ if (contents[i] === "\n") offsets.push(i + 1);
242
+ }
243
+ return offsets;
244
+ }
245
+
246
+ function offsetToLine(offsets: number[], offset: number): number {
247
+ let lo = 0;
248
+ let hi = offsets.length - 1;
249
+ while (lo < hi) {
250
+ const mid = (lo + hi + 1) >>> 1;
251
+ if (offsets[mid] <= offset) lo = mid;
252
+ else hi = mid - 1;
253
+ }
254
+ return lo + 1;
255
+ }
256
+
257
+ function findChainEnd(contents: string, startIdx: number): number {
258
+ let depth = 0;
259
+ let inStr: string | null = null;
260
+ let templateDepth = 0;
261
+ const limit = Math.min(contents.length, startIdx + 10000);
262
+ let sawOpen = false;
263
+ for (let i = startIdx; i < limit; i++) {
264
+ const c = contents[i];
265
+ const prev = contents[i - 1];
266
+ if (inStr) {
267
+ if (inStr === "`") {
268
+ if (c === "`") inStr = null;
269
+ else if (c === "$" && contents[i + 1] === "{") {
270
+ templateDepth++;
271
+ i++;
272
+ }
273
+ } else if (c === inStr && prev !== "\\") {
274
+ inStr = null;
275
+ }
276
+ continue;
277
+ }
278
+ if (templateDepth > 0 && c === "}") {
279
+ templateDepth--;
280
+ inStr = "`";
281
+ continue;
282
+ }
283
+ if (c === '"' || c === "'" || c === "`") {
284
+ inStr = c;
285
+ continue;
286
+ }
287
+ if (c === "(" || c === "{" || c === "[") {
288
+ depth++;
289
+ sawOpen = true;
290
+ } else if (c === ")" || c === "}" || c === "]") {
291
+ depth--;
292
+ } else if (c === ";" && depth <= 0) {
293
+ return i + 1;
294
+ } else if (c === "\n" && sawOpen && depth <= 0) {
295
+ let j = i + 1;
296
+ while (j < limit && /[ \t]/.test(contents[j])) j++;
297
+ if (j >= limit || (contents[j] !== "." && contents[j] !== ")")) {
298
+ return i + 1;
299
+ }
300
+ }
301
+ }
302
+ return limit;
303
+ }
304
+
305
+ interface Statement {
306
+ kind: "drizzle" | "raw-sql";
307
+ op: string;
308
+ name: string;
309
+ line: number;
310
+ queryStart: number;
311
+ queryEnd: number;
312
+ snippet: string;
313
+ }
314
+
315
+ function walkBackToChainHead(contents: string, idx: number): number {
316
+ let i = idx;
317
+ while (i > 0) {
318
+ const c = contents[i];
319
+ if (c === ";" || c === "{" || c === "}") return i + 1;
320
+ if (c === "\n") {
321
+ let j = i + 1;
322
+ while (j < contents.length && /[ \t]/.test(contents[j])) j++;
323
+ if (contents[j] !== "." && contents[j] !== ")") return i + 1;
324
+ }
325
+ i--;
326
+ }
327
+ return 0;
328
+ }
329
+
330
+ function findStatements(
331
+ contents: string,
332
+ ownableNames: Set<string>,
333
+ ownableSqlNames: Set<string>,
334
+ ): Statement[] {
335
+ const statements: Statement[] = [];
336
+ const lineOffsets = computeLineOffsets(contents);
337
+
338
+ const namesAlt = [...ownableNames]
339
+ .map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
340
+ .join("|");
341
+
342
+ if (namesAlt.length > 0) {
343
+ const fromRe = new RegExp(
344
+ `\\.\\s*from\\s*\\(\\s*(?:[a-zA-Z_$][\\w$]*\\s*\\.\\s*)?(${namesAlt})\\b`,
345
+ "g",
346
+ );
347
+ let fromMatch: RegExpExecArray | null;
348
+ while ((fromMatch = fromRe.exec(contents)) !== null) {
349
+ const name = fromMatch[1];
350
+ const queryStart = walkBackToChainHead(contents, fromMatch.index);
351
+ const queryEnd = findChainEnd(contents, fromMatch.index);
352
+ const snippet = contents.slice(queryStart, queryEnd);
353
+ statements.push({
354
+ kind: "drizzle",
355
+ op: "select",
356
+ name,
357
+ line: offsetToLine(lineOffsets, fromMatch.index),
358
+ queryStart,
359
+ queryEnd,
360
+ snippet,
361
+ });
362
+ }
363
+
364
+ for (const op of ["update", "delete", "insert"]) {
365
+ const re = new RegExp(
366
+ `\\bdb\\s*\\.\\s*${op}\\s*\\(\\s*(?:[a-zA-Z_$][\\w$]*\\s*\\.\\s*)?(${namesAlt})\\b`,
367
+ "g",
368
+ );
369
+ let m: RegExpExecArray | null;
370
+ while ((m = re.exec(contents)) !== null) {
371
+ const name = m[1];
372
+ const queryStart = walkBackToChainHead(contents, m.index);
373
+ const queryEnd = findChainEnd(contents, m.index);
374
+ const snippet = contents.slice(queryStart, queryEnd);
375
+ statements.push({
376
+ kind: "drizzle",
377
+ op,
378
+ name,
379
+ line: offsetToLine(lineOffsets, m.index),
380
+ queryStart,
381
+ queryEnd,
382
+ snippet,
383
+ });
384
+ }
385
+ }
386
+ }
387
+
388
+ for (const sqlName of ownableSqlNames) {
389
+ const escaped = sqlName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
390
+ const verbs: Array<[string, string]> = [
391
+ ["select", `\\bFROM\\s+${escaped}\\b`],
392
+ ["update", `\\bUPDATE\\s+${escaped}\\b`],
393
+ ["delete", `\\bDELETE\\s+FROM\\s+${escaped}\\b`],
394
+ ["insert", `\\bINSERT\\s+INTO\\s+${escaped}\\b`],
395
+ ];
396
+ for (const [op, body] of verbs) {
397
+ const re = new RegExp(`["'\`][^"'\`]*${body}[\\s\\S]*?["'\`]`, "gi");
398
+ let m: RegExpExecArray | null;
399
+ while ((m = re.exec(contents)) !== null) {
400
+ const matchStart = m.index;
401
+ statements.push({
402
+ kind: "raw-sql",
403
+ op,
404
+ name: sqlName,
405
+ line: offsetToLine(lineOffsets, matchStart),
406
+ queryStart: matchStart,
407
+ queryEnd: matchStart + m[0].length,
408
+ snippet: m[0],
409
+ });
410
+ }
411
+ }
412
+ }
413
+
414
+ return statements;
415
+ }
416
+
417
+ function isControlFlowBlock(contents: string, block: Block): boolean {
418
+ let i = block.open - 1;
419
+ while (i > 0 && /[ \t\n\r]/.test(contents[i])) i--;
420
+ if (contents[i] === ")") {
421
+ let depth = 1;
422
+ let j = i - 1;
423
+ while (j > 0 && depth > 0) {
424
+ if (contents[j] === ")") depth++;
425
+ else if (contents[j] === "(") depth--;
426
+ if (depth === 0) break;
427
+ j--;
428
+ }
429
+ j--;
430
+ while (j > 0 && /[ \t\n\r]/.test(contents[j])) j--;
431
+ let end = j + 1;
432
+ while (j > 0 && /[a-zA-Z_$]/.test(contents[j])) j--;
433
+ const word = contents.slice(j + 1, end);
434
+ return ["if", "for", "while", "switch", "catch"].includes(word);
435
+ }
436
+ let end = i + 1;
437
+ while (i > 0 && /[a-zA-Z_$]/.test(contents[i])) i--;
438
+ const word = contents.slice(i + 1, end);
439
+ return ["else", "try", "do", "finally"].includes(word);
440
+ }
441
+
442
+ function directBlockText(
443
+ contents: string,
444
+ block: Block,
445
+ blocks: Block[],
446
+ queryOffset: number,
447
+ ): string {
448
+ const candidates = blocks.filter(
449
+ (b) =>
450
+ b.open > block.open &&
451
+ b.close < block.close &&
452
+ !(b.open <= queryOffset && b.close >= queryOffset) &&
453
+ isControlFlowBlock(contents, b),
454
+ );
455
+ const descendants = candidates
456
+ .filter(
457
+ (b) =>
458
+ !candidates.some(
459
+ (p) => p !== b && p.open < b.open && p.close > b.close,
460
+ ),
461
+ )
462
+ .sort((a, b) => b.open - a.open);
463
+
464
+ let result = contents.slice(block.open, block.close + 1);
465
+ for (const child of descendants) {
466
+ const start = child.open - block.open;
467
+ const end = child.close - block.open;
468
+ if (start < 0 || end >= result.length) continue;
469
+ const inner = result.slice(start + 1, end);
470
+ const blanked = inner.replace(/[^\n]/g, " ");
471
+ result = result.slice(0, start + 1) + blanked + result.slice(end);
472
+ }
473
+ return result;
474
+ }
475
+
476
+ function blockHasAccessControl(blockText: string): boolean {
477
+ if (ACCESS_CONTROL_HELPERS.some((re) => re.test(blockText))) return true;
478
+ if (EXPLICIT_OWNER_FILTERS.some((re) => re.test(blockText))) return true;
479
+ if (BLOCK_OWNERSHIP_SIGNALS.some((re) => re.test(blockText))) return true;
480
+ return false;
481
+ }
482
+
483
+ function collectAccessControlBindings(contents: string): Set<string> {
484
+ const names = new Set<string>();
485
+ const bindRe =
486
+ /\b(?:const|let|var)\s+([a-zA-Z_$][\w$]*)\s*(?::[^=]+)?\s*=\s*([\s\S]{0,400}?)(?:;|\n\s*(?:const|let|var|if|return|await|function|export|}|\/\/))/g;
487
+ let m: RegExpExecArray | null;
488
+ while ((m = bindRe.exec(contents)) !== null) {
489
+ const name = m[1];
490
+ const rhs = m[2];
491
+ if (
492
+ ACCESS_CONTROL_HELPERS.some((re) => re.test(rhs)) ||
493
+ EXPLICIT_OWNER_FILTERS.some((re) => re.test(rhs))
494
+ ) {
495
+ names.add(name);
496
+ }
497
+ }
498
+ const pushRe = /\b([a-zA-Z_$][\w$]*)\.push\s*\(([^;]{0,400})\)/g;
499
+ while ((m = pushRe.exec(contents)) !== null) {
500
+ const name = m[1];
501
+ const arg = m[2];
502
+ if (
503
+ ACCESS_CONTROL_HELPERS.some((re) => re.test(arg)) ||
504
+ EXPLICIT_OWNER_FILTERS.some((re) => re.test(arg))
505
+ ) {
506
+ names.add(name);
507
+ }
508
+ }
509
+ return names;
510
+ }
511
+
512
+ function statementHasInlineAccessControl(stmt: Statement): boolean {
513
+ const snippet = stmt.snippet;
514
+ if (ACCESS_CONTROL_HELPERS.some((re) => re.test(snippet))) return true;
515
+ if (
516
+ stmt.kind === "drizzle" &&
517
+ EXPLICIT_OWNER_FILTERS.some((re) => re.test(snippet))
518
+ )
519
+ return true;
520
+ if (stmt.op === "insert") {
521
+ if (INSERT_OWNER_PATTERNS.some((re) => re.test(snippet))) return true;
522
+ }
523
+ if (stmt.kind === "raw-sql") {
524
+ if (
525
+ /\bowner_email\b/i.test(snippet) ||
526
+ /\buser_email\b/i.test(snippet) ||
527
+ /\borg_id\b/i.test(snippet)
528
+ ) {
529
+ return true;
530
+ }
531
+ }
532
+ return false;
533
+ }
534
+
535
+ function isOptedOutWithinBlock(blockText: string): boolean {
536
+ return OPT_OUT_MARKER.test(blockText);
537
+ }
538
+
539
+ function isEligibleScanPath(rel: string): boolean {
540
+ return /^actions\//.test(rel) || /^server\//.test(rel);
541
+ }
542
+
543
+ function scanFiles(
544
+ root: string,
545
+ ownablesByDir: Map<string, Set<string>>,
546
+ extraExemptPaths: string[],
547
+ ): Array<{ file: string; hits: Statement[] }> {
548
+ const allOwnableNames = new Set<string>();
549
+ const allOwnableSqlNames = new Set<string>();
550
+ for (const set of ownablesByDir.values()) {
551
+ for (const name of set) {
552
+ if (name.startsWith("__sql__")) allOwnableSqlNames.add(name.slice(7));
553
+ else allOwnableNames.add(name);
554
+ }
555
+ }
556
+
557
+ const violations: Array<{ file: string; hits: Statement[] }> = [];
558
+
559
+ for (const file of walk(root)) {
560
+ if (!file.endsWith(".ts") && !file.endsWith(".tsx")) continue;
561
+ if (file.endsWith(".d.ts")) continue;
562
+ const rel = relPosix(root, file);
563
+ if (extraExemptPaths.includes(rel)) continue;
564
+ if (rel.endsWith("/db/schema.ts")) continue;
565
+ if (!isEligibleScanPath(rel)) continue;
566
+
567
+ const contents = readFileSafe(file);
568
+ if (contents === null) continue;
569
+
570
+ if (
571
+ !/\bfrom\s*\(/.test(contents) &&
572
+ !/\bdb\s*\.\s*(update|delete|insert)\b/.test(contents) &&
573
+ !/\b(FROM|UPDATE|INSERT INTO|DELETE FROM)\b/i.test(contents)
574
+ ) {
575
+ continue;
576
+ }
577
+
578
+ const head = contents.split("\n").slice(0, 30).join("\n");
579
+ if (OPT_OUT_MARKER.test(head)) continue;
580
+
581
+ const statements = findStatements(
582
+ contents,
583
+ allOwnableNames,
584
+ allOwnableSqlNames,
585
+ );
586
+ if (statements.length === 0) continue;
587
+
588
+ const fileHasAccessControl =
589
+ ACCESS_CONTROL_HELPERS.some((re) => re.test(contents)) ||
590
+ EXPLICIT_OWNER_FILTERS.some((re) => re.test(contents));
591
+ if (!fileHasAccessControl) continue;
592
+
593
+ const blocks = buildBlockTree(contents);
594
+ const accessControlBindings = collectAccessControlBindings(contents);
595
+
596
+ const fileViolations: Statement[] = [];
597
+ for (const stmt of statements) {
598
+ if (statementHasInlineAccessControl(stmt)) continue;
599
+
600
+ let scoped = false;
601
+ let cur = innermostBlock(blocks, stmt.queryStart, contents.length);
602
+ let levels = 0;
603
+ while (cur && levels < 8) {
604
+ const directText = directBlockText(
605
+ contents,
606
+ cur,
607
+ blocks,
608
+ stmt.queryStart,
609
+ );
610
+ if (isOptedOutWithinBlock(directText)) {
611
+ scoped = true;
612
+ break;
613
+ }
614
+ if (blockHasAccessControl(directText)) {
615
+ scoped = true;
616
+ break;
617
+ }
618
+ if (
619
+ accessControlBindings.size > 0 &&
620
+ [...accessControlBindings].some((name) =>
621
+ new RegExp(`\\b${name}\\b`).test(stmt.snippet),
622
+ )
623
+ ) {
624
+ scoped = true;
625
+ break;
626
+ }
627
+ const parents = blocks.filter(
628
+ (b) => b.open < cur.open && b.close > cur.close,
629
+ );
630
+ const parent =
631
+ parents.length > 0
632
+ ? parents.reduce((a, b) => (a.open > b.open ? a : b))
633
+ : null;
634
+ if (!parent) break;
635
+ cur = parent;
636
+ levels++;
637
+ }
638
+ if (scoped) continue;
639
+
640
+ fileViolations.push(stmt);
641
+ }
642
+ if (fileViolations.length > 0) {
643
+ violations.push({ file: rel, hits: fileViolations });
644
+ }
645
+ }
646
+
647
+ return violations;
648
+ }
649
+
650
+ interface MentionViolation {
651
+ file: string;
652
+ line: number;
653
+ table: string;
654
+ }
655
+
656
+ function scanMentionProviders(
657
+ root: string,
658
+ ownablesByDir: Map<string, Set<string>>,
659
+ extraExemptPaths: string[],
660
+ ): MentionViolation[] {
661
+ const allOwnableNames = new Set<string>();
662
+ for (const set of ownablesByDir.values()) {
663
+ for (const name of set) {
664
+ if (!name.startsWith("__sql__")) allOwnableNames.add(name);
665
+ }
666
+ }
667
+ if (allOwnableNames.size === 0) return [];
668
+
669
+ const namesAlt = [...allOwnableNames]
670
+ .map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
671
+ .join("|");
672
+
673
+ const fromOwnableRe = new RegExp(
674
+ `\\.\\s*from\\s*\\(\\s*(?:[a-zA-Z_$][\\w$]*\\s*\\.\\s*)?(${namesAlt})\\b`,
675
+ "g",
676
+ );
677
+
678
+ const CLOSURE_ACCESS_PATTERNS = [
679
+ ...ACCESS_CONTROL_HELPERS,
680
+ ...EXPLICIT_OWNER_FILTERS,
681
+ ...BLOCK_OWNERSHIP_SIGNALS,
682
+ ];
683
+
684
+ const violations: MentionViolation[] = [];
685
+
686
+ for (const file of walk(root)) {
687
+ if (!file.endsWith(".ts") && !file.endsWith(".tsx")) continue;
688
+ if (file.endsWith(".d.ts")) continue;
689
+ const rel = relPosix(root, file);
690
+ if (extraExemptPaths.includes(rel)) continue;
691
+ if (!/^server\//.test(rel)) continue;
692
+
693
+ const contents = readFileSafe(file);
694
+ if (contents === null) continue;
695
+ if (
696
+ !/\bmentionProviders\b/.test(contents) ||
697
+ !/\bfrom\s*\(/.test(contents)
698
+ ) {
699
+ continue;
700
+ }
701
+
702
+ const head = contents.split("\n").slice(0, 30).join("\n");
703
+ if (OPT_OUT_MARKER.test(head)) continue;
704
+
705
+ const lineOffsets = computeLineOffsets(contents);
706
+
707
+ const mpHeaderRe = /\bmentionProviders\s*:/g;
708
+ while (mpHeaderRe.exec(contents) !== null) {
709
+ let i = mpHeaderRe.lastIndex;
710
+ while (i < contents.length && contents[i] !== "{" && contents[i] !== "\n")
711
+ i++;
712
+ if (i >= contents.length || contents[i] !== "{") continue;
713
+
714
+ let depth = 0;
715
+ let inStr: string | null = null;
716
+ const mpStart = i;
717
+ let mpEnd = -1;
718
+ for (let j = i; j < contents.length; j++) {
719
+ const c = contents[j];
720
+ if (inStr) {
721
+ if (c === "\\" && inStr !== "`") {
722
+ j++;
723
+ continue;
724
+ }
725
+ if (c === inStr) inStr = null;
726
+ continue;
727
+ }
728
+ if (c === '"' || c === "'" || c === "`") {
729
+ inStr = c;
730
+ continue;
731
+ }
732
+ if (c === "{") depth++;
733
+ else if (c === "}") {
734
+ depth--;
735
+ if (depth === 0) {
736
+ mpEnd = j;
737
+ break;
738
+ }
739
+ }
740
+ }
741
+ if (mpEnd === -1) continue;
742
+
743
+ const mpBody = contents.slice(mpStart, mpEnd + 1);
744
+
745
+ const searchRe = /\bsearch\s*:\s*async\s*\([^)]*\)\s*=>\s*\{/g;
746
+ let searchMatch: RegExpExecArray | null;
747
+ while ((searchMatch = searchRe.exec(mpBody)) !== null) {
748
+ const closureStart =
749
+ mpStart + searchMatch.index + searchMatch[0].length - 1;
750
+ let closureDepth = 0;
751
+ let closureEnd = -1;
752
+ let closureInStr: string | null = null;
753
+ for (let j = closureStart; j < mpEnd; j++) {
754
+ const c = contents[j];
755
+ if (closureInStr) {
756
+ if (c === "\\" && closureInStr !== "`") {
757
+ j++;
758
+ continue;
759
+ }
760
+ if (c === closureInStr) closureInStr = null;
761
+ continue;
762
+ }
763
+ if (c === '"' || c === "'" || c === "`") {
764
+ closureInStr = c;
765
+ continue;
766
+ }
767
+ if (c === "{") closureDepth++;
768
+ else if (c === "}") {
769
+ closureDepth--;
770
+ if (closureDepth === 0) {
771
+ closureEnd = j;
772
+ break;
773
+ }
774
+ }
775
+ }
776
+ if (closureEnd === -1) continue;
777
+
778
+ const closureBody = contents.slice(closureStart, closureEnd + 1);
779
+ if (OPT_OUT_MARKER.test(closureBody)) continue;
780
+
781
+ fromOwnableRe.lastIndex = 0;
782
+ let fromMatch: RegExpExecArray | null;
783
+ while ((fromMatch = fromOwnableRe.exec(closureBody)) !== null) {
784
+ const tableName = fromMatch[1];
785
+ if (CLOSURE_ACCESS_PATTERNS.some((re) => re.test(closureBody)))
786
+ continue;
787
+ const absOffset = closureStart + fromMatch.index;
788
+ const line = offsetToLine(lineOffsets, absOffset);
789
+ violations.push({ file: rel, line, table: tableName });
790
+ }
791
+ }
792
+ }
793
+ }
794
+
795
+ return violations;
796
+ }
797
+
798
+ export function scanUnscopedQueries(
799
+ options: UnscopedQueriesOptions,
800
+ ): GuardResult {
801
+ const { root, extraExemptPaths = [] } = options;
802
+ const findings: GuardFinding[] = [];
803
+
804
+ const ownablesByDir = collectOwnableTables(root);
805
+ if (ownablesByDir.size === 0) {
806
+ return { name: "no-unscoped-queries", findings };
807
+ }
808
+
809
+ const violations = scanFiles(root, ownablesByDir, extraExemptPaths);
810
+ for (const v of violations) {
811
+ for (const hit of v.hits) {
812
+ findings.push({
813
+ file: v.file,
814
+ line: hit.line,
815
+ message: `unscoped ${hit.op} on "${hit.name}" (${hit.kind}) — add accessFilter/resolveAccess/assertAccess or an explicit ownerEmail/userEmail/orgId filter.`,
816
+ });
817
+ }
818
+ }
819
+
820
+ const mentionViolations = scanMentionProviders(
821
+ root,
822
+ ownablesByDir,
823
+ extraExemptPaths,
824
+ );
825
+ for (const v of mentionViolations) {
826
+ findings.push({
827
+ file: v.file,
828
+ line: v.line,
829
+ message: `mentionProviders search closure queries "${v.table}" without access control — every user who types @ in chat would see rows owned by other users.`,
830
+ });
831
+ }
832
+
833
+ return { name: "no-unscoped-queries", findings };
834
+ }