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

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 +1293 -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 +744 -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 +1522 -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 +1589 -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 +808 -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 +7 -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 +2127 -0
  385. package/src/ControlRpcs.ts +443 -0
  386. package/src/ControlRuntime.ts +1601 -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 +2478 -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,493 @@
1
+ /**
2
+ * Channel contracts and the in-memory channel coordinator.
3
+ *
4
+ * A channel verifies opaque transport data before it decodes or maps it. The
5
+ * resulting request is then dispatched through the Control service; channels
6
+ * do not acquire an execution path of their own.
7
+ *
8
+ * @since 0.1.0
9
+ */
10
+
11
+ import * as Sha256 from "@smthrs/crypto/Sha256"
12
+ import { Clock, Context, Effect, Layer, Ref, type Schema, Semaphore } from "effect"
13
+ import { Control } from "./Control.ts"
14
+ import { type ControlError, InvalidInput, type Unauthorized, Unavailable } from "./ControlError.ts"
15
+ import { ControlRuntime } from "./ControlRuntime.ts"
16
+ import type { FlowId, IdempotencyKey, Receipt, RunId, RunSummary, SignalPayload } from "./ControlSchema.ts"
17
+ import { alreadyApplied } from "./internal/planning.ts"
18
+
19
+ /**
20
+ * Opaque request data passed to a channel before decoding.
21
+ *
22
+ * @category models
23
+ * @since 0.1.0
24
+ */
25
+ export interface RawInbound {
26
+ readonly body: Uint8Array
27
+ readonly headers: Readonly<Record<string, string | undefined>>
28
+ readonly idempotencyKey: IdempotencyKey
29
+ }
30
+
31
+ /**
32
+ * The channel mapping after a verified payload has been decoded.
33
+ *
34
+ * @category models
35
+ * @since 0.1.0
36
+ */
37
+ export type InboundResult =
38
+ | { readonly _tag: "Start"; readonly flowId: FlowId; readonly input: unknown }
39
+ | { readonly _tag: "Signal"; readonly runId: RunId; readonly signal: SignalPayload }
40
+
41
+ /**
42
+ * A process-local per-channel delivery record. `messageId` identifies an existing
43
+ * platform message, so a reconnect can update it instead of posting again.
44
+ *
45
+ * @category models
46
+ * @since 0.1.0
47
+ */
48
+ export interface Delivery {
49
+ readonly cursor: string
50
+ readonly messageId?: string | undefined
51
+ }
52
+
53
+ /**
54
+ * A side-effect-free outbound projection. Network delivery belongs to the
55
+ * transport adapter, which consumes this value after it is journaled.
56
+ *
57
+ * @category models
58
+ * @since 0.1.0
59
+ */
60
+ export interface DeliveryProjection {
61
+ readonly cursor: string
62
+ readonly messageId?: string | undefined
63
+ readonly operation: "post" | "edit" | "noop"
64
+ readonly message: unknown
65
+ }
66
+
67
+ /**
68
+ * A bidirectional platform adapter.
69
+ *
70
+ * `verify` must only inspect opaque bytes and headers. It always precedes
71
+ * `decode`, preventing untrusted public requests from reaching planning.
72
+ *
73
+ * @category services
74
+ * @since 0.1.0
75
+ */
76
+ export interface Channel<A = unknown> {
77
+ readonly name: string
78
+ readonly schema: Schema.Schema<A>
79
+ /**
80
+ * Non-secret HTTP header names whose values change the decoded command.
81
+ * Names are matched case-insensitively and folded into durable idempotency;
82
+ * signature, authorization, and credential headers must not be declared.
83
+ */
84
+ readonly fingerprintHeaders?: ReadonlyArray<string> | undefined
85
+ readonly verify: (raw: RawInbound) => Effect.Effect<void, Unauthorized>
86
+ /** Deterministic, side-effect-free decoding; retries may evaluate it again. */
87
+ readonly decode: (raw: RawInbound) => Effect.Effect<A, InvalidInput>
88
+ /** Deterministic, side-effect-free mapping; retries may evaluate it again. */
89
+ readonly map: (payload: A) => Effect.Effect<InboundResult, InvalidInput>
90
+ readonly project: (run: RunSummary, delivery: Delivery | undefined) => DeliveryProjection
91
+ }
92
+
93
+ /**
94
+ * A registered channel with its payload type hidden. Decoding and mapping stay
95
+ * paired, so lookup never exposes a mapper accepting arbitrary unknown data.
96
+ *
97
+ * @category models
98
+ * @since 1.0.0
99
+ */
100
+ export interface RegisteredChannel extends Omit<Channel, "decode" | "map"> {
101
+ readonly decodeAndMap: (raw: RawInbound) => Effect.Effect<InboundResult, InvalidInput>
102
+ }
103
+
104
+ const eraseChannel = <A>(channel: Channel<A>): RegisteredChannel => ({
105
+ name: channel.name,
106
+ schema: channel.schema,
107
+ fingerprintHeaders: channel.fingerprintHeaders,
108
+ verify: (raw) => channel.verify(raw),
109
+ decodeAndMap: (raw) => Effect.flatMap(channel.decode(raw), (payload) => channel.map(payload)),
110
+ project: (run, delivery) => channel.project(run, delivery)
111
+ })
112
+
113
+ /**
114
+ * Arguments for ingesting one authenticated channel request.
115
+ *
116
+ * @category models
117
+ * @since 0.1.0
118
+ */
119
+ export interface IngestRequest {
120
+ readonly channel: string
121
+ readonly raw: RawInbound
122
+ }
123
+
124
+ /**
125
+ * Arguments for projecting one run onto a channel.
126
+ *
127
+ * @category models
128
+ * @since 0.1.0
129
+ */
130
+ export interface ProjectRequest {
131
+ readonly channel: string
132
+ readonly run: RunSummary
133
+ }
134
+
135
+ /**
136
+ * The channel coordinator.
137
+ *
138
+ * @category services
139
+ * @since 0.1.0
140
+ */
141
+ export interface Channels {
142
+ readonly register: <A>(channel: Channel<A>) => Effect.Effect<void>
143
+ readonly lookup: (name: string) => Effect.Effect<RegisteredChannel, Unavailable>
144
+ readonly ingest: (request: IngestRequest) => Effect.Effect<Receipt, ControlError>
145
+ readonly project: (request: ProjectRequest) => Effect.Effect<DeliveryProjection, Unavailable>
146
+ }
147
+
148
+ /**
149
+ * Service tag for channel registration, ingestion, and pure projection.
150
+ *
151
+ * @category services
152
+ * @since 0.1.0
153
+ */
154
+ export const Channels: Context.Service<Channels, Channels> = Context.Service("/control/Channels")
155
+
156
+ const unavailable = (feature: string): Unavailable =>
157
+ new Unavailable({
158
+ feature,
159
+ ticket: "control-channel-registry"
160
+ })
161
+
162
+ const deliveryKey = (channel: string, run: RunSummary): string => `${channel.length}:${channel}:${run.runId}`
163
+
164
+ /** Collision-free control-plane key for one channel-owned external key. */
165
+ const scopedKey = (channel: string, key: IdempotencyKey): IdempotencyKey =>
166
+ `channel:${channel.length}:${channel}:${key}`
167
+
168
+ const mutationKey = (channel: string, key: IdempotencyKey): IdempotencyKey =>
169
+ `channel.ingest:${scopedKey(channel, key)}`
170
+
171
+ const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype) as object
172
+ const typedArrayBuffer = Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer")?.get
173
+ const typedArrayByteOffset = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteOffset")?.get
174
+ const typedArrayByteLength = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteLength")?.get
175
+
176
+ class InboundBoundaryError extends TypeError {
177
+ readonly issue: string
178
+ constructor(issue: string) {
179
+ super(issue)
180
+ this.issue = issue
181
+ }
182
+ }
183
+
184
+ const boundary = (issue: string): never => {
185
+ throw new InboundBoundaryError(issue)
186
+ }
187
+
188
+ const plainRecord = (input: unknown, path: string): Record<PropertyKey, unknown> => {
189
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
190
+ return boundary(`${path}: must be a plain record`)
191
+ }
192
+ const prototype = Object.getPrototypeOf(input)
193
+ if (prototype !== Object.prototype && prototype !== null) {
194
+ return boundary(`${path}: must have a plain prototype`)
195
+ }
196
+ return input as Record<PropertyKey, unknown>
197
+ }
198
+
199
+ const ownData = (input: Record<PropertyKey, unknown>, key: PropertyKey, path: string): unknown => {
200
+ const descriptor = Object.getOwnPropertyDescriptor(input, key)
201
+ if (descriptor === undefined || !("value" in descriptor)) return boundary(`${path}: must be an own data property`)
202
+ return descriptor.value
203
+ }
204
+
205
+ const copyBody = (input: unknown): Uint8Array => {
206
+ /* v8 ignore next 4 -- every host that has `Uint8Array` has its prototype accessors; the refusal exists so a host without them fails closed rather than reading a caller-owned buffer */
207
+ if (
208
+ typedArrayBuffer === undefined || typedArrayByteOffset === undefined ||
209
+ typedArrayByteLength === undefined
210
+ ) return boundary("raw.body: this host cannot inspect typed arrays")
211
+ try {
212
+ const buffer = Reflect.apply(typedArrayBuffer, input, []) as ArrayBufferLike
213
+ const byteOffset = Reflect.apply(typedArrayByteOffset, input, []) as number
214
+ const byteLength = Reflect.apply(typedArrayByteLength, input, []) as number
215
+ const source = new Uint8Array(buffer, byteOffset, byteLength)
216
+ const snapshot = new Uint8Array(byteLength)
217
+ snapshot.set(source)
218
+ return snapshot
219
+ } catch {
220
+ return boundary("raw.body: must be a Uint8Array")
221
+ }
222
+ }
223
+
224
+ const snapshotHeaders = (input: unknown): Readonly<Record<string, string | undefined>> => {
225
+ const record = plainRecord(input, "raw.headers")
226
+ const snapshot = Object.create(null) as Record<string, string | undefined>
227
+ for (const key of Reflect.ownKeys(record)) {
228
+ if (typeof key !== "string") return boundary("raw.headers: symbol keys are not supported")
229
+ const descriptor = Object.getOwnPropertyDescriptor(record, key)
230
+ if (descriptor === undefined || !("value" in descriptor) || !descriptor.enumerable) {
231
+ return boundary(`raw.headers.${key}: must be an enumerable data property`)
232
+ }
233
+ if (descriptor.value !== undefined && typeof descriptor.value !== "string") {
234
+ return boundary(`raw.headers.${key}: must be a string or undefined`)
235
+ }
236
+ const normalized = key.toLowerCase()
237
+ if (Object.hasOwn(snapshot, normalized)) {
238
+ return boundary(`raw.headers.${normalized}: duplicate case-insensitive name`)
239
+ }
240
+ snapshot[normalized] = descriptor.value as string | undefined
241
+ }
242
+ return Object.freeze(snapshot)
243
+ }
244
+
245
+ const snapshotRequest = (
246
+ input: IngestRequest
247
+ ): Effect.Effect<{ readonly channel: string; readonly raw: RawInbound }, InvalidInput> =>
248
+ Effect.try({
249
+ try: () => {
250
+ const request = plainRecord(input, "request")
251
+ const channel = ownData(request, "channel", "request.channel")
252
+ const candidate = plainRecord(ownData(request, "raw", "request.raw"), "request.raw")
253
+ const idempotencyKey = ownData(candidate, "idempotencyKey", "raw.idempotencyKey")
254
+ if (typeof channel !== "string" || channel.length === 0) return boundary("request.channel: must be non-empty")
255
+ if (typeof idempotencyKey !== "string" || idempotencyKey.length === 0) {
256
+ return boundary("raw.idempotencyKey: must be non-empty")
257
+ }
258
+ return Object.freeze({
259
+ channel,
260
+ raw: Object.freeze({
261
+ body: copyBody(ownData(candidate, "body", "raw.body")),
262
+ headers: snapshotHeaders(ownData(candidate, "headers", "raw.headers")),
263
+ idempotencyKey
264
+ })
265
+ })
266
+ },
267
+ catch: (cause) =>
268
+ new InvalidInput({
269
+ issue: cause instanceof InboundBoundaryError ? cause.issue : "channel request could not be inspected safely"
270
+ })
271
+ })
272
+
273
+ const normalizedFingerprintHeaders = (channel: RegisteredChannel): ReadonlyArray<string> =>
274
+ Array.from(new Set((channel.fingerprintHeaders ?? []).map((name) => name.toLowerCase()))).sort()
275
+
276
+ /** Digests the body plus only the adapter-declared, non-secret semantic headers. */
277
+ const fingerprint = (
278
+ body: Uint8Array,
279
+ headers: Readonly<Record<string, string | undefined>>,
280
+ names: ReadonlyArray<string>
281
+ ): string => {
282
+ const document = JSON.stringify([
283
+ Sha256.digestSync(body),
284
+ names.map((name) => [name, headers[name] ?? null])
285
+ ])
286
+ return `channel-ingress:v2:${Sha256.digestSync(new TextEncoder().encode(document))}`
287
+ }
288
+
289
+ const externalReceipt = (receipt: Receipt, key: IdempotencyKey): Receipt => {
290
+ switch (receipt._tag) {
291
+ case "Accepted":
292
+ case "AlreadyApplied":
293
+ case "Parked":
294
+ return { ...receipt, receiptId: key }
295
+ default:
296
+ return receipt
297
+ }
298
+ }
299
+
300
+ /** The slice of the control runtime's mutation store that inbound idempotency uses. */
301
+ interface InboundReceiptStore {
302
+ readonly lookupMutation: (
303
+ key: IdempotencyKey,
304
+ fingerprint: string
305
+ ) => Effect.Effect<Receipt | undefined, ControlError>
306
+ readonly recordMutation: (
307
+ key: IdempotencyKey,
308
+ fingerprint: string,
309
+ receipt: Receipt
310
+ ) => Effect.Effect<void, ControlError>
311
+ }
312
+
313
+ /**
314
+ * Builds an in-memory channel registry and delivery map over Control's durable
315
+ * mutation store. Inbound idempotency therefore survives coordinator restarts;
316
+ * only registration and outbound projection cursors are process-local.
317
+ */
318
+ const makeWith = (runtime: InboundReceiptStore) =>
319
+ Effect.gen(function*() {
320
+ const channels = yield* Ref.make(new Map<string, RegisteredChannel>())
321
+ const deliveries = new Map<string, Delivery>()
322
+ // Live identities are never evicted. Terminal identities have a FIFO window
323
+ // for reconnects; retaining one per historical run would grow without bound.
324
+ const terminalDeliveries = new Set<string>()
325
+ const maximumTerminalDeliveries = 1024
326
+ const ingestion = yield* Semaphore.make(1)
327
+ const control = yield* Control
328
+
329
+ const lookup = Effect.fn("Channels.lookup")(
330
+ function*(name: string): Effect.fn.Return<RegisteredChannel, Unavailable> {
331
+ return yield* Effect.flatMap(Ref.get(channels), (registered) => {
332
+ const channel = registered.get(name)
333
+ return channel === undefined
334
+ ? Effect.fail(unavailable(`channel "${name}" is not registered`))
335
+ : Effect.succeed(channel)
336
+ })
337
+ }
338
+ )
339
+
340
+ return Channels.of({
341
+ register: Effect.fn("Channels.register")(<A>(channel: Channel<A>) =>
342
+ Ref.update(channels, (registered) => {
343
+ const next = new Map(registered)
344
+ next.set(channel.name, eraseChannel(channel))
345
+ return next
346
+ })
347
+ ),
348
+ lookup,
349
+ ingest: Effect.fn("Channels.ingest")((request) =>
350
+ Effect.flatMap(snapshotRequest(request), (snapshot) =>
351
+ ingestion.withPermits(1)(Effect.gen(function*() {
352
+ const channel = yield* lookup(snapshot.channel)
353
+ const fingerprintHeaders = normalizedFingerprintHeaders(channel)
354
+ const bodyFingerprint = fingerprint(snapshot.raw.body, snapshot.raw.headers, fingerprintHeaders)
355
+ // This ordering is intentional: signature verification is the
356
+ // amplification guard and must happen before decode or Control access.
357
+ // The verifier receives its own body copy, so even a verifier that
358
+ // edits bytes cannot change what the decoder sees after approval.
359
+ yield* channel.verify({ ...snapshot.raw, body: copyBody(snapshot.raw.body) })
360
+ const externalKey = snapshot.raw.idempotencyKey
361
+ const durableKey = mutationKey(snapshot.channel, externalKey)
362
+ const prior = yield* runtime.lookupMutation(durableKey, bodyFingerprint)
363
+ if (prior !== undefined) return externalReceipt(prior, externalKey)
364
+
365
+ const mapped = yield* channel.decodeAndMap(snapshot.raw)
366
+ const key = scopedKey(snapshot.channel, externalKey)
367
+ let receipt: Receipt
368
+ if (mapped._tag === "Signal") {
369
+ // The channel is the caller, not the local operator: a webhook
370
+ // body names the run and wait, so a signal it maps to answers a
371
+ // human wait only if the host delegates approval to this channel.
372
+ receipt = yield* control.signal({
373
+ runId: mapped.runId,
374
+ signal: mapped.signal,
375
+ idempotencyKey: key,
376
+ principal: { id: snapshot.channel, kind: "channel", stampedAt: yield* Clock.currentTimeMillis }
377
+ })
378
+ } else {
379
+ const plan = yield* control.plan({
380
+ flowId: mapped.flowId,
381
+ input: mapped.input,
382
+ idempotencyKey: key
383
+ })
384
+ receipt = yield* control.run({
385
+ _tag: "Plan",
386
+ planId: plan.planId,
387
+ digest: plan.digest,
388
+ envelope: plan.envelope,
389
+ idempotencyKey: key
390
+ })
391
+ }
392
+ // A parked start has not launched. Leave ingress unsettled so a
393
+ // redelivery can retry the same Control key after plan approval.
394
+ if (receipt._tag !== "Conflict" && receipt._tag !== "Parked") {
395
+ yield* runtime.recordMutation(durableKey, bodyFingerprint, receipt)
396
+ }
397
+ return externalReceipt(receipt, externalKey)
398
+ })))
399
+ ),
400
+ project: Effect.fn("Channels.project")(function*(request) {
401
+ const channel = yield* lookup(request.channel)
402
+ const key = deliveryKey(request.channel, request.run)
403
+ // Keep the read, projection and update synchronous so concurrent fibers
404
+ // cannot project from the same stale delivery identity.
405
+ return yield* Effect.sync(() => {
406
+ const prior = deliveries.get(key)
407
+ const projection = channel.project(request.run, prior)
408
+ if (
409
+ projection.operation !== "noop" &&
410
+ (prior === undefined || prior.cursor !== projection.cursor || prior.messageId !== projection.messageId)
411
+ ) {
412
+ deliveries.set(key, { cursor: projection.cursor, messageId: projection.messageId })
413
+ }
414
+ if (deliveries.has(key)) {
415
+ const status = request.run.status
416
+ if (status === "completed" || status === "failed" || status === "cancelled") {
417
+ terminalDeliveries.add(key)
418
+ if (terminalDeliveries.size > maximumTerminalDeliveries) {
419
+ // The set is nonempty because it just exceeded the limit.
420
+ const oldest = terminalDeliveries.values().next().value!
421
+ terminalDeliveries.delete(oldest)
422
+ deliveries.delete(oldest)
423
+ }
424
+ } else {
425
+ terminalDeliveries.delete(key)
426
+ }
427
+ }
428
+ return projection
429
+ })
430
+ })
431
+ })
432
+ })
433
+
434
+ /**
435
+ * Builds the coordinator over Control's durable mutation store.
436
+ *
437
+ * @category constructors
438
+ * @since 1.0.0
439
+ */
440
+ export const make = Effect.gen(function*() {
441
+ const runtime = yield* ControlRuntime
442
+ return yield* makeWith(runtime)
443
+ })
444
+
445
+ /**
446
+ * Builds a process-local coordinator for adapter unit tests.
447
+ *
448
+ * Production hosts use {@link layer}; this constructor deliberately makes no
449
+ * restart guarantee.
450
+ *
451
+ * @category constructors
452
+ * @since 1.0.0
453
+ */
454
+ export const makeMemory = Effect.gen(function*() {
455
+ const records = yield* Ref.make(
456
+ new Map<IdempotencyKey, {
457
+ readonly fingerprint: string
458
+ readonly receipt: Receipt
459
+ }>()
460
+ )
461
+ return yield* makeWith({
462
+ lookupMutation: (key, candidate) =>
463
+ Ref.get(records).pipe(Effect.map((stored) => {
464
+ const prior = stored.get(key)
465
+ if (prior === undefined) return undefined
466
+ return prior.fingerprint === candidate
467
+ ? alreadyApplied(key, prior.receipt)
468
+ : { _tag: "Conflict", message: `idempotency key ${key} was used for another mutation` }
469
+ })),
470
+ recordMutation: (key, candidate, receipt) =>
471
+ Ref.update(records, (stored) => {
472
+ const next = new Map(stored)
473
+ next.set(key, { fingerprint: candidate, receipt })
474
+ return next
475
+ })
476
+ })
477
+ })
478
+
479
+ /**
480
+ * Channel layer with durable inbound receipts supplied by `ControlRuntime`.
481
+ *
482
+ * @category layers
483
+ * @since 0.1.0
484
+ */
485
+ export const layer = Layer.effect(Channels, make)
486
+
487
+ /**
488
+ * Process-local channel layer for adapter unit tests only.
489
+ *
490
+ * @category layers
491
+ * @since 1.0.0
492
+ */
493
+ export const layerMemory: Layer.Layer<Channels, never, Control> = Layer.effect(Channels, makeMemory)