@starci/hfs 4.11.22 → 4.12.2
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 +31 -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 +414 -325
- 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 +95 -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 +14 -22
- 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 +493 -348
- 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/sync/index.mjs
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// and are listed in this module: the marked blocks of the root .gitignore and README.md, and .starciwork/.gitignore, which lives inside the
|
|
11
11
|
// .starciwork directory slot. Every file is rendered with the app's hfs.json (both sides and their apps) and, for the Sonar
|
|
12
12
|
// exclusions, the jest preset the app installs for its be side and the one coverage scope derived from the slot manifest
|
|
13
|
-
// (scripts/hfs/coverage-scope.mjs: the be/jest.config.js scope, sonar.coverage.exclusions and the codecov.yml paths, components and exclusions).
|
|
14
|
-
// file on disk and fails on any drift; `--
|
|
13
|
+
// (scripts/hfs/coverage-scope.mjs: the be/jest.config.js scope, sonar.coverage.exclusions and the codecov.yml paths, components and exclusions). The default run (a dry run) compares the sha256 of the rendered content with the
|
|
14
|
+
// file on disk and fails on any drift; `--execute` rewrites the drifted files. `.gitignore` and README.md are shared files: only the marked
|
|
15
15
|
// block is managed and the app's own lines around it are left alone. The root package.json is managed by its `scripts` block
|
|
16
16
|
// only (mode scripts, compared as parsed JSON): the rest of the file (dependencies, the npm workspaces fe/apps/* and fe/packages/*,
|
|
17
17
|
// HFS_MONO_WORKSPACES) is the app's. The fe side runs through turbo (turbo.json, app.task-graph): each fe app and package is a workspace.
|
|
@@ -22,7 +22,7 @@ import path from 'node:path';
|
|
|
22
22
|
import { fileURLToPath } from 'node:url';
|
|
23
23
|
import { braceVariants } from '../runtime/scripts/lib/glob.mjs';
|
|
24
24
|
import { codecovPaths, coverageComponents, jestCoverage, sonarCoverageExclusions } from '../runtime/scripts/hfs/coverage-scope.mjs';
|
|
25
|
-
import { APP_SCOPE, SIDES, litePresenceOf, loadSlotManifest,
|
|
25
|
+
import { APP_SCOPE, SIDES, litePresenceOf, loadSlotManifest, resolveAppDeclaration, slotInEdition } from '../runtime/scripts/hfs/slots.mjs';
|
|
26
26
|
import { managedGroupOf } from '../runtime/scripts/hfs/edition-slots.mjs';
|
|
27
27
|
import { declaredSlotEnabled } from '../runtime/scripts/hfs/declaration-slots.mjs';
|
|
28
28
|
import { feAppPackageName } from '../runtime/scripts/hfs/rules/monorepo.mjs';
|
|
@@ -42,7 +42,6 @@ import { readTruths } from '../runtime/scripts/lib/loosening-state.mjs';
|
|
|
42
42
|
import { parseYaml as bundledParseYaml } from '../runtime/engine/yaml.mjs';
|
|
43
43
|
import { bootstrapSection } from '../runtime/scripts/hfs/rules/database-constants.mjs';
|
|
44
44
|
import { SERVER_AGE_IDENTITY } from '../stack/server-key.mjs';
|
|
45
|
-
|
|
46
45
|
export const TEMPLATES_DIR = path.join(import.meta.dirname, '..', 'templates');
|
|
47
46
|
const NODE_MAJOR = 22;
|
|
48
47
|
const APP_BINARY = 'starci app';
|
|
@@ -50,116 +49,114 @@ const APP_BINARY = 'starci app';
|
|
|
50
49
|
export const SCOPES = Object.freeze([APP_SCOPE, ...SIDES]);
|
|
51
50
|
const BLOCK_BEGIN = '# >>> starci app sync (managed block; do not edit) >>>';
|
|
52
51
|
const BLOCK_END = '# <<< starci app sync <<<';
|
|
53
|
-
const HEADER = scope => `# Generated by ${APP_BINARY} sync (${scope === APP_SCOPE ? 'app root' : scope + ' side'}). Do not edit: run "npx ${APP_BINARY} sync --
|
|
54
|
-
|
|
52
|
+
const HEADER = (scope) => `# Generated by ${APP_BINARY} sync (${scope === APP_SCOPE ? 'app root' : scope + ' side'}). Do not edit: run "npx ${APP_BINARY} sync --execute".`;
|
|
55
53
|
export class SyncError extends Error {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
code;
|
|
55
|
+
constructor(code, message) {
|
|
56
|
+
super(`${code}: ${message}`);
|
|
57
|
+
this.code = code;
|
|
58
|
+
}
|
|
60
59
|
}
|
|
61
|
-
|
|
62
60
|
// mode: file = whole file, block = the marked block inside a file the app also writes to, scripts = the `scripts` block of
|
|
63
61
|
// package.json, section = the whole file but the one marked section a database verb owns (db/bootstrap.sql, whose squash section
|
|
64
62
|
// `starci app db baseline --squash` writes). A template that can hold a comment opens with {{header}}; a file whose exact content is
|
|
65
63
|
// specified (JSON, the eslint one-liner) has no header.
|
|
66
64
|
const MODE_OF_GROUP = Object.freeze({ 'package-scripts': 'scripts', 'package-scripts-lite': 'scripts', 'db-bootstrap': 'section' });
|
|
67
65
|
const GLOB_CHARACTERS = new Set('*?<>{}[]');
|
|
68
|
-
const literalFile = file => file.length >= 2 && !file.endsWith('/') && ![...file].some(character => GLOB_CHARACTERS.has(character));
|
|
69
|
-
|
|
66
|
+
const literalFile = (file) => file.length >= 2 && !file.endsWith('/') && ![...file].some(character => GLOB_CHARACTERS.has(character));
|
|
70
67
|
/** The targets no managedBy slot lists as a whole file (see the header of this module); both belong to the app root. */
|
|
71
68
|
const UNLISTED_TARGETS = Object.freeze([
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
].map(Object.freeze));
|
|
75
|
-
|
|
69
|
+
{ path: '.gitignore', template: 'app/gitignore', mode: 'block' },
|
|
70
|
+
{ path: '.starciwork/.gitignore', template: 'app/starciwork.gitignore', mode: 'file' },
|
|
71
|
+
].map((target) => Object.freeze(target)));
|
|
76
72
|
const templateName = (scope, group, file) => `${scope}/${group}/${file.split('/').map(segment => segment.replace(/^\./, '')).join('/')}`;
|
|
77
73
|
const onSide = (scope, file) => (scope === APP_SCOPE ? file : `${scope}/${file}`);
|
|
78
|
-
|
|
79
74
|
function managedTemplate(scope, group, file, hasTemplate) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
const directories = [scope, 'common'];
|
|
76
|
+
const undotted = directories.map(dir => templateName(dir, group, file)).find(name => hasTemplate(name));
|
|
77
|
+
if (undotted || !['skeleton', 'skeleton-lite'].includes(group))
|
|
78
|
+
return undotted;
|
|
79
|
+
return directories.map(dir => `${dir}/${group}/${file}`).find(name => hasTemplate(name));
|
|
84
80
|
}
|
|
85
|
-
|
|
86
81
|
function slotTargets(slot, scope, edition, manifest, hasTemplate, enabled) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
82
|
+
if (!slot.profiles.includes(scope) || !slotInEdition(manifest, slot, edition))
|
|
83
|
+
return [];
|
|
84
|
+
// An opt-in slot is rendered only for a repository that enables it (app.browser-config with `browser: true`).
|
|
85
|
+
if (slot.presence === 'opt-in' && !enabled(slot))
|
|
86
|
+
return [];
|
|
87
|
+
if (edition === 'lite' && litePresenceOf(slot, scope) === 'forbidden')
|
|
88
|
+
return [];
|
|
89
|
+
const group = managedGroupOf(slot, edition);
|
|
90
|
+
if (group === undefined)
|
|
91
|
+
return [];
|
|
92
|
+
const effectivePath = edition === 'lite' ? (slot.lite?.path ?? slot.path) : slot.path;
|
|
93
|
+
return braceVariants(effectivePath).map((file) => {
|
|
94
|
+
const managedKey = edition === 'lite' && slot.liteManagedBy !== undefined ? 'liteManagedBy' : 'managedBy';
|
|
95
|
+
if (!literalFile(file))
|
|
96
|
+
throw new SyncError('HFS_SYNC_MANIFEST_MANAGED', `slot ${slot.id} names ${managedKey} but its path ${effectivePath} is not a list of literal files (${file})`);
|
|
97
|
+
const template = managedTemplate(scope, group, file, hasTemplate);
|
|
98
|
+
if (!template)
|
|
99
|
+
throw new SyncError('HFS_SYNC_TEMPLATE_MISSING', `slot ${slot.id} manages ${file} for ${scope}, but templates/{${scope},common}/${group} has no template for it`);
|
|
100
|
+
return { path: file, template, mode: MODE_OF_GROUP[group] ?? 'file', slot: slot.id };
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
103
|
function unlistedTargets(scope, edition) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
if (scope !== APP_SCOPE)
|
|
105
|
+
return [];
|
|
106
|
+
return UNLISTED_TARGETS.map(target => {
|
|
107
|
+
if (edition !== 'lite')
|
|
108
|
+
return { ...target };
|
|
109
|
+
return { ...target, template: target.path === '.gitignore' ? 'app/gitignore-lite' : 'app/starciwork.gitignore-lite' };
|
|
110
|
+
});
|
|
109
111
|
}
|
|
110
|
-
|
|
111
112
|
/**
|
|
112
113
|
* Every target of `scope` (app, be or fe), its path relative to that scope's folder: the files the manifest's managedBy slots
|
|
113
114
|
* list, then (app root) the unlisted ones. A slot that names managedBy lists literal files only, and each has a template under
|
|
114
115
|
* its scope or under common. `enabled(slot)` decides an opt-in slot (renderTargets passes the declaration's); without it every slot
|
|
115
116
|
* counts, which is what an inventory of the templates needs.
|
|
116
117
|
*/
|
|
117
|
-
export function targetsOf(scope, { edition = 'full', manifest = loadSlotManifest(), hasTemplate = name => fs.existsSync(path.join(TEMPLATES_DIR, name)), enabled = () => true } = {}) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
export const hashOf = text => createHash('sha256').update(lf(text)).digest('hex');
|
|
124
|
-
|
|
118
|
+
export function targetsOf(scope, { edition = 'full', manifest = loadSlotManifest(), hasTemplate = (name) => fs.existsSync(path.join(TEMPLATES_DIR, name)), enabled = (_slot) => true } = {}) {
|
|
119
|
+
const listed = manifest.slots.flatMap(slot => slotTargets(slot, scope, edition, manifest, hasTemplate, enabled));
|
|
120
|
+
return [...listed, ...unlistedTargets(scope, edition)];
|
|
121
|
+
}
|
|
122
|
+
const lf = (text) => text.replace(/\r\n/g, '\n');
|
|
123
|
+
export const hashOf = (text) => createHash('sha256').update(lf(text)).digest('hex');
|
|
125
124
|
/**
|
|
126
125
|
* The hfs.json sync reads: an app declaration valid for the manifest it pins (both sides, their apps, connections, optional slots,
|
|
127
126
|
* reads). Sync never renders configs for a declaration the eslint canons and starci app check would refuse, so a pin bump cannot leave
|
|
128
127
|
* lint unable to start. Answers the resolved app.
|
|
129
128
|
*/
|
|
130
129
|
export function validateHfs(hfs, manifest = loadSlotManifest()) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
130
|
+
try {
|
|
131
|
+
return resolveAppDeclaration(manifest, hfs);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
throw new SyncError('HFS_SYNC_HFS_INVALID', `hfs.json is not a valid app declaration for manifest ${manifest.version}: ${error.message}`);
|
|
135
|
+
}
|
|
136
136
|
}
|
|
137
|
-
|
|
138
137
|
function readBundled(name) {
|
|
139
|
-
|
|
138
|
+
return lf(fs.readFileSync(path.join(TEMPLATES_DIR, name), 'utf8'));
|
|
140
139
|
}
|
|
141
|
-
|
|
142
140
|
/**
|
|
143
141
|
* Fill `{{name}}` from vars and expand `{{> partial}}` lines. A partial line may be written as a line comment (`// {{> partial}}`)
|
|
144
142
|
* so a JavaScript template stays valid source before rendering. Variable-only lines may also use a line comment;
|
|
145
143
|
* empty variable-only lines disappear and an unknown name is an error.
|
|
146
144
|
*/
|
|
147
145
|
export function render(text, vars, readTemplate = readBundled) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
146
|
+
const withPartials = text.replace(/^(?:\/\/ )?\{\{> ([\w./-]+)\}\}\n/gm, (_, name) => trailingNewline(render(readTemplate(name), vars, readTemplate)));
|
|
147
|
+
const presentLines = withPartials.replace(/^[ \t]*(?:\/\/ )?\{\{([A-Za-z]\w*)\}\}[ \t]*(?:\n|$)/gm, (line, key) => vars[key] === '' ? '' : line.replace(/^(\s*)\/\/ /, '$1'));
|
|
148
|
+
return presentLines.replace(/\{\{([A-Za-z]\w*)\}\}/g, (_, key) => {
|
|
149
|
+
if (!Object.hasOwn(vars, key))
|
|
150
|
+
throw new SyncError('HFS_SYNC_TEMPLATE_VARIABLE', `template names {{${key}}}, which sync does not provide`);
|
|
151
|
+
return vars[key];
|
|
152
|
+
});
|
|
153
|
+
}
|
|
157
154
|
function trailingNewline(text) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
let end = text.length;
|
|
156
|
+
while (end > 0 && text[end - 1] === '\n')
|
|
157
|
+
end -= 1;
|
|
158
|
+
return text.slice(0, end) + '\n';
|
|
161
159
|
}
|
|
162
|
-
|
|
163
160
|
/**
|
|
164
161
|
* The base image of a lite app's managed .starcistacks/images/db/Dockerfile (contexts/stack/pins.yaml images postgres, ruling:lite-official-postgres-image): the
|
|
165
162
|
* Docker Official postgres image by digest, to which the Dockerfile adds PGVECTOR_PACKAGE from PGDG and the PGMQ release.
|
|
@@ -172,57 +169,53 @@ export const PGVECTOR_PACKAGE = 'postgresql-17-pgvector=0.8.7-1.pgdg13+1';
|
|
|
172
169
|
* when Docker adds it. PGDG does not package pgmq; it is SQL objects only, so the Dockerfile copies its control and script files.
|
|
173
170
|
*/
|
|
174
171
|
export const PGMQ = Object.freeze({
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
172
|
+
version: '1.13.1',
|
|
173
|
+
source: 'https://github.com/pgmq/pgmq/archive/refs/tags/v1.13.1.tar.gz',
|
|
174
|
+
sha256: '67221f288f42f95c002a64df40f7d660e765e32df8ada0f2672ba915a14827f7',
|
|
178
175
|
});
|
|
179
176
|
/** The local tag the development db container and the drift scratch database run, built from the app's .starcistacks/images/db/Dockerfile. */
|
|
180
|
-
export const dbLocalImage = project => `${project}-db:local`;
|
|
177
|
+
export const dbLocalImage = (project) => `${project}-db:local`;
|
|
181
178
|
/** The digest-pinned image of a lite app's declared Redis, in every environment that runs it (ruling:R212/case-10). */
|
|
182
179
|
export const REDIS_IMAGE = 'redis:7@sha256:c6eabf748fc7a61dbb5a705c78bcf3d6377b1127a97d0ce965c11c44ba46896f';
|
|
183
|
-
|
|
184
|
-
const redisDevText = project => render(readBundled('app/package-scripts/redis-dev.json'), { project, redisImage: REDIS_IMAGE });
|
|
185
|
-
|
|
180
|
+
const redisDevText = (project) => render(readBundled('app/package-scripts/redis-dev.json'), { project, redisImage: REDIS_IMAGE });
|
|
186
181
|
/** The development scripts of a lite app's declared Redis (create once, then start and stop it), as a scripts object. */
|
|
187
|
-
export const redisDevScripts = project => JSON.parse(`{${redisDevText(project).trim().replace(/,$/, '')}}`);
|
|
188
|
-
|
|
182
|
+
export const redisDevScripts = (project) => JSON.parse(`{${redisDevText(project).trim().replace(/,$/, '')}}`);
|
|
189
183
|
/** What the app's sync reads from the jest preset it installs for its be side: the Sonar exclusions ({ sonarExclusions }); both editions install it (a lite back end keeps full's unit run, ruling:R212/case-1, amended by ruling:R212/case-4). */
|
|
190
184
|
export async function loadPresets(root) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
185
|
+
const name = '@starci/jest-preset';
|
|
186
|
+
const require = createRequire(path.join(root, 'package.json'));
|
|
187
|
+
let resolved;
|
|
188
|
+
try {
|
|
189
|
+
resolved = require.resolve(name);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
throw new SyncError('HFS_SYNC_PRESET_MISSING', `${name} is not installed under ${root}; set it to the exact version in knowledge/hfs/canon-pins.yaml and reinstall`);
|
|
193
|
+
}
|
|
194
|
+
return { sonarExclusions: require(resolved).sonarExclusions() };
|
|
195
|
+
}
|
|
202
196
|
/**
|
|
203
197
|
* The jest preset's Sonar exclusions as @starci/hfs ships them: `@starci/jest-preset/sonar-exclusions.cjs` (a require-free module),
|
|
204
198
|
* carried byte for byte in packages/hfs/runtime, so a fresh `starci app scaffold` (nothing installed
|
|
205
199
|
* yet) and an upgrade render the same list the app's installed preset answers. A missing copy is a refusal, never a render without it.
|
|
206
200
|
*/
|
|
207
201
|
const BUNDLED_SONAR_EXCLUSIONS = new URL('../runtime/packages/jest-preset/sonar-exclusions.cjs', import.meta.url);
|
|
208
|
-
|
|
209
202
|
/** The presets ({ sonarExclusions }) of the jest preset version this @starci/hfs pins, read from its bundled copy. */
|
|
210
203
|
export function bundledPresets() {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
|
|
204
|
+
let list;
|
|
205
|
+
try {
|
|
206
|
+
list = createRequire(import.meta.url)(fileURLToPath(BUNDLED_SONAR_EXCLUSIONS));
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
throw new SyncError('HFS_SYNC_PRESET_MISSING', '@starci/hfs ships no runtime/packages/jest-preset/sonar-exclusions.cjs; reinstall @starci/hfs at its published version');
|
|
210
|
+
}
|
|
211
|
+
return { sonarExclusions: list.join(',') };
|
|
212
|
+
}
|
|
220
213
|
/** Where the be unit run writes the lcov report (jest `coverageDirectory` coverage under be/, reporter lcov), from the app root. */
|
|
221
214
|
const LCOV_REPORT = 'be/coverage/lcov.info';
|
|
222
215
|
/** The design truths this package ships: the one list of the exceptions the canon allows, each with its owner ruling. */
|
|
223
216
|
const DESIGN_TRUTHS = path.join(import.meta.dirname, '..', 'runtime', 'knowledge', 'hfs', 'design-truths.yaml');
|
|
224
217
|
/** Every entry the design truths allow on `list`, in manifest order. */
|
|
225
|
-
const designTruthEntries = list => [...new Set(readTruths(bundledParseYaml(fs.readFileSync(DESIGN_TRUTHS, 'utf8'))).literal.filter(allow => allow.list === list).flatMap(allow => allow.entries))];
|
|
218
|
+
const designTruthEntries = (list) => [...new Set(readTruths(bundledParseYaml(fs.readFileSync(DESIGN_TRUTHS, 'utf8'))).literal.filter((allow) => allow.list === list).flatMap((allow) => allow.entries))];
|
|
226
219
|
/**
|
|
227
220
|
* The entries Sonar's copy-paste detection leaves out: every `cpd-exclusions` entry the design truths
|
|
228
221
|
* (knowledge/hfs/design-truths.yaml) allow, today the message catalogs (ruling message-catalogs-not-duplicate-code): a catalog
|
|
@@ -231,7 +224,6 @@ const designTruthEntries = list => [...new Set(readTruths(bundledParseYaml(fs.re
|
|
|
231
224
|
* accepts the block only as this manifest derives it.
|
|
232
225
|
*/
|
|
233
226
|
export const SONAR_CPD_EXCLUSIONS = Object.freeze(designTruthEntries(LIST.cpd));
|
|
234
|
-
|
|
235
227
|
/**
|
|
236
228
|
* The Sonar scope of the jest preset's exclusions (presets.sonarExclusions): its file patterns are the tests, which
|
|
237
229
|
* `sonar.test.inclusions` takes and `sonar.exclusions` moves out of the sources (`sonar.tests` names every source folder, so the
|
|
@@ -239,14 +231,12 @@ export const SONAR_CPD_EXCLUSIONS = Object.freeze(designTruthEntries(LIST.cpd));
|
|
|
239
231
|
* build and dependency folders are no source at all. Nothing else is excluded: a generated file is analysed like any other.
|
|
240
232
|
*/
|
|
241
233
|
export function sonarScope(presets) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
234
|
+
const preset = String(presets?.sonarExclusions ?? '').split(',').map(glob => glob.trim()).filter(Boolean);
|
|
235
|
+
const tests = preset.filter(glob => !glob.endsWith('/**'));
|
|
236
|
+
return { tests, exclusions: [...new Set([...preset, '**/.next/**', '**/node_modules/**'])] };
|
|
245
237
|
}
|
|
246
|
-
|
|
247
238
|
const SOURCE_FILE = /\.[cm]?ts$/;
|
|
248
239
|
const SOURCE_SKIPPED = new Set(['node_modules', 'dist', 'coverage']);
|
|
249
|
-
|
|
250
240
|
/**
|
|
251
241
|
* The be source of the app at `root` the coverage components read: { files, read }, `files` be-relative posix paths of every `*.ts` file under
|
|
252
242
|
* be/apps and be/src (build output and dependencies skipped) and `read` their text. `workPresent` records whether the optional
|
|
@@ -254,40 +244,48 @@ const SOURCE_SKIPPED = new Set(['node_modules', 'dist', 'coverage']);
|
|
|
254
244
|
* their content. An app with no be folder has no source files.
|
|
255
245
|
*/
|
|
256
246
|
export function appSource(root, { parseYaml, notices } = {}) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
247
|
+
const files = [];
|
|
248
|
+
const walk = (dir) => {
|
|
249
|
+
let entries;
|
|
250
|
+
try {
|
|
251
|
+
entries = fs.readdirSync(path.join(root, 'be', dir), { withFileTypes: true });
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
for (const entry of entries) {
|
|
257
|
+
const rel = `${dir}/${entry.name}`;
|
|
258
|
+
if (entry.isDirectory()) {
|
|
259
|
+
if (!SOURCE_SKIPPED.has(entry.name))
|
|
260
|
+
walk(rel);
|
|
261
|
+
}
|
|
262
|
+
else if (SOURCE_FILE.test(entry.name))
|
|
263
|
+
files.push(rel);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
for (const dir of ['apps', 'src'])
|
|
267
|
+
walk(dir);
|
|
268
|
+
return { runtimeExample: isRuntimeExampleApp(root), files: files.sort(byCodeUnit), read: (file) => fs.readFileSync(path.join(root, 'be', file), 'utf8'),
|
|
269
|
+
workPresent: fs.existsSync(path.join(root, '.starciwork')), hasImage: (file) => isFile(path.join(root, file), { followLinks: false }),
|
|
270
|
+
stack: readDeclaredStack(root, { parseYaml }), quality: readDeclaredQuality(root, { parseYaml }),
|
|
271
|
+
badges: readDeclaredBadges(root, { parseYaml, notices }),
|
|
272
|
+
qualityDeclared: hasDeclaredServices(root, { parseYaml }) };
|
|
273
|
+
}
|
|
274
274
|
/**
|
|
275
275
|
* The Codecov `individual_components` entries of components [{ id, name, paths }]: one `component_id` block each, `prefix` ahead of every path
|
|
276
276
|
* (the app folder in the runtime repository) and `ids` mapping a component id to its name there.
|
|
277
277
|
*/
|
|
278
|
-
export function componentsYaml(components, { prefix = '', ids = id => id } = {}) {
|
|
279
|
-
|
|
278
|
+
export function componentsYaml(components, { prefix = '', ids = (id) => id } = {}) {
|
|
279
|
+
return components.map(component => [` - component_id: ${ids(component.id)}`, ` name: ${ids(component.name)}`, ' paths:', ...component.paths.map(glob => ` - ${JSON.stringify(prefix + glob)}`)].join('\n')).join('\n');
|
|
280
280
|
}
|
|
281
|
-
|
|
282
281
|
/** The managed be/jest.config.js option text of a coverage scope { roots, roles, files, excludes }, laid out exactly as prettier lays it out (width 120, indent 4). */
|
|
283
282
|
export function jestCoverageSource(coverage) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
283
|
+
const list = (key, items) => {
|
|
284
|
+
const one = ` ${key}: [${items.map(item => JSON.stringify(item)).join(', ')}],`;
|
|
285
|
+
return one.length <= 120 ? one : [` ${key}: [`, ...items.map(item => ` ${JSON.stringify(item)},`), ' ],'].join('\n');
|
|
286
|
+
};
|
|
287
|
+
return ['{', list('roots', coverage.roots), list('roles', coverage.roles), list('files', coverage.files), list('excludes', coverage.excludes), ' }'].join('\n');
|
|
289
288
|
}
|
|
290
|
-
|
|
291
289
|
/**
|
|
292
290
|
* The script lines the apps add to the root package.json, each ending with a comma (the template puts them mid-object). A be
|
|
293
291
|
* script runs from be/ (`cd be && ...`, the folder its tsconfig and jest configuration are relative to) or runs the built app; an
|
|
@@ -300,369 +298,392 @@ export function jestCoverageSource(coverage) {
|
|
|
300
298
|
* `docker:build` builds every image, one after the other, never pushing.
|
|
301
299
|
*/
|
|
302
300
|
export function appScripts(app, source) {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
301
|
+
const line = (name, command) => `${JSON.stringify(name)}: ${JSON.stringify(command)},`;
|
|
302
|
+
const be = app.sides.be.apps;
|
|
303
|
+
const fe = app.sides.fe.apps;
|
|
304
|
+
const apis = be.filter(entry => entry.kind === 'api');
|
|
305
|
+
const connections = app.sides.be.connections ?? [];
|
|
306
|
+
const watch = (entry) => `cd be && ts-node-dev --respawn -r tsconfig-paths/register apps/${entry.name}/src/main.ts`;
|
|
307
|
+
const built = (entry) => `node be/dist/apps/${entry.name}/src/main.js`;
|
|
308
|
+
const workspace = (entry) => feAppPackageName(app.project, entry.name);
|
|
309
|
+
// Both editions generate before they run (owner ruling 2026-10-13): the fe's GraphQL wire types, and under lite the database types check.
|
|
310
|
+
const dev = (entry) => `npm run codegen --silent && turbo run dev --filter=${workspace(entry)}`;
|
|
311
|
+
const images = imageEntries(app, source);
|
|
312
|
+
const imageCommand = ({ side, entry }) => `docker build -f ${dockerfilePath(side, entry.name)} -t ${app.project}/${entry.name}:dev .`;
|
|
313
|
+
return [
|
|
314
|
+
...(apis.length === 1 ? [line('dev:be', watch(apis[0]))] : apis.map(entry => line(`dev:be:${entry.name}`, watch(entry)))),
|
|
315
|
+
...(fe.length === 1 ? [line('dev:fe', dev(fe[0]))] : fe.map(entry => line(`dev:fe:${entry.name}`, dev(entry)))),
|
|
316
|
+
...be.flatMap(entry => {
|
|
317
|
+
if (entry.kind !== 'cli')
|
|
318
|
+
return [line(`start:${entry.name}`, built(entry))];
|
|
319
|
+
return [line('cli', built(entry)), ...(connections.length ? [line('migrate', `${built(entry)} ${MIGRATE_COMMAND}`)] : [])];
|
|
320
|
+
}),
|
|
321
|
+
...fe.map(entry => line(`start:${entry.name}`, `npm run start -w ${workspace(entry)}`)),
|
|
322
|
+
...(app.edition !== 'lite' && app.optionalSlots.includes('app.browser') ? [line('test:browser', 'playwright test -c browser/playwright.config.ts')] : []),
|
|
323
|
+
line('docker:build', images.map(image => `npm run docker:build:${image.entry.name}`).join(' && ')),
|
|
324
|
+
...images.map(image => line(`docker:build:${image.entry.name}`, imageCommand(image))),
|
|
325
|
+
].join('\n ');
|
|
326
|
+
}
|
|
329
327
|
/** The cli command that migrates every connection (src/features/cli/migrate/subs/run.cli.ts). */
|
|
330
328
|
const MIGRATE_COMMAND = 'migrate run';
|
|
331
|
-
|
|
332
329
|
/** True when the fe side opts into a workspace package (repo.packages or any fe.package.* slot): the sources then include fe/packages/. */
|
|
333
|
-
const opensPackages = side => (side.optionalSlots ?? []).some(id => id === 'repo.packages' || String(id).startsWith('fe.package.'));
|
|
334
|
-
|
|
330
|
+
const opensPackages = (side) => (side.optionalSlots ?? []).some(id => id === 'repo.packages' || String(id).startsWith('fe.package.'));
|
|
335
331
|
/** The stylesheets of the fe side the CSS canon judges, relative to fe/: every app and every workspace package (slot fe.route, fe.package.*). */
|
|
336
332
|
export const STYLE_GLOB = '{apps,packages}/*/src/**/*.css';
|
|
337
|
-
|
|
338
333
|
/** Required app images plus lite front ends whose optional Dockerfile the source holds. */
|
|
339
334
|
function imageEntries(app, source) {
|
|
340
|
-
|
|
341
|
-
|
|
335
|
+
const frontend = app.sides.fe.apps.filter(entry => app.edition !== 'lite' || source?.hasImage?.(dockerfilePath('fe', entry.name)));
|
|
336
|
+
return [...app.sides.be.apps.map((entry) => ({ side: 'be', entry })), ...frontend.map((entry) => ({ side: 'fe', entry }))];
|
|
342
337
|
}
|
|
343
|
-
|
|
344
338
|
/**
|
|
345
339
|
* The build matrix of the images workflow: one entry per declared app (be then fe, then a lite app's db image), each with the image name and its Dockerfile. The workflow
|
|
346
340
|
* runs on the release tag, so every image is built there; no path filter narrows it. A YAML block mapping per entry, indented for
|
|
347
341
|
* `strategy.matrix.include`.
|
|
348
342
|
*/
|
|
349
343
|
export function imageMatrix(app, source) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
344
|
+
const entry = (side, item) => ` - name: ${item.name}\n file: ${dockerfilePath(side, item.name)}`;
|
|
345
|
+
const db = app.edition === 'lite' ? [` - name: ${DB_IMAGE_APP}\n file: ${DB_DOCKERFILE}`] : [];
|
|
346
|
+
return [...imageEntries(app, source).map(image => entry(image.side, image.entry)), ...db].join('\n');
|
|
353
347
|
}
|
|
354
|
-
|
|
355
348
|
/** The Dockerfile of the app a deploy image names (be first, then fe, then a lite app's db image); an app hfs.json does not declare cannot be built by the managed workflow. */
|
|
356
349
|
function stackDockerfile(app, name) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
350
|
+
if (app.edition === 'lite' && name === DB_IMAGE_APP)
|
|
351
|
+
return DB_DOCKERFILE;
|
|
352
|
+
const side = ['be', 'fe'].find(which => app.sides[which].apps.some(entry => entry.name === name));
|
|
353
|
+
if (!side)
|
|
354
|
+
throw new SyncError('HFS_SYNC_STACK_IMAGE', `deploy.images names the app ${name}, which hfs.json does not declare under be or fe`);
|
|
355
|
+
return dockerfilePath(side, name);
|
|
361
356
|
}
|
|
362
|
-
|
|
363
357
|
const IMAGE_TEMPLATE = Object.freeze({ api: 'be/image/api', worker: 'be/image/worker', cli: 'be/image/cli', next: 'fe/image/next' });
|
|
364
|
-
|
|
365
358
|
/**
|
|
366
359
|
* The Dockerfile of every declared app, [{ path, content }] (app-relative): written once by starci app scaffold from templates/<side>/image/<kind>
|
|
367
360
|
* and then the app's own, judged by the docker rules (R187-R191). A Next image copies the fe packages only when the fe side opts into
|
|
368
361
|
* them and the be contracts only when the fe side reads them, so each COPY names a folder the app has.
|
|
369
362
|
*/
|
|
370
363
|
export function imageFiles(app, source) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
|
|
364
|
+
const side = app.sides.fe;
|
|
365
|
+
const inputs = [...(opensPackages(side) ? ['fe/packages'] : []), ...((side.reads ?? []).includes('be/contracts/') ? ['be/contracts'] : [])];
|
|
366
|
+
const copyInputs = inputs.map(folder => `COPY ${folder} ${folder}\n`).join('');
|
|
367
|
+
// The folders outside be/ that the back end declares it reads (the generated database types of a lite back end, db/types/) are in every one of its images.
|
|
368
|
+
const beFolders = (app.sides.be.reads ?? []).map(folder => folder.replace(/\/$/, ''));
|
|
369
|
+
const copyBeInputs = beFolders.map(folder => `COPY ${folder} ${folder}\n`).join('');
|
|
370
|
+
const entries = imageEntries(app, source).map(({ side: which, entry: item }) => ({ side: which, item }));
|
|
371
|
+
return entries.map(({ side: which, item }) => {
|
|
372
|
+
const template = IMAGE_TEMPLATE[item.kind];
|
|
373
|
+
const vars = { project: app.project, app: item.name, nodeImage: NODE_IMAGE, port: DEFAULT_PORT, copyInputs, copyBeInputs };
|
|
374
|
+
return { path: dockerfilePath(which, item.name), content: render(readBundled(`${template}/Dockerfile`), vars) };
|
|
375
|
+
});
|
|
376
|
+
}
|
|
385
377
|
/** Every value a template of `scope` can name, derived from hfs.json and the presets. */
|
|
386
378
|
export function variables(app, scope, presets, sonarKey, manifest = loadSlotManifest(), source = { files: [], read: () => '' }) {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
|
|
379
|
+
const stack = source.stack ?? { images: [], passEnv: [] };
|
|
380
|
+
const fe = app.sides.fe;
|
|
381
|
+
const packages = opensPackages(fe);
|
|
382
|
+
const lite = app.edition === 'lite';
|
|
383
|
+
const providers = (app.sides.be.connections ?? []).map(connection => connection.provider);
|
|
384
|
+
const quality = source.quality ?? qualityServices({});
|
|
385
|
+
const grammarLint = scope === 'fe' ? grammarLintFor(fe.grammar) : null;
|
|
386
|
+
return {
|
|
387
|
+
header: HEADER(scope),
|
|
388
|
+
readmeBadges: source.badges ?? '',
|
|
389
|
+
project: app.project,
|
|
390
|
+
appBinary: APP_BINARY,
|
|
391
|
+
appScripts: appScripts(app, source),
|
|
392
|
+
// A lite app's own database runs in development as one container of the image its .starcistacks/images/db/Dockerfile builds (ruling:lite-db-image-in-stacks).
|
|
393
|
+
dbImage: dbLocalImage(app.project),
|
|
394
|
+
dbBaseImage: DB_BASE_IMAGE,
|
|
395
|
+
pgvectorPackage: PGVECTOR_PACKAGE,
|
|
396
|
+
pgmqVersion: PGMQ.version,
|
|
397
|
+
pgmqSource: PGMQ.source,
|
|
398
|
+
pgmqSha256: PGMQ.sha256,
|
|
399
|
+
// A lite app's declared Redis (sides.be.backing, ruling:R212/case-10) runs in development as one container of its pinned image.
|
|
400
|
+
backingScripts: lite && (app.sides.be.backing ?? []).includes('redis') ? redisDevText(app.project) : '',
|
|
401
|
+
// turbo builds every fe app workspace; ^build (turbo.json) builds the packages each app imports first, and caches both.
|
|
402
|
+
buildFe: 'npm run codegen --silent && turbo run build --filter=./fe/apps/*',
|
|
403
|
+
// The be side with its tsc; every fe workspace with its own typecheck script through turbo (the packages are built first: ^build).
|
|
404
|
+
typecheck: 'npm run codegen --silent && tsc -p be/tsconfig.json && turbo run typecheck',
|
|
405
|
+
// The typed lint reads the types the fe packages declare (their dist, turbo.json: lint dependsOn ^build), so the packages are built first.
|
|
406
|
+
lintPrefix: packages ? 'npm run codegen --silent && turbo run build --filter=./fe/packages/* && ' : 'npm run codegen --silent && ',
|
|
407
|
+
nodeMajor: String(NODE_MAJOR),
|
|
408
|
+
// The deploy server's age identity the restore workflow writes (stack/server-key.mjs owns the path).
|
|
409
|
+
serverAgeIdentity: SERVER_AGE_IDENTITY,
|
|
410
|
+
sonarKey: sonarKey ?? app.project,
|
|
411
|
+
sonarHostLine: sonarHostLine(quality.sonar),
|
|
412
|
+
sonarExclusions: sonarScope(presets).exclusions.join(','),
|
|
413
|
+
sonarTestInclusions: sonarScope(presets).tests.join(','),
|
|
414
|
+
sonarSources: ['be/apps', 'be/src', 'fe/apps', ...(packages ? ['fe/packages'] : [])].join(','),
|
|
415
|
+
lcovReport: LCOV_REPORT,
|
|
416
|
+
cpdExclusions: SONAR_CPD_EXCLUSIONS.join(','),
|
|
417
|
+
...ciWorkflowCommands(source, LCOV_REPORT, source.qualityDeclared === false ? undefined : source.quality, { app }),
|
|
418
|
+
// The coverage scope is the same in both editions: lite measures exactly what full measures (ruling:R212/case-1, amended by ruling:R212/case-4).
|
|
419
|
+
jestCoverage: scope === 'be' ? jestCoverageSource(jestCoverage(manifest, providers)) : '',
|
|
420
|
+
coverageExclusions: scope === APP_SCOPE ? sonarCoverageExclusions(manifest, providers).join(',') : '',
|
|
421
|
+
codecovExclusions: scope === APP_SCOPE ? sonarCoverageExclusions(manifest, providers).map(glob => ` - ${JSON.stringify(glob)}`).join('\n') : '',
|
|
422
|
+
codecovPaths: scope === APP_SCOPE ? codecovPaths(manifest, providers).map(glob => ` - ${JSON.stringify(glob)}`).join('\n') : '',
|
|
423
|
+
codecovComponents: scope === APP_SCOPE ? componentsYaml(coverageComponents(manifest, { ...source, apps: app.sides.be.apps, providers })) : '',
|
|
424
|
+
codecovTarget: quality.codecov.target,
|
|
425
|
+
dependabotUpdates: dependabotUpdates(quality.dependabot),
|
|
426
|
+
tsconfigPaths: ['be/tsconfig.json', ...fe.apps.map(entry => `fe/apps/${entry.name}/tsconfig.json`), ...(packages ? ['fe/packages/*/tsconfig.json'] : [])].join(','),
|
|
427
|
+
styleGlob: STYLE_GLOB,
|
|
428
|
+
grammarLintImport: grammarLint?.package ? `import { ${grammarLint.factory} } from "${grammarLint.package}"` : '',
|
|
429
|
+
grammarLintExport: grammarLint?.package ? `export default [...starciFeConfig({ hfs }), ...${grammarLint.factory}({ hfs })]` : 'export default starciFeConfig({ hfs })',
|
|
430
|
+
imageMatrix: imageMatrix(app, source),
|
|
431
|
+
imageProject: app.project,
|
|
432
|
+
...stackWorkflowVariables(stack, app.project, (name) => stackDockerfile(app, name)),
|
|
433
|
+
};
|
|
434
|
+
}
|
|
444
435
|
// The scripts of a package.json as one comparable text: a line per script, sorted by name (order is not drift).
|
|
445
|
-
const scriptsText = scripts => Object.keys(scripts).sort(byCodeUnit)
|
|
446
|
-
|
|
447
|
-
|
|
436
|
+
const scriptsText = (scripts) => Object.keys(scripts).sort(byCodeUnit)
|
|
437
|
+
.map(name => `${name}: ${typeof scripts[name] === 'string' ? scripts[name] : JSON.stringify(scripts[name])}`).join('\n') + '\n';
|
|
448
438
|
function parseScripts(text) {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
439
|
+
try {
|
|
440
|
+
const { scripts } = JSON.parse(text);
|
|
441
|
+
return scripts && typeof scripts === 'object' && !Array.isArray(scripts) ? scripts : null;
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
455
446
|
}
|
|
456
|
-
|
|
457
447
|
/**
|
|
458
448
|
* The managed content of every target of the app: [{ path, mode, content, hash, scope }], paths app-relative (a side's targets under
|
|
459
449
|
* its folder); a scripts target also carries `scripts`, the parsed block. `sonarKey` is the key the be side's stack declaration
|
|
460
450
|
* names; without one the key is the project.
|
|
461
451
|
*/
|
|
462
452
|
export function renderTargets(hfs, presets, { sonarKey, readTemplate = readBundled, manifest = loadSlotManifest(), source } = {}) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
453
|
+
const app = validateHfs(hfs, manifest);
|
|
454
|
+
const hasTemplate = (name) => { try {
|
|
455
|
+
return readTemplate(name) !== undefined;
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
return false;
|
|
459
|
+
} };
|
|
460
|
+
return SCOPES.flatMap(scope => {
|
|
461
|
+
const vars = variables(app, scope, presets, sonarKey, manifest, source);
|
|
462
|
+
const repo = scope === APP_SCOPE ? app : app.sides[scope];
|
|
463
|
+
const declaredTargets = targetsOf(scope, { edition: app.edition, manifest, hasTemplate, enabled: slot => declaredSlotEnabled(slot, repo) });
|
|
464
|
+
if (scope === APP_SCOPE && source?.badges)
|
|
465
|
+
declaredTargets.push({ path: 'README.md', mode: 'block', markdown: true, template: 'app/readme-badges/README.md' });
|
|
466
|
+
const targets = declaredTargets
|
|
467
|
+
.filter(target => !(app.edition === 'lite' && source?.workPresent === false && target.path === '.starciwork/.gitignore'));
|
|
468
|
+
return targets.map((target) => {
|
|
469
|
+
const template = target.path === 'codecov.yml' && source?.quality?.codecov.enabled === false
|
|
470
|
+
? '{{header}}\n# Codecov is disabled in the manifest.\ncodecov:\n require_ci_to_pass: false\n'
|
|
471
|
+
: readTemplate(target.template);
|
|
472
|
+
const body = trailingNewline(render(template, vars, readTemplate));
|
|
473
|
+
const where = onSide(scope, target.path);
|
|
474
|
+
if (target.mode === 'scripts') {
|
|
475
|
+
const scripts = parseScripts(body);
|
|
476
|
+
if (!scripts)
|
|
477
|
+
throw new SyncError('HFS_SYNC_TEMPLATE_VARIABLE', `the rendered ${target.template} has no scripts object`);
|
|
478
|
+
const content = scriptsText(scripts);
|
|
479
|
+
return { path: where, scope, mode: 'scripts', content, hash: hashOf(content), scripts };
|
|
480
|
+
}
|
|
481
|
+
const markers = target.markdown ? { begin: '<!-- >>> starci app sync (managed block; do not edit) >>> -->', end: '<!-- <<< starci app sync <<< -->' } : { begin: BLOCK_BEGIN, end: BLOCK_END };
|
|
482
|
+
const spacing = target.markdown ? '\n' : '';
|
|
483
|
+
const managed = target.mode === 'block' ? `${markers.begin}\n${spacing}${trailingNewline(body)}${spacing}${markers.end}\n` : body;
|
|
484
|
+
return { path: where, scope, mode: target.mode, markdown: target.markdown, markers, content: managed, hash: hashOf(managed) };
|
|
485
|
+
});
|
|
488
486
|
});
|
|
489
|
-
});
|
|
490
487
|
}
|
|
491
|
-
|
|
492
488
|
// The part of a file sync manages: all of it, all of it but the verb's section, the marked block, or the scripts block as text.
|
|
493
489
|
function managedPart(mode, text, markers = { begin: BLOCK_BEGIN, end: BLOCK_END }) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
490
|
+
if (mode === 'file')
|
|
491
|
+
return text;
|
|
492
|
+
if (mode === 'section')
|
|
493
|
+
return bootstrapSection(text).head;
|
|
494
|
+
if (mode === 'scripts') {
|
|
495
|
+
const scripts = parseScripts(text);
|
|
496
|
+
return scripts ? scriptsText(scripts) : null;
|
|
497
|
+
}
|
|
498
|
+
const start = text.indexOf(markers.begin);
|
|
499
|
+
const end = text.indexOf(markers.end);
|
|
500
|
+
if (start < 0 || end < start)
|
|
501
|
+
return null;
|
|
502
|
+
const stop = text.indexOf('\n', end);
|
|
503
|
+
return text.slice(start, stop < 0 ? text.length : stop + 1);
|
|
504
|
+
}
|
|
507
505
|
function firstDifference(expected, actual) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
506
|
+
const want = expected.split('\n'), have = actual.split('\n');
|
|
507
|
+
for (let index = 0; index < Math.max(want.length, have.length); index += 1) {
|
|
508
|
+
if (want[index] !== have[index])
|
|
509
|
+
return { line: index + 1, expected: want[index] ?? '(end of file)', actual: have[index] ?? '(end of file)' };
|
|
510
|
+
}
|
|
511
|
+
return null;
|
|
513
512
|
}
|
|
514
|
-
|
|
515
513
|
/** Compare every rendered target with the disk: [{ path, status: ok | missing | drift, expectedHash, actualHash?, difference? }]. */
|
|
516
514
|
export function checkTargets(root, targets) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
|
|
515
|
+
return targets.map((target) => {
|
|
516
|
+
const file = path.join(root, target.path);
|
|
517
|
+
if (!fs.existsSync(file))
|
|
518
|
+
return { path: target.path, status: 'missing', expectedHash: target.hash };
|
|
519
|
+
const part = managedPart(target.mode, lf(fs.readFileSync(file, 'utf8')), target.markers);
|
|
520
|
+
if (part === null)
|
|
521
|
+
return { path: target.path, status: 'missing', expectedHash: target.hash };
|
|
522
|
+
const actualHash = hashOf(part);
|
|
523
|
+
if (actualHash === target.hash)
|
|
524
|
+
return { path: target.path, status: 'ok', expectedHash: target.hash, actualHash };
|
|
525
|
+
return { path: target.path, status: 'drift', expectedHash: target.hash, actualHash, difference: firstDifference(target.content, part) };
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
528
|
function insertAfterTitle(existing, content) {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
529
|
+
const title = /^# [^\n]*(?:\n|$)/m.exec(existing);
|
|
530
|
+
if (!title)
|
|
531
|
+
return `${content}\n${existing}`;
|
|
532
|
+
const end = title.index + title[0].length;
|
|
533
|
+
const heading = trailingNewline(existing.slice(0, end));
|
|
534
|
+
return `${heading}\n${content}${existing.slice(end)}`;
|
|
534
535
|
}
|
|
535
|
-
|
|
536
536
|
/** Apply exactly one target to its whole file while preserving content outside the managed block or scripts. */
|
|
537
537
|
export function writtenContent(target, existing) {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
538
|
+
if (target.mode === 'scripts') {
|
|
539
|
+
let pkg = {};
|
|
540
|
+
if (existing) {
|
|
541
|
+
try {
|
|
542
|
+
pkg = JSON.parse(existing);
|
|
543
|
+
}
|
|
544
|
+
catch {
|
|
545
|
+
throw new SyncError('HFS_SYNC_HFS_INVALID', `${target.path} is not valid JSON; fix it by hand before sync can set its scripts`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return `${JSON.stringify({ ...pkg, scripts: target.scripts }, null, 2)}\n`;
|
|
542
549
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
550
|
+
if (target.mode === 'section')
|
|
551
|
+
return `${target.content}${bootstrapSection(existing ?? '').section ?? ''}`;
|
|
552
|
+
if (target.mode === 'block' && existing) {
|
|
553
|
+
const current = managedPart('block', existing, target.markers);
|
|
554
|
+
if (current !== null)
|
|
555
|
+
return existing.replace(current, () => target.content);
|
|
556
|
+
if (target.markdown)
|
|
557
|
+
return insertAfterTitle(existing, target.content);
|
|
558
|
+
return `${target.content}\n${existing}`;
|
|
559
|
+
}
|
|
560
|
+
return target.content;
|
|
561
|
+
}
|
|
555
562
|
export function writeTargets(root, targets) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
563
|
+
const written = [];
|
|
564
|
+
for (const result of checkTargets(root, targets)) {
|
|
565
|
+
if (result.status === 'ok')
|
|
566
|
+
continue;
|
|
567
|
+
const target = targets.find(candidate => candidate.path === result.path);
|
|
568
|
+
const file = path.join(root, target.path);
|
|
569
|
+
const existing = fs.existsSync(file) ? lf(fs.readFileSync(file, 'utf8')) : '';
|
|
570
|
+
const next = writtenContent(target, existing);
|
|
571
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
572
|
+
fs.writeFileSync(file, next);
|
|
573
|
+
written.push(target.path);
|
|
574
|
+
}
|
|
575
|
+
return written;
|
|
576
|
+
}
|
|
570
577
|
/** The hfs.json object of the app at `root` (validated), or a SyncError. */
|
|
571
578
|
export function loadHfs(root, manifest = loadSlotManifest()) {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
579
|
+
const file = path.join(root, 'hfs.json');
|
|
580
|
+
if (!fs.existsSync(file))
|
|
581
|
+
throw new SyncError('HFS_SYNC_HFS_INVALID', `${file} does not exist; starci app sync runs at the app root`);
|
|
582
|
+
let hfs;
|
|
583
|
+
try {
|
|
584
|
+
hfs = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
throw new SyncError('HFS_SYNC_HFS_INVALID', `${file} is not valid JSON: ${error.message}`);
|
|
588
|
+
}
|
|
589
|
+
validateHfs(hfs, manifest);
|
|
590
|
+
return hfs;
|
|
591
|
+
}
|
|
584
592
|
/** The rendered targets of the app at `root`: its hfs.json, the Sonar key the be side's stack declaration names, the presets it installs. */
|
|
585
593
|
export async function renderRepo(root, { presets, parseYaml, notices, manifest = loadSlotManifest() } = {}) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
594
|
+
const hfs = loadHfs(root, manifest);
|
|
595
|
+
const sonarKey = await readDeclaredSonarKey(root, { parseYaml, fail: (message) => { throw new SyncError('HFS_SYNC_SONAR_KEY', message); } });
|
|
596
|
+
return { hfs, targets: renderTargets(hfs, presets ?? await loadPresets(root), { sonarKey, manifest, source: appSource(root, { parseYaml, notices }) }) };
|
|
589
597
|
}
|
|
590
|
-
|
|
591
598
|
/** The folders a lite app's sync retires (ruling lite-self-hosted-postgres-passport-minio): the generated Supabase row types nothing reads any more. */
|
|
592
599
|
const LITE_RETIRED_DIRS = Object.freeze(['supabase/types']);
|
|
593
|
-
/** The files a lite app's sync retires, each with the reason
|
|
600
|
+
/** The files a lite app's sync retires, each with the reason the dry run prints. */
|
|
594
601
|
const LITE_RETIRED_FILES = Object.freeze({
|
|
595
|
-
|
|
602
|
+
[RETIRED_DB_DOCKERFILE]: `the db image moved to ${DB_DOCKERFILE} (ruling lite-db-image-in-stacks)`,
|
|
596
603
|
});
|
|
597
604
|
/** Why a retired file goes: a retired file's own reason, else the folder's. */
|
|
598
605
|
const retiredReason = (file) => LITE_RETIRED_FILES[file] ?? 'the lite edition generates no database types';
|
|
599
|
-
|
|
600
|
-
/** The app-relative files of the retired folders that still exist under `root` of a lite app; sync --write deletes them, --check reports them. */
|
|
606
|
+
/** The app-relative files of the retired folders that still exist under `root` of a lite app; sync --execute deletes them, the dry run reports them. */
|
|
601
607
|
export function retiredFiles(root, hfs) {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
608
|
+
if (hfs?.edition !== 'lite')
|
|
609
|
+
return [];
|
|
610
|
+
const found = [];
|
|
611
|
+
const walk = (rel) => {
|
|
612
|
+
const full = path.join(root, rel);
|
|
613
|
+
const stat = fs.lstatSync(full, { throwIfNoEntry: false });
|
|
614
|
+
if (!stat)
|
|
615
|
+
return;
|
|
616
|
+
if (stat.isDirectory())
|
|
617
|
+
for (const name of fs.readdirSync(full).sort(byCodeUnit))
|
|
618
|
+
walk(`${rel}/${name}`);
|
|
619
|
+
else
|
|
620
|
+
found.push(rel);
|
|
621
|
+
};
|
|
622
|
+
for (const dir of LITE_RETIRED_DIRS)
|
|
623
|
+
walk(dir);
|
|
624
|
+
for (const file of Object.keys(LITE_RETIRED_FILES))
|
|
625
|
+
walk(file);
|
|
626
|
+
return found;
|
|
627
|
+
}
|
|
628
|
+
/** `starci app sync [--execute] [--cwd <dir>]` at the app root: the dry run reports drift, --execute writes; returns 0 clean, 1 drift, 2 usage. */
|
|
617
629
|
function syncOptions(argv) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
630
|
+
const write = argv.includes('--execute');
|
|
631
|
+
const cwdAt = argv.indexOf('--cwd');
|
|
632
|
+
const known = new Set(['--execute', '--cwd']);
|
|
633
|
+
const unknown = argv.find((arg, index) => !known.has(arg) && (cwdAt < 0 || index !== cwdAt + 1));
|
|
634
|
+
if (unknown !== undefined || (cwdAt >= 0 && argv[cwdAt + 1] === undefined) || argv.indexOf('--execute') !== argv.lastIndexOf('--execute')) {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
return { write, cwdAt };
|
|
626
638
|
}
|
|
627
|
-
|
|
628
639
|
function reportSyncCheck(root, targets, out, retired = []) {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
export async function runSync(argv, { cwd = process.cwd(), out = line => process.stdout.write(`${line}\n`), presets, parseYaml } = {}) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
640
|
+
const results = checkTargets(root, targets);
|
|
641
|
+
const bad = results.filter(item => item.status !== 'ok');
|
|
642
|
+
for (const file of retired)
|
|
643
|
+
out(`HFS_SYNC_DRIFT ${file}: retired, ${retiredReason(file)}; run "npx --no-install starci app sync --execute" to delete it`);
|
|
644
|
+
for (const result of bad) {
|
|
645
|
+
const found = result.actualHash ? `, found ${result.actualHash.slice(0, 12)}` : '';
|
|
646
|
+
const where = result.difference ? ` (line ${result.difference.line}: expected ${JSON.stringify(result.difference.expected)}, found ${JSON.stringify(result.difference.actual)})` : '';
|
|
647
|
+
out(`HFS_SYNC_DRIFT ${result.path}: ${result.status}, expected sha256 ${result.expectedHash.slice(0, 12)}${found}${where}`);
|
|
648
|
+
}
|
|
649
|
+
out(`starci app sync: ${results.length - bad.length} of ${results.length} in sync${bad.length ? '; run "npx --no-install starci app sync --execute"' : ''}`);
|
|
650
|
+
return bad.length || retired.length ? 1 : 0;
|
|
651
|
+
}
|
|
652
|
+
export async function runSync(argv, { cwd = process.cwd(), out = (line) => process.stdout.write(`${line}\n`), presets, parseYaml } = {}) {
|
|
653
|
+
const options = syncOptions(argv);
|
|
654
|
+
if (!options) {
|
|
655
|
+
out('usage: starci app sync [--execute] [--cwd <dir>]');
|
|
656
|
+
return 2;
|
|
657
|
+
}
|
|
658
|
+
const { write, cwdAt } = options;
|
|
659
|
+
const root = cwdAt >= 0 ? path.resolve(cwd, argv[cwdAt + 1]) : cwd;
|
|
660
|
+
try {
|
|
661
|
+
const notices = [];
|
|
662
|
+
const { hfs, targets } = await renderRepo(root, { presets, parseYaml, notices });
|
|
663
|
+
const retired = retiredFiles(root, hfs);
|
|
664
|
+
if (targets.some(target => target.path === 'README.md'))
|
|
665
|
+
for (const notice of new Set(notices))
|
|
666
|
+
out(notice);
|
|
667
|
+
if (write) {
|
|
668
|
+
const written = writeTargets(root, targets);
|
|
669
|
+
for (const file of written)
|
|
670
|
+
out(`wrote ${file}`);
|
|
671
|
+
for (const file of retired) {
|
|
672
|
+
fs.rmSync(path.join(root, file));
|
|
673
|
+
out(`removed ${file} (retired)`);
|
|
674
|
+
}
|
|
675
|
+
for (const dir of LITE_RETIRED_DIRS)
|
|
676
|
+
if (retired.length && fs.existsSync(path.join(root, dir)) && !fs.readdirSync(path.join(root, dir)).length)
|
|
677
|
+
fs.rmdirSync(path.join(root, dir));
|
|
678
|
+
out(`starci app sync: ${written.length} written, ${targets.length - written.length} already in sync`);
|
|
679
|
+
return 0;
|
|
680
|
+
}
|
|
681
|
+
return reportSyncCheck(root, targets, out, retired);
|
|
682
|
+
}
|
|
683
|
+
catch (error) {
|
|
684
|
+
if (!(error instanceof SyncError))
|
|
685
|
+
throw error;
|
|
686
|
+
out(error.message);
|
|
687
|
+
return 1;
|
|
661
688
|
}
|
|
662
|
-
return reportSyncCheck(root, targets, out, retired);
|
|
663
|
-
} catch (error) {
|
|
664
|
-
if (!(error instanceof SyncError)) throw error;
|
|
665
|
-
out(error.message);
|
|
666
|
-
return 1;
|
|
667
|
-
}
|
|
668
689
|
}
|