@starci/hfs 4.7.32 → 4.7.34
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 +10 -0
- package/README.md +13 -6
- package/emit/contracts.mjs +4 -3
- package/emit/form-bounds-reader.ts.partial +58 -0
- package/emit/form-bounds.mjs +155 -0
- package/emit/graphql-input-bounds.mjs +97 -0
- package/emit/input-bounds.mjs +44 -0
- package/emit/operation-schemas.mjs +137 -0
- package/emit/operations-worker.mjs +2 -2
- package/emit/operations.mjs +52 -16
- package/emit/schema-worker.mjs +17 -4
- package/emit/type-schema.mjs +17 -5
- package/package.json +9 -2
- package/release/gate.mjs +18 -23
- package/release/index.mjs +1 -1
- package/release/push.mjs +4 -5
- package/runtime/engine/admission.mjs +331 -0
- package/runtime/engine/canonical-json.mjs +14 -0
- package/runtime/engine/db/blob.mjs +380 -0
- package/runtime/engine/db/event-compact.mjs +73 -0
- package/runtime/engine/db/ledger-open.mjs +38 -0
- package/runtime/engine/db/ledger-paths.mjs +87 -0
- package/runtime/engine/db/ledger.mjs +1068 -0
- package/runtime/engine/db/machine-connection.mjs +150 -0
- package/runtime/engine/db/machine-open.mjs +60 -0
- package/runtime/engine/db/machine-schema.mjs +105 -0
- package/runtime/engine/db/machine.mjs +1317 -0
- package/runtime/engine/db/provider-reservations.mjs +127 -0
- package/runtime/engine/db/provision-authority.mjs +76 -0
- package/runtime/engine/db/provision-lock.mjs +29 -0
- package/runtime/engine/db/provision-operations.mjs +146 -0
- package/runtime/engine/db/ref-value.mjs +67 -0
- package/runtime/engine/db/schema/machine.sql +920 -0
- package/runtime/engine/db/schema/runtime.sql +1113 -0
- package/runtime/engine/refuse.mjs +11 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +65 -9
- package/runtime/knowledge/hfs/design-truths.yaml +149 -0
- package/runtime/knowledge/hfs/fe-stack.yaml +23 -5
- package/runtime/knowledge/hfs/rules.yaml +269 -48
- package/runtime/knowledge/hfs/slots.yaml +113 -53
- package/runtime/knowledge/patterns/be/api.yaml +46 -20
- package/runtime/knowledge/patterns/be/event-bus.yaml +19 -12
- package/runtime/knowledge/patterns/be/idempotency.yaml +265 -0
- package/runtime/knowledge/patterns/be/jobs.yaml +17 -12
- package/runtime/knowledge/patterns/be/projections.yaml +2 -2
- package/runtime/knowledge/patterns/be/queues.yaml +57 -22
- package/runtime/knowledge/patterns/be/reactors.yaml +1 -1
- package/runtime/knowledge/patterns/be/realtime.yaml +326 -27
- package/runtime/knowledge/patterns/be/saga.yaml +2 -2
- package/runtime/knowledge/sonar-gate.yaml +1 -1
- package/runtime/modules/kernel/command-policy.yaml +249 -0
- package/runtime/modules/kernel/failure-codes.yaml +211 -52
- package/runtime/modules/kernel/hook-input.yaml +6 -0
- package/runtime/modules/kernel/protected-zone.yaml +81 -0
- package/runtime/modules/kernel/removed-vocabulary.yaml +62 -0
- package/runtime/modules/kernel/roles.yaml +405 -0
- package/runtime/modules/models/registry.yaml +3 -1
- package/runtime/modules/models/runtimes.yaml +2 -0
- package/runtime/modules/schemas/application-stacks.schema.yaml +10 -2
- package/runtime/packages/cli/src/catalog.generated.mjs +46 -59
- package/runtime/packages/grammar/scripts/build-stamp.mjs +98 -0
- package/runtime/scripts/agent/codex-app-server.mjs +79 -0
- package/runtime/scripts/agent/codex-mirror-source.mjs +34 -0
- package/runtime/scripts/agent/host-agents.mjs +80 -0
- package/runtime/scripts/agent/launch-trust-policy.mjs +53 -0
- package/runtime/scripts/agent/trust-launch.mjs +191 -0
- package/runtime/scripts/agent/trust.mjs +523 -0
- package/runtime/scripts/api/fs/rename-over.mjs +21 -0
- package/runtime/scripts/api/fs/temp-path.mjs +8 -0
- package/runtime/scripts/api/fs/write-json-file.mjs +10 -0
- package/runtime/scripts/api/git/diff-names.mjs +8 -0
- package/runtime/scripts/api/git/head-time.mjs +10 -0
- package/runtime/scripts/api/git/index-lock.mjs +78 -0
- package/runtime/scripts/api/git/is-ancestor.mjs +5 -0
- package/runtime/scripts/api/git/log.mjs +5 -0
- package/runtime/scripts/api/git/merge-base-query.mjs +5 -0
- package/runtime/scripts/api/git/merge-tree.mjs +5 -0
- package/runtime/scripts/api/git/rev-list.mjs +5 -0
- package/runtime/scripts/api/git/rev-parse.mjs +13 -0
- package/runtime/scripts/api/git/status-query.mjs +5 -0
- package/runtime/scripts/api/git/worktree-list-query.mjs +5 -0
- package/runtime/scripts/api/node/spawn-node.mjs +6 -0
- package/runtime/scripts/api/npm/dist-tag.mjs +8 -0
- package/runtime/scripts/api/npm/lib.mjs +32 -0
- package/runtime/scripts/api/npm/pack-dry-run.mjs +9 -0
- package/runtime/scripts/api/npm/run-npm.mjs +6 -0
- package/runtime/scripts/api/npm/view.mjs +30 -0
- package/runtime/scripts/api/npm/whoami.mjs +8 -0
- package/runtime/scripts/api/process/hide-child-windows.mjs +31 -0
- package/runtime/scripts/api/process/kill-tree.mjs +22 -0
- package/runtime/scripts/api/process/lib.mjs +125 -0
- package/runtime/scripts/api/process/probe-guard-command.mjs +74 -0
- package/runtime/scripts/api/process/process-list.mjs +28 -0
- package/runtime/scripts/api/process/system-tool.mjs +37 -0
- package/runtime/scripts/gates/canon-digest.mjs +81 -0
- package/runtime/scripts/gates/canon-pins.mjs +16 -0
- package/runtime/scripts/gates/commit-proof.mjs +53 -0
- package/runtime/scripts/gates/gate-input.mjs +98 -0
- package/runtime/scripts/gates/gate.mjs +669 -0
- package/runtime/scripts/gates/grammar-dist.mjs +206 -0
- package/runtime/scripts/gates/runtime-package-selection.mjs +27 -0
- package/runtime/scripts/gates/test-world-run.mjs +254 -0
- package/runtime/scripts/gates/type-impact.mjs +277 -0
- package/runtime/scripts/gates/type-program.mjs +113 -0
- package/runtime/scripts/guards/assigned-command.mjs +12 -0
- package/runtime/scripts/guards/call-rights.mjs +47 -0
- package/runtime/scripts/guards/command-guard.mjs +468 -0
- package/runtime/scripts/guards/command-policy.mjs +342 -0
- package/runtime/scripts/guards/critic-reach.mjs +82 -0
- package/runtime/scripts/guards/deps-guard.mjs +150 -0
- package/runtime/scripts/guards/env-dump-verdict.mjs +89 -0
- package/runtime/scripts/guards/git-pathspec.mjs +225 -0
- package/runtime/scripts/guards/git-policy.mjs +355 -0
- package/runtime/scripts/guards/guards-root.mjs +27 -0
- package/runtime/scripts/guards/hook-install.mjs +343 -0
- package/runtime/scripts/guards/hook-io.mjs +76 -0
- package/runtime/scripts/guards/hook-verdict.mjs +12 -0
- package/runtime/scripts/guards/install-verdict.mjs +41 -0
- package/runtime/scripts/guards/kernel-seat.mjs +63 -0
- package/runtime/scripts/guards/launch-verdict.mjs +74 -0
- package/runtime/scripts/guards/op-starci.mjs +16 -0
- package/runtime/scripts/guards/op-write-scope.mjs +27 -0
- package/runtime/scripts/guards/orca-self-lifecycle.mjs +39 -0
- package/runtime/scripts/guards/process-kill-verdict.mjs +106 -0
- package/runtime/scripts/guards/protected-zone.mjs +56 -0
- package/runtime/scripts/guards/refusals.mjs +27 -0
- package/runtime/scripts/guards/release-definition.mjs +185 -0
- package/runtime/scripts/guards/release-push-gate.mjs +72 -0
- package/runtime/scripts/guards/release-record.mjs +58 -0
- package/runtime/scripts/guards/release-suite-mode.mjs +15 -0
- package/runtime/scripts/guards/rights.mjs +268 -0
- package/runtime/scripts/guards/seat-tools.mjs +47 -0
- package/runtime/scripts/guards/shell-commands.mjs +328 -0
- package/runtime/scripts/guards/supervisor-seat.mjs +80 -0
- package/runtime/scripts/guards/verdict-process.mjs +81 -0
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +10 -10
- package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +1 -1
- package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +53 -0
- package/runtime/scripts/hfs/architecture/reachability.mjs +1 -1
- package/runtime/scripts/hfs/architecture/sql-owner.mjs +17 -6
- package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +105 -0
- package/runtime/scripts/hfs/architecture/sql-tokens.mjs +38 -52
- package/runtime/scripts/hfs/architecture/supabase-keys.mjs +261 -0
- package/runtime/scripts/hfs/architecture/transport-owner.mjs +49 -3
- package/runtime/scripts/hfs/architecture/typescript.mjs +1 -1
- package/runtime/scripts/hfs/check.mjs +6 -4
- package/runtime/scripts/hfs/coverage-scope.mjs +28 -1
- package/runtime/scripts/hfs/db-restamp-verb.mjs +56 -16
- package/runtime/scripts/hfs/declaration-shape.mjs +4 -4
- package/runtime/scripts/hfs/declaration-slots.mjs +14 -3
- package/runtime/scripts/hfs/manifest-shape.mjs +10 -6
- package/runtime/scripts/hfs/rule-params-shape.mjs +18 -6
- package/runtime/scripts/hfs/rules/a15-findings.mjs +4 -1
- package/runtime/scripts/hfs/rules/bypass-markers.mjs +22 -7
- package/runtime/scripts/hfs/rules/database-migrations.mjs +69 -14
- package/runtime/scripts/hfs/rules/database-queue-sources.mjs +9 -7
- package/runtime/scripts/hfs/rules/database-queues.mjs +68 -18
- package/runtime/scripts/hfs/rules/edition.mjs +56 -12
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -10
- package/runtime/scripts/hfs/rules/fe-stack.mjs +12 -7
- package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +1 -1
- package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +75 -9
- package/runtime/scripts/hfs/rules/stacks-runtime.mjs +1 -1
- package/runtime/scripts/hfs/rules/stacks-swarm.mjs +15 -4
- package/runtime/scripts/hfs/rules/text-integrity.mjs +73 -0
- package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +74 -0
- package/runtime/scripts/hfs/runtime-rules/release-notes.mjs +44 -0
- package/runtime/scripts/hfs/sealed-members.mjs +3 -3
- package/runtime/scripts/hfs/slot-side-problems.mjs +3 -3
- package/runtime/scripts/hfs/slots.mjs +2 -1
- package/runtime/scripts/hfs/stack-deploy-config.mjs +22 -5
- package/runtime/scripts/hfs/stacks-gate.mjs +28 -7
- package/runtime/scripts/hfs/view.mjs +2 -1
- package/runtime/scripts/lib/app-data.mjs +11 -0
- package/runtime/scripts/lib/bypass-markers.mjs +272 -75
- package/runtime/scripts/lib/check-format.mjs +7 -0
- package/runtime/scripts/lib/cli-arg.mjs +120 -0
- package/runtime/scripts/lib/css-rules.mjs +220 -0
- package/runtime/scripts/lib/dom-tree.mjs +4 -0
- package/runtime/scripts/lib/escape.mjs +16 -0
- package/runtime/scripts/lib/event-items.mjs +22 -0
- package/runtime/scripts/lib/failure-code-template-errors.mjs +161 -0
- package/runtime/scripts/lib/git-dir.mjs +120 -0
- package/runtime/scripts/lib/grammar-vendor-parity.mjs +377 -0
- package/runtime/scripts/lib/guard-command.mjs +24 -0
- package/runtime/scripts/lib/hook-limits.mjs +5 -0
- package/runtime/scripts/lib/interrupt-cleanup.mjs +38 -0
- package/runtime/scripts/lib/js-lex.mjs +200 -0
- package/runtime/scripts/lib/json-formats.mjs +0 -1
- package/runtime/scripts/lib/language.mjs +94 -1
- package/runtime/scripts/lib/loosening-budgets.mjs +44 -0
- package/runtime/scripts/lib/loosening-config.mjs +361 -0
- package/runtime/scripts/lib/loosening-state.mjs +223 -0
- package/runtime/scripts/lib/menu-parts.mjs +11 -0
- package/runtime/scripts/lib/normalize.mjs +25 -0
- package/runtime/scripts/lib/op-gate.mjs +15 -0
- package/runtime/scripts/lib/redact.mjs +208 -0
- package/runtime/scripts/lib/runtime-location.mjs +21 -0
- package/runtime/scripts/lib/runtime-package-inventory.mjs +21 -0
- package/runtime/scripts/lib/runtime-package-manifests.mjs +84 -0
- package/runtime/scripts/lib/runtime-publication-tags.mjs +99 -0
- package/runtime/scripts/lib/seat-env.mjs +43 -0
- package/runtime/scripts/lib/secret-patterns.mjs +58 -9
- package/runtime/scripts/lib/shell-source.mjs +4 -0
- package/runtime/scripts/lib/source-phrases.mjs +34 -0
- package/runtime/scripts/lib/sqlite.mjs +21 -0
- package/runtime/scripts/lib/swarm-stack.mjs +2 -1
- package/runtime/scripts/lib/tar-files.mjs +39 -0
- package/runtime/scripts/lib/ts-analysis.mjs +10 -0
- package/runtime/scripts/lib/worktree-exclude.mjs +35 -0
- package/runtime/scripts/lib/worktree-record.mjs +14 -0
- package/runtime/scripts/machine/artifact-hold.mjs +52 -0
- package/runtime/scripts/machine/ask-receipts.mjs +113 -0
- package/runtime/scripts/machine/evidence-store.mjs +223 -0
- package/runtime/scripts/machine/home.mjs +216 -0
- package/runtime/scripts/machine/host-lock.mjs +184 -0
- package/runtime/scripts/machine/lock-recovery.mjs +55 -0
- package/runtime/scripts/machine/roles-contract.mjs +90 -0
- package/runtime/scripts/machine/runtime-change.mjs +20 -0
- package/runtime/scripts/machine/workflow-tree.mjs +122 -0
- package/runtime/scripts/reconciler/checklist-items.mjs +7 -0
- package/runtime/scripts/reconciler/guard-row.mjs +25 -0
- package/runtime/scripts/work/asset-slot.mjs +284 -0
- package/runtime/scripts/work/brand/brand-colour.mjs +125 -0
- package/runtime/scripts/work/brand/brand-tokens.mjs +167 -0
- package/runtime/scripts/work/brand/brand-value-source.mjs +106 -0
- package/runtime/scripts/work/brand/brand.mjs +892 -0
- package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +60 -0
- package/runtime/scripts/work/draw/draw-dna-findings.mjs +256 -0
- package/runtime/scripts/work/draw/draw-dna-selector.mjs +38 -0
- package/runtime/scripts/work/draw/draw-dna.mjs +483 -0
- package/runtime/scripts/work/draw/draw-layer.mjs +305 -0
- package/runtime/scripts/work/draw/draw-rationale-page.mjs +237 -0
- package/runtime/scripts/work/draw/draw-rationale-ref.mjs +14 -0
- package/runtime/scripts/work/draw/draw-rationale.mjs +353 -0
- package/runtime/scripts/work/draw/draw-source.mjs +412 -0
- package/runtime/scripts/work/draw/draw-taste.mjs +278 -0
- package/runtime/scripts/work/draw/draw-typecheck.mjs +72 -0
- package/runtime/scripts/work/draw/rationale-findings.mjs +205 -0
- package/runtime/scripts/work/draw-grammar.mjs +175 -0
- package/runtime/scripts/work/draw-render-page.mjs +188 -0
- package/runtime/scripts/work/draw-render.mjs +626 -0
- package/runtime/scripts/work/grammar-proposal.mjs +279 -0
- package/runtime/scripts/work/png.mjs +237 -0
- package/runtime/scripts/work/render-tools.mjs +64 -0
- package/runtime/scripts/work/work-io.mjs +119 -0
- package/scaffold/add-inbox-lite.mjs +2 -2
- package/scaffold/add-plan.mjs +40 -13
- package/scaffold/add-queue-lite.mjs +372 -0
- package/scaffold/add.mjs +5 -2
- package/scaffold/app.mjs +1 -2
- package/scaffold/edition-gate.mjs +11 -7
- package/scaffold/lite-exports.mjs +10 -0
- package/scaffold/pattern-file-slots.mjs +33 -0
- package/scaffold/test-world.mjs +1 -1
- package/scaffold/yaml-block-edit.mjs +117 -0
- package/src/main.mjs +5 -4
- package/stack/deploy.mjs +7 -3
- package/stack/post-deploy.mjs +48 -0
- package/sync/index.mjs +10 -0
- package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +1 -1
- package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +1 -1
- package/templates/app/codegen-graphql.mjs.partial +59 -12
- package/templates/app/hooks/husky/pre-commit +2 -2
- package/templates/app/hooks/husky/pre-push +10 -3
- package/templates/app/package-scripts/redis-dev.json +3 -0
- package/templates/app/package-scripts-lite/package.json +1 -0
- package/templates/app/skeleton/.starcistacks/application-stacks.yaml +36 -8
- package/templates/app/skeleton/.starcistacks/dev/README.md +1 -1
- package/templates/app/skeleton/.starcistacks/production/README.md +10 -9
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/postgres-init.sh +21 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/recovery/restore-proof.md +1 -1
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/images.lock.yaml +1 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +47 -5
- package/templates/app/skeleton/.starcistacks/production/runtime/env/KEYS.md +5 -3
- package/templates/app/skeleton/README.md +2 -0
- package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +5 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/README.md +2 -2
- package/templates/app/skeleton-lite/.starcistacks/production/README.md +1 -1
- package/templates/app/skeleton-lite/README.md +1 -1
- package/templates/be/inbox/platform/client-operation-outcomes.sql.tpl +18 -0
- package/templates/be/inbox/platform/event-bus/errors/event-bus.error.ts.tpl +16 -0
- package/templates/be/inbox/platform/event-bus/event-bus.contracts.ts.tpl +10 -0
- package/templates/be/inbox/platform/event-bus/event-bus.port.ts.tpl +1 -1
- package/templates/be/inbox/platform/event-bus/event-bus.service.spec.ts.tpl +15 -3
- package/templates/be/inbox/platform/event-bus/event-bus.service.ts.tpl +11 -3
- package/templates/be/inbox/platform/event-bus/index.ts.tpl +2 -0
- package/templates/be/inbox/platform/event-bus/messages/event-bus.messages.ts.tpl +7 -0
- package/templates/be/inbox/platform/event-bus/persistence/event-bus.sql.ts.tpl +2 -2
- package/templates/be/inbox/platform/idempotency/errors/idempotency.error.ts.tpl +19 -0
- package/templates/be/inbox/platform/idempotency/index.ts.tpl +2 -0
- package/templates/be/inbox/platform/idempotency/messages/idempotency.messages.ts.tpl +13 -0
- package/templates/be/inbox/platform/inbox/client-operation.policy.spec.ts.tpl +32 -0
- package/templates/be/inbox/platform/inbox/client-operation.policy.ts.tpl +17 -0
- package/templates/be/inbox/platform/inbox/errors/inbox.error.ts.tpl +22 -0
- package/templates/be/inbox/platform/inbox/inbox.port.ts.tpl +21 -0
- package/templates/be/inbox/platform/inbox/inbox.service.spec.ts.tpl +334 -11
- package/templates/be/inbox/platform/inbox/inbox.service.ts.tpl +55 -4
- package/templates/be/inbox/platform/inbox/index.ts.tpl +2 -0
- package/templates/be/inbox/platform/inbox/messages/inbox.messages.ts.tpl +15 -0
- package/templates/be/inbox/platform/inbox/persistence/inbox.rows.ts.tpl +33 -0
- package/templates/be/inbox/platform/inbox/persistence/inbox.sql.ts.tpl +26 -0
- package/templates/be/inbox/platform/inbox/request-fingerprint.policy.spec.ts.tpl +76 -0
- package/templates/be/inbox/platform/inbox/request-fingerprint.policy.ts.tpl +36 -0
- package/templates/be/inbox/platform/migration.sql.tpl +1 -0
- package/templates/be/inbox/service.spec.ts.tpl +4 -4
- package/templates/be/inbox/service.ts.tpl +3 -1
- package/templates/be/inbox/webhook-door.spec.ts.tpl +3 -2
- package/templates/be/inbox/webhook-door.ts.tpl +3 -2
- package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +3 -0
- package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +10 -0
- package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +2 -2
- package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +16 -3
- package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +11 -3
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +139 -50
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +25 -2
- package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +139 -78
- package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +10 -6
- package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +262 -159
- package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +32 -5
- package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +2 -0
- package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +5 -1
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +2 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +4 -4
- package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +1 -0
- package/templates/be/patterns/idempotency/platform/idempotency/errors/idempotency.error.ts.tpl +19 -0
- package/templates/be/patterns/idempotency/platform/idempotency/index.ts.tpl +2 -0
- package/templates/be/patterns/idempotency/platform/idempotency/messages/idempotency.messages.ts.tpl +13 -0
- package/templates/be/patterns/idempotency/platform/inbox/client-operation.policy.spec.ts.tpl +32 -0
- package/templates/be/patterns/idempotency/platform/inbox/client-operation.policy.ts.tpl +17 -0
- package/templates/be/patterns/idempotency/platform/inbox/client-outcome-backfill.client.spec.ts.tpl +66 -0
- package/templates/be/patterns/idempotency/platform/inbox/client-outcome-backfill.client.ts.tpl +24 -0
- package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-backfill.client.spec.ts.tpl +60 -0
- package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-backfill.client.ts.tpl +12 -0
- package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-release.client.spec.ts.tpl +49 -0
- package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-release.client.ts.tpl +12 -0
- package/templates/be/patterns/idempotency/platform/inbox/effectful.decorators.ts.tpl +7 -0
- package/templates/be/patterns/idempotency/platform/inbox/errors/inbox.error.ts.tpl +22 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.decorators.ts.tpl +17 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.module-definition.ts.tpl +7 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.module.ts.tpl +28 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.options.ts.tpl +7 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.port.ts.tpl +44 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.service.spec.ts.tpl +388 -0
- package/templates/be/patterns/idempotency/platform/inbox/inbox.service.ts.tpl +77 -0
- package/templates/be/patterns/idempotency/platform/inbox/index.ts.tpl +10 -0
- package/templates/be/patterns/idempotency/platform/inbox/messages/inbox.messages.ts.tpl +15 -0
- package/templates/be/patterns/idempotency/platform/inbox/persistence/connection.ts.tpl +9 -0
- package/templates/be/patterns/idempotency/platform/inbox/persistence/entities/inbox-claim.entity.ts.tpl +25 -0
- package/templates/be/patterns/idempotency/platform/inbox/persistence/inbox.rows.ts.tpl +33 -0
- package/templates/be/patterns/idempotency/platform/inbox/persistence/inbox.sql.ts.tpl +39 -0
- package/templates/be/patterns/idempotency/platform/inbox/persistence/migrations/1789800005000-create-inbox-claims.ts.tpl +21 -0
- package/templates/be/patterns/idempotency/platform/inbox/persistence/migrations/1792800000000-client-operation-outcomes.ts.tpl +21 -0
- package/templates/be/patterns/idempotency/platform/inbox/request-fingerprint.policy.spec.ts.tpl +76 -0
- package/templates/be/patterns/idempotency/platform/inbox/request-fingerprint.policy.ts.tpl +36 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +1 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +4 -3
- package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +2 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +20 -2
- package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +1 -0
- package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +4 -0
- package/templates/be/patterns/jobs/platform-lite/jobs.index.ts.tpl +10 -0
- package/templates/be/patterns/jobs/platform-lite/jobs.sql.tpl +44 -0
- package/templates/be/patterns/jobs/platform-lite/persistence.jobs.sql.ts.tpl +33 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +203 -18
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +78 -22
- package/templates/be/patterns/queues/platform/errors/queue.error.ts.tpl +19 -0
- package/templates/be/patterns/queues/platform/messages/queue.messages.ts.tpl +13 -0
- package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +1 -0
- package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +4 -0
- package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +2 -0
- package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +4 -4
- package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +14 -2
- package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +5 -2
- package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +72 -74
- package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +1 -1
- package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +23 -8
- package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +29 -8
- package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +7 -3
- package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +5 -0
- package/templates/be/patterns/queues/platform/queue.index.ts.tpl +2 -0
- package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +4 -0
- package/templates/be/patterns/queues/platform/queue.module.ts.tpl +2 -1
- package/templates/be/patterns/queues/platform/queue.port.ts.tpl +1 -1
- package/templates/be/patterns/queues/platform-lite/bullmq-queue-transport.client.spec.ts.tpl +417 -0
- package/templates/be/patterns/queues/platform-lite/bullmq-queue-transport.client.ts.tpl +172 -0
- package/templates/be/patterns/queues/platform-lite/persistence.queue.sql.ts.tpl +12 -0
- package/templates/be/patterns/queues/platform-lite/queue-outbox.sql.tpl +32 -0
- package/templates/be/patterns/queues/platform-lite/queue-relay.service.spec.ts.tpl +148 -0
- package/templates/be/patterns/queues/platform-lite/queue-relay.service.ts.tpl +51 -0
- package/templates/be/patterns/queues/platform-lite/queue-transport.port.ts.tpl +163 -0
- package/templates/be/patterns/queues/platform-lite/queue.config.ts.tpl +17 -0
- package/templates/be/patterns/queues/platform-lite/queue.error.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform-lite/queue.index.ts.tpl +8 -0
- package/templates/be/patterns/queues/platform-lite/queue.messages.ts.tpl +21 -0
- package/templates/be/patterns/queues/platform-lite/queue.module.ts.tpl +74 -0
- package/templates/be/patterns/queues/platform-lite/queue.options.ts.tpl +38 -0
- package/templates/be/patterns/queues/queue.queue.ts.tpl +2 -2
- package/templates/be/patterns/reactors/application.contracts.ts.tpl +2 -0
- package/templates/be/patterns/reactors/consumer.ts.tpl +5 -1
- package/templates/be/platform/graphql/graphql.contracts.ts +2 -1
- package/templates/be/platform/graphql/localize-errors.mapper.spec.ts +1 -1
- package/templates/be/skeleton/apps/__app__/src/compose/platform.ts +6 -1
- package/templates/be/skeleton/apps/__app__/src/main.ts +7 -4
- package/templates/be/skeleton/apps/cli/src/compose/platform.ts +4 -0
- package/templates/be/skeleton/apps/cli/src/main.ts +7 -4
- package/templates/be/skeleton/src/modules/platform/database/index.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/http/errors/http.error.ts +22 -0
- package/templates/be/skeleton/src/modules/platform/http/fetch-http-client.client.spec.ts +235 -0
- package/templates/be/skeleton/src/modules/platform/http/fetch-http-client.client.ts +85 -0
- package/templates/be/skeleton/src/modules/platform/http/graphql-call.mapper.spec.ts +92 -0
- package/templates/be/skeleton/src/modules/platform/http/graphql-call.mapper.ts +52 -0
- package/templates/be/skeleton/src/modules/platform/http/http.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/http/http.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/http/http.module.ts +19 -0
- package/templates/be/skeleton/src/modules/platform/http/http.options.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/http/http.port.ts +40 -0
- package/templates/be/skeleton/src/modules/platform/http/index.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/http/messages/http.messages.ts +15 -0
- package/templates/be/skeleton/src/modules/platform/ids/ids.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/ids/ids.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/ids/ids.module.ts +19 -0
- package/templates/be/skeleton/src/modules/platform/ids/ids.options.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/ids/ids.port.ts +5 -0
- package/templates/be/skeleton/src/modules/platform/ids/index.ts +4 -0
- package/templates/be/skeleton/src/modules/platform/ids/system-ids.service.spec.ts +15 -0
- package/templates/be/skeleton/src/modules/platform/ids/system-ids.service.ts +10 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation-request.policy.spec.ts +59 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation-request.policy.ts +21 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation.contracts.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation.policy.spec.ts +150 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation.policy.ts +42 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation.port.ts +15 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation.service.spec.ts +23 -0
- package/templates/be/skeleton/src/modules/platform/logging/correlation.service.ts +28 -0
- package/templates/be/skeleton/src/modules/platform/logging/index.ts +14 -1
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +39 -6
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +15 -3
- package/templates/be/skeleton/src/modules/platform/logging/logging.decorators.ts +17 -2
- package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +13 -1
- package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +13 -3
- package/templates/be/skeleton/src/modules/platform/logging/nest-logger.service.spec.ts +69 -0
- package/templates/be/skeleton/src/modules/platform/logging/nest-logger.service.ts +48 -0
- package/templates/be/skeleton/src/modules/platform/primitives/index.ts +1 -0
- package/templates/be/skeleton/src/modules/platform/primitives/record.policy.spec.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/primitives/record.policy.ts +3 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/platform.ts +6 -1
- package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +1 -0
- package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +14 -1
- package/templates/be/skeleton-lite/src/modules/platform/logging/logging.log-events.ts +12 -0
- package/templates/be/skeleton-lite/src/modules/platform/primitives/index.ts +2 -0
- package/templates/be/test-world/world/test-apps.options.ts.tpl +2 -0
- package/templates/be/test-world/world/test-world.config.ts.tpl +1 -0
- package/upgrade/check.mjs +12 -135
- package/upgrade/file-state.mjs +1 -16
- package/upgrade/index.mjs +34 -361
- package/runtime/scripts/lib/check-code-loosening.mjs +0 -128
- package/runtime/scripts/lib/gate-loosening.mjs +0 -292
- package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +0 -89
- package/templates/app/upgrade-full/.starcistacks/dev/README.md +0 -16
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +0 -13
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +0 -3
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +0 -12
- package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +0 -7
- package/templates/be/skeleton-lite/apps/api/src/main.ts +0 -26
- package/templates/be/upgrade-full/apps/cli/src/app.module.ts +0 -12
- package/templates/be/upgrade-full/apps/cli/src/cli.env.ts +0 -7
- package/templates/be/upgrade-full/apps/cli/src/compose/cli.ts +0 -5
- package/templates/be/upgrade-full/apps/cli/src/compose/platform.ts +0 -9
- package/templates/be/upgrade-full/apps/cli/src/main.ts +0 -29
- package/templates/be/upgrade-full/src/features/cli/cli.module.ts +0 -7
- package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +0 -23
package/upgrade/index.mjs
CHANGED
|
@@ -1,35 +1,17 @@
|
|
|
1
|
-
// starci app upgrade
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// starci app upgrade: completes an existing FULL app. It adds the test world (scaffold/test-world.mjs) the app lacks, with the world's
|
|
2
|
+
// devDependencies at canon pins, and never rewrites a file the app already has. Editions are fixed at scaffold: a lite app is refused
|
|
3
|
+
// (HFS_UPGRADE_EDITION_FIXED), there is no lite to full migration.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// resolves the lockfile once when it added dependencies. If that resolution fails, every file touched by this invocation is
|
|
8
|
-
// restored before the refusal is returned.
|
|
5
|
+
// A dry run returns the exact ordered operations; apply performs those operations and resolves the lockfile once when it added
|
|
6
|
+
// dependencies. If that resolution fails, every file touched by this invocation is restored before the refusal is returned.
|
|
9
7
|
import fs from "node:fs";
|
|
10
8
|
import path from "node:path";
|
|
11
|
-
import {
|
|
9
|
+
import { remember, ensureParent, writeFile, restore } from "./file-state.mjs";
|
|
12
10
|
import { parseYaml } from "../runtime/engine/yaml.mjs";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
resolveRepoDeclaration,
|
|
16
|
-
} from "../runtime/scripts/hfs/slots.mjs";
|
|
17
|
-
import { managedScriptNames } from "../runtime/scripts/hfs/architecture/managed-scripts.mjs";
|
|
18
|
-
import { LOCK_STEP, npmLock, scaffoldWorkSeeds } from "../scaffold/app.mjs";
|
|
11
|
+
import { loadSlotManifest } from "../runtime/scripts/hfs/slots.mjs";
|
|
12
|
+
import { LOCK_STEP, npmLock } from "../scaffold/app.mjs";
|
|
19
13
|
import { WORLD_MARKER, testWorldFiles } from "../scaffold/test-world.mjs";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
TEMPLATES_DIR,
|
|
23
|
-
appSource,
|
|
24
|
-
bundledPresets,
|
|
25
|
-
checkTargets,
|
|
26
|
-
imageFiles,
|
|
27
|
-
loadHfs,
|
|
28
|
-
render,
|
|
29
|
-
renderTargets,
|
|
30
|
-
writeTargets,
|
|
31
|
-
} from "../sync/index.mjs";
|
|
32
|
-
import { readDeclaredStack } from "../sync/stack-images.mjs";
|
|
14
|
+
import { loadHfs } from "../sync/index.mjs";
|
|
33
15
|
|
|
34
16
|
const PACKAGE_ROOT = path.join(import.meta.dirname, "..");
|
|
35
17
|
const PINS_FILE = path.join(
|
|
@@ -48,21 +30,6 @@ const FULL_DEV_DEPENDENCIES = Object.freeze([
|
|
|
48
30
|
"ts-jest",
|
|
49
31
|
]);
|
|
50
32
|
const FULL_DEPENDENCIES = Object.freeze(["nest-commander"]);
|
|
51
|
-
// Upgrade must render the full managed files before it can add/install the Jest preset a lite app scaffolded before the 2026-10-12
|
|
52
|
-
// ruling lacks (a current lite app already has it, and the e2e world's @starci/test-world is what full adds). These are the preset's two
|
|
53
|
-
// public sync inputs; once apply resolves the new dependency, normal full sync reads them from @starci/jest-preset again.
|
|
54
|
-
export const UPGRADE_PRESETS = Object.freeze({
|
|
55
|
-
sonarExclusions: bundledPresets().sonarExclusions,
|
|
56
|
-
coverageSources: Object.freeze([
|
|
57
|
-
"src/**/*.service.ts",
|
|
58
|
-
"src/features/cli/**/*.cli.ts",
|
|
59
|
-
]),
|
|
60
|
-
});
|
|
61
|
-
const STANDARD_CLI_FILES = Object.freeze([
|
|
62
|
-
"src/features/cli/index.ts",
|
|
63
|
-
"src/features/cli/migrate/migrate.cli.ts",
|
|
64
|
-
"src/features/cli/migrate/migrate.module.ts",
|
|
65
|
-
]);
|
|
66
33
|
|
|
67
34
|
export class UpgradeError extends Error {
|
|
68
35
|
constructor(code, message) {
|
|
@@ -71,7 +38,6 @@ export class UpgradeError extends Error {
|
|
|
71
38
|
}
|
|
72
39
|
}
|
|
73
40
|
|
|
74
|
-
const posix = (value) => value.split(path.sep).join("/");
|
|
75
41
|
const jsonText = (value) => `${JSON.stringify(value, null, 2)}\n`;
|
|
76
42
|
const fileText = (root, file) =>
|
|
77
43
|
fs
|
|
@@ -81,44 +47,6 @@ const sameText = (root, file, content) =>
|
|
|
81
47
|
fs.existsSync(path.join(root, ...file.split("/"))) &&
|
|
82
48
|
fileText(root, file) === content.replace(/\r\n/g, "\n");
|
|
83
49
|
|
|
84
|
-
const readmeCommand = (name) =>
|
|
85
|
-
name === "test" ? "npm test" : `npm run ${name}`;
|
|
86
|
-
|
|
87
|
-
function listsCommand(section, command) {
|
|
88
|
-
const escaped = command.replace(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`);
|
|
89
|
-
return new RegExp(String.raw`^\s*${escaped}\s*$`, "mu").test(section);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Add only the top-level commands that the full managed scripts introduce, preserving every existing README byte around them. */
|
|
93
|
-
function upgradedReadme(root) {
|
|
94
|
-
const file = path.join(root, "README.md");
|
|
95
|
-
if (!fs.existsSync(file)) return null;
|
|
96
|
-
const source = fs.readFileSync(file, "utf8");
|
|
97
|
-
const newline = source.includes("\r\n") ? "\r\n" : "\n";
|
|
98
|
-
const lines = source.split(/\r?\n/u);
|
|
99
|
-
const start = lines.findIndex((line) => /^## Development\s*$/u.test(line));
|
|
100
|
-
if (start < 0) return null;
|
|
101
|
-
const end = lines.findIndex(
|
|
102
|
-
(line, index) => index > start && /^## /u.test(line),
|
|
103
|
-
);
|
|
104
|
-
const stop = end < 0 ? lines.length : end;
|
|
105
|
-
const addedNames = [...managedScriptNames("app", "full")].filter(
|
|
106
|
-
(name) =>
|
|
107
|
-
!name.includes(":") && !managedScriptNames("app", "lite").has(name),
|
|
108
|
-
);
|
|
109
|
-
const section = lines.slice(start + 1, stop).join("\n");
|
|
110
|
-
const commands = addedNames
|
|
111
|
-
.map(readmeCommand)
|
|
112
|
-
.filter((command) => !listsCommand(section, command));
|
|
113
|
-
if (commands.length === 0) return null;
|
|
114
|
-
let insert = -1;
|
|
115
|
-
for (let index = start + 1; index < stop; index += 1)
|
|
116
|
-
if (/^\s*npm run\s+/u.test(lines[index])) insert = index + 1;
|
|
117
|
-
if (insert < 0) return null;
|
|
118
|
-
lines.splice(insert, 0, ...commands);
|
|
119
|
-
return lines.join(newline);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
50
|
function readJson(root, file) {
|
|
123
51
|
try {
|
|
124
52
|
return JSON.parse(fileText(root, file));
|
|
@@ -130,45 +58,6 @@ function readJson(root, file) {
|
|
|
130
58
|
}
|
|
131
59
|
}
|
|
132
60
|
|
|
133
|
-
function listFiles(dir, base = dir) {
|
|
134
|
-
if (!fs.existsSync(dir)) return [];
|
|
135
|
-
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
136
|
-
const target = path.join(dir, entry.name);
|
|
137
|
-
return entry.isDirectory()
|
|
138
|
-
? listFiles(target, base)
|
|
139
|
-
: [posix(path.relative(base, target))];
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** The full declaration produced from a lite declaration. The edition field disappears and the one cli app becomes required. */
|
|
144
|
-
export function fullEditionDeclaration(
|
|
145
|
-
declaration,
|
|
146
|
-
manifest = loadSlotManifest(),
|
|
147
|
-
) {
|
|
148
|
-
if (declaration?.edition !== "lite") {
|
|
149
|
-
const actual = declaration?.edition ?? "full";
|
|
150
|
-
throw new UpgradeError(
|
|
151
|
-
"HFS_UPGRADE_ALREADY_FULL",
|
|
152
|
-
`hfs.json edition is ${actual}; upgrade accepts only an edition lite app`,
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
const next = structuredClone(declaration);
|
|
156
|
-
delete next.edition;
|
|
157
|
-
const cliApps =
|
|
158
|
-
next.sides?.be?.apps?.filter((app) => app.kind === "cli") ?? [];
|
|
159
|
-
if (cliApps.some((app) => app.name !== "cli") || cliApps.length > 1) {
|
|
160
|
-
throw new UpgradeError(
|
|
161
|
-
"HFS_UPGRADE_CLI_CONFLICT",
|
|
162
|
-
"the lite declaration has a cli app that is not the one be/apps/cli; rename it before upgrading",
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
if (cliApps.length === 0)
|
|
166
|
-
next.sides.be.apps.push({ name: "cli", kind: "cli" });
|
|
167
|
-
next.sides.be.kinds = [...new Set([...(next.sides.be.kinds ?? []), "cli"])];
|
|
168
|
-
resolveRepoDeclaration(manifest, next);
|
|
169
|
-
return next;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
61
|
function pinnedPackage(root, pins) {
|
|
173
62
|
const current = readJson(root, "package.json");
|
|
174
63
|
const section = (name, dependencies) => {
|
|
@@ -193,115 +82,11 @@ function pinnedPackage(root, pins) {
|
|
|
193
82
|
};
|
|
194
83
|
}
|
|
195
84
|
|
|
196
|
-
function nestCliText(declaration) {
|
|
197
|
-
const apps = declaration.sides.be.apps;
|
|
198
|
-
const projects = Object.fromEntries(
|
|
199
|
-
apps.map((app) => [
|
|
200
|
-
app.name,
|
|
201
|
-
{
|
|
202
|
-
type: "application",
|
|
203
|
-
root: `apps/${app.name}`,
|
|
204
|
-
entryFile: "main",
|
|
205
|
-
sourceRoot: `apps/${app.name}/src`,
|
|
206
|
-
},
|
|
207
|
-
]),
|
|
208
|
-
);
|
|
209
|
-
const api = apps.find((app) => app.kind === "api");
|
|
210
|
-
return jsonText({
|
|
211
|
-
$schema: "https://json.schemastore.org/nest-cli",
|
|
212
|
-
collection: "@nestjs/schematics",
|
|
213
|
-
monorepo: true,
|
|
214
|
-
root: `apps/${api.name}`,
|
|
215
|
-
sourceRoot: `apps/${api.name}/src`,
|
|
216
|
-
projects,
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function templateFiles(group, prefix, variables) {
|
|
221
|
-
const dir = path.join(TEMPLATES_DIR, group);
|
|
222
|
-
return listFiles(dir).map((file) => ({
|
|
223
|
-
path: `${prefix}${file}`,
|
|
224
|
-
content: render(
|
|
225
|
-
fs
|
|
226
|
-
.readFileSync(path.join(dir, ...file.split("/")), "utf8")
|
|
227
|
-
.replace(/\r\n/g, "\n"),
|
|
228
|
-
variables,
|
|
229
|
-
),
|
|
230
|
-
}));
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/** Keep an existing topology and its runbooks together; the fallback stack is only for apps without a declaration. */
|
|
234
|
-
function stackAdditions(root, variables) {
|
|
235
|
-
const declaration = ".starcistacks/application-stacks.yaml";
|
|
236
|
-
const hasStacks = fs.existsSync(path.join(root, declaration));
|
|
237
|
-
return templateFiles("app/upgrade-full", "", variables).filter((file) =>
|
|
238
|
-
!hasStacks || file.path === declaration || !file.path.startsWith(".starcistacks/"));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function additions(root, full, hadCli, manifest) {
|
|
242
|
-
const variables = { project: full.project, app: "cli", appPascal: "Cli" };
|
|
243
|
-
const files = [
|
|
244
|
-
...stackAdditions(root, variables),
|
|
245
|
-
...scaffoldWorkSeeds(full.project).filter((file) =>
|
|
246
|
-
!fs.existsSync(path.join(root, file.path))
|
|
247
|
-
&& (file.path === ".starciwork/workspace.yaml" || !fs.existsSync(path.join(root, ".starciwork", "index.yaml")))),
|
|
248
|
-
...(!hadCli
|
|
249
|
-
? [
|
|
250
|
-
...STANDARD_CLI_FILES.map((file) => ({
|
|
251
|
-
path: `be/${file}`,
|
|
252
|
-
content: fs
|
|
253
|
-
.readFileSync(
|
|
254
|
-
path.join(TEMPLATES_DIR, "be", "skeleton", ...file.split("/")),
|
|
255
|
-
"utf8",
|
|
256
|
-
)
|
|
257
|
-
.replace(/\r\n/g, "\n"),
|
|
258
|
-
})),
|
|
259
|
-
...templateFiles("be/upgrade-full", "be/", variables),
|
|
260
|
-
]
|
|
261
|
-
: []),
|
|
262
|
-
];
|
|
263
|
-
const requiredImages = imageFiles(
|
|
264
|
-
resolveRepoDeclaration(manifest, full),
|
|
265
|
-
).filter((file) => !file.path.startsWith("be/apps/api/"));
|
|
266
|
-
for (const file of requiredImages) files.push(file);
|
|
267
|
-
return files;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/** The post-upgrade back-end source view used by the managed coverage render before those additions exist on disk. */
|
|
271
|
-
function sourceWithAdditions(root, additions) {
|
|
272
|
-
const current = appSource(root);
|
|
273
|
-
const added = new Map(
|
|
274
|
-
additions
|
|
275
|
-
.filter(
|
|
276
|
-
(file) => file.path.startsWith("be/") && /\.[cm]?ts$/u.test(file.path),
|
|
277
|
-
)
|
|
278
|
-
.map((file) => [file.path.slice("be/".length), file.content]),
|
|
279
|
-
);
|
|
280
|
-
return {
|
|
281
|
-
files: [...new Set([...current.files, ...added.keys()])].sort(byCodeUnit),
|
|
282
|
-
read: (file) => added.get(file) ?? current.read(file),
|
|
283
|
-
// The declared images and pass-through variables render the managed stack-deploy.yml exactly as `app sync` will.
|
|
284
|
-
stack: readDeclaredStack(root, { parseYaml }),
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
288
85
|
const publicStep = ({ op, path: file, why }) => ({ op, path: file, why });
|
|
289
86
|
|
|
290
|
-
function
|
|
291
|
-
if (file.startsWith(".starcistacks/")) return "Add the pinned Supabase/Postgres and api full-stack skeleton.";
|
|
292
|
-
if (file.startsWith(".starciwork/")) return "Add the canonical product catalog and existing liveness feature overview.";
|
|
293
|
-
if (file.includes("/tests/")) return "Open the full test layer without inventing a spec.";
|
|
294
|
-
return "Add the full-only cli or image scaffold.";
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function additionStep(root, file, authored) {
|
|
87
|
+
function additionStep(root, file) {
|
|
298
88
|
const target = path.join(root, ...file.path.split("/"));
|
|
299
|
-
if (!fs.existsSync(target)) return {
|
|
300
|
-
op: "add", path: file.path, why: additionReason(file.path), content: file.content, kind: "file",
|
|
301
|
-
};
|
|
302
|
-
if (authored.has(file.path)) return {
|
|
303
|
-
op: "keep", path: file.path, why: authored.get(file.path), kind: "keep",
|
|
304
|
-
};
|
|
89
|
+
if (!fs.existsSync(target)) return { op: "add", path: file.path, why: "Open the full test layer without inventing a spec.", content: file.content, kind: "file" };
|
|
305
90
|
if (!sameText(root, file.path, file.content)) throw new UpgradeError(
|
|
306
91
|
"HFS_UPGRADE_FILE_CONFLICT",
|
|
307
92
|
`${file.path} already exists and is not the upgrade scaffold; no file was overwritten`,
|
|
@@ -317,7 +102,7 @@ function fullCompletion(root, declaration) {
|
|
|
317
102
|
const steps = [];
|
|
318
103
|
if (!fs.existsSync(path.join(root, ...WORLD_MARKER.split("/")))) {
|
|
319
104
|
for (const file of testWorldFiles(declaration)) {
|
|
320
|
-
const step = additionStep(root, file
|
|
105
|
+
const step = additionStep(root, file);
|
|
321
106
|
if (step) steps.push({ ...step, why: "Add the full test world and its baseline integration and e2e specs." });
|
|
322
107
|
}
|
|
323
108
|
}
|
|
@@ -344,147 +129,36 @@ function fullCompletion(root, declaration) {
|
|
|
344
129
|
return { managed: [], steps, dependenciesChanged: missing.length > 0 };
|
|
345
130
|
}
|
|
346
131
|
|
|
347
|
-
|
|
348
|
-
if (to !== undefined && to !== "full")
|
|
349
|
-
throw new UpgradeError(
|
|
350
|
-
"HFS_UPGRADE_TARGET_INVALID",
|
|
351
|
-
"upgrade supports only --edition full",
|
|
352
|
-
);
|
|
132
|
+
function model({ root, manifest }) {
|
|
353
133
|
const declaration = loadHfs(root, manifest);
|
|
354
|
-
if (declaration?.edition
|
|
355
|
-
if (to === undefined)
|
|
356
|
-
throw new UpgradeError(
|
|
357
|
-
"HFS_UPGRADE_USAGE",
|
|
358
|
-
"a lite app upgrades with starci app upgrade --edition full",
|
|
359
|
-
);
|
|
360
|
-
const hadCli = declaration.sides.be.apps.some(
|
|
361
|
-
(app) => app.kind === "cli" && app.name === "cli",
|
|
362
|
-
);
|
|
363
|
-
const full = fullEditionDeclaration(declaration, manifest);
|
|
364
|
-
const desired = additions(root, full, hadCli, manifest);
|
|
365
|
-
const authored = authoredAdditionReasons(declaration, appSource(root));
|
|
366
|
-
const pins = parseYaml(fs.readFileSync(PINS_FILE, "utf8")).pins;
|
|
367
|
-
const upgradedPackage = pinnedPackage(root, pins);
|
|
368
|
-
const resolvedPresets = presets ?? UPGRADE_PRESETS;
|
|
369
|
-
const managed = renderTargets(full, resolvedPresets, {
|
|
370
|
-
manifest,
|
|
371
|
-
source: sourceWithAdditions(root, desired),
|
|
372
|
-
});
|
|
373
|
-
const packageTarget = managed.find(
|
|
374
|
-
(target) => target.path === "package.json",
|
|
375
|
-
);
|
|
376
|
-
if (!packageTarget)
|
|
134
|
+
if (declaration?.edition === "lite")
|
|
377
135
|
throw new UpgradeError(
|
|
378
|
-
"
|
|
379
|
-
"
|
|
136
|
+
"HFS_UPGRADE_EDITION_FIXED",
|
|
137
|
+
"editions are fixed at scaffold: a lite app stays lite and a full app stays full; there is no lite to full upgrade",
|
|
380
138
|
);
|
|
381
|
-
|
|
382
|
-
const packageChanged =
|
|
383
|
-
jsonText(nextPackage) !== fileText(root, "package.json");
|
|
384
|
-
const dependenciesChanged =
|
|
385
|
-
[...FULL_DEPENDENCIES].some(
|
|
386
|
-
(name) =>
|
|
387
|
-
readJson(root, "package.json").dependencies?.[name] !==
|
|
388
|
-
nextPackage.dependencies[name],
|
|
389
|
-
) ||
|
|
390
|
-
[...FULL_DEV_DEPENDENCIES].some(
|
|
391
|
-
(name) =>
|
|
392
|
-
readJson(root, "package.json").devDependencies?.[name] !==
|
|
393
|
-
nextPackage.devDependencies[name],
|
|
394
|
-
);
|
|
395
|
-
const managedWithoutPackage = managed.filter(
|
|
396
|
-
(target) => target.path !== "package.json",
|
|
397
|
-
);
|
|
398
|
-
const targetResults = checkTargets(root, managedWithoutPackage);
|
|
399
|
-
const steps = [
|
|
400
|
-
{
|
|
401
|
-
op: "remove-field",
|
|
402
|
-
path: "hfs.json",
|
|
403
|
-
why: "Full is the default edition; declare the required cli app without changing the HFS major.",
|
|
404
|
-
content: jsonText(full),
|
|
405
|
-
kind: "file",
|
|
406
|
-
},
|
|
407
|
-
];
|
|
408
|
-
const readme = upgradedReadme(root);
|
|
409
|
-
if (readme !== null)
|
|
410
|
-
steps.push({
|
|
411
|
-
op: "rewrite-readme",
|
|
412
|
-
path: "README.md",
|
|
413
|
-
why: "List the full edition's newly managed top-level scripts in Development without changing other README text.",
|
|
414
|
-
content: readme,
|
|
415
|
-
kind: "file",
|
|
416
|
-
});
|
|
417
|
-
for (const result of targetResults) {
|
|
418
|
-
if (result.status === "ok") continue;
|
|
419
|
-
steps.push({
|
|
420
|
-
op: result.status === "missing" ? "add" : "rewrite-managed",
|
|
421
|
-
path: result.path,
|
|
422
|
-
why: "Render the full-edition managed file through the normal sync renderer.",
|
|
423
|
-
kind: "managed",
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
if (packageChanged)
|
|
427
|
-
steps.push({
|
|
428
|
-
op: "rewrite-managed",
|
|
429
|
-
path: "package.json",
|
|
430
|
-
why: "Add the full test toolchain (the e2e world and any unit tooling a lite app lacks) at canon pins and render the full root scripts.",
|
|
431
|
-
content: jsonText(nextPackage),
|
|
432
|
-
kind: "file",
|
|
433
|
-
});
|
|
434
|
-
for (const file of desired) {
|
|
435
|
-
const step = additionStep(root, file, authored);
|
|
436
|
-
if (step) steps.push(step);
|
|
437
|
-
}
|
|
438
|
-
if (!sameText(root, "be/nest-cli.json", nestCliText(full)))
|
|
439
|
-
steps.push({
|
|
440
|
-
op: "rewrite-managed",
|
|
441
|
-
path: "be/nest-cli.json",
|
|
442
|
-
why: "Register the required cli app in the Nest monorepo map.",
|
|
443
|
-
content: nestCliText(full),
|
|
444
|
-
kind: "file",
|
|
445
|
-
});
|
|
446
|
-
if (dependenciesChanged)
|
|
447
|
-
steps.push({
|
|
448
|
-
op: "rewrite-managed",
|
|
449
|
-
path: "package-lock.json",
|
|
450
|
-
why: `Resolve the added pinned dependencies with ${LOCK_STEP}.`,
|
|
451
|
-
kind: "lock",
|
|
452
|
-
});
|
|
453
|
-
return { full, managed: managedWithoutPackage, steps, dependenciesChanged };
|
|
139
|
+
return fullCompletion(root, declaration);
|
|
454
140
|
}
|
|
455
141
|
|
|
456
|
-
|
|
457
142
|
/**
|
|
458
|
-
* Plans or applies the
|
|
459
|
-
* `
|
|
143
|
+
* Plans or applies the completion of a full app. Returns the ordered public plan (`{op,path,why}[]`) in both modes.
|
|
144
|
+
* `lock` is the test seam for the npm lock resolution.
|
|
460
145
|
*/
|
|
461
146
|
async function upgradeEdition({
|
|
462
147
|
root,
|
|
463
|
-
to,
|
|
464
148
|
plan = false,
|
|
465
|
-
presets,
|
|
466
149
|
manifest = loadSlotManifest(),
|
|
467
150
|
lock = npmLock,
|
|
468
151
|
}) {
|
|
469
152
|
const repoRoot = path.resolve(root);
|
|
470
|
-
const built =
|
|
153
|
+
const built = model({ root: repoRoot, manifest });
|
|
471
154
|
const result = built.steps.map(publicStep);
|
|
472
155
|
if (plan) return result;
|
|
473
156
|
const snapshot = new Map();
|
|
474
157
|
const directories = [];
|
|
475
158
|
try {
|
|
476
159
|
for (const step of built.steps) {
|
|
477
|
-
if (step.kind === "lock"
|
|
478
|
-
|
|
479
|
-
const target = built.managed.find(
|
|
480
|
-
(candidate) => candidate.path === step.path,
|
|
481
|
-
);
|
|
482
|
-
const file = path.join(repoRoot, ...step.path.split("/"));
|
|
483
|
-
remember(snapshot, file);
|
|
484
|
-
ensureParent(repoRoot, file, directories);
|
|
485
|
-
writeTargets(repoRoot, [target]);
|
|
486
|
-
} else
|
|
487
|
-
writeFile(repoRoot, step.path, step.content, snapshot, directories);
|
|
160
|
+
if (step.kind === "lock") continue;
|
|
161
|
+
writeFile(repoRoot, step.path, step.content, snapshot, directories);
|
|
488
162
|
}
|
|
489
163
|
if (built.dependenciesChanged) {
|
|
490
164
|
const lockFile = path.join(repoRoot, "package-lock.json");
|
|
@@ -504,33 +178,32 @@ async function upgradeEdition({
|
|
|
504
178
|
}
|
|
505
179
|
|
|
506
180
|
function upgradeArguments(argv) {
|
|
507
|
-
let to;
|
|
508
181
|
let plan = false;
|
|
509
182
|
let root = process.cwd();
|
|
510
183
|
for (let index = 0; index < argv.length; index += 1) {
|
|
511
184
|
const arg = argv[index];
|
|
512
|
-
if (arg === "--
|
|
185
|
+
if (arg === "--repo") {
|
|
513
186
|
if (argv[index + 1] === undefined)
|
|
514
187
|
throw new UpgradeError("HFS_UPGRADE_USAGE", `${arg} needs a value`);
|
|
515
|
-
|
|
516
|
-
else root = path.resolve(argv[index + 1]);
|
|
188
|
+
root = path.resolve(argv[index + 1]);
|
|
517
189
|
index += 1;
|
|
518
190
|
} else if (arg === "--plan") plan = true;
|
|
191
|
+
else if (arg === "--edition")
|
|
192
|
+
throw new UpgradeError("HFS_UPGRADE_USAGE", "upgrade takes no --edition: editions are fixed at scaffold");
|
|
519
193
|
else throw new UpgradeError("HFS_UPGRADE_USAGE", `unknown argument ${arg}`);
|
|
520
194
|
}
|
|
521
|
-
return { root,
|
|
195
|
+
return { root, plan };
|
|
522
196
|
}
|
|
523
197
|
|
|
524
198
|
/** CLI adapter kept outside the CLI entry so that verb wiring remains one line. */
|
|
525
|
-
export async function upgradeMain(
|
|
526
|
-
argv
|
|
527
|
-
|
|
528
|
-
) {
|
|
529
|
-
|
|
530
|
-
const steps = await upgradeEdition({ root, to, plan, presets });
|
|
531
|
-
for (const step of steps) stdout(`${step.op} ${step.path}: ${step.why}\n`);
|
|
199
|
+
export async function upgradeMain(argv, { stdout = (value) => process.stdout.write(value) } = {}) {
|
|
200
|
+
const { root, plan } = upgradeArguments(argv);
|
|
201
|
+
const steps = await upgradeEdition({ root, plan });
|
|
202
|
+
for (const step of steps) stdout(`${step.op} ${step.path}: ${step.why}
|
|
203
|
+
`);
|
|
532
204
|
stdout(
|
|
533
|
-
`starci app upgrade${
|
|
205
|
+
`starci app upgrade${plan ? " --plan" : ""}: ${steps.length} step${steps.length === 1 ? "" : "s"} ${plan ? "planned; no file written" : "applied"}${steps.length === 0 ? " (the full app is complete)" : ""}
|
|
206
|
+
`,
|
|
534
207
|
);
|
|
535
208
|
return 0;
|
|
536
209
|
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// check-code-loosening.mjs - what loosens a gate when the gate is CODE: a check script, a canon template, a lint package, a workflow or a hook.
|
|
2
|
-
// gate-loosening.mjs judges the lists and numbers of the listed gate files; a bypass done by editing the check itself (a skip, an inline disable,
|
|
3
|
-
// a swallowed failure, a ban or an assertion deleted, an exemption widened) is judged here, over the same unified diff, rename-aware (a line
|
|
4
|
-
// that moves keeps its text, so it is paired off against its removal anywhere in the change). The kinds it reports:
|
|
5
|
-
// bypass-added a bypass marker added to a file of checkCode (scripts/lib/bypass-markers.mjs)
|
|
6
|
-
// check-weakened the change removes more enforcement lines from the files of checkCode than it adds back to them
|
|
7
|
-
// check-removed a pattern-table row or quoted list entry removed from a check script and added nowhere in the change (a quoted
|
|
8
|
-
// operand of a string concatenation, the text of a message, is no row)
|
|
9
|
-
// scope-widened an exemption added: an ignore / exclude / exclusion key gaining an entry, a line more in an ignore file, an item added
|
|
10
|
-
// under codecov.yml `ignore:`, or skipLibCheck turned on
|
|
11
|
-
// A deleted file is not counted for check-weakened or check-removed: a registered check is judged by its entry in a gate file
|
|
12
|
-
// (knowledge/hfs/runtime-slots.yaml), and an unregistered script deleted is dead code (scripts/checks/check-dead-scripts.mjs).
|
|
13
|
-
import { bypassFileKind, bypassLabelsOf } from './bypass-markers.mjs';
|
|
14
|
-
|
|
15
|
-
const SPEC_NAME = /\.spec\.[cm]?[jt]sx?$/;
|
|
16
|
-
const FIXTURE_NAME = /\.fixture(?:\.\w+)?$/;
|
|
17
|
-
const CODE_NAME = /\.[cm]?[jt]sx?$/;
|
|
18
|
-
const COMMENT_LINE = /^\s*(?:\/\/|\/\*|\*|#)/;
|
|
19
|
-
const NOT_TEXT = /^\s*(?:#|\/\/|$)/;
|
|
20
|
-
|
|
21
|
-
const trimmed = (line) => line.trim();
|
|
22
|
-
const clip = (text) => (text.length > 90 ? `${text.slice(0, 89)}…` : text);
|
|
23
|
-
|
|
24
|
-
/** Whether `file` is one of the entries: a folder (the entry ends in a slash) or one file. */
|
|
25
|
-
const listed = (file, entries = []) => entries.some((entry) => (entry.endsWith('/') ? file.startsWith(entry) : file === entry));
|
|
26
|
-
|
|
27
|
-
/** Whether `file` is a check, a canon template, a lint package, a workflow or a hook (checkCode); its specs and fixtures spell markers on purpose and are not. */
|
|
28
|
-
export const isCheckCode = (file, rules) => listed(file, rules.checkCode) && !listed(file, rules.capabilityFiles) && !SPEC_NAME.test(file) && !FIXTURE_NAME.test(file);
|
|
29
|
-
|
|
30
|
-
const WORD = String.raw`\b(?:findings|violations|failures|errors|problems|issues|found|flag|fail)\s*(?:\.push\(|\()`;
|
|
31
|
-
const EXIT = String.raw`process\.exit(?:Code)?\b|\bassert[.(]|\bexpect\(|\bok\s*:\s*false\b`;
|
|
32
|
-
/** The lines that make a check fail: a finding pushed, a failing exit, an assertion. */
|
|
33
|
-
const ENFORCEMENT = new RegExp(`${WORD}|${EXIT}`);
|
|
34
|
-
const enforcementCount = (lines) => lines.filter((line) => !COMMENT_LINE.test(line) && ENFORCEMENT.test(line)).length;
|
|
35
|
-
|
|
36
|
-
const LITERAL = '/.+/[a-z]*|\'[^\']*\'|"[^"]*"|`[^`]*`';
|
|
37
|
-
/** A pattern-table row or a quoted list entry of a check script: the shape of a ban list or a rule table. */
|
|
38
|
-
const LIST_ENTRY = new RegExp(String.raw`^\s*(?:\[\s*(?:${LITERAL})\s*,.*\]|${LITERAL})\s*,?\s*(?://.*)?$`);
|
|
39
|
-
|
|
40
|
-
const countOf = (lines) => lines.reduce((counts, line) => counts.set(trimmed(line), (counts.get(trimmed(line)) ?? 0) + 1), new Map());
|
|
41
|
-
|
|
42
|
-
/** Each file's added lines once every line that also appears removed somewhere in the change (it only moved) is paired off: Map(entry -> {added, removed}). */
|
|
43
|
-
function unmovedOf(files) {
|
|
44
|
-
const added = countOf(files.flatMap((entry) => entry.added));
|
|
45
|
-
const removed = countOf(files.flatMap((entry) => entry.removed));
|
|
46
|
-
const keep = (line) => {
|
|
47
|
-
const key = trimmed(line);
|
|
48
|
-
if ((added.get(key) ?? 0) <= 0 || (removed.get(key) ?? 0) <= 0) return true;
|
|
49
|
-
added.set(key, added.get(key) - 1);
|
|
50
|
-
removed.set(key, removed.get(key) - 1);
|
|
51
|
-
return false;
|
|
52
|
-
};
|
|
53
|
-
return new Map(files.map((entry) => [entry, { added: entry.added.filter(keep), removed: entry.removed }]));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function bypassesAdded(entry, unmoved) {
|
|
57
|
-
const kind = bypassFileKind(entry.file);
|
|
58
|
-
if (!kind || entry.deleted) return [];
|
|
59
|
-
return unmoved.added.flatMap((line) => bypassLabelsOf(kind, line, { pending: true })
|
|
60
|
-
.map((label) => ({ kind: 'bypass-added', file: entry.file, detail: `${label}: ${clip(trimmed(line))}`, text: trimmed(line) })));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function entriesRemoved(entry, addedBack) {
|
|
64
|
-
if (entry.deleted || !CODE_NAME.test(entry.file)) return [];
|
|
65
|
-
const operand = (line) => entry.operands?.has(line) === true;
|
|
66
|
-
return entry.removed.filter((line) => LIST_ENTRY.test(line) && !COMMENT_LINE.test(line) && !operand(line)).flatMap((line) => {
|
|
67
|
-
const left = addedBack.get(trimmed(line)) ?? 0;
|
|
68
|
-
if (left > 0) { addedBack.set(trimmed(line), left - 1); return []; }
|
|
69
|
-
return [{ kind: 'check-removed', file: entry.file, detail: clip(trimmed(line)) }];
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const EXEMPT_WORDS = ['ignores?', 'excludes?', 'exclusions?', 'coverageExclusions', '(?:coverage|testPath|modulePath)(?:Path)?IgnorePatterns', 'globalIgnores', String.raw`sonar\.(?:coverage\.)?exclusions`];
|
|
74
|
-
const EXEMPT_KEY = new RegExp(String.raw`["']?(?:${EXEMPT_WORDS.join('|')})["']?\s*[:=]`, 'i');
|
|
75
|
-
const SKIP_LIB_CHECK = /skipLibCheck["']?\s*:\s*true/;
|
|
76
|
-
const IGNORE_FILE = /(?:^|\/)[^/]*ignore$/;
|
|
77
|
-
const CODECOV_FILE = /(?:^|\/)codecov\.ya?ml$/;
|
|
78
|
-
|
|
79
|
-
const itemsOf = (line) => (line.match(/[^\s,"'[\]{}=:]+/g) ?? []).slice(1);
|
|
80
|
-
|
|
81
|
-
function scopesWidened(entry, unmoved) {
|
|
82
|
-
if (entry.deleted) return [];
|
|
83
|
-
const widened = (line) => ({ kind: 'scope-widened', file: entry.file, detail: clip(trimmed(line)) });
|
|
84
|
-
// An ignore file that gains more lines than it loses (a line rewritten is not a line more); codecov.yml: a list item added under `ignore:`.
|
|
85
|
-
if (IGNORE_FILE.test(entry.file)) return unmoved.added.filter((line) => !NOT_TEXT.test(line)).slice(unmoved.removed.filter((line) => !NOT_TEXT.test(line)).length).map(widened);
|
|
86
|
-
if (CODECOV_FILE.test(entry.file)) return unmoved.added.filter((line) => (entry.under?.get(line) ?? []).some((section) => /^ignore\b/.test(section))).map(widened);
|
|
87
|
-
return unmoved.added.flatMap((line) => {
|
|
88
|
-
if (SKIP_LIB_CHECK.test(line)) return [widened(line)];
|
|
89
|
-
const key = EXEMPT_KEY.exec(line)?.[0];
|
|
90
|
-
if (!key) return [];
|
|
91
|
-
const before = unmoved.removed.find((value) => value.includes(key));
|
|
92
|
-
const known = new Set(before === undefined ? [] : itemsOf(before));
|
|
93
|
-
return before === undefined || itemsOf(line).some((item) => !known.has(item)) ? [widened(line)] : [];
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** An import of the runtime's one exception list (scripts/lib/allowlist.mjs). */
|
|
98
|
-
const ALLOWLIST_IMPORT = /\bfrom\s+['"][./]*(?:scripts\/)?lib\/allowlist\.mjs['"]/;
|
|
99
|
-
const NAMES_ALLOWLIST = /allowlist/i;
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* The removed lines of `entry` that count as enforcement lost. A check that stops reading the exception list (the change removes its import of
|
|
103
|
-
* scripts/lib/allowlist.mjs and adds none back) loses the enforcement that policed that list's own entries (a stale entry, an entry code now
|
|
104
|
-
* reads): those lines name the list, and with the list gone they police nothing. Every other removed enforcement line counts.
|
|
105
|
-
*/
|
|
106
|
-
function enforcementRemoved(entry) {
|
|
107
|
-
const dropsList = entry.removed.some((line) => ALLOWLIST_IMPORT.test(line)) && !entry.added.some((line) => ALLOWLIST_IMPORT.test(line));
|
|
108
|
-
return dropsList ? entry.removed.filter((line) => !NAMES_ALLOWLIST.test(line)) : entry.removed;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** Every finding the check files of the change `files` (parseDiff entries) add under `rules` (modules/kernel/gate-loosening.yaml): [{kind, file, detail}]. */
|
|
112
|
-
export function checkCodeFindings(files, rules) {
|
|
113
|
-
const watched = files.filter((entry) => isCheckCode(entry.file, rules));
|
|
114
|
-
const unmoved = unmovedOf(watched);
|
|
115
|
-
const alive = watched.filter((entry) => !entry.deleted);
|
|
116
|
-
const fewerInChange = enforcementCount(alive.flatMap(enforcementRemoved)) - enforcementCount(alive.flatMap((entry) => entry.added));
|
|
117
|
-
const addedBack = countOf(watched.flatMap((entry) => entry.added));
|
|
118
|
-
return watched.flatMap((entry) => {
|
|
119
|
-
const own = unmoved.get(entry);
|
|
120
|
-
const fewer = enforcementCount(enforcementRemoved(entry)) - enforcementCount(entry.added);
|
|
121
|
-
return [
|
|
122
|
-
...bypassesAdded(entry, own),
|
|
123
|
-
...entriesRemoved(entry, addedBack),
|
|
124
|
-
...scopesWidened(entry, own),
|
|
125
|
-
...(fewerInChange > 0 && !entry.deleted && fewer > 0 ? [{ kind: 'check-weakened', file: entry.file, detail: `${fewer} enforcement line(s) fewer` }] : []),
|
|
126
|
-
];
|
|
127
|
-
});
|
|
128
|
-
}
|