@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,38 @@
1
+ /**
2
+ * scanDbToolScoping — ported from `scripts/guard-db-tool-scoping.mjs`.
3
+ *
4
+ * The agent's raw DB tools (`db-query`, `db-exec`, `db-patch`) can only
5
+ * safely expose tables with an explicit tenant scope (`owner_email` and/or
6
+ * `org_id`) or a documented, reviewed exception. This guard keeps schema
7
+ * drift visible: any table without raw-DB scope must either add
8
+ * `owner_email`/`org_id`, or be added to the denylist with a
9
+ * reviewer-readable reason.
10
+ *
11
+ * Conditional guard — per report 005's V1 guard set table: the original
12
+ * walks every `templates/*\/server/db/schema.ts` and keys its denylist
13
+ * `"<template>:<table>"`. A generated app has exactly one
14
+ * `server/db/schema.ts` (confirmed convention), so this port scans that
15
+ * single file and uses bare `"<table>"` denylist keys. The denylist itself
16
+ * comes from `agent-native.json`'s `doctor.dbToolScopingDenylist` (see
17
+ * `../cli/doctor.ts`) — empty by default; app authors add entries with the
18
+ * same reviewer-readable-reason convention as the original constant.
19
+ *
20
+ * Not ported: the original also resolves `export * from
21
+ * "@agent-native/<pkg>/schema"` re-exports back to that package's
22
+ * `packages/<pkg>/src/schema/*.ts` monorepo source, so template schemas
23
+ * that re-export scheduling/dispatch tables get scanned too. In a
24
+ * generated app those packages are compiled `node_modules` output (no
25
+ * `.ts` source to brace-parse), and report 005's parameterization note
26
+ * doesn't cover that case, so re-export resolution is intentionally
27
+ * dropped for app mode: a re-exported table from an `@agent-native/*`
28
+ * package is not scanned here (false-negative, not false-positive) — see
29
+ * the plan's STOP-condition guidance ("report rather than invent new
30
+ * detection logic").
31
+ */
32
+ import type { GuardResult, GuardScanOptions } from "./types.js";
33
+ export interface DbToolScopingOptions extends GuardScanOptions {
34
+ /** Table name -> reviewer-readable reason. Default `{}`. */
35
+ denylist?: Record<string, string>;
36
+ }
37
+ export declare function scanDbToolScoping(options: DbToolScopingOptions): GuardResult;
38
+ //# sourceMappingURL=db-tool-scoping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-tool-scoping.d.ts","sourceRoot":"","sources":["../../src/guards/db-tool-scoping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAgB,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9E,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAsDD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAoC5E"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * scanDbToolScoping — ported from `scripts/guard-db-tool-scoping.mjs`.
3
+ *
4
+ * The agent's raw DB tools (`db-query`, `db-exec`, `db-patch`) can only
5
+ * safely expose tables with an explicit tenant scope (`owner_email` and/or
6
+ * `org_id`) or a documented, reviewed exception. This guard keeps schema
7
+ * drift visible: any table without raw-DB scope must either add
8
+ * `owner_email`/`org_id`, or be added to the denylist with a
9
+ * reviewer-readable reason.
10
+ *
11
+ * Conditional guard — per report 005's V1 guard set table: the original
12
+ * walks every `templates/*\/server/db/schema.ts` and keys its denylist
13
+ * `"<template>:<table>"`. A generated app has exactly one
14
+ * `server/db/schema.ts` (confirmed convention), so this port scans that
15
+ * single file and uses bare `"<table>"` denylist keys. The denylist itself
16
+ * comes from `agent-native.json`'s `doctor.dbToolScopingDenylist` (see
17
+ * `../cli/doctor.ts`) — empty by default; app authors add entries with the
18
+ * same reviewer-readable-reason convention as the original constant.
19
+ *
20
+ * Not ported: the original also resolves `export * from
21
+ * "@agent-native/<pkg>/schema"` re-exports back to that package's
22
+ * `packages/<pkg>/src/schema/*.ts` monorepo source, so template schemas
23
+ * that re-export scheduling/dispatch tables get scanned too. In a
24
+ * generated app those packages are compiled `node_modules` output (no
25
+ * `.ts` source to brace-parse), and report 005's parameterization note
26
+ * doesn't cover that case, so re-export resolution is intentionally
27
+ * dropped for app mode: a re-exported table from an `@agent-native/*`
28
+ * package is not scanned here (false-negative, not false-positive) — see
29
+ * the plan's STOP-condition guidance ("report rather than invent new
30
+ * detection logic").
31
+ */
32
+ import { readFileSafe, relPosix, walk } from "./scan-utils.js";
33
+ function extractTableCalls(contents) {
34
+ const out = [];
35
+ const headerRegex = /export\s+const\s+([a-zA-Z_$][\w$]*)\s*=\s*(?:[a-zA-Z_$][\w$]*Table|table)\s*\(\s*"([^"]+)"\s*,\s*\{/gm;
36
+ let match;
37
+ while ((match = headerRegex.exec(contents)) !== null) {
38
+ const exportName = match[1];
39
+ const sqlName = match[2];
40
+ const start = headerRegex.lastIndex - 1;
41
+ let depth = 0;
42
+ let inStr = null;
43
+ let bodyEnd = -1;
44
+ for (let i = start; i < contents.length; i++) {
45
+ const c = contents[i];
46
+ const prev = contents[i - 1];
47
+ if (inStr) {
48
+ if (c === inStr && prev !== "\\")
49
+ inStr = null;
50
+ continue;
51
+ }
52
+ if (c === '"' || c === "'" || c === "`") {
53
+ inStr = c;
54
+ continue;
55
+ }
56
+ if (c === "{")
57
+ depth++;
58
+ else if (c === "}") {
59
+ depth--;
60
+ if (depth === 0) {
61
+ bodyEnd = i;
62
+ break;
63
+ }
64
+ }
65
+ }
66
+ if (bodyEnd === -1)
67
+ continue;
68
+ out.push({ exportName, sqlName, body: contents.slice(start + 1, bodyEnd) });
69
+ }
70
+ return out;
71
+ }
72
+ function hasRawDbScope(tableBody) {
73
+ return (/\.\.\.ownableColumns\s*\(/.test(tableBody) ||
74
+ /\b[\w$]+\s*:\s*text\s*\(\s*["']owner_email["']/.test(tableBody) ||
75
+ /\b[\w$]+\s*:\s*text\s*\(\s*["']org_id["']/.test(tableBody));
76
+ }
77
+ export function scanDbToolScoping(options) {
78
+ const { root, denylist = {} } = options;
79
+ const findings = [];
80
+ const seenAllowed = new Set();
81
+ for (const file of walk(root)) {
82
+ if (!file.endsWith("/server/db/schema.ts"))
83
+ continue;
84
+ const contents = readFileSafe(file);
85
+ if (contents === null)
86
+ continue;
87
+ const rel = relPosix(root, file);
88
+ const tables = extractTableCalls(contents);
89
+ for (const table of tables) {
90
+ if (hasRawDbScope(table.body))
91
+ continue;
92
+ if (Object.hasOwn(denylist, table.sqlName)) {
93
+ seenAllowed.add(table.sqlName);
94
+ continue;
95
+ }
96
+ findings.push({
97
+ file: rel,
98
+ line: 1,
99
+ message: `Table "${table.sqlName}" (export ${table.exportName}) has no owner_email/org_id scope and is not on the doctor.dbToolScopingDenylist — add tenant scope, or add it to agent-native.json's "doctor.dbToolScopingDenylist" with a reason.`,
100
+ });
101
+ }
102
+ }
103
+ for (const key of Object.keys(denylist)) {
104
+ if (!seenAllowed.has(key)) {
105
+ findings.push({
106
+ file: "agent-native.json",
107
+ line: 1,
108
+ message: `Stale doctor.dbToolScopingDenylist entry "${key}" — no matching table found in server/db/schema.ts. Remove it.`,
109
+ });
110
+ }
111
+ }
112
+ return { name: "db-tool-scoping", findings };
113
+ }
114
+ //# sourceMappingURL=db-tool-scoping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-tool-scoping.js","sourceRoot":"","sources":["../../src/guards/db-tool-scoping.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * scanDbToolScoping — ported from `scripts/guard-db-tool-scoping.mjs`.\n *\n * The agent's raw DB tools (`db-query`, `db-exec`, `db-patch`) can only\n * safely expose tables with an explicit tenant scope (`owner_email` and/or\n * `org_id`) or a documented, reviewed exception. This guard keeps schema\n * drift visible: any table without raw-DB scope must either add\n * `owner_email`/`org_id`, or be added to the denylist with a\n * reviewer-readable reason.\n *\n * Conditional guard — per report 005's V1 guard set table: the original\n * walks every `templates/*\\/server/db/schema.ts` and keys its denylist\n * `\"<template>:<table>\"`. A generated app has exactly one\n * `server/db/schema.ts` (confirmed convention), so this port scans that\n * single file and uses bare `\"<table>\"` denylist keys. The denylist itself\n * comes from `agent-native.json`'s `doctor.dbToolScopingDenylist` (see\n * `../cli/doctor.ts`) — empty by default; app authors add entries with the\n * same reviewer-readable-reason convention as the original constant.\n *\n * Not ported: the original also resolves `export * from\n * \"@agent-native/<pkg>/schema\"` re-exports back to that package's\n * `packages/<pkg>/src/schema/*.ts` monorepo source, so template schemas\n * that re-export scheduling/dispatch tables get scanned too. In a\n * generated app those packages are compiled `node_modules` output (no\n * `.ts` source to brace-parse), and report 005's parameterization note\n * doesn't cover that case, so re-export resolution is intentionally\n * dropped for app mode: a re-exported table from an `@agent-native/*`\n * package is not scanned here (false-negative, not false-positive) — see\n * the plan's STOP-condition guidance (\"report rather than invent new\n * detection logic\").\n */\n\nimport { readFileSafe, relPosix, walk } from \"./scan-utils.js\";\nimport type { GuardFinding, GuardResult, GuardScanOptions } from \"./types.js\";\n\nexport interface DbToolScopingOptions extends GuardScanOptions {\n /** Table name -> reviewer-readable reason. Default `{}`. */\n denylist?: Record<string, string>;\n}\n\ninterface TableCall {\n exportName: string;\n sqlName: string;\n body: string;\n}\n\nfunction extractTableCalls(contents: string): TableCall[] {\n const out: TableCall[] = [];\n const headerRegex =\n /export\\s+const\\s+([a-zA-Z_$][\\w$]*)\\s*=\\s*(?:[a-zA-Z_$][\\w$]*Table|table)\\s*\\(\\s*\"([^\"]+)\"\\s*,\\s*\\{/gm;\n let match: RegExpExecArray | null;\n while ((match = headerRegex.exec(contents)) !== null) {\n const exportName = match[1];\n const sqlName = match[2];\n const start = headerRegex.lastIndex - 1;\n let depth = 0;\n let inStr: string | null = null;\n let bodyEnd = -1;\n for (let i = start; i < contents.length; i++) {\n const c = contents[i];\n const prev = contents[i - 1];\n if (inStr) {\n if (c === inStr && prev !== \"\\\\\") inStr = null;\n continue;\n }\n if (c === '\"' || c === \"'\" || c === \"`\") {\n inStr = c;\n continue;\n }\n if (c === \"{\") depth++;\n else if (c === \"}\") {\n depth--;\n if (depth === 0) {\n bodyEnd = i;\n break;\n }\n }\n }\n if (bodyEnd === -1) continue;\n out.push({ exportName, sqlName, body: contents.slice(start + 1, bodyEnd) });\n }\n return out;\n}\n\nfunction hasRawDbScope(tableBody: string): boolean {\n return (\n /\\.\\.\\.ownableColumns\\s*\\(/.test(tableBody) ||\n /\\b[\\w$]+\\s*:\\s*text\\s*\\(\\s*[\"']owner_email[\"']/.test(tableBody) ||\n /\\b[\\w$]+\\s*:\\s*text\\s*\\(\\s*[\"']org_id[\"']/.test(tableBody)\n );\n}\n\nexport function scanDbToolScoping(options: DbToolScopingOptions): GuardResult {\n const { root, denylist = {} } = options;\n const findings: GuardFinding[] = [];\n const seenAllowed = new Set<string>();\n\n for (const file of walk(root)) {\n if (!file.endsWith(\"/server/db/schema.ts\")) continue;\n const contents = readFileSafe(file);\n if (contents === null) continue;\n const rel = relPosix(root, file);\n const tables = extractTableCalls(contents);\n for (const table of tables) {\n if (hasRawDbScope(table.body)) continue;\n if (Object.hasOwn(denylist, table.sqlName)) {\n seenAllowed.add(table.sqlName);\n continue;\n }\n findings.push({\n file: rel,\n line: 1,\n message: `Table \"${table.sqlName}\" (export ${table.exportName}) has no owner_email/org_id scope and is not on the doctor.dbToolScopingDenylist — add tenant scope, or add it to agent-native.json's \"doctor.dbToolScopingDenylist\" with a reason.`,\n });\n }\n }\n\n for (const key of Object.keys(denylist)) {\n if (!seenAllowed.has(key)) {\n findings.push({\n file: \"agent-native.json\",\n line: 1,\n message: `Stale doctor.dbToolScopingDenylist entry \"${key}\" — no matching table found in server/db/schema.ts. Remove it.`,\n });\n }\n }\n\n return { name: \"db-tool-scoping\", findings };\n}\n"]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `agent-native doctor`'s guard functions — the source-code safety
3
+ * invariants ported from this monorepo's `scripts/guard-*.mjs` CI guards
4
+ * (see report `advisor-plans/reports/005-doctor-design.md` for the
5
+ * classification and per-guard parameterization). Each guard is a pure,
6
+ * synchronous function that scans an app root and returns a `GuardResult`.
7
+ *
8
+ * `../cli/doctor.ts` is the only in-package caller; this module is also
9
+ * published under the `./guards` export subpath for advanced/CI use
10
+ * outside the CLI.
11
+ */
12
+ export { scanDbToolScoping } from "./db-tool-scoping.js";
13
+ export type { DbToolScopingOptions } from "./db-tool-scoping.js";
14
+ export { scanDrizzlePush } from "./no-drizzle-push.js";
15
+ export { scanEnvCredentials } from "./no-env-credentials.js";
16
+ export { scanEnvMutation } from "./no-env-mutation.js";
17
+ export { scanLocalhostFallback } from "./no-localhost-fallback.js";
18
+ export type { LocalhostFallbackOptions } from "./no-localhost-fallback.js";
19
+ export { scanUnscopedCredentials } from "./no-unscoped-credentials.js";
20
+ export { scanUnscopedQueries } from "./no-unscoped-queries.js";
21
+ export type { UnscopedQueriesOptions } from "./no-unscoped-queries.js";
22
+ export type { GuardFinding, GuardResult, GuardScanOptions } from "./types.js";
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `agent-native doctor`'s guard functions — the source-code safety
3
+ * invariants ported from this monorepo's `scripts/guard-*.mjs` CI guards
4
+ * (see report `advisor-plans/reports/005-doctor-design.md` for the
5
+ * classification and per-guard parameterization). Each guard is a pure,
6
+ * synchronous function that scans an app root and returns a `GuardResult`.
7
+ *
8
+ * `../cli/doctor.ts` is the only in-package caller; this module is also
9
+ * published under the `./guards` export subpath for advanced/CI use
10
+ * outside the CLI.
11
+ */
12
+ export { scanDbToolScoping } from "./db-tool-scoping.js";
13
+ export { scanDrizzlePush } from "./no-drizzle-push.js";
14
+ export { scanEnvCredentials } from "./no-env-credentials.js";
15
+ export { scanEnvMutation } from "./no-env-mutation.js";
16
+ export { scanLocalhostFallback } from "./no-localhost-fallback.js";
17
+ export { scanUnscopedCredentials } from "./no-unscoped-credentials.js";
18
+ export { scanUnscopedQueries } from "./no-unscoped-queries.js";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["/**\n * `agent-native doctor`'s guard functions — the source-code safety\n * invariants ported from this monorepo's `scripts/guard-*.mjs` CI guards\n * (see report `advisor-plans/reports/005-doctor-design.md` for the\n * classification and per-guard parameterization). Each guard is a pure,\n * synchronous function that scans an app root and returns a `GuardResult`.\n *\n * `../cli/doctor.ts` is the only in-package caller; this module is also\n * published under the `./guards` export subpath for advanced/CI use\n * outside the CLI.\n */\n\nexport { scanDbToolScoping } from \"./db-tool-scoping.js\";\nexport type { DbToolScopingOptions } from \"./db-tool-scoping.js\";\nexport { scanDrizzlePush } from \"./no-drizzle-push.js\";\nexport { scanEnvCredentials } from \"./no-env-credentials.js\";\nexport { scanEnvMutation } from \"./no-env-mutation.js\";\nexport { scanLocalhostFallback } from \"./no-localhost-fallback.js\";\nexport type { LocalhostFallbackOptions } from \"./no-localhost-fallback.js\";\nexport { scanUnscopedCredentials } from \"./no-unscoped-credentials.js\";\nexport { scanUnscopedQueries } from \"./no-unscoped-queries.js\";\nexport type { UnscopedQueriesOptions } from \"./no-unscoped-queries.js\";\nexport type { GuardFinding, GuardResult, GuardScanOptions } from \"./types.js\";\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * scanDrizzlePush — ported from `scripts/guard-no-drizzle-push.mjs`.
3
+ *
4
+ * Refuse to let `drizzle-kit push` (or `drizzle push`) get wired into any
5
+ * build/deploy path (`netlify.toml`, or a `package.json` build/deploy
6
+ * script). Generic guard — no monorepo-specific path assumption in the
7
+ * original, ported as-is.
8
+ *
9
+ * Standalone `db:push` / `db:push:*` npm scripts are intentionally NOT
10
+ * flagged — those are explicit, human-invoked commands, not build hooks.
11
+ */
12
+ import type { GuardResult, GuardScanOptions } from "./types.js";
13
+ export declare function scanDrizzlePush(options: GuardScanOptions): GuardResult;
14
+ //# sourceMappingURL=no-drizzle-push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-drizzle-push.d.ts","sourceRoot":"","sources":["../../src/guards/no-drizzle-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAgB,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgC9E,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,WAAW,CActE"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * scanDrizzlePush — ported from `scripts/guard-no-drizzle-push.mjs`.
3
+ *
4
+ * Refuse to let `drizzle-kit push` (or `drizzle push`) get wired into any
5
+ * build/deploy path (`netlify.toml`, or a `package.json` build/deploy
6
+ * script). Generic guard — no monorepo-specific path assumption in the
7
+ * original, ported as-is.
8
+ *
9
+ * Standalone `db:push` / `db:push:*` npm scripts are intentionally NOT
10
+ * flagged — those are explicit, human-invoked commands, not build hooks.
11
+ */
12
+ import { lineColForOffset, readFileSafe, relPosix, walk, } from "./scan-utils.js";
13
+ const DANGEROUS_SCRIPT_HOOKS = new Set([
14
+ "build",
15
+ "prebuild",
16
+ "postbuild",
17
+ "install",
18
+ "preinstall",
19
+ "postinstall",
20
+ "deploy",
21
+ "predeploy",
22
+ "postdeploy",
23
+ "start",
24
+ "prestart",
25
+ "poststart",
26
+ "ci",
27
+ "release",
28
+ "prerelease",
29
+ "postrelease",
30
+ ]);
31
+ const PATTERNS = [/\bdrizzle-kit\s+push\b/, /\bdrizzle\s+push\b/];
32
+ function matchesForbidden(str) {
33
+ if (!str || typeof str !== "string")
34
+ return false;
35
+ return PATTERNS.some((p) => p.test(str));
36
+ }
37
+ export function scanDrizzlePush(options) {
38
+ const { root } = options;
39
+ const findings = [];
40
+ for (const file of walk(root)) {
41
+ const base = file.split("/").pop() ?? file;
42
+ if (base === "netlify.toml") {
43
+ scanNetlifyToml(root, file, findings);
44
+ }
45
+ else if (base === "package.json") {
46
+ scanPackageJson(root, file, findings);
47
+ }
48
+ }
49
+ return { name: "no-drizzle-push", findings };
50
+ }
51
+ function scanNetlifyToml(root, file, findings) {
52
+ const contents = readFileSafe(file);
53
+ if (contents === null || !matchesForbidden(contents))
54
+ return;
55
+ const lines = contents.split("\n");
56
+ const rel = relPosix(root, file);
57
+ for (let i = 0; i < lines.length; i++) {
58
+ if (matchesForbidden(lines[i])) {
59
+ findings.push({
60
+ file: rel,
61
+ line: i + 1,
62
+ message: `forbidden \`drizzle-kit push\` in netlify.toml: ${lines[i].trim()}`,
63
+ });
64
+ }
65
+ }
66
+ }
67
+ function scanPackageJson(root, file, findings) {
68
+ const contents = readFileSafe(file);
69
+ if (contents === null)
70
+ return;
71
+ let json;
72
+ try {
73
+ json = JSON.parse(contents);
74
+ }
75
+ catch {
76
+ return;
77
+ }
78
+ const scripts = json.scripts;
79
+ if (!scripts || typeof scripts !== "object")
80
+ return;
81
+ const rel = relPosix(root, file);
82
+ for (const [name, cmd] of Object.entries(scripts)) {
83
+ if (!DANGEROUS_SCRIPT_HOOKS.has(name))
84
+ continue;
85
+ if (matchesForbidden(cmd)) {
86
+ // Locate the line for a readable finding; fall back to line 1.
87
+ const idx = contents.indexOf(`"${name}"`);
88
+ const line = idx >= 0 ? lineColForOffset(contents, idx).line : 1;
89
+ findings.push({
90
+ file: rel,
91
+ line,
92
+ message: `forbidden \`drizzle-kit push\` in scripts.${name}: ${String(cmd)}`,
93
+ });
94
+ }
95
+ }
96
+ }
97
+ //# sourceMappingURL=no-drizzle-push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-drizzle-push.js","sourceRoot":"","sources":["../../src/guards/no-drizzle-push.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * scanDrizzlePush — ported from `scripts/guard-no-drizzle-push.mjs`.\n *\n * Refuse to let `drizzle-kit push` (or `drizzle push`) get wired into any\n * build/deploy path (`netlify.toml`, or a `package.json` build/deploy\n * script). Generic guard — no monorepo-specific path assumption in the\n * original, ported as-is.\n *\n * Standalone `db:push` / `db:push:*` npm scripts are intentionally NOT\n * flagged — those are explicit, human-invoked commands, not build hooks.\n */\n\nimport {\n lineColForOffset,\n readFileSafe,\n relPosix,\n walk,\n} from \"./scan-utils.js\";\nimport type { GuardFinding, GuardResult, GuardScanOptions } from \"./types.js\";\n\nconst DANGEROUS_SCRIPT_HOOKS = new Set([\n \"build\",\n \"prebuild\",\n \"postbuild\",\n \"install\",\n \"preinstall\",\n \"postinstall\",\n \"deploy\",\n \"predeploy\",\n \"postdeploy\",\n \"start\",\n \"prestart\",\n \"poststart\",\n \"ci\",\n \"release\",\n \"prerelease\",\n \"postrelease\",\n]);\n\nconst PATTERNS = [/\\bdrizzle-kit\\s+push\\b/, /\\bdrizzle\\s+push\\b/];\n\nfunction matchesForbidden(str: unknown): str is string {\n if (!str || typeof str !== \"string\") return false;\n return PATTERNS.some((p) => p.test(str));\n}\n\ninterface PackageJsonLike {\n scripts?: Record<string, unknown>;\n}\n\nexport function scanDrizzlePush(options: GuardScanOptions): GuardResult {\n const { root } = options;\n const findings: GuardFinding[] = [];\n\n for (const file of walk(root)) {\n const base = file.split(\"/\").pop() ?? file;\n if (base === \"netlify.toml\") {\n scanNetlifyToml(root, file, findings);\n } else if (base === \"package.json\") {\n scanPackageJson(root, file, findings);\n }\n }\n\n return { name: \"no-drizzle-push\", findings };\n}\n\nfunction scanNetlifyToml(\n root: string,\n file: string,\n findings: GuardFinding[],\n): void {\n const contents = readFileSafe(file);\n if (contents === null || !matchesForbidden(contents)) return;\n const lines = contents.split(\"\\n\");\n const rel = relPosix(root, file);\n for (let i = 0; i < lines.length; i++) {\n if (matchesForbidden(lines[i])) {\n findings.push({\n file: rel,\n line: i + 1,\n message: `forbidden \\`drizzle-kit push\\` in netlify.toml: ${lines[i].trim()}`,\n });\n }\n }\n}\n\nfunction scanPackageJson(\n root: string,\n file: string,\n findings: GuardFinding[],\n): void {\n const contents = readFileSafe(file);\n if (contents === null) return;\n let json: PackageJsonLike;\n try {\n json = JSON.parse(contents) as PackageJsonLike;\n } catch {\n return;\n }\n const scripts = json.scripts;\n if (!scripts || typeof scripts !== \"object\") return;\n const rel = relPosix(root, file);\n for (const [name, cmd] of Object.entries(scripts)) {\n if (!DANGEROUS_SCRIPT_HOOKS.has(name)) continue;\n if (matchesForbidden(cmd)) {\n // Locate the line for a readable finding; fall back to line 1.\n const idx = contents.indexOf(`\"${name}\"`);\n const line = idx >= 0 ? lineColForOffset(contents, idx).line : 1;\n findings.push({\n file: rel,\n line,\n message: `forbidden \\`drizzle-kit push\\` in scripts.${name}: ${String(cmd)}`,\n });\n }\n }\n}\n"]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * scanEnvCredentials — ported from `scripts/guard-no-env-credentials.mjs`.
3
+ *
4
+ * User credentials are per-user (or per-org) data. They MUST live in SQL,
5
+ * scoped by `userEmail` / `orgId`, never in `process.env` — a deployment's
6
+ * env vars are shared by every signed-in user. This guard flags any
7
+ * `process.env.<KEY>` / `process.env["KEY"]` read whose key is not on the
8
+ * deploy-level allowlist (`DATABASE_URL`, `BETTER_AUTH_SECRET`, etc.), plus
9
+ * any dynamic `process.env[key]` read (the key is only known at runtime, so
10
+ * it can never be allowlisted safely).
11
+ *
12
+ * Conditional guard — per report 005's V1 guard set table, this is "the big
13
+ * one": the original only scans a curated set of monorepo subtrees
14
+ * (`packages/core/src/{credentials,secrets,vault,agent}/`, template
15
+ * credential libs/routes) via `FORBIDDEN_PATH_PREDICATES` — none of which
16
+ * exist in a generated app, so nothing would ever be scanned. This port
17
+ * replaces that default-allow-outside-a-curated-subtree behavior with
18
+ * default-deny across the whole app source tree: every `process.env.<KEY>`
19
+ * read anywhere in app source must be on the deploy-var allowlist (kept
20
+ * verbatim) or carry the opt-out marker. `HIGH_RISK_ENV_KEY_ALLOWLIST`,
21
+ * `HIGH_RISK_PROCESS_ENV_ALLOWLIST`, and `HIGH_RISK_ENV_VARS_WRITE_ALLOWLIST`
22
+ * — the three monorepo-file-keyed exception maps for specific template
23
+ * platform-adapter files — are dropped entirely per the report; with
24
+ * default-deny scanning already covering every `process.env` read
25
+ * everywhere, the narrower `env-config.ts`/`core-routes.ts`-specific
26
+ * registration checks those maps supported become redundant (any
27
+ * high-risk key would already be caught by the general scan) and are
28
+ * dropped along with them. The per-line `// guard:allow-env-credential`
29
+ * marker remains the only escape hatch.
30
+ *
31
+ * Opt-out (same line, or the line immediately above):
32
+ * process.env.SOMETHING // guard:allow-env-credential — short reason
33
+ */
34
+ import type { GuardResult, GuardScanOptions } from "./types.js";
35
+ export declare function scanEnvCredentials(options: GuardScanOptions): GuardResult;
36
+ //# sourceMappingURL=no-env-credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-env-credentials.d.ts","sourceRoot":"","sources":["../../src/guards/no-env-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAQH,OAAO,KAAK,EAAgB,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA4G9E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,WAAW,CAgFzE"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * scanEnvCredentials — ported from `scripts/guard-no-env-credentials.mjs`.
3
+ *
4
+ * User credentials are per-user (or per-org) data. They MUST live in SQL,
5
+ * scoped by `userEmail` / `orgId`, never in `process.env` — a deployment's
6
+ * env vars are shared by every signed-in user. This guard flags any
7
+ * `process.env.<KEY>` / `process.env["KEY"]` read whose key is not on the
8
+ * deploy-level allowlist (`DATABASE_URL`, `BETTER_AUTH_SECRET`, etc.), plus
9
+ * any dynamic `process.env[key]` read (the key is only known at runtime, so
10
+ * it can never be allowlisted safely).
11
+ *
12
+ * Conditional guard — per report 005's V1 guard set table, this is "the big
13
+ * one": the original only scans a curated set of monorepo subtrees
14
+ * (`packages/core/src/{credentials,secrets,vault,agent}/`, template
15
+ * credential libs/routes) via `FORBIDDEN_PATH_PREDICATES` — none of which
16
+ * exist in a generated app, so nothing would ever be scanned. This port
17
+ * replaces that default-allow-outside-a-curated-subtree behavior with
18
+ * default-deny across the whole app source tree: every `process.env.<KEY>`
19
+ * read anywhere in app source must be on the deploy-var allowlist (kept
20
+ * verbatim) or carry the opt-out marker. `HIGH_RISK_ENV_KEY_ALLOWLIST`,
21
+ * `HIGH_RISK_PROCESS_ENV_ALLOWLIST`, and `HIGH_RISK_ENV_VARS_WRITE_ALLOWLIST`
22
+ * — the three monorepo-file-keyed exception maps for specific template
23
+ * platform-adapter files — are dropped entirely per the report; with
24
+ * default-deny scanning already covering every `process.env` read
25
+ * everywhere, the narrower `env-config.ts`/`core-routes.ts`-specific
26
+ * registration checks those maps supported become redundant (any
27
+ * high-risk key would already be caught by the general scan) and are
28
+ * dropped along with them. The per-line `// guard:allow-env-credential`
29
+ * marker remains the only escape hatch.
30
+ *
31
+ * Opt-out (same line, or the line immediately above):
32
+ * process.env.SOMETHING // guard:allow-env-credential — short reason
33
+ */
34
+ import { lineColForOffset, readFileSafe, relPosix, walk, } from "./scan-utils.js";
35
+ const ALLOWLIST_EXACT = new Set([
36
+ "DATABASE_URL",
37
+ "DATABASE_AUTH_TOKEN",
38
+ "NODE_ENV",
39
+ "CI",
40
+ "DEBUG",
41
+ "NETLIFY",
42
+ "VERCEL",
43
+ "RENDER",
44
+ "FLY_APP_NAME",
45
+ "K_SERVICE",
46
+ "AWS_LAMBDA_FUNCTION_NAME",
47
+ "BETTER_AUTH_SECRET",
48
+ "BETTER_AUTH_URL",
49
+ "NOTION_CLIENT_ID",
50
+ "NOTION_CLIENT_SECRET",
51
+ "NOTION_STATE_SECRET",
52
+ "GOOGLE_SIGN_IN_CLIENT_ID",
53
+ "GOOGLE_SIGN_IN_CLIENT_SECRET",
54
+ "AUTH_SECRET",
55
+ "A2A_SECRET",
56
+ "ACCESS_TOKEN",
57
+ "PORT",
58
+ "HOST",
59
+ "SECRETS_ENCRYPTION_KEY",
60
+ ]);
61
+ const ALLOWLIST_PREFIX = [
62
+ "npm_",
63
+ "AGENT_NATIVE_",
64
+ "AGENT_",
65
+ "NETLIFY_",
66
+ "VERCEL_",
67
+ "CF_",
68
+ ];
69
+ /** Dev-only paths where ANTHROPIC_API_KEY etc. may legitimately be read
70
+ * from env (local dev tooling, scripts, tests). Portable subset of the
71
+ * original — the monorepo-only `packages/core/src/dev` predicate is
72
+ * dropped (see report 005's V1 guard set table). */
73
+ const DEV_ONLY_PATH_PATTERNS = [
74
+ /\.spec\.[tj]sx?$/,
75
+ /\.test\.[tj]sx?$/,
76
+ /^scripts\//,
77
+ ];
78
+ const DEV_ONLY_KEYS = new Set(["ANTHROPIC_API_KEY"]);
79
+ const OPT_OUT_MARKER = /\/\/\s*guard:allow-env-credential\b[^\n]*/;
80
+ const OPT_OUT_REQUIRES_REASON = /\/\/\s*guard:allow-env-credential\s*[—-]\s*\S/;
81
+ const ENV_READ_REGEX = /process\.env(?:\.([A-Z][A-Z0-9_]*)|\[\s*["']([A-Z][A-Z0-9_]*)["']\s*\])/g;
82
+ const ENV_DYNAMIC_READ_REGEX = /process\.env(?:\?\.)?\s*\[\s*(?!["'])([^\]\n]+?)\s*\]/g;
83
+ function isAllowlistedKey(key) {
84
+ if (ALLOWLIST_EXACT.has(key))
85
+ return true;
86
+ return ALLOWLIST_PREFIX.some((prefix) => key.startsWith(prefix));
87
+ }
88
+ function isDevOnlyPath(rel) {
89
+ return DEV_ONLY_PATH_PATTERNS.some((re) => re.test(rel));
90
+ }
91
+ function hasOptOutOnLine(lines, lineIdx) {
92
+ const cur = lines[lineIdx] ?? "";
93
+ if (OPT_OUT_MARKER.test(cur))
94
+ return true;
95
+ const prev = lines[lineIdx - 1] ?? "";
96
+ if (/^\s*\/\//.test(prev) && OPT_OUT_MARKER.test(prev))
97
+ return true;
98
+ return false;
99
+ }
100
+ function optOutOnLineIsValid(lines, lineIdx, key, rel) {
101
+ const cur = lines[lineIdx] ?? "";
102
+ const prev = lines[lineIdx - 1] ?? "";
103
+ const candidate = OPT_OUT_REQUIRES_REASON.test(cur)
104
+ ? cur
105
+ : OPT_OUT_REQUIRES_REASON.test(prev)
106
+ ? prev
107
+ : null;
108
+ if (!candidate)
109
+ return { ok: false, why: "missing or empty reason" };
110
+ if (/dev-only\b/i.test(candidate)) {
111
+ if (!DEV_ONLY_KEYS.has(key)) {
112
+ return {
113
+ ok: false,
114
+ why: `key "${key}" is not in the dev-only credential allowlist`,
115
+ };
116
+ }
117
+ if (!isDevOnlyPath(rel)) {
118
+ return {
119
+ ok: false,
120
+ why: "dev-only opt-out used outside dev / scripts / test paths",
121
+ };
122
+ }
123
+ }
124
+ return { ok: true };
125
+ }
126
+ export function scanEnvCredentials(options) {
127
+ const { root } = options;
128
+ const findings = [];
129
+ for (const file of walk(root)) {
130
+ if (!/\.(ts|tsx|mts|cts|js|mjs|cjs)$/.test(file))
131
+ continue;
132
+ if (file.endsWith(".d.ts"))
133
+ continue;
134
+ const rel = relPosix(root, file);
135
+ const contents = readFileSafe(file);
136
+ if (contents === null || !contents.includes("process.env"))
137
+ continue;
138
+ const lines = contents.split("\n");
139
+ ENV_READ_REGEX.lastIndex = 0;
140
+ let m;
141
+ while ((m = ENV_READ_REGEX.exec(contents)) !== null) {
142
+ const key = m[1] ?? m[2];
143
+ if (!key)
144
+ continue;
145
+ const { line } = lineColForOffset(contents, m.index);
146
+ const lineIdx = line - 1;
147
+ const lineText = lines[lineIdx] ?? "";
148
+ const trimmed = lineText.trimStart();
149
+ if (trimmed.startsWith("*") ||
150
+ trimmed.startsWith("//") ||
151
+ trimmed.startsWith("/*")) {
152
+ continue;
153
+ }
154
+ if (isAllowlistedKey(key))
155
+ continue;
156
+ if (hasOptOutOnLine(lines, lineIdx)) {
157
+ const verdict = optOutOnLineIsValid(lines, lineIdx, key, rel);
158
+ if (verdict.ok)
159
+ continue;
160
+ findings.push({
161
+ file: rel,
162
+ line,
163
+ message: `process.env.${key} opt-out invalid: ${verdict.why}`,
164
+ });
165
+ continue;
166
+ }
167
+ findings.push({
168
+ file: rel,
169
+ line,
170
+ message: `process.env.${key} read — not a deploy-level allowlisted key. User credentials must be read via resolveCredential(key, { userEmail, orgId }), never process.env.`,
171
+ });
172
+ }
173
+ ENV_DYNAMIC_READ_REGEX.lastIndex = 0;
174
+ while ((m = ENV_DYNAMIC_READ_REGEX.exec(contents)) !== null) {
175
+ const { line } = lineColForOffset(contents, m.index);
176
+ const lineIdx = line - 1;
177
+ const lineText = lines[lineIdx] ?? "";
178
+ const trimmed = lineText.trimStart();
179
+ if (trimmed.startsWith("*") ||
180
+ trimmed.startsWith("//") ||
181
+ trimmed.startsWith("/*")) {
182
+ continue;
183
+ }
184
+ if (hasOptOutOnLine(lines, lineIdx)) {
185
+ const verdict = optOutOnLineIsValid(lines, lineIdx, "<dynamic>", rel);
186
+ if (verdict.ok)
187
+ continue;
188
+ findings.push({
189
+ file: rel,
190
+ line,
191
+ message: `process.env[<dynamic>] opt-out invalid: ${verdict.why}`,
192
+ });
193
+ continue;
194
+ }
195
+ findings.push({
196
+ file: rel,
197
+ line,
198
+ message: `process.env[<dynamic key>] read — dynamic keys can never be allowlisted safely.`,
199
+ });
200
+ }
201
+ }
202
+ return { name: "no-env-credentials", findings };
203
+ }
204
+ //# sourceMappingURL=no-env-credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-env-credentials.js","sourceRoot":"","sources":["../../src/guards/no-env-credentials.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * scanEnvCredentials — ported from `scripts/guard-no-env-credentials.mjs`.\n *\n * User credentials are per-user (or per-org) data. They MUST live in SQL,\n * scoped by `userEmail` / `orgId`, never in `process.env` — a deployment's\n * env vars are shared by every signed-in user. This guard flags any\n * `process.env.<KEY>` / `process.env[\"KEY\"]` read whose key is not on the\n * deploy-level allowlist (`DATABASE_URL`, `BETTER_AUTH_SECRET`, etc.), plus\n * any dynamic `process.env[key]` read (the key is only known at runtime, so\n * it can never be allowlisted safely).\n *\n * Conditional guard — per report 005's V1 guard set table, this is \"the big\n * one\": the original only scans a curated set of monorepo subtrees\n * (`packages/core/src/{credentials,secrets,vault,agent}/`, template\n * credential libs/routes) via `FORBIDDEN_PATH_PREDICATES` — none of which\n * exist in a generated app, so nothing would ever be scanned. This port\n * replaces that default-allow-outside-a-curated-subtree behavior with\n * default-deny across the whole app source tree: every `process.env.<KEY>`\n * read anywhere in app source must be on the deploy-var allowlist (kept\n * verbatim) or carry the opt-out marker. `HIGH_RISK_ENV_KEY_ALLOWLIST`,\n * `HIGH_RISK_PROCESS_ENV_ALLOWLIST`, and `HIGH_RISK_ENV_VARS_WRITE_ALLOWLIST`\n * — the three monorepo-file-keyed exception maps for specific template\n * platform-adapter files — are dropped entirely per the report; with\n * default-deny scanning already covering every `process.env` read\n * everywhere, the narrower `env-config.ts`/`core-routes.ts`-specific\n * registration checks those maps supported become redundant (any\n * high-risk key would already be caught by the general scan) and are\n * dropped along with them. The per-line `// guard:allow-env-credential`\n * marker remains the only escape hatch.\n *\n * Opt-out (same line, or the line immediately above):\n * process.env.SOMETHING // guard:allow-env-credential — short reason\n */\n\nimport {\n lineColForOffset,\n readFileSafe,\n relPosix,\n walk,\n} from \"./scan-utils.js\";\nimport type { GuardFinding, GuardResult, GuardScanOptions } from \"./types.js\";\n\nconst ALLOWLIST_EXACT = new Set([\n \"DATABASE_URL\",\n \"DATABASE_AUTH_TOKEN\",\n \"NODE_ENV\",\n \"CI\",\n \"DEBUG\",\n \"NETLIFY\",\n \"VERCEL\",\n \"RENDER\",\n \"FLY_APP_NAME\",\n \"K_SERVICE\",\n \"AWS_LAMBDA_FUNCTION_NAME\",\n \"BETTER_AUTH_SECRET\",\n \"BETTER_AUTH_URL\",\n \"NOTION_CLIENT_ID\",\n \"NOTION_CLIENT_SECRET\",\n \"NOTION_STATE_SECRET\",\n \"GOOGLE_SIGN_IN_CLIENT_ID\",\n \"GOOGLE_SIGN_IN_CLIENT_SECRET\",\n \"AUTH_SECRET\",\n \"A2A_SECRET\",\n \"ACCESS_TOKEN\",\n \"PORT\",\n \"HOST\",\n \"SECRETS_ENCRYPTION_KEY\",\n]);\n\nconst ALLOWLIST_PREFIX = [\n \"npm_\",\n \"AGENT_NATIVE_\",\n \"AGENT_\",\n \"NETLIFY_\",\n \"VERCEL_\",\n \"CF_\",\n];\n\n/** Dev-only paths where ANTHROPIC_API_KEY etc. may legitimately be read\n * from env (local dev tooling, scripts, tests). Portable subset of the\n * original — the monorepo-only `packages/core/src/dev` predicate is\n * dropped (see report 005's V1 guard set table). */\nconst DEV_ONLY_PATH_PATTERNS = [\n /\\.spec\\.[tj]sx?$/,\n /\\.test\\.[tj]sx?$/,\n /^scripts\\//,\n];\n\nconst DEV_ONLY_KEYS = new Set([\"ANTHROPIC_API_KEY\"]);\n\nconst OPT_OUT_MARKER = /\\/\\/\\s*guard:allow-env-credential\\b[^\\n]*/;\nconst OPT_OUT_REQUIRES_REASON = /\\/\\/\\s*guard:allow-env-credential\\s*[—-]\\s*\\S/;\n\nconst ENV_READ_REGEX =\n /process\\.env(?:\\.([A-Z][A-Z0-9_]*)|\\[\\s*[\"']([A-Z][A-Z0-9_]*)[\"']\\s*\\])/g;\n\nconst ENV_DYNAMIC_READ_REGEX =\n /process\\.env(?:\\?\\.)?\\s*\\[\\s*(?![\"'])([^\\]\\n]+?)\\s*\\]/g;\n\nfunction isAllowlistedKey(key: string): boolean {\n if (ALLOWLIST_EXACT.has(key)) return true;\n return ALLOWLIST_PREFIX.some((prefix) => key.startsWith(prefix));\n}\n\nfunction isDevOnlyPath(rel: string): boolean {\n return DEV_ONLY_PATH_PATTERNS.some((re) => re.test(rel));\n}\n\nfunction hasOptOutOnLine(lines: string[], lineIdx: number): boolean {\n const cur = lines[lineIdx] ?? \"\";\n if (OPT_OUT_MARKER.test(cur)) return true;\n const prev = lines[lineIdx - 1] ?? \"\";\n if (/^\\s*\\/\\//.test(prev) && OPT_OUT_MARKER.test(prev)) return true;\n return false;\n}\n\nfunction optOutOnLineIsValid(\n lines: string[],\n lineIdx: number,\n key: string,\n rel: string,\n): { ok: boolean; why?: string } {\n const cur = lines[lineIdx] ?? \"\";\n const prev = lines[lineIdx - 1] ?? \"\";\n const candidate = OPT_OUT_REQUIRES_REASON.test(cur)\n ? cur\n : OPT_OUT_REQUIRES_REASON.test(prev)\n ? prev\n : null;\n if (!candidate) return { ok: false, why: \"missing or empty reason\" };\n\n if (/dev-only\\b/i.test(candidate)) {\n if (!DEV_ONLY_KEYS.has(key)) {\n return {\n ok: false,\n why: `key \"${key}\" is not in the dev-only credential allowlist`,\n };\n }\n if (!isDevOnlyPath(rel)) {\n return {\n ok: false,\n why: \"dev-only opt-out used outside dev / scripts / test paths\",\n };\n }\n }\n return { ok: true };\n}\n\nexport function scanEnvCredentials(options: GuardScanOptions): GuardResult {\n const { root } = options;\n const findings: GuardFinding[] = [];\n\n for (const file of walk(root)) {\n if (!/\\.(ts|tsx|mts|cts|js|mjs|cjs)$/.test(file)) continue;\n if (file.endsWith(\".d.ts\")) continue;\n const rel = relPosix(root, file);\n\n const contents = readFileSafe(file);\n if (contents === null || !contents.includes(\"process.env\")) continue;\n\n const lines = contents.split(\"\\n\");\n\n ENV_READ_REGEX.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = ENV_READ_REGEX.exec(contents)) !== null) {\n const key = m[1] ?? m[2];\n if (!key) continue;\n const { line } = lineColForOffset(contents, m.index);\n const lineIdx = line - 1;\n const lineText = lines[lineIdx] ?? \"\";\n const trimmed = lineText.trimStart();\n if (\n trimmed.startsWith(\"*\") ||\n trimmed.startsWith(\"//\") ||\n trimmed.startsWith(\"/*\")\n ) {\n continue;\n }\n if (isAllowlistedKey(key)) continue;\n if (hasOptOutOnLine(lines, lineIdx)) {\n const verdict = optOutOnLineIsValid(lines, lineIdx, key, rel);\n if (verdict.ok) continue;\n findings.push({\n file: rel,\n line,\n message: `process.env.${key} opt-out invalid: ${verdict.why}`,\n });\n continue;\n }\n findings.push({\n file: rel,\n line,\n message: `process.env.${key} read — not a deploy-level allowlisted key. User credentials must be read via resolveCredential(key, { userEmail, orgId }), never process.env.`,\n });\n }\n\n ENV_DYNAMIC_READ_REGEX.lastIndex = 0;\n while ((m = ENV_DYNAMIC_READ_REGEX.exec(contents)) !== null) {\n const { line } = lineColForOffset(contents, m.index);\n const lineIdx = line - 1;\n const lineText = lines[lineIdx] ?? \"\";\n const trimmed = lineText.trimStart();\n if (\n trimmed.startsWith(\"*\") ||\n trimmed.startsWith(\"//\") ||\n trimmed.startsWith(\"/*\")\n ) {\n continue;\n }\n if (hasOptOutOnLine(lines, lineIdx)) {\n const verdict = optOutOnLineIsValid(lines, lineIdx, \"<dynamic>\", rel);\n if (verdict.ok) continue;\n findings.push({\n file: rel,\n line,\n message: `process.env[<dynamic>] opt-out invalid: ${verdict.why}`,\n });\n continue;\n }\n findings.push({\n file: rel,\n line,\n message: `process.env[<dynamic key>] read — dynamic keys can never be allowlisted safely.`,\n });\n }\n }\n\n return { name: \"no-env-credentials\", findings };\n}\n"]}