@kelpie/server 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +5 -2
  2. package/dist/index.d.ts +17 -8
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +8 -4
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/actor.d.ts +9 -1
  7. package/dist/lib/actor.d.ts.map +1 -1
  8. package/dist/lib/actor.js +13 -0
  9. package/dist/lib/actor.js.map +1 -1
  10. package/dist/lib/config.d.ts +44 -6
  11. package/dist/lib/config.d.ts.map +1 -1
  12. package/dist/lib/config.js +9 -5
  13. package/dist/lib/config.js.map +1 -1
  14. package/dist/lib/email.d.ts +15 -63
  15. package/dist/lib/email.d.ts.map +1 -1
  16. package/dist/lib/email.js +13 -65
  17. package/dist/lib/email.js.map +1 -1
  18. package/dist/lib/fromEnv.d.ts +60 -0
  19. package/dist/lib/fromEnv.d.ts.map +1 -0
  20. package/dist/lib/fromEnv.js +94 -0
  21. package/dist/lib/fromEnv.js.map +1 -0
  22. package/dist/lib/ids.d.ts +6 -0
  23. package/dist/lib/ids.d.ts.map +1 -1
  24. package/dist/lib/ids.js +6 -0
  25. package/dist/lib/ids.js.map +1 -1
  26. package/dist/lib/kelpieConfigFile.d.ts +123 -0
  27. package/dist/lib/kelpieConfigFile.d.ts.map +1 -0
  28. package/dist/lib/kelpieConfigFile.js +111 -0
  29. package/dist/lib/kelpieConfigFile.js.map +1 -0
  30. package/dist/lib/logger.d.ts +38 -7
  31. package/dist/lib/logger.d.ts.map +1 -1
  32. package/dist/lib/logger.js +58 -20
  33. package/dist/lib/logger.js.map +1 -1
  34. package/dist/modules/agent-tasks/index.d.ts.map +1 -1
  35. package/dist/modules/agent-tasks/index.js +4 -1
  36. package/dist/modules/agent-tasks/index.js.map +1 -1
  37. package/dist/modules/agent-tasks/prompt.d.ts +36 -6
  38. package/dist/modules/agent-tasks/prompt.d.ts.map +1 -1
  39. package/dist/modules/agent-tasks/prompt.js +33 -4
  40. package/dist/modules/agent-tasks/prompt.js.map +1 -1
  41. package/dist/modules/agent-tasks/service.d.ts.map +1 -1
  42. package/dist/modules/agent-tasks/service.js +3 -2
  43. package/dist/modules/agent-tasks/service.js.map +1 -1
  44. package/dist/modules/agent-tasks/wire.d.ts +11 -0
  45. package/dist/modules/agent-tasks/wire.d.ts.map +1 -1
  46. package/dist/modules/agent-tasks/wire.js +1 -0
  47. package/dist/modules/agent-tasks/wire.js.map +1 -1
  48. package/dist/modules/auth/index.d.ts.map +1 -1
  49. package/dist/modules/auth/index.js +8 -7
  50. package/dist/modules/auth/index.js.map +1 -1
  51. package/dist/modules/companies/events.d.ts +22 -0
  52. package/dist/modules/companies/events.d.ts.map +1 -0
  53. package/dist/modules/companies/events.js +8 -0
  54. package/dist/modules/companies/events.js.map +1 -0
  55. package/dist/modules/companies/index.d.ts.map +1 -1
  56. package/dist/modules/companies/index.js +2 -0
  57. package/dist/modules/companies/index.js.map +1 -1
  58. package/dist/modules/companies/service.d.ts +1 -0
  59. package/dist/modules/companies/service.d.ts.map +1 -1
  60. package/dist/modules/companies/service.js +8 -11
  61. package/dist/modules/companies/service.js.map +1 -1
  62. package/dist/modules/core.d.ts.map +1 -1
  63. package/dist/modules/core.js +4 -0
  64. package/dist/modules/core.js.map +1 -1
  65. package/dist/modules/deals/events.d.ts +31 -0
  66. package/dist/modules/deals/events.d.ts.map +1 -0
  67. package/dist/modules/deals/events.js +12 -0
  68. package/dist/modules/deals/events.js.map +1 -0
  69. package/dist/modules/deals/index.d.ts.map +1 -1
  70. package/dist/modules/deals/index.js +2 -0
  71. package/dist/modules/deals/index.js.map +1 -1
  72. package/dist/modules/deals/service.d.ts +1 -0
  73. package/dist/modules/deals/service.d.ts.map +1 -1
  74. package/dist/modules/deals/service.js +9 -18
  75. package/dist/modules/deals/service.js.map +1 -1
  76. package/dist/modules/decisions/events.d.ts +21 -0
  77. package/dist/modules/decisions/events.d.ts.map +1 -0
  78. package/dist/modules/decisions/events.js +11 -0
  79. package/dist/modules/decisions/events.js.map +1 -0
  80. package/dist/modules/decisions/index.d.ts.map +1 -1
  81. package/dist/modules/decisions/index.js +2 -0
  82. package/dist/modules/decisions/index.js.map +1 -1
  83. package/dist/modules/decisions/service.d.ts +1 -0
  84. package/dist/modules/decisions/service.d.ts.map +1 -1
  85. package/dist/modules/decisions/service.js +4 -7
  86. package/dist/modules/decisions/service.js.map +1 -1
  87. package/dist/modules/forms/events.d.ts +37 -0
  88. package/dist/modules/forms/events.d.ts.map +1 -0
  89. package/dist/modules/forms/events.js +15 -0
  90. package/dist/modules/forms/events.js.map +1 -0
  91. package/dist/modules/forms/index.d.ts.map +1 -1
  92. package/dist/modules/forms/index.js +2 -0
  93. package/dist/modules/forms/index.js.map +1 -1
  94. package/dist/modules/forms/service.d.ts +1 -0
  95. package/dist/modules/forms/service.d.ts.map +1 -1
  96. package/dist/modules/forms/service.js +8 -11
  97. package/dist/modules/forms/service.js.map +1 -1
  98. package/dist/modules/forms/submission.d.ts +5 -0
  99. package/dist/modules/forms/submission.d.ts.map +1 -1
  100. package/dist/modules/forms/submission.js +54 -28
  101. package/dist/modules/forms/submission.js.map +1 -1
  102. package/dist/modules/handbook/events.d.ts +28 -0
  103. package/dist/modules/handbook/events.d.ts.map +1 -0
  104. package/dist/modules/handbook/events.js +14 -0
  105. package/dist/modules/handbook/events.js.map +1 -0
  106. package/dist/modules/handbook/index.d.ts.map +1 -1
  107. package/dist/modules/handbook/index.js +2 -0
  108. package/dist/modules/handbook/index.js.map +1 -1
  109. package/dist/modules/handbook/service.d.ts +1 -0
  110. package/dist/modules/handbook/service.d.ts.map +1 -1
  111. package/dist/modules/handbook/service.js +8 -15
  112. package/dist/modules/handbook/service.js.map +1 -1
  113. package/dist/modules/hiring/candidates.d.ts +1 -0
  114. package/dist/modules/hiring/candidates.d.ts.map +1 -1
  115. package/dist/modules/hiring/candidates.js +8 -11
  116. package/dist/modules/hiring/candidates.js.map +1 -1
  117. package/dist/modules/hiring/events.d.ts +35 -0
  118. package/dist/modules/hiring/events.d.ts.map +1 -0
  119. package/dist/modules/hiring/events.js +11 -0
  120. package/dist/modules/hiring/events.js.map +1 -0
  121. package/dist/modules/hiring/index.d.ts.map +1 -1
  122. package/dist/modules/hiring/index.js +2 -0
  123. package/dist/modules/hiring/index.js.map +1 -1
  124. package/dist/modules/hiring/roles.d.ts +1 -0
  125. package/dist/modules/hiring/roles.d.ts.map +1 -1
  126. package/dist/modules/hiring/roles.js +8 -11
  127. package/dist/modules/hiring/roles.js.map +1 -1
  128. package/dist/modules/import-export/events.d.ts +22 -0
  129. package/dist/modules/import-export/events.d.ts.map +1 -0
  130. package/dist/modules/import-export/events.js +12 -0
  131. package/dist/modules/import-export/events.js.map +1 -0
  132. package/dist/modules/import-export/index.d.ts.map +1 -1
  133. package/dist/modules/import-export/index.js +2 -0
  134. package/dist/modules/import-export/index.js.map +1 -1
  135. package/dist/modules/import-export/service.d.ts +5 -0
  136. package/dist/modules/import-export/service.d.ts.map +1 -1
  137. package/dist/modules/import-export/service.js +53 -14
  138. package/dist/modules/import-export/service.js.map +1 -1
  139. package/dist/modules/notes/events.d.ts +22 -0
  140. package/dist/modules/notes/events.d.ts.map +1 -0
  141. package/dist/modules/notes/events.js +12 -0
  142. package/dist/modules/notes/events.js.map +1 -0
  143. package/dist/modules/notes/index.d.ts.map +1 -1
  144. package/dist/modules/notes/index.js +2 -0
  145. package/dist/modules/notes/index.js.map +1 -1
  146. package/dist/modules/notes/service.d.ts +1 -0
  147. package/dist/modules/notes/service.d.ts.map +1 -1
  148. package/dist/modules/notes/service.js +4 -7
  149. package/dist/modules/notes/service.js.map +1 -1
  150. package/dist/modules/opportunities/events.d.ts +31 -0
  151. package/dist/modules/opportunities/events.d.ts.map +1 -0
  152. package/dist/modules/opportunities/events.js +12 -0
  153. package/dist/modules/opportunities/events.js.map +1 -0
  154. package/dist/modules/opportunities/index.d.ts.map +1 -1
  155. package/dist/modules/opportunities/index.js +2 -0
  156. package/dist/modules/opportunities/index.js.map +1 -1
  157. package/dist/modules/opportunities/service.d.ts +1 -0
  158. package/dist/modules/opportunities/service.d.ts.map +1 -1
  159. package/dist/modules/opportunities/service.js +9 -18
  160. package/dist/modules/opportunities/service.js.map +1 -1
  161. package/dist/modules/partnerships/events.d.ts +31 -0
  162. package/dist/modules/partnerships/events.d.ts.map +1 -0
  163. package/dist/modules/partnerships/events.js +12 -0
  164. package/dist/modules/partnerships/events.js.map +1 -0
  165. package/dist/modules/partnerships/index.d.ts.map +1 -1
  166. package/dist/modules/partnerships/index.js +2 -0
  167. package/dist/modules/partnerships/index.js.map +1 -1
  168. package/dist/modules/partnerships/service.d.ts +1 -0
  169. package/dist/modules/partnerships/service.d.ts.map +1 -1
  170. package/dist/modules/partnerships/service.js +9 -18
  171. package/dist/modules/partnerships/service.js.map +1 -1
  172. package/dist/modules/people/events.d.ts +28 -0
  173. package/dist/modules/people/events.d.ts.map +1 -0
  174. package/dist/modules/people/events.js +18 -0
  175. package/dist/modules/people/events.js.map +1 -0
  176. package/dist/modules/people/index.d.ts.map +1 -1
  177. package/dist/modules/people/index.js +2 -0
  178. package/dist/modules/people/index.js.map +1 -1
  179. package/dist/modules/people/service.d.ts +1 -0
  180. package/dist/modules/people/service.d.ts.map +1 -1
  181. package/dist/modules/people/service.js +8 -11
  182. package/dist/modules/people/service.js.map +1 -1
  183. package/dist/modules/pipelines/service.d.ts +4 -0
  184. package/dist/modules/pipelines/service.d.ts.map +1 -1
  185. package/dist/modules/pipelines/service.js +31 -8
  186. package/dist/modules/pipelines/service.js.map +1 -1
  187. package/dist/modules/plans/events.d.ts +21 -0
  188. package/dist/modules/plans/events.d.ts.map +1 -0
  189. package/dist/modules/plans/events.js +11 -0
  190. package/dist/modules/plans/events.js.map +1 -0
  191. package/dist/modules/plans/index.d.ts.map +1 -1
  192. package/dist/modules/plans/index.js +2 -0
  193. package/dist/modules/plans/index.js.map +1 -1
  194. package/dist/modules/plans/service.d.ts +1 -0
  195. package/dist/modules/plans/service.d.ts.map +1 -1
  196. package/dist/modules/plans/service.js +6 -14
  197. package/dist/modules/plans/service.js.map +1 -1
  198. package/dist/modules/positions/events.d.ts +22 -0
  199. package/dist/modules/positions/events.d.ts.map +1 -0
  200. package/dist/modules/positions/events.js +8 -0
  201. package/dist/modules/positions/events.js.map +1 -0
  202. package/dist/modules/positions/index.d.ts.map +1 -1
  203. package/dist/modules/positions/index.js +2 -0
  204. package/dist/modules/positions/index.js.map +1 -1
  205. package/dist/modules/positions/service.d.ts +1 -0
  206. package/dist/modules/positions/service.d.ts.map +1 -1
  207. package/dist/modules/positions/service.js +8 -11
  208. package/dist/modules/positions/service.js.map +1 -1
  209. package/dist/modules/raises/events.d.ts +31 -0
  210. package/dist/modules/raises/events.d.ts.map +1 -0
  211. package/dist/modules/raises/events.js +12 -0
  212. package/dist/modules/raises/events.js.map +1 -0
  213. package/dist/modules/raises/index.d.ts.map +1 -1
  214. package/dist/modules/raises/index.js +2 -0
  215. package/dist/modules/raises/index.js.map +1 -1
  216. package/dist/modules/raises/service.d.ts +1 -0
  217. package/dist/modules/raises/service.d.ts.map +1 -1
  218. package/dist/modules/raises/service.js +9 -18
  219. package/dist/modules/raises/service.js.map +1 -1
  220. package/dist/modules/reseal.d.ts +55 -0
  221. package/dist/modules/reseal.d.ts.map +1 -1
  222. package/dist/modules/reseal.js +90 -1
  223. package/dist/modules/reseal.js.map +1 -1
  224. package/dist/modules/smtp-email/index.d.ts +69 -0
  225. package/dist/modules/smtp-email/index.d.ts.map +1 -0
  226. package/dist/modules/smtp-email/index.js +82 -0
  227. package/dist/modules/smtp-email/index.js.map +1 -0
  228. package/dist/modules/webhooks/index.d.ts.map +1 -1
  229. package/dist/modules/webhooks/index.js +5 -1
  230. package/dist/modules/webhooks/index.js.map +1 -1
  231. package/dist/modules/webhooks/payloads.d.ts +22 -7
  232. package/dist/modules/webhooks/payloads.d.ts.map +1 -1
  233. package/dist/modules/webhooks/payloads.js +63 -44
  234. package/dist/modules/webhooks/payloads.js.map +1 -1
  235. package/dist/modules/workspace/events.d.ts +52 -0
  236. package/dist/modules/workspace/events.d.ts.map +1 -0
  237. package/dist/modules/workspace/events.js +16 -0
  238. package/dist/modules/workspace/events.js.map +1 -0
  239. package/dist/modules/workspace/index.d.ts.map +1 -1
  240. package/dist/modules/workspace/index.js +6 -2
  241. package/dist/modules/workspace/index.js.map +1 -1
  242. package/dist/modules/workspace/service.d.ts +1 -0
  243. package/dist/modules/workspace/service.d.ts.map +1 -1
  244. package/dist/modules/workspace/service.js +13 -15
  245. package/dist/modules/workspace/service.js.map +1 -1
  246. package/dist/runtime/events.d.ts +86 -108
  247. package/dist/runtime/events.d.ts.map +1 -1
  248. package/dist/runtime/events.js +123 -52
  249. package/dist/runtime/events.js.map +1 -1
  250. package/dist/runtime/module.d.ts +54 -2
  251. package/dist/runtime/module.d.ts.map +1 -1
  252. package/dist/runtime/registry.d.ts +23 -0
  253. package/dist/runtime/registry.d.ts.map +1 -1
  254. package/dist/runtime/registry.js +102 -2
  255. package/dist/runtime/registry.js.map +1 -1
  256. package/dist/runtime/transaction.d.ts +29 -4
  257. package/dist/runtime/transaction.d.ts.map +1 -1
  258. package/dist/runtime/transaction.js +48 -7
  259. package/dist/runtime/transaction.js.map +1 -1
  260. package/dist/testing/app.d.ts.map +1 -1
  261. package/dist/testing/app.js +11 -3
  262. package/dist/testing/app.js.map +1 -1
  263. package/dist/testing/database.d.ts.map +1 -1
  264. package/dist/testing/database.js +6 -3
  265. package/dist/testing/database.js.map +1 -1
  266. package/dist/testing/services.d.ts +21 -1
  267. package/dist/testing/services.d.ts.map +1 -1
  268. package/dist/testing/services.js +20 -5
  269. package/dist/testing/services.js.map +1 -1
  270. package/package.json +5 -2
  271. package/src/index.ts +44 -9
  272. package/src/lib/actor.ts +15 -1
  273. package/src/lib/config.ts +56 -7
  274. package/src/lib/email.ts +22 -92
  275. package/src/lib/fromEnv.ts +143 -0
  276. package/src/lib/ids.ts +6 -0
  277. package/src/lib/kelpieConfigFile.ts +283 -0
  278. package/src/lib/logger.ts +92 -34
  279. package/src/modules/agent-tasks/index.ts +4 -1
  280. package/src/modules/agent-tasks/prompt.ts +57 -9
  281. package/src/modules/agent-tasks/service.ts +3 -2
  282. package/src/modules/agent-tasks/wire.ts +12 -0
  283. package/src/modules/auth/index.ts +11 -9
  284. package/src/modules/companies/events.ts +25 -0
  285. package/src/modules/companies/index.ts +2 -0
  286. package/src/modules/companies/service.ts +8 -11
  287. package/src/modules/core.ts +4 -0
  288. package/src/modules/deals/events.ts +34 -0
  289. package/src/modules/deals/index.ts +2 -0
  290. package/src/modules/deals/service.ts +17 -18
  291. package/src/modules/decisions/events.ts +24 -0
  292. package/src/modules/decisions/index.ts +2 -0
  293. package/src/modules/decisions/service.ts +8 -7
  294. package/src/modules/forms/events.ts +37 -0
  295. package/src/modules/forms/index.ts +2 -0
  296. package/src/modules/forms/service.ts +12 -11
  297. package/src/modules/forms/submission.ts +80 -29
  298. package/src/modules/handbook/events.ts +31 -0
  299. package/src/modules/handbook/index.ts +2 -0
  300. package/src/modules/handbook/service.ts +8 -15
  301. package/src/modules/hiring/candidates.ts +8 -11
  302. package/src/modules/hiring/events.ts +36 -0
  303. package/src/modules/hiring/index.ts +2 -0
  304. package/src/modules/hiring/roles.ts +8 -11
  305. package/src/modules/import-export/events.ts +25 -0
  306. package/src/modules/import-export/index.ts +2 -0
  307. package/src/modules/import-export/service.ts +83 -15
  308. package/src/modules/notes/events.ts +25 -0
  309. package/src/modules/notes/index.ts +2 -0
  310. package/src/modules/notes/service.ts +8 -7
  311. package/src/modules/opportunities/events.ts +34 -0
  312. package/src/modules/opportunities/index.ts +2 -0
  313. package/src/modules/opportunities/service.ts +17 -18
  314. package/src/modules/partnerships/events.ts +34 -0
  315. package/src/modules/partnerships/index.ts +2 -0
  316. package/src/modules/partnerships/service.ts +17 -18
  317. package/src/modules/people/events.ts +36 -0
  318. package/src/modules/people/index.ts +2 -0
  319. package/src/modules/people/service.ts +97 -87
  320. package/src/modules/pipelines/service.ts +47 -8
  321. package/src/modules/plans/events.ts +24 -0
  322. package/src/modules/plans/index.ts +2 -0
  323. package/src/modules/plans/service.ts +14 -14
  324. package/src/modules/positions/events.ts +25 -0
  325. package/src/modules/positions/index.ts +2 -0
  326. package/src/modules/positions/service.ts +8 -11
  327. package/src/modules/raises/events.ts +34 -0
  328. package/src/modules/raises/index.ts +2 -0
  329. package/src/modules/raises/service.ts +17 -18
  330. package/src/modules/reseal.ts +144 -1
  331. package/src/modules/smtp-email/index.ts +119 -0
  332. package/src/modules/webhooks/index.ts +5 -1
  333. package/src/modules/webhooks/payloads.ts +94 -48
  334. package/src/modules/workspace/events.ts +46 -0
  335. package/src/modules/workspace/index.ts +6 -2
  336. package/src/modules/workspace/service.ts +37 -15
  337. package/src/runtime/events.ts +268 -107
  338. package/src/runtime/module.ts +55 -2
  339. package/src/runtime/registry.ts +169 -1
  340. package/src/runtime/transaction.ts +94 -17
  341. package/src/testing/app.ts +11 -3
  342. package/src/testing/database.ts +6 -3
  343. package/src/testing/services.ts +34 -5
@@ -0,0 +1,94 @@
1
+ /**
2
+ * A marker a `kelpie.config.ts` file uses to say "read this leaf from the
3
+ * environment." The assembly's config file is the shape and the defaults;
4
+ * `fromEnv` marks the leaves a deployment may override without a code change.
5
+ *
6
+ * Every marker names an env var, the Zod schema that parses it, and optionally
7
+ * a default. Without a default the marker is required: the env var must be set,
8
+ * or boot fails with the other configuration problems.
9
+ *
10
+ * The resolver walks the config object, replaces each marker with the parsed
11
+ * value, and returns the fully-resolved object. Nothing in the app reads
12
+ * `process.env` for these fields after boot.
13
+ */
14
+ const FROM_ENV_MARKER = Symbol.for('kelpie.fromEnv');
15
+ export function fromEnv(envKey, schema, defaultValue) {
16
+ const hasDefault = arguments.length >= 3;
17
+ return {
18
+ [FROM_ENV_MARKER]: true,
19
+ envKey,
20
+ schema,
21
+ defaultValue: hasDefault ? defaultValue : undefined,
22
+ hasDefault,
23
+ };
24
+ }
25
+ export function isFromEnvMarker(value) {
26
+ return typeof value === 'object' && value !== null && value[FROM_ENV_MARKER] === true;
27
+ }
28
+ /**
29
+ * Resolves one marker against an environment.
30
+ *
31
+ * Missing and no default: one required problem.
32
+ * Missing with default: the default, unvalidated. A hardcoded default is
33
+ * trusted because the developer wrote it in the assembly file.
34
+ * Present: parsed through the marker's schema. Parse failures become problems.
35
+ */
36
+ export function resolveMarker(marker, environment, path) {
37
+ const raw = environment[marker.envKey];
38
+ if (raw === undefined) {
39
+ if (marker.hasDefault) {
40
+ return { value: marker.defaultValue, problems: [] };
41
+ }
42
+ return {
43
+ value: undefined,
44
+ problems: [{ path, message: `${marker.envKey} is required` }],
45
+ };
46
+ }
47
+ const result = marker.schema.safeParse(raw);
48
+ if (!result.success) {
49
+ return {
50
+ value: undefined,
51
+ problems: result.error.issues.map((issue) => ({
52
+ path,
53
+ message: `${marker.envKey}: ${issue.message}`,
54
+ })),
55
+ };
56
+ }
57
+ return { value: result.data, problems: [] };
58
+ }
59
+ /**
60
+ * Walks any value, replacing every `FromEnvMarker` with its resolved value.
61
+ * Objects and arrays are walked recursively; other values pass through.
62
+ *
63
+ * Collects problems from every marker rather than throwing at the first one,
64
+ * so a self-hoster fixes their environment once rather than a variable at a
65
+ * time.
66
+ */
67
+ export function resolveMarkers(input, environment, path = '') {
68
+ if (isFromEnvMarker(input)) {
69
+ return resolveMarker(input, environment, path);
70
+ }
71
+ if (Array.isArray(input)) {
72
+ const problems = [];
73
+ const value = input.map((item, index) => {
74
+ const childPath = `${path}[${String(index)}]`;
75
+ const result = resolveMarkers(item, environment, childPath);
76
+ problems.push(...result.problems);
77
+ return result.value;
78
+ });
79
+ return { value, problems };
80
+ }
81
+ if (typeof input === 'object' && input !== null) {
82
+ const problems = [];
83
+ const value = {};
84
+ for (const [key, child] of Object.entries(input)) {
85
+ const childPath = path.length > 0 ? `${path}.${key}` : key;
86
+ const result = resolveMarkers(child, environment, childPath);
87
+ problems.push(...result.problems);
88
+ value[key] = result.value;
89
+ }
90
+ return { value, problems };
91
+ }
92
+ return { value: input, problems: [] };
93
+ }
94
+ //# sourceMappingURL=fromEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fromEnv.js","sourceRoot":"","sources":["../../src/lib/fromEnv.ts"],"names":[],"mappings":"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"}
package/dist/lib/ids.d.ts CHANGED
@@ -50,6 +50,12 @@ export declare const idPrefixes: {
50
50
  * a bucket is bookkeeping the rate limiter owns, not a resource with routes.
51
51
  */
52
52
  readonly rateLimitBucket: 'rl';
53
+ /**
54
+ * One published domain event. Stamped on the envelope so downstream consumers
55
+ * (webhooks, MCP subscribers, an eventual outbox) have a stable idempotency
56
+ * key. Not persisted by core.
57
+ */
58
+ readonly event: 'ev';
53
59
  };
54
60
  export type ObjectKind = keyof typeof idPrefixes;
55
61
  export type IdFactory = (kind: ObjectKind) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/lib/ids.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,UAAU;aACrB,SAAS,EAAE,IAAI;aACf,IAAI,EAAE,KAAK;aACX,OAAO,EAAE,KAAK;aACd,kBAAkB,EAAE,KAAK;IACzB,wFAAwF;aACxF,sBAAsB,EAAE,KAAK;aAC7B,UAAU,EAAE,KAAK;aACjB,MAAM,EAAE,KAAK;aACb,MAAM,EAAE,KAAK;aACb,MAAM,EAAE,KAAK;aACb,OAAO,EAAE,KAAK;aACd,QAAQ,EAAE,KAAK;aACf,aAAa,EAAE,OAAO;aACtB,IAAI,EAAE,MAAM;aACZ,WAAW,EAAE,KAAK;aAClB,WAAW,EAAE,KAAK;aAClB,KAAK,EAAE,KAAK;aACZ,IAAI,EAAE,MAAM;aACZ,SAAS,EAAE,MAAM;aACjB,QAAQ,EAAE,MAAM;aAChB,QAAQ,EAAE,KAAK;aACf,IAAI,EAAE,MAAM;aACZ,QAAQ,EAAE,KAAK;aACf,YAAY,EAAE,IAAI;aAClB,IAAI,EAAE,MAAM;aACZ,SAAS,EAAE,IAAI;aACf,cAAc,EAAE,KAAK;aACrB,OAAO,EAAE,IAAI;IACb,8EAA8E;aAC9E,eAAe,EAAE,KAAK;aACtB,iBAAiB,EAAE,IAAI;aACvB,QAAQ,EAAE,KAAK;aACf,SAAS,EAAE,KAAK;IAChB,6FAA6F;aAC7F,aAAa,EAAE,MAAM;IACrB;;;;;OAKG;aACH,cAAc,EAAE,MAAM;IACtB;;;OAGG;aACH,eAAe,EAAE,IAAI;CACb,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,CAAA;AAEhD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,GAAE,MAAM,MAAa,GAAG,SAAS,CAE5E"}
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/lib/ids.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,UAAU;aACrB,SAAS,EAAE,IAAI;aACf,IAAI,EAAE,KAAK;aACX,OAAO,EAAE,KAAK;aACd,kBAAkB,EAAE,KAAK;IACzB,wFAAwF;aACxF,sBAAsB,EAAE,KAAK;aAC7B,UAAU,EAAE,KAAK;aACjB,MAAM,EAAE,KAAK;aACb,MAAM,EAAE,KAAK;aACb,MAAM,EAAE,KAAK;aACb,OAAO,EAAE,KAAK;aACd,QAAQ,EAAE,KAAK;aACf,aAAa,EAAE,OAAO;aACtB,IAAI,EAAE,MAAM;aACZ,WAAW,EAAE,KAAK;aAClB,WAAW,EAAE,KAAK;aAClB,KAAK,EAAE,KAAK;aACZ,IAAI,EAAE,MAAM;aACZ,SAAS,EAAE,MAAM;aACjB,QAAQ,EAAE,MAAM;aAChB,QAAQ,EAAE,KAAK;aACf,IAAI,EAAE,MAAM;aACZ,QAAQ,EAAE,KAAK;aACf,YAAY,EAAE,IAAI;aAClB,IAAI,EAAE,MAAM;aACZ,SAAS,EAAE,IAAI;aACf,cAAc,EAAE,KAAK;aACrB,OAAO,EAAE,IAAI;IACb,8EAA8E;aAC9E,eAAe,EAAE,KAAK;aACtB,iBAAiB,EAAE,IAAI;aACvB,QAAQ,EAAE,KAAK;aACf,SAAS,EAAE,KAAK;IAChB,6FAA6F;aAC7F,aAAa,EAAE,MAAM;IACrB;;;;;OAKG;aACH,cAAc,EAAE,MAAM;IACtB;;;OAGG;aACH,eAAe,EAAE,IAAI;IACrB;;;;OAIG;aACH,KAAK,EAAE,IAAI;CACH,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,CAAA;AAEhD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,GAAE,MAAM,MAAa,GAAG,SAAS,CAE5E"}
package/dist/lib/ids.js CHANGED
@@ -51,6 +51,12 @@ export const idPrefixes = {
51
51
  * a bucket is bookkeeping the rate limiter owns, not a resource with routes.
52
52
  */
53
53
  rateLimitBucket: 'rl',
54
+ /**
55
+ * One published domain event. Stamped on the envelope so downstream consumers
56
+ * (webhooks, MCP subscribers, an eventual outbox) have a stable idempotency
57
+ * key. Not persisted by core.
58
+ */
59
+ event: 'ev',
54
60
  };
55
61
  /**
56
62
  * Builds the id factory. The ULID generator is injected so tests can pin ids;
@@ -1 +1 @@
1
- {"version":3,"file":"ids.js","sourceRoot":"","sources":["../../src/lib/ids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,KAAK;IACd,kBAAkB,EAAE,KAAK;IACzB,wFAAwF;IACxF,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,OAAO;IACtB,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,KAAK;IAClB,WAAW,EAAE,KAAK;IAClB,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,IAAI;IAClB,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,KAAK;IACrB,OAAO,EAAE,IAAI;IACb,8EAA8E;IAC9E,eAAe,EAAE,KAAK;IACtB,iBAAiB,EAAE,IAAI;IACvB,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,KAAK;IAChB,6FAA6F;IAC7F,aAAa,EAAE,MAAM;IACrB;;;;;OAKG;IACH,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,eAAe,EAAE,IAAI;CACb,CAAA;AAMV;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,YAAY,GAAiB,IAAI;IAC/D,OAAO,CAAC,IAAgB,EAAU,EAAE,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,YAAY,EAAE,EAAE,CAAA;AAC9E,CAAC"}
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../../src/lib/ids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,KAAK;IACd,kBAAkB,EAAE,KAAK;IACzB,wFAAwF;IACxF,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,OAAO;IACtB,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,KAAK;IAClB,WAAW,EAAE,KAAK;IAClB,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,IAAI;IAClB,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,KAAK;IACrB,OAAO,EAAE,IAAI;IACb,8EAA8E;IAC9E,eAAe,EAAE,KAAK;IACtB,iBAAiB,EAAE,IAAI;IACvB,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,KAAK;IAChB,6FAA6F;IAC7F,aAAa,EAAE,MAAM;IACrB;;;;;OAKG;IACH,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,eAAe,EAAE,IAAI;IACrB;;;;OAIG;IACH,KAAK,EAAE,IAAI;CACH,CAAA;AAMV;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,YAAY,GAAiB,IAAI;IAC/D,OAAO,CAAC,IAAgB,EAAU,EAAE,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,YAAY,EAAE,EAAE,CAAA;AAC9E,CAAC"}
@@ -0,0 +1,123 @@
1
+ import type { KelpieModule } from '../runtime/module.ts';
2
+ import { type Environment, type KelpieConfig, type LogLevel, type RuntimeMode } from './config.ts';
3
+ import { type ConfigValue } from './fromEnv.ts';
4
+ import type { LoggingDestination } from './logger.ts';
5
+ /**
6
+ * The shape a `kelpie.config.ts` file declares.
7
+ *
8
+ * Every leaf is either a literal value the assembly commits to git, or a
9
+ * `fromEnv(...)` marker the deployment fills in. The resolver walks this
10
+ * object, replaces markers with parsed values, and returns a fully-populated
11
+ * `KelpieConfig`.
12
+ *
13
+ * The file is the map. `fromEnv(...)` marks the leaves a deployment overrides.
14
+ * Nothing in the app reads `process.env` for these fields after boot.
15
+ */
16
+ export interface KelpieConfigInput {
17
+ readonly runtimeMode: ConfigValue<RuntimeMode>;
18
+ readonly port: ConfigValue<number>;
19
+ readonly databaseUrl: ConfigValue<string>;
20
+ readonly logging: LoggingInput;
21
+ /** Optional; unset in development, set to the built web bundle in a deployment. */
22
+ readonly webBundleDirectory?: ConfigValue<string | undefined>;
23
+ /** Optional; unset in development, set to the deploy-time module override file. */
24
+ readonly moduleConfigPath?: ConfigValue<string | undefined>;
25
+ /** Optional; defaults to 0 (no proxy in front). */
26
+ readonly trustedProxyHopCount?: ConfigValue<number>;
27
+ /**
28
+ * The deployment's base URL. Every emailed link (password reset, email
29
+ * verification, invite) is built from it. Required by the workspace and auth
30
+ * modules. Optional here so an older assembly can omit it and let those
31
+ * modules fall back to the `context.config(appUrlConfigSchema)` path.
32
+ */
33
+ readonly appBaseUrl?: ConfigValue<string>;
34
+ /**
35
+ * Keys that seal stored secrets (webhook signing secrets, agent-task auth
36
+ * headers). Required by the webhooks and agent-tasks modules. Optional here
37
+ * for the same reason `appBaseUrl` is.
38
+ */
39
+ readonly secretEncryption?: SecretEncryptionInput;
40
+ readonly email: EmailInput;
41
+ /** Optional; each unset field falls back to the same defaults `loadConfig` used. */
42
+ readonly rateLimit?: RateLimitInput;
43
+ /**
44
+ * Env-keyed values the assembly can lock in code, or defer to the
45
+ * environment. Modules read this through `context.config(schema)`; each
46
+ * module's own Zod schema still names the keys and validates them.
47
+ *
48
+ * A key present here overrides the same key in `process.env`. A key absent
49
+ * here falls through to `process.env` unchanged, so the section is a
50
+ * progressive migration: lock what you want to lock, leave the rest.
51
+ *
52
+ * Literal: `SECRET_ENCRYPTION_KEY: 'a-committed-key'` (don't do this for
53
+ * secrets — the point is you can, if the value is not a secret).
54
+ * Marker: `SECRET_ENCRYPTION_KEY: fromEnv('SECRET_ENCRYPTION_KEY', z.string())`
55
+ * defers to the environment, same as today.
56
+ */
57
+ readonly env?: Readonly<Record<string, ConfigValue<string | undefined>>>;
58
+ /** The module list the assembly composes. Same shape it had before. */
59
+ readonly modules: readonly KelpieModule[];
60
+ }
61
+ /**
62
+ * The `logging` sub-tree of the assembly config.
63
+ *
64
+ * `level` is the minimum severity to emit. `destinations` is the ordered list
65
+ * of destinations each line writes to; stdout is the default entry in the
66
+ * template assembly, and a self-hoster adds another by extending
67
+ * `LoggingDestination` in `@kelpie/server` and putting a matching entry here.
68
+ */
69
+ export interface LoggingInput {
70
+ readonly level: ConfigValue<LogLevel>;
71
+ readonly destinations: readonly LoggingDestination[];
72
+ }
73
+ /**
74
+ * The `email` sub-tree of the assembly config.
75
+ *
76
+ * `provider` names one entry in the runtime's provider registry. `'log'` is a
77
+ * built-in the runtime always registers; `'smtp'` is registered by the
78
+ * built-in `smtp-email` core module; third-party provider modules register
79
+ * their own names (an API-based provider might register `'resend'` or
80
+ * `'postmark'`, and so on). Free-string so a self-hoster can install a
81
+ * module core has never heard of.
82
+ *
83
+ * `from` is the address on every outgoing message. Provider-specific config
84
+ * (SMTP host and credentials, an API key) belongs to the provider module,
85
+ * which reads it through `context.config(...)`; putting it here would tie the
86
+ * assembly config to a single transport.
87
+ */
88
+ export interface EmailInput {
89
+ readonly provider: ConfigValue<string>;
90
+ readonly from: ConfigValue<string>;
91
+ }
92
+ export interface SecretEncryptionInput {
93
+ readonly key: ConfigValue<string>;
94
+ /** Absent (or blank) is normal; only set while rotating away from an older key. */
95
+ readonly previousKey?: ConfigValue<string | undefined>;
96
+ }
97
+ export interface RateLimitBudgetInput {
98
+ readonly limit?: ConfigValue<number>;
99
+ readonly windowSeconds?: ConfigValue<number>;
100
+ }
101
+ export interface RateLimitInput {
102
+ readonly forms?: RateLimitBudgetInput;
103
+ readonly auth?: RateLimitBudgetInput;
104
+ readonly loginAccount?: RateLimitBudgetInput;
105
+ readonly api?: RateLimitBudgetInput;
106
+ }
107
+ /**
108
+ * Identity helper for the assembly's config file. It exists for the type-check
109
+ * only: `defineKelpieConfig({...})` makes TypeScript check the object against
110
+ * `KelpieConfigInput` at the call site, so a wrong-shape field is caught in
111
+ * the assembly rather than at boot.
112
+ */
113
+ export declare function defineKelpieConfig(input: KelpieConfigInput): KelpieConfigInput;
114
+ /**
115
+ * Resolves an assembly's config against an environment.
116
+ *
117
+ * Every `fromEnv` marker is resolved. Missing required variables and parse
118
+ * failures are collected together, so a self-hoster fixes them in one pass.
119
+ *
120
+ * @throws ConfigurationError listing every problem.
121
+ */
122
+ export declare function resolveKelpieConfig(input: KelpieConfigInput, environment: Environment): KelpieConfig;
123
+ //# sourceMappingURL=kelpieConfigFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kelpieConfigFile.d.ts","sourceRoot":"","sources":["../../src/lib/kelpieConfigFile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import { ConfigurationError } from './config.js';
2
+ import { resolveMarkers } from './fromEnv.js';
3
+ /**
4
+ * The defaults for each rate-limit budget, from `lib/rateLimit.ts`. Kept in
5
+ * this file so the assembly can leave `rateLimit` unset and still get the same
6
+ * numbers `loadConfig` produced.
7
+ */
8
+ const RATE_LIMIT_DEFAULTS = {
9
+ forms: { limit: 20, windowSeconds: 60 },
10
+ auth: { limit: 10, windowSeconds: 60 },
11
+ loginAccount: { limit: 10, windowSeconds: 900 },
12
+ api: { limit: 600, windowSeconds: 60 },
13
+ };
14
+ /**
15
+ * Identity helper for the assembly's config file. It exists for the type-check
16
+ * only: `defineKelpieConfig({...})` makes TypeScript check the object against
17
+ * `KelpieConfigInput` at the call site, so a wrong-shape field is caught in
18
+ * the assembly rather than at boot.
19
+ */
20
+ export function defineKelpieConfig(input) {
21
+ return input;
22
+ }
23
+ /**
24
+ * Resolves an assembly's config against an environment.
25
+ *
26
+ * Every `fromEnv` marker is resolved. Missing required variables and parse
27
+ * failures are collected together, so a self-hoster fixes them in one pass.
28
+ *
29
+ * @throws ConfigurationError listing every problem.
30
+ */
31
+ export function resolveKelpieConfig(input, environment) {
32
+ const walked = resolveMarkers(input, environment);
33
+ const problems = [...walked.problems.map((problem) => (problem.path.length > 0 ? `${problem.path}: ${problem.message}` : problem.message))];
34
+ // Even when problems exist, the walk still produced a partial object. Reshape
35
+ // it now: any field a problem covered will be undefined, which is fine, since
36
+ // we throw before returning.
37
+ const resolved = walked.value;
38
+ const email = buildEmailConfig(resolved.email);
39
+ const rateLimit = buildRateLimitConfig(resolved.rateLimit);
40
+ const env = mergeEnv(environment, resolved.env);
41
+ const secretEncryption = buildSecretEncryptionConfig(resolved.secretEncryption);
42
+ if (problems.length > 0) {
43
+ throw new ConfigurationError(problems);
44
+ }
45
+ return {
46
+ runtimeMode: resolved.runtimeMode,
47
+ port: resolved.port,
48
+ databaseUrl: resolved.databaseUrl,
49
+ logging: {
50
+ level: resolved.logging.level,
51
+ destinations: resolved.logging.destinations,
52
+ },
53
+ email,
54
+ moduleConfigPath: resolved.moduleConfigPath,
55
+ webBundleDirectory: resolved.webBundleDirectory,
56
+ rateLimit,
57
+ trustedProxyHopCount: resolved.trustedProxyHopCount ?? 0,
58
+ env,
59
+ appBaseUrl: resolved.appBaseUrl,
60
+ secretEncryption,
61
+ };
62
+ }
63
+ /**
64
+ * `kelpie.config.ts` env wins per-key; unset keys pass through from `environment`.
65
+ * Absent env section returns `environment` unchanged, so a self-hoster who has
66
+ * not opted in gets the same behaviour they had before pass 2.
67
+ */
68
+ function mergeEnv(environment, resolvedEnv) {
69
+ if (resolvedEnv === undefined) {
70
+ return environment;
71
+ }
72
+ return { ...environment, ...resolvedEnv };
73
+ }
74
+ function buildEmailConfig(resolved) {
75
+ // Missing `email.provider` or `email.from` is already recorded by the
76
+ // walker; return a placeholder so `resolveKelpieConfig` reaches its throw
77
+ // below.
78
+ return {
79
+ EMAIL_PROVIDER: resolved?.provider ?? '',
80
+ EMAIL_FROM: resolved?.from ?? '',
81
+ };
82
+ }
83
+ /**
84
+ * Reshape the resolved leaves into the `SecretEncryptionConfig` shape modules
85
+ * already consume. Returns undefined when the config file omits the field, in
86
+ * which case a module falls back to reading `context.config(...)`.
87
+ */
88
+ function buildSecretEncryptionConfig(resolved) {
89
+ if (resolved === undefined) {
90
+ return undefined;
91
+ }
92
+ return resolved.previousKey === undefined
93
+ ? { SECRET_ENCRYPTION_KEY: resolved.key }
94
+ : { SECRET_ENCRYPTION_KEY: resolved.key, SECRET_ENCRYPTION_KEY_PREVIOUS: resolved.previousKey };
95
+ }
96
+ function buildRateLimitConfig(resolved) {
97
+ return {
98
+ forms: budget('forms', resolved?.forms),
99
+ auth: budget('auth', resolved?.auth),
100
+ loginAccount: budget('loginAccount', resolved?.loginAccount),
101
+ api: budget('api', resolved?.api),
102
+ };
103
+ }
104
+ function budget(key, input) {
105
+ const defaults = RATE_LIMIT_DEFAULTS[key];
106
+ return {
107
+ limit: input?.limit ?? defaults.limit,
108
+ windowMs: (input?.windowSeconds ?? defaults.windowSeconds) * 1000,
109
+ };
110
+ }
111
+ //# sourceMappingURL=kelpieConfigFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kelpieConfigFile.js","sourceRoot":"","sources":["../../src/lib/kelpieConfigFile.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,15 @@
1
+ import Transport from 'winston-transport';
1
2
  import type { LogLevel } from './config.ts';
2
3
  /**
3
- * Structured logging as JSON lines. The sink is injected so tests capture output
4
- * instead of writing to stdout, and so a deployment can redirect it.
4
+ * Structured logging as JSON lines. Every line goes through one or more
5
+ * transports, each of which is a named destination (`createStdoutTransport`,
6
+ * `createCaptureTransport`, and whatever a deployment adds). Nothing defaults:
7
+ * an empty transport list means the logger writes nowhere, which the assembly
8
+ * must notice.
9
+ *
10
+ * Winston handles level filtering and fan-out to transports. The JSON line
11
+ * itself is built in this file and passed through as the message, so the
12
+ * envelope order (`time`, `level`, `message` last) is preserved exactly.
5
13
  */
6
14
  export type LogFields = Readonly<Record<string, unknown>>;
7
15
  export interface Logger {
@@ -12,11 +20,34 @@ export interface Logger {
12
20
  /** Returns a logger that stamps `fields` onto every line, e.g. a request id. */
13
21
  child(fields: LogFields): Logger;
14
22
  }
15
- export type LogSink = (line: string) => void;
16
23
  /**
17
- * @param level Minimum level to emit. Lines below it are dropped.
18
- * @param sink Receives one complete JSON line per log call.
19
- * @param now Injected so tests get deterministic timestamps.
24
+ * A destination declared in `kelpie.config.ts`. Extend the union to add a new
25
+ * kind; the switch in `createTransportForDestination` fails to compile until it
26
+ * covers every new variant, so a destination cannot be added in config without
27
+ * a matching transport factory.
20
28
  */
21
- export declare function createLogger(level: LogLevel, sink?: LogSink, now?: () => Date): Logger;
29
+ export type LoggingDestination = {
30
+ readonly kind: 'stdout';
31
+ };
32
+ /** Writes each line plus a trailing newline directly to stdout. */
33
+ export declare function createStdoutTransport(): Transport;
34
+ /** Hands each line to a callback. Tests use it to capture output. */
35
+ export declare function createCaptureTransport(onLine: (line: string) => void): Transport;
36
+ /**
37
+ * Builds the transport for one declared destination. The switch is exhaustive
38
+ * so adding a new `LoggingDestination` kind without a factory clause fails to
39
+ * compile.
40
+ */
41
+ export declare function createTransportForDestination(destination: LoggingDestination): Transport;
42
+ export interface CreateLoggerOptions {
43
+ readonly level: LogLevel;
44
+ readonly transports: readonly Transport[];
45
+ /** Injected so tests get deterministic timestamps. Defaults to the wall clock. */
46
+ readonly now?: () => Date;
47
+ }
48
+ /**
49
+ * Builds a logger. `transports` is required: an empty list writes nowhere and
50
+ * that is the assembly's decision to make, not a silent default.
51
+ */
52
+ export declare function createLogger(options: CreateLoggerOptions): Logger;
22
53
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C;;;GAGG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAEzD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAChD,gFAAgF;IAChF,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAA;CACjC;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAa5C;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EACf,IAAI,GAAE,OAAuB,EAC7B,GAAG,GAAE,MAAM,IAAuB,GACjC,MAAM,CAgCR"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,mBAAmB,CAAA;AAEzC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAEzD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAChD,gFAAgF;IAChF,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAA;CACjC;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAA;AAyB5D,mEAAmE;AACnE,wBAAgB,qBAAqB,IAAI,SAAS,CAIjD;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,kBAAkB,GAAG,SAAS,CAKxF;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAA;IACzC,kFAAkF;IAClF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAoCjE"}
@@ -1,34 +1,72 @@
1
- const severityByLevel = {
2
- debug: 10,
3
- info: 20,
4
- warn: 30,
5
- error: 40,
1
+ import winston from 'winston';
2
+ import Transport from 'winston-transport';
3
+ const LEVELS = {
4
+ error: 0,
5
+ warn: 1,
6
+ info: 2,
7
+ debug: 3,
6
8
  };
7
- function writeToStdout(line) {
8
- process.stdout.write(`${line}\n`);
9
+ class LineTransport extends Transport {
10
+ writeLine;
11
+ constructor(writeLine) {
12
+ super();
13
+ this.writeLine = writeLine;
14
+ }
15
+ log(info, next) {
16
+ this.writeLine(info.message);
17
+ // Winston expects the transport to emit 'logged' after handling.
18
+ setImmediate(() => this.emit('logged', info));
19
+ next();
20
+ }
21
+ }
22
+ /** Writes each line plus a trailing newline directly to stdout. */
23
+ export function createStdoutTransport() {
24
+ return new LineTransport((line) => {
25
+ process.stdout.write(`${line}\n`);
26
+ });
27
+ }
28
+ /** Hands each line to a callback. Tests use it to capture output. */
29
+ export function createCaptureTransport(onLine) {
30
+ return new LineTransport(onLine);
31
+ }
32
+ /**
33
+ * Builds the transport for one declared destination. The switch is exhaustive
34
+ * so adding a new `LoggingDestination` kind without a factory clause fails to
35
+ * compile.
36
+ */
37
+ export function createTransportForDestination(destination) {
38
+ switch (destination.kind) {
39
+ case 'stdout':
40
+ return createStdoutTransport();
41
+ }
9
42
  }
10
43
  /**
11
- * @param level Minimum level to emit. Lines below it are dropped.
12
- * @param sink Receives one complete JSON line per log call.
13
- * @param now Injected so tests get deterministic timestamps.
44
+ * Builds a logger. `transports` is required: an empty list writes nowhere and
45
+ * that is the assembly's decision to make, not a silent default.
14
46
  */
15
- export function createLogger(level, sink = writeToStdout, now = () => new Date()) {
16
- const threshold = severityByLevel[level];
47
+ export function createLogger(options) {
48
+ const now = options.now ?? (() => new Date());
49
+ const winstonLogger = winston.createLogger({
50
+ levels: LEVELS,
51
+ level: options.level,
52
+ transports: [...options.transports],
53
+ });
17
54
  function build(boundFields) {
18
55
  function emit(lineLevel, message, fields) {
19
- if (severityByLevel[lineLevel] < threshold) {
20
- return;
21
- }
22
- // The envelope is written last so a field called `message`, `level`, or
23
- // `time` cannot overwrite it. A colliding field is dropped; a corrupted
24
- // envelope would make the whole line untrustworthy.
25
- sink(JSON.stringify({
56
+ // The envelope is written last so a bound or per-call field called
57
+ // `message`, `level`, or `time` cannot overwrite it. A colliding field
58
+ // is dropped; a corrupted envelope would make the whole line untrustworthy.
59
+ const line = JSON.stringify({
26
60
  ...boundFields,
27
61
  ...fields,
28
62
  time: now().toISOString(),
29
63
  level: lineLevel,
30
64
  message,
31
- }));
65
+ });
66
+ // The full JSON line is passed as `message` and each transport writes it
67
+ // verbatim. Winston still filters by level and fans out to transports;
68
+ // it does not re-format the line.
69
+ winstonLogger.log({ level: lineLevel, message: line });
32
70
  }
33
71
  return {
34
72
  debug: (message, fields) => emit('debug', message, fields),
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAoBA,MAAM,eAAe,GAAuC;IAC1D,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAA;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAA;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAe,EACf,IAAI,GAAY,aAAa,EAC7B,GAAG,GAAe,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE;IAElC,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IAExC,SAAS,KAAK,CAAC,WAAsB;QACnC,SAAS,IAAI,CAAC,SAAmB,EAAE,OAAe,EAAE,MAAkB;YACpE,IAAI,eAAe,CAAC,SAAS,CAAC,GAAG,SAAS,EAAE,CAAC;gBAC3C,OAAM;YACR,CAAC;YACD,wEAAwE;YACxE,wEAAwE;YACxE,oDAAoD;YACpD,IAAI,CACF,IAAI,CAAC,SAAS,CAAC;gBACb,GAAG,WAAW;gBACd,GAAG,MAAM;gBACT,IAAI,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;gBACzB,KAAK,EAAE,SAAS;gBAChB,OAAO;aACR,CAAC,CACH,CAAA;QACH,CAAC;QAED,OAAO;YACL,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC;YAC1D,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;YACxD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;YACxD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC;YAC1D,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;SACxD,CAAA;IACH,CAAC;IAED,OAAO,KAAK,CAAC,EAAE,CAAC,CAAA;AAClB,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/agent-tasks/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAKjD;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAC7B;AAED,wBAAgB,sBAAsB,CACpC,mBAAmB,EAAE,MAAM,EAC3B,OAAO,GAAE,uBAA4B,GACpC,YAAY,CAsDd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/agent-tasks/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAKjD;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAC7B;AAED,wBAAgB,sBAAsB,CACpC,mBAAmB,EAAE,MAAM,EAC3B,OAAO,GAAE,uBAA4B,GACpC,YAAY,CAyDd"}
@@ -27,7 +27,10 @@ export function createAgentTasksModule(migrationsDirectory, options = {}) {
27
27
  // Validated at boot rather than on the first run: a missing or malformed
28
28
  // key means no stored auth header can ever be read back, and finding that
29
29
  // out when a dispatch quietly fails is far too late.
30
- const cipher = createSecretCipher(context.config(secretEncryptionConfigSchema));
30
+ //
31
+ // Prefer the top-level `secretEncryption` from the assembly's
32
+ // kelpie.config.ts; fall back to the schema read for older assemblies.
33
+ const cipher = createSecretCipher(context.secretEncryption ?? context.config(secretEncryptionConfigSchema));
31
34
  const egress = createEgressGuard(context.config(egressConfigSchema));
32
35
  const engine = createDispatchEngine({
33
36
  db: context.db,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/agent-tasks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AAEvF,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAgBtD,MAAM,UAAU,sBAAsB,CACpC,mBAA2B,EAC3B,OAAO,GAA4B,EAAE;IAErC,OAAO;QACL,EAAE,EAAE,aAAa;QACjB,QAAQ,EAAE;YACR,WAAW;YACX,QAAQ;YACR,WAAW;YACX,WAAW;YACX,WAAW;YACX,OAAO;YACP,eAAe;YACf,cAAc;YACd,QAAQ;YACR,QAAQ;YACR,OAAO;YACP,WAAW;YACX,OAAO;YACP,UAAU;SACX;QAED,QAAQ,CAAC,OAAO;YACd,yEAAyE;YACzE,0EAA0E;YAC1E,qDAAqD;YACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAA;YAC/E,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAA;YAEpE,MAAM,MAAM,GAAG,oBAAoB,CAAC;gBAClC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM;gBACN,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC;gBAC9C,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,uBAAuB,CAAC;gBACtC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM;gBACN,MAAM;gBACN,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAA;YAEF,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;YAE3C,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE;gBACxB,qBAAqB,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAA;YAC9E,CAAC,CAAC,CAAA;YAEF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/agent-tasks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AAEvF,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAgBtD,MAAM,UAAU,sBAAsB,CACpC,mBAA2B,EAC3B,OAAO,GAA4B,EAAE;IAErC,OAAO;QACL,EAAE,EAAE,aAAa;QACjB,QAAQ,EAAE;YACR,WAAW;YACX,QAAQ;YACR,WAAW;YACX,WAAW;YACX,WAAW;YACX,OAAO;YACP,eAAe;YACf,cAAc;YACd,QAAQ;YACR,QAAQ;YACR,OAAO;YACP,WAAW;YACX,OAAO;YACP,UAAU;SACX;QAED,QAAQ,CAAC,OAAO;YACd,yEAAyE;YACzE,0EAA0E;YAC1E,qDAAqD;YACrD,EAAE;YACF,8DAA8D;YAC9D,uEAAuE;YACvE,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAA;YAC3G,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAA;YAEpE,MAAM,MAAM,GAAG,oBAAoB,CAAC;gBAClC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM;gBACN,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC;gBAC9C,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,uBAAuB,CAAC;gBACtC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM;gBACN,MAAM;gBACN,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAA;YAEF,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;YAE3C,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE;gBACxB,qBAAqB,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAA;YAC9E,CAAC,CAAC,CAAA;YAEF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC"}