@starci/hfs 4.0.8 → 4.0.10

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 (703) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +81 -39
  4. package/emit/contracts.mjs +56 -9
  5. package/emit/db-types.mjs +169 -0
  6. package/emit/events.mjs +41 -0
  7. package/emit/operations-worker.mjs +1 -1
  8. package/emit/operations.mjs +2 -2
  9. package/emit/schema-worker.mjs +1 -1
  10. package/lint/bound-sys.cjs +50 -0
  11. package/lint/run.mjs +131 -24
  12. package/package.json +16 -10
  13. package/report/sonar.mjs +8 -8
  14. package/runtime/engine/admission.mjs +308 -0
  15. package/runtime/engine/canonical-json.mjs +10 -0
  16. package/runtime/engine/config.mjs +486 -0
  17. package/runtime/engine/db/blob.mjs +315 -0
  18. package/runtime/engine/db/ledger-paths.mjs +83 -0
  19. package/runtime/engine/db/ledger.mjs +1118 -0
  20. package/runtime/engine/db/machine-connection.mjs +135 -0
  21. package/runtime/engine/db/machine-schema.mjs +84 -0
  22. package/runtime/engine/db/machine.mjs +1367 -0
  23. package/runtime/engine/db/migrations/machine/0001-init.sql +924 -0
  24. package/runtime/engine/db/migrations/runtime/0001-init.sql +1108 -0
  25. package/runtime/engine/db/provider-reservations.mjs +101 -0
  26. package/runtime/engine/digest.mjs +16 -0
  27. package/runtime/engine/invalid-config.mjs +15 -0
  28. package/runtime/engine/orca-config.mjs +27 -0
  29. package/runtime/engine/refuse.mjs +11 -0
  30. package/runtime/engine/secrets.mjs +130 -0
  31. package/runtime/knowledge/hfs/canon-pins.yaml +162 -31
  32. package/runtime/knowledge/hfs/peer-integrations.yaml +2 -2
  33. package/runtime/knowledge/hfs/rules.yaml +2059 -0
  34. package/runtime/knowledge/hfs/slots.yaml +912 -120
  35. package/runtime/knowledge/patterns/be/api.yaml +369 -0
  36. package/runtime/knowledge/patterns/be/cli.yaml +297 -0
  37. package/runtime/knowledge/patterns/be/domain.yaml +113 -0
  38. package/runtime/knowledge/patterns/be/event-bus.yaml +285 -0
  39. package/runtime/knowledge/patterns/be/jobs.yaml +261 -0
  40. package/runtime/knowledge/patterns/be/projections.yaml +178 -0
  41. package/runtime/knowledge/patterns/be/queues.yaml +236 -0
  42. package/runtime/knowledge/patterns/be/reactors.yaml +140 -0
  43. package/runtime/knowledge/patterns/be/realtime.yaml +222 -0
  44. package/runtime/knowledge/patterns/be/saga.yaml +248 -0
  45. package/runtime/knowledge/patterns/be/webhooks.yaml +221 -0
  46. package/runtime/knowledge/patterns/fe/folder.yaml +131 -25
  47. package/runtime/knowledge/sonar-gate.yaml +52 -18
  48. package/runtime/modules/kernel/failure-codes.yaml +611 -51
  49. package/runtime/modules/models/registry.yaml +553 -0
  50. package/runtime/modules/models/runtimes.yaml +695 -0
  51. package/runtime/modules/ops/_labels.yaml +53 -0
  52. package/runtime/scripts/api/fs/forbidden-root.mjs +51 -0
  53. package/runtime/scripts/api/fs/is-link-like.mjs +25 -0
  54. package/runtime/scripts/api/fs/lib.mjs +16 -2
  55. package/runtime/scripts/api/fs/safe-remove.mjs +12 -132
  56. package/runtime/scripts/api/git/config-get.mjs +10 -0
  57. package/runtime/scripts/api/git/diff.mjs +5 -0
  58. package/runtime/scripts/api/git/lib.mjs +18 -26
  59. package/runtime/scripts/api/git/log.mjs +5 -0
  60. package/runtime/scripts/api/git/ls-files.mjs +6 -0
  61. package/runtime/scripts/api/git/ls-tree.mjs +5 -0
  62. package/runtime/scripts/api/git/merge-base.mjs +9 -0
  63. package/runtime/scripts/api/git/remote.mjs +5 -0
  64. package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
  65. package/runtime/scripts/api/git/show.mjs +6 -0
  66. package/runtime/scripts/api/node/lib.mjs +14 -0
  67. package/runtime/scripts/api/node/spawn-node.mjs +6 -0
  68. package/runtime/scripts/api/process/lib.mjs +111 -0
  69. package/runtime/scripts/api/process/owned-process.mjs +78 -0
  70. package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -0
  71. package/runtime/scripts/api/process/run-program.mjs +7 -0
  72. package/runtime/scripts/api/process/stop-owned-process.mjs +9 -0
  73. package/runtime/scripts/api/sops/decrypt.mjs +9 -12
  74. package/runtime/scripts/api/sops/lib.mjs +255 -0
  75. package/runtime/scripts/api/sops/seal.mjs +22 -0
  76. package/runtime/scripts/connectors/lib.mjs +488 -0
  77. package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
  78. package/runtime/scripts/hfs/architecture/backend.mjs +16 -23
  79. package/runtime/scripts/hfs/architecture/background-unowned.mjs +16 -34
  80. package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +3 -1
  81. package/runtime/scripts/hfs/architecture/clones.mjs +4 -4
  82. package/runtime/scripts/hfs/architecture/config.mjs +9 -6
  83. package/runtime/scripts/hfs/architecture/connection-map.mjs +20 -8
  84. package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
  85. package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
  86. package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
  87. package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
  88. package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
  89. package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +4 -10
  90. package/runtime/scripts/hfs/architecture/contracts.mjs +33 -162
  91. package/runtime/scripts/hfs/architecture/dead-exports.mjs +58 -29
  92. package/runtime/scripts/hfs/architecture/doc-language.mjs +1 -1
  93. package/runtime/scripts/hfs/architecture/entrypoint.mjs +2 -1
  94. package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +2 -2
  95. package/runtime/scripts/hfs/architecture/feature-shape.mjs +5 -2
  96. package/runtime/scripts/hfs/architecture/framework-pinned.mjs +1 -1
  97. package/runtime/scripts/hfs/architecture/frontend.mjs +17 -43
  98. package/runtime/scripts/hfs/architecture/hfs.mjs +24 -39
  99. package/runtime/scripts/hfs/architecture/i18n-keys.mjs +1 -1
  100. package/runtime/scripts/hfs/architecture/index.mjs +17 -4
  101. package/runtime/scripts/hfs/architecture/machine-ast.mjs +44 -11
  102. package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
  103. package/runtime/scripts/hfs/architecture/module-per-transport.mjs +30 -6
  104. package/runtime/scripts/hfs/architecture/next-data.mjs +22 -63
  105. package/runtime/scripts/hfs/architecture/owners.mjs +35 -15
  106. package/runtime/scripts/hfs/architecture/register-once.mjs +2 -1
  107. package/runtime/scripts/hfs/architecture/registration.mjs +23 -81
  108. package/runtime/scripts/hfs/architecture/required-files.mjs +20 -12
  109. package/runtime/scripts/hfs/architecture/schema-owner.mjs +17 -114
  110. package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
  111. package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
  112. package/runtime/scripts/hfs/architecture/source-names.mjs +27 -147
  113. package/runtime/scripts/hfs/architecture/sql-owner.mjs +59 -18
  114. package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
  115. package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
  116. package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
  117. package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
  118. package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
  119. package/runtime/scripts/hfs/architecture/surface.mjs +9 -3
  120. package/runtime/scripts/hfs/architecture/test-world-files.mjs +9 -19
  121. package/runtime/scripts/hfs/architecture/tiers.mjs +47 -5
  122. package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -3
  123. package/runtime/scripts/hfs/architecture/typescript.mjs +12 -26
  124. package/runtime/scripts/hfs/architecture.mjs +4 -4
  125. package/runtime/scripts/hfs/check.mjs +75 -72
  126. package/runtime/scripts/hfs/coverage-scope.mjs +162 -0
  127. package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
  128. package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
  129. package/runtime/scripts/hfs/edition-slots.mjs +66 -0
  130. package/runtime/scripts/hfs/manifest-shape.mjs +109 -32
  131. package/runtime/scripts/hfs/param-names.mjs +18 -0
  132. package/runtime/scripts/hfs/path-findings.mjs +1 -1
  133. package/runtime/scripts/hfs/repo-identity.mjs +9 -6
  134. package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
  135. package/runtime/scripts/hfs/rules/app-root.mjs +51 -0
  136. package/runtime/scripts/hfs/rules/cli.mjs +37 -0
  137. package/runtime/scripts/hfs/rules/contract-compat.mjs +71 -0
  138. package/runtime/scripts/hfs/rules/contract.mjs +10 -9
  139. package/runtime/scripts/hfs/rules/database-config.mjs +102 -0
  140. package/runtime/scripts/hfs/rules/database-constants.mjs +13 -0
  141. package/runtime/scripts/hfs/rules/database-migrations.mjs +111 -0
  142. package/runtime/scripts/hfs/rules/database-plpgsql.mjs +233 -0
  143. package/runtime/scripts/hfs/rules/database-sql.mjs +336 -0
  144. package/runtime/scripts/hfs/rules/database.mjs +68 -0
  145. package/runtime/scripts/hfs/rules/deps.mjs +1 -1
  146. package/runtime/scripts/hfs/rules/docker.mjs +259 -0
  147. package/runtime/scripts/hfs/rules/edition.mjs +111 -0
  148. package/runtime/scripts/hfs/rules/event-bus.mjs +153 -0
  149. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -1
  150. package/runtime/scripts/hfs/rules/fe-no-tests.mjs +6 -5
  151. package/runtime/scripts/hfs/rules/frontend-tree.mjs +9 -9
  152. package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -6
  153. package/runtime/scripts/hfs/rules/kinds.mjs +84 -0
  154. package/runtime/scripts/hfs/rules/lint-suppression.mjs +1 -1
  155. package/runtime/scripts/hfs/rules/monorepo.mjs +179 -0
  156. package/runtime/scripts/hfs/rules/peer-integrations.mjs +3 -3
  157. package/runtime/scripts/hfs/rules/pipeline.mjs +11 -21
  158. package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -2
  159. package/runtime/scripts/hfs/rules/read.mjs +1 -1
  160. package/runtime/scripts/hfs/rules/repo-local-checks.mjs +2 -2
  161. package/runtime/scripts/hfs/rules/saga.mjs +170 -0
  162. package/runtime/scripts/hfs/rules/secrets.mjs +3 -3
  163. package/runtime/scripts/hfs/rules/services.mjs +220 -0
  164. package/runtime/scripts/hfs/rules/spec-placement.mjs +1 -1
  165. package/runtime/scripts/hfs/rules/stacks.mjs +3 -3
  166. package/runtime/scripts/hfs/rules/supabase-secrets.mjs +89 -0
  167. package/runtime/scripts/hfs/rules/test-topology.mjs +2 -2
  168. package/runtime/scripts/hfs/secret.mjs +209 -0
  169. package/runtime/scripts/hfs/slots.mjs +78 -108
  170. package/runtime/scripts/hfs/sql/pg-parse.mjs +46 -0
  171. package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
  172. package/runtime/scripts/hfs/tree.mjs +5 -4
  173. package/runtime/scripts/hfs/typescript-programs.mjs +0 -5
  174. package/runtime/scripts/hfs/view.mjs +3 -2
  175. package/runtime/scripts/lib/clip.mjs +19 -0
  176. package/runtime/scripts/lib/display-names.mjs +259 -0
  177. package/runtime/scripts/lib/dockerfile.mjs +124 -0
  178. package/runtime/scripts/lib/env.mjs +10 -0
  179. package/runtime/scripts/lib/event-contract.mjs +103 -0
  180. package/runtime/scripts/lib/example-refs.mjs +158 -0
  181. package/runtime/scripts/lib/fs-kind.mjs +14 -4
  182. package/runtime/scripts/lib/git.mjs +36 -0
  183. package/runtime/scripts/lib/graphql-contract.mjs +1 -1
  184. package/runtime/scripts/lib/i18n.mjs +86 -0
  185. package/runtime/scripts/lib/json-schema.mjs +52 -0
  186. package/runtime/scripts/lib/json.mjs +13 -3
  187. package/runtime/scripts/lib/language.mjs +24 -5
  188. package/runtime/scripts/lib/list.mjs +20 -0
  189. package/runtime/scripts/lib/mutation-fence.mjs +15 -0
  190. package/runtime/scripts/lib/package-at.mjs +37 -0
  191. package/runtime/scripts/lib/path-key.mjs +57 -2
  192. package/runtime/scripts/lib/process-identity.mjs +6 -0
  193. package/runtime/scripts/lib/read-text.mjs +34 -0
  194. package/runtime/scripts/lib/read-yaml.mjs +18 -0
  195. package/runtime/scripts/lib/redact.mjs +161 -0
  196. package/runtime/scripts/lib/regex.mjs +4 -0
  197. package/runtime/scripts/lib/same-text.mjs +5 -0
  198. package/runtime/scripts/lib/secret-patterns.mjs +4 -3
  199. package/runtime/scripts/lib/sleep-sync.mjs +2 -1
  200. package/runtime/scripts/lib/sleep.mjs +7 -0
  201. package/runtime/scripts/lib/sops-envelope.mjs +112 -0
  202. package/runtime/scripts/lib/source-phrases.mjs +34 -0
  203. package/runtime/scripts/lib/sqlite.mjs +21 -0
  204. package/runtime/scripts/lib/stack-services.mjs +7 -31
  205. package/runtime/scripts/lib/ts-ast.mjs +35 -0
  206. package/runtime/scripts/lib/walk.mjs +4 -3
  207. package/scaffold/add-app.mjs +174 -0
  208. package/scaffold/add-cli-lite.mjs +257 -0
  209. package/scaffold/add-inbox-lite.mjs +314 -0
  210. package/scaffold/add-table.mjs +344 -0
  211. package/scaffold/add.mjs +299 -0
  212. package/scaffold/app.mjs +358 -69
  213. package/scaffold/edition-gate.mjs +25 -0
  214. package/scaffold/image.mjs +19 -0
  215. package/scaffold/lite-exports.mjs +186 -0
  216. package/scaffold/service.mjs +32 -26
  217. package/scaffold/supabase-ports.mjs +26 -0
  218. package/src/main.mjs +327 -0
  219. package/sync/cli.mjs +6 -9
  220. package/sync/format.mjs +1 -1
  221. package/sync/hygiene.mjs +10 -10
  222. package/sync/index.mjs +167 -104
  223. package/sync/managed.mjs +19 -11
  224. package/sync/sonar-key.mjs +5 -0
  225. package/templates/app/ci-workflows/github/workflows/ci.yml +14 -14
  226. package/templates/app/ci-workflows/github/workflows/images.yml +37 -0
  227. package/templates/app/ci-workflows/sonar-steps.yml +9 -0
  228. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +66 -0
  229. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +31 -0
  230. package/templates/app/ci-workflows-lite/github/workflows/images.yml +37 -0
  231. package/templates/app/codegen-lite/scripts/codegen.mjs +32 -0
  232. package/templates/app/docker-ignore/dockerignore +50 -0
  233. package/templates/app/gitignore-lite +35 -0
  234. package/templates/app/hooks/husky/pre-commit +3 -8
  235. package/templates/app/hooks/husky/pre-push +45 -6
  236. package/templates/app/package-scripts/core.json +8 -0
  237. package/templates/app/package-scripts/package.json +3 -10
  238. package/templates/app/package-scripts-lite/package.json +15 -0
  239. package/templates/app/quality-config/codecov.yml +15 -3
  240. package/templates/app/quality-config/sonar-base.properties +4 -0
  241. package/templates/app/quality-config/sonar-project.properties +1 -4
  242. package/templates/app/quality-config-lite/sonar-project.properties +5 -0
  243. package/templates/app/skeleton/.starcistacks/dev/seeds/primary-notes.sql +5 -0
  244. package/templates/app/skeleton/.starciwork/features/system-health/index.yaml +4 -0
  245. package/templates/app/skeleton/.starciwork/{features/index.yaml → index.yaml} +2 -2
  246. package/templates/app/skeleton/README.md +7 -5
  247. package/templates/app/skeleton-lite/.sops.yaml +3 -0
  248. package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +5 -0
  249. package/templates/app/skeleton-lite/.starcistacks/dev/secrets/.gitkeep +1 -0
  250. package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +55 -0
  251. package/templates/app/skeleton-lite/README.md +40 -0
  252. package/templates/app/skeleton-lite/supabase/config.toml +41 -0
  253. package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +56 -0
  254. package/templates/app/skeleton-lite/supabase/seed.sql +0 -0
  255. package/templates/app/task-graph/turbo.json +23 -0
  256. package/templates/app/tool-config-lite/prettierignore +2 -0
  257. package/templates/app/tool-config-lite/prettierrc +1 -0
  258. package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +38 -0
  259. package/templates/app/upgrade-full/.starcistacks/dev/README.md +10 -0
  260. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +13 -0
  261. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +3 -0
  262. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +12 -0
  263. package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +7 -0
  264. package/templates/be/common/main-listen.ts.partial +14 -0
  265. package/templates/be/common/sql-ident.ts.partial +7 -0
  266. package/templates/be/common/sql-tag.ts.partial +5 -0
  267. package/templates/be/image/api/Dockerfile +38 -0
  268. package/templates/be/image/cli/Dockerfile +38 -0
  269. package/templates/be/image/worker/Dockerfile +36 -0
  270. package/templates/be/inbox/database-client.ts.tpl +50 -0
  271. package/templates/be/inbox/index.ts.tpl +2 -0
  272. package/templates/be/inbox/migration.sql.tpl +29 -0
  273. package/templates/be/inbox/module-definition.ts.tpl +6 -0
  274. package/templates/be/inbox/module.ts.tpl +14 -0
  275. package/templates/be/inbox/options.ts.tpl +2 -0
  276. package/templates/be/inbox/service.ts.tpl +33 -0
  277. package/templates/be/inbox/sql.ts.tpl +16 -0
  278. package/templates/be/inbox/webhook-door.ts.tpl +36 -0
  279. package/templates/be/patterns/api/application.command.http.ts.tpl +10 -0
  280. package/templates/be/patterns/api/application.command.ts.tpl +10 -0
  281. package/templates/be/patterns/api/application.contracts.ts.tpl +11 -0
  282. package/templates/be/patterns/api/application.handler.http.ts.tpl +22 -0
  283. package/templates/be/patterns/api/application.handler.ts.tpl +22 -0
  284. package/templates/be/patterns/api/feature.index.http.ts.tpl +1 -0
  285. package/templates/be/patterns/api/feature.index.ts.tpl +1 -0
  286. package/templates/be/patterns/api/feature.module.ts.tpl +6 -0
  287. package/templates/be/patterns/api/graphql.input.ts.tpl +13 -0
  288. package/templates/be/patterns/api/graphql.mapper.ts.tpl +9 -0
  289. package/templates/be/patterns/api/graphql.module.ts.tpl +7 -0
  290. package/templates/be/patterns/api/graphql.resolver.ts.tpl +27 -0
  291. package/templates/be/patterns/api/graphql.type.ts.tpl +9 -0
  292. package/templates/be/patterns/api/http.controller.ts.tpl +27 -0
  293. package/templates/be/patterns/api/http.mapper.ts.tpl +9 -0
  294. package/templates/be/patterns/api/http.module.ts.tpl +7 -0
  295. package/templates/be/patterns/api/http.request.ts.tpl +10 -0
  296. package/templates/be/patterns/api/http.response.ts.tpl +5 -0
  297. package/templates/be/patterns/cli/group.cli.spec.ts.tpl +15 -0
  298. package/templates/be/patterns/cli/group.cli.ts.tpl +11 -0
  299. package/templates/be/patterns/cli/group.module.ts.tpl +7 -0
  300. package/templates/be/patterns/cli/sub.run.cli.spec.ts.tpl +17 -0
  301. package/templates/be/patterns/cli/sub.run.cli.ts.tpl +15 -0
  302. package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +22 -0
  303. package/templates/be/patterns/event-bus/platform/event-bus.config.ts.tpl +19 -0
  304. package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +58 -0
  305. package/templates/be/patterns/event-bus/platform/event-bus.decorators.ts.tpl +46 -0
  306. package/templates/be/patterns/event-bus/platform/event-bus.log-events.ts.tpl +12 -0
  307. package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +10 -0
  308. package/templates/be/patterns/event-bus/platform/event-bus.module.ts.tpl +52 -0
  309. package/templates/be/patterns/event-bus/platform/event-bus.options.ts.tpl +19 -0
  310. package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +28 -0
  311. package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +165 -0
  312. package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +93 -0
  313. package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +90 -0
  314. package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +58 -0
  315. package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +136 -0
  316. package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +56 -0
  317. package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +272 -0
  318. package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +128 -0
  319. package/templates/be/patterns/event-bus/platform/event-transport.port.ts.tpl +180 -0
  320. package/templates/be/patterns/event-bus/platform/event.policy.spec.ts.tpl +67 -0
  321. package/templates/be/patterns/event-bus/platform/event.policy.ts.tpl +38 -0
  322. package/templates/be/patterns/event-bus/platform/index.ts.tpl +11 -0
  323. package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.spec.ts.tpl +348 -0
  324. package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.ts.tpl +241 -0
  325. package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +15 -0
  326. package/templates/be/patterns/event-bus/platform/persistence/connection.ts.tpl +8 -0
  327. package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +37 -0
  328. package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +11 -0
  329. package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +12 -0
  330. package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +26 -0
  331. package/templates/be/patterns/jobs/job.index.ts.tpl +1 -0
  332. package/templates/be/patterns/jobs/job.module.ts.tpl +6 -0
  333. package/templates/be/patterns/jobs/job.processor.ts.tpl +20 -0
  334. package/templates/be/patterns/jobs/job.queue.module.ts.tpl +20 -0
  335. package/templates/be/patterns/jobs/job.step.ts.tpl +19 -0
  336. package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +31 -0
  337. package/templates/be/patterns/jobs/platform/fenced.processor.ts.tpl +13 -0
  338. package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +150 -0
  339. package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +100 -0
  340. package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +138 -0
  341. package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +69 -0
  342. package/templates/be/patterns/jobs/platform/jobs.config.ts.tpl +11 -0
  343. package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +62 -0
  344. package/templates/be/patterns/jobs/platform/jobs.decorators.ts.tpl +31 -0
  345. package/templates/be/patterns/jobs/platform/jobs.error.ts.tpl +22 -0
  346. package/templates/be/patterns/jobs/platform/jobs.index.ts.tpl +11 -0
  347. package/templates/be/patterns/jobs/platform/jobs.log-events.ts.tpl +9 -0
  348. package/templates/be/patterns/jobs/platform/jobs.messages.ts.tpl +15 -0
  349. package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +10 -0
  350. package/templates/be/patterns/jobs/platform/jobs.module.ts.tpl +32 -0
  351. package/templates/be/patterns/jobs/platform/jobs.options.ts.tpl +11 -0
  352. package/templates/be/patterns/jobs/platform/jobs.port.ts.tpl +36 -0
  353. package/templates/be/patterns/jobs/platform/persistence.connection.ts.tpl +8 -0
  354. package/templates/be/patterns/jobs/platform/persistence.job.entity.ts.tpl +53 -0
  355. package/templates/be/patterns/jobs/platform/persistence.jobs.rows.ts.tpl +13 -0
  356. package/templates/be/patterns/jobs/platform/persistence.jobs.sql.ts.tpl +33 -0
  357. package/templates/be/patterns/jobs/platform/persistence.migration.ts.tpl +29 -0
  358. package/templates/be/patterns/outbox/platform/index.ts.tpl +2 -0
  359. package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +96 -0
  360. package/templates/be/patterns/outbox/platform/outbox-relay.policy.ts.tpl +78 -0
  361. package/templates/be/patterns/outbox/platform/outbox.log-events.ts.tpl +5 -0
  362. package/templates/be/patterns/projections/migration.ts.tpl +18 -0
  363. package/templates/be/patterns/projections/persistence.connection.ts.tpl +8 -0
  364. package/templates/be/patterns/projections/projection.entity.ts.tpl +9 -0
  365. package/templates/be/patterns/projections/projection.index.ts.tpl +3 -0
  366. package/templates/be/patterns/projections/projection.module-definition.ts.tpl +7 -0
  367. package/templates/be/patterns/projections/projection.module.ts.tpl +18 -0
  368. package/templates/be/patterns/projections/projection.options.ts.tpl +2 -0
  369. package/templates/be/patterns/projections/projection.projection.spec.ts.tpl +55 -0
  370. package/templates/be/patterns/projections/projection.projection.ts.tpl +21 -0
  371. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +142 -0
  372. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +81 -0
  373. package/templates/be/patterns/queues/platform/persistence.connection.ts.tpl +8 -0
  374. package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +25 -0
  375. package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +25 -0
  376. package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +9 -0
  377. package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +12 -0
  378. package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +48 -0
  379. package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +17 -0
  380. package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +128 -0
  381. package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +48 -0
  382. package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +115 -0
  383. package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +91 -0
  384. package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +45 -0
  385. package/templates/be/patterns/queues/platform/queue.config.ts.tpl +15 -0
  386. package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +31 -0
  387. package/templates/be/patterns/queues/platform/queue.decorators.ts.tpl +45 -0
  388. package/templates/be/patterns/queues/platform/queue.index.ts.tpl +7 -0
  389. package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +5 -0
  390. package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +10 -0
  391. package/templates/be/patterns/queues/platform/queue.module.ts.tpl +62 -0
  392. package/templates/be/patterns/queues/platform/queue.options.ts.tpl +22 -0
  393. package/templates/be/patterns/queues/platform/queue.policy.spec.ts.tpl +19 -0
  394. package/templates/be/patterns/queues/platform/queue.policy.ts.tpl +11 -0
  395. package/templates/be/patterns/queues/platform/queue.port.ts.tpl +14 -0
  396. package/templates/be/patterns/queues/queue.index.ts.tpl +3 -0
  397. package/templates/be/patterns/queues/queue.module.ts.tpl +6 -0
  398. package/templates/be/patterns/queues/queue.queue.ts.tpl +23 -0
  399. package/templates/be/patterns/reactors/application.command.ts.tpl +10 -0
  400. package/templates/be/patterns/reactors/application.contracts.ts.tpl +12 -0
  401. package/templates/be/patterns/reactors/application.handler.ts.tpl +22 -0
  402. package/templates/be/patterns/reactors/consumer.ts.tpl +19 -0
  403. package/templates/be/patterns/reactors/message.module.ts.tpl +20 -0
  404. package/templates/be/patterns/reactors/reactor.index.ts.tpl +1 -0
  405. package/templates/be/patterns/reactors/reactor.module.ts.tpl +6 -0
  406. package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +6 -0
  407. package/templates/be/patterns/realtime/channel.index.ts.tpl +1 -0
  408. package/templates/be/patterns/realtime/channel.input.ts.tpl +12 -0
  409. package/templates/be/patterns/realtime/channel.subscription.spec.ts.tpl +51 -0
  410. package/templates/be/patterns/realtime/channel.subscription.ts.tpl +32 -0
  411. package/templates/be/patterns/realtime/channel.type.ts.tpl +9 -0
  412. package/templates/be/patterns/saga/saga.compensate.command.ts.tpl +11 -0
  413. package/templates/be/patterns/saga/saga.compensate.contracts.ts.tpl +7 -0
  414. package/templates/be/patterns/saga/saga.compensate.handler.ts.tpl +22 -0
  415. package/templates/be/patterns/saga/saga.compensation.ts.tpl +21 -0
  416. package/templates/be/patterns/saga/saga.complete.command.ts.tpl +11 -0
  417. package/templates/be/patterns/saga/saga.complete.contracts.ts.tpl +7 -0
  418. package/templates/be/patterns/saga/saga.complete.handler.ts.tpl +22 -0
  419. package/templates/be/patterns/saga/saga.done.consumer.ts.tpl +21 -0
  420. package/templates/be/patterns/saga/saga.failed.consumer.ts.tpl +21 -0
  421. package/templates/be/patterns/saga/saga.index.ts.tpl +1 -0
  422. package/templates/be/patterns/saga/saga.message.module.ts.tpl +23 -0
  423. package/templates/be/patterns/saga/saga.module.ts.tpl +20 -0
  424. package/templates/be/patterns/saga/saga.service.spec.ts.tpl +70 -0
  425. package/templates/be/patterns/saga/saga.service.ts.tpl +44 -0
  426. package/templates/be/patterns/saga/saga.state.ts.tpl +14 -0
  427. package/templates/be/patterns/saga/saga.step.ts.tpl +11 -0
  428. package/templates/be/patterns/saga/saga.undo.command.ts.tpl +10 -0
  429. package/templates/be/patterns/saga/saga.undo.contracts.ts.tpl +5 -0
  430. package/templates/be/patterns/saga/saga.undo.handler.ts.tpl +21 -0
  431. package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +72 -0
  432. package/templates/be/patterns/webhooks/webhook.door.ts.tpl +36 -0
  433. package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +6 -0
  434. package/templates/be/patterns/webhooks/webhook.index.ts.tpl +1 -0
  435. package/templates/be/patterns/webhooks/webhook.request.ts.tpl +9 -0
  436. package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +3 -0
  437. package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -2
  438. package/templates/be/skeleton/apps/__app__/src/main.ts +7 -15
  439. package/templates/be/skeleton/apps/cli/src/app.module.ts +30 -0
  440. package/templates/be/skeleton/apps/cli/src/cli.options.ts +22 -0
  441. package/templates/be/skeleton/apps/cli/src/main.ts +24 -0
  442. package/templates/be/skeleton/src/features/cli/cli.module.ts +7 -0
  443. package/templates/be/skeleton/src/features/cli/index.ts +1 -0
  444. package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.spec.ts +17 -0
  445. package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.ts +15 -0
  446. package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +7 -0
  447. package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.spec.ts +17 -0
  448. package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.ts +18 -0
  449. package/templates/be/skeleton/src/features/cli/seed/seed.cli.spec.ts +17 -0
  450. package/templates/be/skeleton/src/features/cli/seed/seed.cli.ts +15 -0
  451. package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +7 -0
  452. package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +33 -0
  453. package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.ts +34 -0
  454. package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +13 -0
  455. package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +40 -0
  456. package/templates/be/skeleton/src/modules/domain/identity/messages/identity.messages.ts +1 -1
  457. package/templates/be/skeleton/src/modules/domain/note/errors/note.error.ts +16 -0
  458. package/templates/be/skeleton/src/modules/domain/note/index.ts +3 -0
  459. package/templates/be/skeleton/src/modules/domain/note/note.contracts.ts +19 -0
  460. package/templates/be/skeleton/src/modules/domain/note/note.decorators.ts +9 -0
  461. package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +7 -0
  462. package/templates/be/skeleton/src/modules/domain/note/note.module.ts +19 -0
  463. package/templates/be/skeleton/src/modules/domain/note/note.options.ts +2 -0
  464. package/templates/be/skeleton/src/modules/domain/note/note.service.spec.ts +76 -0
  465. package/templates/be/skeleton/src/modules/domain/note/note.service.ts +37 -0
  466. package/templates/be/skeleton/src/modules/domain/note/persistence/connection.ts +8 -0
  467. package/templates/be/skeleton/src/modules/domain/note/persistence/entities/note.entity.ts +17 -0
  468. package/templates/be/skeleton/src/modules/domain/note/persistence/migrations/1790000000000-init-note.ts +22 -0
  469. package/templates/be/skeleton/src/modules/domain/note/persistence/note.rows.ts +17 -0
  470. package/templates/be/skeleton/src/modules/domain/note/persistence/note.sql.ts +4 -0
  471. package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +20 -0
  472. package/templates/be/skeleton/src/modules/platform/config/index.ts +1 -1
  473. package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +18 -0
  474. package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +41 -0
  475. package/templates/be/skeleton/src/modules/platform/database/connection-source.client.ts +17 -0
  476. package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +13 -0
  477. package/templates/be/skeleton/src/modules/platform/database/database.module.ts +77 -0
  478. package/templates/be/skeleton/src/modules/platform/database/database.options.ts +30 -0
  479. package/templates/be/skeleton/src/modules/platform/database/database.port.ts +65 -0
  480. package/templates/be/skeleton/src/modules/platform/database/database.sql.ts +47 -0
  481. package/templates/be/skeleton/src/modules/platform/database/errors/database.error.ts +16 -0
  482. package/templates/be/skeleton/src/modules/platform/database/index.ts +9 -0
  483. package/templates/be/skeleton/src/modules/platform/database/migrate-connections.client.ts +30 -0
  484. package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.spec.ts +84 -0
  485. package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.ts +23 -0
  486. package/templates/be/skeleton/src/modules/platform/database/primary.config.ts +9 -0
  487. package/templates/be/skeleton/src/modules/platform/database/primary.connection.ts +2 -0
  488. package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +10 -0
  489. package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +108 -0
  490. package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.ts +75 -0
  491. package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.spec.ts +88 -0
  492. package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.ts +29 -0
  493. package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +48 -0
  494. package/templates/be/skeleton/src/modules/platform/errors/messages/errors.messages.ts +1 -1
  495. package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +12 -0
  496. package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -0
  497. package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +8 -1
  498. package/templates/be/skeleton/src/modules/platform/http-security/http-security.decorators.ts +8 -0
  499. package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +14 -1
  500. package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +12 -0
  501. package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +10 -2
  502. package/templates/be/skeleton/src/modules/platform/http-security/origin.guard.spec.ts +63 -0
  503. package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +108 -0
  504. package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.spec.ts +39 -0
  505. package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.ts +25 -0
  506. package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +172 -0
  507. package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.ts +66 -0
  508. package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +3 -1
  509. package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +52 -0
  510. package/templates/be/skeleton-lite/apps/api/Dockerfile +37 -0
  511. package/templates/be/skeleton-lite/apps/api/src/api.options.ts +16 -0
  512. package/templates/be/skeleton-lite/apps/api/src/app.module.ts +81 -0
  513. package/templates/be/skeleton-lite/apps/api/src/main.ts +34 -0
  514. package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +14 -0
  515. package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +50 -0
  516. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +26 -0
  517. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +19 -0
  518. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +26 -0
  519. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +7 -0
  520. package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +6 -0
  521. package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +19 -0
  522. package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +10 -0
  523. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +24 -0
  524. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +8 -0
  525. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +17 -0
  526. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +32 -0
  527. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +24 -0
  528. package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +4 -0
  529. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +54 -0
  530. package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +23 -0
  531. package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +10 -0
  532. package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +49 -0
  533. package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +4 -0
  534. package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +21 -0
  535. package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +11 -0
  536. package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +28 -0
  537. package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +25 -0
  538. package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +9 -0
  539. package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +4 -0
  540. package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +5 -0
  541. package/templates/be/table/error.ts.tpl +16 -0
  542. package/templates/be/table/index.ts.tpl +2 -0
  543. package/templates/be/table/migration.sql.tpl +51 -0
  544. package/templates/be/table/module-definition.ts.tpl +7 -0
  545. package/templates/be/table/module.ts.tpl +14 -0
  546. package/templates/be/table/options.ts.tpl +2 -0
  547. package/templates/be/table/rows.ts.tpl +4 -0
  548. package/templates/be/table/service.ts.tpl +23 -0
  549. package/templates/be/table/sql.ts.tpl +4 -0
  550. package/templates/be/tool-config/jest.config.js +3 -1
  551. package/templates/be/upgrade-full/apps/cli/src/app.module.ts +14 -0
  552. package/templates/be/upgrade-full/apps/cli/src/main.ts +26 -0
  553. package/templates/be/upgrade-full/src/features/cli/cli.module.ts +6 -0
  554. package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +23 -0
  555. package/templates/common/gitignore.base +1 -2
  556. package/templates/fe/app/package.json.tpl +1 -0
  557. package/templates/fe/app/tsconfig.json +12 -0
  558. package/templates/fe/common/app-layout.tsx.partial +8 -0
  559. package/templates/fe/common/site-shell.tsx.partial +9 -0
  560. package/templates/fe/image/next/Dockerfile +42 -0
  561. package/templates/fe/skeleton/apps/app/next.config.ts +23 -0
  562. package/templates/fe/skeleton/apps/app/postcss.config.mjs +7 -0
  563. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/error.tsx +2 -2
  564. package/templates/fe/skeleton/apps/app/src/app/[locale]/layout.tsx +22 -0
  565. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/loading.tsx +2 -2
  566. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/not-found.tsx +2 -2
  567. package/templates/fe/skeleton/apps/app/src/app/[locale]/page.tsx +9 -0
  568. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/global-error.tsx +2 -2
  569. package/templates/fe/skeleton/apps/app/src/app/globals.css +10 -0
  570. package/templates/fe/skeleton/apps/app/src/features/layouts/AppLayout/index.tsx +18 -0
  571. package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/component.tsx +19 -0
  572. package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/index.tsx +11 -0
  573. package/templates/fe/skeleton/apps/app/src/features/pages/AppGlobalErrorPage/index.tsx +16 -0
  574. package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/component.tsx +10 -0
  575. package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +15 -0
  576. package/templates/fe/skeleton/apps/app/src/features/pages/AppLoadingPage/index.tsx +8 -0
  577. package/templates/fe/skeleton/apps/app/src/features/pages/AppNotFoundPage/index.tsx +9 -0
  578. package/templates/fe/skeleton/apps/app/src/modules/i18n/index.ts +4 -0
  579. package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +28 -0
  580. package/templates/fe/skeleton/apps/app/src/modules/i18n/request.ts +4 -0
  581. package/templates/fe/skeleton/apps/app/src/modules/routes/index.ts +4 -0
  582. package/templates/fe/skeleton/apps/app/src/proxy.ts +1 -0
  583. package/templates/fe/skeleton/apps/{__app__ → landing}/next.config.ts +4 -2
  584. package/templates/fe/skeleton/apps/landing/postcss.config.mjs +7 -0
  585. package/templates/fe/skeleton/apps/landing/src/app/[locale]/error.tsx +10 -0
  586. package/templates/fe/skeleton/apps/landing/src/app/[locale]/layout.tsx +22 -0
  587. package/templates/fe/skeleton/apps/landing/src/app/[locale]/loading.tsx +6 -0
  588. package/templates/fe/skeleton/apps/landing/src/app/[locale]/not-found.tsx +6 -0
  589. package/templates/fe/skeleton/apps/landing/src/app/[locale]/page.tsx +9 -0
  590. package/templates/fe/skeleton/apps/landing/src/app/global-error.tsx +10 -0
  591. package/templates/fe/skeleton/apps/landing/src/app/globals.css +10 -0
  592. package/templates/fe/skeleton/apps/landing/src/features/layouts/LandingLayout/index.tsx +24 -0
  593. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/component.tsx +18 -0
  594. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/index.tsx +11 -0
  595. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingGlobalErrorPage/index.tsx +16 -0
  596. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingLoadingPage/index.tsx +8 -0
  597. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingNotFoundPage/index.tsx +9 -0
  598. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/component.tsx +24 -0
  599. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/index.tsx +16 -0
  600. package/templates/fe/skeleton/apps/landing/src/modules/config/index.ts +12 -0
  601. package/templates/fe/skeleton/apps/landing/src/modules/i18n/index.ts +7 -0
  602. package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/vi.json +31 -0
  603. package/templates/fe/skeleton/apps/landing/src/modules/i18n/request.ts +4 -0
  604. package/templates/fe/skeleton/apps/landing/src/modules/routes/index.ts +4 -0
  605. package/templates/fe/skeleton/apps/landing/src/proxy.ts +1 -0
  606. package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +49 -0
  607. package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +24 -0
  608. package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +20 -0
  609. package/templates/fe/skeleton/packages/__project__-ui/src/branches/Providers/index.tsx +23 -0
  610. package/templates/fe/skeleton/packages/__project__-ui/src/composites/ErrorNotice/index.tsx +14 -0
  611. package/templates/fe/skeleton/packages/__project__-ui/src/composites/GlobalErrorNotice/index.tsx +25 -0
  612. package/templates/fe/skeleton/packages/__project__-ui/src/composites/LoadingNotice/index.tsx +9 -0
  613. package/templates/fe/skeleton/packages/__project__-ui/src/composites/LocaleShell/index.tsx +21 -0
  614. package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +19 -0
  615. package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/classNames.ts +4 -0
  616. package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/index.tsx +19 -0
  617. package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +6 -0
  618. package/templates/fe/skeleton-lite/apps/web/next.config.ts +22 -0
  619. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/error.tsx +10 -0
  620. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +37 -0
  621. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/loading.tsx +6 -0
  622. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/not-found.tsx +6 -0
  623. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/page.tsx +9 -0
  624. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/providers.tsx +26 -0
  625. package/templates/fe/skeleton-lite/apps/web/src/app/auth/callback/route.ts +24 -0
  626. package/templates/fe/skeleton-lite/apps/web/src/app/global-error.tsx +10 -0
  627. package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/src/app/globals.css +1 -1
  628. package/templates/fe/skeleton-lite/apps/web/src/app/health/live/route.ts +5 -0
  629. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/component.tsx +29 -0
  630. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/index.tsx +41 -0
  631. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/component.tsx +17 -0
  632. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/index.tsx +38 -0
  633. package/templates/fe/skeleton-lite/apps/web/src/components/composites/ErrorNotice/index.tsx +13 -0
  634. package/templates/fe/skeleton-lite/apps/web/src/components/composites/GlobalErrorNotice/index.tsx +24 -0
  635. package/templates/fe/skeleton-lite/apps/web/src/components/composites/LoadingNotice/index.tsx +7 -0
  636. package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +18 -0
  637. package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/classNames.ts +4 -0
  638. package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/index.tsx +13 -0
  639. package/templates/fe/skeleton-lite/apps/web/src/features/layouts/AppLayout/index.tsx +31 -0
  640. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/component.tsx +12 -0
  641. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/index.tsx +10 -0
  642. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppGlobalErrorPage/index.tsx +15 -0
  643. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +14 -0
  644. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +30 -0
  645. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppLoadingPage/index.tsx +8 -0
  646. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppNotFoundPage/index.tsx +9 -0
  647. package/templates/fe/skeleton-lite/apps/web/src/modules/brand/brand.css +20 -0
  648. package/templates/fe/skeleton-lite/apps/web/src/modules/brand/index.ts +2 -0
  649. package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +20 -0
  650. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/read-session.ts +25 -0
  651. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-in.ts +25 -0
  652. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-out.ts +17 -0
  653. package/templates/fe/skeleton-lite/apps/web/src/modules/db/browser.ts +14 -0
  654. package/templates/fe/skeleton-lite/apps/web/src/modules/db/index.ts +3 -0
  655. package/templates/fe/skeleton-lite/apps/web/src/modules/db/outcome.ts +59 -0
  656. package/templates/fe/skeleton-lite/apps/web/src/modules/db/principal.ts +29 -0
  657. package/templates/fe/skeleton-lite/apps/web/src/modules/db/server.ts +70 -0
  658. package/templates/fe/skeleton-lite/apps/web/src/modules/db/validation/validation.mapper.ts +50 -0
  659. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +8 -0
  660. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +48 -0
  661. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +16 -0
  662. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +14 -0
  663. package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +7 -0
  664. package/templates/fe/skeleton-lite/apps/web/src/modules/routes/safe-next-path.ts +26 -0
  665. package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +43 -0
  666. package/templates/fe/table/read.ts.tpl +16 -0
  667. package/templates/fe/table/write.ts.tpl +16 -0
  668. package/upgrade/check.mjs +137 -0
  669. package/upgrade/index.mjs +524 -0
  670. package/bin/hfs.mjs +0 -233
  671. package/runtime/scripts/api/fs/rmdir-link.mjs +0 -12
  672. package/runtime/scripts/lib/test-secrets.mjs +0 -116
  673. package/templates/fe/skeleton/apps/__app__/src/app/[locale]/layout.tsx +0 -20
  674. package/templates/fe/skeleton/apps/__app__/src/app/[locale]/page.tsx +0 -9
  675. package/templates/fe/skeleton/apps/__app__/src/components/composites/FailureScreen/index.tsx +0 -28
  676. package/templates/fe/skeleton/apps/__app__/src/features/layouts/LocaleShell/index.tsx +0 -35
  677. package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/component.tsx +0 -19
  678. package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/index.tsx +0 -11
  679. package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/component.tsx +0 -24
  680. package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/index.tsx +0 -14
  681. package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/component.tsx +0 -21
  682. package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/index.tsx +0 -15
  683. package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/component.tsx +0 -23
  684. package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/index.tsx +0 -8
  685. package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/component.tsx +0 -28
  686. package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/index.tsx +0 -8
  687. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/config.ts +0 -8
  688. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/index.ts +0 -2
  689. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/messages/vi.json +0 -25
  690. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/request.ts +0 -19
  691. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/routing.ts +0 -9
  692. package/templates/fe/skeleton/apps/__app__/src/modules/routes/index.ts +0 -4
  693. package/templates/fe/skeleton/apps/__app__/src/proxy.ts +0 -10
  694. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.contracts.ts +0 -0
  695. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.handler.ts +0 -0
  696. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.query.ts +0 -0
  697. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/index.ts +0 -0
  698. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/system-health.module.ts +0 -0
  699. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/live.controller.ts +0 -0
  700. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/system-health-http.module.ts +0 -0
  701. /package/templates/fe/skeleton/apps/{__app__ → app}/src/app/health/live/route.ts +0 -0
  702. /package/templates/fe/skeleton/apps/{__app__ → app}/src/modules/config/index.ts +0 -0
  703. /package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/postcss.config.mjs +0 -0
@@ -6,7 +6,8 @@ import { machineKit } from './machine-ast.mjs';
6
6
  * `client-fetch-has-signal`. ESLint judges one file at a time by the spelling of a call; the machine judges the repository by
7
7
  * what the checker resolves. A repository has exactly ONE transport client and ONE Outcome union, both named by slot (never
8
8
  * by a path spelled here): the api package's (`fe.package.api.client`, `fe.package.api.outcome`) when the repository shares
9
- * it, or the only app's (`fe.transport.client`, `fe.transport.outcome`) when the repository declares exactly one app.
9
+ * it, or the only app's (`fe.transport.client`, `fe.transport.outcome`) when the repository declares exactly one app. The
10
+ * Outcome homes are the slots the manifest marks `outcomeHome` (the lite edition adds `fe.modules.db.outcome`), not a list kept here.
10
11
  *
11
12
  * - two or more clients, or two or more Outcome unions, in the repository (two apps each keeping one, or a package one plus
12
13
  * an app one) are findings on every copy;
@@ -30,7 +31,6 @@ const APP_CLIENT_SLOT = 'fe.transport.client';
30
31
  const APP_OUTCOME_SLOT = 'fe.transport.outcome';
31
32
  const PACKAGE_API_SLOT = 'fe.package.api';
32
33
  const CLIENT_SLOTS = new Set([APP_CLIENT_SLOT, 'fe.package.api.client']);
33
- const OUTCOME_SLOTS = new Set([APP_OUTCOME_SLOT, 'fe.package.api.outcome']);
34
34
  const NO_CLIENT = "the repository has no transport client. Create the one client (packages/<family>-api/src/client.ts, or the only app's modules/api/client.ts) and call it.";
35
35
 
36
36
  export function checkTransportOwner(input) {
@@ -60,7 +60,7 @@ export function checkTransportOwner(input) {
60
60
 
61
61
  const files = [...graph.files.values()].filter(file => file.slot && file.tier !== 'e2e');
62
62
  const clients = files.filter(file => CLIENT_SLOTS.has(file.slot));
63
- const outcomes = files.filter(file => OUTCOME_SLOTS.has(file.slot));
63
+ const outcomes = files.filter(file => resolver.slot(file.slot)?.outcomeHome === true);
64
64
  const clientRels = new Set(clients.map(file => file.rel));
65
65
  const list = items => items.map(item => item.rel).join(', ');
66
66
  const owned = clients.length ? `the repository has one transport (${list(clients)}). Call the client and take its Outcome.` : NO_CLIENT;
@@ -2,9 +2,11 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { createRequire } from 'node:module';
4
4
  import { canonical, isInside, slash } from './config.mjs';
5
+ import { crossesSide } from './side-boundary.mjs';
5
6
  import { sameOrUnder } from '../../lib/path-key.mjs';
6
7
  import { createTypeScriptProgram, readTypeScriptProject, resolveTypeScriptModule, sharedInProgramRun, typeScriptProjectReferencePath } from '../typescript-programs.mjs';
7
8
  import { readJsonFile } from '../../lib/json.mjs';
9
+ import { sourceLocation } from '../../lib/ts-ast.mjs';
8
10
  import { locateDeclaration } from '../slots.mjs';
9
11
 
10
12
  const CODE_EXTENSIONS = /\.(?:[cm]?[jt]sx?)$/i;
@@ -12,21 +14,11 @@ const TEST_FILE = /(?:^|[.-])(?:spec|test)\.[cm]?[jt]sx?$/i;
12
14
  const ASSET_EXTENSION = /\.(?:css|scss|sass|less|svg|png|jpe?g|gif|webp|avif|ico|woff2?|ttf|eot|ya?ml|json)$/i;
13
15
  // Framework build output a tsconfig may include (Next writes `.next/types/**/*.ts` back into tsconfig.json on
14
16
  // every build) is compiled for type resolution but is never source: it is gitignored, regenerated, and no
15
- // canon or architecture rule applies to it (starci-next inc-2260b3754afa, nivo inc-ffe60c49f502).
16
- export const GENERATED_SEGMENTS = new Set(['.next', '.turbo', '.vercel', '.output', '.nuxt', '.svelte-kit', '.expo', '.docusaurus', '.swc', '.cache']);
17
- export function isGeneratedPath(root, fileName) {
17
+ // canon or architecture rule applies to it (inc-ffe60c49f502).
18
+ const GENERATED_SEGMENTS = new Set(['.next', '.turbo', '.vercel', '.output', '.nuxt', '.svelte-kit', '.expo', '.docusaurus', '.swc', '.cache']);
19
+ function isGeneratedPath(root, fileName) {
18
20
  return slash(path.relative(root, fileName)).split('/').slice(0, -1).some(segment => GENERATED_SEGMENTS.has(segment));
19
21
  }
20
- // A `<tool>.config.*` or `<tool>.setup.*` module at the root of a project (beside a package manifest or a tsconfig.json:
21
- // next.config.ts and postcss.config.mjs of an app, which has no package.json of its own) is build tooling a broad `**/*.ts`
22
- // include pulls in; a `*.config.ts` inside a source tree (src/config/database.config.ts) has neither beside it and stays source.
23
- // The architecture program still reads tooling modules (a profile may declare one as source); the lint (hfs lint) judges one only
24
- // through the repository's own eslint.config.
25
- const TOOLING_MODULE = /^[^/]+\.(?:config|setup)\.[cm]?[jt]sx?$/i;
26
- export function isToolingModule(fileName) {
27
- return TOOLING_MODULE.test(path.basename(fileName)) && ['package.json', 'tsconfig.json'].some((manifest) => fs.existsSync(path.join(path.dirname(fileName), manifest)));
28
- }
29
-
30
22
  function diagnosticMessage(ts, diagnostic) {
31
23
  return ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
32
24
  }
@@ -53,7 +45,7 @@ function compilerError(ts, root, diagnostic, project, ruleId = 'ARCH_TSCONFIG_IN
53
45
  * Load TypeScript through the target package boundary, never through StarCi's own dependency graph. A side folder of an app has no
54
46
  * package.json of its own: the app root's one manifest is the boundary its TypeScript is installed under.
55
47
  */
56
- export function loadTargetTypeScript(repositoryRoot) {
48
+ function loadTargetTypeScript(repositoryRoot) {
57
49
  const packageFile = path.join(locateDeclaration(repositoryRoot).appRoot, 'package.json');
58
50
  if (!fs.existsSync(packageFile)) throw Error('ARCH_TYPESCRIPT_MISSING: target package.json is required to resolve target-installed TypeScript.');
59
51
  const targetRequire = createRequire(packageFile);
@@ -98,7 +90,7 @@ function runtimeImport(ts, node) {
98
90
  return true;
99
91
  }
100
92
 
101
- function isUnshadowedCommonJsRequire(ts, checker, expression) {
93
+ export function isUnshadowedCommonJsRequire(ts, checker, expression) {
102
94
  if (!ts.isIdentifier(expression) || expression.text !== 'require') return false;
103
95
  const symbol = checker?.getSymbolAtLocation(expression);
104
96
  if (!symbol) return true;
@@ -113,7 +105,7 @@ function isUnshadowedCommonJsRequire(ts, checker, expression) {
113
105
  * existing directory and a data-asset extension tail qualify; code never does, since a context of code would
114
106
  * be an import graph nobody wrote down. Returns the specifiers, or null when the import stays unproven.
115
107
  */
116
- export function assetContextSpecifiers(ts, sourceFile, argument) {
108
+ function assetContextSpecifiers(ts, sourceFile, argument) {
117
109
  if (!argument || !ts.isTemplateExpression(argument)) return null;
118
110
  const head = argument.head.text;
119
111
  const spans = argument.templateSpans;
@@ -168,11 +160,6 @@ function moduleReferences(ts, sourceFile, checker) {
168
160
  return { found, unproven };
169
161
  }
170
162
 
171
- function sourceLocation(sourceFile, node) {
172
- const point = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
173
- return { line: point.line + 1, column: point.character + 1 };
174
- }
175
-
176
163
  function isProductionSource(root, sourceFile) {
177
164
  return isInside(root, sourceFile.fileName)
178
165
  && CODE_EXTENSIONS.test(sourceFile.fileName)
@@ -210,7 +197,7 @@ function exportPatternCapture(pattern, request) {
210
197
  return request.startsWith(before) && request.endsWith(after) ? request.slice(before.length, request.length - after.length) : null;
211
198
  }
212
199
 
213
- function exportTargetStrings(value) {
200
+ export function exportTargetStrings(value) {
214
201
  if (typeof value === 'string') return [value];
215
202
  if (Array.isArray(value)) return value.flatMap(exportTargetStrings);
216
203
  if (value && typeof value === 'object' && !Object.keys(value).some(key => key.startsWith('.'))) return Object.values(value).flatMap(exportTargetStrings);
@@ -497,9 +484,7 @@ function typeScriptContext(config, loaded, paths) {
497
484
  || (config.repository && isInside(config.repository, actualTarget) && !slash(actualTarget).includes('/node_modules/'));
498
485
  // A side of an app (config.root is be/ or fe/) imports nothing of the app outside itself: the root holds no source, the other
499
486
  // side is another program, and a declared read (sides.fe.reads, be/contracts/) is codegen input, never an import.
500
- const crossesSide = config.packageRoot !== undefined && config.packageRoot !== config.root
501
- && isInside(config.packageRoot, actualTarget) && !isInside(config.root, actualTarget) && !slash(actualTarget).includes('/node_modules/');
502
- if (internal && crossesSide) {
487
+ if (internal && crossesSide(config, actualTarget)) {
503
488
  errors.push({
504
489
  ruleId: 'ARCH_INTERNAL_IMPORT_OUTSIDE',
505
490
  project: project.relative,
@@ -581,6 +566,8 @@ export function unwrapExpression(ts, expression) {
581
566
  return expression;
582
567
  }
583
568
 
569
+ /* ---- the AST walks every architecture checker shares ---- */
570
+
584
571
  /** The names of `expected` an import or re-export statement binds (all of them for a namespace or star form). */
585
572
  export function referencedExports(ts, statement, expected) {
586
573
  if (ts.isImportDeclaration(statement)) {
@@ -595,4 +582,3 @@ export function referencedExports(ts, statement, expected) {
595
582
  return [...expected];
596
583
  }
597
584
 
598
- export { isUnshadowedCommonJsRequire, sourceLocation };
@@ -1,6 +1,6 @@
1
- // architecture.mjs — the architecture check (docs/architecture-check.md).
1
+ // architecture.mjs — the architecture check (docs/architecture.md).
2
2
  //
3
- // node scripts/hfs/architecture.mjs <repo-root> [--base <commit>]
3
+ // starci runtime architecture <repo-root> [--base <commit>]
4
4
  //
5
5
  // Prints one starci/architecture-check@1 record. Exit 0: ok. Exit 1: violations or errors (a check that
6
6
  // cannot run is an error, never a pass). Exit 2: bad arguments.
@@ -11,9 +11,9 @@ import { isMain } from '../lib/is-main.mjs';
11
11
 
12
12
  export {checkArchitecture};
13
13
 
14
- const USAGE = 'usage: architecture.mjs <repo-root> [--base <commit>]';
14
+ const USAGE = 'usage: starci runtime architecture <repo-root> [--base <commit>]';
15
15
 
16
- export function parseArchitectureArgs(argv) {
16
+ function parseArchitectureArgs(argv) {
17
17
  let root = null, base;
18
18
  for (let index = 0; index < argv.length; index += 1) {
19
19
  const value = argv[index];
@@ -1,4 +1,4 @@
1
- // hfs-check.mjs - the HFS app check, behind `hfs check | explain` (packages/hfs) and reusable by any
1
+ // hfs-check.mjs - the HFS app check, behind `starci app check | explain` (packages/hfs) and reusable by any
2
2
  // runtime check. It reads three things and nothing else: the app's hfs.json, the slot manifest
3
3
  // (knowledge/hfs/slots.yaml through scripts/hfs/slots.mjs) and the pins (knowledge/hfs/canon-pins.yaml). It never
4
4
  // writes to the repository it inspects.
@@ -15,22 +15,29 @@
15
15
  // and passed in as `extraFindings` (this module does not read the templates)
16
16
  // HFS_SLOT_REQUIRED_MISSING a file or directory a required slot (or an instance of one) must contain
17
17
  // HFS_MIN_INSTANCES fewer instances of a slot than minInstances
18
- // HFS_PLAINTEXT_SECRET (R06, hfs-rules/secrets.mjs) a plaintext secret file or value in a tracked file; a `.enc` that is no sops envelope
19
- // HFS_STACKS_SHAPE (R10, hfs-rules/stacks.mjs) a `.starcistacks` path outside the standard shape, or a Sonar owner that is not the host
20
- // HFS_CI_MISSING_CANON (R13, hfs-rules/pipeline.mjs) CI without the pinned `hfs check`, pre-push without typecheck or lint
21
- // HFS_DEP_VERSION_SKEW (R14, hfs-rules/deps.mjs) a dependency at two versions in the workspace, or a nested copy in the lockfile
22
- // HFS_CONTRACT_SNAPSHOT_DRIFT (R23, hfs-rules/contract.mjs) an uncommitted back-end snapshot, or a front-end copy that differs from it
23
- // BE_TEST_TOPOLOGY (R47, hfs-rules/test-topology.mjs) a `.test` file, a testing/ folder, a second jest configuration
24
- // FE_NO_TESTS (R97, hfs-rules/fe-no-tests.mjs) a front end holds a spec, e2e or test-tool file, a test script or a test dependency; no exception
25
- // BE_SPEC_PLACEMENT (R102, hfs-rules/spec-placement.mjs) a spec or test file outside the four test layers, scripts/ and tools/ included
26
- // HFS_REPO_LOCAL_CHECK (R103, hfs-rules/repo-local-checks.mjs) a local eslint rule or plugin, a `check-*` script, a relative import in eslint.config
27
- // HFS_LINT_SUPPRESSION_FILE (R104, hfs-rules/lint-suppression.mjs) an eslint suppressions file, script or option
28
- // HFS_PROOF_COMMAND_FILE_MISSING (R105, hfs-rules/proof-commands.mjs) a .starciwork proof command that runs a file the repository does not hold
29
- // HFS_PEER_INTEGRATION_MISSING (R111, hfs-rules/peer-integrations.mjs) the app root package.json lacks the runtime peer a driver integration needs
30
- // BE_INTEGRATION_SPEC_MISSING (R112, hfs-rules/integration-specs.mjs) an integration with no integration spec that registers its module, maps its refusals and drives an outage
31
- // FE_GRAPHQL_CONTRACT (R113, hfs-rules/fe-contract-documents.mjs) a front-end GraphQL document the back end's contract snapshot does not serve
32
- // FE_WIRE_GENERATED, FE_I18N_PLACEMENT, FE_I18N_CATALOG (R52, R59, R60, hfs-rules/frontend.mjs) the front-end tree of each app
33
- // HFS_GITIGNORE_BLOCK_DRIFT, HFS_SONAR_CONFIG (R04, R11) produced by packages/hfs/sync/managed.mjs, which renders the templates
18
+ // HFS_PLAINTEXT_SECRET (R06, rules/secrets.mjs) a plaintext secret file or value in a tracked file; a `.enc` that is no sops envelope
19
+ // HFS_STACKS_SHAPE (R10, rules/stacks.mjs) a `.starcistacks` path outside the standard shape, or a Sonar owner that is not the host
20
+ // HFS_CI_MISSING_CANON (R13, rules/pipeline.mjs) CI without the pinned `starci app check`, pre-push without typecheck or lint
21
+ // HFS_DEP_VERSION_SKEW (R14, rules/deps.mjs) a dependency at two versions in the workspace, or a nested copy in the lockfile
22
+ // HFS_CONTRACT_SNAPSHOT_DRIFT (R23, rules/contract.mjs) an uncommitted back-end snapshot, or a front-end copy that differs from it
23
+ // BE_TEST_TOPOLOGY (R47, rules/test-topology.mjs) a `.test` file, a testing/ folder, a second jest configuration
24
+ // FE_NO_TESTS (R97, rules/fe-no-tests.mjs) a front end holds a spec, e2e or test-tool file, a test script or a test dependency; no exception
25
+ // HFS_LITE_SECRET_CUSTODY (R220, rules/supabase-secrets.mjs) under edition lite: secret material or a forbidden custody path; the R06 scan itself runs for every edition
26
+ // HFS_EDITION_FORBIDDEN_PRESENT (R212, rules/edition.mjs) under edition lite: a test script, dependency or tool config in a
27
+ // package.json or the tree, or a declared worker app, event pattern or trigger kind lite does not have
28
+ // DB_MIGRATION_SHAPE ... DB_TYPES_DRIFT (R213-R216, rules/database.mjs, async: passed in as extraFindings) the Supabase migrations, policies, definer functions, buckets, config.toml and generated types
29
+ // BE_SPEC_PLACEMENT (R102, rules/spec-placement.mjs) a spec or test file outside the four test layers, scripts/ and tools/ included
30
+ // HFS_REPO_LOCAL_CHECK (R103, rules/repo-local-checks.mjs) a local eslint rule or plugin, a `check-*` script, a relative import in eslint.config
31
+ // HFS_LINT_SUPPRESSION_FILE (R104, rules/lint-suppression.mjs) an eslint suppressions file, script or option
32
+ // HFS_PROOF_COMMAND_FILE_MISSING (R105, rules/proof-commands.mjs) a .starciwork proof command that runs a file the repository does not hold
33
+ // HFS_PEER_INTEGRATION_MISSING (R111, rules/peer-integrations.mjs) the app root package.json lacks the runtime peer a driver integration needs
34
+ // BE_INTEGRATION_SPEC_MISSING (R112, rules/integration-specs.mjs) an integration with no integration spec that registers its module, maps its refusals and drives an outage
35
+ // FE_GRAPHQL_CONTRACT (R113, rules/fe-contract-documents.mjs) a front-end GraphQL document the back end's contract snapshot does not serve
36
+ // HFS_MONO_* (R143-R146, rules/monorepo.mjs) the monorepo shape; BE_CLI_REQUIRED (R147, rules/cli.mjs) the one cli app
37
+ // HFS_SERVICE_PLACEMENT, HFS_IMAGE_UNPINNED, HFS_SERVICE_STACK_DECLARATION, HFS_EVENT_CONTRACT, BE_ASYNC_SPEC_MISSING (R163-R167, rules/services.mjs) the microservice policy of a product with more than one service
38
+ // BE_EVENT_CLASS_CONTRACT, BE_PATTERN_SPEC_MISSING, BE_KIND_DECLARATION, BE_KIND_EMPTY (rules/app-root.mjs: event-bus.mjs and kinds.mjs) a typed event class the vendored contract does not list, a declared pattern whose proof scenarios have no test, and the trigger kinds of the features (declared, whole, never empty)
39
+ // FE_WIRE_GENERATED, FE_I18N_PLACEMENT, FE_I18N_CATALOG (R52, R59, R60, rules/frontend.mjs) the front-end tree of each app
40
+ // HFS_GITIGNORE_BLOCK_DRIFT, HFS_SONAR_CONFIG, HFS_COVERAGE_SCOPE_DRIFT (R04, R11, R204) produced by packages/hfs/sync/managed.mjs, which renders the templates
34
41
  // HFS_FORMAT (R19) produced by packages/hfs/sync/format.mjs, which runs the repository's own prettier
35
42
  // both are passed in as `extraFindings`: this module reads no template and starts no tool
36
43
  // HFS_CANON_PIN_DRIFT a dependency whose declared version is not the pinned one
@@ -41,7 +48,7 @@
41
48
  // HFS_UNTRACKED_ROOT_ENTRY an entry git neither tracks nor ignores, outside an `ignored` slot (R03)
42
49
  // A runtime repository (hfs.json kind runtime, judged with knowledge/hfs/runtime-slots.yaml) gets the per-path slot findings,
43
50
  // the required files and minimum instances and the tree findings only; scripts/hfs/runtime-check.mjs adds the runtime rules.
44
- // checkRepository() is the whole `hfs check`: checkRepo() plus the architecture machine (scripts/hfs/architecture.mjs, one
51
+ // checkRepository() is the whole `starci app check`: checkRepo() plus the architecture machine (scripts/hfs/architecture.mjs, one
45
52
  // implementation; the published bundle carries a byte copy), its violations and errors reported as findings under their own
46
53
  // codes; `fast` limits both to the owners changed since the merge-base. Every finding carries its code and the Vietnamese why text of modules/kernel/failure-codes.yaml. Only `error`
47
54
  // findings fail the check.
@@ -50,40 +57,40 @@ import path from 'node:path';
50
57
  import { skillRoot } from '../../engine/runtime-root.mjs';
51
58
  import { ARCHITECTURE_RULE_IDS, checkArchitecture } from './architecture/index.mjs';
52
59
  import { parseYaml } from '../../engine/yaml.mjs';
53
- import { APP_SCOPE, HFS_DECLARATION_FILE, appRelativeMessages, HfsSlotsError, SIDES, createSlotResolver, loadSlotManifest, readRepoDeclaration, resolveRepoDeclaration } from './slots.mjs';
60
+ import { APP_SCOPE, HFS_DECLARATION_FILE, appRelativeMessages, HfsSlotsError, SIDES, createSlotResolver, loadRuleCatalog, loadSlotManifest, readRepoDeclaration, resolveRepoDeclaration } from './slots.mjs';
54
61
  import { allowsFile } from './allows.mjs';
55
62
  import { RUNTIME_KIND } from './manifest-shape.mjs';
56
- import { gitOutput } from '../api/git/lib.mjs';
63
+ import { lsFiles } from '../api/git/ls-files.mjs';
64
+ import { diff as gitDiff } from '../api/git/diff.mjs';
65
+ import { mergeBase } from '../api/git/merge-base.mjs';
66
+ import { gitOutputOf } from '../lib/git.mjs';
57
67
  import { posixPath } from '../lib/path-key.mjs';
58
68
  import { readTree, treeFacts, untrackedEntries } from './tree.mjs';
59
69
  import { contractFindings } from './rules/contract.mjs';
60
- import { depFindings } from './rules/deps.mjs';
61
- import { appFrontendFindings, frontendFindings } from './rules/frontend-tree.mjs';
62
- import { feContractFindings } from './rules/fe-contract-documents.mjs';
63
- import { integrationSpecFindings } from './rules/integration-specs.mjs';
70
+ import { appRootFindings } from './rules/app-root.mjs';
71
+ import { frontendFindings } from './rules/frontend-tree.mjs';
64
72
  import { lintSuppressionFindings } from './rules/lint-suppression.mjs';
65
- import { peerIntegrationFindings } from './rules/peer-integrations.mjs';
66
- import { pipelineFindings } from './rules/pipeline.mjs';
67
- import { proofCommandFindings } from './rules/proof-commands.mjs';
68
73
  import { repoLocalCheckFindings } from './rules/repo-local-checks.mjs';
69
74
  import { readJson } from './rules/read.mjs';
70
- import { secretFindings } from './rules/secrets.mjs';
75
+ import { supabaseSecretFindings } from './rules/supabase-secrets.mjs';
71
76
  import { pathFindings } from './path-findings.mjs';
72
77
  import { onLintSurface } from './architecture/surface.mjs';
73
78
  import { checkAppRoot, trackedTreeView } from './architecture/hfs.mjs';
74
- import { stacksFindings } from './rules/stacks.mjs';
75
79
  import { testTopologyFindings } from './rules/test-topology.mjs';
76
80
  import { feNoTestsFindings, isFeTestPath } from './rules/fe-no-tests.mjs';
81
+ import { editionFindings } from './rules/edition.mjs';
82
+ // The database rules (R213-R216) read SQL through a WASM parser, so they are async: `starci app check` calls them beside the other emitters and passes the findings in as `extraFindings`.
83
+ export { checkDatabase } from './rules/database.mjs';
77
84
 
78
- export const CANON_PINS_FILE = 'knowledge/hfs/canon-pins.yaml';
85
+ const CANON_PINS_FILE = 'knowledge/hfs/canon-pins.yaml';
79
86
  export const FAILURE_CODES_FILE = 'modules/kernel/failure-codes.yaml';
80
87
  /**
81
- * The codes `hfs check` reports when it cannot judge (an unreadable repository, a refused declaration or manifest, a missing
88
+ * The codes `starci app check` reports when it cannot judge (an unreadable repository, a refused declaration or manifest, a missing
82
89
  * formatter): infrastructure refusals, never obligations, so no rule of knowledge/hfs/rules.yaml owns them.
83
90
  */
84
91
  export const REFUSAL_CODES = Object.freeze([
85
92
  'HFS_REPO_UNREADABLE',
86
- 'HFS_DECLARATION_INVALID', 'HFS_MANIFEST_MAJOR_MISMATCH', 'HFS_MANIFEST_INVALID', 'HFS_FORMAT_TOOL_MISSING',
93
+ 'HFS_DECLARATION_INVALID', 'HFS_MANIFEST_MAJOR_MISMATCH', 'HFS_MANIFEST_INVALID', 'HFS_FORMAT_TOOL_MISSING', 'HFS_EDITION_INVALID',
87
94
  ]);
88
95
  /** The codes this module emits that are not the slot loader's own: the why bundle of packages/hfs ships exactly these plus the loader's. */
89
96
  export const CHECK_CODES = Object.freeze([
@@ -91,12 +98,14 @@ export const CHECK_CODES = Object.freeze([
91
98
  'HFS_SLOT_REQUIRED_MISSING', 'HFS_MIN_INSTANCES', 'HFS_CANON_PIN_DRIFT', 'HFS_SIZE_SOFT_BACKLOG', 'BE_SOURCE_FORM',
92
99
  'HFS_MANAGED_FILE_DRIFT', 'HFS_TOOL_CONFIG_LOCAL', 'HFS_RULE_OFF_WITHOUT_REPLACEMENT', 'HFS_TS_STRICT',
93
100
  'HFS_PLAINTEXT_SECRET', 'HFS_STACKS_SHAPE', 'HFS_CI_MISSING_CANON', 'HFS_DEP_VERSION_SKEW', 'HFS_CONTRACT_SNAPSHOT_DRIFT',
94
- 'BE_TEST_TOPOLOGY', 'BE_SPEC_PLACEMENT', 'HFS_REPO_LOCAL_CHECK', 'HFS_LINT_SUPPRESSION_FILE', 'HFS_PROOF_COMMAND_FILE_MISSING', 'HFS_PEER_INTEGRATION_MISSING', 'BE_INTEGRATION_SPEC_MISSING', 'FE_GRAPHQL_CONTRACT', 'FE_NO_TESTS', 'FE_WIRE_GENERATED', 'FE_I18N_PLACEMENT', 'FE_I18N_CATALOG',
95
- 'HFS_GITIGNORE_BLOCK_DRIFT', 'HFS_SONAR_CONFIG', 'HFS_FORMAT',
101
+ 'BE_TEST_TOPOLOGY', 'BE_SPEC_PLACEMENT', 'HFS_REPO_LOCAL_CHECK', 'HFS_LINT_SUPPRESSION_FILE', 'HFS_PROOF_COMMAND_FILE_MISSING', 'HFS_PEER_INTEGRATION_MISSING', 'BE_INTEGRATION_SPEC_MISSING', 'FE_GRAPHQL_CONTRACT', 'FE_NO_TESTS', 'HFS_MONO_WORKSPACES', 'HFS_MONO_FE_WORKSPACE', 'HFS_MONO_NEST_PROJECTS', 'HFS_MONO_WORKSPACE_DEP', 'BE_CLI_REQUIRED', 'FE_WIRE_GENERATED', 'FE_I18N_PLACEMENT', 'FE_I18N_CATALOG', 'HFS_SERVICE_PLACEMENT', 'HFS_IMAGE_UNPINNED', 'HFS_SERVICE_STACK_DECLARATION', 'HFS_EVENT_CONTRACT', 'BE_ASYNC_SPEC_MISSING', 'BE_SAGA_STEP_COMPENSATION', 'BE_SAGA_STATE_VERSIONED', 'BE_SAGA_EVENT_CONTRACT', 'BE_SAGA_CONSUMER_DEDUPE', 'BE_EVENT_CLASS_CONTRACT', 'BE_PATTERN_SPEC_MISSING', 'BE_CONTRACT_BREAKING', 'BE_KIND_DECLARATION', 'BE_KIND_EMPTY', 'HFS_DOCKER_BUILD_CONTEXT', 'HFS_DOCKER_STAGES', 'HFS_DOCKER_ENTRY', 'HFS_DOCKER_BASE_PIN', 'HFS_DOCKER_SECRETS', 'BE_SAGA_E2E_MISSING',
102
+ 'HFS_EDITION_FORBIDDEN_PRESENT', 'HFS_LITE_SECRET_CUSTODY',
103
+ 'DB_MIGRATION_SHAPE', 'DB_RLS_REQUIRED', 'DB_DYNAMIC_DDL', 'DB_POLICY_SHAPE', 'DB_DEFINER_SAFE', 'DB_STORAGE_POLICY', 'DB_CONFIG_POLICY', 'DB_TYPES_DRIFT',
104
+ 'HFS_GITIGNORE_BLOCK_DRIFT', 'HFS_SONAR_CONFIG', 'HFS_COVERAGE_SCOPE_DRIFT', 'HFS_FORMAT',
96
105
  'HFS_EMPTY_DIR', 'HFS_GHOST_TREE', 'HFS_UNTRACKED_ROOT_ENTRY',
97
106
  ...REFUSAL_CODES,
98
107
  ]);
99
- /** Every code `hfs check` can report: its own and every code the architecture machine can emit (derived from the machine's rule id lists). */
108
+ /** Every code `starci app check` can report: its own and every code the architecture machine can emit (derived from the machine's rule id lists). */
100
109
  export const ALL_CHECK_CODES = Object.freeze([...new Set([...CHECK_CODES, ...ARCHITECTURE_RULE_IDS])].sort());
101
110
  const SOURCE_EXT = /\.(?:[cm]?[jt]sx?)$/;
102
111
  const VAR = /<([a-z][a-z0-9-]*)>/g;
@@ -120,7 +129,7 @@ export function readWhy(root = skillRoot, codes = CHECK_CODES) {
120
129
  export function trackedFiles(repoRoot) {
121
130
  let out;
122
131
  try {
123
- out = gitOutput(['ls-files', '-z', '--cached', '--exclude-standard'], { dir: repoRoot, maxBuffer: 256 * 1024 * 1024 });
132
+ out = gitOutputOf(lsFiles(['-z', '--cached', '--exclude-standard'], { dir: repoRoot, maxBuffer: 256 * 1024 * 1024 }), 'git ls-files');
124
133
  } catch (error) {
125
134
  refuse('HFS_REPO_UNREADABLE', `${repoRoot} is not a readable Git work tree (${String(error?.stderr ?? error?.message ?? error).trim().split('\n')[0]})`, { repoRoot });
126
135
  }
@@ -129,12 +138,6 @@ export function trackedFiles(repoRoot) {
129
138
 
130
139
  const fill = (text, bindings) => String(text).replace(VAR, (whole, name) => bindings[name] ?? whole);
131
140
 
132
- /** hfs.json of `repoRoot` resolved against the manifest, or the single refusal finding when it is absent or invalid. */
133
- export function openRepo({ repoRoot, root = skillRoot, manifest = loadSlotManifest({ root }) }) {
134
- const repo = readRepoDeclaration(manifest, repoRoot);
135
- return { manifest, repo, resolver: createSlotResolver(manifest, repo) };
136
- }
137
-
138
141
  const pinnedSpec = (spec, pin) => (spec === pin.version ? null : `declared ${spec}, pinned ${pin.version}`);
139
142
 
140
143
  /** The pin map of knowledge/hfs/canon-pins.yaml under `root`. */
@@ -202,6 +205,16 @@ function summarize(findings) {
202
205
  };
203
206
  }
204
207
 
208
+ /**
209
+ * THE edition filter of findings: a finding whose code belongs, through the rule catalog, to a rule the app's edition does not
210
+ * judge (rules.yaml `editions`) is dropped. Codes outside the catalog (refusals, machine codes without a rule) stay. This is the
211
+ * only place the edition touches a finding; no check below it knows the edition.
212
+ */
213
+ function judgedFindings(findings, edition, root) {
214
+ const catalog = loadRuleCatalog({ root });
215
+ return findings.filter((finding) => catalog.judgedIn(finding.code, edition));
216
+ }
217
+
205
218
  /** The tree findings of R03: empty directories, ghost siblings, untracked entries outside an ignored slot. */
206
219
  function treeFindings({ repoRoot, resolver }) {
207
220
  const inIgnoredSlot = (rel) => resolver.classifyPath(`${rel}/.probe`).tracking === 'ignored';
@@ -230,7 +243,7 @@ const onSide = (side, p) => (p ? path.posix.normalize(`${side}/${p}`) : p);
230
243
  * relative to it, exactly as the standalone repository root was). `files` are the scope's tracked paths; `all` (root only) every
231
244
  * tracked path of the app, for the rules that read across it (dependency skew, proof commands).
232
245
  */
233
- function scopeFindings({ repoRoot, root, repo, resolver, files, all = files, scoped }) {
246
+ function scopeFindings({ repoRoot, root, repo, resolver, files, all = files, scoped, manifest, editionDeclaration = true }) {
234
247
  const inScope = (file) => !scoped || scoped.has(file);
235
248
  // A required directory of the root (be/, fe/) is present through the files below it, which are the sides' own.
236
249
  const trackedSet = new Set(all);
@@ -264,28 +277,21 @@ function scopeFindings({ repoRoot, root, repo, resolver, files, all = files, sco
264
277
  const pins = readPins(root);
265
278
  findings.push(...pinFindings({ repoRoot, files, profile: repo.profile, pins, only: scoped }));
266
279
 
267
- // The tree checks of the rules that read file content or configuration (hfs-rules/*): whole-scope, cheap, no tool run.
280
+ // The tree checks of the rules that read file content or configuration (rules/*): whole-scope, cheap, no tool run.
268
281
  findings.push(
269
- ...secretFindings({ repoRoot, files: files.filter(inScope), resolver }),
282
+ ...supabaseSecretFindings({ repoRoot, files: files.filter(inScope), resolver, repo }),
283
+ ...editionFindings({ repoRoot, files: files.filter(inScope), repo, resolver, withDeclaration: editionDeclaration }),
270
284
  ...repoLocalCheckFindings({ repoRoot, files }),
271
285
  ...lintSuppressionFindings({ repoRoot, files }),
272
286
  );
273
287
  if (isRoot) {
274
288
  findings.push(
275
- ...depFindings({ repoRoot, files: all }),
276
- ...peerIntegrationFindings({ repoRoot, files: all }),
277
- ...integrationSpecFindings({ repoRoot, files: all }),
278
- ...feContractFindings({ repoRoot, files: all }),
279
- ...pipelineFindings({ repoRoot, files, pins }),
280
- ...testTopologyFindings({ repoRoot, files }),
281
- ...proofCommandFindings({ repoRoot, files: all, resolver, sides: Object.keys(repo.sides ?? {}) }),
282
- ...appFrontendFindings({ repoRoot, files: all, repo }),
283
- ...stacksFindings({ repoRoot, files, resolver }),
289
+ ...appRootFindings({ repoRoot, files, all, repo, resolver, pins }),
284
290
  // The tree check of the app root the machine runs per side for a side folder: README, root entries, automatic gates, hooks path.
285
291
  ...checkAppRoot({ root: repoRoot, resolver, tree: trackedTreeView(all) }).violations.map((item) => ({ code: item.ruleId, level: 'error', path: item.path, line: item.line, column: item.column, source: 'machine', message: `${item.path}: ${item.message}` })),
286
292
  );
287
293
  } else if (repo.profile === 'be') {
288
- findings.push(...contractFindings({ files, repo, resolver }), ...testTopologyFindings({ repoRoot, files }));
294
+ findings.push(...contractFindings({ repoRoot, files, repo, resolver }), ...testTopologyFindings({ repoRoot, files }));
289
295
  } else {
290
296
  findings.push(...frontendFindings({ repoRoot, files, repo }), ...feNoTestsFindings({ repoRoot, files: files.filter(inScope) }));
291
297
  }
@@ -319,7 +325,7 @@ export function checkRepo({ repoRoot, root = skillRoot, declaration, files, only
319
325
  try {
320
326
  repo = declaration === undefined ? readRepoDeclaration(manifest, repoRoot) : resolveRepoDeclaration(manifest, declaration);
321
327
  } catch (error) {
322
- if (!(error instanceof HfsSlotsError) || !['HFS_DECLARATION_INVALID', 'HFS_MANIFEST_MAJOR_MISMATCH'].includes(error.code)) throw error;
328
+ if (!(error instanceof HfsSlotsError) || !['HFS_DECLARATION_INVALID', 'HFS_MANIFEST_MAJOR_MISMATCH', 'HFS_EDITION_INVALID'].includes(error.code)) throw error;
323
329
  const findings = withWhy([{ code: error.code, level: 'error', path: HFS_DECLARATION_FILE, message: error.message.replace(/^[A-Z_]+: /, ''), problems: error.details.problems }], why);
324
330
  return { ok: false, repoRoot, manifest: manifest.version, profile: null, apps: [], tracked: 0, findings, counts: summarize(findings) };
325
331
  }
@@ -327,28 +333,29 @@ export function checkRepo({ repoRoot, root = skillRoot, declaration, files, only
327
333
  const tracked = files ?? trackedFiles(repoRoot);
328
334
  const scoped = only ? new Set(only) : null;
329
335
  const findings = [];
330
- // `hfs check` leaves to the lint canon the per-path findings that sit on an existing TypeScript file (hfs-path-findings.mjs).
336
+ // `starci app check` leaves to the lint canon the per-path findings that sit on an existing TypeScript file (hfs-path-findings.mjs).
331
337
  const keep = (list, scopeRoot) => (surface === 'check' ? list.filter((finding) => !(finding.origin === 'repo' && onLintSurface(scopeRoot, finding))) : list);
332
338
  if (repo.profile === APP_SCOPE) {
333
339
  const own = tracked.filter((file) => resolver.sideOf(file) === null);
334
- findings.push(...keep(scopeFindings({ repoRoot, root, repo, resolver, files: own, all: tracked, scoped }), repoRoot));
340
+ findings.push(...keep(scopeFindings({ repoRoot, root, repo, resolver, files: own, all: tracked, scoped, manifest }), repoRoot));
335
341
  for (const side of SIDES) {
336
342
  const prefix = `${side}/`;
337
343
  const sideRoot = path.join(repoRoot, side);
338
344
  const sideFiles = tracked.filter((file) => file.startsWith(prefix)).map((file) => file.slice(prefix.length));
339
345
  const sideScoped = scoped ? new Set([...scoped].filter((file) => file.startsWith(prefix)).map((file) => file.slice(prefix.length))) : null;
340
- const sideFindings = scopeFindings({ repoRoot: sideRoot, root, repo: repo.sides[side], resolver: resolver.sides[side], files: sideFiles, scoped: sideScoped });
346
+ const sideFindings = scopeFindings({ repoRoot: sideRoot, root, repo: repo.sides[side], resolver: resolver.sides[side], files: sideFiles, scoped: sideScoped, manifest, editionDeclaration: false });
341
347
  const message = appRelativeMessages(side, sideRoot);
342
348
  findings.push(...keep(sideFindings, sideRoot).map((finding) => ({ ...finding, side, path: onSide(side, finding.path), message: message(finding.message) })));
343
349
  }
344
350
  } else {
345
- findings.push(...keep(scopeFindings({ repoRoot, root, repo, resolver, files: tracked, scoped }), repoRoot));
351
+ findings.push(...keep(scopeFindings({ repoRoot, root, repo, resolver, files: tracked, scoped, manifest }), repoRoot));
346
352
  }
347
353
  findings.push(...extraFindings);
348
354
  if (tree) findings.push(...treeFindings({ repoRoot, resolver }));
349
355
 
350
356
  // The app-root tree check reports machine codes: their why is read with the check's own.
351
- const finished = withWhy(findings, { ...why, ...readWhy(root, [...new Set(findings.map((f) => f.code).filter((code) => !why[code]))]) });
357
+ const judged = judgedFindings(findings, repo.edition ?? 'full', root);
358
+ const finished = withWhy(judged, { ...why, ...readWhy(root, [...new Set(judged.map((f) => f.code).filter((code) => !why[code]))]) });
352
359
  const counts = summarize(finished);
353
360
  const apps = repo.profile === APP_SCOPE ? SIDES.flatMap((side) => repo.sides[side].apps.map((app) => ({ ...app, side }))) : repo.apps;
354
361
  return { ok: counts.error === 0, repoRoot, manifest: manifest.version, profile: repo.profile, apps, tracked: tracked.length, findings: finished, counts };
@@ -356,28 +363,24 @@ export function checkRepo({ repoRoot, root = skillRoot, declaration, files, only
356
363
 
357
364
  // ------------------------------------------------------------------------------------------ the whole check
358
365
 
359
- const gitOut = (repoRoot, args) => gitOutput(args, { dir: repoRoot, maxBuffer: 256 * 1024 * 1024 });
360
-
361
366
  /** The merge-base of HEAD with `base`, else with origin/main, else with main; null when none resolves. */
362
367
  function mergeBaseOf(repoRoot, base) {
363
368
  for (const ref of base ? [base] : ['origin/main', 'main']) {
364
- try {
365
- const sha = gitOut(repoRoot, ['merge-base', 'HEAD', ref]).trim();
366
- if (sha) return sha;
367
- } catch { /* this ref has no merge-base with HEAD; try the next */ }
369
+ const sha = mergeBase(repoRoot, 'HEAD', ref); // null: this ref has no merge-base with HEAD; try the next
370
+ if (sha) return sha;
368
371
  }
369
372
  return null;
370
373
  }
371
374
 
372
375
  /** Tracked paths that differ from the merge-base (commits, staged and unstaged edits; deletions are not paths to judge). */
373
- export function changedSince(repoRoot, base) {
376
+ function changedSince(repoRoot, base) {
374
377
  const sha = mergeBaseOf(repoRoot, base);
375
378
  if (!sha) {
376
379
  throw new Error(base
377
380
  ? `--base ${base} has no merge-base with HEAD; pass a ref this branch descends from`
378
381
  : '--fast needs a merge-base with origin/main or main and found none; run `git fetch origin main` or pass --base <ref>');
379
382
  }
380
- const files = gitOut(repoRoot, ['diff', '--name-only', '--diff-filter=ACMRT', '-z', sha]).split('\0').filter(Boolean).map(posixPath);
383
+ const files = gitOutputOf(gitDiff(['--name-only', '--diff-filter=ACMRT', '-z', sha], { dir: repoRoot, maxBuffer: 256 * 1024 * 1024 }), 'git diff').split('\0').filter(Boolean).map(posixPath);
381
384
  return { base: sha, files };
382
385
  }
383
386
 
@@ -388,7 +391,7 @@ function machineFindings(report) {
388
391
  }
389
392
 
390
393
  /**
391
- * The whole `hfs check` of one app: checkRepo() (the root and both sides: slots, pins, size, tree) and then the architecture machine
394
+ * The whole `starci app check` of one app: checkRepo() (the root and both sides: slots, pins, size, tree) and then the architecture machine
392
395
  * over each side folder (the side as the repository root it judges), its violations and errors merged in as findings with the
393
396
  * Vietnamese why of their codes and the side prefixed onto their paths. `fast` judges only what changed since the merge-base (`base`
394
397
  * names another ref): the per-path slot and pin checks on the changed paths, the machine on the owners of the changed source files
@@ -412,7 +415,7 @@ export function checkRepository({ repoRoot, root = skillRoot, fast = false, base
412
415
  found.push(...run.findings);
413
416
  }
414
417
  const why = readWhy(root, [...new Set(found.map((f) => f.code))]);
415
- const findings = [...slotResult.findings, ...withWhy(found, why)];
418
+ const findings = [...slotResult.findings, ...withWhy(judgedFindings(found, repo.edition ?? 'full', root), why)];
416
419
  const counts = summarize(findings);
417
420
  const ran = runs.filter((info) => info.status === 'ran');
418
421
  return {
@@ -451,7 +454,7 @@ function machineOver({ scope, manifest, machine, changed }) {
451
454
  // --------------------------------------------------------------------------------------------------- explain
452
455
 
453
456
  const TEST_KIND = {
454
- 'unit-beside': 'a <name>.service.spec.ts beside each <name>.service.ts in this slot (only services are unit-tested)',
457
+ 'unit-beside': 'a <name>.service.spec.ts beside each <name>.service.ts in this slot (only services are unit-tested; a webhook or realtime door has its own spec beside it)',
455
458
  e2e: 'an integration, e2e or contract spec covering the flow; no unit spec is required',
456
459
  none: 'no test is required for files in this slot',
457
460
  };