primitive-admin 1.1.0-alpha.9 → 1.1.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 (591) hide show
  1. package/README.md +523 -109
  2. package/assets/skill/skills/primitive-platform/SKILL.md +289 -0
  3. package/dist/bin/primitive.d.ts +2 -0
  4. package/dist/bin/primitive.js +372 -21
  5. package/dist/bin/primitive.js.map +1 -1
  6. package/dist/src/commands/admins.d.ts +2 -0
  7. package/dist/src/commands/admins.js +136 -30
  8. package/dist/src/commands/admins.js.map +1 -1
  9. package/dist/src/commands/analytics.d.ts +2 -0
  10. package/dist/src/commands/analytics.js +713 -55
  11. package/dist/src/commands/analytics.js.map +1 -1
  12. package/dist/src/commands/apps.d.ts +2 -0
  13. package/dist/src/commands/apps.js +65 -100
  14. package/dist/src/commands/apps.js.map +1 -1
  15. package/dist/src/commands/auth-sessions.d.ts +7 -0
  16. package/dist/src/commands/auth-sessions.js +144 -0
  17. package/dist/src/commands/auth-sessions.js.map +1 -0
  18. package/dist/src/commands/auth.d.ts +2 -0
  19. package/dist/src/commands/auth.js +238 -108
  20. package/dist/src/commands/auth.js.map +1 -1
  21. package/dist/src/commands/blob-buckets.d.ts +2 -0
  22. package/dist/src/commands/blob-buckets.js +331 -0
  23. package/dist/src/commands/blob-buckets.js.map +1 -0
  24. package/dist/src/commands/catalog.d.ts +2 -0
  25. package/dist/src/commands/catalog.js +63 -48
  26. package/dist/src/commands/catalog.js.map +1 -1
  27. package/dist/src/commands/collection-type-configs.d.ts +2 -0
  28. package/dist/src/commands/collection-type-configs.js +85 -0
  29. package/dist/src/commands/collection-type-configs.js.map +1 -0
  30. package/dist/src/commands/collections.d.ts +2 -0
  31. package/dist/src/commands/collections.js +1282 -0
  32. package/dist/src/commands/collections.js.map +1 -0
  33. package/dist/src/commands/comparisons.d.ts +2 -0
  34. package/dist/src/commands/comparisons.js +6 -6
  35. package/dist/src/commands/comparisons.js.map +1 -1
  36. package/dist/src/commands/config.d.ts +46 -0
  37. package/dist/src/commands/config.js +465 -0
  38. package/dist/src/commands/config.js.map +1 -0
  39. package/dist/src/commands/connections.d.ts +2 -0
  40. package/dist/src/commands/connections.js +99 -0
  41. package/dist/src/commands/connections.js.map +1 -0
  42. package/dist/src/commands/cron-triggers.d.ts +2 -0
  43. package/dist/src/commands/cron-triggers.js +266 -0
  44. package/dist/src/commands/cron-triggers.js.map +1 -0
  45. package/dist/src/commands/database-type-configs.d.ts +2 -0
  46. package/dist/src/commands/database-type-configs.js +164 -0
  47. package/dist/src/commands/database-type-configs.js.map +1 -0
  48. package/dist/src/commands/database-types.d.ts +2 -0
  49. package/dist/src/commands/database-types.js +471 -0
  50. package/dist/src/commands/database-types.js.map +1 -0
  51. package/dist/src/commands/databases.d.ts +65 -0
  52. package/dist/src/commands/databases.js +1887 -243
  53. package/dist/src/commands/databases.js.map +1 -1
  54. package/dist/src/commands/documents.d.ts +60 -0
  55. package/dist/src/commands/documents.js +2888 -22
  56. package/dist/src/commands/documents.js.map +1 -1
  57. package/dist/src/commands/email-templates.d.ts +2 -0
  58. package/dist/src/commands/email-templates.js +175 -0
  59. package/dist/src/commands/email-templates.js.map +1 -0
  60. package/dist/src/commands/env.d.ts +23 -0
  61. package/dist/src/commands/env.js +395 -0
  62. package/dist/src/commands/env.js.map +1 -0
  63. package/dist/src/commands/feature-flags.d.ts +14 -0
  64. package/dist/src/commands/feature-flags.js +117 -0
  65. package/dist/src/commands/feature-flags.js.map +1 -0
  66. package/dist/src/commands/functions.d.ts +20 -0
  67. package/dist/src/commands/functions.js +1630 -0
  68. package/dist/src/commands/functions.js.map +1 -0
  69. package/dist/src/commands/group-type-configs.d.ts +2 -0
  70. package/dist/src/commands/group-type-configs.js +87 -0
  71. package/dist/src/commands/group-type-configs.js.map +1 -0
  72. package/dist/src/commands/groups.d.ts +2 -0
  73. package/dist/src/commands/groups.js +65 -113
  74. package/dist/src/commands/groups.js.map +1 -1
  75. package/dist/src/commands/guides.d.ts +223 -0
  76. package/dist/src/commands/guides.js +627 -69
  77. package/dist/src/commands/guides.js.map +1 -1
  78. package/dist/src/commands/init.d.ts +37 -0
  79. package/dist/src/commands/init.js +1693 -208
  80. package/dist/src/commands/init.js.map +1 -1
  81. package/dist/src/commands/integrations.d.ts +2 -0
  82. package/dist/src/commands/integrations.js +428 -187
  83. package/dist/src/commands/integrations.js.map +1 -1
  84. package/dist/src/commands/llm.d.ts +2 -0
  85. package/dist/src/commands/llm.js +4 -2
  86. package/dist/src/commands/llm.js.map +1 -1
  87. package/dist/src/commands/locks.d.ts +8 -0
  88. package/dist/src/commands/locks.js +175 -0
  89. package/dist/src/commands/locks.js.map +1 -0
  90. package/dist/src/commands/metadata-category-configs.d.ts +12 -0
  91. package/dist/src/commands/metadata-category-configs.js +113 -0
  92. package/dist/src/commands/metadata-category-configs.js.map +1 -0
  93. package/dist/src/commands/metadata.d.ts +2 -0
  94. package/dist/src/commands/metadata.js +288 -0
  95. package/dist/src/commands/metadata.js.map +1 -0
  96. package/dist/src/commands/prompts.d.ts +2 -0
  97. package/dist/src/commands/prompts.js +322 -634
  98. package/dist/src/commands/prompts.js.map +1 -1
  99. package/dist/src/commands/rule-sets.d.ts +3 -0
  100. package/dist/src/commands/rule-sets.js +139 -148
  101. package/dist/src/commands/rule-sets.js.map +1 -1
  102. package/dist/src/commands/scripts.d.ts +30 -0
  103. package/dist/src/commands/scripts.js +688 -0
  104. package/dist/src/commands/scripts.js.map +1 -0
  105. package/dist/src/commands/secrets.d.ts +2 -0
  106. package/dist/src/commands/secrets.js +109 -0
  107. package/dist/src/commands/secrets.js.map +1 -0
  108. package/dist/src/commands/sessions.d.ts +2 -0
  109. package/dist/src/commands/sessions.js +76 -0
  110. package/dist/src/commands/sessions.js.map +1 -0
  111. package/dist/src/commands/skill.d.ts +2 -0
  112. package/dist/src/commands/skill.js +29 -0
  113. package/dist/src/commands/skill.js.map +1 -0
  114. package/dist/src/commands/sync-app-settings.d.ts +158 -0
  115. package/dist/src/commands/sync-app-settings.js +328 -0
  116. package/dist/src/commands/sync-app-settings.js.map +1 -0
  117. package/dist/src/commands/sync.d.ts +2670 -0
  118. package/dist/src/commands/sync.js +17144 -834
  119. package/dist/src/commands/sync.js.map +1 -1
  120. package/dist/src/commands/tokens.d.ts +2 -0
  121. package/dist/src/commands/tokens.js +132 -22
  122. package/dist/src/commands/tokens.js.map +1 -1
  123. package/dist/src/commands/users.d.ts +2 -0
  124. package/dist/src/commands/users.js +542 -24
  125. package/dist/src/commands/users.js.map +1 -1
  126. package/dist/src/commands/vars.d.ts +8 -0
  127. package/dist/src/commands/vars.js +97 -0
  128. package/dist/src/commands/vars.js.map +1 -0
  129. package/dist/src/commands/waitlist.d.ts +2 -0
  130. package/dist/src/commands/waitlist.js +12 -11
  131. package/dist/src/commands/waitlist.js.map +1 -1
  132. package/dist/src/commands/webhooks.d.ts +31 -0
  133. package/dist/src/commands/webhooks.js +633 -0
  134. package/dist/src/commands/webhooks.js.map +1 -0
  135. package/dist/src/commands/workflows.d.ts +88 -0
  136. package/dist/src/commands/workflows.js +1568 -742
  137. package/dist/src/commands/workflows.js.map +1 -1
  138. package/dist/src/lib/access-rule-display.d.ts +21 -0
  139. package/dist/src/lib/access-rule-display.js +34 -0
  140. package/dist/src/lib/access-rule-display.js.map +1 -0
  141. package/dist/src/lib/api-client.d.ts +2550 -0
  142. package/dist/src/lib/api-client.js +2503 -160
  143. package/dist/src/lib/api-client.js.map +1 -1
  144. package/dist/src/lib/app-settings-descriptor.d.ts +263 -0
  145. package/dist/src/lib/app-settings-descriptor.js +583 -0
  146. package/dist/src/lib/app-settings-descriptor.js.map +1 -0
  147. package/dist/src/lib/auth-flow.d.ts +8 -0
  148. package/dist/src/lib/batch.d.ts +26 -0
  149. package/dist/src/lib/batch.js +32 -0
  150. package/dist/src/lib/batch.js.map +1 -0
  151. package/dist/src/lib/block-layout.d.ts +160 -0
  152. package/dist/src/lib/block-layout.js +451 -0
  153. package/dist/src/lib/block-layout.js.map +1 -0
  154. package/dist/src/lib/block-selector.d.ts +58 -0
  155. package/dist/src/lib/block-selector.js +92 -0
  156. package/dist/src/lib/block-selector.js.map +1 -0
  157. package/dist/src/lib/canonical-json.d.ts +12 -0
  158. package/dist/src/lib/canonical-json.js +35 -0
  159. package/dist/src/lib/canonical-json.js.map +1 -0
  160. package/dist/src/lib/channel.d.ts +30 -0
  161. package/dist/src/lib/channel.js +68 -0
  162. package/dist/src/lib/channel.js.map +1 -0
  163. package/dist/src/lib/cli-manifest.d.ts +68 -0
  164. package/dist/src/lib/cli-manifest.js +71 -0
  165. package/dist/src/lib/cli-manifest.js.map +1 -0
  166. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +101 -0
  167. package/dist/src/lib/codegen-shared/generatedFiles.js +191 -0
  168. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -0
  169. package/dist/src/lib/codegen-shared/prettierStable.d.ts +262 -0
  170. package/dist/src/lib/codegen-shared/prettierStable.js +610 -0
  171. package/dist/src/lib/codegen-shared/prettierStable.js.map +1 -0
  172. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +38 -0
  173. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +46 -0
  174. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -0
  175. package/dist/src/lib/collection-export.d.ts +184 -0
  176. package/dist/src/lib/collection-export.js +252 -0
  177. package/dist/src/lib/collection-export.js.map +1 -0
  178. package/dist/src/lib/config-json-field.d.ts +28 -0
  179. package/dist/src/lib/config-json-field.js +56 -0
  180. package/dist/src/lib/config-json-field.js.map +1 -0
  181. package/dist/src/lib/config-object-descriptor.d.ts +127 -0
  182. package/dist/src/lib/config-object-descriptor.js +740 -0
  183. package/dist/src/lib/config-object-descriptor.js.map +1 -0
  184. package/dist/src/lib/config-payload.d.ts +92 -0
  185. package/dist/src/lib/config-payload.js +161 -0
  186. package/dist/src/lib/config-payload.js.map +1 -0
  187. package/dist/src/lib/config-surface.d.ts +141 -0
  188. package/dist/src/lib/config-surface.js +368 -0
  189. package/dist/src/lib/config-surface.js.map +1 -0
  190. package/dist/src/lib/config-toml.d.ts +10 -0
  191. package/dist/src/lib/config-toml.js +42 -0
  192. package/dist/src/lib/config-toml.js.map +1 -0
  193. package/dist/src/lib/config.d.ts +71 -0
  194. package/dist/src/lib/config.js +71 -68
  195. package/dist/src/lib/config.js.map +1 -1
  196. package/dist/src/lib/confirm-prompt.d.ts +83 -0
  197. package/dist/src/lib/confirm-prompt.js +110 -0
  198. package/dist/src/lib/confirm-prompt.js.map +1 -0
  199. package/dist/src/lib/constants.d.ts +11 -0
  200. package/dist/src/lib/constants.js +12 -0
  201. package/dist/src/lib/constants.js.map +1 -0
  202. package/dist/src/lib/crash-handlers.d.ts +20 -0
  203. package/dist/src/lib/crash-handlers.js +49 -0
  204. package/dist/src/lib/crash-handlers.js.map +1 -0
  205. package/dist/src/lib/credentials-store.d.ts +104 -0
  206. package/dist/src/lib/credentials-store.js +336 -0
  207. package/dist/src/lib/credentials-store.js.map +1 -0
  208. package/dist/src/lib/csv.d.ts +47 -0
  209. package/dist/src/lib/csv.js +172 -0
  210. package/dist/src/lib/csv.js.map +1 -0
  211. package/dist/src/lib/data-input.d.ts +23 -0
  212. package/dist/src/lib/data-input.js +50 -0
  213. package/dist/src/lib/data-input.js.map +1 -0
  214. package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
  215. package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
  216. package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
  217. package/dist/src/lib/db-codegen/dbGenerator.d.ts +67 -0
  218. package/dist/src/lib/db-codegen/dbGenerator.js +170 -0
  219. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
  220. package/dist/src/lib/db-codegen/dbNaming.d.ts +87 -0
  221. package/dist/src/lib/db-codegen/dbNaming.js +180 -0
  222. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
  223. package/dist/src/lib/db-codegen/dbTemplates.d.ts +272 -0
  224. package/dist/src/lib/db-codegen/dbTemplates.js +480 -0
  225. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
  226. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +73 -0
  227. package/dist/src/lib/db-codegen/dbTsTypes.js +139 -0
  228. package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
  229. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
  230. package/dist/src/lib/db-codegen/dbTypeIR.js +525 -0
  231. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
  232. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +112 -0
  233. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +211 -0
  234. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
  235. package/dist/src/lib/deprecation.d.ts +22 -0
  236. package/dist/src/lib/deprecation.js +43 -0
  237. package/dist/src/lib/deprecation.js.map +1 -0
  238. package/dist/src/lib/document-export-permissions.d.ts +30 -0
  239. package/dist/src/lib/document-export-permissions.js +54 -0
  240. package/dist/src/lib/document-export-permissions.js.map +1 -0
  241. package/dist/src/lib/document-ingest-artifact.d.ts +120 -0
  242. package/dist/src/lib/document-ingest-artifact.js +505 -0
  243. package/dist/src/lib/document-ingest-artifact.js.map +1 -0
  244. package/dist/src/lib/document-ingest-input.d.ts +51 -0
  245. package/dist/src/lib/document-ingest-input.js +132 -0
  246. package/dist/src/lib/document-ingest-input.js.map +1 -0
  247. package/dist/src/lib/document-ingest-rows.d.ts +137 -0
  248. package/dist/src/lib/document-ingest-rows.js +181 -0
  249. package/dist/src/lib/document-ingest-rows.js.map +1 -0
  250. package/dist/src/lib/document-ingest.d.ts +101 -0
  251. package/dist/src/lib/document-ingest.js +384 -0
  252. package/dist/src/lib/document-ingest.js.map +1 -0
  253. package/dist/src/lib/env-resolver-core.d.ts +258 -0
  254. package/dist/src/lib/env-resolver-core.js +447 -0
  255. package/dist/src/lib/env-resolver-core.js.map +1 -0
  256. package/dist/src/lib/env-resolver.d.ts +99 -0
  257. package/dist/src/lib/env-resolver.js +153 -0
  258. package/dist/src/lib/env-resolver.js.map +1 -0
  259. package/dist/src/lib/fetch.d.ts +5 -0
  260. package/dist/src/lib/function-bundle.d.ts +147 -0
  261. package/dist/src/lib/function-bundle.js +341 -0
  262. package/dist/src/lib/function-bundle.js.map +1 -0
  263. package/dist/src/lib/function-collect.d.ts +123 -0
  264. package/dist/src/lib/function-collect.js +610 -0
  265. package/dist/src/lib/function-collect.js.map +1 -0
  266. package/dist/src/lib/function-db-types.d.ts +202 -0
  267. package/dist/src/lib/function-db-types.js +870 -0
  268. package/dist/src/lib/function-db-types.js.map +1 -0
  269. package/dist/src/lib/function-document-types.d.ts +144 -0
  270. package/dist/src/lib/function-document-types.js +370 -0
  271. package/dist/src/lib/function-document-types.js.map +1 -0
  272. package/dist/src/lib/function-grants-preflight.d.ts +64 -0
  273. package/dist/src/lib/function-grants-preflight.js +105 -0
  274. package/dist/src/lib/function-grants-preflight.js.map +1 -0
  275. package/dist/src/lib/function-log-lines.d.ts +76 -0
  276. package/dist/src/lib/function-log-lines.js +160 -0
  277. package/dist/src/lib/function-log-lines.js.map +1 -0
  278. package/dist/src/lib/function-log-row.d.ts +29 -0
  279. package/dist/src/lib/function-log-row.js +73 -0
  280. package/dist/src/lib/function-log-row.js.map +1 -0
  281. package/dist/src/lib/function-log-tail.d.ts +132 -0
  282. package/dist/src/lib/function-log-tail.js +262 -0
  283. package/dist/src/lib/function-log-tail.js.map +1 -0
  284. package/dist/src/lib/function-run.d.ts +289 -0
  285. package/dist/src/lib/function-run.js +389 -0
  286. package/dist/src/lib/function-run.js.map +1 -0
  287. package/dist/src/lib/function-schema-codegen.d.ts +143 -0
  288. package/dist/src/lib/function-schema-codegen.js +420 -0
  289. package/dist/src/lib/function-schema-codegen.js.map +1 -0
  290. package/dist/src/lib/function-sync.d.ts +459 -0
  291. package/dist/src/lib/function-sync.js +1258 -0
  292. package/dist/src/lib/function-sync.js.map +1 -0
  293. package/dist/src/lib/function-trigger-listing.d.ts +27 -0
  294. package/dist/src/lib/function-trigger-listing.js +70 -0
  295. package/dist/src/lib/function-trigger-listing.js.map +1 -0
  296. package/dist/src/lib/function-typecheck.d.ts +86 -0
  297. package/dist/src/lib/function-typecheck.js +370 -0
  298. package/dist/src/lib/function-typecheck.js.map +1 -0
  299. package/dist/src/lib/function-versions.d.ts +122 -0
  300. package/dist/src/lib/function-versions.js +182 -0
  301. package/dist/src/lib/function-versions.js.map +1 -0
  302. package/dist/src/lib/generated-allowlist.d.ts +28 -0
  303. package/dist/src/lib/generated-allowlist.js +281 -0
  304. package/dist/src/lib/generated-allowlist.js.map +1 -0
  305. package/dist/src/lib/generated-config-surfaces.d.ts +2936 -0
  306. package/dist/src/lib/generated-config-surfaces.js +10569 -0
  307. package/dist/src/lib/generated-config-surfaces.js.map +1 -0
  308. package/dist/src/lib/generated-sdk-types.d.ts +12 -0
  309. package/dist/src/lib/generated-sdk-types.js +13 -0
  310. package/dist/src/lib/generated-sdk-types.js.map +1 -0
  311. package/dist/src/lib/generated-template-lint.d.ts +212 -0
  312. package/dist/src/lib/generated-template-lint.js +624 -0
  313. package/dist/src/lib/generated-template-lint.js.map +1 -0
  314. package/dist/src/lib/init-adopt.d.ts +16 -0
  315. package/dist/src/lib/init-adopt.js +34 -0
  316. package/dist/src/lib/init-adopt.js.map +1 -0
  317. package/dist/src/lib/init-assets.d.ts +39 -0
  318. package/dist/src/lib/init-assets.js +97 -0
  319. package/dist/src/lib/init-assets.js.map +1 -0
  320. package/dist/src/lib/init-client-platforms.d.ts +14 -0
  321. package/dist/src/lib/init-client-platforms.js +71 -0
  322. package/dist/src/lib/init-client-platforms.js.map +1 -0
  323. package/dist/src/lib/init-config.d.ts +98 -0
  324. package/dist/src/lib/init-config.js +186 -0
  325. package/dist/src/lib/init-config.js.map +1 -0
  326. package/dist/src/lib/init-email-redirect-uris.d.ts +37 -0
  327. package/dist/src/lib/init-email-redirect-uris.js +46 -0
  328. package/dist/src/lib/init-email-redirect-uris.js.map +1 -0
  329. package/dist/src/lib/init-ios-links.d.ts +91 -0
  330. package/dist/src/lib/init-ios-links.js +219 -0
  331. package/dist/src/lib/init-ios-links.js.map +1 -0
  332. package/dist/src/lib/init-plan.d.ts +80 -0
  333. package/dist/src/lib/init-plan.js +95 -0
  334. package/dist/src/lib/init-plan.js.map +1 -0
  335. package/dist/src/lib/init-production-env.d.ts +48 -0
  336. package/dist/src/lib/init-production-env.js +59 -0
  337. package/dist/src/lib/init-production-env.js.map +1 -0
  338. package/dist/src/lib/init-schema.d.ts +74 -0
  339. package/dist/src/lib/init-schema.js +358 -0
  340. package/dist/src/lib/init-schema.js.map +1 -0
  341. package/dist/src/lib/init-xcode.d.ts +34 -0
  342. package/dist/src/lib/init-xcode.js +138 -0
  343. package/dist/src/lib/init-xcode.js.map +1 -0
  344. package/dist/src/lib/integration-request-config.d.ts +30 -0
  345. package/dist/src/lib/integration-request-config.js +145 -0
  346. package/dist/src/lib/integration-request-config.js.map +1 -0
  347. package/dist/src/lib/integration-selector.d.ts +42 -0
  348. package/dist/src/lib/integration-selector.js +46 -0
  349. package/dist/src/lib/integration-selector.js.map +1 -0
  350. package/dist/src/lib/ios-app-id.d.ts +34 -0
  351. package/dist/src/lib/ios-app-id.js +69 -0
  352. package/dist/src/lib/ios-app-id.js.map +1 -0
  353. package/dist/src/lib/list-options.d.ts +68 -0
  354. package/dist/src/lib/list-options.js +89 -0
  355. package/dist/src/lib/list-options.js.map +1 -0
  356. package/dist/src/lib/local-state.d.ts +55 -0
  357. package/dist/src/lib/local-state.js +167 -0
  358. package/dist/src/lib/local-state.js.map +1 -0
  359. package/dist/src/lib/local-test-cases.d.ts +63 -0
  360. package/dist/src/lib/local-test-cases.js +136 -0
  361. package/dist/src/lib/local-test-cases.js.map +1 -0
  362. package/dist/src/lib/log-inspection.d.ts +715 -0
  363. package/dist/src/lib/log-inspection.js +816 -0
  364. package/dist/src/lib/log-inspection.js.map +1 -0
  365. package/dist/src/lib/logout-admin-session.d.ts +33 -0
  366. package/dist/src/lib/logout-admin-session.js +70 -0
  367. package/dist/src/lib/logout-admin-session.js.map +1 -0
  368. package/dist/src/lib/migration-nag.d.ts +49 -0
  369. package/dist/src/lib/migration-nag.js +163 -0
  370. package/dist/src/lib/migration-nag.js.map +1 -0
  371. package/dist/src/lib/object-status-filter.d.ts +22 -0
  372. package/dist/src/lib/object-status-filter.js +45 -0
  373. package/dist/src/lib/object-status-filter.js.map +1 -0
  374. package/dist/src/lib/output.d.ts +124 -0
  375. package/dist/src/lib/output.js +219 -8
  376. package/dist/src/lib/output.js.map +1 -1
  377. package/dist/src/lib/package-manager.d.ts +140 -0
  378. package/dist/src/lib/package-manager.js +305 -0
  379. package/dist/src/lib/package-manager.js.map +1 -0
  380. package/dist/src/lib/paginate.d.ts +98 -0
  381. package/dist/src/lib/paginate.js +112 -0
  382. package/dist/src/lib/paginate.js.map +1 -0
  383. package/dist/src/lib/platform-owned.d.ts +63 -0
  384. package/dist/src/lib/platform-owned.js +85 -0
  385. package/dist/src/lib/platform-owned.js.map +1 -0
  386. package/dist/src/lib/project-config.d.ts +122 -0
  387. package/dist/src/lib/project-config.js +244 -0
  388. package/dist/src/lib/project-config.js.map +1 -0
  389. package/dist/src/lib/prompt-cost-format.d.ts +11 -0
  390. package/dist/src/lib/prompt-cost-format.js +41 -0
  391. package/dist/src/lib/prompt-cost-format.js.map +1 -0
  392. package/dist/src/lib/prompt-schema-codegen.d.ts +147 -0
  393. package/dist/src/lib/prompt-schema-codegen.js +462 -0
  394. package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
  395. package/dist/src/lib/query-operators.d.ts +43 -0
  396. package/dist/src/lib/query-operators.js +80 -0
  397. package/dist/src/lib/query-operators.js.map +1 -0
  398. package/dist/src/lib/record-filter.d.ts +18 -0
  399. package/dist/src/lib/record-filter.js +55 -0
  400. package/dist/src/lib/record-filter.js.map +1 -0
  401. package/dist/src/lib/refresh-admin-credentials.d.ts +73 -0
  402. package/dist/src/lib/refresh-admin-credentials.js +123 -0
  403. package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
  404. package/dist/src/lib/resolve-init-dev-port.d.ts +56 -0
  405. package/dist/src/lib/resolve-init-dev-port.js +55 -0
  406. package/dist/src/lib/resolve-init-dev-port.js.map +1 -0
  407. package/dist/src/lib/resolve-init-server.d.ts +64 -0
  408. package/dist/src/lib/resolve-init-server.js +77 -0
  409. package/dist/src/lib/resolve-init-server.js.map +1 -0
  410. package/dist/src/lib/resolve-owner.d.ts +19 -0
  411. package/dist/src/lib/resolve-owner.js +20 -0
  412. package/dist/src/lib/resolve-owner.js.map +1 -0
  413. package/dist/src/lib/resolve-platform.d.ts +74 -0
  414. package/dist/src/lib/resolve-platform.js +105 -0
  415. package/dist/src/lib/resolve-platform.js.map +1 -0
  416. package/dist/src/lib/run-status.d.ts +19 -0
  417. package/dist/src/lib/run-status.generated.d.ts +39 -0
  418. package/dist/src/lib/run-status.generated.js +66 -0
  419. package/dist/src/lib/run-status.generated.js.map +1 -0
  420. package/dist/src/lib/run-status.js +19 -0
  421. package/dist/src/lib/run-status.js.map +1 -0
  422. package/dist/src/lib/server-text-normalization.d.ts +51 -0
  423. package/dist/src/lib/server-text-normalization.js +90 -0
  424. package/dist/src/lib/server-text-normalization.js.map +1 -0
  425. package/dist/src/lib/server-url.d.ts +22 -0
  426. package/dist/src/lib/server-url.js +33 -0
  427. package/dist/src/lib/server-url.js.map +1 -0
  428. package/dist/src/lib/signing-secret-status.d.ts +81 -0
  429. package/dist/src/lib/signing-secret-status.js +116 -0
  430. package/dist/src/lib/signing-secret-status.js.map +1 -0
  431. package/dist/src/lib/skill-installer.d.ts +71 -0
  432. package/dist/src/lib/skill-installer.js +441 -0
  433. package/dist/src/lib/skill-installer.js.map +1 -0
  434. package/dist/src/lib/snapshot-audit-source.d.ts +45 -0
  435. package/dist/src/lib/snapshot-audit-source.js +58 -0
  436. package/dist/src/lib/snapshot-audit-source.js.map +1 -0
  437. package/dist/src/lib/snapshot-audit-store.d.ts +52 -0
  438. package/dist/src/lib/snapshot-audit-store.js +196 -0
  439. package/dist/src/lib/snapshot-audit-store.js.map +1 -0
  440. package/dist/src/lib/snapshot-audit.d.ts +207 -0
  441. package/dist/src/lib/snapshot-audit.js +431 -0
  442. package/dist/src/lib/snapshot-audit.js.map +1 -0
  443. package/dist/src/lib/snapshot-build-rows.d.ts +60 -0
  444. package/dist/src/lib/snapshot-build-rows.js +87 -0
  445. package/dist/src/lib/snapshot-build-rows.js.map +1 -0
  446. package/dist/src/lib/snapshot-build.d.ts +50 -0
  447. package/dist/src/lib/snapshot-build.js +111 -0
  448. package/dist/src/lib/snapshot-build.js.map +1 -0
  449. package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
  450. package/dist/src/lib/snapshot-manifest-layout.js +70 -0
  451. package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
  452. package/dist/src/lib/snapshots.d.ts +98 -0
  453. package/dist/src/lib/snapshots.js +294 -0
  454. package/dist/src/lib/snapshots.js.map +1 -0
  455. package/dist/src/lib/step-run-table.d.ts +43 -0
  456. package/dist/src/lib/step-run-table.js +129 -0
  457. package/dist/src/lib/step-run-table.js.map +1 -0
  458. package/dist/src/lib/storage-pending-retry.d.ts +26 -0
  459. package/dist/src/lib/storage-pending-retry.js +42 -0
  460. package/dist/src/lib/storage-pending-retry.js.map +1 -0
  461. package/dist/src/lib/swift-codegen/agentGenerator.d.ts +42 -0
  462. package/dist/src/lib/swift-codegen/agentGenerator.js +118 -0
  463. package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -0
  464. package/dist/src/lib/swift-codegen/banners.d.ts +24 -0
  465. package/dist/src/lib/swift-codegen/banners.js +25 -0
  466. package/dist/src/lib/swift-codegen/banners.js.map +1 -0
  467. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +113 -0
  468. package/dist/src/lib/swift-codegen/dbGenerator.js +926 -0
  469. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
  470. package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
  471. package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
  472. package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
  473. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +139 -0
  474. package/dist/src/lib/swift-codegen/functionGenerator.js +462 -0
  475. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -0
  476. package/dist/src/lib/swift-codegen/generator.d.ts +100 -0
  477. package/dist/src/lib/swift-codegen/generator.js +457 -0
  478. package/dist/src/lib/swift-codegen/generator.js.map +1 -0
  479. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +87 -0
  480. package/dist/src/lib/swift-codegen/schemaToSwift.js +661 -0
  481. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
  482. package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +94 -0
  483. package/dist/src/lib/swift-codegen/siblingSymbols.js +155 -0
  484. package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -0
  485. package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
  486. package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
  487. package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
  488. package/dist/src/lib/sync-dir-selector.d.ts +21 -0
  489. package/dist/src/lib/sync-dir-selector.js +30 -0
  490. package/dist/src/lib/sync-dir-selector.js.map +1 -0
  491. package/dist/src/lib/sync-paths.d.ts +128 -0
  492. package/dist/src/lib/sync-paths.js +195 -0
  493. package/dist/src/lib/sync-paths.js.map +1 -0
  494. package/dist/src/lib/sync-resource-types.d.ts +563 -0
  495. package/dist/src/lib/sync-resource-types.js +1073 -0
  496. package/dist/src/lib/sync-resource-types.js.map +1 -0
  497. package/dist/src/lib/sync-selectors.d.ts +138 -0
  498. package/dist/src/lib/sync-selectors.js +289 -0
  499. package/dist/src/lib/sync-selectors.js.map +1 -0
  500. package/dist/src/lib/template.d.ts +170 -0
  501. package/dist/src/lib/template.js +484 -68
  502. package/dist/src/lib/template.js.map +1 -1
  503. package/dist/src/lib/test-case-file-names.d.ts +40 -0
  504. package/dist/src/lib/test-case-file-names.js +91 -0
  505. package/dist/src/lib/test-case-file-names.js.map +1 -0
  506. package/dist/src/lib/test-case-keys.d.ts +29 -0
  507. package/dist/src/lib/test-case-keys.js +55 -0
  508. package/dist/src/lib/test-case-keys.js.map +1 -0
  509. package/dist/src/lib/test-case-variables.d.ts +29 -0
  510. package/dist/src/lib/test-case-variables.js +71 -0
  511. package/dist/src/lib/test-case-variables.js.map +1 -0
  512. package/dist/src/lib/token-inject.d.ts +56 -0
  513. package/dist/src/lib/token-inject.js +204 -0
  514. package/dist/src/lib/token-inject.js.map +1 -0
  515. package/dist/src/lib/toml-database-config.d.ts +123 -0
  516. package/dist/src/lib/toml-database-config.js +544 -0
  517. package/dist/src/lib/toml-database-config.js.map +1 -0
  518. package/dist/src/lib/toml-metadata-config.d.ts +151 -0
  519. package/dist/src/lib/toml-metadata-config.js +476 -0
  520. package/dist/src/lib/toml-metadata-config.js.map +1 -0
  521. package/dist/src/lib/toml-native-form.d.ts +46 -0
  522. package/dist/src/lib/toml-native-form.js +78 -0
  523. package/dist/src/lib/toml-native-form.js.map +1 -0
  524. package/dist/src/lib/toml-params-validator.d.ts +129 -0
  525. package/dist/src/lib/toml-params-validator.js +298 -0
  526. package/dist/src/lib/toml-params-validator.js.map +1 -0
  527. package/dist/src/lib/toml-scalar-edit.d.ts +43 -0
  528. package/dist/src/lib/toml-scalar-edit.js +283 -0
  529. package/dist/src/lib/toml-scalar-edit.js.map +1 -0
  530. package/dist/src/lib/user-selector.d.ts +24 -0
  531. package/dist/src/lib/user-selector.js +33 -0
  532. package/dist/src/lib/user-selector.js.map +1 -0
  533. package/dist/src/lib/version-check.d.ts +35 -0
  534. package/dist/src/lib/version-check.js +241 -0
  535. package/dist/src/lib/version-check.js.map +1 -0
  536. package/dist/src/lib/watch.d.ts +121 -0
  537. package/dist/src/lib/watch.js +169 -0
  538. package/dist/src/lib/watch.js.map +1 -0
  539. package/dist/src/lib/web-url.d.ts +40 -0
  540. package/dist/src/lib/web-url.js +76 -0
  541. package/dist/src/lib/web-url.js.map +1 -0
  542. package/dist/src/lib/webhook-deliver.d.ts +209 -0
  543. package/dist/src/lib/webhook-deliver.js +519 -0
  544. package/dist/src/lib/webhook-deliver.js.map +1 -0
  545. package/dist/src/lib/workflow-apply.d.ts +110 -0
  546. package/dist/src/lib/workflow-apply.js +164 -0
  547. package/dist/src/lib/workflow-apply.js.map +1 -0
  548. package/dist/src/lib/workflow-codegen/generated-schema-descriptor.d.ts +129 -0
  549. package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js +269 -0
  550. package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js.map +1 -0
  551. package/dist/src/lib/workflow-codegen/generator.d.ts +96 -0
  552. package/dist/src/lib/workflow-codegen/generator.js +361 -0
  553. package/dist/src/lib/workflow-codegen/generator.js.map +1 -0
  554. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +94 -0
  555. package/dist/src/lib/workflow-codegen/invokerIR.js +76 -0
  556. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
  557. package/dist/src/lib/workflow-codegen/naming.d.ts +33 -0
  558. package/dist/src/lib/workflow-codegen/naming.js +81 -0
  559. package/dist/src/lib/workflow-codegen/naming.js.map +1 -0
  560. package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +80 -0
  561. package/dist/src/lib/workflow-codegen/schemaToTs.js +303 -0
  562. package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -0
  563. package/dist/src/lib/workflow-config-apply.d.ts +70 -0
  564. package/dist/src/lib/workflow-config-apply.js +137 -0
  565. package/dist/src/lib/workflow-config-apply.js.map +1 -0
  566. package/dist/src/lib/workflow-config-sidecar.d.ts +63 -0
  567. package/dist/src/lib/workflow-config-sidecar.js +96 -0
  568. package/dist/src/lib/workflow-config-sidecar.js.map +1 -0
  569. package/dist/src/lib/workflow-defaults.d.ts +29 -0
  570. package/dist/src/lib/workflow-defaults.js +41 -0
  571. package/dist/src/lib/workflow-defaults.js.map +1 -0
  572. package/dist/src/lib/workflow-fragments.d.ts +64 -0
  573. package/dist/src/lib/workflow-fragments.js +342 -0
  574. package/dist/src/lib/workflow-fragments.js.map +1 -0
  575. package/dist/src/lib/workflow-include-preserve.d.ts +76 -0
  576. package/dist/src/lib/workflow-include-preserve.js +286 -0
  577. package/dist/src/lib/workflow-include-preserve.js.map +1 -0
  578. package/dist/src/lib/workflow-payload.d.ts +98 -0
  579. package/dist/src/lib/workflow-payload.js +178 -0
  580. package/dist/src/lib/workflow-payload.js.map +1 -0
  581. package/dist/src/lib/workflow-toml-validator.d.ts +211 -0
  582. package/dist/src/lib/workflow-toml-validator.js +770 -0
  583. package/dist/src/lib/workflow-toml-validator.js.map +1 -0
  584. package/dist/src/lib/workflow-usage.d.ts +196 -0
  585. package/dist/src/lib/workflow-usage.js +310 -0
  586. package/dist/src/lib/workflow-usage.js.map +1 -0
  587. package/dist/src/types/index.d.ts +591 -0
  588. package/dist/src/validators.d.ts +65 -0
  589. package/dist/src/validators.js +64 -0
  590. package/dist/src/validators.js.map +1 -0
  591. package/package.json +34 -9
@@ -1,18 +1,38 @@
1
- import { readFileSync } from "fs";
2
- import * as TOML from "@iarna/toml";
1
+ import chalk from "chalk";
3
2
  import { ApiClient } from "../lib/api-client.js";
4
3
  import { resolveAppId } from "../lib/config.js";
5
- import { success, error, info, keyValue, formatTable, formatId, formatDate, formatStatus, formatDuration, json, divider, } from "../lib/output.js";
4
+ import { success, error, info, keyValue, result as printResult, formatTable, formatId, formatDate, formatStatus, formatDuration, json, divider, } from "../lib/output.js";
5
+ import { buildIntegrationEnvelope } from "../lib/log-inspection.js";
6
+ import { confirmPrompt } from "../lib/confirm-prompt.js";
7
+ import { parseStatusFilter } from "../lib/object-status-filter.js";
8
+ import { requireTestCaseInputVariables, testCaseInputVariables, } from "../lib/test-case-variables.js";
9
+ import { resolveIntegrationSelector } from "../lib/integration-selector.js";
10
+ import { normalizeCliListEnvelope } from "../lib/paginate.js";
11
+ import { pageCursorOption, pageLimitOption, parsePageLimit, printEmptyPage, printPageHint, } from "../lib/list-options.js";
6
12
  export function registerIntegrationsCommands(program) {
7
13
  const integrations = program
8
14
  .command("integrations")
9
- .description("Configure external HTTP API connections and manage secrets")
15
+ .description("Configure external HTTP API connections")
10
16
  .addHelpText("after", `
11
17
  Examples:
12
18
  $ primitive integrations list
13
- $ primitive integrations create --from-file weather-api.toml
19
+ $ primitive config create integration weather-api # scaffold integrations/weather-api.toml
20
+ $ primitive config push --only integration/weather-api # apply it
14
21
  $ primitive integrations test 01HXY...
15
- $ primitive integrations secrets add 01HXY... --data '{"apiKey":"..."}'
22
+ $ primitive integrations archive 01HXY... # retire it (soft delete)
23
+
24
+ Storing credentials for an integration:
25
+ $ primitive secrets set MY_API_KEY --value <value>
26
+ # then reference it in integration config via {{secrets.MY_API_KEY}}
27
+ `);
28
+ // Server-side configuration is authored in TOML and applied with `config push`
29
+ // (issue #2645) — this group no longer carries config-setting flags.
30
+ integrations.addHelpText("after", `
31
+ Configuration lives in integrations/<key>.toml:
32
+ $ primitive config fields integration # the file's keys, types and defaults
33
+ $ primitive config create integration <key> # scaffold one locally
34
+ $ primitive config set integration/<key> <path>=<value>
35
+ $ primitive config push --only integration/<key>
16
36
  `);
17
37
  // List integrations
18
38
  integrations
@@ -20,21 +40,33 @@ Examples:
20
40
  .description("List integrations")
21
41
  .argument("[app-id]", "App ID (uses current app if not specified)")
22
42
  .option("--app <app-id>", "App ID")
23
- .option("--status <status>", "Filter by status: draft, active, archived")
43
+ .option("--status <status>", "Filter by status: active, inactive, archived")
44
+ .addOption(pageLimitOption())
45
+ .addOption(pageCursorOption())
24
46
  .option("--json", "Output as JSON")
25
47
  .action(async (appId, options) => {
48
+ const limit = parsePageLimit(options.limit);
26
49
  const resolvedAppId = resolveAppId(appId, options);
27
50
  const client = new ApiClient();
28
51
  try {
29
- const { items } = await client.listIntegrations(resolvedAppId, {
30
- status: options.status,
31
- });
52
+ // #2803 — `draft` is gone; refuse it by name rather than returning the
53
+ // empty list a canonical filter would produce.
54
+ const page = normalizeCliListEnvelope(await client.listIntegrations(resolvedAppId, {
55
+ status: parseStatusFilter("integrations", options.status, [
56
+ "active",
57
+ "inactive",
58
+ "archived",
59
+ ]),
60
+ limit,
61
+ cursor: options.cursor,
62
+ }));
63
+ const items = page.items;
32
64
  if (options.json) {
33
- json(items);
65
+ json(page);
34
66
  return;
35
67
  }
36
- if (!items || items.length === 0) {
37
- info("No integrations found.");
68
+ if (items.length === 0) {
69
+ printEmptyPage(page, "integrations");
38
70
  return;
39
71
  }
40
72
  console.log(formatTable(items, [
@@ -44,201 +76,168 @@ Examples:
44
76
  { header: "STATUS", key: "status", format: formatStatus },
45
77
  { header: "MODIFIED", key: "modifiedAt", format: formatDate },
46
78
  ]));
79
+ printPageHint(page);
47
80
  }
48
81
  catch (err) {
49
82
  error(err.message);
50
83
  process.exit(1);
51
84
  }
52
85
  });
53
- // Create integration
86
+ // #2645 criterion 9 / #2803 — the operational verbs. They are the only
87
+ // writers of `status`, which is server-owned and no longer a TOML key.
54
88
  integrations
55
- .command("create")
56
- .description("Create a new integration")
57
- .argument("[app-id]", "App ID (uses current app if not specified)")
58
- .option("--app <app-id>", "App ID")
59
- .option("--key <key>", "Integration key (unique identifier)")
60
- .option("--name <name>", "Display name")
61
- .option("--description <desc>", "Description")
62
- .option("--base-url <url>", "Base URL for API requests")
63
- .option("--allowed-methods <methods>", "Comma-separated list of allowed HTTP methods")
64
- .option("--allowed-paths <paths>", "Comma-separated list of allowed paths")
65
- .option("--timeout-ms <ms>", "Request timeout in milliseconds")
66
- .option("--from-file <path>", "Load integration from TOML file")
89
+ .command("disable")
90
+ .description("Take integration out of service now. Operational, not configuration: `status` is server-owned and 'config push' can neither set nor clear it.")
91
+ .argument("<integration-id>", "Integration ID")
92
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
67
93
  .option("--json", "Output as JSON")
68
- .action(async (appId, options) => {
69
- const resolvedAppId = resolveAppId(appId, options);
94
+ .action(async (id, options) => {
95
+ const resolvedAppId = resolveAppId(undefined, options);
70
96
  const client = new ApiClient();
71
- let payload;
72
- if (options.fromFile) {
73
- try {
74
- const content = readFileSync(options.fromFile, "utf-8");
75
- const tomlData = TOML.parse(content);
76
- payload = {
77
- integrationKey: tomlData.integration?.key || tomlData.key,
78
- displayName: tomlData.integration?.displayName || tomlData.displayName,
79
- description: tomlData.integration?.description || tomlData.description,
80
- requestConfig: tomlData.requestConfig || {},
81
- timeoutMs: tomlData.integration?.timeoutMs || tomlData.timeoutMs,
82
- };
83
- }
84
- catch (err) {
85
- error(`Failed to read TOML file: ${err.message}`);
86
- process.exit(1);
87
- }
88
- }
89
- else {
90
- if (!options.key || !options.name || !options.baseUrl) {
91
- error("Required: --key, --name, --base-url (or use --from-file)");
92
- process.exit(1);
93
- }
94
- payload = {
95
- integrationKey: options.key,
96
- displayName: options.name,
97
- description: options.description,
98
- requestConfig: {
99
- baseUrl: options.baseUrl,
100
- allowedMethods: options.allowedMethods?.split(",").map((s) => s.trim()),
101
- allowedPaths: options.allowedPaths?.split(",").map((s) => s.trim()),
102
- },
103
- timeoutMs: options.timeoutMs ? parseInt(options.timeoutMs) : undefined,
104
- };
105
- }
106
97
  try {
107
- const result = await client.createIntegration(resolvedAppId, payload);
98
+ const result = await client.setIntegrationAvailability(resolvedAppId, id, "disable");
108
99
  if (options.json) {
109
100
  json(result);
110
101
  return;
111
102
  }
112
- success(`Integration created: ${result.displayName}`);
113
- keyValue("Integration ID", result.integrationId);
114
- keyValue("Key", result.integrationKey);
103
+ success(`Integration disabled: ${result.integrationKey || id}`);
115
104
  }
116
105
  catch (err) {
117
106
  error(err.message);
118
107
  process.exit(1);
119
108
  }
120
109
  });
121
- // Get integration
122
110
  integrations
123
- .command("get")
124
- .description("Get integration details")
111
+ .command("enable")
112
+ .description("Put integration back in service.")
125
113
  .argument("<integration-id>", "Integration ID")
126
114
  .option("--app <app-id>", "App ID (uses current app if not specified)")
127
115
  .option("--json", "Output as JSON")
128
- .action(async (integrationId, options) => {
116
+ .action(async (id, options) => {
129
117
  const resolvedAppId = resolveAppId(undefined, options);
130
118
  const client = new ApiClient();
131
119
  try {
132
- const result = await client.getIntegration(resolvedAppId, integrationId);
120
+ const result = await client.setIntegrationAvailability(resolvedAppId, id, "enable");
133
121
  if (options.json) {
134
122
  json(result);
135
123
  return;
136
124
  }
137
- keyValue("Integration ID", result.integrationId);
138
- keyValue("Key", result.integrationKey);
139
- keyValue("Name", result.displayName);
140
- keyValue("Description", result.description);
141
- keyValue("Status", formatStatus(result.status));
142
- keyValue("Timeout", result.timeoutMs ? `${result.timeoutMs}ms` : "-");
143
- if (result.requestConfig) {
144
- divider();
145
- info("Request Config:");
146
- keyValue(" Base URL", result.requestConfig.baseUrl);
147
- keyValue(" Allowed Methods", result.requestConfig.allowedMethods?.join(", ") || "all");
148
- keyValue(" Allowed Paths", result.requestConfig.allowedPaths?.join(", ") || "all");
149
- keyValue(" Response Passthrough", result.requestConfig.responsePassthrough);
150
- if (result.requestConfig.bodyMode) {
151
- keyValue(" Body Mode", result.requestConfig.bodyMode);
152
- }
153
- if (result.requestConfig.multipartFieldMapping?.length) {
154
- keyValue(" Multipart Fields", result.requestConfig.multipartFieldMapping
155
- .map((f) => `${f.fieldName} (${f.type}${f.attachmentIndex != null ? `, attachment[${f.attachmentIndex}]` : ""})`)
156
- .join(", "));
157
- }
158
- }
125
+ success(`Integration enabled: ${result.integrationKey || id}`);
159
126
  }
160
127
  catch (err) {
161
128
  error(err.message);
162
129
  process.exit(1);
163
130
  }
164
131
  });
165
- // Update integration
132
+ // #2907 — the delete flow's CLI spelling. Not a second writer of `status`:
133
+ // this is the plain `DELETE` the server has always answered by writing the
134
+ // tombstone, which until now only the admin API and the console could reach.
135
+ // Named `archive`, not `delete`, because a configuration noun gets no
136
+ // `delete` verb (docs/cli-design.md) and prune-by-push stays the only CLI
137
+ // hard-delete path.
166
138
  integrations
167
- .command("update")
168
- .description("Update an integration")
139
+ .command("archive")
140
+ .description("Retire an integration (soft delete). Delete-lifecycle, not `disable`: the row is kept, goes on holding its key, and there is no un-archive.")
169
141
  .argument("<integration-id>", "Integration ID")
170
142
  .option("--app <app-id>", "App ID (uses current app if not specified)")
171
- .option("--name <name>", "Display name")
172
- .option("--description <desc>", "Description")
173
- .option("--status <status>", "Status: draft, active, archived")
174
- .option("--timeout-ms <ms>", "Request timeout in milliseconds")
143
+ .option("-y, --yes", "Skip confirmation prompt")
175
144
  .option("--json", "Output as JSON")
176
- .action(async (integrationId, options) => {
145
+ .addHelpText("after", `
146
+ What archiving an integration costs:
147
+ The proxy refuses it, and so does every workflow step that calls it.
148
+ The archived row still holds its integrationKey, so a push cannot re-create
149
+ one under the same key.
150
+ \`primitive integrations enable\` refuses an archived integration; there is no
151
+ un-archive.
152
+
153
+ Reclaiming the key means hard-deleting the row:
154
+ $ rm integrations/<key>.toml
155
+ $ primitive config push --prune # confirmed; hard-deletes the row
156
+ # or hard-delete it in the console, then re-add the file and push.
157
+ `)
158
+ .action(async (id, options) => {
177
159
  const resolvedAppId = resolveAppId(undefined, options);
178
- const payload = {};
179
- if (options.name)
180
- payload.displayName = options.name;
181
- if (options.description)
182
- payload.description = options.description;
183
- if (options.status)
184
- payload.status = options.status;
185
- if (options.timeoutMs)
186
- payload.timeoutMs = parseInt(options.timeoutMs);
187
- if (Object.keys(payload).length === 0) {
188
- error("No update options specified.");
189
- process.exit(1);
160
+ if (!options.yes) {
161
+ let confirmed;
162
+ try {
163
+ confirmed = await confirmPrompt(`Archive integration ${id}? It is retired, goes on holding its key, ` +
164
+ `and there is no un-archive.`);
165
+ }
166
+ catch (err) {
167
+ error(err.message);
168
+ process.exit(1);
169
+ }
170
+ if (!confirmed) {
171
+ info("Cancelled.");
172
+ return;
173
+ }
190
174
  }
191
175
  const client = new ApiClient();
192
176
  try {
193
- const result = await client.updateIntegration(resolvedAppId, integrationId, payload);
177
+ // The soft delete: no `hard`, so the server writes the tombstone and
178
+ // keeps the row (and its canonical block mirror) in step.
179
+ const result = await client.deleteIntegration(resolvedAppId, id);
194
180
  if (options.json) {
195
181
  json(result);
196
182
  return;
197
183
  }
198
- success("Integration updated.");
184
+ success(`Integration archived: ${id}`);
185
+ info("It is retired and still holds its key — reclaim the key by removing its file and running a confirmed `primitive config push --prune`.");
199
186
  }
200
187
  catch (err) {
201
188
  error(err.message);
202
189
  process.exit(1);
203
190
  }
204
191
  });
205
- // Delete integration
206
192
  integrations
207
- .command("delete")
208
- .description("Delete or archive an integration")
193
+ .command("get")
194
+ .description("Get integration details")
209
195
  .argument("<integration-id>", "Integration ID")
210
196
  .option("--app <app-id>", "App ID (uses current app if not specified)")
211
- .option("--hard", "Permanently delete instead of archive")
212
- .option("-y, --yes", "Skip confirmation prompt")
197
+ .option("--json", "Output as JSON")
213
198
  .action(async (integrationId, options) => {
214
199
  const resolvedAppId = resolveAppId(undefined, options);
215
- if (!options.yes) {
216
- const action = options.hard ? "permanently delete" : "archive";
217
- const inquirer = await import("inquirer");
218
- const { confirm } = await inquirer.default.prompt([
219
- {
220
- type: "confirm",
221
- name: "confirm",
222
- message: `Are you sure you want to ${action} integration ${integrationId}?`,
223
- default: false,
224
- },
225
- ]);
226
- if (!confirm) {
227
- info("Cancelled.");
228
- return;
229
- }
230
- }
231
200
  const client = new ApiClient();
232
201
  try {
233
- await client.deleteIntegration(resolvedAppId, integrationId, options.hard);
234
- success(`Integration ${options.hard ? "deleted" : "archived"}.`);
202
+ const result = await client.getIntegration(resolvedAppId, integrationId);
203
+ if (options.json) {
204
+ json(result);
205
+ return;
206
+ }
207
+ printResult("Integration ID", result.integrationId);
208
+ printResult("Key", result.integrationKey);
209
+ printResult("Name", result.displayName);
210
+ printResult("Description", result.description);
211
+ printResult("Status", formatStatus(result.status));
212
+ printResult("Timeout", result.timeoutMs ? `${result.timeoutMs}ms` : "-");
213
+ // #2631: no rule means every non-admin call is denied. Print that in
214
+ // words — a blank or "-" would read as "unrestricted" and hide an
215
+ // integration that was never given a rule.
216
+ printResult("Access Rule", typeof result.accessRule === "string" && result.accessRule !== ""
217
+ ? result.accessRule
218
+ : "(none — all non-admin calls are denied; set one to allow callers)");
219
+ if (result.requestConfig) {
220
+ divider();
221
+ info("Request Config:");
222
+ printResult(" Base URL", result.requestConfig.baseUrl);
223
+ printResult(" Allowed Methods", result.requestConfig.allowedMethods?.join(", ") || "all");
224
+ printResult(" Allowed Paths", result.requestConfig.allowedPaths?.join(", ") || "all");
225
+ printResult(" Response Passthrough", result.requestConfig.responsePassthrough);
226
+ if (result.requestConfig.bodyMode) {
227
+ printResult(" Body Mode", result.requestConfig.bodyMode);
228
+ }
229
+ if (result.requestConfig.multipartFieldMapping?.length) {
230
+ printResult(" Multipart Fields", result.requestConfig.multipartFieldMapping
231
+ .map((f) => `${f.fieldName} (${f.type}${f.attachmentIndex != null ? `, attachment[${f.attachmentIndex}]` : ""})`)
232
+ .join(", "));
233
+ }
234
+ }
235
235
  }
236
236
  catch (err) {
237
237
  error(err.message);
238
238
  process.exit(1);
239
239
  }
240
240
  });
241
- // Test integration
242
241
  integrations
243
242
  .command("test")
244
243
  .description("Test an integration by making a request")
@@ -304,20 +303,37 @@ Examples:
304
303
  // List integration logs
305
304
  integrations
306
305
  .command("logs")
307
- .description("View integration request logs")
306
+ .description("View integration request logs (includes workflow-initiated calls; filter with --source workflow|user|admin|test)")
308
307
  .argument("<integration-id>", "Integration ID")
309
308
  .option("--app <app-id>", "App ID (uses current app if not specified)")
310
309
  .option("--limit <n>", "Number of logs to show", "20")
310
+ .option("--source <source>", "Filter by call source: user, admin, test, or workflow")
311
+ .option("--run <run-id>", "Only the calls this run made (a workflow run or a function run)")
312
+ .option("--status <status>", "Filter by upstream HTTP status (e.g. 200, 500)")
313
+ .option("--from <iso>", "Only logs at or after this ISO timestamp")
314
+ .option("--to <iso>", "Only logs at or before this ISO timestamp")
311
315
  .option("--json", "Output as JSON")
312
316
  .action(async (integrationId, options) => {
313
317
  const resolvedAppId = resolveAppId(undefined, options);
314
318
  const client = new ApiClient();
315
319
  try {
320
+ const validSources = new Set(["user", "admin", "test", "workflow"]);
321
+ if (options.source && !validSources.has(options.source)) {
322
+ error(`Invalid --source value '${options.source}'. Must be one of: user, admin, test, workflow.`);
323
+ process.exit(1);
324
+ }
316
325
  const logs = await client.listIntegrationLogs(resolvedAppId, integrationId, {
317
326
  limit: parseInt(options.limit),
327
+ ...(options.source && { source: options.source }),
328
+ // #3691 — the run pivot. A function run's id and a workflow run's
329
+ // are read the same way, because a row names its run either way.
330
+ ...(options.run && { runId: options.run }),
331
+ ...(options.status && { status: options.status }),
332
+ ...(options.from && { from: options.from }),
333
+ ...(options.to && { to: options.to }),
318
334
  });
319
335
  if (options.json) {
320
- json(logs);
336
+ json(buildIntegrationEnvelope(logs));
321
337
  return;
322
338
  }
323
339
  if (!logs || logs.length === 0) {
@@ -326,10 +342,13 @@ Examples:
326
342
  }
327
343
  console.log(formatTable(logs, [
328
344
  { header: "TIME", key: "timestamp", format: formatDate },
345
+ { header: "SOURCE", key: "source", format: (v) => v || "user" },
329
346
  { header: "METHOD", key: "method" },
330
347
  { header: "PATH", key: "path" },
331
348
  { header: "STATUS", key: "status" },
332
349
  { header: "DURATION", key: "durationMs", format: formatDuration },
350
+ { header: "WORKFLOW", key: "workflowKey", format: (v) => v || "" },
351
+ { header: "RUN", key: "runId", format: (v) => (v ? formatId(v) : "") },
333
352
  { header: "TRACE", key: "traceId", format: formatId },
334
353
  ]));
335
354
  }
@@ -338,96 +357,318 @@ Examples:
338
357
  process.exit(1);
339
358
  }
340
359
  });
341
- // Secrets subcommand
342
- const secrets = integrations.command("secrets").description("Manage integration secrets");
343
- // List secrets
344
- secrets
360
+ // ============================================
361
+ // TESTS SUBCOMMAND
362
+ // ============================================
363
+ const tests = integrations
364
+ .command("tests")
365
+ .description("Run and inspect integration test cases")
366
+ .addHelpText("after", `
367
+ Test cases are authored in TOML at integrations/<key>.tests/<name>.toml and
368
+ applied with \`primitive config push\` (issue #2769); \`config fields integration\`
369
+ lists the fields. Deleting a case is removing its file and running
370
+ \`config push --prune\`.
371
+
372
+ Every verb here takes the integration's KEY or its ID (#3000). An identifier
373
+ that names no integration in the app fails; \`Total Tests: 0\` only ever means
374
+ the integration exists and has no cases.
375
+
376
+ Examples:
377
+ $ primitive integrations tests list <integration>
378
+ $ primitive integrations tests run <integration> <test-case-id>
379
+ $ primitive integrations tests run-all <integration>
380
+ $ primitive integrations tests run-all <integration> --test-cases 01ABC,01DEF,01GHI
381
+ `);
382
+ // List test cases
383
+ tests
345
384
  .command("list")
346
- .description("List secrets for an integration")
347
- .argument("<integration-id>", "Integration ID")
385
+ .description("List test cases for an integration")
386
+ .argument("<integration>", "Integration key or ID")
348
387
  .option("--app <app-id>", "App ID (uses current app if not specified)")
388
+ .addOption(pageLimitOption())
389
+ .addOption(pageCursorOption())
349
390
  .option("--json", "Output as JSON")
350
- .action(async (integrationId, options) => {
391
+ .action(async (integration, options) => {
392
+ const limit = parsePageLimit(options.limit);
351
393
  const resolvedAppId = resolveAppId(undefined, options);
352
394
  const client = new ApiClient();
353
395
  try {
354
- const secretsList = await client.listIntegrationSecrets(resolvedAppId, integrationId);
396
+ // #3000 — resolve BEFORE listing: the test-case endpoint answers an
397
+ // unknown block with an empty page, so an unresolved identifier would
398
+ // print "No test cases found." and exit 0.
399
+ const { integrationId } = await resolveIntegrationSelector(client, resolvedAppId, integration);
400
+ const page = normalizeCliListEnvelope(await client.listTestCases(resolvedAppId, "integration", integrationId, {
401
+ limit,
402
+ cursor: options.cursor,
403
+ }));
404
+ const items = page.items;
355
405
  if (options.json) {
356
- json(secretsList);
406
+ json(page);
357
407
  return;
358
408
  }
359
- if (!secretsList || secretsList.length === 0) {
360
- info("No secrets found.");
409
+ if (items.length === 0) {
410
+ printEmptyPage(page, "test cases");
361
411
  return;
362
412
  }
363
- console.log(formatTable(secretsList, [
364
- { header: "ID", key: "secretId", format: formatId },
365
- { header: "VERSION", key: "version" },
366
- { header: "SUMMARY", key: "secretSummary" },
367
- { header: "STATUS", key: "status", format: formatStatus },
413
+ console.log(formatTable(items, [
414
+ { header: "ID", key: "testCaseId", format: formatId },
415
+ { header: "NAME", key: "name" },
416
+ { header: "CONFIG", key: "configId", format: (v) => v ? formatId(v) : "-" },
368
417
  { header: "CREATED", key: "createdAt", format: formatDate },
369
418
  ]));
419
+ printPageHint(page);
370
420
  }
371
421
  catch (err) {
372
422
  error(err.message);
373
423
  process.exit(1);
374
424
  }
375
425
  });
376
- // Add secret
377
- secrets
378
- .command("add")
379
- .description("Add a secret to an integration")
380
- .argument("<integration-id>", "Integration ID")
426
+ // Get test case
427
+ tests
428
+ .command("get")
429
+ .description("Get test case details")
430
+ .argument("<integration>", "Integration key or ID")
431
+ .argument("<test-case-id>", "Test Case ID")
381
432
  .option("--app <app-id>", "App ID (uses current app if not specified)")
382
- .option("--data <json>", "Secret data as JSON (e.g., '{\"apiKey\":\"...\"}' )")
383
- .option("--summary <text>", "Description of the secret")
384
433
  .option("--json", "Output as JSON")
385
- .action(async (integrationId, options) => {
434
+ .action(async (integration, testCaseId, options) => {
386
435
  const resolvedAppId = resolveAppId(undefined, options);
387
- if (!options.data) {
388
- error("--data is required (JSON object with secret values)");
436
+ const client = new ApiClient();
437
+ try {
438
+ const { integrationId } = await resolveIntegrationSelector(client, resolvedAppId, integration);
439
+ const result = await client.getTestCase(resolvedAppId, "integration", integrationId, testCaseId);
440
+ if (options.json) {
441
+ json(result);
442
+ return;
443
+ }
444
+ printResult("Test Case ID", result.testCaseId);
445
+ printResult("Name", result.name);
446
+ printResult("Config ID", result.configId || "-");
447
+ printResult("Created", formatDate(result.createdAt));
448
+ divider();
449
+ info("Input Variables:");
450
+ console.log(JSON.stringify(testCaseInputVariables(result.inputVariables), null, 2));
451
+ if (result.expectedOutputPattern) {
452
+ divider();
453
+ printResult("Expected Pattern", result.expectedOutputPattern);
454
+ }
455
+ if (result.expectedOutputContains) {
456
+ divider();
457
+ info("Expected Contains:");
458
+ try {
459
+ console.log(JSON.stringify(JSON.parse(result.expectedOutputContains), null, 2));
460
+ }
461
+ catch {
462
+ console.log(result.expectedOutputContains);
463
+ }
464
+ }
465
+ if (result.expectedJsonSubset) {
466
+ divider();
467
+ info("Expected JSON Subset:");
468
+ try {
469
+ console.log(JSON.stringify(JSON.parse(result.expectedJsonSubset), null, 2));
470
+ }
471
+ catch {
472
+ console.log(result.expectedJsonSubset);
473
+ }
474
+ }
475
+ if (result.evaluatorPromptId) {
476
+ divider();
477
+ printResult("Evaluator Prompt", result.evaluatorPromptId);
478
+ printResult("Evaluator Config", result.evaluatorConfigId || "-");
479
+ }
480
+ }
481
+ catch (err) {
482
+ error(err.message);
389
483
  process.exit(1);
390
484
  }
391
- let secretData;
485
+ });
486
+ // Run a single test case
487
+ tests
488
+ .command("run")
489
+ .description("Run a single test case")
490
+ .argument("<integration>", "Integration key or ID")
491
+ .argument("<test-case-id>", "Test Case ID")
492
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
493
+ .option("--config <config-id>", "Override config ID")
494
+ .option("--json", "Output as JSON")
495
+ .action(async (integration, testCaseId, options) => {
496
+ const resolvedAppId = resolveAppId(undefined, options);
497
+ const client = new ApiClient();
392
498
  try {
393
- secretData = JSON.parse(options.data);
499
+ const { integrationId } = await resolveIntegrationSelector(client, resolvedAppId, integration);
500
+ // Get test case to retrieve its variables
501
+ const testCase = await client.getTestCase(resolvedAppId, "integration", integrationId, testCaseId);
502
+ // #2968 — the case's variables ARE the request the run issues, so a
503
+ // dropped `inputVariables` here is the config's bare defaults instead
504
+ // of the case's method, path and body. The server hands them back
505
+ // parsed; older servers hand back JSON text. #3158 — an input that
506
+ // cannot be read stops the run and says why, rather than issuing a
507
+ // request the case never authored.
508
+ const variables = requireTestCaseInputVariables(testCase.inputVariables, testCaseId);
509
+ const result = await client.executeBlockTest(resolvedAppId, "integration", integrationId, {
510
+ variables,
511
+ testCaseId,
512
+ configId: options.config || testCase.configId,
513
+ });
514
+ if (options.json) {
515
+ json(result);
516
+ return;
517
+ }
518
+ const passed = result.verification?.passed;
519
+ if (passed) {
520
+ success("Test PASSED");
521
+ }
522
+ else {
523
+ error("Test FAILED");
524
+ }
525
+ keyValue("Duration", formatDuration(result.metrics?.durationMs));
526
+ if (result.verification) {
527
+ divider();
528
+ info("Verification:");
529
+ const v = result.verification;
530
+ keyValue(" Passed", v.passed ? chalk.green("Yes") : chalk.red("No"));
531
+ keyValue(" Checks", `${v.summary?.passed || 0}/${v.summary?.total || 0} passed`);
532
+ if (v.checks && v.checks.length > 0) {
533
+ console.log();
534
+ for (const check of v.checks) {
535
+ const icon = check.passed ? chalk.green("\u2713") : chalk.red("\u2717");
536
+ console.log(` ${icon} ${check.name}`);
537
+ if (!check.passed && check.message) {
538
+ console.log(` ${chalk.dim(check.message)}`);
539
+ }
540
+ }
541
+ }
542
+ }
543
+ if (result.output) {
544
+ divider();
545
+ info("Output:");
546
+ console.log(typeof result.output === "string" ? result.output : JSON.stringify(result.output, null, 2));
547
+ }
548
+ if (result.error) {
549
+ divider();
550
+ error(`Error: ${result.error}`);
551
+ }
552
+ if (!passed) {
553
+ process.exit(1);
554
+ }
394
555
  }
395
- catch {
396
- error("Invalid JSON in --data");
556
+ catch (err) {
557
+ error(err.message);
397
558
  process.exit(1);
398
559
  }
560
+ });
561
+ // Run all test cases (or a specific group)
562
+ tests
563
+ .command("run-all")
564
+ .description("Run all test cases for an integration, or a specific subset")
565
+ .argument("<integration>", "Integration key or ID")
566
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
567
+ .option("--config <config-id>", "Override config ID for all tests")
568
+ .option("--test-cases <ids>", "Comma-separated list of test case IDs to run (runs only these)")
569
+ .option("--json", "Output as JSON")
570
+ .action(async (integration, options) => {
571
+ const resolvedAppId = resolveAppId(undefined, options);
399
572
  const client = new ApiClient();
400
573
  try {
401
- const result = await client.addIntegrationSecret(resolvedAppId, integrationId, {
402
- secretData,
403
- secretSummary: options.summary,
574
+ // #3000 — resolve BEFORE announcing the run: an unresolved identifier
575
+ // came back as `Total Tests: 0 / Failed: 0` and exit 0, which reads as
576
+ // a pass in CI.
577
+ const { integrationId } = await resolveIntegrationSelector(client, resolvedAppId, integration);
578
+ // Parse test case IDs if provided
579
+ let testCaseIds;
580
+ if (options.testCases) {
581
+ testCaseIds = options.testCases.split(",").map((id) => id.trim()).filter(Boolean);
582
+ if (testCaseIds.length === 0) {
583
+ error("No valid test case IDs provided in --test-cases");
584
+ process.exit(1);
585
+ }
586
+ }
587
+ if (!options.json) {
588
+ if (testCaseIds) {
589
+ info(`Running ${testCaseIds.length} selected test case(s)...`);
590
+ }
591
+ else {
592
+ info("Running all test cases...");
593
+ }
594
+ }
595
+ const result = await client.runAllTestCases(resolvedAppId, "integration", integrationId, {
596
+ overrideConfigId: options.config,
597
+ testCaseIds,
404
598
  });
405
599
  if (options.json) {
406
600
  json(result);
407
601
  return;
408
602
  }
409
- success("Secret added.");
410
- keyValue("Secret ID", result?.secretId);
411
- keyValue("Version", result?.version);
603
+ const { summary, runs, comparisonGroup } = result;
604
+ divider();
605
+ keyValue("Comparison Group", comparisonGroup);
606
+ keyValue("Total Tests", summary.total);
607
+ keyValue("Passed", chalk.green(summary.passed));
608
+ keyValue("Failed", summary.failed > 0 ? chalk.red(summary.failed) : "0");
609
+ divider();
610
+ if (runs && runs.length > 0) {
611
+ for (const r of runs) {
612
+ const passed = r.verification?.passed;
613
+ const icon = passed ? chalk.green("\u2713") : chalk.red("\u2717");
614
+ const status = passed ? "PASSED" : "FAILED";
615
+ console.log(`${icon} ${r.testCaseName} - ${status}`);
616
+ if (!passed && r.verification?.details?.reason) {
617
+ console.log(` ${chalk.dim(r.verification.details.reason)}`);
618
+ }
619
+ }
620
+ }
621
+ // Exit with error code if any tests failed
622
+ if (summary.failed > 0) {
623
+ process.exit(1);
624
+ }
412
625
  }
413
626
  catch (err) {
414
627
  error(err.message);
415
628
  process.exit(1);
416
629
  }
417
630
  });
418
- // Archive secret
419
- secrets
420
- .command("archive")
421
- .description("Archive a secret")
422
- .argument("<integration-id>", "Integration ID")
423
- .argument("<secret-id>", "Secret ID")
631
+ // List test runs
632
+ tests
633
+ .command("runs")
634
+ .description("List recent test runs for an integration")
635
+ .argument("<integration>", "Integration key or ID")
424
636
  .option("--app <app-id>", "App ID (uses current app if not specified)")
425
- .action(async (integrationId, secretId, options) => {
637
+ .option("--limit <n>", "Maximum number of runs to show", "20")
638
+ .option("--group <group>", "Filter by comparison group")
639
+ .option("--json", "Output as JSON")
640
+ .action(async (integration, options) => {
426
641
  const resolvedAppId = resolveAppId(undefined, options);
427
642
  const client = new ApiClient();
428
643
  try {
429
- await client.archiveIntegrationSecret(resolvedAppId, integrationId, secretId);
430
- success("Secret archived.");
644
+ const { integrationId } = await resolveIntegrationSelector(client, resolvedAppId, integration);
645
+ const { items } = await client.listTestRuns(resolvedAppId, "integration", integrationId, {
646
+ limit: parseInt(options.limit),
647
+ comparisonGroup: options.group,
648
+ });
649
+ if (options.json) {
650
+ json(items);
651
+ return;
652
+ }
653
+ if (!items || items.length === 0) {
654
+ info("No test runs found.");
655
+ return;
656
+ }
657
+ console.log(formatTable(items, [
658
+ { header: "RUN ID", key: "runId", format: formatId },
659
+ { header: "TEST CASE ID", key: "testCaseId", format: (v) => v ? formatId(v) : "-" },
660
+ {
661
+ header: "PASSED",
662
+ key: "verificationPassed",
663
+ format: (v) => v === true
664
+ ? chalk.green("Yes")
665
+ : v === false
666
+ ? chalk.red("No")
667
+ : "-",
668
+ },
669
+ { header: "DURATION", key: "durationMs", format: formatDuration },
670
+ { header: "STARTED", key: "startedAt", format: formatDate },
671
+ ]));
431
672
  }
432
673
  catch (err) {
433
674
  error(err.message);