@starci/hfs 4.11.22 → 4.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1088) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +31 -31
  3. package/ci/cli.d.mts +15 -0
  4. package/ci/cli.mjs +71 -52
  5. package/ci/github.d.mts +43 -0
  6. package/ci/github.mjs +33 -28
  7. package/ci/local.d.mts +12 -0
  8. package/ci/local.mjs +145 -108
  9. package/ci/secret.d.mts +15 -0
  10. package/ci/secret.mjs +31 -21
  11. package/ci/vars.d.mts +17 -0
  12. package/ci/vars.mjs +47 -33
  13. package/ci/verify.d.mts +18 -0
  14. package/ci/verify.mjs +52 -40
  15. package/codemod/button-intent.d.mts +63 -0
  16. package/codemod/button-intent.mjs +338 -285
  17. package/coverage/cli.d.mts +28 -0
  18. package/coverage/cli.mjs +65 -51
  19. package/db/backup-receipt.d.mts +28 -0
  20. package/db/backup-receipt.mjs +78 -58
  21. package/db/drift.d.mts +86 -0
  22. package/db/drift.mjs +213 -180
  23. package/db/dump.d.mts +52 -0
  24. package/db/dump.mjs +63 -56
  25. package/db/entity-list.d.mts +4 -0
  26. package/db/entity-list.mjs +0 -2
  27. package/db/image.d.mts +8 -0
  28. package/db/image.mjs +1 -2
  29. package/db/migrate.d.mts +104 -0
  30. package/db/migrate.mjs +207 -167
  31. package/db/new.d.mts +11 -0
  32. package/db/new.mjs +25 -25
  33. package/db/post-cutover.d.mts +5 -0
  34. package/db/post-cutover.mjs +89 -82
  35. package/db/postgres.d.mts +71 -0
  36. package/db/postgres.mjs +62 -61
  37. package/emit/compiler.d.mts +3 -0
  38. package/emit/compiler.mjs +25 -27
  39. package/emit/contracts.d.mts +35 -0
  40. package/emit/contracts.mjs +46 -50
  41. package/emit/events.d.mts +9 -0
  42. package/emit/events.mjs +19 -20
  43. package/emit/form-bounds.d.mts +83 -0
  44. package/emit/form-bounds.mjs +133 -117
  45. package/emit/graphql-input-bounds.d.mts +63 -0
  46. package/emit/graphql-input-bounds.mjs +90 -79
  47. package/emit/input-bounds.d.mts +30 -0
  48. package/emit/input-bounds.mjs +29 -27
  49. package/emit/operation-schemas.d.mts +24 -0
  50. package/emit/operation-schemas.mjs +136 -116
  51. package/emit/operations-worker.d.mts +1 -0
  52. package/emit/operations-worker.mjs +9 -7
  53. package/emit/operations.d.mts +47 -0
  54. package/emit/operations.mjs +124 -133
  55. package/emit/schema-worker.d.mts +1 -0
  56. package/emit/schema-worker.mjs +57 -50
  57. package/emit/static-graph.d.mts +48 -0
  58. package/emit/static-graph.mjs +766 -640
  59. package/emit/type-schema.d.mts +29 -0
  60. package/emit/type-schema.mjs +153 -140
  61. package/lint/bound-sys.cjs +27 -33
  62. package/lint/chunk.d.mts +17 -0
  63. package/lint/chunk.mjs +41 -31
  64. package/lint/run.d.mts +120 -0
  65. package/lint/run.mjs +414 -325
  66. package/package.json +21 -4
  67. package/release/candidate-ci.d.mts +46 -0
  68. package/release/candidate-ci.mjs +76 -70
  69. package/release/gate.d.mts +120 -0
  70. package/release/gate.mjs +358 -330
  71. package/release/index.d.mts +68 -0
  72. package/release/index.mjs +95 -73
  73. package/release/lint-report.d.mts +14 -0
  74. package/release/lint-report.mjs +33 -32
  75. package/release/push.d.mts +32 -0
  76. package/release/push.mjs +92 -79
  77. package/release/records.d.mts +18 -0
  78. package/release/records.mjs +22 -21
  79. package/release/sonar-quality-gate.d.mts +18 -0
  80. package/release/sonar-quality-gate.mjs +60 -52
  81. package/release/urgent.d.mts +20 -0
  82. package/release/urgent.mjs +76 -74
  83. package/report/order.d.mts +1 -0
  84. package/report/sonar.d.mts +73 -0
  85. package/report/sonar.mjs +82 -89
  86. package/runtime/engine/admission.d.mts +209 -0
  87. package/runtime/engine/admission.mjs +225 -204
  88. package/runtime/engine/by-code-unit.d.mts +5 -0
  89. package/runtime/engine/by-code-unit.mjs +6 -6
  90. package/runtime/engine/config.d.mts +333 -0
  91. package/runtime/engine/config.mjs +486 -328
  92. package/runtime/engine/db/blob.d.mts +83 -0
  93. package/runtime/engine/db/blob.mjs +344 -268
  94. package/runtime/engine/db/event-compact.d.mts +21 -0
  95. package/runtime/engine/db/event-compact.mjs +34 -38
  96. package/runtime/engine/db/machine-connection.d.mts +68 -0
  97. package/runtime/engine/db/machine-connection.mjs +166 -119
  98. package/runtime/engine/db/machine-open.d.mts +26 -0
  99. package/runtime/engine/db/machine-open.mjs +59 -45
  100. package/runtime/engine/db/machine-schema.d.mts +34 -0
  101. package/runtime/engine/db/machine-schema.mjs +102 -83
  102. package/runtime/engine/db/machine.d.mts +1746 -0
  103. package/runtime/engine/db/machine.mjs +1040 -734
  104. package/runtime/engine/db/provider-reservations.d.mts +169 -0
  105. package/runtime/engine/db/provider-reservations.mjs +141 -119
  106. package/runtime/engine/db/provision-lock.d.mts +23 -0
  107. package/runtime/engine/db/provision-lock.mjs +14 -14
  108. package/runtime/engine/db/ref-value.d.mts +19 -0
  109. package/runtime/engine/db/ref-value.mjs +36 -35
  110. package/runtime/engine/db/sqlite-types.d.mts +28 -0
  111. package/runtime/engine/db/sqlite-types.mjs +4 -0
  112. package/runtime/engine/digest.d.mts +4 -0
  113. package/runtime/engine/digest.mjs +16 -7
  114. package/runtime/engine/invalid-config.d.mts +13 -0
  115. package/runtime/engine/invalid-config.mjs +17 -11
  116. package/runtime/engine/model-config.d.mts +91 -0
  117. package/runtime/engine/model-config.mjs +98 -76
  118. package/runtime/engine/orca-config.d.mts +26 -0
  119. package/runtime/engine/orca-config.mjs +22 -17
  120. package/runtime/engine/plain-object.d.mts +2 -0
  121. package/runtime/engine/refuse.d.mts +9 -0
  122. package/runtime/engine/refuse.mjs +3 -6
  123. package/runtime/engine/release-config.d.mts +19 -0
  124. package/runtime/engine/release-config.mjs +22 -18
  125. package/runtime/engine/removed-vocabulary.d.mts +12 -0
  126. package/runtime/engine/removed-vocabulary.mjs +21 -20
  127. package/runtime/engine/resources-config.d.mts +34 -0
  128. package/runtime/engine/resources-config.mjs +42 -35
  129. package/runtime/engine/runtime-root.d.mts +28 -0
  130. package/runtime/engine/runtime-root.mjs +11 -13
  131. package/runtime/engine/secrets.d.mts +41 -0
  132. package/runtime/engine/secrets.mjs +170 -102
  133. package/runtime/engine/sonar-config.d.mts +10 -0
  134. package/runtime/engine/sonar-config.mjs +16 -13
  135. package/runtime/engine/temp-root.d.mts +17 -0
  136. package/runtime/engine/temp-root.mjs +3 -9
  137. package/runtime/engine/yaml.d.mts +9 -0
  138. package/runtime/knowledge/hfs/canon-pins.yaml +10 -10
  139. package/runtime/knowledge/hfs/ci-standard.yaml +2 -2
  140. package/runtime/knowledge/hfs/rules.yaml +72 -6
  141. package/runtime/knowledge/hfs/slots.yaml +3 -3
  142. package/runtime/knowledge/sonar-gate.yaml +1 -1
  143. package/runtime/modules/kernel/failure-codes.yaml +43 -32
  144. package/runtime/modules/schemas/application-stacks.schema.yaml +3 -3
  145. package/runtime/packages/cli/src/catalog.generated.d.mts +13 -0
  146. package/runtime/packages/cli/src/catalog.generated.mjs +1853 -14824
  147. package/runtime/packages/cli/src/validate-args.d.mts +74 -0
  148. package/runtime/packages/cli/src/validate-args.mjs +183 -171
  149. package/runtime/packages/jest-preset/sonar-exclusions.cjs +5 -5
  150. package/runtime/scripts/api/fs/claim-file.d.mts +12 -0
  151. package/runtime/scripts/api/fs/claim-file.mjs +31 -17
  152. package/runtime/scripts/api/fs/ensure-temp-root.d.mts +4 -0
  153. package/runtime/scripts/api/fs/ensure-temp-root.mjs +15 -14
  154. package/runtime/scripts/api/fs/forbidden-root.d.mts +15 -0
  155. package/runtime/scripts/api/fs/forbidden-root.mjs +31 -23
  156. package/runtime/scripts/api/fs/is-link-like.d.mts +10 -0
  157. package/runtime/scripts/api/fs/is-link-like.mjs +25 -11
  158. package/runtime/scripts/api/fs/lib.d.mts +12 -0
  159. package/runtime/scripts/api/fs/lib.mjs +28 -8
  160. package/runtime/scripts/api/fs/make-temp-dir.d.mts +5 -0
  161. package/runtime/scripts/api/fs/make-temp-dir.mjs +3 -4
  162. package/runtime/scripts/api/fs/rename-over.d.mts +13 -0
  163. package/runtime/scripts/api/fs/rename-over.mjs +16 -10
  164. package/runtime/scripts/api/fs/safe-remove.d.mts +25 -0
  165. package/runtime/scripts/api/fs/safe-remove.mjs +129 -71
  166. package/runtime/scripts/api/git/add.d.mts +3 -0
  167. package/runtime/scripts/api/git/add.mjs +0 -1
  168. package/runtime/scripts/api/git/cat-file.d.mts +3 -0
  169. package/runtime/scripts/api/git/cat-file.mjs +0 -1
  170. package/runtime/scripts/api/git/check-ignore.d.mts +3 -0
  171. package/runtime/scripts/api/git/check-ignore.mjs +0 -1
  172. package/runtime/scripts/api/git/commit-tree.d.mts +3 -0
  173. package/runtime/scripts/api/git/commit-tree.mjs +0 -1
  174. package/runtime/scripts/api/git/config-get.d.mts +10 -0
  175. package/runtime/scripts/api/git/config-get.mjs +1 -2
  176. package/runtime/scripts/api/git/diff.d.mts +3 -0
  177. package/runtime/scripts/api/git/diff.mjs +0 -1
  178. package/runtime/scripts/api/git/init.d.mts +7 -0
  179. package/runtime/scripts/api/git/init.mjs +1 -2
  180. package/runtime/scripts/api/git/is-ancestor.d.mts +5 -0
  181. package/runtime/scripts/api/git/is-ancestor.mjs +0 -1
  182. package/runtime/scripts/api/git/lib.d.mts +67 -0
  183. package/runtime/scripts/api/git/lib.mjs +32 -32
  184. package/runtime/scripts/api/git/ls-files.d.mts +3 -0
  185. package/runtime/scripts/api/git/ls-files.mjs +0 -1
  186. package/runtime/scripts/api/git/ls-tree.d.mts +3 -0
  187. package/runtime/scripts/api/git/ls-tree.mjs +0 -1
  188. package/runtime/scripts/api/git/merge-base.d.mts +5 -0
  189. package/runtime/scripts/api/git/merge-base.mjs +2 -3
  190. package/runtime/scripts/api/git/remote.d.mts +3 -0
  191. package/runtime/scripts/api/git/remote.mjs +0 -1
  192. package/runtime/scripts/api/git/rev-parse-query.d.mts +3 -0
  193. package/runtime/scripts/api/git/rev-parse-query.mjs +0 -1
  194. package/runtime/scripts/api/git/show.d.mts +3 -0
  195. package/runtime/scripts/api/git/show.mjs +0 -1
  196. package/runtime/scripts/api/git/tag.d.mts +3 -0
  197. package/runtime/scripts/api/git/tag.mjs +0 -1
  198. package/runtime/scripts/api/git/update-ref.d.mts +7 -0
  199. package/runtime/scripts/api/git/update-ref.mjs +1 -2
  200. package/runtime/scripts/api/git/write-tree.d.mts +3 -0
  201. package/runtime/scripts/api/git/write-tree.mjs +0 -1
  202. package/runtime/scripts/api/node/lib.d.mts +7 -0
  203. package/runtime/scripts/api/node/lib.mjs +17 -7
  204. package/runtime/scripts/api/node/run-node.d.mts +3 -0
  205. package/runtime/scripts/api/node/run-node.mjs +0 -3
  206. package/runtime/scripts/api/process/resolve-real-tool.d.mts +12 -0
  207. package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -38
  208. package/runtime/scripts/api/process/run-program.d.mts +3 -0
  209. package/runtime/scripts/api/process/run-program.mjs +5 -2
  210. package/runtime/scripts/api/sops/decrypt.d.mts +9 -0
  211. package/runtime/scripts/api/sops/decrypt.mjs +1 -2
  212. package/runtime/scripts/api/sops/lib.d.mts +149 -0
  213. package/runtime/scripts/api/sops/lib.mjs +417 -318
  214. package/runtime/scripts/api/sops/resolve-sops.d.mts +3 -0
  215. package/runtime/scripts/api/sops/resolve-sops.mjs +1 -2
  216. package/runtime/scripts/api/sops/seal.d.mts +19 -0
  217. package/runtime/scripts/api/sops/seal.mjs +14 -10
  218. package/runtime/scripts/api/sops/selected-age-recipient.d.mts +3 -0
  219. package/runtime/scripts/api/sops/selected-age-recipient.mjs +1 -2
  220. package/runtime/scripts/api/sops/update-keys.d.mts +16 -0
  221. package/runtime/scripts/api/sops/update-keys.mjs +11 -8
  222. package/runtime/scripts/cli/gen-catalog.d.mts +42 -0
  223. package/runtime/scripts/cli/gen-catalog.mjs +72 -0
  224. package/runtime/scripts/gates/runtime-host.d.mts +23 -0
  225. package/runtime/scripts/gates/runtime-host.mjs +48 -41
  226. package/runtime/scripts/gates/sonar-gate.d.mts +219 -0
  227. package/runtime/scripts/gates/sonar-gate.mjs +166 -153
  228. package/runtime/scripts/gates/starcistacks-ci.d.mts +35 -0
  229. package/runtime/scripts/gates/starcistacks-ci.mjs +47 -39
  230. package/runtime/scripts/gates/starcistacks-form.d.mts +80 -0
  231. package/runtime/scripts/gates/starcistacks-form.mjs +16 -14
  232. package/runtime/scripts/gates/starcistacks-runtime.d.mts +1 -0
  233. package/runtime/scripts/gates/starcistacks-value-file.d.mts +2 -0
  234. package/runtime/scripts/gates/starcistacks-value-file.mjs +14 -11
  235. package/runtime/scripts/gates/starcistacks.d.mts +141 -0
  236. package/runtime/scripts/gates/starcistacks.mjs +470 -355
  237. package/runtime/scripts/guards/git-pathspec.d.mts +48 -0
  238. package/runtime/scripts/guards/git-pathspec.mjs +215 -130
  239. package/runtime/scripts/guards/git-policy.d.mts +30 -0
  240. package/runtime/scripts/guards/git-policy.mjs +278 -235
  241. package/runtime/scripts/guards/hook-io.d.mts +22 -0
  242. package/runtime/scripts/guards/hook-io.mjs +77 -63
  243. package/runtime/scripts/guards/push-scan.d.mts +31 -0
  244. package/runtime/scripts/guards/push-scan.mjs +93 -80
  245. package/runtime/scripts/guards/release-push-gate.d.mts +22 -0
  246. package/runtime/scripts/guards/release-push-gate.mjs +40 -38
  247. package/runtime/scripts/hfs/allows.d.mts +24 -0
  248. package/runtime/scripts/hfs/allows.mjs +37 -38
  249. package/runtime/scripts/hfs/app-wiring.d.mts +72 -0
  250. package/runtime/scripts/hfs/app-wiring.mjs +197 -167
  251. package/runtime/scripts/hfs/architecture/ast-walks.d.mts +89 -0
  252. package/runtime/scripts/hfs/architecture/ast-walks.mjs +180 -163
  253. package/runtime/scripts/hfs/architecture/automatic-gates.d.mts +21 -0
  254. package/runtime/scripts/hfs/architecture/automatic-gates.mjs +80 -73
  255. package/runtime/scripts/hfs/architecture/backend-app-files.d.mts +10 -0
  256. package/runtime/scripts/hfs/architecture/backend-app-files.mjs +88 -77
  257. package/runtime/scripts/hfs/architecture/backend.d.mts +5 -0
  258. package/runtime/scripts/hfs/architecture/backend.mjs +378 -357
  259. package/runtime/scripts/hfs/architecture/background-unowned.d.mts +25 -0
  260. package/runtime/scripts/hfs/architecture/background-unowned.mjs +201 -187
  261. package/runtime/scripts/hfs/architecture/canon-clones.d.mts +8 -0
  262. package/runtime/scripts/hfs/architecture/canon-clones.mjs +260 -209
  263. package/runtime/scripts/hfs/architecture/canon-jsx-clones.d.mts +5 -0
  264. package/runtime/scripts/hfs/architecture/canon-jsx-clones.mjs +149 -116
  265. package/runtime/scripts/hfs/architecture/client-reaches-server.d.mts +28 -0
  266. package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +72 -68
  267. package/runtime/scripts/hfs/architecture/clones.d.mts +54 -0
  268. package/runtime/scripts/hfs/architecture/clones.mjs +212 -217
  269. package/runtime/scripts/hfs/architecture/config-unread.d.mts +14 -0
  270. package/runtime/scripts/hfs/architecture/config-unread.mjs +7 -9
  271. package/runtime/scripts/hfs/architecture/config.d.mts +74 -0
  272. package/runtime/scripts/hfs/architecture/config.mjs +302 -268
  273. package/runtime/scripts/hfs/architecture/connection-map.d.mts +33 -0
  274. package/runtime/scripts/hfs/architecture/connection-map.mjs +258 -225
  275. package/runtime/scripts/hfs/architecture/constructor-deps.d.mts +57 -0
  276. package/runtime/scripts/hfs/architecture/constructor-deps.mjs +80 -71
  277. package/runtime/scripts/hfs/architecture/context-coupling.d.mts +21 -0
  278. package/runtime/scripts/hfs/architecture/context-coupling.mjs +82 -77
  279. package/runtime/scripts/hfs/architecture/context-map.d.mts +102 -0
  280. package/runtime/scripts/hfs/architecture/context-map.mjs +267 -234
  281. package/runtime/scripts/hfs/architecture/context-owner.d.mts +15 -0
  282. package/runtime/scripts/hfs/architecture/context-owner.mjs +73 -61
  283. package/runtime/scripts/hfs/architecture/context-platform-tables.d.mts +18 -0
  284. package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -43
  285. package/runtime/scripts/hfs/architecture/context-transaction.d.mts +20 -0
  286. package/runtime/scripts/hfs/architecture/context-transaction.mjs +54 -52
  287. package/runtime/scripts/hfs/architecture/contract-fixture-guard.d.mts +37 -0
  288. package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +113 -104
  289. package/runtime/scripts/hfs/architecture/contracts-readonly.d.mts +32 -0
  290. package/runtime/scripts/hfs/architecture/contracts-readonly.mjs +288 -270
  291. package/runtime/scripts/hfs/architecture/contracts.d.mts +30 -0
  292. package/runtime/scripts/hfs/architecture/contracts.mjs +408 -393
  293. package/runtime/scripts/hfs/architecture/cross-app-duplicate.d.mts +27 -0
  294. package/runtime/scripts/hfs/architecture/cross-app-duplicate.mjs +50 -51
  295. package/runtime/scripts/hfs/architecture/dead-exports-bindings.d.mts +21 -0
  296. package/runtime/scripts/hfs/architecture/dead-exports-bindings.mjs +143 -119
  297. package/runtime/scripts/hfs/architecture/dead-exports.d.mts +32 -0
  298. package/runtime/scripts/hfs/architecture/dead-exports.mjs +286 -228
  299. package/runtime/scripts/hfs/architecture/default-deny.d.mts +21 -0
  300. package/runtime/scripts/hfs/architecture/default-deny.mjs +129 -110
  301. package/runtime/scripts/hfs/architecture/doc-language.d.mts +17 -0
  302. package/runtime/scripts/hfs/architecture/doc-language.mjs +24 -19
  303. package/runtime/scripts/hfs/architecture/entity-registry.d.mts +49 -0
  304. package/runtime/scripts/hfs/architecture/entity-registry.mjs +20 -22
  305. package/runtime/scripts/hfs/architecture/entrypoint.d.mts +13 -0
  306. package/runtime/scripts/hfs/architecture/entrypoint.mjs +47 -45
  307. package/runtime/scripts/hfs/architecture/error-codes.d.mts +16 -0
  308. package/runtime/scripts/hfs/architecture/error-codes.mjs +37 -35
  309. package/runtime/scripts/hfs/architecture/error-masked.d.mts +16 -0
  310. package/runtime/scripts/hfs/architecture/error-masked.mjs +55 -59
  311. package/runtime/scripts/hfs/architecture/fe-slot-allows.d.mts +38 -0
  312. package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +24 -23
  313. package/runtime/scripts/hfs/architecture/feature-shape.d.mts +26 -0
  314. package/runtime/scripts/hfs/architecture/feature-shape.mjs +40 -38
  315. package/runtime/scripts/hfs/architecture/framework-pinned.d.mts +3 -0
  316. package/runtime/scripts/hfs/architecture/framework-pinned.mjs +21 -21
  317. package/runtime/scripts/hfs/architecture/frontend-block-render.d.mts +26 -0
  318. package/runtime/scripts/hfs/architecture/frontend-block-render.mjs +106 -98
  319. package/runtime/scripts/hfs/architecture/frontend-grammar.d.mts +7 -0
  320. package/runtime/scripts/hfs/architecture/frontend-grammar.mjs +153 -150
  321. package/runtime/scripts/hfs/architecture/frontend-routing.d.mts +23 -0
  322. package/runtime/scripts/hfs/architecture/frontend-routing.mjs +161 -149
  323. package/runtime/scripts/hfs/architecture/frontend-world-render.d.mts +72 -0
  324. package/runtime/scripts/hfs/architecture/frontend-world-render.mjs +343 -305
  325. package/runtime/scripts/hfs/architecture/frontend-world.d.mts +94 -0
  326. package/runtime/scripts/hfs/architecture/frontend-world.mjs +340 -294
  327. package/runtime/scripts/hfs/architecture/frontend.d.mts +31 -0
  328. package/runtime/scripts/hfs/architecture/frontend.mjs +174 -184
  329. package/runtime/scripts/hfs/architecture/function-spec-providers.d.mts +27 -0
  330. package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +124 -106
  331. package/runtime/scripts/hfs/architecture/hfs-graph.d.mts +78 -0
  332. package/runtime/scripts/hfs/architecture/hfs-graph.mjs +52 -48
  333. package/runtime/scripts/hfs/architecture/hfs.d.mts +135 -0
  334. package/runtime/scripts/hfs/architecture/hfs.mjs +328 -282
  335. package/runtime/scripts/hfs/architecture/hooks-are-hooks.d.mts +24 -0
  336. package/runtime/scripts/hfs/architecture/hooks-are-hooks.mjs +81 -71
  337. package/runtime/scripts/hfs/architecture/i18n-keys.d.mts +31 -0
  338. package/runtime/scripts/hfs/architecture/i18n-keys.mjs +155 -141
  339. package/runtime/scripts/hfs/architecture/identity.d.mts +7 -0
  340. package/runtime/scripts/hfs/architecture/identity.mjs +141 -125
  341. package/runtime/scripts/hfs/architecture/index.d.mts +101 -0
  342. package/runtime/scripts/hfs/architecture/index.mjs +272 -272
  343. package/runtime/scripts/hfs/architecture/injection-token-exported.d.mts +21 -0
  344. package/runtime/scripts/hfs/architecture/injection-token-exported.mjs +45 -43
  345. package/runtime/scripts/hfs/architecture/jwt-ast.d.mts +16 -0
  346. package/runtime/scripts/hfs/architecture/jwt-ast.mjs +195 -176
  347. package/runtime/scripts/hfs/architecture/machine-ast.d.mts +88 -0
  348. package/runtime/scripts/hfs/architecture/machine-ast.mjs +163 -155
  349. package/runtime/scripts/hfs/architecture/managed-scripts.d.mts +2 -0
  350. package/runtime/scripts/hfs/architecture/managed-scripts.mjs +19 -20
  351. package/runtime/scripts/hfs/architecture/module-per-transport.d.mts +35 -0
  352. package/runtime/scripts/hfs/architecture/module-per-transport.mjs +177 -172
  353. package/runtime/scripts/hfs/architecture/next-data-contract.d.mts +35 -0
  354. package/runtime/scripts/hfs/architecture/next-data-contract.mjs +100 -78
  355. package/runtime/scripts/hfs/architecture/next-data-inference.d.mts +39 -0
  356. package/runtime/scripts/hfs/architecture/next-data-inference.mjs +170 -154
  357. package/runtime/scripts/hfs/architecture/next-data-key.d.mts +50 -0
  358. package/runtime/scripts/hfs/architecture/next-data-key.mjs +311 -275
  359. package/runtime/scripts/hfs/architecture/next-data-symbols.d.mts +5 -0
  360. package/runtime/scripts/hfs/architecture/next-data-symbols.mjs +17 -17
  361. package/runtime/scripts/hfs/architecture/next-data.d.mts +36 -0
  362. package/runtime/scripts/hfs/architecture/next-data.mjs +351 -334
  363. package/runtime/scripts/hfs/architecture/operation-contract-roots.d.mts +10 -0
  364. package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +39 -37
  365. package/runtime/scripts/hfs/architecture/owners.d.mts +5 -0
  366. package/runtime/scripts/hfs/architecture/owners.mjs +97 -98
  367. package/runtime/scripts/hfs/architecture/package-shape.d.mts +26 -0
  368. package/runtime/scripts/hfs/architecture/package-shape.mjs +56 -55
  369. package/runtime/scripts/hfs/architecture/presentation.d.mts +24 -0
  370. package/runtime/scripts/hfs/architecture/presentation.mjs +138 -130
  371. package/runtime/scripts/hfs/architecture/reachability.d.mts +25 -0
  372. package/runtime/scripts/hfs/architecture/reachability.mjs +258 -241
  373. package/runtime/scripts/hfs/architecture/register-once.d.mts +18 -0
  374. package/runtime/scripts/hfs/architecture/register-once.mjs +152 -139
  375. package/runtime/scripts/hfs/architecture/registration.d.mts +15 -0
  376. package/runtime/scripts/hfs/architecture/registration.mjs +301 -267
  377. package/runtime/scripts/hfs/architecture/required-files.d.mts +64 -0
  378. package/runtime/scripts/hfs/architecture/required-files.mjs +172 -167
  379. package/runtime/scripts/hfs/architecture/route-files-thin.d.mts +23 -0
  380. package/runtime/scripts/hfs/architecture/route-files-thin.mjs +85 -77
  381. package/runtime/scripts/hfs/architecture/schema-owner.d.mts +34 -0
  382. package/runtime/scripts/hfs/architecture/schema-owner.mjs +206 -181
  383. package/runtime/scripts/hfs/architecture/server-action.d.mts +22 -0
  384. package/runtime/scripts/hfs/architecture/server-action.mjs +48 -48
  385. package/runtime/scripts/hfs/architecture/side-boundary.d.mts +3 -0
  386. package/runtime/scripts/hfs/architecture/side-boundary.mjs +2 -5
  387. package/runtime/scripts/hfs/architecture/source-names-shape.d.mts +85 -0
  388. package/runtime/scripts/hfs/architecture/source-names-shape.mjs +261 -259
  389. package/runtime/scripts/hfs/architecture/source-names.d.mts +7 -0
  390. package/runtime/scripts/hfs/architecture/source-names.mjs +304 -278
  391. package/runtime/scripts/hfs/architecture/sql-keys.d.mts +5 -0
  392. package/runtime/scripts/hfs/architecture/sql-keys.mjs +277 -194
  393. package/runtime/scripts/hfs/architecture/sql-owner.d.mts +30 -0
  394. package/runtime/scripts/hfs/architecture/sql-owner.mjs +236 -194
  395. package/runtime/scripts/hfs/architecture/sql-returning.d.mts +22 -0
  396. package/runtime/scripts/hfs/architecture/sql-returning.mjs +46 -45
  397. package/runtime/scripts/hfs/architecture/sql-token-forms.d.mts +21 -0
  398. package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +86 -74
  399. package/runtime/scripts/hfs/architecture/sql-tokens.d.mts +32 -0
  400. package/runtime/scripts/hfs/architecture/sql-tokens.mjs +456 -341
  401. package/runtime/scripts/hfs/architecture/staged-consumers.d.mts +7 -0
  402. package/runtime/scripts/hfs/architecture/staged-consumers.mjs +35 -30
  403. package/runtime/scripts/hfs/architecture/surface.d.mts +26 -0
  404. package/runtime/scripts/hfs/architecture/surface.mjs +64 -74
  405. package/runtime/scripts/hfs/architecture/symbols.d.mts +11 -0
  406. package/runtime/scripts/hfs/architecture/symbols.mjs +209 -216
  407. package/runtime/scripts/hfs/architecture/test-world-files.d.mts +45 -0
  408. package/runtime/scripts/hfs/architecture/test-world-files.mjs +165 -155
  409. package/runtime/scripts/hfs/architecture/tiers.d.mts +29 -0
  410. package/runtime/scripts/hfs/architecture/tiers.mjs +161 -154
  411. package/runtime/scripts/hfs/architecture/transport-owner.d.mts +37 -0
  412. package/runtime/scripts/hfs/architecture/transport-owner.mjs +155 -149
  413. package/runtime/scripts/hfs/architecture/type-context.d.mts +60 -0
  414. package/runtime/scripts/hfs/architecture/type-context.mjs +255 -250
  415. package/runtime/scripts/hfs/architecture/typescript.d.mts +94 -0
  416. package/runtime/scripts/hfs/architecture/typescript.mjs +358 -318
  417. package/runtime/scripts/hfs/architecture/unit-spec-providers.d.mts +34 -0
  418. package/runtime/scripts/hfs/architecture/unit-spec-providers.mjs +110 -92
  419. package/runtime/scripts/hfs/architecture.d.mts +13 -0
  420. package/runtime/scripts/hfs/architecture.mjs +39 -29
  421. package/runtime/scripts/hfs/canon-pins.d.mts +26 -0
  422. package/runtime/scripts/hfs/canon-pins.mjs +5 -8
  423. package/runtime/scripts/hfs/catalog-once.d.mts +2 -0
  424. package/runtime/scripts/hfs/catalog-once.mjs +8 -9
  425. package/runtime/scripts/hfs/check-results.d.mts +29 -0
  426. package/runtime/scripts/hfs/check-results.mjs +14 -18
  427. package/runtime/scripts/hfs/check.d.mts +144 -0
  428. package/runtime/scripts/hfs/check.mjs +309 -329
  429. package/runtime/scripts/hfs/ci-declaration.d.mts +77 -0
  430. package/runtime/scripts/hfs/ci-declaration.mjs +99 -87
  431. package/runtime/scripts/hfs/coverage-from.d.mts +22 -0
  432. package/runtime/scripts/hfs/coverage-from.mjs +52 -49
  433. package/runtime/scripts/hfs/coverage-scope.d.mts +87 -0
  434. package/runtime/scripts/hfs/coverage-scope.mjs +139 -142
  435. package/runtime/scripts/hfs/db-baseline-verb.d.mts +84 -0
  436. package/runtime/scripts/hfs/db-baseline-verb.mjs +327 -266
  437. package/runtime/scripts/hfs/db-errors.d.mts +2 -0
  438. package/runtime/scripts/hfs/db-errors.mjs +2 -1
  439. package/runtime/scripts/hfs/db-plan-verb.d.mts +33 -0
  440. package/runtime/scripts/hfs/db-plan-verb.mjs +174 -128
  441. package/runtime/scripts/hfs/db-restamp-verb.d.mts +5 -0
  442. package/runtime/scripts/hfs/db-restamp-verb.mjs +94 -70
  443. package/runtime/scripts/hfs/db-squash.d.mts +117 -0
  444. package/runtime/scripts/hfs/db-squash.mjs +414 -351
  445. package/runtime/scripts/hfs/declaration-shape.d.mts +3 -0
  446. package/runtime/scripts/hfs/declaration-shape.mjs +140 -103
  447. package/runtime/scripts/hfs/declaration-slots.d.mts +18 -0
  448. package/runtime/scripts/hfs/declaration-slots.mjs +64 -61
  449. package/runtime/scripts/hfs/doc-commands.d.mts +71 -0
  450. package/runtime/scripts/hfs/doc-commands.mjs +257 -250
  451. package/runtime/scripts/hfs/edition-slots.d.mts +37 -0
  452. package/runtime/scripts/hfs/edition-slots.mjs +43 -40
  453. package/runtime/scripts/hfs/example-secrets.d.mts +18 -0
  454. package/runtime/scripts/hfs/example-secrets.mjs +173 -154
  455. package/runtime/scripts/hfs/gate-threshold.d.mts +20 -0
  456. package/runtime/scripts/hfs/gate-threshold.mjs +14 -22
  457. package/runtime/scripts/hfs/grammar-presentation.d.mts +74 -0
  458. package/runtime/scripts/hfs/grammar-presentation.mjs +109 -106
  459. package/runtime/scripts/hfs/linear-text.d.mts +6 -0
  460. package/runtime/scripts/hfs/linear-text.mjs +20 -20
  461. package/runtime/scripts/hfs/manifest-shape.d.mts +216 -0
  462. package/runtime/scripts/hfs/manifest-shape.mjs +399 -324
  463. package/runtime/scripts/hfs/param-names.d.mts +3 -0
  464. package/runtime/scripts/hfs/param-names.mjs +6 -11
  465. package/runtime/scripts/hfs/path-findings.d.mts +22 -0
  466. package/runtime/scripts/hfs/path-findings.mjs +120 -100
  467. package/runtime/scripts/hfs/pin-findings.d.mts +19 -0
  468. package/runtime/scripts/hfs/pin-findings.mjs +26 -21
  469. package/runtime/scripts/hfs/refusal-codes.d.mts +1 -0
  470. package/runtime/scripts/hfs/refusal-codes.mjs +2 -2
  471. package/runtime/scripts/hfs/repo-identity.d.mts +15 -0
  472. package/runtime/scripts/hfs/repo-identity.mjs +55 -42
  473. package/runtime/scripts/hfs/rule-catalog.d.mts +77 -0
  474. package/runtime/scripts/hfs/rule-catalog.mjs +353 -257
  475. package/runtime/scripts/hfs/rule-params-shape.d.mts +10 -0
  476. package/runtime/scripts/hfs/rule-params-shape.mjs +60 -47
  477. package/runtime/scripts/hfs/rules/a15-findings.d.mts +18 -0
  478. package/runtime/scripts/hfs/rules/a15-findings.mjs +59 -55
  479. package/runtime/scripts/hfs/rules/app-env-required.d.mts +9 -0
  480. package/runtime/scripts/hfs/rules/app-env-required.mjs +13 -13
  481. package/runtime/scripts/hfs/rules/app-root.d.mts +15 -0
  482. package/runtime/scripts/hfs/rules/app-root.mjs +20 -21
  483. package/runtime/scripts/hfs/rules/app-workflow-findings.d.mts +12 -0
  484. package/runtime/scripts/hfs/rules/app-workflow-findings.mjs +4 -4
  485. package/runtime/scripts/hfs/rules/assets.d.mts +13 -0
  486. package/runtime/scripts/hfs/rules/assets.mjs +58 -46
  487. package/runtime/scripts/hfs/rules/boot-proof.d.mts +11 -0
  488. package/runtime/scripts/hfs/rules/boot-proof.mjs +7 -8
  489. package/runtime/scripts/hfs/rules/bypass-markers.d.mts +9 -0
  490. package/runtime/scripts/hfs/rules/bypass-markers.mjs +7 -12
  491. package/runtime/scripts/hfs/rules/canon-copy-drift.d.mts +10 -0
  492. package/runtime/scripts/hfs/rules/canon-copy-drift.mjs +70 -68
  493. package/runtime/scripts/hfs/rules/ci-custody.d.mts +7 -0
  494. package/runtime/scripts/hfs/rules/ci-custody.mjs +72 -73
  495. package/runtime/scripts/hfs/rules/ci-standard.d.mts +12 -0
  496. package/runtime/scripts/hfs/rules/ci-standard.mjs +149 -142
  497. package/runtime/scripts/hfs/rules/cli.d.mts +7 -0
  498. package/runtime/scripts/hfs/rules/cli.mjs +24 -23
  499. package/runtime/scripts/hfs/rules/contract-compat.d.mts +11 -0
  500. package/runtime/scripts/hfs/rules/contract-compat.mjs +64 -53
  501. package/runtime/scripts/hfs/rules/contract.d.mts +26 -0
  502. package/runtime/scripts/hfs/rules/contract.mjs +126 -111
  503. package/runtime/scripts/hfs/rules/coverage-below.d.mts +17 -0
  504. package/runtime/scripts/hfs/rules/coverage-below.mjs +200 -167
  505. package/runtime/scripts/hfs/rules/database-access.d.mts +12 -0
  506. package/runtime/scripts/hfs/rules/database-access.mjs +231 -202
  507. package/runtime/scripts/hfs/rules/database-baseline.d.mts +22 -0
  508. package/runtime/scripts/hfs/rules/database-baseline.mjs +104 -104
  509. package/runtime/scripts/hfs/rules/database-config.d.mts +11 -0
  510. package/runtime/scripts/hfs/rules/database-config.mjs +101 -135
  511. package/runtime/scripts/hfs/rules/database-constants.d.mts +36 -0
  512. package/runtime/scripts/hfs/rules/database-constants.mjs +7 -7
  513. package/runtime/scripts/hfs/rules/database-migrations.d.mts +41 -0
  514. package/runtime/scripts/hfs/rules/database-migrations.mjs +428 -388
  515. package/runtime/scripts/hfs/rules/database-plpgsql.d.mts +5 -0
  516. package/runtime/scripts/hfs/rules/database-plpgsql.mjs +278 -259
  517. package/runtime/scripts/hfs/rules/database-queue-sources.d.mts +4 -0
  518. package/runtime/scripts/hfs/rules/database-queue-sources.mjs +48 -43
  519. package/runtime/scripts/hfs/rules/database-queues.d.mts +15 -0
  520. package/runtime/scripts/hfs/rules/database-queues.mjs +211 -182
  521. package/runtime/scripts/hfs/rules/database-sql.d.mts +16 -0
  522. package/runtime/scripts/hfs/rules/database-sql.mjs +394 -394
  523. package/runtime/scripts/hfs/rules/database-transaction.d.mts +3 -0
  524. package/runtime/scripts/hfs/rules/database-transaction.mjs +25 -27
  525. package/runtime/scripts/hfs/rules/database.d.mts +22 -0
  526. package/runtime/scripts/hfs/rules/database.mjs +42 -58
  527. package/runtime/scripts/hfs/rules/deploy-scan.d.mts +10 -0
  528. package/runtime/scripts/hfs/rules/deploy-scan.mjs +177 -168
  529. package/runtime/scripts/hfs/rules/deploy-workflow.d.mts +3 -0
  530. package/runtime/scripts/hfs/rules/deploy-workflow.mjs +194 -171
  531. package/runtime/scripts/hfs/rules/deps.d.mts +6 -0
  532. package/runtime/scripts/hfs/rules/deps.mjs +61 -60
  533. package/runtime/scripts/hfs/rules/doc-fresh.d.mts +11 -0
  534. package/runtime/scripts/hfs/rules/doc-fresh.mjs +242 -223
  535. package/runtime/scripts/hfs/rules/docker-health.d.mts +9 -0
  536. package/runtime/scripts/hfs/rules/docker-health.mjs +222 -196
  537. package/runtime/scripts/hfs/rules/docker.d.mts +13 -0
  538. package/runtime/scripts/hfs/rules/docker.mjs +234 -208
  539. package/runtime/scripts/hfs/rules/edition.d.mts +18 -0
  540. package/runtime/scripts/hfs/rules/edition.mjs +103 -101
  541. package/runtime/scripts/hfs/rules/env-parity.d.mts +25 -0
  542. package/runtime/scripts/hfs/rules/env-parity.mjs +278 -252
  543. package/runtime/scripts/hfs/rules/env-value-shape.d.mts +21 -0
  544. package/runtime/scripts/hfs/rules/env-value-shape.mjs +82 -67
  545. package/runtime/scripts/hfs/rules/event-bus.d.mts +17 -0
  546. package/runtime/scripts/hfs/rules/event-bus.mjs +145 -133
  547. package/runtime/scripts/hfs/rules/event-tables.d.mts +7 -0
  548. package/runtime/scripts/hfs/rules/event-tables.mjs +77 -75
  549. package/runtime/scripts/hfs/rules/fe-build-args.d.mts +10 -0
  550. package/runtime/scripts/hfs/rules/fe-build-args.mjs +116 -99
  551. package/runtime/scripts/hfs/rules/fe-contract-documents.d.mts +7 -0
  552. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +121 -111
  553. package/runtime/scripts/hfs/rules/fe-no-tests.d.mts +9 -0
  554. package/runtime/scripts/hfs/rules/fe-no-tests.mjs +37 -36
  555. package/runtime/scripts/hfs/rules/fe-stack.d.mts +23 -0
  556. package/runtime/scripts/hfs/rules/fe-stack.mjs +108 -105
  557. package/runtime/scripts/hfs/rules/feature-files.d.mts +10 -0
  558. package/runtime/scripts/hfs/rules/feature-files.mjs +14 -19
  559. package/runtime/scripts/hfs/rules/frontend-tree.d.mts +18 -0
  560. package/runtime/scripts/hfs/rules/frontend-tree.mjs +105 -91
  561. package/runtime/scripts/hfs/rules/integration-specs.d.mts +7 -0
  562. package/runtime/scripts/hfs/rules/integration-specs.mjs +190 -177
  563. package/runtime/scripts/hfs/rules/kinds.d.mts +6 -0
  564. package/runtime/scripts/hfs/rules/kinds.mjs +88 -81
  565. package/runtime/scripts/hfs/rules/lexicon.d.mts +9 -0
  566. package/runtime/scripts/hfs/rules/lexicon.mjs +43 -40
  567. package/runtime/scripts/hfs/rules/lint-suppression.d.mts +5 -0
  568. package/runtime/scripts/hfs/rules/lint-suppression.mjs +22 -20
  569. package/runtime/scripts/hfs/rules/lite-proof-lane.d.mts +9 -0
  570. package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +59 -58
  571. package/runtime/scripts/hfs/rules/lite-secrets.d.mts +12 -0
  572. package/runtime/scripts/hfs/rules/lite-secrets.mjs +60 -63
  573. package/runtime/scripts/hfs/rules/mcp-tools.d.mts +7 -0
  574. package/runtime/scripts/hfs/rules/mcp-tools.mjs +56 -41
  575. package/runtime/scripts/hfs/rules/monorepo.d.mts +17 -0
  576. package/runtime/scripts/hfs/rules/monorepo.mjs +153 -138
  577. package/runtime/scripts/hfs/rules/peer-integrations.d.mts +7 -0
  578. package/runtime/scripts/hfs/rules/peer-integrations.mjs +39 -36
  579. package/runtime/scripts/hfs/rules/pipeline.d.mts +7 -0
  580. package/runtime/scripts/hfs/rules/pipeline.mjs +53 -53
  581. package/runtime/scripts/hfs/rules/proof-commands.d.mts +14 -0
  582. package/runtime/scripts/hfs/rules/proof-commands.mjs +52 -41
  583. package/runtime/scripts/hfs/rules/read.d.mts +7 -0
  584. package/runtime/scripts/hfs/rules/read.mjs +19 -15
  585. package/runtime/scripts/hfs/rules/release-provenance.d.mts +12 -0
  586. package/runtime/scripts/hfs/rules/release-provenance.mjs +196 -159
  587. package/runtime/scripts/hfs/rules/repo-local-checks.d.mts +5 -0
  588. package/runtime/scripts/hfs/rules/repo-local-checks.mjs +19 -17
  589. package/runtime/scripts/hfs/rules/rule-types.d.mts +40 -0
  590. package/runtime/scripts/hfs/rules/rule-types.mjs +4 -0
  591. package/runtime/scripts/hfs/rules/saga-delivery.d.mts +2 -0
  592. package/runtime/scripts/hfs/rules/saga-delivery.mjs +58 -50
  593. package/runtime/scripts/hfs/rules/saga.d.mts +7 -0
  594. package/runtime/scripts/hfs/rules/saga.mjs +151 -145
  595. package/runtime/scripts/hfs/rules/script-hygiene.d.mts +11 -0
  596. package/runtime/scripts/hfs/rules/script-hygiene.mjs +112 -95
  597. package/runtime/scripts/hfs/rules/secret-custody-only.d.mts +7 -0
  598. package/runtime/scripts/hfs/rules/secret-custody-only.mjs +29 -35
  599. package/runtime/scripts/hfs/rules/secrets.d.mts +29 -0
  600. package/runtime/scripts/hfs/rules/secrets.mjs +45 -44
  601. package/runtime/scripts/hfs/rules/services.d.mts +7 -0
  602. package/runtime/scripts/hfs/rules/services.mjs +148 -148
  603. package/runtime/scripts/hfs/rules/spec-placement.d.mts +8 -0
  604. package/runtime/scripts/hfs/rules/spec-placement.mjs +12 -13
  605. package/runtime/scripts/hfs/rules/stack-tooling.d.mts +11 -0
  606. package/runtime/scripts/hfs/rules/stack-tooling.mjs +45 -52
  607. package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.d.mts +30 -0
  608. package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.mjs +149 -0
  609. package/runtime/scripts/hfs/rules/stacks-deploy.d.mts +7 -0
  610. package/runtime/scripts/hfs/rules/stacks-deploy.mjs +32 -42
  611. package/runtime/scripts/hfs/rules/stacks-ingress.d.mts +16 -0
  612. package/runtime/scripts/hfs/rules/stacks-ingress.mjs +62 -64
  613. package/runtime/scripts/hfs/rules/stacks-lite-backing.d.mts +17 -0
  614. package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +111 -116
  615. package/runtime/scripts/hfs/rules/stacks-release.d.mts +26 -0
  616. package/runtime/scripts/hfs/rules/stacks-release.mjs +335 -309
  617. package/runtime/scripts/hfs/rules/stacks-runtime.d.mts +31 -0
  618. package/runtime/scripts/hfs/rules/stacks-runtime.mjs +130 -124
  619. package/runtime/scripts/hfs/rules/stacks-swarm.d.mts +5 -0
  620. package/runtime/scripts/hfs/rules/stacks-swarm.mjs +366 -344
  621. package/runtime/scripts/hfs/rules/stacks.d.mts +7 -0
  622. package/runtime/scripts/hfs/rules/stacks.mjs +37 -38
  623. package/runtime/scripts/hfs/rules/staged-specs.d.mts +10 -0
  624. package/runtime/scripts/hfs/rules/staged-specs.mjs +14 -18
  625. package/runtime/scripts/hfs/rules/supply-chain.d.mts +10 -0
  626. package/runtime/scripts/hfs/rules/supply-chain.mjs +143 -150
  627. package/runtime/scripts/hfs/rules/test-topology.d.mts +5 -0
  628. package/runtime/scripts/hfs/rules/test-topology.mjs +23 -21
  629. package/runtime/scripts/hfs/rules/text-integrity.d.mts +9 -0
  630. package/runtime/scripts/hfs/rules/text-integrity.mjs +47 -43
  631. package/runtime/scripts/hfs/rules/unused-symbol-flow.d.mts +22 -0
  632. package/runtime/scripts/hfs/rules/unused-symbol-flow.mjs +226 -204
  633. package/runtime/scripts/hfs/rules/unused-symbol-ledger.d.mts +7 -0
  634. package/runtime/scripts/hfs/rules/unused-symbol-ledger.mjs +70 -49
  635. package/runtime/scripts/hfs/rules/unused-symbol-properties.d.mts +12 -0
  636. package/runtime/scripts/hfs/rules/unused-symbol-properties.mjs +141 -126
  637. package/runtime/scripts/hfs/rules/unused-symbol-translators.d.mts +8 -0
  638. package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +160 -140
  639. package/runtime/scripts/hfs/rules/unused-symbol-values.d.mts +9 -0
  640. package/runtime/scripts/hfs/rules/unused-symbol-values.mjs +138 -125
  641. package/runtime/scripts/hfs/rules/unused-symbol.d.mts +11 -0
  642. package/runtime/scripts/hfs/rules/unused-symbol.mjs +283 -253
  643. package/runtime/scripts/hfs/rules/workflow-contexts.d.mts +8 -0
  644. package/runtime/scripts/hfs/rules/workflow-contexts.mjs +79 -67
  645. package/runtime/scripts/hfs/runtime-rules/git-triggers.d.mts +6 -0
  646. package/runtime/scripts/hfs/runtime-rules/git-triggers.mjs +36 -35
  647. package/runtime/scripts/hfs/runtime-rules/hook-shape.d.mts +10 -0
  648. package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +45 -42
  649. package/runtime/scripts/hfs/runtime-rules/source-ast.d.mts +39 -0
  650. package/runtime/scripts/hfs/runtime-rules/source-ast.mjs +130 -116
  651. package/runtime/scripts/hfs/runtime-rules/workflow-source.d.mts +5 -0
  652. package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +8 -7
  653. package/runtime/scripts/hfs/sealed-members.d.mts +22 -0
  654. package/runtime/scripts/hfs/sealed-members.mjs +79 -75
  655. package/runtime/scripts/hfs/secret-bootstrap-crypto.d.mts +12 -0
  656. package/runtime/scripts/hfs/secret-bootstrap-crypto.mjs +151 -167
  657. package/runtime/scripts/hfs/secret-document.d.mts +16 -0
  658. package/runtime/scripts/hfs/secret-document.mjs +59 -75
  659. package/runtime/scripts/hfs/secret-edit.d.mts +14 -0
  660. package/runtime/scripts/hfs/secret-edit.mjs +115 -135
  661. package/runtime/scripts/hfs/secret-errors.d.mts +4 -0
  662. package/runtime/scripts/hfs/secret-errors.mjs +19 -16
  663. package/runtime/scripts/hfs/secret-files.d.mts +20 -0
  664. package/runtime/scripts/hfs/secret-files.mjs +103 -112
  665. package/runtime/scripts/hfs/secret-init.d.mts +108 -0
  666. package/runtime/scripts/hfs/secret-init.mjs +304 -346
  667. package/runtime/scripts/hfs/secret-output.d.mts +18 -0
  668. package/runtime/scripts/hfs/secret-output.mjs +52 -80
  669. package/runtime/scripts/hfs/secret-prompt.d.mts +39 -0
  670. package/runtime/scripts/hfs/secret-prompt.mjs +108 -93
  671. package/runtime/scripts/hfs/secret-sops.d.mts +29 -0
  672. package/runtime/scripts/hfs/secret-sops.mjs +161 -199
  673. package/runtime/scripts/hfs/secret-standard.d.mts +89 -0
  674. package/runtime/scripts/hfs/secret-standard.mjs +300 -264
  675. package/runtime/scripts/hfs/secret-store.d.mts +36 -0
  676. package/runtime/scripts/hfs/secret-store.mjs +120 -136
  677. package/runtime/scripts/hfs/secret.d.mts +40 -0
  678. package/runtime/scripts/hfs/secret.mjs +254 -222
  679. package/runtime/scripts/hfs/slot-app-view.d.mts +11 -0
  680. package/runtime/scripts/hfs/slot-app-view.mjs +69 -74
  681. package/runtime/scripts/hfs/slot-classify.d.mts +75 -0
  682. package/runtime/scripts/hfs/slot-classify.mjs +42 -38
  683. package/runtime/scripts/hfs/slot-errors.d.mts +6 -0
  684. package/runtime/scripts/hfs/slot-errors.mjs +8 -7
  685. package/runtime/scripts/hfs/slot-imports.d.mts +8 -0
  686. package/runtime/scripts/hfs/slot-imports.mjs +70 -63
  687. package/runtime/scripts/hfs/slot-manifest-shape.d.mts +9 -0
  688. package/runtime/scripts/hfs/slot-manifest-shape.mjs +74 -52
  689. package/runtime/scripts/hfs/slot-match.d.mts +50 -0
  690. package/runtime/scripts/hfs/slot-match.mjs +122 -111
  691. package/runtime/scripts/hfs/slot-path.d.mts +1 -0
  692. package/runtime/scripts/hfs/slot-path.mjs +0 -2
  693. package/runtime/scripts/hfs/slot-required.d.mts +11 -0
  694. package/runtime/scripts/hfs/slot-required.mjs +65 -59
  695. package/runtime/scripts/hfs/slot-semantic-problems.d.mts +9 -0
  696. package/runtime/scripts/hfs/slot-semantic-problems.mjs +138 -112
  697. package/runtime/scripts/hfs/slot-side-problems.d.mts +3 -0
  698. package/runtime/scripts/hfs/slot-side-problems.mjs +23 -19
  699. package/runtime/scripts/hfs/slots.d.mts +188 -0
  700. package/runtime/scripts/hfs/slots.mjs +175 -152
  701. package/runtime/scripts/hfs/sql/pg-parse.d.mts +9 -0
  702. package/runtime/scripts/hfs/sql/pg-parse.mjs +25 -25
  703. package/runtime/scripts/hfs/stack-config-kit.d.mts +22 -0
  704. package/runtime/scripts/hfs/stack-config-kit.mjs +21 -17
  705. package/runtime/scripts/hfs/stack-deploy-config.d.mts +155 -0
  706. package/runtime/scripts/hfs/stack-deploy-config.mjs +345 -273
  707. package/runtime/scripts/hfs/stack-ingress-config.d.mts +74 -0
  708. package/runtime/scripts/hfs/stack-ingress-config.mjs +211 -177
  709. package/runtime/scripts/hfs/stacks-gate.d.mts +52 -0
  710. package/runtime/scripts/hfs/stacks-gate.mjs +557 -397
  711. package/runtime/scripts/hfs/starcistacks-runtime.d.mts +7 -0
  712. package/runtime/scripts/hfs/starcistacks-runtime.mjs +51 -40
  713. package/runtime/scripts/hfs/test-world-slot.d.mts +2 -0
  714. package/runtime/scripts/hfs/test-world-slot.mjs +0 -1
  715. package/runtime/scripts/hfs/trailing-slashes.d.mts +2 -0
  716. package/runtime/scripts/hfs/trailing-slashes.mjs +4 -4
  717. package/runtime/scripts/hfs/tree-findings.d.mts +9 -0
  718. package/runtime/scripts/hfs/tree-findings.mjs +18 -17
  719. package/runtime/scripts/hfs/tree.d.mts +35 -0
  720. package/runtime/scripts/hfs/tree.mjs +56 -46
  721. package/runtime/scripts/hfs/typescript-programs.d.mts +36 -0
  722. package/runtime/scripts/hfs/typescript-programs.mjs +66 -69
  723. package/runtime/scripts/hfs/view.d.mts +45 -0
  724. package/runtime/scripts/hfs/view.mjs +38 -40
  725. package/runtime/scripts/lib/bypass-markers.d.mts +15 -0
  726. package/runtime/scripts/lib/bypass-markers.mjs +210 -197
  727. package/runtime/scripts/lib/cli-arg.d.mts +67 -0
  728. package/runtime/scripts/lib/cli-arg.mjs +59 -63
  729. package/runtime/scripts/lib/command-tokens.d.mts +11 -0
  730. package/runtime/scripts/lib/command-tokens.mjs +77 -78
  731. package/runtime/scripts/lib/compose-values.d.mts +6 -0
  732. package/runtime/scripts/lib/compose-values.mjs +7 -7
  733. package/runtime/scripts/lib/css-rules.d.mts +36 -0
  734. package/runtime/scripts/lib/css-rules.mjs +181 -171
  735. package/runtime/scripts/lib/deployment-findings.d.mts +9 -0
  736. package/runtime/scripts/lib/deployment-findings.mjs +4 -4
  737. package/runtime/scripts/lib/dockerfile.d.mts +39 -0
  738. package/runtime/scripts/lib/dockerfile.mjs +131 -114
  739. package/runtime/scripts/lib/dom-tree.d.mts +7 -0
  740. package/runtime/scripts/lib/dom-tree.mjs +3 -3
  741. package/runtime/scripts/lib/env.d.mts +12 -0
  742. package/runtime/scripts/lib/env.mjs +3 -6
  743. package/runtime/scripts/lib/escape.d.mts +6 -0
  744. package/runtime/scripts/lib/escape.mjs +2 -6
  745. package/runtime/scripts/lib/event-contract.d.mts +21 -0
  746. package/runtime/scripts/lib/event-contract.mjs +73 -78
  747. package/runtime/scripts/lib/event-items.d.mts +20 -0
  748. package/runtime/scripts/lib/event-items.mjs +27 -15
  749. package/runtime/scripts/lib/example-refs.d.mts +69 -0
  750. package/runtime/scripts/lib/example-refs.mjs +145 -129
  751. package/runtime/scripts/lib/fs-kind.d.mts +12 -0
  752. package/runtime/scripts/lib/fs-kind.mjs +20 -10
  753. package/runtime/scripts/lib/git-hooks-dir.d.mts +15 -0
  754. package/runtime/scripts/lib/git-hooks-dir.mjs +16 -16
  755. package/runtime/scripts/lib/git.d.mts +24 -0
  756. package/runtime/scripts/lib/git.mjs +15 -16
  757. package/runtime/scripts/lib/glob.d.mts +4 -0
  758. package/runtime/scripts/lib/glob.mjs +23 -14
  759. package/runtime/scripts/lib/grammar-lint.d.mts +47 -0
  760. package/runtime/scripts/lib/grammar-lint.mjs +33 -37
  761. package/runtime/scripts/lib/grammar-vendor-parity-jsx.d.mts +40 -0
  762. package/runtime/scripts/lib/grammar-vendor-parity-jsx.mjs +285 -266
  763. package/runtime/scripts/lib/grammar-vendor-parity.d.mts +61 -0
  764. package/runtime/scripts/lib/grammar-vendor-parity.mjs +209 -216
  765. package/runtime/scripts/lib/graphql-contract.d.mts +53 -0
  766. package/runtime/scripts/lib/graphql-contract.mjs +201 -198
  767. package/runtime/scripts/lib/graphql-sdl.d.mts +66 -0
  768. package/runtime/scripts/lib/graphql-sdl.mjs +230 -205
  769. package/runtime/scripts/lib/hook-limits.d.mts +11 -0
  770. package/runtime/scripts/lib/hook-limits.mjs +0 -1
  771. package/runtime/scripts/lib/i18n.d.mts +48 -0
  772. package/runtime/scripts/lib/i18n.mjs +32 -35
  773. package/runtime/scripts/lib/in-order.d.mts +12 -0
  774. package/runtime/scripts/lib/in-order.mjs +57 -38
  775. package/runtime/scripts/lib/is-main.d.mts +6 -0
  776. package/runtime/scripts/lib/is-main.mjs +11 -4
  777. package/runtime/scripts/lib/js-lex.d.mts +32 -0
  778. package/runtime/scripts/lib/js-lex.mjs +196 -162
  779. package/runtime/scripts/lib/json-clone.d.mts +11 -0
  780. package/runtime/scripts/lib/json-clone.mjs +45 -36
  781. package/runtime/scripts/lib/json-schema.d.mts +2 -0
  782. package/runtime/scripts/lib/json-schema.mjs +127 -90
  783. package/runtime/scripts/lib/json.d.mts +16 -0
  784. package/runtime/scripts/lib/json.mjs +26 -14
  785. package/runtime/scripts/lib/language.d.mts +44 -0
  786. package/runtime/scripts/lib/language.mjs +133 -129
  787. package/runtime/scripts/lib/list.d.mts +17 -0
  788. package/runtime/scripts/lib/list.mjs +9 -14
  789. package/runtime/scripts/lib/loosening-budgets.d.mts +12 -0
  790. package/runtime/scripts/lib/loosening-budgets.mjs +35 -29
  791. package/runtime/scripts/lib/loosening-config.d.mts +64 -0
  792. package/runtime/scripts/lib/loosening-config.mjs +267 -236
  793. package/runtime/scripts/lib/loosening-state.d.mts +77 -0
  794. package/runtime/scripts/lib/loosening-state.mjs +134 -128
  795. package/runtime/scripts/lib/mutation-fence.d.mts +11 -0
  796. package/runtime/scripts/lib/mutation-fence.mjs +10 -5
  797. package/runtime/scripts/lib/normalize.d.mts +12 -0
  798. package/runtime/scripts/lib/normalize.mjs +11 -11
  799. package/runtime/scripts/lib/numeric-match.d.mts +2 -0
  800. package/runtime/scripts/lib/numeric-match.mjs +2 -2
  801. package/runtime/scripts/lib/package-at.d.mts +24 -0
  802. package/runtime/scripts/lib/package-at.mjs +34 -31
  803. package/runtime/scripts/lib/path-key.d.mts +76 -0
  804. package/runtime/scripts/lib/path-key.mjs +53 -38
  805. package/runtime/scripts/lib/pid-alive.d.mts +2 -0
  806. package/runtime/scripts/lib/pid-alive.mjs +10 -3
  807. package/runtime/scripts/lib/properties.d.mts +2 -0
  808. package/runtime/scripts/lib/properties.mjs +17 -11
  809. package/runtime/scripts/lib/provision-operation-schema.d.mts +4 -0
  810. package/runtime/scripts/lib/provision-operation-schema.mjs +4 -5
  811. package/runtime/scripts/lib/read-text.d.mts +12 -0
  812. package/runtime/scripts/lib/read-text.mjs +30 -17
  813. package/runtime/scripts/lib/redact.d.mts +52 -0
  814. package/runtime/scripts/lib/redact.mjs +135 -121
  815. package/runtime/scripts/lib/regex.d.mts +2 -0
  816. package/runtime/scripts/lib/regex.mjs +1 -2
  817. package/runtime/scripts/lib/roots.d.mts +32 -0
  818. package/runtime/scripts/lib/roots.mjs +5 -15
  819. package/runtime/scripts/lib/runtime-example.d.mts +1 -0
  820. package/runtime/scripts/lib/runtime-example.mjs +10 -8
  821. package/runtime/scripts/lib/same-text.d.mts +2 -0
  822. package/runtime/scripts/lib/same-text.mjs +0 -1
  823. package/runtime/scripts/lib/sealed-member.d.mts +16 -0
  824. package/runtime/scripts/lib/sealed-member.mjs +8 -13
  825. package/runtime/scripts/lib/secret-patterns.d.mts +30 -0
  826. package/runtime/scripts/lib/secret-patterns.mjs +175 -163
  827. package/runtime/scripts/lib/shell-source.d.mts +2 -0
  828. package/runtime/scripts/lib/shell-source.mjs +0 -1
  829. package/runtime/scripts/lib/sleep-sync.d.mts +2 -0
  830. package/runtime/scripts/lib/sleep-sync.mjs +5 -6
  831. package/runtime/scripts/lib/sops-envelope.d.mts +34 -0
  832. package/runtime/scripts/lib/sops-envelope.mjs +148 -120
  833. package/runtime/scripts/lib/source-phrases.d.mts +4 -0
  834. package/runtime/scripts/lib/source-phrases.mjs +13 -13
  835. package/runtime/scripts/lib/sql-ast.d.mts +13 -0
  836. package/runtime/scripts/lib/sql-ast.mjs +19 -18
  837. package/runtime/scripts/lib/sqlite.d.mts +21 -0
  838. package/runtime/scripts/lib/sqlite.mjs +3 -9
  839. package/runtime/scripts/lib/stack-declaration.d.mts +51 -0
  840. package/runtime/scripts/lib/stack-declaration.mjs +27 -20
  841. package/runtime/scripts/lib/stack-services.d.mts +73 -0
  842. package/runtime/scripts/lib/stack-services.mjs +128 -129
  843. package/runtime/scripts/lib/starciwork-boundary.d.mts +10 -0
  844. package/runtime/scripts/lib/starciwork-boundary.mjs +98 -92
  845. package/runtime/scripts/lib/swarm-stack.d.mts +24 -0
  846. package/runtime/scripts/lib/swarm-stack.mjs +112 -100
  847. package/runtime/scripts/lib/trim-end.d.mts +2 -0
  848. package/runtime/scripts/lib/trim-end.mjs +4 -4
  849. package/runtime/scripts/lib/ts-analysis.d.mts +24 -0
  850. package/runtime/scripts/lib/ts-analysis.mjs +28 -26
  851. package/runtime/scripts/lib/ts-ast.d.mts +36 -0
  852. package/runtime/scripts/lib/ts-ast.mjs +36 -42
  853. package/runtime/scripts/lib/walk.d.mts +19 -0
  854. package/runtime/scripts/lib/walk.mjs +33 -27
  855. package/runtime/scripts/lib/work-edition.d.mts +10 -0
  856. package/runtime/scripts/lib/work-edition.mjs +29 -21
  857. package/runtime/scripts/lib/workflow-events.d.mts +2 -0
  858. package/runtime/scripts/lib/workflow-events.mjs +5 -4
  859. package/runtime/scripts/lib/worktree-exclude.d.mts +16 -0
  860. package/runtime/scripts/lib/worktree-exclude.mjs +6 -8
  861. package/runtime/scripts/lib/yaml-cached.d.mts +2 -0
  862. package/runtime/scripts/lib/yaml-cached.mjs +4 -4
  863. package/runtime/scripts/machine/artifact-hold.d.mts +26 -0
  864. package/runtime/scripts/machine/artifact-hold.mjs +22 -23
  865. package/runtime/scripts/work/asset-slot.d.mts +96 -0
  866. package/runtime/scripts/work/asset-slot.mjs +201 -175
  867. package/runtime/scripts/work/draw/draw-dna-anatomy.d.mts +30 -0
  868. package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +40 -36
  869. package/runtime/scripts/work/draw/draw-dna-findings.d.mts +12 -0
  870. package/runtime/scripts/work/draw/draw-dna-findings.mjs +240 -206
  871. package/runtime/scripts/work/draw/draw-dna-selector.d.mts +7 -0
  872. package/runtime/scripts/work/draw/draw-dna-selector.mjs +28 -28
  873. package/runtime/scripts/work/draw/draw-dna.d.mts +191 -0
  874. package/runtime/scripts/work/draw/draw-dna.mjs +283 -249
  875. package/runtime/scripts/work/grammar-proposal.d.mts +83 -0
  876. package/runtime/scripts/work/grammar-proposal.mjs +215 -178
  877. package/runtime/scripts/work/work-io.d.mts +62 -0
  878. package/runtime/scripts/work/work-io.mjs +82 -63
  879. package/scaffold/add-app.d.mts +15 -0
  880. package/scaffold/add-app.mjs +111 -163
  881. package/scaffold/add-cli-lite.d.mts +8 -0
  882. package/scaffold/add-cli-lite.mjs +173 -207
  883. package/scaffold/add-compose.d.mts +44 -0
  884. package/scaffold/add-compose.mjs +62 -62
  885. package/scaffold/add-database-lite.d.mts +2 -0
  886. package/scaffold/add-database-lite.mjs +10 -10
  887. package/scaffold/add-fe-layout.d.mts +16 -0
  888. package/scaffold/add-fe-layout.mjs +23 -23
  889. package/scaffold/add-fe-overlay.d.mts +17 -0
  890. package/scaffold/add-fe-overlay.mjs +76 -78
  891. package/scaffold/add-fe-page.d.mts +41 -0
  892. package/scaffold/add-fe-page.mjs +84 -89
  893. package/scaffold/add-fe-unit.d.mts +59 -0
  894. package/scaffold/add-fe-unit.mjs +205 -197
  895. package/scaffold/add-inbox-lite.d.mts +17 -0
  896. package/scaffold/add-inbox-lite.mjs +209 -264
  897. package/scaffold/add-plan.d.mts +68 -0
  898. package/scaffold/add-plan.mjs +164 -149
  899. package/scaffold/add-queue-lite.d.mts +34 -0
  900. package/scaffold/add-queue-lite.mjs +267 -267
  901. package/scaffold/add-table.d.mts +16 -0
  902. package/scaffold/add-table.mjs +405 -442
  903. package/scaffold/add.d.mts +34 -0
  904. package/scaffold/add.mjs +260 -246
  905. package/scaffold/app.d.mts +198 -0
  906. package/scaffold/app.mjs +413 -391
  907. package/scaffold/edition-gate.d.mts +49 -0
  908. package/scaffold/edition-gate.mjs +19 -29
  909. package/scaffold/image.d.mts +4 -0
  910. package/scaffold/image.mjs +12 -12
  911. package/scaffold/lite-exports.d.mts +15 -0
  912. package/scaffold/lite-exports.mjs +262 -255
  913. package/scaffold/pattern-file-slots.d.mts +7 -0
  914. package/scaffold/pattern-file-slots.mjs +29 -24
  915. package/scaffold/service.d.mts +60 -0
  916. package/scaffold/service.mjs +297 -279
  917. package/scaffold/test-world.d.mts +31 -0
  918. package/scaffold/test-world.mjs +71 -78
  919. package/scaffold/yaml-block-edit.d.mts +23 -0
  920. package/scaffold/yaml-block-edit.mjs +95 -87
  921. package/scripts/sync-bundles.d.mts +31 -0
  922. package/src/fixtures/bypass-index.d.mts +4 -0
  923. package/src/fixtures/hfs-stack-tooling/passing.d.mts +8 -0
  924. package/src/fixtures/hfs-stack-tooling/violating.d.mts +19 -0
  925. package/src/fixtures/hfs-stacks-full/model-unavailable.d.mts +10 -0
  926. package/src/fixtures/hfs-stacks-full/passing.d.mts +19 -0
  927. package/src/fixtures/hfs-stacks-full/violating.d.mts +10 -0
  928. package/src/fixtures/loosening/adversarial.d.mts +4 -0
  929. package/src/fixtures/loosening/forms.d.mts +16 -0
  930. package/src/fixtures/loosening/swallows.d.mts +5 -0
  931. package/src/helpers/hfs-arch-fixture.d.mts +47 -0
  932. package/src/helpers/hfs-cli-fixture.d.mts +65 -0
  933. package/src/helpers/hfs-hfs-docker-rules-fixture.d.mts +5 -0
  934. package/src/helpers/hfs-secret-fixture.d.mts +19 -0
  935. package/src/helpers/pre-push-fixture.d.mts +21 -0
  936. package/src/helpers/stack-compose.d.mts +6 -0
  937. package/src/helpers/swarm-stack-fixture.d.mts +18 -0
  938. package/src/helpers/tmpdir.d.mts +2 -0
  939. package/src/main.d.mts +58 -0
  940. package/src/main.mjs +493 -348
  941. package/stack/age-install.d.mts +13 -0
  942. package/stack/age-install.mjs +28 -25
  943. package/stack/backup.d.mts +11 -0
  944. package/stack/backup.mjs +76 -69
  945. package/stack/build-args.d.mts +7 -0
  946. package/stack/build-args.mjs +22 -23
  947. package/stack/build.d.mts +8 -0
  948. package/stack/build.mjs +138 -119
  949. package/stack/cli.d.mts +55 -0
  950. package/stack/cli.mjs +187 -130
  951. package/stack/config.d.mts +197 -0
  952. package/stack/config.mjs +47 -33
  953. package/stack/context.d.mts +122 -0
  954. package/stack/context.mjs +63 -65
  955. package/stack/converge.d.mts +13 -0
  956. package/stack/converge.mjs +73 -69
  957. package/stack/deploy.d.mts +88 -0
  958. package/stack/deploy.mjs +272 -224
  959. package/stack/digest.d.mts +8 -0
  960. package/stack/digest.mjs +1 -6
  961. package/stack/docker-transport.d.mts +5 -0
  962. package/stack/docker-transport.mjs +101 -93
  963. package/stack/edge-alias.d.mts +42 -0
  964. package/stack/edge-alias.mjs +62 -60
  965. package/stack/errors.d.mts +18 -0
  966. package/stack/errors.mjs +8 -10
  967. package/stack/image-scan.d.mts +20 -0
  968. package/stack/image-scan.mjs +114 -101
  969. package/stack/ingress-create.d.mts +4 -0
  970. package/stack/ingress-create.mjs +82 -86
  971. package/stack/ingress-publish.d.mts +6 -0
  972. package/stack/ingress-publish.mjs +194 -182
  973. package/stack/ingress.d.mts +55 -0
  974. package/stack/ingress.mjs +534 -524
  975. package/stack/jobs.d.mts +12 -0
  976. package/stack/jobs.mjs +35 -34
  977. package/stack/live-restore.d.mts +35 -0
  978. package/stack/live-restore.mjs +120 -125
  979. package/stack/post-deploy.d.mts +8 -0
  980. package/stack/post-deploy.mjs +25 -25
  981. package/stack/prepare.d.mts +24 -0
  982. package/stack/prepare.mjs +213 -200
  983. package/stack/private-file.d.mts +5 -0
  984. package/stack/private-file.mjs +9 -9
  985. package/stack/provision.d.mts +25 -0
  986. package/stack/provision.mjs +64 -63
  987. package/stack/prune.d.mts +11 -0
  988. package/stack/prune.mjs +38 -27
  989. package/stack/release-store.d.mts +28 -0
  990. package/stack/release-store.mjs +68 -67
  991. package/stack/remote.d.mts +83 -0
  992. package/stack/remote.mjs +176 -162
  993. package/stack/render.d.mts +14 -0
  994. package/stack/render.mjs +132 -124
  995. package/stack/retire.d.mts +9 -0
  996. package/stack/retire.mjs +31 -34
  997. package/stack/sealed.d.mts +46 -0
  998. package/stack/sealed.mjs +78 -82
  999. package/stack/server-key.d.mts +67 -0
  1000. package/stack/server-key.mjs +217 -203
  1001. package/stack/ssh-session.d.mts +29 -0
  1002. package/stack/ssh-session.mjs +133 -123
  1003. package/stack/target-binding.d.mts +21 -0
  1004. package/stack/target-binding.mjs +68 -44
  1005. package/stack/task.d.mts +12 -0
  1006. package/stack/task.mjs +26 -31
  1007. package/stack/urgent-floor.d.mts +106 -0
  1008. package/stack/urgent-floor.mjs +211 -160
  1009. package/stack/urgent-release.d.mts +38 -0
  1010. package/stack/urgent-release.mjs +26 -22
  1011. package/stack/verify.d.mts +14 -0
  1012. package/stack/verify.mjs +75 -65
  1013. package/sync/ci-commands.d.mts +26 -0
  1014. package/sync/ci-commands.mjs +181 -182
  1015. package/sync/cli.d.mts +8 -0
  1016. package/sync/cli.mjs +9 -9
  1017. package/sync/format.d.mts +38 -0
  1018. package/sync/format.mjs +30 -24
  1019. package/sync/hygiene.d.mts +23 -0
  1020. package/sync/hygiene.mjs +113 -99
  1021. package/sync/index.d.mts +237 -0
  1022. package/sync/index.mjs +457 -436
  1023. package/sync/managed.d.mts +23 -0
  1024. package/sync/managed.mjs +104 -94
  1025. package/sync/quality-services.d.mts +35 -0
  1026. package/sync/quality-services.mjs +48 -41
  1027. package/sync/readme-badges.d.mts +13 -0
  1028. package/sync/readme-badges.mjs +45 -44
  1029. package/sync/sonar-key.d.mts +31 -0
  1030. package/sync/sonar-key.mjs +29 -28
  1031. package/sync/stack-images.d.mts +36 -0
  1032. package/sync/stack-images.mjs +85 -95
  1033. package/sync/ts-strict.d.mts +14 -0
  1034. package/sync/ts-strict.mjs +43 -34
  1035. package/templates/app/ci-workflows/github/workflows/ci.yml +1 -1
  1036. package/templates/app/ci-workflows/github/workflows/images.yml +1 -1
  1037. package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +2 -2
  1038. package/templates/app/ci-workflows/github/workflows/stack-key-restore.yml +1 -1
  1039. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +1 -1
  1040. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +3 -3
  1041. package/templates/app/ci-workflows-lite/github/workflows/images.yml +1 -1
  1042. package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +2 -2
  1043. package/templates/app/ci-workflows-lite/github/workflows/stack-key-restore.yml +1 -1
  1044. package/templates/app/codegen-lite/scripts/codegen.mjs +1 -1
  1045. package/templates/app/db-bootstrap/db/bootstrap.sql +1 -1
  1046. package/templates/app/db-image/starcistacks/images/db/Dockerfile +1 -1
  1047. package/templates/app/hooks/husky/pre-commit +2 -2
  1048. package/templates/app/package-scripts/db.json +3 -3
  1049. package/templates/app/package-scripts/package.json +1 -1
  1050. package/templates/app/quality-config/sonar-project.properties +1 -1
  1051. package/templates/app/skeleton/.starcistacks/application-stacks.yaml +2 -2
  1052. package/templates/app/skeleton/.starcistacks/production/README.md +4 -4
  1053. package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +8 -3
  1054. package/templates/app/skeleton/README.md +1 -1
  1055. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +2 -2
  1056. package/templates/app/skeleton-lite/.starcistacks/dev/README.md +1 -1
  1057. package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +6 -2
  1058. package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +3 -2
  1059. package/templates/app/skeleton-lite/.starcistacks/production/README.md +5 -5
  1060. package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +7 -2
  1061. package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +3 -2
  1062. package/templates/app/skeleton-lite/README.md +2 -2
  1063. package/templates/be/skeleton/apps/cli/src/compose/platform.ts +1 -1
  1064. package/templates/be/skeleton/apps/cli/src/main.ts +6 -4
  1065. package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +12 -0
  1066. package/templates/be/skeleton/src/modules/platform/database/abstract.entity.ts +19 -0
  1067. package/templates/be/skeleton/src/modules/platform/database/database.module.ts +7 -1
  1068. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +19 -0
  1069. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +4 -3
  1070. package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +1 -1
  1071. package/templates/be/skeleton/src/modules/platform/logging/logging.options.ts +5 -2
  1072. package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +1 -1
  1073. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.spec.ts +40 -0
  1074. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.ts +1 -0
  1075. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.spec.ts +48 -1
  1076. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.ts +5 -0
  1077. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.options.ts +5 -0
  1078. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/google.strategy.ts +1 -1
  1079. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/oauth-state.store.ts +7 -3
  1080. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +7 -1
  1081. package/templates/be/table/entity.ts.tpl +4 -15
  1082. package/upgrade/check.d.mts +9 -0
  1083. package/upgrade/check.mjs +8 -8
  1084. package/upgrade/file-state.d.mts +6 -0
  1085. package/upgrade/file-state.mjs +32 -40
  1086. package/upgrade/index.d.mts +13 -0
  1087. package/upgrade/index.mjs +122 -151
  1088. package/vendor-types.d.mts +8 -0
@@ -13,135 +13,136 @@ import { fileURLToPath } from 'node:url';
13
13
  import { loadTypescript } from '../../lib/package-at.mjs';
14
14
  import { isConstVariable } from '../../lib/ts-ast.mjs';
15
15
  import { lexicalChecker, unwrapExpression } from '../../lib/ts-analysis.mjs';
16
-
17
16
  const HERE = path.dirname(fileURLToPath(import.meta.url));
18
17
  const MIGRATION_PLAIN = /[a-z0-9]+(?:-[a-z0-9]+)*/;
19
18
  const MIGRATION_CONTRACT_TAIL = /contract_[a-z0-9]+(?:[-_][a-z0-9]+)*/;
20
19
  const MIGRATION_SLUG = [MIGRATION_PLAIN.source, MIGRATION_CONTRACT_TAIL.source, `${MIGRATION_PLAIN.source}_${MIGRATION_CONTRACT_TAIL.source}`].join('|');
21
- const MIGRATION_NAME = new RegExp(String.raw`^(\d{14})_(${MIGRATION_SLUG})\.sql$`);
20
+ const MIGRATION_NAME = new RegExp(String.raw `^(\d{14})_(${MIGRATION_SLUG})\.sql$`);
22
21
  export const isMigrationName = (name) => MIGRATION_NAME.test(name);
23
22
  const RESTAMP_HEADER = /^-- starci:restamp (\d{14}) (\d{14})(?:\r?\n|$)/;
24
23
  const withoutRestampHeader = (text) => text?.replace(RESTAMP_HEADER, '') ?? null;
25
-
26
24
  /** `<ts14>` -> the UTC instant it names, or null when the digits are no real time (month 13, day 32, ...). */
27
25
  export function migrationStamp(text) {
28
- const [year, month, day, hour, minute, second] = [Number(text.slice(0, 4)), ...[4, 6, 8, 10, 12].map((at) => Number(text.slice(at, at + 2)))];
29
- const stamp = Date.UTC(year, month - 1, day, hour, minute, second);
30
- const date = new Date(stamp);
31
- return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day
32
- && date.getUTCHours() === hour && date.getUTCMinutes() === minute && date.getUTCSeconds() === second ? stamp : null;
26
+ const [year, month, day, hour, minute, second] = [Number(text.slice(0, 4)), ...[4, 6, 8, 10, 12].map((at) => Number(text.slice(at, at + 2)))];
27
+ const stamp = Date.UTC(year, month - 1, day, hour, minute, second);
28
+ const date = new Date(stamp);
29
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day
30
+ && date.getUTCHours() === hour && date.getUTCMinutes() === minute && date.getUTCSeconds() === second ? stamp : null;
33
31
  }
34
-
35
32
  /** The three git reads L02 makes: (args, {cwd}) -> {ok, stdout}. */
36
33
  export function defaultGit(args, { cwd }) {
37
- const [verb, ...rest] = args;
38
- const env = withoutGitLocalEnv(process.env);
39
- if (verb === 'merge-base') { const sha = mergeBase(cwd, rest[0], rest[1]); return { ok: sha !== null, stdout: sha ?? '' }; }
40
- let call = show;
41
- if (verb === 'ls-tree') call = lsTree;
42
- const result = call(rest, { cwd, env, maxBuffer: 64 * 1024 * 1024 });
43
- return { ok: !result.error && result.status === 0, stdout: result.stdout };
44
- }
45
-
34
+ const [verb, ...rest] = args;
35
+ const env = withoutGitLocalEnv(process.env);
36
+ if (verb === 'merge-base') {
37
+ const sha = mergeBase(cwd, rest[0], rest[1]);
38
+ return { ok: sha !== null, stdout: sha ?? '' };
39
+ }
40
+ let call = show;
41
+ if (verb === 'ls-tree')
42
+ call = lsTree;
43
+ const result = call(rest, { cwd, env, maxBuffer: 64 * 1024 * 1024 });
44
+ return { ok: !result.error && result.status === 0, stdout: result.stdout };
45
+ }
46
46
  const runGit = (git, repoRoot, args) => Promise.resolve(git(args, { cwd: repoRoot }))
47
- .then((result) => ({ ok: result?.ok === true, stdout: String(result?.stdout ?? '') }));
48
-
47
+ .then((result) => ({ ok: result?.ok === true, stdout: String(result?.stdout ?? '') }));
49
48
  async function baseShaOf(git, repoRoot, base) {
50
- let found = null;
51
- await findInOrder(base ? [base] : ['origin/main', 'main'], async (ref) => {
52
- const result = await runGit(git, repoRoot, ['merge-base', 'HEAD', ref]);
53
- if (result.ok && result.stdout.trim()) found = { ref, sha: result.stdout.trim() };
54
- return found !== null;
55
- });
56
- return found;
57
- }
58
-
49
+ let found = null;
50
+ await findInOrder(base ? [base] : ['origin/main', 'main'], async (ref) => {
51
+ const result = await runGit(git, repoRoot, ['merge-base', 'HEAD', ref]);
52
+ if (result.ok && result.stdout.trim())
53
+ found = { ref, sha: result.stdout.trim() };
54
+ return found !== null;
55
+ });
56
+ return found;
57
+ }
59
58
  async function migrationFilesAt(git, repoRoot, sha) {
60
- const result = await runGit(git, repoRoot, ['ls-tree', '-r', '--name-only', '-z', sha, '--', MIGRATIONS_DIR]);
61
- if (!result.ok) return [];
62
- const prefix = `${MIGRATIONS_DIR}/`;
63
- return result.stdout.split('\0').filter((entry) => entry.startsWith(prefix));
59
+ const result = await runGit(git, repoRoot, ['ls-tree', '-r', '--name-only', '-z', sha, '--', MIGRATIONS_DIR]);
60
+ if (!result.ok)
61
+ return [];
62
+ const prefix = `${MIGRATIONS_DIR}/`;
63
+ return result.stdout.split('\0').filter((entry) => entry.startsWith(prefix));
64
64
  }
65
-
66
65
  async function baseFileText(git, repoRoot, sha, file) {
67
- // `./` reads the path from the app root, which is a folder of a larger repository when the app is nested in one (an example of the runtime).
68
- const result = await runGit(git, repoRoot, ['show', `${sha}:./${file}`]);
69
- return result.ok ? result.stdout : null;
66
+ // `./` reads the path from the app root, which is a folder of a larger repository when the app is nested in one (an example of the runtime).
67
+ const result = await runGit(git, repoRoot, ['show', `${sha}:./${file}`]);
68
+ return result.ok ? result.stdout : null;
70
69
  }
71
-
72
70
  function localMigrationFindings(local) {
73
- const findings = [];
74
- const stamps = new Map();
75
- for (const entry of local) {
76
- if (!entry.match) {
77
- findings.push(found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} is not named <ts14>_<kebab>.sql; a migration is created by \`npm run db:new\` (starci app db new), never renamed by hand`, { expected: '<ts14>_<kebab>.sql' }));
78
- continue;
71
+ const findings = [];
72
+ const stamps = new Map();
73
+ for (const entry of local) {
74
+ if (!entry.match) {
75
+ findings.push(found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} is not named <ts14>_<kebab>.sql; a migration is created by \`npm run db:new\` (starci app db new), never renamed by hand`, { expected: '<ts14>_<kebab>.sql' }));
76
+ continue;
77
+ }
78
+ const stamp = migrationStamp(entry.match[1]);
79
+ if (stamp === null) {
80
+ findings.push(found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} carries ${entry.match[1]}, which is no valid UTC time; a migration stamp must name a valid UTC instant`, { stamp: entry.match[1] }));
81
+ continue;
82
+ }
83
+ if (stamps.has(stamp))
84
+ findings.push(found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} shares stamp ${entry.match[1]} with ${stamps.get(stamp)}; stamps are strictly increasing`, { stamp: entry.match[1], other: stamps.get(stamp) }));
85
+ stamps.set(stamp, entry.file);
79
86
  }
80
- const stamp = migrationStamp(entry.match[1]);
81
- if (stamp === null) {
82
- findings.push(found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} carries ${entry.match[1]}, which is no valid UTC time; a migration stamp must name a valid UTC instant`, { stamp: entry.match[1] }));
83
- continue;
84
- }
85
- if (stamps.has(stamp)) findings.push(found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} shares stamp ${entry.match[1]} with ${stamps.get(stamp)}; stamps are strictly increasing`, { stamp: entry.match[1], other: stamps.get(stamp) }));
86
- stamps.set(stamp, entry.file);
87
- }
88
- return findings;
87
+ return findings;
89
88
  }
90
-
91
89
  /** HEAD owns the append boundary. Archived names retire the old chain, so a replacement baseline starts afresh. */
92
90
  function migrationHistory(files, retired, localNames) {
93
- const prefix = `${MIGRATIONS_DIR}/`;
94
- const onHead = new Set(files.filter(isActiveMigration).map((file) => file.slice(prefix.length)));
95
- const retiredNames = new Set([...retired, ...files.filter((file) => file.startsWith(`${MIGRATIONS_ARCHIVE_DIR}/`)).map((file) => file.slice(MIGRATIONS_ARCHIVE_DIR.length + 1))].filter((name) => !localNames.has(name)));
96
- const stamps = [...onHead].filter((name) => !retiredNames.has(name)).map((name) => MIGRATION_NAME.exec(name)?.[1]).filter(Boolean).map(migrationStamp).filter((stamp) => stamp !== null);
97
- return { onHead, latest: stamps.length ? Math.max(...stamps) : null };
91
+ const prefix = `${MIGRATIONS_DIR}/`;
92
+ const onHead = new Set(files.filter(isActiveMigration).map((file) => file.slice(prefix.length)));
93
+ const retiredNames = new Set([...retired, ...files.filter((file) => file.startsWith(`${MIGRATIONS_ARCHIVE_DIR}/`)).map((file) => file.slice(MIGRATIONS_ARCHIVE_DIR.length + 1))].filter((name) => !localNames.has(name)));
94
+ const stamps = [...onHead].filter((name) => !retiredNames.has(name)).map((name) => MIGRATION_NAME.exec(name)?.[1]).filter((stamp) => Boolean(stamp)).map(migrationStamp).filter((stamp) => stamp !== null);
95
+ return { onHead, latest: stamps.length ? Math.max(...stamps) : null };
98
96
  }
99
-
100
97
  function migrationOrderingFindings(local, history, restamped = new Set()) {
101
- return local.flatMap((entry) => {
102
- const stamp = entry.match ? migrationStamp(entry.match[1]) : null;
103
- if (history.onHead.has(entry.name) || restamped.has(entry.name) || stamp === null || history.latest === null || stamp > history.latest) return [];
104
- return [found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} is stamped ${entry.match[1]}, not after every migration already in repository history (latest active ${new Date(history.latest).toISOString()}); a new migration sorts after the committed active chain`, { stamp: entry.match[1], latest: new Date(history.latest).toISOString() })];
105
- });
98
+ return local.flatMap((entry) => {
99
+ const stamp = entry.match ? migrationStamp(entry.match[1]) : null;
100
+ if (history.onHead.has(entry.name) || restamped.has(entry.name) || stamp === null || history.latest === null || stamp > history.latest)
101
+ return [];
102
+ return [found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} is stamped ${entry.match[1]}, not after every migration already in repository history (latest active ${new Date(history.latest).toISOString()}); a new migration sorts after the committed active chain`, { stamp: entry.match[1], latest: new Date(history.latest).toISOString() })];
103
+ });
106
104
  }
107
-
108
105
  /** A restamp changes only the version, and its header proves the explicit old->new map against repository SQL. */
109
106
  async function verifiedRestamps(local, files, repoRoot, git, sha) {
110
- const prefix = `${MIGRATIONS_DIR}/`;
111
- const active = files.filter(isActiveMigration).map((file) => file.slice(prefix.length));
112
- const claims = local.map((entry) => ({ ...entry, header: RESTAMP_HEADER.exec(readText(repoRoot, entry.file) ?? '') })).filter((entry) => entry.header);
113
- const accepted = [];
114
- await eachInOrder(claims, async (entry) => {
115
- const [, oldStamp, newStamp] = entry.header;
116
- if (!entry.match || entry.match[1] !== newStamp || migrationStamp(oldStamp) === null || oldStamp === newStamp) return;
117
- if (claims.filter((claim) => claim.header[1] === oldStamp).length !== 1) return;
118
- const names = active.filter((name) => name.startsWith(`${oldStamp}_`) && name.slice(14) === entry.name.slice(14));
119
- if (names.length !== 1 || local.some((candidate) => candidate.name === names[0])) return;
120
- const committed = await baseFileText(git, repoRoot, sha, `${prefix}${names[0]}`);
121
- if (committed === null || !sameText(withoutRestampHeader(readText(repoRoot, entry.file)), withoutRestampHeader(committed))) return;
122
- accepted.push({ source: names[0], destination: entry.name });
123
- });
124
- return accepted;
125
- }
126
-
107
+ const prefix = `${MIGRATIONS_DIR}/`;
108
+ const active = files.filter(isActiveMigration).map((file) => file.slice(prefix.length));
109
+ const claims = local.map((entry) => ({ ...entry, header: RESTAMP_HEADER.exec(readText(repoRoot, entry.file) ?? '') })).filter((entry) => entry.header);
110
+ const accepted = [];
111
+ await eachInOrder(claims, async (entry) => {
112
+ const [, oldStamp, newStamp] = entry.header;
113
+ if (!entry.match || entry.match[1] !== newStamp || migrationStamp(oldStamp) === null || oldStamp === newStamp)
114
+ return;
115
+ if (claims.filter((claim) => claim.header[1] === oldStamp).length !== 1)
116
+ return;
117
+ const names = active.filter((name) => name.startsWith(`${oldStamp}_`) && name.slice(14) === entry.name.slice(14));
118
+ if (names.length !== 1 || local.some((candidate) => candidate.name === names[0]))
119
+ return;
120
+ const committed = await baseFileText(git, repoRoot, sha, `${prefix}${names[0]}`);
121
+ if (committed === null || !sameText(withoutRestampHeader(readText(repoRoot, entry.file)), withoutRestampHeader(committed)))
122
+ return;
123
+ accepted.push({ source: names[0], destination: entry.name });
124
+ });
125
+ return accepted;
126
+ }
127
127
  async function baseMigrationEntryFindings(entry, repoRoot, git, baseSha, onBase) {
128
- if (!entry.match) return [];
129
- if (onBase.has(entry.name)) {
130
- const committed = await baseFileText(git, repoRoot, baseSha.sha, entry.file);
131
- const current = readText(repoRoot, entry.file);
132
- if (!sameText(current, committed)) return [found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} differs from its content on ${baseSha.ref}; a migration on the base branch is immutable - write a new migration`, { base: baseSha.ref })];
133
- }
134
- return [];
135
- }
136
-
128
+ if (!entry.match)
129
+ return [];
130
+ if (onBase.has(entry.name)) {
131
+ const committed = await baseFileText(git, repoRoot, baseSha.sha, entry.file);
132
+ const current = readText(repoRoot, entry.file);
133
+ if (!sameText(current, committed))
134
+ return [found(DB_MIGRATION_SHAPE, entry.file, `${entry.file} differs from its content on ${baseSha.ref}; a migration on the base branch is immutable - write a new migration`, { base: baseSha.ref })];
135
+ }
136
+ return [];
137
+ }
137
138
  function removedMigrationFindings(local, retired, baseNames, baseSha) {
138
- const findings = [];
139
- for (const name of baseNames) {
140
- if (!local.some((entry) => entry.name === name) && !retired.has(name)) findings.push(found(DB_MIGRATION_SHAPE, `${MIGRATIONS_DIR}/${name}`, `${MIGRATIONS_DIR}/${name} exists on ${baseSha.ref} but is gone here; a migration on the base branch is immutable - restore it`, { base: baseSha.ref }));
141
- }
142
- return findings;
139
+ const findings = [];
140
+ for (const name of baseNames) {
141
+ if (!local.some((entry) => entry.name === name) && !retired.has(name))
142
+ findings.push(found(DB_MIGRATION_SHAPE, `${MIGRATIONS_DIR}/${name}`, `${MIGRATIONS_DIR}/${name} exists on ${baseSha.ref} but is gone here; a migration on the base branch is immutable - restore it`, { base: baseSha.ref }));
143
+ }
144
+ return findings;
143
145
  }
144
-
145
146
  /**
146
147
  * L02 findings for names, stamps, ordering and immutability of db/migrations/*.sql. `archived` are the files of
147
148
  * db/migrations/archive/ (app.db.migrations.archive): never judged, and a migration moved there at a baseline
@@ -149,341 +150,380 @@ function removedMigrationFindings(local, retired, baseNames, baseSha) {
149
150
  * on archived migrations, remote branches and the wall clock do not constrain a replacement baseline.
150
151
  */
151
152
  export async function migrationShapeFindings({ repoRoot, migrations, archived = [], git, base }) {
152
- const prefix = `${MIGRATIONS_DIR}/`;
153
- const local = migrations.map((file) => {
154
- const name = file.startsWith(prefix) ? file.slice(prefix.length) : file;
155
- return { file, name, match: MIGRATION_NAME.exec(name) };
156
- });
157
- const findings = localMigrationFindings(local);
158
- const retired = new Set(archived.map((file) => file.slice(MIGRATIONS_ARCHIVE_DIR.length + 1)));
159
- const headFiles = await migrationFilesAt(git, repoRoot, 'HEAD');
160
- const baseSha = await baseShaOf(git, repoRoot, base);
161
- const baseFiles = baseSha ? await migrationFilesAt(git, repoRoot, baseSha.sha) : [];
162
- const restamps = await verifiedRestamps(local, baseSha ? baseFiles : headFiles, repoRoot, git, baseSha?.sha ?? 'HEAD');
163
- for (const restamp of restamps) retired.add(restamp.source);
164
- const history = migrationHistory(headFiles, retired, new Set(local.map((entry) => entry.name)));
165
- findings.push(...migrationOrderingFindings(local, history, new Set(restamps.map((entry) => entry.destination))));
166
- if (!baseSha) return findings;
167
- const baseNames = baseFiles.filter(isActiveMigration).map((file) => file.slice(prefix.length));
168
- const onBase = new Set(baseNames);
169
- await eachInOrder(local, async (entry) => {
170
- findings.push(...await baseMigrationEntryFindings(entry, repoRoot, git, baseSha, onBase));
171
- });
172
- findings.push(...removedMigrationFindings(local, retired, baseNames, baseSha));
173
- return findings;
174
- }
175
-
153
+ const prefix = `${MIGRATIONS_DIR}/`;
154
+ const local = migrations.map((file) => {
155
+ const name = file.startsWith(prefix) ? file.slice(prefix.length) : file;
156
+ return { file, name, match: MIGRATION_NAME.exec(name) };
157
+ });
158
+ const findings = localMigrationFindings(local);
159
+ const retired = new Set(archived.map((file) => file.slice(MIGRATIONS_ARCHIVE_DIR.length + 1)));
160
+ const headFiles = await migrationFilesAt(git, repoRoot, 'HEAD');
161
+ const baseSha = await baseShaOf(git, repoRoot, base);
162
+ const baseFiles = baseSha ? await migrationFilesAt(git, repoRoot, baseSha.sha) : [];
163
+ const restamps = await verifiedRestamps(local, baseSha ? baseFiles : headFiles, repoRoot, git, baseSha?.sha ?? 'HEAD');
164
+ for (const restamp of restamps)
165
+ retired.add(restamp.source);
166
+ const history = migrationHistory(headFiles, retired, new Set(local.map((entry) => entry.name)));
167
+ findings.push(...migrationOrderingFindings(local, history, new Set(restamps.map((entry) => entry.destination))));
168
+ if (!baseSha)
169
+ return findings;
170
+ const baseNames = baseFiles.filter(isActiveMigration).map((file) => file.slice(prefix.length));
171
+ const onBase = new Set(baseNames);
172
+ await eachInOrder(local, async (entry) => {
173
+ findings.push(...await baseMigrationEntryFindings(entry, repoRoot, git, baseSha, onBase));
174
+ });
175
+ findings.push(...removedMigrationFindings(local, retired, baseNames, baseSha));
176
+ return findings;
177
+ }
176
178
  const sqlName = (token) => token && ['word', 'ident'].includes(token.t) ? token.v : null;
177
179
  const sqlWord = (token, value) => token?.t === 'word' && token.v === value;
178
-
179
180
  function commentEnd(text, start) {
180
- if (text.startsWith('--', start)) {
181
- const end = text.indexOf('\n', start + 2);
182
- return end === -1 ? text.length : end;
183
- }
184
- if (!text.startsWith('/*', start)) return null;
185
- let depth = 1;
186
- let index = start + 2;
187
- while (index < text.length && depth > 0) {
188
- if (text.startsWith('/*', index)) { depth += 1; index += 2; }
189
- else if (text.startsWith('*/', index)) { depth -= 1; index += 2; }
190
- else index += 1;
191
- }
192
- return index;
193
- }
194
-
181
+ if (text.startsWith('--', start)) {
182
+ const end = text.indexOf('\n', start + 2);
183
+ return end === -1 ? text.length : end;
184
+ }
185
+ if (!text.startsWith('/*', start))
186
+ return null;
187
+ let depth = 1;
188
+ let index = start + 2;
189
+ while (index < text.length && depth > 0) {
190
+ if (text.startsWith('/*', index)) {
191
+ depth += 1;
192
+ index += 2;
193
+ }
194
+ else if (text.startsWith('*/', index)) {
195
+ depth -= 1;
196
+ index += 2;
197
+ }
198
+ else
199
+ index += 1;
200
+ }
201
+ return index;
202
+ }
195
203
  function quotedToken(text, start, quote, escaped = false) {
196
- let index = start + 1;
197
- let value = '';
198
- while (index < text.length) {
199
- if (text[index] === quote && text[index + 1] === quote) { value += quote; index += 2; }
200
- else if (text[index] === quote) return { value, end: index + 1 };
201
- else if (escaped && text[index] === '\\') { value += text[index + 1] ?? ''; index += 2; }
202
- else { value += text[index]; index += 1; }
203
- }
204
- return { value, end: index };
205
- }
206
-
204
+ let index = start + 1;
205
+ let value = '';
206
+ while (index < text.length) {
207
+ if (text[index] === quote && text[index + 1] === quote) {
208
+ value += quote;
209
+ index += 2;
210
+ }
211
+ else if (text[index] === quote)
212
+ return { value, end: index + 1 };
213
+ else if (escaped && text[index] === '\\') {
214
+ value += text[index + 1] ?? '';
215
+ index += 2;
216
+ }
217
+ else {
218
+ value += text[index];
219
+ index += 1;
220
+ }
221
+ }
222
+ return { value, end: index };
223
+ }
207
224
  function sqlTokenAt(text, index) {
208
- const char = text[index];
209
- if (char === "'" || char === '"') {
210
- const token = quotedToken(text, index, char);
211
- return { t: char === '"' ? 'ident' : 'string', v: token.value, end: token.end };
212
- }
213
- if (/[eE]/.test(char) && text[index + 1] === "'") {
214
- const token = quotedToken(text, index + 1, "'", true);
215
- return { t: 'string', v: token.value, end: token.end };
216
- }
217
- const tag = char === '$' ? /^\$(?:[A-Za-z_]\w*)?\$/.exec(text.slice(index))?.[0] : null;
218
- if (tag) {
219
- const end = text.indexOf(tag, index + tag.length);
220
- return { t: 'body', v: text.slice(index + tag.length, end === -1 ? text.length : end), end: end === -1 ? text.length : end + tag.length };
221
- }
222
- const word = /^[A-Za-z_][A-Za-z0-9_$]*/.exec(text.slice(index))?.[0];
223
- if (word) return { t: 'word', v: word.toLowerCase(), end: index + word.length };
224
- const number = /^\d+(?:\.\d+)?/.exec(text.slice(index))?.[0];
225
- if (number) return { t: 'number', v: number, end: index + number.length };
226
- return { t: 'punct', v: char, end: index + 1 };
227
- }
228
-
225
+ const char = text[index];
226
+ if (char === "'" || char === '"') {
227
+ const token = quotedToken(text, index, char);
228
+ return { t: char === '"' ? 'ident' : 'string', v: token.value, end: token.end };
229
+ }
230
+ if (/[eE]/.test(char) && text[index + 1] === "'") {
231
+ const token = quotedToken(text, index + 1, "'", true);
232
+ return { t: 'string', v: token.value, end: token.end };
233
+ }
234
+ const tag = char === '$' ? /^\$(?:[A-Za-z_]\w*)?\$/.exec(text.slice(index))?.[0] : null;
235
+ if (tag) {
236
+ const end = text.indexOf(tag, index + tag.length);
237
+ return { t: 'body', v: text.slice(index + tag.length, end === -1 ? text.length : end), end: end === -1 ? text.length : end + tag.length };
238
+ }
239
+ const word = /^[A-Za-z_][A-Za-z0-9_$]*/.exec(text.slice(index))?.[0];
240
+ if (word)
241
+ return { t: 'word', v: word.toLowerCase(), end: index + word.length };
242
+ const number = /^\d+(?:\.\d+)?/.exec(text.slice(index))?.[0];
243
+ if (number)
244
+ return { t: 'number', v: number, end: index + number.length };
245
+ return { t: 'punct', v: char, end: index + 1 };
246
+ }
229
247
  /** Synchronous SQL tokens; literal values stay internal and must never be copied to a finding. */
230
248
  export function databaseSqlTokens(text) {
231
- const tokens = [];
232
- let index = 0;
233
- let line = 1;
234
- while (index < text.length) {
235
- if (/\s/.test(text[index])) {
236
- if (text[index] === '\n') line += 1;
237
- index += 1;
238
- continue;
249
+ const tokens = [];
250
+ let index = 0;
251
+ let line = 1;
252
+ while (index < text.length) {
253
+ if (/\s/.test(text[index])) {
254
+ if (text[index] === '\n')
255
+ line += 1;
256
+ index += 1;
257
+ continue;
258
+ }
259
+ const end = commentEnd(text, index);
260
+ if (end !== null) {
261
+ line += text.slice(index, end).split('\n').length - 1;
262
+ index = end;
263
+ continue;
264
+ }
265
+ const token = sqlTokenAt(text, index);
266
+ tokens.push({ t: token.t, v: token.v, line, index });
267
+ line += text.slice(index, token.end).split('\n').length - 1;
268
+ index = token.end;
239
269
  }
240
- const end = commentEnd(text, index);
241
- if (end !== null) { line += text.slice(index, end).split('\n').length - 1; index = end; continue; }
242
- const token = sqlTokenAt(text, index);
243
- tokens.push({ t: token.t, v: token.v, line, index });
244
- line += text.slice(index, token.end).split('\n').length - 1;
245
- index = token.end;
246
- }
247
- return tokens;
248
- }
249
-
270
+ return tokens;
271
+ }
250
272
  /** Split executable SQL, retaining function bodies as opaque tokens until their language is known. */
251
273
  export function databaseSqlStatements(tokens) {
252
- const statements = [];
253
- let current = [];
254
- for (const token of tokens) {
255
- if (token.t === 'punct' && token.v === ';') {
256
- if (current.length) statements.push(current);
257
- current = [];
274
+ const statements = [];
275
+ let current = [];
276
+ for (const token of tokens) {
277
+ if (token.t === 'punct' && token.v === ';') {
278
+ if (current.length)
279
+ statements.push(current);
280
+ current = [];
281
+ }
282
+ else
283
+ current.push(token);
258
284
  }
259
- else current.push(token);
260
- }
261
- if (current.length) statements.push(current);
262
- return statements;
285
+ if (current.length)
286
+ statements.push(current);
287
+ return statements;
263
288
  }
264
-
265
289
  function executableStatementTokens(statement, depth) {
266
- const isDo = sqlWord(statement[0], 'do');
267
- const functionAt = statement.findIndex((token) => sqlWord(token, 'function') || sqlWord(token, 'procedure'));
268
- const isFunction = sqlWord(statement[0], 'create') && functionAt > 0 && functionAt < 4;
269
- if (!isDo && !isFunction) return statement;
270
- const languageAt = statement.findIndex((token) => sqlWord(token, 'language'));
271
- const language = statement[languageAt + 1]?.v ?? 'sql';
272
- if (languageAt !== -1 && !['sql', 'plpgsql'].includes(language)) return statement;
273
- return statement.flatMap((token, index) => {
274
- const body = token.t === 'body' || (token.t === 'string' && (isDo || sqlWord(statement[index - 1], 'as')));
275
- if (!body) return [token];
276
- return databaseExecutableTokens(token.v, depth + 1).map((child) => ({ ...child, line: child.line + token.line - 1 }));
277
- });
278
- }
279
-
290
+ const isDo = sqlWord(statement[0], 'do');
291
+ const functionAt = statement.findIndex((token) => sqlWord(token, 'function') || sqlWord(token, 'procedure'));
292
+ const isFunction = sqlWord(statement[0], 'create') && functionAt > 0 && functionAt < 4;
293
+ if (!isDo && !isFunction)
294
+ return statement;
295
+ const languageAt = statement.findIndex((token) => sqlWord(token, 'language'));
296
+ const language = statement[languageAt + 1]?.v ?? 'sql';
297
+ if (languageAt !== -1 && !['sql', 'plpgsql'].includes(language))
298
+ return statement;
299
+ return statement.flatMap((token, index) => {
300
+ const body = token.t === 'body' || (token.t === 'string' && (isDo || sqlWord(statement[index - 1], 'as')));
301
+ if (!body)
302
+ return [token];
303
+ return databaseExecutableTokens(token.v, depth + 1).map((child) => ({ ...child, line: child.line + token.line - 1 }));
304
+ });
305
+ }
280
306
  /** SQL and PL/pgSQL bodies are scanned; comments, data literals and other function languages are opaque. */
281
307
  export function databaseExecutableTokens(text, depth = 0) {
282
- const tokens = databaseSqlTokens(text);
283
- if (depth > 8) return tokens;
284
- return databaseSqlStatements(tokens).flatMap((statement) => [...executableStatementTokens(statement, depth), { t: 'punct', v: ';' }]);
308
+ const tokens = databaseSqlTokens(text);
309
+ if (depth > 8)
310
+ return tokens;
311
+ return databaseSqlStatements(tokens).flatMap((statement) => [...executableStatementTokens(statement, depth), { t: 'punct', v: ';' }]);
285
312
  }
286
-
287
313
  function nameAt(tokens, index) {
288
- const first = sqlName(tokens[index]);
289
- if (first === null) return null;
290
- const parts = [first];
291
- let next = index + 1;
292
- while (tokens[next]?.v === '.' && sqlName(tokens[next + 1]) !== null) { parts.push(sqlName(tokens[next + 1])); next += 2; }
293
- return { name: parts.join('.'), leaf: parts.at(-1), next };
294
- }
295
-
314
+ const first = sqlName(tokens[index]);
315
+ if (first === null)
316
+ return null;
317
+ const parts = [first];
318
+ let next = index + 1;
319
+ while (tokens[next]?.v === '.' && sqlName(tokens[next + 1]) !== null) {
320
+ parts.push(sqlName(tokens[next + 1]));
321
+ next += 2;
322
+ }
323
+ return { name: parts.join('.'), leaf: parts.at(-1), next };
324
+ }
296
325
  const skipWords = (tokens, index, words) => {
297
- let next = index;
298
- while (words.some((word) => sqlWord(tokens[next], word))) next += 1;
299
- return next;
326
+ let next = index;
327
+ while (words.some((word) => sqlWord(tokens[next], word)))
328
+ next += 1;
329
+ return next;
300
330
  };
301
-
302
331
  function dropObjects(tokens, start) {
303
- const kind = tokens[start + 1]?.v;
304
- if (!['table', 'role', 'user', 'schema', 'type', 'view', 'materialized', 'sequence', 'function', 'procedure', 'index', 'policy', 'trigger'].includes(kind)) return [];
305
- let index = skipWords(tokens, start + 2, ['view', 'if', 'exists', 'concurrently']);
306
- const objects = [];
307
- while (index < tokens.length) {
308
- const object = nameAt(tokens, index);
309
- if (!object) break;
310
- objects.push({ ...object, kind, line: tokens[start].line });
311
- if (tokens[object.next]?.v !== ',') break;
312
- index = object.next + 1;
313
- }
314
- return objects;
315
- }
316
-
332
+ const kind = tokens[start + 1]?.v;
333
+ if (!['table', 'role', 'user', 'schema', 'type', 'view', 'materialized', 'sequence', 'function', 'procedure', 'index', 'policy', 'trigger'].includes(kind))
334
+ return [];
335
+ let index = skipWords(tokens, start + 2, ['view', 'if', 'exists', 'concurrently']);
336
+ const objects = [];
337
+ while (index < tokens.length) {
338
+ const object = nameAt(tokens, index);
339
+ if (!object)
340
+ break;
341
+ objects.push({ ...object, kind, line: tokens[start].line });
342
+ if (tokens[object.next]?.v !== ',')
343
+ break;
344
+ index = object.next + 1;
345
+ }
346
+ return objects;
347
+ }
317
348
  function columnAlterObject(tokens, index, table, line) {
318
- let next = index + 1;
319
- if (sqlWord(tokens[next], 'column')) next += 1;
320
- const column = nameAt(tokens, next);
321
- if (!column) return null;
322
- const tail = tokens.slice(column.next);
323
- const type = sqlWord(tail[0], 'type') || (sqlWord(tail[0], 'set') && sqlWord(tail[1], 'data') && sqlWord(tail[2], 'type'));
324
- const notNull = sqlWord(tail[0], 'set') && sqlWord(tail[1], 'not') && sqlWord(tail[2], 'null');
325
- const defaultSet = tokens.some((token, at) => sqlWord(token, 'alter') && sqlName(tokens[at + 1 + Number(sqlWord(tokens[at + 1], 'column'))]) === column.leaf
326
- && sqlWord(tokens[at + 2 + Number(sqlWord(tokens[at + 1], 'column'))], 'set') && sqlWord(tokens[at + 3 + Number(sqlWord(tokens[at + 1], 'column'))], 'default'));
327
- if (!type && !(notNull && !defaultSet)) return null;
328
- return { name: `${table.name}.${column.name}`, leaf: column.leaf, table: table.leaf, kind: 'column', line };
329
- }
330
-
349
+ let next = index + 1;
350
+ if (sqlWord(tokens[next], 'column'))
351
+ next += 1;
352
+ const column = nameAt(tokens, next);
353
+ if (!column)
354
+ return null;
355
+ const tail = tokens.slice(column.next);
356
+ const type = sqlWord(tail[0], 'type') || (sqlWord(tail[0], 'set') && sqlWord(tail[1], 'data') && sqlWord(tail[2], 'type'));
357
+ const notNull = sqlWord(tail[0], 'set') && sqlWord(tail[1], 'not') && sqlWord(tail[2], 'null');
358
+ const defaultSet = tokens.some((token, at) => sqlWord(token, 'alter') && sqlName(tokens[at + 1 + Number(sqlWord(tokens[at + 1], 'column'))]) === column.leaf
359
+ && sqlWord(tokens[at + 2 + Number(sqlWord(tokens[at + 1], 'column'))], 'set') && sqlWord(tokens[at + 3 + Number(sqlWord(tokens[at + 1], 'column'))], 'default'));
360
+ if (!type && !(notNull && !defaultSet))
361
+ return null;
362
+ return { name: `${table.name}.${column.name}`, leaf: column.leaf, table: table.leaf, kind: 'column', line };
363
+ }
331
364
  function alteredColumn(table, column, line) {
332
- return { name: `${table.name}.${column.name}`, leaf: column.leaf, table: table.leaf, kind: 'column', line };
365
+ return { name: `${table.name}.${column.name}`, leaf: column.leaf, table: table.leaf, kind: 'column', line };
333
366
  }
334
-
335
367
  function tableActionObject(body, index, table, line) {
336
- if (sqlWord(body[index], 'drop')) {
337
- const constraint = sqlWord(body[index + 1], 'constraint');
338
- const at = skipWords(body, index + 1, ['column', 'constraint', 'if', 'exists']);
339
- if (sqlWord(body[at], 'default') || sqlWord(body[at], 'not')) return null;
340
- const column = nameAt(body, at);
341
- return column ? { ...alteredColumn(table, column, line), kind: constraint ? 'constraint' : 'column' } : null;
342
- }
343
- if (sqlWord(body[index], 'rename')) {
344
- const column = sqlWord(body[index + 1], 'column') ? nameAt(body, index + 2) : null;
345
- return column ? alteredColumn(table, column, line) : { ...table, kind: 'table', line };
346
- }
347
- return sqlWord(body[index], 'alter') ? columnAlterObject(body, index, table, line) : null;
348
- }
349
-
368
+ if (sqlWord(body[index], 'drop')) {
369
+ const constraint = sqlWord(body[index + 1], 'constraint');
370
+ const at = skipWords(body, index + 1, ['column', 'constraint', 'if', 'exists']);
371
+ if (sqlWord(body[at], 'default') || sqlWord(body[at], 'not'))
372
+ return null;
373
+ const column = nameAt(body, at);
374
+ return column ? { ...alteredColumn(table, column, line), kind: constraint ? 'constraint' : 'column' } : null;
375
+ }
376
+ if (sqlWord(body[index], 'rename')) {
377
+ const column = sqlWord(body[index + 1], 'column') ? nameAt(body, index + 2) : null;
378
+ return column ? alteredColumn(table, column, line) : { ...table, kind: 'table', line };
379
+ }
380
+ return sqlWord(body[index], 'alter') ? columnAlterObject(body, index, table, line) : null;
381
+ }
350
382
  function alterObjects(tokens, start) {
351
- const table = nameAt(tokens, skipWords(tokens, start + 2, ['if', 'exists', 'only']));
352
- if (!table) return [];
353
- const body = tokens.slice(table.next);
354
- return body.map((token, index) => tableActionObject(body, index, table, tokens[start].line)).filter(Boolean);
383
+ const table = nameAt(tokens, skipWords(tokens, start + 2, ['if', 'exists', 'only']));
384
+ if (!table)
385
+ return [];
386
+ const body = tokens.slice(table.next);
387
+ return body.map((_token, index) => tableActionObject(body, index, table, tokens[start].line)).filter(Boolean);
355
388
  }
356
-
357
389
  function truncatedObjects(tokens, start) {
358
- const objects = [];
359
- let index = skipWords(tokens, start + 1, ['table', 'only']);
360
- while (index < tokens.length) {
361
- const table = nameAt(tokens, index);
362
- if (!table) break;
363
- objects.push({ ...table, kind: 'table', line: tokens[start].line });
364
- if (tokens[table.next]?.v !== ',') break;
365
- index = skipWords(tokens, table.next + 1, ['only']);
366
- }
367
- return objects;
368
- }
369
-
390
+ const objects = [];
391
+ let index = skipWords(tokens, start + 1, ['table', 'only']);
392
+ while (index < tokens.length) {
393
+ const table = nameAt(tokens, index);
394
+ if (!table)
395
+ break;
396
+ objects.push({ ...table, kind: 'table', line: tokens[start].line });
397
+ if (tokens[table.next]?.v !== ',')
398
+ break;
399
+ index = skipWords(tokens, table.next + 1, ['only']);
400
+ }
401
+ return objects;
402
+ }
370
403
  function destructiveObjects(statement) {
371
- const objects = [];
372
- for (let index = 0; index < statement.length; index += 1) {
373
- if (sqlWord(statement[index], 'drop')) objects.push(...dropObjects(statement, index));
374
- else if (sqlWord(statement[index], 'truncate')) objects.push(...truncatedObjects(statement, index));
375
- else if (sqlWord(statement[index], 'alter') && sqlWord(statement[index + 1], 'table')) objects.push(...alterObjects(statement, index));
376
- else if (sqlWord(statement[index], 'alter') && ['type', 'schema', 'view', 'sequence', 'function', 'procedure', 'index'].includes(statement[index + 1]?.v)) {
377
- const object = nameAt(statement, index + 2);
378
- if (object && statement.slice(object.next).some((token) => sqlWord(token, 'rename'))) objects.push({ ...object, kind: statement[index + 1].v, line: statement[index].line });
404
+ const objects = [];
405
+ for (let index = 0; index < statement.length; index += 1) {
406
+ if (sqlWord(statement[index], 'drop'))
407
+ objects.push(...dropObjects(statement, index));
408
+ else if (sqlWord(statement[index], 'truncate'))
409
+ objects.push(...truncatedObjects(statement, index));
410
+ else if (sqlWord(statement[index], 'alter') && sqlWord(statement[index + 1], 'table'))
411
+ objects.push(...alterObjects(statement, index));
412
+ else if (sqlWord(statement[index], 'alter') && ['type', 'schema', 'view', 'sequence', 'function', 'procedure', 'index'].includes(statement[index + 1]?.v)) {
413
+ const object = nameAt(statement, index + 2);
414
+ if (object && statement.slice(object.next).some((token) => sqlWord(token, 'rename')))
415
+ objects.push({ ...object, kind: statement[index + 1].v, line: statement[index].line });
416
+ }
379
417
  }
380
- }
381
- return objects;
418
+ return objects;
382
419
  }
383
-
384
420
  /** Keep the static parts of one SQL expression together across interpolation and string concatenation. */
385
421
  function sourceSqlText(ts, expression, checker, visiting = new Set()) {
386
- const node = unwrapExpression(ts, expression);
387
- if (ts.isStringLiteralLike(node)) return node.text;
388
- if (ts.isTaggedTemplateExpression(node)) return sourceSqlText(ts, node.template, checker, visiting);
389
- if (ts.isIdentifier(node)) {
390
- const declaration = checker.getSymbolAtLocation(node)?.valueDeclaration;
391
- if (!declaration || !ts.isVariableDeclaration(declaration) || !isConstVariable(ts, declaration)
392
- || !declaration.initializer || visiting.has(declaration)) return null;
393
- return sourceSqlText(ts, declaration.initializer, checker, new Set([...visiting, declaration]));
394
- }
395
- if (ts.isTemplateExpression(node)) return node.head.text + node.templateSpans.map((span) =>
396
- `${sourceSqlText(ts, span.expression, checker, visiting) ?? ' '}${span.literal.text}`).join('');
397
- if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {
398
- return `${sourceSqlText(ts, node.left, checker, visiting) ?? ' '}${sourceSqlText(ts, node.right, checker, visiting) ?? ' '}`;
399
- }
400
- return null;
401
- }
402
-
422
+ const node = unwrapExpression(ts, expression);
423
+ if (ts.isStringLiteralLike(node))
424
+ return node.text;
425
+ if (ts.isTaggedTemplateExpression(node))
426
+ return sourceSqlText(ts, node.template, checker, visiting);
427
+ if (ts.isIdentifier(node)) {
428
+ const declaration = checker.getSymbolAtLocation(node)?.valueDeclaration;
429
+ if (!declaration || !ts.isVariableDeclaration(declaration) || !isConstVariable(ts, declaration)
430
+ || !declaration.initializer || visiting.has(declaration))
431
+ return null;
432
+ return sourceSqlText(ts, declaration.initializer, checker, new Set([...visiting, declaration]));
433
+ }
434
+ if (ts.isTemplateExpression(node))
435
+ return node.head.text + node.templateSpans.map((span) => `${sourceSqlText(ts, span.expression, checker, visiting) ?? ' '}${span.literal.text}`).join('');
436
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {
437
+ return `${sourceSqlText(ts, node.left, checker, visiting) ?? ' '}${sourceSqlText(ts, node.right, checker, visiting) ?? ' '}`;
438
+ }
439
+ return null;
440
+ }
403
441
  /** SET CONSTRAINTS names have no table qualifier; every matching table's constraint is affected. */
404
442
  function globalConstraintNames(statement) {
405
- const names = new Set();
406
- for (let index = 0; index < statement.length; index += 1) {
407
- if (!sqlWord(statement[index], 'set') || !sqlWord(statement[index + 1], 'constraints')) continue;
408
- let at = index + 2;
409
- while (at < statement.length && !sqlWord(statement[at], 'all')) {
410
- const constraint = nameAt(statement, at);
411
- if (!constraint) break;
412
- names.add(constraint.leaf);
413
- if (statement[constraint.next]?.v !== ',') break;
414
- at = constraint.next + 1;
443
+ const names = new Set();
444
+ for (let index = 0; index < statement.length; index += 1) {
445
+ if (!sqlWord(statement[index], 'set') || !sqlWord(statement[index + 1], 'constraints'))
446
+ continue;
447
+ let at = index + 2;
448
+ while (at < statement.length && !sqlWord(statement[at], 'all')) {
449
+ const constraint = nameAt(statement, at);
450
+ if (!constraint)
451
+ break;
452
+ names.add(constraint.leaf);
453
+ if (statement[constraint.next]?.v !== ',')
454
+ break;
455
+ at = constraint.next + 1;
456
+ }
415
457
  }
416
- }
417
- return names;
458
+ return names;
418
459
  }
419
-
420
460
  function sourceNameScopes(ts, text, file) {
421
- const source = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
422
- const checker = lexicalChecker(ts, source);
423
- const scopes = [];
424
- const entityNames = /\.entity\.[cm]?tsx?$/.test(file) ? new Set() : null;
425
- const addSql = (sql) => {
426
- for (const statement of databaseSqlStatements(databaseSqlTokens(sql))) {
427
- const names = new Set(statement.filter((token) => sqlName(token) !== null).map((token) => token.v));
428
- if (entityNames) for (const name of names) entityNames.add(name);
429
- else {
430
- const constraints = new Set(statement.flatMap((token, index) =>
431
- sqlWord(token, 'constraint') && sqlName(statement[index + 1]) !== null ? [statement[index + 1].v] : []));
432
- scopes.push({ names, constraints, globalConstraints: globalConstraintNames(statement) });
433
- }
434
- }
435
- };
436
- const visit = (node) => {
437
- const sql = sourceSqlText(ts, node, checker);
438
- if (sql !== null) addSql(sql);
439
- if (entityNames && ts.isIdentifier(node)) entityNames.add(node.text);
440
- ts.forEachChild(node, visit);
441
- };
442
- visit(source);
443
- return entityNames ? [{ names: entityNames, constraints: entityNames, globalConstraints: new Set() }] : scopes;
444
- }
445
-
461
+ const source = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
462
+ const checker = lexicalChecker(ts, source);
463
+ const scopes = [];
464
+ const entityNames = /\.entity\.[cm]?tsx?$/.test(file) ? new Set() : null;
465
+ const addSql = (sql) => {
466
+ for (const statement of databaseSqlStatements(databaseSqlTokens(sql))) {
467
+ const names = new Set(statement.filter((token) => sqlName(token) !== null).map((token) => token.v));
468
+ if (entityNames)
469
+ for (const name of names)
470
+ entityNames.add(name);
471
+ else {
472
+ const constraints = new Set(statement.flatMap((token, index) => sqlWord(token, 'constraint') && sqlName(statement[index + 1]) !== null ? [statement[index + 1].v] : []));
473
+ scopes.push({ names, constraints, globalConstraints: globalConstraintNames(statement) });
474
+ }
475
+ }
476
+ };
477
+ const visit = (node) => {
478
+ const sql = sourceSqlText(ts, node, checker);
479
+ if (sql !== null)
480
+ addSql(sql);
481
+ if (entityNames && ts.isIdentifier(node))
482
+ entityNames.add(node.text);
483
+ ts.forEachChild(node, visit);
484
+ };
485
+ visit(source);
486
+ return entityNames ? [{ names: entityNames, constraints: entityNames, globalConstraints: new Set() }] : scopes;
487
+ }
446
488
  /**
447
489
  * Whether a be/src source references a destroyed object. A column (`<schema>.<table>.<column>`) is referenced only by a source that
448
490
  * names both its table and the column in one SQL statement or entity, so separate queries cannot supply each other's names.
449
491
  * SQL constraints require explicit constraint names, while entities retain their table/decorator association.
450
492
  * Other object kinds match their leaf name conservatively.
451
493
  */
452
- const referencesObject = (scopes, object) => scopes.some(({ names, constraints, globalConstraints }) =>
453
- (object.kind === 'constraint' && globalConstraints.has(object.leaf))
454
- || ((object.kind === 'constraint' ? constraints : names).has(object.leaf)
455
- && (!['column', 'constraint'].includes(object.kind) || !object.table || names.has(object.table))));
456
-
494
+ const referencesObject = (scopes, object) => scopes.some(({ names, constraints, globalConstraints }) => (object.kind === 'constraint' && globalConstraints.has(object.leaf))
495
+ || ((object.kind === 'constraint' ? constraints : names).has(object.leaf)
496
+ && (!['column', 'constraint'].includes(object.kind) || !object.table || names.has(object.table))));
457
497
  function destructiveObjectFinding(file, object, contract, references) {
458
- const reference = references.find(({ scopes }) => referencesObject(scopes, object));
459
- if (contract && !reference) return null;
460
- const reason = reference && contract ? `${reference.file} still references this object; remove the reference before the contract migration`
461
- : 'use a *_contract_* migration after the application stops using this object';
462
- return found(DB_MIGRATION_DESTRUCTIVE, file, `${file}:${object.line} destructively changes ${object.name}; ${reason}`,
463
- { line: object.line, object: object.name, ...(reference ? { reference: reference.file } : {}) });
464
- }
465
-
498
+ const reference = references.find(({ scopes }) => referencesObject(scopes, object));
499
+ if (contract && !reference)
500
+ return null;
501
+ const reason = reference && contract ? `${reference.file} still references this object; remove the reference before the contract migration`
502
+ : 'use a *_contract_* migration after the application stops using this object';
503
+ return found(DB_MIGRATION_DESTRUCTIVE, file, `${file}:${object.line} destructively changes ${object.name}; ${reason}`, { line: object.line, object: object.name, ...(reference ? { reference: reference.file } : {}) });
504
+ }
466
505
  function destructiveFileFindings(file, text, references) {
467
- const contract = /_contract_[a-z0-9]+(?:[-_][a-z0-9]+)*\.sql$/.test(file);
468
- const seen = new Set();
469
- const objects = databaseSqlStatements(databaseExecutableTokens(text)).flatMap(destructiveObjects);
470
- return objects.flatMap((object) => {
471
- const key = `${object.line}:${object.kind}:${object.name}`;
472
- if (seen.has(key)) return [];
473
- seen.add(key);
474
- const finding = destructiveObjectFinding(file, object, contract, references);
475
- return finding ? [finding] : [];
476
- });
477
- }
478
-
506
+ const contract = /_contract_[a-z0-9]+(?:[-_][a-z0-9]+)*\.sql$/.test(file);
507
+ const seen = new Set();
508
+ const objects = databaseSqlStatements(databaseExecutableTokens(text)).flatMap(destructiveObjects);
509
+ return objects.flatMap((object) => {
510
+ const key = `${object.line}:${object.kind}:${object.name}`;
511
+ if (seen.has(key))
512
+ return [];
513
+ seen.add(key);
514
+ const finding = destructiveObjectFinding(file, object, contract, references);
515
+ return finding ? [finding] : [];
516
+ });
517
+ }
479
518
  /** Destructive changes require a contract migration and no remaining SQL/entity reference in be/src. */
480
519
  export function destructiveMigrationFindings({ repoRoot, migrations, files }) {
481
- const sources = files.filter((file) => /^be\/src\/.+\.(?:sql|entity)\.[cm]?tsx?$/.test(file));
482
- const ts = sources.length ? loadTypescript(repoRoot, HERE) : null;
483
- if (sources.length && !ts) return [found(DB_MIGRATION_DESTRUCTIVE, 'hfs.json', 'destructive migration checks require the TypeScript parser to read be/src references')];
484
- const references = sources.map((file) => ({ file, scopes: sourceNameScopes(ts, readText(repoRoot, file) ?? '', file) }));
485
- return migrations.flatMap((file) => {
486
- const text = readText(repoRoot, file);
487
- return text === null ? [] : destructiveFileFindings(file, text, references);
488
- });
520
+ const sources = files.filter((file) => /^be\/src\/.+\.(?:sql|entity)\.[cm]?tsx?$/.test(file));
521
+ const ts = sources.length ? loadTypescript(repoRoot, HERE) : null;
522
+ if (sources.length && !ts)
523
+ return [found(DB_MIGRATION_DESTRUCTIVE, 'hfs.json', 'destructive migration checks require the TypeScript parser to read be/src references')];
524
+ const references = ts ? sources.map((file) => ({ file, scopes: sourceNameScopes(ts, readText(repoRoot, file) ?? '', file) })) : [];
525
+ return migrations.flatMap((file) => {
526
+ const text = readText(repoRoot, file);
527
+ return text === null ? [] : destructiveFileFindings(file, text, references);
528
+ });
489
529
  }