pipework 0.252.0 → 0.252.1

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 (690) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/package.json +4 -3
  3. package/src/async/jobs/abortable-delay.ts +18 -0
  4. package/src/async/jobs/claims.ts +52 -0
  5. package/src/async/jobs/cron.ts +179 -0
  6. package/src/async/jobs/errors.ts +56 -0
  7. package/src/async/jobs/exclusion.ts +117 -0
  8. package/src/async/jobs/execute.ts +219 -0
  9. package/src/async/jobs/index.ts +10 -0
  10. package/src/async/jobs/listener.ts +135 -0
  11. package/src/async/jobs/namespace.ts +20 -0
  12. package/src/async/jobs/queue-door.ts +44 -0
  13. package/src/async/jobs/queue.ts +1012 -0
  14. package/src/async/jobs/run-script.ts +67 -0
  15. package/src/async/jobs/scheduler.ts +218 -0
  16. package/src/async/jobs/schedules-table.ts +37 -0
  17. package/src/async/jobs/serialize-error.ts +48 -0
  18. package/src/async/jobs/table.ts +191 -0
  19. package/src/async/pipeline/define.ts +53 -0
  20. package/src/async/pipeline/errors.ts +35 -0
  21. package/src/async/pipeline/execute.ts +53 -0
  22. package/src/async/pipeline/index.ts +13 -0
  23. package/src/async/pipeline/namespace.ts +12 -0
  24. package/src/async/pipeline/resume.ts +67 -0
  25. package/src/async/pipeline/run-steps.ts +98 -0
  26. package/src/async/pipeline/types.ts +57 -0
  27. package/src/async/state-machine/define.ts +64 -0
  28. package/src/async/state-machine/errors.ts +29 -0
  29. package/src/async/state-machine/index.ts +3 -0
  30. package/src/async/state-machine/namespace.ts +12 -0
  31. package/src/async/state-machine/transition.ts +90 -0
  32. package/src/async/state-machine/types.ts +37 -0
  33. package/src/async/steps/errors.ts +31 -0
  34. package/src/async/steps/graph.ts +1214 -0
  35. package/src/async/steps/hash.ts +40 -0
  36. package/src/async/steps/index.ts +7 -0
  37. package/src/async/steps/namespace.ts +7 -0
  38. package/src/async/steps/table.ts +97 -0
  39. package/src/async/steps/types.ts +318 -0
  40. package/src/audit/chain/index.ts +9 -0
  41. package/src/audit/chain/install.ts +113 -0
  42. package/src/audit/chain/retire.ts +52 -0
  43. package/src/audit/chain/verify.ts +257 -0
  44. package/src/audit/query/cursor.ts +37 -0
  45. package/src/audit/query/index.ts +9 -0
  46. package/src/audit/query/query.ts +223 -0
  47. package/src/audit/schema/audit-record-fields.ts +68 -0
  48. package/src/audit/schema/audit-record.ts +23 -0
  49. package/src/auth/auth/audit.ts +31 -0
  50. package/src/auth/auth/chain.ts +84 -0
  51. package/src/auth/auth/cookie.ts +136 -0
  52. package/src/auth/auth/email-links.ts +311 -0
  53. package/src/auth/auth/guard.ts +128 -0
  54. package/src/auth/auth/index.ts +18 -0
  55. package/src/auth/auth/multi-org.ts +337 -0
  56. package/src/auth/auth/namespace.ts +34 -0
  57. package/src/auth/auth/parse-expiry.ts +13 -0
  58. package/src/auth/auth/passwords.ts +110 -0
  59. package/src/auth/auth/schema.ts +110 -0
  60. package/src/auth/auth/sessions.ts +565 -0
  61. package/src/auth/auth/sign-in.ts +156 -0
  62. package/src/auth/auth/signing-keys.ts +69 -0
  63. package/src/auth/auth/types.ts +26 -0
  64. package/src/auth/auth/uuid.ts +10 -0
  65. package/src/auth/rbac/cache.ts +55 -0
  66. package/src/auth/rbac/check.ts +30 -0
  67. package/src/auth/rbac/create.ts +35 -0
  68. package/src/auth/rbac/index.ts +5 -0
  69. package/src/auth/rbac/middleware.ts +20 -0
  70. package/src/auth/rbac/namespace.ts +15 -0
  71. package/src/auth/rbac/resolve.ts +31 -0
  72. package/src/auth/rbac/schema.sql +31 -0
  73. package/src/auth/rbac/seed.ts +67 -0
  74. package/src/auth/rbac/tables.ts +32 -0
  75. package/src/auth/rbac/types.ts +65 -0
  76. package/src/auth/tenant/extract.ts +33 -0
  77. package/src/auth/tenant/in-tenant.ts +49 -0
  78. package/src/auth/tenant/index.ts +7 -0
  79. package/src/auth/tenant/namespace.ts +23 -0
  80. package/src/auth/tenant/propagate.ts +20 -0
  81. package/src/auth/tenant/rls.ts +120 -0
  82. package/src/auth/tenant/scope.ts +33 -0
  83. package/src/auth/tenant/scoped-db.ts +581 -0
  84. package/src/auth/tenant/types.ts +14 -0
  85. package/src/auth/tenant/validate.ts +27 -0
  86. package/src/cli/commands/add.ts +158 -0
  87. package/src/cli/commands/alerts.ts +98 -0
  88. package/src/cli/commands/check.ts +1418 -0
  89. package/src/cli/commands/codemod.ts +78 -0
  90. package/src/cli/commands/db.ts +356 -0
  91. package/src/cli/commands/dev.ts +101 -0
  92. package/src/cli/commands/generate.ts +75 -0
  93. package/src/cli/commands/init.ts +36 -0
  94. package/src/cli/commands/install.ts +28 -0
  95. package/src/cli/commands/lint.ts +62 -0
  96. package/src/cli/commands/migrate.ts +132 -0
  97. package/src/cli/commands/openapi.ts +63 -0
  98. package/src/cli/commands/remove.ts +72 -0
  99. package/src/cli/commands/run.ts +50 -0
  100. package/src/cli/commands/scope.ts +54 -0
  101. package/src/cli/commands/serve.ts +68 -0
  102. package/src/cli/commands/shard.ts +31 -0
  103. package/src/cli/commands/shared/config-pipework-version.ts +28 -0
  104. package/src/cli/commands/shared/find-config.ts +22 -0
  105. package/src/cli/commands/shared/load-config.ts +35 -0
  106. package/src/cli/commands/shared/pnpm-install.ts +95 -0
  107. package/src/cli/commands/shared/report-removed.ts +8 -0
  108. package/src/cli/commands/sync.ts +32 -0
  109. package/src/cli/commands/test.ts +307 -0
  110. package/src/cli/commands/upgrade.ts +48 -0
  111. package/src/cli/dev-bootstrap.ts +24 -0
  112. package/src/cli/errors.ts +10 -0
  113. package/src/cli/index.ts +303 -0
  114. package/src/cli/output.ts +17 -0
  115. package/src/cli/port.ts +15 -0
  116. package/src/cli/surface-kinds.ts +20 -0
  117. package/src/client/index.ts +4 -0
  118. package/src/client/poll.ts +130 -0
  119. package/src/client/report-fault.ts +119 -0
  120. package/src/core/config/app-pool.ts +19 -0
  121. package/src/core/config/aws-env.ts +29 -0
  122. package/src/core/config/base-dir.ts +24 -0
  123. package/src/core/config/discover.ts +64 -0
  124. package/src/core/config/env-resolve.ts +87 -0
  125. package/src/core/config/env-types.ts +116 -0
  126. package/src/core/config/env.ts +55 -0
  127. package/src/core/config/errors.ts +9 -0
  128. package/src/core/config/import-config.ts +40 -0
  129. package/src/core/config/index.ts +8 -0
  130. package/src/core/config/load.ts +417 -0
  131. package/src/core/config/namespace.ts +14 -0
  132. package/src/core/config/resolve.ts +195 -0
  133. package/src/core/config/schema.ts +488 -0
  134. package/src/core/config/statement-observer.ts +48 -0
  135. package/src/core/config/ts-inline-hooks.ts +75 -0
  136. package/src/core/config/ts-register.ts +4 -0
  137. package/src/core/config/ts-resolve-hooks.ts +101 -0
  138. package/src/core/errors/base.ts +49 -0
  139. package/src/core/errors/http.ts +146 -0
  140. package/src/core/errors/index.ts +2 -0
  141. package/src/core/errors/namespace.ts +31 -0
  142. package/src/core/lifecycle/drain.ts +33 -0
  143. package/src/core/lifecycle/health.ts +72 -0
  144. package/src/core/lifecycle/index.ts +4 -0
  145. package/src/core/lifecycle/namespace.ts +7 -0
  146. package/src/core/lifecycle/startup.ts +102 -0
  147. package/src/core/lifecycle/types.ts +36 -0
  148. package/src/core/logging/context.ts +60 -0
  149. package/src/core/logging/error-chain.ts +68 -0
  150. package/src/core/logging/index.ts +5 -0
  151. package/src/core/logging/logger.ts +65 -0
  152. package/src/core/logging/namespace.ts +16 -0
  153. package/src/core/logging/proxy.ts +22 -0
  154. package/src/core/logging/redact-match.ts +24 -0
  155. package/src/core/logging/types.ts +47 -0
  156. package/src/core/pipework.ts +566 -0
  157. package/src/core/runtime/broker.ts +69 -0
  158. package/src/core/surface/http.ts +133 -0
  159. package/src/core/surface/index.ts +11 -0
  160. package/src/core/surface/job-timeout.ts +40 -0
  161. package/src/core/surface/namespace.ts +13 -0
  162. package/src/core/surface/script.ts +33 -0
  163. package/src/core/surface/start.ts +142 -0
  164. package/src/core/surface/types.ts +225 -0
  165. package/src/core/surface/validate.ts +88 -0
  166. package/src/core/surface/worker.ts +528 -0
  167. package/src/core/validation/connectivity.ts +49 -0
  168. package/src/core/validation/domain.ts +99 -0
  169. package/src/core/validation/index.ts +5 -0
  170. package/src/core/validation/queue-tables.ts +312 -0
  171. package/src/core/validation/rls-role.ts +138 -0
  172. package/src/core/validation/startup.ts +51 -0
  173. package/src/core/validation/surfaces.ts +65 -0
  174. package/src/core/validation/types.ts +25 -0
  175. package/src/data/db/advisory-lock.ts +55 -0
  176. package/src/data/db/aggregates.ts +172 -0
  177. package/src/data/db/array-elements.ts +111 -0
  178. package/src/data/db/bulk-set.ts +53 -0
  179. package/src/data/db/col/index.ts +14 -0
  180. package/src/data/db/composed.ts +53 -0
  181. package/src/data/db/db.ts +276 -0
  182. package/src/data/db/excluded.ts +16 -0
  183. package/src/data/db/expressions.ts +473 -0
  184. package/src/data/db/filter.ts +90 -0
  185. package/src/data/db/function-source.ts +114 -0
  186. package/src/data/db/identifiers.ts +16 -0
  187. package/src/data/db/idx/index.ts +9 -0
  188. package/src/data/db/in-list.ts +49 -0
  189. package/src/data/db/index.ts +9 -0
  190. package/src/data/db/insert-split.ts +137 -0
  191. package/src/data/db/instrumentation.ts +82 -0
  192. package/src/data/db/maintenance.ts +28 -0
  193. package/src/data/db/namespace.ts +107 -0
  194. package/src/data/db/owner-labels.ts +9 -0
  195. package/src/data/db/pool.ts +187 -0
  196. package/src/data/db/query-label.ts +13 -0
  197. package/src/data/db/query-watch.ts +116 -0
  198. package/src/data/db/raw-client-warning.ts +37 -0
  199. package/src/data/db/readonly.ts +23 -0
  200. package/src/data/db/reservation.ts +151 -0
  201. package/src/data/db/schema-features.ts +14 -0
  202. package/src/data/db/serializable.ts +83 -0
  203. package/src/data/db/sql.ts +1 -0
  204. package/src/data/db/timeouts.ts +76 -0
  205. package/src/data/db/types.ts +18 -0
  206. package/src/data/db/unbound.ts +33 -0
  207. package/src/data/db/values.ts +29 -0
  208. package/src/data/domain/brand.ts +15 -0
  209. package/src/data/domain/build-factory.ts +193 -0
  210. package/src/data/domain/build-schema.ts +161 -0
  211. package/src/data/domain/build-table.ts +355 -0
  212. package/src/data/domain/define.ts +239 -0
  213. package/src/data/domain/external-registry.ts +34 -0
  214. package/src/data/domain/external.ts +77 -0
  215. package/src/data/domain/field.ts +279 -0
  216. package/src/data/domain/index.ts +13 -0
  217. package/src/data/domain/naming.ts +6 -0
  218. package/src/data/domain/projections.ts +57 -0
  219. package/src/data/domain/trace-safe-projection.ts +31 -0
  220. package/src/data/domain/traits.ts +108 -0
  221. package/src/data/domain/types.ts +289 -0
  222. package/src/data/jsonb/composed.ts +18 -0
  223. package/src/data/jsonb/index.ts +1 -0
  224. package/src/data/jsonb/namespace.ts +30 -0
  225. package/src/data/jsonb/query.ts +86 -0
  226. package/src/data/migrate/append-only-generate.ts +47 -0
  227. package/src/data/migrate/applied.ts +47 -0
  228. package/src/data/migrate/apply.ts +309 -0
  229. package/src/data/migrate/check.ts +119 -0
  230. package/src/data/migrate/diff.ts +357 -0
  231. package/src/data/migrate/door-generate.ts +130 -0
  232. package/src/data/migrate/framework-rls.ts +58 -0
  233. package/src/data/migrate/generate.ts +201 -0
  234. package/src/data/migrate/history.ts +215 -0
  235. package/src/data/migrate/index.ts +9 -0
  236. package/src/data/migrate/internal-definitions.ts +175 -0
  237. package/src/data/migrate/post-process.ts +73 -0
  238. package/src/data/migrate/pragma.ts +73 -0
  239. package/src/data/migrate/provision-framework.ts +147 -0
  240. package/src/data/migrate/rls-generate.ts +61 -0
  241. package/src/data/migrate/run.ts +124 -0
  242. package/src/data/migrate/safety.ts +167 -0
  243. package/src/data/migrate/snapshot.ts +368 -0
  244. package/src/data/migrate/sql-emit.ts +392 -0
  245. package/src/data/migrate/statements.ts +312 -0
  246. package/src/data/query/alias.ts +126 -0
  247. package/src/data/query/batch.ts +8 -0
  248. package/src/data/query/cache/core/cache.ts +78 -0
  249. package/src/data/query/cache/core/index.ts +1 -0
  250. package/src/data/query/cache/core/types.ts +29 -0
  251. package/src/data/query/cache/readme.md +230 -0
  252. package/src/data/query/casing.ts +76 -0
  253. package/src/data/query/collation.ts +11 -0
  254. package/src/data/query/column-builder.ts +370 -0
  255. package/src/data/query/column.ts +150 -0
  256. package/src/data/query/entity.ts +42 -0
  257. package/src/data/query/errors.ts +33 -0
  258. package/src/data/query/index.ts +14 -0
  259. package/src/data/query/logger.ts +47 -0
  260. package/src/data/query/operations.ts +45 -0
  261. package/src/data/query/pg-core/alias.ts +12 -0
  262. package/src/data/query/pg-core/checks.ts +32 -0
  263. package/src/data/query/pg-core/columns/all.ts +71 -0
  264. package/src/data/query/pg-core/columns/bigint.ts +110 -0
  265. package/src/data/query/pg-core/columns/bigserial.ts +128 -0
  266. package/src/data/query/pg-core/columns/boolean.ts +43 -0
  267. package/src/data/query/pg-core/columns/char.ts +85 -0
  268. package/src/data/query/pg-core/columns/cidr.ts +43 -0
  269. package/src/data/query/pg-core/columns/common.ts +366 -0
  270. package/src/data/query/pg-core/columns/custom.ts +232 -0
  271. package/src/data/query/pg-core/columns/date.common.ts +15 -0
  272. package/src/data/query/pg-core/columns/date.ts +112 -0
  273. package/src/data/query/pg-core/columns/double-precision.ts +55 -0
  274. package/src/data/query/pg-core/columns/enum.ts +201 -0
  275. package/src/data/query/pg-core/columns/index.ts +35 -0
  276. package/src/data/query/pg-core/columns/inet.ts +43 -0
  277. package/src/data/query/pg-core/columns/int.common.ts +57 -0
  278. package/src/data/query/pg-core/columns/integer.ts +53 -0
  279. package/src/data/query/pg-core/columns/interval.ts +83 -0
  280. package/src/data/query/pg-core/columns/json.ts +58 -0
  281. package/src/data/query/pg-core/columns/jsonb.ts +56 -0
  282. package/src/data/query/pg-core/columns/line.ts +117 -0
  283. package/src/data/query/pg-core/columns/macaddr.ts +43 -0
  284. package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
  285. package/src/data/query/pg-core/columns/numeric.ts +227 -0
  286. package/src/data/query/pg-core/columns/point.ts +127 -0
  287. package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
  288. package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
  289. package/src/data/query/pg-core/columns/real.ts +58 -0
  290. package/src/data/query/pg-core/columns/serial.ts +55 -0
  291. package/src/data/query/pg-core/columns/smallint.ts +53 -0
  292. package/src/data/query/pg-core/columns/smallserial.ts +60 -0
  293. package/src/data/query/pg-core/columns/text.ts +67 -0
  294. package/src/data/query/pg-core/columns/time.ts +72 -0
  295. package/src/data/query/pg-core/columns/timestamp.ts +163 -0
  296. package/src/data/query/pg-core/columns/uuid.ts +51 -0
  297. package/src/data/query/pg-core/columns/varchar.ts +89 -0
  298. package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
  299. package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
  300. package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
  301. package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
  302. package/src/data/query/pg-core/db.ts +674 -0
  303. package/src/data/query/pg-core/dialect.ts +1404 -0
  304. package/src/data/query/pg-core/expressions.ts +25 -0
  305. package/src/data/query/pg-core/foreign-keys.ts +130 -0
  306. package/src/data/query/pg-core/index.ts +21 -0
  307. package/src/data/query/pg-core/indexes.ts +276 -0
  308. package/src/data/query/pg-core/policies.ts +56 -0
  309. package/src/data/query/pg-core/primary-keys.ts +62 -0
  310. package/src/data/query/pg-core/query-builders/count.ts +86 -0
  311. package/src/data/query/pg-core/query-builders/delete.ts +293 -0
  312. package/src/data/query/pg-core/query-builders/index.ts +7 -0
  313. package/src/data/query/pg-core/query-builders/insert.ts +452 -0
  314. package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
  315. package/src/data/query/pg-core/query-builders/query.ts +157 -0
  316. package/src/data/query/pg-core/query-builders/raw.ts +49 -0
  317. package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
  318. package/src/data/query/pg-core/query-builders/select.ts +1346 -0
  319. package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
  320. package/src/data/query/pg-core/query-builders/update.ts +626 -0
  321. package/src/data/query/pg-core/roles.ts +41 -0
  322. package/src/data/query/pg-core/schema.ts +72 -0
  323. package/src/data/query/pg-core/sequence.ts +41 -0
  324. package/src/data/query/pg-core/session.ts +292 -0
  325. package/src/data/query/pg-core/subquery.ts +46 -0
  326. package/src/data/query/pg-core/table.ts +252 -0
  327. package/src/data/query/pg-core/unique-constraint.ts +73 -0
  328. package/src/data/query/pg-core/utils/array.ts +95 -0
  329. package/src/data/query/pg-core/utils/index.ts +1 -0
  330. package/src/data/query/pg-core/utils.ts +104 -0
  331. package/src/data/query/pg-core/view-base.ts +14 -0
  332. package/src/data/query/pg-core/view-common.ts +1 -0
  333. package/src/data/query/pg-core/view.ts +435 -0
  334. package/src/data/query/pg-core/with-builder.ts +41 -0
  335. package/src/data/query/postgres-js/README.md +46 -0
  336. package/src/data/query/postgres-js/array-parser.ts +45 -0
  337. package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
  338. package/src/data/query/postgres-js/driver.ts +163 -0
  339. package/src/data/query/postgres-js/index.ts +2 -0
  340. package/src/data/query/postgres-js/session.ts +234 -0
  341. package/src/data/query/primary-key.ts +11 -0
  342. package/src/data/query/query-builders/query-builder.ts +19 -0
  343. package/src/data/query/query-builders/select.types.ts +175 -0
  344. package/src/data/query/query-promise.ts +35 -0
  345. package/src/data/query/relations.ts +725 -0
  346. package/src/data/query/runnable-query.ts +12 -0
  347. package/src/data/query/selection-proxy.ts +121 -0
  348. package/src/data/query/session.ts +8 -0
  349. package/src/data/query/sql/expressions/conditions.ts +741 -0
  350. package/src/data/query/sql/expressions/index.ts +2 -0
  351. package/src/data/query/sql/expressions/select.ts +45 -0
  352. package/src/data/query/sql/functions/aggregate.ts +129 -0
  353. package/src/data/query/sql/functions/index.ts +2 -0
  354. package/src/data/query/sql/functions/vector.ts +178 -0
  355. package/src/data/query/sql/index.ts +3 -0
  356. package/src/data/query/sql/sql.ts +794 -0
  357. package/src/data/query/subquery.ts +53 -0
  358. package/src/data/query/table.ts +208 -0
  359. package/src/data/query/table.utils.ts +2 -0
  360. package/src/data/query/tracing-utils.ts +3 -0
  361. package/src/data/query/tracing.ts +11 -0
  362. package/src/data/query/utils.ts +357 -0
  363. package/src/data/query/version.ts +4 -0
  364. package/src/data/query/view-common.ts +1 -0
  365. package/src/data/schema/branded.ts +13 -0
  366. package/src/data/schema/generated/coerce.ts +5 -0
  367. package/src/data/schema/generated/combinator.ts +6 -0
  368. package/src/data/schema/generated/encoding.ts +5 -0
  369. package/src/data/schema/generated/error.ts +6 -0
  370. package/src/data/schema/generated/format.ts +5 -0
  371. package/src/data/schema/generated/type-constructor.ts +10 -0
  372. package/src/data/schema/generated/type.ts +6 -0
  373. package/src/data/schema/index.ts +6 -0
  374. package/src/data/schema/json-schema.ts +33 -0
  375. package/src/data/schema/namespace.ts +55 -0
  376. package/src/data/schema/parse.ts +39 -0
  377. package/src/data/schema/types.ts +39 -0
  378. package/src/data/temporal/append-only.ts +134 -0
  379. package/src/data/temporal/close.ts +27 -0
  380. package/src/data/temporal/columns.ts +10 -0
  381. package/src/data/temporal/definition-queries.ts +70 -0
  382. package/src/data/temporal/errors.ts +10 -0
  383. package/src/data/temporal/get-current.ts +22 -0
  384. package/src/data/temporal/index.ts +9 -0
  385. package/src/data/temporal/namespace.ts +36 -0
  386. package/src/data/temporal/query.ts +25 -0
  387. package/src/data/temporal/resolve.ts +17 -0
  388. package/src/data/temporal/revise.ts +67 -0
  389. package/src/data/temporal/types.ts +22 -0
  390. package/src/data/valve/artifact.ts +33 -0
  391. package/src/data/valve/contract-diff.ts +21 -0
  392. package/src/data/valve/cross.ts +57 -0
  393. package/src/data/valve/crossing-ledger.ts +50 -0
  394. package/src/data/valve/decision.ts +44 -0
  395. package/src/data/valve/durable-crossing.ts +52 -0
  396. package/src/data/valve/execute-crossing.ts +77 -0
  397. package/src/data/valve/faucet.ts +56 -0
  398. package/src/data/valve/gate.ts +114 -0
  399. package/src/data/valve/graph.ts +77 -0
  400. package/src/data/valve/index.ts +53 -0
  401. package/src/data/valve/namespace.ts +57 -0
  402. package/src/data/valve/registry.ts +50 -0
  403. package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
  404. package/src/data/valve/schema/valve-crossing.ts +9 -0
  405. package/src/data/valve/supply.ts +154 -0
  406. package/src/data/valve/types.ts +143 -0
  407. package/src/data/vector/columns.ts +27 -0
  408. package/src/data/vector/index.ts +4 -0
  409. package/src/data/vector/namespace.ts +33 -0
  410. package/src/data/vector/query.ts +85 -0
  411. package/src/data/vector/validate.ts +16 -0
  412. package/src/data/write/audit/actor.ts +15 -0
  413. package/src/data/write/audit/audit-columns.ts +18 -0
  414. package/src/data/write/audit/audit-select.ts +111 -0
  415. package/src/data/write/audit/bound-transaction.ts +14 -0
  416. package/src/data/write/audit/cte-compile.ts +32 -0
  417. package/src/data/write/audit/decode-returning.ts +47 -0
  418. package/src/data/write/audit/final-select.ts +43 -0
  419. package/src/data/write/audit/infra-audit.ts +36 -0
  420. package/src/data/write/audit/primary-key.ts +65 -0
  421. package/src/data/write/audit/projection.ts +41 -0
  422. package/src/data/write/audit/read-touches.ts +86 -0
  423. package/src/data/write/audit/touch-match.ts +78 -0
  424. package/src/data/write/audit/verb-delete.ts +62 -0
  425. package/src/data/write/audit/verb-insert.ts +36 -0
  426. package/src/data/write/audit/verb-select.ts +47 -0
  427. package/src/data/write/audit/verb-update.ts +60 -0
  428. package/src/data/write/audit/verb-upsert.ts +104 -0
  429. package/src/data/write/conflict.ts +43 -0
  430. package/src/data/write/delete.ts +38 -0
  431. package/src/data/write/execute.ts +243 -0
  432. package/src/data/write/index.ts +11 -0
  433. package/src/data/write/insert.ts +63 -0
  434. package/src/data/write/state.ts +43 -0
  435. package/src/data/write/update.ts +54 -0
  436. package/src/data/write/upsert.ts +58 -0
  437. package/src/data/write/values.ts +19 -0
  438. package/src/index.ts +230 -0
  439. package/src/infra/access-links/code.ts +70 -0
  440. package/src/infra/access-links/handle.ts +892 -0
  441. package/src/infra/access-links/index.ts +9 -0
  442. package/src/infra/access-links/namespace.ts +30 -0
  443. package/src/infra/access-links/person-check.ts +177 -0
  444. package/src/infra/access-links/schema.ts +71 -0
  445. package/src/infra/alerts/async-sources.ts +231 -0
  446. package/src/infra/alerts/audit.ts +36 -0
  447. package/src/infra/alerts/beat.ts +123 -0
  448. package/src/infra/alerts/client-faults.ts +111 -0
  449. package/src/infra/alerts/faults.ts +156 -0
  450. package/src/infra/alerts/handle.ts +778 -0
  451. package/src/infra/alerts/http.ts +192 -0
  452. package/src/infra/alerts/index.ts +12 -0
  453. package/src/infra/alerts/infra-sources.ts +180 -0
  454. package/src/infra/alerts/namespace.ts +81 -0
  455. package/src/infra/alerts/redact.ts +21 -0
  456. package/src/infra/alerts/request-faults.ts +41 -0
  457. package/src/infra/alerts/schema.ts +124 -0
  458. package/src/infra/alerts/sinks.ts +125 -0
  459. package/src/infra/alerts/source-options.ts +26 -0
  460. package/src/infra/alerts/sources.ts +503 -0
  461. package/src/infra/alerts/subsystem-sources.ts +137 -0
  462. package/src/infra/audit/emit.ts +87 -0
  463. package/src/infra/audit/index.ts +2 -0
  464. package/src/infra/audit/namespace.ts +22 -0
  465. package/src/infra/audit/schema.sql +35 -0
  466. package/src/infra/audit/types.ts +18 -0
  467. package/src/infra/aws/credentials.ts +147 -0
  468. package/src/infra/aws/sigv4.ts +140 -0
  469. package/src/infra/cache/create.ts +58 -0
  470. package/src/infra/cache/entry.ts +81 -0
  471. package/src/infra/cache/index.ts +4 -0
  472. package/src/infra/cache/namespace.ts +10 -0
  473. package/src/infra/cache/tenant.ts +93 -0
  474. package/src/infra/cache/types.ts +24 -0
  475. package/src/infra/crawl/audit.ts +35 -0
  476. package/src/infra/crawl/errors.ts +25 -0
  477. package/src/infra/crawl/handle.ts +693 -0
  478. package/src/infra/crawl/index.ts +9 -0
  479. package/src/infra/crawl/links.ts +160 -0
  480. package/src/infra/crawl/namespace.ts +36 -0
  481. package/src/infra/crawl/robots.ts +100 -0
  482. package/src/infra/crawl/schema.ts +89 -0
  483. package/src/infra/credit-line/handle.ts +883 -0
  484. package/src/infra/credit-line/index.ts +6 -0
  485. package/src/infra/credit-line/namespace.ts +7 -0
  486. package/src/infra/credit-line/schema.ts +96 -0
  487. package/src/infra/credits/handle.ts +706 -0
  488. package/src/infra/credits/index.ts +5 -0
  489. package/src/infra/credits/namespace.ts +7 -0
  490. package/src/infra/credits/schema.ts +83 -0
  491. package/src/infra/email/audit.ts +36 -0
  492. package/src/infra/email/inbound.ts +622 -0
  493. package/src/infra/email/index.ts +11 -0
  494. package/src/infra/email/mail.ts +517 -0
  495. package/src/infra/email/mime.ts +447 -0
  496. package/src/infra/email/namespace.ts +22 -0
  497. package/src/infra/email/providers.ts +111 -0
  498. package/src/infra/email/schema.ts +96 -0
  499. package/src/infra/email/sns.ts +200 -0
  500. package/src/infra/email/unsubscribe.ts +44 -0
  501. package/src/infra/fetch/address.ts +88 -0
  502. package/src/infra/fetch/connect-retry.ts +87 -0
  503. package/src/infra/fetch/handle.ts +329 -0
  504. package/src/infra/fetch/index.ts +7 -0
  505. package/src/infra/fetch/namespace.ts +70 -0
  506. package/src/infra/idempotency/index.ts +3 -0
  507. package/src/infra/idempotency/middleware.ts +87 -0
  508. package/src/infra/idempotency/store.ts +92 -0
  509. package/src/infra/idempotency/types.ts +30 -0
  510. package/src/infra/join-requests/handle.ts +312 -0
  511. package/src/infra/join-requests/index.ts +2 -0
  512. package/src/infra/join-requests/namespace.ts +7 -0
  513. package/src/infra/join-requests/schema.ts +33 -0
  514. package/src/infra/outbox/core.ts +165 -0
  515. package/src/infra/quota/errors.ts +32 -0
  516. package/src/infra/quota/handle.ts +215 -0
  517. package/src/infra/quota/index.ts +5 -0
  518. package/src/infra/quota/namespace.ts +7 -0
  519. package/src/infra/quota/schema.ts +15 -0
  520. package/src/infra/storage/backend.ts +34 -0
  521. package/src/infra/storage/handle.ts +513 -0
  522. package/src/infra/storage/index.ts +9 -0
  523. package/src/infra/storage/local.ts +104 -0
  524. package/src/infra/storage/namespace.ts +13 -0
  525. package/src/infra/storage/s3.ts +257 -0
  526. package/src/infra/storage/schema.ts +24 -0
  527. package/src/infra/support/handle.ts +854 -0
  528. package/src/infra/support/http.ts +229 -0
  529. package/src/infra/support/index.ts +7 -0
  530. package/src/infra/support/namespace.ts +12 -0
  531. package/src/infra/support/schema.ts +96 -0
  532. package/src/infra/webhook/inbound.ts +45 -0
  533. package/src/infra/webhook/index.ts +5 -0
  534. package/src/infra/webhook/namespace.ts +24 -0
  535. package/src/infra/webhook/outbound.ts +315 -0
  536. package/src/infra/webhook/sign.ts +32 -0
  537. package/src/infra/webhook/verify.ts +82 -0
  538. package/src/invariants/assert.ts +26 -0
  539. package/src/invariants/index.ts +1 -0
  540. package/src/lint/config.ts +56 -0
  541. package/src/lint/doctrine.ts +163 -0
  542. package/src/lint/include.ts +97 -0
  543. package/src/lint/index.ts +3 -0
  544. package/src/lint/preset.ts +10 -0
  545. package/src/lint/resolver.ts +218 -0
  546. package/src/lint/rules/no-reexports.ts +46 -0
  547. package/src/request/behavior/audited.ts +85 -0
  548. package/src/request/behavior/cached.ts +62 -0
  549. package/src/request/behavior/compose.ts +28 -0
  550. package/src/request/behavior/index.ts +5 -0
  551. package/src/request/behavior/namespace.ts +16 -0
  552. package/src/request/behavior/types.ts +26 -0
  553. package/src/request/behavior/versioned.ts +54 -0
  554. package/src/request/context/create.ts +103 -0
  555. package/src/request/context/guard.ts +49 -0
  556. package/src/request/context/index.ts +4 -0
  557. package/src/request/context/run-in-transaction.ts +200 -0
  558. package/src/request/context/store.ts +28 -0
  559. package/src/request/context/types.ts +50 -0
  560. package/src/request/di/builder.ts +535 -0
  561. package/src/request/di/index.ts +8 -0
  562. package/src/request/di/resolve.ts +271 -0
  563. package/src/request/di/types.ts +262 -0
  564. package/src/request/fitting/namespace.ts +7 -0
  565. package/src/request/fixture/batch.ts +71 -0
  566. package/src/request/fixture/builder.ts +26 -0
  567. package/src/request/fixture/errors.ts +10 -0
  568. package/src/request/fixture/index.ts +8 -0
  569. package/src/request/fixture/namespace.ts +23 -0
  570. package/src/request/fixture/paginate.ts +44 -0
  571. package/src/request/fixture/to-handlers.ts +260 -0
  572. package/src/request/fixture/types.ts +79 -0
  573. package/src/request/flow/act-as.ts +78 -0
  574. package/src/request/flow/namespace.ts +17 -0
  575. package/src/request/http/error-step.ts +42 -0
  576. package/src/request/http/file.ts +141 -0
  577. package/src/request/http/index.ts +4 -0
  578. package/src/request/http/middleware.ts +141 -0
  579. package/src/request/http/namespace.ts +5 -0
  580. package/src/request/http/rate-limit-classes.ts +170 -0
  581. package/src/request/http/response.ts +82 -0
  582. package/src/request/http/server.ts +916 -0
  583. package/src/request/http/sniff.ts +261 -0
  584. package/src/request/http/types.ts +250 -0
  585. package/src/request/http/upload.ts +284 -0
  586. package/src/request/internal/text.ts +6 -0
  587. package/src/request/openapi/generate.ts +205 -0
  588. package/src/request/openapi/index.ts +2 -0
  589. package/src/request/openapi/namespace.ts +7 -0
  590. package/src/test/auth.ts +13 -0
  591. package/src/test/auto-setup.ts +45 -0
  592. package/src/test/context.ts +91 -0
  593. package/src/test/crawl-fixture.ts +157 -0
  594. package/src/test/discover-fork.ts +17 -0
  595. package/src/test/fingerprint.ts +135 -0
  596. package/src/test/globals.d.ts +7 -0
  597. package/src/test/index.ts +19 -0
  598. package/src/test/namespace.ts +87 -0
  599. package/src/test/plugin.ts +189 -0
  600. package/src/test/progress.ts +185 -0
  601. package/src/test/reap-after-run.ts +28 -0
  602. package/src/test/reap.ts +286 -0
  603. package/src/test/reset.ts +253 -0
  604. package/src/test/savepoints.ts +172 -0
  605. package/src/test/setup.ts +1422 -0
  606. package/src/test/system-channel.ts +50 -0
  607. package/src/test/vitest-plugin.ts +142 -0
  608. package/src/test/vitest-workspace.ts +507 -0
  609. package/src/test/vitest.ts +333 -0
  610. package/src/test/watch.ts +105 -0
  611. package/src/trace/capture/bounded-serializer.ts +146 -0
  612. package/src/trace/cardinality/analyze.ts +173 -0
  613. package/src/trace/cardinality/branch-context.ts +214 -0
  614. package/src/trace/cardinality/check.ts +33 -0
  615. package/src/trace/cardinality/classify-edge.ts +64 -0
  616. package/src/trace/cardinality/structural-max.ts +107 -0
  617. package/src/trace/check/coverage-check.ts +188 -0
  618. package/src/trace/check/flow-check.ts +103 -0
  619. package/src/trace/check/flow-step-site.ts +234 -0
  620. package/src/trace/check/io-pattern.ts +116 -0
  621. package/src/trace/codemod/add-cardinality.ts +152 -0
  622. package/src/trace/codemod/run.ts +80 -0
  623. package/src/trace/entry/child-trace.ts +21 -0
  624. package/src/trace/entry/close-trace.ts +87 -0
  625. package/src/trace/entry/finalize-trace.ts +28 -0
  626. package/src/trace/entry/open-trace.ts +138 -0
  627. package/src/trace/entry/parent-trace.ts +20 -0
  628. package/src/trace/entry/parse-traceparent.ts +39 -0
  629. package/src/trace/entry/process-start.ts +38 -0
  630. package/src/trace/entry/trace-context.ts +26 -0
  631. package/src/trace/entry/tracing-enabled.ts +10 -0
  632. package/src/trace/external/record.ts +195 -0
  633. package/src/trace/external/report.ts +66 -0
  634. package/src/trace/namespace.ts +19 -0
  635. package/src/trace/partition/day.ts +47 -0
  636. package/src/trace/partition/index.ts +14 -0
  637. package/src/trace/partition/partition-name.ts +23 -0
  638. package/src/trace/partition/plan.ts +82 -0
  639. package/src/trace/partition/schedule.ts +26 -0
  640. package/src/trace/partition/startup-hook.ts +39 -0
  641. package/src/trace/partition/sync.ts +154 -0
  642. package/src/trace/partition/tables.ts +53 -0
  643. package/src/trace/read/tree.ts +83 -0
  644. package/src/trace/retain/copy-on-error.ts +76 -0
  645. package/src/trace/runtime/expire-stale-traces.ts +54 -0
  646. package/src/trace/runtime/flow-step.ts +147 -0
  647. package/src/trace/runtime/flush-steps.ts +31 -0
  648. package/src/trace/runtime/pending-writes.ts +54 -0
  649. package/src/trace/runtime/step-buffer.ts +298 -0
  650. package/src/trace/runtime/step-error.ts +21 -0
  651. package/src/trace/runtime/step-meta.ts +55 -0
  652. package/src/trace/runtime/thenable.ts +12 -0
  653. package/src/trace/runtime/truncate-trace.ts +62 -0
  654. package/src/trace/schema/trace-fields.ts +52 -0
  655. package/src/trace/schema/trace-retained.ts +22 -0
  656. package/src/trace/schema/trace-step-fields.ts +44 -0
  657. package/src/trace/schema/trace-step-retained.ts +25 -0
  658. package/src/trace/schema/trace-step.ts +18 -0
  659. package/src/trace/schema/trace.ts +12 -0
  660. package/src/trace/transformer/apply.ts +79 -0
  661. package/src/trace/transformer/build-meta-literal.ts +30 -0
  662. package/src/trace/transformer/find-flow-step-sites.ts +85 -0
  663. package/src/trace/transformer/inject-flow-step-import.ts +39 -0
  664. package/src/trace/transformer/transform-error.ts +14 -0
  665. package/src/trace/transformer/transform-flow-steps.ts +123 -0
  666. package/src/trace/transformer/wrap-function-declaration.ts +62 -0
  667. package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
  668. package/src/workspace/affected.ts +110 -0
  669. package/src/workspace/changed-files.ts +163 -0
  670. package/src/workspace/check-deps.ts +213 -0
  671. package/src/workspace/checksum.ts +20 -0
  672. package/src/workspace/dependency-graph.ts +67 -0
  673. package/src/workspace/detect-pipework-copies.ts +93 -0
  674. package/src/workspace/discover.ts +206 -0
  675. package/src/workspace/generate.ts +401 -0
  676. package/src/workspace/index.ts +7 -0
  677. package/src/workspace/module-imports-pipework.ts +39 -0
  678. package/src/workspace/module-package-name.ts +12 -0
  679. package/src/workspace/scrub-git-env.ts +23 -0
  680. package/src/workspace/source-paths.ts +36 -0
  681. package/src/workspace/sync.ts +182 -0
  682. package/dist/REFERENCE.md +0 -1477
  683. package/dist/infra/access-links/rate-limit.d.ts +0 -10
  684. package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
  685. package/dist/infra/access-links/rate-limit.js +0 -28
  686. package/dist/infra/access-links/rate-limit.js.map +0 -1
  687. package/dist/infra/email/sigv4.d.ts +0 -24
  688. package/dist/infra/email/sigv4.d.ts.map +0 -1
  689. package/dist/infra/email/sigv4.js +0 -55
  690. package/dist/infra/email/sigv4.js.map +0 -1
@@ -0,0 +1,195 @@
1
+ // `trace.traceparent`, `trace.env` and `trace.record`: carry the current trace
2
+ // to a process outside Node, stage the steps it reports back, and mark point events.
3
+
4
+ import { randomUUID } from 'node:crypto'
5
+ import { getContext } from '../../request/context/store.js'
6
+ import { getBaseLogger } from '../../core/logging/index.js'
7
+ import { recordFault, faultMessage } from '../../infra/alerts/faults.js'
8
+ import { emitReadTouches } from '../../data/write/audit/read-touches.js'
9
+ import { serializeForTrace } from '../capture/bounded-serializer.js'
10
+ import { projectStepError } from '../runtime/step-error.js'
11
+ import type { BegunStep } from '../runtime/step-buffer.js'
12
+ import {
13
+ externalStepNameSchema,
14
+ externalStepReportSchema,
15
+ parseReportTime,
16
+ type ExternalRecordResult,
17
+ type ExternalStepReport,
18
+ } from './report.js'
19
+
20
+ const NONE: ExternalRecordResult = { recorded: 0, invalid: 0, dropped: 0 }
21
+
22
+ /** W3C `traceparent` for the current trace and open step, or `null` outside a traced flow or once the trace is truncated. */
23
+ export function traceparent(): string | null {
24
+ const ctx = getContext()?.trace
25
+ if (ctx === undefined || ctx === null || ctx.buffer.truncated) return null
26
+ const traceHex = ctx.id.replaceAll('-', '')
27
+ const spanSource = (ctx.buffer.openStepId ?? ctx.id).replaceAll('-', '')
28
+ return `00-${traceHex}-${spanSource.slice(-16)}-01`
29
+ }
30
+
31
+ /** `{ TRACEPARENT }` for a child process's environment, or `{}` when there is no traceparent. */
32
+ export function env(): Record<string, string> {
33
+ const value = traceparent()
34
+ return value === null ? {} : { TRACEPARENT: value }
35
+ }
36
+
37
+ /**
38
+ * Records steps reported by an outside process under the step open now (or as
39
+ * root-level steps when none is open). Synchronous and never throws.
40
+ */
41
+ export function record(input: string | Iterable<ExternalStepReport>): ExternalRecordResult {
42
+ try {
43
+ return recordUnsafe(input)
44
+ } catch (err) {
45
+ getBaseLogger().error({ err }, 'trace.record failed; no external steps were recorded')
46
+ void recordFault('trace-record', faultMessage(err))
47
+ return NONE
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Records one zero-length step named `external:<name>` under the step open now,
53
+ * with an optional capture and, when `error` is given, status `error`. Outside a
54
+ * traced flow, or for an invalid name, it records nothing. Never throws.
55
+ */
56
+ export function event(name: string, options?: { capture?: unknown; error?: unknown }): void {
57
+ try {
58
+ const ctx = getContext()?.trace
59
+ if (ctx === undefined || ctx === null) return
60
+ if (!externalStepNameSchema.safeParse(name).success) {
61
+ getBaseLogger().error({ name }, 'trace.event name is invalid; no event was recorded')
62
+ return
63
+ }
64
+ const now = new Date()
65
+ const failed = options !== undefined && 'error' in options && options.error !== undefined
66
+ ctx.buffer.stageExternal({
67
+ id: randomUUID(),
68
+ parentStepId: ctx.buffer.openStepId,
69
+ flowStepRef: `external:${name}`,
70
+ status: failed ? 'error' : 'ok',
71
+ startedAt: now,
72
+ completedAt: now,
73
+ durationMicros: 0n,
74
+ capturedInputs: options?.capture === undefined ? null : [serializeForTrace(options.capture)],
75
+ error: failed ? projectStepError(options.error) : null,
76
+ })
77
+ } catch (err) {
78
+ getBaseLogger().error({ err }, 'trace.event failed; no event was recorded')
79
+ void recordFault('trace-record', faultMessage(err))
80
+ }
81
+ }
82
+
83
+ function recordUnsafe(input: string | Iterable<ExternalStepReport>): ExternalRecordResult {
84
+ const flow = getContext()
85
+ const ctx = flow?.trace
86
+ if (flow === undefined || ctx === undefined || ctx === null) return NONE
87
+ const buffer = ctx.buffer
88
+
89
+ let invalid = 0
90
+ const valid = new Map<string, ExternalStepReport>()
91
+ for (const candidate of candidates(input)) {
92
+ if (candidate === SKIP) continue
93
+ const parsed = candidate === BAD ? null : externalStepReportSchema.safeParse(candidate)
94
+ if (parsed === null || !parsed.success || valid.has(parsed.data.id)) {
95
+ invalid++
96
+ continue
97
+ }
98
+ valid.set(parsed.data.id, parsed.data)
99
+ }
100
+
101
+ // A parent chain that never reaches the calling step (a cycle) invalidates
102
+ // every report on it. Unknown or self parents end the chain at the caller.
103
+ const parentOf = (r: ExternalStepReport): ExternalStepReport | undefined =>
104
+ r.parent == null || r.parent === r.id ? undefined : valid.get(r.parent)
105
+ const cyclic: string[] = []
106
+ for (const r of valid.values()) {
107
+ const seen = new Set<string>()
108
+ for (let cur: ExternalStepReport | undefined = r; cur !== undefined; cur = parentOf(cur)) {
109
+ if (seen.has(cur.id)) { cyclic.push(r.id); break }
110
+ seen.add(cur.id)
111
+ }
112
+ }
113
+ for (const id of cyclic) valid.delete(id)
114
+ invalid += cyclic.length
115
+
116
+ const callerStepId = buffer.openStepId
117
+ const ordered = [...valid.values()]
118
+ .map(r => ({ r, start: parseReportTime(r.start)!, end: parseReportTime(r.end)! }))
119
+ .sort((a, b) => (a.start < b.start ? -1 : a.start > b.start ? 1 : 0))
120
+
121
+ const staged = new Map<string, string>()
122
+ const resolveParent = (r: ExternalStepReport): string | null => {
123
+ for (let p = parentOf(r); p !== undefined; p = parentOf(p)) {
124
+ const id = staged.get(p.id)
125
+ if (id !== undefined) return id
126
+ }
127
+ return callerStepId
128
+ }
129
+
130
+ let recorded = 0
131
+ let dropped = 0
132
+ const ids = new Map(ordered.map(o => [o.r.id, randomUUID()]))
133
+ for (const { r, start, end } of ordered) {
134
+ const id = ids.get(r.id)!
135
+ const parentStepId = resolveParent(r)
136
+ const row = buffer.stageExternal({
137
+ id,
138
+ parentStepId,
139
+ flowStepRef: `external:${r.name}`,
140
+ status: r.status,
141
+ startedAt: new Date(Number(start / 1000n)),
142
+ completedAt: new Date(Number(end / 1000n)),
143
+ durationMicros: end - start,
144
+ capturedInputs: r.capture === undefined ? null : [serializeForTrace(r.capture)],
145
+ error: r.status === 'error'
146
+ ? {
147
+ name: r.error?.name ?? 'ExternalError',
148
+ message: r.error?.message ?? 'step reported error',
149
+ stack: r.error?.stack ?? null,
150
+ }
151
+ : null,
152
+ })
153
+ if (row === null) { dropped++; continue }
154
+ staged.set(r.id, id)
155
+ recorded++
156
+ if (r.status === 'ok' && r.touches !== undefined && r.touches.length > 0) {
157
+ const begun: BegunStep = {
158
+ seq: row.seq,
159
+ stepId: id,
160
+ parentStepId: row.parentStepId,
161
+ flowStepRef: row.flowStepRef,
162
+ startedAt: row.startedAt,
163
+ startHrTime: 0n,
164
+ capturedInputs: row.capturedInputs,
165
+ touches: r.touches.map(t => {
166
+ const at = t.indexOf(':')
167
+ return { entity: t.slice(0, at), verb: t.slice(at + 1) }
168
+ }),
169
+ wroteTouches: new Set(),
170
+ }
171
+ // Sync like a sync flow step: fire and forget; the emitter logs its own failures.
172
+ void emitReadTouches(flow, begun)
173
+ }
174
+ }
175
+ return { recorded, invalid, dropped }
176
+ }
177
+
178
+ const SKIP = Symbol('skip')
179
+ const BAD = Symbol('bad')
180
+
181
+ function* candidates(input: string | Iterable<ExternalStepReport>): Generator<unknown> {
182
+ if (typeof input !== 'string') {
183
+ yield* input
184
+ return
185
+ }
186
+ for (const raw of input.split('\n')) {
187
+ const line = raw.trim()
188
+ if (!line.startsWith('{')) { yield SKIP; continue }
189
+ try {
190
+ yield JSON.parse(line)
191
+ } catch {
192
+ yield BAD
193
+ }
194
+ }
195
+ }
@@ -0,0 +1,66 @@
1
+ // The language-neutral report a process outside Node sends back: one JSON
2
+ // object per line. `parseReportTime` reads RFC 3339 timestamps to microsecond
3
+ // precision (a JS `Date` keeps only milliseconds).
4
+
5
+ import { z } from '../../data/schema/index.js'
6
+
7
+ const RFC3339 = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?([Zz]|[+-]\d{2}:\d{2})$/
8
+
9
+ /** Microseconds since the Unix epoch for an RFC 3339 timestamp with offset, or `null` when malformed. */
10
+ export function parseReportTime(text: string): bigint | null {
11
+ const m = RFC3339.exec(text)
12
+ if (m === null) return null
13
+ const [year, month, day, hour, minute, second] = m.slice(1, 7).map(Number) as [number, number, number, number, number, number]
14
+ if (month < 1 || month > 12 || day < 1 || hour > 23 || minute > 59 || second > 60) return null
15
+ const probe = new Date(Date.UTC(year, month - 1, day))
16
+ if (probe.getUTCMonth() !== month - 1 || probe.getUTCDate() !== day) return null
17
+ let offsetSeconds = 0
18
+ const zone = m[8] as string
19
+ if (zone !== 'Z' && zone !== 'z') {
20
+ const oh = Number(zone.slice(1, 3))
21
+ const om = Number(zone.slice(4, 6))
22
+ if (oh > 23 || om > 59) return null
23
+ offsetSeconds = (oh * 3600 + om * 60) * (zone.startsWith('-') ? -1 : 1)
24
+ }
25
+ const wholeMs = Date.UTC(year, month - 1, day, hour, minute, second)
26
+ const fraction = Number((m[7] ?? '').padEnd(6, '0').slice(0, 6))
27
+ return (BigInt(wholeMs) / 1000n - BigInt(offsetSeconds)) * 1000000n + BigInt(fraction)
28
+ }
29
+
30
+ const timestamp = z.string().refine(v => parseReportTime(v) !== null, 'expected an RFC 3339 timestamp with offset')
31
+
32
+ /** The name rule for an external step and a point event. */
33
+ export const externalStepNameSchema = z.string().min(1).max(200)
34
+
35
+ export const externalStepReportSchema = z.object({
36
+ v: z.literal(1),
37
+ id: z.string().min(1).max(128),
38
+ parent: z.string().nullable().optional(),
39
+ name: externalStepNameSchema,
40
+ start: timestamp,
41
+ end: timestamp,
42
+ status: z.enum(['ok', 'error']),
43
+ error: z.object({
44
+ name: z.string().optional(),
45
+ message: z.string(),
46
+ stack: z.string().optional(),
47
+ }).optional(),
48
+ capture: z.unknown().optional(),
49
+ touches: z.array(z.string().regex(/^[A-Za-z_][A-Za-z0-9_.]*:[A-Za-z_][A-Za-z0-9_-]*$/)).optional(),
50
+ }).refine(
51
+ r => parseReportTime(r.end)! >= parseReportTime(r.start)!,
52
+ { message: 'end is before start' },
53
+ )
54
+
55
+ /** One step reported by an outside process. */
56
+ export type ExternalStepReport = z.infer<typeof externalStepReportSchema>
57
+
58
+ /** What `trace.record` did with a report. */
59
+ export interface ExternalRecordResult {
60
+ /** Steps staged into the trace. */
61
+ readonly recorded: number
62
+ /** Reports skipped as malformed, duplicate, time-inverted or cyclic. */
63
+ readonly invalid: number
64
+ /** Valid reports not recorded: over `trace.maxExternalSteps`, or the trace is truncated. */
65
+ readonly dropped: number
66
+ }
@@ -0,0 +1,19 @@
1
+ import { env, event, record, traceparent } from './external/record.js'
2
+ import { tree } from './read/tree.js'
3
+
4
+ /** Trace namespace — hand the current trace to a process outside Node, record the steps it reports back, mark point events, and read a trace tree. */
5
+ export const trace = {
6
+ /** W3C `traceparent` for the current trace and open step; `null` outside a traced flow or when the trace is truncated. */
7
+ traceparent,
8
+ /** `{ TRACEPARENT }` for a child process's environment, or `{}` when there is no traceparent. */
9
+ env,
10
+ /** Records steps reported as JSON lines (or objects) by an outside process under the step open now. Synchronous; never throws. */
11
+ record,
12
+ /** Records one zero-length step `external:<name>` under the step open now, with an optional `capture` and `error`. A no-op outside a traced flow; never throws. */
13
+ event,
14
+ /**
15
+ * Reads every hot trace sharing `rootId` (a request's trace and the jobs it queued) with their steps. Runs on the
16
+ * given `db`, so tenant policies apply: only an unrestricted connection (table owner, tests) sees every tenant's rows.
17
+ */
18
+ tree,
19
+ }
@@ -0,0 +1,47 @@
1
+ // Day arithmetic for trace partitioning. Trace tables are RANGE-partitioned by
2
+ // a `date` column, one partition per calendar day, reckoned in UTC — the same
3
+ // frame the `date` column stores. All helpers take and return `YYYY-MM-DD`.
4
+
5
+ const DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/
6
+ const MS_PER_DAY = 86_400_000
7
+
8
+ /** The UTC calendar day of an instant, as `YYYY-MM-DD`. */
9
+ export function toDay(date: Date): string {
10
+ return date.toISOString().slice(0, 10)
11
+ }
12
+
13
+ function parseDay(day: string): number {
14
+ if (!DAY_PATTERN.test(day)) {
15
+ throw new Error(
16
+ `[pipework] Invalid day "${day}" — expected YYYY-MM-DD.\n\n` +
17
+ ' Trace partition days are UTC calendar dates with no time component.\n'
18
+ )
19
+ }
20
+ const ms = Date.parse(`${day}T00:00:00.000Z`)
21
+ // Date.parse rolls overflow (`2026-02-30` → March 2) instead of failing, so a
22
+ // well-formed string that isn't a real calendar date round-trips to a
23
+ // different day. Reject those rather than silently shifting the partition.
24
+ if (Number.isNaN(ms) || new Date(ms).toISOString().slice(0, 10) !== day) {
25
+ throw new Error(
26
+ `[pipework] Invalid day "${day}" — well-formed but not a real date.\n\n` +
27
+ ' Check the month and day are within range.\n'
28
+ )
29
+ }
30
+ return ms
31
+ }
32
+
33
+ /** The day `n` days after `day` (negative `n` moves backward). */
34
+ export function addDays(day: string, n: number): string {
35
+ return toDay(new Date(parseDay(day) + n * MS_PER_DAY))
36
+ }
37
+
38
+ /** Every day in `[from, to]` inclusive, ascending. Empty when `from > to`. */
39
+ export function dayRange(from: string, to: string): string[] {
40
+ const start = parseDay(from)
41
+ const end = parseDay(to)
42
+ const days: string[] = []
43
+ for (let ms = start; ms <= end; ms += MS_PER_DAY) {
44
+ days.push(toDay(new Date(ms)))
45
+ }
46
+ return days
47
+ }
@@ -0,0 +1,14 @@
1
+ export { syncTracePartitions } from './sync.js'
2
+ export type { PartitionSyncSummary } from './sync.js'
3
+ export { planPartitions } from './plan.js'
4
+ export type { TracePartitionConfig, DayPartition, PartitionPlan, PartitionPlanInput } from './plan.js'
5
+ export { PARTITIONED_TRACE_TABLES } from './tables.js'
6
+ export type { PartitionedTraceTable, RetentionClass } from './tables.js'
7
+ export { partitionName, parsePartitionDay } from './partition-name.js'
8
+ export { toDay, addDays, dayRange } from './day.js'
9
+ export { createTracePartitionStartupHook, TRACE_PARTITION_HOOK_NAME } from './startup-hook.js'
10
+ export {
11
+ scheduleTracePartitionMaintenance,
12
+ TRACE_PARTITION_MAINTENANCE_JOB,
13
+ TRACE_PARTITION_MAINTENANCE_CRON,
14
+ } from './schedule.js'
@@ -0,0 +1,23 @@
1
+ // The naming convention that ties a day partition back to its parent table and
2
+ // calendar day. `trace` + `2026-05-14` ⇄ `trace_p20260514`. The `_p` separator
3
+ // plus a fixed 8-digit date keeps real table names (`trace_step`,
4
+ // `trace_retained`) from ever parsing as partitions of `trace`.
5
+
6
+ const DIGITS_PATTERN = /^\d{8}$/
7
+
8
+ /** The partition table name for `parent`'s slice covering `day` (`YYYY-MM-DD`). */
9
+ export function partitionName(parent: string, day: string): string {
10
+ return `${parent}_p${day.replace(/-/g, '')}`
11
+ }
12
+
13
+ /**
14
+ * The calendar day a partition name encodes, or `null` when `name` is not a day
15
+ * partition of `parent`. Used to tell which catalog children are ours to manage.
16
+ */
17
+ export function parsePartitionDay(parent: string, name: string): string | null {
18
+ const prefix = `${parent}_p`
19
+ if (!name.startsWith(prefix)) return null
20
+ const digits = name.slice(prefix.length)
21
+ if (!DIGITS_PATTERN.test(digits)) return null
22
+ return `${digits.slice(0, 4)}-${digits.slice(4, 6)}-${digits.slice(6, 8)}`
23
+ }
@@ -0,0 +1,82 @@
1
+ // The pure core of partition maintenance: given the clock, the retention
2
+ // windows, and the partitions that currently exist, decide which day
3
+ // partitions to create and which to drop. No database access — every decision
4
+ // here is a function of its inputs, so the whole policy is unit-testable.
5
+
6
+ import { PARTITIONED_TRACE_TABLES, type RetentionClass } from './tables.js'
7
+ import { partitionName, parsePartitionDay } from './partition-name.js'
8
+ import { toDay, addDays, dayRange } from './day.js'
9
+
10
+ export interface TracePartitionConfig {
11
+ /** Days of hot partitions kept for `trace` / `trace_step`. */
12
+ readonly hotRetentionDays: number
13
+ /** Days of cold partitions kept for `trace_retained` / `trace_step_retained`. */
14
+ readonly errorRetentionDays: number
15
+ /** Days of audit partitions kept for `audit_record` — independent of trace storage. `null` keeps them all: none is dropped and none is created for the past. */
16
+ readonly auditRetentionDays: number | null
17
+ /** Days of partitions pre-created ahead of today so writes never race creation. */
18
+ readonly partitionLeadDays: number
19
+ }
20
+
21
+ /** A single day partition: which parent it belongs to, its name, and its day. */
22
+ export interface DayPartition {
23
+ readonly parent: string
24
+ readonly name: string
25
+ readonly day: string
26
+ }
27
+
28
+ export interface PartitionPlan {
29
+ readonly create: readonly DayPartition[]
30
+ readonly drop: readonly DayPartition[]
31
+ }
32
+
33
+ export interface PartitionPlanInput {
34
+ readonly now: Date
35
+ readonly config: TracePartitionConfig
36
+ /** Existing child partition names per parent table, as found in the catalog. */
37
+ readonly existing: ReadonlyMap<string, ReadonlySet<string>>
38
+ }
39
+
40
+ /**
41
+ * Reconcile desired partitions against existing ones.
42
+ *
43
+ * For each table the desired set spans `[today - retentionDays, today + leadDays]`.
44
+ * `create` is every desired day with no partition yet. `drop` is every existing
45
+ * partition whose day has fallen before the retention cutoff — retention is the
46
+ * dropping of day partitions, never a DELETE. Catalog children that don't parse
47
+ * as our day partitions are left untouched.
48
+ */
49
+ export function planPartitions(input: PartitionPlanInput): PartitionPlan {
50
+ const { config } = input
51
+ const today = toDay(input.now)
52
+ const create: DayPartition[] = []
53
+ const drop: DayPartition[] = []
54
+
55
+ for (const { parent, retention } of PARTITIONED_TRACE_TABLES) {
56
+ const retentionDays = retentionDaysFor(retention, config)
57
+ const keep = retentionDays === null
58
+ // Kept partitions are never dropped, and none is back-filled beyond yesterday.
59
+ const cutoff = addDays(today, keep ? -1 : -retentionDays)
60
+ const existing = input.existing.get(parent) ?? new Set<string>()
61
+
62
+ for (const day of dayRange(cutoff, addDays(today, config.partitionLeadDays))) {
63
+ const name = partitionName(parent, day)
64
+ if (!existing.has(name)) create.push({ parent, name, day })
65
+ }
66
+
67
+ for (const name of existing) {
68
+ const day = parsePartitionDay(parent, name)
69
+ if (!keep && day !== null && day < cutoff) drop.push({ parent, name, day })
70
+ }
71
+ }
72
+
73
+ return { create, drop }
74
+ }
75
+
76
+ function retentionDaysFor(retention: RetentionClass, config: TracePartitionConfig): number | null {
77
+ switch (retention) {
78
+ case 'hot': return config.hotRetentionDays
79
+ case 'cold': return config.errorRetentionDays
80
+ case 'audit': return config.auditRetentionDays
81
+ }
82
+ }
@@ -0,0 +1,26 @@
1
+ // Registers trace maintenance as a recurring job on the cron scheduler. The
2
+ // startup hook covers the boot moment; this keeps things rolling forward for a
3
+ // long-lived process. The consumer's worker dispatch routes
4
+ // `TRACE_PARTITION_MAINTENANCE_JOB` to a body that runs both `syncTracePartitions`
5
+ // (rolls day partitions forward, drops retired ones) and `expireStaleTraces`
6
+ // (force-closes orphan traces past their hot retention window — Q7).
7
+
8
+ import type { DB } from '../../data/db/index.js'
9
+
10
+ export const TRACE_PARTITION_MAINTENANCE_JOB = 'pipework.trace.partition-maintenance'
11
+
12
+ /** Daily at 01:10 UTC — past the midnight day rollover, before business hours. */
13
+ export const TRACE_PARTITION_MAINTENANCE_CRON = '10 1 * * *'
14
+
15
+ /** The scheduler surface this helper needs — structural so it doesn't couple to the job queue. */
16
+ interface SchedulerLike {
17
+ schedule(db: DB, spec: { readonly name: string; readonly cron: string }): Promise<void>
18
+ }
19
+
20
+ export async function scheduleTracePartitionMaintenance(
21
+ scheduler: SchedulerLike,
22
+ db: DB,
23
+ cron: string = TRACE_PARTITION_MAINTENANCE_CRON,
24
+ ): Promise<void> {
25
+ await scheduler.schedule(db, { name: TRACE_PARTITION_MAINTENANCE_JOB, cron })
26
+ }
@@ -0,0 +1,39 @@
1
+ // Trace maintenance as a startup hook. Running it at boot guarantees the
2
+ // near-term partitions exist before the app takes its first request — a fresh
3
+ // deploy on a new day must not write a trace into a partition that doesn't
4
+ // exist yet — and clears any orphan traces left open by a process that died
5
+ // without closing them (Q7 expiry). The cron schedule keeps both current after
6
+ // that.
7
+
8
+ import type { DB } from '../../data/db/index.js'
9
+ import type { StartupHook } from '../../core/lifecycle/types.js'
10
+ import { syncTracePartitions } from './sync.js'
11
+ import { expireStaleTraces } from '../runtime/expire-stale-traces.js'
12
+ import type { TracePartitionConfig } from './plan.js'
13
+ import { installAuditChain } from '../../audit/chain/install.js'
14
+ import { sql } from '../../data/db/sql.js'
15
+
16
+ export const TRACE_PARTITION_HOOK_NAME = 'trace-partition-maintenance'
17
+
18
+ export interface TracePartitionHookOptions {
19
+ /** Blueprint `audit.chain`: (re)install the audit hash chain before partitions are synced. */
20
+ readonly auditChain?: boolean
21
+ }
22
+
23
+ export function createTracePartitionStartupHook(
24
+ db: DB,
25
+ config: TracePartitionConfig,
26
+ options: TracePartitionHookOptions = {},
27
+ ): StartupHook {
28
+ return {
29
+ name: TRACE_PARTITION_HOOK_NAME,
30
+ async execute(): Promise<void> {
31
+ if (options.auditChain === true) {
32
+ const present = await db.execute(sql`SELECT to_regclass('audit_record') IS NOT NULL AS present`)
33
+ if (present[0]?.['present'] === true) await installAuditChain(db)
34
+ }
35
+ await syncTracePartitions(db, config)
36
+ await expireStaleTraces(db)
37
+ },
38
+ }
39
+ }
@@ -0,0 +1,154 @@
1
+ // The impure half of partition maintenance: read the catalog for partitions
2
+ // that exist, ask the planner what should exist, and apply the difference.
3
+ // Creating and dropping day partitions is idempotent — `IF NOT EXISTS` /
4
+ // `IF EXISTS` make a re-run after a crash a no-op — so this is safe to run on
5
+ // every boot and on a cron without coordination.
6
+
7
+ import { sql } from '../../data/db/sql.js'
8
+ import type { DB } from '../../data/db/index.js'
9
+ import { quoteIdentifier } from '../../data/db/identifiers.js'
10
+ import { getBaseLogger } from '../../core/logging/index.js'
11
+ import { PARTITIONED_TRACE_TABLES, STEP_TABLE_PARENTS } from './tables.js'
12
+ import { planPartitions, type DayPartition, type TracePartitionConfig } from './plan.js'
13
+ import { addDays } from './day.js'
14
+ import { auditRecord } from '../../audit/schema/audit-record.js'
15
+ import { withMaintenance } from '../../data/db/maintenance.js'
16
+ import { retireAuditPartition, auditChainInstalled } from '../../audit/chain/retire.js'
17
+
18
+ export interface PartitionSyncOptions {
19
+ /** Called as each partition's CREATE starts; `index` is 1-based of `total` creations. */
20
+ readonly onPartition?: (name: string, index: number, total: number) => void
21
+ }
22
+
23
+ export interface PartitionSyncSummary {
24
+ readonly created: readonly string[]
25
+ readonly dropped: readonly string[]
26
+ }
27
+
28
+ /**
29
+ * Reconcile the trace tables' day partitions with the retention policy.
30
+ *
31
+ * `now` is injectable so the maintenance window is testable without mocking the
32
+ * clock. `options.onPartition` reports each creation as it starts, so a hung
33
+ * CREATE is named. Returns the names created and dropped so a job runner can
34
+ * record them.
35
+ */
36
+ export async function syncTracePartitions(
37
+ db: DB,
38
+ config: TracePartitionConfig,
39
+ now: Date = new Date(),
40
+ options: PartitionSyncOptions = {},
41
+ ): Promise<PartitionSyncSummary> {
42
+ const existingParents = await readExistingParents(db)
43
+ const existing = await readExistingPartitions(db)
44
+ const plan = planPartitions({ now, config, existing })
45
+
46
+ // A parent pipework never provisioned (e.g. `audit` disabled, so no
47
+ // `audit_record`) has no table to attach a partition to — `CREATE TABLE ...
48
+ // PARTITION OF` it would abort the whole pass. Drop those from the plan so
49
+ // the summary reports only partitions actually applied. Issue #313.
50
+ const toCreate = plan.create.filter(partition => existingParents.has(partition.parent))
51
+
52
+ for (const [i, partition] of toCreate.entries()) {
53
+ options.onPartition?.(partition.name, i + 1, toCreate.length)
54
+ const child = quoteIdentifier(partition.name, 'trace partition')
55
+ const parent = quoteIdentifier(partition.parent, 'trace table')
56
+ // addDays re-validates the day; the bound is a generated YYYY-MM-DD literal.
57
+ const upper = addDays(partition.day, 1)
58
+ await db.execute(sql.raw(
59
+ `CREATE TABLE IF NOT EXISTS ${child} PARTITION OF ${parent} ` +
60
+ `FOR VALUES FROM ('${partition.day}') TO ('${upper}')`,
61
+ ))
62
+ }
63
+
64
+ const chained = plan.drop.some(p => p.parent === auditRecord.$name) && await auditChainInstalled(db)
65
+
66
+ const traceParents = new Set(STEP_TABLE_PARENTS.values())
67
+ const stepDrops = new Map<string, DayPartition>()
68
+ for (const partition of plan.drop) {
69
+ if (STEP_TABLE_PARENTS.has(partition.parent)) stepDrops.set(`${partition.parent}:${partition.day}`, partition)
70
+ }
71
+
72
+ for (const partition of plan.drop) {
73
+ const child = quoteIdentifier(partition.name, 'trace partition')
74
+ if (chained && partition.parent === auditRecord.$name) {
75
+ // Keep the dropped rows' hashes so what remains still links back to them.
76
+ // It reads every tenant's rows, so it runs as a maintenance pass.
77
+ await withMaintenance(db, tx => retireAuditPartition(tx, child))
78
+ continue
79
+ }
80
+ if (STEP_TABLE_PARENTS.has(partition.parent)) continue // dropped with its trace partition's day
81
+ if (traceParents.has(partition.parent)) {
82
+ // The step table's foreign key points at this partition: drop the day's
83
+ // step partition first, then detach the trace partition (Postgres will
84
+ // not drop a referenced partition while attached), all or nothing.
85
+ const stepParent = [...STEP_TABLE_PARENTS].find(([, traceParent]) => traceParent === partition.parent)![0]
86
+ const step = stepDrops.get(`${stepParent}:${partition.day}`)
87
+ const parent = quoteIdentifier(partition.parent, 'trace table')
88
+ await db.transaction(async tx => {
89
+ if (step !== undefined) {
90
+ await tx.execute(sql.raw(`DROP TABLE IF EXISTS ${quoteIdentifier(step.name, 'trace partition')}`))
91
+ stepDrops.delete(`${stepParent}:${partition.day}`)
92
+ }
93
+ await tx.execute(sql.raw(`ALTER TABLE ${parent} DETACH PARTITION ${child}`))
94
+ await tx.execute(sql.raw(`DROP TABLE IF EXISTS ${child}`))
95
+ })
96
+ continue
97
+ }
98
+ await db.execute(sql.raw(`DROP TABLE IF EXISTS ${child}`))
99
+ }
100
+
101
+ // A step partition left over has no trace partition planned for its day.
102
+ for (const step of stepDrops.values()) {
103
+ await db.execute(sql.raw(`DROP TABLE IF EXISTS ${quoteIdentifier(step.name, 'trace partition')}`))
104
+ }
105
+
106
+ const summary: PartitionSyncSummary = {
107
+ created: toCreate.map(p => p.name),
108
+ dropped: plan.drop.map(p => p.name),
109
+ }
110
+
111
+ if (summary.created.length > 0 || summary.dropped.length > 0) {
112
+ getBaseLogger().info(
113
+ { created: summary.created, dropped: summary.dropped },
114
+ 'Trace partition maintenance applied',
115
+ )
116
+ }
117
+
118
+ return summary
119
+ }
120
+
121
+ /**
122
+ * Which of the partitioned trace parents actually exist as partitioned tables.
123
+ * A parent pipework never provisioned — `audit` disabled, or a non-default
124
+ * database — must be skipped: `CREATE TABLE ... PARTITION OF` a missing parent
125
+ * aborts the maintenance pass. Issue #313.
126
+ */
127
+ async function readExistingParents(db: DB): Promise<Set<string>> {
128
+ const parents = PARTITIONED_TRACE_TABLES.map(t => t.parent)
129
+ const rows = await db.execute(sql`
130
+ SELECT relname FROM pg_class
131
+ WHERE relkind = 'p' AND relname ${sql.inList(parents)}
132
+ `)
133
+ return new Set(rows.map(row => row['relname'] as string))
134
+ }
135
+
136
+ async function readExistingPartitions(db: DB): Promise<Map<string, Set<string>>> {
137
+ const parents = PARTITIONED_TRACE_TABLES.map(t => t.parent)
138
+ const rows = await db.execute(sql`
139
+ SELECT p.relname AS parent, c.relname AS child
140
+ FROM pg_inherits i
141
+ JOIN pg_class c ON c.oid = i.inhrelid
142
+ JOIN pg_class p ON p.oid = i.inhparent
143
+ WHERE p.relname ${sql.inList(parents)}
144
+ `)
145
+
146
+ const byParent = new Map<string, Set<string>>()
147
+ for (const parent of parents) byParent.set(parent, new Set())
148
+ for (const row of rows) {
149
+ const parent = row['parent'] as string
150
+ const child = row['child'] as string
151
+ byParent.get(parent)?.add(child)
152
+ }
153
+ return byParent
154
+ }