@starci/hfs 4.0.8 → 4.0.10
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 +9 -0
- package/LICENSE +21 -0
- package/README.md +81 -39
- package/emit/contracts.mjs +56 -9
- package/emit/db-types.mjs +169 -0
- package/emit/events.mjs +41 -0
- package/emit/operations-worker.mjs +1 -1
- package/emit/operations.mjs +2 -2
- package/emit/schema-worker.mjs +1 -1
- package/lint/bound-sys.cjs +50 -0
- package/lint/run.mjs +131 -24
- package/package.json +16 -10
- package/report/sonar.mjs +8 -8
- package/runtime/engine/admission.mjs +308 -0
- package/runtime/engine/canonical-json.mjs +10 -0
- package/runtime/engine/config.mjs +486 -0
- package/runtime/engine/db/blob.mjs +315 -0
- package/runtime/engine/db/ledger-paths.mjs +83 -0
- package/runtime/engine/db/ledger.mjs +1118 -0
- package/runtime/engine/db/machine-connection.mjs +135 -0
- package/runtime/engine/db/machine-schema.mjs +84 -0
- package/runtime/engine/db/machine.mjs +1367 -0
- package/runtime/engine/db/migrations/machine/0001-init.sql +924 -0
- package/runtime/engine/db/migrations/runtime/0001-init.sql +1108 -0
- package/runtime/engine/db/provider-reservations.mjs +101 -0
- package/runtime/engine/digest.mjs +16 -0
- package/runtime/engine/invalid-config.mjs +15 -0
- package/runtime/engine/orca-config.mjs +27 -0
- package/runtime/engine/refuse.mjs +11 -0
- package/runtime/engine/secrets.mjs +130 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +162 -31
- package/runtime/knowledge/hfs/peer-integrations.yaml +2 -2
- package/runtime/knowledge/hfs/rules.yaml +2059 -0
- package/runtime/knowledge/hfs/slots.yaml +912 -120
- package/runtime/knowledge/patterns/be/api.yaml +369 -0
- package/runtime/knowledge/patterns/be/cli.yaml +297 -0
- package/runtime/knowledge/patterns/be/domain.yaml +113 -0
- package/runtime/knowledge/patterns/be/event-bus.yaml +285 -0
- package/runtime/knowledge/patterns/be/jobs.yaml +261 -0
- package/runtime/knowledge/patterns/be/projections.yaml +178 -0
- package/runtime/knowledge/patterns/be/queues.yaml +236 -0
- package/runtime/knowledge/patterns/be/reactors.yaml +140 -0
- package/runtime/knowledge/patterns/be/realtime.yaml +222 -0
- package/runtime/knowledge/patterns/be/saga.yaml +248 -0
- package/runtime/knowledge/patterns/be/webhooks.yaml +221 -0
- package/runtime/knowledge/patterns/fe/folder.yaml +131 -25
- package/runtime/knowledge/sonar-gate.yaml +52 -18
- package/runtime/modules/kernel/failure-codes.yaml +611 -51
- package/runtime/modules/models/registry.yaml +553 -0
- package/runtime/modules/models/runtimes.yaml +695 -0
- package/runtime/modules/ops/_labels.yaml +53 -0
- package/runtime/scripts/api/fs/forbidden-root.mjs +51 -0
- package/runtime/scripts/api/fs/is-link-like.mjs +25 -0
- package/runtime/scripts/api/fs/lib.mjs +16 -2
- package/runtime/scripts/api/fs/safe-remove.mjs +12 -132
- package/runtime/scripts/api/git/config-get.mjs +10 -0
- package/runtime/scripts/api/git/diff.mjs +5 -0
- package/runtime/scripts/api/git/lib.mjs +18 -26
- package/runtime/scripts/api/git/log.mjs +5 -0
- package/runtime/scripts/api/git/ls-files.mjs +6 -0
- package/runtime/scripts/api/git/ls-tree.mjs +5 -0
- package/runtime/scripts/api/git/merge-base.mjs +9 -0
- package/runtime/scripts/api/git/remote.mjs +5 -0
- package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
- package/runtime/scripts/api/git/show.mjs +6 -0
- package/runtime/scripts/api/node/lib.mjs +14 -0
- package/runtime/scripts/api/node/spawn-node.mjs +6 -0
- package/runtime/scripts/api/process/lib.mjs +111 -0
- package/runtime/scripts/api/process/owned-process.mjs +78 -0
- package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -0
- package/runtime/scripts/api/process/run-program.mjs +7 -0
- package/runtime/scripts/api/process/stop-owned-process.mjs +9 -0
- package/runtime/scripts/api/sops/decrypt.mjs +9 -12
- package/runtime/scripts/api/sops/lib.mjs +255 -0
- package/runtime/scripts/api/sops/seal.mjs +22 -0
- package/runtime/scripts/connectors/lib.mjs +488 -0
- package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
- package/runtime/scripts/hfs/architecture/backend.mjs +16 -23
- package/runtime/scripts/hfs/architecture/background-unowned.mjs +16 -34
- package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +3 -1
- package/runtime/scripts/hfs/architecture/clones.mjs +4 -4
- package/runtime/scripts/hfs/architecture/config.mjs +9 -6
- package/runtime/scripts/hfs/architecture/connection-map.mjs +20 -8
- package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
- package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
- package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
- package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
- package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
- package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +4 -10
- package/runtime/scripts/hfs/architecture/contracts.mjs +33 -162
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +58 -29
- package/runtime/scripts/hfs/architecture/doc-language.mjs +1 -1
- package/runtime/scripts/hfs/architecture/entrypoint.mjs +2 -1
- package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +2 -2
- package/runtime/scripts/hfs/architecture/feature-shape.mjs +5 -2
- package/runtime/scripts/hfs/architecture/framework-pinned.mjs +1 -1
- package/runtime/scripts/hfs/architecture/frontend.mjs +17 -43
- package/runtime/scripts/hfs/architecture/hfs.mjs +24 -39
- package/runtime/scripts/hfs/architecture/i18n-keys.mjs +1 -1
- package/runtime/scripts/hfs/architecture/index.mjs +17 -4
- package/runtime/scripts/hfs/architecture/machine-ast.mjs +44 -11
- package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +30 -6
- package/runtime/scripts/hfs/architecture/next-data.mjs +22 -63
- package/runtime/scripts/hfs/architecture/owners.mjs +35 -15
- package/runtime/scripts/hfs/architecture/register-once.mjs +2 -1
- package/runtime/scripts/hfs/architecture/registration.mjs +23 -81
- package/runtime/scripts/hfs/architecture/required-files.mjs +20 -12
- package/runtime/scripts/hfs/architecture/schema-owner.mjs +17 -114
- package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
- package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
- package/runtime/scripts/hfs/architecture/source-names.mjs +27 -147
- package/runtime/scripts/hfs/architecture/sql-owner.mjs +59 -18
- package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
- package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
- package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
- package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
- package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
- package/runtime/scripts/hfs/architecture/surface.mjs +9 -3
- package/runtime/scripts/hfs/architecture/test-world-files.mjs +9 -19
- package/runtime/scripts/hfs/architecture/tiers.mjs +47 -5
- package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -3
- package/runtime/scripts/hfs/architecture/typescript.mjs +12 -26
- package/runtime/scripts/hfs/architecture.mjs +4 -4
- package/runtime/scripts/hfs/check.mjs +75 -72
- package/runtime/scripts/hfs/coverage-scope.mjs +162 -0
- package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
- package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
- package/runtime/scripts/hfs/edition-slots.mjs +66 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +109 -32
- package/runtime/scripts/hfs/param-names.mjs +18 -0
- package/runtime/scripts/hfs/path-findings.mjs +1 -1
- package/runtime/scripts/hfs/repo-identity.mjs +9 -6
- package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
- package/runtime/scripts/hfs/rules/app-root.mjs +51 -0
- package/runtime/scripts/hfs/rules/cli.mjs +37 -0
- package/runtime/scripts/hfs/rules/contract-compat.mjs +71 -0
- package/runtime/scripts/hfs/rules/contract.mjs +10 -9
- package/runtime/scripts/hfs/rules/database-config.mjs +102 -0
- package/runtime/scripts/hfs/rules/database-constants.mjs +13 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +111 -0
- package/runtime/scripts/hfs/rules/database-plpgsql.mjs +233 -0
- package/runtime/scripts/hfs/rules/database-sql.mjs +336 -0
- package/runtime/scripts/hfs/rules/database.mjs +68 -0
- package/runtime/scripts/hfs/rules/deps.mjs +1 -1
- package/runtime/scripts/hfs/rules/docker.mjs +259 -0
- package/runtime/scripts/hfs/rules/edition.mjs +111 -0
- package/runtime/scripts/hfs/rules/event-bus.mjs +153 -0
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -1
- package/runtime/scripts/hfs/rules/fe-no-tests.mjs +6 -5
- package/runtime/scripts/hfs/rules/frontend-tree.mjs +9 -9
- package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -6
- package/runtime/scripts/hfs/rules/kinds.mjs +84 -0
- package/runtime/scripts/hfs/rules/lint-suppression.mjs +1 -1
- package/runtime/scripts/hfs/rules/monorepo.mjs +179 -0
- package/runtime/scripts/hfs/rules/peer-integrations.mjs +3 -3
- package/runtime/scripts/hfs/rules/pipeline.mjs +11 -21
- package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -2
- package/runtime/scripts/hfs/rules/read.mjs +1 -1
- package/runtime/scripts/hfs/rules/repo-local-checks.mjs +2 -2
- package/runtime/scripts/hfs/rules/saga.mjs +170 -0
- package/runtime/scripts/hfs/rules/secrets.mjs +3 -3
- package/runtime/scripts/hfs/rules/services.mjs +220 -0
- package/runtime/scripts/hfs/rules/spec-placement.mjs +1 -1
- package/runtime/scripts/hfs/rules/stacks.mjs +3 -3
- package/runtime/scripts/hfs/rules/supabase-secrets.mjs +89 -0
- package/runtime/scripts/hfs/rules/test-topology.mjs +2 -2
- package/runtime/scripts/hfs/secret.mjs +209 -0
- package/runtime/scripts/hfs/slots.mjs +78 -108
- package/runtime/scripts/hfs/sql/pg-parse.mjs +46 -0
- package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
- package/runtime/scripts/hfs/tree.mjs +5 -4
- package/runtime/scripts/hfs/typescript-programs.mjs +0 -5
- package/runtime/scripts/hfs/view.mjs +3 -2
- package/runtime/scripts/lib/clip.mjs +19 -0
- package/runtime/scripts/lib/display-names.mjs +259 -0
- package/runtime/scripts/lib/dockerfile.mjs +124 -0
- package/runtime/scripts/lib/env.mjs +10 -0
- package/runtime/scripts/lib/event-contract.mjs +103 -0
- package/runtime/scripts/lib/example-refs.mjs +158 -0
- package/runtime/scripts/lib/fs-kind.mjs +14 -4
- package/runtime/scripts/lib/git.mjs +36 -0
- package/runtime/scripts/lib/graphql-contract.mjs +1 -1
- package/runtime/scripts/lib/i18n.mjs +86 -0
- package/runtime/scripts/lib/json-schema.mjs +52 -0
- package/runtime/scripts/lib/json.mjs +13 -3
- package/runtime/scripts/lib/language.mjs +24 -5
- package/runtime/scripts/lib/list.mjs +20 -0
- package/runtime/scripts/lib/mutation-fence.mjs +15 -0
- package/runtime/scripts/lib/package-at.mjs +37 -0
- package/runtime/scripts/lib/path-key.mjs +57 -2
- package/runtime/scripts/lib/process-identity.mjs +6 -0
- package/runtime/scripts/lib/read-text.mjs +34 -0
- package/runtime/scripts/lib/read-yaml.mjs +18 -0
- package/runtime/scripts/lib/redact.mjs +161 -0
- package/runtime/scripts/lib/regex.mjs +4 -0
- package/runtime/scripts/lib/same-text.mjs +5 -0
- package/runtime/scripts/lib/secret-patterns.mjs +4 -3
- package/runtime/scripts/lib/sleep-sync.mjs +2 -1
- package/runtime/scripts/lib/sleep.mjs +7 -0
- package/runtime/scripts/lib/sops-envelope.mjs +112 -0
- package/runtime/scripts/lib/source-phrases.mjs +34 -0
- package/runtime/scripts/lib/sqlite.mjs +21 -0
- package/runtime/scripts/lib/stack-services.mjs +7 -31
- package/runtime/scripts/lib/ts-ast.mjs +35 -0
- package/runtime/scripts/lib/walk.mjs +4 -3
- package/scaffold/add-app.mjs +174 -0
- package/scaffold/add-cli-lite.mjs +257 -0
- package/scaffold/add-inbox-lite.mjs +314 -0
- package/scaffold/add-table.mjs +344 -0
- package/scaffold/add.mjs +299 -0
- package/scaffold/app.mjs +358 -69
- package/scaffold/edition-gate.mjs +25 -0
- package/scaffold/image.mjs +19 -0
- package/scaffold/lite-exports.mjs +186 -0
- package/scaffold/service.mjs +32 -26
- package/scaffold/supabase-ports.mjs +26 -0
- package/src/main.mjs +327 -0
- package/sync/cli.mjs +6 -9
- package/sync/format.mjs +1 -1
- package/sync/hygiene.mjs +10 -10
- package/sync/index.mjs +167 -104
- package/sync/managed.mjs +19 -11
- package/sync/sonar-key.mjs +5 -0
- package/templates/app/ci-workflows/github/workflows/ci.yml +14 -14
- package/templates/app/ci-workflows/github/workflows/images.yml +37 -0
- package/templates/app/ci-workflows/sonar-steps.yml +9 -0
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +66 -0
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +31 -0
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +37 -0
- package/templates/app/codegen-lite/scripts/codegen.mjs +32 -0
- package/templates/app/docker-ignore/dockerignore +50 -0
- package/templates/app/gitignore-lite +35 -0
- package/templates/app/hooks/husky/pre-commit +3 -8
- package/templates/app/hooks/husky/pre-push +45 -6
- package/templates/app/package-scripts/core.json +8 -0
- package/templates/app/package-scripts/package.json +3 -10
- package/templates/app/package-scripts-lite/package.json +15 -0
- package/templates/app/quality-config/codecov.yml +15 -3
- package/templates/app/quality-config/sonar-base.properties +4 -0
- package/templates/app/quality-config/sonar-project.properties +1 -4
- package/templates/app/quality-config-lite/sonar-project.properties +5 -0
- package/templates/app/skeleton/.starcistacks/dev/seeds/primary-notes.sql +5 -0
- package/templates/app/skeleton/.starciwork/features/system-health/index.yaml +4 -0
- package/templates/app/skeleton/.starciwork/{features/index.yaml → index.yaml} +2 -2
- package/templates/app/skeleton/README.md +7 -5
- package/templates/app/skeleton-lite/.sops.yaml +3 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +5 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/secrets/.gitkeep +1 -0
- package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +55 -0
- package/templates/app/skeleton-lite/README.md +40 -0
- package/templates/app/skeleton-lite/supabase/config.toml +41 -0
- package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +56 -0
- package/templates/app/skeleton-lite/supabase/seed.sql +0 -0
- package/templates/app/task-graph/turbo.json +23 -0
- package/templates/app/tool-config-lite/prettierignore +2 -0
- package/templates/app/tool-config-lite/prettierrc +1 -0
- package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +38 -0
- package/templates/app/upgrade-full/.starcistacks/dev/README.md +10 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +13 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +3 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +12 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +7 -0
- package/templates/be/common/main-listen.ts.partial +14 -0
- package/templates/be/common/sql-ident.ts.partial +7 -0
- package/templates/be/common/sql-tag.ts.partial +5 -0
- package/templates/be/image/api/Dockerfile +38 -0
- package/templates/be/image/cli/Dockerfile +38 -0
- package/templates/be/image/worker/Dockerfile +36 -0
- package/templates/be/inbox/database-client.ts.tpl +50 -0
- package/templates/be/inbox/index.ts.tpl +2 -0
- package/templates/be/inbox/migration.sql.tpl +29 -0
- package/templates/be/inbox/module-definition.ts.tpl +6 -0
- package/templates/be/inbox/module.ts.tpl +14 -0
- package/templates/be/inbox/options.ts.tpl +2 -0
- package/templates/be/inbox/service.ts.tpl +33 -0
- package/templates/be/inbox/sql.ts.tpl +16 -0
- package/templates/be/inbox/webhook-door.ts.tpl +36 -0
- package/templates/be/patterns/api/application.command.http.ts.tpl +10 -0
- package/templates/be/patterns/api/application.command.ts.tpl +10 -0
- package/templates/be/patterns/api/application.contracts.ts.tpl +11 -0
- package/templates/be/patterns/api/application.handler.http.ts.tpl +22 -0
- package/templates/be/patterns/api/application.handler.ts.tpl +22 -0
- package/templates/be/patterns/api/feature.index.http.ts.tpl +1 -0
- package/templates/be/patterns/api/feature.index.ts.tpl +1 -0
- package/templates/be/patterns/api/feature.module.ts.tpl +6 -0
- package/templates/be/patterns/api/graphql.input.ts.tpl +13 -0
- package/templates/be/patterns/api/graphql.mapper.ts.tpl +9 -0
- package/templates/be/patterns/api/graphql.module.ts.tpl +7 -0
- package/templates/be/patterns/api/graphql.resolver.ts.tpl +27 -0
- package/templates/be/patterns/api/graphql.type.ts.tpl +9 -0
- package/templates/be/patterns/api/http.controller.ts.tpl +27 -0
- package/templates/be/patterns/api/http.mapper.ts.tpl +9 -0
- package/templates/be/patterns/api/http.module.ts.tpl +7 -0
- package/templates/be/patterns/api/http.request.ts.tpl +10 -0
- package/templates/be/patterns/api/http.response.ts.tpl +5 -0
- package/templates/be/patterns/cli/group.cli.spec.ts.tpl +15 -0
- package/templates/be/patterns/cli/group.cli.ts.tpl +11 -0
- package/templates/be/patterns/cli/group.module.ts.tpl +7 -0
- package/templates/be/patterns/cli/sub.run.cli.spec.ts.tpl +17 -0
- package/templates/be/patterns/cli/sub.run.cli.ts.tpl +15 -0
- package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +22 -0
- package/templates/be/patterns/event-bus/platform/event-bus.config.ts.tpl +19 -0
- package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +58 -0
- package/templates/be/patterns/event-bus/platform/event-bus.decorators.ts.tpl +46 -0
- package/templates/be/patterns/event-bus/platform/event-bus.log-events.ts.tpl +12 -0
- package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/event-bus/platform/event-bus.module.ts.tpl +52 -0
- package/templates/be/patterns/event-bus/platform/event-bus.options.ts.tpl +19 -0
- package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +28 -0
- package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +165 -0
- package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +93 -0
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +90 -0
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +58 -0
- package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +136 -0
- package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +56 -0
- package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +272 -0
- package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +128 -0
- package/templates/be/patterns/event-bus/platform/event-transport.port.ts.tpl +180 -0
- package/templates/be/patterns/event-bus/platform/event.policy.spec.ts.tpl +67 -0
- package/templates/be/patterns/event-bus/platform/event.policy.ts.tpl +38 -0
- package/templates/be/patterns/event-bus/platform/index.ts.tpl +11 -0
- package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.spec.ts.tpl +348 -0
- package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.ts.tpl +241 -0
- package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +15 -0
- package/templates/be/patterns/event-bus/platform/persistence/connection.ts.tpl +8 -0
- package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +37 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +11 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +12 -0
- package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +26 -0
- package/templates/be/patterns/jobs/job.index.ts.tpl +1 -0
- package/templates/be/patterns/jobs/job.module.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.processor.ts.tpl +20 -0
- package/templates/be/patterns/jobs/job.queue.module.ts.tpl +20 -0
- package/templates/be/patterns/jobs/job.step.ts.tpl +19 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +31 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.ts.tpl +13 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +150 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +100 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +138 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +69 -0
- package/templates/be/patterns/jobs/platform/jobs.config.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +62 -0
- package/templates/be/patterns/jobs/platform/jobs.decorators.ts.tpl +31 -0
- package/templates/be/patterns/jobs/platform/jobs.error.ts.tpl +22 -0
- package/templates/be/patterns/jobs/platform/jobs.index.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.log-events.ts.tpl +9 -0
- package/templates/be/patterns/jobs/platform/jobs.messages.ts.tpl +15 -0
- package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/jobs/platform/jobs.module.ts.tpl +32 -0
- package/templates/be/patterns/jobs/platform/jobs.options.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.port.ts.tpl +36 -0
- package/templates/be/patterns/jobs/platform/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/jobs/platform/persistence.job.entity.ts.tpl +53 -0
- package/templates/be/patterns/jobs/platform/persistence.jobs.rows.ts.tpl +13 -0
- package/templates/be/patterns/jobs/platform/persistence.jobs.sql.ts.tpl +33 -0
- package/templates/be/patterns/jobs/platform/persistence.migration.ts.tpl +29 -0
- package/templates/be/patterns/outbox/platform/index.ts.tpl +2 -0
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +96 -0
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.ts.tpl +78 -0
- package/templates/be/patterns/outbox/platform/outbox.log-events.ts.tpl +5 -0
- package/templates/be/patterns/projections/migration.ts.tpl +18 -0
- package/templates/be/patterns/projections/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/projections/projection.entity.ts.tpl +9 -0
- package/templates/be/patterns/projections/projection.index.ts.tpl +3 -0
- package/templates/be/patterns/projections/projection.module-definition.ts.tpl +7 -0
- package/templates/be/patterns/projections/projection.module.ts.tpl +18 -0
- package/templates/be/patterns/projections/projection.options.ts.tpl +2 -0
- package/templates/be/patterns/projections/projection.projection.spec.ts.tpl +55 -0
- package/templates/be/patterns/projections/projection.projection.ts.tpl +21 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +142 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +81 -0
- package/templates/be/patterns/queues/platform/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +9 -0
- package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +12 -0
- package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +48 -0
- package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +17 -0
- package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +128 -0
- package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +48 -0
- package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +115 -0
- package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +91 -0
- package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +45 -0
- package/templates/be/patterns/queues/platform/queue.config.ts.tpl +15 -0
- package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +31 -0
- package/templates/be/patterns/queues/platform/queue.decorators.ts.tpl +45 -0
- package/templates/be/patterns/queues/platform/queue.index.ts.tpl +7 -0
- package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +5 -0
- package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/queues/platform/queue.module.ts.tpl +62 -0
- package/templates/be/patterns/queues/platform/queue.options.ts.tpl +22 -0
- package/templates/be/patterns/queues/platform/queue.policy.spec.ts.tpl +19 -0
- package/templates/be/patterns/queues/platform/queue.policy.ts.tpl +11 -0
- package/templates/be/patterns/queues/platform/queue.port.ts.tpl +14 -0
- package/templates/be/patterns/queues/queue.index.ts.tpl +3 -0
- package/templates/be/patterns/queues/queue.module.ts.tpl +6 -0
- package/templates/be/patterns/queues/queue.queue.ts.tpl +23 -0
- package/templates/be/patterns/reactors/application.command.ts.tpl +10 -0
- package/templates/be/patterns/reactors/application.contracts.ts.tpl +12 -0
- package/templates/be/patterns/reactors/application.handler.ts.tpl +22 -0
- package/templates/be/patterns/reactors/consumer.ts.tpl +19 -0
- package/templates/be/patterns/reactors/message.module.ts.tpl +20 -0
- package/templates/be/patterns/reactors/reactor.index.ts.tpl +1 -0
- package/templates/be/patterns/reactors/reactor.module.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.index.ts.tpl +1 -0
- package/templates/be/patterns/realtime/channel.input.ts.tpl +12 -0
- package/templates/be/patterns/realtime/channel.subscription.spec.ts.tpl +51 -0
- package/templates/be/patterns/realtime/channel.subscription.ts.tpl +32 -0
- package/templates/be/patterns/realtime/channel.type.ts.tpl +9 -0
- package/templates/be/patterns/saga/saga.compensate.command.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.compensate.contracts.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.compensate.handler.ts.tpl +22 -0
- package/templates/be/patterns/saga/saga.compensation.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.complete.command.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.complete.contracts.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.complete.handler.ts.tpl +22 -0
- package/templates/be/patterns/saga/saga.done.consumer.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.failed.consumer.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.index.ts.tpl +1 -0
- package/templates/be/patterns/saga/saga.message.module.ts.tpl +23 -0
- package/templates/be/patterns/saga/saga.module.ts.tpl +20 -0
- package/templates/be/patterns/saga/saga.service.spec.ts.tpl +70 -0
- package/templates/be/patterns/saga/saga.service.ts.tpl +44 -0
- package/templates/be/patterns/saga/saga.state.ts.tpl +14 -0
- package/templates/be/patterns/saga/saga.step.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.undo.command.ts.tpl +10 -0
- package/templates/be/patterns/saga/saga.undo.contracts.ts.tpl +5 -0
- package/templates/be/patterns/saga/saga.undo.handler.ts.tpl +21 -0
- package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +72 -0
- package/templates/be/patterns/webhooks/webhook.door.ts.tpl +36 -0
- package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +6 -0
- package/templates/be/patterns/webhooks/webhook.index.ts.tpl +1 -0
- package/templates/be/patterns/webhooks/webhook.request.ts.tpl +9 -0
- package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +3 -0
- package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -2
- package/templates/be/skeleton/apps/__app__/src/main.ts +7 -15
- package/templates/be/skeleton/apps/cli/src/app.module.ts +30 -0
- package/templates/be/skeleton/apps/cli/src/cli.options.ts +22 -0
- package/templates/be/skeleton/apps/cli/src/main.ts +24 -0
- package/templates/be/skeleton/src/features/cli/cli.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/index.ts +1 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.ts +15 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.ts +18 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.cli.ts +15 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +33 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.ts +34 -0
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +13 -0
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +40 -0
- package/templates/be/skeleton/src/modules/domain/identity/messages/identity.messages.ts +1 -1
- package/templates/be/skeleton/src/modules/domain/note/errors/note.error.ts +16 -0
- package/templates/be/skeleton/src/modules/domain/note/index.ts +3 -0
- package/templates/be/skeleton/src/modules/domain/note/note.contracts.ts +19 -0
- package/templates/be/skeleton/src/modules/domain/note/note.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/domain/note/note.module.ts +19 -0
- package/templates/be/skeleton/src/modules/domain/note/note.options.ts +2 -0
- package/templates/be/skeleton/src/modules/domain/note/note.service.spec.ts +76 -0
- package/templates/be/skeleton/src/modules/domain/note/note.service.ts +37 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/connection.ts +8 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/entities/note.entity.ts +17 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/migrations/1790000000000-init-note.ts +22 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/note.rows.ts +17 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/note.sql.ts +4 -0
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +20 -0
- package/templates/be/skeleton/src/modules/platform/config/index.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +18 -0
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +41 -0
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.ts +17 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +13 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module.ts +77 -0
- package/templates/be/skeleton/src/modules/platform/database/database.options.ts +30 -0
- package/templates/be/skeleton/src/modules/platform/database/database.port.ts +65 -0
- package/templates/be/skeleton/src/modules/platform/database/database.sql.ts +47 -0
- package/templates/be/skeleton/src/modules/platform/database/errors/database.error.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/database/index.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/database/migrate-connections.client.ts +30 -0
- package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.spec.ts +84 -0
- package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.ts +23 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.config.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.connection.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +10 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +108 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.ts +75 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.spec.ts +88 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.ts +29 -0
- package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +48 -0
- package/templates/be/skeleton/src/modules/platform/errors/messages/errors.messages.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +8 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.decorators.ts +8 -0
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +14 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +10 -2
- package/templates/be/skeleton/src/modules/platform/http-security/origin.guard.spec.ts +63 -0
- package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +108 -0
- package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.spec.ts +39 -0
- package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.ts +25 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +172 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.ts +66 -0
- package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +3 -1
- package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +52 -0
- package/templates/be/skeleton-lite/apps/api/Dockerfile +37 -0
- package/templates/be/skeleton-lite/apps/api/src/api.options.ts +16 -0
- package/templates/be/skeleton-lite/apps/api/src/app.module.ts +81 -0
- package/templates/be/skeleton-lite/apps/api/src/main.ts +34 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +14 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +50 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +19 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +7 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +6 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +19 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +10 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +8 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +17 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +32 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +54 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +23 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +10 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +49 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +21 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +11 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +28 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +25 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +9 -0
- package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +5 -0
- package/templates/be/table/error.ts.tpl +16 -0
- package/templates/be/table/index.ts.tpl +2 -0
- package/templates/be/table/migration.sql.tpl +51 -0
- package/templates/be/table/module-definition.ts.tpl +7 -0
- package/templates/be/table/module.ts.tpl +14 -0
- package/templates/be/table/options.ts.tpl +2 -0
- package/templates/be/table/rows.ts.tpl +4 -0
- package/templates/be/table/service.ts.tpl +23 -0
- package/templates/be/table/sql.ts.tpl +4 -0
- package/templates/be/tool-config/jest.config.js +3 -1
- package/templates/be/upgrade-full/apps/cli/src/app.module.ts +14 -0
- package/templates/be/upgrade-full/apps/cli/src/main.ts +26 -0
- package/templates/be/upgrade-full/src/features/cli/cli.module.ts +6 -0
- package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +23 -0
- package/templates/common/gitignore.base +1 -2
- package/templates/fe/app/package.json.tpl +1 -0
- package/templates/fe/app/tsconfig.json +12 -0
- package/templates/fe/common/app-layout.tsx.partial +8 -0
- package/templates/fe/common/site-shell.tsx.partial +9 -0
- package/templates/fe/image/next/Dockerfile +42 -0
- package/templates/fe/skeleton/apps/app/next.config.ts +23 -0
- package/templates/fe/skeleton/apps/app/postcss.config.mjs +7 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/error.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/[locale]/layout.tsx +22 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/loading.tsx +2 -2
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/not-found.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/global-error.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/globals.css +10 -0
- package/templates/fe/skeleton/apps/app/src/features/layouts/AppLayout/index.tsx +18 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/component.tsx +19 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/index.tsx +11 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppGlobalErrorPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/component.tsx +10 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +15 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/index.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +28 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/request.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/modules/routes/index.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/proxy.ts +1 -0
- package/templates/fe/skeleton/apps/{__app__ → landing}/next.config.ts +4 -2
- package/templates/fe/skeleton/apps/landing/postcss.config.mjs +7 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/error.tsx +10 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/layout.tsx +22 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/loading.tsx +6 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/not-found.tsx +6 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton/apps/landing/src/app/global-error.tsx +10 -0
- package/templates/fe/skeleton/apps/landing/src/app/globals.css +10 -0
- package/templates/fe/skeleton/apps/landing/src/features/layouts/LandingLayout/index.tsx +24 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/component.tsx +18 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/index.tsx +11 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingGlobalErrorPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/component.tsx +24 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/landing/src/modules/config/index.ts +12 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/index.ts +7 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/vi.json +31 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/request.ts +4 -0
- package/templates/fe/skeleton/apps/landing/src/modules/routes/index.ts +4 -0
- package/templates/fe/skeleton/apps/landing/src/proxy.ts +1 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +49 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +24 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +20 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/branches/Providers/index.tsx +23 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/ErrorNotice/index.tsx +14 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/GlobalErrorNotice/index.tsx +25 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/LoadingNotice/index.tsx +9 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/LocaleShell/index.tsx +21 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +19 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/classNames.ts +4 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/index.tsx +19 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +6 -0
- package/templates/fe/skeleton-lite/apps/web/next.config.ts +22 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/error.tsx +10 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +37 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/loading.tsx +6 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/not-found.tsx +6 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/providers.tsx +26 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/auth/callback/route.ts +24 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/global-error.tsx +10 -0
- package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/src/app/globals.css +1 -1
- package/templates/fe/skeleton-lite/apps/web/src/app/health/live/route.ts +5 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/component.tsx +29 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/index.tsx +41 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/component.tsx +17 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/index.tsx +38 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/ErrorNotice/index.tsx +13 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/GlobalErrorNotice/index.tsx +24 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/LoadingNotice/index.tsx +7 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +18 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/classNames.ts +4 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/index.tsx +13 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/layouts/AppLayout/index.tsx +31 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/component.tsx +12 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/index.tsx +10 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppGlobalErrorPage/index.tsx +15 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +30 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/brand/brand.css +20 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/brand/index.ts +2 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +20 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/read-session.ts +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-in.ts +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-out.ts +17 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/browser.ts +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/index.ts +3 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/outcome.ts +59 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/principal.ts +29 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/server.ts +70 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/validation/validation.mapper.ts +50 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +8 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +48 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +16 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +7 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/safe-next-path.ts +26 -0
- package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +43 -0
- package/templates/fe/table/read.ts.tpl +16 -0
- package/templates/fe/table/write.ts.tpl +16 -0
- package/upgrade/check.mjs +137 -0
- package/upgrade/index.mjs +524 -0
- package/bin/hfs.mjs +0 -233
- package/runtime/scripts/api/fs/rmdir-link.mjs +0 -12
- package/runtime/scripts/lib/test-secrets.mjs +0 -116
- package/templates/fe/skeleton/apps/__app__/src/app/[locale]/layout.tsx +0 -20
- package/templates/fe/skeleton/apps/__app__/src/app/[locale]/page.tsx +0 -9
- package/templates/fe/skeleton/apps/__app__/src/components/composites/FailureScreen/index.tsx +0 -28
- package/templates/fe/skeleton/apps/__app__/src/features/layouts/LocaleShell/index.tsx +0 -35
- package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/component.tsx +0 -19
- package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/index.tsx +0 -11
- package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/component.tsx +0 -24
- package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/index.tsx +0 -14
- package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/component.tsx +0 -21
- package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/index.tsx +0 -15
- package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/component.tsx +0 -23
- package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/index.tsx +0 -8
- package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/component.tsx +0 -28
- package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/index.tsx +0 -8
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/config.ts +0 -8
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/index.ts +0 -2
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/messages/vi.json +0 -25
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/request.ts +0 -19
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/routing.ts +0 -9
- package/templates/fe/skeleton/apps/__app__/src/modules/routes/index.ts +0 -4
- package/templates/fe/skeleton/apps/__app__/src/proxy.ts +0 -10
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.contracts.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.handler.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.query.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/index.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/system-health.module.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/live.controller.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/system-health-http.module.ts +0 -0
- /package/templates/fe/skeleton/apps/{__app__ → app}/src/app/health/live/route.ts +0 -0
- /package/templates/fe/skeleton/apps/{__app__ → app}/src/modules/config/index.ts +0 -0
- /package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/postcss.config.mjs +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Provider receipt SQL participates in the machine writer's existing fenced transactions.
|
|
2
|
+
|
|
3
|
+
export function providerReservationMethods({ need, parse, toJson, hex }) {
|
|
4
|
+
// Provider/account slots are shared by all five agent roles. A clock timeout is not exit evidence.
|
|
5
|
+
const providerReservationRow = (row) => row ? { id: row.id, fence: row.fence, attemptId: row.attempt_id,
|
|
6
|
+
provider: row.provider, account: row.account, model: row.model, role: row.role, state: row.state,
|
|
7
|
+
slots: row.slots, amountUnit: 'concurrent-launch', maxParallel: row.max_parallel,
|
|
8
|
+
handle: row.handle, pid: row.pid, launchIdentity: row.launch_identity, hostRequestId: row.host_request_id, createdAt: row.created_at, updatedAt: row.updated_at,
|
|
9
|
+
scope: parse(row.scope_json), estimate: parse(row.estimate_json), quota: parse(row.quota_json),
|
|
10
|
+
override: parse(row.override_json), releasedAt: row.released_at, proof: parse(row.proof_json) } : null;
|
|
11
|
+
function providerReservations(m, { provider = null, account = null, activeOnly = false } = {}) {
|
|
12
|
+
const where = [], args = [];
|
|
13
|
+
if (provider !== null) { where.push('provider=?'); args.push(provider); }
|
|
14
|
+
if (account !== null) { where.push('account=?'); args.push(account); }
|
|
15
|
+
if (activeOnly) where.push("state<>'released'");
|
|
16
|
+
return m.db.prepare(`SELECT * FROM provider_reservations${where.length ? ` WHERE ${where.join(' AND ')}` : ''} ORDER BY fence`).all(...args).map(providerReservationRow);
|
|
17
|
+
}
|
|
18
|
+
function providerReservationUsage(m, { provider, account = 'default' } = {}) {
|
|
19
|
+
const reservations = providerReservations(m, { provider, account, activeOnly: true });
|
|
20
|
+
return { running: reservations.length, reservations, observed: true };
|
|
21
|
+
}
|
|
22
|
+
/** Atomic last-slot admission. Replays preserve the original receipt; changed attempt meaning refuses. */
|
|
23
|
+
function reserveProvider(m, { provider, account = 'default', attemptId, role, model, maxParallel, scope = null, quota = null, estimate = null, override = null } = {}) {
|
|
24
|
+
need([provider, account, attemptId, model].every((value) => typeof value === 'string' && value.trim()), 'provider reservation needs provider, account, attemptId and concrete model');
|
|
25
|
+
need(typeof role === 'string' && role.trim(), 'provider reservation needs one agent role'); // The DDL owns the allowed role domain.
|
|
26
|
+
need(Number.isInteger(maxParallel) && maxParallel >= 0, 'provider reservation needs nonnegative integer maxParallel');
|
|
27
|
+
return m.transaction((db) => {
|
|
28
|
+
const existing = db.prepare('SELECT * FROM provider_reservations WHERE attempt_id=?').get(attemptId);
|
|
29
|
+
if (existing) {
|
|
30
|
+
if (existing.provider !== provider || existing.account !== account || existing.model !== model || existing.role !== role || existing.scope_json !== toJson(scope))
|
|
31
|
+
return { ok: false, reason: 'attempt-conflict', reservation: providerReservationRow(existing) };
|
|
32
|
+
return { ok: existing.state !== 'released', reason: existing.state === 'released' ? 'attempt-released' : 'reserved', reused: true, reservation: providerReservationRow(existing) };
|
|
33
|
+
}
|
|
34
|
+
const running = Number(db.prepare("SELECT count(*) n FROM provider_reservations WHERE provider=? AND account=? AND state<>'released'").get(provider, account).n);
|
|
35
|
+
if (running >= maxParallel) return { ok: false, reason: 'capacity', running, maxParallel };
|
|
36
|
+
const id = hex(16), at = m.now();
|
|
37
|
+
const result = db.prepare("INSERT INTO provider_reservations(id,attempt_id,provider,account,model,role,scope_json,state,max_parallel,quota_json,estimate_json,override_json,created_at,updated_at) VALUES(?,?,?,?,?,?,?,'reserved',?,?,?,?,?,?)")
|
|
38
|
+
.run(id, attemptId, provider, account, model, role, toJson(scope), maxParallel, toJson(quota), toJson(estimate), toJson(override), at, at);
|
|
39
|
+
db.prepare("INSERT INTO provider_reservation_events(reservation_id,at,from_state,to_state) VALUES(?,?,NULL,'reserved')").run(id, at);
|
|
40
|
+
return { ok: true, reason: 'reserved', reused: false, reservation: providerReservationRow(db.prepare('SELECT * FROM provider_reservations WHERE fence=?').get(result.lastInsertRowid)) };
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const fencedProviderRow = (db, { id, fence, attemptId } = {}) => {
|
|
44
|
+
const row = db.prepare('SELECT * FROM provider_reservations WHERE id=? AND fence=?').get(id ?? '', fence ?? -1);
|
|
45
|
+
return row && (attemptId === undefined || row.attempt_id === attemptId) ? row : null;
|
|
46
|
+
};
|
|
47
|
+
/** Observe launch progress under its original fence; unknown still occupies its slot. */
|
|
48
|
+
function markProviderReservation(m, { id, fence, attemptId, provider, account, model, role, state, launchIdentity = null, hostRequestId = null, handle = null, pid = null } = {}) {
|
|
49
|
+
need(['launching', 'live', 'unknown'].includes(state), 'provider reservation observation needs launching, live or unknown');
|
|
50
|
+
return m.transaction((db) => {
|
|
51
|
+
const row = fencedProviderRow(db, { id, fence, attemptId });
|
|
52
|
+
if (!row) return { ok: false, reason: 'fenced' };
|
|
53
|
+
if (Object.entries({ provider, account, model, role }).some(([key, value]) => value !== undefined && row[key] !== value)) return { ok: false, reason: 'identity-conflict' };
|
|
54
|
+
if (row.state === 'released') return { ok: false, reason: 'released' };
|
|
55
|
+
if (state === 'launching' && (typeof launchIdentity !== 'string' || !launchIdentity.trim())) return { ok: false, reason: 'launch-identity-required' };
|
|
56
|
+
if (launchIdentity !== null && row.launch_identity && row.launch_identity !== launchIdentity) return { ok: false, reason: 'launch-identity-conflict', reservation: providerReservationRow(row) };
|
|
57
|
+
if (hostRequestId !== null && row.host_request_id && row.host_request_id !== hostRequestId) return { ok: false, reason: 'host-request-conflict', reservation: providerReservationRow(row) };
|
|
58
|
+
if (state === 'launching' && row.state !== 'reserved' && row.state !== 'launching') return { ok: false, reason: 'state-regression' };
|
|
59
|
+
if ((row.handle && handle && row.handle !== handle) || (row.pid && pid && row.pid !== pid)) return { ok: false, reason: 'identity-conflict' };
|
|
60
|
+
const at = m.now();
|
|
61
|
+
db.prepare('UPDATE provider_reservations SET state=?,launch_identity=coalesce(launch_identity,?),host_request_id=coalesce(host_request_id,?),handle=coalesce(handle,?),pid=coalesce(pid,?),updated_at=? WHERE id=? AND fence=?')
|
|
62
|
+
.run(state, launchIdentity, hostRequestId, handle, pid, at, id, fence);
|
|
63
|
+
if (row.state !== state) db.prepare('INSERT INTO provider_reservation_events(reservation_id,at,from_state,to_state) VALUES(?,?,?,?)').run(id, at, row.state, state);
|
|
64
|
+
return { ok: true, reservation: providerReservationRow(db.prepare('SELECT * FROM provider_reservations WHERE id=?').get(id)) };
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/** Only the launcher/reconciler's definitive matching exit/no-effect receipt releases capacity. */
|
|
68
|
+
function releaseProviderReservation(m, { id, fence, attemptId, proof } = {}) {
|
|
69
|
+
return m.transaction((db) => {
|
|
70
|
+
const row = fencedProviderRow(db, { id, fence, attemptId });
|
|
71
|
+
if (!row) return { ok: false, reason: 'fenced' };
|
|
72
|
+
if (row.state === 'released') return { ok: true, reused: true, reservation: providerReservationRow(row) };
|
|
73
|
+
const affirmation = proof?.hostAffirmation;
|
|
74
|
+
const reply = affirmation?.receipt, result = reply?.result;
|
|
75
|
+
const residual = result?.residualResources ?? result?.worker?.residualResources;
|
|
76
|
+
const identities = [result, result?.worker, result?.terminal].filter((value) => value && typeof value === 'object');
|
|
77
|
+
const hostNoEffect = reply && typeof reply === 'object' && !['unknown', 'outcome_unknown'].includes(result?.state)
|
|
78
|
+
&& !['unknown', 'outcome_unknown'].includes(result?.worker?.state)
|
|
79
|
+
&& !(residual && typeof residual === 'object' && Object.keys(residual).length > 0)
|
|
80
|
+
&& !identities.some((value) => ['agentTerminalHandle', 'terminalHandle', 'handle', 'pid', 'processId', 'dispatchId'].some((key) => value[key] !== undefined && value[key] !== null && value[key] !== ''))
|
|
81
|
+
&& (result?.failedStage !== undefined || result?.stage !== undefined || typeof reply.error?.code === 'string' && reply.error.code.trim());
|
|
82
|
+
const resolvedUnknown = row.state === 'unknown' && row.launch_identity && proof?.launchIdentity === row.launch_identity
|
|
83
|
+
&& row.host_request_id && affirmation?.requestId === row.host_request_id && affirmation.kind === 'worker-start-replay'
|
|
84
|
+
&& affirmation.replayed === true && affirmation.outcome === 'failed' && affirmation.effectState === 'none'
|
|
85
|
+
&& hostNoEffect;
|
|
86
|
+
const noEffect = proof?.kind === 'failed-before-launch' && proof.confirmed === true && !row.handle && !row.pid
|
|
87
|
+
&& (['reserved', 'launching'].includes(row.state) || resolvedUnknown);
|
|
88
|
+
const terminalEnded = row.handle && proof?.kind === 'closed' && proof.handle === row.handle
|
|
89
|
+
&& ['gone', 'disconnected'].includes(proof.terminalProof) && ['none', 'stopped'].includes(proof.processVerdict);
|
|
90
|
+
const processEnded = !row.handle && row.pid && proof?.kind === 'process-exited' && proof.pid === row.pid;
|
|
91
|
+
const ended = proof?.confirmed === true && (terminalEnded || processEnded)
|
|
92
|
+
&& (!row.pid || proof.pid == null || proof.pid === row.pid);
|
|
93
|
+
if (!noEffect && !ended) return { ok: false, reason: 'exit-unproven', reservation: providerReservationRow(row) };
|
|
94
|
+
const at = m.now();
|
|
95
|
+
db.prepare("UPDATE provider_reservations SET state='released',released_at=?,updated_at=?,proof_json=? WHERE id=? AND fence=?").run(at, at, toJson(proof), id, fence);
|
|
96
|
+
db.prepare("INSERT INTO provider_reservation_events(reservation_id,at,from_state,to_state,proof_json) VALUES(?,?,?,'released',?)").run(id, at, row.state, toJson(proof));
|
|
97
|
+
return { ok: true, reused: false, reservation: providerReservationRow(db.prepare('SELECT * FROM provider_reservations WHERE id=?').get(id)) };
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return { reserveProvider, providerReservations, providerReservationUsage, markProviderReservation, releaseProviderReservation };
|
|
101
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// digest.mjs — the one SHA-256 the runtime hashes with. A leaf: every file's integrity digest,
|
|
2
|
+
// every ledger input ref and every stamped asset is this function, so a byte stream and a file
|
|
3
|
+
// never disagree about what their digest is.
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
|
|
7
|
+
/** The lowercase hex SHA-256 of `value` (string, Buffer or TypedArray). */
|
|
8
|
+
export const sha256 = (value) => createHash('sha256').update(value).digest('hex');
|
|
9
|
+
/** The SHA-256 of the file's exact bytes; throws when the file cannot be read. */
|
|
10
|
+
export function sha256File(file){
|
|
11
|
+
// A numeric descriptor belongs to the caller; positional reads preserve its offset.
|
|
12
|
+
const owned=typeof file!=='number',fd=owned?fs.openSync(file,'r'):file;
|
|
13
|
+
const hash=createHash('sha256'),buffer=Buffer.alloc(1024*1024);
|
|
14
|
+
try{let at=0,n;while((n=fs.readSync(fd,buffer,0,buffer.length,at))>0){hash.update(buffer.subarray(0,n));at+=n;}return hash.digest('hex');}
|
|
15
|
+
finally{if(owned)fs.closeSync(fd);}
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import {isPlainObject as plain} from './plain-object.mjs';
|
|
3
|
+
/** The one `Invalid config.yaml:` raiser every section validator shares: bad('<rest>') throws it. */
|
|
4
|
+
export const invalid=section=>message=>{throw Error(`Invalid config.yaml: ${section}${message}`);};
|
|
5
|
+
|
|
6
|
+
/** The host roots the owner may relocate (config.yaml `roots`): the archive root and the lanes root. */
|
|
7
|
+
const ROOT_KEYS=Object.freeze(['archive','lanes']);
|
|
8
|
+
/** config.yaml `roots` - {archive?, lanes?}: absolute directories, or null; an absent key means <starciLocalRoot>/archive and <starciLocalRoot>/lanes. */
|
|
9
|
+
export function validateRoots(roots){
|
|
10
|
+
if(roots===null)return;
|
|
11
|
+
const bad=invalid('roots');
|
|
12
|
+
if(!plain(roots))bad(` must be {archive?: <absolute directory>, lanes?: <absolute directory>} or null.`);
|
|
13
|
+
for(const key of Object.keys(roots))if(!ROOT_KEYS.includes(key))bad(` has unknown key ${key} (allowed: ${ROOT_KEYS.join(', ')}).`);
|
|
14
|
+
for(const key of ROOT_KEYS)if(roots[key]!==undefined&&roots[key]!==null&&!(typeof roots[key]==='string'&&roots[key].trim()&&path.isAbsolute(roots[key])))bad(`.${key} must be an absolute directory path or null.`);
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {isPlainObject as plain} from './plain-object.mjs';
|
|
2
|
+
import {invalid} from './invalid-config.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* config.yaml `orca` — the owner's Orca app settings the runtime must know. maxWorkerDepth is the deepest worker Orca
|
|
6
|
+
* lets start under the owner's chat (chat = depth 0, a Kernel or the [Supervisor] 1, an op or a [Worker] 2, the draw
|
|
7
|
+
* critic 3); a deeper worker-start is refused by Orca with nested_worker_depth_exceeded. Orca exposes no read of that
|
|
8
|
+
* setting, so it is declared here and MUST equal the Orca app setting: scripts/agent/lib.mjs spawnAgent refuses a launch
|
|
9
|
+
* deeper than it before worker-start (worker-depth-exceeded), and `start --check` with STARCI_ORCA_LIVE=1 compares it with
|
|
10
|
+
* a measured probe (scripts/agent/depth-probe.mjs).
|
|
11
|
+
*/
|
|
12
|
+
export const ORCA_DEFAULTS=Object.freeze({maxWorkerDepth:4});
|
|
13
|
+
export const MAX_WORKER_DEPTH_CEILING=16;
|
|
14
|
+
export function validateOrca(orca){
|
|
15
|
+
if(orca===null)return;
|
|
16
|
+
const bad=invalid('orca');
|
|
17
|
+
if(!plain(orca))bad(' must be {maxWorkerDepth?} or null.');
|
|
18
|
+
for(const key of Object.keys(orca))if(key!=='maxWorkerDepth')bad(` has unknown key ${key} (allowed: maxWorkerDepth).`);
|
|
19
|
+
const v=orca.maxWorkerDepth;
|
|
20
|
+
if(v!==undefined&&v!==null&&!(Number.isInteger(v)&&v>=1&&v<=MAX_WORKER_DEPTH_CEILING))bad(`.maxWorkerDepth must be an integer from 1 to ${MAX_WORKER_DEPTH_CEILING} equal to the Orca app's worker depth setting (default ${ORCA_DEFAULTS.maxWorkerDepth}), or null.`);
|
|
21
|
+
}
|
|
22
|
+
/** The owner's Orca settings: {maxWorkerDepth, source: 'orca'|'default'}. An absent or null block or key is the default. */
|
|
23
|
+
export function orcaSettings(config){
|
|
24
|
+
if(config?.orca!==undefined)validateOrca(config.orca);
|
|
25
|
+
const value=plain(config?.orca)?config.orca.maxWorkerDepth:null;
|
|
26
|
+
return Number.isInteger(value)?{maxWorkerDepth:value,source:'orca'}:{maxWorkerDepth:ORCA_DEFAULTS.maxWorkerDepth,source:'default'};
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// refuse.mjs — the refusal Error every verb raises: a message plus a stable `code` (and any extra fields the
|
|
2
|
+
// caller attaches). `refuse` builds it, `fail` throws it, `need` throws it when a required condition is false.
|
|
3
|
+
|
|
4
|
+
/** An Error carrying `code` and `extra` fields; callers `throw` it or hand it to a result row. */
|
|
5
|
+
export const refuse = (message, code, extra = {}) => Object.assign(new Error(message), { code, ...extra });
|
|
6
|
+
|
|
7
|
+
/** Throws the refusal `refuse` builds — the spelling used where refusing is the whole statement. */
|
|
8
|
+
export const fail = (message, code, extra = {}) => { throw refuse(message, code, extra); };
|
|
9
|
+
|
|
10
|
+
/** Throws `refuse(message, code)` when `ok` is falsy — the assertion spelling of a refusal. */
|
|
11
|
+
export const need = (ok, message, code) => { if (!ok) throw refuse(message, code); };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
/** The host-local credential filename, resolved only against a verified runtime main root. */
|
|
5
|
+
export const SECRET_ENV_FILE='secret.env';
|
|
6
|
+
/** The configured credential variable grammar shared by validation and secret resolution. */
|
|
7
|
+
export const ENV_NAME=/^[A-Z_][A-Z0-9_]{0,63}$/;
|
|
8
|
+
export const CREDENTIAL_FILE_MAX_BYTES=1024*1024;
|
|
9
|
+
const resolvedValues = new Set();
|
|
10
|
+
const remember = value => {
|
|
11
|
+
if (typeof value === 'string' && value.length >= 6) resolvedValues.add(value);
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Filter credentials resolved by this process; the values never leave their resolution owner. */
|
|
16
|
+
export function redactResolvedSecrets(text) {
|
|
17
|
+
let clean = text;
|
|
18
|
+
for (const value of resolvedValues) if (clean.includes(value)) clean = clean.split(value).join('[redacted:resolved-secret]');
|
|
19
|
+
return clean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Check lexical availability only; blank and conventional template markers never prove provider validity. */
|
|
23
|
+
export function credentialPresent(value){
|
|
24
|
+
if(typeof value!=='string'||!value.trim())return false;
|
|
25
|
+
return !/^(?:CHANGE_ME|REPLACE_ME|PLACEHOLDER|TODO|<[^>]*>|YOUR_[A-Z0-9_]+)$/i.test(value.trim());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Read one configured credential file with a finite byte budget; no effects beyond the read. */
|
|
29
|
+
export function readSecretBytes(file){
|
|
30
|
+
const before=fs.lstatSync(file);
|
|
31
|
+
if(!before.isFile()||before.isSymbolicLink())throw new Error('credential file must be a regular file');
|
|
32
|
+
if(before.size>CREDENTIAL_FILE_MAX_BYTES)throw new Error('credential file exceeds the byte budget');
|
|
33
|
+
const fd=fs.openSync(file,fs.constants.O_RDONLY|(fs.constants.O_NOFOLLOW??0));
|
|
34
|
+
let bytes;
|
|
35
|
+
try{
|
|
36
|
+
const stat=fs.fstatSync(fd);
|
|
37
|
+
if(!stat.isFile()||stat.dev!==before.dev||stat.ino!==before.ino)throw new Error('credential file changed during resolution');
|
|
38
|
+
bytes=Buffer.alloc(CREDENTIAL_FILE_MAX_BYTES+1);
|
|
39
|
+
let count=0;
|
|
40
|
+
while(count<bytes.length){const n=fs.readSync(fd,bytes,count,bytes.length-count,null);if(n===0)break;count+=n;}
|
|
41
|
+
if(count>CREDENTIAL_FILE_MAX_BYTES)throw new Error('credential file exceeds the byte budget');
|
|
42
|
+
return bytes.subarray(0,count);
|
|
43
|
+
}catch(error){bytes?.fill(0);throw error;}finally{fs.closeSync(fd);}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const readCredentialFile = file => { const bytes=readSecretBytes(file); try{return bytes.toString('utf8');}finally{bytes.fill(0);} };
|
|
47
|
+
|
|
48
|
+
/** Parse a dotenv file (KEY=VALUE lines, # comments, optional export/quotes). An absent file is {}. */
|
|
49
|
+
export function readDotenv(file){
|
|
50
|
+
let text='';try{text=readCredentialFile(file);}catch(error){if(error?.code==='ENOENT')return {};throw error;}
|
|
51
|
+
const out={};
|
|
52
|
+
for(const line of text.split(/\r?\n/)){
|
|
53
|
+
const m=line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/);
|
|
54
|
+
if(!m)continue;
|
|
55
|
+
let value=m[2];
|
|
56
|
+
if(value.length>=2&&(value[0]==='"'||value[0]==="'")&&value.at(-1)===value[0])value=value.slice(1,-1);
|
|
57
|
+
out[m[1]]=value;
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Resolve a configured variable or its supported NAME_FILE custody pointer. An explicitly supplied
|
|
64
|
+
* blank variable disables the value; it must not resurrect a file value. Never print the result.
|
|
65
|
+
*/
|
|
66
|
+
export function connectorSecret(name,env=process.env){
|
|
67
|
+
if(typeof name!=='string'||!ENV_NAME.test(name))return null;
|
|
68
|
+
if(Object.hasOwn(env,name))return typeof env[name]==='string'?remember(env[name].trim()||null):null;
|
|
69
|
+
const pointer=typeof env[`${name}_FILE`]==='string'?env[`${name}_FILE`].trim():'';
|
|
70
|
+
if(!pointer)return null;
|
|
71
|
+
try{const value=readCredentialFile(pointer).trim();return remember(value||null);}catch{return null;}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Load the verified runtime main's local credentials below the actual environment without mutating
|
|
76
|
+
* either input. The caller owns repository identity; this base-tier reader never infers a root from cwd.
|
|
77
|
+
* Absence is allowed so the action-specific gate can name only the credentials that action requires.
|
|
78
|
+
*/
|
|
79
|
+
export function secretEnv(verifiedRuntimeRoot,env=process.env){
|
|
80
|
+
if(typeof verifiedRuntimeRoot!=='string'||!path.isAbsolute(verifiedRuntimeRoot))
|
|
81
|
+
throw new TypeError('secretEnv requires an absolute verified runtime root');
|
|
82
|
+
if(env===null||typeof env!=='object'||Array.isArray(env))throw new TypeError('secretEnv requires an environment mapping');
|
|
83
|
+
const root=fs.lstatSync(verifiedRuntimeRoot);
|
|
84
|
+
if(!root.isDirectory()||root.isSymbolicLink())throw new Error('secretEnv runtime root must be a regular directory');
|
|
85
|
+
const file=path.join(verifiedRuntimeRoot,SECRET_ENV_FILE);
|
|
86
|
+
let stat;
|
|
87
|
+
try{stat=fs.lstatSync(file);}catch(error){if(error?.code==='ENOENT')return {...env};throw error;}
|
|
88
|
+
if(!stat.isFile()||stat.isSymbolicLink())throw new Error('secret.env must be a regular file');
|
|
89
|
+
const local = readDotenv(file);
|
|
90
|
+
const resolved = {...local,...env};
|
|
91
|
+
for (const name of Object.keys(local)) if (typeof resolved[name] === 'string') remember(resolved[name]);
|
|
92
|
+
return resolved;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Select a supplied age identity without inventing custody or running a key tool. Inline execution awaits its owned isolation capability. */
|
|
96
|
+
export function sopsIdentityEnv(env,{identity=null,required=false,platform=process.platform}={}){
|
|
97
|
+
const refuse=(reason,message)=>{
|
|
98
|
+
const error=new Error(`SOPS identity [${reason}]: ${message}`);
|
|
99
|
+
error.name='SopsIdentityRefusal';error.identityRefusal=reason;
|
|
100
|
+
return {mode:'refused',env:null,error};
|
|
101
|
+
};
|
|
102
|
+
if(!env||typeof env!=='object'||Array.isArray(env))return refuse('invalid-environment','an environment mapping is required');
|
|
103
|
+
const names=name=>Object.keys(env).filter(key=>platform==='win32'?key.toUpperCase()===name:key===name);
|
|
104
|
+
const inline=names('SOPS_AGE_KEY'),files=names('SOPS_AGE_KEY_FILE');
|
|
105
|
+
if(inline.length>1||files.length>1)return refuse('ambiguous-environment','multiple Windows aliases select an age identity');
|
|
106
|
+
if(inline.length){
|
|
107
|
+
const name=inline[0];
|
|
108
|
+
if(!credentialPresent(env[name]))return refuse('disabled-inline','SOPS_AGE_KEY is explicitly empty or invalid');
|
|
109
|
+
remember(env[name].trim());
|
|
110
|
+
return {...refuse('inline-context-unqualified','the supplied SOPS_AGE_KEY awaits an owned selected-identity isolation capability; no SOPS process was launched'),inlineName:name};
|
|
111
|
+
}
|
|
112
|
+
let file=identity;
|
|
113
|
+
if(files.length){
|
|
114
|
+
const value=env[files[0]];
|
|
115
|
+
if(!credentialPresent(value))return refuse('disabled-file','SOPS_AGE_KEY_FILE is explicitly empty or invalid');
|
|
116
|
+
if(identity!==null&&identity!==undefined&&identity!==value)return refuse('conflicting-files','two different original identity files were explicitly selected');
|
|
117
|
+
file=value;
|
|
118
|
+
}
|
|
119
|
+
if(file!==null&&file!==undefined){
|
|
120
|
+
if(!credentialPresent(file))return refuse('invalid-file','the original identity file selection is empty or invalid');
|
|
121
|
+
if(!path.isAbsolute(file))return refuse('identity-file-location-unqualified','select the original identity by its absolute path; caller and SOPS working directories may differ');
|
|
122
|
+
try{
|
|
123
|
+
const stat=fs.lstatSync(file);
|
|
124
|
+
if(!stat.isFile()||stat.isSymbolicLink())return refuse('identity-file-unavailable','the explicitly selected original identity must be a regular non-symlink file');
|
|
125
|
+
}catch{return refuse('identity-file-unavailable','the explicitly selected original identity file is unavailable');}
|
|
126
|
+
return {mode:'file',env:{...env,SOPS_AGE_KEY_FILE:file},error:null};
|
|
127
|
+
}
|
|
128
|
+
if(required)return refuse('identity-not-supplied','supply SOPS_AGE_KEY locally or select the original SOPS_AGE_KEY_FILE; no home default was inferred');
|
|
129
|
+
return {mode:'public-recipient',env:{...env},error:null};
|
|
130
|
+
}
|
|
@@ -3,14 +3,12 @@ purpose: >-
|
|
|
3
3
|
The exact version of every dependency a StarCi product repository pins. One version per dependency for the whole
|
|
4
4
|
family. Raising a version is a change to this file first (with the package bump when it is a @starci package),
|
|
5
5
|
then the repositories' own upgrade lane (each sets the exact version and reinstalls; nothing else installs a @starci package). Read on 2026-09-29 from the packages under
|
|
6
|
-
.claude/packages and from the installed node_modules of
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
.claude/packages and from the installed node_modules of the six product repositories; where they disagreed the
|
|
7
|
+
newest version installed in more than one repository won, and the runtime's own version won for @starci packages.
|
|
8
|
+
An app (hfs 4) has ONE package.json for both sides, so a
|
|
9
9
|
dependency both sides declared at different versions takes one: its pin where it has one, otherwise the higher of the
|
|
10
|
-
two, pinned here with a why (2026-10-01
|
|
11
|
-
|
|
12
|
-
same way on 2026-10-01 (examples/todo-app from todo-app-backend/todo-app-frontend, examples/ecommerce-app from
|
|
13
|
-
ecommerce-app-be/ecommerce-app-fe): no dependency outside this file was declared at two versions across their sides, so
|
|
10
|
+
two, pinned here with a why (2026-10-01: every such conflict but graphql was already pinned). The runtime's example apps
|
|
11
|
+
merged the same way on 2026-10-01: no dependency outside this file was declared at two versions across their sides, so
|
|
14
12
|
every choice is a pin (each side's older @starci pins and graphql moved to the version here). `side` names the side whose code uses
|
|
15
13
|
the dependency; the app root package.json carries the pins of both.
|
|
16
14
|
pins:
|
|
@@ -24,77 +22,89 @@ pins:
|
|
|
24
22
|
source: packages/heroicons/package.json
|
|
25
23
|
why: 'StarCi custom Heroicons-compatible cuts; eslint-canon-fe (icon.mjs) admits @starci/heroicons/24/outline and /16/solid as icon sources, so an app that uses them gets this exact version.'
|
|
26
24
|
'@starci/grammar':
|
|
27
|
-
version: 0.8.
|
|
25
|
+
version: 0.8.3
|
|
28
26
|
group: starci
|
|
29
27
|
install: registry
|
|
30
28
|
side: fe
|
|
31
29
|
source: packages/grammar/package.json
|
|
32
|
-
why:
|
|
30
|
+
why: the product front ends pinned older versions (0.4.11, 0.5.0, 0.5.1); the runtime source is 0.8.0 and wins for a @starci package (the brand layer sets `--font-sans` and `--font-mono`; the grammar reads them; 0.7.2 added the Input tel kind and IconButton disclosure props).
|
|
33
31
|
'@starci/eslint-canon-be':
|
|
34
|
-
version: 3.0.
|
|
32
|
+
version: 3.0.10
|
|
35
33
|
group: starci
|
|
36
34
|
install: registry
|
|
37
35
|
side: be
|
|
38
36
|
source: packages/eslint/be/package.json
|
|
39
37
|
why: '3.0.3: its bundled canon-pins copy pins stylelint-canon 2.0.2 and hfs 4.0.3; no rule changed. 3.0.2: its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root (app.starcistacks, app.sops) and pin hfs 4.0.2. 3.0.1: its bundled canon-pins copy pins hfs 4.0.1. 3.0.0: `loadHfs(import.meta.url)` of be/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the be side; the project graph is built per side. 2.0.0 (C0 release): starciBeConfig({ hfs: loadHfs(import.meta.url) }) typed factory and the BE-CONVENTION laws.'
|
|
40
38
|
'@starci/eslint-canon-fe':
|
|
41
|
-
version: 8.0.
|
|
39
|
+
version: 8.0.10
|
|
42
40
|
group: starci
|
|
43
41
|
install: registry
|
|
44
42
|
side: fe
|
|
45
43
|
source: packages/eslint/fe/package.json
|
|
46
44
|
why: '8.0.3: its bundled canon-pins copy pins stylelint-canon 2.0.2 and hfs 4.0.3; no rule changed. 8.0.2: its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root (app.starcistacks, app.sops) and pin hfs 4.0.2. 8.0.1: its bundled canon-pins copy pins hfs 4.0.1. 8.0.0: `loadHfs(import.meta.url)` of fe/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the fe side; the project graph is built per side. 7.0.0: the front end has no tests (FE_NO_TESTS R97 in hfs); no-vietnamese-in-source (R91).'
|
|
47
45
|
'@starci/stylelint-canon':
|
|
48
|
-
version: 2.0.
|
|
46
|
+
version: 2.0.5
|
|
49
47
|
group: starci
|
|
50
48
|
install: registry
|
|
51
49
|
side: fe
|
|
52
50
|
source: packages/stylelint/package.json
|
|
53
51
|
why: '2.0.2: no-class-selector refuses a compound class selector (`div.card`), which the 2.0.1 pattern let through. 2.0.1 accepts `--font-sans` and `--font-mono` in the brand layer (the vocabulary follows the grammar 0.8.0). 2.0.0 adds status-contrast (HeroUI soft pairs measured per theme), fixes brand-layer-shape on the shared :root,.light,.dark block and the info soft pair, and derives appTokens with loadAppTokens(import.meta.url) for the managed one-line stylelint.config.mjs.'
|
|
54
52
|
'@starci/tsconfig':
|
|
55
|
-
version: 2.0.
|
|
53
|
+
version: 2.0.3
|
|
56
54
|
group: starci
|
|
57
55
|
install: registry
|
|
58
56
|
side: both
|
|
59
57
|
source: packages/tsconfig/package.json
|
|
60
58
|
'@starci/prettier-config':
|
|
61
|
-
version: 1.0.
|
|
59
|
+
version: 1.0.3
|
|
62
60
|
group: starci
|
|
63
61
|
install: registry
|
|
64
62
|
side: both
|
|
65
63
|
source: packages/prettier-config/package.json
|
|
66
64
|
'@starci/jest-preset':
|
|
67
|
-
version: 2.2.
|
|
65
|
+
version: 2.2.5
|
|
68
66
|
group: starci
|
|
69
67
|
install: registry
|
|
70
68
|
side: be
|
|
71
69
|
source: packages/jest-preset/package.json
|
|
72
|
-
why: '2.2.2: the unit run writes the lcov Sonar and Codecov import (services only); 2.2.0: the integration, e2e and contract projects run every spec file in a worker process of its own (world-runner.cjs), so a process-global framework registry (@nestjs/graphql type metadata) never leaks between e2e files; 2.1.0: four projects on the test world, the unit kit (mockEntityManager, fakeTransaction, fakeIds, FakeClock, Outcome matchers) and the recordingOutbox claim side.'
|
|
70
|
+
why: '2.2.4: the world runner runs up to min(--maxWorkers, slots) world files at once, each in its own process bound to one data slot of the test world (STARCI_TEST_WORLD_SLOT), and reads test-world state protocol 2 only: pinned together with @starci/test-world 1.1.0, any other state file is JEST_PRESET_WORLD_PAIR_MISMATCH. 2.2.3: republished after the move (no preset change). 2.2.2: the unit run writes the lcov Sonar and Codecov import (services only); 2.2.0: the integration, e2e and contract projects run every spec file in a worker process of its own (world-runner.cjs), so a process-global framework registry (@nestjs/graphql type metadata) never leaks between e2e files; 2.1.0: four projects on the test world, the unit kit (mockEntityManager, fakeTransaction, fakeIds, FakeClock, Outcome matchers) and the recordingOutbox claim side.'
|
|
73
71
|
'@starci/test-world':
|
|
74
|
-
version: 1.
|
|
72
|
+
version: 1.2.1
|
|
75
73
|
group: starci
|
|
76
74
|
install: registry
|
|
77
75
|
side: be
|
|
78
76
|
source: packages/test-world/package.json
|
|
79
|
-
why: '1.0.5: a modules world boots real peer apps beside its modules, world.apps.<name>.during(fn) is the outage of a peer app, and w.keycloak.clientSecret(client) answers the run-generated secret of a confidential realm client. 1.0.4: world.resolve and scope.resolve take any Nest token (class, string or symbol). 1.0.3: the globalSetup registers the path aliases as TypeScript resolves them (the extends chain, paths from the config that declares them, the effective baseUrl), so a tests tsconfig that only extends the side config loads the declaration. 1.0.2: every path a declaration names (`stack`, seeds, the realm, Dockerfiles) resolves from the app root (the directory of hfs.json), where .starcistacks lives, never from the be side. The shared e2e library of every back end (R47, R48): the warm stack behind toxiproxy, the network-edge fakes, the Nest boot, the typed useTestWorld handle, useSandbox for contract specs
|
|
77
|
+
why: '1.2.0: Kafka as real own infra (the one digest-pinned apache/kafka KRaft image, a broker listener and proxy per slot, slot-prefixed topics, consumer groups and client ids) and schema-per-context Postgres (a schema and a login role per context in a shared database); its CLI main is exported at ./cli for starci app stack, and the former starci app stack bin is removed. 1.1.0: per-worker data slots: a run provisions min(jest workers, workers cap, default 2) slots, each its own namespace (<ns>_w<k>) with its own databases, Keycloak realm, leased Redis DB, bucket/collection/topic prefixes, fakes host, toxiproxy proxies and outage lock, so world files run in parallel; state file protocol 2, paired exactly with @starci/jest-preset 2.2.4 (TEST_WORLD_PAIR_MISMATCH otherwise). 1.0.6: republished after the move (no library change). 1.0.5: a modules world boots real peer apps beside its modules, world.apps.<name>.during(fn) is the outage of a peer app, and w.keycloak.clientSecret(client) answers the run-generated secret of a confidential realm client. 1.0.4: world.resolve and scope.resolve take any Nest token (class, string or symbol). 1.0.3: the globalSetup registers the path aliases as TypeScript resolves them (the extends chain, paths from the config that declares them, the effective baseUrl), so a tests tsconfig that only extends the side config loads the declaration. 1.0.2: every path a declaration names (`stack`, seeds, the realm, Dockerfiles) resolves from the app root (the directory of hfs.json), where .starcistacks lives, never from the be side. The shared e2e library of every back end (R47, R48): the warm stack behind toxiproxy, the network-edge fakes, the Nest boot, the typed useTestWorld handle, useSandbox for contract specs and the outage lock; a devDependency of every back end. 1.0.1: world.keycloak.events/sessions (the user events of the realm and live sessions through the admin API) and world.infra.postgresql.connection(name) (the database of one connection down while the others serve, under the outage lock).'
|
|
78
|
+
'@starci/cli':
|
|
79
|
+
version: 1.0.1
|
|
80
|
+
group: starci
|
|
81
|
+
install: registry
|
|
82
|
+
side: both
|
|
83
|
+
source: packages/cli/package.json
|
|
84
|
+
why: '1.0.0: the only StarCi command package; product repositories install it for starci app, while @starci/hfs remains its pinned transitive implementation.'
|
|
80
85
|
'@starci/hfs':
|
|
81
|
-
version: 4.0.
|
|
86
|
+
version: 4.0.10
|
|
82
87
|
group: starci
|
|
83
88
|
install: registry
|
|
84
89
|
side: both
|
|
85
90
|
source: packages/hfs/package.json
|
|
86
|
-
why: '4.0.
|
|
91
|
+
why: '4.0.9: the transitive app implementation used by @starci/cli; it carries the generated runtime slice read by starci app commands.'
|
|
87
92
|
# --- tooling
|
|
88
93
|
typescript:
|
|
89
94
|
version: 5.9.3
|
|
90
95
|
group: tooling
|
|
91
96
|
side: both
|
|
92
|
-
why: all six repositories resolve 5.9.3 already; the declared ranges (^5, ^5.7.3) become exact.
|
|
97
|
+
why: all six product repositories resolve 5.9.3 already; the declared ranges (^5, ^5.7.3) become exact.
|
|
98
|
+
turbo:
|
|
99
|
+
version: 2.11.6
|
|
100
|
+
group: tooling
|
|
101
|
+
side: fe
|
|
102
|
+
why: 'every app is a monorepo (R143): turbo runs build, dev, lint and typecheck over the fe workspaces fe/apps/* and fe/packages/* from the app root turbo.json, as nivo-fe does; 2.11.6 is the newest 2.x on 2026-10-02.'
|
|
93
103
|
prettier:
|
|
94
104
|
version: 3.9.6
|
|
95
105
|
group: tooling
|
|
96
106
|
side: both
|
|
97
|
-
why: only
|
|
107
|
+
why: only one product repository had it installed (3.9.6); the other five adopt it with the formatter change.
|
|
98
108
|
stylelint:
|
|
99
109
|
version: 17.15.0
|
|
100
110
|
group: tooling
|
|
@@ -109,7 +119,7 @@ pins:
|
|
|
109
119
|
version: 9.39.5
|
|
110
120
|
group: tooling
|
|
111
121
|
side: both
|
|
112
|
-
why: five repositories resolve 9.39.5,
|
|
122
|
+
why: five product repositories resolve 9.39.5, the sixth 9.39.4.
|
|
113
123
|
eslint-plugin-react-hooks:
|
|
114
124
|
version: 7.1.1
|
|
115
125
|
group: tooling
|
|
@@ -119,7 +129,42 @@ pins:
|
|
|
119
129
|
version: 22.20.4
|
|
120
130
|
group: tooling
|
|
121
131
|
side: both
|
|
122
|
-
why:
|
|
132
|
+
why: one front end resolves 20.19.43 and one back end 22.20.0; the package engines are node >=22.
|
|
133
|
+
'@types/express':
|
|
134
|
+
version: 4.17.25
|
|
135
|
+
group: tooling
|
|
136
|
+
side: be
|
|
137
|
+
why: the Express types of a back end; the reference app declares ^4.17.21 and resolves 4.17.25.
|
|
138
|
+
'@types/react':
|
|
139
|
+
version: 19.3.0
|
|
140
|
+
group: tooling
|
|
141
|
+
side: fe
|
|
142
|
+
why: the React types of a front end; the reference app declares ^19.0.0 and resolves 19.3.0.
|
|
143
|
+
'@types/react-dom':
|
|
144
|
+
version: 19.3.0
|
|
145
|
+
group: tooling
|
|
146
|
+
side: fe
|
|
147
|
+
why: the React DOM types of a front end; the reference app declares ^19.0.0 and resolves 19.3.0.
|
|
148
|
+
husky:
|
|
149
|
+
version: 9.1.7
|
|
150
|
+
group: tooling
|
|
151
|
+
side: both
|
|
152
|
+
why: the managed git hooks of the app root (pre-commit, pre-push); the reference app declares ^9.1.7 and resolves 9.1.7.
|
|
153
|
+
ts-node-dev:
|
|
154
|
+
version: 2.0.0
|
|
155
|
+
group: tooling
|
|
156
|
+
side: be
|
|
157
|
+
why: 'the watch runner of the managed dev:be:<app> script (ts-node-dev --respawn -r tsconfig-paths/register); 2.0.0 is its latest release.'
|
|
158
|
+
tsc-alias:
|
|
159
|
+
version: 1.9.7
|
|
160
|
+
group: tooling
|
|
161
|
+
side: be
|
|
162
|
+
why: 'rewrites the path aliases in the compiled output (build:be); the reference app declares ^1.8.10 and resolves 1.9.7.'
|
|
163
|
+
tsconfig-paths:
|
|
164
|
+
version: 4.2.0
|
|
165
|
+
group: tooling
|
|
166
|
+
side: be
|
|
167
|
+
why: 'loads the path aliases for the dev runner (dev:be:<app>); the reference app declares ^4.2.0 and resolves 4.2.0.'
|
|
123
168
|
# --- test
|
|
124
169
|
jest:
|
|
125
170
|
version: 29.7.0
|
|
@@ -146,11 +191,16 @@ pins:
|
|
|
146
191
|
version: 19.2.3
|
|
147
192
|
group: framework
|
|
148
193
|
side: fe
|
|
194
|
+
nest-commander:
|
|
195
|
+
version: 3.21.0
|
|
196
|
+
group: framework
|
|
197
|
+
side: be
|
|
198
|
+
why: 'the one command-line framework of a back end (R148-R150): apps/cli boots with CommandFactory.run and every one-off action is a nest-commander command of src/features/cli; 3.21.0 is the newest on 2026-10-02 and takes @nestjs 11 as its peer.'
|
|
149
199
|
'@nestjs/core':
|
|
150
200
|
version: 11.2.5
|
|
151
201
|
group: framework
|
|
152
202
|
side: be
|
|
153
|
-
why:
|
|
203
|
+
why: one product back end resolves 11.1.27, the others 11.2.5.
|
|
154
204
|
'@nestjs/common':
|
|
155
205
|
version: 11.2.5
|
|
156
206
|
group: framework
|
|
@@ -167,30 +217,111 @@ pins:
|
|
|
167
217
|
version: 11.1.1
|
|
168
218
|
group: framework
|
|
169
219
|
side: be
|
|
170
|
-
why: readiness probes with dependency indicators use Terminus (the liveness route of the
|
|
220
|
+
why: readiness probes with dependency indicators use Terminus (the liveness route of the scaffolded skeleton does not, being a thin door over the liveness service); every measured product back end resolves 11.1.1.
|
|
221
|
+
'@nestjs/cqrs':
|
|
222
|
+
version: 11.0.3
|
|
223
|
+
group: framework
|
|
224
|
+
side: be
|
|
225
|
+
why: 'the CQRS module of the application layer (commands, queries, handlers); the reference app declares ^11.0.3 and resolves 11.0.3.'
|
|
226
|
+
'@nestjs/typeorm':
|
|
227
|
+
version: 11.0.3
|
|
228
|
+
group: framework
|
|
229
|
+
side: be
|
|
230
|
+
why: 'the Nest bridge of TypeORM; the reference app declares ^11.0.3 and resolves 11.0.3.'
|
|
231
|
+
typeorm:
|
|
232
|
+
version: 0.3.31
|
|
233
|
+
group: framework
|
|
234
|
+
side: be
|
|
235
|
+
why: 'the one ORM of a back end; the reference app declares ^0.3.20 and resolves 0.3.31.'
|
|
236
|
+
pg:
|
|
237
|
+
version: 8.23.1
|
|
238
|
+
group: framework
|
|
239
|
+
side: be
|
|
240
|
+
why: 'the Postgres driver behind TypeORM; the reference app declares ^8.12.0 and resolves 8.23.1.'
|
|
241
|
+
reflect-metadata:
|
|
242
|
+
version: 0.2.2
|
|
243
|
+
group: framework
|
|
244
|
+
side: be
|
|
245
|
+
why: 'the decorator-metadata runtime Nest reads; the reference app declares ^0.2.2 and resolves 0.2.2.'
|
|
246
|
+
rxjs:
|
|
247
|
+
version: 7.8.2
|
|
248
|
+
group: framework
|
|
249
|
+
side: be
|
|
250
|
+
why: 'the observable runtime Nest is built on; the reference app declares ^7.8.1 and resolves 7.8.2.'
|
|
251
|
+
tslib:
|
|
252
|
+
version: 2.8.1
|
|
253
|
+
group: framework
|
|
254
|
+
side: be
|
|
255
|
+
why: 'the helper runtime the TypeScript emit references (importHelpers); the reference app declares ^2.8.1 and resolves 2.8.1.'
|
|
256
|
+
server-only:
|
|
257
|
+
version: 0.0.1
|
|
258
|
+
group: framework
|
|
259
|
+
side: fe
|
|
260
|
+
why: 'the Next.js marker that fails a client bundle that imports it; the i18n workspace of the reference app declares ^0.0.1.'
|
|
171
261
|
next-intl:
|
|
172
262
|
version: 4.13.6
|
|
173
263
|
group: framework
|
|
174
264
|
side: fe
|
|
175
|
-
why: every HFS front end uses next-intl with the [locale] segment (
|
|
265
|
+
why: every HFS front end uses next-intl with the [locale] segment (starci app scaffold writes it); the measured front end resolves 4.13.6.
|
|
176
266
|
graphql:
|
|
177
267
|
version: 16.14.2
|
|
178
268
|
group: framework
|
|
179
269
|
side: both
|
|
180
|
-
why: 'one app package.json for both sides (hfs 4):
|
|
270
|
+
why: 'one app package.json for both sides (hfs 4): where the two sides declared different ranges (^16.14.1 on a back end, ^16.14.2 on a front end), the higher wins; the measured product installs resolve 16.14.2. The example apps declared ^16.14.2 as well; each app root now has one dependencies entry at the pin.'
|
|
181
271
|
supertest:
|
|
182
272
|
version: 7.3.0
|
|
183
273
|
group: tooling
|
|
184
274
|
side: be
|
|
185
|
-
why: the e2e world of a back end calls the app over HTTP (/health/live in the skeleton);
|
|
275
|
+
why: the e2e world of a back end calls the app over HTTP (/health/live in the skeleton); two product back ends resolve 7.3.0, one 7.2.2.
|
|
186
276
|
# --- ui
|
|
187
277
|
'@heroui/react':
|
|
188
278
|
version: 3.2.6
|
|
189
279
|
group: ui
|
|
190
280
|
side: fe
|
|
191
|
-
why:
|
|
281
|
+
why: one product front end resolves 3.2.4, the others 3.2.6.
|
|
192
282
|
'@heroui/styles':
|
|
193
283
|
version: 3.2.6
|
|
194
284
|
group: ui
|
|
195
285
|
side: fe
|
|
196
|
-
why:
|
|
286
|
+
why: one product front end resolves 3.2.4, the others 3.2.6.
|
|
287
|
+
tailwindcss:
|
|
288
|
+
version: 4.3.3
|
|
289
|
+
group: ui
|
|
290
|
+
side: fe
|
|
291
|
+
why: 'the styling engine of a front end; the reference app declares ^4 and resolves 4.3.3.'
|
|
292
|
+
'@tailwindcss/postcss':
|
|
293
|
+
version: 4.3.3
|
|
294
|
+
group: ui
|
|
295
|
+
side: fe
|
|
296
|
+
why: 'the PostCSS plugin tailwindcss 4 runs through; the reference app declares ^4 and resolves 4.3.3.'
|
|
297
|
+
# --- Supabase lite
|
|
298
|
+
'@supabase/ssr':
|
|
299
|
+
version: 0.12.7
|
|
300
|
+
group: framework
|
|
301
|
+
side: fe
|
|
302
|
+
why: the one server/browser client factory for a lite Next app; exact version registry-checked for the lite scaffold.
|
|
303
|
+
'@supabase/supabase-js':
|
|
304
|
+
version: 2.117.2
|
|
305
|
+
group: framework
|
|
306
|
+
side: both
|
|
307
|
+
why: the generated Database-typed client used by the FE data owner and the BE Auth/Storage integration.
|
|
308
|
+
jose:
|
|
309
|
+
version: 6.2.12
|
|
310
|
+
group: framework
|
|
311
|
+
side: be
|
|
312
|
+
why: verifies Supabase access tokens against the project JWKS with issuer, audience, expiry and algorithm checks.
|
|
313
|
+
supabase:
|
|
314
|
+
version: 2.119.0
|
|
315
|
+
group: tooling
|
|
316
|
+
side: both
|
|
317
|
+
why: the root CLI wrapper owns local schema lifecycle and generates the committed database types.
|
|
318
|
+
class-transformer:
|
|
319
|
+
version: 0.5.1
|
|
320
|
+
group: framework
|
|
321
|
+
side: be
|
|
322
|
+
why: Nest request transformation in the API runtime, pinned with the validation library.
|
|
323
|
+
class-validator:
|
|
324
|
+
version: 0.15.1
|
|
325
|
+
group: framework
|
|
326
|
+
side: be
|
|
327
|
+
why: Nest boundary validation in the API runtime, pinned with the transformation library.
|