@starci/hfs 4.11.22 → 4.12.2

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 +31 -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 +95 -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,122 +13,124 @@ import { configuredRecipients } from "./secret-init.mjs";
13
13
  import { envelopeOf, validateMap } from "./secret-document.mjs";
14
14
  import { deleteSealed, fileOf, sealedFiles, writeSecret } from "./secret-store.mjs";
15
15
  import { SecretError } from "./secret-errors.mjs";
16
-
17
16
  /** The provider a key belongs to: its first word (`SEPAY_IPN_SECRET_KEY` is `sepay`, `OPENROUTER_API_KEY` is `openrouter`). */
18
17
  export const providerOf = (key) => key.split("_")[0].toLowerCase();
19
-
20
18
  const sameSet = (left, right) => left.length === right.length && left.every((item) => right.includes(item));
21
19
  const keyList = (keys) => keys.join(", ");
22
-
23
20
  /** The member a `secrets:` entry names: `member`, else the slug of `where`, else its `name`. */
24
21
  const memberOfEntry = (entry) => entry?.member ?? /^secrets\/([a-z0-9-]+)/u.exec(entry?.where ?? "")?.[1] ?? entry?.name;
25
-
26
22
  /** The keys an environment's `secrets:` declares for `member`: an entry naming `key` with that `member`, or a whole-member entry. */
27
23
  function declaredKeys(spec, member, keys) {
28
- const entries = Array.isArray(spec?.secrets) ? spec.secrets : [];
29
- if (entries.some((entry) => entry?.key === undefined && memberOfEntry(entry) === member)) return keys;
30
- return entries.filter((entry) => entry?.key !== undefined && memberOfEntry(entry) === member).map((entry) => entry.key);
24
+ const entries = Array.isArray(spec?.secrets) ? spec.secrets : [];
25
+ if (entries.some((entry) => entry?.key === undefined && memberOfEntry(entry) === member))
26
+ return keys;
27
+ return entries.filter((entry) => entry?.key !== undefined && memberOfEntry(entry) === member).map((entry) => entry.key);
31
28
  }
32
-
33
29
  /** The keys of the one sealed SSH member `deploy.remote.sealed` names (stack/remote.mjs): the deploy transport reads exactly these. */
34
30
  const SSH_GROUP = Object.freeze(["VPS_HOST", "VPS_USER", "privateKey", "knownHosts"]);
35
-
36
31
  /**
37
32
  * True when the stack groups `member` on purpose: every key of it is declared in the environment's `secrets:`, per key (`key` with
38
33
  * `member: <member>`) or in the `keys` list of an entry naming the member, or is a key of the sealed SSH member the deploy names.
39
34
  * A member the owner groups (an app's own keys, the keys one service reads, the VPS session) holds keys of several first words by design.
40
35
  */
41
36
  function declaredGroup(spec, member, keys) {
42
- const entries = Array.isArray(spec?.secrets) ? spec.secrets : [];
43
- const sealed = spec?.deploy?.remote?.sealed;
44
- const ssh = (typeof sealed === "string" ? [sealed] : Object.values(sealed ?? {})).includes(member) ? SSH_GROUP : [];
45
- const declared = (key) => ssh.includes(key) || entries.some((entry) => memberOfEntry(entry) === member
46
- && (entry?.key === key || (Array.isArray(entry?.keys) && entry.keys.includes(key))));
47
- return keys.length > 0 && keys.every(declared);
37
+ const entries = Array.isArray(spec?.secrets) ? spec.secrets : [];
38
+ const sealed = spec?.deploy?.remote?.sealed;
39
+ const ssh = (typeof sealed === "string" ? [sealed] : Object.values(sealed ?? {})).includes(member) ? SSH_GROUP : [];
40
+ const declared = (key) => ssh.includes(key) || entries.some((entry) => memberOfEntry(entry) === member
41
+ && (entry?.key === key || (Array.isArray(entry?.keys) && entry.keys.includes(key))));
42
+ return keys.length > 0 && keys.every(declared);
48
43
  }
49
-
50
44
  /** The tracked member file names of one environment, or null outside a git work tree. */
51
45
  function trackedNames(repoRoot, environment) {
52
- const run = lsFiles(["-z", "--", `.starcistacks/${environment}/secrets`], { cwd: repoRoot, encoding: "utf8" });
53
- if (run.error || run.status !== 0) return null;
54
- return new Set(String(run.stdout).split("\0").filter(Boolean).map((file) => path.posix.basename(file)));
46
+ const run = lsFiles(["-z", "--", `.starcistacks/${environment}/secrets`], { cwd: repoRoot, encoding: "utf8" });
47
+ if (run.error || run.status !== 0)
48
+ return null;
49
+ return new Set(String(run.stdout).split("\0").filter(Boolean).map((file) => path.posix.basename(file)));
55
50
  }
56
-
57
51
  const recipientsFor = (repoRoot, file) => {
58
- try { return configuredRecipients(repoRoot, file); } catch { return []; }
52
+ try {
53
+ return configuredRecipients(repoRoot, file);
54
+ }
55
+ catch {
56
+ return [];
57
+ }
59
58
  };
60
-
61
59
  /**
62
60
  * Every deviation of the app at `repoRoot` (one environment, else each with a secrets folder): LEGACY_MEMBER, MIXED_PROVIDERS,
63
61
  * RECIPIENT_DRIFT, UNDECLARED_KEY (only where application-stacks.yaml declares the environment), UNTRACKED. Names only.
64
62
  */
65
63
  export function auditSecrets(repoRoot, environment = null) {
66
- const stacksFile = path.join(repoRoot, ".starcistacks", "application-stacks.yaml");
67
- const stacks = fs.existsSync(stacksFile) ? parseYaml(fs.readFileSync(stacksFile, "utf8")) ?? {} : {};
68
- const root = path.join(repoRoot, ".starcistacks");
69
- const environments = environment
70
- ? [environment]
71
- : (fs.existsSync(root) ? fs.readdirSync(root, { withFileTypes: true }) : [])
72
- .filter((entry) => entry.isDirectory() && fs.existsSync(path.join(root, entry.name, "secrets")))
73
- .map((entry) => entry.name)
74
- .sort();
75
- const findings = [];
76
- for (const env of environments) {
77
- const directory = path.join(root, env, "secrets");
78
- const spec = stacks.environments?.[env];
79
- const tracked = trackedNames(repoRoot, env);
80
- for (const name of sealedFiles(directory)) {
81
- const member = memberOfName(name);
82
- const file = path.join(directory, name);
83
- const envelope = envelopeOf(fs.readFileSync(file, "utf8"));
84
- const add = (code, detail) => findings.push({ code, env, member: name, detail });
85
- const providers = [...new Set(envelope.keys.map(providerOf))];
86
- if (isLegacyName(name)) add("LEGACY_MEMBER", `is a dotenv .enc member; move it: starci app secret migrate ${env} ${member} [--to <provider>] --execute`);
87
- if (providers.length > 1 && !declaredGroup(spec, member, envelope.keys))
88
- add("MIXED_PROVIDERS", `holds keys of ${providers.length} providers by their first word (${providers.join(", ")}) that the stack does not group in it; split it (starci app secret split ${env} ${member} [--group KEY=member] --execute) or declare its keys in environments.${env}.secrets (an entry naming ${member} with keys: [...])`);
89
- const wanted = recipientsFor(repoRoot, path.join(directory, `${member}${MEMBER_SUFFIX}`));
90
- if (!isLegacyName(name) && wanted.length && !sameSet(wanted, envelope.recipients))
91
- add("RECIPIENT_DRIFT", `is sealed to ${keyList(envelope.recipients)}, its environment's rule names ${keyList(wanted)}; seal it again: starci app secret migrate ${env} ${member} --execute`);
92
- if (spec) {
93
- const declared = declaredKeys(spec, member, envelope.keys);
94
- const missing = envelope.keys.filter((key) => !declared.includes(key));
95
- if (missing.length) add("UNDECLARED_KEY", `holds ${keyList(missing)}, not declared in environments.${env}.secrets of application-stacks.yaml`);
96
- }
97
- if (tracked && !tracked.has(name)) add("UNTRACKED", "is not committed; commit it (it is ciphertext)");
64
+ const stacksFile = path.join(repoRoot, ".starcistacks", "application-stacks.yaml");
65
+ const stacks = fs.existsSync(stacksFile) ? parseYaml(fs.readFileSync(stacksFile, "utf8")) ?? {} : {};
66
+ const root = path.join(repoRoot, ".starcistacks");
67
+ const environments = environment
68
+ ? [environment]
69
+ : (fs.existsSync(root) ? fs.readdirSync(root, { withFileTypes: true }) : [])
70
+ .filter((entry) => entry.isDirectory() && fs.existsSync(path.join(root, entry.name, "secrets")))
71
+ .map((entry) => entry.name)
72
+ .sort();
73
+ const findings = [];
74
+ for (const env of environments) {
75
+ const directory = path.join(root, env, "secrets");
76
+ const spec = stacks.environments?.[env];
77
+ const tracked = trackedNames(repoRoot, env);
78
+ for (const name of sealedFiles(directory)) {
79
+ const member = memberOfName(name);
80
+ const file = path.join(directory, name);
81
+ const envelope = envelopeOf(fs.readFileSync(file, "utf8"));
82
+ const add = (code, detail) => findings.push({ code, env, member: name, detail });
83
+ const providers = [...new Set(envelope.keys.map(providerOf))];
84
+ if (isLegacyName(name))
85
+ add("LEGACY_MEMBER", `is a dotenv .enc member; move it: starci app secret migrate --env ${env} ${member} [--to <provider>] --execute`);
86
+ if (providers.length > 1 && !declaredGroup(spec, member, envelope.keys))
87
+ add("MIXED_PROVIDERS", `holds keys of ${providers.length} providers by their first word (${providers.join(", ")}) that the stack does not group in it; split it (starci app secret split --env ${env} ${member} [--group KEY=member] --execute) or declare its keys in environments.${env}.secrets (an entry naming ${member} with keys: [...])`);
88
+ const wanted = recipientsFor(repoRoot, path.join(directory, `${member}${MEMBER_SUFFIX}`));
89
+ if (!isLegacyName(name) && wanted.length && !sameSet(wanted, envelope.recipients))
90
+ add("RECIPIENT_DRIFT", `is sealed to ${keyList(envelope.recipients)}, its environment's rule names ${keyList(wanted)}; seal it again: starci app secret migrate --env ${env} ${member} --execute`);
91
+ if (spec) {
92
+ const declared = declaredKeys(spec, member, envelope.keys);
93
+ const missing = envelope.keys.filter((key) => !declared.includes(key));
94
+ if (missing.length)
95
+ add("UNDECLARED_KEY", `holds ${keyList(missing)}, not declared in environments.${env}.secrets of application-stacks.yaml`);
96
+ }
97
+ if (tracked && !tracked.has(name))
98
+ add("UNTRACKED", "is not committed; commit it (it is ciphertext)");
99
+ }
100
+ const drift = serverRecipientDrift(repoRoot, env, spec);
101
+ if (drift)
102
+ findings.push({ code: "RECIPIENT_DRIFT", env, member: ".sops.yaml", detail: drift });
103
+ for (const entry of Array.isArray(spec?.secrets) ? spec.secrets : []) {
104
+ const member = entry?.member ?? /^secrets\/([a-z0-9-]+)/u.exec(entry?.where ?? "")?.[1];
105
+ if (member && !fs.existsSync(fileOf(directory, member)))
106
+ findings.push({ code: "MISSING", env, member, detail: `is declared by environments.${env}.secrets ${entry.name} but no ${member}${MEMBER_SUFFIX} is sealed; remove the entry or seal the member` });
107
+ }
98
108
  }
99
- const drift = serverRecipientDrift(repoRoot, env, spec);
100
- if (drift) findings.push({ code: "RECIPIENT_DRIFT", env, member: ".sops.yaml", detail: drift });
101
- for (const entry of Array.isArray(spec?.secrets) ? spec.secrets : []) {
102
- const member = entry?.member ?? /^secrets\/([a-z0-9-]+)/u.exec(entry?.where ?? "")?.[1];
103
- if (member && !fs.existsSync(fileOf(directory, member)))
104
- findings.push({ code: "MISSING", env, member, detail: `is declared by environments.${env}.secrets ${entry.name} but no ${member}${MEMBER_SUFFIX} is sealed; remove the entry or seal the member` });
105
- }
106
- }
107
- return findings;
109
+ return findings;
108
110
  }
109
-
110
111
  const indentOf = (line) => /^ */u.exec(line)[0].length;
111
112
  const meaningful = (line) => line.trim() !== "" && !line.trimStart().startsWith("#");
112
-
113
113
  /** The [from, to) lines of the block under line `at`: every following line indented deeper, or blank, or a comment. */
114
114
  function blockOf(lines, at) {
115
- const indent = indentOf(lines[at]);
116
- let to = at + 1;
117
- let last = at;
118
- for (; to < lines.length && (!meaningful(lines[to]) || indentOf(lines[to]) > indent); to += 1) if (meaningful(lines[to])) last = to;
119
- return { from: at + 1, to: last + 1 };
115
+ const indent = indentOf(lines[at]);
116
+ let to = at + 1;
117
+ let last = at;
118
+ for (; to < lines.length && (!meaningful(lines[to]) || indentOf(lines[to]) > indent); to += 1)
119
+ if (meaningful(lines[to]))
120
+ last = to;
121
+ return { from: at + 1, to: last + 1 };
120
122
  }
121
-
122
123
  /** The line of `key:` among the direct children of a block, or -1. */
123
124
  function childLine(lines, block, key) {
124
- const first = lines.slice(block.from, block.to).find(meaningful);
125
- if (first === undefined) return -1;
126
- const indent = indentOf(first);
127
- for (let at = block.from; at < block.to; at += 1)
128
- if (meaningful(lines[at]) && indentOf(lines[at]) === indent && lines[at].trimStart().startsWith(`${key}:`)) return at;
129
- return -1;
125
+ const first = lines.slice(block.from, block.to).find(meaningful);
126
+ if (first === undefined)
127
+ return -1;
128
+ const indent = indentOf(first);
129
+ for (let at = block.from; at < block.to; at += 1)
130
+ if (meaningful(lines[at]) && indentOf(lines[at]) === indent && lines[at].trimStart().startsWith(`${key}:`))
131
+ return at;
132
+ return -1;
130
133
  }
131
-
132
134
  /**
133
135
  * Declares each of `keys` of `member` in environment `environment`'s `secrets:` of application-stacks.yaml, one entry per key
134
136
  * (`name: <kebab of the key>, member, key, where: secrets/<member>`), so the key is materialized as its own `<KEY>_FILE`. A key
@@ -136,47 +138,57 @@ function childLine(lines, block, key) {
136
138
  * expected document; a shape this edit cannot place returns the keys to declare by hand.
137
139
  */
138
140
  export function declareKeys(repoRoot, environment, member, keys) {
139
- const file = path.join(repoRoot, ".starcistacks", "application-stacks.yaml");
140
- if (!fs.existsSync(file)) return { declared: [], byHand: [] };
141
- const text = fs.readFileSync(file, "utf8");
142
- const document = parseYaml(text) ?? {};
143
- const spec = document.environments?.[environment];
144
- if (!spec) return { declared: [], byHand: [] };
145
- const missing = keys.filter((key) => !declaredKeys(spec, member, keys).includes(key));
146
- if (!missing.length) return { declared: [], byHand: [] };
147
- // A swarm environment's secret is a versioned external secret its stack file names (runtimeName, deploy grants): its
148
- // declaration is wired with the stack, not appended here.
149
- if (spec.runtime === "docker-swarm") return { declared: [], byHand: missing };
150
- const sibling = Object.values(document.environments).flatMap((each) => (Array.isArray(each?.secrets) ? each.secrets : []))[0];
151
- const entries = missing.map((key) => ({
152
- name: key.toLowerCase().replaceAll("_", "-"), member, key, where: `secrets/${member}`,
153
- recipientPolicy: "its environment's rule of the app's managed .sops.yaml",
154
- keyCustody: sibling?.keyCustody ?? "SOPS_AGE_KEY in the harness secret.env",
155
- }));
156
- const newline = text.includes("\r\n") ? "\r\n" : "\n";
157
- const lines = text.replace(/\r\n/gu, "\n").split("\n");
158
- const root = lines.findIndex((line) => /^environments:\s*(?:#.*)?$/u.test(line));
159
- const envLine = root < 0 ? -1 : childLine(lines, blockOf(lines, root), environment);
160
- const secrets = envLine < 0 ? -1 : childLine(lines, blockOf(lines, envLine), "secrets");
161
- if (secrets < 0 || !/^ *secrets:\s*(?:\[\s*\])?\s*(?:#.*)?$/u.test(lines[secrets])) return { declared: [], byHand: missing };
162
- const pad = indentOf(lines[secrets]);
163
- lines[secrets] = `${" ".repeat(pad)}secrets:`;
164
- const items = blockOf(lines, secrets);
165
- const firstItem = lines.slice(items.from, items.to).find(meaningful);
166
- const dash = " ".repeat(firstItem === undefined ? pad + 2 : indentOf(firstItem));
167
- const rendered = entries.flatMap((entry) => Object.entries(entry).map(([name, value], index) => `${dash}${index ? " " : "- "}${name}: ${JSON.stringify(value)}`));
168
- lines.splice(items.to, 0, ...rendered);
169
- const expected = structuredClone(document);
170
- const target = expected.environments[environment];
171
- target.secrets = [...(Array.isArray(target.secrets) ? target.secrets : []), ...entries];
172
- const edited = lines.join(newline);
173
- let parsed;
174
- try { parsed = parseYaml(edited); } catch { parsed = undefined; }
175
- if (JSON.stringify(parsed) !== JSON.stringify(expected)) return { declared: [], byHand: missing };
176
- fs.writeFileSync(file, edited);
177
- return { declared: missing, byHand: [] };
141
+ const file = path.join(repoRoot, ".starcistacks", "application-stacks.yaml");
142
+ if (!fs.existsSync(file))
143
+ return { declared: [], byHand: [] };
144
+ const text = fs.readFileSync(file, "utf8");
145
+ const document = parseYaml(text) ?? {}; // reason: parsed YAML boundary, read from disk
146
+ const spec = document.environments?.[environment];
147
+ if (!spec)
148
+ return { declared: [], byHand: [] };
149
+ const missing = keys.filter((key) => !declaredKeys(spec, member, keys).includes(key));
150
+ if (!missing.length)
151
+ return { declared: [], byHand: [] };
152
+ // A swarm environment's secret is a versioned external secret its stack file names (runtimeName, deploy grants): its
153
+ // declaration is wired with the stack, not appended here.
154
+ if (spec.runtime === "docker-swarm")
155
+ return { declared: [], byHand: missing };
156
+ const sibling = Object.values(document.environments).flatMap((each) => (Array.isArray(each?.secrets) ? each.secrets : []))[0];
157
+ const entries = missing.map((key) => ({
158
+ name: key.toLowerCase().replaceAll("_", "-"), member, key, where: `secrets/${member}`,
159
+ recipientPolicy: "its environment's rule of the app's managed .sops.yaml",
160
+ keyCustody: sibling?.keyCustody ?? "SOPS_AGE_KEY in the harness secret.env",
161
+ }));
162
+ const newline = text.includes("\r\n") ? "\r\n" : "\n";
163
+ const lines = text.replace(/\r\n/gu, "\n").split("\n");
164
+ const root = lines.findIndex((line) => /^environments:\s*(?:#.*)?$/u.test(line));
165
+ const envLine = root < 0 ? -1 : childLine(lines, blockOf(lines, root), environment);
166
+ const secrets = envLine < 0 ? -1 : childLine(lines, blockOf(lines, envLine), "secrets");
167
+ if (secrets < 0 || !/^ *secrets:\s*(?:\[\s*\])?\s*(?:#.*)?$/u.test(lines[secrets]))
168
+ return { declared: [], byHand: missing };
169
+ const pad = indentOf(lines[secrets]);
170
+ lines[secrets] = `${" ".repeat(pad)}secrets:`;
171
+ const items = blockOf(lines, secrets);
172
+ const firstItem = lines.slice(items.from, items.to).find(meaningful);
173
+ const dash = " ".repeat(firstItem === undefined ? pad + 2 : indentOf(firstItem));
174
+ const rendered = entries.flatMap((entry) => Object.entries(entry).map(([name, value], index) => `${dash}${index ? " " : "- "}${name}: ${JSON.stringify(value)}`));
175
+ lines.splice(items.to, 0, ...rendered);
176
+ const expected = structuredClone(document);
177
+ const target = expected.environments[environment];
178
+ target.secrets = [...(Array.isArray(target.secrets) ? target.secrets : []), ...entries];
179
+ const edited = lines.join(newline);
180
+ let parsed;
181
+ try {
182
+ parsed = parseYaml(edited);
183
+ }
184
+ catch {
185
+ parsed = undefined;
186
+ }
187
+ if (JSON.stringify(parsed) !== JSON.stringify(expected))
188
+ return { declared: [], byHand: missing };
189
+ fs.writeFileSync(file, edited);
190
+ return { declared: missing, byHand: [] };
178
191
  }
179
-
180
192
  /**
181
193
  * Records `recipient` as `environments.<environment>.deploy.remote.serverRecipient` of application-stacks.yaml: the public age
182
194
  * recipient of the deploy server's own identity, which `starci app secret server-key` made on the server and audit holds the
@@ -184,196 +196,220 @@ export function declareKeys(repoRoot, environment, member, keys) {
184
196
  * `remote:`, and proves the result parses to the expected document; a shape this edit cannot place is refused.
185
197
  */
186
198
  export function recordServerRecipient(repoRoot, environment, recipient) {
187
- const file = path.join(repoRoot, ".starcistacks", "application-stacks.yaml");
188
- const text = fs.readFileSync(file, "utf8");
189
- const document = parseYaml(text) ?? {};
190
- const newline = text.includes("\r\n") ? "\r\n" : "\n";
191
- const lines = text.replace(/\r\n/gu, "\n").split("\n");
192
- const root = lines.findIndex((line) => /^environments:\s*(?:#.*)?$/u.test(line));
193
- const envLine = root < 0 ? -1 : childLine(lines, blockOf(lines, root), environment);
194
- const deploy = envLine < 0 ? -1 : childLine(lines, blockOf(lines, envLine), "deploy");
195
- const remote = deploy < 0 ? -1 : childLine(lines, blockOf(lines, deploy), "remote");
196
- const unplaced = new SecretError(`cannot record the server recipient in environments.${environment}.deploy.remote of application-stacks.yaml; add serverRecipient: ${recipient} there by hand`);
197
- if (remote < 0 || !/^ *remote:\s*(?:#.*)?$/u.test(lines[remote])) throw unplaced;
198
- const block = blockOf(lines, remote);
199
- const own = childLine(lines, block, "serverRecipient");
200
- const first = lines.slice(block.from, block.to).find(meaningful);
201
- const pad = " ".repeat(first === undefined ? indentOf(lines[remote]) + 2 : indentOf(first));
202
- if (own >= 0) lines[own] = `${pad}serverRecipient: ${recipient}`;
203
- else lines.splice(block.to, 0, `${pad}serverRecipient: ${recipient}`);
204
- const expected = structuredClone(document);
205
- expected.environments[environment].deploy.remote.serverRecipient = recipient;
206
- const edited = lines.join(newline);
207
- let parsed;
208
- try { parsed = parseYaml(edited); } catch { parsed = undefined; }
209
- if (JSON.stringify(parsed) !== JSON.stringify(expected)) throw unplaced;
210
- if (edited !== text) fs.writeFileSync(file, edited);
199
+ const file = path.join(repoRoot, ".starcistacks", "application-stacks.yaml");
200
+ const text = fs.readFileSync(file, "utf8");
201
+ const document = parseYaml(text) ?? {}; // reason: parsed YAML boundary, read from disk
202
+ const newline = text.includes("\r\n") ? "\r\n" : "\n";
203
+ const lines = text.replace(/\r\n/gu, "\n").split("\n");
204
+ const root = lines.findIndex((line) => /^environments:\s*(?:#.*)?$/u.test(line));
205
+ const envLine = root < 0 ? -1 : childLine(lines, blockOf(lines, root), environment);
206
+ const deploy = envLine < 0 ? -1 : childLine(lines, blockOf(lines, envLine), "deploy");
207
+ const remote = deploy < 0 ? -1 : childLine(lines, blockOf(lines, deploy), "remote");
208
+ const unplaced = new SecretError(`cannot record the server recipient in environments.${environment}.deploy.remote of application-stacks.yaml; add serverRecipient: ${recipient} there by hand`);
209
+ if (remote < 0 || !/^ *remote:\s*(?:#.*)?$/u.test(lines[remote]))
210
+ throw unplaced;
211
+ const block = blockOf(lines, remote);
212
+ const own = childLine(lines, block, "serverRecipient");
213
+ const first = lines.slice(block.from, block.to).find(meaningful);
214
+ const pad = " ".repeat(first === undefined ? indentOf(lines[remote]) + 2 : indentOf(first));
215
+ if (own >= 0)
216
+ lines[own] = `${pad}serverRecipient: ${recipient}`;
217
+ else
218
+ lines.splice(block.to, 0, `${pad}serverRecipient: ${recipient}`);
219
+ const expected = structuredClone(document);
220
+ const expectedEnvironment = expected.environments[environment];
221
+ expectedEnvironment.deploy.remote.serverRecipient = recipient;
222
+ const edited = lines.join(newline);
223
+ let parsed;
224
+ try {
225
+ parsed = parseYaml(edited);
226
+ }
227
+ catch {
228
+ parsed = undefined;
229
+ }
230
+ if (JSON.stringify(parsed) !== JSON.stringify(expected))
231
+ throw unplaced;
232
+ if (edited !== text)
233
+ fs.writeFileSync(file, edited);
211
234
  }
212
-
213
235
  /**
214
236
  * The RECIPIENT_DRIFT of an environment's rule against its deploy server: a rule that does not name the recorded
215
237
  * `deploy.remote.serverRecipient` together with another recipient (the owner key), or a production swarm deploy with a remote
216
238
  * and no server recipient recorded. Null when the rule holds.
217
239
  */
218
240
  function serverRecipientDrift(repoRoot, env, spec) {
219
- const remote = spec?.deploy?.remote;
220
- if (!remote || typeof remote !== "object") return null;
221
- const server = remote.serverRecipient;
222
- if (server === undefined)
223
- return env === "production" && spec.runtime === "docker-swarm"
224
- ? `records no deploy server recipient; production is sealed to the server key and the owner key: starci app secret server-key ${env} --execute`
225
- : null;
226
- const rule = recipientsFor(repoRoot, path.join(repoRoot, ".starcistacks", env, "secrets", `member${MEMBER_SUFFIX}`));
227
- if (!rule.includes(server)) return `its rule names ${keyList(rule) || "no recipient"}, not the deploy server recipient ${server}; run starci app secret server-key ${env} --execute`;
228
- if (rule.length < 2) return `its rule names only the deploy server recipient ${server}; add the owner key: starci app secret recipients ${env} --add owner, then starci app secret server-key ${env} --execute`;
229
- return null;
241
+ const remote = spec?.deploy?.remote;
242
+ if (!remote || typeof remote !== "object")
243
+ return null;
244
+ const server = remote.serverRecipient;
245
+ if (server === undefined)
246
+ return env === "production" && spec.runtime === "docker-swarm"
247
+ ? `records no deploy server recipient; production is sealed to the server key and the owner key: starci app secret server-key --env ${env} --execute`
248
+ : null;
249
+ const rule = recipientsFor(repoRoot, path.join(repoRoot, ".starcistacks", env, "secrets", `member${MEMBER_SUFFIX}`));
250
+ if (!rule.includes(server))
251
+ return `its rule names ${keyList(rule) || "no recipient"}, not the deploy server recipient ${server}; run starci app secret server-key --env ${env} --execute`;
252
+ if (rule.length < 2)
253
+ return `its rule names only the deploy server recipient ${server}; add the owner key: starci app secret recipients --env ${env} --add owner --execute, then starci app secret server-key --env ${env} --execute`;
254
+ return null;
230
255
  }
231
-
232
- /** `starci app secret audit [<env>]`: each deviation on its own line and exit 1, else one clean line and exit 0. */
256
+ /** `starci app secret audit [--env <env>]`: each deviation on its own line and exit 1, else one clean line and exit 0. */
233
257
  export function printAudit(repoRoot, environment, stdout) {
234
- const findings = auditSecrets(repoRoot, environment);
235
- for (const finding of findings) stdout(`${finding.code} ${finding.env}/${finding.member}: ${finding.detail}\n`);
236
- if (findings.length) return 1;
237
- stdout(`app secrets follow the standard${environment ? ` in ${environment}` : ""}\n`);
238
- return 0;
258
+ const findings = auditSecrets(repoRoot, environment);
259
+ for (const finding of findings)
260
+ stdout(`${finding.code} ${finding.env}/${finding.member}: ${finding.detail}\n`);
261
+ if (findings.length)
262
+ return 1;
263
+ stdout(`app secrets follow the standard${environment ? ` in ${environment}` : ""}\n`);
264
+ return 0;
239
265
  }
240
-
241
266
  /** Seals `map` as member `<slug>.enc.yaml` to the recipients its environment's rule names; `map` holds every key it keeps. */
242
267
  function sealFresh(directory, slug, map, sops) {
243
- const file = path.join(directory, `${slug}${MEMBER_SUFFIX}`);
244
- writeSecret({ file, values: map, age: [], sops });
245
- return file;
268
+ const file = path.join(directory, `${slug}${MEMBER_SUFFIX}`);
269
+ writeSecret({ file, values: map, age: [], sops });
270
+ return file;
246
271
  }
247
-
248
272
  function plannedMember(directory, member) {
249
- const file = fileOf(directory, member);
250
- if (!fs.existsSync(file)) throw new SecretError(`${member} is not a sealed member of this environment`);
251
- return { file, envelope: envelopeOf(fs.readFileSync(file, "utf8")) };
273
+ const file = fileOf(directory, member);
274
+ if (!fs.existsSync(file))
275
+ throw new SecretError(`${member} is not a sealed member of this environment`);
276
+ return { file, envelope: envelopeOf(fs.readFileSync(file, "utf8")) };
252
277
  }
253
-
254
278
  /**
255
279
  * Each target of a move: its keys, whether it is the source member itself (`own`, re-sealed in place) and whether it is another
256
280
  * member that already exists (`existing`, merged into only with --into-existing, never a legacy one). Refuses before any read.
257
281
  */
258
- function plannedTargets({ directory, environment, file, groups, intoExisting, verb }) {
259
- return [...groups].map(([target, keys]) => {
260
- const resolved = fileOf(directory, target);
261
- const own = resolved === file && !isLegacyName(path.basename(file));
262
- const existing = resolved !== file && fs.existsSync(resolved);
263
- const label = `${environment}/${path.basename(resolved)}`;
264
- if (existing && isLegacyName(path.basename(resolved))) throw new SecretError(`${label} is a legacy member; migrate it first, then merge into it`);
265
- if (existing && !intoExisting) throw new SecretError(`${label} already exists; ${verb} merges into it only with --into-existing`);
266
- const held = existing ? envelopeOf(fs.readFileSync(resolved, "utf8")).keys : [];
267
- const overlap = keys.filter((key) => held.includes(key));
268
- return { target, keys, own, existing, overlap, file: existing ? resolved : path.join(directory, `${target}${MEMBER_SUFFIX}`) };
269
- });
282
+ function plannedTargets({ directory, environment, file, groups, intoExisting, verb, }) {
283
+ return [...groups].map(([target, keys]) => {
284
+ const resolved = fileOf(directory, target);
285
+ const own = resolved === file && !isLegacyName(path.basename(file));
286
+ const existing = resolved !== file && fs.existsSync(resolved);
287
+ const label = `${environment}/${path.basename(resolved)}`;
288
+ if (existing && isLegacyName(path.basename(resolved)))
289
+ throw new SecretError(`${label} is a legacy member; migrate it first, then merge into it`);
290
+ if (existing && !intoExisting)
291
+ throw new SecretError(`${label} already exists; ${verb} merges into it only with --into-existing`);
292
+ const held = existing ? envelopeOf(fs.readFileSync(resolved, "utf8")).keys : [];
293
+ const overlap = keys.filter((key) => held.includes(key));
294
+ return { target, keys, own, existing, overlap, file: existing ? resolved : path.join(directory, `${target}${MEMBER_SUFFIX}`) };
295
+ });
270
296
  }
271
-
272
297
  const planText = (environment, targets) => targets.map(({ target, keys, existing, overlap }) => {
273
- const merge = overlap.length ? `; it already holds ${keyList(overlap)}, which must be identical` : "";
274
- return `${environment}/${target}${MEMBER_SUFFIX} (${keyList(keys)})${existing ? ` merged into the existing member${merge}` : ""}`;
298
+ const merge = overlap.length ? `; it already holds ${keyList(overlap)}, which must be identical` : "";
299
+ return `${environment}/${target}${MEMBER_SUFFIX} (${keyList(keys)})${existing ? ` merged into the existing member${merge}` : ""}`;
275
300
  }).join(", ");
276
-
277
301
  /**
278
302
  * Moves the keys of the source member `file` into `targets`, decrypting in memory only. Every existing target is opened and
279
303
  * checked first: a key it already holds with another value refuses the whole move, naming the keys and never a value. Then
280
304
  * each target is written once, and only after every target is written is the source removed (or, for an own target, the
281
305
  * re-sealed copy staged beside it is moved over it), so no key is ever held by no member.
282
306
  */
283
- function moveKeys({ directory, environment, file, envelope, targets, member, sops }) {
284
- const seam = sops();
285
- const map = seam.decrypt(file, envelope.format);
286
- validateMap(map);
287
- if (!sameSet(Object.keys(map), envelope.keys)) throw new SecretError("sops returned keys that differ from the envelope");
288
- const writes = targets.map((target) => {
289
- const values = Object.fromEntries(target.keys.map((key) => [key, map[key]]));
290
- if (!target.existing) return { target, values, colliding: [] };
291
- const held = seam.decrypt(target.file, envelopeOf(fs.readFileSync(target.file, "utf8")).format);
292
- validateMap(held);
293
- const colliding = target.keys.filter((key) => Object.hasOwn(held, key) && held[key] !== values[key]);
294
- return { target, values: { ...held, ...values }, colliding };
295
- });
296
- const collisions = writes.filter((write) => write.colliding.length);
297
- if (collisions.length)
298
- throw new SecretError(`refused, nothing was written: ${collisions.map(({ target, colliding }) => `${environment}/${path.basename(target.file)} already holds ${keyList(colliding)} with another value`).join("; ")}; rename or unset one side first`);
299
- const staging = `${member}-staged`;
300
- if (targets.some((target) => target.own) && fs.existsSync(fileOf(directory, staging)))
301
- throw new SecretError(`${environment}/${staging}${MEMBER_SUFFIX} exists; remove it before moving ${member}`);
302
- let staged = null;
303
- for (const { target, values } of writes) {
304
- if (target.own) staged = sealFresh(directory, staging, values, seam);
305
- else writeSecret({ file: target.file, values, age: [], sops: seam });
306
- }
307
- if (staged) fs.renameSync(staged, file);
308
- else deleteSealed(file);
307
+ function moveKeys({ directory, environment, file, envelope, targets, member, sops, }) {
308
+ const seam = sops();
309
+ const map = seam.decrypt(file, envelope.format);
310
+ validateMap(map);
311
+ if (!sameSet(Object.keys(map), envelope.keys))
312
+ throw new SecretError("sops returned keys that differ from the envelope");
313
+ const writes = targets.map((target) => {
314
+ const values = Object.fromEntries(target.keys.map((key) => [key, map[key]]));
315
+ if (!target.existing)
316
+ return { target, values, colliding: [] };
317
+ const held = seam.decrypt(target.file, envelopeOf(fs.readFileSync(target.file, "utf8")).format);
318
+ validateMap(held);
319
+ const colliding = target.keys.filter((key) => Object.hasOwn(held, key) && held[key] !== values[key]);
320
+ return { target, values: { ...held, ...values }, colliding };
321
+ });
322
+ const collisions = writes.filter((write) => write.colliding.length);
323
+ if (collisions.length)
324
+ throw new SecretError(`refused, nothing was written: ${collisions.map(({ target, colliding }) => `${environment}/${path.basename(target.file)} already holds ${keyList(colliding)} with another value`).join("; ")}; rename or unset one side first`);
325
+ const staging = `${member}-staged`;
326
+ if (targets.some((target) => target.own) && fs.existsSync(fileOf(directory, staging)))
327
+ throw new SecretError(`${environment}/${staging}${MEMBER_SUFFIX} exists; remove it before moving ${member}`);
328
+ let staged = null;
329
+ for (const { target, values } of writes) {
330
+ if (target.own)
331
+ staged = sealFresh(directory, staging, values, seam);
332
+ else
333
+ writeSecret({ file: target.file, values, age: [], sops: seam });
334
+ }
335
+ if (staged)
336
+ fs.renameSync(staged, file);
337
+ else
338
+ deleteSealed(file);
309
339
  }
310
-
311
340
  /** The `--group-file` YAML map (`KEY: member`) and the `--group KEY=member` entries as one map; a key named twice is refused. */
312
341
  export function groupMap(entries = [], groupFile = null) {
313
- const pairs = [];
314
- if (groupFile) {
315
- if (!fs.existsSync(groupFile)) throw new SecretError(`--group-file ${groupFile} does not exist`);
316
- let document;
317
- try { document = parseYaml(fs.readFileSync(groupFile, "utf8")); } catch { document = undefined; }
318
- if (!document || typeof document !== "object" || Array.isArray(document) || Object.values(document).some((value) => typeof value !== "string"))
319
- throw new SecretError(`--group-file ${groupFile} must be a YAML map of KEY: member`);
320
- pairs.push(...Object.entries(document));
321
- }
322
- for (const entry of entries) {
323
- const at = entry.indexOf("=");
324
- if (at < 1 || !entry.slice(at + 1)) throw new SecretError("--group takes KEY=member");
325
- pairs.push([entry.slice(0, at), entry.slice(at + 1)]);
326
- }
327
- const groups = new Map();
328
- for (const [key, member] of pairs) {
329
- if (groups.has(key)) throw new SecretError(`--group names ${key} twice`);
330
- groups.set(key, member);
331
- }
332
- return groups;
342
+ const pairs = [];
343
+ if (groupFile) {
344
+ if (!fs.existsSync(groupFile))
345
+ throw new SecretError(`--group-file ${groupFile} does not exist`);
346
+ let document; // reason: parsed YAML boundary, read from disk
347
+ try {
348
+ document = parseYaml(fs.readFileSync(groupFile, "utf8"));
349
+ }
350
+ catch {
351
+ document = undefined;
352
+ }
353
+ if (!document || typeof document !== "object" || Array.isArray(document) || Object.values(document).some((value) => typeof value !== "string"))
354
+ throw new SecretError(`--group-file ${groupFile} must be a YAML map of KEY: member`);
355
+ pairs.push(...Object.entries(document));
356
+ }
357
+ for (const entry of entries) {
358
+ const at = entry.indexOf("=");
359
+ if (at < 1 || !entry.slice(at + 1))
360
+ throw new SecretError("--group takes KEY=member");
361
+ pairs.push([entry.slice(0, at), entry.slice(at + 1)]);
362
+ }
363
+ const groups = new Map();
364
+ for (const [key, member] of pairs) {
365
+ if (groups.has(key))
366
+ throw new SecretError(`--group names ${key} twice`);
367
+ groups.set(key, member);
368
+ }
369
+ return groups;
333
370
  }
334
-
335
371
  /**
336
- * `migrate <env> <member> [--to <slug>] [--into-existing] [--execute]`: moves a member (a legacy dotenv `.enc`, one sealed to
372
+ * `migrate --env <env> <member> [--to <slug>] [--into-existing] [--execute]`: moves a member (a legacy dotenv `.enc`, one sealed to
337
373
  * other recipients than its rule, or one whose keys belong to another member) to `<slug>.enc.yaml` sealed to the environment's
338
374
  * recipients, merging into an existing `<slug>` only with --into-existing, then removes the old file. A dry run until --execute.
339
375
  */
340
376
  export function migrateMember({ directory, environment, member, to, intoExisting, execute, sops, stdout }) {
341
- const { file, envelope } = plannedMember(directory, member);
342
- const targets = plannedTargets({ directory, environment, file, groups: new Map([[to ?? member, envelope.keys]]), intoExisting, verb: "migrate" });
343
- const plan = `${environment}/${path.basename(file)} to ${planText(environment, targets)}`;
344
- if (!execute) {
345
- stdout(`dry run: would move ${plan}; add --execute\n`);
377
+ const { file, envelope } = plannedMember(directory, member);
378
+ const targets = plannedTargets({ directory, environment, file, groups: new Map([[to ?? member, envelope.keys]]), intoExisting, verb: "migrate" });
379
+ const plan = `${environment}/${path.basename(file)} to ${planText(environment, targets)}`;
380
+ if (!execute) {
381
+ stdout(`dry run: would move ${plan}; add --execute\n`);
382
+ return 0;
383
+ }
384
+ moveKeys({ directory, environment, file, envelope, targets, member, sops });
385
+ stdout(`moved ${plan}\n`);
346
386
  return 0;
347
- }
348
- moveKeys({ directory, environment, file, envelope, targets, member, sops });
349
- stdout(`moved ${plan}\n`);
350
- return 0;
351
387
  }
352
-
353
388
  /**
354
- * `split <env> <member> [--group KEY=member ...] [--group-file <yaml>] [--into-existing] [--execute]`: divides a member into one
389
+ * `split --env <env> <member> [--group KEY=member ...] [--group-file <yaml>] [--into-existing] [--execute]`: divides a member into one
355
390
  * `<member>.enc.yaml` per group, each sealed to the environment's recipients, then removes the old file. A key's group is its
356
391
  * --group member, else its provider (providerOf); an existing member is merged into only with --into-existing. A dry run until
357
392
  * --execute.
358
393
  */
359
394
  export function splitMember({ directory, environment, member, groups: chosen = new Map(), intoExisting, execute, sops, stdout }) {
360
- const { file, envelope } = plannedMember(directory, member);
361
- const stray = [...chosen.keys()].filter((key) => !envelope.keys.includes(key));
362
- if (stray.length) throw new SecretError(`--group names ${keyList(stray)}, which ${environment}/${member} does not hold`);
363
- const groups = new Map();
364
- for (const key of envelope.keys) {
365
- const group = chosen.get(key) ?? providerOf(key);
366
- groups.set(group, [...(groups.get(group) ?? []), key]);
367
- }
368
- if (groups.size < 2 && groups.has(member))
369
- throw new SecretError(`${environment}/${member} holds one group's keys; nothing to split (migrate renames a member)`);
370
- const targets = plannedTargets({ directory, environment, file, groups, intoExisting, verb: "split" });
371
- const plan = planText(environment, targets);
372
- if (!execute) {
373
- stdout(`dry run: would split ${environment}/${path.basename(file)} into ${plan}; add --execute\n`);
395
+ const { file, envelope } = plannedMember(directory, member);
396
+ const stray = [...chosen.keys()].filter((key) => !envelope.keys.includes(key));
397
+ if (stray.length)
398
+ throw new SecretError(`--group names ${keyList(stray)}, which ${environment}/${member} does not hold`);
399
+ const groups = new Map();
400
+ for (const key of envelope.keys) {
401
+ const group = chosen.get(key) ?? providerOf(key);
402
+ groups.set(group, [...(groups.get(group) ?? []), key]);
403
+ }
404
+ if (groups.size < 2 && groups.has(member))
405
+ throw new SecretError(`${environment}/${member} holds one group's keys; nothing to split (migrate renames a member)`);
406
+ const targets = plannedTargets({ directory, environment, file, groups, intoExisting, verb: "split" });
407
+ const plan = planText(environment, targets);
408
+ if (!execute) {
409
+ stdout(`dry run: would split ${environment}/${path.basename(file)} into ${plan}; add --execute\n`);
410
+ return 0;
411
+ }
412
+ moveKeys({ directory, environment, file, envelope, targets, member, sops });
413
+ stdout(`split ${environment}/${path.basename(file)} into ${plan}\n`);
374
414
  return 0;
375
- }
376
- moveKeys({ directory, environment, file, envelope, targets, member, sops });
377
- stdout(`split ${environment}/${path.basename(file)} into ${plan}\n`);
378
- return 0;
379
415
  }