@starci/hfs 4.11.21 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +31 -31
- package/ci/cli.d.mts +15 -0
- package/ci/cli.mjs +71 -52
- package/ci/github.d.mts +43 -0
- package/ci/github.mjs +33 -28
- package/ci/local.d.mts +12 -0
- package/ci/local.mjs +145 -108
- package/ci/secret.d.mts +15 -0
- package/ci/secret.mjs +31 -21
- package/ci/vars.d.mts +17 -0
- package/ci/vars.mjs +47 -33
- package/ci/verify.d.mts +18 -0
- package/ci/verify.mjs +52 -40
- package/codemod/button-intent.d.mts +63 -0
- package/codemod/button-intent.mjs +338 -285
- package/coverage/cli.d.mts +28 -0
- package/coverage/cli.mjs +65 -51
- package/db/backup-receipt.d.mts +28 -0
- package/db/backup-receipt.mjs +78 -58
- package/db/drift.d.mts +86 -0
- package/db/drift.mjs +213 -180
- package/db/dump.d.mts +52 -0
- package/db/dump.mjs +63 -56
- package/db/entity-list.d.mts +4 -0
- package/db/entity-list.mjs +0 -2
- package/db/image.d.mts +8 -0
- package/db/image.mjs +1 -2
- package/db/migrate.d.mts +104 -0
- package/db/migrate.mjs +207 -167
- package/db/new.d.mts +11 -0
- package/db/new.mjs +25 -25
- package/db/post-cutover.d.mts +5 -0
- package/db/post-cutover.mjs +89 -82
- package/db/postgres.d.mts +71 -0
- package/db/postgres.mjs +62 -61
- package/emit/compiler.d.mts +3 -0
- package/emit/compiler.mjs +25 -27
- package/emit/contracts.d.mts +35 -0
- package/emit/contracts.mjs +46 -50
- package/emit/events.d.mts +9 -0
- package/emit/events.mjs +19 -20
- package/emit/form-bounds.d.mts +83 -0
- package/emit/form-bounds.mjs +133 -117
- package/emit/graphql-input-bounds.d.mts +63 -0
- package/emit/graphql-input-bounds.mjs +90 -79
- package/emit/input-bounds.d.mts +30 -0
- package/emit/input-bounds.mjs +29 -27
- package/emit/operation-schemas.d.mts +24 -0
- package/emit/operation-schemas.mjs +136 -116
- package/emit/operations-worker.d.mts +1 -0
- package/emit/operations-worker.mjs +9 -7
- package/emit/operations.d.mts +47 -0
- package/emit/operations.mjs +124 -133
- package/emit/schema-worker.d.mts +1 -0
- package/emit/schema-worker.mjs +57 -50
- package/emit/static-graph.d.mts +48 -0
- package/emit/static-graph.mjs +766 -640
- package/emit/type-schema.d.mts +29 -0
- package/emit/type-schema.mjs +153 -140
- package/lint/bound-sys.cjs +27 -33
- package/lint/chunk.d.mts +17 -0
- package/lint/chunk.mjs +41 -31
- package/lint/run.d.mts +120 -0
- package/lint/run.mjs +415 -322
- package/package.json +21 -4
- package/release/candidate-ci.d.mts +46 -0
- package/release/candidate-ci.mjs +76 -70
- package/release/gate.d.mts +120 -0
- package/release/gate.mjs +358 -330
- package/release/index.d.mts +68 -0
- package/release/index.mjs +95 -73
- package/release/lint-report.d.mts +14 -0
- package/release/lint-report.mjs +33 -32
- package/release/push.d.mts +32 -0
- package/release/push.mjs +92 -79
- package/release/records.d.mts +18 -0
- package/release/records.mjs +22 -21
- package/release/sonar-quality-gate.d.mts +18 -0
- package/release/sonar-quality-gate.mjs +60 -52
- package/release/urgent.d.mts +20 -0
- package/release/urgent.mjs +76 -74
- package/report/order.d.mts +1 -0
- package/report/sonar.d.mts +73 -0
- package/report/sonar.mjs +82 -89
- package/runtime/engine/admission.d.mts +209 -0
- package/runtime/engine/admission.mjs +225 -204
- package/runtime/engine/by-code-unit.d.mts +5 -0
- package/runtime/engine/by-code-unit.mjs +6 -6
- package/runtime/engine/config.d.mts +333 -0
- package/runtime/engine/config.mjs +486 -328
- package/runtime/engine/db/blob.d.mts +83 -0
- package/runtime/engine/db/blob.mjs +344 -268
- package/runtime/engine/db/event-compact.d.mts +21 -0
- package/runtime/engine/db/event-compact.mjs +34 -38
- package/runtime/engine/db/machine-connection.d.mts +68 -0
- package/runtime/engine/db/machine-connection.mjs +166 -119
- package/runtime/engine/db/machine-open.d.mts +26 -0
- package/runtime/engine/db/machine-open.mjs +59 -45
- package/runtime/engine/db/machine-schema.d.mts +34 -0
- package/runtime/engine/db/machine-schema.mjs +102 -83
- package/runtime/engine/db/machine.d.mts +1746 -0
- package/runtime/engine/db/machine.mjs +1040 -734
- package/runtime/engine/db/provider-reservations.d.mts +169 -0
- package/runtime/engine/db/provider-reservations.mjs +141 -119
- package/runtime/engine/db/provision-lock.d.mts +23 -0
- package/runtime/engine/db/provision-lock.mjs +14 -14
- package/runtime/engine/db/ref-value.d.mts +19 -0
- package/runtime/engine/db/ref-value.mjs +36 -35
- package/runtime/engine/db/sqlite-types.d.mts +28 -0
- package/runtime/engine/db/sqlite-types.mjs +4 -0
- package/runtime/engine/digest.d.mts +4 -0
- package/runtime/engine/digest.mjs +16 -7
- package/runtime/engine/invalid-config.d.mts +13 -0
- package/runtime/engine/invalid-config.mjs +17 -11
- package/runtime/engine/model-config.d.mts +91 -0
- package/runtime/engine/model-config.mjs +98 -76
- package/runtime/engine/orca-config.d.mts +26 -0
- package/runtime/engine/orca-config.mjs +22 -17
- package/runtime/engine/plain-object.d.mts +2 -0
- package/runtime/engine/refuse.d.mts +9 -0
- package/runtime/engine/refuse.mjs +3 -6
- package/runtime/engine/release-config.d.mts +19 -0
- package/runtime/engine/release-config.mjs +22 -18
- package/runtime/engine/removed-vocabulary.d.mts +12 -0
- package/runtime/engine/removed-vocabulary.mjs +21 -20
- package/runtime/engine/resources-config.d.mts +34 -0
- package/runtime/engine/resources-config.mjs +42 -35
- package/runtime/engine/runtime-root.d.mts +28 -0
- package/runtime/engine/runtime-root.mjs +11 -13
- package/runtime/engine/secrets.d.mts +41 -0
- package/runtime/engine/secrets.mjs +170 -102
- package/runtime/engine/sonar-config.d.mts +10 -0
- package/runtime/engine/sonar-config.mjs +16 -13
- package/runtime/engine/temp-root.d.mts +17 -0
- package/runtime/engine/temp-root.mjs +3 -9
- package/runtime/engine/yaml.d.mts +9 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +10 -10
- package/runtime/knowledge/hfs/ci-standard.yaml +2 -2
- package/runtime/knowledge/hfs/rules.yaml +72 -6
- package/runtime/knowledge/hfs/slots.yaml +3 -3
- package/runtime/knowledge/sonar-gate.yaml +1 -1
- package/runtime/modules/kernel/failure-codes.yaml +43 -32
- package/runtime/modules/schemas/application-stacks.schema.yaml +3 -3
- package/runtime/packages/cli/src/catalog.generated.d.mts +13 -0
- package/runtime/packages/cli/src/catalog.generated.mjs +1853 -14824
- package/runtime/packages/cli/src/validate-args.d.mts +74 -0
- package/runtime/packages/cli/src/validate-args.mjs +183 -171
- package/runtime/packages/jest-preset/sonar-exclusions.cjs +5 -5
- package/runtime/scripts/api/fs/claim-file.d.mts +12 -0
- package/runtime/scripts/api/fs/claim-file.mjs +31 -17
- package/runtime/scripts/api/fs/ensure-temp-root.d.mts +4 -0
- package/runtime/scripts/api/fs/ensure-temp-root.mjs +15 -14
- package/runtime/scripts/api/fs/forbidden-root.d.mts +15 -0
- package/runtime/scripts/api/fs/forbidden-root.mjs +31 -23
- package/runtime/scripts/api/fs/is-link-like.d.mts +10 -0
- package/runtime/scripts/api/fs/is-link-like.mjs +25 -11
- package/runtime/scripts/api/fs/lib.d.mts +12 -0
- package/runtime/scripts/api/fs/lib.mjs +28 -8
- package/runtime/scripts/api/fs/make-temp-dir.d.mts +5 -0
- package/runtime/scripts/api/fs/make-temp-dir.mjs +3 -4
- package/runtime/scripts/api/fs/rename-over.d.mts +13 -0
- package/runtime/scripts/api/fs/rename-over.mjs +16 -10
- package/runtime/scripts/api/fs/safe-remove.d.mts +25 -0
- package/runtime/scripts/api/fs/safe-remove.mjs +129 -71
- package/runtime/scripts/api/git/add.d.mts +3 -0
- package/runtime/scripts/api/git/add.mjs +0 -1
- package/runtime/scripts/api/git/cat-file.d.mts +3 -0
- package/runtime/scripts/api/git/cat-file.mjs +0 -1
- package/runtime/scripts/api/git/check-ignore.d.mts +3 -0
- package/runtime/scripts/api/git/check-ignore.mjs +0 -1
- package/runtime/scripts/api/git/commit-tree.d.mts +3 -0
- package/runtime/scripts/api/git/commit-tree.mjs +0 -1
- package/runtime/scripts/api/git/config-get.d.mts +10 -0
- package/runtime/scripts/api/git/config-get.mjs +1 -2
- package/runtime/scripts/api/git/diff.d.mts +3 -0
- package/runtime/scripts/api/git/diff.mjs +0 -1
- package/runtime/scripts/api/git/init.d.mts +7 -0
- package/runtime/scripts/api/git/init.mjs +1 -2
- package/runtime/scripts/api/git/is-ancestor.d.mts +5 -0
- package/runtime/scripts/api/git/is-ancestor.mjs +0 -1
- package/runtime/scripts/api/git/lib.d.mts +67 -0
- package/runtime/scripts/api/git/lib.mjs +32 -32
- package/runtime/scripts/api/git/ls-files.d.mts +3 -0
- package/runtime/scripts/api/git/ls-files.mjs +0 -1
- package/runtime/scripts/api/git/ls-tree.d.mts +3 -0
- package/runtime/scripts/api/git/ls-tree.mjs +0 -1
- package/runtime/scripts/api/git/merge-base.d.mts +5 -0
- package/runtime/scripts/api/git/merge-base.mjs +2 -3
- package/runtime/scripts/api/git/remote.d.mts +3 -0
- package/runtime/scripts/api/git/remote.mjs +0 -1
- package/runtime/scripts/api/git/rev-parse-query.d.mts +3 -0
- package/runtime/scripts/api/git/rev-parse-query.mjs +0 -1
- package/runtime/scripts/api/git/show.d.mts +3 -0
- package/runtime/scripts/api/git/show.mjs +0 -1
- package/runtime/scripts/api/git/tag.d.mts +3 -0
- package/runtime/scripts/api/git/tag.mjs +0 -1
- package/runtime/scripts/api/git/update-ref.d.mts +7 -0
- package/runtime/scripts/api/git/update-ref.mjs +1 -2
- package/runtime/scripts/api/git/write-tree.d.mts +3 -0
- package/runtime/scripts/api/git/write-tree.mjs +0 -1
- package/runtime/scripts/api/node/lib.d.mts +7 -0
- package/runtime/scripts/api/node/lib.mjs +17 -7
- package/runtime/scripts/api/node/run-node.d.mts +3 -0
- package/runtime/scripts/api/node/run-node.mjs +0 -3
- package/runtime/scripts/api/process/resolve-real-tool.d.mts +12 -0
- package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -38
- package/runtime/scripts/api/process/run-program.d.mts +3 -0
- package/runtime/scripts/api/process/run-program.mjs +5 -2
- package/runtime/scripts/api/sops/decrypt.d.mts +9 -0
- package/runtime/scripts/api/sops/decrypt.mjs +1 -2
- package/runtime/scripts/api/sops/lib.d.mts +149 -0
- package/runtime/scripts/api/sops/lib.mjs +417 -318
- package/runtime/scripts/api/sops/resolve-sops.d.mts +3 -0
- package/runtime/scripts/api/sops/resolve-sops.mjs +1 -2
- package/runtime/scripts/api/sops/seal.d.mts +19 -0
- package/runtime/scripts/api/sops/seal.mjs +14 -10
- package/runtime/scripts/api/sops/selected-age-recipient.d.mts +3 -0
- package/runtime/scripts/api/sops/selected-age-recipient.mjs +1 -2
- package/runtime/scripts/api/sops/update-keys.d.mts +16 -0
- package/runtime/scripts/api/sops/update-keys.mjs +11 -8
- package/runtime/scripts/cli/gen-catalog.d.mts +42 -0
- package/runtime/scripts/cli/gen-catalog.mjs +72 -0
- package/runtime/scripts/gates/runtime-host.d.mts +23 -0
- package/runtime/scripts/gates/runtime-host.mjs +48 -41
- package/runtime/scripts/gates/sonar-gate.d.mts +219 -0
- package/runtime/scripts/gates/sonar-gate.mjs +166 -153
- package/runtime/scripts/gates/starcistacks-ci.d.mts +35 -0
- package/runtime/scripts/gates/starcistacks-ci.mjs +47 -39
- package/runtime/scripts/gates/starcistacks-form.d.mts +80 -0
- package/runtime/scripts/gates/starcistacks-form.mjs +16 -14
- package/runtime/scripts/gates/starcistacks-runtime.d.mts +1 -0
- package/runtime/scripts/gates/starcistacks-value-file.d.mts +2 -0
- package/runtime/scripts/gates/starcistacks-value-file.mjs +14 -11
- package/runtime/scripts/gates/starcistacks.d.mts +141 -0
- package/runtime/scripts/gates/starcistacks.mjs +470 -355
- package/runtime/scripts/guards/git-pathspec.d.mts +48 -0
- package/runtime/scripts/guards/git-pathspec.mjs +215 -130
- package/runtime/scripts/guards/git-policy.d.mts +30 -0
- package/runtime/scripts/guards/git-policy.mjs +278 -235
- package/runtime/scripts/guards/hook-io.d.mts +22 -0
- package/runtime/scripts/guards/hook-io.mjs +77 -63
- package/runtime/scripts/guards/push-scan.d.mts +31 -0
- package/runtime/scripts/guards/push-scan.mjs +93 -80
- package/runtime/scripts/guards/release-push-gate.d.mts +22 -0
- package/runtime/scripts/guards/release-push-gate.mjs +40 -38
- package/runtime/scripts/hfs/allows.d.mts +24 -0
- package/runtime/scripts/hfs/allows.mjs +37 -38
- package/runtime/scripts/hfs/app-wiring.d.mts +72 -0
- package/runtime/scripts/hfs/app-wiring.mjs +197 -167
- package/runtime/scripts/hfs/architecture/ast-walks.d.mts +89 -0
- package/runtime/scripts/hfs/architecture/ast-walks.mjs +180 -163
- package/runtime/scripts/hfs/architecture/automatic-gates.d.mts +21 -0
- package/runtime/scripts/hfs/architecture/automatic-gates.mjs +80 -73
- package/runtime/scripts/hfs/architecture/backend-app-files.d.mts +10 -0
- package/runtime/scripts/hfs/architecture/backend-app-files.mjs +88 -77
- package/runtime/scripts/hfs/architecture/backend.d.mts +5 -0
- package/runtime/scripts/hfs/architecture/backend.mjs +378 -357
- package/runtime/scripts/hfs/architecture/background-unowned.d.mts +25 -0
- package/runtime/scripts/hfs/architecture/background-unowned.mjs +201 -187
- package/runtime/scripts/hfs/architecture/canon-clones.d.mts +8 -0
- package/runtime/scripts/hfs/architecture/canon-clones.mjs +260 -209
- package/runtime/scripts/hfs/architecture/canon-jsx-clones.d.mts +5 -0
- package/runtime/scripts/hfs/architecture/canon-jsx-clones.mjs +149 -116
- package/runtime/scripts/hfs/architecture/client-reaches-server.d.mts +28 -0
- package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +72 -68
- package/runtime/scripts/hfs/architecture/clones.d.mts +54 -0
- package/runtime/scripts/hfs/architecture/clones.mjs +212 -217
- package/runtime/scripts/hfs/architecture/config-unread.d.mts +14 -0
- package/runtime/scripts/hfs/architecture/config-unread.mjs +7 -9
- package/runtime/scripts/hfs/architecture/config.d.mts +74 -0
- package/runtime/scripts/hfs/architecture/config.mjs +302 -268
- package/runtime/scripts/hfs/architecture/connection-map.d.mts +33 -0
- package/runtime/scripts/hfs/architecture/connection-map.mjs +258 -225
- package/runtime/scripts/hfs/architecture/constructor-deps.d.mts +57 -0
- package/runtime/scripts/hfs/architecture/constructor-deps.mjs +80 -71
- package/runtime/scripts/hfs/architecture/context-coupling.d.mts +21 -0
- package/runtime/scripts/hfs/architecture/context-coupling.mjs +82 -77
- package/runtime/scripts/hfs/architecture/context-map.d.mts +102 -0
- package/runtime/scripts/hfs/architecture/context-map.mjs +267 -234
- package/runtime/scripts/hfs/architecture/context-owner.d.mts +15 -0
- package/runtime/scripts/hfs/architecture/context-owner.mjs +73 -61
- package/runtime/scripts/hfs/architecture/context-platform-tables.d.mts +18 -0
- package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -43
- package/runtime/scripts/hfs/architecture/context-transaction.d.mts +20 -0
- package/runtime/scripts/hfs/architecture/context-transaction.mjs +54 -52
- package/runtime/scripts/hfs/architecture/contract-fixture-guard.d.mts +37 -0
- package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +113 -104
- package/runtime/scripts/hfs/architecture/contracts-readonly.d.mts +32 -0
- package/runtime/scripts/hfs/architecture/contracts-readonly.mjs +288 -270
- package/runtime/scripts/hfs/architecture/contracts.d.mts +30 -0
- package/runtime/scripts/hfs/architecture/contracts.mjs +408 -393
- package/runtime/scripts/hfs/architecture/cross-app-duplicate.d.mts +27 -0
- package/runtime/scripts/hfs/architecture/cross-app-duplicate.mjs +50 -51
- package/runtime/scripts/hfs/architecture/dead-exports-bindings.d.mts +21 -0
- package/runtime/scripts/hfs/architecture/dead-exports-bindings.mjs +143 -119
- package/runtime/scripts/hfs/architecture/dead-exports.d.mts +32 -0
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +286 -228
- package/runtime/scripts/hfs/architecture/default-deny.d.mts +21 -0
- package/runtime/scripts/hfs/architecture/default-deny.mjs +129 -110
- package/runtime/scripts/hfs/architecture/doc-language.d.mts +17 -0
- package/runtime/scripts/hfs/architecture/doc-language.mjs +24 -19
- package/runtime/scripts/hfs/architecture/entity-registry.d.mts +49 -0
- package/runtime/scripts/hfs/architecture/entity-registry.mjs +20 -22
- package/runtime/scripts/hfs/architecture/entrypoint.d.mts +13 -0
- package/runtime/scripts/hfs/architecture/entrypoint.mjs +47 -45
- package/runtime/scripts/hfs/architecture/error-codes.d.mts +16 -0
- package/runtime/scripts/hfs/architecture/error-codes.mjs +37 -35
- package/runtime/scripts/hfs/architecture/error-masked.d.mts +16 -0
- package/runtime/scripts/hfs/architecture/error-masked.mjs +55 -59
- package/runtime/scripts/hfs/architecture/fe-slot-allows.d.mts +38 -0
- package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +24 -23
- package/runtime/scripts/hfs/architecture/feature-shape.d.mts +26 -0
- package/runtime/scripts/hfs/architecture/feature-shape.mjs +40 -38
- package/runtime/scripts/hfs/architecture/framework-pinned.d.mts +3 -0
- package/runtime/scripts/hfs/architecture/framework-pinned.mjs +21 -21
- package/runtime/scripts/hfs/architecture/frontend-block-render.d.mts +26 -0
- package/runtime/scripts/hfs/architecture/frontend-block-render.mjs +106 -98
- package/runtime/scripts/hfs/architecture/frontend-grammar.d.mts +7 -0
- package/runtime/scripts/hfs/architecture/frontend-grammar.mjs +153 -150
- package/runtime/scripts/hfs/architecture/frontend-routing.d.mts +23 -0
- package/runtime/scripts/hfs/architecture/frontend-routing.mjs +161 -149
- package/runtime/scripts/hfs/architecture/frontend-world-render.d.mts +72 -0
- package/runtime/scripts/hfs/architecture/frontend-world-render.mjs +343 -305
- package/runtime/scripts/hfs/architecture/frontend-world.d.mts +94 -0
- package/runtime/scripts/hfs/architecture/frontend-world.mjs +340 -294
- package/runtime/scripts/hfs/architecture/frontend.d.mts +31 -0
- package/runtime/scripts/hfs/architecture/frontend.mjs +174 -184
- package/runtime/scripts/hfs/architecture/function-spec-providers.d.mts +27 -0
- package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +124 -106
- package/runtime/scripts/hfs/architecture/hfs-graph.d.mts +78 -0
- package/runtime/scripts/hfs/architecture/hfs-graph.mjs +52 -48
- package/runtime/scripts/hfs/architecture/hfs.d.mts +135 -0
- package/runtime/scripts/hfs/architecture/hfs.mjs +328 -282
- package/runtime/scripts/hfs/architecture/hooks-are-hooks.d.mts +24 -0
- package/runtime/scripts/hfs/architecture/hooks-are-hooks.mjs +81 -71
- package/runtime/scripts/hfs/architecture/i18n-keys.d.mts +31 -0
- package/runtime/scripts/hfs/architecture/i18n-keys.mjs +155 -141
- package/runtime/scripts/hfs/architecture/identity.d.mts +7 -0
- package/runtime/scripts/hfs/architecture/identity.mjs +141 -125
- package/runtime/scripts/hfs/architecture/index.d.mts +101 -0
- package/runtime/scripts/hfs/architecture/index.mjs +272 -272
- package/runtime/scripts/hfs/architecture/injection-token-exported.d.mts +21 -0
- package/runtime/scripts/hfs/architecture/injection-token-exported.mjs +45 -43
- package/runtime/scripts/hfs/architecture/jwt-ast.d.mts +16 -0
- package/runtime/scripts/hfs/architecture/jwt-ast.mjs +195 -176
- package/runtime/scripts/hfs/architecture/machine-ast.d.mts +88 -0
- package/runtime/scripts/hfs/architecture/machine-ast.mjs +163 -155
- package/runtime/scripts/hfs/architecture/managed-scripts.d.mts +2 -0
- package/runtime/scripts/hfs/architecture/managed-scripts.mjs +19 -20
- package/runtime/scripts/hfs/architecture/module-per-transport.d.mts +35 -0
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +177 -172
- package/runtime/scripts/hfs/architecture/next-data-contract.d.mts +35 -0
- package/runtime/scripts/hfs/architecture/next-data-contract.mjs +100 -78
- package/runtime/scripts/hfs/architecture/next-data-inference.d.mts +39 -0
- package/runtime/scripts/hfs/architecture/next-data-inference.mjs +170 -154
- package/runtime/scripts/hfs/architecture/next-data-key.d.mts +50 -0
- package/runtime/scripts/hfs/architecture/next-data-key.mjs +311 -275
- package/runtime/scripts/hfs/architecture/next-data-symbols.d.mts +5 -0
- package/runtime/scripts/hfs/architecture/next-data-symbols.mjs +17 -17
- package/runtime/scripts/hfs/architecture/next-data.d.mts +36 -0
- package/runtime/scripts/hfs/architecture/next-data.mjs +351 -334
- package/runtime/scripts/hfs/architecture/operation-contract-roots.d.mts +10 -0
- package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +39 -37
- package/runtime/scripts/hfs/architecture/owners.d.mts +5 -0
- package/runtime/scripts/hfs/architecture/owners.mjs +97 -98
- package/runtime/scripts/hfs/architecture/package-shape.d.mts +26 -0
- package/runtime/scripts/hfs/architecture/package-shape.mjs +56 -55
- package/runtime/scripts/hfs/architecture/presentation.d.mts +24 -0
- package/runtime/scripts/hfs/architecture/presentation.mjs +138 -130
- package/runtime/scripts/hfs/architecture/reachability.d.mts +25 -0
- package/runtime/scripts/hfs/architecture/reachability.mjs +258 -241
- package/runtime/scripts/hfs/architecture/register-once.d.mts +18 -0
- package/runtime/scripts/hfs/architecture/register-once.mjs +152 -139
- package/runtime/scripts/hfs/architecture/registration.d.mts +15 -0
- package/runtime/scripts/hfs/architecture/registration.mjs +301 -267
- package/runtime/scripts/hfs/architecture/required-files.d.mts +64 -0
- package/runtime/scripts/hfs/architecture/required-files.mjs +172 -167
- package/runtime/scripts/hfs/architecture/route-files-thin.d.mts +23 -0
- package/runtime/scripts/hfs/architecture/route-files-thin.mjs +85 -77
- package/runtime/scripts/hfs/architecture/schema-owner.d.mts +34 -0
- package/runtime/scripts/hfs/architecture/schema-owner.mjs +206 -181
- package/runtime/scripts/hfs/architecture/server-action.d.mts +22 -0
- package/runtime/scripts/hfs/architecture/server-action.mjs +48 -48
- package/runtime/scripts/hfs/architecture/side-boundary.d.mts +3 -0
- package/runtime/scripts/hfs/architecture/side-boundary.mjs +2 -5
- package/runtime/scripts/hfs/architecture/source-names-shape.d.mts +85 -0
- package/runtime/scripts/hfs/architecture/source-names-shape.mjs +261 -259
- package/runtime/scripts/hfs/architecture/source-names.d.mts +7 -0
- package/runtime/scripts/hfs/architecture/source-names.mjs +304 -278
- package/runtime/scripts/hfs/architecture/sql-keys.d.mts +5 -0
- package/runtime/scripts/hfs/architecture/sql-keys.mjs +277 -194
- package/runtime/scripts/hfs/architecture/sql-owner.d.mts +30 -0
- package/runtime/scripts/hfs/architecture/sql-owner.mjs +236 -194
- package/runtime/scripts/hfs/architecture/sql-returning.d.mts +22 -0
- package/runtime/scripts/hfs/architecture/sql-returning.mjs +46 -45
- package/runtime/scripts/hfs/architecture/sql-token-forms.d.mts +21 -0
- package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +86 -74
- package/runtime/scripts/hfs/architecture/sql-tokens.d.mts +32 -0
- package/runtime/scripts/hfs/architecture/sql-tokens.mjs +456 -341
- package/runtime/scripts/hfs/architecture/staged-consumers.d.mts +7 -0
- package/runtime/scripts/hfs/architecture/staged-consumers.mjs +35 -30
- package/runtime/scripts/hfs/architecture/surface.d.mts +26 -0
- package/runtime/scripts/hfs/architecture/surface.mjs +64 -74
- package/runtime/scripts/hfs/architecture/symbols.d.mts +11 -0
- package/runtime/scripts/hfs/architecture/symbols.mjs +209 -216
- package/runtime/scripts/hfs/architecture/test-world-files.d.mts +45 -0
- package/runtime/scripts/hfs/architecture/test-world-files.mjs +165 -155
- package/runtime/scripts/hfs/architecture/tiers.d.mts +29 -0
- package/runtime/scripts/hfs/architecture/tiers.mjs +161 -154
- package/runtime/scripts/hfs/architecture/transport-owner.d.mts +37 -0
- package/runtime/scripts/hfs/architecture/transport-owner.mjs +155 -149
- package/runtime/scripts/hfs/architecture/type-context.d.mts +60 -0
- package/runtime/scripts/hfs/architecture/type-context.mjs +255 -250
- package/runtime/scripts/hfs/architecture/typescript.d.mts +94 -0
- package/runtime/scripts/hfs/architecture/typescript.mjs +358 -318
- package/runtime/scripts/hfs/architecture/unit-spec-providers.d.mts +34 -0
- package/runtime/scripts/hfs/architecture/unit-spec-providers.mjs +110 -92
- package/runtime/scripts/hfs/architecture.d.mts +13 -0
- package/runtime/scripts/hfs/architecture.mjs +39 -29
- package/runtime/scripts/hfs/canon-pins.d.mts +26 -0
- package/runtime/scripts/hfs/canon-pins.mjs +5 -8
- package/runtime/scripts/hfs/catalog-once.d.mts +2 -0
- package/runtime/scripts/hfs/catalog-once.mjs +8 -9
- package/runtime/scripts/hfs/check-results.d.mts +29 -0
- package/runtime/scripts/hfs/check-results.mjs +14 -18
- package/runtime/scripts/hfs/check.d.mts +144 -0
- package/runtime/scripts/hfs/check.mjs +309 -329
- package/runtime/scripts/hfs/ci-declaration.d.mts +77 -0
- package/runtime/scripts/hfs/ci-declaration.mjs +99 -87
- package/runtime/scripts/hfs/coverage-from.d.mts +22 -0
- package/runtime/scripts/hfs/coverage-from.mjs +52 -49
- package/runtime/scripts/hfs/coverage-scope.d.mts +87 -0
- package/runtime/scripts/hfs/coverage-scope.mjs +139 -142
- package/runtime/scripts/hfs/db-baseline-verb.d.mts +84 -0
- package/runtime/scripts/hfs/db-baseline-verb.mjs +327 -266
- package/runtime/scripts/hfs/db-errors.d.mts +2 -0
- package/runtime/scripts/hfs/db-errors.mjs +2 -1
- package/runtime/scripts/hfs/db-plan-verb.d.mts +33 -0
- package/runtime/scripts/hfs/db-plan-verb.mjs +174 -128
- package/runtime/scripts/hfs/db-restamp-verb.d.mts +5 -0
- package/runtime/scripts/hfs/db-restamp-verb.mjs +94 -70
- package/runtime/scripts/hfs/db-squash.d.mts +117 -0
- package/runtime/scripts/hfs/db-squash.mjs +414 -351
- package/runtime/scripts/hfs/declaration-shape.d.mts +3 -0
- package/runtime/scripts/hfs/declaration-shape.mjs +140 -103
- package/runtime/scripts/hfs/declaration-slots.d.mts +18 -0
- package/runtime/scripts/hfs/declaration-slots.mjs +64 -61
- package/runtime/scripts/hfs/doc-commands.d.mts +71 -0
- package/runtime/scripts/hfs/doc-commands.mjs +257 -250
- package/runtime/scripts/hfs/edition-slots.d.mts +37 -0
- package/runtime/scripts/hfs/edition-slots.mjs +43 -40
- package/runtime/scripts/hfs/example-secrets.d.mts +18 -0
- package/runtime/scripts/hfs/example-secrets.mjs +173 -154
- package/runtime/scripts/hfs/gate-threshold.d.mts +20 -0
- package/runtime/scripts/hfs/gate-threshold.mjs +28 -0
- package/runtime/scripts/hfs/grammar-presentation.d.mts +74 -0
- package/runtime/scripts/hfs/grammar-presentation.mjs +109 -106
- package/runtime/scripts/hfs/linear-text.d.mts +6 -0
- package/runtime/scripts/hfs/linear-text.mjs +20 -20
- package/runtime/scripts/hfs/manifest-shape.d.mts +216 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +399 -324
- package/runtime/scripts/hfs/param-names.d.mts +3 -0
- package/runtime/scripts/hfs/param-names.mjs +6 -11
- package/runtime/scripts/hfs/path-findings.d.mts +22 -0
- package/runtime/scripts/hfs/path-findings.mjs +120 -100
- package/runtime/scripts/hfs/pin-findings.d.mts +19 -0
- package/runtime/scripts/hfs/pin-findings.mjs +26 -21
- package/runtime/scripts/hfs/refusal-codes.d.mts +1 -0
- package/runtime/scripts/hfs/refusal-codes.mjs +2 -2
- package/runtime/scripts/hfs/repo-identity.d.mts +15 -0
- package/runtime/scripts/hfs/repo-identity.mjs +55 -42
- package/runtime/scripts/hfs/rule-catalog.d.mts +77 -0
- package/runtime/scripts/hfs/rule-catalog.mjs +353 -257
- package/runtime/scripts/hfs/rule-params-shape.d.mts +10 -0
- package/runtime/scripts/hfs/rule-params-shape.mjs +60 -47
- package/runtime/scripts/hfs/rules/a15-findings.d.mts +18 -0
- package/runtime/scripts/hfs/rules/a15-findings.mjs +59 -55
- package/runtime/scripts/hfs/rules/app-env-required.d.mts +9 -0
- package/runtime/scripts/hfs/rules/app-env-required.mjs +13 -13
- package/runtime/scripts/hfs/rules/app-root.d.mts +15 -0
- package/runtime/scripts/hfs/rules/app-root.mjs +20 -21
- package/runtime/scripts/hfs/rules/app-workflow-findings.d.mts +12 -0
- package/runtime/scripts/hfs/rules/app-workflow-findings.mjs +4 -4
- package/runtime/scripts/hfs/rules/assets.d.mts +13 -0
- package/runtime/scripts/hfs/rules/assets.mjs +58 -46
- package/runtime/scripts/hfs/rules/boot-proof.d.mts +11 -0
- package/runtime/scripts/hfs/rules/boot-proof.mjs +7 -8
- package/runtime/scripts/hfs/rules/bypass-markers.d.mts +9 -0
- package/runtime/scripts/hfs/rules/bypass-markers.mjs +7 -12
- package/runtime/scripts/hfs/rules/canon-copy-drift.d.mts +10 -0
- package/runtime/scripts/hfs/rules/canon-copy-drift.mjs +70 -68
- package/runtime/scripts/hfs/rules/ci-custody.d.mts +7 -0
- package/runtime/scripts/hfs/rules/ci-custody.mjs +72 -73
- package/runtime/scripts/hfs/rules/ci-standard.d.mts +12 -0
- package/runtime/scripts/hfs/rules/ci-standard.mjs +149 -142
- package/runtime/scripts/hfs/rules/cli.d.mts +7 -0
- package/runtime/scripts/hfs/rules/cli.mjs +24 -23
- package/runtime/scripts/hfs/rules/contract-compat.d.mts +11 -0
- package/runtime/scripts/hfs/rules/contract-compat.mjs +64 -53
- package/runtime/scripts/hfs/rules/contract.d.mts +26 -0
- package/runtime/scripts/hfs/rules/contract.mjs +126 -111
- package/runtime/scripts/hfs/rules/coverage-below.d.mts +17 -0
- package/runtime/scripts/hfs/rules/coverage-below.mjs +200 -167
- package/runtime/scripts/hfs/rules/database-access.d.mts +12 -0
- package/runtime/scripts/hfs/rules/database-access.mjs +231 -202
- package/runtime/scripts/hfs/rules/database-baseline.d.mts +22 -0
- package/runtime/scripts/hfs/rules/database-baseline.mjs +104 -104
- package/runtime/scripts/hfs/rules/database-config.d.mts +11 -0
- package/runtime/scripts/hfs/rules/database-config.mjs +101 -135
- package/runtime/scripts/hfs/rules/database-constants.d.mts +36 -0
- package/runtime/scripts/hfs/rules/database-constants.mjs +7 -7
- package/runtime/scripts/hfs/rules/database-migrations.d.mts +41 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +428 -388
- package/runtime/scripts/hfs/rules/database-plpgsql.d.mts +5 -0
- package/runtime/scripts/hfs/rules/database-plpgsql.mjs +278 -259
- package/runtime/scripts/hfs/rules/database-queue-sources.d.mts +4 -0
- package/runtime/scripts/hfs/rules/database-queue-sources.mjs +48 -43
- package/runtime/scripts/hfs/rules/database-queues.d.mts +15 -0
- package/runtime/scripts/hfs/rules/database-queues.mjs +211 -182
- package/runtime/scripts/hfs/rules/database-sql.d.mts +16 -0
- package/runtime/scripts/hfs/rules/database-sql.mjs +394 -394
- package/runtime/scripts/hfs/rules/database-transaction.d.mts +3 -0
- package/runtime/scripts/hfs/rules/database-transaction.mjs +25 -27
- package/runtime/scripts/hfs/rules/database.d.mts +22 -0
- package/runtime/scripts/hfs/rules/database.mjs +42 -58
- package/runtime/scripts/hfs/rules/deploy-scan.d.mts +10 -0
- package/runtime/scripts/hfs/rules/deploy-scan.mjs +177 -168
- package/runtime/scripts/hfs/rules/deploy-workflow.d.mts +3 -0
- package/runtime/scripts/hfs/rules/deploy-workflow.mjs +194 -171
- package/runtime/scripts/hfs/rules/deps.d.mts +6 -0
- package/runtime/scripts/hfs/rules/deps.mjs +61 -60
- package/runtime/scripts/hfs/rules/doc-fresh.d.mts +11 -0
- package/runtime/scripts/hfs/rules/doc-fresh.mjs +242 -223
- package/runtime/scripts/hfs/rules/docker-health.d.mts +9 -0
- package/runtime/scripts/hfs/rules/docker-health.mjs +222 -196
- package/runtime/scripts/hfs/rules/docker.d.mts +13 -0
- package/runtime/scripts/hfs/rules/docker.mjs +234 -208
- package/runtime/scripts/hfs/rules/edition.d.mts +18 -0
- package/runtime/scripts/hfs/rules/edition.mjs +103 -101
- package/runtime/scripts/hfs/rules/env-parity.d.mts +25 -0
- package/runtime/scripts/hfs/rules/env-parity.mjs +278 -252
- package/runtime/scripts/hfs/rules/env-value-shape.d.mts +21 -0
- package/runtime/scripts/hfs/rules/env-value-shape.mjs +82 -67
- package/runtime/scripts/hfs/rules/event-bus.d.mts +17 -0
- package/runtime/scripts/hfs/rules/event-bus.mjs +145 -133
- package/runtime/scripts/hfs/rules/event-tables.d.mts +7 -0
- package/runtime/scripts/hfs/rules/event-tables.mjs +77 -75
- package/runtime/scripts/hfs/rules/fe-build-args.d.mts +10 -0
- package/runtime/scripts/hfs/rules/fe-build-args.mjs +116 -99
- package/runtime/scripts/hfs/rules/fe-contract-documents.d.mts +7 -0
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +121 -111
- package/runtime/scripts/hfs/rules/fe-no-tests.d.mts +9 -0
- package/runtime/scripts/hfs/rules/fe-no-tests.mjs +37 -36
- package/runtime/scripts/hfs/rules/fe-stack.d.mts +23 -0
- package/runtime/scripts/hfs/rules/fe-stack.mjs +108 -105
- package/runtime/scripts/hfs/rules/feature-files.d.mts +10 -0
- package/runtime/scripts/hfs/rules/feature-files.mjs +14 -19
- package/runtime/scripts/hfs/rules/frontend-tree.d.mts +18 -0
- package/runtime/scripts/hfs/rules/frontend-tree.mjs +105 -91
- package/runtime/scripts/hfs/rules/integration-specs.d.mts +7 -0
- package/runtime/scripts/hfs/rules/integration-specs.mjs +190 -177
- package/runtime/scripts/hfs/rules/kinds.d.mts +6 -0
- package/runtime/scripts/hfs/rules/kinds.mjs +88 -81
- package/runtime/scripts/hfs/rules/lexicon.d.mts +9 -0
- package/runtime/scripts/hfs/rules/lexicon.mjs +43 -40
- package/runtime/scripts/hfs/rules/lint-suppression.d.mts +5 -0
- package/runtime/scripts/hfs/rules/lint-suppression.mjs +22 -20
- package/runtime/scripts/hfs/rules/lite-proof-lane.d.mts +9 -0
- package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +59 -58
- package/runtime/scripts/hfs/rules/lite-secrets.d.mts +12 -0
- package/runtime/scripts/hfs/rules/lite-secrets.mjs +60 -63
- package/runtime/scripts/hfs/rules/mcp-tools.d.mts +7 -0
- package/runtime/scripts/hfs/rules/mcp-tools.mjs +56 -41
- package/runtime/scripts/hfs/rules/monorepo.d.mts +17 -0
- package/runtime/scripts/hfs/rules/monorepo.mjs +153 -138
- package/runtime/scripts/hfs/rules/peer-integrations.d.mts +7 -0
- package/runtime/scripts/hfs/rules/peer-integrations.mjs +39 -36
- package/runtime/scripts/hfs/rules/pipeline.d.mts +7 -0
- package/runtime/scripts/hfs/rules/pipeline.mjs +53 -53
- package/runtime/scripts/hfs/rules/proof-commands.d.mts +14 -0
- package/runtime/scripts/hfs/rules/proof-commands.mjs +52 -41
- package/runtime/scripts/hfs/rules/read.d.mts +7 -0
- package/runtime/scripts/hfs/rules/read.mjs +19 -15
- package/runtime/scripts/hfs/rules/release-provenance.d.mts +12 -0
- package/runtime/scripts/hfs/rules/release-provenance.mjs +196 -159
- package/runtime/scripts/hfs/rules/repo-local-checks.d.mts +5 -0
- package/runtime/scripts/hfs/rules/repo-local-checks.mjs +19 -17
- package/runtime/scripts/hfs/rules/rule-types.d.mts +40 -0
- package/runtime/scripts/hfs/rules/rule-types.mjs +4 -0
- package/runtime/scripts/hfs/rules/saga-delivery.d.mts +2 -0
- package/runtime/scripts/hfs/rules/saga-delivery.mjs +58 -50
- package/runtime/scripts/hfs/rules/saga.d.mts +7 -0
- package/runtime/scripts/hfs/rules/saga.mjs +151 -145
- package/runtime/scripts/hfs/rules/script-hygiene.d.mts +11 -0
- package/runtime/scripts/hfs/rules/script-hygiene.mjs +112 -95
- package/runtime/scripts/hfs/rules/secret-custody-only.d.mts +7 -0
- package/runtime/scripts/hfs/rules/secret-custody-only.mjs +29 -35
- package/runtime/scripts/hfs/rules/secrets.d.mts +29 -0
- package/runtime/scripts/hfs/rules/secrets.mjs +45 -44
- package/runtime/scripts/hfs/rules/services.d.mts +7 -0
- package/runtime/scripts/hfs/rules/services.mjs +148 -148
- package/runtime/scripts/hfs/rules/spec-placement.d.mts +8 -0
- package/runtime/scripts/hfs/rules/spec-placement.mjs +12 -13
- package/runtime/scripts/hfs/rules/stack-tooling.d.mts +11 -0
- package/runtime/scripts/hfs/rules/stack-tooling.mjs +45 -52
- package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.d.mts +30 -0
- package/runtime/scripts/hfs/rules/stacks-auth-cookie-domain.mjs +149 -0
- package/runtime/scripts/hfs/rules/stacks-deploy.d.mts +7 -0
- package/runtime/scripts/hfs/rules/stacks-deploy.mjs +32 -42
- package/runtime/scripts/hfs/rules/stacks-ingress.d.mts +16 -0
- package/runtime/scripts/hfs/rules/stacks-ingress.mjs +62 -64
- package/runtime/scripts/hfs/rules/stacks-lite-backing.d.mts +17 -0
- package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +111 -116
- package/runtime/scripts/hfs/rules/stacks-release.d.mts +26 -0
- package/runtime/scripts/hfs/rules/stacks-release.mjs +335 -309
- package/runtime/scripts/hfs/rules/stacks-runtime.d.mts +31 -0
- package/runtime/scripts/hfs/rules/stacks-runtime.mjs +130 -124
- package/runtime/scripts/hfs/rules/stacks-swarm.d.mts +5 -0
- package/runtime/scripts/hfs/rules/stacks-swarm.mjs +366 -344
- package/runtime/scripts/hfs/rules/stacks.d.mts +7 -0
- package/runtime/scripts/hfs/rules/stacks.mjs +37 -38
- package/runtime/scripts/hfs/rules/staged-specs.d.mts +10 -0
- package/runtime/scripts/hfs/rules/staged-specs.mjs +14 -18
- package/runtime/scripts/hfs/rules/supply-chain.d.mts +10 -0
- package/runtime/scripts/hfs/rules/supply-chain.mjs +143 -150
- package/runtime/scripts/hfs/rules/test-topology.d.mts +5 -0
- package/runtime/scripts/hfs/rules/test-topology.mjs +23 -21
- package/runtime/scripts/hfs/rules/text-integrity.d.mts +9 -0
- package/runtime/scripts/hfs/rules/text-integrity.mjs +47 -43
- package/runtime/scripts/hfs/rules/unused-symbol-flow.d.mts +22 -0
- package/runtime/scripts/hfs/rules/unused-symbol-flow.mjs +226 -204
- package/runtime/scripts/hfs/rules/unused-symbol-ledger.d.mts +7 -0
- package/runtime/scripts/hfs/rules/unused-symbol-ledger.mjs +70 -49
- package/runtime/scripts/hfs/rules/unused-symbol-properties.d.mts +12 -0
- package/runtime/scripts/hfs/rules/unused-symbol-properties.mjs +141 -126
- package/runtime/scripts/hfs/rules/unused-symbol-translators.d.mts +8 -0
- package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +160 -140
- package/runtime/scripts/hfs/rules/unused-symbol-values.d.mts +9 -0
- package/runtime/scripts/hfs/rules/unused-symbol-values.mjs +138 -125
- package/runtime/scripts/hfs/rules/unused-symbol.d.mts +11 -0
- package/runtime/scripts/hfs/rules/unused-symbol.mjs +283 -253
- package/runtime/scripts/hfs/rules/workflow-contexts.d.mts +8 -0
- package/runtime/scripts/hfs/rules/workflow-contexts.mjs +79 -67
- package/runtime/scripts/hfs/runtime-rules/git-triggers.d.mts +6 -0
- package/runtime/scripts/hfs/runtime-rules/git-triggers.mjs +36 -35
- package/runtime/scripts/hfs/runtime-rules/hook-shape.d.mts +10 -0
- package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +45 -42
- package/runtime/scripts/hfs/runtime-rules/source-ast.d.mts +39 -0
- package/runtime/scripts/hfs/runtime-rules/source-ast.mjs +130 -116
- package/runtime/scripts/hfs/runtime-rules/workflow-source.d.mts +5 -0
- package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +8 -7
- package/runtime/scripts/hfs/sealed-members.d.mts +22 -0
- package/runtime/scripts/hfs/sealed-members.mjs +79 -75
- package/runtime/scripts/hfs/secret-bootstrap-crypto.d.mts +12 -0
- package/runtime/scripts/hfs/secret-bootstrap-crypto.mjs +151 -167
- package/runtime/scripts/hfs/secret-document.d.mts +16 -0
- package/runtime/scripts/hfs/secret-document.mjs +59 -75
- package/runtime/scripts/hfs/secret-edit.d.mts +14 -0
- package/runtime/scripts/hfs/secret-edit.mjs +115 -135
- package/runtime/scripts/hfs/secret-errors.d.mts +4 -0
- package/runtime/scripts/hfs/secret-errors.mjs +19 -16
- package/runtime/scripts/hfs/secret-files.d.mts +20 -0
- package/runtime/scripts/hfs/secret-files.mjs +103 -112
- package/runtime/scripts/hfs/secret-init.d.mts +108 -0
- package/runtime/scripts/hfs/secret-init.mjs +304 -346
- package/runtime/scripts/hfs/secret-output.d.mts +18 -0
- package/runtime/scripts/hfs/secret-output.mjs +52 -80
- package/runtime/scripts/hfs/secret-prompt.d.mts +39 -0
- package/runtime/scripts/hfs/secret-prompt.mjs +108 -93
- package/runtime/scripts/hfs/secret-sops.d.mts +29 -0
- package/runtime/scripts/hfs/secret-sops.mjs +161 -199
- package/runtime/scripts/hfs/secret-standard.d.mts +89 -0
- package/runtime/scripts/hfs/secret-standard.mjs +300 -264
- package/runtime/scripts/hfs/secret-store.d.mts +36 -0
- package/runtime/scripts/hfs/secret-store.mjs +120 -136
- package/runtime/scripts/hfs/secret.d.mts +40 -0
- package/runtime/scripts/hfs/secret.mjs +254 -222
- package/runtime/scripts/hfs/slot-app-view.d.mts +11 -0
- package/runtime/scripts/hfs/slot-app-view.mjs +69 -74
- package/runtime/scripts/hfs/slot-classify.d.mts +75 -0
- package/runtime/scripts/hfs/slot-classify.mjs +42 -38
- package/runtime/scripts/hfs/slot-errors.d.mts +6 -0
- package/runtime/scripts/hfs/slot-errors.mjs +8 -7
- package/runtime/scripts/hfs/slot-imports.d.mts +8 -0
- package/runtime/scripts/hfs/slot-imports.mjs +70 -63
- package/runtime/scripts/hfs/slot-manifest-shape.d.mts +9 -0
- package/runtime/scripts/hfs/slot-manifest-shape.mjs +74 -52
- package/runtime/scripts/hfs/slot-match.d.mts +50 -0
- package/runtime/scripts/hfs/slot-match.mjs +122 -111
- package/runtime/scripts/hfs/slot-path.d.mts +1 -0
- package/runtime/scripts/hfs/slot-path.mjs +0 -2
- package/runtime/scripts/hfs/slot-required.d.mts +11 -0
- package/runtime/scripts/hfs/slot-required.mjs +65 -59
- package/runtime/scripts/hfs/slot-semantic-problems.d.mts +9 -0
- package/runtime/scripts/hfs/slot-semantic-problems.mjs +138 -112
- package/runtime/scripts/hfs/slot-side-problems.d.mts +3 -0
- package/runtime/scripts/hfs/slot-side-problems.mjs +23 -19
- package/runtime/scripts/hfs/slots.d.mts +188 -0
- package/runtime/scripts/hfs/slots.mjs +175 -152
- package/runtime/scripts/hfs/sql/pg-parse.d.mts +9 -0
- package/runtime/scripts/hfs/sql/pg-parse.mjs +25 -25
- package/runtime/scripts/hfs/stack-config-kit.d.mts +22 -0
- package/runtime/scripts/hfs/stack-config-kit.mjs +21 -17
- package/runtime/scripts/hfs/stack-deploy-config.d.mts +155 -0
- package/runtime/scripts/hfs/stack-deploy-config.mjs +345 -273
- package/runtime/scripts/hfs/stack-ingress-config.d.mts +74 -0
- package/runtime/scripts/hfs/stack-ingress-config.mjs +211 -177
- package/runtime/scripts/hfs/stacks-gate.d.mts +52 -0
- package/runtime/scripts/hfs/stacks-gate.mjs +557 -397
- package/runtime/scripts/hfs/starcistacks-runtime.d.mts +7 -0
- package/runtime/scripts/hfs/starcistacks-runtime.mjs +51 -40
- package/runtime/scripts/hfs/test-world-slot.d.mts +2 -0
- package/runtime/scripts/hfs/test-world-slot.mjs +0 -1
- package/runtime/scripts/hfs/trailing-slashes.d.mts +2 -0
- package/runtime/scripts/hfs/trailing-slashes.mjs +4 -4
- package/runtime/scripts/hfs/tree-findings.d.mts +9 -0
- package/runtime/scripts/hfs/tree-findings.mjs +18 -17
- package/runtime/scripts/hfs/tree.d.mts +35 -0
- package/runtime/scripts/hfs/tree.mjs +56 -46
- package/runtime/scripts/hfs/typescript-programs.d.mts +36 -0
- package/runtime/scripts/hfs/typescript-programs.mjs +66 -69
- package/runtime/scripts/hfs/view.d.mts +45 -0
- package/runtime/scripts/hfs/view.mjs +38 -40
- package/runtime/scripts/lib/bypass-markers.d.mts +15 -0
- package/runtime/scripts/lib/bypass-markers.mjs +210 -197
- package/runtime/scripts/lib/cli-arg.d.mts +67 -0
- package/runtime/scripts/lib/cli-arg.mjs +59 -63
- package/runtime/scripts/lib/command-tokens.d.mts +11 -0
- package/runtime/scripts/lib/command-tokens.mjs +77 -78
- package/runtime/scripts/lib/compose-values.d.mts +6 -0
- package/runtime/scripts/lib/compose-values.mjs +7 -7
- package/runtime/scripts/lib/css-rules.d.mts +36 -0
- package/runtime/scripts/lib/css-rules.mjs +181 -171
- package/runtime/scripts/lib/deployment-findings.d.mts +9 -0
- package/runtime/scripts/lib/deployment-findings.mjs +4 -4
- package/runtime/scripts/lib/dockerfile.d.mts +39 -0
- package/runtime/scripts/lib/dockerfile.mjs +131 -114
- package/runtime/scripts/lib/dom-tree.d.mts +7 -0
- package/runtime/scripts/lib/dom-tree.mjs +3 -3
- package/runtime/scripts/lib/env.d.mts +12 -0
- package/runtime/scripts/lib/env.mjs +3 -6
- package/runtime/scripts/lib/escape.d.mts +6 -0
- package/runtime/scripts/lib/escape.mjs +2 -6
- package/runtime/scripts/lib/event-contract.d.mts +21 -0
- package/runtime/scripts/lib/event-contract.mjs +73 -78
- package/runtime/scripts/lib/event-items.d.mts +20 -0
- package/runtime/scripts/lib/event-items.mjs +27 -15
- package/runtime/scripts/lib/example-refs.d.mts +69 -0
- package/runtime/scripts/lib/example-refs.mjs +145 -129
- package/runtime/scripts/lib/fs-kind.d.mts +12 -0
- package/runtime/scripts/lib/fs-kind.mjs +20 -10
- package/runtime/scripts/lib/git-hooks-dir.d.mts +15 -0
- package/runtime/scripts/lib/git-hooks-dir.mjs +16 -16
- package/runtime/scripts/lib/git.d.mts +24 -0
- package/runtime/scripts/lib/git.mjs +15 -16
- package/runtime/scripts/lib/glob.d.mts +4 -0
- package/runtime/scripts/lib/glob.mjs +23 -14
- package/runtime/scripts/lib/grammar-lint.d.mts +47 -0
- package/runtime/scripts/lib/grammar-lint.mjs +33 -37
- package/runtime/scripts/lib/grammar-vendor-parity-jsx.d.mts +40 -0
- package/runtime/scripts/lib/grammar-vendor-parity-jsx.mjs +285 -266
- package/runtime/scripts/lib/grammar-vendor-parity.d.mts +61 -0
- package/runtime/scripts/lib/grammar-vendor-parity.mjs +209 -216
- package/runtime/scripts/lib/graphql-contract.d.mts +53 -0
- package/runtime/scripts/lib/graphql-contract.mjs +201 -198
- package/runtime/scripts/lib/graphql-sdl.d.mts +66 -0
- package/runtime/scripts/lib/graphql-sdl.mjs +230 -205
- package/runtime/scripts/lib/hook-limits.d.mts +11 -0
- package/runtime/scripts/lib/hook-limits.mjs +0 -1
- package/runtime/scripts/lib/i18n.d.mts +48 -0
- package/runtime/scripts/lib/i18n.mjs +32 -35
- package/runtime/scripts/lib/in-order.d.mts +12 -0
- package/runtime/scripts/lib/in-order.mjs +57 -38
- package/runtime/scripts/lib/is-main.d.mts +6 -0
- package/runtime/scripts/lib/is-main.mjs +11 -4
- package/runtime/scripts/lib/js-lex.d.mts +32 -0
- package/runtime/scripts/lib/js-lex.mjs +196 -162
- package/runtime/scripts/lib/json-clone.d.mts +11 -0
- package/runtime/scripts/lib/json-clone.mjs +45 -36
- package/runtime/scripts/lib/json-schema.d.mts +2 -0
- package/runtime/scripts/lib/json-schema.mjs +127 -90
- package/runtime/scripts/lib/json.d.mts +16 -0
- package/runtime/scripts/lib/json.mjs +26 -14
- package/runtime/scripts/lib/language.d.mts +44 -0
- package/runtime/scripts/lib/language.mjs +133 -129
- package/runtime/scripts/lib/list.d.mts +17 -0
- package/runtime/scripts/lib/list.mjs +9 -14
- package/runtime/scripts/lib/loosening-budgets.d.mts +12 -0
- package/runtime/scripts/lib/loosening-budgets.mjs +35 -29
- package/runtime/scripts/lib/loosening-config.d.mts +64 -0
- package/runtime/scripts/lib/loosening-config.mjs +267 -236
- package/runtime/scripts/lib/loosening-state.d.mts +77 -0
- package/runtime/scripts/lib/loosening-state.mjs +134 -128
- package/runtime/scripts/lib/mutation-fence.d.mts +11 -0
- package/runtime/scripts/lib/mutation-fence.mjs +10 -5
- package/runtime/scripts/lib/normalize.d.mts +12 -0
- package/runtime/scripts/lib/normalize.mjs +11 -11
- package/runtime/scripts/lib/numeric-match.d.mts +2 -0
- package/runtime/scripts/lib/numeric-match.mjs +2 -2
- package/runtime/scripts/lib/package-at.d.mts +24 -0
- package/runtime/scripts/lib/package-at.mjs +34 -31
- package/runtime/scripts/lib/path-key.d.mts +76 -0
- package/runtime/scripts/lib/path-key.mjs +53 -38
- package/runtime/scripts/lib/pid-alive.d.mts +2 -0
- package/runtime/scripts/lib/pid-alive.mjs +10 -3
- package/runtime/scripts/lib/properties.d.mts +2 -0
- package/runtime/scripts/lib/properties.mjs +17 -11
- package/runtime/scripts/lib/provision-operation-schema.d.mts +4 -0
- package/runtime/scripts/lib/provision-operation-schema.mjs +4 -5
- package/runtime/scripts/lib/read-text.d.mts +12 -0
- package/runtime/scripts/lib/read-text.mjs +30 -17
- package/runtime/scripts/lib/redact.d.mts +52 -0
- package/runtime/scripts/lib/redact.mjs +135 -121
- package/runtime/scripts/lib/regex.d.mts +2 -0
- package/runtime/scripts/lib/regex.mjs +1 -2
- package/runtime/scripts/lib/roots.d.mts +32 -0
- package/runtime/scripts/lib/roots.mjs +5 -15
- package/runtime/scripts/lib/runtime-example.d.mts +1 -0
- package/runtime/scripts/lib/runtime-example.mjs +10 -8
- package/runtime/scripts/lib/same-text.d.mts +2 -0
- package/runtime/scripts/lib/same-text.mjs +0 -1
- package/runtime/scripts/lib/sealed-member.d.mts +16 -0
- package/runtime/scripts/lib/sealed-member.mjs +8 -13
- package/runtime/scripts/lib/secret-patterns.d.mts +30 -0
- package/runtime/scripts/lib/secret-patterns.mjs +175 -163
- package/runtime/scripts/lib/shell-source.d.mts +2 -0
- package/runtime/scripts/lib/shell-source.mjs +0 -1
- package/runtime/scripts/lib/sleep-sync.d.mts +2 -0
- package/runtime/scripts/lib/sleep-sync.mjs +5 -6
- package/runtime/scripts/lib/sops-envelope.d.mts +34 -0
- package/runtime/scripts/lib/sops-envelope.mjs +148 -120
- package/runtime/scripts/lib/source-phrases.d.mts +4 -0
- package/runtime/scripts/lib/source-phrases.mjs +13 -13
- package/runtime/scripts/lib/sql-ast.d.mts +13 -0
- package/runtime/scripts/lib/sql-ast.mjs +19 -18
- package/runtime/scripts/lib/sqlite.d.mts +21 -0
- package/runtime/scripts/lib/sqlite.mjs +3 -9
- package/runtime/scripts/lib/stack-declaration.d.mts +51 -0
- package/runtime/scripts/lib/stack-declaration.mjs +27 -20
- package/runtime/scripts/lib/stack-services.d.mts +73 -0
- package/runtime/scripts/lib/stack-services.mjs +128 -129
- package/runtime/scripts/lib/starciwork-boundary.d.mts +10 -0
- package/runtime/scripts/lib/starciwork-boundary.mjs +98 -92
- package/runtime/scripts/lib/swarm-stack.d.mts +24 -0
- package/runtime/scripts/lib/swarm-stack.mjs +112 -100
- package/runtime/scripts/lib/trim-end.d.mts +2 -0
- package/runtime/scripts/lib/trim-end.mjs +4 -4
- package/runtime/scripts/lib/ts-analysis.d.mts +24 -0
- package/runtime/scripts/lib/ts-analysis.mjs +28 -26
- package/runtime/scripts/lib/ts-ast.d.mts +36 -0
- package/runtime/scripts/lib/ts-ast.mjs +36 -42
- package/runtime/scripts/lib/walk.d.mts +19 -0
- package/runtime/scripts/lib/walk.mjs +33 -27
- package/runtime/scripts/lib/work-edition.d.mts +10 -0
- package/runtime/scripts/lib/work-edition.mjs +29 -21
- package/runtime/scripts/lib/workflow-events.d.mts +2 -0
- package/runtime/scripts/lib/workflow-events.mjs +5 -4
- package/runtime/scripts/lib/worktree-exclude.d.mts +16 -0
- package/runtime/scripts/lib/worktree-exclude.mjs +6 -8
- package/runtime/scripts/lib/yaml-cached.d.mts +2 -0
- package/runtime/scripts/lib/yaml-cached.mjs +4 -4
- package/runtime/scripts/machine/artifact-hold.d.mts +26 -0
- package/runtime/scripts/machine/artifact-hold.mjs +22 -23
- package/runtime/scripts/work/asset-slot.d.mts +96 -0
- package/runtime/scripts/work/asset-slot.mjs +201 -175
- package/runtime/scripts/work/draw/draw-dna-anatomy.d.mts +30 -0
- package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +40 -36
- package/runtime/scripts/work/draw/draw-dna-findings.d.mts +12 -0
- package/runtime/scripts/work/draw/draw-dna-findings.mjs +240 -206
- package/runtime/scripts/work/draw/draw-dna-selector.d.mts +7 -0
- package/runtime/scripts/work/draw/draw-dna-selector.mjs +28 -28
- package/runtime/scripts/work/draw/draw-dna.d.mts +191 -0
- package/runtime/scripts/work/draw/draw-dna.mjs +283 -249
- package/runtime/scripts/work/grammar-proposal.d.mts +83 -0
- package/runtime/scripts/work/grammar-proposal.mjs +215 -178
- package/runtime/scripts/work/work-io.d.mts +62 -0
- package/runtime/scripts/work/work-io.mjs +82 -63
- package/scaffold/add-app.d.mts +15 -0
- package/scaffold/add-app.mjs +111 -163
- package/scaffold/add-cli-lite.d.mts +8 -0
- package/scaffold/add-cli-lite.mjs +173 -207
- package/scaffold/add-compose.d.mts +44 -0
- package/scaffold/add-compose.mjs +62 -62
- package/scaffold/add-database-lite.d.mts +2 -0
- package/scaffold/add-database-lite.mjs +10 -10
- package/scaffold/add-fe-layout.d.mts +16 -0
- package/scaffold/add-fe-layout.mjs +23 -23
- package/scaffold/add-fe-overlay.d.mts +17 -0
- package/scaffold/add-fe-overlay.mjs +76 -78
- package/scaffold/add-fe-page.d.mts +41 -0
- package/scaffold/add-fe-page.mjs +84 -89
- package/scaffold/add-fe-unit.d.mts +59 -0
- package/scaffold/add-fe-unit.mjs +205 -197
- package/scaffold/add-inbox-lite.d.mts +17 -0
- package/scaffold/add-inbox-lite.mjs +209 -264
- package/scaffold/add-plan.d.mts +68 -0
- package/scaffold/add-plan.mjs +164 -149
- package/scaffold/add-queue-lite.d.mts +34 -0
- package/scaffold/add-queue-lite.mjs +267 -267
- package/scaffold/add-table.d.mts +16 -0
- package/scaffold/add-table.mjs +405 -442
- package/scaffold/add.d.mts +34 -0
- package/scaffold/add.mjs +260 -246
- package/scaffold/app.d.mts +198 -0
- package/scaffold/app.mjs +413 -391
- package/scaffold/edition-gate.d.mts +49 -0
- package/scaffold/edition-gate.mjs +19 -29
- package/scaffold/image.d.mts +4 -0
- package/scaffold/image.mjs +12 -12
- package/scaffold/lite-exports.d.mts +15 -0
- package/scaffold/lite-exports.mjs +262 -255
- package/scaffold/pattern-file-slots.d.mts +7 -0
- package/scaffold/pattern-file-slots.mjs +29 -24
- package/scaffold/service.d.mts +60 -0
- package/scaffold/service.mjs +297 -279
- package/scaffold/test-world.d.mts +31 -0
- package/scaffold/test-world.mjs +71 -78
- package/scaffold/yaml-block-edit.d.mts +23 -0
- package/scaffold/yaml-block-edit.mjs +95 -87
- package/scripts/sync-bundles.d.mts +31 -0
- package/src/fixtures/bypass-index.d.mts +4 -0
- package/src/fixtures/hfs-stack-tooling/passing.d.mts +8 -0
- package/src/fixtures/hfs-stack-tooling/violating.d.mts +19 -0
- package/src/fixtures/hfs-stacks-full/model-unavailable.d.mts +10 -0
- package/src/fixtures/hfs-stacks-full/passing.d.mts +19 -0
- package/src/fixtures/hfs-stacks-full/violating.d.mts +10 -0
- package/src/fixtures/loosening/adversarial.d.mts +4 -0
- package/src/fixtures/loosening/forms.d.mts +16 -0
- package/src/fixtures/loosening/swallows.d.mts +5 -0
- package/src/helpers/hfs-arch-fixture.d.mts +47 -0
- package/src/helpers/hfs-cli-fixture.d.mts +65 -0
- package/src/helpers/hfs-hfs-docker-rules-fixture.d.mts +5 -0
- package/src/helpers/hfs-secret-fixture.d.mts +19 -0
- package/src/helpers/pre-push-fixture.d.mts +21 -0
- package/src/helpers/stack-compose.d.mts +6 -0
- package/src/helpers/swarm-stack-fixture.d.mts +18 -0
- package/src/helpers/tmpdir.d.mts +2 -0
- package/src/main.d.mts +58 -0
- package/src/main.mjs +494 -346
- package/stack/age-install.d.mts +13 -0
- package/stack/age-install.mjs +28 -25
- package/stack/backup.d.mts +11 -0
- package/stack/backup.mjs +76 -69
- package/stack/build-args.d.mts +7 -0
- package/stack/build-args.mjs +22 -23
- package/stack/build.d.mts +8 -0
- package/stack/build.mjs +138 -119
- package/stack/cli.d.mts +55 -0
- package/stack/cli.mjs +187 -130
- package/stack/config.d.mts +197 -0
- package/stack/config.mjs +47 -33
- package/stack/context.d.mts +122 -0
- package/stack/context.mjs +63 -65
- package/stack/converge.d.mts +13 -0
- package/stack/converge.mjs +73 -69
- package/stack/deploy.d.mts +88 -0
- package/stack/deploy.mjs +272 -224
- package/stack/digest.d.mts +8 -0
- package/stack/digest.mjs +1 -6
- package/stack/docker-transport.d.mts +5 -0
- package/stack/docker-transport.mjs +101 -93
- package/stack/edge-alias.d.mts +42 -0
- package/stack/edge-alias.mjs +62 -60
- package/stack/errors.d.mts +18 -0
- package/stack/errors.mjs +8 -10
- package/stack/image-scan.d.mts +20 -0
- package/stack/image-scan.mjs +114 -101
- package/stack/ingress-create.d.mts +4 -0
- package/stack/ingress-create.mjs +82 -86
- package/stack/ingress-publish.d.mts +6 -0
- package/stack/ingress-publish.mjs +194 -182
- package/stack/ingress.d.mts +55 -0
- package/stack/ingress.mjs +534 -524
- package/stack/jobs.d.mts +12 -0
- package/stack/jobs.mjs +35 -34
- package/stack/live-restore.d.mts +35 -0
- package/stack/live-restore.mjs +120 -125
- package/stack/post-deploy.d.mts +8 -0
- package/stack/post-deploy.mjs +25 -25
- package/stack/prepare.d.mts +24 -0
- package/stack/prepare.mjs +213 -200
- package/stack/private-file.d.mts +5 -0
- package/stack/private-file.mjs +9 -9
- package/stack/provision.d.mts +25 -0
- package/stack/provision.mjs +64 -63
- package/stack/prune.d.mts +11 -0
- package/stack/prune.mjs +38 -27
- package/stack/release-store.d.mts +28 -0
- package/stack/release-store.mjs +68 -67
- package/stack/remote.d.mts +83 -0
- package/stack/remote.mjs +176 -162
- package/stack/render.d.mts +14 -0
- package/stack/render.mjs +132 -124
- package/stack/retire.d.mts +9 -0
- package/stack/retire.mjs +31 -34
- package/stack/sealed.d.mts +46 -0
- package/stack/sealed.mjs +78 -82
- package/stack/server-key.d.mts +67 -0
- package/stack/server-key.mjs +217 -203
- package/stack/ssh-session.d.mts +29 -0
- package/stack/ssh-session.mjs +133 -123
- package/stack/target-binding.d.mts +21 -0
- package/stack/target-binding.mjs +68 -44
- package/stack/task.d.mts +12 -0
- package/stack/task.mjs +26 -31
- package/stack/urgent-floor.d.mts +106 -0
- package/stack/urgent-floor.mjs +211 -160
- package/stack/urgent-release.d.mts +38 -0
- package/stack/urgent-release.mjs +26 -22
- package/stack/verify.d.mts +14 -0
- package/stack/verify.mjs +75 -65
- package/sync/ci-commands.d.mts +26 -0
- package/sync/ci-commands.mjs +181 -182
- package/sync/cli.d.mts +8 -0
- package/sync/cli.mjs +9 -9
- package/sync/format.d.mts +38 -0
- package/sync/format.mjs +30 -24
- package/sync/hygiene.d.mts +23 -0
- package/sync/hygiene.mjs +113 -99
- package/sync/index.d.mts +237 -0
- package/sync/index.mjs +457 -436
- package/sync/managed.d.mts +23 -0
- package/sync/managed.mjs +104 -94
- package/sync/quality-services.d.mts +35 -0
- package/sync/quality-services.mjs +48 -41
- package/sync/readme-badges.d.mts +13 -0
- package/sync/readme-badges.mjs +45 -44
- package/sync/sonar-key.d.mts +31 -0
- package/sync/sonar-key.mjs +29 -28
- package/sync/stack-images.d.mts +36 -0
- package/sync/stack-images.mjs +85 -95
- package/sync/ts-strict.d.mts +14 -0
- package/sync/ts-strict.mjs +43 -34
- package/templates/app/ci-workflows/github/workflows/ci.yml +1 -1
- package/templates/app/ci-workflows/github/workflows/images.yml +1 -1
- package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +2 -2
- package/templates/app/ci-workflows/github/workflows/stack-key-restore.yml +1 -1
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +1 -1
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +3 -3
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +1 -1
- package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +2 -2
- package/templates/app/ci-workflows-lite/github/workflows/stack-key-restore.yml +1 -1
- package/templates/app/codegen-lite/scripts/codegen.mjs +1 -1
- package/templates/app/db-bootstrap/db/bootstrap.sql +1 -1
- package/templates/app/db-image/starcistacks/images/db/Dockerfile +1 -1
- package/templates/app/hooks/husky/pre-commit +2 -2
- package/templates/app/package-scripts/db.json +3 -3
- package/templates/app/package-scripts/package.json +1 -1
- package/templates/app/quality-config/sonar-project.properties +1 -1
- package/templates/app/skeleton/.starcistacks/application-stacks.yaml +2 -2
- package/templates/app/skeleton/.starcistacks/production/README.md +4 -4
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +8 -3
- package/templates/app/skeleton/README.md +1 -1
- package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +2 -2
- package/templates/app/skeleton-lite/.starcistacks/dev/README.md +1 -1
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +6 -2
- package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +3 -2
- package/templates/app/skeleton-lite/.starcistacks/production/README.md +5 -5
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +7 -2
- package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +3 -2
- package/templates/app/skeleton-lite/README.md +2 -2
- package/templates/be/skeleton/apps/cli/src/compose/platform.ts +1 -1
- package/templates/be/skeleton/apps/cli/src/main.ts +6 -4
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/database/abstract.entity.ts +19 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module.ts +7 -1
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +19 -0
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +4 -3
- package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/logging/logging.options.ts +5 -2
- package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +1 -1
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.spec.ts +40 -0
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.ts +1 -0
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.spec.ts +48 -1
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.ts +5 -0
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.options.ts +5 -0
- package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/google.strategy.ts +1 -1
- package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/oauth-state.store.ts +7 -3
- package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +7 -1
- package/templates/be/table/entity.ts.tpl +4 -15
- package/upgrade/check.d.mts +9 -0
- package/upgrade/check.mjs +8 -8
- package/upgrade/file-state.d.mts +6 -0
- package/upgrade/file-state.mjs +32 -40
- package/upgrade/index.d.mts +13 -0
- package/upgrade/index.mjs +122 -151
- package/vendor-types.d.mts +8 -0
package/release/gate.mjs
CHANGED
|
@@ -14,10 +14,8 @@ import { failure, refusal } from '../stack/errors.mjs';
|
|
|
14
14
|
import { produceLintReports } from './lint-report.mjs';
|
|
15
15
|
import { URGENT_RULING, l4Path, readUrgent, recordRow, writeUrgent } from './records.mjs';
|
|
16
16
|
import { sonarQualityGate } from './sonar-quality-gate.mjs';
|
|
17
|
-
|
|
18
17
|
export const RELEASE_CODE = 'RELEASE_CONFIG_INVALID';
|
|
19
18
|
const SONAR_UNREACHABLE = 'SONAR_UNREACHABLE';
|
|
20
|
-
|
|
21
19
|
const FIELDS = new Set(['gates', 'tagPrefix', 'defaultBranch', 'requireCi']);
|
|
22
20
|
/** Release-block keys that no longer exist, each with what replaced it. */
|
|
23
21
|
const REMOVED_FIELDS = new Map([['tagMatchesVersion', 'the release tag is always <tagPrefix><package.json version>; delete the key']]);
|
|
@@ -40,433 +38,463 @@ const SCRIPT_GATES = ['format:check', 'typecheck', 'build:be', 'lint', 'db:lint'
|
|
|
40
38
|
const WORLD_SCRIPTS = ['test:integration', 'test:e2e', 'test:contract'];
|
|
41
39
|
// An app with an entity list (db/entity-list.mjs) checks its entities against the migrated schema: a row of every gate, declared or default.
|
|
42
40
|
const DB_DRIFT = { name: 'db-drift', command: ['npx', 'starci', 'app', 'db', 'drift'], summary: null, env: {} };
|
|
43
|
-
|
|
44
41
|
/** True for a branch or remote name git can take as one argument (no leading dash, only path-like characters). */
|
|
45
42
|
export const refName = (value) => typeof value === 'string' && REF_NAME.test(value);
|
|
46
|
-
|
|
47
43
|
const scriptGate = (script) => ({
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
name: script.replaceAll(':', '-'),
|
|
45
|
+
command: ['npm', 'run', script],
|
|
46
|
+
summary: script === 'test' ? 'jest' : null,
|
|
47
|
+
env: {},
|
|
52
48
|
});
|
|
53
|
-
|
|
54
49
|
/** Default gates run app-check, the enabled audit, then every managed script present in the app and the entity drift row, Sonar following when it is declared. */
|
|
55
50
|
function defaultGates(scripts, audit, entities) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
const present = SCRIPT_GATES.filter((script) => typeof scripts?.[script] === 'string');
|
|
52
|
+
const world = typeof scripts?.['test:e2e'] === 'string' ? WORLD_SCRIPTS.filter((script) => typeof scripts?.[script] === 'string') : [];
|
|
53
|
+
return [{ name: 'app-check', command: ['npx', 'starci', 'app', 'check'], summary: null, env: {} }, ...(audit ? [audit] : []), ...present.map(scriptGate), ...world.map(scriptGate), ...(entities ? [DB_DRIFT] : [])];
|
|
59
54
|
}
|
|
60
|
-
|
|
61
55
|
/** Shared quality settings retain the release reader's audit validation, disabled mode and legacy string host compatibility. */
|
|
62
56
|
function releaseServices(services, options) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
57
|
+
const audit = services?.audit ?? {};
|
|
58
|
+
if (!plain(audit) || (audit.in !== undefined && (!Array.isArray(audit.in) || !audit.in.every((scope) => typeof scope === 'string'))) || (audit.omitDev !== undefined && typeof audit.omitDev !== 'boolean'))
|
|
59
|
+
throw refusal(RELEASE_CODE, 'services.audit must be a mapping with a string-list in and boolean omitDev');
|
|
60
|
+
const sonar = services?.sonar;
|
|
61
|
+
const compatible = typeof sonar?.host === 'string' ? { ...sonar, host: { public: sonar.host } } : sonar;
|
|
62
|
+
const quality = qualityServices({ services: { ...services, sonar: compatible } }, options);
|
|
63
|
+
if (audit.mode === 'disabled')
|
|
64
|
+
quality.audit = null;
|
|
65
|
+
return quality;
|
|
66
|
+
}
|
|
72
67
|
/** The shared audit settings preserve release scope, level and development-dependency selection. */
|
|
73
68
|
function auditGate(audit) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
if (!audit || !audit.in.includes('release-gate'))
|
|
70
|
+
return null;
|
|
71
|
+
if (!['info', 'low', 'moderate', 'high', 'critical'].includes(audit.level))
|
|
72
|
+
throw refusal(RELEASE_CODE, 'services.audit.level must be an npm audit level');
|
|
73
|
+
return { name: 'audit', command: ['npm', 'audit', ...(audit.omitDev ? ['--omit=dev'] : []), `--audit-level=${audit.level}`], summary: null, env: {} };
|
|
77
74
|
}
|
|
78
|
-
|
|
79
75
|
/** A requested local Sonar scan uses only the declared host and token variable; the token never enters argv. */
|
|
80
76
|
function sonarGate(services, env) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
77
|
+
const configured = services?.sonar;
|
|
78
|
+
const sonar = configured?.provider === 'sonarcloud' ? { ...configured, host: 'https://sonarcloud.io' } : configured;
|
|
79
|
+
const tokenName = sonar?.token;
|
|
80
|
+
if (!sonar?.host || !ENV_KEY.test(tokenName) || !env[tokenName])
|
|
81
|
+
throw refusal('RELEASE_SONAR_UNAVAILABLE', 'declare an enabled services.sonar host and set its ci.token environment variable');
|
|
82
|
+
const command = ['npx', '--yes', '@sonar/scan@4.3.0', `-Dsonar.host.url=${sonar.host}`];
|
|
83
|
+
const organization = sonar.organization ?? (sonar.organizationVar ? env[sonar.organizationVar] : null);
|
|
84
|
+
if (organization)
|
|
85
|
+
command.push(`-Dsonar.organization=${organization}`);
|
|
86
|
+
if (!command.every((word) => TOKEN.test(word)))
|
|
87
|
+
throw refusal('RELEASE_SONAR_UNAVAILABLE', 'Sonar host and organization must be plain command arguments');
|
|
88
|
+
return { name: 'sonar', command, summary: null, env: { SONAR_TOKEN: env[tokenName] }, provider: sonar,
|
|
89
|
+
credentialNames: [...new Set(['SONAR_TOKEN', tokenName])] };
|
|
90
|
+
}
|
|
93
91
|
function gateProblems(entry, at, seen) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
92
|
+
const found = [];
|
|
93
|
+
for (const key of Object.keys(entry))
|
|
94
|
+
if (!GATE_FIELDS.has(key))
|
|
95
|
+
found.push(`${at}.${key}: is not a field of a gate`);
|
|
96
|
+
if (typeof entry.name !== 'string' || !GATE_NAME.test(entry.name))
|
|
97
|
+
found.push(`${at}.name: must match ${GATE_NAME}`);
|
|
98
|
+
else if (seen.has(entry.name))
|
|
99
|
+
found.push(`${at}.name: ${entry.name} is declared twice`);
|
|
100
|
+
const command = entry.command;
|
|
101
|
+
if (!Array.isArray(command) || command.length === 0 || !command.every((word) => typeof word === 'string' && TOKEN.test(word)))
|
|
102
|
+
found.push(`${at}.command: must be a non-empty list of plain words (no shell strings)`);
|
|
103
|
+
if (entry.summary !== undefined && entry.summary !== 'jest')
|
|
104
|
+
found.push(`${at}.summary: must be jest`);
|
|
105
|
+
const env = entry.env ?? {};
|
|
106
|
+
if (!plain(env) || !Object.entries(env).every(([key, value]) => ENV_KEY.test(key) && typeof value === 'string'))
|
|
107
|
+
found.push(`${at}.env: must map UPPER_CASE names to string values`);
|
|
108
|
+
return found;
|
|
109
|
+
}
|
|
106
110
|
function gatesOf(list, problems) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
const seen = new Set();
|
|
112
|
-
const gates = [];
|
|
113
|
-
list.forEach((entry, index) => {
|
|
114
|
-
const at = `release.gates[${index}]`;
|
|
115
|
-
const found = plain(entry) ? gateProblems(entry, at, seen) : [`${at}: must be a mapping`];
|
|
116
|
-
problems.push(...found);
|
|
117
|
-
if (found.length === 0) {
|
|
118
|
-
seen.add(entry.name);
|
|
119
|
-
gates.push({ name: entry.name, command: entry.command, summary: entry.summary ?? null, env: entry.env ?? {} });
|
|
111
|
+
if (!Array.isArray(list) || list.length === 0) {
|
|
112
|
+
problems.push('release.gates: must be a non-empty list');
|
|
113
|
+
return [];
|
|
120
114
|
}
|
|
121
|
-
|
|
122
|
-
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
const gates = [];
|
|
117
|
+
list.forEach((entry, index) => {
|
|
118
|
+
const at = `release.gates[${index}]`;
|
|
119
|
+
const found = plain(entry) ? gateProblems(entry, at, seen) : [`${at}: must be a mapping`];
|
|
120
|
+
problems.push(...found);
|
|
121
|
+
if (found.length === 0) {
|
|
122
|
+
seen.add(entry.name);
|
|
123
|
+
gates.push({ name: entry.name, command: entry.command, summary: entry.summary ?? null, env: entry.env ?? {} });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
return gates;
|
|
123
127
|
}
|
|
124
|
-
|
|
125
128
|
/** Judges the optional `release:` block. Absence is fine (defaults). Returns { config } or { problems }. */
|
|
126
129
|
export function normalizeRelease(block, scripts = {}, services = {}, options = {}) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
130
|
+
const given = block ?? {};
|
|
131
|
+
if (!plain(given))
|
|
132
|
+
return { problems: ['release: must be a mapping'] };
|
|
133
|
+
const raw = given; // reason: the release block is YAML parsed from disk; every field is judged below
|
|
134
|
+
const problems = [];
|
|
135
|
+
for (const key of Object.keys(raw)) {
|
|
136
|
+
if (REMOVED_FIELDS.has(key))
|
|
137
|
+
problems.push(`release.${key}: is removed (${REMOVED_FIELDS.get(key)})`);
|
|
138
|
+
else if (!FIELDS.has(key))
|
|
139
|
+
problems.push(`release.${key}: is not a field of the release block`);
|
|
140
|
+
}
|
|
141
|
+
const tagPrefix = raw.tagPrefix ?? 'v';
|
|
142
|
+
const defaultBranch = raw.defaultBranch ?? 'main';
|
|
143
|
+
// The candidate CI of `release push` is an app's choice and off by default (owner ruling release-require-ci-per-project); the local gate never is.
|
|
144
|
+
const requireCi = raw.requireCi ?? false;
|
|
145
|
+
if (typeof tagPrefix !== 'string' || !PREFIX.test(tagPrefix))
|
|
146
|
+
problems.push(`release.tagPrefix: must match ${PREFIX}`);
|
|
147
|
+
if (!refName(defaultBranch))
|
|
148
|
+
problems.push(`release.defaultBranch: must match ${REF_NAME}`);
|
|
149
|
+
if (typeof requireCi !== 'boolean')
|
|
150
|
+
problems.push('release.requireCi: must be true or false');
|
|
151
|
+
const quality = releaseServices(services, options);
|
|
152
|
+
const audit = auditGate(quality.audit);
|
|
153
|
+
const gates = raw.gates === undefined ? defaultGates(scripts, audit, options.entities === true) : gatesOf(raw.gates, problems);
|
|
154
|
+
if (raw.gates !== undefined && audit && !gates.some((gate) => gate.name === 'audit'))
|
|
155
|
+
gates.push(audit);
|
|
156
|
+
if (raw.gates !== undefined && options.entities === true && !gates.some((gate) => gate.name === DB_DRIFT.name))
|
|
157
|
+
gates.push(DB_DRIFT);
|
|
158
|
+
return problems.length === 0 ? { config: { gates, tagPrefix, defaultBranch, requireCi, services: quality } } : { problems };
|
|
159
|
+
}
|
|
149
160
|
/* ---- git through the seam */
|
|
150
|
-
|
|
151
161
|
/** Runs git in the app root; a missing git or (unless allowFail) a non-zero exit is a failure whose message names the first stderr line. */
|
|
152
162
|
export function git(ctx, args, { allowFail = false } = {}) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
163
|
+
const run = tool(ctx, 'git', args, { cwd: ctx.cwd, env: ctx.env });
|
|
164
|
+
if (run.error)
|
|
165
|
+
throw failure('RELEASE_GIT_MISSING', `cannot run git (${run.error.message})`);
|
|
166
|
+
if (run.status !== 0 && !allowFail)
|
|
167
|
+
throw failure('RELEASE_GIT_FAILED', `git ${args.slice(0, 2).join(' ')}: ${firstLine(run.stderr)}`);
|
|
168
|
+
return { code: run.status, stdout: String(run.stdout ?? '').trim(), stderr: String(run.stderr ?? '') };
|
|
157
169
|
}
|
|
158
|
-
|
|
159
170
|
/** The directory that holds the L4 records: <git common dir>/starci-release. */
|
|
160
171
|
export const releaseDir = (ctx) => path.join(path.resolve(ctx.cwd, git(ctx, ['rev-parse', '--git-common-dir']).stdout), 'starci-release');
|
|
161
|
-
|
|
162
172
|
/** Annotated tags `<prefix><digit>*` that point at HEAD (lightweight tags do not count: the hook ignores them). */
|
|
163
173
|
export function annotatedOnHead(ctx, prefix) {
|
|
164
|
-
|
|
165
|
-
|
|
174
|
+
const names = lines(git(ctx, ['tag', '--points-at', 'HEAD', '--list', `${prefix}[0-9]*`]).stdout);
|
|
175
|
+
return names.filter((name) => git(ctx, ['cat-file', '-t', `refs/tags/${name}`], { allowFail: true }).stdout === 'tag');
|
|
166
176
|
}
|
|
167
|
-
|
|
168
177
|
/** Every tag on HEAD whose name ends in a version, annotated or not, under any prefix: a release commit carries exactly one. */
|
|
169
178
|
const versionTagsOnHead = (ctx) => lines(git(ctx, ['tag', '--points-at', 'HEAD']).stdout).filter((name) => /[0-9]+[.][0-9]+[.][0-9]+$/u.test(name));
|
|
170
|
-
|
|
171
179
|
/** The rewrittenBy predicate of the app's slots: true for a path a dev server writes (hfs slots `rewrittenBy`); without a readable hfs.json, for none. */
|
|
172
180
|
function rewrittenByDevServer(root) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
let hfs; // reason: openHfs is the slot machine of the app's hfs.json (runtime/scripts/hfs/slots.mjs)
|
|
182
|
+
try {
|
|
183
|
+
hfs = openHfs({ repoRoot: root });
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return () => false;
|
|
187
|
+
}
|
|
188
|
+
return (file) => typeof hfs.slotOf(file)?.rewrittenBy === 'string';
|
|
176
189
|
}
|
|
177
|
-
|
|
178
190
|
/**
|
|
179
191
|
* The paths that make the tree dirty: every changed tracked path and every untracked one, except an untracked file the app's slots declare a dev
|
|
180
192
|
* server rewrites (`rewrittenBy`, e.g. the AGENTS.md `next dev` writes): that one is known generated output, never a change of the release.
|
|
181
193
|
*/
|
|
182
194
|
export function dirtyPaths(ctx) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
195
|
+
const rewritten = rewrittenByDevServer(ctx.cwd);
|
|
196
|
+
return lines(git(ctx, ['status', '--porcelain', '--untracked-files=all']).stdout)
|
|
197
|
+
.filter((line) => !(line.startsWith('?? ') && rewritten(line.slice(3).replace(/^"|"$/gu, ''))));
|
|
186
198
|
}
|
|
187
|
-
|
|
188
199
|
/** Tag names that exist locally or on the remote. */
|
|
189
200
|
function takenTags(ctx, prefix, remote) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
201
|
+
const local = lines(git(ctx, ['tag', '--list', `${prefix}*`]).stdout);
|
|
202
|
+
const listed = lines(git(ctx, ['ls-remote', '--tags', remote], { allowFail: true }).stdout);
|
|
203
|
+
const remoteNames = listed.map((line) => line.split('refs/tags/')[1]?.replace(/\^\{\}$/u, '')).filter((name) => Boolean(name));
|
|
204
|
+
return new Set([...local, ...remoteNames]);
|
|
194
205
|
}
|
|
195
|
-
|
|
196
206
|
/** The tag this release uses is `<prefix><package version>`; its state is on-head (reused), free (will be created) or taken (exists on another commit). */
|
|
197
207
|
function chooseTag(ctx, config, { prefix, remote }) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
208
|
+
const tag = `${prefix}${config.version}`;
|
|
209
|
+
if (annotatedOnHead(ctx, prefix).includes(tag))
|
|
210
|
+
return { tag, state: 'on-head' };
|
|
211
|
+
return { tag, state: takenTags(ctx, prefix, remote).has(tag) ? 'taken' : 'free' };
|
|
201
212
|
}
|
|
202
|
-
|
|
203
213
|
/* ---- gate results */
|
|
204
|
-
|
|
205
214
|
const sha256 = (file) => createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
|
206
|
-
|
|
207
215
|
const lineAfter = (text, label) => {
|
|
208
|
-
|
|
209
|
-
|
|
216
|
+
const found = text.split('\n').find((line) => line.startsWith(label));
|
|
217
|
+
return found === undefined ? null : found.slice(label.length).trim();
|
|
210
218
|
};
|
|
211
|
-
|
|
212
219
|
/** The jest summary lines of a log: { suites, failedSuites, tests, failed, passed } or null when jest printed none. */
|
|
213
220
|
function jestSummary(text) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
221
|
+
const suites = lineAfter(text, 'Test Suites:');
|
|
222
|
+
const tests = lineAfter(text, 'Tests:');
|
|
223
|
+
if (suites === null || tests === null)
|
|
224
|
+
return null;
|
|
225
|
+
const count = (line, word) => Number(new RegExp(String.raw `(\d+) ${word}`, 'u').exec(line)?.[1] ?? 0);
|
|
226
|
+
return {
|
|
227
|
+
suites: count(suites, 'total'), failedSuites: count(suites, 'failed'),
|
|
228
|
+
tests: count(tests, 'total'), failed: count(tests, 'failed'), passed: count(tests, 'passed'),
|
|
229
|
+
};
|
|
230
|
+
}
|
|
224
231
|
/** Judges a jest-style gate from its log: green needs suites that all passed, every test passed and no coverage threshold miss. */
|
|
225
232
|
function judgeJest(text) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
233
|
+
const summary = jestSummary(text);
|
|
234
|
+
const misses = (text.match(THRESHOLD_MISS) ?? []).length;
|
|
235
|
+
if (!summary)
|
|
236
|
+
return { pass: false, detail: 'no jest summary in the log', summary: null, misses };
|
|
237
|
+
const pass = summary.suites > 0 && summary.failedSuites === 0 && summary.failed === 0 && summary.passed === summary.tests && misses === 0;
|
|
238
|
+
const detail = `suites ${summary.suites - summary.failedSuites}/${summary.suites}, tests ${summary.passed}/${summary.tests}, coverage-threshold misses ${misses}`;
|
|
239
|
+
return { pass, detail, summary, misses };
|
|
240
|
+
}
|
|
234
241
|
/** [command, args] to start an argv; on Windows npm and npx are .cmd files, so they start through cmd.exe (words are validated, never a shell string). */
|
|
235
242
|
export function launch(argv, platform) {
|
|
236
|
-
|
|
237
|
-
|
|
243
|
+
if (platform === 'win32' && WRAPPED.has(argv[0]))
|
|
244
|
+
return ['cmd.exe', ['/d', '/s', '/c', ...argv]];
|
|
245
|
+
return [argv[0], argv.slice(1)];
|
|
238
246
|
}
|
|
239
|
-
|
|
240
247
|
/** Sonar availability is public and bounded; HTTP uses the existing injected fetch seam. An unreachable host is a red row: Sonar is required. */
|
|
241
248
|
async function sonarAvailability(ctx, gate) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
const sonar = gate.provider;
|
|
250
|
+
if (!sonar)
|
|
251
|
+
return null;
|
|
252
|
+
let up = false;
|
|
253
|
+
try {
|
|
254
|
+
const response = await ctx.fetch(sonar.host.replace(/\/$/u, '') + '/api/system/status', { signal: AbortSignal.timeout(10000) });
|
|
255
|
+
up = response.ok && (await response.json()).status === 'UP';
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
up = false;
|
|
259
|
+
}
|
|
260
|
+
if (up)
|
|
261
|
+
return null;
|
|
262
|
+
return { pass: false, detail: `${SONAR_UNREACHABLE}: ${sonar.host} did not report UP within ten seconds` };
|
|
263
|
+
}
|
|
253
264
|
/** An unreachable Sonar host stays a red row with a real log and no scan invocation. */
|
|
254
265
|
export async function runAvailableGate(ctx, gate, options) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
const availability = await sonarAvailability(ctx, gate);
|
|
267
|
+
const log = path.join(options.dir, `${gate.name}.log`);
|
|
268
|
+
if (!availability) {
|
|
269
|
+
if (!gate.provider)
|
|
270
|
+
return runGate(ctx, gate, options);
|
|
271
|
+
// The scanner imports the app's declared external issues report: produce it first with the app's own lint, as the managed CI does.
|
|
272
|
+
const started = ctx.now();
|
|
273
|
+
const lint = produceLintReports(ctx, { launch, platform: options.platform, env: withoutCredentials(ctx.env, options.credentialNames) });
|
|
274
|
+
if (lint.pass)
|
|
275
|
+
return judgeQualityGate(ctx, gate, runGate(ctx, gate, { ...options, preface: lint.text }));
|
|
276
|
+
fs.writeFileSync(log, lint.text);
|
|
277
|
+
return { name: gate.name, command: gate.command.join(' '), pass: false, detail: 'lint report failed (see log)', seconds: Math.round((ctx.now() - started) / 1000),
|
|
278
|
+
summary: null, log: path.resolve(log), logSha256: sha256(log), env: Object.keys(gate.env) };
|
|
279
|
+
}
|
|
280
|
+
fs.writeFileSync(log, availability.detail + '\n');
|
|
281
|
+
return { name: gate.name, command: gate.command.join(' '), ...availability, seconds: 0,
|
|
282
|
+
summary: null, log: path.resolve(log), logSha256: sha256(log), env: Object.keys(gate.env) };
|
|
283
|
+
}
|
|
272
284
|
/**
|
|
273
285
|
* A scanner that exited 0 only uploaded its report: the row passes when the server's quality gate of that analysis is OK
|
|
274
286
|
* (sonar-quality-gate.mjs). The verdict replaces the row's detail and is appended to its log; the row's time includes the wait.
|
|
275
287
|
*/
|
|
276
288
|
async function judgeQualityGate(ctx, gate, row) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
|
|
289
|
+
if (!row.pass)
|
|
290
|
+
return row;
|
|
291
|
+
const started = ctx.now();
|
|
292
|
+
const verdict = await sonarQualityGate(ctx, { cwd: ctx.cwd, host: gate.provider.host, token: gate.env.SONAR_TOKEN });
|
|
293
|
+
const failed = (verdict.conditions ?? []).map((line) => ` failed: ${line}\n`).join('');
|
|
294
|
+
fs.appendFileSync(row.log, `\nquality gate: ${verdict.detail}\n${failed}`);
|
|
295
|
+
return { ...row, pass: verdict.pass, detail: verdict.detail, seconds: row.seconds + Math.round((ctx.now() - started) / 1000), logSha256: sha256(row.log) };
|
|
296
|
+
}
|
|
285
297
|
export const withoutCredentials = (values, credentialNames) => {
|
|
286
|
-
|
|
287
|
-
|
|
298
|
+
const selected = new Set(credentialNames);
|
|
299
|
+
return Object.fromEntries(Object.entries(values ?? {}).filter(([key]) => !selected.has(key.toUpperCase())));
|
|
288
300
|
};
|
|
289
|
-
|
|
290
301
|
export function runGate(ctx, gate, { dir, platform, credentialNames, preface = '' }) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
|
|
302
|
+
const log = path.join(dir, `${gate.name}.log`);
|
|
303
|
+
const started = ctx.now();
|
|
304
|
+
const [command, args] = launch(gate.command, platform);
|
|
305
|
+
// The native scanner alone consumes Sonar credentials; ordinary gates cannot inherit or reintroduce them.
|
|
306
|
+
const env = { ...ctx.env, ...(gate.provider ? gate.env : withoutCredentials(gate.env, credentialNames)) };
|
|
307
|
+
const run = tool(ctx, command, args, { cwd: ctx.cwd, env });
|
|
308
|
+
const output = `${run.stdout ?? ''}${run.stderr ?? ''}`;
|
|
309
|
+
const text = gate.name === 'sonar' && gate.env.SONAR_TOKEN ? output.replaceAll(gate.env.SONAR_TOKEN, '[REDACTED]') : output;
|
|
310
|
+
fs.writeFileSync(log, preface + text);
|
|
311
|
+
const verdict = judgeVerdict(run, gate, text);
|
|
312
|
+
if (gate.name === 'sonar' && gate.env.SONAR_TOKEN)
|
|
313
|
+
verdict.detail = verdict.detail.replaceAll(gate.env.SONAR_TOKEN, '[REDACTED]');
|
|
314
|
+
const seconds = Math.round((ctx.now() - started) / 1000);
|
|
315
|
+
return {
|
|
316
|
+
name: gate.name, command: gate.command.join(' '), pass: verdict.pass, detail: verdict.detail, seconds,
|
|
317
|
+
summary: verdict.summary ?? null, log: path.resolve(log), logSha256: sha256(log), env: Object.keys(gate.env),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
309
320
|
function judgeVerdict(run, gate, text) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
321
|
+
if (run.error)
|
|
322
|
+
return { pass: false, detail: `cannot run (${run.error.message})` };
|
|
323
|
+
if (run.status !== 0)
|
|
324
|
+
return { pass: false, detail: `exit ${run.status}` };
|
|
325
|
+
if (gate.summary === 'jest')
|
|
326
|
+
return judgeJest(text);
|
|
327
|
+
return { pass: true, detail: 'exit 0' };
|
|
314
328
|
}
|
|
315
|
-
|
|
316
329
|
/* ---- the gate */
|
|
317
|
-
|
|
318
330
|
function sourceProblem(ctx, source, head) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
331
|
+
if (source === 'HEAD')
|
|
332
|
+
return null;
|
|
333
|
+
if (!refName(source))
|
|
334
|
+
return `--sha ${source} is not a ref name`;
|
|
335
|
+
const resolved = git(ctx, ['rev-parse', '--verify', `${source}^{commit}`], { allowFail: true });
|
|
336
|
+
if (resolved.code !== 0)
|
|
337
|
+
return `cannot resolve --sha ${source}`;
|
|
338
|
+
if (resolved.stdout !== head)
|
|
339
|
+
return `--sha ${source} is ${resolved.stdout.slice(0, 10)} but HEAD is ${head.slice(0, 10)}: the hook and the L4 record are about HEAD; check the candidate out first`;
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
327
342
|
function tagLine({ tag, state }) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
343
|
+
if (state === 'on-head')
|
|
344
|
+
return `tag ${tag} (annotated, already on HEAD)`;
|
|
345
|
+
if (state === 'taken')
|
|
346
|
+
return `tag ${tag} (TAKEN by another commit)`;
|
|
347
|
+
return `tag ${tag} (free: will be created, annotated)`;
|
|
331
348
|
}
|
|
332
|
-
|
|
333
349
|
/** Everything that can be known without running a gate: the facts, the red preconditions and the lines that describe them. */
|
|
334
350
|
export function inspect(ctx, config, options) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
|
|
351
|
+
const head = git(ctx, ['rev-parse', 'HEAD']).stdout;
|
|
352
|
+
const branch = git(ctx, ['rev-parse', '--abbrev-ref', 'HEAD'], { allowFail: true }).stdout;
|
|
353
|
+
const out = [`checkout ${ctx.cwd}`, `HEAD ${head} (${branch})`];
|
|
354
|
+
const red = [];
|
|
355
|
+
const problem = sourceProblem(ctx, (options.source ?? 'HEAD'), head);
|
|
356
|
+
if (problem)
|
|
357
|
+
red.push(problem);
|
|
358
|
+
const dirty = dirtyPaths(ctx);
|
|
359
|
+
if (dirty.length > 0)
|
|
360
|
+
red.push(`working tree is not clean (${dirty.length} path(s), first: ${dirty[0].slice(0, 100)}): the record would vouch for files that are not in HEAD`);
|
|
361
|
+
else
|
|
362
|
+
out.push('worktree clean');
|
|
363
|
+
const prefix = (options.tagPrefix ?? config.tagPrefix);
|
|
364
|
+
if (!PREFIX.test(prefix))
|
|
365
|
+
throw refusal('RELEASE_USAGE', `--tag-prefix must match ${PREFIX}`);
|
|
366
|
+
const chosen = chooseTag(ctx, config, { prefix, remote: 'origin' });
|
|
367
|
+
if (chosen.state === 'taken')
|
|
368
|
+
red.push(`tag ${chosen.tag} already exists on another commit (local or remote)`);
|
|
369
|
+
const stray = versionTagsOnHead(ctx).filter((name) => name !== chosen.tag);
|
|
370
|
+
if (stray.length > 0)
|
|
371
|
+
red.push(`HEAD already carries the release tag ${stray[0]} but package.json version ${config.version} gives ${chosen.tag}: a release commit carries exactly one tag, so set the version to match the tag or release a new commit`);
|
|
372
|
+
out.push(tagLine(chosen));
|
|
373
|
+
return { head, chosen, red, out };
|
|
374
|
+
}
|
|
354
375
|
function planLines(config, facts, dir, recordPath) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
|
|
376
|
+
const out = [`L4 record ${recordPath}`, `logs ${dir}`, '', 'gates (every gate must pass, in this order):'];
|
|
377
|
+
for (const gate of config.gates) {
|
|
378
|
+
const summary = gate.summary ? ` (summary: ${gate.summary})` : '';
|
|
379
|
+
const teardown = gate.teardownOf ? ` (teardown of ${gate.teardownOf}: runs whenever it ran)` : '';
|
|
380
|
+
out.push(` ${gate.name.padEnd(17)} ${gate.command.join(' ')}${summary}${teardown}`);
|
|
381
|
+
}
|
|
382
|
+
out.push(`then: write ${path.basename(recordPath)} and \`git tag -a ${facts.chosen.tag}\` on ${facts.head.slice(0, 10)}; push it with \`starci app release push\`.`);
|
|
383
|
+
return out;
|
|
384
|
+
}
|
|
365
385
|
export function assertUnmoved(ctx, head) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
386
|
+
const now = git(ctx, ['rev-parse', 'HEAD']).stdout;
|
|
387
|
+
if (now !== head)
|
|
388
|
+
throw failure('RELEASE_HEAD_MOVED', `HEAD moved during the gates (${head.slice(0, 10)} -> ${now.slice(0, 10)}). No record.`);
|
|
389
|
+
const dirty = dirtyPaths(ctx);
|
|
390
|
+
if (dirty.length > 0)
|
|
391
|
+
throw failure('RELEASE_TREE_DIRTY', `the gates left ${dirty.length} changed or untracked path(s) (first: ${dirty[0].slice(0, 100)}): generated files differ from HEAD. Commit or ignore them properly, then rerun. No record.`);
|
|
370
392
|
}
|
|
371
|
-
|
|
372
393
|
function writeRecord(ctx, { head, tag, results, recordPath, requireCi, promotedFrom = null }) {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
|
|
394
|
+
const record = {
|
|
395
|
+
schema: 'starci-app-l4-record/1', head, tag, createdAt: new Date(ctx.now()).toISOString(), producedBy: 'starci app release gate',
|
|
396
|
+
note: 'Every gate passed on a clean HEAD; every entry links its log and sha256.',
|
|
397
|
+
ci: requireCi === true ? { required: true, note: 'starci app release push waits for the candidate CI of this sha (release.requireCi=true)' } : { required: false, note: CI_NOT_REQUIRED },
|
|
398
|
+
...(promotedFrom ? { promotedFrom } : {}),
|
|
399
|
+
gates: results,
|
|
400
|
+
};
|
|
401
|
+
fs.mkdirSync(path.dirname(recordPath), { recursive: true });
|
|
402
|
+
fs.writeFileSync(recordPath, `${JSON.stringify(record, null, 2)}\n`);
|
|
403
|
+
}
|
|
384
404
|
/**
|
|
385
405
|
* Gates run sequentially because each failure prevents subsequent commands and record creation. A teardown row (`teardownOf`) is the exception: it runs
|
|
386
406
|
* whenever the row it tears down ran, red or green, so a red row never leaves a started service behind; its own verdict counts like any row's.
|
|
387
407
|
*/
|
|
388
408
|
async function runAll(ctx, config, options) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
|
|
409
|
+
fs.mkdirSync(options.dir, { recursive: true });
|
|
410
|
+
return config.gates.reduce(async (pending, gate) => {
|
|
411
|
+
const results = await pending;
|
|
412
|
+
if (results.some((result) => !result.pass) && !(gate.teardownOf && results.some((result) => result.name === gate.teardownOf)))
|
|
413
|
+
return results;
|
|
414
|
+
const result = await runAvailableGate(ctx, gate, options);
|
|
415
|
+
recordRow(options.common, options.head, result);
|
|
416
|
+
return [...results, result];
|
|
417
|
+
}, Promise.resolve([]));
|
|
418
|
+
}
|
|
399
419
|
export function summaryOf(result) {
|
|
400
|
-
|
|
420
|
+
return `${result.pass ? 'PASS' : 'FAIL'} ${result.name} (${result.detail}, ${result.seconds}s) log ${result.log}`;
|
|
401
421
|
}
|
|
402
|
-
|
|
403
422
|
/**
|
|
404
423
|
* The urgent release a back-fill judges: `tag` must name HEAD (the back-fill runs on the very commit that shipped, never a re-release) and HEAD must
|
|
405
424
|
* carry an urgent record of that tag. Returns the record; refuses otherwise.
|
|
406
425
|
*/
|
|
407
426
|
function backfillTarget(ctx, common, tag, head) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
427
|
+
if (!refName(tag))
|
|
428
|
+
throw refusal('RELEASE_USAGE', `--backfill ${tag} is not a tag name`);
|
|
429
|
+
const resolved = git(ctx, ['rev-parse', '--verify', '--quiet', `refs/tags/${tag}^{commit}`], { allowFail: true });
|
|
430
|
+
if (resolved.code !== 0 || resolved.stdout === '')
|
|
431
|
+
throw refusal('RELEASE_BACKFILL_TAG_UNKNOWN', `no tag ${tag} in this repository`);
|
|
432
|
+
if (resolved.stdout !== head)
|
|
433
|
+
throw refusal('RELEASE_BACKFILL_NOT_ON_TAG', `${tag} is ${resolved.stdout.slice(0, 10)} but HEAD is ${head.slice(0, 10)}: run the back-fill in a clean checkout of the tag (git worktree add --detach <dir> ${tag}), so the full gate judges exactly what shipped`);
|
|
434
|
+
const urgent = readUrgent(common, head);
|
|
435
|
+
if (!urgent || urgent.tag !== tag)
|
|
436
|
+
throw refusal('RELEASE_BACKFILL_NOT_URGENT', `${tag} has no urgent record on ${head.slice(0, 10)}: only a release pushed with release push --urgent is back-filled`);
|
|
437
|
+
return urgent;
|
|
438
|
+
}
|
|
417
439
|
/** A red back-fill: the urgent record keeps the verdict and the fix ticket (kind verify) the harness opened; nothing on the remote or on prod changes. */
|
|
418
440
|
function backfillRed(ctx, { common, urgent, failed, openTicket }) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
}
|
|
429
|
-
|
|
441
|
+
const names = failed.map((item) => item.name);
|
|
442
|
+
const title = `RELEASE_BACKFILL_RED: the back-fill of urgent release ${urgent.tag} (${urgent.head.slice(0, 12)}) is red at ${names.join(', ')}`;
|
|
443
|
+
const tail = failed.map((item) => `${item.name}: ${item.detail} (log ${item.log})`).join('\n');
|
|
444
|
+
const ticket = typeof openTicket === 'function' ? openTicket({ title, tail, code: 'RELEASE_BACKFILL_RED', tag: urgent.tag, head: urgent.head }) : null;
|
|
445
|
+
writeUrgent(common, { ...urgent, backfill: { state: 'red', at: new Date(ctx.now()).toISOString(), failed: names, ticket: ticket ?? null } });
|
|
446
|
+
const said = ticket
|
|
447
|
+
? `back-fill red: fix ticket ${ticket} opened (kind verify); ${urgent.tag} stays an urgent release and nothing on the remote or on prod changed`
|
|
448
|
+
: `back-fill red: no ticket queue in this run (run it through the starci CLI to open one); ${urgent.tag} stays an urgent release and nothing on the remote or on prod changed`;
|
|
449
|
+
return { said, ticket: ticket ?? null };
|
|
450
|
+
}
|
|
430
451
|
/**
|
|
431
452
|
* `starci app release gate`: dry run prints the preconditions, the gate list, the head and the tag; --execute runs every gate and, only if required gates pass,
|
|
432
|
-
* writes the L4 record and creates the annotated tag. options: { execute,
|
|
453
|
+
* writes the L4 record and creates the annotated tag. options: { execute, source (the --sha ref), tagPrefix, platform, backfill, openTicket }.
|
|
433
454
|
* With `backfill` (a tag pushed by `release push --urgent`, checked out at HEAD) the same full gate judges that commit: green writes its L4 record
|
|
434
455
|
* (promotedFrom the urgent record) and marks the urgent record promoted, with no new tag and no push; red opens a fix ticket through `openTicket`.
|
|
435
456
|
*/
|
|
436
457
|
export async function releaseGate(ctx, config, options = {}) {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
458
|
+
// Sonar is a row of the managed CI, so it is a row of the local gate whenever the app declares services.sonar; a missing token is a refusal, never a skip.
|
|
459
|
+
if (config.services?.sonar)
|
|
460
|
+
config = { ...config, gates: [...config.gates.filter((gate) => gate.name !== 'sonar'), sonarGate(config.services, ctx.env)] };
|
|
461
|
+
const credentialNames = config.gates.find(gate => gate.provider)?.credentialNames ?? ['SONAR_TOKEN', config.services?.sonar?.token].filter(Boolean);
|
|
462
|
+
ctx = Object.create(ctx, { env: { value: withoutCredentials(ctx.env, credentialNames) } });
|
|
463
|
+
// The CI verdict of a release is the candidate run of its own sha, judged by `starci app release push` (candidate-ci.mjs, OWNER RULING candidate-ci 2026-10-18):
|
|
464
|
+
// the gate no longer refuses over the latest default-branch run.
|
|
465
|
+
const facts = inspect(ctx, config, options);
|
|
466
|
+
const common = releaseDir(ctx);
|
|
467
|
+
const urgent = options.backfill === undefined ? null : backfillTarget(ctx, common, options.backfill, facts.head);
|
|
468
|
+
const recordPath = l4Path(common, facts.head);
|
|
469
|
+
const dir = path.join(common, facts.head.slice(0, 12));
|
|
470
|
+
const plan = [...facts.out, ...planLines(config, facts, dir, recordPath)];
|
|
471
|
+
if (urgent)
|
|
472
|
+
plan.push(`back-fill urgent release ${urgent.tag} (${URGENT_RULING}): green promotes it to this L4 record with no new tag and no push; red opens a fix ticket and changes nothing on prod`);
|
|
473
|
+
const base = { head: facts.head, tag: facts.chosen.tag, record: recordPath, gates: config.gates.map((gate) => gate.name), ...(urgent ? { backfill: urgent.tag } : {}) };
|
|
474
|
+
if (urgent?.backfill?.state === 'promoted')
|
|
475
|
+
return { ok: true, lines: [...plan, `back-fill already promoted ${urgent.tag} to ${urgent.backfill.l4}. Nothing to do.`], data: { ...base, red: [], executed: false, promoted: true } };
|
|
476
|
+
if (facts.red.length > 0)
|
|
477
|
+
return { ok: false, lines: [...plan, ...facts.red.map((item) => `RED: ${item}`), 'nothing was run.'], data: { ...base, red: facts.red, executed: false } };
|
|
478
|
+
if (options.execute !== true)
|
|
479
|
+
return { ok: true, lines: [...plan, '', 'dry run: no gate was run, nothing written. preconditions OK.'], data: { ...base, red: [], executed: false } };
|
|
480
|
+
const results = await runAll(ctx, config, { dir, common, head: facts.head, platform: options.platform ?? process.platform, credentialNames });
|
|
481
|
+
const report = results.map(summaryOf);
|
|
482
|
+
const failed = results.filter((result) => !result.pass);
|
|
483
|
+
if (failed.length > 0 && urgent) {
|
|
484
|
+
const { said, ticket } = backfillRed(ctx, { common, urgent, failed, openTicket: options.openTicket });
|
|
485
|
+
return { ok: false, lines: [...plan, ...report, `gate(s) red: ${failed.map((item) => item.name).join(', ')}. No L4 record.`, said], data: { ...base, executed: true, results, promoted: false, ticket } };
|
|
486
|
+
}
|
|
487
|
+
if (failed.length > 0)
|
|
488
|
+
return { ok: false, lines: [...plan, ...report, `gate(s) red: ${failed.map((item) => item.name).join(', ')}. No L4 record, no tag.`], data: { ...base, executed: true, results } };
|
|
489
|
+
assertUnmoved(ctx, facts.head);
|
|
490
|
+
writeRecord(ctx, { head: facts.head, tag: facts.chosen.tag, results, recordPath, requireCi: config.requireCi, promotedFrom: urgent ? { record: `${facts.head}.urgent.json`, reason: urgent.reason, role: urgent.role, at: urgent.createdAt } : null });
|
|
491
|
+
if (urgent) {
|
|
492
|
+
writeUrgent(common, { ...urgent, backfill: { state: 'promoted', at: new Date(ctx.now()).toISOString(), l4: recordPath } });
|
|
493
|
+
return { ok: true, lines: [...plan, ...report, `L4 record written: ${recordPath}`, `back-fill green: urgent release ${urgent.tag} is promoted to a normal L4 release (no re-release, no push)`], data: { ...base, executed: true, results, promoted: true } };
|
|
494
|
+
}
|
|
495
|
+
const created = facts.chosen.state !== 'on-head';
|
|
496
|
+
if (created)
|
|
497
|
+
git(ctx, ['tag', '-a', facts.chosen.tag, '-m', `release ${facts.chosen.tag}: required gates passed on ${facts.head.slice(0, 12)} (L4 record ${path.basename(recordPath)})`, facts.head]);
|
|
498
|
+
const tagged = created ? `annotated tag ${facts.chosen.tag} created on ${facts.head.slice(0, 10)}` : `annotated tag ${facts.chosen.tag} already on ${facts.head.slice(0, 10)}`;
|
|
499
|
+
return { ok: true, lines: [...plan, ...report, `L4 record written: ${recordPath}`, tagged], data: { ...base, executed: true, results, tagCreated: created } };
|
|
472
500
|
}
|