@starci/hfs 4.11.22 → 4.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1088) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +31 -31
  3. package/ci/cli.d.mts +15 -0
  4. package/ci/cli.mjs +71 -52
  5. package/ci/github.d.mts +43 -0
  6. package/ci/github.mjs +33 -28
  7. package/ci/local.d.mts +12 -0
  8. package/ci/local.mjs +145 -108
  9. package/ci/secret.d.mts +15 -0
  10. package/ci/secret.mjs +31 -21
  11. package/ci/vars.d.mts +17 -0
  12. package/ci/vars.mjs +47 -33
  13. package/ci/verify.d.mts +18 -0
  14. package/ci/verify.mjs +52 -40
  15. package/codemod/button-intent.d.mts +63 -0
  16. package/codemod/button-intent.mjs +338 -285
  17. package/coverage/cli.d.mts +28 -0
  18. package/coverage/cli.mjs +65 -51
  19. package/db/backup-receipt.d.mts +28 -0
  20. package/db/backup-receipt.mjs +78 -58
  21. package/db/drift.d.mts +86 -0
  22. package/db/drift.mjs +213 -180
  23. package/db/dump.d.mts +52 -0
  24. package/db/dump.mjs +63 -56
  25. package/db/entity-list.d.mts +4 -0
  26. package/db/entity-list.mjs +0 -2
  27. package/db/image.d.mts +8 -0
  28. package/db/image.mjs +1 -2
  29. package/db/migrate.d.mts +104 -0
  30. package/db/migrate.mjs +207 -167
  31. package/db/new.d.mts +11 -0
  32. package/db/new.mjs +25 -25
  33. package/db/post-cutover.d.mts +5 -0
  34. package/db/post-cutover.mjs +89 -82
  35. package/db/postgres.d.mts +71 -0
  36. package/db/postgres.mjs +62 -61
  37. package/emit/compiler.d.mts +3 -0
  38. package/emit/compiler.mjs +25 -27
  39. package/emit/contracts.d.mts +35 -0
  40. package/emit/contracts.mjs +46 -50
  41. package/emit/events.d.mts +9 -0
  42. package/emit/events.mjs +19 -20
  43. package/emit/form-bounds.d.mts +83 -0
  44. package/emit/form-bounds.mjs +133 -117
  45. package/emit/graphql-input-bounds.d.mts +63 -0
  46. package/emit/graphql-input-bounds.mjs +90 -79
  47. package/emit/input-bounds.d.mts +30 -0
  48. package/emit/input-bounds.mjs +29 -27
  49. package/emit/operation-schemas.d.mts +24 -0
  50. package/emit/operation-schemas.mjs +136 -116
  51. package/emit/operations-worker.d.mts +1 -0
  52. package/emit/operations-worker.mjs +9 -7
  53. package/emit/operations.d.mts +47 -0
  54. package/emit/operations.mjs +124 -133
  55. package/emit/schema-worker.d.mts +1 -0
  56. package/emit/schema-worker.mjs +57 -50
  57. package/emit/static-graph.d.mts +48 -0
  58. package/emit/static-graph.mjs +766 -640
  59. package/emit/type-schema.d.mts +29 -0
  60. package/emit/type-schema.mjs +153 -140
  61. package/lint/bound-sys.cjs +27 -33
  62. package/lint/chunk.d.mts +17 -0
  63. package/lint/chunk.mjs +41 -31
  64. package/lint/run.d.mts +120 -0
  65. package/lint/run.mjs +414 -325
  66. package/package.json +21 -4
  67. package/release/candidate-ci.d.mts +46 -0
  68. package/release/candidate-ci.mjs +76 -70
  69. package/release/gate.d.mts +120 -0
  70. package/release/gate.mjs +358 -330
  71. package/release/index.d.mts +68 -0
  72. package/release/index.mjs +95 -73
  73. package/release/lint-report.d.mts +14 -0
  74. package/release/lint-report.mjs +33 -32
  75. package/release/push.d.mts +32 -0
  76. package/release/push.mjs +92 -79
  77. package/release/records.d.mts +18 -0
  78. package/release/records.mjs +22 -21
  79. package/release/sonar-quality-gate.d.mts +18 -0
  80. package/release/sonar-quality-gate.mjs +60 -52
  81. package/release/urgent.d.mts +20 -0
  82. package/release/urgent.mjs +76 -74
  83. package/report/order.d.mts +1 -0
  84. package/report/sonar.d.mts +73 -0
  85. package/report/sonar.mjs +82 -89
  86. package/runtime/engine/admission.d.mts +209 -0
  87. package/runtime/engine/admission.mjs +225 -204
  88. package/runtime/engine/by-code-unit.d.mts +5 -0
  89. package/runtime/engine/by-code-unit.mjs +6 -6
  90. package/runtime/engine/config.d.mts +333 -0
  91. package/runtime/engine/config.mjs +486 -328
  92. package/runtime/engine/db/blob.d.mts +83 -0
  93. package/runtime/engine/db/blob.mjs +344 -268
  94. package/runtime/engine/db/event-compact.d.mts +21 -0
  95. package/runtime/engine/db/event-compact.mjs +34 -38
  96. package/runtime/engine/db/machine-connection.d.mts +68 -0
  97. package/runtime/engine/db/machine-connection.mjs +166 -119
  98. package/runtime/engine/db/machine-open.d.mts +26 -0
  99. package/runtime/engine/db/machine-open.mjs +59 -45
  100. package/runtime/engine/db/machine-schema.d.mts +34 -0
  101. package/runtime/engine/db/machine-schema.mjs +102 -83
  102. package/runtime/engine/db/machine.d.mts +1746 -0
  103. package/runtime/engine/db/machine.mjs +1040 -734
  104. package/runtime/engine/db/provider-reservations.d.mts +169 -0
  105. package/runtime/engine/db/provider-reservations.mjs +141 -119
  106. package/runtime/engine/db/provision-lock.d.mts +23 -0
  107. package/runtime/engine/db/provision-lock.mjs +14 -14
  108. package/runtime/engine/db/ref-value.d.mts +19 -0
  109. package/runtime/engine/db/ref-value.mjs +36 -35
  110. package/runtime/engine/db/sqlite-types.d.mts +28 -0
  111. package/runtime/engine/db/sqlite-types.mjs +4 -0
  112. package/runtime/engine/digest.d.mts +4 -0
  113. package/runtime/engine/digest.mjs +16 -7
  114. package/runtime/engine/invalid-config.d.mts +13 -0
  115. package/runtime/engine/invalid-config.mjs +17 -11
  116. package/runtime/engine/model-config.d.mts +91 -0
  117. package/runtime/engine/model-config.mjs +98 -76
  118. package/runtime/engine/orca-config.d.mts +26 -0
  119. package/runtime/engine/orca-config.mjs +22 -17
  120. package/runtime/engine/plain-object.d.mts +2 -0
  121. package/runtime/engine/refuse.d.mts +9 -0
  122. package/runtime/engine/refuse.mjs +3 -6
  123. package/runtime/engine/release-config.d.mts +19 -0
  124. package/runtime/engine/release-config.mjs +22 -18
  125. package/runtime/engine/removed-vocabulary.d.mts +12 -0
  126. package/runtime/engine/removed-vocabulary.mjs +21 -20
  127. package/runtime/engine/resources-config.d.mts +34 -0
  128. package/runtime/engine/resources-config.mjs +42 -35
  129. package/runtime/engine/runtime-root.d.mts +28 -0
  130. package/runtime/engine/runtime-root.mjs +11 -13
  131. package/runtime/engine/secrets.d.mts +41 -0
  132. package/runtime/engine/secrets.mjs +170 -102
  133. package/runtime/engine/sonar-config.d.mts +10 -0
  134. package/runtime/engine/sonar-config.mjs +16 -13
  135. package/runtime/engine/temp-root.d.mts +17 -0
  136. package/runtime/engine/temp-root.mjs +3 -9
  137. package/runtime/engine/yaml.d.mts +9 -0
  138. package/runtime/knowledge/hfs/canon-pins.yaml +10 -10
  139. package/runtime/knowledge/hfs/ci-standard.yaml +2 -2
  140. package/runtime/knowledge/hfs/rules.yaml +72 -6
  141. package/runtime/knowledge/hfs/slots.yaml +3 -3
  142. package/runtime/knowledge/sonar-gate.yaml +1 -1
  143. package/runtime/modules/kernel/failure-codes.yaml +43 -32
  144. package/runtime/modules/schemas/application-stacks.schema.yaml +3 -3
  145. package/runtime/packages/cli/src/catalog.generated.d.mts +13 -0
  146. package/runtime/packages/cli/src/catalog.generated.mjs +1853 -14824
  147. package/runtime/packages/cli/src/validate-args.d.mts +74 -0
  148. package/runtime/packages/cli/src/validate-args.mjs +183 -171
  149. package/runtime/packages/jest-preset/sonar-exclusions.cjs +5 -5
  150. package/runtime/scripts/api/fs/claim-file.d.mts +12 -0
  151. package/runtime/scripts/api/fs/claim-file.mjs +31 -17
  152. package/runtime/scripts/api/fs/ensure-temp-root.d.mts +4 -0
  153. package/runtime/scripts/api/fs/ensure-temp-root.mjs +15 -14
  154. package/runtime/scripts/api/fs/forbidden-root.d.mts +15 -0
  155. package/runtime/scripts/api/fs/forbidden-root.mjs +31 -23
  156. package/runtime/scripts/api/fs/is-link-like.d.mts +10 -0
  157. package/runtime/scripts/api/fs/is-link-like.mjs +25 -11
  158. package/runtime/scripts/api/fs/lib.d.mts +12 -0
  159. package/runtime/scripts/api/fs/lib.mjs +28 -8
  160. package/runtime/scripts/api/fs/make-temp-dir.d.mts +5 -0
  161. package/runtime/scripts/api/fs/make-temp-dir.mjs +3 -4
  162. package/runtime/scripts/api/fs/rename-over.d.mts +13 -0
  163. package/runtime/scripts/api/fs/rename-over.mjs +16 -10
  164. package/runtime/scripts/api/fs/safe-remove.d.mts +25 -0
  165. package/runtime/scripts/api/fs/safe-remove.mjs +129 -71
  166. package/runtime/scripts/api/git/add.d.mts +3 -0
  167. package/runtime/scripts/api/git/add.mjs +0 -1
  168. package/runtime/scripts/api/git/cat-file.d.mts +3 -0
  169. package/runtime/scripts/api/git/cat-file.mjs +0 -1
  170. package/runtime/scripts/api/git/check-ignore.d.mts +3 -0
  171. package/runtime/scripts/api/git/check-ignore.mjs +0 -1
  172. package/runtime/scripts/api/git/commit-tree.d.mts +3 -0
  173. package/runtime/scripts/api/git/commit-tree.mjs +0 -1
  174. package/runtime/scripts/api/git/config-get.d.mts +10 -0
  175. package/runtime/scripts/api/git/config-get.mjs +1 -2
  176. package/runtime/scripts/api/git/diff.d.mts +3 -0
  177. package/runtime/scripts/api/git/diff.mjs +0 -1
  178. package/runtime/scripts/api/git/init.d.mts +7 -0
  179. package/runtime/scripts/api/git/init.mjs +1 -2
  180. package/runtime/scripts/api/git/is-ancestor.d.mts +5 -0
  181. package/runtime/scripts/api/git/is-ancestor.mjs +0 -1
  182. package/runtime/scripts/api/git/lib.d.mts +67 -0
  183. package/runtime/scripts/api/git/lib.mjs +32 -32
  184. package/runtime/scripts/api/git/ls-files.d.mts +3 -0
  185. package/runtime/scripts/api/git/ls-files.mjs +0 -1
  186. package/runtime/scripts/api/git/ls-tree.d.mts +3 -0
  187. package/runtime/scripts/api/git/ls-tree.mjs +0 -1
  188. package/runtime/scripts/api/git/merge-base.d.mts +5 -0
  189. package/runtime/scripts/api/git/merge-base.mjs +2 -3
  190. package/runtime/scripts/api/git/remote.d.mts +3 -0
  191. package/runtime/scripts/api/git/remote.mjs +0 -1
  192. package/runtime/scripts/api/git/rev-parse-query.d.mts +3 -0
  193. package/runtime/scripts/api/git/rev-parse-query.mjs +0 -1
  194. package/runtime/scripts/api/git/show.d.mts +3 -0
  195. package/runtime/scripts/api/git/show.mjs +0 -1
  196. package/runtime/scripts/api/git/tag.d.mts +3 -0
  197. package/runtime/scripts/api/git/tag.mjs +0 -1
  198. package/runtime/scripts/api/git/update-ref.d.mts +7 -0
  199. package/runtime/scripts/api/git/update-ref.mjs +1 -2
  200. package/runtime/scripts/api/git/write-tree.d.mts +3 -0
  201. package/runtime/scripts/api/git/write-tree.mjs +0 -1
  202. package/runtime/scripts/api/node/lib.d.mts +7 -0
  203. package/runtime/scripts/api/node/lib.mjs +17 -7
  204. package/runtime/scripts/api/node/run-node.d.mts +3 -0
  205. package/runtime/scripts/api/node/run-node.mjs +0 -3
  206. package/runtime/scripts/api/process/resolve-real-tool.d.mts +12 -0
  207. package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -38
  208. package/runtime/scripts/api/process/run-program.d.mts +3 -0
  209. package/runtime/scripts/api/process/run-program.mjs +5 -2
  210. package/runtime/scripts/api/sops/decrypt.d.mts +9 -0
  211. package/runtime/scripts/api/sops/decrypt.mjs +1 -2
  212. package/runtime/scripts/api/sops/lib.d.mts +149 -0
  213. package/runtime/scripts/api/sops/lib.mjs +417 -318
  214. package/runtime/scripts/api/sops/resolve-sops.d.mts +3 -0
  215. package/runtime/scripts/api/sops/resolve-sops.mjs +1 -2
  216. package/runtime/scripts/api/sops/seal.d.mts +19 -0
  217. package/runtime/scripts/api/sops/seal.mjs +14 -10
  218. package/runtime/scripts/api/sops/selected-age-recipient.d.mts +3 -0
  219. package/runtime/scripts/api/sops/selected-age-recipient.mjs +1 -2
  220. package/runtime/scripts/api/sops/update-keys.d.mts +16 -0
  221. package/runtime/scripts/api/sops/update-keys.mjs +11 -8
  222. package/runtime/scripts/cli/gen-catalog.d.mts +42 -0
  223. package/runtime/scripts/cli/gen-catalog.mjs +72 -0
  224. package/runtime/scripts/gates/runtime-host.d.mts +23 -0
  225. package/runtime/scripts/gates/runtime-host.mjs +48 -41
  226. package/runtime/scripts/gates/sonar-gate.d.mts +219 -0
  227. package/runtime/scripts/gates/sonar-gate.mjs +166 -153
  228. package/runtime/scripts/gates/starcistacks-ci.d.mts +35 -0
  229. package/runtime/scripts/gates/starcistacks-ci.mjs +47 -39
  230. package/runtime/scripts/gates/starcistacks-form.d.mts +80 -0
  231. package/runtime/scripts/gates/starcistacks-form.mjs +16 -14
  232. package/runtime/scripts/gates/starcistacks-runtime.d.mts +1 -0
  233. package/runtime/scripts/gates/starcistacks-value-file.d.mts +2 -0
  234. package/runtime/scripts/gates/starcistacks-value-file.mjs +14 -11
  235. package/runtime/scripts/gates/starcistacks.d.mts +141 -0
  236. package/runtime/scripts/gates/starcistacks.mjs +470 -355
  237. package/runtime/scripts/guards/git-pathspec.d.mts +48 -0
  238. package/runtime/scripts/guards/git-pathspec.mjs +215 -130
  239. package/runtime/scripts/guards/git-policy.d.mts +30 -0
  240. package/runtime/scripts/guards/git-policy.mjs +278 -235
  241. package/runtime/scripts/guards/hook-io.d.mts +22 -0
  242. package/runtime/scripts/guards/hook-io.mjs +77 -63
  243. package/runtime/scripts/guards/push-scan.d.mts +31 -0
  244. package/runtime/scripts/guards/push-scan.mjs +93 -80
  245. package/runtime/scripts/guards/release-push-gate.d.mts +22 -0
  246. package/runtime/scripts/guards/release-push-gate.mjs +40 -38
  247. package/runtime/scripts/hfs/allows.d.mts +24 -0
  248. package/runtime/scripts/hfs/allows.mjs +37 -38
  249. package/runtime/scripts/hfs/app-wiring.d.mts +72 -0
  250. package/runtime/scripts/hfs/app-wiring.mjs +197 -167
  251. package/runtime/scripts/hfs/architecture/ast-walks.d.mts +89 -0
  252. package/runtime/scripts/hfs/architecture/ast-walks.mjs +180 -163
  253. package/runtime/scripts/hfs/architecture/automatic-gates.d.mts +21 -0
  254. package/runtime/scripts/hfs/architecture/automatic-gates.mjs +80 -73
  255. package/runtime/scripts/hfs/architecture/backend-app-files.d.mts +10 -0
  256. package/runtime/scripts/hfs/architecture/backend-app-files.mjs +88 -77
  257. package/runtime/scripts/hfs/architecture/backend.d.mts +5 -0
  258. package/runtime/scripts/hfs/architecture/backend.mjs +378 -357
  259. package/runtime/scripts/hfs/architecture/background-unowned.d.mts +25 -0
  260. package/runtime/scripts/hfs/architecture/background-unowned.mjs +201 -187
  261. package/runtime/scripts/hfs/architecture/canon-clones.d.mts +8 -0
  262. package/runtime/scripts/hfs/architecture/canon-clones.mjs +260 -209
  263. package/runtime/scripts/hfs/architecture/canon-jsx-clones.d.mts +5 -0
  264. package/runtime/scripts/hfs/architecture/canon-jsx-clones.mjs +149 -116
  265. package/runtime/scripts/hfs/architecture/client-reaches-server.d.mts +28 -0
  266. package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +72 -68
  267. package/runtime/scripts/hfs/architecture/clones.d.mts +54 -0
  268. package/runtime/scripts/hfs/architecture/clones.mjs +212 -217
  269. package/runtime/scripts/hfs/architecture/config-unread.d.mts +14 -0
  270. package/runtime/scripts/hfs/architecture/config-unread.mjs +7 -9
  271. package/runtime/scripts/hfs/architecture/config.d.mts +74 -0
  272. package/runtime/scripts/hfs/architecture/config.mjs +302 -268
  273. package/runtime/scripts/hfs/architecture/connection-map.d.mts +33 -0
  274. package/runtime/scripts/hfs/architecture/connection-map.mjs +258 -225
  275. package/runtime/scripts/hfs/architecture/constructor-deps.d.mts +57 -0
  276. package/runtime/scripts/hfs/architecture/constructor-deps.mjs +80 -71
  277. package/runtime/scripts/hfs/architecture/context-coupling.d.mts +21 -0
  278. package/runtime/scripts/hfs/architecture/context-coupling.mjs +82 -77
  279. package/runtime/scripts/hfs/architecture/context-map.d.mts +102 -0
  280. package/runtime/scripts/hfs/architecture/context-map.mjs +267 -234
  281. package/runtime/scripts/hfs/architecture/context-owner.d.mts +15 -0
  282. package/runtime/scripts/hfs/architecture/context-owner.mjs +73 -61
  283. package/runtime/scripts/hfs/architecture/context-platform-tables.d.mts +18 -0
  284. package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -43
  285. package/runtime/scripts/hfs/architecture/context-transaction.d.mts +20 -0
  286. package/runtime/scripts/hfs/architecture/context-transaction.mjs +54 -52
  287. package/runtime/scripts/hfs/architecture/contract-fixture-guard.d.mts +37 -0
  288. package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +113 -104
  289. package/runtime/scripts/hfs/architecture/contracts-readonly.d.mts +32 -0
  290. package/runtime/scripts/hfs/architecture/contracts-readonly.mjs +288 -270
  291. package/runtime/scripts/hfs/architecture/contracts.d.mts +30 -0
  292. package/runtime/scripts/hfs/architecture/contracts.mjs +408 -393
  293. package/runtime/scripts/hfs/architecture/cross-app-duplicate.d.mts +27 -0
  294. package/runtime/scripts/hfs/architecture/cross-app-duplicate.mjs +50 -51
  295. package/runtime/scripts/hfs/architecture/dead-exports-bindings.d.mts +21 -0
  296. package/runtime/scripts/hfs/architecture/dead-exports-bindings.mjs +143 -119
  297. package/runtime/scripts/hfs/architecture/dead-exports.d.mts +32 -0
  298. package/runtime/scripts/hfs/architecture/dead-exports.mjs +286 -228
  299. package/runtime/scripts/hfs/architecture/default-deny.d.mts +21 -0
  300. package/runtime/scripts/hfs/architecture/default-deny.mjs +129 -110
  301. package/runtime/scripts/hfs/architecture/doc-language.d.mts +17 -0
  302. package/runtime/scripts/hfs/architecture/doc-language.mjs +24 -19
  303. package/runtime/scripts/hfs/architecture/entity-registry.d.mts +49 -0
  304. package/runtime/scripts/hfs/architecture/entity-registry.mjs +20 -22
  305. package/runtime/scripts/hfs/architecture/entrypoint.d.mts +13 -0
  306. package/runtime/scripts/hfs/architecture/entrypoint.mjs +47 -45
  307. package/runtime/scripts/hfs/architecture/error-codes.d.mts +16 -0
  308. package/runtime/scripts/hfs/architecture/error-codes.mjs +37 -35
  309. package/runtime/scripts/hfs/architecture/error-masked.d.mts +16 -0
  310. package/runtime/scripts/hfs/architecture/error-masked.mjs +55 -59
  311. package/runtime/scripts/hfs/architecture/fe-slot-allows.d.mts +38 -0
  312. package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +24 -23
  313. package/runtime/scripts/hfs/architecture/feature-shape.d.mts +26 -0
  314. package/runtime/scripts/hfs/architecture/feature-shape.mjs +40 -38
  315. package/runtime/scripts/hfs/architecture/framework-pinned.d.mts +3 -0
  316. package/runtime/scripts/hfs/architecture/framework-pinned.mjs +21 -21
  317. package/runtime/scripts/hfs/architecture/frontend-block-render.d.mts +26 -0
  318. package/runtime/scripts/hfs/architecture/frontend-block-render.mjs +106 -98
  319. package/runtime/scripts/hfs/architecture/frontend-grammar.d.mts +7 -0
  320. package/runtime/scripts/hfs/architecture/frontend-grammar.mjs +153 -150
  321. package/runtime/scripts/hfs/architecture/frontend-routing.d.mts +23 -0
  322. package/runtime/scripts/hfs/architecture/frontend-routing.mjs +161 -149
  323. package/runtime/scripts/hfs/architecture/frontend-world-render.d.mts +72 -0
  324. package/runtime/scripts/hfs/architecture/frontend-world-render.mjs +343 -305
  325. package/runtime/scripts/hfs/architecture/frontend-world.d.mts +94 -0
  326. package/runtime/scripts/hfs/architecture/frontend-world.mjs +340 -294
  327. package/runtime/scripts/hfs/architecture/frontend.d.mts +31 -0
  328. package/runtime/scripts/hfs/architecture/frontend.mjs +174 -184
  329. package/runtime/scripts/hfs/architecture/function-spec-providers.d.mts +27 -0
  330. package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +124 -106
  331. package/runtime/scripts/hfs/architecture/hfs-graph.d.mts +78 -0
  332. package/runtime/scripts/hfs/architecture/hfs-graph.mjs +52 -48
  333. package/runtime/scripts/hfs/architecture/hfs.d.mts +135 -0
  334. package/runtime/scripts/hfs/architecture/hfs.mjs +328 -282
  335. package/runtime/scripts/hfs/architecture/hooks-are-hooks.d.mts +24 -0
  336. package/runtime/scripts/hfs/architecture/hooks-are-hooks.mjs +81 -71
  337. package/runtime/scripts/hfs/architecture/i18n-keys.d.mts +31 -0
  338. package/runtime/scripts/hfs/architecture/i18n-keys.mjs +155 -141
  339. package/runtime/scripts/hfs/architecture/identity.d.mts +7 -0
  340. package/runtime/scripts/hfs/architecture/identity.mjs +141 -125
  341. package/runtime/scripts/hfs/architecture/index.d.mts +101 -0
  342. package/runtime/scripts/hfs/architecture/index.mjs +272 -272
  343. package/runtime/scripts/hfs/architecture/injection-token-exported.d.mts +21 -0
  344. package/runtime/scripts/hfs/architecture/injection-token-exported.mjs +45 -43
  345. package/runtime/scripts/hfs/architecture/jwt-ast.d.mts +16 -0
  346. package/runtime/scripts/hfs/architecture/jwt-ast.mjs +195 -176
  347. package/runtime/scripts/hfs/architecture/machine-ast.d.mts +88 -0
  348. package/runtime/scripts/hfs/architecture/machine-ast.mjs +163 -155
  349. package/runtime/scripts/hfs/architecture/managed-scripts.d.mts +2 -0
  350. package/runtime/scripts/hfs/architecture/managed-scripts.mjs +19 -20
  351. package/runtime/scripts/hfs/architecture/module-per-transport.d.mts +35 -0
  352. package/runtime/scripts/hfs/architecture/module-per-transport.mjs +177 -172
  353. package/runtime/scripts/hfs/architecture/next-data-contract.d.mts +35 -0
  354. package/runtime/scripts/hfs/architecture/next-data-contract.mjs +100 -78
  355. package/runtime/scripts/hfs/architecture/next-data-inference.d.mts +39 -0
  356. package/runtime/scripts/hfs/architecture/next-data-inference.mjs +170 -154
  357. package/runtime/scripts/hfs/architecture/next-data-key.d.mts +50 -0
  358. package/runtime/scripts/hfs/architecture/next-data-key.mjs +311 -275
  359. package/runtime/scripts/hfs/architecture/next-data-symbols.d.mts +5 -0
  360. package/runtime/scripts/hfs/architecture/next-data-symbols.mjs +17 -17
  361. package/runtime/scripts/hfs/architecture/next-data.d.mts +36 -0
  362. package/runtime/scripts/hfs/architecture/next-data.mjs +351 -334
  363. package/runtime/scripts/hfs/architecture/operation-contract-roots.d.mts +10 -0
  364. package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +39 -37
  365. package/runtime/scripts/hfs/architecture/owners.d.mts +5 -0
  366. package/runtime/scripts/hfs/architecture/owners.mjs +97 -98
  367. package/runtime/scripts/hfs/architecture/package-shape.d.mts +26 -0
  368. package/runtime/scripts/hfs/architecture/package-shape.mjs +56 -55
  369. package/runtime/scripts/hfs/architecture/presentation.d.mts +24 -0
  370. package/runtime/scripts/hfs/architecture/presentation.mjs +138 -130
  371. package/runtime/scripts/hfs/architecture/reachability.d.mts +25 -0
  372. package/runtime/scripts/hfs/architecture/reachability.mjs +258 -241
  373. package/runtime/scripts/hfs/architecture/register-once.d.mts +18 -0
  374. package/runtime/scripts/hfs/architecture/register-once.mjs +152 -139
  375. package/runtime/scripts/hfs/architecture/registration.d.mts +15 -0
  376. package/runtime/scripts/hfs/architecture/registration.mjs +301 -267
  377. package/runtime/scripts/hfs/architecture/required-files.d.mts +64 -0
  378. package/runtime/scripts/hfs/architecture/required-files.mjs +172 -167
  379. package/runtime/scripts/hfs/architecture/route-files-thin.d.mts +23 -0
  380. package/runtime/scripts/hfs/architecture/route-files-thin.mjs +85 -77
  381. package/runtime/scripts/hfs/architecture/schema-owner.d.mts +34 -0
  382. package/runtime/scripts/hfs/architecture/schema-owner.mjs +206 -181
  383. package/runtime/scripts/hfs/architecture/server-action.d.mts +22 -0
  384. package/runtime/scripts/hfs/architecture/server-action.mjs +48 -48
  385. package/runtime/scripts/hfs/architecture/side-boundary.d.mts +3 -0
  386. package/runtime/scripts/hfs/architecture/side-boundary.mjs +2 -5
  387. package/runtime/scripts/hfs/architecture/source-names-shape.d.mts +85 -0
  388. package/runtime/scripts/hfs/architecture/source-names-shape.mjs +261 -259
  389. package/runtime/scripts/hfs/architecture/source-names.d.mts +7 -0
  390. package/runtime/scripts/hfs/architecture/source-names.mjs +304 -278
  391. package/runtime/scripts/hfs/architecture/sql-keys.d.mts +5 -0
  392. package/runtime/scripts/hfs/architecture/sql-keys.mjs +277 -194
  393. package/runtime/scripts/hfs/architecture/sql-owner.d.mts +30 -0
  394. package/runtime/scripts/hfs/architecture/sql-owner.mjs +236 -194
  395. package/runtime/scripts/hfs/architecture/sql-returning.d.mts +22 -0
  396. package/runtime/scripts/hfs/architecture/sql-returning.mjs +46 -45
  397. package/runtime/scripts/hfs/architecture/sql-token-forms.d.mts +21 -0
  398. package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +86 -74
  399. package/runtime/scripts/hfs/architecture/sql-tokens.d.mts +32 -0
  400. package/runtime/scripts/hfs/architecture/sql-tokens.mjs +456 -341
  401. package/runtime/scripts/hfs/architecture/staged-consumers.d.mts +7 -0
  402. package/runtime/scripts/hfs/architecture/staged-consumers.mjs +35 -30
  403. package/runtime/scripts/hfs/architecture/surface.d.mts +26 -0
  404. package/runtime/scripts/hfs/architecture/surface.mjs +64 -74
  405. package/runtime/scripts/hfs/architecture/symbols.d.mts +11 -0
  406. package/runtime/scripts/hfs/architecture/symbols.mjs +209 -216
  407. package/runtime/scripts/hfs/architecture/test-world-files.d.mts +45 -0
  408. package/runtime/scripts/hfs/architecture/test-world-files.mjs +165 -155
  409. package/runtime/scripts/hfs/architecture/tiers.d.mts +29 -0
  410. package/runtime/scripts/hfs/architecture/tiers.mjs +161 -154
  411. package/runtime/scripts/hfs/architecture/transport-owner.d.mts +37 -0
  412. package/runtime/scripts/hfs/architecture/transport-owner.mjs +155 -149
  413. package/runtime/scripts/hfs/architecture/type-context.d.mts +60 -0
  414. package/runtime/scripts/hfs/architecture/type-context.mjs +255 -250
  415. package/runtime/scripts/hfs/architecture/typescript.d.mts +94 -0
  416. package/runtime/scripts/hfs/architecture/typescript.mjs +358 -318
  417. package/runtime/scripts/hfs/architecture/unit-spec-providers.d.mts +34 -0
  418. package/runtime/scripts/hfs/architecture/unit-spec-providers.mjs +110 -92
  419. package/runtime/scripts/hfs/architecture.d.mts +13 -0
  420. package/runtime/scripts/hfs/architecture.mjs +39 -29
  421. package/runtime/scripts/hfs/canon-pins.d.mts +26 -0
  422. package/runtime/scripts/hfs/canon-pins.mjs +5 -8
  423. package/runtime/scripts/hfs/catalog-once.d.mts +2 -0
  424. package/runtime/scripts/hfs/catalog-once.mjs +8 -9
  425. package/runtime/scripts/hfs/check-results.d.mts +29 -0
  426. package/runtime/scripts/hfs/check-results.mjs +14 -18
  427. package/runtime/scripts/hfs/check.d.mts +144 -0
  428. package/runtime/scripts/hfs/check.mjs +309 -329
  429. package/runtime/scripts/hfs/ci-declaration.d.mts +77 -0
  430. package/runtime/scripts/hfs/ci-declaration.mjs +99 -87
  431. package/runtime/scripts/hfs/coverage-from.d.mts +22 -0
  432. package/runtime/scripts/hfs/coverage-from.mjs +52 -49
  433. package/runtime/scripts/hfs/coverage-scope.d.mts +87 -0
  434. package/runtime/scripts/hfs/coverage-scope.mjs +139 -142
  435. package/runtime/scripts/hfs/db-baseline-verb.d.mts +84 -0
  436. package/runtime/scripts/hfs/db-baseline-verb.mjs +327 -266
  437. package/runtime/scripts/hfs/db-errors.d.mts +2 -0
  438. package/runtime/scripts/hfs/db-errors.mjs +2 -1
  439. package/runtime/scripts/hfs/db-plan-verb.d.mts +33 -0
  440. package/runtime/scripts/hfs/db-plan-verb.mjs +174 -128
  441. package/runtime/scripts/hfs/db-restamp-verb.d.mts +5 -0
  442. package/runtime/scripts/hfs/db-restamp-verb.mjs +94 -70
  443. package/runtime/scripts/hfs/db-squash.d.mts +117 -0
  444. package/runtime/scripts/hfs/db-squash.mjs +414 -351
  445. package/runtime/scripts/hfs/declaration-shape.d.mts +3 -0
  446. package/runtime/scripts/hfs/declaration-shape.mjs +140 -103
  447. package/runtime/scripts/hfs/declaration-slots.d.mts +18 -0
  448. package/runtime/scripts/hfs/declaration-slots.mjs +64 -61
  449. package/runtime/scripts/hfs/doc-commands.d.mts +71 -0
  450. package/runtime/scripts/hfs/doc-commands.mjs +257 -250
  451. package/runtime/scripts/hfs/edition-slots.d.mts +37 -0
  452. package/runtime/scripts/hfs/edition-slots.mjs +43 -40
  453. package/runtime/scripts/hfs/example-secrets.d.mts +18 -0
  454. package/runtime/scripts/hfs/example-secrets.mjs +173 -154
  455. package/runtime/scripts/hfs/gate-threshold.d.mts +20 -0
  456. package/runtime/scripts/hfs/gate-threshold.mjs +14 -22
  457. package/runtime/scripts/hfs/grammar-presentation.d.mts +74 -0
  458. package/runtime/scripts/hfs/grammar-presentation.mjs +109 -106
  459. package/runtime/scripts/hfs/linear-text.d.mts +6 -0
  460. package/runtime/scripts/hfs/linear-text.mjs +20 -20
  461. package/runtime/scripts/hfs/manifest-shape.d.mts +216 -0
  462. package/runtime/scripts/hfs/manifest-shape.mjs +399 -324
  463. package/runtime/scripts/hfs/param-names.d.mts +3 -0
  464. package/runtime/scripts/hfs/param-names.mjs +6 -11
  465. package/runtime/scripts/hfs/path-findings.d.mts +22 -0
  466. package/runtime/scripts/hfs/path-findings.mjs +120 -100
  467. package/runtime/scripts/hfs/pin-findings.d.mts +19 -0
  468. package/runtime/scripts/hfs/pin-findings.mjs +26 -21
  469. package/runtime/scripts/hfs/refusal-codes.d.mts +1 -0
  470. package/runtime/scripts/hfs/refusal-codes.mjs +2 -2
  471. package/runtime/scripts/hfs/repo-identity.d.mts +15 -0
  472. package/runtime/scripts/hfs/repo-identity.mjs +55 -42
  473. package/runtime/scripts/hfs/rule-catalog.d.mts +77 -0
  474. package/runtime/scripts/hfs/rule-catalog.mjs +353 -257
  475. package/runtime/scripts/hfs/rule-params-shape.d.mts +10 -0
  476. package/runtime/scripts/hfs/rule-params-shape.mjs +60 -47
  477. package/runtime/scripts/hfs/rules/a15-findings.d.mts +18 -0
  478. package/runtime/scripts/hfs/rules/a15-findings.mjs +59 -55
  479. package/runtime/scripts/hfs/rules/app-env-required.d.mts +9 -0
  480. package/runtime/scripts/hfs/rules/app-env-required.mjs +13 -13
  481. package/runtime/scripts/hfs/rules/app-root.d.mts +15 -0
  482. package/runtime/scripts/hfs/rules/app-root.mjs +20 -21
  483. package/runtime/scripts/hfs/rules/app-workflow-findings.d.mts +12 -0
  484. package/runtime/scripts/hfs/rules/app-workflow-findings.mjs +4 -4
  485. package/runtime/scripts/hfs/rules/assets.d.mts +13 -0
  486. package/runtime/scripts/hfs/rules/assets.mjs +58 -46
  487. package/runtime/scripts/hfs/rules/boot-proof.d.mts +11 -0
  488. package/runtime/scripts/hfs/rules/boot-proof.mjs +7 -8
  489. package/runtime/scripts/hfs/rules/bypass-markers.d.mts +9 -0
  490. package/runtime/scripts/hfs/rules/bypass-markers.mjs +7 -12
  491. package/runtime/scripts/hfs/rules/canon-copy-drift.d.mts +10 -0
  492. package/runtime/scripts/hfs/rules/canon-copy-drift.mjs +70 -68
  493. package/runtime/scripts/hfs/rules/ci-custody.d.mts +7 -0
  494. package/runtime/scripts/hfs/rules/ci-custody.mjs +72 -73
  495. package/runtime/scripts/hfs/rules/ci-standard.d.mts +12 -0
  496. package/runtime/scripts/hfs/rules/ci-standard.mjs +149 -142
  497. package/runtime/scripts/hfs/rules/cli.d.mts +7 -0
  498. package/runtime/scripts/hfs/rules/cli.mjs +24 -23
  499. package/runtime/scripts/hfs/rules/contract-compat.d.mts +11 -0
  500. package/runtime/scripts/hfs/rules/contract-compat.mjs +64 -53
  501. package/runtime/scripts/hfs/rules/contract.d.mts +26 -0
  502. package/runtime/scripts/hfs/rules/contract.mjs +126 -111
  503. package/runtime/scripts/hfs/rules/coverage-below.d.mts +17 -0
  504. package/runtime/scripts/hfs/rules/coverage-below.mjs +200 -167
  505. package/runtime/scripts/hfs/rules/database-access.d.mts +12 -0
  506. package/runtime/scripts/hfs/rules/database-access.mjs +231 -202
  507. package/runtime/scripts/hfs/rules/database-baseline.d.mts +22 -0
  508. package/runtime/scripts/hfs/rules/database-baseline.mjs +104 -104
  509. package/runtime/scripts/hfs/rules/database-config.d.mts +11 -0
  510. package/runtime/scripts/hfs/rules/database-config.mjs +101 -135
  511. package/runtime/scripts/hfs/rules/database-constants.d.mts +36 -0
  512. package/runtime/scripts/hfs/rules/database-constants.mjs +7 -7
  513. package/runtime/scripts/hfs/rules/database-migrations.d.mts +41 -0
  514. package/runtime/scripts/hfs/rules/database-migrations.mjs +428 -388
  515. package/runtime/scripts/hfs/rules/database-plpgsql.d.mts +5 -0
  516. package/runtime/scripts/hfs/rules/database-plpgsql.mjs +278 -259
  517. package/runtime/scripts/hfs/rules/database-queue-sources.d.mts +4 -0
  518. package/runtime/scripts/hfs/rules/database-queue-sources.mjs +48 -43
  519. package/runtime/scripts/hfs/rules/database-queues.d.mts +15 -0
  520. package/runtime/scripts/hfs/rules/database-queues.mjs +211 -182
  521. package/runtime/scripts/hfs/rules/database-sql.d.mts +16 -0
  522. package/runtime/scripts/hfs/rules/database-sql.mjs +394 -394
  523. package/runtime/scripts/hfs/rules/database-transaction.d.mts +3 -0
  524. package/runtime/scripts/hfs/rules/database-transaction.mjs +25 -27
  525. package/runtime/scripts/hfs/rules/database.d.mts +22 -0
  526. package/runtime/scripts/hfs/rules/database.mjs +42 -58
  527. package/runtime/scripts/hfs/rules/deploy-scan.d.mts +10 -0
  528. package/runtime/scripts/hfs/rules/deploy-scan.mjs +177 -168
  529. package/runtime/scripts/hfs/rules/deploy-workflow.d.mts +3 -0
  530. package/runtime/scripts/hfs/rules/deploy-workflow.mjs +194 -171
  531. package/runtime/scripts/hfs/rules/deps.d.mts +6 -0
  532. package/runtime/scripts/hfs/rules/deps.mjs +61 -60
  533. package/runtime/scripts/hfs/rules/doc-fresh.d.mts +11 -0
  534. package/runtime/scripts/hfs/rules/doc-fresh.mjs +242 -223
  535. package/runtime/scripts/hfs/rules/docker-health.d.mts +9 -0
  536. package/runtime/scripts/hfs/rules/docker-health.mjs +222 -196
  537. package/runtime/scripts/hfs/rules/docker.d.mts +13 -0
  538. package/runtime/scripts/hfs/rules/docker.mjs +234 -208
  539. package/runtime/scripts/hfs/rules/edition.d.mts +18 -0
  540. package/runtime/scripts/hfs/rules/edition.mjs +103 -101
  541. package/runtime/scripts/hfs/rules/env-parity.d.mts +25 -0
  542. package/runtime/scripts/hfs/rules/env-parity.mjs +278 -252
  543. package/runtime/scripts/hfs/rules/env-value-shape.d.mts +21 -0
  544. package/runtime/scripts/hfs/rules/env-value-shape.mjs +82 -67
  545. package/runtime/scripts/hfs/rules/event-bus.d.mts +17 -0
  546. package/runtime/scripts/hfs/rules/event-bus.mjs +145 -133
  547. package/runtime/scripts/hfs/rules/event-tables.d.mts +7 -0
  548. package/runtime/scripts/hfs/rules/event-tables.mjs +77 -75
  549. package/runtime/scripts/hfs/rules/fe-build-args.d.mts +10 -0
  550. package/runtime/scripts/hfs/rules/fe-build-args.mjs +116 -99
  551. package/runtime/scripts/hfs/rules/fe-contract-documents.d.mts +7 -0
  552. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +121 -111
  553. package/runtime/scripts/hfs/rules/fe-no-tests.d.mts +9 -0
  554. package/runtime/scripts/hfs/rules/fe-no-tests.mjs +37 -36
  555. package/runtime/scripts/hfs/rules/fe-stack.d.mts +23 -0
  556. package/runtime/scripts/hfs/rules/fe-stack.mjs +108 -105
  557. package/runtime/scripts/hfs/rules/feature-files.d.mts +10 -0
  558. package/runtime/scripts/hfs/rules/feature-files.mjs +14 -19
  559. package/runtime/scripts/hfs/rules/frontend-tree.d.mts +18 -0
  560. package/runtime/scripts/hfs/rules/frontend-tree.mjs +105 -91
  561. package/runtime/scripts/hfs/rules/integration-specs.d.mts +7 -0
  562. package/runtime/scripts/hfs/rules/integration-specs.mjs +190 -177
  563. package/runtime/scripts/hfs/rules/kinds.d.mts +6 -0
  564. package/runtime/scripts/hfs/rules/kinds.mjs +88 -81
  565. package/runtime/scripts/hfs/rules/lexicon.d.mts +9 -0
  566. package/runtime/scripts/hfs/rules/lexicon.mjs +43 -40
  567. package/runtime/scripts/hfs/rules/lint-suppression.d.mts +5 -0
  568. package/runtime/scripts/hfs/rules/lint-suppression.mjs +22 -20
  569. package/runtime/scripts/hfs/rules/lite-proof-lane.d.mts +9 -0
  570. package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +59 -58
  571. package/runtime/scripts/hfs/rules/lite-secrets.d.mts +12 -0
  572. package/runtime/scripts/hfs/rules/lite-secrets.mjs +60 -63
  573. package/runtime/scripts/hfs/rules/mcp-tools.d.mts +7 -0
  574. package/runtime/scripts/hfs/rules/mcp-tools.mjs +56 -41
  575. package/runtime/scripts/hfs/rules/monorepo.d.mts +17 -0
  576. package/runtime/scripts/hfs/rules/monorepo.mjs +153 -138
  577. package/runtime/scripts/hfs/rules/peer-integrations.d.mts +7 -0
  578. package/runtime/scripts/hfs/rules/peer-integrations.mjs +39 -36
  579. package/runtime/scripts/hfs/rules/pipeline.d.mts +7 -0
  580. package/runtime/scripts/hfs/rules/pipeline.mjs +53 -53
  581. package/runtime/scripts/hfs/rules/proof-commands.d.mts +14 -0
  582. package/runtime/scripts/hfs/rules/proof-commands.mjs +52 -41
  583. package/runtime/scripts/hfs/rules/read.d.mts +7 -0
  584. package/runtime/scripts/hfs/rules/read.mjs +19 -15
  585. package/runtime/scripts/hfs/rules/release-provenance.d.mts +12 -0
  586. package/runtime/scripts/hfs/rules/release-provenance.mjs +196 -159
  587. package/runtime/scripts/hfs/rules/repo-local-checks.d.mts +5 -0
  588. package/runtime/scripts/hfs/rules/repo-local-checks.mjs +19 -17
  589. package/runtime/scripts/hfs/rules/rule-types.d.mts +40 -0
  590. package/runtime/scripts/hfs/rules/rule-types.mjs +4 -0
  591. package/runtime/scripts/hfs/rules/saga-delivery.d.mts +2 -0
  592. package/runtime/scripts/hfs/rules/saga-delivery.mjs +58 -50
  593. package/runtime/scripts/hfs/rules/saga.d.mts +7 -0
  594. package/runtime/scripts/hfs/rules/saga.mjs +151 -145
  595. package/runtime/scripts/hfs/rules/script-hygiene.d.mts +11 -0
  596. package/runtime/scripts/hfs/rules/script-hygiene.mjs +112 -95
  597. package/runtime/scripts/hfs/rules/secret-custody-only.d.mts +7 -0
  598. package/runtime/scripts/hfs/rules/secret-custody-only.mjs +29 -35
  599. package/runtime/scripts/hfs/rules/secrets.d.mts +29 -0
  600. package/runtime/scripts/hfs/rules/secrets.mjs +45 -44
  601. package/runtime/scripts/hfs/rules/services.d.mts +7 -0
  602. package/runtime/scripts/hfs/rules/services.mjs +148 -148
  603. package/runtime/scripts/hfs/rules/spec-placement.d.mts +8 -0
  604. package/runtime/scripts/hfs/rules/spec-placement.mjs +12 -13
  605. package/runtime/scripts/hfs/rules/stack-tooling.d.mts +11 -0
  606. package/runtime/scripts/hfs/rules/stack-tooling.mjs +45 -52
  607. package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.d.mts +30 -0
  608. package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.mjs +149 -0
  609. package/runtime/scripts/hfs/rules/stacks-deploy.d.mts +7 -0
  610. package/runtime/scripts/hfs/rules/stacks-deploy.mjs +32 -42
  611. package/runtime/scripts/hfs/rules/stacks-ingress.d.mts +16 -0
  612. package/runtime/scripts/hfs/rules/stacks-ingress.mjs +62 -64
  613. package/runtime/scripts/hfs/rules/stacks-lite-backing.d.mts +17 -0
  614. package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +111 -116
  615. package/runtime/scripts/hfs/rules/stacks-release.d.mts +26 -0
  616. package/runtime/scripts/hfs/rules/stacks-release.mjs +335 -309
  617. package/runtime/scripts/hfs/rules/stacks-runtime.d.mts +31 -0
  618. package/runtime/scripts/hfs/rules/stacks-runtime.mjs +130 -124
  619. package/runtime/scripts/hfs/rules/stacks-swarm.d.mts +5 -0
  620. package/runtime/scripts/hfs/rules/stacks-swarm.mjs +366 -344
  621. package/runtime/scripts/hfs/rules/stacks.d.mts +7 -0
  622. package/runtime/scripts/hfs/rules/stacks.mjs +37 -38
  623. package/runtime/scripts/hfs/rules/staged-specs.d.mts +10 -0
  624. package/runtime/scripts/hfs/rules/staged-specs.mjs +14 -18
  625. package/runtime/scripts/hfs/rules/supply-chain.d.mts +10 -0
  626. package/runtime/scripts/hfs/rules/supply-chain.mjs +143 -150
  627. package/runtime/scripts/hfs/rules/test-topology.d.mts +5 -0
  628. package/runtime/scripts/hfs/rules/test-topology.mjs +23 -21
  629. package/runtime/scripts/hfs/rules/text-integrity.d.mts +9 -0
  630. package/runtime/scripts/hfs/rules/text-integrity.mjs +47 -43
  631. package/runtime/scripts/hfs/rules/unused-symbol-flow.d.mts +22 -0
  632. package/runtime/scripts/hfs/rules/unused-symbol-flow.mjs +226 -204
  633. package/runtime/scripts/hfs/rules/unused-symbol-ledger.d.mts +7 -0
  634. package/runtime/scripts/hfs/rules/unused-symbol-ledger.mjs +70 -49
  635. package/runtime/scripts/hfs/rules/unused-symbol-properties.d.mts +12 -0
  636. package/runtime/scripts/hfs/rules/unused-symbol-properties.mjs +141 -126
  637. package/runtime/scripts/hfs/rules/unused-symbol-translators.d.mts +8 -0
  638. package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +160 -140
  639. package/runtime/scripts/hfs/rules/unused-symbol-values.d.mts +9 -0
  640. package/runtime/scripts/hfs/rules/unused-symbol-values.mjs +138 -125
  641. package/runtime/scripts/hfs/rules/unused-symbol.d.mts +11 -0
  642. package/runtime/scripts/hfs/rules/unused-symbol.mjs +283 -253
  643. package/runtime/scripts/hfs/rules/workflow-contexts.d.mts +8 -0
  644. package/runtime/scripts/hfs/rules/workflow-contexts.mjs +79 -67
  645. package/runtime/scripts/hfs/runtime-rules/git-triggers.d.mts +6 -0
  646. package/runtime/scripts/hfs/runtime-rules/git-triggers.mjs +36 -35
  647. package/runtime/scripts/hfs/runtime-rules/hook-shape.d.mts +10 -0
  648. package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +45 -42
  649. package/runtime/scripts/hfs/runtime-rules/source-ast.d.mts +39 -0
  650. package/runtime/scripts/hfs/runtime-rules/source-ast.mjs +130 -116
  651. package/runtime/scripts/hfs/runtime-rules/workflow-source.d.mts +5 -0
  652. package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +8 -7
  653. package/runtime/scripts/hfs/sealed-members.d.mts +22 -0
  654. package/runtime/scripts/hfs/sealed-members.mjs +79 -75
  655. package/runtime/scripts/hfs/secret-bootstrap-crypto.d.mts +12 -0
  656. package/runtime/scripts/hfs/secret-bootstrap-crypto.mjs +151 -167
  657. package/runtime/scripts/hfs/secret-document.d.mts +16 -0
  658. package/runtime/scripts/hfs/secret-document.mjs +59 -75
  659. package/runtime/scripts/hfs/secret-edit.d.mts +14 -0
  660. package/runtime/scripts/hfs/secret-edit.mjs +115 -135
  661. package/runtime/scripts/hfs/secret-errors.d.mts +4 -0
  662. package/runtime/scripts/hfs/secret-errors.mjs +19 -16
  663. package/runtime/scripts/hfs/secret-files.d.mts +20 -0
  664. package/runtime/scripts/hfs/secret-files.mjs +103 -112
  665. package/runtime/scripts/hfs/secret-init.d.mts +108 -0
  666. package/runtime/scripts/hfs/secret-init.mjs +304 -346
  667. package/runtime/scripts/hfs/secret-output.d.mts +18 -0
  668. package/runtime/scripts/hfs/secret-output.mjs +52 -80
  669. package/runtime/scripts/hfs/secret-prompt.d.mts +39 -0
  670. package/runtime/scripts/hfs/secret-prompt.mjs +108 -93
  671. package/runtime/scripts/hfs/secret-sops.d.mts +29 -0
  672. package/runtime/scripts/hfs/secret-sops.mjs +161 -199
  673. package/runtime/scripts/hfs/secret-standard.d.mts +89 -0
  674. package/runtime/scripts/hfs/secret-standard.mjs +300 -264
  675. package/runtime/scripts/hfs/secret-store.d.mts +36 -0
  676. package/runtime/scripts/hfs/secret-store.mjs +120 -136
  677. package/runtime/scripts/hfs/secret.d.mts +40 -0
  678. package/runtime/scripts/hfs/secret.mjs +254 -222
  679. package/runtime/scripts/hfs/slot-app-view.d.mts +11 -0
  680. package/runtime/scripts/hfs/slot-app-view.mjs +69 -74
  681. package/runtime/scripts/hfs/slot-classify.d.mts +75 -0
  682. package/runtime/scripts/hfs/slot-classify.mjs +42 -38
  683. package/runtime/scripts/hfs/slot-errors.d.mts +6 -0
  684. package/runtime/scripts/hfs/slot-errors.mjs +8 -7
  685. package/runtime/scripts/hfs/slot-imports.d.mts +8 -0
  686. package/runtime/scripts/hfs/slot-imports.mjs +70 -63
  687. package/runtime/scripts/hfs/slot-manifest-shape.d.mts +9 -0
  688. package/runtime/scripts/hfs/slot-manifest-shape.mjs +74 -52
  689. package/runtime/scripts/hfs/slot-match.d.mts +50 -0
  690. package/runtime/scripts/hfs/slot-match.mjs +122 -111
  691. package/runtime/scripts/hfs/slot-path.d.mts +1 -0
  692. package/runtime/scripts/hfs/slot-path.mjs +0 -2
  693. package/runtime/scripts/hfs/slot-required.d.mts +11 -0
  694. package/runtime/scripts/hfs/slot-required.mjs +65 -59
  695. package/runtime/scripts/hfs/slot-semantic-problems.d.mts +9 -0
  696. package/runtime/scripts/hfs/slot-semantic-problems.mjs +138 -112
  697. package/runtime/scripts/hfs/slot-side-problems.d.mts +3 -0
  698. package/runtime/scripts/hfs/slot-side-problems.mjs +23 -19
  699. package/runtime/scripts/hfs/slots.d.mts +188 -0
  700. package/runtime/scripts/hfs/slots.mjs +175 -152
  701. package/runtime/scripts/hfs/sql/pg-parse.d.mts +9 -0
  702. package/runtime/scripts/hfs/sql/pg-parse.mjs +25 -25
  703. package/runtime/scripts/hfs/stack-config-kit.d.mts +22 -0
  704. package/runtime/scripts/hfs/stack-config-kit.mjs +21 -17
  705. package/runtime/scripts/hfs/stack-deploy-config.d.mts +155 -0
  706. package/runtime/scripts/hfs/stack-deploy-config.mjs +345 -273
  707. package/runtime/scripts/hfs/stack-ingress-config.d.mts +74 -0
  708. package/runtime/scripts/hfs/stack-ingress-config.mjs +211 -177
  709. package/runtime/scripts/hfs/stacks-gate.d.mts +52 -0
  710. package/runtime/scripts/hfs/stacks-gate.mjs +557 -397
  711. package/runtime/scripts/hfs/starcistacks-runtime.d.mts +7 -0
  712. package/runtime/scripts/hfs/starcistacks-runtime.mjs +51 -40
  713. package/runtime/scripts/hfs/test-world-slot.d.mts +2 -0
  714. package/runtime/scripts/hfs/test-world-slot.mjs +0 -1
  715. package/runtime/scripts/hfs/trailing-slashes.d.mts +2 -0
  716. package/runtime/scripts/hfs/trailing-slashes.mjs +4 -4
  717. package/runtime/scripts/hfs/tree-findings.d.mts +9 -0
  718. package/runtime/scripts/hfs/tree-findings.mjs +18 -17
  719. package/runtime/scripts/hfs/tree.d.mts +35 -0
  720. package/runtime/scripts/hfs/tree.mjs +56 -46
  721. package/runtime/scripts/hfs/typescript-programs.d.mts +36 -0
  722. package/runtime/scripts/hfs/typescript-programs.mjs +66 -69
  723. package/runtime/scripts/hfs/view.d.mts +45 -0
  724. package/runtime/scripts/hfs/view.mjs +38 -40
  725. package/runtime/scripts/lib/bypass-markers.d.mts +15 -0
  726. package/runtime/scripts/lib/bypass-markers.mjs +210 -197
  727. package/runtime/scripts/lib/cli-arg.d.mts +67 -0
  728. package/runtime/scripts/lib/cli-arg.mjs +59 -63
  729. package/runtime/scripts/lib/command-tokens.d.mts +11 -0
  730. package/runtime/scripts/lib/command-tokens.mjs +77 -78
  731. package/runtime/scripts/lib/compose-values.d.mts +6 -0
  732. package/runtime/scripts/lib/compose-values.mjs +7 -7
  733. package/runtime/scripts/lib/css-rules.d.mts +36 -0
  734. package/runtime/scripts/lib/css-rules.mjs +181 -171
  735. package/runtime/scripts/lib/deployment-findings.d.mts +9 -0
  736. package/runtime/scripts/lib/deployment-findings.mjs +4 -4
  737. package/runtime/scripts/lib/dockerfile.d.mts +39 -0
  738. package/runtime/scripts/lib/dockerfile.mjs +131 -114
  739. package/runtime/scripts/lib/dom-tree.d.mts +7 -0
  740. package/runtime/scripts/lib/dom-tree.mjs +3 -3
  741. package/runtime/scripts/lib/env.d.mts +12 -0
  742. package/runtime/scripts/lib/env.mjs +3 -6
  743. package/runtime/scripts/lib/escape.d.mts +6 -0
  744. package/runtime/scripts/lib/escape.mjs +2 -6
  745. package/runtime/scripts/lib/event-contract.d.mts +21 -0
  746. package/runtime/scripts/lib/event-contract.mjs +73 -78
  747. package/runtime/scripts/lib/event-items.d.mts +20 -0
  748. package/runtime/scripts/lib/event-items.mjs +27 -15
  749. package/runtime/scripts/lib/example-refs.d.mts +69 -0
  750. package/runtime/scripts/lib/example-refs.mjs +145 -129
  751. package/runtime/scripts/lib/fs-kind.d.mts +12 -0
  752. package/runtime/scripts/lib/fs-kind.mjs +20 -10
  753. package/runtime/scripts/lib/git-hooks-dir.d.mts +15 -0
  754. package/runtime/scripts/lib/git-hooks-dir.mjs +16 -16
  755. package/runtime/scripts/lib/git.d.mts +24 -0
  756. package/runtime/scripts/lib/git.mjs +15 -16
  757. package/runtime/scripts/lib/glob.d.mts +4 -0
  758. package/runtime/scripts/lib/glob.mjs +23 -14
  759. package/runtime/scripts/lib/grammar-lint.d.mts +47 -0
  760. package/runtime/scripts/lib/grammar-lint.mjs +33 -37
  761. package/runtime/scripts/lib/grammar-vendor-parity-jsx.d.mts +40 -0
  762. package/runtime/scripts/lib/grammar-vendor-parity-jsx.mjs +285 -266
  763. package/runtime/scripts/lib/grammar-vendor-parity.d.mts +61 -0
  764. package/runtime/scripts/lib/grammar-vendor-parity.mjs +209 -216
  765. package/runtime/scripts/lib/graphql-contract.d.mts +53 -0
  766. package/runtime/scripts/lib/graphql-contract.mjs +201 -198
  767. package/runtime/scripts/lib/graphql-sdl.d.mts +66 -0
  768. package/runtime/scripts/lib/graphql-sdl.mjs +230 -205
  769. package/runtime/scripts/lib/hook-limits.d.mts +11 -0
  770. package/runtime/scripts/lib/hook-limits.mjs +0 -1
  771. package/runtime/scripts/lib/i18n.d.mts +48 -0
  772. package/runtime/scripts/lib/i18n.mjs +32 -35
  773. package/runtime/scripts/lib/in-order.d.mts +12 -0
  774. package/runtime/scripts/lib/in-order.mjs +57 -38
  775. package/runtime/scripts/lib/is-main.d.mts +6 -0
  776. package/runtime/scripts/lib/is-main.mjs +11 -4
  777. package/runtime/scripts/lib/js-lex.d.mts +32 -0
  778. package/runtime/scripts/lib/js-lex.mjs +196 -162
  779. package/runtime/scripts/lib/json-clone.d.mts +11 -0
  780. package/runtime/scripts/lib/json-clone.mjs +45 -36
  781. package/runtime/scripts/lib/json-schema.d.mts +2 -0
  782. package/runtime/scripts/lib/json-schema.mjs +127 -90
  783. package/runtime/scripts/lib/json.d.mts +16 -0
  784. package/runtime/scripts/lib/json.mjs +26 -14
  785. package/runtime/scripts/lib/language.d.mts +44 -0
  786. package/runtime/scripts/lib/language.mjs +133 -129
  787. package/runtime/scripts/lib/list.d.mts +17 -0
  788. package/runtime/scripts/lib/list.mjs +9 -14
  789. package/runtime/scripts/lib/loosening-budgets.d.mts +12 -0
  790. package/runtime/scripts/lib/loosening-budgets.mjs +35 -29
  791. package/runtime/scripts/lib/loosening-config.d.mts +64 -0
  792. package/runtime/scripts/lib/loosening-config.mjs +267 -236
  793. package/runtime/scripts/lib/loosening-state.d.mts +77 -0
  794. package/runtime/scripts/lib/loosening-state.mjs +134 -128
  795. package/runtime/scripts/lib/mutation-fence.d.mts +11 -0
  796. package/runtime/scripts/lib/mutation-fence.mjs +10 -5
  797. package/runtime/scripts/lib/normalize.d.mts +12 -0
  798. package/runtime/scripts/lib/normalize.mjs +11 -11
  799. package/runtime/scripts/lib/numeric-match.d.mts +2 -0
  800. package/runtime/scripts/lib/numeric-match.mjs +2 -2
  801. package/runtime/scripts/lib/package-at.d.mts +24 -0
  802. package/runtime/scripts/lib/package-at.mjs +34 -31
  803. package/runtime/scripts/lib/path-key.d.mts +76 -0
  804. package/runtime/scripts/lib/path-key.mjs +53 -38
  805. package/runtime/scripts/lib/pid-alive.d.mts +2 -0
  806. package/runtime/scripts/lib/pid-alive.mjs +10 -3
  807. package/runtime/scripts/lib/properties.d.mts +2 -0
  808. package/runtime/scripts/lib/properties.mjs +17 -11
  809. package/runtime/scripts/lib/provision-operation-schema.d.mts +4 -0
  810. package/runtime/scripts/lib/provision-operation-schema.mjs +4 -5
  811. package/runtime/scripts/lib/read-text.d.mts +12 -0
  812. package/runtime/scripts/lib/read-text.mjs +30 -17
  813. package/runtime/scripts/lib/redact.d.mts +52 -0
  814. package/runtime/scripts/lib/redact.mjs +135 -121
  815. package/runtime/scripts/lib/regex.d.mts +2 -0
  816. package/runtime/scripts/lib/regex.mjs +1 -2
  817. package/runtime/scripts/lib/roots.d.mts +32 -0
  818. package/runtime/scripts/lib/roots.mjs +5 -15
  819. package/runtime/scripts/lib/runtime-example.d.mts +1 -0
  820. package/runtime/scripts/lib/runtime-example.mjs +10 -8
  821. package/runtime/scripts/lib/same-text.d.mts +2 -0
  822. package/runtime/scripts/lib/same-text.mjs +0 -1
  823. package/runtime/scripts/lib/sealed-member.d.mts +16 -0
  824. package/runtime/scripts/lib/sealed-member.mjs +8 -13
  825. package/runtime/scripts/lib/secret-patterns.d.mts +30 -0
  826. package/runtime/scripts/lib/secret-patterns.mjs +175 -163
  827. package/runtime/scripts/lib/shell-source.d.mts +2 -0
  828. package/runtime/scripts/lib/shell-source.mjs +0 -1
  829. package/runtime/scripts/lib/sleep-sync.d.mts +2 -0
  830. package/runtime/scripts/lib/sleep-sync.mjs +5 -6
  831. package/runtime/scripts/lib/sops-envelope.d.mts +34 -0
  832. package/runtime/scripts/lib/sops-envelope.mjs +148 -120
  833. package/runtime/scripts/lib/source-phrases.d.mts +4 -0
  834. package/runtime/scripts/lib/source-phrases.mjs +13 -13
  835. package/runtime/scripts/lib/sql-ast.d.mts +13 -0
  836. package/runtime/scripts/lib/sql-ast.mjs +19 -18
  837. package/runtime/scripts/lib/sqlite.d.mts +21 -0
  838. package/runtime/scripts/lib/sqlite.mjs +3 -9
  839. package/runtime/scripts/lib/stack-declaration.d.mts +51 -0
  840. package/runtime/scripts/lib/stack-declaration.mjs +27 -20
  841. package/runtime/scripts/lib/stack-services.d.mts +73 -0
  842. package/runtime/scripts/lib/stack-services.mjs +128 -129
  843. package/runtime/scripts/lib/starciwork-boundary.d.mts +10 -0
  844. package/runtime/scripts/lib/starciwork-boundary.mjs +98 -92
  845. package/runtime/scripts/lib/swarm-stack.d.mts +24 -0
  846. package/runtime/scripts/lib/swarm-stack.mjs +112 -100
  847. package/runtime/scripts/lib/trim-end.d.mts +2 -0
  848. package/runtime/scripts/lib/trim-end.mjs +4 -4
  849. package/runtime/scripts/lib/ts-analysis.d.mts +24 -0
  850. package/runtime/scripts/lib/ts-analysis.mjs +28 -26
  851. package/runtime/scripts/lib/ts-ast.d.mts +36 -0
  852. package/runtime/scripts/lib/ts-ast.mjs +36 -42
  853. package/runtime/scripts/lib/walk.d.mts +19 -0
  854. package/runtime/scripts/lib/walk.mjs +33 -27
  855. package/runtime/scripts/lib/work-edition.d.mts +10 -0
  856. package/runtime/scripts/lib/work-edition.mjs +29 -21
  857. package/runtime/scripts/lib/workflow-events.d.mts +2 -0
  858. package/runtime/scripts/lib/workflow-events.mjs +5 -4
  859. package/runtime/scripts/lib/worktree-exclude.d.mts +16 -0
  860. package/runtime/scripts/lib/worktree-exclude.mjs +6 -8
  861. package/runtime/scripts/lib/yaml-cached.d.mts +2 -0
  862. package/runtime/scripts/lib/yaml-cached.mjs +4 -4
  863. package/runtime/scripts/machine/artifact-hold.d.mts +26 -0
  864. package/runtime/scripts/machine/artifact-hold.mjs +22 -23
  865. package/runtime/scripts/work/asset-slot.d.mts +96 -0
  866. package/runtime/scripts/work/asset-slot.mjs +201 -175
  867. package/runtime/scripts/work/draw/draw-dna-anatomy.d.mts +30 -0
  868. package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +40 -36
  869. package/runtime/scripts/work/draw/draw-dna-findings.d.mts +12 -0
  870. package/runtime/scripts/work/draw/draw-dna-findings.mjs +240 -206
  871. package/runtime/scripts/work/draw/draw-dna-selector.d.mts +7 -0
  872. package/runtime/scripts/work/draw/draw-dna-selector.mjs +28 -28
  873. package/runtime/scripts/work/draw/draw-dna.d.mts +191 -0
  874. package/runtime/scripts/work/draw/draw-dna.mjs +283 -249
  875. package/runtime/scripts/work/grammar-proposal.d.mts +83 -0
  876. package/runtime/scripts/work/grammar-proposal.mjs +215 -178
  877. package/runtime/scripts/work/work-io.d.mts +62 -0
  878. package/runtime/scripts/work/work-io.mjs +82 -63
  879. package/scaffold/add-app.d.mts +15 -0
  880. package/scaffold/add-app.mjs +111 -163
  881. package/scaffold/add-cli-lite.d.mts +8 -0
  882. package/scaffold/add-cli-lite.mjs +173 -207
  883. package/scaffold/add-compose.d.mts +44 -0
  884. package/scaffold/add-compose.mjs +62 -62
  885. package/scaffold/add-database-lite.d.mts +2 -0
  886. package/scaffold/add-database-lite.mjs +10 -10
  887. package/scaffold/add-fe-layout.d.mts +16 -0
  888. package/scaffold/add-fe-layout.mjs +23 -23
  889. package/scaffold/add-fe-overlay.d.mts +17 -0
  890. package/scaffold/add-fe-overlay.mjs +76 -78
  891. package/scaffold/add-fe-page.d.mts +41 -0
  892. package/scaffold/add-fe-page.mjs +84 -89
  893. package/scaffold/add-fe-unit.d.mts +59 -0
  894. package/scaffold/add-fe-unit.mjs +205 -197
  895. package/scaffold/add-inbox-lite.d.mts +17 -0
  896. package/scaffold/add-inbox-lite.mjs +209 -264
  897. package/scaffold/add-plan.d.mts +68 -0
  898. package/scaffold/add-plan.mjs +164 -149
  899. package/scaffold/add-queue-lite.d.mts +34 -0
  900. package/scaffold/add-queue-lite.mjs +267 -267
  901. package/scaffold/add-table.d.mts +16 -0
  902. package/scaffold/add-table.mjs +405 -442
  903. package/scaffold/add.d.mts +34 -0
  904. package/scaffold/add.mjs +260 -246
  905. package/scaffold/app.d.mts +198 -0
  906. package/scaffold/app.mjs +413 -391
  907. package/scaffold/edition-gate.d.mts +49 -0
  908. package/scaffold/edition-gate.mjs +19 -29
  909. package/scaffold/image.d.mts +4 -0
  910. package/scaffold/image.mjs +12 -12
  911. package/scaffold/lite-exports.d.mts +15 -0
  912. package/scaffold/lite-exports.mjs +262 -255
  913. package/scaffold/pattern-file-slots.d.mts +7 -0
  914. package/scaffold/pattern-file-slots.mjs +29 -24
  915. package/scaffold/service.d.mts +60 -0
  916. package/scaffold/service.mjs +297 -279
  917. package/scaffold/test-world.d.mts +31 -0
  918. package/scaffold/test-world.mjs +71 -78
  919. package/scaffold/yaml-block-edit.d.mts +23 -0
  920. package/scaffold/yaml-block-edit.mjs +95 -87
  921. package/scripts/sync-bundles.d.mts +31 -0
  922. package/src/fixtures/bypass-index.d.mts +4 -0
  923. package/src/fixtures/hfs-stack-tooling/passing.d.mts +8 -0
  924. package/src/fixtures/hfs-stack-tooling/violating.d.mts +19 -0
  925. package/src/fixtures/hfs-stacks-full/model-unavailable.d.mts +10 -0
  926. package/src/fixtures/hfs-stacks-full/passing.d.mts +19 -0
  927. package/src/fixtures/hfs-stacks-full/violating.d.mts +10 -0
  928. package/src/fixtures/loosening/adversarial.d.mts +4 -0
  929. package/src/fixtures/loosening/forms.d.mts +16 -0
  930. package/src/fixtures/loosening/swallows.d.mts +5 -0
  931. package/src/helpers/hfs-arch-fixture.d.mts +47 -0
  932. package/src/helpers/hfs-cli-fixture.d.mts +65 -0
  933. package/src/helpers/hfs-hfs-docker-rules-fixture.d.mts +5 -0
  934. package/src/helpers/hfs-secret-fixture.d.mts +19 -0
  935. package/src/helpers/pre-push-fixture.d.mts +21 -0
  936. package/src/helpers/stack-compose.d.mts +6 -0
  937. package/src/helpers/swarm-stack-fixture.d.mts +18 -0
  938. package/src/helpers/tmpdir.d.mts +2 -0
  939. package/src/main.d.mts +58 -0
  940. package/src/main.mjs +493 -348
  941. package/stack/age-install.d.mts +13 -0
  942. package/stack/age-install.mjs +28 -25
  943. package/stack/backup.d.mts +11 -0
  944. package/stack/backup.mjs +76 -69
  945. package/stack/build-args.d.mts +7 -0
  946. package/stack/build-args.mjs +22 -23
  947. package/stack/build.d.mts +8 -0
  948. package/stack/build.mjs +138 -119
  949. package/stack/cli.d.mts +55 -0
  950. package/stack/cli.mjs +187 -130
  951. package/stack/config.d.mts +197 -0
  952. package/stack/config.mjs +47 -33
  953. package/stack/context.d.mts +122 -0
  954. package/stack/context.mjs +63 -65
  955. package/stack/converge.d.mts +13 -0
  956. package/stack/converge.mjs +73 -69
  957. package/stack/deploy.d.mts +88 -0
  958. package/stack/deploy.mjs +272 -224
  959. package/stack/digest.d.mts +8 -0
  960. package/stack/digest.mjs +1 -6
  961. package/stack/docker-transport.d.mts +5 -0
  962. package/stack/docker-transport.mjs +101 -93
  963. package/stack/edge-alias.d.mts +42 -0
  964. package/stack/edge-alias.mjs +62 -60
  965. package/stack/errors.d.mts +18 -0
  966. package/stack/errors.mjs +8 -10
  967. package/stack/image-scan.d.mts +20 -0
  968. package/stack/image-scan.mjs +114 -101
  969. package/stack/ingress-create.d.mts +4 -0
  970. package/stack/ingress-create.mjs +82 -86
  971. package/stack/ingress-publish.d.mts +6 -0
  972. package/stack/ingress-publish.mjs +194 -182
  973. package/stack/ingress.d.mts +55 -0
  974. package/stack/ingress.mjs +534 -524
  975. package/stack/jobs.d.mts +12 -0
  976. package/stack/jobs.mjs +35 -34
  977. package/stack/live-restore.d.mts +35 -0
  978. package/stack/live-restore.mjs +120 -125
  979. package/stack/post-deploy.d.mts +8 -0
  980. package/stack/post-deploy.mjs +25 -25
  981. package/stack/prepare.d.mts +24 -0
  982. package/stack/prepare.mjs +213 -200
  983. package/stack/private-file.d.mts +5 -0
  984. package/stack/private-file.mjs +9 -9
  985. package/stack/provision.d.mts +25 -0
  986. package/stack/provision.mjs +64 -63
  987. package/stack/prune.d.mts +11 -0
  988. package/stack/prune.mjs +38 -27
  989. package/stack/release-store.d.mts +28 -0
  990. package/stack/release-store.mjs +68 -67
  991. package/stack/remote.d.mts +83 -0
  992. package/stack/remote.mjs +176 -162
  993. package/stack/render.d.mts +14 -0
  994. package/stack/render.mjs +132 -124
  995. package/stack/retire.d.mts +9 -0
  996. package/stack/retire.mjs +31 -34
  997. package/stack/sealed.d.mts +46 -0
  998. package/stack/sealed.mjs +78 -82
  999. package/stack/server-key.d.mts +67 -0
  1000. package/stack/server-key.mjs +217 -203
  1001. package/stack/ssh-session.d.mts +29 -0
  1002. package/stack/ssh-session.mjs +133 -123
  1003. package/stack/target-binding.d.mts +21 -0
  1004. package/stack/target-binding.mjs +68 -44
  1005. package/stack/task.d.mts +12 -0
  1006. package/stack/task.mjs +26 -31
  1007. package/stack/urgent-floor.d.mts +106 -0
  1008. package/stack/urgent-floor.mjs +211 -160
  1009. package/stack/urgent-release.d.mts +38 -0
  1010. package/stack/urgent-release.mjs +26 -22
  1011. package/stack/verify.d.mts +14 -0
  1012. package/stack/verify.mjs +75 -65
  1013. package/sync/ci-commands.d.mts +26 -0
  1014. package/sync/ci-commands.mjs +181 -182
  1015. package/sync/cli.d.mts +8 -0
  1016. package/sync/cli.mjs +9 -9
  1017. package/sync/format.d.mts +38 -0
  1018. package/sync/format.mjs +30 -24
  1019. package/sync/hygiene.d.mts +23 -0
  1020. package/sync/hygiene.mjs +113 -99
  1021. package/sync/index.d.mts +237 -0
  1022. package/sync/index.mjs +457 -436
  1023. package/sync/managed.d.mts +23 -0
  1024. package/sync/managed.mjs +104 -94
  1025. package/sync/quality-services.d.mts +35 -0
  1026. package/sync/quality-services.mjs +48 -41
  1027. package/sync/readme-badges.d.mts +13 -0
  1028. package/sync/readme-badges.mjs +45 -44
  1029. package/sync/sonar-key.d.mts +31 -0
  1030. package/sync/sonar-key.mjs +29 -28
  1031. package/sync/stack-images.d.mts +36 -0
  1032. package/sync/stack-images.mjs +85 -95
  1033. package/sync/ts-strict.d.mts +14 -0
  1034. package/sync/ts-strict.mjs +43 -34
  1035. package/templates/app/ci-workflows/github/workflows/ci.yml +1 -1
  1036. package/templates/app/ci-workflows/github/workflows/images.yml +1 -1
  1037. package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +2 -2
  1038. package/templates/app/ci-workflows/github/workflows/stack-key-restore.yml +1 -1
  1039. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +1 -1
  1040. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +3 -3
  1041. package/templates/app/ci-workflows-lite/github/workflows/images.yml +1 -1
  1042. package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +2 -2
  1043. package/templates/app/ci-workflows-lite/github/workflows/stack-key-restore.yml +1 -1
  1044. package/templates/app/codegen-lite/scripts/codegen.mjs +1 -1
  1045. package/templates/app/db-bootstrap/db/bootstrap.sql +1 -1
  1046. package/templates/app/db-image/starcistacks/images/db/Dockerfile +1 -1
  1047. package/templates/app/hooks/husky/pre-commit +2 -2
  1048. package/templates/app/package-scripts/db.json +3 -3
  1049. package/templates/app/package-scripts/package.json +1 -1
  1050. package/templates/app/quality-config/sonar-project.properties +1 -1
  1051. package/templates/app/skeleton/.starcistacks/application-stacks.yaml +2 -2
  1052. package/templates/app/skeleton/.starcistacks/production/README.md +4 -4
  1053. package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +8 -3
  1054. package/templates/app/skeleton/README.md +1 -1
  1055. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +2 -2
  1056. package/templates/app/skeleton-lite/.starcistacks/dev/README.md +1 -1
  1057. package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +6 -2
  1058. package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +3 -2
  1059. package/templates/app/skeleton-lite/.starcistacks/production/README.md +5 -5
  1060. package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +7 -2
  1061. package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +3 -2
  1062. package/templates/app/skeleton-lite/README.md +2 -2
  1063. package/templates/be/skeleton/apps/cli/src/compose/platform.ts +1 -1
  1064. package/templates/be/skeleton/apps/cli/src/main.ts +6 -4
  1065. package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +12 -0
  1066. package/templates/be/skeleton/src/modules/platform/database/abstract.entity.ts +19 -0
  1067. package/templates/be/skeleton/src/modules/platform/database/database.module.ts +7 -1
  1068. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +19 -0
  1069. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +4 -3
  1070. package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +1 -1
  1071. package/templates/be/skeleton/src/modules/platform/logging/logging.options.ts +5 -2
  1072. package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +1 -1
  1073. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.spec.ts +40 -0
  1074. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.ts +1 -0
  1075. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.spec.ts +48 -1
  1076. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.ts +5 -0
  1077. package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.options.ts +5 -0
  1078. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/google.strategy.ts +1 -1
  1079. package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/oauth-state.store.ts +7 -3
  1080. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +7 -1
  1081. package/templates/be/table/entity.ts.tpl +4 -15
  1082. package/upgrade/check.d.mts +9 -0
  1083. package/upgrade/check.mjs +8 -8
  1084. package/upgrade/file-state.d.mts +6 -0
  1085. package/upgrade/file-state.mjs +32 -40
  1086. package/upgrade/index.d.mts +13 -0
  1087. package/upgrade/index.mjs +122 -151
  1088. package/vendor-types.d.mts +8 -0
@@ -5,12 +5,11 @@
5
5
  // parsed manifest or slot and returns a list of problems in the words of modules/schemas/hfs-slots.schema.yaml.
6
6
  import { isPlainObject } from '../../engine/plain-object.mjs';
7
7
  import { stringList, byCodeUnit, nonemptyUniqueList } from '../lib/list.mjs';
8
-
9
8
  export const SEMVER = /^(\d+)\.(\d+)\.(\d+)$/;
10
9
  export const NAME = /^[a-z][a-z0-9-]*$/;
11
10
  /** An npm package name, scoped or not. */
12
11
  export const PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
13
- const ENV_PREFIX =/^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/;
12
+ const ENV_PREFIX = /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/;
14
13
  /** How a bounded context (a connection) is isolated: its own logical database, or its own schema of a shared one. */
15
14
  const CONTEXT_ISOLATIONS = Object.freeze(["database", "schema"]);
16
15
  /** The app kinds that may own a context: the services, never the migrate or cli apps that only run migrations. */
@@ -30,12 +29,13 @@ export const SCHEMA_AUTHORITIES = Object.freeze(["typeorm", "sql"]);
30
29
  * @returns {string[]} The problems, none when the shape is right.
31
30
  */
32
31
  export function connectionShapeProblems(list, apps) {
33
- const keys = (c) => isPlainObject(c) && NAME.test(String(c.name)) && ENV_PREFIX.test(String(c.envPrefix)) && NAME.test(String(c.owner)) && CONTEXT_ISOLATIONS.includes(c.isolation)
34
- && (c.provider === undefined || CONNECTION_PROVIDERS.includes(c.provider))
35
- && Object.keys(c).every((k) => ['name', 'envPrefix', 'owner', 'isolation', 'provider'].includes(k)) && ['name', 'envPrefix', 'owner', 'isolation'].every((k) => k in c);
36
- if (!list?.every(keys)) return [`connections must be a list of {name: kebab-case context name, envPrefix: UPPER_SNAKE prefix of its env keys, owner: the service app that owns the context, isolation: ${CONTEXT_ISOLATIONS.join(' | ')}, provider?: ${CONNECTION_PROVIDERS.join(' | ')}}`];
37
- const owns = (c) => Array.isArray(apps) && apps.some((app) => isPlainObject(app) && app.name === c.owner && CONTEXT_OWNER_KINDS.includes(app.kind));
38
- return list.filter((c) => !owns(c)).map((c) => `connections ${c.name} is owned by ${c.owner}, which is not a ${CONTEXT_OWNER_KINDS.join(' or ')} app declared in the same side`);
32
+ const keys = (c) => isPlainObject(c) && NAME.test(String(c.name)) && ENV_PREFIX.test(String(c.envPrefix)) && NAME.test(String(c.owner)) && CONTEXT_ISOLATIONS.includes(c.isolation)
33
+ && (c.provider === undefined || CONNECTION_PROVIDERS.includes(c.provider))
34
+ && Object.keys(c).every((k) => ['name', 'envPrefix', 'owner', 'isolation', 'provider'].includes(k)) && ['name', 'envPrefix', 'owner', 'isolation'].every((k) => k in c);
35
+ if (!list?.every(keys))
36
+ return [`connections must be a list of {name: kebab-case context name, envPrefix: UPPER_SNAKE prefix of its env keys, owner: the service app that owns the context, isolation: ${CONTEXT_ISOLATIONS.join(' | ')}, provider?: ${CONNECTION_PROVIDERS.join(' | ')}}`];
37
+ const owns = (c) => Array.isArray(apps) && apps.some((app) => isPlainObject(app) && app.name === c.owner && CONTEXT_OWNER_KINDS.includes(app.kind));
38
+ return list.filter((c) => !owns(c)).map((c) => `connections ${c.name} is owned by ${c.owner}, which is not a ${CONTEXT_OWNER_KINDS.join(' or ')} app declared in the same side`);
39
39
  }
40
40
  export const SLOT_ID = /^(app|repo|be|fe)\.[a-z0-9-]+(\.[a-z0-9-]+)*$/;
41
41
  const RUNTIME_SLOT_ID = /^runtime\.[a-z0-9-]+(\.[a-z0-9-]+)*$/;
@@ -47,72 +47,73 @@ export const TESTS = ['unit-beside', 'e2e', 'none'];
47
47
  /** The coverage mode of a tracked slot of the be profile or of a runtime manifest (scripts/hfs/coverage-scope.mjs and scripts/hfs/runtime-coverage-scope.mjs derive the coverage consumers from it). */
48
48
  export const COVERAGE = ['required', 'none'];
49
49
  export const APP_KIND = 'app';
50
-
51
50
  /**
52
51
  * The unit-tested roles of a back end whose spec is required (ruleParams.be.unitRoles of the slot manifest): [{ role, spec, slot?, exempt? }].
53
52
  * THE one list: every check that asks "is this file unit-tested, and where is its spec" asks it here. What the unit run MEASURES is
54
53
  * logicRoles over the coverage-required slots (coverage-scope.mjs), not this list.
55
54
  */
56
55
  export const unitRolesOf = (manifest) => manifest.ruleParams.be.unitRoles;
57
-
58
56
  /** The roles that carry logic (ruleParams.be.logicRoles): measured at 100 per file inside a coverage-required slot. */
59
57
  export const logicRolesOf = (manifest) => manifest.ruleParams.be.logicRoles;
60
-
61
58
  /** A declared logic file: `<name>.<part>.ts` below the slot path, kebab-case parts, no placeholder, glob or spec. */
62
59
  const LOGIC_FILE = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*\/)*[a-z0-9]+(?:-[a-z0-9]+)*(?:\.[a-z0-9]+(?:-[a-z0-9]+)*)+\.ts$/;
63
-
64
60
  /** The role suffix of a file name (`passport.tokens.ts` gives `tokens`). */
65
61
  export const suffixOf = (file) => /\.([a-z0-9-]+)\.ts$/.exec(file)?.[1] ?? null;
66
-
67
62
  /**
68
63
  * The files a slot declares as logic (`logic`, names relative to the slot path): a file that carries logic without a logic-role suffix.
69
64
  * Each is measured at 100 per file like a logic-role file (scripts/hfs/coverage-scope.mjs), and its `<stem>.spec.ts` beside it is a
70
65
  * legitimate unit spec its slot admits (scripts/hfs/allows.mjs, eslint-canon-be unit-test-colocated). No role name is added for it.
71
66
  */
72
67
  export const declaredLogicOf = (slot) => (Array.isArray(slot?.logic) ? slot.logic : []);
73
-
74
68
  /** The unit spec beside a declared logic file: `passport.tokens.ts` gives `passport.tokens.spec.ts`. */
75
69
  export const declaredLogicSpecOf = (file) => file.replace(/\.ts$/, '.spec.ts');
76
-
77
70
  /**
78
71
  * Shape problems of a slot's `logic`: a non-empty list of unique `<name>.<part>.ts` files, each one the slot requires or allows by that
79
72
  * exact name, on a tracked directory slot of profile be that is coverage: required and unit-beside, and (given the logic roles) none
80
73
  * already of a logic role, which its role measures.
81
74
  */
82
75
  export function slotLogicProblems(slot, at, logicRoles = []) {
83
- if (slot.logic === undefined) return [];
84
- const list = slot.logic;
85
- if (!strList(list) || !list.length || new Set(list).size !== list.length || !list.every((file) => LOGIC_FILE.test(file) && !file.endsWith('.spec.ts'))) return [`${at}: logic must be a non-empty list of unique <name>.<part>.ts files relative to the slot path`];
86
- const bad = [];
87
- const home = typeof slot.path === 'string' && slot.path.endsWith('/') && slot.tracked === 'tracked' && Array.isArray(slot.profiles) && slot.profiles.includes('be') && slot.coverage === 'required' && slot.tests === 'unit-beside';
88
- if (!home) bad.push(`${at}: logic belongs to a tracked directory slot of profile be whose coverage is required and whose tests are unit-beside`);
89
- const named = [...(slot.requires ?? []), ...(slot.allows ?? [])];
90
- for (const file of list.filter((entry) => !named.includes(entry))) bad.push(`${at}: logic file ${file} must be one the slot requires or allows by that name`);
91
- for (const file of list.filter((entry) => logicRoles.includes(suffixOf(entry)))) bad.push(`${at}: logic file ${file} is of the logic role ${suffixOf(file)}, which measures it already`);
92
- return bad;
93
- }
94
-
95
-
76
+ if (slot.logic === undefined)
77
+ return [];
78
+ const list = slot.logic;
79
+ if (!strList(list) || !list.length || new Set(list).size !== list.length || !list.every((file) => LOGIC_FILE.test(file) && !file.endsWith('.spec.ts')))
80
+ return [`${at}: logic must be a non-empty list of unique <name>.<part>.ts files relative to the slot path`];
81
+ const bad = [];
82
+ const home = typeof slot.path === 'string' && slot.path.endsWith('/') && slot.tracked === 'tracked' && Array.isArray(slot.profiles) && slot.profiles.includes('be') && slot.coverage === 'required' && slot.tests === 'unit-beside';
83
+ if (!home)
84
+ bad.push(`${at}: logic belongs to a tracked directory slot of profile be whose coverage is required and whose tests are unit-beside`);
85
+ const named = [...(slot.requires ?? []), ...(slot.allows ?? [])];
86
+ for (const file of list.filter((entry) => !named.includes(entry)))
87
+ bad.push(`${at}: logic file ${file} must be one the slot requires or allows by that name`);
88
+ for (const file of list.filter((entry) => logicRoles.includes(suffixOf(entry))))
89
+ bad.push(`${at}: logic file ${file} is of the logic role ${suffixOf(file)}, which measures it already`);
90
+ return bad;
91
+ }
96
92
  /** Shape problems of ruleParams.be.unitRoles: unique roles of the suffix vocabulary, each spec `<role>.spec`. */
97
93
  export function unitRolesProblems(be) {
98
- const roles = be.unitRoles;
99
- const roleOk = (r) => r !== null && typeof r === 'object' && !Array.isArray(r) && Object.keys(r).every((k) => ['role', 'spec', 'slot', 'exempt'].includes(k)) && NAME.test(String(r.role)) && String(r.spec) === `${r.role}.spec` && (r.slot === undefined || /^be.[a-z0-9.-]+$/.test(String(r.slot))) && (r.exempt === undefined || (Array.isArray(r.exempt) && r.exempt.every((c) => /^[A-Z][A-Z0-9_]+$/.test(String(c)))));
100
- if (!Array.isArray(roles) || !roles.length || !roles.every(roleOk) || new Set(roles.map((r) => r.role)).size !== roles.length) return ['ruleParams.be.unitRoles must be a non-empty list of unique {role, spec: <role>.spec, slot?, exempt?: [rule codes]}'];
101
- if (Array.isArray(be.suffixes) && roles.some((r) => !be.suffixes.includes(r.role))) return ['ruleParams.be.unitRoles names a role that is not in ruleParams.be.suffixes'];
102
- return [];
94
+ const roles = be.unitRoles;
95
+ const roleOk = (r) => r !== null && typeof r === 'object' && !Array.isArray(r) && Object.keys(r).every((k) => ['role', 'spec', 'slot', 'exempt'].includes(k)) && NAME.test(String(r.role)) && String(r.spec) === `${r.role}.spec` && (r.slot === undefined || /^be.[a-z0-9.-]+$/.test(String(r.slot))) && (r.exempt === undefined || (Array.isArray(r.exempt) && r.exempt.every((c) => /^[A-Z][A-Z0-9_]+$/.test(String(c)))));
96
+ if (!Array.isArray(roles) || !roles.length || !roles.every(roleOk) || new Set(roles.map((r) => r.role)).size !== roles.length)
97
+ return ['ruleParams.be.unitRoles must be a non-empty list of unique {role, spec: <role>.spec, slot?, exempt?: [rule codes]}'];
98
+ if (Array.isArray(be.suffixes) && roles.some((r) => !be.suffixes.includes(r.role)))
99
+ return ['ruleParams.be.unitRoles names a role that is not in ruleParams.be.suffixes'];
100
+ return [];
103
101
  }
104
-
105
102
  /** Shape problems of ruleParams.be.logicRoles, valueRoles and thinRoles: each a non-empty list of unique roles of the suffix vocabulary; every unit role is a logic role. */
106
103
  export function roleListProblems(be) {
107
- const bad = [];
108
- for (const key of ['logicRoles', 'valueRoles', 'thinRoles']) {
109
- const list = be[key];
110
- if (!strList(list) || !list.length || new Set(list).size !== list.length || !list.every((role) => NAME.test(role))) bad.push(`ruleParams.be.${key} must be a non-empty list of unique kebab-case roles`);
111
- else if (Array.isArray(be.suffixes) && list.some((role) => !be.suffixes.includes(role))) bad.push(`ruleParams.be.${key} names a role that is not in ruleParams.be.suffixes`);
112
- }
113
- if (strList(be.valueRoles) && strList(be.logicRoles) && be.valueRoles.some((role) => !be.logicRoles.includes(role))) bad.push('every ruleParams.be.valueRoles role is a logic role (ruleParams.be.logicRoles)');
114
- if (strList(be.logicRoles) && Array.isArray(be.unitRoles) && be.unitRoles.some((r) => r?.slot === undefined && !be.logicRoles.includes(r?.role))) bad.push('every ruleParams.be.unitRoles role that is not tied to a slot is a logic role (ruleParams.be.logicRoles)');
115
- return bad;
104
+ const bad = [];
105
+ for (const key of ['logicRoles', 'valueRoles', 'thinRoles']) {
106
+ const list = be[key];
107
+ if (!strList(list) || !list.length || new Set(list).size !== list.length || !list.every((role) => NAME.test(role)))
108
+ bad.push(`ruleParams.be.${key} must be a non-empty list of unique kebab-case roles`);
109
+ else if (Array.isArray(be.suffixes) && list.some((role) => !be.suffixes.includes(role)))
110
+ bad.push(`ruleParams.be.${key} names a role that is not in ruleParams.be.suffixes`);
111
+ }
112
+ if (strList(be.valueRoles) && strList(be.logicRoles) && be.valueRoles.some((role) => !be.logicRoles.includes(role)))
113
+ bad.push('every ruleParams.be.valueRoles role is a logic role (ruleParams.be.logicRoles)');
114
+ if (strList(be.logicRoles) && Array.isArray(be.unitRoles) && be.unitRoles.some((r) => r?.slot === undefined && !be.logicRoles.includes(r?.role)))
115
+ bad.push('every ruleParams.be.unitRoles role that is not tied to a slot is a logic role (ruleParams.be.logicRoles)');
116
+ return bad;
116
117
  }
117
118
  /** The kind of a manifest and of a declaration that describes the StarCi runtime repository; also its one profile. */
118
119
  export const RUNTIME_KIND = 'runtime';
@@ -120,7 +121,6 @@ export const MANIFEST_KINDS = [APP_KIND, RUNTIME_KIND];
120
121
  /** The kind of a parsed manifest: `kind`, or app when absent (knowledge/hfs/slots.yaml carries none). */
121
122
  export const manifestKind = (m) => (isPlainObject(m) && m.kind !== undefined ? m.kind : APP_KIND);
122
123
  const strList = (v) => stringList(v);
123
-
124
124
  const APP_SLOT_KEYS = ['id', 'profiles', 'path', 'presence', 'tracked', 'tier', 'tests', 'owner', 'appKind', 'minInstances', 'requiredWhen', 'requiredInstances', 'requires', 'pattern', 'trigger', 'allows', 'forbids', 'layers', 'kinds', 'roles', 'composedBy', 'budget', 'managedBy', 'liteManagedBy', 'rules', 'goesTo', 'why', 'since', 'perConnection', 'parent', 'editions', 'editionWhy', 'litePresence', 'lite', 'provider', 'coverage', 'entries', 'outcomeHome', 'templateNa', 'exemplifiedBy', 'role', 'importedBy', 'rewrittenBy', 'logic'];
125
125
  /** The roles a file slot may play that a rule reads (`role`): the entity registry of persistence.md BE-PERSISTENCE-3 (architecture/entity-registry.mjs). */
126
126
  const SLOT_ROLES = ['entity-registry'];
@@ -128,348 +128,423 @@ const SLOT_ROLES = ['entity-registry'];
128
128
  const LITE_OVERLAY_KEYS = ['path', 'requires', 'allows', 'forbids', 'minInstances', 'requiredInstances', 'why'];
129
129
  /** A runtime slot has no app kind, side composition, layer or managed template; it may name the generator of a generated copy. */
130
130
  const RUNTIME_SLOT_KEYS = ['id', 'profiles', 'path', 'presence', 'tracked', 'tier', 'tests', 'owner', 'minInstances', 'requires', 'allows', 'forbids', 'budget', 'rules', 'goesTo', 'why', 'since', 'generatedBy', 'parent', 'coverage'];
131
-
132
131
  const isPositiveInt = (v) => Number.isInteger(v) && v >= 1;
133
132
  const instancesShapeOk = (v) => isPlainObject(v) && Object.values(v).every((list) => strList(list) && list.length);
134
-
135
133
  const generatedByInvalid = (generatedBy) => typeof generatedBy !== 'string' || !generatedBy || generatedBy.startsWith('/') || generatedBy.includes('..');
136
-
137
134
  const profilesInvalid = (profiles, appScope, scopes) => !Array.isArray(profiles) || !profiles.length || !profiles.every((p) => scopes.includes(p)) || new Set(profiles).size !== profiles.length || (profiles.includes(appScope) && profiles.length !== 1);
138
-
139
135
  function runtimeIdentityProblems(slot, at) {
140
- const bad = [];
141
- if (!RUNTIME_SLOT_ID.test(String(slot.id))) bad.push(`${at}: id must look like runtime.<name>`);
142
- if (JSON.stringify(slot.profiles) !== JSON.stringify([RUNTIME_KIND])) bad.push(`${at}: profiles must be [runtime]`);
143
- if (slot.tracked === 'generated' && generatedByInvalid(slot.generatedBy)) bad.push(`${at}: a generated slot names its generator (generatedBy, a repository-relative path)`);
144
- if (slot.generatedBy !== undefined && slot.tracked !== 'generated') bad.push(`${at}: generatedBy belongs to a generated slot`);
145
- return bad;
146
- }
147
-
136
+ const bad = [];
137
+ if (!RUNTIME_SLOT_ID.test(String(slot.id)))
138
+ bad.push(`${at}: id must look like runtime.<name>`);
139
+ if (JSON.stringify(slot.profiles) !== JSON.stringify([RUNTIME_KIND]))
140
+ bad.push(`${at}: profiles must be [runtime]`);
141
+ if (slot.tracked === 'generated' && generatedByInvalid(slot.generatedBy))
142
+ bad.push(`${at}: a generated slot names its generator (generatedBy, a repository-relative path)`);
143
+ if (slot.generatedBy !== undefined && slot.tracked !== 'generated')
144
+ bad.push(`${at}: generatedBy belongs to a generated slot`);
145
+ return bad;
146
+ }
148
147
  function appIdentityProblems(slot, at, appScope, scopes) {
149
- const bad = [];
150
- if (!SLOT_ID.test(String(slot.id))) bad.push(`${at}: id must look like be.transport.http`);
151
- if (profilesInvalid(slot.profiles, appScope, scopes)) bad.push(`${at}: profiles must be [app] or a unique non-empty subset of be, fe`);
152
- else if ((slot.profiles[0] === appScope) !== String(slot.id).startsWith(`${appScope}.`)) bad.push(`${at}: an app-root slot has profiles [app] and an id app.<name>, and only it`);
153
- if (slot.rewrittenBy !== undefined && (typeof slot.rewrittenBy !== 'string' || !slot.rewrittenBy.trim() || slot.tracked !== 'ignored' || String(slot.path).endsWith('/'))) bad.push(`${at}: rewrittenBy names the dev server that writes the files of an ignored file slot`);
154
- return bad;
155
- }
156
-
148
+ const bad = [];
149
+ if (!SLOT_ID.test(String(slot.id)))
150
+ bad.push(`${at}: id must look like be.transport.http`);
151
+ if (profilesInvalid(slot.profiles, appScope, scopes))
152
+ bad.push(`${at}: profiles must be [app] or a unique non-empty subset of be, fe`);
153
+ else if ((slot.profiles[0] === appScope) !== String(slot.id).startsWith(`${appScope}.`))
154
+ bad.push(`${at}: an app-root slot has profiles [app] and an id app.<name>, and only it`);
155
+ if (slot.rewrittenBy !== undefined && (typeof slot.rewrittenBy !== 'string' || !slot.rewrittenBy.trim() || slot.tracked !== 'ignored' || String(slot.path).endsWith('/')))
156
+ bad.push(`${at}: rewrittenBy names the dev server that writes the files of an ignored file slot`);
157
+ return bad;
158
+ }
157
159
  /** Shape problems of one slot of a manifest of `kind` (app or runtime). */
158
160
  function slotIdentityProblems(slot, runtime, slotKeys, at, appScope, scopes) {
159
- const bad = [];
160
- for (const key of Object.keys(slot)) if (!slotKeys.has(key)) bad.push(`${at}: unknown field ${key}`);
161
- bad.push(...(runtime ? runtimeIdentityProblems(slot, at) : appIdentityProblems(slot, at, appScope, scopes)));
162
- return bad;
161
+ const bad = [];
162
+ for (const key of Object.keys(slot))
163
+ if (!slotKeys.has(key))
164
+ bad.push(`${at}: unknown field ${key}`);
165
+ bad.push(...(runtime ? runtimeIdentityProblems(slot, at) : appIdentityProblems(slot, at, appScope, scopes)));
166
+ return bad;
163
167
  }
164
-
165
168
  function slotCoverageProblems(slot, at, runtime) {
166
- const bad = [];
167
- const measured = slot.tracked === 'tracked' && (runtime || (Array.isArray(slot.profiles) && slot.profiles.includes('be')));
168
- if (measured && !COVERAGE.includes(slot.coverage)) bad.push(`${at}: coverage must be one of ${COVERAGE.join(', ')} (every tracked slot of ${runtime ? 'a runtime manifest' : 'the be profile'} declares it)`);
169
- if (!measured && slot.coverage !== undefined) bad.push(`${at}: coverage belongs to a tracked slot of ${runtime ? 'a runtime manifest' : 'the be profile'} only`);
170
- return bad;
169
+ const bad = [];
170
+ const measured = slot.tracked === 'tracked' && (runtime || (Array.isArray(slot.profiles) && slot.profiles.includes('be')));
171
+ if (measured && !COVERAGE.includes(slot.coverage))
172
+ bad.push(`${at}: coverage must be one of ${COVERAGE.join(', ')} (every tracked slot of ${runtime ? 'a runtime manifest' : 'the be profile'} declares it)`);
173
+ if (!measured && slot.coverage !== undefined)
174
+ bad.push(`${at}: coverage belongs to a tracked slot of ${runtime ? 'a runtime manifest' : 'the be profile'} only`);
175
+ return bad;
171
176
  }
172
-
173
177
  function slotLocationProblems(slot, at, runtime, tracked) {
174
- const bad = [];
175
- if (typeof slot.path !== 'string' || !slot.path) bad.push(`${at}: path is required`);
176
- if (slot.parent !== undefined && !/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/.test(String(slot.parent))) bad.push(`${at}: parent must be a slot id`);
177
- if (!PRESENCE.includes(slot.presence)) bad.push(`${at}: presence must be one of ${PRESENCE.join(', ')}`);
178
- if (!tracked.includes(slot.tracked)) bad.push(`${at}: tracked must be one of ${tracked.join(', ')}`);
179
- if (!NAME.test(String(slot.tier))) bad.push(`${at}: tier must be a tier name, none or inherit`);
180
- if (!TESTS.includes(slot.tests)) bad.push(`${at}: tests must be one of ${TESTS.join(', ')}`);
181
- if (slot.owner !== undefined && typeof slot.owner !== 'boolean') bad.push(`${at}: owner must be a boolean`);
182
- bad.push(...slotCoverageProblems(slot, at, runtime));
183
- return bad;
184
- }
185
-
178
+ const bad = [];
179
+ if (typeof slot.path !== 'string' || !slot.path)
180
+ bad.push(`${at}: path is required`);
181
+ if (slot.parent !== undefined && !/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/.test(String(slot.parent)))
182
+ bad.push(`${at}: parent must be a slot id`);
183
+ if (!PRESENCE.includes(slot.presence))
184
+ bad.push(`${at}: presence must be one of ${PRESENCE.join(', ')}`);
185
+ if (!tracked.includes(slot.tracked))
186
+ bad.push(`${at}: tracked must be one of ${tracked.join(', ')}`);
187
+ if (!NAME.test(String(slot.tier)))
188
+ bad.push(`${at}: tier must be a tier name, none or inherit`);
189
+ if (!TESTS.includes(slot.tests))
190
+ bad.push(`${at}: tests must be one of ${TESTS.join(', ')}`);
191
+ if (slot.owner !== undefined && typeof slot.owner !== 'boolean')
192
+ bad.push(`${at}: owner must be a boolean`);
193
+ bad.push(...slotCoverageProblems(slot, at, runtime));
194
+ return bad;
195
+ }
186
196
  const NAMED_SLOT_FIELDS = [['appKind', 'appKind must be a name'], ['trigger', 'trigger must be a trigger kind name'], ['pattern', 'pattern must be a pattern name']];
187
-
188
197
  function slotInstanceProblems(slot, at) {
189
- const bad = [];
190
- if (slot.pattern !== undefined && !/^[a-z][a-z0-9-]*$/.test(String(slot.pattern))) bad.push(`${at}: pattern must be a kebab-case pattern name`);
191
- if (slot.requiredInstances !== undefined && !instancesShapeOk(slot.requiredInstances)) bad.push(`${at}: requiredInstances must map a variable to a non-empty list of names`);
192
- return bad;
198
+ const bad = [];
199
+ if (slot.pattern !== undefined && !/^[a-z][a-z0-9-]*$/.test(String(slot.pattern)))
200
+ bad.push(`${at}: pattern must be a kebab-case pattern name`);
201
+ if (slot.requiredInstances !== undefined && !instancesShapeOk(slot.requiredInstances))
202
+ bad.push(`${at}: requiredInstances must map a variable to a non-empty list of names`);
203
+ return bad;
193
204
  }
194
-
195
205
  function slotPatternProblems(slot, at) {
196
- const bad = [];
197
- for (const [key, what] of NAMED_SLOT_FIELDS) if (slot[key] !== undefined && !NAME.test(String(slot[key]))) bad.push(`${at}: ${what}`);
198
- if (slot.minInstances !== undefined && !isPositiveInt(slot.minInstances)) bad.push(`${at}: minInstances must be a positive integer`);
199
- if (slot.requiredWhen !== undefined && slot.requiredWhen !== 'connections') bad.push(`${at}: requiredWhen may only be connections`);
200
- bad.push(...slotInstanceProblems(slot, at));
201
- return bad;
202
- }
203
-
206
+ const bad = [];
207
+ for (const [key, what] of NAMED_SLOT_FIELDS)
208
+ if (slot[key] !== undefined && !NAME.test(String(slot[key])))
209
+ bad.push(`${at}: ${what}`);
210
+ if (slot.minInstances !== undefined && !isPositiveInt(slot.minInstances))
211
+ bad.push(`${at}: minInstances must be a positive integer`);
212
+ if (slot.requiredWhen !== undefined && slot.requiredWhen !== 'connections')
213
+ bad.push(`${at}: requiredWhen may only be connections`);
214
+ bad.push(...slotInstanceProblems(slot, at));
215
+ return bad;
216
+ }
204
217
  const kindsInvalid = (slot) => {
205
- if (slot.kinds === undefined || !strList(slot.kinds)) return false;
206
- return !slot.kinds.length || new Set(slot.kinds).size !== slot.kinds.length || slot.kinds.some((k) => !NAME.test(k) || (slot.layers ?? []).includes(k));
218
+ if (slot.kinds === undefined || !strList(slot.kinds))
219
+ return false;
220
+ return !slot.kinds.length || new Set(slot.kinds).size !== slot.kinds.length || slot.kinds.some((k) => !NAME.test(k) || (slot.layers ?? []).includes(k));
207
221
  };
208
222
  const rolesValid = (roles) => isPlainObject(roles) && Object.keys(roles).length && Object.entries(roles).every(([role, file]) => NAME.test(role) && typeof file === 'string' && file && !file.includes('/'));
209
223
  const composedByValid = (list) => strList(list) && list.length && new Set(list).size === list.length;
210
224
  const budgetValid = (budget) => isPlainObject(budget) && Object.keys(budget).length && Object.values(budget).every(isPositiveInt);
211
-
212
225
  function slotListProblems(slot, at) {
213
- const bad = [];
214
- for (const key of ['requires', 'allows', 'forbids', 'layers', 'kinds']) if (slot[key] !== undefined && !strList(slot[key])) bad.push(`${at}: ${key} must be a list of strings`);
215
- if (kindsInvalid(slot)) bad.push(`${at}: kinds must be a non-empty list of unique folder names that are not layers`);
216
- if (slot.roles !== undefined && !rolesValid(slot.roles)) bad.push(`${at}: roles must map a role name to a file name`);
217
- if (slot.composedBy !== undefined && !composedByValid(slot.composedBy)) bad.push(`${at}: composedBy must be a non-empty list of unique app kinds`);
218
- if (slot.budget !== undefined && !budgetValid(slot.budget)) bad.push(`${at}: budget must map names to positive integers`);
219
- for (const key of ['managedBy', 'liteManagedBy']) if (slot[key] !== undefined && !NAME.test(String(slot[key]))) bad.push(`${at}: ${key} must be a template id`);
220
- return bad;
221
- }
222
-
226
+ const bad = [];
227
+ for (const key of ['requires', 'allows', 'forbids', 'layers', 'kinds'])
228
+ if (slot[key] !== undefined && !strList(slot[key]))
229
+ bad.push(`${at}: ${key} must be a list of strings`);
230
+ if (kindsInvalid(slot))
231
+ bad.push(`${at}: kinds must be a non-empty list of unique folder names that are not layers`);
232
+ if (slot.roles !== undefined && !rolesValid(slot.roles))
233
+ bad.push(`${at}: roles must map a role name to a file name`);
234
+ if (slot.composedBy !== undefined && !composedByValid(slot.composedBy))
235
+ bad.push(`${at}: composedBy must be a non-empty list of unique app kinds`);
236
+ if (slot.budget !== undefined && !budgetValid(slot.budget))
237
+ bad.push(`${at}: budget must map names to positive integers`);
238
+ for (const key of ['managedBy', 'liteManagedBy'])
239
+ if (slot[key] !== undefined && !NAME.test(String(slot[key])))
240
+ bad.push(`${at}: ${key} must be a template id`);
241
+ return bad;
242
+ }
223
243
  function slotAppOptionProblems(slot, at) {
224
- const bad = [];
225
- bad.push(...slotEditionWhyProblems(slot, at), ...slotCoverageEvidenceProblems(slot, at));
226
- // Legacy coverage status derives only from an explicit `since`; a slot that omits it is refused, so a new slot can never be taken for an old one.
227
- if (slot.since === undefined) bad.push(`${at}: since is required (the manifest version that added the slot)`);
228
- if (slot.editions !== undefined && !(Array.isArray(slot.editions) && slot.editions.length && slot.editions.every((e) => EDITIONS.includes(e)) && new Set(slot.editions).size === slot.editions.length)) bad.push(`${at}: editions must be a non-empty subset of ${EDITIONS.join(', ')}`);
229
- if (slot.litePresence !== undefined && !(PRESENCE.includes(slot.litePresence) || (isPlainObject(slot.litePresence) && Object.keys(slot.litePresence).length && Object.entries(slot.litePresence).every(([side, value]) => ['be', 'fe'].includes(side) && PRESENCE.includes(value))))) bad.push(`${at}: litePresence must be a presence value or map sides to presence values`);
230
- if (slot.provider !== undefined) {
231
- if (!CONNECTION_PROVIDERS.includes(slot.provider)) bad.push(`${at}: provider must be one of ${CONNECTION_PROVIDERS.join(' | ')}`);
232
- else if (slot.presence !== 'opt-in' || slot.appKind !== undefined) bad.push(`${at}: provider belongs to an opt-in slot that is not an app kind (a connection with that provider enables it)`);
233
- }
234
- return bad;
235
- }
236
-
244
+ const bad = [];
245
+ bad.push(...slotEditionWhyProblems(slot, at), ...slotCoverageEvidenceProblems(slot, at));
246
+ // Legacy coverage status derives only from an explicit `since`; a slot that omits it is refused, so a new slot can never be taken for an old one.
247
+ if (slot.since === undefined)
248
+ bad.push(`${at}: since is required (the manifest version that added the slot)`);
249
+ if (slot.editions !== undefined && !(Array.isArray(slot.editions) && slot.editions.length && slot.editions.every((e) => EDITIONS.includes(e)) && new Set(slot.editions).size === slot.editions.length))
250
+ bad.push(`${at}: editions must be a non-empty subset of ${EDITIONS.join(', ')}`);
251
+ if (slot.litePresence !== undefined && !(PRESENCE.includes(slot.litePresence) || (isPlainObject(slot.litePresence) && Object.keys(slot.litePresence).length && Object.entries(slot.litePresence).every(([side, value]) => ['be', 'fe'].includes(side) && PRESENCE.includes(value)))))
252
+ bad.push(`${at}: litePresence must be a presence value or map sides to presence values`);
253
+ if (slot.provider !== undefined) {
254
+ if (!CONNECTION_PROVIDERS.includes(slot.provider))
255
+ bad.push(`${at}: provider must be one of ${CONNECTION_PROVIDERS.join(' | ')}`);
256
+ else if (slot.presence !== 'opt-in' || slot.appKind !== undefined)
257
+ bad.push(`${at}: provider belongs to an opt-in slot that is not an app kind (a connection with that provider enables it)`);
258
+ }
259
+ return bad;
260
+ }
237
261
  function slotEditionWhyProblems(slot, at) {
238
- if (slot.editionWhy === undefined) return [];
239
- return typeof slot.editionWhy === 'string' && slot.editionWhy.trim()
240
- ? [] : [`${at}: editionWhy must be non-empty text`];
262
+ if (slot.editionWhy === undefined)
263
+ return [];
264
+ return typeof slot.editionWhy === 'string' && slot.editionWhy.trim()
265
+ ? [] : [`${at}: editionWhy must be non-empty text`];
241
266
  }
242
-
243
267
  const slotEvidencePathValid = (value) => relPath(value) && /^[^\s]+$/.test(value);
244
-
245
268
  function slotEvidenceRefValid(ref) {
246
- if (typeof ref === 'string') return slotEvidencePathValid(ref);
247
- if (!isPlainObject(ref) || !slotEvidencePathValid(ref.path)) return false;
248
- if (!Object.keys(ref).every((key) => ['path', 'edition', 'editions'].includes(key))) return false;
249
- if (ref.edition !== undefined && !EDITIONS.includes(ref.edition)) return false;
250
- if (ref.editions !== undefined && !nonemptyUniqueList(ref.editions, (edition) => EDITIONS.includes(edition))) return false;
251
- return ref.edition === undefined || ref.editions === undefined;
252
- }
253
-
269
+ if (typeof ref === 'string')
270
+ return slotEvidencePathValid(ref);
271
+ if (!isPlainObject(ref) || !slotEvidencePathValid(ref.path))
272
+ return false;
273
+ if (!Object.keys(ref).every((key) => ['path', 'edition', 'editions'].includes(key)))
274
+ return false;
275
+ if (ref.edition !== undefined && !EDITIONS.includes(ref.edition))
276
+ return false;
277
+ if (ref.editions !== undefined && !nonemptyUniqueList(ref.editions, (edition) => EDITIONS.includes(edition)))
278
+ return false;
279
+ return ref.edition === undefined || ref.editions === undefined;
280
+ }
254
281
  const slotEvidenceRefKey = (ref) => typeof ref === 'string' ? ref
255
- : JSON.stringify([ref.path, ref.edition, ref.editions]);
256
-
282
+ : JSON.stringify([ref.path, ref.edition, ref.editions]);
257
283
  function slotCoverageEvidenceProblems(slot, at) {
258
- const bad = [];
259
- if (slot.templateNa !== undefined && !(typeof slot.templateNa === 'string' && slot.templateNa.trim()))
260
- bad.push(`${at}: templateNa must be non-empty text`);
261
- if (slot.exemplifiedBy === undefined) return bad;
262
- const refs = slot.exemplifiedBy;
263
- const valid = Array.isArray(refs) && refs.length > 0 && refs.every(slotEvidenceRefValid)
264
- && new Set(refs.map(slotEvidenceRefKey)).size === refs.length;
265
- if (!valid) bad.push(`${at}: exemplifiedBy must be unique repository-relative paths or {path, edition? | editions?} references`);
266
- return bad;
267
- }
268
-
284
+ const bad = [];
285
+ if (slot.templateNa !== undefined && !(typeof slot.templateNa === 'string' && slot.templateNa.trim()))
286
+ bad.push(`${at}: templateNa must be non-empty text`);
287
+ if (slot.exemplifiedBy === undefined)
288
+ return bad;
289
+ const refs = slot.exemplifiedBy;
290
+ const valid = Array.isArray(refs) && refs.length > 0 && refs.every(slotEvidenceRefValid)
291
+ && new Set(refs.map(slotEvidenceRefKey)).size === refs.length;
292
+ if (!valid)
293
+ bad.push(`${at}: exemplifiedBy must be unique repository-relative paths or {path, edition? | editions?} references`);
294
+ return bad;
295
+ }
269
296
  function slotLiteOverlayProblems(slot, at) {
270
- if (slot.lite === undefined) return [];
271
- const ok = isPlainObject(slot.lite) && Object.keys(slot.lite).length && Object.keys(slot.lite).every((key) => LITE_OVERLAY_KEYS.includes(key))
272
- && (slot.lite.path === undefined || (typeof slot.lite.path === 'string' && slot.lite.path))
273
- && (slot.lite.why === undefined || (typeof slot.lite.why === 'string' && slot.lite.why.trim()))
274
- && ['requires', 'allows', 'forbids'].every((key) => slot.lite[key] === undefined || strList(slot.lite[key]))
275
- && (slot.lite.minInstances === undefined || (Number.isInteger(slot.lite.minInstances) && slot.lite.minInstances >= 1))
276
- && (slot.lite.requiredInstances === undefined || (isPlainObject(slot.lite.requiredInstances) && Object.values(slot.lite.requiredInstances).every((v) => strList(v) && v.length)));
277
- return ok ? [] : [`${at}: lite may hold only ${LITE_OVERLAY_KEYS.join(', ')}, each shaped as in the slot body`];
278
- }
279
-
297
+ if (slot.lite === undefined)
298
+ return [];
299
+ const ok = isPlainObject(slot.lite) && Object.keys(slot.lite).length && Object.keys(slot.lite).every((key) => LITE_OVERLAY_KEYS.includes(key))
300
+ && (slot.lite.path === undefined || (typeof slot.lite.path === 'string' && slot.lite.path))
301
+ && (slot.lite.why === undefined || (typeof slot.lite.why === 'string' && slot.lite.why.trim()))
302
+ && ['requires', 'allows', 'forbids'].every((key) => slot.lite[key] === undefined || strList(slot.lite[key]))
303
+ && (slot.lite.minInstances === undefined || (Number.isInteger(slot.lite.minInstances) && slot.lite.minInstances >= 1))
304
+ && (slot.lite.requiredInstances === undefined || (isPlainObject(slot.lite.requiredInstances) && Object.values(slot.lite.requiredInstances).every((v) => strList(v) && v.length)));
305
+ return ok ? [] : [`${at}: lite may hold only ${LITE_OVERLAY_KEYS.join(', ')}, each shaped as in the slot body`];
306
+ }
280
307
  function slotEntryProblems(slot, at) {
281
- const bad = [];
282
- if (slot.entries !== undefined) {
283
- const listed = strList(slot.entries) && slot.entries.length > 0 && new Set(slot.entries).size === slot.entries.length && slot.entries.every(relPath);
284
- if (!listed) bad.push(`${at}: entries must be a non-empty list of unique relative file paths`);
285
- else if (typeof slot.path !== 'string' || !slot.path.endsWith('/')) bad.push(`${at}: entries belong to a directory slot (they name its explicit public API files)`);
286
- else if (Array.isArray(slot.allows) && slot.entries.some((entry) => !slot.allows.includes(entry))) bad.push(`${at}: every entry must be one of the names the slot allows`);
287
- }
288
- if (slot.outcomeHome !== undefined && !(slot.outcomeHome === true && typeof slot.path === 'string' && slot.path && !slot.path.endsWith('/'))) bad.push(`${at}: outcomeHome is true and belongs to a file slot (the one file that declares the repository's Outcome union)`);
289
- if (slot.role !== undefined && !(SLOT_ROLES.includes(slot.role) && typeof slot.path === 'string' && slot.path && !slot.path.endsWith('/'))) bad.push(`${at}: role is one of ${SLOT_ROLES.join(', ')} and belongs to a file slot`);
290
- if (slot.importedBy !== undefined && !(slot.role !== undefined && strList(slot.importedBy) && slot.importedBy.length && new Set(slot.importedBy).size === slot.importedBy.length && slot.importedBy.every(relPath))) bad.push(`${at}: importedBy is a non-empty list of unique relative path patterns of the only files that import the slot's file by deep path, on a slot with a role`);
291
- return bad;
292
- }
293
-
308
+ const bad = [];
309
+ if (slot.entries !== undefined) {
310
+ const listed = strList(slot.entries) && slot.entries.length > 0 && new Set(slot.entries).size === slot.entries.length && slot.entries.every(relPath);
311
+ if (!listed)
312
+ bad.push(`${at}: entries must be a non-empty list of unique relative file paths`);
313
+ else if (typeof slot.path !== 'string' || !slot.path.endsWith('/'))
314
+ bad.push(`${at}: entries belong to a directory slot (they name its explicit public API files)`);
315
+ else if (Array.isArray(slot.allows) && slot.entries.some((entry) => !slot.allows.includes(entry)))
316
+ bad.push(`${at}: every entry must be one of the names the slot allows`);
317
+ }
318
+ if (slot.outcomeHome !== undefined && !(slot.outcomeHome === true && typeof slot.path === 'string' && slot.path && !slot.path.endsWith('/')))
319
+ bad.push(`${at}: outcomeHome is true and belongs to a file slot (the one file that declares the repository's Outcome union)`);
320
+ if (slot.role !== undefined && !(SLOT_ROLES.includes(slot.role) && typeof slot.path === 'string' && slot.path && !slot.path.endsWith('/')))
321
+ bad.push(`${at}: role is one of ${SLOT_ROLES.join(', ')} and belongs to a file slot`);
322
+ if (slot.importedBy !== undefined && !(slot.role !== undefined && strList(slot.importedBy) && slot.importedBy.length && new Set(slot.importedBy).size === slot.importedBy.length && slot.importedBy.every(relPath)))
323
+ bad.push(`${at}: importedBy is a non-empty list of unique relative path patterns of the only files that import the slot's file by deep path, on a slot with a role`);
324
+ return bad;
325
+ }
294
326
  function slotPolicyProblems(slot, at) {
295
- const bad = [];
296
- if (slot.rules !== undefined && !(Array.isArray(slot.rules) && slot.rules.every((r) => /^[A-Z][A-Z0-9_]*\*?$/.test(String(r))) && new Set(slot.rules).size === slot.rules.length)) bad.push(`${at}: rules must be unique rule ids`);
297
- if (slot.perConnection !== undefined && !(slot.id === 'be.persistence' && strList(slot.perConnection) && slot.perConnection.length && new Set(slot.perConnection).size === slot.perConnection.length && slot.perConnection.every((name) => NAME.test(name)))) bad.push(`${at}: perConnection is a unique list of capability names, only on be.persistence (the platform capabilities whose tables exist on every connection that uses them)`);
298
- if (slot.since !== undefined && !SEMVER.test(String(slot.since))) bad.push(`${at}: since must be a version`);
299
- if (slot.tracked === 'external' && (typeof slot.goesTo !== 'string' || slot.presence !== 'forbidden')) bad.push(`${at}: an external slot is forbidden and says where it goes (goesTo)`);
300
- if (slot.presence === 'forbidden' && slot.tracked !== 'external') bad.push(`${at}: a forbidden slot is external`);
301
- return bad;
302
- }
303
-
327
+ const bad = [];
328
+ if (slot.rules !== undefined && !(Array.isArray(slot.rules) && slot.rules.every((r) => /^[A-Z][A-Z0-9_]*\*?$/.test(String(r))) && new Set(slot.rules).size === slot.rules.length))
329
+ bad.push(`${at}: rules must be unique rule ids`);
330
+ if (slot.perConnection !== undefined && !(slot.id === 'be.persistence' && strList(slot.perConnection) && slot.perConnection.length && new Set(slot.perConnection).size === slot.perConnection.length && slot.perConnection.every((name) => NAME.test(name))))
331
+ bad.push(`${at}: perConnection is a unique list of capability names, only on be.persistence (the platform capabilities whose tables exist on every connection that uses them)`);
332
+ if (slot.since !== undefined && !SEMVER.test(String(slot.since)))
333
+ bad.push(`${at}: since must be a version`);
334
+ if (slot.tracked === 'external' && (typeof slot.goesTo !== 'string' || slot.presence !== 'forbidden'))
335
+ bad.push(`${at}: an external slot is forbidden and says where it goes (goesTo)`);
336
+ if (slot.presence === 'forbidden' && slot.tracked !== 'external')
337
+ bad.push(`${at}: a forbidden slot is external`);
338
+ return bad;
339
+ }
304
340
  export function slotProblems(slot, index, kind, { appScope = 'app', scopes = [], logicRoles = [] } = {}) {
305
- const runtime = kind === RUNTIME_KIND;
306
- const slotKeys = new Set(runtime ? RUNTIME_SLOT_KEYS : APP_SLOT_KEYS);
307
- const tracked = runtime ? RUNTIME_TRACKED : TRACKED;
308
- const at = isPlainObject(slot) && typeof slot.id === 'string' ? `slot ${slot.id}` : `slots[${index}]`;
309
- if (!isPlainObject(slot)) return [`${at} is not a map`];
310
- const bad = slotIdentityProblems(slot, runtime, slotKeys, at, appScope, scopes);
311
- bad.push(...slotLocationProblems(slot, at, runtime, tracked), ...slotPatternProblems(slot, at), ...slotListProblems(slot, at));
312
- if (!runtime) bad.push(...slotAppOptionProblems(slot, at), ...slotLiteOverlayProblems(slot, at));
313
- bad.push(...slotEntryProblems(slot, at), ...slotPolicyProblems(slot, at));
314
- if (!runtime) bad.push(...slotLogicProblems(slot, at, logicRoles));
315
- return bad;
316
- }
317
-
341
+ const runtime = kind === RUNTIME_KIND;
342
+ const slotKeys = new Set(runtime ? RUNTIME_SLOT_KEYS : APP_SLOT_KEYS);
343
+ const tracked = runtime ? RUNTIME_TRACKED : TRACKED;
344
+ const at = isPlainObject(slot) && typeof slot.id === 'string' ? `slot ${slot.id}` : `slots[${index}]`;
345
+ if (!isPlainObject(slot))
346
+ return [`${at} is not a map`];
347
+ const bad = slotIdentityProblems(slot, runtime, slotKeys, at, appScope, scopes);
348
+ bad.push(...slotLocationProblems(slot, at, runtime, tracked), ...slotPatternProblems(slot, at), ...slotListProblems(slot, at));
349
+ if (!runtime)
350
+ bad.push(...slotAppOptionProblems(slot, at), ...slotLiteOverlayProblems(slot, at));
351
+ bad.push(...slotEntryProblems(slot, at), ...slotPolicyProblems(slot, at));
352
+ if (!runtime)
353
+ bad.push(...slotLogicProblems(slot, at, logicRoles));
354
+ return bad;
355
+ }
318
356
  /** The owners of an external call in a runtime manifest: an api system folder (`api/<system>`, `api/*` any system) or the DB tier. */
319
357
  const INFRA_OWNER = /^(?:api\/(?:\*|[a-z][a-z0-9-]*)|engine\/db)$/;
320
358
  const RUNTIME_PARAM_KEYS = new Set(['fileLines', 'sourceRoots', 'infraOwners', 'baseWriteMembers', 'baseEnvSeams', 'apiContracts', 'sourceName', 'oneOffNames', 'sharedBasenames', 'generated', 'heldSecrets', 'pinned', 'selfChecks']);
321
359
  const relPath = (v) => typeof v === 'string' && v.length > 0 && !v.startsWith('/') && !v.includes('..') && !v.includes('\\');
322
-
323
360
  function runtimeHeaderProblems(m) {
324
- const bad = [];
325
- const allowed = new Set(['schema', 'kind', 'version', 'versioning', 'presenceValues', 'trackedValues', 'testValues', 'profiles', 'tiers', 'ruleParams', 'crossOwner', 'crossSystem', 'slots', 'consumers']);
326
- for (const key of Object.keys(m)) if (!allowed.has(key)) bad.push(`unknown top-level key ${key}`);
327
- if (!/^starci\/runtime-slots@\d+$/.test(String(m.schema))) bad.push('schema must be starci/runtime-slots@<major>');
328
- if (!SEMVER.test(String(m.version))) bad.push('version must be MAJOR.MINOR.PATCH');
329
- if (!isPlainObject(m.versioning) || !['patch', 'minor', 'major', 'pins'].every((k) => typeof m.versioning[k] === 'string')) bad.push('versioning needs patch, minor, major and pins text');
330
- if (JSON.stringify(m.presenceValues) !== JSON.stringify(PRESENCE)) bad.push(`presenceValues must be ${PRESENCE.join(', ')}`);
331
- if (JSON.stringify(m.trackedValues) !== JSON.stringify(RUNTIME_TRACKED)) bad.push(`trackedValues must be ${RUNTIME_TRACKED.join(', ')}`);
332
- if (JSON.stringify(m.testValues) !== JSON.stringify(TESTS)) bad.push(`testValues must be ${TESTS.join(', ')}`);
333
- if (JSON.stringify(m.profiles) !== JSON.stringify([RUNTIME_KIND])) bad.push('profiles must be [runtime]');
334
- return bad;
335
- }
336
-
361
+ const bad = [];
362
+ const allowed = new Set(['schema', 'kind', 'version', 'versioning', 'presenceValues', 'trackedValues', 'testValues', 'profiles', 'tiers', 'ruleParams', 'crossOwner', 'crossSystem', 'slots', 'consumers']);
363
+ for (const key of Object.keys(m))
364
+ if (!allowed.has(key))
365
+ bad.push(`unknown top-level key ${key}`);
366
+ if (!/^starci\/runtime-slots@\d+$/.test(String(m.schema)))
367
+ bad.push('schema must be starci/runtime-slots@<major>');
368
+ if (!SEMVER.test(String(m.version)))
369
+ bad.push('version must be MAJOR.MINOR.PATCH');
370
+ if (!isPlainObject(m.versioning) || !['patch', 'minor', 'major', 'pins'].every((k) => typeof m.versioning[k] === 'string'))
371
+ bad.push('versioning needs patch, minor, major and pins text');
372
+ if (JSON.stringify(m.presenceValues) !== JSON.stringify(PRESENCE))
373
+ bad.push(`presenceValues must be ${PRESENCE.join(', ')}`);
374
+ if (JSON.stringify(m.trackedValues) !== JSON.stringify(RUNTIME_TRACKED))
375
+ bad.push(`trackedValues must be ${RUNTIME_TRACKED.join(', ')}`);
376
+ if (JSON.stringify(m.testValues) !== JSON.stringify(TESTS))
377
+ bad.push(`testValues must be ${TESTS.join(', ')}`);
378
+ if (JSON.stringify(m.profiles) !== JSON.stringify([RUNTIME_KIND]))
379
+ bad.push('profiles must be [runtime]');
380
+ return bad;
381
+ }
337
382
  function runtimeSectionsProblems(m) {
338
- const bad = [];
339
- for (const key of ['crossOwner', 'crossSystem']) if (m[key] !== undefined && typeof m[key] !== 'string') bad.push(`${key} must be text`);
340
- if (!isPlainObject(m.tiers) || Object.keys(m.tiers).join() !== RUNTIME_KIND) bad.push('tiers must be a map with exactly runtime');
341
- else bad.push(...tierMapProblems(RUNTIME_KIND, m.tiers.runtime));
342
- const rp = m.ruleParams;
343
- if (!isPlainObject(rp) || Object.keys(rp).join() !== RUNTIME_KIND || !isPlainObject(rp.runtime)) bad.push('ruleParams must be a map with exactly runtime');
344
- else bad.push(...runtimeParamProblems(rp.runtime));
345
- if (!Array.isArray(m.slots) || !m.slots.length) bad.push('slots must be a non-empty list');
346
- else m.slots.forEach((slot, index) => bad.push(...slotProblems(slot, index, RUNTIME_KIND)));
347
- if (m.consumers !== undefined && !strList(m.consumers)) bad.push('consumers must be a list of paths');
348
- return bad;
349
- }
350
-
383
+ const bad = [];
384
+ for (const key of ['crossOwner', 'crossSystem'])
385
+ if (m[key] !== undefined && typeof m[key] !== 'string')
386
+ bad.push(`${key} must be text`);
387
+ if (!isPlainObject(m.tiers) || Object.keys(m.tiers).join() !== RUNTIME_KIND)
388
+ bad.push('tiers must be a map with exactly runtime');
389
+ else
390
+ bad.push(...tierMapProblems(RUNTIME_KIND, m.tiers.runtime));
391
+ const rp = m.ruleParams;
392
+ if (!isPlainObject(rp) || Object.keys(rp).join() !== RUNTIME_KIND || !isPlainObject(rp.runtime))
393
+ bad.push('ruleParams must be a map with exactly runtime');
394
+ else
395
+ bad.push(...runtimeParamProblems(rp.runtime));
396
+ if (!Array.isArray(m.slots) || !m.slots.length)
397
+ bad.push('slots must be a non-empty list');
398
+ else
399
+ m.slots.forEach((slot, index) => bad.push(...slotProblems(slot, index, RUNTIME_KIND)));
400
+ if (m.consumers !== undefined && !strList(m.consumers))
401
+ bad.push('consumers must be a list of paths');
402
+ return bad;
403
+ }
351
404
  /** Shape problems of a parsed manifest of kind runtime (knowledge/hfs/runtime-slots.yaml), in the words of modules/schemas/hfs-slots.schema.yaml. */
352
405
  export function runtimeShapeProblems(m) {
353
- return [...runtimeHeaderProblems(m), ...runtimeSectionsProblems(m)];
406
+ return [...runtimeHeaderProblems(m), ...runtimeSectionsProblems(m)];
354
407
  }
355
-
356
408
  /** Shape problems of ruleParams.runtime. */
357
409
  function runtimeParamKeyProblems(rp) {
358
- const bad = [];
359
- for (const key of Object.keys(rp)) if (!RUNTIME_PARAM_KEYS.has(key)) bad.push(`ruleParams.runtime.${key} is not a runtime parameter`);
360
- for (const key of RUNTIME_PARAM_KEYS) if (!(key in rp)) bad.push(`ruleParams.runtime.${key} is missing`);
361
- return bad;
410
+ const bad = [];
411
+ for (const key of Object.keys(rp))
412
+ if (!RUNTIME_PARAM_KEYS.has(key))
413
+ bad.push(`ruleParams.runtime.${key} is not a runtime parameter`);
414
+ for (const key of RUNTIME_PARAM_KEYS)
415
+ if (!(key in rp))
416
+ bad.push(`ruleParams.runtime.${key} is missing`);
417
+ return bad;
362
418
  }
363
-
364
419
  function runtimeParamFoundationProblems(rp) {
365
- const bad = [];
366
- const fl = rp.fileLines;
367
- if (!(isPlainObject(fl) && Number.isInteger(fl.soft) && fl.soft >= 1 && typeof fl.hardGrowth === 'boolean' && Object.keys(fl).length === 2)) bad.push('ruleParams.runtime.fileLines must be {soft, hardGrowth}');
368
- const owners = rp.infraOwners;
369
- const ownerMap = (v) => isPlainObject(v) && Object.entries(v).every(([key, list]) => key && Array.isArray(list) && list.every((o) => INFRA_OWNER.test(String(o))) && new Set(list).size === list.length);
370
- if (!isPlainObject(owners) || Object.keys(owners).sort(byCodeUnit).join() !== 'globals,modules,programs' || !['globals', 'modules', 'programs'].every((k) => ownerMap(owners[k]))) bad.push('ruleParams.runtime.infraOwners must be {modules, globals, programs}, each mapping a name to unique owners api/<system>, api/* or engine/db ([] means nowhere)');
371
- return bad;
372
- }
373
-
420
+ const bad = [];
421
+ const fl = rp.fileLines;
422
+ if (!(isPlainObject(fl) && Number.isInteger(fl.soft) && fl.soft >= 1 && typeof fl.hardGrowth === 'boolean' && Object.keys(fl).length === 2))
423
+ bad.push('ruleParams.runtime.fileLines must be {soft, hardGrowth}');
424
+ const owners = rp.infraOwners;
425
+ const ownerMap = (v) => isPlainObject(v) && Object.entries(v).every(([key, list]) => key && Array.isArray(list) && list.every((o) => INFRA_OWNER.test(String(o))) && new Set(list).size === list.length);
426
+ if (!isPlainObject(owners) || Object.keys(owners).sort(byCodeUnit).join() !== 'globals,modules,programs' || !['globals', 'modules', 'programs'].every((k) => ownerMap(owners[k])))
427
+ bad.push('ruleParams.runtime.infraOwners must be {modules, globals, programs}, each mapping a name to unique owners api/<system>, api/* or engine/db ([] means nowhere)');
428
+ return bad;
429
+ }
374
430
  function runtimeParamListProblems(rp) {
375
- const bad = [];
376
- for (const key of ['sourceRoots', 'baseWriteMembers', 'oneOffNames', 'sharedBasenames']) if (!(strList(rp[key]) && rp[key].length && new Set(rp[key]).size === rp[key].length)) bad.push(`ruleParams.runtime.${key} must be a non-empty list of unique strings`);
377
- if (!(Array.isArray(rp.baseEnvSeams) && rp.baseEnvSeams.every(relPath))) bad.push('ruleParams.runtime.baseEnvSeams must be a list of repository-relative paths');
378
- if (!(isPlainObject(rp.apiContracts) && Object.entries(rp.apiContracts).every(([system, file]) => NAME.test(system) && relPath(file)))) bad.push('ruleParams.runtime.apiContracts must map an api system to its calls contract path');
379
- return bad;
431
+ const bad = [];
432
+ for (const key of ['sourceRoots', 'baseWriteMembers', 'oneOffNames', 'sharedBasenames'])
433
+ if (!(strList(rp[key]) && rp[key].length && new Set(rp[key]).size === rp[key].length))
434
+ bad.push(`ruleParams.runtime.${key} must be a non-empty list of unique strings`);
435
+ if (!(Array.isArray(rp.baseEnvSeams) && rp.baseEnvSeams.every(relPath)))
436
+ bad.push('ruleParams.runtime.baseEnvSeams must be a list of repository-relative paths');
437
+ if (!(isPlainObject(rp.apiContracts) && Object.entries(rp.apiContracts).every(([system, file]) => NAME.test(system) && relPath(file))))
438
+ bad.push('ruleParams.runtime.apiContracts must map an api system to its calls contract path');
439
+ return bad;
380
440
  }
381
-
382
441
  function runtimeParamArtifactProblems(rp) {
383
- const bad = [];
384
- let sourceNameOk = typeof rp.sourceName === 'string';
385
- try { if (sourceNameOk) new RegExp(rp.sourceName); } catch { sourceNameOk = false; }
386
- if (!sourceNameOk) bad.push('ruleParams.runtime.sourceName must be a regular expression');
387
- if (!(Array.isArray(rp.generated) && rp.generated.length && rp.generated.every((g) => isPlainObject(g) && relPath(g.root) && relPath(g.generatedBy) && Object.keys(g).length === 2))) bad.push('ruleParams.runtime.generated must be a non-empty list of {root, generatedBy}');
388
- if (!(Array.isArray(rp.pinned) && rp.pinned.length && rp.pinned.every((p) => isPlainObject(p) && relPath(p.path) && typeof p.why === 'string' && p.why && Object.keys(p).length === 2))) bad.push('ruleParams.runtime.pinned must be a non-empty list of {path, why}');
389
- if (!(Array.isArray(rp.selfChecks) && rp.selfChecks.length && rp.selfChecks.every((c) => isPlainObject(c) && NAME.test(String(c.id)) && relPath(c.run) && (c.args === undefined || strList(c.args)) && Object.keys(c).every((k) => ['id', 'run', 'args'].includes(k))))) bad.push('ruleParams.runtime.selfChecks must be a non-empty list of {id, run, args?}');
390
- return bad;
391
- }
392
-
442
+ const bad = [];
443
+ let sourceNameOk = typeof rp.sourceName === 'string';
444
+ try {
445
+ if (sourceNameOk)
446
+ new RegExp(rp.sourceName);
447
+ }
448
+ catch {
449
+ sourceNameOk = false;
450
+ }
451
+ if (!sourceNameOk)
452
+ bad.push('ruleParams.runtime.sourceName must be a regular expression');
453
+ if (!(Array.isArray(rp.generated) && rp.generated.length && rp.generated.every((g) => isPlainObject(g) && relPath(g.root) && relPath(g.generatedBy) && Object.keys(g).length === 2)))
454
+ bad.push('ruleParams.runtime.generated must be a non-empty list of {root, generatedBy}');
455
+ if (!(Array.isArray(rp.pinned) && rp.pinned.length && rp.pinned.every((p) => isPlainObject(p) && relPath(p.path) && typeof p.why === 'string' && p.why && Object.keys(p).length === 2)))
456
+ bad.push('ruleParams.runtime.pinned must be a non-empty list of {path, why}');
457
+ if (!(Array.isArray(rp.selfChecks) && rp.selfChecks.length && rp.selfChecks.every((c) => isPlainObject(c) && NAME.test(String(c.id)) && relPath(c.run) && (c.args === undefined || strList(c.args)) && Object.keys(c).every((k) => ['id', 'run', 'args'].includes(k)))))
458
+ bad.push('ruleParams.runtime.selfChecks must be a non-empty list of {id, run, args?}');
459
+ return bad;
460
+ }
393
461
  function runtimeParamProblems(rp) {
394
- return [
395
- ...runtimeParamKeyProblems(rp),
396
- ...runtimeParamFoundationProblems(rp),
397
- ...runtimeParamListProblems(rp),
398
- ...runtimeParamArtifactProblems(rp),
399
- ];
400
- }
401
-
402
- const folderKindsValid = list => strList(list) && list.length > 0 && new Set(list).size === list.length && list.every(kind => NAME.test(kind));
403
- const kindPairValid = pair => isPlainObject(pair) && Object.keys(pair).sort(byCodeUnit).join() === 'from,to'
404
- && ['from', 'to'].every(side => folderKindsValid(pair[side]));
462
+ return [
463
+ ...runtimeParamKeyProblems(rp),
464
+ ...runtimeParamFoundationProblems(rp),
465
+ ...runtimeParamListProblems(rp),
466
+ ...runtimeParamArtifactProblems(rp),
467
+ ];
468
+ }
469
+ const folderKindsValid = (list) => strList(list) && list.length > 0 && new Set(list).size === list.length && list.every((kind) => NAME.test(kind));
470
+ const kindPairValid = (pair) => isPlainObject(pair) && Object.keys(pair).sort(byCodeUnit).join() === 'from,to'
471
+ && ['from', 'to'].every(side => folderKindsValid(pair[side]));
405
472
  /** A non-empty map whose every key is a name and every value satisfies `valid`. */
406
473
  export const namedMapValid = (map, valid) => isPlainObject(map) && Object.keys(map).length > 0
407
- && Object.entries(map).every(([name, entry]) => NAME.test(name) && valid(entry));
408
- const kindRestrictionValid = kinds => namedMapValid(kinds, kindPairValid);
409
- const slotIdsValid = list => strList(list) && list.length > 0 && new Set(list).size === list.length
410
- && list.every(id => SLOT_ID.test(id) || RUNTIME_SLOT_ID.test(id));
411
- const slotRestrictionPairValid = pair => isPlainObject(pair) && Object.keys(pair).join() === 'from' && slotIdsValid(pair.from);
412
- const slotRestrictionValid = slots => namedMapValid(slots, slotRestrictionPairValid);
413
-
474
+ && Object.entries(map).every(([name, entry]) => NAME.test(name) && valid(entry));
475
+ const kindRestrictionValid = (kinds) => namedMapValid(kinds, kindPairValid);
476
+ const slotIdsValid = (list) => strList(list) && list.length > 0 && new Set(list).size === list.length
477
+ && list.every((id) => SLOT_ID.test(id) || RUNTIME_SLOT_ID.test(id));
478
+ const slotRestrictionPairValid = (pair) => isPlainObject(pair) && Object.keys(pair).join() === 'from' && slotIdsValid(pair.from);
479
+ const slotRestrictionValid = (slots) => namedMapValid(slots, slotRestrictionPairValid);
414
480
  function tierDefinitionProblems(profile, tier, def) {
415
- const bad = [];
416
- const at = `tiers.${profile}.${tier}`;
417
- if (!isPlainObject(def) || !Array.isArray(def.mayImport) || !def.mayImport.every((t) => NAME.test(String(t)))) bad.push(`${at}.mayImport must be a list of tier names`);
418
- if (def?.mayImportKinds !== undefined && !kindRestrictionValid(def.mayImportKinds)) bad.push(`${at}.mayImportKinds must map tier names to {from, to} non-empty lists of unique folder kinds`);
419
- if (def?.mayImportSlots !== undefined && !slotRestrictionValid(def.mayImportSlots)) bad.push(`${at}.mayImportSlots must map tier names to {from} non-empty lists of unique slot ids`);
420
- for (const key of Object.keys(def ?? {})) if (!['mayImport', 'mayImportKinds', 'mayImportSlots', 'acyclic', 'lowerLayerOnly'].includes(key)) bad.push(`${at}.${key} is not a tier field`);
421
- return bad;
422
- }
423
-
481
+ const bad = [];
482
+ const at = `tiers.${profile}.${tier}`;
483
+ if (!isPlainObject(def) || !Array.isArray(def.mayImport) || !def.mayImport.every((t) => NAME.test(String(t))))
484
+ bad.push(`${at}.mayImport must be a list of tier names`);
485
+ if (def?.mayImportKinds !== undefined && !kindRestrictionValid(def.mayImportKinds))
486
+ bad.push(`${at}.mayImportKinds must map tier names to {from, to} non-empty lists of unique folder kinds`);
487
+ if (def?.mayImportSlots !== undefined && !slotRestrictionValid(def.mayImportSlots))
488
+ bad.push(`${at}.mayImportSlots must map tier names to {from} non-empty lists of unique slot ids`);
489
+ for (const key of Object.keys(def ?? {}))
490
+ if (!['mayImport', 'mayImportKinds', 'mayImportSlots', 'acyclic', 'lowerLayerOnly'].includes(key))
491
+ bad.push(`${at}.${key} is not a tier field`);
492
+ return bad;
493
+ }
424
494
  /** Shape problems of the tier map of one profile. */
425
495
  export function tierMapProblems(profile, tiers) {
426
- const bad = [];
427
- if (!isPlainObject(tiers) || !Object.keys(tiers).length) return [`tiers.${profile} must be a non-empty map`];
428
- for (const [tier, def] of Object.entries(tiers)) {
429
- if (!NAME.test(tier)) bad.push(`tiers.${profile}.${tier} is not a tier name`);
430
- bad.push(...tierDefinitionProblems(profile, tier, def));
431
- }
432
- return bad;
433
- }
434
-
496
+ const bad = [];
497
+ if (!isPlainObject(tiers) || !Object.keys(tiers).length)
498
+ return [`tiers.${profile} must be a non-empty map`];
499
+ for (const [tier, def] of Object.entries(tiers)) {
500
+ if (!NAME.test(tier))
501
+ bad.push(`tiers.${profile}.${tier} is not a tier name`);
502
+ bad.push(...tierDefinitionProblems(profile, tier, def));
503
+ }
504
+ return bad;
505
+ }
435
506
  function tierFolderKindProblems(manifest, profile, tier, kinds, at) {
436
- const known = new Set(manifest.slots.filter((slot) => slot.profiles.includes(profile) && slot.tier === tier).flatMap((slot) => [...(slot.kinds ?? []), ...(slot.layers ?? [])]));
437
- return kinds.filter(kind => !known.has(kind)).map(kind => `${at} names ${kind}, which is not a folder kind of the ${tier} tier`);
507
+ const known = new Set(manifest.slots.filter((slot) => slot.profiles.includes(profile) && slot.tier === tier).flatMap((slot) => [...(slot.kinds ?? []), ...(slot.layers ?? [])]));
508
+ return kinds.filter((kind) => !known.has(kind)).map((kind) => `${at} names ${kind}, which is not a folder kind of the ${tier} tier`);
438
509
  }
439
-
440
510
  function tierSlotRestrictionProblems(manifest, profile, tier, def) {
441
- const bad = [];
442
- const known = new Set(manifest.slots.filter(slot => slot.profiles.includes(profile) && slot.tier === tier).map(slot => slot.id));
443
- for (const [target, restriction] of Object.entries(def.mayImportSlots ?? {})) {
444
- const at = `tiers.${profile}.${tier}.mayImportSlots.${target}`;
445
- if (!def.mayImport.includes(target)) bad.push(`${at} restricts a tier that mayImport does not allow`);
446
- for (const id of restriction.from) if (!known.has(id)) bad.push(`${at}.from names ${id}, which is not a slot of the ${profile} ${tier} tier`);
447
- }
448
- return bad;
449
- }
450
-
511
+ const bad = [];
512
+ const known = new Set(manifest.slots.filter(slot => slot.profiles.includes(profile) && slot.tier === tier).map(slot => slot.id));
513
+ for (const [target, restriction] of Object.entries(def.mayImportSlots ?? {})) {
514
+ const at = `tiers.${profile}.${tier}.mayImportSlots.${target}`;
515
+ if (!def.mayImport.includes(target))
516
+ bad.push(`${at} restricts a tier that mayImport does not allow`);
517
+ for (const id of restriction.from)
518
+ if (!known.has(id))
519
+ bad.push(`${at}.from names ${id}, which is not a slot of the ${profile} ${tier} tier`);
520
+ }
521
+ return bad;
522
+ }
451
523
  /** Kind and slot restrictions narrow allowed tier edges and name declared source and target roles. */
452
524
  export function tierKindProblems(manifest, profile) {
453
- const bad = [];
454
- for (const [tier, def] of Object.entries(manifest.tiers[profile])) {
455
- bad.push(...tierSlotRestrictionProblems(manifest, profile, tier, def));
456
- for (const [target, kinds] of Object.entries(def.mayImportKinds ?? {})) {
457
- const at = `tiers.${profile}.${tier}.mayImportKinds.${target}`;
458
- if (!def.mayImport.includes(target)) bad.push(`${at} restricts a tier that mayImport does not allow`);
459
- bad.push(...tierFolderKindProblems(manifest, profile, tier, kinds.from, `${at}.from`), ...tierFolderKindProblems(manifest, profile, target, kinds.to, `${at}.to`));
525
+ const bad = [];
526
+ for (const [tier, def] of Object.entries(manifest.tiers[profile])) {
527
+ bad.push(...tierSlotRestrictionProblems(manifest, profile, tier, def));
528
+ for (const [target, kinds] of Object.entries(def.mayImportKinds ?? {})) {
529
+ const at = `tiers.${profile}.${tier}.mayImportKinds.${target}`;
530
+ if (!def.mayImport.includes(target))
531
+ bad.push(`${at} restricts a tier that mayImport does not allow`);
532
+ bad.push(...tierFolderKindProblems(manifest, profile, tier, kinds.from, `${at}.from`), ...tierFolderKindProblems(manifest, profile, target, kinds.to, `${at}.to`));
533
+ }
460
534
  }
461
- }
462
- return bad;
535
+ return bad;
463
536
  }
464
-
465
537
  /** The semantic rules of a runtime manifest beyond the slot rules both kinds share: tier names and the schema major. */
466
538
  export function runtimeSemanticProblems(m) {
467
- const bad = tierKindProblems(m, RUNTIME_KIND);
468
- const tiers = m.tiers.runtime;
469
- for (const [tier, def] of Object.entries(tiers)) {
470
- for (const target of def.mayImport) if (!(target in tiers)) bad.push(`tiers.runtime.${tier}.mayImport names ${target}, which is not a runtime tier`);
471
- }
472
- const major = Number(m.version.split('.')[0]);
473
- if (String(m.schema) !== `starci/runtime-slots@${major}`) bad.push(`schema ${m.schema} does not carry the major of version ${m.version}`);
474
- return bad;
539
+ const bad = tierKindProblems(m, RUNTIME_KIND);
540
+ const tiers = m.tiers.runtime;
541
+ for (const [tier, def] of Object.entries(tiers)) {
542
+ for (const target of def.mayImport)
543
+ if (!(target in tiers))
544
+ bad.push(`tiers.runtime.${tier}.mayImport names ${target}, which is not a runtime tier`);
545
+ }
546
+ const major = Number(m.version.split('.')[0]);
547
+ if (String(m.schema) !== `starci/runtime-slots@${major}`)
548
+ bad.push(`schema ${m.schema} does not carry the major of version ${m.version}`);
549
+ return bad;
475
550
  }