pipework 0.252.0 → 0.253.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 (695) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/infra/support/handle.d.ts +8 -1
  3. package/dist/infra/support/handle.d.ts.map +1 -1
  4. package/dist/infra/support/handle.js +9 -2
  5. package/dist/infra/support/handle.js.map +1 -1
  6. package/dist/infra/support/namespace.d.ts.map +1 -1
  7. package/package.json +4 -3
  8. package/src/async/jobs/abortable-delay.ts +18 -0
  9. package/src/async/jobs/claims.ts +52 -0
  10. package/src/async/jobs/cron.ts +179 -0
  11. package/src/async/jobs/errors.ts +56 -0
  12. package/src/async/jobs/exclusion.ts +117 -0
  13. package/src/async/jobs/execute.ts +219 -0
  14. package/src/async/jobs/index.ts +10 -0
  15. package/src/async/jobs/listener.ts +135 -0
  16. package/src/async/jobs/namespace.ts +20 -0
  17. package/src/async/jobs/queue-door.ts +44 -0
  18. package/src/async/jobs/queue.ts +1012 -0
  19. package/src/async/jobs/run-script.ts +67 -0
  20. package/src/async/jobs/scheduler.ts +218 -0
  21. package/src/async/jobs/schedules-table.ts +37 -0
  22. package/src/async/jobs/serialize-error.ts +48 -0
  23. package/src/async/jobs/table.ts +191 -0
  24. package/src/async/pipeline/define.ts +53 -0
  25. package/src/async/pipeline/errors.ts +35 -0
  26. package/src/async/pipeline/execute.ts +53 -0
  27. package/src/async/pipeline/index.ts +13 -0
  28. package/src/async/pipeline/namespace.ts +12 -0
  29. package/src/async/pipeline/resume.ts +67 -0
  30. package/src/async/pipeline/run-steps.ts +98 -0
  31. package/src/async/pipeline/types.ts +57 -0
  32. package/src/async/state-machine/define.ts +64 -0
  33. package/src/async/state-machine/errors.ts +29 -0
  34. package/src/async/state-machine/index.ts +3 -0
  35. package/src/async/state-machine/namespace.ts +12 -0
  36. package/src/async/state-machine/transition.ts +90 -0
  37. package/src/async/state-machine/types.ts +37 -0
  38. package/src/async/steps/errors.ts +31 -0
  39. package/src/async/steps/graph.ts +1214 -0
  40. package/src/async/steps/hash.ts +40 -0
  41. package/src/async/steps/index.ts +7 -0
  42. package/src/async/steps/namespace.ts +7 -0
  43. package/src/async/steps/table.ts +97 -0
  44. package/src/async/steps/types.ts +318 -0
  45. package/src/audit/chain/index.ts +9 -0
  46. package/src/audit/chain/install.ts +113 -0
  47. package/src/audit/chain/retire.ts +52 -0
  48. package/src/audit/chain/verify.ts +257 -0
  49. package/src/audit/query/cursor.ts +37 -0
  50. package/src/audit/query/index.ts +9 -0
  51. package/src/audit/query/query.ts +223 -0
  52. package/src/audit/schema/audit-record-fields.ts +68 -0
  53. package/src/audit/schema/audit-record.ts +23 -0
  54. package/src/auth/auth/audit.ts +31 -0
  55. package/src/auth/auth/chain.ts +84 -0
  56. package/src/auth/auth/cookie.ts +136 -0
  57. package/src/auth/auth/email-links.ts +311 -0
  58. package/src/auth/auth/guard.ts +128 -0
  59. package/src/auth/auth/index.ts +18 -0
  60. package/src/auth/auth/multi-org.ts +337 -0
  61. package/src/auth/auth/namespace.ts +34 -0
  62. package/src/auth/auth/parse-expiry.ts +13 -0
  63. package/src/auth/auth/passwords.ts +110 -0
  64. package/src/auth/auth/schema.ts +110 -0
  65. package/src/auth/auth/sessions.ts +565 -0
  66. package/src/auth/auth/sign-in.ts +156 -0
  67. package/src/auth/auth/signing-keys.ts +69 -0
  68. package/src/auth/auth/types.ts +26 -0
  69. package/src/auth/auth/uuid.ts +10 -0
  70. package/src/auth/rbac/cache.ts +55 -0
  71. package/src/auth/rbac/check.ts +30 -0
  72. package/src/auth/rbac/create.ts +35 -0
  73. package/src/auth/rbac/index.ts +5 -0
  74. package/src/auth/rbac/middleware.ts +20 -0
  75. package/src/auth/rbac/namespace.ts +15 -0
  76. package/src/auth/rbac/resolve.ts +31 -0
  77. package/src/auth/rbac/schema.sql +31 -0
  78. package/src/auth/rbac/seed.ts +67 -0
  79. package/src/auth/rbac/tables.ts +32 -0
  80. package/src/auth/rbac/types.ts +65 -0
  81. package/src/auth/tenant/extract.ts +33 -0
  82. package/src/auth/tenant/in-tenant.ts +49 -0
  83. package/src/auth/tenant/index.ts +7 -0
  84. package/src/auth/tenant/namespace.ts +23 -0
  85. package/src/auth/tenant/propagate.ts +20 -0
  86. package/src/auth/tenant/rls.ts +120 -0
  87. package/src/auth/tenant/scope.ts +33 -0
  88. package/src/auth/tenant/scoped-db.ts +581 -0
  89. package/src/auth/tenant/types.ts +14 -0
  90. package/src/auth/tenant/validate.ts +27 -0
  91. package/src/cli/commands/add.ts +158 -0
  92. package/src/cli/commands/alerts.ts +98 -0
  93. package/src/cli/commands/check.ts +1418 -0
  94. package/src/cli/commands/codemod.ts +78 -0
  95. package/src/cli/commands/db.ts +356 -0
  96. package/src/cli/commands/dev.ts +101 -0
  97. package/src/cli/commands/generate.ts +75 -0
  98. package/src/cli/commands/init.ts +36 -0
  99. package/src/cli/commands/install.ts +28 -0
  100. package/src/cli/commands/lint.ts +62 -0
  101. package/src/cli/commands/migrate.ts +132 -0
  102. package/src/cli/commands/openapi.ts +63 -0
  103. package/src/cli/commands/remove.ts +72 -0
  104. package/src/cli/commands/run.ts +50 -0
  105. package/src/cli/commands/scope.ts +54 -0
  106. package/src/cli/commands/serve.ts +68 -0
  107. package/src/cli/commands/shard.ts +31 -0
  108. package/src/cli/commands/shared/config-pipework-version.ts +28 -0
  109. package/src/cli/commands/shared/find-config.ts +22 -0
  110. package/src/cli/commands/shared/load-config.ts +35 -0
  111. package/src/cli/commands/shared/pnpm-install.ts +95 -0
  112. package/src/cli/commands/shared/report-removed.ts +8 -0
  113. package/src/cli/commands/sync.ts +32 -0
  114. package/src/cli/commands/test.ts +307 -0
  115. package/src/cli/commands/upgrade.ts +48 -0
  116. package/src/cli/dev-bootstrap.ts +24 -0
  117. package/src/cli/errors.ts +10 -0
  118. package/src/cli/index.ts +303 -0
  119. package/src/cli/output.ts +17 -0
  120. package/src/cli/port.ts +15 -0
  121. package/src/cli/surface-kinds.ts +20 -0
  122. package/src/client/index.ts +4 -0
  123. package/src/client/poll.ts +130 -0
  124. package/src/client/report-fault.ts +119 -0
  125. package/src/core/config/app-pool.ts +19 -0
  126. package/src/core/config/aws-env.ts +29 -0
  127. package/src/core/config/base-dir.ts +24 -0
  128. package/src/core/config/discover.ts +64 -0
  129. package/src/core/config/env-resolve.ts +87 -0
  130. package/src/core/config/env-types.ts +116 -0
  131. package/src/core/config/env.ts +55 -0
  132. package/src/core/config/errors.ts +9 -0
  133. package/src/core/config/import-config.ts +40 -0
  134. package/src/core/config/index.ts +8 -0
  135. package/src/core/config/load.ts +417 -0
  136. package/src/core/config/namespace.ts +14 -0
  137. package/src/core/config/resolve.ts +195 -0
  138. package/src/core/config/schema.ts +488 -0
  139. package/src/core/config/statement-observer.ts +48 -0
  140. package/src/core/config/ts-inline-hooks.ts +75 -0
  141. package/src/core/config/ts-register.ts +4 -0
  142. package/src/core/config/ts-resolve-hooks.ts +101 -0
  143. package/src/core/errors/base.ts +49 -0
  144. package/src/core/errors/http.ts +146 -0
  145. package/src/core/errors/index.ts +2 -0
  146. package/src/core/errors/namespace.ts +31 -0
  147. package/src/core/lifecycle/drain.ts +33 -0
  148. package/src/core/lifecycle/health.ts +72 -0
  149. package/src/core/lifecycle/index.ts +4 -0
  150. package/src/core/lifecycle/namespace.ts +7 -0
  151. package/src/core/lifecycle/startup.ts +102 -0
  152. package/src/core/lifecycle/types.ts +36 -0
  153. package/src/core/logging/context.ts +60 -0
  154. package/src/core/logging/error-chain.ts +68 -0
  155. package/src/core/logging/index.ts +5 -0
  156. package/src/core/logging/logger.ts +65 -0
  157. package/src/core/logging/namespace.ts +16 -0
  158. package/src/core/logging/proxy.ts +22 -0
  159. package/src/core/logging/redact-match.ts +24 -0
  160. package/src/core/logging/types.ts +47 -0
  161. package/src/core/pipework.ts +566 -0
  162. package/src/core/runtime/broker.ts +69 -0
  163. package/src/core/surface/http.ts +133 -0
  164. package/src/core/surface/index.ts +11 -0
  165. package/src/core/surface/job-timeout.ts +40 -0
  166. package/src/core/surface/namespace.ts +13 -0
  167. package/src/core/surface/script.ts +33 -0
  168. package/src/core/surface/start.ts +142 -0
  169. package/src/core/surface/types.ts +225 -0
  170. package/src/core/surface/validate.ts +88 -0
  171. package/src/core/surface/worker.ts +528 -0
  172. package/src/core/validation/connectivity.ts +49 -0
  173. package/src/core/validation/domain.ts +99 -0
  174. package/src/core/validation/index.ts +5 -0
  175. package/src/core/validation/queue-tables.ts +312 -0
  176. package/src/core/validation/rls-role.ts +138 -0
  177. package/src/core/validation/startup.ts +51 -0
  178. package/src/core/validation/surfaces.ts +65 -0
  179. package/src/core/validation/types.ts +25 -0
  180. package/src/data/db/advisory-lock.ts +55 -0
  181. package/src/data/db/aggregates.ts +172 -0
  182. package/src/data/db/array-elements.ts +111 -0
  183. package/src/data/db/bulk-set.ts +53 -0
  184. package/src/data/db/col/index.ts +14 -0
  185. package/src/data/db/composed.ts +53 -0
  186. package/src/data/db/db.ts +276 -0
  187. package/src/data/db/excluded.ts +16 -0
  188. package/src/data/db/expressions.ts +473 -0
  189. package/src/data/db/filter.ts +90 -0
  190. package/src/data/db/function-source.ts +114 -0
  191. package/src/data/db/identifiers.ts +16 -0
  192. package/src/data/db/idx/index.ts +9 -0
  193. package/src/data/db/in-list.ts +49 -0
  194. package/src/data/db/index.ts +9 -0
  195. package/src/data/db/insert-split.ts +137 -0
  196. package/src/data/db/instrumentation.ts +82 -0
  197. package/src/data/db/maintenance.ts +28 -0
  198. package/src/data/db/namespace.ts +107 -0
  199. package/src/data/db/owner-labels.ts +9 -0
  200. package/src/data/db/pool.ts +187 -0
  201. package/src/data/db/query-label.ts +13 -0
  202. package/src/data/db/query-watch.ts +116 -0
  203. package/src/data/db/raw-client-warning.ts +37 -0
  204. package/src/data/db/readonly.ts +23 -0
  205. package/src/data/db/reservation.ts +151 -0
  206. package/src/data/db/schema-features.ts +14 -0
  207. package/src/data/db/serializable.ts +83 -0
  208. package/src/data/db/sql.ts +1 -0
  209. package/src/data/db/timeouts.ts +76 -0
  210. package/src/data/db/types.ts +18 -0
  211. package/src/data/db/unbound.ts +33 -0
  212. package/src/data/db/values.ts +29 -0
  213. package/src/data/domain/brand.ts +15 -0
  214. package/src/data/domain/build-factory.ts +193 -0
  215. package/src/data/domain/build-schema.ts +161 -0
  216. package/src/data/domain/build-table.ts +355 -0
  217. package/src/data/domain/define.ts +239 -0
  218. package/src/data/domain/external-registry.ts +34 -0
  219. package/src/data/domain/external.ts +77 -0
  220. package/src/data/domain/field.ts +279 -0
  221. package/src/data/domain/index.ts +13 -0
  222. package/src/data/domain/naming.ts +6 -0
  223. package/src/data/domain/projections.ts +57 -0
  224. package/src/data/domain/trace-safe-projection.ts +31 -0
  225. package/src/data/domain/traits.ts +108 -0
  226. package/src/data/domain/types.ts +289 -0
  227. package/src/data/jsonb/composed.ts +18 -0
  228. package/src/data/jsonb/index.ts +1 -0
  229. package/src/data/jsonb/namespace.ts +30 -0
  230. package/src/data/jsonb/query.ts +86 -0
  231. package/src/data/migrate/append-only-generate.ts +47 -0
  232. package/src/data/migrate/applied.ts +47 -0
  233. package/src/data/migrate/apply.ts +309 -0
  234. package/src/data/migrate/check.ts +119 -0
  235. package/src/data/migrate/diff.ts +357 -0
  236. package/src/data/migrate/door-generate.ts +130 -0
  237. package/src/data/migrate/framework-rls.ts +58 -0
  238. package/src/data/migrate/generate.ts +201 -0
  239. package/src/data/migrate/history.ts +215 -0
  240. package/src/data/migrate/index.ts +9 -0
  241. package/src/data/migrate/internal-definitions.ts +175 -0
  242. package/src/data/migrate/post-process.ts +73 -0
  243. package/src/data/migrate/pragma.ts +73 -0
  244. package/src/data/migrate/provision-framework.ts +147 -0
  245. package/src/data/migrate/rls-generate.ts +61 -0
  246. package/src/data/migrate/run.ts +124 -0
  247. package/src/data/migrate/safety.ts +167 -0
  248. package/src/data/migrate/snapshot.ts +368 -0
  249. package/src/data/migrate/sql-emit.ts +392 -0
  250. package/src/data/migrate/statements.ts +312 -0
  251. package/src/data/query/alias.ts +126 -0
  252. package/src/data/query/batch.ts +8 -0
  253. package/src/data/query/cache/core/cache.ts +78 -0
  254. package/src/data/query/cache/core/index.ts +1 -0
  255. package/src/data/query/cache/core/types.ts +29 -0
  256. package/src/data/query/cache/readme.md +230 -0
  257. package/src/data/query/casing.ts +76 -0
  258. package/src/data/query/collation.ts +11 -0
  259. package/src/data/query/column-builder.ts +370 -0
  260. package/src/data/query/column.ts +150 -0
  261. package/src/data/query/entity.ts +42 -0
  262. package/src/data/query/errors.ts +33 -0
  263. package/src/data/query/index.ts +14 -0
  264. package/src/data/query/logger.ts +47 -0
  265. package/src/data/query/operations.ts +45 -0
  266. package/src/data/query/pg-core/alias.ts +12 -0
  267. package/src/data/query/pg-core/checks.ts +32 -0
  268. package/src/data/query/pg-core/columns/all.ts +71 -0
  269. package/src/data/query/pg-core/columns/bigint.ts +110 -0
  270. package/src/data/query/pg-core/columns/bigserial.ts +128 -0
  271. package/src/data/query/pg-core/columns/boolean.ts +43 -0
  272. package/src/data/query/pg-core/columns/char.ts +85 -0
  273. package/src/data/query/pg-core/columns/cidr.ts +43 -0
  274. package/src/data/query/pg-core/columns/common.ts +366 -0
  275. package/src/data/query/pg-core/columns/custom.ts +232 -0
  276. package/src/data/query/pg-core/columns/date.common.ts +15 -0
  277. package/src/data/query/pg-core/columns/date.ts +112 -0
  278. package/src/data/query/pg-core/columns/double-precision.ts +55 -0
  279. package/src/data/query/pg-core/columns/enum.ts +201 -0
  280. package/src/data/query/pg-core/columns/index.ts +35 -0
  281. package/src/data/query/pg-core/columns/inet.ts +43 -0
  282. package/src/data/query/pg-core/columns/int.common.ts +57 -0
  283. package/src/data/query/pg-core/columns/integer.ts +53 -0
  284. package/src/data/query/pg-core/columns/interval.ts +83 -0
  285. package/src/data/query/pg-core/columns/json.ts +58 -0
  286. package/src/data/query/pg-core/columns/jsonb.ts +56 -0
  287. package/src/data/query/pg-core/columns/line.ts +117 -0
  288. package/src/data/query/pg-core/columns/macaddr.ts +43 -0
  289. package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
  290. package/src/data/query/pg-core/columns/numeric.ts +227 -0
  291. package/src/data/query/pg-core/columns/point.ts +127 -0
  292. package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
  293. package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
  294. package/src/data/query/pg-core/columns/real.ts +58 -0
  295. package/src/data/query/pg-core/columns/serial.ts +55 -0
  296. package/src/data/query/pg-core/columns/smallint.ts +53 -0
  297. package/src/data/query/pg-core/columns/smallserial.ts +60 -0
  298. package/src/data/query/pg-core/columns/text.ts +67 -0
  299. package/src/data/query/pg-core/columns/time.ts +72 -0
  300. package/src/data/query/pg-core/columns/timestamp.ts +163 -0
  301. package/src/data/query/pg-core/columns/uuid.ts +51 -0
  302. package/src/data/query/pg-core/columns/varchar.ts +89 -0
  303. package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
  304. package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
  305. package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
  306. package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
  307. package/src/data/query/pg-core/db.ts +674 -0
  308. package/src/data/query/pg-core/dialect.ts +1404 -0
  309. package/src/data/query/pg-core/expressions.ts +25 -0
  310. package/src/data/query/pg-core/foreign-keys.ts +130 -0
  311. package/src/data/query/pg-core/index.ts +21 -0
  312. package/src/data/query/pg-core/indexes.ts +276 -0
  313. package/src/data/query/pg-core/policies.ts +56 -0
  314. package/src/data/query/pg-core/primary-keys.ts +62 -0
  315. package/src/data/query/pg-core/query-builders/count.ts +86 -0
  316. package/src/data/query/pg-core/query-builders/delete.ts +293 -0
  317. package/src/data/query/pg-core/query-builders/index.ts +7 -0
  318. package/src/data/query/pg-core/query-builders/insert.ts +452 -0
  319. package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
  320. package/src/data/query/pg-core/query-builders/query.ts +157 -0
  321. package/src/data/query/pg-core/query-builders/raw.ts +49 -0
  322. package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
  323. package/src/data/query/pg-core/query-builders/select.ts +1346 -0
  324. package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
  325. package/src/data/query/pg-core/query-builders/update.ts +626 -0
  326. package/src/data/query/pg-core/roles.ts +41 -0
  327. package/src/data/query/pg-core/schema.ts +72 -0
  328. package/src/data/query/pg-core/sequence.ts +41 -0
  329. package/src/data/query/pg-core/session.ts +292 -0
  330. package/src/data/query/pg-core/subquery.ts +46 -0
  331. package/src/data/query/pg-core/table.ts +252 -0
  332. package/src/data/query/pg-core/unique-constraint.ts +73 -0
  333. package/src/data/query/pg-core/utils/array.ts +95 -0
  334. package/src/data/query/pg-core/utils/index.ts +1 -0
  335. package/src/data/query/pg-core/utils.ts +104 -0
  336. package/src/data/query/pg-core/view-base.ts +14 -0
  337. package/src/data/query/pg-core/view-common.ts +1 -0
  338. package/src/data/query/pg-core/view.ts +435 -0
  339. package/src/data/query/pg-core/with-builder.ts +41 -0
  340. package/src/data/query/postgres-js/README.md +46 -0
  341. package/src/data/query/postgres-js/array-parser.ts +45 -0
  342. package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
  343. package/src/data/query/postgres-js/driver.ts +163 -0
  344. package/src/data/query/postgres-js/index.ts +2 -0
  345. package/src/data/query/postgres-js/session.ts +234 -0
  346. package/src/data/query/primary-key.ts +11 -0
  347. package/src/data/query/query-builders/query-builder.ts +19 -0
  348. package/src/data/query/query-builders/select.types.ts +175 -0
  349. package/src/data/query/query-promise.ts +35 -0
  350. package/src/data/query/relations.ts +725 -0
  351. package/src/data/query/runnable-query.ts +12 -0
  352. package/src/data/query/selection-proxy.ts +121 -0
  353. package/src/data/query/session.ts +8 -0
  354. package/src/data/query/sql/expressions/conditions.ts +741 -0
  355. package/src/data/query/sql/expressions/index.ts +2 -0
  356. package/src/data/query/sql/expressions/select.ts +45 -0
  357. package/src/data/query/sql/functions/aggregate.ts +129 -0
  358. package/src/data/query/sql/functions/index.ts +2 -0
  359. package/src/data/query/sql/functions/vector.ts +178 -0
  360. package/src/data/query/sql/index.ts +3 -0
  361. package/src/data/query/sql/sql.ts +794 -0
  362. package/src/data/query/subquery.ts +53 -0
  363. package/src/data/query/table.ts +208 -0
  364. package/src/data/query/table.utils.ts +2 -0
  365. package/src/data/query/tracing-utils.ts +3 -0
  366. package/src/data/query/tracing.ts +11 -0
  367. package/src/data/query/utils.ts +357 -0
  368. package/src/data/query/version.ts +4 -0
  369. package/src/data/query/view-common.ts +1 -0
  370. package/src/data/schema/branded.ts +13 -0
  371. package/src/data/schema/generated/coerce.ts +5 -0
  372. package/src/data/schema/generated/combinator.ts +6 -0
  373. package/src/data/schema/generated/encoding.ts +5 -0
  374. package/src/data/schema/generated/error.ts +6 -0
  375. package/src/data/schema/generated/format.ts +5 -0
  376. package/src/data/schema/generated/type-constructor.ts +10 -0
  377. package/src/data/schema/generated/type.ts +6 -0
  378. package/src/data/schema/index.ts +6 -0
  379. package/src/data/schema/json-schema.ts +33 -0
  380. package/src/data/schema/namespace.ts +55 -0
  381. package/src/data/schema/parse.ts +39 -0
  382. package/src/data/schema/types.ts +39 -0
  383. package/src/data/temporal/append-only.ts +134 -0
  384. package/src/data/temporal/close.ts +27 -0
  385. package/src/data/temporal/columns.ts +10 -0
  386. package/src/data/temporal/definition-queries.ts +70 -0
  387. package/src/data/temporal/errors.ts +10 -0
  388. package/src/data/temporal/get-current.ts +22 -0
  389. package/src/data/temporal/index.ts +9 -0
  390. package/src/data/temporal/namespace.ts +36 -0
  391. package/src/data/temporal/query.ts +25 -0
  392. package/src/data/temporal/resolve.ts +17 -0
  393. package/src/data/temporal/revise.ts +67 -0
  394. package/src/data/temporal/types.ts +22 -0
  395. package/src/data/valve/artifact.ts +33 -0
  396. package/src/data/valve/contract-diff.ts +21 -0
  397. package/src/data/valve/cross.ts +57 -0
  398. package/src/data/valve/crossing-ledger.ts +50 -0
  399. package/src/data/valve/decision.ts +44 -0
  400. package/src/data/valve/durable-crossing.ts +52 -0
  401. package/src/data/valve/execute-crossing.ts +77 -0
  402. package/src/data/valve/faucet.ts +56 -0
  403. package/src/data/valve/gate.ts +114 -0
  404. package/src/data/valve/graph.ts +77 -0
  405. package/src/data/valve/index.ts +53 -0
  406. package/src/data/valve/namespace.ts +57 -0
  407. package/src/data/valve/registry.ts +50 -0
  408. package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
  409. package/src/data/valve/schema/valve-crossing.ts +9 -0
  410. package/src/data/valve/supply.ts +154 -0
  411. package/src/data/valve/types.ts +143 -0
  412. package/src/data/vector/columns.ts +27 -0
  413. package/src/data/vector/index.ts +4 -0
  414. package/src/data/vector/namespace.ts +33 -0
  415. package/src/data/vector/query.ts +85 -0
  416. package/src/data/vector/validate.ts +16 -0
  417. package/src/data/write/audit/actor.ts +15 -0
  418. package/src/data/write/audit/audit-columns.ts +18 -0
  419. package/src/data/write/audit/audit-select.ts +111 -0
  420. package/src/data/write/audit/bound-transaction.ts +14 -0
  421. package/src/data/write/audit/cte-compile.ts +32 -0
  422. package/src/data/write/audit/decode-returning.ts +47 -0
  423. package/src/data/write/audit/final-select.ts +43 -0
  424. package/src/data/write/audit/infra-audit.ts +36 -0
  425. package/src/data/write/audit/primary-key.ts +65 -0
  426. package/src/data/write/audit/projection.ts +41 -0
  427. package/src/data/write/audit/read-touches.ts +86 -0
  428. package/src/data/write/audit/touch-match.ts +78 -0
  429. package/src/data/write/audit/verb-delete.ts +62 -0
  430. package/src/data/write/audit/verb-insert.ts +36 -0
  431. package/src/data/write/audit/verb-select.ts +47 -0
  432. package/src/data/write/audit/verb-update.ts +60 -0
  433. package/src/data/write/audit/verb-upsert.ts +104 -0
  434. package/src/data/write/conflict.ts +43 -0
  435. package/src/data/write/delete.ts +38 -0
  436. package/src/data/write/execute.ts +243 -0
  437. package/src/data/write/index.ts +11 -0
  438. package/src/data/write/insert.ts +63 -0
  439. package/src/data/write/state.ts +43 -0
  440. package/src/data/write/update.ts +54 -0
  441. package/src/data/write/upsert.ts +58 -0
  442. package/src/data/write/values.ts +19 -0
  443. package/src/index.ts +230 -0
  444. package/src/infra/access-links/code.ts +70 -0
  445. package/src/infra/access-links/handle.ts +892 -0
  446. package/src/infra/access-links/index.ts +9 -0
  447. package/src/infra/access-links/namespace.ts +30 -0
  448. package/src/infra/access-links/person-check.ts +177 -0
  449. package/src/infra/access-links/schema.ts +71 -0
  450. package/src/infra/alerts/async-sources.ts +231 -0
  451. package/src/infra/alerts/audit.ts +36 -0
  452. package/src/infra/alerts/beat.ts +123 -0
  453. package/src/infra/alerts/client-faults.ts +111 -0
  454. package/src/infra/alerts/faults.ts +156 -0
  455. package/src/infra/alerts/handle.ts +778 -0
  456. package/src/infra/alerts/http.ts +192 -0
  457. package/src/infra/alerts/index.ts +12 -0
  458. package/src/infra/alerts/infra-sources.ts +180 -0
  459. package/src/infra/alerts/namespace.ts +81 -0
  460. package/src/infra/alerts/redact.ts +21 -0
  461. package/src/infra/alerts/request-faults.ts +41 -0
  462. package/src/infra/alerts/schema.ts +124 -0
  463. package/src/infra/alerts/sinks.ts +125 -0
  464. package/src/infra/alerts/source-options.ts +26 -0
  465. package/src/infra/alerts/sources.ts +503 -0
  466. package/src/infra/alerts/subsystem-sources.ts +137 -0
  467. package/src/infra/audit/emit.ts +87 -0
  468. package/src/infra/audit/index.ts +2 -0
  469. package/src/infra/audit/namespace.ts +22 -0
  470. package/src/infra/audit/schema.sql +35 -0
  471. package/src/infra/audit/types.ts +18 -0
  472. package/src/infra/aws/credentials.ts +147 -0
  473. package/src/infra/aws/sigv4.ts +140 -0
  474. package/src/infra/cache/create.ts +58 -0
  475. package/src/infra/cache/entry.ts +81 -0
  476. package/src/infra/cache/index.ts +4 -0
  477. package/src/infra/cache/namespace.ts +10 -0
  478. package/src/infra/cache/tenant.ts +93 -0
  479. package/src/infra/cache/types.ts +24 -0
  480. package/src/infra/crawl/audit.ts +35 -0
  481. package/src/infra/crawl/errors.ts +25 -0
  482. package/src/infra/crawl/handle.ts +693 -0
  483. package/src/infra/crawl/index.ts +9 -0
  484. package/src/infra/crawl/links.ts +160 -0
  485. package/src/infra/crawl/namespace.ts +36 -0
  486. package/src/infra/crawl/robots.ts +100 -0
  487. package/src/infra/crawl/schema.ts +89 -0
  488. package/src/infra/credit-line/handle.ts +883 -0
  489. package/src/infra/credit-line/index.ts +6 -0
  490. package/src/infra/credit-line/namespace.ts +7 -0
  491. package/src/infra/credit-line/schema.ts +96 -0
  492. package/src/infra/credits/handle.ts +706 -0
  493. package/src/infra/credits/index.ts +5 -0
  494. package/src/infra/credits/namespace.ts +7 -0
  495. package/src/infra/credits/schema.ts +83 -0
  496. package/src/infra/email/audit.ts +36 -0
  497. package/src/infra/email/inbound.ts +622 -0
  498. package/src/infra/email/index.ts +11 -0
  499. package/src/infra/email/mail.ts +517 -0
  500. package/src/infra/email/mime.ts +447 -0
  501. package/src/infra/email/namespace.ts +22 -0
  502. package/src/infra/email/providers.ts +111 -0
  503. package/src/infra/email/schema.ts +96 -0
  504. package/src/infra/email/sns.ts +200 -0
  505. package/src/infra/email/unsubscribe.ts +44 -0
  506. package/src/infra/fetch/address.ts +88 -0
  507. package/src/infra/fetch/connect-retry.ts +87 -0
  508. package/src/infra/fetch/handle.ts +329 -0
  509. package/src/infra/fetch/index.ts +7 -0
  510. package/src/infra/fetch/namespace.ts +70 -0
  511. package/src/infra/idempotency/index.ts +3 -0
  512. package/src/infra/idempotency/middleware.ts +87 -0
  513. package/src/infra/idempotency/store.ts +92 -0
  514. package/src/infra/idempotency/types.ts +30 -0
  515. package/src/infra/join-requests/handle.ts +312 -0
  516. package/src/infra/join-requests/index.ts +2 -0
  517. package/src/infra/join-requests/namespace.ts +7 -0
  518. package/src/infra/join-requests/schema.ts +33 -0
  519. package/src/infra/outbox/core.ts +165 -0
  520. package/src/infra/quota/errors.ts +32 -0
  521. package/src/infra/quota/handle.ts +215 -0
  522. package/src/infra/quota/index.ts +5 -0
  523. package/src/infra/quota/namespace.ts +7 -0
  524. package/src/infra/quota/schema.ts +15 -0
  525. package/src/infra/storage/backend.ts +34 -0
  526. package/src/infra/storage/handle.ts +513 -0
  527. package/src/infra/storage/index.ts +9 -0
  528. package/src/infra/storage/local.ts +104 -0
  529. package/src/infra/storage/namespace.ts +13 -0
  530. package/src/infra/storage/s3.ts +257 -0
  531. package/src/infra/storage/schema.ts +24 -0
  532. package/src/infra/support/handle.ts +869 -0
  533. package/src/infra/support/http.ts +229 -0
  534. package/src/infra/support/index.ts +7 -0
  535. package/src/infra/support/namespace.ts +12 -0
  536. package/src/infra/support/schema.ts +96 -0
  537. package/src/infra/webhook/inbound.ts +45 -0
  538. package/src/infra/webhook/index.ts +5 -0
  539. package/src/infra/webhook/namespace.ts +24 -0
  540. package/src/infra/webhook/outbound.ts +315 -0
  541. package/src/infra/webhook/sign.ts +32 -0
  542. package/src/infra/webhook/verify.ts +82 -0
  543. package/src/invariants/assert.ts +26 -0
  544. package/src/invariants/index.ts +1 -0
  545. package/src/lint/config.ts +56 -0
  546. package/src/lint/doctrine.ts +163 -0
  547. package/src/lint/include.ts +97 -0
  548. package/src/lint/index.ts +3 -0
  549. package/src/lint/preset.ts +10 -0
  550. package/src/lint/resolver.ts +218 -0
  551. package/src/lint/rules/no-reexports.ts +46 -0
  552. package/src/request/behavior/audited.ts +85 -0
  553. package/src/request/behavior/cached.ts +62 -0
  554. package/src/request/behavior/compose.ts +28 -0
  555. package/src/request/behavior/index.ts +5 -0
  556. package/src/request/behavior/namespace.ts +16 -0
  557. package/src/request/behavior/types.ts +26 -0
  558. package/src/request/behavior/versioned.ts +54 -0
  559. package/src/request/context/create.ts +103 -0
  560. package/src/request/context/guard.ts +49 -0
  561. package/src/request/context/index.ts +4 -0
  562. package/src/request/context/run-in-transaction.ts +200 -0
  563. package/src/request/context/store.ts +28 -0
  564. package/src/request/context/types.ts +50 -0
  565. package/src/request/di/builder.ts +535 -0
  566. package/src/request/di/index.ts +8 -0
  567. package/src/request/di/resolve.ts +271 -0
  568. package/src/request/di/types.ts +262 -0
  569. package/src/request/fitting/namespace.ts +7 -0
  570. package/src/request/fixture/batch.ts +71 -0
  571. package/src/request/fixture/builder.ts +26 -0
  572. package/src/request/fixture/errors.ts +10 -0
  573. package/src/request/fixture/index.ts +8 -0
  574. package/src/request/fixture/namespace.ts +23 -0
  575. package/src/request/fixture/paginate.ts +44 -0
  576. package/src/request/fixture/to-handlers.ts +260 -0
  577. package/src/request/fixture/types.ts +79 -0
  578. package/src/request/flow/act-as.ts +78 -0
  579. package/src/request/flow/namespace.ts +17 -0
  580. package/src/request/http/error-step.ts +42 -0
  581. package/src/request/http/file.ts +141 -0
  582. package/src/request/http/index.ts +4 -0
  583. package/src/request/http/middleware.ts +141 -0
  584. package/src/request/http/namespace.ts +5 -0
  585. package/src/request/http/rate-limit-classes.ts +170 -0
  586. package/src/request/http/response.ts +82 -0
  587. package/src/request/http/server.ts +916 -0
  588. package/src/request/http/sniff.ts +261 -0
  589. package/src/request/http/types.ts +250 -0
  590. package/src/request/http/upload.ts +284 -0
  591. package/src/request/internal/text.ts +6 -0
  592. package/src/request/openapi/generate.ts +205 -0
  593. package/src/request/openapi/index.ts +2 -0
  594. package/src/request/openapi/namespace.ts +7 -0
  595. package/src/test/auth.ts +13 -0
  596. package/src/test/auto-setup.ts +45 -0
  597. package/src/test/context.ts +91 -0
  598. package/src/test/crawl-fixture.ts +157 -0
  599. package/src/test/discover-fork.ts +17 -0
  600. package/src/test/fingerprint.ts +135 -0
  601. package/src/test/globals.d.ts +7 -0
  602. package/src/test/index.ts +19 -0
  603. package/src/test/namespace.ts +87 -0
  604. package/src/test/plugin.ts +189 -0
  605. package/src/test/progress.ts +185 -0
  606. package/src/test/reap-after-run.ts +28 -0
  607. package/src/test/reap.ts +286 -0
  608. package/src/test/reset.ts +253 -0
  609. package/src/test/savepoints.ts +172 -0
  610. package/src/test/setup.ts +1422 -0
  611. package/src/test/system-channel.ts +50 -0
  612. package/src/test/vitest-plugin.ts +142 -0
  613. package/src/test/vitest-workspace.ts +507 -0
  614. package/src/test/vitest.ts +333 -0
  615. package/src/test/watch.ts +105 -0
  616. package/src/trace/capture/bounded-serializer.ts +146 -0
  617. package/src/trace/cardinality/analyze.ts +173 -0
  618. package/src/trace/cardinality/branch-context.ts +214 -0
  619. package/src/trace/cardinality/check.ts +33 -0
  620. package/src/trace/cardinality/classify-edge.ts +64 -0
  621. package/src/trace/cardinality/structural-max.ts +107 -0
  622. package/src/trace/check/coverage-check.ts +188 -0
  623. package/src/trace/check/flow-check.ts +103 -0
  624. package/src/trace/check/flow-step-site.ts +234 -0
  625. package/src/trace/check/io-pattern.ts +116 -0
  626. package/src/trace/codemod/add-cardinality.ts +152 -0
  627. package/src/trace/codemod/run.ts +80 -0
  628. package/src/trace/entry/child-trace.ts +21 -0
  629. package/src/trace/entry/close-trace.ts +87 -0
  630. package/src/trace/entry/finalize-trace.ts +28 -0
  631. package/src/trace/entry/open-trace.ts +138 -0
  632. package/src/trace/entry/parent-trace.ts +20 -0
  633. package/src/trace/entry/parse-traceparent.ts +39 -0
  634. package/src/trace/entry/process-start.ts +38 -0
  635. package/src/trace/entry/trace-context.ts +26 -0
  636. package/src/trace/entry/tracing-enabled.ts +10 -0
  637. package/src/trace/external/record.ts +195 -0
  638. package/src/trace/external/report.ts +66 -0
  639. package/src/trace/namespace.ts +19 -0
  640. package/src/trace/partition/day.ts +47 -0
  641. package/src/trace/partition/index.ts +14 -0
  642. package/src/trace/partition/partition-name.ts +23 -0
  643. package/src/trace/partition/plan.ts +82 -0
  644. package/src/trace/partition/schedule.ts +26 -0
  645. package/src/trace/partition/startup-hook.ts +39 -0
  646. package/src/trace/partition/sync.ts +154 -0
  647. package/src/trace/partition/tables.ts +53 -0
  648. package/src/trace/read/tree.ts +83 -0
  649. package/src/trace/retain/copy-on-error.ts +76 -0
  650. package/src/trace/runtime/expire-stale-traces.ts +54 -0
  651. package/src/trace/runtime/flow-step.ts +147 -0
  652. package/src/trace/runtime/flush-steps.ts +31 -0
  653. package/src/trace/runtime/pending-writes.ts +54 -0
  654. package/src/trace/runtime/step-buffer.ts +298 -0
  655. package/src/trace/runtime/step-error.ts +21 -0
  656. package/src/trace/runtime/step-meta.ts +55 -0
  657. package/src/trace/runtime/thenable.ts +12 -0
  658. package/src/trace/runtime/truncate-trace.ts +62 -0
  659. package/src/trace/schema/trace-fields.ts +52 -0
  660. package/src/trace/schema/trace-retained.ts +22 -0
  661. package/src/trace/schema/trace-step-fields.ts +44 -0
  662. package/src/trace/schema/trace-step-retained.ts +25 -0
  663. package/src/trace/schema/trace-step.ts +18 -0
  664. package/src/trace/schema/trace.ts +12 -0
  665. package/src/trace/transformer/apply.ts +79 -0
  666. package/src/trace/transformer/build-meta-literal.ts +30 -0
  667. package/src/trace/transformer/find-flow-step-sites.ts +85 -0
  668. package/src/trace/transformer/inject-flow-step-import.ts +39 -0
  669. package/src/trace/transformer/transform-error.ts +14 -0
  670. package/src/trace/transformer/transform-flow-steps.ts +123 -0
  671. package/src/trace/transformer/wrap-function-declaration.ts +62 -0
  672. package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
  673. package/src/workspace/affected.ts +110 -0
  674. package/src/workspace/changed-files.ts +163 -0
  675. package/src/workspace/check-deps.ts +213 -0
  676. package/src/workspace/checksum.ts +20 -0
  677. package/src/workspace/dependency-graph.ts +67 -0
  678. package/src/workspace/detect-pipework-copies.ts +93 -0
  679. package/src/workspace/discover.ts +206 -0
  680. package/src/workspace/generate.ts +401 -0
  681. package/src/workspace/index.ts +7 -0
  682. package/src/workspace/module-imports-pipework.ts +39 -0
  683. package/src/workspace/module-package-name.ts +12 -0
  684. package/src/workspace/scrub-git-env.ts +23 -0
  685. package/src/workspace/source-paths.ts +36 -0
  686. package/src/workspace/sync.ts +182 -0
  687. package/dist/REFERENCE.md +0 -1477
  688. package/dist/infra/access-links/rate-limit.d.ts +0 -10
  689. package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
  690. package/dist/infra/access-links/rate-limit.js +0 -28
  691. package/dist/infra/access-links/rate-limit.js.map +0 -1
  692. package/dist/infra/email/sigv4.d.ts +0 -24
  693. package/dist/infra/email/sigv4.d.ts.map +0 -1
  694. package/dist/infra/email/sigv4.js +0 -55
  695. package/dist/infra/email/sigv4.js.map +0 -1
@@ -0,0 +1,566 @@
1
+ import type { ResolvedConfig } from './config/load.js'
2
+ import type { ResolvedDatabase } from './config/load.js'
3
+ import { loadConfig as parseConfig } from './config/load.js'
4
+ import type { AcceptReadonly } from '../data/db/readonly.js'
5
+ import type { BlueprintInput } from './config/schema.js'
6
+ import type { EnvDefs, ResolveEnvDefs } from './config/env-types.js'
7
+ import type { ManagedConnection, ConnectionRole } from '../data/db/pool.js'
8
+ import { createManagedConnection } from '../data/db/pool.js'
9
+ import { createReservationPublisher, computeBudget, BUDGET_QUERY, type ConnectionBudget } from '../data/db/reservation.js'
10
+ import { sql } from '../data/db/sql.js'
11
+ import { InvariantViolation } from '../invariants/assert.js'
12
+ import type { Surface, SurfaceContext, SurfaceKind } from './surface/types.js'
13
+ import type { StartResult } from './surface/start.js'
14
+ import { startSurfaces } from './surface/start.js'
15
+ import { runScript } from '../async/jobs/run-script.js'
16
+ import { orchestrateStartup } from './lifecycle/startup.js'
17
+ import type { LifecycleConfig, StartupHook, ShutdownHook } from './lifecycle/types.js'
18
+ import { getBaseLogger } from './logging/index.js'
19
+ import { validateStartup, type ValidationContext } from './validation/startup.js'
20
+ import { ownerSystemChannelWarnings } from './validation/rls-role.js'
21
+ import { createJobContext } from '../request/context/create.js'
22
+ import { runInContext } from '../request/context/store.js'
23
+
24
+ /** The application instance — holds config, connection pools, surfaces, and lifecycle. */
25
+ export interface Manifold<TEnv extends EnvDefs = EnvDefs> {
26
+ /** Resolved configuration derived from the Blueprint passed to createManifold. */
27
+ readonly config: ResolvedConfig
28
+ /** The release this process runs, read from the variable `release.env` names; null when no release is configured or the variable is unset or empty. Written on every trace and on the job row of the worker that ran it. */
29
+ readonly release: string | null
30
+ /** Typed environment variables resolved from the `env` config field. */
31
+ readonly env: Readonly<ResolveEnvDefs<TEnv>>
32
+ /** Database connection pool manager — use `pool.getOrCreate(config.database(name))` outside managed contexts. */
33
+ readonly pool: PoolState
34
+ /** Test isolation lifecycle tracker — used internally by pipework/test. */
35
+ readonly isolation: IsolationState
36
+ /** Connection leak detector — tracks active connections for assertNoLeaks(). */
37
+ readonly connections: ConnectionTracker
38
+ /** Returns the names of all registered surfaces (http, worker, script). */
39
+ surfaceNames(): readonly string[]
40
+ /** Returns a copy of the surface map keyed by surface name. */
41
+ surfaceMap(): Readonly<Record<string, Surface>>
42
+ /**
43
+ * Starts all surfaces and installs SIGTERM/SIGINT handlers. Throws if already started.
44
+ * `options.port` is the port for the http surface that declares none (what `serve --port` / `PORT` set).
45
+ */
46
+ start(options?: StartOptions): Promise<void>
47
+ /**
48
+ * Runs the startup checks that need no database (domain integrity, surfaces) and throws
49
+ * `StartupValidationError` listing every issue. What `start()` runs first; call it from an
50
+ * app's test to catch what `serve` would refuse.
51
+ */
52
+ validate(): Promise<void>
53
+ /**
54
+ * Runs pre-shutdown hooks, tells every surface to stop accepting work at once, drains them up to
55
+ * `lifecycle.drainTimeoutMs`, then closes all pools (5s bound). At the deadline the surfaces are forced
56
+ * (open sockets destroyed, in-flight jobs aborted and handed back) and `forced` is true. A SIGTERM/SIGINT
57
+ * handler exits 1 when forced or when this rejects, else 0.
58
+ */
59
+ stop(): Promise<StopResult>
60
+ /** Runs a callback in a managed job context — the canonical entry point for seed scripts and one-off tasks. */
61
+ seed<T>(fn: () => T | Promise<T>, options?: SeedOptions): Promise<T>
62
+ /**
63
+ * Runs `fn` as a traced process-level flow: its own trace (phase `script`, surfaces `[name]`, job type `name`),
64
+ * opened with a step naming this process (host, pid, release) and closed when `fn` settles. With a tenant, the
65
+ * default database's transaction is bound to the flow. It is what an app uses for work in a standalone script.
66
+ */
67
+ script<T>(name: string, fn: () => T | Promise<T>, options?: ScriptOptions): Promise<T>
68
+ }
69
+
70
+ /** What {@link Manifold.stop} resolves with: `forced` is true when the drain deadline fired. */
71
+ export interface StopResult {
72
+ readonly forced: boolean
73
+ }
74
+
75
+ /** Options for {@link Manifold.script}. */
76
+ export interface ScriptOptions {
77
+ tenant?: string | null
78
+ auth?: unknown
79
+ }
80
+
81
+ /** Options for {@link Manifold.start}. */
82
+ export interface StartOptions {
83
+ /** The port for the http surface that declares none. */
84
+ port?: number
85
+ /**
86
+ * Start only the surfaces of these kinds (for a worker-only process: `['worker']`). Unset starts
87
+ * every surface. Every surface is still validated; a filter that matches none is a `ConfigError`.
88
+ */
89
+ kinds?: readonly SurfaceKind[]
90
+ }
91
+
92
+ /** ALS context the {@link Manifold.seed} callback runs under — tenant scope, auth principal, and job type. */
93
+ export interface SeedOptions {
94
+ tenant?: string | null
95
+ auth?: unknown
96
+ jobType?: string
97
+ }
98
+
99
+ /** Manages database connection pools keyed by database name. */
100
+ export interface PoolState {
101
+ /**
102
+ * Returns existing pool or creates one for this database config and role. With no role the
103
+ * default follows the database's mode: `system` (the platform role, `config.systemUrl`) where
104
+ * `rls.platformRole` is set, `owner` otherwise. The `app` role connects via `config.appUrl`
105
+ * (falling back to `url` when unset). An explicit `'owner'` always gives the owner connection;
106
+ * in platform mode that is for DDL only, and `label` names the caller in the one info line it logs.
107
+ */
108
+ getOrCreate(config: ResolvedDatabase, role?: ConnectionRole, label?: string): ManagedConnection
109
+ /** How many owner-role connections this pool has created (test overrides excluded). In platform mode a running manifold keeps it at 0. */
110
+ ownerConnectionsCreated(): number
111
+ /**
112
+ * The connections this database's server can still give this process without starving other
113
+ * pipework processes: `max_connections` less the reserved slots, the connections held now, and
114
+ * every other publishing process's unopened reservation. Needs `pool.publishReservation: true` on
115
+ * the databases whose pools should count. Waits for this process's own pending publication first.
116
+ */
117
+ connectionBudget(name: string): Promise<ConnectionBudget>
118
+ /** Returns pool by name, or undefined if not yet created. */
119
+ get(name: string): ManagedConnection | undefined
120
+ /** True when a test-harness override is registered for this database — collapsed (transaction-isolation) mode, where every role shares the single rolled-back connection. */
121
+ isOverridden(name: string): boolean
122
+ /** Closes all managed connections; with `timeoutSeconds`, queries still running then are cancelled. */
123
+ closeAll(options?: { timeoutSeconds?: number }): Promise<void>
124
+ /** Number of active connection pools. */
125
+ count(): number
126
+ /** Registers a test-mode connection override. getOrCreate() returns overrides before creating new connections. */
127
+ override(name: string, conn: ManagedConnection): void
128
+ /** Removes all test-mode connection overrides. */
129
+ clearOverrides(): void
130
+ }
131
+
132
+ /** Tracks test isolation lifecycle — detects leaked isolation contexts. */
133
+ export interface IsolationState {
134
+ /** Marks the start of an isolation context (e.g. BEGIN in a test). */
135
+ markBegin(): void
136
+ /** Marks the end of an isolation context (e.g. ROLLBACK in a test). */
137
+ markEnd(): void
138
+ /** Throws InvariantViolation if any isolation contexts are still active. */
139
+ assertClean(): void
140
+ /** Returns counts of active, total begins, and total ends. */
141
+ stats(): { active: number; totalBegins: number; totalEnds: number }
142
+ /** Resets all counters — only for test infrastructure. */
143
+ reset(): void
144
+ }
145
+
146
+ /** Tracks active database connections for leak detection. */
147
+ export interface ConnectionTracker {
148
+ /** Records a new active connection with its origin context. */
149
+ track(id: string, name: string, context: string): void
150
+ /** Marks a connection as released. */
151
+ release(id: string): void
152
+ /** Number of currently tracked connections. */
153
+ activeCount(): number
154
+ /** Throws InvariantViolation if active connections exceed maxExpected. */
155
+ assertNoLeaks(maxExpected: number): void
156
+ }
157
+
158
+ /**
159
+ * Creates the Pipework application instance. This is the entry point for every Pipework app.
160
+ * Define in `pipework.config.ts` and export as default.
161
+ *
162
+ * The `env` field declares the app's environment variables — the canonical
163
+ * home for runtime config (ports, service tokens, bucket names, flags) in
164
+ * place of scattered `process.env` reads. Each variable is read once at config
165
+ * load, validated and coerced to its declared type (loud error on a bad or
166
+ * missing-required value), and exposed typed on `manifold.env`.
167
+ *
168
+ * @example
169
+ * const manifold = createManifold({
170
+ * databases: { app: { url: 'DATABASE_URL', testUrl: 'DATABASE_URL_TEST' } },
171
+ * env: {
172
+ * PORT: { type: 'number', defaults: { development: '3000', test: '0' } },
173
+ * S3_BUCKET: { type: 'string', required: true },
174
+ * API_TOKEN: { type: 'string', required: true, sensitive: true },
175
+ * },
176
+ * })
177
+ * manifold.env.PORT // number — from process.env.PORT, or the per-environment default
178
+ * manifold.env.S3_BUCKET // string — startup fails loudly if unset
179
+ * export default manifold
180
+ */
181
+ export function createManifold<const TEnv extends EnvDefs = EnvDefs>(
182
+ raw: AcceptReadonly<Omit<BlueprintInput, 'env'>> & {
183
+ env?: TEnv | undefined
184
+ surfaces?: Record<string, Surface>
185
+ lifecycle?: LifecycleConfig
186
+ },
187
+ ): Manifold<TEnv> {
188
+ const { surfaces: surfacesDef, lifecycle: lifecycleDef, ...blueprintRaw } = raw
189
+ const config = parseConfig(blueprintRaw)
190
+ const pool = createPoolState(config)
191
+ const isolation = createIsolationState()
192
+ const connections = createConnectionTracker()
193
+ const surfaces = surfacesDef ?? {}
194
+ const lifecycleConfig = lifecycleDef ?? {}
195
+
196
+ // The database queue migrations land in: the sole database, or the declared
197
+ // defaultDatabase. Ambiguous multi-DB configs (no default) already fail at
198
+ // `pipework generate`, so skipping there loses nothing.
199
+ const startupContext = (connectivity: boolean): ValidationContext => {
200
+ const names = config.databaseNames()
201
+ const defaultDbName = names.length === 1 ? names[0] : config.raw.defaultDatabase
202
+ return {
203
+ configuredDatabases: names,
204
+ environment: config.environment,
205
+ surfaces,
206
+ defaultDbAvailable: names.length === 1,
207
+ ...(connectivity
208
+ ? {
209
+ databases: config.databases(),
210
+ defaultDatabase: defaultDbName !== undefined ? config.database(defaultDbName) : undefined,
211
+ }
212
+ : { connectivityCheck: false }),
213
+ }
214
+ }
215
+
216
+ let running: StartResult | null = null
217
+ let signalCleanup: (() => void) | null = null
218
+
219
+ const manifold: Manifold<TEnv> = {
220
+ config,
221
+ release: config.release,
222
+ env: config.env as ResolveEnvDefs<TEnv>,
223
+ pool,
224
+ isolation,
225
+ connections,
226
+
227
+ surfaceNames(): readonly string[] {
228
+ return Object.keys(surfaces)
229
+ },
230
+
231
+ surfaceMap(): Readonly<Record<string, Surface>> {
232
+ return { ...surfaces }
233
+ },
234
+
235
+ async start(options?: StartOptions): Promise<void> {
236
+ if (running !== null) {
237
+ throw new Error(
238
+ '[pipework] Manifold is already started.\n\n' +
239
+ ' Call stop() before starting again.\n',
240
+ )
241
+ }
242
+
243
+ const startupOpts: import('./lifecycle/startup.js').StartupOptions = {}
244
+ if (lifecycleConfig.preStart !== undefined) {
245
+ ;(startupOpts as { hooks: readonly StartupHook[] }).hooks = lifecycleConfig.preStart as readonly StartupHook[]
246
+ }
247
+ if (lifecycleConfig.startupTimeoutMs !== undefined) {
248
+ ;(startupOpts as { timeoutMs: number }).timeoutMs = lifecycleConfig.startupTimeoutMs
249
+ }
250
+ await orchestrateStartup(manifold, startupOpts)
251
+
252
+ await validateStartup(startupContext(true))
253
+ for (const message of ownerSystemChannelWarnings(config.databases())) getBaseLogger().warn(message)
254
+
255
+ const context: SurfaceContext = manifold
256
+ running = await startSurfaces(context, config, surfaces, {
257
+ ...(options?.port === undefined ? {} : { port: options.port }),
258
+ ...(options?.kinds === undefined ? {} : { kinds: options.kinds }),
259
+ })
260
+
261
+ signalCleanup = installSignalHandlers(manifold, lifecycleConfig.drainTimeoutMs ?? 30_000)
262
+ },
263
+
264
+ async validate(): Promise<void> {
265
+ await validateStartup(startupContext(false))
266
+ },
267
+
268
+ async seed<T>(fn: () => T | Promise<T>, options?: SeedOptions): Promise<T> {
269
+ const ctx = createJobContext({
270
+ instance: manifold,
271
+ jobType: options?.jobType ?? 'seed',
272
+ auth: options?.auth ?? null,
273
+ tenant: options?.tenant ?? null,
274
+ })
275
+ return runInContext(ctx, fn)
276
+ },
277
+
278
+ async script<T>(name: string, fn: () => T | Promise<T>, options?: ScriptOptions): Promise<T> {
279
+ return runScript(manifold, fn, {
280
+ jobType: name,
281
+ tenant: options?.tenant ?? null,
282
+ auth: options?.auth ?? null,
283
+ process: { phase: 'script', surfaces: [name] },
284
+ })
285
+ },
286
+
287
+ async stop(): Promise<StopResult> {
288
+ const logger = getBaseLogger()
289
+ const deadlineMs = lifecycleConfig.drainTimeoutMs ?? 30_000
290
+
291
+ logger.info({ deadlineMs }, 'Shutdown initiated')
292
+
293
+ if (signalCleanup !== null) {
294
+ signalCleanup()
295
+ signalCleanup = null
296
+ }
297
+
298
+ if (lifecycleConfig.preShutdown) {
299
+ for (const hook of lifecycleConfig.preShutdown) {
300
+ try {
301
+ logger.info({ hook: hook.name }, 'Running pre-shutdown hook')
302
+ await (hook as ShutdownHook).execute()
303
+ } catch (err) {
304
+ logger.error({ hook: hook.name, err }, 'Pre-shutdown hook failed')
305
+ }
306
+ }
307
+ }
308
+
309
+ let forced = false
310
+ const stopFailure: { failed: boolean; err?: unknown } = { failed: false }
311
+
312
+ if (running !== null) {
313
+ const stopping = running
314
+ logger.info({ surfaces: [...stopping.handles.keys()] }, 'Stopping surfaces')
315
+ const controller = new AbortController()
316
+ const settled = stopping.stop(controller.signal).then(
317
+ () => 'done' as const,
318
+ (err: unknown) => { stopFailure.failed = true; stopFailure.err = err; return 'done' as const },
319
+ )
320
+
321
+ const drained = await raceDelay(settled, deadlineMs)
322
+ if (drained === 'timeout') {
323
+ forced = true
324
+ logger.warn({ label: 'Surface shutdown', deadlineMs }, `Surface shutdown exceeded ${deadlineMs}ms deadline`)
325
+ logger.warn({ deadlineMs }, 'Surface shutdown exceeded deadline — forcing close')
326
+ controller.abort()
327
+ const returned = await raceDelay(settled, FORCE_WAIT_MS)
328
+ if (returned === 'timeout') {
329
+ logger.error(
330
+ { surfaces: stopping.pending(), waitedMs: FORCE_WAIT_MS },
331
+ 'Surfaces still running after forced shutdown; closing pools anyway',
332
+ )
333
+ }
334
+ }
335
+ running = null
336
+ }
337
+
338
+ logger.info('Closing connection pools')
339
+ await pool.closeAll({ timeoutSeconds: POOL_CLOSE_TIMEOUT_S })
340
+ logger.info('Shutdown complete')
341
+
342
+ if (stopFailure.failed) throw stopFailure.err
343
+ return { forced }
344
+ },
345
+ }
346
+
347
+ return manifold
348
+ }
349
+
350
+ const FORCE_WAIT_MS = 5_000
351
+ const POOL_CLOSE_TIMEOUT_S = 5
352
+ const EXIT_BACKSTOP_MS = 15_000
353
+
354
+ /** Resolves with `work`'s value, or `'timeout'` after `ms`; the timer never holds the process open. */
355
+ async function raceDelay<T>(work: Promise<T>, ms: number): Promise<T | 'timeout'> {
356
+ let timer: NodeJS.Timeout | undefined
357
+ const timeout = new Promise<'timeout'>((resolve) => {
358
+ timer = setTimeout(() => resolve('timeout'), ms)
359
+ timer.unref()
360
+ })
361
+ try {
362
+ return await Promise.race([work, timeout])
363
+ } finally {
364
+ clearTimeout(timer)
365
+ }
366
+ }
367
+
368
+ function installSignalHandlers(manifold: Manifold, drainTimeoutMs: number): () => void {
369
+ const logger = getBaseLogger()
370
+ let stopping = false
371
+
372
+ const handler = (signal: string) => {
373
+ if (stopping) return
374
+ stopping = true
375
+ logger.info({ signal }, 'Shutdown signal received')
376
+
377
+ // Backstop: a hang in a pre-shutdown hook or a pool must still end the process.
378
+ const backstop = setTimeout(() => {
379
+ logger.fatal({ signal, backstopMs: drainTimeoutMs + EXIT_BACKSTOP_MS }, 'Shutdown did not finish; exiting')
380
+ process.exit(1)
381
+ }, drainTimeoutMs + EXIT_BACKSTOP_MS)
382
+ backstop.unref()
383
+
384
+ void manifold.stop().then(({ forced }) => {
385
+ process.exit(forced ? 1 : 0)
386
+ }).catch((err) => {
387
+ logger.error({ err }, 'Error during shutdown')
388
+ process.exit(1)
389
+ })
390
+ }
391
+
392
+ const sigterm = () => handler('SIGTERM')
393
+ const sigint = () => handler('SIGINT')
394
+
395
+ process.on('SIGTERM', sigterm)
396
+ process.on('SIGINT', sigint)
397
+
398
+ return () => {
399
+ process.removeListener('SIGTERM', sigterm)
400
+ process.removeListener('SIGINT', sigint)
401
+ }
402
+ }
403
+
404
+ function createPoolState(resolvedConfig: ResolvedConfig): PoolState {
405
+ const map = new Map<string, ManagedConnection>()
406
+ const overrides = new Map<string, ManagedConnection>()
407
+ let ownerCreated = 0
408
+ const reservations = createReservationPublisher()
409
+
410
+ return {
411
+ getOrCreate(config: ResolvedDatabase, explicitRole?: ConnectionRole, label?: string): ManagedConnection {
412
+ const platform = config.rls?.platformRole !== undefined
413
+ const role: ConnectionRole = explicitRole ?? (platform ? 'system' : 'owner')
414
+ const key = role === 'owner' ? config.name : `${config.name}::${role}`
415
+
416
+ // Role-specific override first; fall back to the base (owner) override so a
417
+ // test running under transaction-isolation keeps every role on the single
418
+ // rolled-back connection. A real app-role connection is only created when no
419
+ // override is registered (i.e. production / database-isolation).
420
+ const overridden = overrides.get(key) ?? overrides.get(config.name)
421
+ if (overridden) return overridden
422
+
423
+ if (platform && explicitRole === 'owner') {
424
+ getBaseLogger().info(
425
+ { database: config.name, caller: label ?? 'unlabelled' },
426
+ `Owner-role connection requested on platform-mode database "${config.name}" by ${label ?? 'an unlabelled caller'}`,
427
+ )
428
+ }
429
+
430
+ const existing = map.get(key)
431
+ if (existing) return existing
432
+
433
+ const roleUrl = role === 'app' ? config.appUrl : role === 'system' ? config.systemUrl : undefined
434
+ const effectiveConfig = roleUrl !== undefined ? { ...config, url: roleUrl } : config
435
+ const publishing = config.pool.publishReservation === true
436
+ const release = publishing ? reservations.reserve(effectiveConfig.url, config.pool.max) : undefined
437
+ const managed = createManagedConnection(
438
+ effectiveConfig,
439
+ () => { map.delete(key); release?.() },
440
+ resolvedConfig.observability,
441
+ publishing ? reservations.poolTag : undefined,
442
+ )
443
+ map.set(key, managed)
444
+ if (role === 'owner') ownerCreated++
445
+ return managed
446
+ },
447
+
448
+ ownerConnectionsCreated(): number {
449
+ return ownerCreated
450
+ },
451
+
452
+ async connectionBudget(name: string): Promise<ConnectionBudget> {
453
+ const config = resolvedConfig.database(name)
454
+ await reservations.settled()
455
+ const rows = await this.getOrCreate(config).drizzle.execute(sql.raw(BUDGET_QUERY))
456
+ const row = rows[0] as unknown as Parameters<typeof computeBudget>[0]
457
+ return computeBudget(row, reservations.id)
458
+ },
459
+
460
+ get(name: string): ManagedConnection | undefined {
461
+ return overrides.get(name) ?? map.get(name)
462
+ },
463
+
464
+ isOverridden(name: string): boolean {
465
+ return overrides.has(name)
466
+ },
467
+
468
+ async closeAll(options?: { timeoutSeconds?: number }): Promise<void> {
469
+ const closing = [...map.values()].map(c => c.close(options))
470
+ await Promise.all(closing)
471
+ await reservations.closeAll()
472
+ overrides.clear()
473
+ },
474
+
475
+ count(): number {
476
+ return map.size + overrides.size
477
+ },
478
+
479
+ override(name: string, conn: ManagedConnection): void {
480
+ overrides.set(name, conn)
481
+ },
482
+
483
+ clearOverrides(): void {
484
+ overrides.clear()
485
+ },
486
+ }
487
+ }
488
+
489
+ function createIsolationState(): IsolationState {
490
+ let active = 0
491
+ let totalBegins = 0
492
+ let totalEnds = 0
493
+
494
+ return {
495
+ markBegin() {
496
+ active++
497
+ totalBegins++
498
+ },
499
+
500
+ markEnd() {
501
+ if (active <= 0) {
502
+ throw new InvariantViolation('isolation-end-without-begin', {
503
+ activeIsolationContexts: active,
504
+ totalBegins,
505
+ totalEnds,
506
+ })
507
+ }
508
+ active--
509
+ totalEnds++
510
+ },
511
+
512
+ assertClean() {
513
+ if (active !== 0) {
514
+ throw new InvariantViolation('isolation-context-leak', {
515
+ activeIsolationContexts: active,
516
+ totalBegins,
517
+ totalEnds,
518
+ delta: totalBegins - totalEnds,
519
+ })
520
+ }
521
+ },
522
+
523
+ stats() {
524
+ return { active, totalBegins, totalEnds }
525
+ },
526
+
527
+ reset() {
528
+ active = 0
529
+ totalBegins = 0
530
+ totalEnds = 0
531
+ },
532
+ }
533
+ }
534
+
535
+ function createConnectionTracker(): ConnectionTracker {
536
+ const tracked = new Map<string, { name: string; createdAt: number; context: string }>()
537
+
538
+ return {
539
+ track(id: string, name: string, context: string) {
540
+ tracked.set(id, { name, createdAt: Date.now(), context })
541
+ },
542
+
543
+ release(id: string) {
544
+ tracked.delete(id)
545
+ },
546
+
547
+ activeCount() {
548
+ return tracked.size
549
+ },
550
+
551
+ assertNoLeaks(maxExpected: number) {
552
+ if (tracked.size > maxExpected) {
553
+ throw new InvariantViolation('connection-pool-bounded', {
554
+ active: tracked.size,
555
+ maxExpected,
556
+ connections: [...tracked.entries()].map(([id, c]) => ({
557
+ id,
558
+ name: c.name,
559
+ age_ms: Date.now() - c.createdAt,
560
+ context: c.context,
561
+ })),
562
+ })
563
+ }
564
+ },
565
+ }
566
+ }
@@ -0,0 +1,69 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks'
2
+ import { readFileSync } from 'node:fs'
3
+ import type { Flow } from '../../request/context/types.js'
4
+
5
+ // The version this physical pipework copy reports. Read from the package.json that
6
+ // sits three levels above this module — correct whether running from `dist/core/
7
+ // runtime/broker.js` (→ dist/../package.json) or `src/core/runtime/broker.ts`
8
+ // under a type-stripping loader (→ repo-root package.json). Falls back to a sentinel
9
+ // if the file can't be resolved (e.g. an esbuild bundle relocates this module); two
10
+ // copies that both fall back compare equal and simply share the slot, which is the
11
+ // desired "N copies behave as one" outcome.
12
+ // Stryker disable all: readVersion runs only at module load (static init); ignoreStatic makes its
13
+ // mutants unreachable. The version it produces is exercised by the runtime() version-guard tests.
14
+ function readVersion(): string {
15
+ try {
16
+ const pkg = JSON.parse(
17
+ readFileSync(new URL('../../../package.json', import.meta.url), 'utf8'),
18
+ ) as { version?: string }
19
+ return pkg.version ?? '0.0.0-unknown'
20
+ } catch {
21
+ return '0.0.0-unknown'
22
+ }
23
+ }
24
+ // Stryker restore all
25
+
26
+ export const VERSION = readVersion()
27
+
28
+ // Cross-realm singleton broker. When a self-contained pipework workspace consumes
29
+ // a shared library that ALSO imports pipework at runtime, pnpm resolves two physical
30
+ // copies of pipework. Each copy's module-level singletons (the request ALS) would
31
+ // otherwise be distinct objects, so a context entered by one copy is invisible to
32
+ // `pipe()` in the other. Pinning the ALS to a process-global slot keyed by a global
33
+ // Symbol makes every physical copy of the SAME version share one AsyncLocalStorage —
34
+ // the property the `link:`-shared-leaf topology needs. Two copies of DIFFERENT
35
+ // versions must not share (their Flow shapes may diverge), so the second one throws
36
+ // an actionable error instead of silently forking.
37
+ // Stryker disable next-line StringLiteral: static module-init constant; ignoreStatic makes the mutant
38
+ // unreachable. The slot's identity is covered by the runtime() broker tests.
39
+ const SLOT = Symbol.for('pipework.runtime')
40
+
41
+ interface RuntimeSlot {
42
+ readonly version: string
43
+ readonly flowStorage: AsyncLocalStorage<Flow>
44
+ }
45
+
46
+ export function runtime(): RuntimeSlot {
47
+ const slots = globalThis as unknown as Record<symbol, RuntimeSlot | undefined>
48
+ const existing = slots[SLOT]
49
+ if (existing !== undefined) {
50
+ if (existing.version !== VERSION) {
51
+ throw new Error(
52
+ '[pipework] Two incompatible pipework versions are loaded in one process:\n\n' +
53
+ ` ${existing.version} (already initialized) and ${VERSION} (loading now).\n\n` +
54
+ ' A shared library that imports pipework at runtime must resolve the SAME\n' +
55
+ ' version as the workspace consuming it. Otherwise their AsyncLocalStorage\n' +
56
+ ' contexts and error classes are distinct objects, and a context entered by\n' +
57
+ ' one copy is invisible to pipe() in the other (no active context; 403→500).\n\n' +
58
+ ' Fix: align the leaf library and the workspace to a single pipework version.\n',
59
+ )
60
+ }
61
+ return existing
62
+ }
63
+ const fresh: RuntimeSlot = {
64
+ version: VERSION,
65
+ flowStorage: new AsyncLocalStorage<Flow>(),
66
+ }
67
+ slots[SLOT] = fresh
68
+ return fresh
69
+ }