@starci/hfs 4.7.31 → 4.7.33

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 (473) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +13 -6
  3. package/emit/contracts.mjs +4 -3
  4. package/emit/form-bounds-reader.ts.partial +58 -0
  5. package/emit/form-bounds.mjs +155 -0
  6. package/emit/graphql-input-bounds.mjs +97 -0
  7. package/emit/input-bounds.mjs +44 -0
  8. package/emit/operation-schemas.mjs +137 -0
  9. package/emit/operations-worker.mjs +2 -2
  10. package/emit/operations.mjs +52 -16
  11. package/emit/schema-worker.mjs +17 -4
  12. package/emit/type-schema.mjs +17 -5
  13. package/package.json +9 -2
  14. package/release/gate.mjs +18 -23
  15. package/release/index.mjs +1 -1
  16. package/release/push.mjs +4 -5
  17. package/runtime/engine/admission.mjs +331 -0
  18. package/runtime/engine/canonical-json.mjs +14 -0
  19. package/runtime/engine/db/blob.mjs +380 -0
  20. package/runtime/engine/db/event-compact.mjs +73 -0
  21. package/runtime/engine/db/ledger-open.mjs +38 -0
  22. package/runtime/engine/db/ledger-paths.mjs +87 -0
  23. package/runtime/engine/db/ledger.mjs +1068 -0
  24. package/runtime/engine/db/machine-connection.mjs +150 -0
  25. package/runtime/engine/db/machine-open.mjs +60 -0
  26. package/runtime/engine/db/machine-schema.mjs +105 -0
  27. package/runtime/engine/db/machine.mjs +1317 -0
  28. package/runtime/engine/db/provider-reservations.mjs +127 -0
  29. package/runtime/engine/db/provision-authority.mjs +76 -0
  30. package/runtime/engine/db/provision-lock.mjs +29 -0
  31. package/runtime/engine/db/provision-operations.mjs +146 -0
  32. package/runtime/engine/db/ref-value.mjs +67 -0
  33. package/runtime/engine/db/schema/machine.sql +920 -0
  34. package/runtime/engine/db/schema/runtime.sql +1113 -0
  35. package/runtime/engine/refuse.mjs +11 -0
  36. package/runtime/knowledge/hfs/canon-pins.yaml +65 -9
  37. package/runtime/knowledge/hfs/design-truths.yaml +149 -0
  38. package/runtime/knowledge/hfs/fe-stack.yaml +23 -5
  39. package/runtime/knowledge/hfs/rules.yaml +269 -48
  40. package/runtime/knowledge/hfs/slots.yaml +113 -53
  41. package/runtime/knowledge/patterns/be/api.yaml +46 -20
  42. package/runtime/knowledge/patterns/be/event-bus.yaml +19 -12
  43. package/runtime/knowledge/patterns/be/idempotency.yaml +265 -0
  44. package/runtime/knowledge/patterns/be/jobs.yaml +17 -12
  45. package/runtime/knowledge/patterns/be/projections.yaml +2 -2
  46. package/runtime/knowledge/patterns/be/queues.yaml +57 -22
  47. package/runtime/knowledge/patterns/be/reactors.yaml +1 -1
  48. package/runtime/knowledge/patterns/be/realtime.yaml +326 -27
  49. package/runtime/knowledge/patterns/be/saga.yaml +2 -2
  50. package/runtime/knowledge/sonar-gate.yaml +1 -1
  51. package/runtime/modules/kernel/command-policy.yaml +249 -0
  52. package/runtime/modules/kernel/failure-codes.yaml +211 -52
  53. package/runtime/modules/kernel/hook-input.yaml +6 -0
  54. package/runtime/modules/kernel/protected-zone.yaml +81 -0
  55. package/runtime/modules/kernel/removed-vocabulary.yaml +62 -0
  56. package/runtime/modules/kernel/roles.yaml +405 -0
  57. package/runtime/modules/models/registry.yaml +3 -1
  58. package/runtime/modules/models/runtimes.yaml +2 -0
  59. package/runtime/modules/schemas/application-stacks.schema.yaml +10 -2
  60. package/runtime/packages/cli/src/catalog.generated.mjs +46 -59
  61. package/runtime/packages/grammar/scripts/build-stamp.mjs +98 -0
  62. package/runtime/scripts/agent/codex-app-server.mjs +79 -0
  63. package/runtime/scripts/agent/codex-mirror-source.mjs +34 -0
  64. package/runtime/scripts/agent/host-agents.mjs +80 -0
  65. package/runtime/scripts/agent/launch-trust-policy.mjs +53 -0
  66. package/runtime/scripts/agent/trust-launch.mjs +191 -0
  67. package/runtime/scripts/agent/trust.mjs +523 -0
  68. package/runtime/scripts/api/fs/rename-over.mjs +21 -0
  69. package/runtime/scripts/api/fs/temp-path.mjs +8 -0
  70. package/runtime/scripts/api/fs/write-json-file.mjs +10 -0
  71. package/runtime/scripts/api/git/diff-names.mjs +8 -0
  72. package/runtime/scripts/api/git/head-time.mjs +10 -0
  73. package/runtime/scripts/api/git/index-lock.mjs +78 -0
  74. package/runtime/scripts/api/git/is-ancestor.mjs +5 -0
  75. package/runtime/scripts/api/git/log.mjs +5 -0
  76. package/runtime/scripts/api/git/merge-base-query.mjs +5 -0
  77. package/runtime/scripts/api/git/merge-tree.mjs +5 -0
  78. package/runtime/scripts/api/git/rev-list.mjs +5 -0
  79. package/runtime/scripts/api/git/rev-parse.mjs +13 -0
  80. package/runtime/scripts/api/git/status-query.mjs +5 -0
  81. package/runtime/scripts/api/git/worktree-list-query.mjs +5 -0
  82. package/runtime/scripts/api/node/spawn-node.mjs +6 -0
  83. package/runtime/scripts/api/npm/dist-tag.mjs +8 -0
  84. package/runtime/scripts/api/npm/lib.mjs +32 -0
  85. package/runtime/scripts/api/npm/pack-dry-run.mjs +9 -0
  86. package/runtime/scripts/api/npm/run-npm.mjs +6 -0
  87. package/runtime/scripts/api/npm/view.mjs +30 -0
  88. package/runtime/scripts/api/npm/whoami.mjs +8 -0
  89. package/runtime/scripts/api/process/hide-child-windows.mjs +31 -0
  90. package/runtime/scripts/api/process/kill-tree.mjs +22 -0
  91. package/runtime/scripts/api/process/lib.mjs +125 -0
  92. package/runtime/scripts/api/process/probe-guard-command.mjs +74 -0
  93. package/runtime/scripts/api/process/process-list.mjs +28 -0
  94. package/runtime/scripts/api/process/system-tool.mjs +37 -0
  95. package/runtime/scripts/gates/canon-digest.mjs +81 -0
  96. package/runtime/scripts/gates/canon-pins.mjs +16 -0
  97. package/runtime/scripts/gates/commit-proof.mjs +53 -0
  98. package/runtime/scripts/gates/gate-input.mjs +98 -0
  99. package/runtime/scripts/gates/gate.mjs +669 -0
  100. package/runtime/scripts/gates/grammar-dist.mjs +206 -0
  101. package/runtime/scripts/gates/runtime-package-selection.mjs +27 -0
  102. package/runtime/scripts/gates/test-world-run.mjs +254 -0
  103. package/runtime/scripts/gates/type-impact.mjs +277 -0
  104. package/runtime/scripts/gates/type-program.mjs +113 -0
  105. package/runtime/scripts/guards/assigned-command.mjs +12 -0
  106. package/runtime/scripts/guards/call-rights.mjs +47 -0
  107. package/runtime/scripts/guards/command-guard.mjs +468 -0
  108. package/runtime/scripts/guards/command-policy.mjs +342 -0
  109. package/runtime/scripts/guards/critic-reach.mjs +82 -0
  110. package/runtime/scripts/guards/deps-guard.mjs +150 -0
  111. package/runtime/scripts/guards/env-dump-verdict.mjs +89 -0
  112. package/runtime/scripts/guards/git-pathspec.mjs +225 -0
  113. package/runtime/scripts/guards/git-policy.mjs +355 -0
  114. package/runtime/scripts/guards/guards-root.mjs +27 -0
  115. package/runtime/scripts/guards/hook-install.mjs +343 -0
  116. package/runtime/scripts/guards/hook-io.mjs +76 -0
  117. package/runtime/scripts/guards/hook-verdict.mjs +12 -0
  118. package/runtime/scripts/guards/install-verdict.mjs +41 -0
  119. package/runtime/scripts/guards/kernel-seat.mjs +63 -0
  120. package/runtime/scripts/guards/launch-verdict.mjs +74 -0
  121. package/runtime/scripts/guards/op-starci.mjs +16 -0
  122. package/runtime/scripts/guards/op-write-scope.mjs +27 -0
  123. package/runtime/scripts/guards/orca-self-lifecycle.mjs +39 -0
  124. package/runtime/scripts/guards/process-kill-verdict.mjs +106 -0
  125. package/runtime/scripts/guards/protected-zone.mjs +56 -0
  126. package/runtime/scripts/guards/refusals.mjs +27 -0
  127. package/runtime/scripts/guards/release-definition.mjs +185 -0
  128. package/runtime/scripts/guards/release-push-gate.mjs +72 -0
  129. package/runtime/scripts/guards/release-record.mjs +58 -0
  130. package/runtime/scripts/guards/release-suite-mode.mjs +15 -0
  131. package/runtime/scripts/guards/rights.mjs +268 -0
  132. package/runtime/scripts/guards/seat-tools.mjs +47 -0
  133. package/runtime/scripts/guards/shell-commands.mjs +328 -0
  134. package/runtime/scripts/guards/supervisor-seat.mjs +80 -0
  135. package/runtime/scripts/guards/verdict-process.mjs +81 -0
  136. package/runtime/scripts/hfs/architecture/dead-exports.mjs +10 -10
  137. package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +1 -1
  138. package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +53 -0
  139. package/runtime/scripts/hfs/architecture/reachability.mjs +1 -1
  140. package/runtime/scripts/hfs/architecture/sql-owner.mjs +17 -6
  141. package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +105 -0
  142. package/runtime/scripts/hfs/architecture/sql-tokens.mjs +38 -52
  143. package/runtime/scripts/hfs/architecture/supabase-keys.mjs +261 -0
  144. package/runtime/scripts/hfs/architecture/transport-owner.mjs +49 -3
  145. package/runtime/scripts/hfs/architecture/typescript.mjs +1 -1
  146. package/runtime/scripts/hfs/check.mjs +6 -4
  147. package/runtime/scripts/hfs/coverage-scope.mjs +28 -1
  148. package/runtime/scripts/hfs/db-restamp-verb.mjs +54 -14
  149. package/runtime/scripts/hfs/declaration-shape.mjs +4 -4
  150. package/runtime/scripts/hfs/declaration-slots.mjs +14 -3
  151. package/runtime/scripts/hfs/manifest-shape.mjs +10 -6
  152. package/runtime/scripts/hfs/rule-params-shape.mjs +18 -6
  153. package/runtime/scripts/hfs/rules/a15-findings.mjs +4 -1
  154. package/runtime/scripts/hfs/rules/bypass-markers.mjs +22 -7
  155. package/runtime/scripts/hfs/rules/database-migrations.mjs +69 -14
  156. package/runtime/scripts/hfs/rules/database-queue-sources.mjs +9 -7
  157. package/runtime/scripts/hfs/rules/database-queues.mjs +68 -18
  158. package/runtime/scripts/hfs/rules/edition.mjs +56 -12
  159. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -10
  160. package/runtime/scripts/hfs/rules/fe-stack.mjs +12 -7
  161. package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +1 -1
  162. package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +75 -9
  163. package/runtime/scripts/hfs/rules/stacks-runtime.mjs +1 -1
  164. package/runtime/scripts/hfs/rules/stacks-swarm.mjs +15 -4
  165. package/runtime/scripts/hfs/rules/text-integrity.mjs +73 -0
  166. package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +74 -0
  167. package/runtime/scripts/hfs/runtime-rules/release-notes.mjs +44 -0
  168. package/runtime/scripts/hfs/sealed-members.mjs +3 -3
  169. package/runtime/scripts/hfs/slot-side-problems.mjs +3 -3
  170. package/runtime/scripts/hfs/slots.mjs +2 -1
  171. package/runtime/scripts/hfs/stack-deploy-config.mjs +22 -5
  172. package/runtime/scripts/hfs/stacks-gate.mjs +28 -7
  173. package/runtime/scripts/hfs/view.mjs +2 -1
  174. package/runtime/scripts/lib/app-data.mjs +11 -0
  175. package/runtime/scripts/lib/bypass-markers.mjs +272 -75
  176. package/runtime/scripts/lib/check-format.mjs +7 -0
  177. package/runtime/scripts/lib/cli-arg.mjs +120 -0
  178. package/runtime/scripts/lib/css-rules.mjs +220 -0
  179. package/runtime/scripts/lib/dom-tree.mjs +4 -0
  180. package/runtime/scripts/lib/escape.mjs +16 -0
  181. package/runtime/scripts/lib/event-items.mjs +22 -0
  182. package/runtime/scripts/lib/failure-code-template-errors.mjs +161 -0
  183. package/runtime/scripts/lib/git-dir.mjs +120 -0
  184. package/runtime/scripts/lib/grammar-vendor-parity.mjs +377 -0
  185. package/runtime/scripts/lib/guard-command.mjs +24 -0
  186. package/runtime/scripts/lib/hook-limits.mjs +5 -0
  187. package/runtime/scripts/lib/interrupt-cleanup.mjs +38 -0
  188. package/runtime/scripts/lib/js-lex.mjs +200 -0
  189. package/runtime/scripts/lib/json-formats.mjs +0 -1
  190. package/runtime/scripts/lib/language.mjs +94 -1
  191. package/runtime/scripts/lib/loosening-budgets.mjs +44 -0
  192. package/runtime/scripts/lib/loosening-config.mjs +361 -0
  193. package/runtime/scripts/lib/loosening-state.mjs +223 -0
  194. package/runtime/scripts/lib/menu-parts.mjs +11 -0
  195. package/runtime/scripts/lib/normalize.mjs +25 -0
  196. package/runtime/scripts/lib/op-gate.mjs +15 -0
  197. package/runtime/scripts/lib/redact.mjs +208 -0
  198. package/runtime/scripts/lib/runtime-location.mjs +21 -0
  199. package/runtime/scripts/lib/runtime-package-inventory.mjs +21 -0
  200. package/runtime/scripts/lib/runtime-package-manifests.mjs +84 -0
  201. package/runtime/scripts/lib/runtime-publication-tags.mjs +99 -0
  202. package/runtime/scripts/lib/seat-env.mjs +43 -0
  203. package/runtime/scripts/lib/secret-patterns.mjs +58 -9
  204. package/runtime/scripts/lib/shell-source.mjs +4 -0
  205. package/runtime/scripts/lib/source-phrases.mjs +34 -0
  206. package/runtime/scripts/lib/sqlite.mjs +21 -0
  207. package/runtime/scripts/lib/swarm-stack.mjs +2 -1
  208. package/runtime/scripts/lib/tar-files.mjs +39 -0
  209. package/runtime/scripts/lib/ts-analysis.mjs +10 -0
  210. package/runtime/scripts/lib/worktree-exclude.mjs +35 -0
  211. package/runtime/scripts/lib/worktree-record.mjs +14 -0
  212. package/runtime/scripts/machine/artifact-hold.mjs +52 -0
  213. package/runtime/scripts/machine/ask-receipts.mjs +113 -0
  214. package/runtime/scripts/machine/evidence-store.mjs +223 -0
  215. package/runtime/scripts/machine/home.mjs +216 -0
  216. package/runtime/scripts/machine/host-lock.mjs +184 -0
  217. package/runtime/scripts/machine/lock-recovery.mjs +55 -0
  218. package/runtime/scripts/machine/roles-contract.mjs +90 -0
  219. package/runtime/scripts/machine/runtime-change.mjs +20 -0
  220. package/runtime/scripts/machine/workflow-tree.mjs +122 -0
  221. package/runtime/scripts/reconciler/checklist-items.mjs +7 -0
  222. package/runtime/scripts/reconciler/guard-row.mjs +25 -0
  223. package/runtime/scripts/work/asset-slot.mjs +284 -0
  224. package/runtime/scripts/work/brand/brand-colour.mjs +125 -0
  225. package/runtime/scripts/work/brand/brand-tokens.mjs +167 -0
  226. package/runtime/scripts/work/brand/brand-value-source.mjs +106 -0
  227. package/runtime/scripts/work/brand/brand.mjs +892 -0
  228. package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +60 -0
  229. package/runtime/scripts/work/draw/draw-dna-findings.mjs +256 -0
  230. package/runtime/scripts/work/draw/draw-dna-selector.mjs +38 -0
  231. package/runtime/scripts/work/draw/draw-dna.mjs +483 -0
  232. package/runtime/scripts/work/draw/draw-layer.mjs +305 -0
  233. package/runtime/scripts/work/draw/draw-rationale-page.mjs +237 -0
  234. package/runtime/scripts/work/draw/draw-rationale-ref.mjs +14 -0
  235. package/runtime/scripts/work/draw/draw-rationale.mjs +353 -0
  236. package/runtime/scripts/work/draw/draw-source.mjs +412 -0
  237. package/runtime/scripts/work/draw/draw-taste.mjs +278 -0
  238. package/runtime/scripts/work/draw/draw-typecheck.mjs +72 -0
  239. package/runtime/scripts/work/draw/rationale-findings.mjs +205 -0
  240. package/runtime/scripts/work/draw-grammar.mjs +175 -0
  241. package/runtime/scripts/work/draw-render-page.mjs +188 -0
  242. package/runtime/scripts/work/draw-render.mjs +626 -0
  243. package/runtime/scripts/work/grammar-proposal.mjs +279 -0
  244. package/runtime/scripts/work/png.mjs +237 -0
  245. package/runtime/scripts/work/render-tools.mjs +64 -0
  246. package/runtime/scripts/work/work-io.mjs +119 -0
  247. package/scaffold/add-inbox-lite.mjs +2 -2
  248. package/scaffold/add-plan.mjs +40 -13
  249. package/scaffold/add-queue-lite.mjs +372 -0
  250. package/scaffold/add.mjs +5 -2
  251. package/scaffold/app.mjs +1 -2
  252. package/scaffold/edition-gate.mjs +11 -7
  253. package/scaffold/lite-exports.mjs +10 -0
  254. package/scaffold/pattern-file-slots.mjs +33 -0
  255. package/scaffold/test-world.mjs +1 -1
  256. package/scaffold/yaml-block-edit.mjs +117 -0
  257. package/src/main.mjs +5 -4
  258. package/stack/deploy.mjs +7 -3
  259. package/stack/post-deploy.mjs +48 -0
  260. package/sync/index.mjs +10 -0
  261. package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +1 -1
  262. package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +1 -1
  263. package/templates/app/codegen-graphql.mjs.partial +59 -12
  264. package/templates/app/hooks/husky/pre-commit +2 -2
  265. package/templates/app/hooks/husky/pre-push +10 -3
  266. package/templates/app/package-scripts/redis-dev.json +3 -0
  267. package/templates/app/package-scripts-lite/package.json +1 -0
  268. package/templates/app/skeleton/.starcistacks/application-stacks.yaml +36 -8
  269. package/templates/app/skeleton/.starcistacks/dev/README.md +1 -1
  270. package/templates/app/skeleton/.starcistacks/production/README.md +10 -9
  271. package/templates/app/skeleton/.starcistacks/production/infra/swarm/postgres-init.sh +21 -0
  272. package/templates/app/skeleton/.starcistacks/production/infra/swarm/recovery/restore-proof.md +1 -1
  273. package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/images.lock.yaml +1 -0
  274. package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +47 -5
  275. package/templates/app/skeleton/.starcistacks/production/runtime/env/KEYS.md +5 -3
  276. package/templates/app/skeleton/README.md +2 -0
  277. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +5 -0
  278. package/templates/app/skeleton-lite/.starcistacks/dev/README.md +2 -2
  279. package/templates/app/skeleton-lite/.starcistacks/production/README.md +1 -1
  280. package/templates/app/skeleton-lite/README.md +1 -1
  281. package/templates/be/inbox/platform/client-operation-outcomes.sql.tpl +18 -0
  282. package/templates/be/inbox/platform/event-bus/errors/event-bus.error.ts.tpl +16 -0
  283. package/templates/be/inbox/platform/event-bus/event-bus.contracts.ts.tpl +10 -0
  284. package/templates/be/inbox/platform/event-bus/event-bus.port.ts.tpl +1 -1
  285. package/templates/be/inbox/platform/event-bus/event-bus.service.spec.ts.tpl +15 -3
  286. package/templates/be/inbox/platform/event-bus/event-bus.service.ts.tpl +11 -3
  287. package/templates/be/inbox/platform/event-bus/index.ts.tpl +2 -0
  288. package/templates/be/inbox/platform/event-bus/messages/event-bus.messages.ts.tpl +7 -0
  289. package/templates/be/inbox/platform/event-bus/persistence/event-bus.sql.ts.tpl +2 -2
  290. package/templates/be/inbox/platform/idempotency/errors/idempotency.error.ts.tpl +19 -0
  291. package/templates/be/inbox/platform/idempotency/index.ts.tpl +2 -0
  292. package/templates/be/inbox/platform/idempotency/messages/idempotency.messages.ts.tpl +13 -0
  293. package/templates/be/inbox/platform/inbox/client-operation.policy.spec.ts.tpl +32 -0
  294. package/templates/be/inbox/platform/inbox/client-operation.policy.ts.tpl +17 -0
  295. package/templates/be/inbox/platform/inbox/errors/inbox.error.ts.tpl +22 -0
  296. package/templates/be/inbox/platform/inbox/inbox.port.ts.tpl +21 -0
  297. package/templates/be/inbox/platform/inbox/inbox.service.spec.ts.tpl +334 -11
  298. package/templates/be/inbox/platform/inbox/inbox.service.ts.tpl +55 -4
  299. package/templates/be/inbox/platform/inbox/index.ts.tpl +2 -0
  300. package/templates/be/inbox/platform/inbox/messages/inbox.messages.ts.tpl +15 -0
  301. package/templates/be/inbox/platform/inbox/persistence/inbox.rows.ts.tpl +33 -0
  302. package/templates/be/inbox/platform/inbox/persistence/inbox.sql.ts.tpl +26 -0
  303. package/templates/be/inbox/platform/inbox/request-fingerprint.policy.spec.ts.tpl +76 -0
  304. package/templates/be/inbox/platform/inbox/request-fingerprint.policy.ts.tpl +36 -0
  305. package/templates/be/inbox/platform/migration.sql.tpl +1 -0
  306. package/templates/be/inbox/service.spec.ts.tpl +4 -4
  307. package/templates/be/inbox/service.ts.tpl +3 -1
  308. package/templates/be/inbox/webhook-door.spec.ts.tpl +3 -2
  309. package/templates/be/inbox/webhook-door.ts.tpl +3 -2
  310. package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +3 -0
  311. package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +10 -0
  312. package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +2 -2
  313. package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +16 -3
  314. package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +11 -3
  315. package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +139 -50
  316. package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +25 -2
  317. package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +139 -78
  318. package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +10 -6
  319. package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +262 -159
  320. package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +32 -5
  321. package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +2 -0
  322. package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +5 -1
  323. package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +2 -0
  324. package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +4 -4
  325. package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +1 -0
  326. package/templates/be/patterns/idempotency/platform/idempotency/errors/idempotency.error.ts.tpl +19 -0
  327. package/templates/be/patterns/idempotency/platform/idempotency/index.ts.tpl +2 -0
  328. package/templates/be/patterns/idempotency/platform/idempotency/messages/idempotency.messages.ts.tpl +13 -0
  329. package/templates/be/patterns/idempotency/platform/inbox/client-operation.policy.spec.ts.tpl +32 -0
  330. package/templates/be/patterns/idempotency/platform/inbox/client-operation.policy.ts.tpl +17 -0
  331. package/templates/be/patterns/idempotency/platform/inbox/client-outcome-backfill.client.spec.ts.tpl +66 -0
  332. package/templates/be/patterns/idempotency/platform/inbox/client-outcome-backfill.client.ts.tpl +24 -0
  333. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-backfill.client.spec.ts.tpl +60 -0
  334. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-backfill.client.ts.tpl +12 -0
  335. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-release.client.spec.ts.tpl +49 -0
  336. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-release.client.ts.tpl +12 -0
  337. package/templates/be/patterns/idempotency/platform/inbox/effectful.decorators.ts.tpl +7 -0
  338. package/templates/be/patterns/idempotency/platform/inbox/errors/inbox.error.ts.tpl +22 -0
  339. package/templates/be/patterns/idempotency/platform/inbox/inbox.decorators.ts.tpl +17 -0
  340. package/templates/be/patterns/idempotency/platform/inbox/inbox.module-definition.ts.tpl +7 -0
  341. package/templates/be/patterns/idempotency/platform/inbox/inbox.module.ts.tpl +28 -0
  342. package/templates/be/patterns/idempotency/platform/inbox/inbox.options.ts.tpl +7 -0
  343. package/templates/be/patterns/idempotency/platform/inbox/inbox.port.ts.tpl +44 -0
  344. package/templates/be/patterns/idempotency/platform/inbox/inbox.service.spec.ts.tpl +388 -0
  345. package/templates/be/patterns/idempotency/platform/inbox/inbox.service.ts.tpl +77 -0
  346. package/templates/be/patterns/idempotency/platform/inbox/index.ts.tpl +10 -0
  347. package/templates/be/patterns/idempotency/platform/inbox/messages/inbox.messages.ts.tpl +15 -0
  348. package/templates/be/patterns/idempotency/platform/inbox/persistence/connection.ts.tpl +9 -0
  349. package/templates/be/patterns/idempotency/platform/inbox/persistence/entities/inbox-claim.entity.ts.tpl +25 -0
  350. package/templates/be/patterns/idempotency/platform/inbox/persistence/inbox.rows.ts.tpl +33 -0
  351. package/templates/be/patterns/idempotency/platform/inbox/persistence/inbox.sql.ts.tpl +39 -0
  352. package/templates/be/patterns/idempotency/platform/inbox/persistence/migrations/1789800005000-create-inbox-claims.ts.tpl +21 -0
  353. package/templates/be/patterns/idempotency/platform/inbox/persistence/migrations/1792800000000-client-operation-outcomes.ts.tpl +21 -0
  354. package/templates/be/patterns/idempotency/platform/inbox/request-fingerprint.policy.spec.ts.tpl +76 -0
  355. package/templates/be/patterns/idempotency/platform/inbox/request-fingerprint.policy.ts.tpl +36 -0
  356. package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +1 -0
  357. package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +4 -3
  358. package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +2 -0
  359. package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +20 -2
  360. package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +1 -0
  361. package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +4 -0
  362. package/templates/be/patterns/jobs/platform-lite/jobs.index.ts.tpl +10 -0
  363. package/templates/be/patterns/jobs/platform-lite/jobs.sql.tpl +44 -0
  364. package/templates/be/patterns/jobs/platform-lite/persistence.jobs.sql.ts.tpl +33 -0
  365. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +203 -18
  366. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +78 -22
  367. package/templates/be/patterns/queues/platform/errors/queue.error.ts.tpl +19 -0
  368. package/templates/be/patterns/queues/platform/messages/queue.messages.ts.tpl +13 -0
  369. package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +1 -0
  370. package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +4 -0
  371. package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +2 -0
  372. package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +4 -4
  373. package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +14 -2
  374. package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +5 -2
  375. package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +72 -74
  376. package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +1 -1
  377. package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +23 -8
  378. package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +29 -8
  379. package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +7 -3
  380. package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +5 -0
  381. package/templates/be/patterns/queues/platform/queue.index.ts.tpl +2 -0
  382. package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +4 -0
  383. package/templates/be/patterns/queues/platform/queue.module.ts.tpl +2 -1
  384. package/templates/be/patterns/queues/platform/queue.port.ts.tpl +1 -1
  385. package/templates/be/patterns/queues/platform-lite/bullmq-queue-transport.client.spec.ts.tpl +417 -0
  386. package/templates/be/patterns/queues/platform-lite/bullmq-queue-transport.client.ts.tpl +172 -0
  387. package/templates/be/patterns/queues/platform-lite/persistence.queue.sql.ts.tpl +12 -0
  388. package/templates/be/patterns/queues/platform-lite/queue-outbox.sql.tpl +32 -0
  389. package/templates/be/patterns/queues/platform-lite/queue-relay.service.spec.ts.tpl +148 -0
  390. package/templates/be/patterns/queues/platform-lite/queue-relay.service.ts.tpl +51 -0
  391. package/templates/be/patterns/queues/platform-lite/queue-transport.port.ts.tpl +163 -0
  392. package/templates/be/patterns/queues/platform-lite/queue.config.ts.tpl +17 -0
  393. package/templates/be/patterns/queues/platform-lite/queue.error.ts.tpl +25 -0
  394. package/templates/be/patterns/queues/platform-lite/queue.index.ts.tpl +8 -0
  395. package/templates/be/patterns/queues/platform-lite/queue.messages.ts.tpl +21 -0
  396. package/templates/be/patterns/queues/platform-lite/queue.module.ts.tpl +74 -0
  397. package/templates/be/patterns/queues/platform-lite/queue.options.ts.tpl +38 -0
  398. package/templates/be/patterns/queues/queue.queue.ts.tpl +2 -2
  399. package/templates/be/patterns/reactors/application.contracts.ts.tpl +2 -0
  400. package/templates/be/patterns/reactors/consumer.ts.tpl +5 -1
  401. package/templates/be/platform/graphql/graphql.contracts.ts +2 -1
  402. package/templates/be/platform/graphql/localize-errors.mapper.spec.ts +1 -1
  403. package/templates/be/skeleton/apps/__app__/src/compose/platform.ts +6 -1
  404. package/templates/be/skeleton/apps/__app__/src/main.ts +7 -4
  405. package/templates/be/skeleton/apps/cli/src/compose/platform.ts +4 -0
  406. package/templates/be/skeleton/apps/cli/src/main.ts +7 -4
  407. package/templates/be/skeleton/src/modules/platform/database/index.ts +1 -1
  408. package/templates/be/skeleton/src/modules/platform/http/errors/http.error.ts +22 -0
  409. package/templates/be/skeleton/src/modules/platform/http/fetch-http-client.client.spec.ts +235 -0
  410. package/templates/be/skeleton/src/modules/platform/http/fetch-http-client.client.ts +85 -0
  411. package/templates/be/skeleton/src/modules/platform/http/graphql-call.mapper.spec.ts +92 -0
  412. package/templates/be/skeleton/src/modules/platform/http/graphql-call.mapper.ts +52 -0
  413. package/templates/be/skeleton/src/modules/platform/http/http.decorators.ts +9 -0
  414. package/templates/be/skeleton/src/modules/platform/http/http.module-definition.ts +7 -0
  415. package/templates/be/skeleton/src/modules/platform/http/http.module.ts +19 -0
  416. package/templates/be/skeleton/src/modules/platform/http/http.options.ts +2 -0
  417. package/templates/be/skeleton/src/modules/platform/http/http.port.ts +40 -0
  418. package/templates/be/skeleton/src/modules/platform/http/index.ts +7 -0
  419. package/templates/be/skeleton/src/modules/platform/http/messages/http.messages.ts +15 -0
  420. package/templates/be/skeleton/src/modules/platform/ids/ids.decorators.ts +9 -0
  421. package/templates/be/skeleton/src/modules/platform/ids/ids.module-definition.ts +7 -0
  422. package/templates/be/skeleton/src/modules/platform/ids/ids.module.ts +19 -0
  423. package/templates/be/skeleton/src/modules/platform/ids/ids.options.ts +2 -0
  424. package/templates/be/skeleton/src/modules/platform/ids/ids.port.ts +5 -0
  425. package/templates/be/skeleton/src/modules/platform/ids/index.ts +4 -0
  426. package/templates/be/skeleton/src/modules/platform/ids/system-ids.service.spec.ts +15 -0
  427. package/templates/be/skeleton/src/modules/platform/ids/system-ids.service.ts +10 -0
  428. package/templates/be/skeleton/src/modules/platform/logging/correlation-request.policy.spec.ts +59 -0
  429. package/templates/be/skeleton/src/modules/platform/logging/correlation-request.policy.ts +21 -0
  430. package/templates/be/skeleton/src/modules/platform/logging/correlation.contracts.ts +16 -0
  431. package/templates/be/skeleton/src/modules/platform/logging/correlation.policy.spec.ts +150 -0
  432. package/templates/be/skeleton/src/modules/platform/logging/correlation.policy.ts +42 -0
  433. package/templates/be/skeleton/src/modules/platform/logging/correlation.port.ts +15 -0
  434. package/templates/be/skeleton/src/modules/platform/logging/correlation.service.spec.ts +23 -0
  435. package/templates/be/skeleton/src/modules/platform/logging/correlation.service.ts +28 -0
  436. package/templates/be/skeleton/src/modules/platform/logging/index.ts +14 -1
  437. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +39 -6
  438. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +15 -3
  439. package/templates/be/skeleton/src/modules/platform/logging/logging.decorators.ts +17 -2
  440. package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +13 -1
  441. package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +13 -3
  442. package/templates/be/skeleton/src/modules/platform/logging/nest-logger.service.spec.ts +69 -0
  443. package/templates/be/skeleton/src/modules/platform/logging/nest-logger.service.ts +48 -0
  444. package/templates/be/skeleton/src/modules/platform/primitives/index.ts +1 -0
  445. package/templates/be/skeleton/src/modules/platform/primitives/record.policy.spec.ts +12 -0
  446. package/templates/be/skeleton/src/modules/platform/primitives/record.policy.ts +3 -0
  447. package/templates/be/skeleton-lite/apps/api/src/compose/platform.ts +6 -1
  448. package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +4 -0
  449. package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +1 -0
  450. package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +14 -1
  451. package/templates/be/skeleton-lite/src/modules/platform/logging/logging.log-events.ts +12 -0
  452. package/templates/be/skeleton-lite/src/modules/platform/primitives/index.ts +2 -0
  453. package/templates/be/test-world/world/test-apps.options.ts.tpl +2 -0
  454. package/templates/be/test-world/world/test-world.config.ts.tpl +1 -0
  455. package/upgrade/check.mjs +12 -135
  456. package/upgrade/file-state.mjs +1 -16
  457. package/upgrade/index.mjs +34 -361
  458. package/runtime/scripts/lib/check-code-loosening.mjs +0 -128
  459. package/runtime/scripts/lib/gate-loosening.mjs +0 -292
  460. package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +0 -89
  461. package/templates/app/upgrade-full/.starcistacks/dev/README.md +0 -16
  462. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +0 -13
  463. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +0 -3
  464. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +0 -12
  465. package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +0 -7
  466. package/templates/be/skeleton-lite/apps/api/src/main.ts +0 -26
  467. package/templates/be/upgrade-full/apps/cli/src/app.module.ts +0 -12
  468. package/templates/be/upgrade-full/apps/cli/src/cli.env.ts +0 -7
  469. package/templates/be/upgrade-full/apps/cli/src/compose/cli.ts +0 -5
  470. package/templates/be/upgrade-full/apps/cli/src/compose/platform.ts +0 -9
  471. package/templates/be/upgrade-full/apps/cli/src/main.ts +0 -29
  472. package/templates/be/upgrade-full/src/features/cli/cli.module.ts +0 -7
  473. package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +0 -23
@@ -0,0 +1,89 @@
1
+ // env-dump-verdict.mjs - the command guard's ENV_DUMP rule: a command that writes the WHOLE environment to output (`env`,
2
+ // `printenv`, bare `set`, `export -p`, `declare -x|-p`, `Get-ChildItem env:`, [Environment]::GetEnvironmentVariables(),
3
+ // `node -p process.env`, `python -c "print(os.environ)"`, `cmd /c set`). The environment carries every token and key the
4
+ // session holds (the AWS, Azure and Anthropic values reached a transcript through `env | grep ... | sed`); a filter or a
5
+ // redaction after the dump does not make it safe, because names outside the pattern leak. Reading ONE named variable
6
+ // (`echo $PATH`, `printenv HOME`, `$env:PATH`, process.env.HOME), `env VAR=x cmd`, `env -u VAR cmd` and shell options
7
+ // (`set -e`, `set -euo pipefail`) pass, and so does any text that only mentions these commands: the rule judges parsed
8
+ // commands, so an echo, a commit message, a heredoc or a comment never reaches it.
9
+ import { assignedCommand } from './assigned-command.mjs';
10
+
11
+ const ENV_DRIVE = /^env:[\\/]?\*?$/i;
12
+ const LISTERS = new Set(['get-childitem', 'gci', 'dir', 'ls', 'get-item', 'gi']);
13
+ const GET_ENV = /^\[(?:system\.)?environment\]::getenvironmentvariables$/i;
14
+ const NODE_PROGRAMS = new Set(['node', 'nodejs']);
15
+ const PYTHON_PROGRAMS = new Set(['python', 'python3', 'python2', 'py']);
16
+ // process.env as the whole argument of a printing or serialising call; or the whole value of `node -p`.
17
+ const NODE_WHOLE = new RegExp([
18
+ String.raw`(?:console\.\w+|JSON\.stringify|util\.inspect|\binspect|Object\.(?:keys|entries|values)|process\.std(?:out|err)\.write|require\(['"]fs['"]\)\.\w+|writeFileSync)`,
19
+ String.raw`\s*\(\s*(?:[^()]*,\s*)?process\.env\s*[,)]`,
20
+ ].join(''));
21
+ const NODE_PRINT_WHOLE = new RegExp([String.raw`^\s*`, String.raw`process\.env`, String.raw`\s*;?\s*$`].join(''));
22
+ const PYTHON_WHOLE = new RegExp([
23
+ String.raw`(?:\bprint|pprint|json\.dumps|\bdict|\blist|\bsorted|\brepr|\bstr)`,
24
+ String.raw`\s*\(\s*(?:[^()]*,\s*)?(?:os\.)?environ\s*[,)\]]|\benviron\.(?:items|keys|values|copy)\s*\(`,
25
+ ].join(''));
26
+ const PYTHON_OUTPUT = /\bprint\b|pprint|json\.dumps|stdout|\.write\(/;
27
+
28
+ const refusal = (c, how) => ({ code: 'ENV_DUMP', command: [c.program, ...c.args].join(' ').slice(0, 200),
29
+ reason: `${how} writes the whole environment to output, including every token and key the session holds; a grep or a redaction after it still leaks the names it does not match (the AWS, Azure and Anthropic values reached a transcript that way)`,
30
+ remedy: 'read only the one named, non-secret variable you need (echo $NAME, $env:NAME, printenv NAME); never dump the environment' });
31
+
32
+ const namesNothing = (args) => !args.some((a) => !a.startsWith('-'));
33
+ const scriptAfter = (args, flag) => { const at = args.findIndex((a) => flag.test(a)); return at >= 0 ? args[at + 1] ?? '' : null; };
34
+
35
+ // A relative path such as runtime/env is a file of that name, not the env program (an absolute path still is).
36
+ const isRelativeProgramPath = (word) => /[\\/]/.test(String(word ?? '')) && !/^(?:[a-z]:)?[\\/]/i.test(String(word));
37
+
38
+ // `declare`/`typeset` with no name lists every variable (no option, or -x / -p).
39
+ const declareListsAll = (args) => {
40
+ const options = args.filter((a) => /^-[a-zA-Z]+$/.test(a)).join('');
41
+ return namesNothing(args) && (!options || /[xp]/.test(options));
42
+ };
43
+
44
+ const declareDump = (c) => (declareListsAll(c.args) ? refusal(c, `${c.program} with no name`) : null);
45
+ const BUILTIN_DUMPS = new Map([
46
+ ['set', (c) => (c.args.length === 0 && c.dialect !== 'powershell' ? refusal(c, 'set') : null)],
47
+ ['export', (c) => (c.args.length === 0 || (c.args.length === 1 && c.args[0] === '-p') ? refusal(c, 'export -p') : null)],
48
+ ['declare', declareDump],
49
+ ['typeset', declareDump],
50
+ ]);
51
+
52
+ /** The shell-form dumpers (env/printenv/set/export/declare, PowerShell env: listers, GetEnvironmentVariables). */
53
+ const shellDumpVerdict = (c) => {
54
+ const { program, args } = c;
55
+ if ((program === 'env' || program === 'printenv') && !isRelativeProgramPath(c.word)) return namesNothing(args) ? refusal(c, program) : null;
56
+ const builtin = BUILTIN_DUMPS.get(program);
57
+ if (builtin) return builtin(c);
58
+ if (LISTERS.has(program) && args.some((a) => ENV_DRIVE.test(a))) return refusal(c, `${program} env:`);
59
+ if (GET_ENV.test(program)) return refusal(c, '[Environment]::GetEnvironmentVariables()');
60
+ return null;
61
+ };
62
+
63
+ /** `node -p|-e` whose script body prints or serializes process.env whole. */
64
+ const nodeDumpHow = (args) => {
65
+ const print = scriptAfter(args, /^(?:-p|--print)$/);
66
+ const evalOnly = scriptAfter(args, /^(?:-e|--eval)$/);
67
+ const body = print ?? evalOnly;
68
+ return body != null && (NODE_WHOLE.test(body) || (print != null && NODE_PRINT_WHOLE.test(body))) ? 'a node script printing process.env' : null;
69
+ };
70
+
71
+ /** `python -c` whose script body prints os.environ. */
72
+ const pythonDumpHow = (args) => {
73
+ const body = scriptAfter(args, /^-c$/);
74
+ return body != null && PYTHON_WHOLE.test(body) && PYTHON_OUTPUT.test(body) ? 'a python script printing os.environ' : null;
75
+ };
76
+
77
+ /** The ENV_DUMP refusal for one parsed command, or null. */
78
+ const interpreterDumpVerdict = (c) => {
79
+ if (NODE_PROGRAMS.has(c.program)) { const how = nodeDumpHow(c.args); if (how) return refusal(c, how); }
80
+ if (PYTHON_PROGRAMS.has(c.program)) { const how = pythonDumpHow(c.args); if (how) return refusal(c, how); }
81
+ return null;
82
+ };
83
+
84
+ export function envDumpVerdict(parsed) {
85
+ const c = assignedCommand(parsed);
86
+ const shell = shellDumpVerdict(c);
87
+ if (shell) return shell;
88
+ return interpreterDumpVerdict(c);
89
+ }
@@ -0,0 +1,225 @@
1
+ // git-pathspec.mjs — the git argv and pathspec machinery of the shared-checkout policy
2
+ // (git-policy.mjs): splitting `git [global options] <sub> <args...>`, reading pathspecs
3
+ // (including --pathspec-from-file lists) the way git does, and the literal reading of App
4
+ // Router segments (engine/admission.mjs isAppRouterSegment). Pure: argv and text in, parts out.
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { isAppRouterSegment } from '../../engine/admission.mjs';
8
+ import { pathKey } from '../lib/path-key.mjs';
9
+
10
+ // git's global options that consume the next argument.
11
+ const GLOBAL_WITH_VALUE = new Set(['-C', '-c', '--git-dir', '--work-tree', '--namespace', '--exec-path', '--super-prefix', '--config-env', '--attr-source']);
12
+
13
+ // The global options of `git [global options] <sub>`: -C dirs are applied to cwd
14
+ // in order, like git does; -c/--config-env collect their <name>=<value>.
15
+ const scanGlobalArgs = (args, dir) => {
16
+ const config = [];
17
+ let i = 0;
18
+ while (i < args.length) {
19
+ const a = args[i];
20
+ if (a === '-C' && i + 1 < args.length) { dir = path.resolve(dir, args[i + 1]); i += 2; continue; }
21
+ // --config-env <name>=<envvar>: the key is what matters, whatever the variable holds.
22
+ if ((a === '-c' || a === '--config-env') && i + 1 < args.length) { config.push(args[i + 1]); i += 2; continue; }
23
+ if (a.startsWith('--config-env=')) { config.push(a.slice('--config-env='.length)); i += 1; continue; }
24
+ if (GLOBAL_WITH_VALUE.has(a) && i + 1 < args.length) { i += 2; continue; }
25
+ if (a.startsWith('-')) { i += 1; continue; }
26
+ break;
27
+ }
28
+ return { dir, config, i };
29
+ };
30
+
31
+ // Split `git [global options] <sub> <args...>` into its parts; -C dirs are
32
+ // applied to cwd in order, like git does.
33
+ export function parseGitArgv(argv, cwd = process.cwd()) {
34
+ const args = [...argv].map(String);
35
+ const { dir, config, i } = scanGlobalArgs(args, cwd);
36
+ return { cwd: dir, config, sub: args[i] ?? null, rest: args.slice(i + 1) };
37
+ }
38
+
39
+ const norm = pathKey;
40
+ // git's glob characters. A Next.js App Router segment (`[locale]`, `[...slug]`, `[[...opt]]`, `(.)[id]`)
41
+ // carries `[` but is a literal directory name - the reading owned-path admission gives it
42
+ // (engine/admission.mjs isAppRouterSegment, ownedPathspec). Cutting every pathspec at its first `[`
43
+ // scoped `src/app/[locale]/x` to `src/app/`, outside the grant `src/app/[locale]`, and refused the op's
44
+ // own paths PATH_NOT_OWNED. Git, though, still reads a plain `[...slug]` as a
45
+ // character class (`src/app/[...slug]/page.tsx` also matches a peer's `src/app/l/page.tsx`), so a pathspec
46
+ // the guard reads literally must reach git literally too: the command guard (command-guard.mjs) refuses a
47
+ // command whose glob reading reaches a path the literal reading does not, naming the literalAppRouterArgv form. A pathspec that also carries a real glob, or `:(glob)` magic, keeps git's glob
48
+ // reading and is scoped from before its first glob character, App Router segment or not.
49
+ const GIT_GLOB = /[*?[]/;
50
+ const PATHSPEC_MAGIC = /^:(\([^)]*\)|[/!^]*)/;
51
+ const segmentsOf = (s) => s.split(/[/\\]/);
52
+ // {names, long, rest}: the magic words of a pathspec (short `:/`, `:!`, `:^` spelled as top/exclude) and its path.
53
+ function pathspecMagic(spec) {
54
+ const s = String(spec);
55
+ const magic = PATHSPEC_MAGIC.exec(s);
56
+ if (!magic) return { names: [], long: null, rest: s };
57
+ const m = magic[1];
58
+ const names = m.startsWith('(')
59
+ ? m.slice(1, -1).split(',').map((w) => w.trim().split(':')[0]).filter(Boolean)
60
+ : [...new Set([...m].map((c) => (c === '/' ? 'top' : 'exclude')))];
61
+ return { names, long: m.startsWith('(') ? m.slice(1, -1) : null, rest: s.slice(magic[0].length) };
62
+ }
63
+ // Whether git reads this pathspec path as a glob that the literal reading would not give.
64
+ const readsAsGlob = (rest, names) => segmentsOf(rest).some((seg) => GIT_GLOB.test(seg) && (names.includes('glob') || !isAppRouterSegment(seg)));
65
+ /**
66
+ * The pathspec git must be given for the guard's literal reading to hold: one whose App Router segments are
67
+ * its only glob characters gains `literal` magic (`src/app/[locale]/x` -> `:(literal)src/app/[locale]/x`,
68
+ * `:/src/app/[id]` -> `:(top,literal)src/app/[id]`); every other pathspec is returned unchanged.
69
+ */
70
+ export function literalPathspec(spec) {
71
+ const s = String(spec);
72
+ const { names, long, rest } = pathspecMagic(s);
73
+ if (names.includes('literal') || names.includes('glob') || readsAsGlob(rest, names)) return s;
74
+ if (!segmentsOf(rest).some(isAppRouterSegment)) return s;
75
+ if (!s.startsWith(':')) return `:(literal)${s}`;
76
+ return `:(${[...(long != null ? [long] : names), 'literal'].filter(Boolean).join(',')})${rest}`;
77
+ }
78
+ // The literal directory a pathspec names: magic prefixes stripped, the segments
79
+ // before the first glob segment kept. `:/` and `:(top)` name the root.
80
+ const pathspecBase = (spec, cwd, top) => {
81
+ const { names, rest } = pathspecMagic(spec);
82
+ let s = rest;
83
+ const base = names.includes('top') ? top ?? cwd : cwd;
84
+ if (names.includes('exclude')) return null; // an exclusion narrows, never widens
85
+ // :(literal)src/app/[id] names exactly that path; so does src/app/[id], whose glob reading the command guard checks
86
+ if (!names.includes('literal') && readsAsGlob(rest, names)) {
87
+ const segments = segmentsOf(s);
88
+ s = segments.slice(0, segments.findIndex((seg) => GIT_GLOB.test(seg))).join('/');
89
+ }
90
+ return path.resolve(base, s || '.');
91
+ };
92
+
93
+ /** True when every pathspec names a place inside one owned path (absolute owned roots). */
94
+ export function pathspecsWithinOwned(specs, { cwd, owned, top = null }) {
95
+ if (!Array.isArray(owned) || !owned.length) return { ok: false, outside: [...specs] };
96
+ const roots = owned.map((p) => norm(p));
97
+ const outside = [];
98
+ for (const spec of specs) {
99
+ const base = pathspecBase(spec, cwd, top);
100
+ if (base === null) continue;
101
+ const n = norm(base);
102
+ if (!roots.some((r) => n === r || n.startsWith(`${r}/`))) outside.push(spec);
103
+ }
104
+ return { ok: outside.length === 0, outside };
105
+ }
106
+
107
+ // --pathspec-from-file=<file> (or <file> as the next word; `-` is stdin) with --pathspec-file-nul:
108
+ // the pathspecs of add, commit, reset, restore, checkout and rm live in a file (inc-d1833bc89c1f). The
109
+ // guard reads the list the way git does and scopes every entry exactly like an explicit pathspec.
110
+ export const PATHSPEC_FILE = '--pathspec-from-file';
111
+ export const PATHSPEC_FILE_SUBS = new Set(['add', 'commit', 'reset', 'restore', 'checkout', 'rm', 'stash']);
112
+ export function takePathspecFile(rest) {
113
+ const out = [];
114
+ let file = null, nul = false;
115
+ for (let i = 0; i < rest.length; i += 1) {
116
+ const a = rest[i];
117
+ if (a === '--') { out.push(...rest.slice(i)); break; }
118
+ if (a === PATHSPEC_FILE && i + 1 < rest.length) { file = rest[i + 1]; i += 1; continue; }
119
+ if (a.startsWith(`${PATHSPEC_FILE}=`)) { file = a.slice(PATHSPEC_FILE.length + 1); continue; }
120
+ if (a === '--pathspec-file-nul') { nul = true; continue; }
121
+ out.push(a);
122
+ }
123
+ return { rest: out, file, nul };
124
+ }
125
+ // git's C-style quoting of a pathspec line (core.quotePath); null when badly quoted.
126
+ const C_ESCAPES = { a: 7, b: 8, f: 12, n: 10, r: 13, t: 9, v: 11, '\\': 92, '"': 34 };
127
+ function unquoteC(line) {
128
+ if (!line.startsWith('"')) return line;
129
+ const bytes = [];
130
+ for (let i = 1; i < line.length; i += 1) {
131
+ const c = line[i];
132
+ if (c === '"') return i === line.length - 1 ? Buffer.from(bytes).toString('utf8') : null;
133
+ if (c !== '\\') { bytes.push(...Buffer.from(c, 'utf8')); continue; }
134
+ const n = line[i + 1];
135
+ if (n in C_ESCAPES) { bytes.push(C_ESCAPES[n]); i += 1; continue; }
136
+ const oct = line.slice(i + 1, i + 4);
137
+ if (/^[0-3][0-7]{2}$/.test(oct)) { bytes.push(Number.parseInt(oct, 8)); i += 3; continue; }
138
+ return null;
139
+ }
140
+ return null;
141
+ }
142
+ /** The pathspecs of a --pathspec-from-file list, split like git's parse_pathspec_file. */
143
+ export function parsePathspecList(text, nul = false) {
144
+ const items = String(text ?? '').split(nul ? '\0' : '\n');
145
+ if (items.length && items.at(-1) === '') items.pop();
146
+ if (nul) return items;
147
+ // A badly quoted line stays raw: it names no owned path, so it is refused (git itself dies on it).
148
+ return items.map((l) => (l.endsWith('\r') ? l.slice(0, -1) : l)).map((l) => unquoteC(l) ?? l);
149
+ }
150
+ // The file resolves against the command's directory (git's OPT_FILENAME); `-` is stdin (ctx.stdin), which the
151
+ // command guard never sees before the command runs, so a stdin list is refused with the list-file remedy.
152
+ export const readPathspecFile = (file, dir, stdin) => {
153
+ if (file === '-') return stdin == null ? null : String(stdin);
154
+ try { return fs.readFileSync(path.resolve(dir, file), 'utf8'); } catch { return null; }
155
+ };
156
+
157
+ // The pathspec positions of the path-scoped subcommands: everything after `--` and a pathspec list; before
158
+ // `--`, the words of the commands whose words are pathspecs (reset and checkout words are revisions),
159
+ // skipping the values of their options.
160
+ const LITERAL_SUBS = new Set(['add', 'commit', 'reset', 'restore', 'checkout', 'rm', 'clean']);
161
+ const WORD_PATHSPEC_SUBS = new Set(['add', 'commit', 'restore', 'rm', 'clean']);
162
+ const SUB_VALUE_OPTIONS = { restore: new Set(['-s', '--source']), clean: new Set(['-e', '--exclude']) };
163
+ // `git commit -m msg path`: the word after -m/-F/-C/-c/--author... is a value, not a pathspec.
164
+ export const VALUE_OPTIONS = new Set(['-m', '--message', '-F', '--file', '-C', '--reuse-message', '-c', '--reedit-message', '--author', '--date', '-t', '--template', '--cleanup', '--fixup', '--squash', '--trailer', '-S', '--gpg-sign']);
165
+
166
+ const LIST = Symbol('pathspec list');
167
+ // One rest token of literalAppRouterArgv: pathspecs are literal-ized, option values skipped, and the
168
+ // --pathspec-from-file markers kept as LIST placeholders for the rewritten list file. Returns how many
169
+ // extra tokens the token consumed (an option value or the list file name).
170
+ const takeLiteralArg = (st, a, i, rest) => {
171
+ if (st.dashDash) { st.out.push(st.lit(a)); return 0; }
172
+ if (a === '--') { st.dashDash = true; st.out.push(a); return 0; }
173
+ if (a === PATHSPEC_FILE && i + 1 < rest.length) { st.file = rest[i + 1]; st.out.push({ [LIST]: [a, rest[i + 1]] }); return 1; }
174
+ if (a.startsWith(`${PATHSPEC_FILE}=`)) { st.file = a.slice(PATHSPEC_FILE.length + 1); st.out.push({ [LIST]: [a] }); return 0; }
175
+ if (a === '--pathspec-file-nul') { st.nul = true; st.out.push({ [LIST]: [a] }); return 0; }
176
+ if (a.startsWith('-')) {
177
+ st.out.push(a);
178
+ if (st.values.has(a) && i + 1 < rest.length) { st.out.push(rest[i + 1]); return 1; }
179
+ return 0;
180
+ }
181
+ st.out.push(WORD_PATHSPEC_SUBS.has(st.sub) ? st.lit(a) : a);
182
+ return 0;
183
+ };
184
+ /**
185
+ * literalAppRouterArgv(argv, {cwd, stdin, listFile}) -> {argv, list, changed}: the argv with which git reads every
186
+ * pathspec the way the guard scoped it (literalPathspec on each pathspec position). A --pathspec-from-file list
187
+ * with such a pathspec comes back as `list` (NUL-separated text) for the caller to write to `listFile`, which the argv then names with --pathspec-file-nul. Anything else passes
188
+ * byte for byte.
189
+ */
190
+ export function literalAppRouterArgv(argv, { cwd = process.cwd(), stdin = null, listFile = null } = {}) {
191
+ const args = [...argv].map(String);
192
+ const { cwd: dir, sub, rest } = parseGitArgv(args, cwd);
193
+ if (!LITERAL_SUBS.has(sub)) return { argv: args, list: null, changed: false };
194
+ const head = args.slice(0, args.length - rest.length);
195
+ const values = sub === 'commit' ? VALUE_OPTIONS : SUB_VALUE_OPTIONS[sub] ?? new Set();
196
+ let changed = false;
197
+ const lit = (a) => { const l = literalPathspec(a); if (l !== a) { changed = true; } return l; };
198
+ const st = { out: [], file: null, nul: false, dashDash: false, values, sub, lit };
199
+ for (let i = 0; i < rest.length; i += 1) i += takeLiteralArg(st, rest[i], i, rest);
200
+ let list = null;
201
+ if (st.file != null && listFile && PATHSPEC_FILE_SUBS.has(sub)) {
202
+ const text = readPathspecFile(st.file, dir, stdin);
203
+ const specs = text == null ? [] : parsePathspecList(text, st.nul);
204
+ const literal = specs.map(literalPathspec);
205
+ if (literal.some((l, k) => l !== specs[k])) { list = literal.map((l) => `${l}\0`).join(''); changed = true; }
206
+ }
207
+ let named = false;
208
+ const flat = st.out.flatMap((a) => {
209
+ if (typeof a === 'string') return [a];
210
+ if (list == null) return a[LIST];
211
+ if (named) return [];
212
+ named = true;
213
+ return [`${PATHSPEC_FILE}=${listFile}`, '--pathspec-file-nul'];
214
+ });
215
+ return { argv: [...head, ...flat], list, changed };
216
+ }
217
+
218
+ // `--pathspec-from-file=-` (or `--pathspec-from-file -`) before a bare `--`: the list is on stdin.
219
+ export function pathspecListOnStdin(args) {
220
+ for (let i = 0; i < args.length; i += 1) {
221
+ if (args[i] === '--') return false;
222
+ if (args[i] === '--pathspec-from-file=-' || (args[i] === '--pathspec-from-file' && args[i + 1] === '-')) return true;
223
+ }
224
+ return false;
225
+ }