pipework 0.251.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 (730) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/core/config/load.d.ts +2 -0
  3. package/dist/core/config/load.d.ts.map +1 -1
  4. package/dist/core/config/load.js +1 -0
  5. package/dist/core/config/load.js.map +1 -1
  6. package/dist/core/config/namespace.d.ts +1 -0
  7. package/dist/core/config/namespace.d.ts.map +1 -1
  8. package/dist/core/config/schema.d.ts +2 -0
  9. package/dist/core/config/schema.d.ts.map +1 -1
  10. package/dist/core/config/schema.js +1 -0
  11. package/dist/core/config/schema.js.map +1 -1
  12. package/dist/core/surface/types.d.ts +1 -0
  13. package/dist/core/surface/types.d.ts.map +1 -1
  14. package/dist/data/db/namespace.d.ts +3 -0
  15. package/dist/data/db/namespace.d.ts.map +1 -1
  16. package/dist/data/db/namespace.js +3 -0
  17. package/dist/data/db/namespace.js.map +1 -1
  18. package/dist/data/db/pool.d.ts.map +1 -1
  19. package/dist/data/db/pool.js +6 -1
  20. package/dist/data/db/pool.js.map +1 -1
  21. package/dist/data/db/query-label.d.ts +5 -0
  22. package/dist/data/db/query-label.d.ts.map +1 -0
  23. package/dist/data/db/query-label.js +11 -0
  24. package/dist/data/db/query-label.js.map +1 -0
  25. package/dist/data/db/query-watch.d.ts +21 -0
  26. package/dist/data/db/query-watch.d.ts.map +1 -0
  27. package/dist/data/db/query-watch.js +90 -0
  28. package/dist/data/db/query-watch.js.map +1 -0
  29. package/dist/data/query/postgres-js/driver.js +1 -1
  30. package/dist/data/query/postgres-js/driver.js.map +1 -1
  31. package/dist/data/query/postgres-js/session.d.ts +5 -1
  32. package/dist/data/query/postgres-js/session.d.ts.map +1 -1
  33. package/dist/data/query/postgres-js/session.js +16 -11
  34. package/dist/data/query/postgres-js/session.js.map +1 -1
  35. package/dist/data/query/utils.d.ts +2 -0
  36. package/dist/data/query/utils.d.ts.map +1 -1
  37. package/dist/data/query/utils.js.map +1 -1
  38. package/dist/infra/credits/schema.d.ts +1 -1
  39. package/dist/test/plugin.d.ts.map +1 -1
  40. package/dist/test/plugin.js +10 -4
  41. package/dist/test/plugin.js.map +1 -1
  42. package/package.json +4 -3
  43. package/src/async/jobs/abortable-delay.ts +18 -0
  44. package/src/async/jobs/claims.ts +52 -0
  45. package/src/async/jobs/cron.ts +179 -0
  46. package/src/async/jobs/errors.ts +56 -0
  47. package/src/async/jobs/exclusion.ts +117 -0
  48. package/src/async/jobs/execute.ts +219 -0
  49. package/src/async/jobs/index.ts +10 -0
  50. package/src/async/jobs/listener.ts +135 -0
  51. package/src/async/jobs/namespace.ts +20 -0
  52. package/src/async/jobs/queue-door.ts +44 -0
  53. package/src/async/jobs/queue.ts +1012 -0
  54. package/src/async/jobs/run-script.ts +67 -0
  55. package/src/async/jobs/scheduler.ts +218 -0
  56. package/src/async/jobs/schedules-table.ts +37 -0
  57. package/src/async/jobs/serialize-error.ts +48 -0
  58. package/src/async/jobs/table.ts +191 -0
  59. package/src/async/pipeline/define.ts +53 -0
  60. package/src/async/pipeline/errors.ts +35 -0
  61. package/src/async/pipeline/execute.ts +53 -0
  62. package/src/async/pipeline/index.ts +13 -0
  63. package/src/async/pipeline/namespace.ts +12 -0
  64. package/src/async/pipeline/resume.ts +67 -0
  65. package/src/async/pipeline/run-steps.ts +98 -0
  66. package/src/async/pipeline/types.ts +57 -0
  67. package/src/async/state-machine/define.ts +64 -0
  68. package/src/async/state-machine/errors.ts +29 -0
  69. package/src/async/state-machine/index.ts +3 -0
  70. package/src/async/state-machine/namespace.ts +12 -0
  71. package/src/async/state-machine/transition.ts +90 -0
  72. package/src/async/state-machine/types.ts +37 -0
  73. package/src/async/steps/errors.ts +31 -0
  74. package/src/async/steps/graph.ts +1214 -0
  75. package/src/async/steps/hash.ts +40 -0
  76. package/src/async/steps/index.ts +7 -0
  77. package/src/async/steps/namespace.ts +7 -0
  78. package/src/async/steps/table.ts +97 -0
  79. package/src/async/steps/types.ts +318 -0
  80. package/src/audit/chain/index.ts +9 -0
  81. package/src/audit/chain/install.ts +113 -0
  82. package/src/audit/chain/retire.ts +52 -0
  83. package/src/audit/chain/verify.ts +257 -0
  84. package/src/audit/query/cursor.ts +37 -0
  85. package/src/audit/query/index.ts +9 -0
  86. package/src/audit/query/query.ts +223 -0
  87. package/src/audit/schema/audit-record-fields.ts +68 -0
  88. package/src/audit/schema/audit-record.ts +23 -0
  89. package/src/auth/auth/audit.ts +31 -0
  90. package/src/auth/auth/chain.ts +84 -0
  91. package/src/auth/auth/cookie.ts +136 -0
  92. package/src/auth/auth/email-links.ts +311 -0
  93. package/src/auth/auth/guard.ts +128 -0
  94. package/src/auth/auth/index.ts +18 -0
  95. package/src/auth/auth/multi-org.ts +337 -0
  96. package/src/auth/auth/namespace.ts +34 -0
  97. package/src/auth/auth/parse-expiry.ts +13 -0
  98. package/src/auth/auth/passwords.ts +110 -0
  99. package/src/auth/auth/schema.ts +110 -0
  100. package/src/auth/auth/sessions.ts +565 -0
  101. package/src/auth/auth/sign-in.ts +156 -0
  102. package/src/auth/auth/signing-keys.ts +69 -0
  103. package/src/auth/auth/types.ts +26 -0
  104. package/src/auth/auth/uuid.ts +10 -0
  105. package/src/auth/rbac/cache.ts +55 -0
  106. package/src/auth/rbac/check.ts +30 -0
  107. package/src/auth/rbac/create.ts +35 -0
  108. package/src/auth/rbac/index.ts +5 -0
  109. package/src/auth/rbac/middleware.ts +20 -0
  110. package/src/auth/rbac/namespace.ts +15 -0
  111. package/src/auth/rbac/resolve.ts +31 -0
  112. package/src/auth/rbac/schema.sql +31 -0
  113. package/src/auth/rbac/seed.ts +67 -0
  114. package/src/auth/rbac/tables.ts +32 -0
  115. package/src/auth/rbac/types.ts +65 -0
  116. package/src/auth/tenant/extract.ts +33 -0
  117. package/src/auth/tenant/in-tenant.ts +49 -0
  118. package/src/auth/tenant/index.ts +7 -0
  119. package/src/auth/tenant/namespace.ts +23 -0
  120. package/src/auth/tenant/propagate.ts +20 -0
  121. package/src/auth/tenant/rls.ts +120 -0
  122. package/src/auth/tenant/scope.ts +33 -0
  123. package/src/auth/tenant/scoped-db.ts +581 -0
  124. package/src/auth/tenant/types.ts +14 -0
  125. package/src/auth/tenant/validate.ts +27 -0
  126. package/src/cli/commands/add.ts +158 -0
  127. package/src/cli/commands/alerts.ts +98 -0
  128. package/src/cli/commands/check.ts +1418 -0
  129. package/src/cli/commands/codemod.ts +78 -0
  130. package/src/cli/commands/db.ts +356 -0
  131. package/src/cli/commands/dev.ts +101 -0
  132. package/src/cli/commands/generate.ts +75 -0
  133. package/src/cli/commands/init.ts +36 -0
  134. package/src/cli/commands/install.ts +28 -0
  135. package/src/cli/commands/lint.ts +62 -0
  136. package/src/cli/commands/migrate.ts +132 -0
  137. package/src/cli/commands/openapi.ts +63 -0
  138. package/src/cli/commands/remove.ts +72 -0
  139. package/src/cli/commands/run.ts +50 -0
  140. package/src/cli/commands/scope.ts +54 -0
  141. package/src/cli/commands/serve.ts +68 -0
  142. package/src/cli/commands/shard.ts +31 -0
  143. package/src/cli/commands/shared/config-pipework-version.ts +28 -0
  144. package/src/cli/commands/shared/find-config.ts +22 -0
  145. package/src/cli/commands/shared/load-config.ts +35 -0
  146. package/src/cli/commands/shared/pnpm-install.ts +95 -0
  147. package/src/cli/commands/shared/report-removed.ts +8 -0
  148. package/src/cli/commands/sync.ts +32 -0
  149. package/src/cli/commands/test.ts +307 -0
  150. package/src/cli/commands/upgrade.ts +48 -0
  151. package/src/cli/dev-bootstrap.ts +24 -0
  152. package/src/cli/errors.ts +10 -0
  153. package/src/cli/index.ts +303 -0
  154. package/src/cli/output.ts +17 -0
  155. package/src/cli/port.ts +15 -0
  156. package/src/cli/surface-kinds.ts +20 -0
  157. package/src/client/index.ts +4 -0
  158. package/src/client/poll.ts +130 -0
  159. package/src/client/report-fault.ts +119 -0
  160. package/src/core/config/app-pool.ts +19 -0
  161. package/src/core/config/aws-env.ts +29 -0
  162. package/src/core/config/base-dir.ts +24 -0
  163. package/src/core/config/discover.ts +64 -0
  164. package/src/core/config/env-resolve.ts +87 -0
  165. package/src/core/config/env-types.ts +116 -0
  166. package/src/core/config/env.ts +55 -0
  167. package/src/core/config/errors.ts +9 -0
  168. package/src/core/config/import-config.ts +40 -0
  169. package/src/core/config/index.ts +8 -0
  170. package/src/core/config/load.ts +417 -0
  171. package/src/core/config/namespace.ts +14 -0
  172. package/src/core/config/resolve.ts +195 -0
  173. package/src/core/config/schema.ts +488 -0
  174. package/src/core/config/statement-observer.ts +48 -0
  175. package/src/core/config/ts-inline-hooks.ts +75 -0
  176. package/src/core/config/ts-register.ts +4 -0
  177. package/src/core/config/ts-resolve-hooks.ts +101 -0
  178. package/src/core/errors/base.ts +49 -0
  179. package/src/core/errors/http.ts +146 -0
  180. package/src/core/errors/index.ts +2 -0
  181. package/src/core/errors/namespace.ts +31 -0
  182. package/src/core/lifecycle/drain.ts +33 -0
  183. package/src/core/lifecycle/health.ts +72 -0
  184. package/src/core/lifecycle/index.ts +4 -0
  185. package/src/core/lifecycle/namespace.ts +7 -0
  186. package/src/core/lifecycle/startup.ts +102 -0
  187. package/src/core/lifecycle/types.ts +36 -0
  188. package/src/core/logging/context.ts +60 -0
  189. package/src/core/logging/error-chain.ts +68 -0
  190. package/src/core/logging/index.ts +5 -0
  191. package/src/core/logging/logger.ts +65 -0
  192. package/src/core/logging/namespace.ts +16 -0
  193. package/src/core/logging/proxy.ts +22 -0
  194. package/src/core/logging/redact-match.ts +24 -0
  195. package/src/core/logging/types.ts +47 -0
  196. package/src/core/pipework.ts +566 -0
  197. package/src/core/runtime/broker.ts +69 -0
  198. package/src/core/surface/http.ts +133 -0
  199. package/src/core/surface/index.ts +11 -0
  200. package/src/core/surface/job-timeout.ts +40 -0
  201. package/src/core/surface/namespace.ts +13 -0
  202. package/src/core/surface/script.ts +33 -0
  203. package/src/core/surface/start.ts +142 -0
  204. package/src/core/surface/types.ts +225 -0
  205. package/src/core/surface/validate.ts +88 -0
  206. package/src/core/surface/worker.ts +528 -0
  207. package/src/core/validation/connectivity.ts +49 -0
  208. package/src/core/validation/domain.ts +99 -0
  209. package/src/core/validation/index.ts +5 -0
  210. package/src/core/validation/queue-tables.ts +312 -0
  211. package/src/core/validation/rls-role.ts +138 -0
  212. package/src/core/validation/startup.ts +51 -0
  213. package/src/core/validation/surfaces.ts +65 -0
  214. package/src/core/validation/types.ts +25 -0
  215. package/src/data/db/advisory-lock.ts +55 -0
  216. package/src/data/db/aggregates.ts +172 -0
  217. package/src/data/db/array-elements.ts +111 -0
  218. package/src/data/db/bulk-set.ts +53 -0
  219. package/src/data/db/col/index.ts +14 -0
  220. package/src/data/db/composed.ts +53 -0
  221. package/src/data/db/db.ts +276 -0
  222. package/src/data/db/excluded.ts +16 -0
  223. package/src/data/db/expressions.ts +473 -0
  224. package/src/data/db/filter.ts +90 -0
  225. package/src/data/db/function-source.ts +114 -0
  226. package/src/data/db/identifiers.ts +16 -0
  227. package/src/data/db/idx/index.ts +9 -0
  228. package/src/data/db/in-list.ts +49 -0
  229. package/src/data/db/index.ts +9 -0
  230. package/src/data/db/insert-split.ts +137 -0
  231. package/src/data/db/instrumentation.ts +82 -0
  232. package/src/data/db/maintenance.ts +28 -0
  233. package/src/data/db/namespace.ts +107 -0
  234. package/src/data/db/owner-labels.ts +9 -0
  235. package/src/data/db/pool.ts +187 -0
  236. package/src/data/db/query-label.ts +13 -0
  237. package/src/data/db/query-watch.ts +116 -0
  238. package/src/data/db/raw-client-warning.ts +37 -0
  239. package/src/data/db/readonly.ts +23 -0
  240. package/src/data/db/reservation.ts +151 -0
  241. package/src/data/db/schema-features.ts +14 -0
  242. package/src/data/db/serializable.ts +83 -0
  243. package/src/data/db/sql.ts +1 -0
  244. package/src/data/db/timeouts.ts +76 -0
  245. package/src/data/db/types.ts +18 -0
  246. package/src/data/db/unbound.ts +33 -0
  247. package/src/data/db/values.ts +29 -0
  248. package/src/data/domain/brand.ts +15 -0
  249. package/src/data/domain/build-factory.ts +193 -0
  250. package/src/data/domain/build-schema.ts +161 -0
  251. package/src/data/domain/build-table.ts +355 -0
  252. package/src/data/domain/define.ts +239 -0
  253. package/src/data/domain/external-registry.ts +34 -0
  254. package/src/data/domain/external.ts +77 -0
  255. package/src/data/domain/field.ts +279 -0
  256. package/src/data/domain/index.ts +13 -0
  257. package/src/data/domain/naming.ts +6 -0
  258. package/src/data/domain/projections.ts +57 -0
  259. package/src/data/domain/trace-safe-projection.ts +31 -0
  260. package/src/data/domain/traits.ts +108 -0
  261. package/src/data/domain/types.ts +289 -0
  262. package/src/data/jsonb/composed.ts +18 -0
  263. package/src/data/jsonb/index.ts +1 -0
  264. package/src/data/jsonb/namespace.ts +30 -0
  265. package/src/data/jsonb/query.ts +86 -0
  266. package/src/data/migrate/append-only-generate.ts +47 -0
  267. package/src/data/migrate/applied.ts +47 -0
  268. package/src/data/migrate/apply.ts +309 -0
  269. package/src/data/migrate/check.ts +119 -0
  270. package/src/data/migrate/diff.ts +357 -0
  271. package/src/data/migrate/door-generate.ts +130 -0
  272. package/src/data/migrate/framework-rls.ts +58 -0
  273. package/src/data/migrate/generate.ts +201 -0
  274. package/src/data/migrate/history.ts +215 -0
  275. package/src/data/migrate/index.ts +9 -0
  276. package/src/data/migrate/internal-definitions.ts +175 -0
  277. package/src/data/migrate/post-process.ts +73 -0
  278. package/src/data/migrate/pragma.ts +73 -0
  279. package/src/data/migrate/provision-framework.ts +147 -0
  280. package/src/data/migrate/rls-generate.ts +61 -0
  281. package/src/data/migrate/run.ts +124 -0
  282. package/src/data/migrate/safety.ts +167 -0
  283. package/src/data/migrate/snapshot.ts +368 -0
  284. package/src/data/migrate/sql-emit.ts +392 -0
  285. package/src/data/migrate/statements.ts +312 -0
  286. package/src/data/query/alias.ts +126 -0
  287. package/src/data/query/batch.ts +8 -0
  288. package/src/data/query/cache/core/cache.ts +78 -0
  289. package/src/data/query/cache/core/index.ts +1 -0
  290. package/src/data/query/cache/core/types.ts +29 -0
  291. package/src/data/query/cache/readme.md +230 -0
  292. package/src/data/query/casing.ts +76 -0
  293. package/src/data/query/collation.ts +11 -0
  294. package/src/data/query/column-builder.ts +370 -0
  295. package/src/data/query/column.ts +150 -0
  296. package/src/data/query/entity.ts +42 -0
  297. package/src/data/query/errors.ts +33 -0
  298. package/src/data/query/index.ts +14 -0
  299. package/src/data/query/logger.ts +47 -0
  300. package/src/data/query/operations.ts +45 -0
  301. package/src/data/query/pg-core/alias.ts +12 -0
  302. package/src/data/query/pg-core/checks.ts +32 -0
  303. package/src/data/query/pg-core/columns/all.ts +71 -0
  304. package/src/data/query/pg-core/columns/bigint.ts +110 -0
  305. package/src/data/query/pg-core/columns/bigserial.ts +128 -0
  306. package/src/data/query/pg-core/columns/boolean.ts +43 -0
  307. package/src/data/query/pg-core/columns/char.ts +85 -0
  308. package/src/data/query/pg-core/columns/cidr.ts +43 -0
  309. package/src/data/query/pg-core/columns/common.ts +366 -0
  310. package/src/data/query/pg-core/columns/custom.ts +232 -0
  311. package/src/data/query/pg-core/columns/date.common.ts +15 -0
  312. package/src/data/query/pg-core/columns/date.ts +112 -0
  313. package/src/data/query/pg-core/columns/double-precision.ts +55 -0
  314. package/src/data/query/pg-core/columns/enum.ts +201 -0
  315. package/src/data/query/pg-core/columns/index.ts +35 -0
  316. package/src/data/query/pg-core/columns/inet.ts +43 -0
  317. package/src/data/query/pg-core/columns/int.common.ts +57 -0
  318. package/src/data/query/pg-core/columns/integer.ts +53 -0
  319. package/src/data/query/pg-core/columns/interval.ts +83 -0
  320. package/src/data/query/pg-core/columns/json.ts +58 -0
  321. package/src/data/query/pg-core/columns/jsonb.ts +56 -0
  322. package/src/data/query/pg-core/columns/line.ts +117 -0
  323. package/src/data/query/pg-core/columns/macaddr.ts +43 -0
  324. package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
  325. package/src/data/query/pg-core/columns/numeric.ts +227 -0
  326. package/src/data/query/pg-core/columns/point.ts +127 -0
  327. package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
  328. package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
  329. package/src/data/query/pg-core/columns/real.ts +58 -0
  330. package/src/data/query/pg-core/columns/serial.ts +55 -0
  331. package/src/data/query/pg-core/columns/smallint.ts +53 -0
  332. package/src/data/query/pg-core/columns/smallserial.ts +60 -0
  333. package/src/data/query/pg-core/columns/text.ts +67 -0
  334. package/src/data/query/pg-core/columns/time.ts +72 -0
  335. package/src/data/query/pg-core/columns/timestamp.ts +163 -0
  336. package/src/data/query/pg-core/columns/uuid.ts +51 -0
  337. package/src/data/query/pg-core/columns/varchar.ts +89 -0
  338. package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
  339. package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
  340. package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
  341. package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
  342. package/src/data/query/pg-core/db.ts +674 -0
  343. package/src/data/query/pg-core/dialect.ts +1404 -0
  344. package/src/data/query/pg-core/expressions.ts +25 -0
  345. package/src/data/query/pg-core/foreign-keys.ts +130 -0
  346. package/src/data/query/pg-core/index.ts +21 -0
  347. package/src/data/query/pg-core/indexes.ts +276 -0
  348. package/src/data/query/pg-core/policies.ts +56 -0
  349. package/src/data/query/pg-core/primary-keys.ts +62 -0
  350. package/src/data/query/pg-core/query-builders/count.ts +86 -0
  351. package/src/data/query/pg-core/query-builders/delete.ts +293 -0
  352. package/src/data/query/pg-core/query-builders/index.ts +7 -0
  353. package/src/data/query/pg-core/query-builders/insert.ts +452 -0
  354. package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
  355. package/src/data/query/pg-core/query-builders/query.ts +157 -0
  356. package/src/data/query/pg-core/query-builders/raw.ts +49 -0
  357. package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
  358. package/src/data/query/pg-core/query-builders/select.ts +1346 -0
  359. package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
  360. package/src/data/query/pg-core/query-builders/update.ts +626 -0
  361. package/src/data/query/pg-core/roles.ts +41 -0
  362. package/src/data/query/pg-core/schema.ts +72 -0
  363. package/src/data/query/pg-core/sequence.ts +41 -0
  364. package/src/data/query/pg-core/session.ts +292 -0
  365. package/src/data/query/pg-core/subquery.ts +46 -0
  366. package/src/data/query/pg-core/table.ts +252 -0
  367. package/src/data/query/pg-core/unique-constraint.ts +73 -0
  368. package/src/data/query/pg-core/utils/array.ts +95 -0
  369. package/src/data/query/pg-core/utils/index.ts +1 -0
  370. package/src/data/query/pg-core/utils.ts +104 -0
  371. package/src/data/query/pg-core/view-base.ts +14 -0
  372. package/src/data/query/pg-core/view-common.ts +1 -0
  373. package/src/data/query/pg-core/view.ts +435 -0
  374. package/src/data/query/pg-core/with-builder.ts +41 -0
  375. package/src/data/query/postgres-js/README.md +46 -0
  376. package/src/data/query/postgres-js/array-parser.ts +45 -0
  377. package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
  378. package/src/data/query/postgres-js/driver.ts +163 -0
  379. package/src/data/query/postgres-js/index.ts +2 -0
  380. package/src/data/query/postgres-js/session.ts +234 -0
  381. package/src/data/query/primary-key.ts +11 -0
  382. package/src/data/query/query-builders/query-builder.ts +19 -0
  383. package/src/data/query/query-builders/select.types.ts +175 -0
  384. package/src/data/query/query-promise.ts +35 -0
  385. package/src/data/query/relations.ts +725 -0
  386. package/src/data/query/runnable-query.ts +12 -0
  387. package/src/data/query/selection-proxy.ts +121 -0
  388. package/src/data/query/session.ts +8 -0
  389. package/src/data/query/sql/expressions/conditions.ts +741 -0
  390. package/src/data/query/sql/expressions/index.ts +2 -0
  391. package/src/data/query/sql/expressions/select.ts +45 -0
  392. package/src/data/query/sql/functions/aggregate.ts +129 -0
  393. package/src/data/query/sql/functions/index.ts +2 -0
  394. package/src/data/query/sql/functions/vector.ts +178 -0
  395. package/src/data/query/sql/index.ts +3 -0
  396. package/src/data/query/sql/sql.ts +794 -0
  397. package/src/data/query/subquery.ts +53 -0
  398. package/src/data/query/table.ts +208 -0
  399. package/src/data/query/table.utils.ts +2 -0
  400. package/src/data/query/tracing-utils.ts +3 -0
  401. package/src/data/query/tracing.ts +11 -0
  402. package/src/data/query/utils.ts +357 -0
  403. package/src/data/query/version.ts +4 -0
  404. package/src/data/query/view-common.ts +1 -0
  405. package/src/data/schema/branded.ts +13 -0
  406. package/src/data/schema/generated/coerce.ts +5 -0
  407. package/src/data/schema/generated/combinator.ts +6 -0
  408. package/src/data/schema/generated/encoding.ts +5 -0
  409. package/src/data/schema/generated/error.ts +6 -0
  410. package/src/data/schema/generated/format.ts +5 -0
  411. package/src/data/schema/generated/type-constructor.ts +10 -0
  412. package/src/data/schema/generated/type.ts +6 -0
  413. package/src/data/schema/index.ts +6 -0
  414. package/src/data/schema/json-schema.ts +33 -0
  415. package/src/data/schema/namespace.ts +55 -0
  416. package/src/data/schema/parse.ts +39 -0
  417. package/src/data/schema/types.ts +39 -0
  418. package/src/data/temporal/append-only.ts +134 -0
  419. package/src/data/temporal/close.ts +27 -0
  420. package/src/data/temporal/columns.ts +10 -0
  421. package/src/data/temporal/definition-queries.ts +70 -0
  422. package/src/data/temporal/errors.ts +10 -0
  423. package/src/data/temporal/get-current.ts +22 -0
  424. package/src/data/temporal/index.ts +9 -0
  425. package/src/data/temporal/namespace.ts +36 -0
  426. package/src/data/temporal/query.ts +25 -0
  427. package/src/data/temporal/resolve.ts +17 -0
  428. package/src/data/temporal/revise.ts +67 -0
  429. package/src/data/temporal/types.ts +22 -0
  430. package/src/data/valve/artifact.ts +33 -0
  431. package/src/data/valve/contract-diff.ts +21 -0
  432. package/src/data/valve/cross.ts +57 -0
  433. package/src/data/valve/crossing-ledger.ts +50 -0
  434. package/src/data/valve/decision.ts +44 -0
  435. package/src/data/valve/durable-crossing.ts +52 -0
  436. package/src/data/valve/execute-crossing.ts +77 -0
  437. package/src/data/valve/faucet.ts +56 -0
  438. package/src/data/valve/gate.ts +114 -0
  439. package/src/data/valve/graph.ts +77 -0
  440. package/src/data/valve/index.ts +53 -0
  441. package/src/data/valve/namespace.ts +57 -0
  442. package/src/data/valve/registry.ts +50 -0
  443. package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
  444. package/src/data/valve/schema/valve-crossing.ts +9 -0
  445. package/src/data/valve/supply.ts +154 -0
  446. package/src/data/valve/types.ts +143 -0
  447. package/src/data/vector/columns.ts +27 -0
  448. package/src/data/vector/index.ts +4 -0
  449. package/src/data/vector/namespace.ts +33 -0
  450. package/src/data/vector/query.ts +85 -0
  451. package/src/data/vector/validate.ts +16 -0
  452. package/src/data/write/audit/actor.ts +15 -0
  453. package/src/data/write/audit/audit-columns.ts +18 -0
  454. package/src/data/write/audit/audit-select.ts +111 -0
  455. package/src/data/write/audit/bound-transaction.ts +14 -0
  456. package/src/data/write/audit/cte-compile.ts +32 -0
  457. package/src/data/write/audit/decode-returning.ts +47 -0
  458. package/src/data/write/audit/final-select.ts +43 -0
  459. package/src/data/write/audit/infra-audit.ts +36 -0
  460. package/src/data/write/audit/primary-key.ts +65 -0
  461. package/src/data/write/audit/projection.ts +41 -0
  462. package/src/data/write/audit/read-touches.ts +86 -0
  463. package/src/data/write/audit/touch-match.ts +78 -0
  464. package/src/data/write/audit/verb-delete.ts +62 -0
  465. package/src/data/write/audit/verb-insert.ts +36 -0
  466. package/src/data/write/audit/verb-select.ts +47 -0
  467. package/src/data/write/audit/verb-update.ts +60 -0
  468. package/src/data/write/audit/verb-upsert.ts +104 -0
  469. package/src/data/write/conflict.ts +43 -0
  470. package/src/data/write/delete.ts +38 -0
  471. package/src/data/write/execute.ts +243 -0
  472. package/src/data/write/index.ts +11 -0
  473. package/src/data/write/insert.ts +63 -0
  474. package/src/data/write/state.ts +43 -0
  475. package/src/data/write/update.ts +54 -0
  476. package/src/data/write/upsert.ts +58 -0
  477. package/src/data/write/values.ts +19 -0
  478. package/src/index.ts +230 -0
  479. package/src/infra/access-links/code.ts +70 -0
  480. package/src/infra/access-links/handle.ts +892 -0
  481. package/src/infra/access-links/index.ts +9 -0
  482. package/src/infra/access-links/namespace.ts +30 -0
  483. package/src/infra/access-links/person-check.ts +177 -0
  484. package/src/infra/access-links/schema.ts +71 -0
  485. package/src/infra/alerts/async-sources.ts +231 -0
  486. package/src/infra/alerts/audit.ts +36 -0
  487. package/src/infra/alerts/beat.ts +123 -0
  488. package/src/infra/alerts/client-faults.ts +111 -0
  489. package/src/infra/alerts/faults.ts +156 -0
  490. package/src/infra/alerts/handle.ts +778 -0
  491. package/src/infra/alerts/http.ts +192 -0
  492. package/src/infra/alerts/index.ts +12 -0
  493. package/src/infra/alerts/infra-sources.ts +180 -0
  494. package/src/infra/alerts/namespace.ts +81 -0
  495. package/src/infra/alerts/redact.ts +21 -0
  496. package/src/infra/alerts/request-faults.ts +41 -0
  497. package/src/infra/alerts/schema.ts +124 -0
  498. package/src/infra/alerts/sinks.ts +125 -0
  499. package/src/infra/alerts/source-options.ts +26 -0
  500. package/src/infra/alerts/sources.ts +503 -0
  501. package/src/infra/alerts/subsystem-sources.ts +137 -0
  502. package/src/infra/audit/emit.ts +87 -0
  503. package/src/infra/audit/index.ts +2 -0
  504. package/src/infra/audit/namespace.ts +22 -0
  505. package/src/infra/audit/schema.sql +35 -0
  506. package/src/infra/audit/types.ts +18 -0
  507. package/src/infra/aws/credentials.ts +147 -0
  508. package/src/infra/aws/sigv4.ts +140 -0
  509. package/src/infra/cache/create.ts +58 -0
  510. package/src/infra/cache/entry.ts +81 -0
  511. package/src/infra/cache/index.ts +4 -0
  512. package/src/infra/cache/namespace.ts +10 -0
  513. package/src/infra/cache/tenant.ts +93 -0
  514. package/src/infra/cache/types.ts +24 -0
  515. package/src/infra/crawl/audit.ts +35 -0
  516. package/src/infra/crawl/errors.ts +25 -0
  517. package/src/infra/crawl/handle.ts +693 -0
  518. package/src/infra/crawl/index.ts +9 -0
  519. package/src/infra/crawl/links.ts +160 -0
  520. package/src/infra/crawl/namespace.ts +36 -0
  521. package/src/infra/crawl/robots.ts +100 -0
  522. package/src/infra/crawl/schema.ts +89 -0
  523. package/src/infra/credit-line/handle.ts +883 -0
  524. package/src/infra/credit-line/index.ts +6 -0
  525. package/src/infra/credit-line/namespace.ts +7 -0
  526. package/src/infra/credit-line/schema.ts +96 -0
  527. package/src/infra/credits/handle.ts +706 -0
  528. package/src/infra/credits/index.ts +5 -0
  529. package/src/infra/credits/namespace.ts +7 -0
  530. package/src/infra/credits/schema.ts +83 -0
  531. package/src/infra/email/audit.ts +36 -0
  532. package/src/infra/email/inbound.ts +622 -0
  533. package/src/infra/email/index.ts +11 -0
  534. package/src/infra/email/mail.ts +517 -0
  535. package/src/infra/email/mime.ts +447 -0
  536. package/src/infra/email/namespace.ts +22 -0
  537. package/src/infra/email/providers.ts +111 -0
  538. package/src/infra/email/schema.ts +96 -0
  539. package/src/infra/email/sns.ts +200 -0
  540. package/src/infra/email/unsubscribe.ts +44 -0
  541. package/src/infra/fetch/address.ts +88 -0
  542. package/src/infra/fetch/connect-retry.ts +87 -0
  543. package/src/infra/fetch/handle.ts +329 -0
  544. package/src/infra/fetch/index.ts +7 -0
  545. package/src/infra/fetch/namespace.ts +70 -0
  546. package/src/infra/idempotency/index.ts +3 -0
  547. package/src/infra/idempotency/middleware.ts +87 -0
  548. package/src/infra/idempotency/store.ts +92 -0
  549. package/src/infra/idempotency/types.ts +30 -0
  550. package/src/infra/join-requests/handle.ts +312 -0
  551. package/src/infra/join-requests/index.ts +2 -0
  552. package/src/infra/join-requests/namespace.ts +7 -0
  553. package/src/infra/join-requests/schema.ts +33 -0
  554. package/src/infra/outbox/core.ts +165 -0
  555. package/src/infra/quota/errors.ts +32 -0
  556. package/src/infra/quota/handle.ts +215 -0
  557. package/src/infra/quota/index.ts +5 -0
  558. package/src/infra/quota/namespace.ts +7 -0
  559. package/src/infra/quota/schema.ts +15 -0
  560. package/src/infra/storage/backend.ts +34 -0
  561. package/src/infra/storage/handle.ts +513 -0
  562. package/src/infra/storage/index.ts +9 -0
  563. package/src/infra/storage/local.ts +104 -0
  564. package/src/infra/storage/namespace.ts +13 -0
  565. package/src/infra/storage/s3.ts +257 -0
  566. package/src/infra/storage/schema.ts +24 -0
  567. package/src/infra/support/handle.ts +854 -0
  568. package/src/infra/support/http.ts +229 -0
  569. package/src/infra/support/index.ts +7 -0
  570. package/src/infra/support/namespace.ts +12 -0
  571. package/src/infra/support/schema.ts +96 -0
  572. package/src/infra/webhook/inbound.ts +45 -0
  573. package/src/infra/webhook/index.ts +5 -0
  574. package/src/infra/webhook/namespace.ts +24 -0
  575. package/src/infra/webhook/outbound.ts +315 -0
  576. package/src/infra/webhook/sign.ts +32 -0
  577. package/src/infra/webhook/verify.ts +82 -0
  578. package/src/invariants/assert.ts +26 -0
  579. package/src/invariants/index.ts +1 -0
  580. package/src/lint/config.ts +56 -0
  581. package/src/lint/doctrine.ts +163 -0
  582. package/src/lint/include.ts +97 -0
  583. package/src/lint/index.ts +3 -0
  584. package/src/lint/preset.ts +10 -0
  585. package/src/lint/resolver.ts +218 -0
  586. package/src/lint/rules/no-reexports.ts +46 -0
  587. package/src/request/behavior/audited.ts +85 -0
  588. package/src/request/behavior/cached.ts +62 -0
  589. package/src/request/behavior/compose.ts +28 -0
  590. package/src/request/behavior/index.ts +5 -0
  591. package/src/request/behavior/namespace.ts +16 -0
  592. package/src/request/behavior/types.ts +26 -0
  593. package/src/request/behavior/versioned.ts +54 -0
  594. package/src/request/context/create.ts +103 -0
  595. package/src/request/context/guard.ts +49 -0
  596. package/src/request/context/index.ts +4 -0
  597. package/src/request/context/run-in-transaction.ts +200 -0
  598. package/src/request/context/store.ts +28 -0
  599. package/src/request/context/types.ts +50 -0
  600. package/src/request/di/builder.ts +535 -0
  601. package/src/request/di/index.ts +8 -0
  602. package/src/request/di/resolve.ts +271 -0
  603. package/src/request/di/types.ts +262 -0
  604. package/src/request/fitting/namespace.ts +7 -0
  605. package/src/request/fixture/batch.ts +71 -0
  606. package/src/request/fixture/builder.ts +26 -0
  607. package/src/request/fixture/errors.ts +10 -0
  608. package/src/request/fixture/index.ts +8 -0
  609. package/src/request/fixture/namespace.ts +23 -0
  610. package/src/request/fixture/paginate.ts +44 -0
  611. package/src/request/fixture/to-handlers.ts +260 -0
  612. package/src/request/fixture/types.ts +79 -0
  613. package/src/request/flow/act-as.ts +78 -0
  614. package/src/request/flow/namespace.ts +17 -0
  615. package/src/request/http/error-step.ts +42 -0
  616. package/src/request/http/file.ts +141 -0
  617. package/src/request/http/index.ts +4 -0
  618. package/src/request/http/middleware.ts +141 -0
  619. package/src/request/http/namespace.ts +5 -0
  620. package/src/request/http/rate-limit-classes.ts +170 -0
  621. package/src/request/http/response.ts +82 -0
  622. package/src/request/http/server.ts +916 -0
  623. package/src/request/http/sniff.ts +261 -0
  624. package/src/request/http/types.ts +250 -0
  625. package/src/request/http/upload.ts +284 -0
  626. package/src/request/internal/text.ts +6 -0
  627. package/src/request/openapi/generate.ts +205 -0
  628. package/src/request/openapi/index.ts +2 -0
  629. package/src/request/openapi/namespace.ts +7 -0
  630. package/src/test/auth.ts +13 -0
  631. package/src/test/auto-setup.ts +45 -0
  632. package/src/test/context.ts +91 -0
  633. package/src/test/crawl-fixture.ts +157 -0
  634. package/src/test/discover-fork.ts +17 -0
  635. package/src/test/fingerprint.ts +135 -0
  636. package/src/test/globals.d.ts +7 -0
  637. package/src/test/index.ts +19 -0
  638. package/src/test/namespace.ts +87 -0
  639. package/src/test/plugin.ts +189 -0
  640. package/src/test/progress.ts +185 -0
  641. package/src/test/reap-after-run.ts +28 -0
  642. package/src/test/reap.ts +286 -0
  643. package/src/test/reset.ts +253 -0
  644. package/src/test/savepoints.ts +172 -0
  645. package/src/test/setup.ts +1422 -0
  646. package/src/test/system-channel.ts +50 -0
  647. package/src/test/vitest-plugin.ts +142 -0
  648. package/src/test/vitest-workspace.ts +507 -0
  649. package/src/test/vitest.ts +333 -0
  650. package/src/test/watch.ts +105 -0
  651. package/src/trace/capture/bounded-serializer.ts +146 -0
  652. package/src/trace/cardinality/analyze.ts +173 -0
  653. package/src/trace/cardinality/branch-context.ts +214 -0
  654. package/src/trace/cardinality/check.ts +33 -0
  655. package/src/trace/cardinality/classify-edge.ts +64 -0
  656. package/src/trace/cardinality/structural-max.ts +107 -0
  657. package/src/trace/check/coverage-check.ts +188 -0
  658. package/src/trace/check/flow-check.ts +103 -0
  659. package/src/trace/check/flow-step-site.ts +234 -0
  660. package/src/trace/check/io-pattern.ts +116 -0
  661. package/src/trace/codemod/add-cardinality.ts +152 -0
  662. package/src/trace/codemod/run.ts +80 -0
  663. package/src/trace/entry/child-trace.ts +21 -0
  664. package/src/trace/entry/close-trace.ts +87 -0
  665. package/src/trace/entry/finalize-trace.ts +28 -0
  666. package/src/trace/entry/open-trace.ts +138 -0
  667. package/src/trace/entry/parent-trace.ts +20 -0
  668. package/src/trace/entry/parse-traceparent.ts +39 -0
  669. package/src/trace/entry/process-start.ts +38 -0
  670. package/src/trace/entry/trace-context.ts +26 -0
  671. package/src/trace/entry/tracing-enabled.ts +10 -0
  672. package/src/trace/external/record.ts +195 -0
  673. package/src/trace/external/report.ts +66 -0
  674. package/src/trace/namespace.ts +19 -0
  675. package/src/trace/partition/day.ts +47 -0
  676. package/src/trace/partition/index.ts +14 -0
  677. package/src/trace/partition/partition-name.ts +23 -0
  678. package/src/trace/partition/plan.ts +82 -0
  679. package/src/trace/partition/schedule.ts +26 -0
  680. package/src/trace/partition/startup-hook.ts +39 -0
  681. package/src/trace/partition/sync.ts +154 -0
  682. package/src/trace/partition/tables.ts +53 -0
  683. package/src/trace/read/tree.ts +83 -0
  684. package/src/trace/retain/copy-on-error.ts +76 -0
  685. package/src/trace/runtime/expire-stale-traces.ts +54 -0
  686. package/src/trace/runtime/flow-step.ts +147 -0
  687. package/src/trace/runtime/flush-steps.ts +31 -0
  688. package/src/trace/runtime/pending-writes.ts +54 -0
  689. package/src/trace/runtime/step-buffer.ts +298 -0
  690. package/src/trace/runtime/step-error.ts +21 -0
  691. package/src/trace/runtime/step-meta.ts +55 -0
  692. package/src/trace/runtime/thenable.ts +12 -0
  693. package/src/trace/runtime/truncate-trace.ts +62 -0
  694. package/src/trace/schema/trace-fields.ts +52 -0
  695. package/src/trace/schema/trace-retained.ts +22 -0
  696. package/src/trace/schema/trace-step-fields.ts +44 -0
  697. package/src/trace/schema/trace-step-retained.ts +25 -0
  698. package/src/trace/schema/trace-step.ts +18 -0
  699. package/src/trace/schema/trace.ts +12 -0
  700. package/src/trace/transformer/apply.ts +79 -0
  701. package/src/trace/transformer/build-meta-literal.ts +30 -0
  702. package/src/trace/transformer/find-flow-step-sites.ts +85 -0
  703. package/src/trace/transformer/inject-flow-step-import.ts +39 -0
  704. package/src/trace/transformer/transform-error.ts +14 -0
  705. package/src/trace/transformer/transform-flow-steps.ts +123 -0
  706. package/src/trace/transformer/wrap-function-declaration.ts +62 -0
  707. package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
  708. package/src/workspace/affected.ts +110 -0
  709. package/src/workspace/changed-files.ts +163 -0
  710. package/src/workspace/check-deps.ts +213 -0
  711. package/src/workspace/checksum.ts +20 -0
  712. package/src/workspace/dependency-graph.ts +67 -0
  713. package/src/workspace/detect-pipework-copies.ts +93 -0
  714. package/src/workspace/discover.ts +206 -0
  715. package/src/workspace/generate.ts +401 -0
  716. package/src/workspace/index.ts +7 -0
  717. package/src/workspace/module-imports-pipework.ts +39 -0
  718. package/src/workspace/module-package-name.ts +12 -0
  719. package/src/workspace/scrub-git-env.ts +23 -0
  720. package/src/workspace/source-paths.ts +36 -0
  721. package/src/workspace/sync.ts +182 -0
  722. package/dist/REFERENCE.md +0 -1477
  723. package/dist/infra/access-links/rate-limit.d.ts +0 -10
  724. package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
  725. package/dist/infra/access-links/rate-limit.js +0 -28
  726. package/dist/infra/access-links/rate-limit.js.map +0 -1
  727. package/dist/infra/email/sigv4.d.ts +0 -24
  728. package/dist/infra/email/sigv4.d.ts.map +0 -1
  729. package/dist/infra/email/sigv4.js +0 -55
  730. package/dist/infra/email/sigv4.js.map +0 -1
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Migration pragmas — per-file declarations read from the migration's own
3
+ * comments.
4
+ *
5
+ * Authorization for a hazardous migration lives here rather than on the
6
+ * `pipework migrate` command line, and the distinction is the whole point.
7
+ * A CLI flag authorizes an *invocation*: it is written once, into a deploy
8
+ * workflow, by someone who cannot know what migration 0071 will contain nine
9
+ * months later. The first destructive migration that has to ship puts
10
+ * `--allow-destructive` in CI permanently, and from then on the gate is
11
+ * decorative — every later migration is pre-approved by a decision nobody
12
+ * revisits, and nothing about it shows up in review.
13
+ *
14
+ * A pragma authorizes a *file*. It is written by the person writing the
15
+ * destructive statement, at the moment they write it; it appears in the diff,
16
+ * so it is reviewed; it is versioned, so `git log` says who approved which
17
+ * drop; and it cannot go blanket — a pragma in 0065 says nothing about 0071.
18
+ * The deploy command stays a bare `pipework migrate` forever, which means
19
+ * there is no flag to erode.
20
+ *
21
+ * The migration tracker records a content hash per applied migration and
22
+ * refuses edited-but-applied files. Only `expect-*` lines are ignored by that
23
+ * hash, so annotating history is allowed and nothing else about it is.
24
+ */
25
+
26
+ export const PRAGMA_PREFIX = '-- pipework:'
27
+
28
+ /** Hazard classes that require a per-migration declaration. */
29
+ export type PragmaKind = 'destructive' | 'locking' | 'dynamic'
30
+
31
+ export const PRAGMA_FOR: Record<PragmaKind, string> = {
32
+ destructive: 'pipework:expect-destructive',
33
+ locking: 'pipework:expect-locking',
34
+ dynamic: 'pipework:expect-dynamic',
35
+ }
36
+
37
+ /**
38
+ * True when `sql` declares the given pragma. Pragmas are recognized only on
39
+ * their own comment line, so prose that happens to mention one does not
40
+ * authorize anything.
41
+ */
42
+ export function hasPragma(sql: string, kind: PragmaKind): boolean {
43
+ const wanted = PRAGMA_FOR[kind]
44
+ for (const line of sql.split('\n')) {
45
+ if (pragmaOfLine(line) === wanted) return true
46
+ }
47
+ return false
48
+ }
49
+
50
+ const DECLARED = new Set<string>(Object.values(PRAGMA_FOR))
51
+
52
+ /** The pragma a single line declares, or undefined when it declares none. */
53
+ function pragmaOfLine(line: string): string | undefined {
54
+ const trimmed = line.trim()
55
+ if (!trimmed.startsWith('--')) return undefined
56
+ return trimmed.slice(2).trim()
57
+ }
58
+
59
+ /**
60
+ * `sql` with every `expect-*` pragma line removed, line terminator included.
61
+ * A pragma declares a hazard; it does not change what the migration does, so
62
+ * the tracker's immutability check ignores it: an app may annotate an applied
63
+ * file so a fresh database can replay history through the gate.
64
+ */
65
+ export function stripPragmaLines(sql: string): string {
66
+ const lines = sql.match(/[^\n]*\n|[^\n]+$/g) ?? []
67
+ return lines
68
+ .filter((line) => {
69
+ const pragma = pragmaOfLine(line)
70
+ return pragma === undefined || !DECLARED.has(pragma)
71
+ })
72
+ .join('')
73
+ }
@@ -0,0 +1,147 @@
1
+ // Provisions pipework's framework-owned partitioned tables — the trace family.
2
+ // `generate` deliberately keeps them out of application migrations (#313): a
3
+ // bare CREATE TABLE of a PARTITION BY RANGE table accepts no rows. pipework
4
+ // creates them itself — the parent tables, then their day partitions —
5
+ // wherever a database is provisioned: the test harness (src/test/setup.ts) and
6
+ // `migrate` (src/data/migrate/run.ts).
7
+
8
+ import { sql } from '../db/sql.js'
9
+ import { quoteIdentifier } from '../db/identifiers.js'
10
+ import type { DB } from '../db/index.js'
11
+ import type { Blueprint } from '../../core/config/schema.js'
12
+ import { syncTracePartitions, type TracePartitionConfig } from '../../trace/partition/index.js'
13
+ import { PARTITIONED_TRACE_TABLE_NAMES } from '../../trace/partition/tables.js'
14
+ import { AUDIT_ENTITY_INDEX_SQL } from '../../audit/schema/audit-record.js'
15
+ import { installAuditChain } from '../../audit/chain/install.js'
16
+ import { loadInternalDefinitions } from './internal-definitions.js'
17
+ import { buildSnapshot, EMPTY_SNAPSHOT } from './snapshot.js'
18
+ import type { DiffOp } from './diff.js'
19
+ import { emitSQL } from './sql-emit.js'
20
+ import { makeTablesUnlogged } from './apply.js'
21
+ import { installFrameworkPolicies, type FrameworkRls } from './framework-rls.js'
22
+
23
+ export interface FrameworkTablesResult {
24
+ /** Parent tables that did not exist and were created. */
25
+ created: string[]
26
+ /** `table.column` for every column added to a table that already existed. */
27
+ columnsAdded: string[]
28
+ /** Day partitions created. */
29
+ partitionsCreated: string[]
30
+ }
31
+
32
+ export function frameworkTablesChanged(r: FrameworkTablesResult): boolean {
33
+ return r.created.length + r.columnsAdded.length + r.partitionsCreated.length > 0
34
+ }
35
+
36
+ export class FrameworkTableColumnError extends Error {
37
+ override readonly name = 'FrameworkTableColumnError'
38
+ }
39
+
40
+ /**
41
+ * Create the framework-owned partitioned tables and their day partitions.
42
+ *
43
+ * Trace and audit storage rides the default database only, and only when the
44
+ * blueprint enables `trace` or `audit`. `valve_crossing` is framework-owned but
45
+ * not partitioned — it ships in the application migration like any ordinary
46
+ * table — so it is not provisioned here. Issue #313.
47
+ *
48
+ * Missing tables are created. A table that exists gains any column its
49
+ * definition has and it lacks; nothing is dropped, renamed or altered. A
50
+ * missing NOT NULL column with no default cannot be added to a table that has
51
+ * rows and fails naming the table and column. `unlogged` is for test databases;
52
+ * a real database gets logged tables. When the database configures `rls`, each
53
+ * table also gets the tenant policies of `framework-rls.ts`, replaced on every
54
+ * run so an existing database picks them up. Idempotent.
55
+ */
56
+ export async function provisionFrameworkTables(
57
+ db: DB,
58
+ blueprint: Blueprint,
59
+ traceConfig: TracePartitionConfig,
60
+ isDefaultDatabase: boolean,
61
+ options: {
62
+ unlogged: boolean
63
+ rls?: FrameworkRls | undefined
64
+ /** Told as each step starts; a partition reports `step` 'partition' with `i/n name` as detail. */
65
+ onProgress?: ((step: string, detail?: string) => void) | undefined
66
+ } = { unlogged: true },
67
+ ): Promise<FrameworkTablesResult> {
68
+ const result: FrameworkTablesResult = { created: [], columnsAdded: [], partitionsCreated: [] }
69
+ const progress = options.onProgress ?? (() => {})
70
+ if (!isDefaultDatabase) return result
71
+ if (blueprint.trace === undefined && blueprint.audit === undefined) return result
72
+
73
+ const definitions = await loadInternalDefinitions(blueprint, { isDefaultDatabase })
74
+ const snapshot = buildSnapshot(definitions, EMPTY_SNAPSHOT.id)
75
+ const tables = Object.values(snapshot.tables).filter(t => PARTITIONED_TRACE_TABLE_NAMES.has(t.name))
76
+
77
+ const live = await readLiveColumns(db, tables.map(t => t.name))
78
+ const createOps: DiffOp[] = []
79
+ const alterStatements: string[] = []
80
+
81
+ for (const table of tables) {
82
+ const liveColumns = live.get(table.name)
83
+ if (liveColumns === undefined) {
84
+ createOps.push({ type: 'create_table', table })
85
+ result.created.push(table.name)
86
+ continue
87
+ }
88
+ for (const column of Object.values(table.columns)) {
89
+ if (liveColumns.has(column.name)) continue
90
+ if (column.notNull && column.default === undefined && column.identity === undefined && column.generated === undefined) {
91
+ const rows = await db.execute(sql.raw(`SELECT 1 FROM ${quoteIdentifier(table.name, 'table')} LIMIT 1`))
92
+ if (rows.length > 0) {
93
+ throw new FrameworkTableColumnError(
94
+ `Cannot add column "${column.name}" to framework table "${table.name}": it is NOT NULL with no default ` +
95
+ `and the table has rows. Backfill is a decision for the application — add the column by hand ` +
96
+ `(nullable, backfill, then SET NOT NULL) and run migrate again.`,
97
+ )
98
+ }
99
+ }
100
+ const [statement] = emitSQL([{ type: 'add_column', tableName: table.name, tableSchema: table.schema, column }])
101
+ alterStatements.push(statement!.replace('ADD COLUMN', 'ADD COLUMN IF NOT EXISTS'))
102
+ result.columnsAdded.push(`${table.name}.${column.name}`)
103
+ }
104
+ }
105
+
106
+ progress('tables')
107
+ const createStatements = emitSQL(createOps)
108
+ for (const [i, statement] of createStatements.entries()) {
109
+ await db.execute(sql.raw(options.unlogged ? makeTablesUnlogged(statement) : statement))
110
+ progress('tables', `create ${i + 1}/${createStatements.length}`)
111
+ }
112
+ for (const [i, statement] of alterStatements.entries()) {
113
+ await db.execute(sql.raw(statement))
114
+ progress('tables', `alter ${i + 1}/${alterStatements.length}`)
115
+ }
116
+ if (tables.some(t => t.name === 'audit_record')) await db.execute(sql.raw(AUDIT_ENTITY_INDEX_SQL))
117
+
118
+ if (blueprint.audit?.chain === true) {
119
+ progress('audit-chain')
120
+ await installAuditChain(db)
121
+ }
122
+ if (options.rls !== undefined) {
123
+ progress('policies')
124
+ await installFrameworkPolicies(db, tables.map(t => t.name), options.rls)
125
+ }
126
+
127
+ const synced = await syncTracePartitions(db, traceConfig, undefined, {
128
+ onPartition: (name, index, total) => progress('partition', `${index}/${total} ${name}`),
129
+ })
130
+ result.partitionsCreated.push(...synced.created)
131
+ return result
132
+ }
133
+
134
+ /** Column names of each named public table that exists; absent tables are not in the map. */
135
+ async function readLiveColumns(db: DB, names: string[]): Promise<Map<string, Set<string>>> {
136
+ const out = new Map<string, Set<string>>()
137
+ for (const name of names) {
138
+ const rows = await db.execute(sql`
139
+ SELECT a.attname AS name
140
+ FROM pg_attribute a
141
+ WHERE a.attrelid = to_regclass(${quoteIdentifier(name, 'table')})
142
+ AND a.attnum > 0 AND NOT a.attisdropped
143
+ `)
144
+ if (rows.length > 0) out.set(name, new Set(rows.map(r => String(r['name']))))
145
+ }
146
+ return out
147
+ }
@@ -0,0 +1,61 @@
1
+ import type { DefinedTable, FieldKind } from '../domain/types.js'
2
+ import { camelToSnake } from '../domain/naming.js'
3
+ import { tenantIsolationPolicy, type TenantKeyType } from '../../auth/tenant/rls.js'
4
+
5
+ // A fresh matcher per call. A `g` regex carries lastIndex; sharing one instance
6
+ // corrupts the next call when a previous run exits mid-iteration (e.g.
7
+ // tenantKeyTypeForKind throws), making exec() resume mid-string and silently
8
+ // skip tables — dropping their RLS. Each call gets its own.
9
+ const createTableMatcher = (): RegExp => /CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"([^"]+)"|([a-z_][a-z0-9_]*))/gi
10
+
11
+ export function generateRlsStatements(
12
+ migrationSql: string,
13
+ definitions: ReadonlyMap<string, DefinedTable>,
14
+ sessionVar: string,
15
+ force: boolean = true,
16
+ ): string {
17
+ const rlsBlocks: string[] = []
18
+ let match: RegExpExecArray | null
19
+
20
+ const createTableRe = createTableMatcher()
21
+ while ((match = createTableRe.exec(migrationSql)) !== null) {
22
+ const tableName = match[1] ?? match[2]
23
+ if (tableName === undefined) continue
24
+
25
+ const definition = definitions.get(tableName)
26
+ if (definition === undefined) continue
27
+
28
+ const tenantFieldKey = Object.keys(definition.$fields).find(
29
+ (key) => definition.$fields[key]!._meta.tenant === true,
30
+ )
31
+ if (tenantFieldKey === undefined) continue
32
+
33
+ const tenantField = definition.$fields[tenantFieldKey]!
34
+ const columnName = camelToSnake(tenantFieldKey)
35
+ const keyType = tenantKeyTypeForKind(tenantField._meta.kind, tableName, tenantFieldKey)
36
+
37
+ if (migrationSql.includes(`"${tableName}" ENABLE ROW LEVEL SECURITY`) ||
38
+ migrationSql.includes(`${tableName} ENABLE ROW LEVEL SECURITY`)) {
39
+ continue
40
+ }
41
+
42
+ rlsBlocks.push(tenantIsolationPolicy(tableName, columnName, keyType, sessionVar, force))
43
+ }
44
+
45
+ if (rlsBlocks.length === 0) return migrationSql
46
+
47
+ return migrationSql + '\n\n' + rlsBlocks.join(';\n\n') + ';'
48
+ }
49
+
50
+ const TENANT_KEY_KINDS: ReadonlySet<string> = new Set(['uuid', 'text', 'integer', 'bigint'])
51
+
52
+ function tenantKeyTypeForKind(kind: FieldKind, table: string, field: string): TenantKeyType {
53
+ if (TENANT_KEY_KINDS.has(kind)) return kind as TenantKeyType
54
+ throw new Error(
55
+ `[pipework] Field "${field}" on table "${table}" is marked .tenant() but its kind is '${kind}'.\n\n` +
56
+ ` A tenant discriminator must be uuid, text, integer, or bigint — the generated RLS\n` +
57
+ ` policy casts current_setting() to that type. Mark the uuid/text tenant key with\n` +
58
+ ` .tenant(), not a '${kind}' column.`,
59
+ )
60
+ }
61
+
@@ -0,0 +1,124 @@
1
+ import { sql } from '../query/index.js'
2
+ import type { Manifold } from '../../core/pipework.js'
3
+ import type { ResolvedDatabase } from '../../core/config/index.js'
4
+ import { quoteIdentifier } from '../db/identifiers.js'
5
+ import { OWNER_LABEL_MIGRATE } from '../db/owner-labels.js'
6
+ import { checkMigrations, type MigrationCheckResult } from './check.js'
7
+ import { readAppliedState } from './applied.js'
8
+ import { applyMigrations } from './apply.js'
9
+ import { provisionFrameworkTables, type FrameworkTablesResult } from './provision-framework.js'
10
+
11
+ // Deliberately empty of hazard switches. Authorization for a hazardous
12
+ // migration is declared in that migration's own file (see pragma.ts) — an
13
+ // option here would be an invocation-level approval, which is exactly the
14
+ // thing that gets written into a deploy workflow once and never revisited.
15
+ export interface MigrateOptions {}
16
+
17
+ export interface MigrateResult {
18
+ database: string
19
+ migrationsRun: number
20
+ extensions: string[]
21
+ safetyCheck: MigrationCheckResult
22
+ /** No-transaction files picked up half applied and finished. Issue #378. */
23
+ resumed: ResumedMigration[]
24
+ /** Trace/audit tables, columns and day partitions this run provisioned. */
25
+ frameworkTables: FrameworkTablesResult
26
+ }
27
+
28
+ export interface ResumedMigration {
29
+ tag: string
30
+ /** 1-based statement the rerun started from. */
31
+ fromStatement: number
32
+ totalStatements: number
33
+ }
34
+
35
+ export class UnsafeMigrationError extends Error {
36
+ override readonly name = 'UnsafeMigrationError'
37
+ constructor(
38
+ public readonly check: MigrationCheckResult,
39
+ message: string,
40
+ ) {
41
+ super(message)
42
+ }
43
+ }
44
+
45
+ export async function migrateAll(instance: Manifold, options: MigrateOptions = {}): Promise<MigrateResult[]> {
46
+ const results: MigrateResult[] = []
47
+
48
+ for (const [, dbConfig] of instance.config.databases()) {
49
+ if (dbConfig.migrations === undefined) continue
50
+ const result = await migrateOne(instance, dbConfig, options)
51
+ results.push(result)
52
+ }
53
+
54
+ return results
55
+ }
56
+
57
+ export async function migrateOne(instance: Manifold, dbConfig: ResolvedDatabase, _options: MigrateOptions = {}): Promise<MigrateResult> {
58
+ const conn = instance.pool.getOrCreate(dbConfig, 'owner', OWNER_LABEL_MIGRATE)
59
+
60
+ // Scope the safety gate to pending migrations only — hazards in already-applied
61
+ // migrations are history, not a decision the operator still gets to make.
62
+ // Without this, a fully-current database with a destructive op anywhere in its
63
+ // history can never run a clean no-op `migrate`.
64
+ const safetyCheck = dbConfig.migrations !== undefined
65
+ ? checkMigrations(dbConfig.migrations, await readAppliedState(conn.drizzle, dbConfig.migrationTable))
66
+ : { safe: true, hasDestructive: false, hasLocking: false, hasDynamic: false, declared: true, fileHazards: [] } as MigrationCheckResult
67
+
68
+ if (!safetyCheck.declared) {
69
+ const files = safetyCheck.fileHazards.filter(f => f.undeclared.length > 0)
70
+ const detail = files
71
+ .map(f => `${f.file} (${f.undeclared.join(', ')})`)
72
+ .join(', ')
73
+ throw new UnsafeMigrationError(
74
+ safetyCheck,
75
+ `Migration for "${dbConfig.name}" raises hazards that its own file does not declare: ${detail}. ` +
76
+ `Add the matching \`-- pipework:expect-*\` pragma to each migration and commit it.`,
77
+ )
78
+ }
79
+
80
+ let extensionsCreated: string[] = []
81
+
82
+ if (dbConfig.extensions.length > 0) {
83
+ for (const ext of dbConfig.extensions) {
84
+ await conn.drizzle.execute(sql.raw(`CREATE EXTENSION IF NOT EXISTS ${quoteIdentifier(ext, 'extension')}`))
85
+ }
86
+ extensionsCreated = [...dbConfig.extensions]
87
+ }
88
+
89
+ const resumed: ResumedMigration[] = []
90
+ const migrationsRun = await applyMigrations({
91
+ migrationsFolder: dbConfig.migrations!,
92
+ migrationsTable: dbConfig.migrationTable,
93
+ connectionUrl: dbConfig.url,
94
+ onResume: (tag, fromStatement, totalStatements) => resumed.push({ tag, fromStatement, totalStatements }),
95
+ })
96
+
97
+ // Trace and audit storage rides the default database; their partitioned
98
+ // tables are kept out of generated migrations (#313), so migrate provisions them.
99
+ const frameworkTables = await provisionFrameworkTables(
100
+ conn.drizzle,
101
+ instance.config.raw,
102
+ {
103
+ hotRetentionDays: instance.config.trace.hotRetentionDays,
104
+ errorRetentionDays: instance.config.trace.errorRetentionDays,
105
+ auditRetentionDays: instance.config.audit.retentionDays === 'keep' ? null : instance.config.audit.retentionDays,
106
+ partitionLeadDays: instance.config.trace.partitionLeadDays,
107
+ },
108
+ wantsFrameworkTables(instance) && dbConfig.name === instance.config.defaultDatabaseName(),
109
+ { unlogged: false, rls: dbConfig.rls },
110
+ )
111
+
112
+ return {
113
+ database: dbConfig.name,
114
+ migrationsRun,
115
+ extensions: extensionsCreated,
116
+ safetyCheck,
117
+ resumed,
118
+ frameworkTables,
119
+ }
120
+ }
121
+
122
+ function wantsFrameworkTables(instance: Manifold): boolean {
123
+ return instance.config.raw.trace !== undefined || instance.config.raw.audit !== undefined
124
+ }
@@ -0,0 +1,167 @@
1
+ import { scanStatements, blankLiterals } from './statements.js'
2
+
3
+ export type Severity = 'destructive' | 'locking' | 'dynamic' | 'safe'
4
+
5
+ export interface MigrationHazard {
6
+ severity: Severity
7
+ operation: string
8
+ statement: string
9
+ suggestion: string
10
+ }
11
+
12
+ interface Rule {
13
+ pattern: RegExp
14
+ severity: Severity
15
+ operation: string
16
+ suggestion: string
17
+ except?: RegExp
18
+ }
19
+
20
+ const RULES: Rule[] = [
21
+ // ── Destructive (data loss / backward-incompatible) ───────────────────
22
+ {
23
+ pattern: /\bDROP\s+TABLE\b/i,
24
+ severity: 'destructive',
25
+ operation: 'DROP TABLE',
26
+ suggestion: 'Rename the table first, deploy, verify no access, then drop in a follow-up migration.',
27
+ },
28
+ {
29
+ pattern: /\bDROP\s+COLUMN\b/i,
30
+ severity: 'destructive',
31
+ operation: 'DROP COLUMN',
32
+ suggestion: 'Stop reading the column in application code first, then drop in a follow-up migration.',
33
+ },
34
+ {
35
+ pattern: /\bALTER\s+COLUMN\b[^;]*\bSET\s+NOT\s+NULL\b/i,
36
+ severity: 'destructive',
37
+ operation: 'SET NOT NULL',
38
+ suggestion: 'Add a CHECK constraint with NOT VALID, validate it separately, then convert to NOT NULL.',
39
+ },
40
+ {
41
+ pattern: /\bALTER\s+COLUMN\b[^;]*\bTYPE\b/i,
42
+ severity: 'destructive',
43
+ operation: 'ALTER COLUMN TYPE',
44
+ suggestion: 'Add a new column with the target type, backfill, swap reads, then drop the old column.',
45
+ },
46
+ {
47
+ pattern: /\bTRUNCATE\b/i,
48
+ severity: 'destructive',
49
+ operation: 'TRUNCATE',
50
+ suggestion: 'Use DELETE with a WHERE clause if you need to remove rows in a migration.',
51
+ },
52
+
53
+ // ── Locking (acquires heavy locks, risks downtime under load) ─────────
54
+ {
55
+ pattern: /\bCREATE\s+(?:UNIQUE\s+)?INDEX\b(?!\s+CONCURRENTLY)/i,
56
+ severity: 'locking',
57
+ operation: 'CREATE INDEX (non-concurrent)',
58
+ suggestion: 'Use CREATE INDEX CONCURRENTLY to avoid blocking writes.',
59
+ except: /\bCONCURRENTLY\b/i,
60
+ },
61
+ {
62
+ pattern: /\bRENAME\s+COLUMN\b/i,
63
+ severity: 'locking',
64
+ operation: 'RENAME COLUMN',
65
+ suggestion: 'Add a new column, backfill, migrate reads, then drop the old column.',
66
+ },
67
+ {
68
+ pattern: /\bRENAME\s+TABLE\b/i,
69
+ severity: 'locking',
70
+ operation: 'RENAME TABLE',
71
+ suggestion: 'Create a new table, migrate data, swap reads, then drop the old table.',
72
+ },
73
+ {
74
+ pattern: /\bRENAME\s+TO\b/i,
75
+ severity: 'locking',
76
+ operation: 'RENAME TO',
77
+ suggestion: 'Renames acquire AccessExclusive locks. Consider a multi-step migration instead.',
78
+ except: /\bRENAME\s+COLUMN\b|\bRENAME\s+TABLE\b|\bALTER\s+INDEX\b/i,
79
+ },
80
+ {
81
+ pattern: /\bADD\s+CONSTRAINT\b[^;]*\bFOREIGN\s+KEY\b(?![^;]*\bNOT\s+VALID\b)/i,
82
+ severity: 'locking',
83
+ operation: 'ADD FOREIGN KEY (without NOT VALID)',
84
+ suggestion: 'Add the constraint with NOT VALID, then VALIDATE CONSTRAINT in a separate statement.',
85
+ },
86
+ {
87
+ // Locking rather than destructive: on a non-empty table this fails loudly
88
+ // instead of losing data, so it aborts the deploy rather than silently
89
+ // damaging it. It is still a gate-worthy hazard, hence the rule (#334).
90
+ pattern: /\bADD\s+COLUMN\b[^;]*\bNOT\s+NULL\b/i,
91
+ severity: 'locking',
92
+ operation: 'ADD COLUMN NOT NULL (without DEFAULT)',
93
+ suggestion:
94
+ 'Add the column nullable, backfill, then SET NOT NULL — or give it a DEFAULT so existing rows can be filled.',
95
+ except: /\bDEFAULT\b/i,
96
+ },
97
+
98
+ // ── Dynamic (SQL assembled at runtime — unanalyzable) ────────────────
99
+ {
100
+ // The gate reads text; `EXECUTE` runs text that does not exist yet. Rather
101
+ // than pretend to see through it, name it. This is also what lets string
102
+ // literals be treated as the inert data they almost always are: a literal
103
+ // is dangerous exactly when something EXECUTEs it, and that is structural
104
+ // rather than a guess about its contents (#334). `EXECUTE FUNCTION|PROCEDURE`
105
+ // (triggers) and `EXECUTE ON` (GRANT/REVOKE) name an existing function or
106
+ // privilege and build no SQL, so they are not this (#480).
107
+ pattern: /\bEXECUTE\b(?!\s+(?:FUNCTION|PROCEDURE|ON)\b)/i,
108
+ severity: 'dynamic',
109
+ operation: 'dynamic SQL (EXECUTE)',
110
+ suggestion:
111
+ 'The gate cannot analyze SQL built at runtime. Prefer static DDL; if runtime assembly is required, declare it in the migration.',
112
+ },
113
+ ]
114
+
115
+ export function analyzeSQL(sql: string): MigrationHazard[] {
116
+ const statements = scanStatements(sql)
117
+ const hazards: MigrationHazard[] = []
118
+
119
+ for (const stmt of statements) {
120
+ // Rules match against the statement with string-literal contents blanked:
121
+ // literals are data, and DDL keywords sitting in seed data execute
122
+ // nothing. Dollar-quoted bodies stay intact — those are code.
123
+ const subject = blankLiterals(stmt)
124
+
125
+ for (const rule of RULES) {
126
+ if (!rule.pattern.test(subject)) continue
127
+ if (rule.except !== undefined && rule.except.test(subject)) continue
128
+
129
+ hazards.push({
130
+ severity: rule.severity,
131
+ operation: rule.operation,
132
+ statement: stmt.trim().slice(0, 200),
133
+ suggestion: rule.suggestion,
134
+ })
135
+ }
136
+ }
137
+
138
+ return hazards
139
+ }
140
+
141
+ export function formatHazards(hazards: MigrationHazard[], file: string): string {
142
+ const lines: string[] = []
143
+
144
+ lines.push(` ${file}:`)
145
+
146
+ const label: Record<string, string> = {
147
+ destructive: '✗ DESTRUCTIVE',
148
+ locking: '⚠ LOCKING',
149
+ dynamic: '? DYNAMIC',
150
+ }
151
+
152
+ for (const severity of ['destructive', 'locking', 'dynamic'] as const) {
153
+ for (const h of hazards.filter(x => x.severity === severity)) {
154
+ lines.push(` ${label[severity]}: ${h.operation}`)
155
+ lines.push(` ${truncate(h.statement, 120)}`)
156
+ lines.push(` → ${h.suggestion}`)
157
+ }
158
+ }
159
+
160
+ return lines.join('\n')
161
+ }
162
+
163
+ function truncate(s: string, max: number): string {
164
+ const oneLine = s.replace(/\s+/g, ' ')
165
+ if (oneLine.length <= max) return oneLine
166
+ return oneLine.slice(0, max - 3) + '...'
167
+ }