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,173 @@
1
+ // The cardinality analyzer. Given the `@flow_step` sites of a source set, it
2
+ // classifies every `@downstream` edge structurally (classify-edge.ts), reports
3
+ // the edges whose declared cardinality disagrees with the structure or whose
4
+ // cardinality could not be resolved, and derives the Q7 `structuralMax` step
5
+ // cap from the resulting graph. Pure over its inputs — file I/O lives in
6
+ // check.ts. See PLAN.tracing.md, component 3.
7
+
8
+ import type { FlowStepSite } from '../check/flow-step-site.js'
9
+ import { classifyEdge, type EdgeClassification } from './classify-edge.js'
10
+ import { computeStructuralMax, type StepEdge } from './structural-max.js'
11
+ import type { BranchKind } from './branch-context.js'
12
+
13
+ /** A `@flow_step` site paired with the source path it was found in. */
14
+ export interface AnalyzerEntry {
15
+ /** Source path relative to `cwd` — the node-id prefix and the diagnostic file. */
16
+ readonly file: string
17
+ readonly site: FlowStepSite
18
+ }
19
+
20
+ export interface CardinalityViolation {
21
+ readonly rule: string
22
+ readonly file: string
23
+ readonly line: number
24
+ readonly message: string
25
+ }
26
+
27
+ export interface CardinalityResult {
28
+ /** Structural verdict for every `@downstream` edge across the input. */
29
+ readonly classifications: readonly EdgeClassification[]
30
+ readonly violations: readonly CardinalityViolation[]
31
+ /** The Q7 step cap: longest chain of `step` edges through the flow graph. */
32
+ readonly structuralMax: number
33
+ /** Count of flow-step sites the analyzer classified. */
34
+ readonly analyzed: number
35
+ }
36
+
37
+ /** The `path:symbol` flow-graph node id — the single place ids are composed. */
38
+ function nodeId(path: string, symbol: string): string {
39
+ return `${path}:${symbol}`
40
+ }
41
+
42
+ /** Classifies every `@downstream` edge across `entries` and derives the step cap. */
43
+ export function analyzeCardinality(entries: readonly AnalyzerEntry[]): CardinalityResult {
44
+ const classifications: EdgeClassification[] = []
45
+ const violations: CardinalityViolation[] = []
46
+ const nodeIds: string[] = []
47
+ const stepEdges: StepEdge[] = []
48
+ // Keyed `${from}\n${target}` so a `step`-cycle violation can recover the
49
+ // exact classification of the edge that closes the ring.
50
+ const stepEdgeIndex = new Map<string, EdgeClassification>()
51
+
52
+ for (const { file, site } of entries) {
53
+ // An orphan annotation documents no function, and an invalid one never
54
+ // parsed into edges — both are the `flow` check's diagnostics, not this
55
+ // one's. Nothing here to classify.
56
+ if (site.subject.node === null) continue
57
+ if (site.annotation.kind !== 'annotation') continue
58
+
59
+ const from = nodeId(file, site.subject.name)
60
+ nodeIds.push(from)
61
+
62
+ for (const edge of site.annotation.annotation.downstream) {
63
+ const classification = classifyEdge(file, site, edge)
64
+ classifications.push(classification)
65
+ const violation = violationFor(classification, site)
66
+ if (violation !== null) violations.push(violation)
67
+
68
+ if (classification.structural === 'step') {
69
+ const to = nodeId(edge.path, edge.symbol)
70
+ stepEdges.push({ from, to })
71
+ stepEdgeIndex.set(`${from}\n${to}`, classification)
72
+ }
73
+ }
74
+ }
75
+
76
+ const { value, cycles } = computeStructuralMax(nodeIds, stepEdges)
77
+ for (const cycle of cycles) {
78
+ violations.push(cycleViolation(cycle, stepEdgeIndex))
79
+ }
80
+
81
+ return {
82
+ classifications,
83
+ violations,
84
+ structuralMax: value,
85
+ analyzed: nodeIds.length,
86
+ }
87
+ }
88
+
89
+ /** The violation a single classified edge raises, or `null` when it is sound. */
90
+ function violationFor(
91
+ classification: EdgeClassification,
92
+ site: FlowStepSite,
93
+ ): CardinalityViolation | null {
94
+ const { edge, structural, branchKind } = classification
95
+ const target = nodeId(edge.path, edge.symbol)
96
+ const file = classification.file
97
+ const line = classification.line ?? site.commentLine
98
+
99
+ if (edge.cardinality === null) {
100
+ // A missing cardinality the analyzer *can* resolve is the `flow` check's
101
+ // `missing-cardinality` warning, and the classification is what the codemod
102
+ // consumes to fill it in. Only an unresolved one is this check's to raise.
103
+ if (structural !== 'ambiguous') return null
104
+ return {
105
+ rule: 'cardinality/unannotated-ambiguity',
106
+ file,
107
+ line,
108
+ message:
109
+ `@downstream ${target} has no cardinality and the analyzer cannot locate the call — `
110
+ + `${edge.symbol} is reached through indirection (a bare callback, dynamic dispatch). `
111
+ + `Declare it explicitly: "@downstream ${target} step" or "@downstream ${target} branch".`,
112
+ }
113
+ }
114
+
115
+ // The author declared a cardinality the analyzer could not verify — the
116
+ // annotation is the source of truth for indirection it cannot follow.
117
+ if (structural === 'ambiguous') return null
118
+ if (structural === edge.cardinality) return null
119
+
120
+ if (structural === 'branch') {
121
+ const phrase = branchPhrase(branchKind!)
122
+ return {
123
+ rule: 'cardinality/mismatch',
124
+ file,
125
+ line,
126
+ message:
127
+ `@downstream ${target} is declared "step" but ${edge.symbol} is called inside `
128
+ + `${phrase} — that call site is traversed more than once, which is a `
129
+ + `branch. Change the cardinality to "branch", or hoist the call out of ${phrase}.`,
130
+ }
131
+ }
132
+ return {
133
+ rule: 'cardinality/mismatch',
134
+ file,
135
+ line,
136
+ message:
137
+ `@downstream ${target} is declared "branch" but every located call to ${edge.symbol} is `
138
+ + `linear — it is traversed at most once, which is a step. Change the cardinality to "step".`,
139
+ }
140
+ }
141
+
142
+ /** The violation for one `step`-edge cycle, attributed to the edge that opens it. */
143
+ function cycleViolation(
144
+ cycle: readonly string[],
145
+ stepEdgeIndex: ReadonlyMap<string, EdgeClassification>,
146
+ ): CardinalityViolation {
147
+ // A `step`-edge cycle has at least two nodes — a self `step` edge is
148
+ // impossible, since a self-call is always classified `recursion` (a branch).
149
+ const source = cycle[0]!
150
+ const target = cycle[1]!
151
+ // Every node in a `step`-edge cycle is the `from` of a `step` edge in the
152
+ // ring, so the closing edge is always indexed.
153
+ const edge = stepEdgeIndex.get(`${source}\n${target}`)!
154
+ const ring = [...cycle, source].join(' → ')
155
+ return {
156
+ rule: 'cardinality/step-cycle',
157
+ file: edge.file,
158
+ line: edge.line!,
159
+ message:
160
+ `@downstream forms a cycle of "step" edges: ${ring}. A step edge that loops back makes the `
161
+ + `per-trace step count unbounded — one edge in this ring is a branch (mutual recursion is a `
162
+ + `branch). Re-classify the edge that closes the loop.`,
163
+ }
164
+ }
165
+
166
+ function branchPhrase(kind: BranchKind): string {
167
+ switch (kind) {
168
+ case 'loop': return 'a loop'
169
+ case 'iteration-method': return 'an iteration callback (.map, .forEach, …)'
170
+ case 'fan-out': return 'a Promise combinator (Promise.all, …)'
171
+ case 'recursion': return 'a recursive call'
172
+ }
173
+ }
@@ -0,0 +1,214 @@
1
+ // Locates every call to a target symbol inside a flow-step function body and
2
+ // classifies each call's traversal context. A call reached through a loop, an
3
+ // iteration method, a Promise-combinator fan-out, or a self-recursive edge is
4
+ // "branching" — the single call site is traversed more than once per execution
5
+ // of the parent. Anything else is linear. This is the structural half of the
6
+ // cardinality analyzer: it reads AST shape only, never runtime behaviour, and
7
+ // never resolves imports or types. See PLAN.tracing.md, Q1.
8
+
9
+ import { isNode, type AstNode } from '../check/flow-step-site.js'
10
+
11
+ /** The construct that makes a call site traversed more than once. */
12
+ export type BranchKind = 'loop' | 'iteration-method' | 'fan-out' | 'recursion'
13
+
14
+ /** One located call to the target symbol, with its traversal context. */
15
+ export interface CallSite {
16
+ /** 1-based file line of the call. */
17
+ readonly line: number
18
+ /** The branching construct enclosing the call, or `null` when the call is linear. */
19
+ readonly branchKind: BranchKind | null
20
+ }
21
+
22
+ // Array methods whose callback argument is invoked once per element — a
23
+ // downstream call inside the callback is traversed more than once. Lexical:
24
+ // `.map` on a non-array still reads as iteration, by design (Q1).
25
+ const ITERATION_METHODS = new Set([
26
+ 'map', 'forEach', 'flatMap', 'filter',
27
+ 'reduce', 'reduceRight',
28
+ 'some', 'every',
29
+ 'find', 'findIndex', 'findLast', 'findLastIndex',
30
+ ])
31
+
32
+ // Promise combinators that run their arguments as concurrent siblings.
33
+ const PROMISE_COMBINATORS = new Set(['all', 'allSettled', 'race', 'any'])
34
+
35
+ const FUNCTION_TYPES = new Set([
36
+ 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression',
37
+ ])
38
+
39
+ const SKIP_KEYS = new Set(['loc', 'range', 'parent'])
40
+
41
+ interface Context {
42
+ /** Name of the enclosing flow step — a call to it is recursion. */
43
+ readonly ownName: string
44
+ /** Symbol the `@downstream` edge points at. */
45
+ readonly target: string
46
+ /** The branching construct currently in scope, or `null` at linear depth. */
47
+ readonly branchKind: BranchKind | null
48
+ readonly out: CallSite[]
49
+ }
50
+
51
+ /** Every call to `target` inside `body`, each tagged with its traversal context. */
52
+ export function findCallSites(body: AstNode, ownName: string, target: string): CallSite[] {
53
+ const out: CallSite[] = []
54
+ visit(body, { ownName, target, branchKind: null, out })
55
+ return out
56
+ }
57
+
58
+ function visit(node: AstNode, ctx: Context): void {
59
+ // A nested closure reached by ordinary descent is indirection the analyzer
60
+ // does not follow. Iteration-method callbacks are the one exception, and
61
+ // those are entered explicitly from `visitCall`.
62
+ if (FUNCTION_TYPES.has(node.type)) return
63
+
64
+ switch (node.type) {
65
+ case 'CallExpression':
66
+ visitCall(node, ctx)
67
+ return
68
+ case 'ForStatement':
69
+ visitForStatement(node, ctx)
70
+ return
71
+ case 'ForOfStatement':
72
+ case 'ForInStatement':
73
+ visitForInOf(node, ctx)
74
+ return
75
+ case 'WhileStatement':
76
+ case 'DoWhileStatement':
77
+ visitWhile(node, ctx)
78
+ return
79
+ default:
80
+ for (const child of childNodes(node)) visit(child, ctx)
81
+ }
82
+ }
83
+
84
+ function visitCall(node: AstNode, ctx: Context): void {
85
+ const callee = node['callee']
86
+ const name = calleeName(callee)
87
+ if (name === ctx.target) {
88
+ ctx.out.push({
89
+ line: node.loc.start.line,
90
+ branchKind: name === ctx.ownName ? 'recursion' : ctx.branchKind,
91
+ })
92
+ }
93
+
94
+ const args = nodeArray(node['arguments'])
95
+
96
+ if (isPromiseCombinator(callee)) {
97
+ // Each argument runs as a concurrent sibling — a fan-out.
98
+ for (const arg of args) visit(arg, branched(ctx, 'fan-out'))
99
+ return
100
+ }
101
+
102
+ if (isIterationMethod(callee)) {
103
+ // The receiver is evaluated once; the callback runs once per element.
104
+ if (isNode(callee)) visitChild(callee['object'], ctx)
105
+ for (const arg of args) visitIterationArg(arg, ctx)
106
+ return
107
+ }
108
+
109
+ // An ordinary call: callee and arguments stay at the current depth.
110
+ visitChild(callee, ctx)
111
+ for (const arg of args) visit(arg, ctx)
112
+ }
113
+
114
+ function visitIterationArg(arg: AstNode, ctx: Context): void {
115
+ if (arg.type === 'Identifier' && arg['name'] === ctx.target) {
116
+ // `items.map(downstream)` — the symbol is itself the per-element callback.
117
+ ctx.out.push({
118
+ line: arg.loc.start.line,
119
+ branchKind: arg['name'] === ctx.ownName ? 'recursion' : 'iteration-method',
120
+ })
121
+ return
122
+ }
123
+ if (FUNCTION_TYPES.has(arg.type)) {
124
+ visitChild(arg['body'], branched(ctx, 'iteration-method'))
125
+ return
126
+ }
127
+ // A non-callback argument (e.g. `reduce`'s seed) runs at the current depth.
128
+ visit(arg, ctx)
129
+ }
130
+
131
+ function visitForStatement(node: AstNode, ctx: Context): void {
132
+ // `init` runs once; `test`, `update`, and `body` run every iteration.
133
+ visitChild(node['init'], ctx)
134
+ const looped = branched(ctx, 'loop')
135
+ visitChild(node['test'], looped)
136
+ visitChild(node['update'], looped)
137
+ visitChild(node['body'], looped)
138
+ }
139
+
140
+ function visitForInOf(node: AstNode, ctx: Context): void {
141
+ // `right` (the iterable) is evaluated once; `body` runs once per element.
142
+ visitChild(node['right'], ctx)
143
+ visitChild(node['body'], branched(ctx, 'loop'))
144
+ }
145
+
146
+ function visitWhile(node: AstNode, ctx: Context): void {
147
+ // Both `test` and `body` run every iteration.
148
+ const looped = branched(ctx, 'loop')
149
+ visitChild(node['test'], looped)
150
+ visitChild(node['body'], looped)
151
+ }
152
+
153
+ /** Enters `branchKind` scope, keeping the outermost construct already in scope. */
154
+ function branched(ctx: Context, kind: BranchKind): Context {
155
+ return { ...ctx, branchKind: ctx.branchKind ?? kind }
156
+ }
157
+
158
+ function visitChild(value: unknown, ctx: Context): void {
159
+ if (isNode(value)) visit(value, ctx)
160
+ }
161
+
162
+ function calleeName(callee: unknown): string | null {
163
+ if (!isNode(callee)) return null
164
+ if (callee.type === 'Identifier') {
165
+ const name = callee['name']
166
+ return typeof name === 'string' ? name : null
167
+ }
168
+ if (callee.type === 'MemberExpression' && callee['computed'] === false) {
169
+ const prop = callee['property']
170
+ if (isNode(prop) && prop.type === 'Identifier' && typeof prop['name'] === 'string') {
171
+ return prop['name']
172
+ }
173
+ }
174
+ return null
175
+ }
176
+
177
+ function isPromiseCombinator(callee: unknown): boolean {
178
+ if (!isNode(callee) || callee.type !== 'MemberExpression' || callee['computed'] !== false) {
179
+ return false
180
+ }
181
+ const obj = callee['object']
182
+ const prop = callee['property']
183
+ return isNode(obj) && obj.type === 'Identifier' && obj['name'] === 'Promise'
184
+ && isNode(prop) && prop.type === 'Identifier'
185
+ && typeof prop['name'] === 'string' && PROMISE_COMBINATORS.has(prop['name'])
186
+ }
187
+
188
+ function isIterationMethod(callee: unknown): boolean {
189
+ if (!isNode(callee) || callee.type !== 'MemberExpression' || callee['computed'] !== false) {
190
+ return false
191
+ }
192
+ const prop = callee['property']
193
+ return isNode(prop) && prop.type === 'Identifier'
194
+ && typeof prop['name'] === 'string' && ITERATION_METHODS.has(prop['name'])
195
+ }
196
+
197
+ function nodeArray(value: unknown): AstNode[] {
198
+ if (!Array.isArray(value)) return []
199
+ return value.filter(isNode)
200
+ }
201
+
202
+ function* childNodes(node: AstNode): Generator<AstNode> {
203
+ for (const key of Object.keys(node)) {
204
+ if (SKIP_KEYS.has(key)) continue
205
+ const value = node[key]
206
+ if (Array.isArray(value)) {
207
+ for (const item of value) {
208
+ if (isNode(item)) yield item
209
+ }
210
+ } else if (isNode(value)) {
211
+ yield value
212
+ }
213
+ }
214
+ }
@@ -0,0 +1,33 @@
1
+ // File-scanning wrapper around the cardinality analyzer: reads each source
2
+ // file, collects its `@flow_step` sites, and runs `analyzeCardinality` over
3
+ // the lot. Mirrors flow-check.ts — the analyzer itself is pure (analyze.ts);
4
+ // this is the only part of the cardinality check that touches the filesystem.
5
+
6
+ import { readFileSync } from 'node:fs'
7
+ import { join } from 'node:path'
8
+ import { collectFlowStepSites } from '../check/flow-step-site.js'
9
+ import { analyzeCardinality, type AnalyzerEntry, type CardinalityResult } from './analyze.js'
10
+
11
+ /** Analyzes `@downstream` cardinality across `sourceFiles` (paths relative to `cwd`). */
12
+ export function checkCardinality(cwd: string, sourceFiles: readonly string[]): CardinalityResult {
13
+ const entries: AnalyzerEntry[] = []
14
+
15
+ for (const file of sourceFiles) {
16
+ const abs = join(cwd, file)
17
+
18
+ let sites
19
+ try {
20
+ sites = collectFlowStepSites(readFileSync(abs, 'utf-8'), file)
21
+ } catch {
22
+ // Missing or unparseable file — nothing to analyze; a syntax error is
23
+ // the type checker's diagnostic, not this check's.
24
+ continue
25
+ }
26
+
27
+ for (const site of sites) {
28
+ entries.push({ file, site })
29
+ }
30
+ }
31
+
32
+ return analyzeCardinality(entries)
33
+ }
@@ -0,0 +1,64 @@
1
+ // Structural cardinality verdict for one declared `@downstream` edge: locate
2
+ // the edge's call sites in the flow-step body and decide whether the edge is a
3
+ // plain `step`, a `branch` (a single call site reached through a loop, an
4
+ // iteration method, a fan-out, or recursion), or `ambiguous` — reached through
5
+ // indirection the analyzer cannot follow. See PLAN.tracing.md, Q1.
6
+
7
+ import type { DownstreamEdge } from 'pipework-flow-parser'
8
+ import type { FlowStepSite } from '../check/flow-step-site.js'
9
+ import { findCallSites, type BranchKind } from './branch-context.js'
10
+
11
+ /**
12
+ * The analyzer's structural verdict for a `@downstream` edge.
13
+ *
14
+ * - `step` — every located call site is linear; traversed at most once.
15
+ * - `branch` — at least one call site is reached through a loop, an iteration
16
+ * method, a Promise-combinator fan-out, or recursion.
17
+ * - `ambiguous` — no call site could be located. The edge is reached through
18
+ * indirection the analyzer does not follow (a bare callback, dynamic
19
+ * dispatch), so its cardinality must be declared by hand. See Q1.
20
+ */
21
+ export type StructuralCardinality = 'step' | 'branch' | 'ambiguous'
22
+
23
+ export interface EdgeClassification {
24
+ /** Source path of the flow step the edge is declared on, relative to `cwd`. */
25
+ readonly file: string
26
+ /** Name of the flow step the edge is declared on. */
27
+ readonly from: string
28
+ /** The declared edge, verbatim from the annotation. */
29
+ readonly edge: DownstreamEdge
30
+ /** The analyzer's structural verdict. */
31
+ readonly structural: StructuralCardinality
32
+ /** The branching construct, when `structural` is `branch`; otherwise `null`. */
33
+ readonly branchKind: BranchKind | null
34
+ /** 1-based file line of the call site driving the verdict; `null` when none was located. */
35
+ readonly line: number | null
36
+ }
37
+
38
+ /** Classifies one `@downstream` edge of `site` against the flow-step body. */
39
+ export function classifyEdge(
40
+ file: string,
41
+ site: FlowStepSite,
42
+ edge: DownstreamEdge,
43
+ ): EdgeClassification {
44
+ const from = site.subject.name
45
+ const base = { file, from, edge }
46
+
47
+ const body = site.subject.body
48
+ if (body === null) {
49
+ // An orphan annotation — no function body to walk. The `flow` check owns
50
+ // the diagnostic; here the edge is simply unresolvable.
51
+ return { ...base, structural: 'ambiguous', branchKind: null, line: null }
52
+ }
53
+
54
+ const sites = findCallSites(body, from, edge.symbol)
55
+ if (sites.length === 0) {
56
+ return { ...base, structural: 'ambiguous', branchKind: null, line: null }
57
+ }
58
+
59
+ const branching = sites.find(s => s.branchKind !== null)
60
+ if (branching !== undefined) {
61
+ return { ...base, structural: 'branch', branchKind: branching.branchKind, line: branching.line }
62
+ }
63
+ return { ...base, structural: 'step', branchKind: null, line: sites[0]!.line }
64
+ }
@@ -0,0 +1,107 @@
1
+ // The Q7 step-cap derivation. Once batching is forced to branch, a single
2
+ // trace's step count is bounded by the static flow graph: a `branch` edge
3
+ // opens a *child* trace, so only `step` edges extend the current one.
4
+ // `structuralMax` is the longest chain of `step` edges, counted in nodes.
5
+ //
6
+ // A cycle of `step` edges is unbounded — and a bug. A direct self-call is
7
+ // caught as recursion by branch-context, but *mutual* recursion (A step-calls
8
+ // B, B step-calls A) is invisible to single-function analysis; it surfaces
9
+ // here as a `step`-edge cycle. One of the edges that close the loop should
10
+ // have been a branch. See PLAN.tracing.md, Q7.
11
+
12
+ /** One `step` edge of the flow graph, both endpoints as `path:symbol` node ids. */
13
+ export interface StepEdge {
14
+ readonly from: string
15
+ readonly to: string
16
+ }
17
+
18
+ export interface StructuralMax {
19
+ /** Longest chain of `step` edges through the graph, counted in nodes. */
20
+ readonly value: number
21
+ /** Every `step`-edge cycle found — each a ring of `path:symbol` node ids. */
22
+ readonly cycles: readonly (readonly string[])[]
23
+ }
24
+
25
+ /** Longest `step`-edge chain across the flow graph, plus any `step`-edge cycles. */
26
+ export function computeStructuralMax(
27
+ nodeIds: readonly string[],
28
+ edges: readonly StepEdge[],
29
+ ): StructuralMax {
30
+ const adjacency = buildAdjacency(nodeIds, edges)
31
+ const longest = new Map<string, number>()
32
+ const visiting = new Set<string>()
33
+ const cycles: string[][] = []
34
+
35
+ function dfs(node: string, stack: string[]): number {
36
+ const cached = longest.get(node)
37
+ if (cached !== undefined) return cached
38
+ if (visiting.has(node)) {
39
+ // Back-edge: record the ring and treat this edge as contributing nothing,
40
+ // so the walk terminates. The node's own length is left uncached.
41
+ cycles.push([...stack.slice(stack.indexOf(node)), node])
42
+ return 0
43
+ }
44
+
45
+ visiting.add(node)
46
+ stack.push(node)
47
+ let best = 0
48
+ // `node` is always an adjacency key — it came from `keys()` or from a
49
+ // neighbour set, and `buildAdjacency` ensures every endpoint is a key.
50
+ for (const target of adjacency.get(node)!) {
51
+ best = Math.max(best, dfs(target, stack))
52
+ }
53
+ stack.pop()
54
+ visiting.delete(node)
55
+
56
+ const result = 1 + best
57
+ longest.set(node, result)
58
+ return result
59
+ }
60
+
61
+ let value = 0
62
+ for (const node of adjacency.keys()) {
63
+ value = Math.max(value, dfs(node, []))
64
+ }
65
+ return { value, cycles: dedupeCycles(cycles) }
66
+ }
67
+
68
+ /**
69
+ * The `step`-edge adjacency of the flow graph. Every analyzed flow step is a
70
+ * node; a `step` edge to a target that is not itself an analyzed flow step
71
+ * still adds that target as a terminal node, so the cap stays an upper bound.
72
+ */
73
+ function buildAdjacency(
74
+ nodeIds: readonly string[],
75
+ edges: readonly StepEdge[],
76
+ ): Map<string, Set<string>> {
77
+ const adjacency = new Map<string, Set<string>>()
78
+ const ensure = (id: string): Set<string> => {
79
+ let targets = adjacency.get(id)
80
+ if (targets === undefined) {
81
+ targets = new Set()
82
+ adjacency.set(id, targets)
83
+ }
84
+ return targets
85
+ }
86
+
87
+ for (const id of nodeIds) ensure(id)
88
+ for (const { from, to } of edges) {
89
+ ensure(to)
90
+ ensure(from).add(to)
91
+ }
92
+ return adjacency
93
+ }
94
+
95
+ /** Collapses rotations and re-discoveries of the same ring to one entry each. */
96
+ function dedupeCycles(cycles: readonly string[][]): string[][] {
97
+ const seen = new Map<string, string[]>()
98
+ for (const cycle of cycles) {
99
+ // Drop the repeated closing node, then rotate so the smallest id leads —
100
+ // a canonical form shared by every rotation and rediscovery of the ring.
101
+ const ring = cycle.slice(0, -1)
102
+ const pivot = ring.indexOf([...ring].sort()[0]!)
103
+ const canonical = [...ring.slice(pivot), ...ring.slice(0, pivot)]
104
+ seen.set(canonical.join(' '), canonical)
105
+ }
106
+ return [...seen.values()]
107
+ }