@agent-native/core 0.96.0 → 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 (450) hide show
  1. package/README.md +6 -0
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +39 -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 +9 -2
  81. package/corpus/core/src/a2a/auth-policy.ts +33 -0
  82. package/corpus/core/src/agent/durable-background.ts +15 -7
  83. package/corpus/core/src/agent/run-store.ts +13 -4
  84. package/corpus/core/src/audit/actions/export-audit-events.ts +162 -0
  85. package/corpus/core/src/audit/store.ts +8 -3
  86. package/corpus/core/src/audit/types.ts +3 -0
  87. package/corpus/core/src/cli/doctor.ts +396 -0
  88. package/corpus/core/src/cli/index.ts +56 -0
  89. package/corpus/core/src/cli/info.ts +3 -3
  90. package/corpus/core/src/cli/package-lifecycle.ts +821 -0
  91. package/corpus/core/src/client/agent-chat-adapter.ts +9 -9
  92. package/corpus/core/src/guards/db-tool-scoping.ts +129 -0
  93. package/corpus/core/src/guards/index.ts +23 -0
  94. package/corpus/core/src/guards/no-drizzle-push.ts +116 -0
  95. package/corpus/core/src/guards/no-env-credentials.ts +229 -0
  96. package/corpus/core/src/guards/no-env-mutation.ts +114 -0
  97. package/corpus/core/src/guards/no-localhost-fallback.ts +124 -0
  98. package/corpus/core/src/guards/no-unscoped-credentials.ts +227 -0
  99. package/corpus/core/src/guards/no-unscoped-queries.ts +834 -0
  100. package/corpus/core/src/guards/scan-utils.ts +105 -0
  101. package/corpus/core/src/guards/types.ts +30 -0
  102. package/corpus/core/src/org/accept-pending.ts +9 -1
  103. package/corpus/core/src/org/migrations.ts +41 -0
  104. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  105. package/corpus/core/src/package-lifecycle/manifest.ts +120 -0
  106. package/corpus/core/src/provider-api/custom-registry.ts +56 -0
  107. package/corpus/core/src/provider-api/index.ts +2 -0
  108. package/corpus/core/src/secrets/storage.ts +47 -27
  109. package/corpus/core/src/server/action-discovery.ts +4 -0
  110. package/corpus/core/src/server/agent-chat-plugin.ts +54 -12
  111. package/corpus/core/src/server/core-routes-plugin.ts +30 -14
  112. package/corpus/core/src/server/csrf.ts +24 -5
  113. package/corpus/core/src/server/framework-request-handler.ts +34 -0
  114. package/corpus/core/src/server/google-realtime-session.ts +1 -36
  115. package/corpus/core/src/server/poll.ts +24 -2
  116. package/corpus/core/src/server/realtime-voice.ts +9 -0
  117. package/corpus/core/src/server/request-origin.ts +63 -0
  118. package/corpus/core/src/server/transcribe-voice.ts +1 -50
  119. package/corpus/core/src/templates/default/package.json +2 -2
  120. package/corpus/core/src/templates/headless/package.json +0 -1
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  123. package/corpus/core/src/templates/workspace-core/package.json +0 -1
  124. package/corpus/core/src/templates/workspace-root/package.json +0 -1
  125. package/corpus/core/src/triggers/actions.ts +11 -3
  126. package/corpus/core/src/triggers/types.ts +7 -1
  127. package/corpus/templates/analytics/actions/compose-dashboard.ts +65 -37
  128. package/corpus/templates/analytics/actions/mutate-dashboard.ts +73 -24
  129. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +16 -13
  130. package/corpus/templates/analytics/actions/update-dashboard.ts +53 -42
  131. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-edits-from-the-agent-and-the-ui-at-the-same-time-n.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-timed-out-bigquery-jobs-are-now-cancelled-so-they-stop-consu.md +6 -0
  133. package/corpus/templates/analytics/package.json +1 -2
  134. package/corpus/templates/analytics/server/lib/bigquery.ts +3 -2
  135. package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
  136. package/corpus/templates/assets/package.json +1 -2
  137. package/corpus/templates/brain/package.json +1 -2
  138. package/corpus/templates/calendar/package.json +1 -2
  139. package/corpus/templates/chat/package.json +1 -2
  140. package/corpus/templates/clips/changelog/2026-07-10-atomic-view-tracking.md +6 -0
  141. package/corpus/templates/clips/chrome-extension/package.json +3 -2
  142. package/corpus/templates/clips/desktop/package.json +6 -4
  143. package/corpus/templates/clips/desktop/src/lib/recorder.ts +26 -13
  144. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +4 -1
  145. package/corpus/templates/clips/package.json +1 -2
  146. package/corpus/templates/clips/server/db/schema.ts +29 -17
  147. package/corpus/templates/clips/server/plugins/db.ts +8 -0
  148. package/corpus/templates/clips/server/routes/api/view-event.post.ts +260 -105
  149. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +16 -0
  150. package/corpus/templates/content/AGENTS.md +72 -62
  151. package/corpus/templates/content/actions/_content-database-source-adapters.ts +84 -0
  152. package/corpus/templates/content/actions/_database-source-utils.ts +206 -96
  153. package/corpus/templates/content/actions/_notion-database-source-adapter.ts +216 -0
  154. package/corpus/templates/content/actions/_position-utils.ts +76 -0
  155. package/corpus/templates/content/actions/_property-utils.ts +31 -20
  156. package/corpus/templates/content/actions/add-database-item.ts +52 -39
  157. package/corpus/templates/content/actions/attach-content-database-source.ts +95 -11
  158. package/corpus/templates/content/actions/change-content-database-source-role.ts +24 -1
  159. package/corpus/templates/content/actions/configure-document-property.ts +36 -27
  160. package/corpus/templates/content/actions/create-content-database.ts +40 -30
  161. package/corpus/templates/content/actions/create-document.ts +39 -32
  162. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -28
  163. package/corpus/templates/content/actions/list-notion-database-sources.ts +80 -0
  164. package/corpus/templates/content/actions/move-document.ts +64 -48
  165. package/corpus/templates/content/actions/refresh-content-database-source.ts +42 -3
  166. package/corpus/templates/content/actions/share-local-file-document.ts +36 -27
  167. package/corpus/templates/content/actions/suggest-source-join-key.ts +39 -16
  168. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +89 -23
  169. package/corpus/templates/content/app/components/editor/database/settings.tsx +1 -1
  170. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -1
  171. package/corpus/templates/content/app/i18n/zh-TW.ts +4 -0
  172. package/corpus/templates/content/app/i18n-data.ts +40 -0
  173. package/corpus/templates/content/changelog/2026-07-10-failed-row-creation-and-source-attach-now-show-an-error-inst.md +6 -0
  174. package/corpus/templates/content/changelog/2026-07-10-items-added-at-the-same-time-no-longer-end-up-with-identical.md +6 -0
  175. package/corpus/templates/content/changelog/2026-07-10-notion-databases-can-add-read-only-details-to-content-tables.md +6 -0
  176. package/corpus/templates/content/package.json +1 -2
  177. package/corpus/templates/content/parity/matrix.md +25 -25
  178. package/corpus/templates/content/parity/matrix.ts +1 -0
  179. package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +43 -26
  180. package/corpus/templates/content/shared/api.ts +16 -1
  181. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +8 -4
  182. package/corpus/templates/design/AGENTS.md +12 -2
  183. package/corpus/templates/design/DEVELOPING.md +10 -6
  184. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -6
  185. package/corpus/templates/design/actions/duplicate-design.ts +31 -25
  186. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +5 -1
  187. package/corpus/templates/design/changelog/2026-07-10-duplicating-a-design-can-no-longer-produce-a-copy-with-missi.md +6 -0
  188. package/corpus/templates/design/changelog/2026-07-10-local-visual-edits-can-now-save-safe-leaf-text-class-and.md +6 -0
  189. package/corpus/templates/design/package.json +1 -1
  190. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +388 -0
  191. package/corpus/templates/dispatch/package.json +1 -2
  192. package/corpus/templates/forms/actions/patch-form-fields.ts +82 -44
  193. package/corpus/templates/forms/changelog/2026-07-10-simultaneous-edits-to-different-form-fields-no-longer-overwr.md +6 -0
  194. package/corpus/templates/forms/package.json +1 -2
  195. package/corpus/templates/macros/package.json +1 -2
  196. package/corpus/templates/mail/app/components/email/EmailThread.tsx +3 -1
  197. package/corpus/templates/mail/changelog/2026-07-10-fixed-calendar-rsvp-buttons-in-emails-firing-duplicate-respo.md +6 -0
  198. package/corpus/templates/mail/package.json +1 -2
  199. package/corpus/templates/plan/actions/restore-plan-version.ts +126 -96
  200. package/corpus/templates/plan/changelog/2026-07-10-restoring-a-plan-version-can-no-longer-leave-a-plan-half-res.md +6 -0
  201. package/corpus/templates/plan/package.json +1 -2
  202. package/corpus/templates/plan/server/plans.ts +9 -2
  203. package/corpus/templates/slides/actions/list-decks.ts +28 -0
  204. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +41 -26
  205. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +4 -8
  206. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -4
  207. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -8
  208. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -12
  209. package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +3 -6
  210. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +3 -6
  211. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -5
  212. package/corpus/templates/slides/app/context/DeckContext.tsx +47 -4
  213. package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -30
  214. package/corpus/templates/slides/app/pages/Index.tsx +2 -3
  215. package/corpus/templates/slides/app/root.tsx +0 -5
  216. package/corpus/templates/slides/changelog/2026-07-10-deck-lists-load-much-faster-and-no-longer-re-download-slide-.md +6 -0
  217. package/corpus/templates/slides/package.json +1 -2
  218. package/dist/a2a/auth-policy.d.ts +19 -0
  219. package/dist/a2a/auth-policy.d.ts.map +1 -1
  220. package/dist/a2a/auth-policy.js +32 -0
  221. package/dist/a2a/auth-policy.js.map +1 -1
  222. package/dist/agent/durable-background.d.ts +8 -5
  223. package/dist/agent/durable-background.d.ts.map +1 -1
  224. package/dist/agent/durable-background.js +15 -8
  225. package/dist/agent/durable-background.js.map +1 -1
  226. package/dist/agent/run-store.d.ts.map +1 -1
  227. package/dist/agent/run-store.js +9 -4
  228. package/dist/agent/run-store.js.map +1 -1
  229. package/dist/audit/actions/export-audit-events.d.ts +27 -0
  230. package/dist/audit/actions/export-audit-events.d.ts.map +1 -0
  231. package/dist/audit/actions/export-audit-events.js +144 -0
  232. package/dist/audit/actions/export-audit-events.js.map +1 -0
  233. package/dist/audit/store.d.ts +1 -0
  234. package/dist/audit/store.d.ts.map +1 -1
  235. package/dist/audit/store.js +8 -3
  236. package/dist/audit/store.js.map +1 -1
  237. package/dist/audit/types.d.ts +3 -0
  238. package/dist/audit/types.d.ts.map +1 -1
  239. package/dist/audit/types.js.map +1 -1
  240. package/dist/cli/doctor.d.ts +83 -0
  241. package/dist/cli/doctor.d.ts.map +1 -0
  242. package/dist/cli/doctor.js +277 -0
  243. package/dist/cli/doctor.js.map +1 -0
  244. package/dist/cli/index.js +50 -0
  245. package/dist/cli/index.js.map +1 -1
  246. package/dist/cli/info.js +3 -3
  247. package/dist/cli/info.js.map +1 -1
  248. package/dist/cli/package-lifecycle.d.ts +50 -0
  249. package/dist/cli/package-lifecycle.d.ts.map +1 -0
  250. package/dist/cli/package-lifecycle.js +560 -0
  251. package/dist/cli/package-lifecycle.js.map +1 -0
  252. package/dist/client/agent-chat-adapter.js +7 -3
  253. package/dist/client/agent-chat-adapter.js.map +1 -1
  254. package/dist/collab/struct-routes.d.ts +1 -1
  255. package/dist/guards/db-tool-scoping.d.ts +38 -0
  256. package/dist/guards/db-tool-scoping.d.ts.map +1 -0
  257. package/dist/guards/db-tool-scoping.js +114 -0
  258. package/dist/guards/db-tool-scoping.js.map +1 -0
  259. package/dist/guards/index.d.ts +23 -0
  260. package/dist/guards/index.d.ts.map +1 -0
  261. package/dist/guards/index.js +19 -0
  262. package/dist/guards/index.js.map +1 -0
  263. package/dist/guards/no-drizzle-push.d.ts +14 -0
  264. package/dist/guards/no-drizzle-push.d.ts.map +1 -0
  265. package/dist/guards/no-drizzle-push.js +97 -0
  266. package/dist/guards/no-drizzle-push.js.map +1 -0
  267. package/dist/guards/no-env-credentials.d.ts +36 -0
  268. package/dist/guards/no-env-credentials.d.ts.map +1 -0
  269. package/dist/guards/no-env-credentials.js +204 -0
  270. package/dist/guards/no-env-credentials.js.map +1 -0
  271. package/dist/guards/no-env-mutation.d.ts +23 -0
  272. package/dist/guards/no-env-mutation.d.ts.map +1 -0
  273. package/dist/guards/no-env-mutation.js +90 -0
  274. package/dist/guards/no-env-mutation.js.map +1 -0
  275. package/dist/guards/no-localhost-fallback.d.ts +30 -0
  276. package/dist/guards/no-localhost-fallback.d.ts.map +1 -0
  277. package/dist/guards/no-localhost-fallback.js +105 -0
  278. package/dist/guards/no-localhost-fallback.js.map +1 -0
  279. package/dist/guards/no-unscoped-credentials.d.ts +28 -0
  280. package/dist/guards/no-unscoped-credentials.d.ts.map +1 -0
  281. package/dist/guards/no-unscoped-credentials.js +199 -0
  282. package/dist/guards/no-unscoped-credentials.js.map +1 -0
  283. package/dist/guards/no-unscoped-queries.d.ts +32 -0
  284. package/dist/guards/no-unscoped-queries.d.ts.map +1 -0
  285. package/dist/guards/no-unscoped-queries.js +720 -0
  286. package/dist/guards/no-unscoped-queries.js.map +1 -0
  287. package/dist/guards/scan-utils.d.ts +28 -0
  288. package/dist/guards/scan-utils.d.ts.map +1 -0
  289. package/dist/guards/scan-utils.js +92 -0
  290. package/dist/guards/scan-utils.js.map +1 -0
  291. package/dist/guards/types.d.ts +28 -0
  292. package/dist/guards/types.d.ts.map +1 -0
  293. package/dist/guards/types.js +11 -0
  294. package/dist/guards/types.js.map +1 -0
  295. package/dist/org/accept-pending.d.ts.map +1 -1
  296. package/dist/org/accept-pending.js +9 -1
  297. package/dist/org/accept-pending.js.map +1 -1
  298. package/dist/org/migrations.d.ts +7 -2
  299. package/dist/org/migrations.d.ts.map +1 -1
  300. package/dist/org/migrations.js +41 -0
  301. package/dist/org/migrations.js.map +1 -1
  302. package/dist/package-lifecycle/index.d.ts +2 -0
  303. package/dist/package-lifecycle/index.d.ts.map +1 -0
  304. package/dist/package-lifecycle/index.js +2 -0
  305. package/dist/package-lifecycle/index.js.map +1 -0
  306. package/dist/package-lifecycle/manifest.d.ts +24 -0
  307. package/dist/package-lifecycle/manifest.d.ts.map +1 -0
  308. package/dist/package-lifecycle/manifest.js +81 -0
  309. package/dist/package-lifecycle/manifest.js.map +1 -0
  310. package/dist/progress/routes.d.ts +1 -1
  311. package/dist/provider-api/custom-registry.d.ts +32 -1
  312. package/dist/provider-api/custom-registry.d.ts.map +1 -1
  313. package/dist/provider-api/custom-registry.js +41 -1
  314. package/dist/provider-api/custom-registry.js.map +1 -1
  315. package/dist/provider-api/index.d.ts +1 -1
  316. package/dist/provider-api/index.d.ts.map +1 -1
  317. package/dist/provider-api/index.js +1 -1
  318. package/dist/provider-api/index.js.map +1 -1
  319. package/dist/secrets/storage.d.ts.map +1 -1
  320. package/dist/secrets/storage.js +45 -27
  321. package/dist/secrets/storage.js.map +1 -1
  322. package/dist/server/action-discovery.d.ts.map +1 -1
  323. package/dist/server/action-discovery.js +4 -0
  324. package/dist/server/action-discovery.js.map +1 -1
  325. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  326. package/dist/server/agent-chat-plugin.js +47 -13
  327. package/dist/server/agent-chat-plugin.js.map +1 -1
  328. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  329. package/dist/server/core-routes-plugin.js +23 -12
  330. package/dist/server/core-routes-plugin.js.map +1 -1
  331. package/dist/server/csrf.d.ts.map +1 -1
  332. package/dist/server/csrf.js +18 -5
  333. package/dist/server/csrf.js.map +1 -1
  334. package/dist/server/framework-request-handler.d.ts.map +1 -1
  335. package/dist/server/framework-request-handler.js +34 -0
  336. package/dist/server/framework-request-handler.js.map +1 -1
  337. package/dist/server/google-realtime-session.d.ts.map +1 -1
  338. package/dist/server/google-realtime-session.js +2 -34
  339. package/dist/server/google-realtime-session.js.map +1 -1
  340. package/dist/server/poll.d.ts.map +1 -1
  341. package/dist/server/poll.js +24 -2
  342. package/dist/server/poll.js.map +1 -1
  343. package/dist/server/realtime-voice.d.ts.map +1 -1
  344. package/dist/server/realtime-voice.js +9 -0
  345. package/dist/server/realtime-voice.js.map +1 -1
  346. package/dist/server/request-origin.d.ts +10 -0
  347. package/dist/server/request-origin.d.ts.map +1 -0
  348. package/dist/server/request-origin.js +60 -0
  349. package/dist/server/request-origin.js.map +1 -0
  350. package/dist/server/transcribe-voice.d.ts.map +1 -1
  351. package/dist/server/transcribe-voice.js +2 -48
  352. package/dist/server/transcribe-voice.js.map +1 -1
  353. package/dist/templates/default/package.json +2 -2
  354. package/dist/templates/headless/package.json +0 -1
  355. package/dist/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  356. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  357. package/dist/templates/workspace-core/package.json +0 -1
  358. package/dist/templates/workspace-root/package.json +0 -1
  359. package/dist/triggers/actions.d.ts.map +1 -1
  360. package/dist/triggers/actions.js +8 -3
  361. package/dist/triggers/actions.js.map +1 -1
  362. package/dist/triggers/types.d.ts +7 -1
  363. package/dist/triggers/types.d.ts.map +1 -1
  364. package/dist/triggers/types.js.map +1 -1
  365. package/docs/content/audit-log.mdx +2 -1
  366. package/docs/content/automations.mdx +7 -7
  367. package/docs/content/creating-templates.mdx +1 -1
  368. package/docs/content/internationalization.mdx +2 -1
  369. package/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  370. package/docs/content/locales/ar-SA/automations.mdx +7 -7
  371. package/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  372. package/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  373. package/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  374. package/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  375. package/docs/content/locales/ar-SA/security.mdx +8 -0
  376. package/docs/content/locales/de-DE/audit-log.mdx +2 -1
  377. package/docs/content/locales/de-DE/automations.mdx +7 -7
  378. package/docs/content/locales/de-DE/getting-started.mdx +7 -1
  379. package/docs/content/locales/de-DE/internationalization.mdx +1 -1
  380. package/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  381. package/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  382. package/docs/content/locales/de-DE/security.mdx +8 -0
  383. package/docs/content/locales/es-ES/audit-log.mdx +2 -1
  384. package/docs/content/locales/es-ES/automations.mdx +7 -7
  385. package/docs/content/locales/es-ES/getting-started.mdx +7 -1
  386. package/docs/content/locales/es-ES/internationalization.mdx +1 -1
  387. package/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  388. package/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  389. package/docs/content/locales/es-ES/security.mdx +8 -0
  390. package/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  391. package/docs/content/locales/fr-FR/automations.mdx +7 -7
  392. package/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  393. package/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  394. package/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  395. package/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  396. package/docs/content/locales/fr-FR/security.mdx +8 -0
  397. package/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  398. package/docs/content/locales/hi-IN/automations.mdx +7 -7
  399. package/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  400. package/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  401. package/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  402. package/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  403. package/docs/content/locales/hi-IN/security.mdx +8 -0
  404. package/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  405. package/docs/content/locales/ja-JP/automations.mdx +7 -7
  406. package/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  407. package/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  408. package/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  409. package/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  410. package/docs/content/locales/ja-JP/security.mdx +8 -0
  411. package/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  412. package/docs/content/locales/ko-KR/automations.mdx +7 -7
  413. package/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  414. package/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  415. package/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  416. package/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  417. package/docs/content/locales/ko-KR/security.mdx +8 -0
  418. package/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  419. package/docs/content/locales/pt-BR/automations.mdx +7 -7
  420. package/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  421. package/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  422. package/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  423. package/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  424. package/docs/content/locales/pt-BR/security.mdx +8 -0
  425. package/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  426. package/docs/content/locales/zh-CN/automations.mdx +7 -7
  427. package/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  428. package/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  429. package/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  430. package/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  431. package/docs/content/locales/zh-CN/security.mdx +8 -0
  432. package/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  433. package/docs/content/locales/zh-TW/automations.mdx +7 -7
  434. package/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  435. package/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  436. package/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  437. package/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  438. package/docs/content/locales/zh-TW/security.mdx +8 -0
  439. package/docs/content/package-lifecycle.mdx +51 -0
  440. package/docs/content/sandbox-adapters.mdx +16 -5
  441. package/package.json +10 -3
  442. package/src/templates/default/package.json +2 -2
  443. package/src/templates/headless/package.json +0 -1
  444. package/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  445. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  446. package/src/templates/workspace-core/package.json +0 -1
  447. package/src/templates/workspace-root/package.json +0 -1
  448. package/corpus/templates/slides/app/components/ui/toast.tsx +0 -1
  449. package/corpus/templates/slides/app/components/ui/toaster.tsx +0 -1
  450. package/corpus/templates/slides/app/hooks/use-toast.ts +0 -1
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Bulk-export audit-log events as CSV or NDJSON — the "bulk export" sensitive
3
+ * read the audit doc itself names. Pages past the per-call row clamp
4
+ * (`queryAuditEvents`'s `MAX_LIMIT`) up to `maxRows`, scoped in SQL to the
5
+ * caller's identity exactly like `list-audit-events`. Read-only; never
6
+ * exposes other tenants' rows.
7
+ */
8
+ declare const _default: import("../../action.js").ActionDefinition<{
9
+ targetType?: string;
10
+ targetId?: string;
11
+ actorKind?: "agent" | "human" | "system";
12
+ actorEmail?: string;
13
+ status?: "denied" | "error" | "success";
14
+ threadId?: string;
15
+ turnId?: string;
16
+ action?: string;
17
+ sinceMs?: number;
18
+ format?: "csv" | "ndjson";
19
+ maxRows?: number;
20
+ }, {
21
+ content: string;
22
+ rowCount: number;
23
+ truncated: boolean;
24
+ format: "csv" | "ndjson";
25
+ }>;
26
+ export default _default;
27
+ //# sourceMappingURL=export-audit-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-audit-events.d.ts","sourceRoot":"","sources":["../../../src/audit/actions/export-audit-events.ts"],"names":[],"mappings":"AAwDA;;;;;;GAMG"}
@@ -0,0 +1,144 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { MAX_LIMIT, queryAuditEvents } from "../store.js";
4
+ const DEFAULT_MAX_ROWS = 5000;
5
+ const HARD_CAP_ROWS = 10000;
6
+ // Deterministic column order for CSV — mirrors the store's list projection
7
+ // (`LIST_COLUMNS`), which deliberately excludes `input` so a bulk export
8
+ // never streams every event's (redacted) request body at once. Future
9
+ // columns added to the audit store must be reflected here too.
10
+ const CSV_COLUMNS = [
11
+ ["id", "id"],
12
+ ["createdAt", "created_at"],
13
+ ["action", "action"],
14
+ ["caller", "caller"],
15
+ ["actorKind", "actor_kind"],
16
+ ["actorEmail", "actor_email"],
17
+ ["orgId", "org_id"],
18
+ ["threadId", "thread_id"],
19
+ ["turnId", "turn_id"],
20
+ ["targetType", "target_type"],
21
+ ["targetId", "target_id"],
22
+ ["status", "status"],
23
+ ["summary", "summary"],
24
+ ["errorCode", "error_code"],
25
+ ["ownerEmail", "owner_email"],
26
+ ["visibility", "visibility"],
27
+ ];
28
+ /** Hand-rolled CSV field escaper — quotes a field when it contains a comma,
29
+ * quote, or newline, doubling any embedded quotes. No dependency needed for
30
+ * ~10 lines of RFC 4180 escaping. */
31
+ function csvField(value) {
32
+ if (value === null || value === undefined)
33
+ return "";
34
+ const raw = String(value);
35
+ if (/[",\n\r]/.test(raw)) {
36
+ return `"${raw.replace(/"/g, '""')}"`;
37
+ }
38
+ return raw;
39
+ }
40
+ function toCsv(events) {
41
+ const header = CSV_COLUMNS.map(([, label]) => label).join(",");
42
+ const rows = events.map((event) => CSV_COLUMNS.map(([key]) => csvField(event[key])).join(","));
43
+ return [header, ...rows].join("\n");
44
+ }
45
+ function toNdjson(events) {
46
+ return events.map((event) => JSON.stringify(event)).join("\n");
47
+ }
48
+ /**
49
+ * Bulk-export audit-log events as CSV or NDJSON — the "bulk export" sensitive
50
+ * read the audit doc itself names. Pages past the per-call row clamp
51
+ * (`queryAuditEvents`'s `MAX_LIMIT`) up to `maxRows`, scoped in SQL to the
52
+ * caller's identity exactly like `list-audit-events`. Read-only; never
53
+ * exposes other tenants' rows.
54
+ */
55
+ export default defineAction({
56
+ description: "Export audit-log events as a CSV or NDJSON document for offline/compliance pulls (up to maxRows, default 5000, hard cap 10000). Use this instead of hand-paging list-audit-events when you need a bulk download of the trail; use list-audit-events instead for browsing recent activity or answering 'what changed'.",
57
+ schema: z.object({
58
+ targetType: z
59
+ .string()
60
+ .optional()
61
+ .describe("Filter to one resource type, e.g. 'recording'."),
62
+ targetId: z
63
+ .string()
64
+ .optional()
65
+ .describe("Filter to one resource id (pair with targetType)."),
66
+ actorKind: z
67
+ .enum(["agent", "human", "system"])
68
+ .optional()
69
+ .describe("Filter to changes made by the agent, a human, or the system."),
70
+ actorEmail: z.string().optional().describe("Filter to one actor's email."),
71
+ status: z
72
+ .enum(["success", "error", "denied"])
73
+ .optional()
74
+ .describe("Filter by outcome."),
75
+ threadId: z.string().optional().describe("Filter to one agent thread."),
76
+ turnId: z
77
+ .string()
78
+ .optional()
79
+ .describe("Filter to one agent turn (a single agent response)."),
80
+ action: z.string().optional().describe("Filter to one action name."),
81
+ sinceMs: z
82
+ .number()
83
+ .optional()
84
+ .describe("Only events at or after this Unix epoch (ms)."),
85
+ format: z
86
+ .enum(["csv", "ndjson"])
87
+ .default("csv")
88
+ .describe("Export format — CSV with a header row, or one JSON event per line."),
89
+ maxRows: z
90
+ .number()
91
+ .optional()
92
+ .describe("Max rows to export (default 5000, hard cap 10000)."),
93
+ }),
94
+ http: { method: "GET" },
95
+ audit: {
96
+ // Read-only actions are skipped by default — this is exactly the
97
+ // "bulk export" sensitive read the framework's own audit doc calls out.
98
+ onRead: true,
99
+ summary: (args) => `Bulk export of audit events (${args.format ?? "csv"})`,
100
+ },
101
+ run: async (args, ctx) => {
102
+ const scope = { userEmail: ctx?.userEmail, orgId: ctx?.orgId ?? null };
103
+ const cap = Math.min(Math.max(1, Math.floor(args.maxRows ?? DEFAULT_MAX_ROWS)), HARD_CAP_ROWS);
104
+ const filters = {
105
+ ...(args.targetType ? { targetType: args.targetType } : {}),
106
+ ...(args.targetId ? { targetId: args.targetId } : {}),
107
+ ...(args.actorKind ? { actorKind: args.actorKind } : {}),
108
+ ...(args.actorEmail ? { actorEmail: args.actorEmail } : {}),
109
+ ...(args.status ? { status: args.status } : {}),
110
+ ...(args.threadId ? { threadId: args.threadId } : {}),
111
+ ...(args.turnId ? { turnId: args.turnId } : {}),
112
+ ...(args.action ? { action: args.action } : {}),
113
+ ...(typeof args.sinceMs === "number" ? { sinceMs: args.sinceMs } : {}),
114
+ };
115
+ const events = [];
116
+ let offset = 0;
117
+ while (events.length < cap) {
118
+ const pageLimit = Math.min(MAX_LIMIT, cap - events.length);
119
+ const page = await queryAuditEvents(scope, {
120
+ ...filters,
121
+ limit: pageLimit,
122
+ offset,
123
+ });
124
+ events.push(...page);
125
+ offset += page.length;
126
+ if (page.length < pageLimit)
127
+ break; // exhausted — no more matching rows
128
+ }
129
+ // We stopped because we hit the cap, not because we ran out of rows —
130
+ // probe one more row to know whether the export was actually truncated.
131
+ let truncated = false;
132
+ if (events.length >= cap) {
133
+ const probe = await queryAuditEvents(scope, {
134
+ ...filters,
135
+ limit: 1,
136
+ offset,
137
+ });
138
+ truncated = probe.length > 0;
139
+ }
140
+ const content = args.format === "ndjson" ? toNdjson(events) : toCsv(events);
141
+ return { content, rowCount: events.length, truncated, format: args.format };
142
+ },
143
+ });
144
+ //# sourceMappingURL=export-audit-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-audit-events.js","sourceRoot":"","sources":["../../../src/audit/actions/export-audit-events.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { MAX_LIMIT, queryAuditEvents } from \"../store.js\";\nimport type { AuditEvent } from \"../types.js\";\n\nconst DEFAULT_MAX_ROWS = 5000;\nconst HARD_CAP_ROWS = 10000;\n\n// Deterministic column order for CSV — mirrors the store's list projection\n// (`LIST_COLUMNS`), which deliberately excludes `input` so a bulk export\n// never streams every event's (redacted) request body at once. Future\n// columns added to the audit store must be reflected here too.\nconst CSV_COLUMNS: Array<[key: keyof AuditEvent, header: string]> = [\n [\"id\", \"id\"],\n [\"createdAt\", \"created_at\"],\n [\"action\", \"action\"],\n [\"caller\", \"caller\"],\n [\"actorKind\", \"actor_kind\"],\n [\"actorEmail\", \"actor_email\"],\n [\"orgId\", \"org_id\"],\n [\"threadId\", \"thread_id\"],\n [\"turnId\", \"turn_id\"],\n [\"targetType\", \"target_type\"],\n [\"targetId\", \"target_id\"],\n [\"status\", \"status\"],\n [\"summary\", \"summary\"],\n [\"errorCode\", \"error_code\"],\n [\"ownerEmail\", \"owner_email\"],\n [\"visibility\", \"visibility\"],\n];\n\n/** Hand-rolled CSV field escaper — quotes a field when it contains a comma,\n * quote, or newline, doubling any embedded quotes. No dependency needed for\n * ~10 lines of RFC 4180 escaping. */\nfunction csvField(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n const raw = String(value);\n if (/[\",\\n\\r]/.test(raw)) {\n return `\"${raw.replace(/\"/g, '\"\"')}\"`;\n }\n return raw;\n}\n\nfunction toCsv(events: AuditEvent[]): string {\n const header = CSV_COLUMNS.map(([, label]) => label).join(\",\");\n const rows = events.map((event) =>\n CSV_COLUMNS.map(([key]) => csvField(event[key])).join(\",\"),\n );\n return [header, ...rows].join(\"\\n\");\n}\n\nfunction toNdjson(events: AuditEvent[]): string {\n return events.map((event) => JSON.stringify(event)).join(\"\\n\");\n}\n\n/**\n * Bulk-export audit-log events as CSV or NDJSON — the \"bulk export\" sensitive\n * read the audit doc itself names. Pages past the per-call row clamp\n * (`queryAuditEvents`'s `MAX_LIMIT`) up to `maxRows`, scoped in SQL to the\n * caller's identity exactly like `list-audit-events`. Read-only; never\n * exposes other tenants' rows.\n */\nexport default defineAction({\n description:\n \"Export audit-log events as a CSV or NDJSON document for offline/compliance pulls (up to maxRows, default 5000, hard cap 10000). Use this instead of hand-paging list-audit-events when you need a bulk download of the trail; use list-audit-events instead for browsing recent activity or answering 'what changed'.\",\n schema: z.object({\n targetType: z\n .string()\n .optional()\n .describe(\"Filter to one resource type, e.g. 'recording'.\"),\n targetId: z\n .string()\n .optional()\n .describe(\"Filter to one resource id (pair with targetType).\"),\n actorKind: z\n .enum([\"agent\", \"human\", \"system\"])\n .optional()\n .describe(\"Filter to changes made by the agent, a human, or the system.\"),\n actorEmail: z.string().optional().describe(\"Filter to one actor's email.\"),\n status: z\n .enum([\"success\", \"error\", \"denied\"])\n .optional()\n .describe(\"Filter by outcome.\"),\n threadId: z.string().optional().describe(\"Filter to one agent thread.\"),\n turnId: z\n .string()\n .optional()\n .describe(\"Filter to one agent turn (a single agent response).\"),\n action: z.string().optional().describe(\"Filter to one action name.\"),\n sinceMs: z\n .number()\n .optional()\n .describe(\"Only events at or after this Unix epoch (ms).\"),\n format: z\n .enum([\"csv\", \"ndjson\"])\n .default(\"csv\")\n .describe(\n \"Export format — CSV with a header row, or one JSON event per line.\",\n ),\n maxRows: z\n .number()\n .optional()\n .describe(\"Max rows to export (default 5000, hard cap 10000).\"),\n }),\n http: { method: \"GET\" },\n audit: {\n // Read-only actions are skipped by default — this is exactly the\n // \"bulk export\" sensitive read the framework's own audit doc calls out.\n onRead: true,\n summary: (args) =>\n `Bulk export of audit events (${(args as { format?: string }).format ?? \"csv\"})`,\n },\n run: async (args, ctx) => {\n const scope = { userEmail: ctx?.userEmail, orgId: ctx?.orgId ?? null };\n const cap = Math.min(\n Math.max(1, Math.floor(args.maxRows ?? DEFAULT_MAX_ROWS)),\n HARD_CAP_ROWS,\n );\n\n const filters = {\n ...(args.targetType ? { targetType: args.targetType } : {}),\n ...(args.targetId ? { targetId: args.targetId } : {}),\n ...(args.actorKind ? { actorKind: args.actorKind } : {}),\n ...(args.actorEmail ? { actorEmail: args.actorEmail } : {}),\n ...(args.status ? { status: args.status } : {}),\n ...(args.threadId ? { threadId: args.threadId } : {}),\n ...(args.turnId ? { turnId: args.turnId } : {}),\n ...(args.action ? { action: args.action } : {}),\n ...(typeof args.sinceMs === \"number\" ? { sinceMs: args.sinceMs } : {}),\n };\n\n const events: AuditEvent[] = [];\n let offset = 0;\n while (events.length < cap) {\n const pageLimit = Math.min(MAX_LIMIT, cap - events.length);\n const page = await queryAuditEvents(scope, {\n ...filters,\n limit: pageLimit,\n offset,\n });\n events.push(...page);\n offset += page.length;\n if (page.length < pageLimit) break; // exhausted — no more matching rows\n }\n\n // We stopped because we hit the cap, not because we ran out of rows —\n // probe one more row to know whether the export was actually truncated.\n let truncated = false;\n if (events.length >= cap) {\n const probe = await queryAuditEvents(scope, {\n ...filters,\n limit: 1,\n offset,\n });\n truncated = probe.length > 0;\n }\n\n const content = args.format === \"ndjson\" ? toNdjson(events) : toCsv(events);\n return { content, rowCount: events.length, truncated, format: args.format };\n },\n});\n"]}
@@ -5,6 +5,7 @@ export interface AuditReadScope {
5
5
  userEmail?: string;
6
6
  orgId?: string | null;
7
7
  }
8
+ export declare const MAX_LIMIT = 500;
8
9
  export declare function queryAuditEvents(scope: AuditReadScope, filters?: AuditQueryFilters): Promise<AuditEvent[]>;
9
10
  export declare function getAuditEventById(id: string, scope: AuditReadScope): Promise<AuditEvent | null>;
10
11
  /** Purge audit rows older than `cutoffMs`. Returns the deleted row count. */
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/audit/store.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAIpB,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqHvD;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAyCvE;AAkCD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AA2CD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,UAAU,EAAE,CAAC,CA0CvB;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAW5B;AAED,6EAA6E;AAC7E,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,gFAAgF;AAChF,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/audit/store.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAIpB,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqHvD;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAyCvE;AAkCD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAkCD,eAAO,MAAM,SAAS,MAAM,CAAC;AAW7B,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,UAAU,EAAE,CAAC,CA6CvB;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAW5B;AAED,6EAA6E;AAC7E,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,gFAAgF;AAChF,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
@@ -208,7 +208,9 @@ function scopeClause(scope) {
208
208
  return { sql: "1=0", args };
209
209
  return { sql: `(${clauses.join(" OR ")})`, args };
210
210
  }
211
- const MAX_LIMIT = 500;
211
+ // Exported so callers that must page past a single call (e.g.
212
+ // `export-audit-events`) can mirror the clamp instead of guessing it.
213
+ export const MAX_LIMIT = 500;
212
214
  const DEFAULT_LIMIT = 100;
213
215
  // Columns returned by the list surface — deliberately EXCLUDES `input` so a
214
216
  // timeline query never streams every event's (redacted) request body in bulk.
@@ -254,12 +256,15 @@ export async function queryAuditEvents(scope, filters = {}) {
254
256
  push("created_at >= ?", Math.floor(filters.sinceMs));
255
257
  }
256
258
  const limit = Math.min(Math.max(1, Math.floor(filters.limit ?? DEFAULT_LIMIT)), MAX_LIMIT);
259
+ // 0-based, default-compatible: existing callers that never pass `offset`
260
+ // keep selecting from the top of the ordered result set.
261
+ const offset = Math.max(0, Math.floor(filters.offset ?? 0));
257
262
  const result = await client.execute({
258
263
  sql: `SELECT ${LIST_COLUMNS} FROM agent_audit_log
259
264
  WHERE ${where.join(" AND ")}
260
265
  ORDER BY created_at DESC
261
- LIMIT ?`,
262
- args: [...args, limit],
266
+ LIMIT ? OFFSET ?`,
267
+ args: [...args, limit, offset],
263
268
  });
264
269
  return (result.rows ?? []).map(mapRow);
265
270
  }
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/audit/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SQL persistence for the framework audit log.\n *\n * Follows the same raw-SQL, provider-agnostic pattern as observability/store.ts\n * and usage/store.ts — framework tables use `getDbExec()` + `intType()` rather\n * than Drizzle ORM (which is for template-level schemas). One append-only table\n * `agent_audit_log`; reads are scoped to the caller's identity in SQL (no\n * shares table — audit rows are never individually shared).\n */\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport {\n ensureColumnExists,\n ensureTableExists,\n ensureIndexExists,\n} from \"../db/ddl-guard.js\";\nimport type {\n AuditEvent,\n AuditQueryFilters,\n AuditVisibility,\n} from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\nexport async function ensureAuditTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS agent_audit_log (\n id TEXT PRIMARY KEY,\n created_at ${intType()} NOT NULL,\n action TEXT NOT NULL,\n caller TEXT NOT NULL,\n actor_kind TEXT NOT NULL,\n actor_email TEXT,\n org_id TEXT,\n thread_id TEXT,\n turn_id TEXT,\n target_type TEXT,\n target_id TEXT,\n status TEXT NOT NULL DEFAULT 'success',\n summary TEXT,\n input TEXT,\n error_code TEXT,\n owner_email TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n ,run_id TEXT\n ,task_id TEXT\n ,parent_task_id TEXT\n ,source_kind TEXT\n ,source_platform TEXT\n ,source_id TEXT\n ,source_url TEXT\n ,network_protocol TEXT\n ,network_id TEXT\n ,network_peer TEXT\n )\n `;\n const lineageColumns = [\n \"run_id\",\n \"task_id\",\n \"parent_task_id\",\n \"source_kind\",\n \"source_platform\",\n \"source_id\",\n \"source_url\",\n \"network_protocol\",\n \"network_id\",\n \"network_peer\",\n ];\n\n if (isPostgres()) {\n // PG-guard: probe information_schema / pg_indexes before issuing DDL to\n // avoid ACCESS EXCLUSIVE lock contention in fresh background-worker processes.\n await ensureTableExists(\"agent_audit_log\", createSql);\n for (const column of lineageColumns) {\n await ensureColumnExists(\n \"agent_audit_log\",\n column,\n `ALTER TABLE agent_audit_log ADD COLUMN IF NOT EXISTS ${column} TEXT`,\n );\n }\n await ensureIndexExists(\n \"idx_audit_owner\",\n `CREATE INDEX IF NOT EXISTS idx_audit_owner ON agent_audit_log (owner_email, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_org\",\n `CREATE INDEX IF NOT EXISTS idx_audit_org ON agent_audit_log (org_id, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_target\",\n `CREATE INDEX IF NOT EXISTS idx_audit_target ON agent_audit_log (target_type, target_id, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_turn\",\n `CREATE INDEX IF NOT EXISTS idx_audit_turn ON agent_audit_log (turn_id)`,\n );\n await ensureIndexExists(\n \"idx_audit_actor\",\n `CREATE INDEX IF NOT EXISTS idx_audit_actor ON agent_audit_log (actor_email, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_created\",\n `CREATE INDEX IF NOT EXISTS idx_audit_created ON agent_audit_log (created_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n for (const column of lineageColumns) {\n try {\n await client.execute(\n `ALTER TABLE agent_audit_log ADD COLUMN ${column} TEXT`,\n );\n } catch {}\n }\n const indexes = [\n `CREATE INDEX IF NOT EXISTS idx_audit_owner ON agent_audit_log (owner_email, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_org ON agent_audit_log (org_id, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_target ON agent_audit_log (target_type, target_id, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_turn ON agent_audit_log (turn_id)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_actor ON agent_audit_log (actor_email, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_created ON agent_audit_log (created_at)`,\n ];\n for (const sql of indexes) {\n try {\n await client.execute(sql);\n } catch {\n // Index creation is best-effort; a racing boot may have created it.\n }\n }\n })().catch((err) => {\n // Allow a later call to retry if the first init failed.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nexport async function insertAuditEvent(event: AuditEvent): Promise<void> {\n await ensureAuditTables();\n const client = getDbExec();\n await client.execute({\n sql: `INSERT INTO agent_audit_log\n (id, created_at, action, caller, actor_kind, actor_email, org_id,\n thread_id, turn_id, target_type, target_id, status, summary, input,\n error_code, owner_email, visibility, run_id, task_id, parent_task_id,\n source_kind, source_platform, source_id, source_url, network_protocol,\n network_id, network_peer)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n event.id,\n event.createdAt,\n event.action,\n event.caller,\n event.actorKind,\n event.actorEmail,\n event.orgId,\n event.threadId,\n event.turnId,\n event.targetType,\n event.targetId,\n event.status,\n event.summary,\n event.input,\n event.errorCode,\n event.ownerEmail,\n event.visibility,\n event.runId ?? null,\n event.taskId ?? null,\n event.parentTaskId ?? null,\n event.sourceKind ?? null,\n event.sourcePlatform ?? null,\n event.sourceId ?? null,\n event.sourceUrl ?? null,\n event.networkProtocol ?? null,\n event.networkId ?? null,\n event.networkPeer ?? null,\n ],\n });\n}\n\nfunction mapRow(row: any): AuditEvent {\n return {\n id: String(row.id),\n createdAt: Number(row.created_at),\n action: String(row.action),\n caller: String(row.caller),\n actorKind: row.actor_kind,\n actorEmail: row.actor_email ?? null,\n orgId: row.org_id ?? null,\n threadId: row.thread_id ?? null,\n turnId: row.turn_id ?? null,\n targetType: row.target_type ?? null,\n targetId: row.target_id ?? null,\n status: row.status,\n summary: row.summary ?? null,\n input: row.input ?? null,\n errorCode: row.error_code ?? null,\n ownerEmail: row.owner_email ?? null,\n visibility: (row.visibility ?? \"private\") as AuditVisibility,\n runId: row.run_id ?? null,\n taskId: row.task_id ?? null,\n parentTaskId: row.parent_task_id ?? null,\n sourceKind: row.source_kind ?? null,\n sourcePlatform: row.source_platform ?? null,\n sourceId: row.source_id ?? null,\n sourceUrl: row.source_url ?? null,\n networkProtocol: row.network_protocol ?? null,\n networkId: row.network_id ?? null,\n networkPeer: row.network_peer ?? null,\n };\n}\n\nexport interface AuditReadScope {\n userEmail?: string;\n orgId?: string | null;\n}\n\n/**\n * Build the access-scoping WHERE fragment + args. A caller sees audit rows they\n * own, plus org-visible rows in their org. With no identity, nothing matches —\n * the audit log never leaks cross-tenant. Mirrors the core ownership clause of\n * `accessFilter` (minus shares, which audit rows don't have).\n */\nfunction scopeClause(scope: AuditReadScope): { sql: string; args: any[] } {\n const clauses: string[] = [];\n const args: any[] = [];\n if (scope.userEmail) {\n if (scope.orgId) {\n // Constrain the owner's rows to the active org — plus legacy/solo rows\n // that predate org-scoping (org_id IS NULL) — mirroring sharing's\n // `ownerScopeFilter`, so switching orgs doesn't surface another org's\n // trail.\n clauses.push(\"(owner_email = ? AND (org_id = ? OR org_id IS NULL))\");\n args.push(scope.userEmail, scope.orgId);\n } else {\n clauses.push(\"owner_email = ?\");\n args.push(scope.userEmail);\n }\n }\n if (scope.orgId) {\n clauses.push(\"(visibility = 'org' AND org_id = ?)\");\n args.push(scope.orgId);\n }\n if (clauses.length === 0) return { sql: \"1=0\", args };\n return { sql: `(${clauses.join(\" OR \")})`, args };\n}\n\nconst MAX_LIMIT = 500;\nconst DEFAULT_LIMIT = 100;\n\n// Columns returned by the list surface — deliberately EXCLUDES `input` so a\n// timeline query never streams every event's (redacted) request body in bulk.\n// Fetch the full payload one event at a time via `getAuditEventById`.\nconst LIST_COLUMNS =\n \"id, created_at, action, caller, actor_kind, actor_email, org_id, \" +\n \"thread_id, turn_id, target_type, target_id, status, summary, \" +\n \"error_code, owner_email, visibility\";\n\nexport async function queryAuditEvents(\n scope: AuditReadScope,\n filters: AuditQueryFilters = {},\n): Promise<AuditEvent[]> {\n await ensureAuditTables();\n if (!scope.userEmail && !scope.orgId) return [];\n const client = getDbExec();\n\n const scoped = scopeClause(scope);\n const where: string[] = [scoped.sql];\n const args: any[] = [...scoped.args];\n\n const push = (clause: string, value: any) => {\n where.push(clause);\n args.push(value);\n };\n if (filters.targetType) push(\"target_type = ?\", filters.targetType);\n if (filters.targetId) push(\"target_id = ?\", filters.targetId);\n if (filters.actorKind) push(\"actor_kind = ?\", filters.actorKind);\n if (filters.actorEmail) push(\"actor_email = ?\", filters.actorEmail);\n if (filters.status) push(\"status = ?\", filters.status);\n if (filters.threadId) push(\"thread_id = ?\", filters.threadId);\n if (filters.turnId) push(\"turn_id = ?\", filters.turnId);\n if (filters.action) push(\"action = ?\", filters.action);\n if (filters.taskId) push(\"task_id = ?\", filters.taskId);\n if (filters.runId) push(\"run_id = ?\", filters.runId);\n if (filters.sourcePlatform)\n push(\"source_platform = ?\", filters.sourcePlatform);\n if (typeof filters.sinceMs === \"number\") {\n push(\"created_at >= ?\", Math.floor(filters.sinceMs));\n }\n\n const limit = Math.min(\n Math.max(1, Math.floor(filters.limit ?? DEFAULT_LIMIT)),\n MAX_LIMIT,\n );\n\n const result = await client.execute({\n sql: `SELECT ${LIST_COLUMNS} FROM agent_audit_log\n WHERE ${where.join(\" AND \")}\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [...args, limit],\n });\n return (result.rows ?? []).map(mapRow);\n}\n\nexport async function getAuditEventById(\n id: string,\n scope: AuditReadScope,\n): Promise<AuditEvent | null> {\n await ensureAuditTables();\n if (!scope.userEmail && !scope.orgId) return null;\n const client = getDbExec();\n const scoped = scopeClause(scope);\n const result = await client.execute({\n sql: `SELECT * FROM agent_audit_log WHERE id = ? AND ${scoped.sql} LIMIT 1`,\n args: [id, ...scoped.args],\n });\n const row = (result.rows ?? [])[0];\n return row ? mapRow(row) : null;\n}\n\n/** Purge audit rows older than `cutoffMs`. Returns the deleted row count. */\nexport async function deleteOldAuditEvents(cutoffMs: number): Promise<number> {\n await ensureAuditTables();\n const client = getDbExec();\n const result = await client.execute({\n sql: `DELETE FROM agent_audit_log WHERE created_at < ?`,\n args: [Math.floor(cutoffMs)],\n });\n return Number(result.rowsAffected ?? 0);\n}\n\n/** Test-only: reset the cached init promise so a fresh DB re-creates tables. */\nexport function __resetAuditInitForTests(): void {\n _initPromise = undefined;\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/audit/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SQL persistence for the framework audit log.\n *\n * Follows the same raw-SQL, provider-agnostic pattern as observability/store.ts\n * and usage/store.ts — framework tables use `getDbExec()` + `intType()` rather\n * than Drizzle ORM (which is for template-level schemas). One append-only table\n * `agent_audit_log`; reads are scoped to the caller's identity in SQL (no\n * shares table — audit rows are never individually shared).\n */\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport {\n ensureColumnExists,\n ensureTableExists,\n ensureIndexExists,\n} from \"../db/ddl-guard.js\";\nimport type {\n AuditEvent,\n AuditQueryFilters,\n AuditVisibility,\n} from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\nexport async function ensureAuditTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS agent_audit_log (\n id TEXT PRIMARY KEY,\n created_at ${intType()} NOT NULL,\n action TEXT NOT NULL,\n caller TEXT NOT NULL,\n actor_kind TEXT NOT NULL,\n actor_email TEXT,\n org_id TEXT,\n thread_id TEXT,\n turn_id TEXT,\n target_type TEXT,\n target_id TEXT,\n status TEXT NOT NULL DEFAULT 'success',\n summary TEXT,\n input TEXT,\n error_code TEXT,\n owner_email TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n ,run_id TEXT\n ,task_id TEXT\n ,parent_task_id TEXT\n ,source_kind TEXT\n ,source_platform TEXT\n ,source_id TEXT\n ,source_url TEXT\n ,network_protocol TEXT\n ,network_id TEXT\n ,network_peer TEXT\n )\n `;\n const lineageColumns = [\n \"run_id\",\n \"task_id\",\n \"parent_task_id\",\n \"source_kind\",\n \"source_platform\",\n \"source_id\",\n \"source_url\",\n \"network_protocol\",\n \"network_id\",\n \"network_peer\",\n ];\n\n if (isPostgres()) {\n // PG-guard: probe information_schema / pg_indexes before issuing DDL to\n // avoid ACCESS EXCLUSIVE lock contention in fresh background-worker processes.\n await ensureTableExists(\"agent_audit_log\", createSql);\n for (const column of lineageColumns) {\n await ensureColumnExists(\n \"agent_audit_log\",\n column,\n `ALTER TABLE agent_audit_log ADD COLUMN IF NOT EXISTS ${column} TEXT`,\n );\n }\n await ensureIndexExists(\n \"idx_audit_owner\",\n `CREATE INDEX IF NOT EXISTS idx_audit_owner ON agent_audit_log (owner_email, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_org\",\n `CREATE INDEX IF NOT EXISTS idx_audit_org ON agent_audit_log (org_id, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_target\",\n `CREATE INDEX IF NOT EXISTS idx_audit_target ON agent_audit_log (target_type, target_id, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_turn\",\n `CREATE INDEX IF NOT EXISTS idx_audit_turn ON agent_audit_log (turn_id)`,\n );\n await ensureIndexExists(\n \"idx_audit_actor\",\n `CREATE INDEX IF NOT EXISTS idx_audit_actor ON agent_audit_log (actor_email, created_at)`,\n );\n await ensureIndexExists(\n \"idx_audit_created\",\n `CREATE INDEX IF NOT EXISTS idx_audit_created ON agent_audit_log (created_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n for (const column of lineageColumns) {\n try {\n await client.execute(\n `ALTER TABLE agent_audit_log ADD COLUMN ${column} TEXT`,\n );\n } catch {}\n }\n const indexes = [\n `CREATE INDEX IF NOT EXISTS idx_audit_owner ON agent_audit_log (owner_email, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_org ON agent_audit_log (org_id, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_target ON agent_audit_log (target_type, target_id, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_turn ON agent_audit_log (turn_id)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_actor ON agent_audit_log (actor_email, created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_audit_created ON agent_audit_log (created_at)`,\n ];\n for (const sql of indexes) {\n try {\n await client.execute(sql);\n } catch {\n // Index creation is best-effort; a racing boot may have created it.\n }\n }\n })().catch((err) => {\n // Allow a later call to retry if the first init failed.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nexport async function insertAuditEvent(event: AuditEvent): Promise<void> {\n await ensureAuditTables();\n const client = getDbExec();\n await client.execute({\n sql: `INSERT INTO agent_audit_log\n (id, created_at, action, caller, actor_kind, actor_email, org_id,\n thread_id, turn_id, target_type, target_id, status, summary, input,\n error_code, owner_email, visibility, run_id, task_id, parent_task_id,\n source_kind, source_platform, source_id, source_url, network_protocol,\n network_id, network_peer)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n event.id,\n event.createdAt,\n event.action,\n event.caller,\n event.actorKind,\n event.actorEmail,\n event.orgId,\n event.threadId,\n event.turnId,\n event.targetType,\n event.targetId,\n event.status,\n event.summary,\n event.input,\n event.errorCode,\n event.ownerEmail,\n event.visibility,\n event.runId ?? null,\n event.taskId ?? null,\n event.parentTaskId ?? null,\n event.sourceKind ?? null,\n event.sourcePlatform ?? null,\n event.sourceId ?? null,\n event.sourceUrl ?? null,\n event.networkProtocol ?? null,\n event.networkId ?? null,\n event.networkPeer ?? null,\n ],\n });\n}\n\nfunction mapRow(row: any): AuditEvent {\n return {\n id: String(row.id),\n createdAt: Number(row.created_at),\n action: String(row.action),\n caller: String(row.caller),\n actorKind: row.actor_kind,\n actorEmail: row.actor_email ?? null,\n orgId: row.org_id ?? null,\n threadId: row.thread_id ?? null,\n turnId: row.turn_id ?? null,\n targetType: row.target_type ?? null,\n targetId: row.target_id ?? null,\n status: row.status,\n summary: row.summary ?? null,\n input: row.input ?? null,\n errorCode: row.error_code ?? null,\n ownerEmail: row.owner_email ?? null,\n visibility: (row.visibility ?? \"private\") as AuditVisibility,\n runId: row.run_id ?? null,\n taskId: row.task_id ?? null,\n parentTaskId: row.parent_task_id ?? null,\n sourceKind: row.source_kind ?? null,\n sourcePlatform: row.source_platform ?? null,\n sourceId: row.source_id ?? null,\n sourceUrl: row.source_url ?? null,\n networkProtocol: row.network_protocol ?? null,\n networkId: row.network_id ?? null,\n networkPeer: row.network_peer ?? null,\n };\n}\n\nexport interface AuditReadScope {\n userEmail?: string;\n orgId?: string | null;\n}\n\n/**\n * Build the access-scoping WHERE fragment + args. A caller sees audit rows they\n * own, plus org-visible rows in their org. With no identity, nothing matches —\n * the audit log never leaks cross-tenant. Mirrors the core ownership clause of\n * `accessFilter` (minus shares, which audit rows don't have).\n */\nfunction scopeClause(scope: AuditReadScope): { sql: string; args: any[] } {\n const clauses: string[] = [];\n const args: any[] = [];\n if (scope.userEmail) {\n if (scope.orgId) {\n // Constrain the owner's rows to the active org — plus legacy/solo rows\n // that predate org-scoping (org_id IS NULL) — mirroring sharing's\n // `ownerScopeFilter`, so switching orgs doesn't surface another org's\n // trail.\n clauses.push(\"(owner_email = ? AND (org_id = ? OR org_id IS NULL))\");\n args.push(scope.userEmail, scope.orgId);\n } else {\n clauses.push(\"owner_email = ?\");\n args.push(scope.userEmail);\n }\n }\n if (scope.orgId) {\n clauses.push(\"(visibility = 'org' AND org_id = ?)\");\n args.push(scope.orgId);\n }\n if (clauses.length === 0) return { sql: \"1=0\", args };\n return { sql: `(${clauses.join(\" OR \")})`, args };\n}\n\n// Exported so callers that must page past a single call (e.g.\n// `export-audit-events`) can mirror the clamp instead of guessing it.\nexport const MAX_LIMIT = 500;\nconst DEFAULT_LIMIT = 100;\n\n// Columns returned by the list surface — deliberately EXCLUDES `input` so a\n// timeline query never streams every event's (redacted) request body in bulk.\n// Fetch the full payload one event at a time via `getAuditEventById`.\nconst LIST_COLUMNS =\n \"id, created_at, action, caller, actor_kind, actor_email, org_id, \" +\n \"thread_id, turn_id, target_type, target_id, status, summary, \" +\n \"error_code, owner_email, visibility\";\n\nexport async function queryAuditEvents(\n scope: AuditReadScope,\n filters: AuditQueryFilters = {},\n): Promise<AuditEvent[]> {\n await ensureAuditTables();\n if (!scope.userEmail && !scope.orgId) return [];\n const client = getDbExec();\n\n const scoped = scopeClause(scope);\n const where: string[] = [scoped.sql];\n const args: any[] = [...scoped.args];\n\n const push = (clause: string, value: any) => {\n where.push(clause);\n args.push(value);\n };\n if (filters.targetType) push(\"target_type = ?\", filters.targetType);\n if (filters.targetId) push(\"target_id = ?\", filters.targetId);\n if (filters.actorKind) push(\"actor_kind = ?\", filters.actorKind);\n if (filters.actorEmail) push(\"actor_email = ?\", filters.actorEmail);\n if (filters.status) push(\"status = ?\", filters.status);\n if (filters.threadId) push(\"thread_id = ?\", filters.threadId);\n if (filters.turnId) push(\"turn_id = ?\", filters.turnId);\n if (filters.action) push(\"action = ?\", filters.action);\n if (filters.taskId) push(\"task_id = ?\", filters.taskId);\n if (filters.runId) push(\"run_id = ?\", filters.runId);\n if (filters.sourcePlatform)\n push(\"source_platform = ?\", filters.sourcePlatform);\n if (typeof filters.sinceMs === \"number\") {\n push(\"created_at >= ?\", Math.floor(filters.sinceMs));\n }\n\n const limit = Math.min(\n Math.max(1, Math.floor(filters.limit ?? DEFAULT_LIMIT)),\n MAX_LIMIT,\n );\n // 0-based, default-compatible: existing callers that never pass `offset`\n // keep selecting from the top of the ordered result set.\n const offset = Math.max(0, Math.floor(filters.offset ?? 0));\n\n const result = await client.execute({\n sql: `SELECT ${LIST_COLUMNS} FROM agent_audit_log\n WHERE ${where.join(\" AND \")}\n ORDER BY created_at DESC\n LIMIT ? OFFSET ?`,\n args: [...args, limit, offset],\n });\n return (result.rows ?? []).map(mapRow);\n}\n\nexport async function getAuditEventById(\n id: string,\n scope: AuditReadScope,\n): Promise<AuditEvent | null> {\n await ensureAuditTables();\n if (!scope.userEmail && !scope.orgId) return null;\n const client = getDbExec();\n const scoped = scopeClause(scope);\n const result = await client.execute({\n sql: `SELECT * FROM agent_audit_log WHERE id = ? AND ${scoped.sql} LIMIT 1`,\n args: [id, ...scoped.args],\n });\n const row = (result.rows ?? [])[0];\n return row ? mapRow(row) : null;\n}\n\n/** Purge audit rows older than `cutoffMs`. Returns the deleted row count. */\nexport async function deleteOldAuditEvents(cutoffMs: number): Promise<number> {\n await ensureAuditTables();\n const client = getDbExec();\n const result = await client.execute({\n sql: `DELETE FROM agent_audit_log WHERE created_at < ?`,\n args: [Math.floor(cutoffMs)],\n });\n return Number(result.rowsAffected ?? 0);\n}\n\n/** Test-only: reset the cached init promise so a fresh DB re-creates tables. */\nexport function __resetAuditInitForTests(): void {\n _initPromise = undefined;\n}\n"]}
@@ -123,5 +123,8 @@ export interface AuditQueryFilters {
123
123
  sourcePlatform?: string;
124
124
  sinceMs?: number;
125
125
  limit?: number;
126
+ /** Skip this many matching rows before applying `limit` (0-based). Used by
127
+ * `export-audit-events` to page past the per-call `MAX_LIMIT` clamp. */
128
+ offset?: number;
126
129
  }
127
130
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/audit/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,yCAAyC;AACzC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE3D;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qEAAqE;IACrE,MAAM,CAAC,EAAE,CACP,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,aAAa,KAChB,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,KAAK,MAAM,CAAC;CACvE;AAED,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,cAAc,CAAC;IAC1B,qEAAqE;IACrE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,oDAAoD;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sEAAsE;IACtE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/audit/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/audit/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG","sourcesContent":["/**\n * Types for the framework audit log.\n *\n * The audit log is a durable, complete, access-scoped, append-only record of\n * *who mutated what app data, when, from where, and — when it was the agent —\n * in which run*. It is deliberately distinct from observability (sampled\n * agent-run telemetry) and tracking (fire-and-forget product analytics): audit\n * rows are complete, locally queryable, and scoped to the data they describe.\n *\n * Capture happens automatically at the action-execution seam (`defineAction`):\n * every mutating action records an audit event after it runs. Read-only (GET /\n * `readOnly`) actions are skipped unless they opt in via `audit.onRead`.\n */\n\n/** Outcome of an audited action call. */\nexport type AuditStatus = \"success\" | \"error\" | \"denied\";\n\n/**\n * Who performed the mutation.\n * - `agent` — the in-app assistant / sub-agents / A2A (caller `\"tool\"`).\n * - `human` — a person via the UI, HTTP, CLI, or an external MCP client.\n * - `system` — no resolved identity (background jobs, schedules).\n */\nexport type AuditActorKind = \"agent\" | \"human\" | \"system\";\n\nexport type AuditVisibility = \"private\" | \"org\" | \"public\";\n\n/**\n * The resource an action mutated, plus the ownership used to scope who can\n * read the resulting audit event. Returned by an action's `audit.target`.\n *\n * `ownerEmail` / `orgId` / `visibility` default to the actor's identity when\n * omitted, which is correct for the common case where a user mutates their own\n * data. Provide them explicitly when a user edits a resource owned by someone\n * else so the *owner* sees the change in their audit trail.\n */\nexport interface AuditTarget {\n type?: string;\n id?: string;\n ownerEmail?: string | null;\n orgId?: string | null;\n visibility?: AuditVisibility;\n}\n\n/** Metadata about the call, passed to `audit.target` / `audit.summary`. */\nexport interface AuditCallMeta {\n status: AuditStatus;\n caller: string;\n userEmail?: string;\n orgId?: string | null;\n}\n\n/**\n * Per-action audit configuration, set on `defineAction({ audit })`.\n *\n * Audit is **default-on for mutating actions** — you only need this object to\n * *tune* capture (declare the target, customize the summary) or to opt a\n * read-only action in / a noisy action out.\n */\nexport interface ActionAuditConfig {\n /**\n * Force audit on (`true`) or off (`false`). Overrides every default,\n * including the read-only skip and the high-frequency denylist. When\n * omitted, mutating actions are audited and read-only actions are not.\n */\n enabled?: boolean;\n /**\n * Audit this action even though it is read-only (GET). Use for sensitive\n * reads worth recording — secret access, bulk export. Ignored when\n * `enabled` is set explicitly.\n */\n onRead?: boolean;\n /** Capture the (redacted) call arguments. Default `true`. */\n recordInputs?: boolean;\n /** Resolve the mutated resource + its ownership for scoped reads. */\n target?: (\n args: any,\n result: unknown,\n meta: AuditCallMeta,\n ) => AuditTarget | null | undefined;\n /** Build a short human-readable summary line for the event. */\n summary?: (args: any, result: unknown, meta: AuditCallMeta) => string;\n}\n\n/** A persisted audit event. */\nexport interface AuditEvent {\n id: string;\n createdAt: number;\n /** Action name (the registry key, e.g. `delete-recording`). */\n action: string;\n /** Invocation surface: tool | frontend | http | cli | mcp | a2a. */\n caller: string;\n actorKind: AuditActorKind;\n /** Human on whose behalf it ran — populated even for agent calls. */\n actorEmail: string | null;\n orgId: string | null;\n /** Agent conversation thread, when caller is the agent loop. */\n threadId: string | null;\n /** Agent turn that produced the mutation — the unit of one agent response. */\n turnId: string | null;\n targetType: string | null;\n targetId: string | null;\n status: AuditStatus;\n summary: string | null;\n /** Redacted JSON of the call arguments, or null. */\n input: string | null;\n errorCode: string | null;\n /** Denormalized owner used to scope reads (defaults to the actor). */\n ownerEmail: string | null;\n visibility: AuditVisibility;\n runId?: string | null;\n taskId?: string | null;\n parentTaskId?: string | null;\n sourceKind?: string | null;\n sourcePlatform?: string | null;\n sourceId?: string | null;\n sourceUrl?: string | null;\n networkProtocol?: string | null;\n networkId?: string | null;\n networkPeer?: string | null;\n}\n\n/** Filters for `queryAuditEvents`. */\nexport interface AuditQueryFilters {\n targetType?: string;\n targetId?: string;\n actorKind?: AuditActorKind;\n actorEmail?: string;\n status?: AuditStatus;\n threadId?: string;\n turnId?: string;\n action?: string;\n taskId?: string;\n runId?: string;\n sourcePlatform?: string;\n sinceMs?: number;\n limit?: number;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/audit/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG","sourcesContent":["/**\n * Types for the framework audit log.\n *\n * The audit log is a durable, complete, access-scoped, append-only record of\n * *who mutated what app data, when, from where, and — when it was the agent —\n * in which run*. It is deliberately distinct from observability (sampled\n * agent-run telemetry) and tracking (fire-and-forget product analytics): audit\n * rows are complete, locally queryable, and scoped to the data they describe.\n *\n * Capture happens automatically at the action-execution seam (`defineAction`):\n * every mutating action records an audit event after it runs. Read-only (GET /\n * `readOnly`) actions are skipped unless they opt in via `audit.onRead`.\n */\n\n/** Outcome of an audited action call. */\nexport type AuditStatus = \"success\" | \"error\" | \"denied\";\n\n/**\n * Who performed the mutation.\n * - `agent` — the in-app assistant / sub-agents / A2A (caller `\"tool\"`).\n * - `human` — a person via the UI, HTTP, CLI, or an external MCP client.\n * - `system` — no resolved identity (background jobs, schedules).\n */\nexport type AuditActorKind = \"agent\" | \"human\" | \"system\";\n\nexport type AuditVisibility = \"private\" | \"org\" | \"public\";\n\n/**\n * The resource an action mutated, plus the ownership used to scope who can\n * read the resulting audit event. Returned by an action's `audit.target`.\n *\n * `ownerEmail` / `orgId` / `visibility` default to the actor's identity when\n * omitted, which is correct for the common case where a user mutates their own\n * data. Provide them explicitly when a user edits a resource owned by someone\n * else so the *owner* sees the change in their audit trail.\n */\nexport interface AuditTarget {\n type?: string;\n id?: string;\n ownerEmail?: string | null;\n orgId?: string | null;\n visibility?: AuditVisibility;\n}\n\n/** Metadata about the call, passed to `audit.target` / `audit.summary`. */\nexport interface AuditCallMeta {\n status: AuditStatus;\n caller: string;\n userEmail?: string;\n orgId?: string | null;\n}\n\n/**\n * Per-action audit configuration, set on `defineAction({ audit })`.\n *\n * Audit is **default-on for mutating actions** — you only need this object to\n * *tune* capture (declare the target, customize the summary) or to opt a\n * read-only action in / a noisy action out.\n */\nexport interface ActionAuditConfig {\n /**\n * Force audit on (`true`) or off (`false`). Overrides every default,\n * including the read-only skip and the high-frequency denylist. When\n * omitted, mutating actions are audited and read-only actions are not.\n */\n enabled?: boolean;\n /**\n * Audit this action even though it is read-only (GET). Use for sensitive\n * reads worth recording — secret access, bulk export. Ignored when\n * `enabled` is set explicitly.\n */\n onRead?: boolean;\n /** Capture the (redacted) call arguments. Default `true`. */\n recordInputs?: boolean;\n /** Resolve the mutated resource + its ownership for scoped reads. */\n target?: (\n args: any,\n result: unknown,\n meta: AuditCallMeta,\n ) => AuditTarget | null | undefined;\n /** Build a short human-readable summary line for the event. */\n summary?: (args: any, result: unknown, meta: AuditCallMeta) => string;\n}\n\n/** A persisted audit event. */\nexport interface AuditEvent {\n id: string;\n createdAt: number;\n /** Action name (the registry key, e.g. `delete-recording`). */\n action: string;\n /** Invocation surface: tool | frontend | http | cli | mcp | a2a. */\n caller: string;\n actorKind: AuditActorKind;\n /** Human on whose behalf it ran — populated even for agent calls. */\n actorEmail: string | null;\n orgId: string | null;\n /** Agent conversation thread, when caller is the agent loop. */\n threadId: string | null;\n /** Agent turn that produced the mutation — the unit of one agent response. */\n turnId: string | null;\n targetType: string | null;\n targetId: string | null;\n status: AuditStatus;\n summary: string | null;\n /** Redacted JSON of the call arguments, or null. */\n input: string | null;\n errorCode: string | null;\n /** Denormalized owner used to scope reads (defaults to the actor). */\n ownerEmail: string | null;\n visibility: AuditVisibility;\n runId?: string | null;\n taskId?: string | null;\n parentTaskId?: string | null;\n sourceKind?: string | null;\n sourcePlatform?: string | null;\n sourceId?: string | null;\n sourceUrl?: string | null;\n networkProtocol?: string | null;\n networkId?: string | null;\n networkPeer?: string | null;\n}\n\n/** Filters for `queryAuditEvents`. */\nexport interface AuditQueryFilters {\n targetType?: string;\n targetId?: string;\n actorKind?: AuditActorKind;\n actorEmail?: string;\n status?: AuditStatus;\n threadId?: string;\n turnId?: string;\n action?: string;\n taskId?: string;\n runId?: string;\n sourcePlatform?: string;\n sinceMs?: number;\n limit?: number;\n /** Skip this many matching rows before applying `limit` (0-based). Used by\n * `export-audit-events` to page past the per-call `MAX_LIMIT` clamp. */\n offset?: number;\n}\n"]}
@@ -0,0 +1,83 @@
1
+ export type GuardName = "no-drizzle-push" | "no-unscoped-credentials" | "no-unscoped-queries" | "no-env-credentials" | "db-tool-scoping" | "no-env-mutation" | "no-localhost-fallback";
2
+ export declare const ALL_GUARD_NAMES: GuardName[];
3
+ export interface DoctorConfig {
4
+ disabledGuards: string[];
5
+ dbToolScopingDenylist: Record<string, string>;
6
+ failOnBuild: boolean;
7
+ }
8
+ export interface DoctorFinding {
9
+ guard: string;
10
+ file: string;
11
+ line: number;
12
+ message: string;
13
+ }
14
+ export interface DoctorReport {
15
+ ok: boolean;
16
+ findings: DoctorFinding[];
17
+ guardsRun: string[];
18
+ }
19
+ /**
20
+ * Reads the optional `"doctor"` key from `<root>/agent-native.json`. All
21
+ * fields are optional with sane empty defaults — an app needs zero config
22
+ * to run `agent-native doctor` with every v1 guard enabled.
23
+ */
24
+ export declare function readDoctorConfig(root: string): DoctorConfig;
25
+ export interface RunDoctorScanOptions {
26
+ root: string;
27
+ /** Restrict to these guard names. When omitted, runs every guard not
28
+ * listed in `agent-native.json`'s `doctor.disabledGuards`. Unknown names
29
+ * are silently ignored here — the CLI layer (`runDoctor`) validates
30
+ * `--only` and reports a usage error before calling this. */
31
+ only?: string[];
32
+ }
33
+ /** Pure scan orchestrator: runs the selected guards against `root` and
34
+ * returns a flat report. No I/O beyond reading `agent-native.json` and the
35
+ * app source tree — no printing, no process.exit. */
36
+ export declare function runDoctorScan(options: RunDoctorScanOptions): DoctorReport;
37
+ /** Pure escalation rule shared by the CLI (`--strict`) and the `build`
38
+ * pre-step (`--strict` / `agent-native.json` `doctor.failOnBuild`). Doctor
39
+ * findings never fail anything on their own — only `strict` or
40
+ * `failOnBuild` turn findings into a hard failure. */
41
+ export declare function shouldFailBuild(hasFindings: boolean, opts: {
42
+ strict?: boolean;
43
+ failOnBuild?: boolean;
44
+ }): boolean;
45
+ export interface DoctorIo {
46
+ log: (message: string) => void;
47
+ err: (message: string) => void;
48
+ }
49
+ export interface DoctorCliOptions {
50
+ json?: boolean;
51
+ cwd?: string;
52
+ only?: string[];
53
+ strict?: boolean;
54
+ help?: boolean;
55
+ fix?: boolean;
56
+ }
57
+ export declare function parseDoctorArgs(argv: string[]): DoctorCliOptions;
58
+ export declare function printDoctorHelp(io?: Pick<DoctorIo, "log">): void;
59
+ /** `agent-native doctor` CLI entrypoint. Returns the process exit code —
60
+ * callers are responsible for calling `process.exit(code)`. */
61
+ export declare function runDoctor(argv: string[], io?: DoctorIo): Promise<number>;
62
+ export interface DoctorBuildHookOptions {
63
+ cwd: string;
64
+ /** Set when the caller passed `agent-native build --strict`. */
65
+ strict?: boolean;
66
+ }
67
+ export interface DoctorBuildHookResult {
68
+ /** False only when findings are present AND (`strict` was requested OR
69
+ * `agent-native.json`'s `doctor.failOnBuild` is true). */
70
+ ok: boolean;
71
+ report: DoctorReport;
72
+ }
73
+ /**
74
+ * `agent-native build`'s doctor pre-step. Always runs every enabled guard
75
+ * and always prints findings (as warnings) to `io.err` — never silent.
76
+ * Never causes the build to fail unless `strict` was passed or
77
+ * `agent-native.json` sets `doctor.failOnBuild: true` (see report 005,
78
+ * "Where it runs" — the v1 doctor has zero field mileage against arbitrary
79
+ * app layouts, so shipping fail-by-default would risk breaking a first
80
+ * deploy on a false positive).
81
+ */
82
+ export declare function runDoctorBuildHook(options: DoctorBuildHookOptions, io?: DoctorIo): Promise<DoctorBuildHookResult>;
83
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAoCA,MAAM,MAAM,SAAS,GACjB,iBAAiB,GACjB,yBAAyB,GACzB,qBAAqB,GACrB,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,uBAAuB,CAAC;AAE5B,eAAO,MAAM,eAAe,EAAE,SAAS,EAQtC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,WAAW,EAAE,OAAO,CAAC;CACtB;AAQD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CA6B3D;AA4BD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb;;;iEAG6D;IAC7D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;qDAEqD;AACrD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,YAAY,CA4BzE;AAED;;;sDAGsD;AACtD,wBAAgB,eAAe,CAC7B,WAAW,EAAE,OAAO,EACpB,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAChD,OAAO,CAET;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAsBD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAuBhE;AASD,wBAAgB,eAAe,CAAC,EAAE,GAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAa,GAAG,IAAI,CAwB3E;AAED;+DAC+D;AAC/D,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,QAAoB,GACvB,OAAO,CAAC,MAAM,CAAC,CAmDjB;AAED,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC;8DAC0D;IAC1D,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,sBAAsB,EAC/B,EAAE,GAAE,QAAoB,GACvB,OAAO,CAAC,qBAAqB,CAAC,CAyBhC"}