@smthrs/control 0.0.0-stage → 1.0.0-rc.3

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 (418) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/LICENSE +21 -0
  3. package/README.md +168 -2
  4. package/dist/cjs/ApprovalAuthority.d.ts +73 -0
  5. package/dist/cjs/ApprovalAuthority.d.ts.map +1 -0
  6. package/dist/cjs/ApprovalAuthority.js +62 -0
  7. package/dist/cjs/ApprovalAuthority.js.map +7 -0
  8. package/dist/cjs/Cancellation.d.ts +107 -0
  9. package/dist/cjs/Cancellation.d.ts.map +1 -0
  10. package/dist/cjs/Cancellation.js +72 -0
  11. package/dist/cjs/Cancellation.js.map +7 -0
  12. package/dist/cjs/Channels.d.ts +170 -0
  13. package/dist/cjs/Channels.d.ts.map +1 -0
  14. package/dist/cjs/Channels.js +278 -0
  15. package/dist/cjs/Channels.js.map +7 -0
  16. package/dist/cjs/Control.d.ts +202 -0
  17. package/dist/cjs/Control.d.ts.map +1 -0
  18. package/dist/cjs/Control.js +47 -0
  19. package/dist/cjs/Control.js.map +7 -0
  20. package/dist/cjs/ControlClient.d.ts +52 -0
  21. package/dist/cjs/ControlClient.d.ts.map +1 -0
  22. package/dist/cjs/ControlClient.js +191 -0
  23. package/dist/cjs/ControlClient.js.map +7 -0
  24. package/dist/cjs/ControlError.d.ts +318 -0
  25. package/dist/cjs/ControlError.d.ts.map +1 -0
  26. package/dist/cjs/ControlError.js +249 -0
  27. package/dist/cjs/ControlError.js.map +7 -0
  28. package/dist/cjs/ControlExecutor.d.ts +372 -0
  29. package/dist/cjs/ControlExecutor.d.ts.map +1 -0
  30. package/dist/cjs/ControlExecutor.js +123 -0
  31. package/dist/cjs/ControlExecutor.js.map +7 -0
  32. package/dist/cjs/ControlFacts.d.ts +454 -0
  33. package/dist/cjs/ControlFacts.d.ts.map +1 -0
  34. package/dist/cjs/ControlFacts.js +261 -0
  35. package/dist/cjs/ControlFacts.js.map +7 -0
  36. package/dist/cjs/ControlLive.d.ts +23 -0
  37. package/dist/cjs/ControlLive.d.ts.map +1 -0
  38. package/dist/cjs/ControlLive.js +1280 -0
  39. package/dist/cjs/ControlLive.js.map +7 -0
  40. package/dist/cjs/ControlRpcs.d.ts +1204 -0
  41. package/dist/cjs/ControlRpcs.d.ts.map +1 -0
  42. package/dist/cjs/ControlRpcs.js +247 -0
  43. package/dist/cjs/ControlRpcs.js.map +7 -0
  44. package/dist/cjs/ControlRuntime.d.ts +635 -0
  45. package/dist/cjs/ControlRuntime.d.ts.map +1 -0
  46. package/dist/cjs/ControlRuntime.js +740 -0
  47. package/dist/cjs/ControlRuntime.js.map +7 -0
  48. package/dist/cjs/ControlSchema.d.ts +2642 -0
  49. package/dist/cjs/ControlSchema.d.ts.map +1 -0
  50. package/dist/cjs/ControlSchema.js +634 -0
  51. package/dist/cjs/ControlSchema.js.map +7 -0
  52. package/dist/cjs/ControlServer.d.ts +51 -0
  53. package/dist/cjs/ControlServer.d.ts.map +1 -0
  54. package/dist/cjs/ControlServer.js +121 -0
  55. package/dist/cjs/ControlServer.js.map +7 -0
  56. package/dist/cjs/Credential.d.ts +136 -0
  57. package/dist/cjs/Credential.d.ts.map +1 -0
  58. package/dist/cjs/Credential.js +168 -0
  59. package/dist/cjs/Credential.js.map +7 -0
  60. package/dist/cjs/CredentialCipher.d.ts +90 -0
  61. package/dist/cjs/CredentialCipher.d.ts.map +1 -0
  62. package/dist/cjs/CredentialCipher.js +45 -0
  63. package/dist/cjs/CredentialCipher.js.map +7 -0
  64. package/dist/cjs/CredentialStore.d.ts +97 -0
  65. package/dist/cjs/CredentialStore.d.ts.map +1 -0
  66. package/dist/cjs/CredentialStore.js +81 -0
  67. package/dist/cjs/CredentialStore.js.map +7 -0
  68. package/dist/cjs/DispatchReader.d.ts +112 -0
  69. package/dist/cjs/DispatchReader.d.ts.map +1 -0
  70. package/dist/cjs/DispatchReader.js +45 -0
  71. package/dist/cjs/DispatchReader.js.map +7 -0
  72. package/dist/cjs/Health.d.ts +333 -0
  73. package/dist/cjs/Health.d.ts.map +1 -0
  74. package/dist/cjs/Health.js +311 -0
  75. package/dist/cjs/Health.js.map +7 -0
  76. package/dist/cjs/JevSessionChecker.d.ts +57 -0
  77. package/dist/cjs/JevSessionChecker.d.ts.map +1 -0
  78. package/dist/cjs/JevSessionChecker.js +113 -0
  79. package/dist/cjs/JevSessionChecker.js.map +7 -0
  80. package/dist/cjs/Lineage.d.ts +131 -0
  81. package/dist/cjs/Lineage.d.ts.map +1 -0
  82. package/dist/cjs/Lineage.js +81 -0
  83. package/dist/cjs/Lineage.js.map +7 -0
  84. package/dist/cjs/Migrations.d.ts +34 -0
  85. package/dist/cjs/Migrations.d.ts.map +1 -0
  86. package/dist/cjs/Migrations.js +60 -0
  87. package/dist/cjs/Migrations.js.map +7 -0
  88. package/dist/cjs/Monitor.d.ts +282 -0
  89. package/dist/cjs/Monitor.d.ts.map +1 -0
  90. package/dist/cjs/Monitor.js +283 -0
  91. package/dist/cjs/Monitor.js.map +7 -0
  92. package/dist/cjs/ScopedToken.d.ts +193 -0
  93. package/dist/cjs/ScopedToken.d.ts.map +1 -0
  94. package/dist/cjs/ScopedToken.js +135 -0
  95. package/dist/cjs/ScopedToken.js.map +7 -0
  96. package/dist/cjs/SqlControlRuntime.d.ts +161 -0
  97. package/dist/cjs/SqlControlRuntime.d.ts.map +1 -0
  98. package/dist/cjs/SqlControlRuntime.js +1521 -0
  99. package/dist/cjs/SqlControlRuntime.js.map +7 -0
  100. package/dist/cjs/SqlCredentialStore.d.ts +43 -0
  101. package/dist/cjs/SqlCredentialStore.d.ts.map +1 -0
  102. package/dist/cjs/SqlCredentialStore.js +113 -0
  103. package/dist/cjs/SqlCredentialStore.js.map +7 -0
  104. package/dist/cjs/Steering.d.ts +69 -0
  105. package/dist/cjs/Steering.d.ts.map +1 -0
  106. package/dist/cjs/Steering.js +49 -0
  107. package/dist/cjs/Steering.js.map +7 -0
  108. package/dist/cjs/SystemFlows.d.ts +223 -0
  109. package/dist/cjs/SystemFlows.d.ts.map +1 -0
  110. package/dist/cjs/SystemFlows.js +195 -0
  111. package/dist/cjs/SystemFlows.js.map +7 -0
  112. package/dist/cjs/WebCryptoCipher.d.ts +49 -0
  113. package/dist/cjs/WebCryptoCipher.d.ts.map +1 -0
  114. package/dist/cjs/WebCryptoCipher.js +129 -0
  115. package/dist/cjs/WebCryptoCipher.js.map +7 -0
  116. package/dist/cjs/WebhookChannel.d.ts +113 -0
  117. package/dist/cjs/WebhookChannel.d.ts.map +1 -0
  118. package/dist/cjs/WebhookChannel.js +98 -0
  119. package/dist/cjs/WebhookChannel.js.map +7 -0
  120. package/dist/cjs/index.d.ts +160 -0
  121. package/dist/cjs/index.d.ts.map +1 -0
  122. package/dist/cjs/index.js +91 -0
  123. package/dist/cjs/index.js.map +7 -0
  124. package/dist/cjs/internal/MutationBoundary.d.ts +27 -0
  125. package/dist/cjs/internal/MutationBoundary.d.ts.map +1 -0
  126. package/dist/cjs/internal/MutationBoundary.js +50 -0
  127. package/dist/cjs/internal/MutationBoundary.js.map +7 -0
  128. package/dist/cjs/internal/activeFibers.d.ts +12 -0
  129. package/dist/cjs/internal/activeFibers.d.ts.map +1 -0
  130. package/dist/cjs/internal/activeFibers.js +30 -0
  131. package/dist/cjs/internal/activeFibers.js.map +7 -0
  132. package/dist/cjs/internal/issues.d.ts +28 -0
  133. package/dist/cjs/internal/issues.d.ts.map +1 -0
  134. package/dist/cjs/internal/issues.js +34 -0
  135. package/dist/cjs/internal/issues.js.map +7 -0
  136. package/dist/cjs/internal/planning.d.ts +347 -0
  137. package/dist/cjs/internal/planning.d.ts.map +1 -0
  138. package/dist/cjs/internal/planning.js +137 -0
  139. package/dist/cjs/internal/planning.js.map +7 -0
  140. package/dist/cjs/internal/sqlSchemaErrors.d.ts +18 -0
  141. package/dist/cjs/internal/sqlSchemaErrors.d.ts.map +1 -0
  142. package/dist/cjs/internal/sqlSchemaErrors.js +40 -0
  143. package/dist/cjs/internal/sqlSchemaErrors.js.map +7 -0
  144. package/dist/cjs/migrations/0001_control_tables.d.ts +18 -0
  145. package/dist/cjs/migrations/0001_control_tables.d.ts.map +1 -0
  146. package/dist/cjs/migrations/0001_control_tables.js +115 -0
  147. package/dist/cjs/migrations/0001_control_tables.js.map +7 -0
  148. package/dist/cjs/migrations/0002_run_keys.d.ts +15 -0
  149. package/dist/cjs/migrations/0002_run_keys.d.ts.map +1 -0
  150. package/dist/cjs/migrations/0002_run_keys.js +44 -0
  151. package/dist/cjs/migrations/0002_run_keys.js.map +7 -0
  152. package/dist/cjs/migrations/0003_signal_commands.d.ts +13 -0
  153. package/dist/cjs/migrations/0003_signal_commands.d.ts.map +1 -0
  154. package/dist/cjs/migrations/0003_signal_commands.js +50 -0
  155. package/dist/cjs/migrations/0003_signal_commands.js.map +7 -0
  156. package/dist/cjs/migrations/0004_approval_decisions.d.ts +13 -0
  157. package/dist/cjs/migrations/0004_approval_decisions.d.ts.map +1 -0
  158. package/dist/cjs/migrations/0004_approval_decisions.js +45 -0
  159. package/dist/cjs/migrations/0004_approval_decisions.js.map +7 -0
  160. package/dist/cjs/migrations/0005_signal_principals.d.ts +18 -0
  161. package/dist/cjs/migrations/0005_signal_principals.d.ts.map +1 -0
  162. package/dist/cjs/migrations/0005_signal_principals.js +45 -0
  163. package/dist/cjs/migrations/0005_signal_principals.js.map +7 -0
  164. package/dist/cjs/migrations/0006_run_principals.d.ts +18 -0
  165. package/dist/cjs/migrations/0006_run_principals.d.ts.map +1 -0
  166. package/dist/cjs/migrations/0006_run_principals.js +49 -0
  167. package/dist/cjs/migrations/0006_run_principals.js.map +7 -0
  168. package/dist/cjs/migrations/0007_resume_consent.d.ts +18 -0
  169. package/dist/cjs/migrations/0007_resume_consent.d.ts.map +1 -0
  170. package/dist/cjs/migrations/0007_resume_consent.js +46 -0
  171. package/dist/cjs/migrations/0007_resume_consent.js.map +7 -0
  172. package/dist/cjs/package.json +1 -0
  173. package/dist/cjs/test/TestControl.d.ts +19 -0
  174. package/dist/cjs/test/TestControl.d.ts.map +1 -0
  175. package/dist/cjs/test/TestControl.js +62 -0
  176. package/dist/cjs/test/TestControl.js.map +7 -0
  177. package/dist/esm/ApprovalAuthority.d.ts +73 -0
  178. package/dist/esm/ApprovalAuthority.d.ts.map +1 -0
  179. package/dist/esm/ApprovalAuthority.js +72 -0
  180. package/dist/esm/ApprovalAuthority.js.map +1 -0
  181. package/dist/esm/Cancellation.d.ts +107 -0
  182. package/dist/esm/Cancellation.d.ts.map +1 -0
  183. package/dist/esm/Cancellation.js +116 -0
  184. package/dist/esm/Cancellation.js.map +1 -0
  185. package/dist/esm/Channels.d.ts +170 -0
  186. package/dist/esm/Channels.d.ts.map +1 -0
  187. package/dist/esm/Channels.js +312 -0
  188. package/dist/esm/Channels.js.map +1 -0
  189. package/dist/esm/Control.d.ts +202 -0
  190. package/dist/esm/Control.d.ts.map +1 -0
  191. package/dist/esm/Control.js +42 -0
  192. package/dist/esm/Control.js.map +1 -0
  193. package/dist/esm/ControlClient.d.ts +52 -0
  194. package/dist/esm/ControlClient.d.ts.map +1 -0
  195. package/dist/esm/ControlClient.js +217 -0
  196. package/dist/esm/ControlClient.js.map +1 -0
  197. package/dist/esm/ControlError.d.ts +318 -0
  198. package/dist/esm/ControlError.d.ts.map +1 -0
  199. package/dist/esm/ControlError.js +359 -0
  200. package/dist/esm/ControlError.js.map +1 -0
  201. package/dist/esm/ControlExecutor.d.ts +372 -0
  202. package/dist/esm/ControlExecutor.d.ts.map +1 -0
  203. package/dist/esm/ControlExecutor.js +212 -0
  204. package/dist/esm/ControlExecutor.js.map +1 -0
  205. package/dist/esm/ControlFacts.d.ts +454 -0
  206. package/dist/esm/ControlFacts.d.ts.map +1 -0
  207. package/dist/esm/ControlFacts.js +324 -0
  208. package/dist/esm/ControlFacts.js.map +1 -0
  209. package/dist/esm/ControlLive.d.ts +23 -0
  210. package/dist/esm/ControlLive.d.ts.map +1 -0
  211. package/dist/esm/ControlLive.js +1585 -0
  212. package/dist/esm/ControlLive.js.map +1 -0
  213. package/dist/esm/ControlRpcs.d.ts +1204 -0
  214. package/dist/esm/ControlRpcs.d.ts.map +1 -0
  215. package/dist/esm/ControlRpcs.js +299 -0
  216. package/dist/esm/ControlRpcs.js.map +1 -0
  217. package/dist/esm/ControlRuntime.d.ts +635 -0
  218. package/dist/esm/ControlRuntime.d.ts.map +1 -0
  219. package/dist/esm/ControlRuntime.js +807 -0
  220. package/dist/esm/ControlRuntime.js.map +1 -0
  221. package/dist/esm/ControlSchema.d.ts +2642 -0
  222. package/dist/esm/ControlSchema.d.ts.map +1 -0
  223. package/dist/esm/ControlSchema.js +1030 -0
  224. package/dist/esm/ControlSchema.js.map +1 -0
  225. package/dist/esm/ControlServer.d.ts +51 -0
  226. package/dist/esm/ControlServer.d.ts.map +1 -0
  227. package/dist/esm/ControlServer.js +145 -0
  228. package/dist/esm/ControlServer.js.map +1 -0
  229. package/dist/esm/Credential.d.ts +136 -0
  230. package/dist/esm/Credential.d.ts.map +1 -0
  231. package/dist/esm/Credential.js +190 -0
  232. package/dist/esm/Credential.js.map +1 -0
  233. package/dist/esm/CredentialCipher.d.ts +90 -0
  234. package/dist/esm/CredentialCipher.d.ts.map +1 -0
  235. package/dist/esm/CredentialCipher.js +56 -0
  236. package/dist/esm/CredentialCipher.js.map +1 -0
  237. package/dist/esm/CredentialStore.d.ts +97 -0
  238. package/dist/esm/CredentialStore.d.ts.map +1 -0
  239. package/dist/esm/CredentialStore.js +101 -0
  240. package/dist/esm/CredentialStore.js.map +1 -0
  241. package/dist/esm/DispatchReader.d.ts +112 -0
  242. package/dist/esm/DispatchReader.d.ts.map +1 -0
  243. package/dist/esm/DispatchReader.js +76 -0
  244. package/dist/esm/DispatchReader.js.map +1 -0
  245. package/dist/esm/Health.d.ts +333 -0
  246. package/dist/esm/Health.d.ts.map +1 -0
  247. package/dist/esm/Health.js +400 -0
  248. package/dist/esm/Health.js.map +1 -0
  249. package/dist/esm/JevSessionChecker.d.ts +57 -0
  250. package/dist/esm/JevSessionChecker.d.ts.map +1 -0
  251. package/dist/esm/JevSessionChecker.js +108 -0
  252. package/dist/esm/JevSessionChecker.js.map +1 -0
  253. package/dist/esm/Lineage.d.ts +131 -0
  254. package/dist/esm/Lineage.d.ts.map +1 -0
  255. package/dist/esm/Lineage.js +174 -0
  256. package/dist/esm/Lineage.js.map +1 -0
  257. package/dist/esm/Migrations.d.ts +34 -0
  258. package/dist/esm/Migrations.d.ts.map +1 -0
  259. package/dist/esm/Migrations.js +53 -0
  260. package/dist/esm/Migrations.js.map +1 -0
  261. package/dist/esm/Monitor.d.ts +282 -0
  262. package/dist/esm/Monitor.d.ts.map +1 -0
  263. package/dist/esm/Monitor.js +415 -0
  264. package/dist/esm/Monitor.js.map +1 -0
  265. package/dist/esm/ScopedToken.d.ts +193 -0
  266. package/dist/esm/ScopedToken.d.ts.map +1 -0
  267. package/dist/esm/ScopedToken.js +224 -0
  268. package/dist/esm/ScopedToken.js.map +1 -0
  269. package/dist/esm/SqlControlRuntime.d.ts +161 -0
  270. package/dist/esm/SqlControlRuntime.d.ts.map +1 -0
  271. package/dist/esm/SqlControlRuntime.js +1756 -0
  272. package/dist/esm/SqlControlRuntime.js.map +1 -0
  273. package/dist/esm/SqlCredentialStore.d.ts +43 -0
  274. package/dist/esm/SqlCredentialStore.d.ts.map +1 -0
  275. package/dist/esm/SqlCredentialStore.js +97 -0
  276. package/dist/esm/SqlCredentialStore.js.map +1 -0
  277. package/dist/esm/Steering.d.ts +69 -0
  278. package/dist/esm/Steering.d.ts.map +1 -0
  279. package/dist/esm/Steering.js +89 -0
  280. package/dist/esm/Steering.js.map +1 -0
  281. package/dist/esm/SystemFlows.d.ts +223 -0
  282. package/dist/esm/SystemFlows.d.ts.map +1 -0
  283. package/dist/esm/SystemFlows.js +198 -0
  284. package/dist/esm/SystemFlows.js.map +1 -0
  285. package/dist/esm/WebCryptoCipher.d.ts +49 -0
  286. package/dist/esm/WebCryptoCipher.d.ts.map +1 -0
  287. package/dist/esm/WebCryptoCipher.js +123 -0
  288. package/dist/esm/WebCryptoCipher.js.map +1 -0
  289. package/dist/esm/WebhookChannel.d.ts +113 -0
  290. package/dist/esm/WebhookChannel.d.ts.map +1 -0
  291. package/dist/esm/WebhookChannel.js +109 -0
  292. package/dist/esm/WebhookChannel.js.map +1 -0
  293. package/dist/esm/index.d.ts +160 -0
  294. package/dist/esm/index.d.ts.map +1 -0
  295. package/dist/esm/index.js +160 -0
  296. package/dist/esm/index.js.map +1 -0
  297. package/dist/esm/internal/MutationBoundary.d.ts +27 -0
  298. package/dist/esm/internal/MutationBoundary.d.ts.map +1 -0
  299. package/dist/esm/internal/MutationBoundary.js +40 -0
  300. package/dist/esm/internal/MutationBoundary.js.map +1 -0
  301. package/dist/esm/internal/activeFibers.d.ts +12 -0
  302. package/dist/esm/internal/activeFibers.d.ts.map +1 -0
  303. package/dist/esm/internal/activeFibers.js +17 -0
  304. package/dist/esm/internal/activeFibers.js.map +1 -0
  305. package/dist/esm/internal/issues.d.ts +28 -0
  306. package/dist/esm/internal/issues.d.ts.map +1 -0
  307. package/dist/esm/internal/issues.js +35 -0
  308. package/dist/esm/internal/issues.js.map +1 -0
  309. package/dist/esm/internal/planning.d.ts +347 -0
  310. package/dist/esm/internal/planning.d.ts.map +1 -0
  311. package/dist/esm/internal/planning.js +199 -0
  312. package/dist/esm/internal/planning.js.map +1 -0
  313. package/dist/esm/internal/sqlSchemaErrors.d.ts +18 -0
  314. package/dist/esm/internal/sqlSchemaErrors.d.ts.map +1 -0
  315. package/dist/esm/internal/sqlSchemaErrors.js +38 -0
  316. package/dist/esm/internal/sqlSchemaErrors.js.map +1 -0
  317. package/dist/esm/migrations/0001_control_tables.d.ts +18 -0
  318. package/dist/esm/migrations/0001_control_tables.d.ts.map +1 -0
  319. package/dist/esm/migrations/0001_control_tables.js +96 -0
  320. package/dist/esm/migrations/0001_control_tables.js.map +1 -0
  321. package/dist/esm/migrations/0002_run_keys.d.ts +15 -0
  322. package/dist/esm/migrations/0002_run_keys.d.ts.map +1 -0
  323. package/dist/esm/migrations/0002_run_keys.js +22 -0
  324. package/dist/esm/migrations/0002_run_keys.js.map +1 -0
  325. package/dist/esm/migrations/0003_signal_commands.d.ts +13 -0
  326. package/dist/esm/migrations/0003_signal_commands.d.ts.map +1 -0
  327. package/dist/esm/migrations/0003_signal_commands.js +26 -0
  328. package/dist/esm/migrations/0003_signal_commands.js.map +1 -0
  329. package/dist/esm/migrations/0004_approval_decisions.d.ts +13 -0
  330. package/dist/esm/migrations/0004_approval_decisions.d.ts.map +1 -0
  331. package/dist/esm/migrations/0004_approval_decisions.js +25 -0
  332. package/dist/esm/migrations/0004_approval_decisions.js.map +1 -0
  333. package/dist/esm/migrations/0005_signal_principals.d.ts +18 -0
  334. package/dist/esm/migrations/0005_signal_principals.d.ts.map +1 -0
  335. package/dist/esm/migrations/0005_signal_principals.js +27 -0
  336. package/dist/esm/migrations/0005_signal_principals.js.map +1 -0
  337. package/dist/esm/migrations/0006_run_principals.d.ts +18 -0
  338. package/dist/esm/migrations/0006_run_principals.d.ts.map +1 -0
  339. package/dist/esm/migrations/0006_run_principals.js +30 -0
  340. package/dist/esm/migrations/0006_run_principals.js.map +1 -0
  341. package/dist/esm/migrations/0007_resume_consent.d.ts +18 -0
  342. package/dist/esm/migrations/0007_resume_consent.d.ts.map +1 -0
  343. package/dist/esm/migrations/0007_resume_consent.js +27 -0
  344. package/dist/esm/migrations/0007_resume_consent.js.map +1 -0
  345. package/dist/esm/test/TestControl.d.ts +19 -0
  346. package/dist/esm/test/TestControl.d.ts.map +1 -0
  347. package/dist/esm/test/TestControl.js +30 -0
  348. package/dist/esm/test/TestControl.js.map +1 -0
  349. package/docs/README.md +189 -0
  350. package/docs/api.md +982 -0
  351. package/docs/concepts/authority.md +109 -0
  352. package/docs/concepts/cancellation.md +129 -0
  353. package/docs/concepts/lineage.md +132 -0
  354. package/docs/concepts/ownership.md +139 -0
  355. package/docs/concepts/projections.md +203 -0
  356. package/docs/concepts/receipts.md +128 -0
  357. package/docs/guides/approvals.md +284 -0
  358. package/docs/guides/cancel-and-resume.md +162 -0
  359. package/docs/guides/durable-storage.md +147 -0
  360. package/docs/guides/implement-an-executor.md +173 -0
  361. package/docs/guides/ingest-a-webhook.md +177 -0
  362. package/docs/guides/list-runs.md +160 -0
  363. package/docs/guides/monitor-runs.md +176 -0
  364. package/docs/guides/observe-health.md +147 -0
  365. package/docs/guides/postgres-tests.md +5 -0
  366. package/docs/guides/serve-over-rpc.md +220 -0
  367. package/docs/guides/signal-a-run.md +53 -0
  368. package/docs/guides/steer-a-run.md +138 -0
  369. package/docs/guides/store-credentials.md +164 -0
  370. package/docs/guides/testing.md +139 -0
  371. package/docs/guides/watch-a-run.md +154 -0
  372. package/docs/installation.md +106 -0
  373. package/docs/quickstart.md +163 -0
  374. package/docs/troubleshooting.md +208 -0
  375. package/package.json +405 -3
  376. package/src/ApprovalAuthority.ts +114 -0
  377. package/src/Cancellation.ts +172 -0
  378. package/src/Channels.ts +493 -0
  379. package/src/Control.ts +337 -0
  380. package/src/ControlClient.ts +319 -0
  381. package/src/ControlError.ts +378 -0
  382. package/src/ControlExecutor.ts +490 -0
  383. package/src/ControlFacts.ts +383 -0
  384. package/src/ControlLive.ts +2113 -0
  385. package/src/ControlRpcs.ts +443 -0
  386. package/src/ControlRuntime.ts +1597 -0
  387. package/src/ControlSchema.ts +1380 -0
  388. package/src/ControlServer.ts +182 -0
  389. package/src/Credential.ts +310 -0
  390. package/src/CredentialCipher.ts +110 -0
  391. package/src/CredentialStore.ts +152 -0
  392. package/src/DispatchReader.ts +122 -0
  393. package/src/Health.ts +591 -0
  394. package/src/JevSessionChecker.ts +127 -0
  395. package/src/Lineage.ts +203 -0
  396. package/src/Migrations.ts +56 -0
  397. package/src/Monitor.ts +600 -0
  398. package/src/ScopedToken.ts +306 -0
  399. package/src/SqlControlRuntime.ts +2476 -0
  400. package/src/SqlCredentialStore.ts +148 -0
  401. package/src/Steering.ts +96 -0
  402. package/src/SystemFlows.ts +225 -0
  403. package/src/WebCryptoCipher.ts +169 -0
  404. package/src/WebhookChannel.ts +166 -0
  405. package/src/index.ts +188 -0
  406. package/src/internal/MutationBoundary.ts +46 -0
  407. package/src/internal/activeFibers.ts +22 -0
  408. package/src/internal/issues.ts +40 -0
  409. package/src/internal/planning.ts +262 -0
  410. package/src/internal/sqlSchemaErrors.ts +37 -0
  411. package/src/migrations/0001_control_tables.ts +99 -0
  412. package/src/migrations/0002_run_keys.ts +23 -0
  413. package/src/migrations/0003_signal_commands.ts +27 -0
  414. package/src/migrations/0004_approval_decisions.ts +25 -0
  415. package/src/migrations/0005_signal_principals.ts +27 -0
  416. package/src/migrations/0006_run_principals.ts +31 -0
  417. package/src/migrations/0007_resume_consent.ts +28 -0
  418. package/src/test/TestControl.ts +47 -0
@@ -0,0 +1,160 @@
1
+ ---
2
+ title: "Find runs and page through them"
3
+ description: "List the flows a host can plan and the runs it knows about: the run filters, the page bounds a listing enforces, the cursor contract, and the two refusals a listing answers instead of guessing."
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ `list` answers four questions under one verb, selected by the request's tag:
9
+ what can this host plan, what runs exist, which triggers are registered, and
10
+ what became of each trigger occurrence.
11
+
12
+ ## List the flows a host can plan
13
+
14
+ ```ts
15
+ const catalogued = yield * control.list({ _tag: "flows" })
16
+ const flows = catalogued._tag === "flows" ? catalogued.items : []
17
+ // [{ flowId: "ops/Deploy", description: "Deploys one build" }]
18
+ ```
19
+
20
+ The items come from the [registry](/api/registry) when it has discovered
21
+ anything, and fall back to the runtime's own flow catalog when it has not.
22
+ `warnings` carries the registry's discovery diagnostics when a scan produced
23
+ any, so a flow that failed to load is visible rather than silently missing.
24
+
25
+ ## List runs
26
+
27
+ ```ts
28
+ const listed = yield * control.list({ _tag: "runs", filters: { status: "parked" } })
29
+ const runs = listed._tag === "runs" ? listed.items : []
30
+ ```
31
+
32
+ Six filters are supported, and they combine:
33
+
34
+ | Filter | Selects |
35
+ | ------------- | ------------------------------------------------------------ |
36
+ | `runId` | Exactly one run, read directly rather than scanned. |
37
+ | `flowId` | Runs of one flow. |
38
+ | `status` | Runs in one of the seven `RunStatus` values. |
39
+ | `terminal` | `true`: completed, failed or cancelled; `false`: unfinished. |
40
+ | `parentRunId` | The runs one run spawned, forked, or handed off to. |
41
+ | `lineageId` | Every round of one trampoline lineage. |
42
+
43
+ Filtering on `runId` is one read. Other queries filter before decoding the
44
+ selected page. An executor that supplies observed status is post-filtered to
45
+ keep the returned status consistent: a `status` or `terminal` page walks the
46
+ source until it is full, so it can observe more runs than `limit`.
47
+
48
+ Use `order: "newest"` to order by creation time descending, with stable
49
+ sequence/id tie breakers. Omission preserves the historical order. A cursor
50
+ is bound to both its filters and order. For example, duration history asks:
51
+
52
+ ```ts
53
+ const recent = yield * control.list({
54
+ _tag: "runs",
55
+ filters: { flowId: "ops/Deploy", terminal: true },
56
+ order: "newest",
57
+ limit: 20
58
+ })
59
+ ```
60
+
61
+ `filters.principalId` selects the runs a principal with that id launched
62
+ (`RunSummary.launchedBy`). It narrows a listing and is not a tenant boundary:
63
+ over RPC the server already restricts a principal that is not an operator to
64
+ its own runs, whatever filter it sends. See
65
+ [serve over RPC](./serve-over-rpc.md#who-reads-which-runs).
66
+
67
+ ## List triggers and their fires
68
+
69
+ ```ts
70
+ const registered = yield * control.list({ _tag: "triggers", filters: { enabled: true } })
71
+ const triggers = registered._tag === "triggers" ? registered.items : []
72
+ // [{ triggerId: "nightly-lint", flowId: "lint", cron: "0 3 * * *", enabled: true, nextOccurrencesMs: [...], ... }]
73
+
74
+ const ledger = yield * control.list({ _tag: "fires", filters: { runId } })
75
+ const fires = ledger._tag === "fires" ? ledger.items : []
76
+ // [{ triggerId: "nightly-lint", occurrenceAtMs, outcome: "launched", runId }]
77
+ ```
78
+
79
+ `triggers` filters on `triggerId`, `flowId`, and `enabled`; `fires` filters on
80
+ `triggerId`, `runId`, and `outcome`, and the ledger comes back newest first. Both
81
+ are read through the `DispatchReader` port the host composes over its trigger
82
+ store. A host that provides none refuses both variants with `InvalidInput` and
83
+ the issue `this host serves no trigger store`. It never answers an empty page
84
+ for them, because an empty page would claim the host has no triggers when it
85
+ cannot read its store at all.
86
+
87
+ ## Page through the result
88
+
89
+ A listing is bounded, always:
90
+
91
+ | Bound | Value |
92
+ | ----------------- | ------------------------------------ |
93
+ | Default page size | `ControlSchema.defaultPageSize`, 100 |
94
+ | Maximum page size | `ControlSchema.maxPageSize`, 500 |
95
+
96
+ `nextCursor` is present exactly when more rows follow. Pass it back as
97
+ `cursor`:
98
+
99
+ ```ts
100
+ import * as Effect from "effect/Effect"
101
+
102
+ const everyRun = Effect.gen(function*() {
103
+ const control = yield* Control
104
+ const items = []
105
+ let cursor: string | undefined
106
+ do {
107
+ const page = yield* control.list({
108
+ _tag: "runs",
109
+ limit: 200,
110
+ ...(cursor === undefined ? {} : { cursor })
111
+ })
112
+ if (page._tag !== "runs") break
113
+ items.push(...page.items)
114
+ cursor = page.nextCursor
115
+ } while (cursor !== undefined)
116
+ return items
117
+ })
118
+ ```
119
+
120
+ Only a cursor this listing issued is accepted. A `limit` outside 1 to 500, and
121
+ an unparsable cursor, are both refused with `InvalidInput` rather than answered
122
+ with a plausible page:
123
+
124
+ ```text
125
+ InvalidInput: limit: must be an integer between 1 and 500, received 0
126
+ InvalidInput: cursor: must be a cursor this listing returned, received "abc"
127
+ ```
128
+
129
+ ## What a summary carries
130
+
131
+ `RunSummary` is the projection every listing returns. Beyond `runId`,
132
+ `flowId`, `status`, `createdAt`, and `updatedAt`:
133
+
134
+ | Field | Present when |
135
+ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
136
+ | `planId`, `planDigest` | The run was launched from a plan on this plane. |
137
+ | `ownerId` | A process holds the row. |
138
+ | `parentRunId`, `lineageId`, `roundOrdinal`, `origin` | The run has an ancestor. See [run lineage](../concepts/lineage.md). |
139
+ | `waitingReason` | The engine parked the run and named a reason. |
140
+ | `parkedBy` | The park was written under a fence. |
141
+ | `pendingResume` | A resume has been recorded and no host has taken it up. |
142
+ | `steering` | The notification queue answered how many steers are pending. |
143
+ | `cancellation` | Somebody or something cancelled the run. See [cancellation attribution](../concepts/cancellation.md). |
144
+
145
+ `steering.pending` is read from the queue rather than from a column, because
146
+ pending is admitted minus promoted and the queue owns both halves. A queue that
147
+ cannot answer leaves the field absent, because "not known" is representable and
148
+ it is the truth.
149
+
150
+ Several of these fields are filled in only by the durable runtime, and only
151
+ when it shares a database with the engine. See
152
+ [Store control state in a database](./durable-storage.md).
153
+
154
+ ## Where to go next
155
+
156
+ - [Watch a run's events](./watch-a-run.md): the same runs, as they change.
157
+ - [Run lineage](../concepts/lineage.md): what `parentRunId` and `lineageId`
158
+ select.
159
+ - [`smthrs runs list`](/cli/runs) and `smthrs runs show`: the operator
160
+ surface over this verb.
@@ -0,0 +1,176 @@
1
+ ---
2
+ title: "Monitor a run and heal it"
3
+ description: "Classify a run's health from durable evidence, beat over the control plane, and apply a bounded remedy: the seven healths, the two records a beat writes, and why autoHeal is empty by default."
4
+ sidebar:
5
+ order: 10
6
+ ---
7
+
8
+ A control plane answers "what is this run doing". `Monitor` answers the
9
+ question after it: is that all right, and if not, what now.
10
+
11
+ `classify` is pure, so the vocabulary an operator reads on a dashboard is the
12
+ one a heal loop branches on and the one a test can enumerate.
13
+
14
+ ## Classify one observation
15
+
16
+ ```ts
17
+ import * as Monitor from "@smthrs/control/Monitor"
18
+
19
+ Monitor.classify({
20
+ summary,
21
+ events, // the run's journal, oldest first
22
+ beatsWithoutProgress: 3,
23
+ stallBeats: 3
24
+ })
25
+ // "stalled"
26
+ ```
27
+
28
+ The rules run in this order, and each earns its place by naming a different
29
+ response:
30
+
31
+ | Condition | Health | Because |
32
+ | --------------------------------------------- | ---------------- | --------------------------------------------------------------------- |
33
+ | No summary | `unknown` | Nothing to say, and nothing to do. |
34
+ | `failed` | `failing` | The run itself reported the failure. |
35
+ | `completed`, `cancelled` | `healthy` | A finished run needs nothing. |
36
+ | `waiting-approval`, or parked on `approval` | `awaiting-human` | A human owes it an answer. |
37
+ | Parked with no waiting reason | `awaiting-human` | Only an operator's own park writes no reason, so a person stopped it. |
38
+ | `roundOrdinal` at or past `roundBound` | `runaway-loop` | The lineage loops without converging. |
39
+ | The last settled attempt failed | `failing` | The run is alive and its work is not landing. |
40
+ | No progress for `stallBeats`, an attempt open | `wedged-node` | One attempt started and never settled. |
41
+ | No progress for `stallBeats` | `stalled` | Nothing is happening and nothing is in flight. |
42
+ | Anything else | `healthy` | Entries are still arriving. |
43
+
44
+ `awaiting-human` outranks `failing` on purpose. A run parked for approval after
45
+ a failed attempt is waiting for a person, and resuming or cancelling it would
46
+ take the decision away from them. A park with no reason is the same case: the
47
+ engine names every park it makes, so an unnamed one was an operator's, and
48
+ undoing a deliberate act is the worst thing an unattended loop can do.
49
+
50
+ Progress is measured from `flows.engine.attempt-started` and
51
+ `flows.engine.attempt-finished`, which the engine journals as a pair. An excess
52
+ of starts is an attempt still in flight. The classification reads durable
53
+ evidence only, never an in-process fiber, which is what lets a monitor watch a
54
+ run in another process.
55
+
56
+ `roundBound` defaults to 32 rounds.
57
+
58
+ ## Beat over the control plane
59
+
60
+ `Monitor.run` requires `Control` and `Journal`, and nothing else. Its first
61
+ beat reads a finite snapshot. Later beats pass the last `event.cursor` as
62
+ `afterCursor` and fold only new events into an open-attempt count and the last
63
+ attempt outcome. Monitor beat and heal records advance the cursor but do not
64
+ count as progress. Providers that omit cursor metadata use `afterSequence`
65
+ after each completed snapshot. The loop retains no historical event array:
66
+
67
+ ```ts
68
+ const report = yield * Monitor.run({
69
+ runId: "run-17",
70
+ monitorId: "oncall-supervisor",
71
+ intervalMs: 5_000,
72
+ maxChecks: 60,
73
+ stallBeats: 3,
74
+ autoHeal: ["stalled", "wedged-node"]
75
+ })
76
+ // { runId: "run-17", beats: [...], health: "healthy" }
77
+ ```
78
+
79
+ | Option | Default |
80
+ | ------------ | ------------------------------------------------------ |
81
+ | `monitorId` | `default` |
82
+ | `intervalMs` | 1,000 |
83
+ | `maxChecks` | 10 |
84
+ | `stallBeats` | 3 |
85
+ | `roundBound` | 32 |
86
+ | `autoHeal` | none |
87
+ | `heal` | `Control.resume` and `Control.cancel`, per `remedyFor` |
88
+
89
+ Each beat lists the run, replays its journal, classifies, and records
90
+ `control.monitor.beat` carrying the remedy it is about to attempt, _before_
91
+ applying it, so a monitor that crashes mid-heal leaves the evidence of what it
92
+ decided.
93
+
94
+ The remedy is a second record, `control.monitor.healed`, written only once the
95
+ heal returned an `Accepted` or `AlreadyApplied` receipt. A heal that failed,
96
+ was refused as a `Conflict`, or found the run already `Terminal` must not leave
97
+ a durable record saying the run was healed, and only an applied remedy resets
98
+ the stall evidence. A `Terminal` receipt ends the loop, because there is
99
+ nothing left to remedy.
100
+
101
+ Both records are excluded from the progress measurement. A monitor that counted
102
+ its own bookkeeping as progress could never observe a stall: the beat it wrote
103
+ at the top of the loop would be the new entry it congratulated the run for at
104
+ the bottom.
105
+
106
+ ## Choose what it may do
107
+
108
+ `remedyFor` maps a health onto an action, and `autoHeal` decides which of those
109
+ the monitor may actually apply:
110
+
111
+ | Health | Remedy |
112
+ | ------------------------- | -------------------------------------------------------- |
113
+ | `stalled`, `wedged-node` | `resume`: nobody is driving the run, so claim it. |
114
+ | `failing`, `runaway-loop` | `cancel`: it will not get better by being driven harder. |
115
+ | everything else | `none` |
116
+
117
+ `autoHeal` is empty by default, because a monitor that healed by default would
118
+ cancel a run the first time it looked at one.
119
+
120
+ A remedy resets the stall count, so one stall produces one resume rather than
121
+ one per beat.
122
+
123
+ ## Two monitors on one run
124
+
125
+ Nothing on the control plane leases a run to one watcher. Two monitors both
126
+ beat and both remedy, so `monitorId` is what makes their evidence tellable
127
+ apart and their remedies distinct:
128
+
129
+ - Every record this monitor writes has source `/control/monitor/<monitorId>`
130
+ and carries `monitorId` in its payload.
131
+ - The built-in remedies key on
132
+ `monitor:<monitorId>:<remedy>:<runId>:<beat>`.
133
+
134
+ A remedy must be idempotent on the control plane. A custom `heal` owes the same
135
+ property:
136
+
137
+ ```ts
138
+ const report = yield * Monitor.run({
139
+ runId: "run-17",
140
+ autoHeal: ["failing"],
141
+ heal: ({ runId, health, beat }) =>
142
+ control.cancel({
143
+ runId,
144
+ reason: `page-oncall:${health}`,
145
+ idempotencyKey: `oncall:${runId}:${beat}`
146
+ })
147
+ })
148
+ ```
149
+
150
+ ## Alert on what the monitor wrote
151
+
152
+ `Monitor.beatEventType` is a journal kind, so an alert policy in
153
+ [`@smthrs/notifications`](/api/notifications) can detect on it directly:
154
+
155
+ ```ts
156
+ const rules = {
157
+ defaults: { severity: "warning", owner: "oncall" },
158
+ rules: { "wedged-node": { afterMs: 900_000, runbook: "https://runbook/wedged-runs" } },
159
+ detectors: {
160
+ "wedged-node": { field: "health", value: "wedged-node", eventTypes: [Monitor.beatEventType] }
161
+ }
162
+ }
163
+ ```
164
+
165
+ Narrowing the detector to the beat keeps the heal record, which names the same
166
+ health, from reopening a condition the next beat closed. The complete loop, with
167
+ two real durable runs, is
168
+ [`examples/src/38-monitor-and-alert.ts`](https://github.com/smithersai/smithers/blob/main/examples/src/38-monitor-and-alert.ts).
169
+
170
+ ## Where to go next
171
+
172
+ - [Watch a run's events](./watch-a-run.md): the stream a beat reads.
173
+ - [Cancel a run, and restart one](./cancel-and-resume.md): the two default
174
+ remedies.
175
+ - [Test against the control plane](./testing.md): classify is pure, so most of
176
+ a monitor needs no stack at all.
@@ -0,0 +1,147 @@
1
+ # Configure observational health
2
+
3
+ `Health` separates authoritative lifecycle from observed activity, derived health,
4
+ human attention, and reading freshness. A live process is not proof of semantic
5
+ work, and an approval wait always remains an approval wait.
6
+
7
+ Register trusted TypeScript checkers through the native CLI's
8
+ `Application.Config.health`, binding checker IDs to flow IDs. The desktop local
9
+ server accepts the same configuration for role and harness IDs. Pure flow bodies
10
+ and browser requests do not contain executable health functions.
11
+
12
+ ```ts
13
+ import * as Health from "@smthrs/control/Health"
14
+ import { Effect, Schema } from "effect"
15
+
16
+ const Settings = Schema.Struct({ worker: Schema.String })
17
+ declare const inspectWorker: (id: string) => Effect.Effect<Health.ProbeReport, unknown>
18
+
19
+ const checker: Health.HealthChecker<typeof Settings.Type> = {
20
+ id: "worker.activity",
21
+ configSchema: Settings,
22
+ probe: (_context, config) => inspectWorker(config.worker)
23
+ }
24
+
25
+ const health: Health.HealthConfig = {
26
+ checkers: [checker],
27
+ bindings: {
28
+ "build/review": {
29
+ checkerId: "worker.activity",
30
+ config: { worker: "reviewer" },
31
+ policy: { intervalMs: 5_000, timeoutMs: 2_000, ttlMs: 20_000, stallAfterMs: 120_000 }
32
+ }
33
+ },
34
+ limits: { maxSubjects: 128, maxConcurrentProbes: 8 }
35
+ }
36
+ ```
37
+
38
+ Reports contain `activity` (`working`, `idle`, `needs-input`, or `unknown`) and an
39
+ optional closed reason code. Silence and changing terminal output do not establish
40
+ any of these semantics. The lifecycle defaults return unknown activity. Explicit
41
+ `no-progress` or `unreachable` reasons may mark health unhealthy. Known engine
42
+ timer, event, quota, and approval waits retain their authoritative meaning.
43
+
44
+ A run parked on `released` reports `health: "awaiting-human"`,
45
+ `attention: "needs-resume"`, and reason `released`, whatever a probe says. Its
46
+ owner released executions while still alive, usually because the run lease
47
+ lapsed on a stalled host, and nothing restarts them until an operator runs
48
+ `smthrs runs resume <run>`.
49
+
50
+ ## Detect a session waiting on a person
51
+
52
+ `jev.session` is registered in every host, so a binding is the whole opt-in. It is
53
+ registration, not a binding: a host that never names it keeps the lifecycle
54
+ default it had.
55
+
56
+ ```ts
57
+ import * as Health from "@smthrs/control/Health"
58
+
59
+ const health: Health.HealthConfig = {
60
+ bindings: { terminal: { checkerId: "jev.session", exposeOutput: true } }
61
+ }
62
+ ```
63
+
64
+ The desktop local server writes that binding itself: with a subscription evaluator configured
65
+ in its process it binds `jev.session` with `exposeOutput: true` for every session
66
+ subject it resolves, so a session's output tail is sent to the gateway with zero
67
+ data retention; without the key its configuration is exactly what a caller passed,
68
+ and a subject a caller bound keeps that caller's checker. The native CLI host
69
+ observes runs rather than sessions, so it never binds this checker.
70
+
71
+ The checker sends the session's `alive`, `exitCode`, and the newest 4 KiB of its
72
+ output to Jev, TypeSafe's decision model, through the Vercel AI Gateway, with zero
73
+ data retention. Jev answers one choice question (`working`, `idle`, `needs-input`)
74
+ and one boolean question about whether the output ends waiting for a person, both
75
+ in one request that returns in about 300 ms. `exposeOutput: true` is required:
76
+ without it the host sends no tail and the probe answers unknown.
77
+
78
+ An answer becomes a report only at confidence 0.7 or above. TypeSafe claims 76%
79
+ agreement with a human rater, so a Jev that is merely leaning is a coin flip
80
+ dressed as a reading: a false `needs-input` pages a person who is not needed, and
81
+ a false `idle` retires an agent that is still working. `needs-input` carries the
82
+ reason `prompt-detected`, which the rollup turns into `attention: "needs-input"`.
83
+ A reading below the floor is Jev's own answer and stays `unknown`.
84
+
85
+ ## When Jev cannot answer
86
+
87
+ A host that binds `jev.session` supplies its existing evaluator through
88
+ `Health.makeRegistry(config, kind, evaluator)` or
89
+ `JevSessionChecker.makeJevSessionChecker({ evaluator })`. Native hosts resolve
90
+ that judge from their subscription seats. No separate gateway credential is
91
+ read. Without a judge the probe fails with `unconfigured` and remains
92
+ `probe-error`.
93
+
94
+ An unavailable subscription, a plan refusal, a rate limit, a dead socket, an unreadable body and
95
+ the call's own 45 s deadline fail the probe the same way, with the reason that
96
+ names the fault: `http` carrying the provider's status, `unreachable`, `timeout`,
97
+ or `malformed`. `Health.evaluate` records any failing probe as `outcome: "error"`
98
+ with reason `probe-error` and no report, so the rollup reads the subject `stale`
99
+ with activity `unknown`, health `unknown`, and reason `probe-error`, and the
100
+ binding's `backoff` spaces the retries from five up to sixty seconds. A monitor
101
+ that cannot see is worse when it looks calm, so it says so.
102
+
103
+ Two cases are not Jev failing and keep the lifecycle answer: a session that is no
104
+ longer alive, and a session whose output tail the host did not expose. There is
105
+ nothing to ask about either one.
106
+
107
+ The native host admits at most 128 subjects and eight simultaneous probes by
108
+ default. It scans every five seconds, checks each subject every five seconds,
109
+ times out a probe after two seconds, expires observations after twenty seconds,
110
+ and allows two minutes of missing flow progress before classifying it as stalled.
111
+ Failure backoff starts at five seconds and caps at sixty seconds. Per-binding
112
+ policies and host limits are validated before monitoring starts. Unknown checker
113
+ IDs use the lifecycle fallback; malformed configured policies or checker-specific
114
+ configuration fail startup.
115
+
116
+ The host stamps ownership, lifecycle, timing, and evidence position. Reports from
117
+ a changed owner are discarded. A successful observation is recorded under
118
+ `control.status.observed` before publication. Equal evidence positions are ordered
119
+ by durable journal sequence, never by comparing opaque owner identities. Unchanged
120
+ observations are coalesced and renewed before expiry. The gateway's existing
121
+ run-summary projection carries `statusRollup`, and clients expire its semantic
122
+ activity independently if the host stops answering.
123
+
124
+ Native flow monitoring reads events incrementally; the callback receives at most
125
+ 256 recent execution events per beat. Observer/notification bookkeeping does not
126
+ count as progress. Derived gateway projections retain bounded recent health
127
+ observations while preserving their original journal cursor, so repeated probes
128
+ do not exhaust the projection's event budget. Raw run-event history keeps its
129
+ existing resource limits and durable journal retention remains the host's policy.
130
+
131
+ `Health.evaluate` is transport-neutral for other trusted hosts. It returns a
132
+ validated observation as an Effect; the host checks ownership again, commits it,
133
+ and passes `{ observation, sequence }` to `Health.rollup`. `Health.makeRegistry`
134
+ and `registry.resolve(key)` are synchronous constructors. Callback Effects must
135
+ have their service requirements provided before registration.
136
+
137
+ These callbacks are trusted host code, not sandboxed plugins. Read-only context
138
+ types do not constrain captured ambient authority, and cooperative Effect
139
+ interruption cannot preempt arbitrary synchronous JavaScript. Status output omits
140
+ raw exceptions, terminal contents, and arbitrary metrics. Probe outcomes and
141
+ latency are measured by `smithers.health.probes` and
142
+ `smithers.health.probe_duration_ms`; the probe span is `smithers.health.probe`.
143
+
144
+ Checker output never authorizes a control mutation. Production observation starts
145
+ with `autoHeal: []`. Existing Alerts policies can consume recorded status fields
146
+ with an explicitly configured real sink; a status observation alone does not
147
+ claim notification delivery.
@@ -0,0 +1,5 @@
1
+ # PostgreSQL inventory tests
2
+
3
+ The default unit suite needs no PostgreSQL server. Set `SMITHERS_TEST_PG_URL` to run `test/SqlControlRuntimePostgres.test.ts` against a dedicated test database.
4
+
5
+ `//packages/smithers/control:postgresInventory` runs the same assertions on Linux with the `adapterPostgresDatabase` service and loopback networking. It checks filtered inventory pagination, duplicate and absent IDs, empty filters, large ID sets, and time boundaries.