@starci/hfs 4.0.8 → 4.0.9

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 (667) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +81 -39
  3. package/emit/contracts.mjs +56 -9
  4. package/emit/db-types.mjs +169 -0
  5. package/emit/events.mjs +41 -0
  6. package/emit/operations-worker.mjs +1 -1
  7. package/emit/operations.mjs +2 -2
  8. package/emit/schema-worker.mjs +1 -1
  9. package/lint/bound-sys.cjs +50 -0
  10. package/lint/run.mjs +53 -19
  11. package/package.json +14 -9
  12. package/report/sonar.mjs +8 -8
  13. package/runtime/engine/config.mjs +494 -0
  14. package/runtime/engine/invalid-config.mjs +15 -0
  15. package/runtime/engine/orca-config.mjs +27 -0
  16. package/runtime/knowledge/hfs/canon-pins.yaml +160 -29
  17. package/runtime/knowledge/hfs/peer-integrations.yaml +2 -2
  18. package/runtime/knowledge/hfs/rules.yaml +2059 -0
  19. package/runtime/knowledge/hfs/slots.yaml +912 -120
  20. package/runtime/knowledge/patterns/be/api.yaml +369 -0
  21. package/runtime/knowledge/patterns/be/cli.yaml +297 -0
  22. package/runtime/knowledge/patterns/be/domain.yaml +113 -0
  23. package/runtime/knowledge/patterns/be/event-bus.yaml +285 -0
  24. package/runtime/knowledge/patterns/be/jobs.yaml +261 -0
  25. package/runtime/knowledge/patterns/be/projections.yaml +178 -0
  26. package/runtime/knowledge/patterns/be/queues.yaml +236 -0
  27. package/runtime/knowledge/patterns/be/reactors.yaml +140 -0
  28. package/runtime/knowledge/patterns/be/realtime.yaml +222 -0
  29. package/runtime/knowledge/patterns/be/saga.yaml +248 -0
  30. package/runtime/knowledge/patterns/be/webhooks.yaml +221 -0
  31. package/runtime/knowledge/patterns/fe/folder.yaml +131 -25
  32. package/runtime/knowledge/sonar-gate.yaml +52 -18
  33. package/runtime/modules/kernel/failure-codes.yaml +571 -51
  34. package/runtime/modules/models/registry.yaml +591 -0
  35. package/runtime/modules/models/runtimes.yaml +701 -0
  36. package/runtime/scripts/api/fs/forbidden-root.mjs +51 -0
  37. package/runtime/scripts/api/fs/is-link-like.mjs +25 -0
  38. package/runtime/scripts/api/fs/lib.mjs +10 -2
  39. package/runtime/scripts/api/fs/safe-remove.mjs +12 -132
  40. package/runtime/scripts/api/git/config-get.mjs +10 -0
  41. package/runtime/scripts/api/git/diff.mjs +5 -0
  42. package/runtime/scripts/api/git/lib.mjs +16 -26
  43. package/runtime/scripts/api/git/log.mjs +5 -0
  44. package/runtime/scripts/api/git/ls-files.mjs +6 -0
  45. package/runtime/scripts/api/git/ls-tree.mjs +5 -0
  46. package/runtime/scripts/api/git/merge-base.mjs +9 -0
  47. package/runtime/scripts/api/git/remote.mjs +5 -0
  48. package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
  49. package/runtime/scripts/api/git/show.mjs +6 -0
  50. package/runtime/scripts/api/sops/decrypt.mjs +9 -5
  51. package/runtime/scripts/api/sops/lib.mjs +35 -0
  52. package/runtime/scripts/api/sops/seal.mjs +18 -0
  53. package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
  54. package/runtime/scripts/hfs/architecture/backend.mjs +16 -23
  55. package/runtime/scripts/hfs/architecture/background-unowned.mjs +16 -34
  56. package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +3 -1
  57. package/runtime/scripts/hfs/architecture/clones.mjs +4 -4
  58. package/runtime/scripts/hfs/architecture/config.mjs +9 -6
  59. package/runtime/scripts/hfs/architecture/connection-map.mjs +20 -8
  60. package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
  61. package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
  62. package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
  63. package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
  64. package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
  65. package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +4 -10
  66. package/runtime/scripts/hfs/architecture/contracts.mjs +33 -162
  67. package/runtime/scripts/hfs/architecture/dead-exports.mjs +58 -29
  68. package/runtime/scripts/hfs/architecture/doc-language.mjs +1 -1
  69. package/runtime/scripts/hfs/architecture/entrypoint.mjs +2 -1
  70. package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +1 -1
  71. package/runtime/scripts/hfs/architecture/feature-shape.mjs +5 -2
  72. package/runtime/scripts/hfs/architecture/framework-pinned.mjs +1 -1
  73. package/runtime/scripts/hfs/architecture/frontend.mjs +17 -43
  74. package/runtime/scripts/hfs/architecture/hfs.mjs +24 -39
  75. package/runtime/scripts/hfs/architecture/i18n-keys.mjs +1 -1
  76. package/runtime/scripts/hfs/architecture/index.mjs +17 -4
  77. package/runtime/scripts/hfs/architecture/machine-ast.mjs +44 -11
  78. package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
  79. package/runtime/scripts/hfs/architecture/module-per-transport.mjs +30 -6
  80. package/runtime/scripts/hfs/architecture/next-data.mjs +22 -63
  81. package/runtime/scripts/hfs/architecture/owners.mjs +35 -15
  82. package/runtime/scripts/hfs/architecture/register-once.mjs +2 -1
  83. package/runtime/scripts/hfs/architecture/registration.mjs +23 -81
  84. package/runtime/scripts/hfs/architecture/required-files.mjs +20 -12
  85. package/runtime/scripts/hfs/architecture/schema-owner.mjs +17 -114
  86. package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
  87. package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
  88. package/runtime/scripts/hfs/architecture/source-names.mjs +27 -147
  89. package/runtime/scripts/hfs/architecture/sql-owner.mjs +59 -18
  90. package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
  91. package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
  92. package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
  93. package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
  94. package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
  95. package/runtime/scripts/hfs/architecture/surface.mjs +9 -3
  96. package/runtime/scripts/hfs/architecture/test-world-files.mjs +9 -19
  97. package/runtime/scripts/hfs/architecture/tiers.mjs +47 -5
  98. package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -3
  99. package/runtime/scripts/hfs/architecture/typescript.mjs +12 -26
  100. package/runtime/scripts/hfs/architecture.mjs +4 -4
  101. package/runtime/scripts/hfs/check.mjs +75 -72
  102. package/runtime/scripts/hfs/coverage-scope.mjs +162 -0
  103. package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
  104. package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
  105. package/runtime/scripts/hfs/edition-slots.mjs +66 -0
  106. package/runtime/scripts/hfs/manifest-shape.mjs +109 -32
  107. package/runtime/scripts/hfs/param-names.mjs +18 -0
  108. package/runtime/scripts/hfs/path-findings.mjs +1 -1
  109. package/runtime/scripts/hfs/repo-identity.mjs +9 -6
  110. package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
  111. package/runtime/scripts/hfs/rules/app-root.mjs +51 -0
  112. package/runtime/scripts/hfs/rules/cli.mjs +37 -0
  113. package/runtime/scripts/hfs/rules/contract-compat.mjs +71 -0
  114. package/runtime/scripts/hfs/rules/contract.mjs +10 -9
  115. package/runtime/scripts/hfs/rules/database-config.mjs +102 -0
  116. package/runtime/scripts/hfs/rules/database-constants.mjs +13 -0
  117. package/runtime/scripts/hfs/rules/database-migrations.mjs +111 -0
  118. package/runtime/scripts/hfs/rules/database-plpgsql.mjs +233 -0
  119. package/runtime/scripts/hfs/rules/database-sql.mjs +336 -0
  120. package/runtime/scripts/hfs/rules/database.mjs +68 -0
  121. package/runtime/scripts/hfs/rules/deps.mjs +1 -1
  122. package/runtime/scripts/hfs/rules/docker.mjs +259 -0
  123. package/runtime/scripts/hfs/rules/edition.mjs +111 -0
  124. package/runtime/scripts/hfs/rules/event-bus.mjs +153 -0
  125. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -1
  126. package/runtime/scripts/hfs/rules/fe-no-tests.mjs +6 -5
  127. package/runtime/scripts/hfs/rules/frontend-tree.mjs +9 -9
  128. package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -6
  129. package/runtime/scripts/hfs/rules/kinds.mjs +84 -0
  130. package/runtime/scripts/hfs/rules/lint-suppression.mjs +1 -1
  131. package/runtime/scripts/hfs/rules/monorepo.mjs +179 -0
  132. package/runtime/scripts/hfs/rules/peer-integrations.mjs +3 -3
  133. package/runtime/scripts/hfs/rules/pipeline.mjs +11 -21
  134. package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -2
  135. package/runtime/scripts/hfs/rules/read.mjs +1 -1
  136. package/runtime/scripts/hfs/rules/repo-local-checks.mjs +2 -2
  137. package/runtime/scripts/hfs/rules/saga.mjs +170 -0
  138. package/runtime/scripts/hfs/rules/secrets.mjs +3 -3
  139. package/runtime/scripts/hfs/rules/services.mjs +220 -0
  140. package/runtime/scripts/hfs/rules/spec-placement.mjs +1 -1
  141. package/runtime/scripts/hfs/rules/stacks.mjs +3 -3
  142. package/runtime/scripts/hfs/rules/supabase-secrets.mjs +89 -0
  143. package/runtime/scripts/hfs/rules/test-topology.mjs +2 -2
  144. package/runtime/scripts/hfs/secret.mjs +175 -0
  145. package/runtime/scripts/hfs/slots.mjs +78 -108
  146. package/runtime/scripts/hfs/sql/pg-parse.mjs +46 -0
  147. package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
  148. package/runtime/scripts/hfs/tree.mjs +5 -4
  149. package/runtime/scripts/hfs/typescript-programs.mjs +0 -5
  150. package/runtime/scripts/hfs/view.mjs +3 -2
  151. package/runtime/scripts/lib/dockerfile.mjs +124 -0
  152. package/runtime/scripts/lib/env.mjs +10 -0
  153. package/runtime/scripts/lib/event-contract.mjs +103 -0
  154. package/runtime/scripts/lib/git.mjs +36 -0
  155. package/runtime/scripts/lib/graphql-contract.mjs +1 -1
  156. package/runtime/scripts/lib/i18n.mjs +86 -0
  157. package/runtime/scripts/lib/json.mjs +13 -3
  158. package/runtime/scripts/lib/language.mjs +24 -5
  159. package/runtime/scripts/lib/list.mjs +20 -0
  160. package/runtime/scripts/lib/package-at.mjs +37 -0
  161. package/runtime/scripts/lib/path-key.mjs +57 -2
  162. package/runtime/scripts/lib/read-text.mjs +34 -0
  163. package/runtime/scripts/lib/regex.mjs +4 -0
  164. package/runtime/scripts/lib/same-text.mjs +5 -0
  165. package/runtime/scripts/lib/secret-patterns.mjs +4 -3
  166. package/runtime/scripts/lib/sleep-sync.mjs +2 -1
  167. package/runtime/scripts/lib/sops-envelope.mjs +58 -0
  168. package/runtime/scripts/lib/stack-services.mjs +7 -31
  169. package/runtime/scripts/lib/ts-ast.mjs +35 -0
  170. package/runtime/scripts/lib/walk.mjs +4 -3
  171. package/scaffold/add-app.mjs +174 -0
  172. package/scaffold/add-cli-lite.mjs +257 -0
  173. package/scaffold/add-inbox-lite.mjs +314 -0
  174. package/scaffold/add-table.mjs +344 -0
  175. package/scaffold/add.mjs +299 -0
  176. package/scaffold/app.mjs +358 -69
  177. package/scaffold/edition-gate.mjs +25 -0
  178. package/scaffold/image.mjs +19 -0
  179. package/scaffold/lite-exports.mjs +186 -0
  180. package/scaffold/service.mjs +32 -26
  181. package/scaffold/supabase-ports.mjs +26 -0
  182. package/src/main.mjs +327 -0
  183. package/sync/cli.mjs +6 -9
  184. package/sync/format.mjs +1 -1
  185. package/sync/hygiene.mjs +10 -10
  186. package/sync/index.mjs +167 -104
  187. package/sync/managed.mjs +19 -11
  188. package/sync/sonar-key.mjs +5 -0
  189. package/templates/app/ci-workflows/github/workflows/ci.yml +14 -14
  190. package/templates/app/ci-workflows/github/workflows/images.yml +37 -0
  191. package/templates/app/ci-workflows/sonar-steps.yml +9 -0
  192. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +66 -0
  193. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +31 -0
  194. package/templates/app/ci-workflows-lite/github/workflows/images.yml +37 -0
  195. package/templates/app/codegen-lite/scripts/codegen.mjs +32 -0
  196. package/templates/app/docker-ignore/dockerignore +50 -0
  197. package/templates/app/gitignore-lite +35 -0
  198. package/templates/app/hooks/husky/pre-commit +3 -8
  199. package/templates/app/hooks/husky/pre-push +45 -6
  200. package/templates/app/package-scripts/core.json +8 -0
  201. package/templates/app/package-scripts/package.json +3 -10
  202. package/templates/app/package-scripts-lite/package.json +15 -0
  203. package/templates/app/quality-config/codecov.yml +15 -3
  204. package/templates/app/quality-config/sonar-base.properties +4 -0
  205. package/templates/app/quality-config/sonar-project.properties +1 -4
  206. package/templates/app/quality-config-lite/sonar-project.properties +5 -0
  207. package/templates/app/skeleton/.starcistacks/dev/seeds/primary-notes.sql +5 -0
  208. package/templates/app/skeleton/.starciwork/features/system-health/index.yaml +4 -0
  209. package/templates/app/skeleton/.starciwork/{features/index.yaml → index.yaml} +2 -2
  210. package/templates/app/skeleton/README.md +7 -5
  211. package/templates/app/skeleton-lite/.sops.yaml +3 -0
  212. package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +5 -0
  213. package/templates/app/skeleton-lite/.starcistacks/dev/secrets/.gitkeep +1 -0
  214. package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +55 -0
  215. package/templates/app/skeleton-lite/README.md +40 -0
  216. package/templates/app/skeleton-lite/supabase/config.toml +41 -0
  217. package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +56 -0
  218. package/templates/app/skeleton-lite/supabase/seed.sql +0 -0
  219. package/templates/app/task-graph/turbo.json +23 -0
  220. package/templates/app/tool-config-lite/prettierignore +2 -0
  221. package/templates/app/tool-config-lite/prettierrc +1 -0
  222. package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +38 -0
  223. package/templates/app/upgrade-full/.starcistacks/dev/README.md +10 -0
  224. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +13 -0
  225. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +3 -0
  226. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +12 -0
  227. package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +7 -0
  228. package/templates/be/common/main-listen.ts.partial +14 -0
  229. package/templates/be/common/sql-ident.ts.partial +7 -0
  230. package/templates/be/common/sql-tag.ts.partial +5 -0
  231. package/templates/be/image/api/Dockerfile +38 -0
  232. package/templates/be/image/cli/Dockerfile +38 -0
  233. package/templates/be/image/worker/Dockerfile +36 -0
  234. package/templates/be/inbox/database-client.ts.tpl +50 -0
  235. package/templates/be/inbox/index.ts.tpl +2 -0
  236. package/templates/be/inbox/migration.sql.tpl +29 -0
  237. package/templates/be/inbox/module-definition.ts.tpl +6 -0
  238. package/templates/be/inbox/module.ts.tpl +14 -0
  239. package/templates/be/inbox/options.ts.tpl +2 -0
  240. package/templates/be/inbox/service.ts.tpl +33 -0
  241. package/templates/be/inbox/sql.ts.tpl +16 -0
  242. package/templates/be/inbox/webhook-door.ts.tpl +36 -0
  243. package/templates/be/patterns/api/application.command.http.ts.tpl +10 -0
  244. package/templates/be/patterns/api/application.command.ts.tpl +10 -0
  245. package/templates/be/patterns/api/application.contracts.ts.tpl +11 -0
  246. package/templates/be/patterns/api/application.handler.http.ts.tpl +22 -0
  247. package/templates/be/patterns/api/application.handler.ts.tpl +22 -0
  248. package/templates/be/patterns/api/feature.index.http.ts.tpl +1 -0
  249. package/templates/be/patterns/api/feature.index.ts.tpl +1 -0
  250. package/templates/be/patterns/api/feature.module.ts.tpl +6 -0
  251. package/templates/be/patterns/api/graphql.input.ts.tpl +13 -0
  252. package/templates/be/patterns/api/graphql.mapper.ts.tpl +9 -0
  253. package/templates/be/patterns/api/graphql.module.ts.tpl +7 -0
  254. package/templates/be/patterns/api/graphql.resolver.ts.tpl +27 -0
  255. package/templates/be/patterns/api/graphql.type.ts.tpl +9 -0
  256. package/templates/be/patterns/api/http.controller.ts.tpl +27 -0
  257. package/templates/be/patterns/api/http.mapper.ts.tpl +9 -0
  258. package/templates/be/patterns/api/http.module.ts.tpl +7 -0
  259. package/templates/be/patterns/api/http.request.ts.tpl +10 -0
  260. package/templates/be/patterns/api/http.response.ts.tpl +5 -0
  261. package/templates/be/patterns/cli/group.cli.spec.ts.tpl +15 -0
  262. package/templates/be/patterns/cli/group.cli.ts.tpl +11 -0
  263. package/templates/be/patterns/cli/group.module.ts.tpl +7 -0
  264. package/templates/be/patterns/cli/sub.run.cli.spec.ts.tpl +17 -0
  265. package/templates/be/patterns/cli/sub.run.cli.ts.tpl +15 -0
  266. package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +22 -0
  267. package/templates/be/patterns/event-bus/platform/event-bus.config.ts.tpl +19 -0
  268. package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +58 -0
  269. package/templates/be/patterns/event-bus/platform/event-bus.decorators.ts.tpl +46 -0
  270. package/templates/be/patterns/event-bus/platform/event-bus.log-events.ts.tpl +12 -0
  271. package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +10 -0
  272. package/templates/be/patterns/event-bus/platform/event-bus.module.ts.tpl +52 -0
  273. package/templates/be/patterns/event-bus/platform/event-bus.options.ts.tpl +19 -0
  274. package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +28 -0
  275. package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +165 -0
  276. package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +93 -0
  277. package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +90 -0
  278. package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +58 -0
  279. package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +136 -0
  280. package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +56 -0
  281. package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +272 -0
  282. package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +128 -0
  283. package/templates/be/patterns/event-bus/platform/event-transport.port.ts.tpl +180 -0
  284. package/templates/be/patterns/event-bus/platform/event.policy.spec.ts.tpl +67 -0
  285. package/templates/be/patterns/event-bus/platform/event.policy.ts.tpl +38 -0
  286. package/templates/be/patterns/event-bus/platform/index.ts.tpl +11 -0
  287. package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.spec.ts.tpl +348 -0
  288. package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.ts.tpl +241 -0
  289. package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +15 -0
  290. package/templates/be/patterns/event-bus/platform/persistence/connection.ts.tpl +8 -0
  291. package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +37 -0
  292. package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +11 -0
  293. package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +12 -0
  294. package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +26 -0
  295. package/templates/be/patterns/jobs/job.index.ts.tpl +1 -0
  296. package/templates/be/patterns/jobs/job.module.ts.tpl +6 -0
  297. package/templates/be/patterns/jobs/job.processor.ts.tpl +20 -0
  298. package/templates/be/patterns/jobs/job.queue.module.ts.tpl +20 -0
  299. package/templates/be/patterns/jobs/job.step.ts.tpl +19 -0
  300. package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +31 -0
  301. package/templates/be/patterns/jobs/platform/fenced.processor.ts.tpl +13 -0
  302. package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +150 -0
  303. package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +100 -0
  304. package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +138 -0
  305. package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +69 -0
  306. package/templates/be/patterns/jobs/platform/jobs.config.ts.tpl +11 -0
  307. package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +62 -0
  308. package/templates/be/patterns/jobs/platform/jobs.decorators.ts.tpl +31 -0
  309. package/templates/be/patterns/jobs/platform/jobs.error.ts.tpl +22 -0
  310. package/templates/be/patterns/jobs/platform/jobs.index.ts.tpl +11 -0
  311. package/templates/be/patterns/jobs/platform/jobs.log-events.ts.tpl +9 -0
  312. package/templates/be/patterns/jobs/platform/jobs.messages.ts.tpl +15 -0
  313. package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +10 -0
  314. package/templates/be/patterns/jobs/platform/jobs.module.ts.tpl +32 -0
  315. package/templates/be/patterns/jobs/platform/jobs.options.ts.tpl +11 -0
  316. package/templates/be/patterns/jobs/platform/jobs.port.ts.tpl +36 -0
  317. package/templates/be/patterns/jobs/platform/persistence.connection.ts.tpl +8 -0
  318. package/templates/be/patterns/jobs/platform/persistence.job.entity.ts.tpl +53 -0
  319. package/templates/be/patterns/jobs/platform/persistence.jobs.rows.ts.tpl +13 -0
  320. package/templates/be/patterns/jobs/platform/persistence.jobs.sql.ts.tpl +33 -0
  321. package/templates/be/patterns/jobs/platform/persistence.migration.ts.tpl +29 -0
  322. package/templates/be/patterns/outbox/platform/index.ts.tpl +2 -0
  323. package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +96 -0
  324. package/templates/be/patterns/outbox/platform/outbox-relay.policy.ts.tpl +78 -0
  325. package/templates/be/patterns/outbox/platform/outbox.log-events.ts.tpl +5 -0
  326. package/templates/be/patterns/projections/migration.ts.tpl +18 -0
  327. package/templates/be/patterns/projections/persistence.connection.ts.tpl +8 -0
  328. package/templates/be/patterns/projections/projection.entity.ts.tpl +9 -0
  329. package/templates/be/patterns/projections/projection.index.ts.tpl +3 -0
  330. package/templates/be/patterns/projections/projection.module-definition.ts.tpl +7 -0
  331. package/templates/be/patterns/projections/projection.module.ts.tpl +18 -0
  332. package/templates/be/patterns/projections/projection.options.ts.tpl +2 -0
  333. package/templates/be/patterns/projections/projection.projection.spec.ts.tpl +55 -0
  334. package/templates/be/patterns/projections/projection.projection.ts.tpl +21 -0
  335. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +142 -0
  336. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +81 -0
  337. package/templates/be/patterns/queues/platform/persistence.connection.ts.tpl +8 -0
  338. package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +25 -0
  339. package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +25 -0
  340. package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +9 -0
  341. package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +12 -0
  342. package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +48 -0
  343. package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +17 -0
  344. package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +128 -0
  345. package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +48 -0
  346. package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +115 -0
  347. package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +91 -0
  348. package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +45 -0
  349. package/templates/be/patterns/queues/platform/queue.config.ts.tpl +15 -0
  350. package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +31 -0
  351. package/templates/be/patterns/queues/platform/queue.decorators.ts.tpl +45 -0
  352. package/templates/be/patterns/queues/platform/queue.index.ts.tpl +7 -0
  353. package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +5 -0
  354. package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +10 -0
  355. package/templates/be/patterns/queues/platform/queue.module.ts.tpl +62 -0
  356. package/templates/be/patterns/queues/platform/queue.options.ts.tpl +22 -0
  357. package/templates/be/patterns/queues/platform/queue.policy.spec.ts.tpl +19 -0
  358. package/templates/be/patterns/queues/platform/queue.policy.ts.tpl +11 -0
  359. package/templates/be/patterns/queues/platform/queue.port.ts.tpl +14 -0
  360. package/templates/be/patterns/queues/queue.index.ts.tpl +3 -0
  361. package/templates/be/patterns/queues/queue.module.ts.tpl +6 -0
  362. package/templates/be/patterns/queues/queue.queue.ts.tpl +23 -0
  363. package/templates/be/patterns/reactors/application.command.ts.tpl +10 -0
  364. package/templates/be/patterns/reactors/application.contracts.ts.tpl +12 -0
  365. package/templates/be/patterns/reactors/application.handler.ts.tpl +22 -0
  366. package/templates/be/patterns/reactors/consumer.ts.tpl +19 -0
  367. package/templates/be/patterns/reactors/message.module.ts.tpl +20 -0
  368. package/templates/be/patterns/reactors/reactor.index.ts.tpl +1 -0
  369. package/templates/be/patterns/reactors/reactor.module.ts.tpl +6 -0
  370. package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +6 -0
  371. package/templates/be/patterns/realtime/channel.index.ts.tpl +1 -0
  372. package/templates/be/patterns/realtime/channel.input.ts.tpl +12 -0
  373. package/templates/be/patterns/realtime/channel.subscription.spec.ts.tpl +51 -0
  374. package/templates/be/patterns/realtime/channel.subscription.ts.tpl +32 -0
  375. package/templates/be/patterns/realtime/channel.type.ts.tpl +9 -0
  376. package/templates/be/patterns/saga/saga.compensate.command.ts.tpl +11 -0
  377. package/templates/be/patterns/saga/saga.compensate.contracts.ts.tpl +7 -0
  378. package/templates/be/patterns/saga/saga.compensate.handler.ts.tpl +22 -0
  379. package/templates/be/patterns/saga/saga.compensation.ts.tpl +21 -0
  380. package/templates/be/patterns/saga/saga.complete.command.ts.tpl +11 -0
  381. package/templates/be/patterns/saga/saga.complete.contracts.ts.tpl +7 -0
  382. package/templates/be/patterns/saga/saga.complete.handler.ts.tpl +22 -0
  383. package/templates/be/patterns/saga/saga.done.consumer.ts.tpl +21 -0
  384. package/templates/be/patterns/saga/saga.failed.consumer.ts.tpl +21 -0
  385. package/templates/be/patterns/saga/saga.index.ts.tpl +1 -0
  386. package/templates/be/patterns/saga/saga.message.module.ts.tpl +23 -0
  387. package/templates/be/patterns/saga/saga.module.ts.tpl +20 -0
  388. package/templates/be/patterns/saga/saga.service.spec.ts.tpl +70 -0
  389. package/templates/be/patterns/saga/saga.service.ts.tpl +44 -0
  390. package/templates/be/patterns/saga/saga.state.ts.tpl +14 -0
  391. package/templates/be/patterns/saga/saga.step.ts.tpl +11 -0
  392. package/templates/be/patterns/saga/saga.undo.command.ts.tpl +10 -0
  393. package/templates/be/patterns/saga/saga.undo.contracts.ts.tpl +5 -0
  394. package/templates/be/patterns/saga/saga.undo.handler.ts.tpl +21 -0
  395. package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +72 -0
  396. package/templates/be/patterns/webhooks/webhook.door.ts.tpl +36 -0
  397. package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +6 -0
  398. package/templates/be/patterns/webhooks/webhook.index.ts.tpl +1 -0
  399. package/templates/be/patterns/webhooks/webhook.request.ts.tpl +9 -0
  400. package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +3 -0
  401. package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -2
  402. package/templates/be/skeleton/apps/__app__/src/main.ts +7 -15
  403. package/templates/be/skeleton/apps/cli/src/app.module.ts +30 -0
  404. package/templates/be/skeleton/apps/cli/src/cli.options.ts +22 -0
  405. package/templates/be/skeleton/apps/cli/src/main.ts +24 -0
  406. package/templates/be/skeleton/src/features/cli/cli.module.ts +7 -0
  407. package/templates/be/skeleton/src/features/cli/index.ts +1 -0
  408. package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.spec.ts +17 -0
  409. package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.ts +15 -0
  410. package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +7 -0
  411. package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.spec.ts +17 -0
  412. package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.ts +18 -0
  413. package/templates/be/skeleton/src/features/cli/seed/seed.cli.spec.ts +17 -0
  414. package/templates/be/skeleton/src/features/cli/seed/seed.cli.ts +15 -0
  415. package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +7 -0
  416. package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +33 -0
  417. package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.ts +34 -0
  418. package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +13 -0
  419. package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +40 -0
  420. package/templates/be/skeleton/src/modules/domain/identity/messages/identity.messages.ts +1 -1
  421. package/templates/be/skeleton/src/modules/domain/note/errors/note.error.ts +16 -0
  422. package/templates/be/skeleton/src/modules/domain/note/index.ts +3 -0
  423. package/templates/be/skeleton/src/modules/domain/note/note.contracts.ts +19 -0
  424. package/templates/be/skeleton/src/modules/domain/note/note.decorators.ts +9 -0
  425. package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +7 -0
  426. package/templates/be/skeleton/src/modules/domain/note/note.module.ts +19 -0
  427. package/templates/be/skeleton/src/modules/domain/note/note.options.ts +2 -0
  428. package/templates/be/skeleton/src/modules/domain/note/note.service.spec.ts +76 -0
  429. package/templates/be/skeleton/src/modules/domain/note/note.service.ts +37 -0
  430. package/templates/be/skeleton/src/modules/domain/note/persistence/connection.ts +8 -0
  431. package/templates/be/skeleton/src/modules/domain/note/persistence/entities/note.entity.ts +17 -0
  432. package/templates/be/skeleton/src/modules/domain/note/persistence/migrations/1790000000000-init-note.ts +22 -0
  433. package/templates/be/skeleton/src/modules/domain/note/persistence/note.rows.ts +17 -0
  434. package/templates/be/skeleton/src/modules/domain/note/persistence/note.sql.ts +4 -0
  435. package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +20 -0
  436. package/templates/be/skeleton/src/modules/platform/config/index.ts +1 -1
  437. package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +18 -0
  438. package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +41 -0
  439. package/templates/be/skeleton/src/modules/platform/database/connection-source.client.ts +17 -0
  440. package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +13 -0
  441. package/templates/be/skeleton/src/modules/platform/database/database.module.ts +77 -0
  442. package/templates/be/skeleton/src/modules/platform/database/database.options.ts +30 -0
  443. package/templates/be/skeleton/src/modules/platform/database/database.port.ts +65 -0
  444. package/templates/be/skeleton/src/modules/platform/database/database.sql.ts +47 -0
  445. package/templates/be/skeleton/src/modules/platform/database/errors/database.error.ts +16 -0
  446. package/templates/be/skeleton/src/modules/platform/database/index.ts +9 -0
  447. package/templates/be/skeleton/src/modules/platform/database/migrate-connections.client.ts +30 -0
  448. package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.spec.ts +84 -0
  449. package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.ts +23 -0
  450. package/templates/be/skeleton/src/modules/platform/database/primary.config.ts +9 -0
  451. package/templates/be/skeleton/src/modules/platform/database/primary.connection.ts +2 -0
  452. package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +10 -0
  453. package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +108 -0
  454. package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.ts +75 -0
  455. package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.spec.ts +88 -0
  456. package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.ts +29 -0
  457. package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +48 -0
  458. package/templates/be/skeleton/src/modules/platform/errors/messages/errors.messages.ts +1 -1
  459. package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +12 -0
  460. package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -0
  461. package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +8 -1
  462. package/templates/be/skeleton/src/modules/platform/http-security/http-security.decorators.ts +8 -0
  463. package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +14 -1
  464. package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +12 -0
  465. package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +10 -2
  466. package/templates/be/skeleton/src/modules/platform/http-security/origin.guard.spec.ts +63 -0
  467. package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +108 -0
  468. package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.spec.ts +39 -0
  469. package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.ts +25 -0
  470. package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +172 -0
  471. package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.ts +66 -0
  472. package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +3 -1
  473. package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +52 -0
  474. package/templates/be/skeleton-lite/apps/api/Dockerfile +37 -0
  475. package/templates/be/skeleton-lite/apps/api/src/api.options.ts +16 -0
  476. package/templates/be/skeleton-lite/apps/api/src/app.module.ts +81 -0
  477. package/templates/be/skeleton-lite/apps/api/src/main.ts +34 -0
  478. package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +14 -0
  479. package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +50 -0
  480. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +26 -0
  481. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +19 -0
  482. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +26 -0
  483. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +7 -0
  484. package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +6 -0
  485. package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +19 -0
  486. package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +10 -0
  487. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +24 -0
  488. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +8 -0
  489. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +17 -0
  490. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +32 -0
  491. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +24 -0
  492. package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +4 -0
  493. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +54 -0
  494. package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +23 -0
  495. package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +10 -0
  496. package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +49 -0
  497. package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +4 -0
  498. package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +21 -0
  499. package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +11 -0
  500. package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +28 -0
  501. package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +25 -0
  502. package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +9 -0
  503. package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +4 -0
  504. package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +5 -0
  505. package/templates/be/table/error.ts.tpl +16 -0
  506. package/templates/be/table/index.ts.tpl +2 -0
  507. package/templates/be/table/migration.sql.tpl +51 -0
  508. package/templates/be/table/module-definition.ts.tpl +7 -0
  509. package/templates/be/table/module.ts.tpl +14 -0
  510. package/templates/be/table/options.ts.tpl +2 -0
  511. package/templates/be/table/rows.ts.tpl +4 -0
  512. package/templates/be/table/service.ts.tpl +23 -0
  513. package/templates/be/table/sql.ts.tpl +4 -0
  514. package/templates/be/tool-config/jest.config.js +3 -1
  515. package/templates/be/upgrade-full/apps/cli/src/app.module.ts +14 -0
  516. package/templates/be/upgrade-full/apps/cli/src/main.ts +26 -0
  517. package/templates/be/upgrade-full/src/features/cli/cli.module.ts +6 -0
  518. package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +23 -0
  519. package/templates/common/gitignore.base +1 -2
  520. package/templates/fe/app/package.json.tpl +1 -0
  521. package/templates/fe/app/tsconfig.json +12 -0
  522. package/templates/fe/common/app-layout.tsx.partial +8 -0
  523. package/templates/fe/common/site-shell.tsx.partial +9 -0
  524. package/templates/fe/image/next/Dockerfile +42 -0
  525. package/templates/fe/skeleton/apps/app/next.config.ts +23 -0
  526. package/templates/fe/skeleton/apps/app/postcss.config.mjs +7 -0
  527. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/error.tsx +2 -2
  528. package/templates/fe/skeleton/apps/app/src/app/[locale]/layout.tsx +22 -0
  529. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/loading.tsx +2 -2
  530. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/not-found.tsx +2 -2
  531. package/templates/fe/skeleton/apps/app/src/app/[locale]/page.tsx +9 -0
  532. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/global-error.tsx +2 -2
  533. package/templates/fe/skeleton/apps/app/src/app/globals.css +10 -0
  534. package/templates/fe/skeleton/apps/app/src/features/layouts/AppLayout/index.tsx +18 -0
  535. package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/component.tsx +19 -0
  536. package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/index.tsx +11 -0
  537. package/templates/fe/skeleton/apps/app/src/features/pages/AppGlobalErrorPage/index.tsx +16 -0
  538. package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/component.tsx +10 -0
  539. package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +15 -0
  540. package/templates/fe/skeleton/apps/app/src/features/pages/AppLoadingPage/index.tsx +8 -0
  541. package/templates/fe/skeleton/apps/app/src/features/pages/AppNotFoundPage/index.tsx +9 -0
  542. package/templates/fe/skeleton/apps/app/src/modules/i18n/index.ts +4 -0
  543. package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +28 -0
  544. package/templates/fe/skeleton/apps/app/src/modules/i18n/request.ts +4 -0
  545. package/templates/fe/skeleton/apps/app/src/modules/routes/index.ts +4 -0
  546. package/templates/fe/skeleton/apps/app/src/proxy.ts +1 -0
  547. package/templates/fe/skeleton/apps/{__app__ → landing}/next.config.ts +4 -2
  548. package/templates/fe/skeleton/apps/landing/postcss.config.mjs +7 -0
  549. package/templates/fe/skeleton/apps/landing/src/app/[locale]/error.tsx +10 -0
  550. package/templates/fe/skeleton/apps/landing/src/app/[locale]/layout.tsx +22 -0
  551. package/templates/fe/skeleton/apps/landing/src/app/[locale]/loading.tsx +6 -0
  552. package/templates/fe/skeleton/apps/landing/src/app/[locale]/not-found.tsx +6 -0
  553. package/templates/fe/skeleton/apps/landing/src/app/[locale]/page.tsx +9 -0
  554. package/templates/fe/skeleton/apps/landing/src/app/global-error.tsx +10 -0
  555. package/templates/fe/skeleton/apps/landing/src/app/globals.css +10 -0
  556. package/templates/fe/skeleton/apps/landing/src/features/layouts/LandingLayout/index.tsx +24 -0
  557. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/component.tsx +18 -0
  558. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/index.tsx +11 -0
  559. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingGlobalErrorPage/index.tsx +16 -0
  560. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingLoadingPage/index.tsx +8 -0
  561. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingNotFoundPage/index.tsx +9 -0
  562. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/component.tsx +24 -0
  563. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/index.tsx +16 -0
  564. package/templates/fe/skeleton/apps/landing/src/modules/config/index.ts +12 -0
  565. package/templates/fe/skeleton/apps/landing/src/modules/i18n/index.ts +7 -0
  566. package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/vi.json +31 -0
  567. package/templates/fe/skeleton/apps/landing/src/modules/i18n/request.ts +4 -0
  568. package/templates/fe/skeleton/apps/landing/src/modules/routes/index.ts +4 -0
  569. package/templates/fe/skeleton/apps/landing/src/proxy.ts +1 -0
  570. package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +49 -0
  571. package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +24 -0
  572. package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +20 -0
  573. package/templates/fe/skeleton/packages/__project__-ui/src/branches/Providers/index.tsx +23 -0
  574. package/templates/fe/skeleton/packages/__project__-ui/src/composites/ErrorNotice/index.tsx +14 -0
  575. package/templates/fe/skeleton/packages/__project__-ui/src/composites/GlobalErrorNotice/index.tsx +25 -0
  576. package/templates/fe/skeleton/packages/__project__-ui/src/composites/LoadingNotice/index.tsx +9 -0
  577. package/templates/fe/skeleton/packages/__project__-ui/src/composites/LocaleShell/index.tsx +21 -0
  578. package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +19 -0
  579. package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/classNames.ts +4 -0
  580. package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/index.tsx +19 -0
  581. package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +6 -0
  582. package/templates/fe/skeleton-lite/apps/web/next.config.ts +22 -0
  583. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/error.tsx +10 -0
  584. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +37 -0
  585. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/loading.tsx +6 -0
  586. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/not-found.tsx +6 -0
  587. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/page.tsx +9 -0
  588. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/providers.tsx +26 -0
  589. package/templates/fe/skeleton-lite/apps/web/src/app/auth/callback/route.ts +24 -0
  590. package/templates/fe/skeleton-lite/apps/web/src/app/global-error.tsx +10 -0
  591. package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/src/app/globals.css +1 -1
  592. package/templates/fe/skeleton-lite/apps/web/src/app/health/live/route.ts +5 -0
  593. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/component.tsx +29 -0
  594. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/index.tsx +41 -0
  595. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/component.tsx +17 -0
  596. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/index.tsx +38 -0
  597. package/templates/fe/skeleton-lite/apps/web/src/components/composites/ErrorNotice/index.tsx +13 -0
  598. package/templates/fe/skeleton-lite/apps/web/src/components/composites/GlobalErrorNotice/index.tsx +24 -0
  599. package/templates/fe/skeleton-lite/apps/web/src/components/composites/LoadingNotice/index.tsx +7 -0
  600. package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +18 -0
  601. package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/classNames.ts +4 -0
  602. package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/index.tsx +13 -0
  603. package/templates/fe/skeleton-lite/apps/web/src/features/layouts/AppLayout/index.tsx +31 -0
  604. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/component.tsx +12 -0
  605. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/index.tsx +10 -0
  606. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppGlobalErrorPage/index.tsx +15 -0
  607. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +14 -0
  608. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +30 -0
  609. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppLoadingPage/index.tsx +8 -0
  610. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppNotFoundPage/index.tsx +9 -0
  611. package/templates/fe/skeleton-lite/apps/web/src/modules/brand/brand.css +20 -0
  612. package/templates/fe/skeleton-lite/apps/web/src/modules/brand/index.ts +2 -0
  613. package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +20 -0
  614. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/read-session.ts +25 -0
  615. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-in.ts +25 -0
  616. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-out.ts +17 -0
  617. package/templates/fe/skeleton-lite/apps/web/src/modules/db/browser.ts +14 -0
  618. package/templates/fe/skeleton-lite/apps/web/src/modules/db/index.ts +3 -0
  619. package/templates/fe/skeleton-lite/apps/web/src/modules/db/outcome.ts +59 -0
  620. package/templates/fe/skeleton-lite/apps/web/src/modules/db/principal.ts +29 -0
  621. package/templates/fe/skeleton-lite/apps/web/src/modules/db/server.ts +70 -0
  622. package/templates/fe/skeleton-lite/apps/web/src/modules/db/validation/validation.mapper.ts +50 -0
  623. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +8 -0
  624. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +48 -0
  625. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +16 -0
  626. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +14 -0
  627. package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +7 -0
  628. package/templates/fe/skeleton-lite/apps/web/src/modules/routes/safe-next-path.ts +26 -0
  629. package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +43 -0
  630. package/templates/fe/table/read.ts.tpl +16 -0
  631. package/templates/fe/table/write.ts.tpl +16 -0
  632. package/upgrade/check.mjs +137 -0
  633. package/upgrade/index.mjs +524 -0
  634. package/bin/hfs.mjs +0 -233
  635. package/runtime/scripts/api/fs/rmdir-link.mjs +0 -12
  636. package/runtime/scripts/lib/test-secrets.mjs +0 -116
  637. package/templates/fe/skeleton/apps/__app__/src/app/[locale]/layout.tsx +0 -20
  638. package/templates/fe/skeleton/apps/__app__/src/app/[locale]/page.tsx +0 -9
  639. package/templates/fe/skeleton/apps/__app__/src/components/composites/FailureScreen/index.tsx +0 -28
  640. package/templates/fe/skeleton/apps/__app__/src/features/layouts/LocaleShell/index.tsx +0 -35
  641. package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/component.tsx +0 -19
  642. package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/index.tsx +0 -11
  643. package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/component.tsx +0 -24
  644. package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/index.tsx +0 -14
  645. package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/component.tsx +0 -21
  646. package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/index.tsx +0 -15
  647. package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/component.tsx +0 -23
  648. package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/index.tsx +0 -8
  649. package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/component.tsx +0 -28
  650. package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/index.tsx +0 -8
  651. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/config.ts +0 -8
  652. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/index.ts +0 -2
  653. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/messages/vi.json +0 -25
  654. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/request.ts +0 -19
  655. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/routing.ts +0 -9
  656. package/templates/fe/skeleton/apps/__app__/src/modules/routes/index.ts +0 -4
  657. package/templates/fe/skeleton/apps/__app__/src/proxy.ts +0 -10
  658. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.contracts.ts +0 -0
  659. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.handler.ts +0 -0
  660. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.query.ts +0 -0
  661. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/index.ts +0 -0
  662. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/system-health.module.ts +0 -0
  663. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/live.controller.ts +0 -0
  664. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/system-health-http.module.ts +0 -0
  665. /package/templates/fe/skeleton/apps/{__app__ → app}/src/app/health/live/route.ts +0 -0
  666. /package/templates/fe/skeleton/apps/{__app__ → app}/src/modules/config/index.ts +0 -0
  667. /package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/postcss.config.mjs +0 -0
@@ -0,0 +1,221 @@
1
+ schema: starci/knowledge-source@1
2
+ id: be.feature.webhooks
3
+ title: Provider webhooks
4
+ purpose: |-
5
+ Given a delivery a payment, identity or shipping provider POSTs to us, how is it received? A webhook is a feature KIND:
6
+ `be/src/features/webhooks/<provider>/` holds one signed door that proves the delivery came from the provider (signature and
7
+ replay window), then hands it to exactly ONE domain intake method. That method records the delivery (deduplicated through the
8
+ inbox) and publishes the domain event with `eventBus.publish(event, tx)` inside its own transaction, because publishing is
9
+ allowed only from `modules/domain`. The door writes nothing and decides nothing; everything after the proof is an event.
10
+ appliesTo:
11
+ - backend
12
+ family: be
13
+ provenance:
14
+ reviewedAt: 2026-10-02
15
+ sources:
16
+ - knowledge/hfs/README.md
17
+ - knowledge/hfs/slots.yaml
18
+ - knowledge/hfs/rules.yaml
19
+ - knowledge/patterns/be/api-auth.yaml
20
+ - knowledge/patterns/be/idempotency.yaml
21
+ - owner decision 2026-10-02 (feature kinds: webhooks, realtime, reactors, saga, jobs, cli; no kind imports another)
22
+ limitations: |-
23
+ Static checks prove the door's shape, that the proof is its first statement and that the only thing it can call after it is
24
+ one domain service method. They do not prove the HMAC scheme matches the provider's documentation, that the replay window
25
+ is the right length or that the intake is idempotent; the provider fake of the test world and the three
26
+ `webhooks/*` scenarios prove those against the real stack.
27
+ rules:
28
+ - id: BE-WEBHOOK-1
29
+ title: A webhook is a kind folder with one door, its module and its own spec
30
+ kind: mandatory
31
+ hfsRules: [R01, R02, R47]
32
+ requirement: |-
33
+ A provider webhook lives in `be/src/features/webhooks/<provider>/` (slot `be.feature.webhooks`), enabled by declaring the pattern
34
+ `webhooks` in `hfs.json` `sides.be.patterns`. The folder holds `index.ts` (the module class an app composes), `transport/http/<provider>-http.module.ts`, `transport/http/<provider>.webhook.ts` (the
35
+ door), `<provider>.webhook.spec.ts` (its spec — the kind's door has no service of its own, so the door carries it) and an optional `transport/http/dto/` of typed
36
+ payload classes (`<event>.request.ts`). Nothing else exists there: no application layer, no handler, no consumer. The kind
37
+ imports only `modules/*`, never another kind, and only an api-kind app composes `<provider>-http.module.ts`.
38
+ rationale: |-
39
+ A webhook is an external caller we do not control, so its door is kept apart from the api features a client uses. One place
40
+ and one shape let a reader find every public signed door and its proof in one folder.
41
+ cases:
42
+ - id: case-1
43
+ when: A new provider (a payment gateway)
44
+ write: 'features/webhooks/payment-gateway/ with index.ts, transport/http/payment-gateway-http.module.ts, transport/http/payment-gateway.webhook.ts, transport/http/payment-gateway.webhook.spec.ts and transport/http/dto/payment-notification.request.ts.'
45
+ verification:
46
+ automated:
47
+ - HFS_SLOT_UNDECLARED
48
+ - HFS_SLOT_AMBIGUOUS
49
+ - HFS_SLOT_NOT_ENABLED
50
+ - HFS_FORBIDDEN_PRESENT
51
+ - HFS_TRACKED_MUST_BE_IGNORED
52
+ - HFS_ROOT_ENTRY_FORBIDDEN
53
+ - HFS_ROOT_MARKDOWN_FORBIDDEN
54
+ - HFS_ROOT_SRC_FORBIDDEN_FE
55
+ - HFS_SRC_LAYOUT_INVALID
56
+ - HFS_MODULE_TIER_INVALID
57
+ - HFS_WORK_IN_FE
58
+ - HFS_STACKS_IN_SIDE
59
+ - HFS_SLOT_REQUIRED_MISSING
60
+ - HFS_MIN_INSTANCES
61
+ - HFS_REQUIRED_FILE_MISSING
62
+ - HFS_ROOT_ENTRY_MISSING
63
+ - HFS_APPS_REQUIRED
64
+ - HFS_APP_LAYOUT_INVALID
65
+ - HFS_README_TITLE_INVALID
66
+ - HFS_README_DESCRIPTION_INVALID
67
+ - HFS_README_SECTION_MISSING
68
+ - HFS_README_SECTION_ORDER
69
+ - HFS_README_DEVELOPMENT_INCOMPLETE
70
+ - HFS_README_WORK_POINTER_MISSING
71
+ - HFS_README_PRIVATE_URL
72
+ - HFS_README_BADGE_NOT_LIVE
73
+ - BE_TEST_TOPOLOGY
74
+ - BE_CONTRACT_UNGUARDED
75
+ manual:
76
+ - Confirm the provider endpoint is one door and that a second endpoint of the same provider is a second door only when it has a different proof.
77
+ relatedExamples: [webhooks]
78
+ - id: BE-WEBHOOK-2
79
+ title: The door verifies first, then makes one domain call
80
+ kind: mandatory
81
+ hfsRules: [R182, R183, R41, R42, R203]
82
+ requirement: |-
83
+ `<provider>.webhook.ts` is one `@Controller` with one `@Post` handler declared
84
+ `@Public({ reason: PublicReason.SignedWebhook })`, thin (R203 `BE_FEATURE_THIN`). The handler's FIRST statement is the unconditional
85
+ `this.<signature>.verify({ provider, rawBody, signature, timestamp })` of the `WebhookSignatureService` of `platform/http-security`
86
+ (HMAC-SHA256 over `<timestamp>.<raw body>` with the provider's secret, a constant-time comparison and a replay window on the signed timestamp; it throws before anything else runs). The provider key and its secret and tolerance are options of `platform/http-security` (`options.webhooks[provider]`). The
87
+ second and last call is one method of a domain service, the intake. The door injects only that service and the signature
88
+ service (injected with `@InjectWebhookSignature()`), holds no branch, loop or `try`, calls nothing else (no parsing, mapping or publishing) and returns nothing: the
89
+ provider gets its status code and an empty body. `@RateLimit(RateTier.Strict)` is required by the signed-webhook reason.
90
+ rationale: |-
91
+ The signature is the authentication of a public door. Making the proof the first statement removes every path to the intake
92
+ that skips it, and a door with one call and no decision has nothing left to test except the proof and the hand-over.
93
+ cases:
94
+ - id: case-1
95
+ when: The door of a payment gateway
96
+ write: |-
97
+ @Controller("webhooks/payment-gateway")
98
+ export class PaymentGatewayWebhook {
99
+ constructor(
100
+ @InjectWebhookSignature() private readonly signature: WebhookSignatureService,
101
+ private readonly payments: PaymentService,
102
+ ) {}
103
+
104
+ @Post()
105
+ @HttpCode(HttpStatus.NO_CONTENT)
106
+ @Public({ reason: PublicReason.SignedWebhook })
107
+ @RateLimit(RateTier.Strict)
108
+ async receive(@Req() request: RawBodyRequest<Request>, @Headers("x-signature") signature: string | undefined, @Headers("x-timestamp") timestamp: string | undefined, @Body() body: PaymentNotificationRequest): Promise<void> {
109
+ this.signature.verify({ provider: "payment-gateway", rawBody: request.rawBody, signature, timestamp })
110
+ await this.payments.acceptNotification(body)
111
+ }
112
+ }
113
+ - id: case-2
114
+ when: A delivery whose raw body must be hashed
115
+ write: 'enable the raw body for the app (`NestFactory.create(..., { rawBody: true })` in the api app) and read `request.rawBody`; never hash a re-serialized `body`.'
116
+ verification:
117
+ automated:
118
+ - BE_WEBHOOK_SHAPE
119
+ - BE_WEBHOOK_UNVERIFIED
120
+ - BE_DEFAULT_DENY
121
+ - BE_INPUT_BOUNDED
122
+ - BE_FEATURE_THIN
123
+ manual:
124
+ - Review that the raw body, not a re-serialized one, is verified, and that the replay window matches the provider's tolerance.
125
+ relatedExamples: [webhooks]
126
+ - id: BE-WEBHOOK-3
127
+ title: The intake publishes the event inside its own transaction
128
+ kind: mandatory
129
+ hfsRules: [R80, R152, R151]
130
+ requirement: |-
131
+ The domain intake method (`PaymentService.acceptNotification`) is the delivery method of R80: its first awaited expression
132
+ claims `(source, eventId)` in the `Inbox` and it returns when the claim answers false, so a redelivery is a no-op. It then
133
+ records the delivery and calls `this.eventBus.publish(PaymentConfirmedEvent.create({...}), manager)` inside the same
134
+ transaction (`entityManager.transaction`). The events are typed classes in `modules/events/<service>/<event>.event.ts` that
135
+ equal their `be/contracts/<service>/events.json` entry (`payment.confirmed`, `payment.failed`). The webhook door never
136
+ imports `modules/events` or the event bus.
137
+ rationale: |-
138
+ Recording the delivery and writing the outbox row in one transaction means a crash cannot lose or duplicate the event, and
139
+ keeping the publish in `modules/domain` keeps one place that owns the transaction boundary.
140
+ cases:
141
+ - id: case-1
142
+ when: A confirmed payment arrives
143
+ write: 'acceptNotification claims the inbox row, updates the payment row and publishes PaymentConfirmedEvent in one transaction; a second delivery of the same eventId changes nothing.'
144
+ verification:
145
+ automated:
146
+ - BE_INBOX_DEDUPE_MISSING
147
+ - BE_OUTBOX_WRITE_TX
148
+ - BE_EVENT_CLASS_CONTRACT
149
+ manual:
150
+ - Confirm each provider event kind maps to exactly one published event and that an unknown kind is acknowledged and ignored, not published.
151
+ relatedExamples: [webhooks]
152
+ - id: BE-WEBHOOK-4
153
+ title: Three behaviours are proven on the test world
154
+ kind: mandatory
155
+ hfsRules: [R155]
156
+ requirement: |-
157
+ Declaring the pattern `webhooks` requires e2e or integration tests titled `webhooks/<scenario>: ...` for each scenario
158
+ `bad-signature-is-refused` (a tampered body is refused and nothing is published), `replay-is-refused` (a stale timestamp is
159
+ refused and nothing is published) and `accepted-delivery-publishes-once` (a valid delivery publishes the event once and a
160
+ redelivery publishes nothing more). The provider is the network-edge fake of the test world (`world.fake.<provider>`), which
161
+ signs with the test secret; a real provider is never called. The unit spec `<provider>.webhook.spec.ts` covers the door
162
+ itself with the Nest testing module, a real `WebhookSignatureService` configured with a test secret and a double of the
163
+ domain service.
164
+ rationale: |-
165
+ The door has no logic of its own, so the risk is in the wiring: the raw body, the headers, the real signature scheme and the
166
+ transaction behind the intake. Only a signed request through the real app proves it.
167
+ cases:
168
+ - id: case-1
169
+ when: The e2e of the payment gateway
170
+ write: 'e2e/payment/payment-gateway-webhook.e2e-spec.ts has `it("webhooks/bad-signature-is-refused: ...")`, `it("webhooks/replay-is-refused: ...")` and `it("webhooks/accepted-delivery-publishes-once: ...")`.'
171
+ verification:
172
+ automated:
173
+ - BE_PATTERN_SPEC_MISSING
174
+ manual:
175
+ - Confirm the fake signs exactly as the provider documents and that a contract spec guards its payload fixtures.
176
+ relatedExamples: [webhooks]
177
+ files:
178
+ - path: src/features/webhooks/<provider>/index.ts
179
+ slot: be.feature.webhooks
180
+ template: webhooks/webhook.index.ts.tpl
181
+ role: The public surface of the kind folder, the module class an api-kind app composes.
182
+ - path: src/features/webhooks/<provider>/transport/http/<provider>-http.module.ts
183
+ slot: be.feature.webhooks.http
184
+ template: webhooks/webhook.http.module.ts.tpl
185
+ role: Nest module of the door, composed only by an api-kind app.
186
+ - path: src/features/webhooks/<provider>/transport/http/<provider>.webhook.ts
187
+ slot: be.feature.webhooks.http
188
+ template: webhooks/webhook.door.ts.tpl
189
+ role: The signed door, one controller with one POST handler.
190
+ rules: [BE_WEBHOOK_SHAPE, BE_WEBHOOK_UNVERIFIED, BE_DEFAULT_DENY, BE_INPUT_BOUNDED]
191
+ spec: src/features/webhooks/<provider>/transport/http/<provider>.webhook.spec.ts
192
+ - path: src/features/webhooks/<provider>/transport/http/<provider>.webhook.spec.ts
193
+ slot: be.feature.webhooks.http
194
+ template: webhooks/webhook.door.spec.ts.tpl
195
+ role: Unit spec of the door beside it.
196
+ - path: src/features/webhooks/<provider>/transport/http/dto/<event>.request.ts
197
+ slot: be.feature.webhooks.dto
198
+ role: The typed, bounded provider payload.
199
+ rules: [BE_INPUT_BOUNDED]
200
+ template: webhooks/webhook.request.ts.tpl
201
+ - path: src/modules/platform/http-security/webhook-signature.service.ts
202
+ slot: be.platform
203
+ role: WebhookSignatureService, the one owner of the signature and replay proof.
204
+ spec: src/modules/platform/http-security/webhook-signature.service.spec.ts
205
+ optional: true
206
+ - path: src/modules/domain/<capability>/<capability>.service.ts
207
+ slot: be.domain
208
+ role: The intake method, which claims the inbox and publishes the event in its transaction.
209
+ rules: [BE_INBOX_DEDUPE_MISSING, BE_OUTBOX_WRITE_TX]
210
+ optional: true
211
+ - path: src/modules/events/<service>/<event>.event.ts
212
+ slot: be.events
213
+ role: The typed event the intake publishes.
214
+ rules: [BE_EVENT_CLASS_CONTRACT]
215
+ optional: true
216
+ - path: src/tests/e2e/<area>/<provider>-webhook.e2e-spec.ts
217
+ slot: be.tests.e2e
218
+ role: "Titles webhooks/<scenario>: ... prove the pattern against the provider fake."
219
+ spec: webhooks/bad-signature-is-refused, webhooks/replay-is-refused, webhooks/accepted-delivery-publishes-once
220
+ rules: [BE_PATTERN_SPEC_MISSING]
221
+ optional: true
@@ -23,14 +23,16 @@ rules:
23
23
  - id: FE-FOLDER-1
24
24
  title: Responsibility directories
25
25
  kind: mandatory
26
- hfsRules: [R01, R02, R59, R64]
26
+ hfsRules: [R01, R02, R59, R64, R26, R54, R56, R91, R94]
27
27
  requirement: |
28
- The front end of every app (`fe/`) is an fe/apps/<app>/ monorepo even with one app, named by its role (for example
29
- web), and all product source lives under fe/apps/<app>/src. An fe/src/ does not exist. Each Next source root
28
+ The front end of every app (`fe/`) is an fe/apps/<app>/ monorepo even with one app — each app declared in
29
+ `hfs.json` `sides.fe.apps` with kind `next` (slot `fe.app.next`; the scaffold writes `landing` and `app`) — and all
30
+ product source lives under fe/apps/<app>/src. An fe/src/ does not exist. Each Next source root
30
31
  (fe/apps/<app>/src) uses app/ for framework adapters; features/{pages,layouts,overlays} for route-facing product
31
32
  composition; components/{blocks,composites,branches,leaves} for product visuals; hooks/<domain> for React hooks;
32
- and modules/<capability> for cohesive reusable technical and domain capabilities. Every app has the modules api,
33
- config, i18n and routes, and one brand.css under modules/brand when it sets brand tokens. No other empty role
33
+ and modules/<capability> for cohesive reusable technical and domain capabilities. Every app carries the required
34
+ module instances of slot `fe.modules` and one brand.css under modules/brand when it sets brand tokens
35
+ (`fe.modules.brand`). No other empty role
34
36
  folder is required. Grammar remains a separate product-agnostic package. The only files that may sit directly in the
35
37
  source root (the directory holding app/) are the framework-pinned root files listed in frameworkPinnedRootFiles
36
38
  below: Next.js loads them from that exact place. Each is a thin framework adapter whose internal imports enter
@@ -46,9 +48,8 @@ rules:
46
48
  # keep is decided by the slot fe.source-root-pinned and FE_NEXT_CONVENTIONS, not by this list.
47
49
  # Machine list read by scripts/hfs/architecture/framework-pinned.mjs (FE_SOURCE_LAYOUT_INVALID
48
50
  # accepts exactly these basenames directly in a Next source root;
49
- # their imports follow the FE_TIER_DIRECTION matrix). Exact names, case-sensitive, no globs. Supervisor rulings for nivo
50
- # wf-nivo-fe-debt-mug06w7h inc-2e42a24b74e4 and inc-846867b9a34e (proxy is the Next 16 name of
51
- # middleware, listed so the list survives the upgrade).
51
+ # their imports follow the FE_TIER_DIRECTION matrix). Exact names, case-sensitive, no globs. Supervisor rulings
52
+ # (proxy is the Next 16 name of middleware, listed so the list survives the upgrade).
52
53
  - middleware.ts
53
54
  - middleware.js
54
55
  - middleware.mjs
@@ -82,7 +83,7 @@ rules:
82
83
  fe/apps/<app>/src/modules/api/ or fe/apps/<app>/src/modules/session/ with one explicit public index.ts entry
83
84
  - id: case-3
84
85
  when: "A reusable product visual without scenario ownership"
85
- write: "fe/apps/<app>/src/components/{blocks,composites,branches,leaves}/<Name>/index.tsx"
86
+ write: "an owner folder of slot `fe.components` under the layer it belongs to — for example fe/apps/<app>/src/components/leaves/<Name>/index.tsx"
86
87
  - id: case-4
87
88
  when: "A React hook"
88
89
  write: "fe/apps/<app>/src/hooks/<domain>/useAutoScroll.ts; built-in React hook calls may remain in visuals"
@@ -94,7 +95,7 @@ rules:
94
95
  fe/apps/<app>/src/modules/i18n/ and the adapter imports it; the names the framework mandates there
95
96
  (frameworkPinnedRootExports, for example export const config = { matcher }) keep their framework spelling
96
97
  - id: case-6
97
- when: "Any other file or folder directly under the source root (fe/apps/<app>/src/i18n/request.ts, fe/apps/<app>/src/config.ts), and an fe/src/"
98
+ when: "Any other file or folder directly under the source root (an `i18n/request.ts` or a `config.ts` there), and an fe/src/"
98
99
  write: >
99
100
  Move it to its owner, for example fe/apps/<app>/src/modules/i18n/request.ts, and point framework configuration
100
101
  (fe/apps/<app>/next.config.ts) at the new path
@@ -106,13 +107,53 @@ rules:
106
107
  verification:
107
108
  automated:
108
109
  - HFS_SLOT_UNDECLARED
110
+ - HFS_SLOT_AMBIGUOUS
111
+ - HFS_SLOT_NOT_ENABLED
112
+ - HFS_FORBIDDEN_PRESENT
113
+ - HFS_TRACKED_MUST_BE_IGNORED
114
+ - HFS_ROOT_ENTRY_FORBIDDEN
115
+ - HFS_ROOT_MARKDOWN_FORBIDDEN
116
+ - HFS_ROOT_SRC_FORBIDDEN_FE
117
+ - HFS_SRC_LAYOUT_INVALID
118
+ - HFS_MODULE_TIER_INVALID
119
+ - HFS_WORK_IN_FE
120
+ - HFS_STACKS_IN_SIDE
109
121
  - HFS_SLOT_REQUIRED_MISSING
110
- - FE_SOURCE_LAYOUT_INVALID
111
- - FE_NEXT_CONVENTIONS
122
+ - HFS_MIN_INSTANCES
123
+ - HFS_REQUIRED_FILE_MISSING
124
+ - HFS_ROOT_ENTRY_MISSING
125
+ - HFS_APPS_REQUIRED
126
+ - HFS_APP_LAYOUT_INVALID
127
+ - HFS_README_TITLE_INVALID
128
+ - HFS_README_DESCRIPTION_INVALID
129
+ - HFS_README_SECTION_MISSING
130
+ - HFS_README_SECTION_ORDER
131
+ - HFS_README_DEVELOPMENT_INCOMPLETE
132
+ - HFS_README_WORK_POINTER_MISSING
133
+ - HFS_README_PRIVATE_URL
134
+ - HFS_README_BADGE_NOT_LIVE
135
+ - FE_I18N_PLACEMENT
136
+ - FE_I18N_NAVIGATION
137
+ - FE_I18N_FORMATTER
138
+ - FE_APP_ISOLATION
139
+ - BE_TIER_DIRECTION
112
140
  - FE_TIER_DIRECTION
141
+ - ARCH_PACKAGE_IMPORTS_APP
142
+ - FE_ROUTE_FILES_THIN
143
+ - FE_NEXT_CONVENTIONS
144
+ - FE_PAGE_METADATA_MISSING
145
+ - FE_ROUTE_ONE_PAGE
146
+ - FE_ROUTE_DRAWING_DECISION
147
+ - FE_ROUTE_CLIENT_BOUNDARY
148
+ - FE_ROUTE_CLIENT_HOOK
149
+ - FE_ROUTE_DEFAULT_EXPORT
150
+ - FE_HOOKS_ARE_HOOKS
113
151
  - FE_CUSTOM_HOOK_LOCATION
114
- - HFS_APPS_REQUIRED
115
- - HFS_ROOT_SRC_FORBIDDEN_FE
152
+ - FE_BLOCK_PRODUCT_HOOK_DEFINITION
153
+ - FE_COMPONENT_DEEP_HOOK_IMPORT
154
+ - FE_SOURCE_FORM
155
+ - FE_SOURCE_LAYOUT_INVALID
156
+ - FE_SLOT_FILE_ROLE
116
157
  manual:
117
158
  - Confirm the unit's responsibility and public entry, rather than assigning it by consumer count.
118
159
  relatedExamples:
@@ -121,7 +162,7 @@ rules:
121
162
  - id: FE-FOLDER-2
122
163
  title: Discoverable files for one unit
123
164
  kind: mandatory
124
- hfsRules: [R02, R55, R65]
165
+ hfsRules: [R02, R55, R65, R20, R92]
125
166
  requirement: |
126
167
  A split unit (a connected block, and a feature page, layout or overlay) uses index.tsx for the connected X and
127
168
  sibling component.tsx for the pure XBase, its XBaseProps and xDefaultState, plus XState when the shape is its own union
@@ -149,12 +190,40 @@ rules:
149
190
  write: "hooks/<domain>/useX.ts or modules/<capability>/...; do not create visual twins"
150
191
  verification:
151
192
  automated:
152
- - class-names-in-colocated-file
153
- - no-inline-class-name
154
- - FE_CONNECTED_BLOCK_RENDER_PAIR
193
+ - HFS_SLOT_REQUIRED_MISSING
194
+ - HFS_MIN_INSTANCES
195
+ - HFS_REQUIRED_FILE_MISSING
196
+ - HFS_ROOT_ENTRY_MISSING
197
+ - HFS_APPS_REQUIRED
198
+ - HFS_APP_LAYOUT_INVALID
199
+ - HFS_README_TITLE_INVALID
200
+ - HFS_README_DESCRIPTION_INVALID
201
+ - HFS_README_SECTION_MISSING
202
+ - HFS_README_SECTION_ORDER
203
+ - HFS_README_DEVELOPMENT_INCOMPLETE
204
+ - HFS_README_WORK_POINTER_MISSING
205
+ - HFS_README_PRIVATE_URL
206
+ - HFS_README_BADGE_NOT_LIVE
207
+ - FE_CLIENT_BOUNDARY
208
+ - FE_CLIENT_SERVER_IMPORT
209
+ - FE_CLIENT_REACHES_SERVER
210
+ - FE_SERVER_ONLY_MARK
211
+ - FE_STORAGE_OUTSIDE_MODULES
212
+ - FE_DANGEROUS_HTML
155
213
  - FE_SIZE_AND_STATE_BUDGET
214
+ - FE_LIST_KEY
215
+ - FE_EFFECT_CLEANUP
216
+ - FE_SWALLOWED_ERROR
217
+ - FE_CONSOLE_CALL
156
218
  - HFS_SIZE_GROWTH
157
- - starci-fe/base-import-pair
219
+ - HFS_SIZE_SOFT_BACKLOG
220
+ - FE_COMPONENT_API
221
+ - FE_COMPONENT_WORLD_OWNERSHIP
222
+ - FE_WORLD_OWNER_RENDER_BOUNDARY
223
+ - FE_CONNECTED_BLOCK_RENDER_PAIR
224
+ - FE_PURE_REACHES_DATA
225
+ - FE_PURE_WORLD_HOOK
226
+ - FE_PURE_WORLD_IMPORT
158
227
  manual:
159
228
  - Confirm each file owns a real responsibility; do not add a component.tsx twin by habit.
160
229
  relatedExamples:
@@ -163,7 +232,7 @@ rules:
163
232
  - id: FE-FOLDER-3
164
233
  title: Route files adapt to one visual owner and every app has its boundaries
165
234
  kind: mandatory
166
- hfsRules: [R53, R54, R55, R57]
235
+ hfsRules: [R53, R54, R55, R57, R26]
167
236
  requirement: |
168
237
  Route files under app/[locale]/ (page, layout, template, loading, not-found) are server components. A route may
169
238
  resolve framework server inputs (params, searchParams, headers, cookies), then mounts one page-level visual owner.
@@ -192,10 +261,27 @@ rules:
192
261
  verification:
193
262
  automated:
194
263
  - FE_ERROR_BOUNDARY_MISSING
264
+ - FE_SUSPENSE_NULL_FALLBACK
195
265
  - FE_ROUTE_FILES_THIN
266
+ - FE_NEXT_CONVENTIONS
267
+ - FE_PAGE_METADATA_MISSING
268
+ - FE_ROUTE_ONE_PAGE
269
+ - FE_ROUTE_DRAWING_DECISION
270
+ - FE_ROUTE_CLIENT_BOUNDARY
271
+ - FE_ROUTE_CLIENT_HOOK
272
+ - FE_ROUTE_DEFAULT_EXPORT
196
273
  - FE_CLIENT_BOUNDARY
274
+ - FE_CLIENT_SERVER_IMPORT
275
+ - FE_CLIENT_REACHES_SERVER
276
+ - FE_SERVER_ONLY_MARK
277
+ - FE_STORAGE_OUTSIDE_MODULES
278
+ - FE_DANGEROUS_HTML
197
279
  - FE_OWNER_REACHABLE
280
+ - FE_ROUTE_HARDCODED
281
+ - FE_HREF_RESOLVES
282
+ - BE_TIER_DIRECTION
198
283
  - FE_TIER_DIRECTION
284
+ - ARCH_PACKAGE_IMPORTS_APP
199
285
  manual:
200
286
  - Confirm visual routes have one page owner and redirect-only routes have no visual tree.
201
287
  relatedExamples: []
@@ -203,7 +289,7 @@ rules:
203
289
  - id: FE-FOLDER-4
204
290
  title: Hooks are hooks; readers and transport live in modules
205
291
  kind: mandatory
206
- hfsRules: [R56, R50, R49]
292
+ hfsRules: [R56, R50, R49, R21, R26]
207
293
  requirement: |
208
294
  hooks/<domain>/ holds React hooks (use*.ts, one hook per file) and exactly one <domain>.shared.ts for shared
209
295
  non-hook helpers of that domain (key builders, token readers). A file in hooks/ that is not a hook and is not the shared
@@ -235,8 +321,19 @@ rules:
235
321
  automated:
236
322
  - FE_HOOKS_ARE_HOOKS
237
323
  - FE_CUSTOM_HOOK_LOCATION
324
+ - FE_BLOCK_PRODUCT_HOOK_DEFINITION
325
+ - FE_COMPONENT_DEEP_HOOK_IMPORT
326
+ - FE_TRANSPORT_OWNER
327
+ - FE_EFFECT_FETCH
328
+ - FE_SWR_KEY_IDENTITY
329
+ - FE_SWR_MUTATION_RESOURCE_IDENTITY
330
+ - FE_ENV_OWNER
238
331
  - HFS_DUPLICATE_CODE
332
+ - HFS_DUPLICATE_SYMBOL
333
+ - FE_CROSS_APP_DUPLICATE
334
+ - BE_TIER_DIRECTION
239
335
  - FE_TIER_DIRECTION
336
+ - ARCH_PACKAGE_IMPORTS_APP
240
337
  manual:
241
338
  - Confirm each lifecycle has one feature owner and transport mechanics have one module owner.
242
339
  relatedExamples:
@@ -274,7 +371,7 @@ rules:
274
371
  - id: FE-FOLDER-6
275
372
  title: Keep units cohesive
276
373
  kind: mandatory
277
- hfsRules: [R49, R21]
374
+ hfsRules: [R49, R21, R91, R92]
278
375
  requirement: |
279
376
  A unit folder contains files that change for the same responsibility. Do not create generic helpers/ or utils/
280
377
  buckets inside components, read deployment configuration in presentation, or split files solely to meet a count.
@@ -301,9 +398,18 @@ rules:
301
398
  verification:
302
399
  automated:
303
400
  - FE_ENV_OWNER
304
- - class-names-in-colocated-file
305
- - no-inline-class-name
306
- - no-helper-folder-in-components
401
+ - HFS_DUPLICATE_CODE
402
+ - HFS_DUPLICATE_SYMBOL
403
+ - FE_CROSS_APP_DUPLICATE
404
+ - FE_SOURCE_FORM
405
+ - FE_SOURCE_LAYOUT_INVALID
406
+ - FE_COMPONENT_API
407
+ - FE_COMPONENT_WORLD_OWNERSHIP
408
+ - FE_WORLD_OWNER_RENDER_BOUNDARY
409
+ - FE_CONNECTED_BLOCK_RENDER_PAIR
410
+ - FE_PURE_REACHES_DATA
411
+ - FE_PURE_WORLD_HOOK
412
+ - FE_PURE_WORLD_IMPORT
307
413
  manual:
308
414
  - Confirm extraction is justified by ownership or lifecycle rather than file length or count.
309
415
  relatedExamples: []
@@ -13,16 +13,16 @@ purpose: |
13
13
  vulnerability, every hotspot reviewed, no duplicated-lines excess, no cognitive-complexity issue). The one Sonar
14
14
  mechanism of the HFS canon is packages/hfs/README.md section "Sonar".
15
15
  gate:
16
- name: starci-new-code
17
- # A project with no new-code baseline judges the whole project as new code (nivo inc-f92febebbb64); a fixed
16
+ name: starci-quality
17
+ # A project with no new-code baseline judges the whole project as new code; a fixed
18
18
  # window keeps "new code" the recent work on main, so the server gate is passable on a healthy main.
19
19
  newCodePeriod: {type: NUMBER_OF_DAYS, value: 30}
20
20
  newCode:
21
- # Coverage of the services only. The be unit run writes coverage/lcov.info (@starci/jest-preset coverageReporters lcov) and the
21
+ # Coverage of the measured logic files only (the `ruleParams.be.logicRoles` roles of the `coverage: required` slots). The be unit run writes coverage/lcov.info (@starci/jest-preset coverageReporters lcov) and the
22
22
  # managed sonar-project.properties imports it (sonar.javascript.lcov.reportPaths=be/coverage/lcov.info) with
23
- # sonar.coverage.exclusions = the complement of be/src/**/*.service.ts (SonarQube has no coverage inclusions), rendered by hfs sync from the preset's COVERAGE_SOURCES and the slot manifest (codecov.yml
24
- # is rendered from the same constant). A handler, resolver, controller, module, config file or test is not a coverage target and
25
- # fe/ is outside coverage entirely, so coverage on these conditions is the services' coverage alone.
23
+ # sonar.coverage.exclusions = the complement of the measured files (SonarQube has no coverage inclusions), rendered by starci app sync from the one derivation scripts/hfs/coverage-scope.mjs (be/jest.config.js and codecov.yml
24
+ # are rendered from it too; a hand edit of any of them is R204 HFS_COVERAGE_SCOPE_DRIFT). The feature tier, declaration files, tests and
25
+ # fe/ are never coverage targets, so coverage on these conditions is the coverage of the modules' logic alone.
26
26
  coverage:
27
27
  metric: new_coverage
28
28
  minPercent: 100
@@ -40,11 +40,11 @@ newCode:
40
40
  metric: new_security_hotspots_reviewed
41
41
  minReviewedPercent: 100
42
42
  unreviewedMax: 0
43
- # The whole code, not only the new code. Every finding of the HFS canon reaches Sonar through ONE entry, `hfs lint`
43
+ # The whole code, not only the new code. Every finding of the HFS canon reaches Sonar through ONE entry, `starci app lint`
44
44
  # (packages/hfs, contract changes hfs-sonar-import and hfs-lint-entry), which writes ONE file, reports/lint.sonar.json
45
- # (`npm run lint -- --sonar reports/lint.sonar.json`), named by sonar.externalIssuesReportPaths; the gate holds the open-issue count of
45
+ # (`starci app lint --sonar reports/lint.sonar.json`), named by sonar.externalIssuesReportPaths; the gate holds the open-issue count of
46
46
  # the whole project at zero. The file carries three engines:
47
- # starci-hfs the repository findings of `hfs check` (managed files, tree, pins, CI, contracts; the rule id is the finding code)
47
+ # starci-hfs the repository findings of `starci app check` (managed files, tree, pins, CI, contracts; the rule id is the finding code)
48
48
  # eslint ESLint's json over the repository (the BE and FE canon plugins alike, per-file and project-graph rules)
49
49
  # stylelint stylelint's json over the style glob (front ends)
50
50
  # The engines share ONE placement rule (a finding on a file Sonar does not index is filed on the first source file); Sonar's own
@@ -63,9 +63,9 @@ overall:
63
63
  hotspots:
64
64
  metric: security_hotspots_reviewed
65
65
  minReviewedPercent: 100
66
- # The services' coverage (see newCode.coverage), overall and per file: with the inclusions in place each `*.service.ts` is its
67
- # own measure, so one service below 100 fails the slice verdict (sonar-local evaluateSlice) and the dashboard verdict
68
- # (sonar-local dashboard) although the project average may round to 100. A file outside the inclusions is never read.
66
+ # The measured files' coverage (see newCode.coverage), overall and per file: with the exclusions in place each measured file is its
67
+ # own measure, so one measured file below 100 fails the slice verdict (sonar-local evaluateSlice) and the dashboard verdict
68
+ # (sonar-local dashboard) although the project average may round to 100. A file outside the scope is never read.
69
69
  coverage:
70
70
  metric: coverage
71
71
  minPercent: 100
@@ -81,6 +81,40 @@ overall:
81
81
  cognitiveComplexity:
82
82
  rule: typescript:S3776
83
83
  via: overall.issues
84
+ # Lite is the same quality policy without a test or coverage world. Readers select this block from hfs.json edition;
85
+ # keeping both gates in this document makes every threshold data, never a branch-local restatement.
86
+ lite:
87
+ gate:
88
+ name: starci-quality-lite
89
+ newCodePeriod: {type: NUMBER_OF_DAYS, value: 30}
90
+ newCode:
91
+ ignoreBelowChangedLines: 20
92
+ duplication:
93
+ metric: new_duplicated_lines_density
94
+ maxPercent: 3
95
+ issues:
96
+ blockingSeverities: [BLOCKER, CRITICAL]
97
+ metrics: {BLOCKER: new_blocker_violations, CRITICAL: new_critical_violations}
98
+ max: 0
99
+ hotspots:
100
+ metric: new_security_hotspots_reviewed
101
+ minReviewedPercent: 100
102
+ unreviewedMax: 0
103
+ overall:
104
+ issues:
105
+ metric: violations
106
+ max: 0
107
+ engines: [starci-hfs, eslint, stylelint]
108
+ types: {bugs: BUG, code_smells: CODE_SMELL, vulnerabilities: VULNERABILITY}
109
+ hotspots:
110
+ metric: security_hotspots_reviewed
111
+ minReviewedPercent: 100
112
+ duplication:
113
+ metric: duplicated_lines_density
114
+ maxPercent: 3
115
+ cognitiveComplexity:
116
+ rule: typescript:S3776
117
+ via: overall.issues
84
118
  # The Sonar enforcers of the rule catalog (knowledge/hfs/rules.yaml): the failure code each condition above is the gate of.
85
119
  enforces:
86
120
  - {rule: R20, code: HFS_SIZE_GROWTH, enforcer: cognitive-complexity, condition: cognitiveComplexity}
@@ -91,19 +125,19 @@ enforcedOps: [backend.implement, interface.implement, code.refactor]
91
125
  reasoning: |
92
126
  Chosen against the four projects the local server holds on 2026-09-29 (whole-project duplicated lines
93
127
  1.6 / 2.1 / 1.7 / 0.0 percent), so new code that meets them is at or below what main already carries.
94
- coverage 100 on services, overall and new code (owner 2026-10-01): the unit project already fails below its per-file
95
- 100 threshold on `*.service.ts`; Sonar imports the same run's lcov with the same scope, so the dashboard, the slice
96
- verdict and the server gate show the number the runner enforces, file by file. Only services count: business logic
97
- lives there, the thin layers are covered through them, and the front end has no unit tests.
128
+ coverage 100 on the measured logic files, overall and new code (owner 2026-10-01): the unit project already fails below its per-file
129
+ 100 threshold on the `ruleParams.be.logicRoles` files of the `coverage: required` slots; Sonar imports the same run's lcov with the same scope, so the dashboard, the slice
130
+ verdict and the server gate show the number the runner enforces, file by file. Only the modules' logic counts: business logic
131
+ lives there, the feature tier is thin (R203) and proven by integration and e2e, and the front end has no unit tests.
98
132
  duplication 3: the Sonar way value; the worst project today is 2.1, so 3 rejects a real copy-paste block and
99
133
  passes ordinary work.
100
134
  blocker/critical 0: the two severities that are defects, not style. main carries old debt of both kinds
101
- (nivo-backend 3 blocker, 137 critical), so the SLICE verdict reads only changed lines and never main's backlog;
135
+ (one product repository carries 3 blocker and 137 critical), so the SLICE verdict reads only changed lines and never main's backlog;
102
136
  major and lower are reported on the summary and never fail a slice.
103
137
  overall issues 0 and overall duplication 3: the server gate is also the owner's definition of done for the HFS canon:
104
138
  a repository that carries any open ESLint, stylelint or HFS finding is not green, whatever the age of the line. The
105
139
  op slice keeps judging changed lines (an op cannot fix a repository's whole backlog); the dashboard and CI show the
106
- whole-project condition. Adopting a repository therefore means clearing its imported findings, which `hfs check`,
140
+ whole-project condition. Adopting a repository therefore means clearing its imported findings, which `starci app check`,
107
141
  eslint and stylelint already demand at land.
108
142
  hotspots 0 unreviewed: a hotspot is a question the author must answer; on changed lines it is answered in the
109
143
  same slice.