@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
package/CHANGELOG.md ADDED
@@ -0,0 +1,194 @@
1
+ # @smthrs/control
2
+
3
+ ## [Unreleased]
4
+
5
+ ### Added
6
+
7
+ - `ControlExecutor.Service.requestComplete` optionally closes a retained run
8
+ after its last native module completes, through the host executor.
9
+
10
+ - `PlanInput.budget` can override budget fields, including the optional
11
+ `onExceeded` policy. Resume accepts `allowCodeDrift`; run and approval
12
+ operations can also fail with `CodeDrift`. Custom runtime implementations
13
+ must provide `codeDrift`; SQL runtime options accept `currentFlows`
14
+ for checking the current catalog (#1807, #1843).
15
+
16
+ - A run records its flow's `executionDigest` and the host's `engineVersion`
17
+ (`SqlControlRuntime` and memory option `engineVersion`) on `RunSummary`.
18
+ `Control.resume` refuses a run whose flow's digest changed with `CodeDrift`
19
+ before claiming it, unless `allowCodeDrift` is set.
20
+
21
+ - `Health.makeRegistry` takes an optional third argument, `evaluator`: the
22
+ judge the registered `jev.session` checker asks.
23
+
24
+ - `SqlControlRuntime` takes `isAlive`: with it, `resume` takes over a running
25
+ run whose owner is gone (a host killed mid-run) once the dead owner's lease
26
+ has expired, instead of answering `ClaimLost`; the run store verifies the
27
+ expired lease.
28
+
29
+ - `ControlExecutor.makeObserving` wraps an executor for a host that observes
30
+ runs and drives none: `readExecution`, `requestCancel`, `deliverSignal` and
31
+ `settleCancelledPark` pass through, and `launch` and `resumeRun` die. A host
32
+ with no completion judge composes one, so it can list and diagnose runs
33
+ without being able to admit one it could never judge.
34
+
35
+ ### Changed
36
+
37
+ - **Breaking:** `JevSessionChecker` asks the host's `Evaluator` instead of
38
+ calling the Vercel AI Gateway itself. `jevEvaluationUrl`, `jevModelId` and
39
+ the `env`, `fetch` and `url` options are removed; `evaluator` replaces them.
40
+ Without an evaluator the probe fails with reason `unconfigured`.
41
+ `jevRequestTimeoutMs` is now 45000 (was 1500) and `jevProbeTimeoutMs` 50000
42
+ (was 2500).
43
+ - A journal read that fails during `watch` answers `PersistenceError` with
44
+ operation `watch` and the journal's error as its `cause`. It used to answer
45
+ `Unavailable`, which reads as a missing feature. A closed journal still
46
+ answers `Unavailable`.
47
+ - `WebCryptoCipher.open` answers `PersistenceError` with operation
48
+ `credential.open` when a record does not open, naming a malformed nonce or a
49
+ failed authentication (a different key, changed metadata, or tampered
50
+ ciphertext), and logs the reason. `WebCryptoCipher.make` refuses a key that
51
+ is not 32 base64-encoded bytes with `InvalidInput`. Both used to answer
52
+ `Unavailable`, which is now kept for a host without Web Crypto.
53
+ - Breaking: `ApprovalAuthority.local` no longer delegates the in-memory test
54
+ identity `memory`/`test`. A caller naming kind `test` held full approval
55
+ authority under the production default. `ControlRuntime.layerMemory`
56
+ delegates that identity in its own default policy.
57
+ - Removed the 195 internal `@slop` review markers from `src` and the published
58
+ declarations. `test/ReviewMarkers.test.ts` keeps them out.
59
+ - Breaking: approval decisions require an independent `ApprovalAuthority` host
60
+ policy, checked before reads/replay and again at resolution. Custom agent,
61
+ gateway, and operator identities need explicit delegation; attribution and
62
+ authentication alone do not authorize approval. RPC approval errors include
63
+ `Unauthorized`. Policy storage failure leaves the gate closed.
64
+
65
+ - Breaking: approval tokens now expose `Pending`, `Approved`, or `Denied`
66
+ instead of `resolved`. Terminal decisions retain their principal and time;
67
+ approvals also retain scope. `requireApproved` fails closed on pending or
68
+ denied requests. The documented gate no longer proceeds after denial or
69
+ mistakes a storage error for approval.
70
+ - Migration 6004 stores the decision atomically with resolution. Legacy pending
71
+ requests remain pending; old terminal requests that erased their decision are
72
+ refused on recovery. Preserve old evidence and start a new run/request. This
73
+ does not migrate old executable identities or cached gate results.
74
+
75
+ ### Fixed
76
+
77
+ - Durable sequence allocation rejects missing, nonpositive, or unsafe numeric
78
+ readbacks inside its transaction, so storage faults cannot create zero or
79
+ rounded plan, run, or resume identities.
80
+ - Optional SQL table reads fall back only when the driver names that exact
81
+ missing relation. A broken view referencing a similarly named missing table
82
+ now reports a persistence failure instead of silently dropping run ancestry.
83
+
84
+ - Fixed the CommonJS build of the migration set. `migrations/0001_control_tables`
85
+ now exports `initial` as a named binding and every importer reads it by name,
86
+ because esbuild's Node interop for a default import of a sibling module
87
+ resolved to the whole exports object instead of the Effect, so
88
+ `require("@smthrs/control")` failed at load with
89
+ `initial.pipe is not a function`.
90
+
91
+ ## [1.0.0-rc.0] - 2026-09-01
92
+
93
+ ### Added
94
+
95
+ - Added `ControlExecutor`, the port that hands launches, cancellations,
96
+ signals, and resumes to a real run executor, so `ControlLive` drives an
97
+ engine instead of describing one.
98
+ - Added `SqlControlRuntime`, the durable `ControlRuntime` over `@smthrs/journal`
99
+ and the fenced `@smthrs/run-store`, and the credential subsystem behind it
100
+ (`Credential`, `CredentialCipher`, `CredentialStore`, `SqlCredentialStore`,
101
+ `WebCryptoCipher`).
102
+ - Added durable resume delegation: a decided run's restart is recorded for the
103
+ host that owns it and taken up on that host's next poll, rather than claimed
104
+ by a control plane with no executor (triage B-15).
105
+ - Added cancellation attribution: `control.run.cancel-requested` carries the
106
+ authenticated principal and the operator's stated reason, and
107
+ `Cancellation.attribute` folds a run's own evidence and its ancestors' into
108
+ `RunSummary.cancellation`.
109
+ - Added `NoMatchingWait`, so a signal naming a wait point no run has open is
110
+ refused where it arrives instead of being recorded as delivered.
111
+ - Added `Monitor`, which classifies run health from durable evidence and
112
+ applies only the remedies `autoHeal` names.
113
+ - Added `Lineage` and `Steering` projections, so a client reading the journal
114
+ directly reaches the same conclusions the server does.
115
+ - Added `ControlSchema.defaultPageSize`, `ControlSchema.maxPageSize`, and
116
+ `ControlSchema.PageLimit`, so a listing has a documented bound the wire
117
+ enforces.
118
+ - Added `ControlError.ControlErrorSchema` as the single membership list for the
119
+ `ControlError` union, and added `CredentialConflict` to it.
120
+ - Added `SystemFlows.plannable` and a `plannable` marker on every catalog entry,
121
+ so a verb the release policy removed cannot be planned as a flow.
122
+ - Added the namespaced `Migrations` module for every control and credential
123
+ table, while standalone adapters reuse the same idempotent schema source.
124
+
125
+ ### Changed
126
+
127
+ - `Control.run({_tag: "Resume"})` is the same operation as `Control.resume`.
128
+ It used to be a second path that claimed without `scope: "launched"` (which
129
+ overwrote an engine-created run's continuation state), replayed a recorded
130
+ receipt for a run that had since settled, and journaled `control.run.resumed`,
131
+ which the agent bridge reads as an approval delegation.
132
+ - `Control.resume` records the authenticated principal and the stated reason on
133
+ `control.run.resume`, and the `Resume` RPC payload carries `reason` so a local
134
+ and a remote resume no longer differ.
135
+ - `Control.plan` journals `control.plan.created` only when it created a plan.
136
+ `ControlRuntime.plan` returns `{ card, created }` to say which happened.
137
+ - `Control.list` reads one run through `getRun` when `filters.runId` names one,
138
+ instead of projecting every row in the database.
139
+ - `Control.list` refuses `filters.principalId`. It was accepted and applied
140
+ nowhere, so a caller using it as a tenant restriction received every run.
141
+ - `Control.list` refuses a page size that cannot make progress and a cursor it
142
+ did not issue, and applies `defaultPageSize` when the caller names none. A
143
+ zero-sized page used to answer with a cursor a client loops on forever.
144
+ - `Control.steer` refuses a message whose `message.runId` disagrees with the
145
+ run the call names, and records the message's stated `createdAt` on
146
+ `control.steer.enqueued`.
147
+ - `Control.watch` refuses `afterSequence` without `runId`. Journal sequences are
148
+ partition-local, so one scalar cursor applied to every partition skipped
149
+ unseen entries in all of them but its own.
150
+ - Unscoped follow mode now subscribes before pinning one high-water mark per
151
+ partition, then joins the finite snapshot to the buffered tail at those
152
+ marks. The former 1,024-key cache could re-emit old overlap after eviction.
153
+ - A cancel that learns the engine row already settled reconciles the control row
154
+ onto the engine's own status instead of leaving it non-terminal forever.
155
+ - Mutations now snapshot at an inert, schema-decoded 4 MiB boundary before
156
+ their first wait. Durable identity is a fixed-size canonical SHA-256 digest
157
+ scoped to the authenticated actor's stable id and kind; accessors and
158
+ `toJSON` never participate, server timestamps do not split retries, and a
159
+ nested `principal` remains caller intent.
160
+ - `ControlClient` classifies a transport failure by what actually happened. A
161
+ request it could not encode, a response it could not decode, an unusable URL
162
+ and an HTTP 4xx are final; a connection it could not open and an HTTP 5xx are
163
+ retryable. Every failure used to be reported as retryable, carrying the
164
+ transport's own message, so a keyless call was retried after a refusal that
165
+ repeating could not fix. An interrupted call stays interrupted.
166
+ - `Monitor` records `control.monitor.healed` only for an `Accepted` or
167
+ `AlreadyApplied` receipt, stops on a `Terminal` one, and no longer resets its
168
+ stall evidence for a remedy that was refused.
169
+ - `SqlControlRuntime.listRuns` omits a row deleted between reading the id index
170
+ and reading the row, instead of collapsing the whole listing to `[]`.
171
+ - Separately constructed `SqlControlRuntime` instances now mint distinct valid
172
+ default owner identities, so one runtime cannot write through another's
173
+ process fence when a host omits an explicit owner.
174
+ - Channel ingestion snapshots caller-owned bytes and headers before
175
+ verification, and adapters declare the non-secret semantic headers included
176
+ in durable idempotency fingerprints.
177
+ - `SqlControlRuntime.make` is the only exported constructor; the duplicate
178
+ `make_` and the re-exported `FlowId` are gone.
179
+ - Approval tokens and bulk grants use the complete plan or node identity in
180
+ memory and SQL. The SQL storage format now records target kind, run, target
181
+ id, and the authenticated principal that resolved each token.
182
+ - Credential ciphertext authenticates a versioned canonical encoding of its
183
+ stored id, name, and credential version, so blob moves, renames, and version
184
+ rollbacks fail closed.
185
+ - The memory control runtime and credential store copy values at their storage
186
+ boundaries, matching SQL serialization when callers mutate inputs or results.
187
+ - Public control JSDoc points only to documentation paths present in this
188
+ repository.
189
+
190
+ ### Removed
191
+
192
+ - Removed `Control.pause`. The frozen 1.0.0-rc.0 contract has no pause verb; an
193
+ operator park is written through
194
+ `ControlRuntime.writeStatus(runId, fence, "parked")`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 William Cory and the Smithers Flows contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,169 @@
1
- # Temporary Holding Version
1
+ # @smthrs/control
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Release candidate scope, host requirements and compatibility review are defined in the [library support policy](https://github.com/smithersai/smithers/blob/main/RELEASE_SUPPORT.md).
4
+
5
+ This package declares `effect` as an exact
6
+ `4.0.0-rc.115` peer dependency. Keep the application on that version so
7
+ all Smithers packages share one Effect runtime.
8
+
9
+ **Documentation:** https://control.smithers.sh
10
+
11
+ Control services and RPC projections for flows. It defines the
12
+ transport-independent Control service, its runtime and execution ports, local
13
+ and RPC implementations, verified ingress channels, credentials, and the shared
14
+ wire schemas both halves decode.
15
+
16
+ Not on npm yet; see [Installation](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/flow/docs/installation.md#use-the-libraries).
17
+
18
+ The package
19
+ requires Node.js 26.4.0 or later and ships as both ESM and CommonJS with
20
+ TypeScript declarations.
21
+
22
+ It imports no `node:*` module, so the same modules run in Node.js and in a
23
+ browser that supplies a SQL driver. That is a statement about the imports, not
24
+ a tested guarantee: verify your own bundle before you depend on it.
25
+
26
+ The `smthrs` command line, [`@smthrs/cli`](https://cli.smithers.sh), is a host
27
+ over this package: its verbs call the `Control` service defined here and
28
+ nothing else. Install the CLI to drive runs from a shell; install this package
29
+ to build a host of your own, such as a gateway, an MCP server, or a dashboard.
30
+
31
+ ## Public API
32
+
33
+ The root entry point exports these namespaces; each is also importable from
34
+ `@smthrs/control/<Module>`. Every export of every namespace, with its
35
+ signature, is on the [API reference](https://control.smithers.sh/reference/api/).
36
+
37
+ | Namespace | What it is |
38
+ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
39
+ | `Control` | The service: `plan`, `run`, `approve`, `deny`, `steer`, `signal`, `cancel`, `resume`, `list`, `watch`. |
40
+ | `ControlSchema` | The serializable values both halves of the wire decode, and the RPC request schemas. |
41
+ | `ControlError` | Every stable failure, as classes and as one membership schema. |
42
+ | `ControlLive` | The in-process implementation over the runtime, the journal, the notification queue, and the registry. |
43
+ | `ControlRuntime` | The persistence port, plus `layerMemory`. |
44
+ | `SqlControlRuntime` | The durable persistence adapter over a SQL database and the fenced run store. |
45
+ | `ControlExecutor` | The execution port: launch, cancel, signal, resume, and the park settlement a cancel needs. |
46
+ | `DispatchReader` | The trigger read port: registered triggers and the fire ledger `list` pages; `layerNone` refuses. |
47
+ | `ControlRpcs`, `ControlServer`, `ControlClient` | The RPC contract, the HTTP and WebSocket mount, and the client projected back into `Control`. |
48
+ | `ScopedToken` | Scoped, expiring tokens minted under a bearer credential and verified with it. |
49
+ | `Lineage`, `Cancellation`, `Steering` | Pure projections: how a run came to exist, who cancelled it, and when a steer was delivered. |
50
+ | `Monitor` | Run health as a pure classification, and the beat loop that acts on it. |
51
+ | `Health` | Configurable Effect checks, bounded observation policies, provenance, and the shared status rollup. |
52
+ | `JevSessionChecker` | The registered `jev.session` checker: does this session's own output show it waiting on a person? |
53
+ | `Channels`, `WebhookChannel` | Verified ingress: an external request becomes a control mutation, once. |
54
+ | `Credential`, `CredentialStore`, `CredentialCipher` | The credential boundary and its two ports. |
55
+ | `SqlCredentialStore`, `WebCryptoCipher` | Their durable and AES-256-GCM adapters. |
56
+ | `Migrations` | The package's namespaced migration set and the layer that runs it. |
57
+ | `SystemFlows` | The reserved CLI verb to flow-id catalog. |
58
+
59
+ A host that binds `jev.session` supplies its existing evaluator through
60
+ `Health.makeRegistry(config, kind, evaluator)`. Native hosts use a subscription
61
+ seat. Missing configuration, unavailable seats and invalid judgments produce
62
+ `probe-error`, never a healthy result. No gateway key or separate auth path is
63
+ used.
64
+
65
+ ```ts
66
+ import { Control } from "@smthrs/control"
67
+ import { Effect } from "effect"
68
+
69
+ const program = Effect.gen(function*() {
70
+ const control = yield* Control.Control
71
+ return yield* control.list({ _tag: "runs" })
72
+ }).pipe(Effect.provide(Control.layerNoop))
73
+ ```
74
+
75
+ Use `ControlLive.layer` for in-process operation, `ControlClient.layer({ url, credential })`
76
+ for authenticated RPC, or `ControlRuntime.layerMemory()` when assembling a
77
+ deterministic runtime. `@smthrs/control/package.json` is also exported;
78
+ `internal/*` and nested `*/index` subpaths are blocked.
79
+
80
+ ## Receipts and failures
81
+
82
+ Every mutation answers a `ControlSchema.Receipt` rather than throwing on a
83
+ second ask. `Accepted` means this call did the work, `AlreadyApplied` means an
84
+ earlier call under the same idempotency key did, `Conflict` means the key names
85
+ a different intent, `Parked` means the plan is waiting for an approval, and
86
+ `Terminal` means the run had already settled and reports the status it settled
87
+ with.
88
+
89
+ For `signal`, `Accepted` means durable admission. The command and its receipt
90
+ commit before execution observes the payload. Delivery is tracked separately
91
+ by `ControlRuntime.signalCommand`: `pending`, `delivered`, `rejected`, or
92
+ `terminal`. A definite incompatible wait still raises `NoMatchingWait`, and
93
+ that rejected disposition survives retries. Admission emits
94
+ `control.signal.admitted`; queued commands are never announced as delivered.
95
+
96
+ Before its first wait, each mutation copies only bounded JSON own data fields
97
+ and schema-decodes that detached value. Its durable fingerprint is a canonical
98
+ SHA-256 digest, and an authenticated request namespaces its idempotency key by
99
+ the principal's stable `kind` and `id`, not the changing server timestamp.
100
+ Accessors, `toJSON`, sparse arrays, cycles, and non-JSON objects are refused
101
+ with `InvalidInput` before any collaborator sees them.
102
+
103
+ `Channels.ingest` copies inbound bytes and own string header fields before
104
+ verification. A channel lists only the non-secret headers that change its
105
+ decoded command in `fingerprintHeaders`; those names are normalized
106
+ case-insensitively and joined with the body digest. Signature, authorization,
107
+ cookie, token, and credential headers stay outside durable identity. Reusing a
108
+ key with different declared semantics returns `Conflict`, while rotating an
109
+ excluded credential header remains the same delivery.
110
+
111
+ | Verb | Receipts | Typed failures |
112
+ | -------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
113
+ | `plan` | returns a `PlanCard`, not a receipt | `FlowNotFound`, `InvalidInput`, `PersistenceError`, `Unavailable` |
114
+ | `run` (`Plan`) | `Accepted`, `AlreadyApplied`, `Conflict`, `Parked` | `PlanNotFound`, `PlanDenied`, `PlanDigestMismatch`, `EnvelopeMismatch`, `ClaimLost`, `InvalidInput`, `LaunchFailed`, `PersistenceError`, `Unavailable` |
115
+ | `run` (`Resume`), `resume` | `Accepted`, `AlreadyApplied`, `Conflict`, `Terminal` | `RunNotFound`, `ClaimLost`, `CodeDrift`, `InvalidInput`, `PersistenceError`, `Unavailable` |
116
+ | `approve`, `deny` | `Accepted`, `AlreadyApplied`, `Conflict`, `Terminal` | `PlanDigestMismatch`, `EnvelopeMismatch`, `AlreadyResolved`, `PlanNotFound`, `RunNotFound`, `InvalidInput`, `PersistenceError`, `Unavailable` |
117
+ | `steer` | `Accepted`, `AlreadyApplied`, `Conflict`, `Terminal` | `RunNotFound`, `InvalidInput`, `PersistenceError`, `Unavailable` |
118
+ | `signal` | `Accepted`, `AlreadyApplied`, `Conflict`, `Terminal` | `RunNotFound`, `NoMatchingWait`, `InvalidInput`, `PersistenceError`, `Unavailable` |
119
+ | `cancel` | `Accepted`, `Terminal` | `RunNotFound`, `ClaimLost`, `InvalidInput`, `PersistenceError`, `Unavailable` |
120
+ | `list`, `watch` | a page or a stream | every member of `ControlError` |
121
+
122
+ `ControlError.ControlErrorSchema` is the single membership list for the union,
123
+ including `CredentialConflict`, and `ControlClient.isControlError` is derived
124
+ from it. Each class carries a stable `code` (`plan_not_found`, `plan_denied`,
125
+ `run_not_found`, `claim_lost`, `no_matching_wait`, `invalid_input`, and so on)
126
+ that clients may branch on.
127
+
128
+ ## Deployment requirements
129
+
130
+ `SqlControlRuntime` reads the engine's own columns for the projections it
131
+ reports: `flows_runs.waiting_reason`, the `flows_run_parents` spawn edges, fork
132
+ markers and `flows.engine.interrupted` entries in `flows_journal_events`, and
133
+ `cancel_requested_at_ms`. It reads them through the `SqlClient` it was built
134
+ over, so a composition that wants `RunSummary.waitingReason`, engine-created
135
+ children and forks in `list`, or `source: "engine"` cancel attribution must give
136
+ the control runtime and the engine ONE database.
137
+
138
+ The shipped `smthrs` CLI does not: it keeps `.flows/control.db` and
139
+ `.flows/engine.db` as two files, so one run has two rows. Cancellation still
140
+ converges, because the request is recorded on the engine row through the
141
+ `ControlExecutor` port and the owning driver settles from it. The projections
142
+ above are empty there.
143
+
144
+ ## Limits
145
+
146
+ | Bound | Value | Refusal |
147
+ | --------------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
148
+ | `list` page size | `ControlSchema.defaultPageSize` (100) by default, `ControlSchema.maxPageSize` (500) maximum | `InvalidInput` with code `invalid_input`, naming `limit` |
149
+ | `list` cursor | only a cursor a previous page returned | `InvalidInput`, naming `cursor` |
150
+ | `list` run filters | `runId`, `flowId`, `status`, `parentRunId`, `lineageId` | `InvalidInput` for `principalId`, which rc.0 records nothing to evaluate |
151
+ | `list` trigger listings | `triggers` filters `triggerId`, `flowId`, `enabled`; `fires` filters `triggerId`, `runId`, `outcome` | `InvalidInput` naming `this host serves no trigger store` when no `DispatchReader` is provided |
152
+ | `watch` cursor | `afterSequence` requires `runId` | `InvalidInput`, naming `afterSequence` |
153
+ | `watch` follow-mode handoff | one high-water mark per partition present when the watch starts | snapshot rows at or below the mark; buffered tail rows above it |
154
+ | `watch` partition reads | 8 partition snapshots at a time, plus one reserved slot for the live tail | queued, never refused |
155
+ | webhook request body | `WebhookChannel.maximumBodyBytes` (1 MiB), lowered per mount by `handler`'s third argument | `InvalidInput` naming both byte counts, before the read when `content-length` declares it |
156
+ | mutation identity | 4 MiB, 128 levels, 100,000 values and members; idempotency keys are 1 to 1,024 characters | `InvalidInput` before the first wait |
157
+
158
+ A `steer` whose `message.runId` disagrees with the run the call names is
159
+ refused with `InvalidInput` before anything is admitted to the queue.
160
+
161
+ Approval and denial default to the exact identity `local/operator`, for both
162
+ plan and node targets and all grant scopes. The memory adapter's own default
163
+ also delegates its `memory/test` identity. Authentication
164
+ and approval authority are independent: a custom operator identity has no
165
+ authority until the host explicitly delegates it. Hosts may delegate exact
166
+ identity tuples, including agents, with specific target kinds and approval
167
+ scopes. Denial requires a delegated target kind and installs no grant. Callers
168
+ without authority receive `Unauthorized` (`code: "unauthorized"`) before target
169
+ reads or receipt replay. See [who may decide](docs/guides/approvals.md#who-may-decide).
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Host-owned approval authority, separate from principal attribution and from
3
+ * the permissions a workflow receives after approval.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import { Effect, Schema } from "effect";
8
+ import { InvalidInput, type PersistenceError, Unauthorized } from "./ControlError.ts";
9
+ import { type ApprovalTarget, GrantScope, type Principal } from "./ControlSchema.ts";
10
+ /**
11
+ * An approval decision whose caller has already been authenticated by its host.
12
+ * @category models
13
+ * @since 1.0.0
14
+ */
15
+ export interface Request {
16
+ readonly principal: Principal;
17
+ readonly target: ApprovalTarget;
18
+ readonly decision: "approved" | "denied";
19
+ readonly scope: GrantScope;
20
+ }
21
+ /**
22
+ * A trusted host policy. Both refusals and unavailable policy storage fail
23
+ * closed. Implementations must be bounded and safe inside a write transaction;
24
+ * they must not recursively invoke Control or perform the gated work.
25
+ * @category services
26
+ * @since 1.0.0
27
+ */
28
+ export interface Service {
29
+ readonly authorize: (request: Request) => Effect.Effect<void, Unauthorized | PersistenceError>;
30
+ }
31
+ /**
32
+ * An explicit delegation to one authenticated identity, not everyone whose
33
+ * kind resembles a role. Scopes are exact, not implicitly hierarchical. A
34
+ * delegation may approve only its listed scopes and may deny either target
35
+ * kind it names (denial installs no grant).
36
+ * Delegation is reusable: `scopes: ["once"]` permits once-scoped grants, not
37
+ * one lifetime decision. Use a host policy for expiry or one-use delegation.
38
+ * @category schemas
39
+ * @since 1.0.0
40
+ */
41
+ export declare const Delegation: Schema.Struct<{
42
+ readonly principal: Schema.Struct<{
43
+ readonly id: Schema.String;
44
+ readonly kind: Schema.String;
45
+ }>;
46
+ readonly scopes: Schema.$Array<Schema.Literals<readonly ["once", "run", "remembered"]>>;
47
+ readonly targets: Schema.$Array<Schema.Literals<readonly ["Plan", "Node"]>>;
48
+ }>;
49
+ /**
50
+ * One explicit host-owned approval delegation.
51
+ * @category models
52
+ * @since 1.0.0
53
+ */
54
+ export type Delegation = typeof Delegation.Type;
55
+ /**
56
+ * Builds an immutable policy from explicit host configuration. Invalid
57
+ * configuration is refused without including its contents in the error.
58
+ * The caller's arrays and objects are not retained after acquisition.
59
+ * @category constructors
60
+ * @since 1.0.0
61
+ */
62
+ export declare const make: (delegations: ReadonlyArray<Delegation>) => Effect.Effect<Service, InvalidInput>;
63
+ /**
64
+ * Default trusted-local policy. Only the local operator identity is an
65
+ * approver. A custom actor, gateway identity, or agent needs explicit host
66
+ * delegation; setting Principal.kind is not itself an authorization. The
67
+ * in-memory test adapter's `memory`/`test` identity is delegated only by that
68
+ * adapter's own default policy, never here.
69
+ * @category policies
70
+ * @since 1.0.0
71
+ */
72
+ export declare const local: Service;
73
+ //# sourceMappingURL=ApprovalAuthority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApprovalAuthority.d.ts","sourceRoot":"","sources":["../../src/ApprovalAuthority.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrF,OAAO,EAAE,KAAK,cAAc,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEpF;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,QAAQ,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAAC,CAAA;CAC/F;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU;;;;;;;EAIrB,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AA4B/C;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GACf,aAAa,aAAa,CAAC,UAAU,CAAC,KACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAMnC,CAAA;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,KAAK,EAAE,OAElB,CAAA"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var ApprovalAuthority_exports = {};
20
+ __export(ApprovalAuthority_exports, {
21
+ Delegation: () => Delegation,
22
+ local: () => local,
23
+ make: () => make
24
+ });
25
+ module.exports = __toCommonJS(ApprovalAuthority_exports);
26
+ var import_effect = require("effect");
27
+ var import_ControlError = require("./ControlError.js");
28
+ var import_ControlSchema = require("./ControlSchema.js");
29
+ const IdentityPart = import_effect.Schema.String.check(import_effect.Schema.isMinLength(1), import_effect.Schema.isMaxLength(1024));
30
+ const Delegation = import_effect.Schema.Struct({
31
+ principal: import_effect.Schema.Struct({ id: IdentityPart, kind: IdentityPart }),
32
+ scopes: import_effect.Schema.Array(import_ControlSchema.GrantScope).check(import_effect.Schema.isMinLength(1), import_effect.Schema.isMaxLength(3)),
33
+ targets: import_effect.Schema.Array(import_effect.Schema.Literals(["Plan", "Node"])).check(import_effect.Schema.isMinLength(1), import_effect.Schema.isMaxLength(2))
34
+ });
35
+ const identity = (principal) => JSON.stringify([principal.id, principal.kind]);
36
+ const compile = (delegations) => {
37
+ const permissions = /* @__PURE__ */ new Map();
38
+ for (const delegation of delegations) {
39
+ for (const target of delegation.targets) {
40
+ const key = JSON.stringify([identity(delegation.principal), target]);
41
+ const scopes = permissions.get(key) ?? /* @__PURE__ */ new Set();
42
+ for (const scope of delegation.scopes) scopes.add(scope);
43
+ permissions.set(key, scopes);
44
+ }
45
+ }
46
+ return Object.freeze({
47
+ authorize: (request) => import_effect.Effect.suspend(() => {
48
+ const scopes = permissions.get(JSON.stringify([identity(request.principal), request.target._tag]));
49
+ return scopes !== void 0 && (request.decision === "denied" || request.decision === "approved" && scopes.has(request.scope)) ? import_effect.Effect.void : import_effect.Effect.fail(new import_ControlError.Unauthorized({ message: "This caller has no authority to make this approval decision" }));
50
+ })
51
+ });
52
+ };
53
+ const make = (delegations) => import_effect.Schema.decodeUnknownEffect(import_effect.Schema.Array(Delegation).check(import_effect.Schema.isMaxLength(1024)))(delegations, {
54
+ onExcessProperty: "error"
55
+ }).pipe(
56
+ import_effect.Effect.mapError(() => new import_ControlError.InvalidInput({ issue: "Invalid approval-authority delegation configuration" })),
57
+ import_effect.Effect.map(compile)
58
+ );
59
+ const local = compile([
60
+ { principal: { id: "local", kind: "operator" }, scopes: ["once", "run", "remembered"], targets: ["Plan", "Node"] }
61
+ ]);
62
+ //# sourceMappingURL=ApprovalAuthority.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ApprovalAuthority.ts"],
4
+ "sourcesContent": ["/**\n * Host-owned approval authority, separate from principal attribution and from\n * the permissions a workflow receives after approval.\n *\n * @since 1.0.0\n */\n\nimport { Effect, Schema } from \"effect\"\nimport { InvalidInput, type PersistenceError, Unauthorized } from \"./ControlError.ts\"\nimport { type ApprovalTarget, GrantScope, type Principal } from \"./ControlSchema.ts\"\n\n/**\n * An approval decision whose caller has already been authenticated by its host.\n * @category models\n * @since 1.0.0\n */\nexport interface Request {\n readonly principal: Principal\n readonly target: ApprovalTarget\n readonly decision: \"approved\" | \"denied\"\n readonly scope: GrantScope\n}\n\n/**\n * A trusted host policy. Both refusals and unavailable policy storage fail\n * closed. Implementations must be bounded and safe inside a write transaction;\n * they must not recursively invoke Control or perform the gated work.\n * @category services\n * @since 1.0.0\n */\nexport interface Service {\n readonly authorize: (request: Request) => Effect.Effect<void, Unauthorized | PersistenceError>\n}\n\nconst IdentityPart = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(1024))\n\n/**\n * An explicit delegation to one authenticated identity, not everyone whose\n * kind resembles a role. Scopes are exact, not implicitly hierarchical. A\n * delegation may approve only its listed scopes and may deny either target\n * kind it names (denial installs no grant).\n * Delegation is reusable: `scopes: [\"once\"]` permits once-scoped grants, not\n * one lifetime decision. Use a host policy for expiry or one-use delegation.\n * @category schemas\n * @since 1.0.0\n */\nexport const Delegation = Schema.Struct({\n principal: Schema.Struct({ id: IdentityPart, kind: IdentityPart }),\n scopes: Schema.Array(GrantScope).check(Schema.isMinLength(1), Schema.isMaxLength(3)),\n targets: Schema.Array(Schema.Literals([\"Plan\", \"Node\"])).check(Schema.isMinLength(1), Schema.isMaxLength(2))\n})\n\n/**\n * One explicit host-owned approval delegation.\n * @category models\n * @since 1.0.0\n */\nexport type Delegation = typeof Delegation.Type\n\nconst identity = (principal: Pick<Principal, \"id\" | \"kind\">): string => JSON.stringify([principal.id, principal.kind])\n\nconst compile = (delegations: ReadonlyArray<Delegation>): Service => {\n // Separate target keys preserve each delegation's target/scope pairing;\n // unioning both dimensions independently would grant a cross product.\n const permissions = new Map<string, Set<GrantScope>>()\n for (const delegation of delegations) {\n for (const target of delegation.targets) {\n const key = JSON.stringify([identity(delegation.principal), target])\n const scopes = permissions.get(key) ?? new Set<GrantScope>()\n for (const scope of delegation.scopes) scopes.add(scope)\n permissions.set(key, scopes)\n }\n }\n return Object.freeze({\n authorize: (request: Request) =>\n Effect.suspend(() => {\n const scopes = permissions.get(JSON.stringify([identity(request.principal), request.target._tag]))\n return scopes !== undefined &&\n (request.decision === \"denied\" || (request.decision === \"approved\" && scopes.has(request.scope)))\n ? Effect.void\n : Effect.fail(new Unauthorized({ message: \"This caller has no authority to make this approval decision\" }))\n })\n })\n}\n\n/**\n * Builds an immutable policy from explicit host configuration. Invalid\n * configuration is refused without including its contents in the error.\n * The caller's arrays and objects are not retained after acquisition.\n * @category constructors\n * @since 1.0.0\n */\nexport const make = (\n delegations: ReadonlyArray<Delegation>\n): Effect.Effect<Service, InvalidInput> =>\n Schema.decodeUnknownEffect(Schema.Array(Delegation).check(Schema.isMaxLength(1024)))(delegations, {\n onExcessProperty: \"error\"\n }).pipe(\n Effect.mapError(() => new InvalidInput({ issue: \"Invalid approval-authority delegation configuration\" })),\n Effect.map(compile)\n )\n\n/**\n * Default trusted-local policy. Only the local operator identity is an\n * approver. A custom actor, gateway identity, or agent needs explicit host\n * delegation; setting Principal.kind is not itself an authorization. The\n * in-memory test adapter's `memory`/`test` identity is delegated only by that\n * adapter's own default policy, never here.\n * @category policies\n * @since 1.0.0\n */\nexport const local: Service = compile([\n { principal: { id: \"local\", kind: \"operator\" }, scopes: [\"once\", \"run\", \"remembered\"], targets: [\"Plan\", \"Node\"] }\n])\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,oBAA+B;AAC/B,0BAAkE;AAClE,2BAAgE;AAyBhE,MAAM,eAAe,qBAAO,OAAO,MAAM,qBAAO,YAAY,CAAC,GAAG,qBAAO,YAAY,IAAI,CAAC;AAYjF,MAAM,aAAa,qBAAO,OAAO;AAAA,EACtC,WAAW,qBAAO,OAAO,EAAE,IAAI,cAAc,MAAM,aAAa,CAAC;AAAA,EACjE,QAAQ,qBAAO,MAAM,+BAAU,EAAE,MAAM,qBAAO,YAAY,CAAC,GAAG,qBAAO,YAAY,CAAC,CAAC;AAAA,EACnF,SAAS,qBAAO,MAAM,qBAAO,SAAS,CAAC,QAAQ,MAAM,CAAC,CAAC,EAAE,MAAM,qBAAO,YAAY,CAAC,GAAG,qBAAO,YAAY,CAAC,CAAC;AAC7G,CAAC;AASD,MAAM,WAAW,CAAC,cAAsD,KAAK,UAAU,CAAC,UAAU,IAAI,UAAU,IAAI,CAAC;AAErH,MAAM,UAAU,CAAC,gBAAoD;AAGnE,QAAM,cAAc,oBAAI,IAA6B;AACrD,aAAW,cAAc,aAAa;AACpC,eAAW,UAAU,WAAW,SAAS;AACvC,YAAM,MAAM,KAAK,UAAU,CAAC,SAAS,WAAW,SAAS,GAAG,MAAM,CAAC;AACnE,YAAM,SAAS,YAAY,IAAI,GAAG,KAAK,oBAAI,IAAgB;AAC3D,iBAAW,SAAS,WAAW,OAAQ,QAAO,IAAI,KAAK;AACvD,kBAAY,IAAI,KAAK,MAAM;AAAA,IAC7B;AAAA,EACF;AACA,SAAO,OAAO,OAAO;AAAA,IACnB,WAAW,CAAC,YACV,qBAAO,QAAQ,MAAM;AACnB,YAAM,SAAS,YAAY,IAAI,KAAK,UAAU,CAAC,SAAS,QAAQ,SAAS,GAAG,QAAQ,OAAO,IAAI,CAAC,CAAC;AACjG,aAAO,WAAW,WACb,QAAQ,aAAa,YAAa,QAAQ,aAAa,cAAc,OAAO,IAAI,QAAQ,KAAK,KAC9F,qBAAO,OACP,qBAAO,KAAK,IAAI,iCAAa,EAAE,SAAS,8DAA8D,CAAC,CAAC;AAAA,IAC9G,CAAC;AAAA,EACL,CAAC;AACH;AASO,MAAM,OAAO,CAClB,gBAEA,qBAAO,oBAAoB,qBAAO,MAAM,UAAU,EAAE,MAAM,qBAAO,YAAY,IAAI,CAAC,CAAC,EAAE,aAAa;AAAA,EAChG,kBAAkB;AACpB,CAAC,EAAE;AAAA,EACD,qBAAO,SAAS,MAAM,IAAI,iCAAa,EAAE,OAAO,sDAAsD,CAAC,CAAC;AAAA,EACxG,qBAAO,IAAI,OAAO;AACpB;AAWK,MAAM,QAAiB,QAAQ;AAAA,EACpC,EAAE,WAAW,EAAE,IAAI,SAAS,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,OAAO,YAAY,GAAG,SAAS,CAAC,QAAQ,MAAM,EAAE;AACnH,CAAC;",
6
+ "names": []
7
+ }