@starci/hfs 4.2.17 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +7 -0
- package/db/migrate.mjs +361 -0
- package/db/post-cutover.mjs +136 -0
- package/emit/db-types.mjs +10 -1
- package/lint/run.mjs +1 -1
- package/package.json +4 -1
- package/release/gate.mjs +298 -0
- package/release/index.mjs +103 -0
- package/release/push.mjs +110 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +11 -11
- package/runtime/knowledge/hfs/fe-stack.yaml +22 -1
- package/runtime/knowledge/hfs/rules.yaml +3437 -160
- package/runtime/knowledge/hfs/slots.yaml +430 -92
- package/runtime/knowledge/patterns/be/api.yaml +92 -2
- package/runtime/knowledge/patterns/be/cli.yaml +37 -9
- package/runtime/knowledge/patterns/be/event-bus.yaml +3 -3
- package/runtime/knowledge/patterns/be/jobs.yaml +20 -2
- package/runtime/knowledge/patterns/be/projections.yaml +4 -2
- package/runtime/knowledge/patterns/be/queues.yaml +11 -3
- package/runtime/knowledge/patterns/be/reactors.yaml +20 -1
- package/runtime/knowledge/patterns/be/realtime.yaml +25 -3
- package/runtime/knowledge/patterns/be/saga.yaml +20 -3
- package/runtime/knowledge/patterns/be/webhooks.yaml +210 -36
- package/runtime/knowledge/patterns/fe/folder.yaml +4 -0
- package/runtime/knowledge/sonar-gate.yaml +1 -1
- package/runtime/modules/kernel/failure-codes.yaml +3128 -47
- package/runtime/modules/models/runtimes.yaml +1 -1
- package/runtime/modules/schemas/application-stacks.schema.yaml +663 -0
- package/runtime/packages/cli/src/catalog.generated.mjs +14104 -0
- package/runtime/packages/cli/src/validate-args.mjs +213 -0
- package/runtime/scripts/api/git/add.mjs +5 -0
- package/runtime/scripts/api/git/cat-file.mjs +5 -0
- package/runtime/scripts/api/git/init.mjs +7 -0
- package/runtime/scripts/api/git/lib.mjs +3 -0
- package/runtime/scripts/api/git/tag.mjs +5 -0
- package/runtime/scripts/api/node/lib.mjs +20 -0
- package/runtime/scripts/api/node/run-node.mjs +6 -0
- package/runtime/scripts/api/sops/lib.mjs +41 -0
- package/runtime/scripts/api/sops/resolve-sops.mjs +7 -0
- package/runtime/scripts/api/sops/seal.mjs +1 -1
- package/runtime/scripts/api/sops/selected-age-recipient.mjs +7 -0
- package/runtime/scripts/api/supabase/database-dump.mjs +5 -0
- package/runtime/scripts/api/supabase/database-query.mjs +5 -0
- package/runtime/scripts/api/supabase/lib.mjs +44 -0
- package/runtime/scripts/api/supabase/migration-repair.mjs +5 -0
- package/runtime/scripts/hfs/app-wiring.mjs +201 -0
- package/runtime/scripts/hfs/architecture/backend-app-files.mjs +103 -0
- package/runtime/scripts/hfs/architecture/backend.mjs +22 -10
- package/runtime/scripts/hfs/architecture/background-unowned.mjs +157 -41
- package/runtime/scripts/hfs/architecture/canon-clones.mjs +240 -0
- package/runtime/scripts/hfs/architecture/canon-jsx-clones.mjs +143 -0
- package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +6 -3
- package/runtime/scripts/hfs/architecture/clones.mjs +17 -8
- package/runtime/scripts/hfs/architecture/connection-map.mjs +14 -12
- package/runtime/scripts/hfs/architecture/context-map.mjs +25 -14
- package/runtime/scripts/hfs/architecture/context-owner.mjs +1 -2
- package/runtime/scripts/hfs/architecture/dead-exports-bindings.mjs +149 -0
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +23 -50
- package/runtime/scripts/hfs/architecture/default-deny.mjs +8 -6
- package/runtime/scripts/hfs/architecture/frontend-block-render.mjs +104 -0
- package/runtime/scripts/hfs/architecture/frontend-world-render.mjs +30 -11
- package/runtime/scripts/hfs/architecture/frontend-world.mjs +1 -1
- package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +153 -0
- package/runtime/scripts/hfs/architecture/hfs.mjs +3 -3
- package/runtime/scripts/hfs/architecture/i18n-keys.mjs +16 -3
- package/runtime/scripts/hfs/architecture/machine-ast.mjs +17 -0
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +49 -25
- package/runtime/scripts/hfs/architecture/next-data-inference.mjs +176 -0
- package/runtime/scripts/hfs/architecture/next-data-symbols.mjs +26 -0
- package/runtime/scripts/hfs/architecture/next-data.mjs +31 -23
- package/runtime/scripts/hfs/architecture/reachability.mjs +14 -0
- package/runtime/scripts/hfs/architecture/register-once.mjs +15 -7
- package/runtime/scripts/hfs/architecture/required-files.mjs +2 -1
- package/runtime/scripts/hfs/architecture/source-names.mjs +48 -3
- package/runtime/scripts/hfs/architecture/staged-consumers.mjs +37 -0
- package/runtime/scripts/hfs/architecture/supabase-ast.mjs +214 -17
- package/runtime/scripts/hfs/architecture/supabase-be.mjs +1 -6
- package/runtime/scripts/hfs/architecture/supabase.mjs +59 -21
- package/runtime/scripts/hfs/architecture/surface.mjs +2 -1
- package/runtime/scripts/hfs/architecture/tiers.mjs +11 -4
- package/runtime/scripts/hfs/architecture/typescript.mjs +1 -8
- package/runtime/scripts/hfs/architecture/unit-spec-providers.mjs +9 -13
- package/runtime/scripts/hfs/check-results.mjs +28 -0
- package/runtime/scripts/hfs/check.mjs +63 -72
- package/runtime/scripts/hfs/coverage-from.mjs +70 -0
- package/runtime/scripts/hfs/db-baseline-verb.mjs +276 -0
- package/runtime/scripts/hfs/db-plan-verb.mjs +254 -0
- package/runtime/scripts/hfs/db-restamp-verb.mjs +60 -0
- package/runtime/scripts/hfs/declaration-shape.mjs +39 -3
- package/runtime/scripts/hfs/doc-commands.mjs +367 -0
- package/runtime/scripts/hfs/edition-slots.mjs +2 -2
- package/runtime/scripts/hfs/example-secrets.mjs +158 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +91 -6
- package/runtime/scripts/hfs/path-findings.mjs +32 -2
- package/runtime/scripts/hfs/refusal-codes.mjs +6 -0
- package/runtime/scripts/hfs/rule-catalog.mjs +156 -11
- package/runtime/scripts/hfs/rule-params-shape.mjs +22 -10
- package/runtime/scripts/hfs/rules/a15-findings.mjs +88 -0
- package/runtime/scripts/hfs/rules/app-env-required.mjs +20 -0
- package/runtime/scripts/hfs/rules/app-root.mjs +2 -2
- package/runtime/scripts/hfs/rules/assets.mjs +79 -0
- package/runtime/scripts/hfs/rules/boot-proof.mjs +16 -0
- package/runtime/scripts/hfs/rules/canon-copy-drift.mjs +59 -0
- package/runtime/scripts/hfs/rules/contract.mjs +66 -5
- package/runtime/scripts/hfs/rules/coverage-below.mjs +230 -0
- package/runtime/scripts/hfs/rules/database-access.mjs +343 -0
- package/runtime/scripts/hfs/rules/database-baseline.mjs +142 -0
- package/runtime/scripts/hfs/rules/database-config.mjs +250 -2
- package/runtime/scripts/hfs/rules/database-constants.mjs +9 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +317 -37
- package/runtime/scripts/hfs/rules/database-plpgsql.mjs +119 -9
- package/runtime/scripts/hfs/rules/database-queue-sources.mjs +176 -0
- package/runtime/scripts/hfs/rules/database-queues.mjs +361 -0
- package/runtime/scripts/hfs/rules/database-sql.mjs +91 -9
- package/runtime/scripts/hfs/rules/database.mjs +11 -2
- package/runtime/scripts/hfs/rules/deploy-scan.mjs +192 -0
- package/runtime/scripts/hfs/rules/deploy-workflow.mjs +219 -0
- package/runtime/scripts/hfs/rules/doc-fresh.mjs +286 -0
- package/runtime/scripts/hfs/rules/docker-health.mjs +249 -0
- package/runtime/scripts/hfs/rules/docker.mjs +24 -7
- package/runtime/scripts/hfs/rules/edition.mjs +11 -10
- package/runtime/scripts/hfs/rules/env-parity.mjs +373 -0
- package/runtime/scripts/hfs/rules/env-value-shape.mjs +113 -0
- package/runtime/scripts/hfs/rules/event-bus.mjs +3 -2
- package/runtime/scripts/hfs/rules/event-tables.mjs +100 -0
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +115 -15
- package/runtime/scripts/hfs/rules/fe-stack.mjs +57 -0
- package/runtime/scripts/hfs/rules/feature-files.mjs +28 -0
- package/runtime/scripts/hfs/rules/frontend-tree.mjs +54 -35
- package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -2
- package/runtime/scripts/hfs/rules/lexicon.mjs +62 -0
- package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +89 -0
- package/runtime/scripts/hfs/rules/monorepo.mjs +14 -1
- package/runtime/scripts/hfs/rules/pipeline.mjs +8 -1
- package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -0
- package/runtime/scripts/hfs/rules/release-provenance.mjs +211 -0
- package/runtime/scripts/hfs/rules/saga-delivery.mjs +66 -0
- package/runtime/scripts/hfs/rules/saga.mjs +8 -16
- package/runtime/scripts/hfs/rules/script-hygiene.mjs +151 -0
- package/runtime/scripts/hfs/rules/secret-custody-only.mjs +65 -0
- package/runtime/scripts/hfs/rules/secrets.mjs +26 -0
- package/runtime/scripts/hfs/rules/services.mjs +4 -4
- package/runtime/scripts/hfs/rules/stack-tooling.mjs +93 -0
- package/runtime/scripts/hfs/rules/stacks-deploy.mjs +76 -0
- package/runtime/scripts/hfs/rules/stacks-ingress.mjs +87 -0
- package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +111 -0
- package/runtime/scripts/hfs/rules/stacks-release.mjs +366 -0
- package/runtime/scripts/hfs/rules/stacks-runtime.mjs +168 -0
- package/runtime/scripts/hfs/rules/stacks-swarm.mjs +417 -0
- package/runtime/scripts/hfs/rules/stacks.mjs +13 -8
- package/runtime/scripts/hfs/rules/supabase-secrets.mjs +1 -1
- package/runtime/scripts/hfs/rules/supply-chain.mjs +167 -0
- package/runtime/scripts/hfs/rules/unused-symbol-flow.mjs +101 -0
- package/runtime/scripts/hfs/rules/unused-symbol-ledger.mjs +77 -0
- package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +165 -0
- package/runtime/scripts/hfs/rules/unused-symbol-values.mjs +103 -0
- package/runtime/scripts/hfs/rules/unused-symbol.mjs +320 -0
- package/runtime/scripts/hfs/runtime-rules/source-ast.mjs +185 -0
- package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +19 -0
- package/runtime/scripts/hfs/sealed-members.mjs +101 -0
- package/runtime/scripts/hfs/secret-bootstrap-crypto.mjs +200 -0
- package/runtime/scripts/hfs/secret-document.mjs +97 -0
- package/runtime/scripts/hfs/secret-edit.mjs +170 -0
- package/runtime/scripts/hfs/secret-errors.mjs +20 -0
- package/runtime/scripts/hfs/secret-files.mjs +124 -0
- package/runtime/scripts/hfs/secret-init.mjs +300 -0
- package/runtime/scripts/hfs/secret-output.mjs +100 -0
- package/runtime/scripts/hfs/secret-sops.mjs +130 -0
- package/runtime/scripts/hfs/secret-store.mjs +163 -0
- package/runtime/scripts/hfs/secret.mjs +162 -193
- package/runtime/scripts/hfs/slot-imports.mjs +18 -3
- package/runtime/scripts/hfs/slot-required.mjs +13 -0
- package/runtime/scripts/hfs/slot-semantic-problems.mjs +2 -1
- package/runtime/scripts/hfs/slots.mjs +1 -0
- package/runtime/scripts/hfs/stack-config-kit.mjs +34 -0
- package/runtime/scripts/hfs/stack-deploy-config.mjs +313 -0
- package/runtime/scripts/hfs/stack-ingress-config.mjs +237 -0
- package/runtime/scripts/hfs/stacks-gate.mjs +414 -0
- package/runtime/scripts/hfs/starcistacks-runtime.mjs +61 -0
- package/runtime/scripts/hfs/tree-findings.mjs +22 -0
- package/runtime/scripts/lib/command-tokens.mjs +126 -0
- package/runtime/scripts/lib/compose-values.mjs +11 -0
- package/runtime/scripts/lib/deployment-findings.mjs +7 -0
- package/runtime/scripts/lib/json-clone.mjs +61 -0
- package/runtime/scripts/lib/list.mjs +4 -0
- package/runtime/scripts/lib/roots.mjs +59 -0
- package/runtime/scripts/lib/runtime-example.mjs +13 -0
- package/runtime/scripts/lib/secret-patterns.mjs +60 -5
- package/runtime/scripts/lib/sql-ast.mjs +32 -0
- package/runtime/scripts/lib/stack-services.mjs +1 -1
- package/runtime/scripts/lib/swarm-stack.mjs +126 -0
- package/runtime/scripts/lib/trim-end.mjs +8 -0
- package/runtime/scripts/lib/ts-analysis.mjs +23 -0
- package/runtime/scripts/lib/ts-ast.mjs +27 -2
- package/runtime/scripts/lib/workflow-events.mjs +8 -0
- package/scaffold/add-app.mjs +77 -59
- package/scaffold/add-cli-lite.mjs +24 -17
- package/scaffold/add-compose.mjs +79 -0
- package/scaffold/add-database-lite.mjs +14 -0
- package/scaffold/add-fe-overlay.mjs +122 -0
- package/scaffold/add-fe-page.mjs +269 -0
- package/scaffold/add-inbox-lite.mjs +87 -124
- package/scaffold/add-plan.mjs +183 -0
- package/scaffold/add-table.mjs +132 -70
- package/scaffold/add.mjs +186 -204
- package/scaffold/app.mjs +128 -43
- package/scaffold/edition-gate.mjs +3 -3
- package/scaffold/image.mjs +2 -2
- package/scaffold/lite-exports.mjs +2 -1
- package/scaffold/service.mjs +2 -2
- package/src/main.mjs +238 -119
- package/stack/age-install.mjs +37 -0
- package/stack/backup.mjs +100 -0
- package/stack/build-args.mjs +42 -0
- package/stack/build.mjs +173 -0
- package/stack/cli.mjs +130 -0
- package/stack/config.mjs +57 -0
- package/stack/context.mjs +57 -0
- package/stack/converge.mjs +107 -0
- package/stack/deploy.mjs +301 -0
- package/stack/digest.mjs +16 -0
- package/stack/docker-transport.mjs +53 -0
- package/stack/edge-alias.mjs +118 -0
- package/stack/errors.mjs +21 -0
- package/stack/image-scan.mjs +152 -0
- package/stack/ingress-create.mjs +114 -0
- package/stack/ingress-publish.mjs +273 -0
- package/stack/ingress.mjs +706 -0
- package/stack/jobs.mjs +51 -0
- package/stack/live-restore.mjs +177 -0
- package/stack/prepare.mjs +266 -0
- package/stack/private-file.mjs +22 -0
- package/stack/provision.mjs +90 -0
- package/stack/prune.mjs +46 -0
- package/stack/release-store.mjs +87 -0
- package/stack/remote.mjs +205 -0
- package/stack/render.mjs +149 -0
- package/stack/retire.mjs +47 -0
- package/stack/sealed.mjs +149 -0
- package/stack/task.mjs +42 -0
- package/stack/verify.mjs +99 -0
- package/sync/ci-commands.mjs +13 -0
- package/sync/index.mjs +127 -64
- package/sync/stack-images.mjs +127 -0
- package/templates/app/ci-workflows/github/workflows/ci.yml +5 -1
- package/templates/app/ci-workflows/github/workflows/images.yml +15 -3
- package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +148 -0
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +7 -3
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +38 -6
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +14 -2
- package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +148 -0
- package/templates/app/codegen-graphql.mjs.partial +13 -2
- package/templates/app/codegen-lite/scripts/codegen.mjs +6 -1
- package/templates/app/codegen-prelude.mjs.partial +8 -0
- package/templates/app/gitignore +4 -0
- package/templates/app/gitignore-lite +4 -0
- package/templates/app/hooks/husky/pre-commit +7 -12
- package/templates/app/package-scripts/package.json +1 -0
- package/templates/app/package-scripts/supabase.json +7 -0
- package/templates/app/package-scripts-lite/package.json +1 -7
- package/templates/app/skeleton/.editorconfig +1 -0
- package/templates/app/skeleton/.gitattributes +7 -1
- package/templates/app/skeleton/.github/dependabot.yml +17 -0
- package/templates/app/skeleton/.nvmrc +1 -1
- package/templates/app/skeleton/.sops.yaml +1 -1
- package/templates/app/skeleton/.starcistacks/application-stacks.yaml +134 -1
- package/templates/app/skeleton/.starcistacks/dev/README.md +16 -0
- package/templates/app/skeleton/.starcistacks/dev/environment.json +5 -0
- package/templates/app/skeleton/.starcistacks/dev/infra/compose/stack.yaml +71 -0
- package/templates/app/skeleton/.starcistacks/dev/runtime/env/KEYS.md +14 -0
- package/templates/app/skeleton/.starcistacks/production/README.md +37 -0
- package/templates/app/skeleton/.starcistacks/production/environment.json +5 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/Caddyfile +15 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/owner-actions.md +11 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/recovery/restore-proof.md +7 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/current.yaml +6 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/images.lock.yaml +9 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/previous.yaml +6 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +142 -0
- package/templates/app/skeleton/.starcistacks/production/runtime/env/KEYS.md +14 -0
- package/templates/app/skeleton/README.md +6 -6
- package/templates/app/skeleton/scripts/codegen.mjs +1 -2
- package/templates/app/skeleton-lite/.editorconfig +16 -0
- package/templates/app/skeleton-lite/.gitattributes +8 -0
- package/templates/app/skeleton-lite/.github/dependabot.yml +17 -0
- package/templates/app/skeleton-lite/.nvmrc +1 -0
- package/templates/app/skeleton-lite/.sops.yaml +3 -2
- package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +193 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/README.md +20 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +2 -1
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/Caddyfile +16 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/owner-actions.md +11 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/recovery/restore-proof.md +7 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/current.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/images.lock.yaml +8 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/previous.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +120 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +18 -0
- package/templates/app/skeleton-lite/.starcistacks/production/README.md +38 -0
- package/templates/app/skeleton-lite/.starcistacks/production/environment.json +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/Caddyfile +11 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/owner-actions.md +11 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/recovery/restore-proof.md +7 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/releases/current.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/releases/images.lock.yaml +8 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/releases/previous.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +121 -0
- package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +21 -0
- package/templates/app/skeleton-lite/.starciwork/brand/index.yaml +12 -0
- package/templates/app/skeleton-lite/.starciwork/workspace.yaml +9 -0
- package/templates/app/skeleton-lite/README.md +8 -4
- package/templates/app/skeleton-lite/supabase/config.toml +8 -1
- package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +15 -6
- package/templates/app/starciwork.gitignore-lite +6 -0
- package/templates/app/upgrade-full/.starcistacks/dev/README.md +13 -7
- package/templates/be/image/worker/Dockerfile +1 -1
- package/templates/be/inbox/database-client.spec.ts.tpl +22 -28
- package/templates/be/inbox/database-client.ts.tpl +14 -28
- package/templates/be/inbox/delivery-recorded.event.ts.tpl +36 -0
- package/templates/be/inbox/event-index.ts.tpl +1 -0
- package/templates/be/inbox/events.json.tpl +10 -0
- package/templates/be/inbox/migration.sql.tpl +1 -0
- package/templates/be/inbox/platform/event-bus/event-bus.contracts.ts.tpl +42 -0
- package/templates/be/inbox/platform/event-bus/event-bus.decorators.ts.tpl +9 -0
- package/templates/be/inbox/platform/event-bus/event-bus.module-definition.ts.tpl +6 -0
- package/templates/be/inbox/platform/event-bus/event-bus.module.ts.tpl +19 -0
- package/templates/be/inbox/platform/event-bus/event-bus.options.ts.tpl +2 -0
- package/templates/be/inbox/platform/event-bus/event-bus.port.ts.tpl +16 -0
- package/templates/be/inbox/platform/event-bus/event-bus.service.spec.ts.tpl +45 -0
- package/templates/be/inbox/platform/event-bus/event-bus.service.ts.tpl +15 -0
- package/templates/be/inbox/platform/event-bus/index.ts.tpl +5 -0
- package/templates/be/inbox/platform/event-bus/persistence/event-bus.sql.ts.tpl +5 -0
- package/templates/be/inbox/platform/inbox/inbox.decorators.ts.tpl +9 -0
- package/templates/be/inbox/platform/inbox/inbox.module-definition.ts.tpl +6 -0
- package/templates/be/inbox/platform/inbox/inbox.module.ts.tpl +19 -0
- package/templates/be/inbox/platform/inbox/inbox.options.ts.tpl +2 -0
- package/templates/be/inbox/platform/inbox/inbox.port.ts.tpl +10 -0
- package/templates/be/inbox/platform/inbox/inbox.service.spec.ts.tpl +41 -0
- package/templates/be/inbox/platform/inbox/inbox.service.ts.tpl +19 -0
- package/templates/be/inbox/platform/inbox/index.ts.tpl +3 -0
- package/templates/be/inbox/platform/inbox/persistence/inbox.sql.ts.tpl +7 -0
- package/templates/be/inbox/platform/migration.sql.tpl +48 -0
- package/templates/be/inbox/service.spec.ts.tpl +49 -20
- package/templates/be/inbox/service.ts.tpl +27 -16
- package/templates/be/inbox/sql.ts.tpl +2 -2
- package/templates/be/inbox/webhook-door.spec.ts.tpl +3 -3
- package/templates/be/inbox/webhook-door.ts.tpl +4 -3
- package/templates/be/patterns/api/feature.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/api/feature.module.ts.tpl +2 -1
- package/templates/be/patterns/api/feature.options.ts.tpl +2 -0
- package/templates/be/patterns/api/graphql.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/api/graphql.module.ts.tpl +3 -2
- package/templates/be/patterns/api/graphql.options.ts.tpl +2 -0
- package/templates/be/patterns/cli/group.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/cli/group.module.ts.tpl +2 -1
- package/templates/be/patterns/cli/group.options.ts.tpl +2 -0
- package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +0 -3
- package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +0 -2
- package/templates/be/patterns/jobs/job.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.module.ts.tpl +2 -1
- package/templates/be/patterns/jobs/job.options.ts.tpl +2 -0
- package/templates/be/patterns/jobs/job.queue.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.queue.module.ts.tpl +6 -3
- package/templates/be/patterns/jobs/job.queue.options.ts.tpl +2 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +3 -1
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +25 -9
- package/templates/be/patterns/queues/platform/queue.config.ts.tpl +1 -1
- package/templates/be/patterns/queues/platform/queue.index.ts.tpl +1 -1
- package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +2 -2
- package/templates/be/patterns/queues/platform/queue.module.ts.tpl +11 -0
- package/templates/be/patterns/queues/platform/queue.options.ts.tpl +10 -0
- package/templates/be/patterns/queues/queue.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/queues/queue.module.ts.tpl +2 -1
- package/templates/be/patterns/queues/queue.options.ts.tpl +2 -0
- package/templates/be/patterns/reactors/message.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/reactors/message.module.ts.tpl +6 -3
- package/templates/be/patterns/reactors/message.options.ts.tpl +2 -0
- package/templates/be/patterns/reactors/reactor.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/reactors/reactor.module.ts.tpl +2 -1
- package/templates/be/patterns/reactors/reactor.options.ts.tpl +2 -0
- package/templates/be/patterns/realtime/channel.gateway.spec.ts.tpl +188 -0
- package/templates/be/patterns/realtime/channel.gateway.ts.tpl +22 -0
- package/templates/be/patterns/realtime/channel.graphql.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +2 -1
- package/templates/be/patterns/realtime/channel.graphql.options.ts.tpl +2 -0
- package/templates/be/patterns/realtime/channel.websocket.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.websocket.module.ts.tpl +110 -0
- package/templates/be/patterns/realtime/channel.websocket.options.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.message.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/saga/saga.message.module.ts.tpl +6 -3
- package/templates/be/patterns/saga/saga.message.options.ts.tpl +2 -0
- package/templates/be/patterns/saga/saga.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/saga/saga.module.ts.tpl +2 -1
- package/templates/be/patterns/saga/saga.options.ts.tpl +2 -0
- package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +3 -3
- package/templates/be/patterns/webhooks/webhook.door.ts.tpl +3 -3
- package/templates/be/patterns/webhooks/webhook.http.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +2 -1
- package/templates/be/patterns/webhooks/webhook.http.options.ts.tpl +2 -0
- package/templates/be/platform/graphql/localize-errors.mapper.spec.ts +80 -26
- package/templates/be/platform/graphql/localize-errors.mapper.ts +2 -5
- package/templates/be/skeleton/apps/__app__/src/__app__.env.ts +21 -0
- package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +1 -1
- package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -45
- package/templates/be/skeleton/apps/__app__/src/compose/api.ts +4 -0
- package/templates/be/skeleton/apps/__app__/src/compose/domain.ts +11 -0
- package/templates/be/skeleton/apps/__app__/src/compose/platform.ts +44 -0
- package/templates/be/skeleton/apps/__app__/src/compose/system.ts +5 -0
- package/templates/be/skeleton/apps/__app__/src/compose/webhooks.ts +4 -0
- package/templates/be/skeleton/apps/__app__/src/main.ts +18 -10
- package/templates/be/skeleton/apps/cli/src/app.module.ts +3 -13
- package/templates/be/skeleton/apps/cli/src/cli.env.ts +13 -0
- package/templates/be/skeleton/apps/cli/src/cli.options.ts +7 -17
- package/templates/be/skeleton/apps/cli/src/compose/cli.ts +5 -0
- package/templates/be/skeleton/apps/cli/src/compose/platform.ts +24 -0
- package/templates/be/skeleton/apps/cli/src/main.ts +3 -2
- package/templates/be/skeleton/src/features/api/system-health/application/check-readiness.contracts.ts +2 -0
- package/templates/be/skeleton/src/features/api/system-health/application/check-readiness.handler.ts +22 -0
- package/templates/be/skeleton/src/features/api/system-health/application/check-readiness.query.ts +11 -0
- package/templates/be/skeleton/src/features/api/system-health/system-health.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/api/system-health/system-health.module.ts +5 -3
- package/templates/be/skeleton/src/features/api/system-health/system-health.options.ts +2 -0
- package/templates/be/skeleton/src/features/api/system-health/transport/http/ready.controller.ts +19 -0
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.module.ts +8 -3
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/cli.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/cli/cli.module.ts +3 -2
- package/templates/be/skeleton/src/features/cli/cli.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +2 -1
- package/templates/be/skeleton/src/features/cli/migrate/migrate.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +2 -1
- package/templates/be/skeleton/src/features/cli/seed/seed.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +5 -6
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +56 -4
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.ts +36 -5
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +39 -8
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.ts +14 -8
- package/templates/be/skeleton/src/modules/domain/identity/credential.contracts.ts +26 -0
- package/templates/be/skeleton/src/modules/domain/identity/credential.guard.spec.ts +119 -0
- package/templates/be/skeleton/src/modules/domain/identity/credential.guard.ts +43 -0
- package/templates/be/skeleton/src/modules/domain/identity/identity.contracts.ts +16 -0
- package/templates/be/skeleton/src/modules/domain/identity/identity.decorators.ts +18 -1
- package/templates/be/skeleton/src/modules/domain/identity/identity.module.ts +22 -4
- package/templates/be/skeleton/src/modules/domain/identity/identity.options.ts +8 -2
- package/templates/be/skeleton/src/modules/domain/identity/index.ts +1 -0
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +6 -6
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +11 -4
- package/templates/be/skeleton/src/modules/platform/database/database-probe.service.spec.ts +32 -0
- package/templates/be/skeleton/src/modules/platform/database/database-probe.service.ts +14 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module.ts +7 -1
- package/templates/be/skeleton/src/modules/platform/database/index.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +8 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +25 -6
- package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +16 -6
- package/templates/be/skeleton/src/modules/platform/http-security/edge-security.service.spec.ts +130 -0
- package/templates/be/skeleton/src/modules/platform/http-security/edge-security.service.ts +58 -0
- package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +3 -0
- package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -4
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +16 -10
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +3 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/http-security/index.ts +5 -0
- package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +12 -5
- package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +13 -8
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.contracts.ts +5 -0
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.decorators.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.service.spec.ts +86 -0
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.service.ts +39 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +139 -131
- package/templates/be/skeleton/src/modules/platform/i18n/index.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +91 -67
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +5 -4
- package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +0 -2
- package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +20 -6
- package/templates/be/skeleton/src/modules/platform/primitives/sequence.policy.spec.ts +16 -4
- package/templates/be/skeleton/src/modules/platform/retry/index.ts +3 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.module.ts +19 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.options.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.port.ts +11 -0
- package/templates/be/skeleton/src/modules/platform/retry/system-timer.service.spec.ts +36 -0
- package/templates/be/skeleton/src/modules/platform/retry/system-timer.service.ts +10 -0
- package/templates/be/skeleton/src/tests/contract/http-security/http-security.contract-spec.ts +54 -0
- package/templates/be/skeleton-lite/apps/api/src/api.env.ts +25 -0
- package/templates/be/skeleton-lite/apps/api/src/api.options.ts +1 -1
- package/templates/be/skeleton-lite/apps/api/src/app.module.ts +18 -58
- package/templates/be/skeleton-lite/apps/api/src/compose/api.ts +4 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/domain.ts +10 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/integrations.ts +16 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/platform.ts +47 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/system.ts +5 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/webhooks.ts +4 -0
- package/templates/be/skeleton-lite/apps/api/src/main.ts +5 -13
- package/templates/be/skeleton-lite/apps/cli/src/cli.env.ts +17 -0
- package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +12 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.spec.ts +71 -5
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +29 -2
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.spec.ts +68 -15
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +14 -9
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +9 -2
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +16 -1
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +19 -4
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +5 -1
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +2 -1
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +0 -3
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.spec.ts +17 -5
- package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +24 -13
- package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +5 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/errors/database.error.ts +16 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +3 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +5 -2
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +4 -1
- package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +1 -1
- package/templates/be/skeleton-lite/src/modules/platform/logging/logging.log-events.ts +7 -0
- package/templates/be/skeleton-lite/src/tests/fixtures/builders/api.builder.ts +29 -0
- package/templates/be/skeleton-lite/src/tests/fixtures/builders/cli.builder.ts +16 -0
- package/templates/be/table/api/feature.module-definition.ts.tpl +6 -0
- package/templates/be/table/api/feature.module.ts.tpl +2 -1
- package/templates/be/table/api/feature.options.ts.tpl +2 -0
- package/templates/be/table/api/graphql.module-definition.ts.tpl +6 -0
- package/templates/be/table/api/graphql.module.ts.tpl +3 -2
- package/templates/be/table/api/graphql.options.ts.tpl +2 -0
- package/templates/be/table/migration.sql.tpl +1 -0
- package/templates/be/upgrade-full/apps/cli/src/app.module.ts +4 -6
- package/templates/be/upgrade-full/apps/cli/src/cli.env.ts +7 -0
- package/templates/be/upgrade-full/apps/cli/src/compose/cli.ts +5 -0
- package/templates/be/upgrade-full/apps/cli/src/compose/platform.ts +9 -0
- package/templates/be/upgrade-full/apps/cli/src/main.ts +3 -0
- package/templates/be/upgrade-full/src/features/cli/cli.module.ts +3 -2
- package/templates/fe/auth/supabase-client.ts.tpl +34 -0
- package/templates/fe/skeleton/apps/__app__/src/app/auth/callback/route.ts +11 -0
- package/templates/fe/skeleton/apps/__app__/src/components/blocks/SignInForm/index.tsx +6 -1
- package/templates/fe/skeleton/apps/__app__/src/components/leaves/Icon/index.tsx +4 -0
- package/templates/fe/skeleton/apps/__app__/src/features/overlays/AppGuideOverlay/component.tsx +31 -0
- package/templates/fe/skeleton/apps/__app__/src/features/overlays/AppGuideOverlay/index.tsx +24 -0
- package/templates/fe/skeleton/apps/__app__/src/hooks/auth/useSession.ts +6 -1
- package/templates/fe/skeleton/apps/__app__/src/hooks/auth/useSignOut.ts +3 -4
- package/templates/fe/skeleton/apps/__app__/src/hooks/zustand/appGuide/index.ts +1 -0
- package/templates/fe/skeleton/apps/__app__/src/hooks/zustand/appGuide/store.ts +15 -0
- package/templates/fe/skeleton/apps/__app__/src/modules/auth/pkce-client.ts +18 -0
- package/templates/fe/skeleton/apps/__app__/src/modules/auth/server.ts +19 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +7 -1
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/en.json +57 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +6 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/en.json +31 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +1 -1
- package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +1 -0
- package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/client.ts +1 -34
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +7 -1
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/en.json +57 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +30 -24
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +1 -1
- package/templates/fe/transport/graphql/clients/clients/auth.ts +1 -1
- package/templates/fe/transport/graphql/clients/links/locale.ts +2 -2
- package/upgrade/check.mjs +3 -1
- package/upgrade/file-state.mjs +68 -0
- package/upgrade/index.mjs +58 -94
- package/runtime/scripts/api/git/log.mjs +0 -5
- package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +0 -55
|
@@ -12,7 +12,7 @@ appliesTo:
|
|
|
12
12
|
family: be
|
|
13
13
|
# The slot ids this topic teaches (knowledge/hfs/slots.yaml); scripts/gates/read-digest.mjs inverts these
|
|
14
14
|
# into the READ-step slot -> pattern-topic map (knowledge/op-gate.yaml kinds), each slot's topics in index.yaml order.
|
|
15
|
-
slots: [be.feature, be.feature.application]
|
|
15
|
+
slots: [be.feature, be.feature.application, be.app.api]
|
|
16
16
|
provenance:
|
|
17
17
|
reviewedAt: 2026-10-02
|
|
18
18
|
sources:
|
|
@@ -21,6 +21,7 @@ provenance:
|
|
|
21
21
|
- knowledge/hfs/rules.yaml
|
|
22
22
|
- owner-locked BE convention 2026-09-30
|
|
23
23
|
- owner decision 2026-10-02 (features grouped by trigger kind; synchronous inside a context)
|
|
24
|
+
- owner ruling 2026-10-14 (app composition standard: options, compose/<area>.ts groups, budgets)
|
|
24
25
|
- https://docs.nestjs.com/recipes/cqrs
|
|
25
26
|
limitations: |-
|
|
26
27
|
Static checks prove the shape of a feature, a message, its handler and the dispatch, and that SQL touches only tables its
|
|
@@ -245,10 +246,79 @@ rules:
|
|
|
245
246
|
manual:
|
|
246
247
|
- Confirm the spec asserts the error code of each refusal, not only a status.
|
|
247
248
|
relatedExamples: [api]
|
|
249
|
+
- id: BE-API-4
|
|
250
|
+
title: An api app parses env separately and composes in area groups; its options hold values and port bindings only
|
|
251
|
+
kind: mandatory
|
|
252
|
+
hfsRules: [R245, R246, R32, R45, R43, R265, R289]
|
|
253
|
+
requirement: |-
|
|
254
|
+
An app's `src/` (slot `be.app.api`, and alike `be.app.worker` and `be.app.cli`) holds five app roles, each within the
|
|
255
|
+
line budget its slot names (owner ruling 2026-10-14):
|
|
256
|
+
- `main.ts` (80 lines) builds `EnvSource` once, imports and calls `read<App>Env` from `<app>.env.ts`, builds the options
|
|
257
|
+
and boots the app.
|
|
258
|
+
- `<app>.env.ts` (150) exports an explicit typed `<App>Env` interface and `read<App>Env(env: EnvSource): <App>Env`
|
|
259
|
+
(for example `ApiEnv` and `readApiEnv`). It holds fail-fast environment parsing only, via the app's `EnvSource` and
|
|
260
|
+
unchanged capability `parse<C>Config` helpers, with no localhost or default host fallback. Secrets use `env.secret`:
|
|
261
|
+
`EnvSource` resolves `<NAME>_FILE` first for `.starcistacks` custody, then plain `<NAME>` when the file key is absent.
|
|
262
|
+
It holds no logic, module composition, business code or feature imports. Only this app file and `main.ts` may read
|
|
263
|
+
`process.env` or `EnvSource`; `platform/config` owns the standard `EnvSource` reader. The role name stays
|
|
264
|
+
`<app>.env.ts`, never `env.ts`; its interface declares its own readonly parsed members, such as
|
|
265
|
+
`readonly server: ReturnType<typeof parseServerConfig>`, structurally compatible with the app's options.
|
|
266
|
+
- `<app>.options.ts` (200) holds the env-derived values plus its port bindings: provider maps such as
|
|
267
|
+
`{ approvalGate: ApprovalGateAdapter }`, with no environment parsing or reads of `process.env` or `EnvSource`.
|
|
268
|
+
Neither it nor `<app>.env.ts` holds an array
|
|
269
|
+
listing `*Module` classes, module or queue registrations (`register`, `forRoot`, `registerQueue`) or scheduler entries,
|
|
270
|
+
or an `imports`, `modules`, `schedulers` or `processors` list. The env file also refuses standalone module or queue
|
|
271
|
+
registration calls (`BE_APP_OPTIONS_COMPOSITION`).
|
|
272
|
+
- `compose/<area>.ts` (120) is a composition group: it exports explicitly typed module, DynamicModule, Provider, queue or
|
|
273
|
+
scheduler lists and maps for one area of the app (the platform, the
|
|
274
|
+
background mechanisms with their message and queue doors, a product area), as a function of the options when it needs
|
|
275
|
+
them, and the providers of the area's global ports when it has any. It is composition only: no business logic, no
|
|
276
|
+
environment read (no `parse<C>Config`, `process.env` or `EnvSource` reads), and its `X.register({ isGlobal: true, ...options.x })` calls
|
|
277
|
+
count as the app root's registrations (R45).
|
|
278
|
+
- `app.module.ts` (250) imports the groups and spreads them into its `imports` (`...platformModules(options)`); its own
|
|
279
|
+
providers bind only the app-wide guards and filter. Module-list literals belong in the compose groups.
|
|
280
|
+
Resolved composition types establish these roles even when imports are aliased, a registration is saved to a constant,
|
|
281
|
+
or scheduler definitions use a typed constant array. `starci app add` writes and updates the generated feature's typed
|
|
282
|
+
area group. A compose group holds no business arrow, branch or other decision that belongs in a tested module.
|
|
283
|
+
A file over its budget is `BE_APP_COMPOSITION_BUDGET`; the budget is absolute, so an app root that outgrows 250 lines
|
|
284
|
+
moves an area into a new group, never into the env or options file. An entrypoint over 80 moves its parsing into the env file.
|
|
285
|
+
rationale: |-
|
|
286
|
+
A long app root invites moving its module lists into the options file, which then mixes configuration with composition
|
|
287
|
+
and grows without a bound. One group per area keeps each composition reviewable, the options pure data, and the root a
|
|
288
|
+
table of contents. The env file keeps typed, fail-fast parsing visible while the entrypoint stays within 80 lines.
|
|
289
|
+
cases:
|
|
290
|
+
- id: case-1
|
|
291
|
+
when: A new api app is scaffolded
|
|
292
|
+
write: 'apps/api/src/compose/platform.ts exports platformModules(options) (clock, logging, i18n, errors, cqrs, http security, database), and app.module.ts spreads ...platformModules(options) before the domain modules and the guards.'
|
|
293
|
+
- id: case-2
|
|
294
|
+
when: The app root passes 250 lines because every module is listed in it
|
|
295
|
+
write: 'Move one area into apps/<app>/src/compose/<area>.ts (for example compose/background.ts with the event bus, the queue and its schedulers, the jobs and the message and queue doors) and spread it in app.module.ts.'
|
|
296
|
+
- id: case-3
|
|
297
|
+
when: 'api.options.ts exports `modules: [...]`, a `BullModule.registerQueue(...)` list or `schedulers: [orderExpirySchedulerOf(...)]`'
|
|
298
|
+
write: 'Refused (BE_APP_OPTIONS_COMPOSITION): keep only the parsed values (orderExpiry: { everyMs, olderThanMs }) and the port map in the options; the list goes into compose/<area>.ts.'
|
|
299
|
+
- id: case-4
|
|
300
|
+
when: An api app reads capability configuration
|
|
301
|
+
write: 'api.env.ts exports interface ApiEnv and readApiEnv(env: EnvSource): ApiEnv (at most 150 lines); main.ts passes its EnvSource to that reader and builds AppOptions from the parsed values and port bindings within 80 lines. No module list or feature import goes into api.env.ts.'
|
|
302
|
+
verification:
|
|
303
|
+
automated:
|
|
304
|
+
- BE_APP_OPTIONS_COMPOSITION
|
|
305
|
+
- BE_APP_COMPOSITION_BUDGET
|
|
306
|
+
- BE_APP_COMPOSITION_ONLY
|
|
307
|
+
- BE_APP_BUSINESS_ROLE
|
|
308
|
+
- BE_MODULE_SHAPE
|
|
309
|
+
- BE_MODULE_HANDLER_REGISTRATION
|
|
310
|
+
- BE_MODULE_PROVIDER_REREGISTRATION
|
|
311
|
+
- BE_CONFIG_OWNER
|
|
312
|
+
- BE_COMPOSITION_UNTYPED
|
|
313
|
+
- BE_APP_ENV_REQUIRED
|
|
314
|
+
- BE_APP_MODULE_LIST_INLINE
|
|
315
|
+
manual:
|
|
316
|
+
- Confirm each group is one area of the app and holds no decision a capability should own.
|
|
317
|
+
relatedExamples: [api]
|
|
248
318
|
- id: BE-OPERATIONS-1
|
|
249
319
|
title: A versioned operation is declared once in the app's typed operation table
|
|
250
320
|
kind: mandatory
|
|
251
|
-
hfsRules: [R95, R88, R23]
|
|
321
|
+
hfsRules: [R95, R88, R23, R278]
|
|
252
322
|
requirement: |-
|
|
253
323
|
A versioned operation `<name>@<version>` (for example `sales.policy@1`) that an app serves over one operation route is
|
|
254
324
|
declared once, in the app's operation table `be/apps/<app>/src/operations.ts`, which exports `OPERATIONS`. The table is made by
|
|
@@ -261,6 +331,8 @@ rules:
|
|
|
261
331
|
outcome }` out, `outcome` being the canon Outcome `{ kind: "ok", value }` or `{ kind: "refused", code }`. `starci app emit`
|
|
262
332
|
derives `be/contracts/<app>/openapi.json` (OpenAPI 3.1, `x-operation: "<name>@<version>"`, a oneOf over the operations) from the
|
|
263
333
|
table with the type checker, and the full `starci app check` fails when the committed file is stale.
|
|
334
|
+
A public REST operation in either edition belongs to this nonempty table, and its route decorator supplies its own
|
|
335
|
+
versioned-operation evidence; a class-level reference does not justify a route absent from the table.
|
|
264
336
|
rationale: |-
|
|
265
337
|
The operation set of an app is a contract the front end (`fe/`, through the root codegen) and other consumers generate a client from. A name-to-string registry with `unknown`
|
|
266
338
|
bodies and results forces every client to hand-type the wire; one typed table gives the client generator, the route and the
|
|
@@ -282,6 +354,8 @@ rules:
|
|
|
282
354
|
- BE_OPERATION_CONTRACT
|
|
283
355
|
- BE_TRANSPORT_SHAPE
|
|
284
356
|
- HFS_CONTRACT_SNAPSHOT_DRIFT
|
|
357
|
+
- BE_REST_DOOR_EVIDENCE
|
|
358
|
+
- BE_REST_ROUTE_UNDECLARED
|
|
285
359
|
manual:
|
|
286
360
|
- Confirm each refusal code is one the operation's owner can actually answer.
|
|
287
361
|
relatedExamples: [api]
|
|
@@ -291,6 +365,14 @@ files:
|
|
|
291
365
|
role: The public surface of the feature; only apps import it.
|
|
292
366
|
rules: [BE_PUBLIC_SURFACE]
|
|
293
367
|
template: api/feature.index.ts.tpl
|
|
368
|
+
- path: src/features/api/<feature>/<feature>.options.ts
|
|
369
|
+
slot: be.feature
|
|
370
|
+
template: api/feature.options.ts.tpl
|
|
371
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
372
|
+
- path: src/features/api/<feature>/<feature>.module-definition.ts
|
|
373
|
+
slot: be.feature
|
|
374
|
+
template: api/feature.module-definition.ts.tpl
|
|
375
|
+
role: The configurable-module base of the module, registered as register.
|
|
294
376
|
- path: src/features/api/<feature>/<feature>.module.ts
|
|
295
377
|
slot: be.feature
|
|
296
378
|
role: Composes the application handlers.
|
|
@@ -325,6 +407,14 @@ files:
|
|
|
325
407
|
slot: be.transport.graphql
|
|
326
408
|
role: Maps the input to the request and the result to the type.
|
|
327
409
|
template: api/graphql.mapper.ts.tpl
|
|
410
|
+
- path: src/features/api/<feature>/transport/graphql/<feature>-graphql.options.ts
|
|
411
|
+
slot: be.transport.graphql
|
|
412
|
+
template: api/graphql.options.ts.tpl
|
|
413
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
414
|
+
- path: src/features/api/<feature>/transport/graphql/<feature>-graphql.module-definition.ts
|
|
415
|
+
slot: be.transport.graphql
|
|
416
|
+
template: api/graphql.module-definition.ts.tpl
|
|
417
|
+
role: The configurable-module base of the module, registered as register.
|
|
328
418
|
- path: src/features/api/<feature>/transport/graphql/<feature>-graphql.module.ts
|
|
329
419
|
slot: be.transport.graphql
|
|
330
420
|
role: One module for the whole GraphQL transport of the feature.
|
|
@@ -41,8 +41,16 @@ rules:
|
|
|
41
41
|
nest-commander and never serves: no `NestFactory.create*`, no `.listen()`, no microservice connection, no
|
|
42
42
|
`@nestjs/platform-*` adapter and no `@nestjs/microservices`. `apps/cli/src/app.module.ts` composes the platform modules
|
|
43
43
|
the commands need (the database capability over every connection with its entities and migrations, like an api app) and
|
|
44
|
-
the static cli feature root module `CliModule
|
|
45
|
-
|
|
44
|
+
the static cli feature root module `CliModule`. `apps/cli/src/cli.env.ts` (at most 150 lines) exports an explicit typed
|
|
45
|
+
`CliEnv` interface and `readCliEnv(env: EnvSource): CliEnv` using `EnvSource` and unchanged capability parse helpers.
|
|
46
|
+
The interface declares its own readonly parsed members with types matching those helpers; the options factory binds
|
|
47
|
+
these values to its connection list.
|
|
48
|
+
It holds fail-fast parsing only, with no localhost or default host fallback, logic, module composition, business code
|
|
49
|
+
or feature imports. Secrets use `env.secret`, with `<NAME>_FILE` first for `.starcistacks` custody, then plain `<NAME>`
|
|
50
|
+
when the file key is absent. `main.ts` (at most 80 lines) builds `EnvSource` once and imports and calls `readCliEnv`.
|
|
51
|
+
Only these two app files may read the environment; the role name stays `cli.env.ts`, never `env.ts`.
|
|
52
|
+
`apps/cli/src/cli.options.ts` carries the env-derived values and port bindings, the connections it migrates among them,
|
|
53
|
+
with no parsing or reads of `process.env` or `EnvSource`; compose groups never read the environment either.
|
|
46
54
|
rationale: |-
|
|
47
55
|
One image for every operator action gives one place to find, deploy and audit them, and a process that never listens
|
|
48
56
|
cannot become a second, unguarded door into the application.
|
|
@@ -52,7 +60,9 @@ rules:
|
|
|
52
60
|
write: |-
|
|
53
61
|
// be/apps/cli/src/main.ts
|
|
54
62
|
async function bootstrap(): Promise<void> {
|
|
55
|
-
|
|
63
|
+
const env = EnvSource.fromProcess()
|
|
64
|
+
const options = createCliAppOptions(readCliEnv(env))
|
|
65
|
+
await CommandFactory.run(AppModule.register(options), new JsonLinesLogger())
|
|
56
66
|
}
|
|
57
67
|
void bootstrap()
|
|
58
68
|
- id: case-2
|
|
@@ -60,7 +70,7 @@ rules:
|
|
|
60
70
|
write: 'Refused (BE_CLI_BOOTSTRAP): the cli app boots only through CommandFactory.run.'
|
|
61
71
|
- id: case-3
|
|
62
72
|
when: A back end declares a connection and has no apps/cli
|
|
63
|
-
write: 'Refused (BE_CLI_REQUIRED): add be/apps/cli with main.ts, app.module.ts, cli.options.ts and its Dockerfile, declared as { "name": "cli", "kind": "cli" } in hfs.json sides.be.apps.'
|
|
73
|
+
write: 'Refused (BE_CLI_REQUIRED): add be/apps/cli with main.ts, app.module.ts, cli.env.ts, cli.options.ts and its Dockerfile, declared as { "name": "cli", "kind": "cli" } in hfs.json sides.be.apps.'
|
|
64
74
|
verification:
|
|
65
75
|
automated:
|
|
66
76
|
- BE_CLI_REQUIRED
|
|
@@ -71,14 +81,15 @@ rules:
|
|
|
71
81
|
- id: BE-CLI-2
|
|
72
82
|
title: Commands live in the cli feature root as groups and sub-commands
|
|
73
83
|
kind: mandatory
|
|
74
|
-
hfsRules: [R149]
|
|
84
|
+
hfsRules: [R149, R295]
|
|
75
85
|
requirement: |-
|
|
76
86
|
A nest-commander command (`@Command` or `@SubCommand`) is declared only in the cli feature root `src/features/cli/`
|
|
77
87
|
(slot `be.cli`). The root holds `index.ts` and `cli.module.ts` and one folder per group: `<group>/<group>.cli.ts` (the
|
|
78
88
|
group `@Command` with its `subCommands`), `<group>/<group>.module.ts` and `<group>/subs/<name>.cli.ts` (a `@SubCommand`
|
|
79
|
-
class extending `CommandRunner`), one command per file.
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
class extending `CommandRunner`), one command per file. Every module of the cli feature root has a module definition
|
|
90
|
+
and an options file beside it (owner:module-definition-everywhere, R295) and declares only its `@Module({ imports,
|
|
91
|
+
providers })` metadata, with no `register` override: `CliModule` imports each group module as `<Group>Module.register({})`
|
|
92
|
+
and a group module provides its commands. A command makes its one delegating call on an
|
|
82
93
|
injected runner service of the modules (the migrate and seed runners of `platform/database`) and takes its options
|
|
83
94
|
from a nest-commander `@Option` of its own (`cli seed run --env <name>`). The suffix is
|
|
84
95
|
`.cli.ts`, because `.command.ts` is the CQRS message (api.yaml).
|
|
@@ -92,6 +103,7 @@ rules:
|
|
|
92
103
|
verification:
|
|
93
104
|
automated:
|
|
94
105
|
- BE_CLI_COMMAND_SHAPE
|
|
106
|
+
- BE_MODULE_DEFINITION_MISSING
|
|
95
107
|
manual: []
|
|
96
108
|
relatedExamples: [cli]
|
|
97
109
|
- id: BE-CLI-3
|
|
@@ -196,10 +208,18 @@ files:
|
|
|
196
208
|
- path: apps/cli/src/cli.options.ts
|
|
197
209
|
slot: be.app.cli
|
|
198
210
|
optional: true
|
|
199
|
-
role:
|
|
211
|
+
role: env-derived values and port bindings without parsing, the connection list it migrates among them
|
|
200
212
|
rules:
|
|
201
213
|
- BE_CLI_REQUIRED
|
|
202
214
|
- BE_SCHEMA_AUTHORITY
|
|
215
|
+
- path: apps/cli/src/cli.env.ts
|
|
216
|
+
slot: be.app.cli
|
|
217
|
+
optional: true
|
|
218
|
+
role: 'exports interface CliEnv and readCliEnv(env: EnvSource): CliEnv; fail-fast parsing only, no localhost fallback, logic, composition, business code or feature imports; secrets use env.secret with _FILE first'
|
|
219
|
+
rules:
|
|
220
|
+
- BE_CONFIG_OWNER
|
|
221
|
+
- BE_APP_OPTIONS_COMPOSITION
|
|
222
|
+
- BE_APP_COMPOSITION_BUDGET
|
|
203
223
|
- path: src/features/cli/index.ts
|
|
204
224
|
slot: be.cli
|
|
205
225
|
optional: true
|
|
@@ -269,6 +289,14 @@ files:
|
|
|
269
289
|
slot: be.cli
|
|
270
290
|
role: the unit spec of the group, beside it
|
|
271
291
|
template: cli/group.cli.spec.ts.tpl
|
|
292
|
+
- path: src/features/cli/<group>/<group>.options.ts
|
|
293
|
+
slot: be.cli
|
|
294
|
+
template: cli/group.options.ts.tpl
|
|
295
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
296
|
+
- path: src/features/cli/<group>/<group>.module-definition.ts
|
|
297
|
+
slot: be.cli
|
|
298
|
+
template: cli/group.module-definition.ts.tpl
|
|
299
|
+
role: The configurable-module base of the module, registered as register.
|
|
272
300
|
- path: src/features/cli/<group>/<group>.module.ts
|
|
273
301
|
slot: be.cli
|
|
274
302
|
role: "the static group module: provides its command and sub-commands"
|
|
@@ -283,7 +283,7 @@ files:
|
|
|
283
283
|
role: "The consumed event's e2e flow; titles event-bus/<scenario>: ... prove the pattern."
|
|
284
284
|
spec: event-bus/atomic-with-transaction, event-bus/relay-only-after-commit, event-bus/redelivery-then-dead-letter, event-bus/duplicate-delivery-is-a-noop
|
|
285
285
|
rules: [BE_PATTERN_SPEC_MISSING]
|
|
286
|
-
# Edition lite (owner ruling 2026-10-
|
|
286
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports and rules, a Supabase adapter behind them.
|
|
287
287
|
liteAdapter:
|
|
288
288
|
summary: >-
|
|
289
289
|
Under lite the event bus keeps typed events, the vendored contract, publish(event, tx) in the domain transaction, the outbox,
|
|
@@ -295,6 +295,6 @@ liteAdapter:
|
|
|
295
295
|
- {port: EventConsumer (platform/event-bus), adapter: "pgmq.read with a visibility timeout, the inbox claim on the event id, pgmq.delete on success, pgmq.archive as the dead letter"}
|
|
296
296
|
forbids: [kafkajs]
|
|
297
297
|
proof: >-
|
|
298
|
-
Unit specs as full;
|
|
299
|
-
|
|
298
|
+
Unit specs as full; declaring event-bus requires integration specs titled `event-bus/<scenario>: ...` for every declared
|
|
299
|
+
scenario on `starci supabase start` (R284). Lite has no e2e world.
|
|
300
300
|
see: [knowledge/patterns/be/supabase-queues.yaml]
|
|
@@ -228,9 +228,25 @@ files:
|
|
|
228
228
|
- path: src/features/jobs/<job>/index.ts
|
|
229
229
|
slot: be.feature.jobs
|
|
230
230
|
template: jobs/job.index.ts.tpl
|
|
231
|
+
- path: src/features/jobs/<job>/<job>.options.ts
|
|
232
|
+
slot: be.feature.jobs
|
|
233
|
+
template: jobs/job.options.ts.tpl
|
|
234
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
235
|
+
- path: src/features/jobs/<job>/<job>.module-definition.ts
|
|
236
|
+
slot: be.feature.jobs
|
|
237
|
+
template: jobs/job.module-definition.ts.tpl
|
|
238
|
+
role: The configurable-module base of the module, registered as register.
|
|
231
239
|
- path: src/features/jobs/<job>/<job>.module.ts
|
|
232
240
|
slot: be.feature.jobs
|
|
233
241
|
template: jobs/job.module.ts.tpl
|
|
242
|
+
- path: src/features/jobs/<job>/transport/queue/<job>-queue.options.ts
|
|
243
|
+
slot: be.feature.jobs.queue
|
|
244
|
+
template: jobs/job.queue.options.ts.tpl
|
|
245
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
246
|
+
- path: src/features/jobs/<job>/transport/queue/<job>-queue.module-definition.ts
|
|
247
|
+
slot: be.feature.jobs.queue
|
|
248
|
+
template: jobs/job.queue.module-definition.ts.tpl
|
|
249
|
+
role: The configurable-module base of the module, registered as register.
|
|
234
250
|
- path: src/features/jobs/<job>/transport/queue/<job>-queue.module.ts
|
|
235
251
|
slot: be.feature.jobs.queue
|
|
236
252
|
template: jobs/job.queue.module.ts.tpl
|
|
@@ -259,7 +275,7 @@ files:
|
|
|
259
275
|
role: "Titles fenced-job/<scenario>: ... prove the pattern."
|
|
260
276
|
spec: fenced-job/claim-bumps-token, fenced-job/zombie-fenced-out, fenced-job/redispatch-isolated
|
|
261
277
|
rules: [BE_PATTERN_SPEC_MISSING]
|
|
262
|
-
# Edition lite (owner ruling 2026-10-
|
|
278
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports and rules, a Supabase adapter behind them.
|
|
263
279
|
liteAdapter:
|
|
264
280
|
summary: >-
|
|
265
281
|
Under lite a fenced job is unchanged: the job row with its fencing token, the atomic claim, guarded writes and run keys. The
|
|
@@ -267,5 +283,7 @@ liteAdapter:
|
|
|
267
283
|
ports:
|
|
268
284
|
- {port: job claim (platform/jobs), adapter: "the same claim SQL through the shared EntityManager; the table comes from supabase/migrations"}
|
|
269
285
|
- {port: processor delivery, adapter: "the lite queue worker (pgmq.read, visibility timeout, archive on dead letter)"}
|
|
270
|
-
proof:
|
|
286
|
+
proof: >-
|
|
287
|
+
Unit specs as full (job-claim.service.spec.ts); declaring fenced-job requires integration specs titled
|
|
288
|
+
`fenced-job/<scenario>: ...` for every declared scenario on `starci supabase start` (R284).
|
|
271
289
|
see: [knowledge/patterns/be/supabase-queues.yaml]
|
|
@@ -176,7 +176,7 @@ files:
|
|
|
176
176
|
role: "Titles projection/<scenario>: ... prove the pattern."
|
|
177
177
|
spec: projection/recompute-is-idempotent, projection/replay-rebuilds
|
|
178
178
|
rules: [BE_PATTERN_SPEC_MISSING]
|
|
179
|
-
# Edition lite (owner ruling 2026-10-
|
|
179
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports and rules, a Supabase adapter behind them.
|
|
180
180
|
liteAdapter:
|
|
181
181
|
summary: >-
|
|
182
182
|
Under lite a projection is unchanged in behaviour (only it writes its table, recompute is idempotent and replayable, readers
|
|
@@ -184,5 +184,7 @@ liteAdapter:
|
|
|
184
184
|
overlay), and it is kept current by a reactor or a job on the lite transport.
|
|
185
185
|
ports:
|
|
186
186
|
- {port: read model table, adapter: "a supabase migration plus <name>.sql.ts and <name>.rows.ts under persistence/"}
|
|
187
|
-
proof:
|
|
187
|
+
proof: >-
|
|
188
|
+
Unit specs as full (the projection is a logic role at 100 per file); declaring projection requires integration specs titled
|
|
189
|
+
`projection/<scenario>: ...` for every declared scenario on `starci supabase start` (R284).
|
|
188
190
|
see: [knowledge/patterns/be/supabase-queues.yaml]
|
|
@@ -216,6 +216,14 @@ files:
|
|
|
216
216
|
- path: src/modules/queues/<queue>/index.ts
|
|
217
217
|
slot: be.queues
|
|
218
218
|
template: queues/queue.index.ts.tpl
|
|
219
|
+
- path: src/modules/queues/<queue>/<queue>.options.ts
|
|
220
|
+
slot: be.queues
|
|
221
|
+
template: queues/queue.options.ts.tpl
|
|
222
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
223
|
+
- path: src/modules/queues/<queue>/<queue>.module-definition.ts
|
|
224
|
+
slot: be.queues
|
|
225
|
+
template: queues/queue.module-definition.ts.tpl
|
|
226
|
+
role: The configurable-module base of the module, registered as register.
|
|
219
227
|
- path: src/modules/queues/<queue>/<queue>.module.ts
|
|
220
228
|
slot: be.queues
|
|
221
229
|
role: The Nest module that provides the typed producer.
|
|
@@ -234,7 +242,7 @@ files:
|
|
|
234
242
|
role: "Titles queue/<scenario>: ... prove the pattern."
|
|
235
243
|
spec: queue/enqueue-atomic-with-transaction, queue/relay-job-id-is-outbox-id, queue/scheduler-fires-once
|
|
236
244
|
rules: [BE_PATTERN_SPEC_MISSING]
|
|
237
|
-
# Edition lite (owner ruling 2026-10-
|
|
245
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports and rules, a Supabase adapter behind them.
|
|
238
246
|
liteAdapter:
|
|
239
247
|
summary: >-
|
|
240
248
|
Under lite the queue pattern is unchanged above the port (producers, the outbox written in the caller's transaction, processors,
|
|
@@ -246,6 +254,6 @@ liteAdapter:
|
|
|
246
254
|
- {port: schedulers, adapter: "a pg_cron job declared in a supabase migration that calls pgmq.send; no BullMQ job scheduler"}
|
|
247
255
|
forbids: [bullmq, "@nestjs/bullmq", redis, ioredis, "@nestjs/schedule"]
|
|
248
256
|
proof: >-
|
|
249
|
-
Unit specs as full (queue-outbox, relay and worker services, the pgmq client against mockEntityManager);
|
|
250
|
-
|
|
257
|
+
Unit specs as full (queue-outbox, relay and worker services, the pgmq client against mockEntityManager); declaring queue
|
|
258
|
+
requires integration specs titled `queue/<scenario>: ...` for every declared scenario on `starci supabase start` (R284).
|
|
251
259
|
see: [knowledge/patterns/be/supabase-queues.yaml]
|
|
@@ -114,6 +114,14 @@ files:
|
|
|
114
114
|
- path: src/features/reactors/<reactor>/index.ts
|
|
115
115
|
slot: be.feature.reactors
|
|
116
116
|
template: reactors/reactor.index.ts.tpl
|
|
117
|
+
- path: src/features/reactors/<reactor>/<reactor>.options.ts
|
|
118
|
+
slot: be.feature.reactors
|
|
119
|
+
template: reactors/reactor.options.ts.tpl
|
|
120
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
121
|
+
- path: src/features/reactors/<reactor>/<reactor>.module-definition.ts
|
|
122
|
+
slot: be.feature.reactors
|
|
123
|
+
template: reactors/reactor.module-definition.ts.tpl
|
|
124
|
+
role: The configurable-module base of the module, registered as register.
|
|
117
125
|
- path: src/features/reactors/<reactor>/<reactor>.module.ts
|
|
118
126
|
slot: be.feature.reactors
|
|
119
127
|
template: reactors/reactor.module.ts.tpl
|
|
@@ -131,6 +139,14 @@ files:
|
|
|
131
139
|
template: reactors/consumer.ts.tpl
|
|
132
140
|
role: The consumer door of one event.
|
|
133
141
|
rules: [BE_EVENT_CONSUMER_SHAPE]
|
|
142
|
+
- path: src/features/reactors/<reactor>/transport/message/<reactor>-message.options.ts
|
|
143
|
+
slot: be.transport.message
|
|
144
|
+
template: reactors/message.options.ts.tpl
|
|
145
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
146
|
+
- path: src/features/reactors/<reactor>/transport/message/<reactor>-message.module-definition.ts
|
|
147
|
+
slot: be.transport.message
|
|
148
|
+
template: reactors/message.module-definition.ts.tpl
|
|
149
|
+
role: The configurable-module base of the module, registered as register.
|
|
134
150
|
- path: src/features/reactors/<reactor>/transport/message/<reactor>-message.module.ts
|
|
135
151
|
slot: be.transport.message
|
|
136
152
|
template: reactors/message.module.ts.tpl
|
|
@@ -138,11 +154,14 @@ files:
|
|
|
138
154
|
- path: src/tests/e2e/<area>/<event>.e2e-spec.ts
|
|
139
155
|
slot: be.tests.e2e
|
|
140
156
|
role: The reactor's event flow through the bus, redelivery included.
|
|
141
|
-
# Edition lite (owner ruling 2026-10-
|
|
157
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports and rules, a Supabase adapter behind them.
|
|
142
158
|
liteAdapter:
|
|
143
159
|
summary: >-
|
|
144
160
|
Under lite a reactor is unchanged: a thin consumer of another context's events that dispatches one command. Its deliveries
|
|
145
161
|
come from the lite event bus (its own pgmq queue per consumer group).
|
|
146
162
|
ports:
|
|
147
163
|
- {port: EventConsumer delivery, adapter: "the reactor's pgmq queue (see event-bus.yaml liteAdapter)"}
|
|
164
|
+
proof: >-
|
|
165
|
+
`starci app check --wiring` proves the composing lite app's module graph with doubles (R272); declaring event-bus requires
|
|
166
|
+
its scenario-titled integration specs on `starci supabase start` (R284), including redelivery through the reactor.
|
|
148
167
|
see: [knowledge/patterns/be/supabase-queues.yaml]
|
|
@@ -155,22 +155,43 @@ files:
|
|
|
155
155
|
slot: be.feature.realtime
|
|
156
156
|
template: realtime/channel.index.ts.tpl
|
|
157
157
|
role: The public surface of the kind folder, the module class an api-kind app composes.
|
|
158
|
+
- path: src/features/realtime/<channel>/transport/graphql/<channel>-graphql.options.ts
|
|
159
|
+
slot: be.feature.realtime.graphql
|
|
160
|
+
template: realtime/channel.graphql.options.ts.tpl
|
|
161
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
162
|
+
- path: src/features/realtime/<channel>/transport/graphql/<channel>-graphql.module-definition.ts
|
|
163
|
+
slot: be.feature.realtime.graphql
|
|
164
|
+
template: realtime/channel.graphql.module-definition.ts.tpl
|
|
165
|
+
role: The configurable-module base of the module, registered as register.
|
|
158
166
|
- path: src/features/realtime/<channel>/transport/graphql/<channel>-graphql.module.ts
|
|
159
167
|
slot: be.feature.realtime.graphql
|
|
160
168
|
template: realtime/channel.graphql.module.ts.tpl
|
|
161
169
|
role: Nest module of the subscription door, composed only by an api-kind app.
|
|
170
|
+
- path: src/features/realtime/<channel>/transport/websocket/<channel>-websocket.options.ts
|
|
171
|
+
slot: be.feature.realtime.websocket
|
|
172
|
+
template: realtime/channel.websocket.options.ts.tpl
|
|
173
|
+
role: The options of the gateway door's module - the cryptographic verifier that authenticates each connection.
|
|
174
|
+
optional: true
|
|
175
|
+
- path: src/features/realtime/<channel>/transport/websocket/<channel>-websocket.module-definition.ts
|
|
176
|
+
slot: be.feature.realtime.websocket
|
|
177
|
+
template: realtime/channel.websocket.module-definition.ts.tpl
|
|
178
|
+
role: The configurable-module base of the gateway door's module, registered as register.
|
|
179
|
+
optional: true
|
|
162
180
|
- path: src/features/realtime/<channel>/transport/websocket/<channel>-websocket.module.ts
|
|
163
181
|
slot: be.feature.realtime.websocket
|
|
182
|
+
template: realtime/channel.websocket.module.ts.tpl
|
|
164
183
|
role: Nest module of the gateway door, composed only by an api-kind app.
|
|
165
184
|
optional: true
|
|
166
185
|
- path: src/features/realtime/<channel>/transport/websocket/<channel>.gateway.ts
|
|
167
186
|
slot: be.feature.realtime.websocket
|
|
187
|
+
template: realtime/channel.gateway.ts.tpl
|
|
168
188
|
role: A socket door (one WebSocketGateway class); exactly one of gateway or subscription per channel file name.
|
|
169
189
|
rules: [BE_REALTIME_SHAPE, BE_REALTIME_WRITES, BE_REALTIME_TOPIC_SCOPE]
|
|
170
190
|
spec: src/features/realtime/<channel>/transport/websocket/<channel>.gateway.spec.ts
|
|
171
191
|
optional: true
|
|
172
192
|
- path: src/features/realtime/<channel>/transport/websocket/<channel>.gateway.spec.ts
|
|
173
193
|
slot: be.feature.realtime.websocket
|
|
194
|
+
template: realtime/channel.gateway.spec.ts.tpl
|
|
174
195
|
role: Unit spec of the gateway beside it.
|
|
175
196
|
optional: true
|
|
176
197
|
- path: src/features/realtime/<channel>/transport/graphql/<channel>.subscription.ts
|
|
@@ -207,7 +228,7 @@ files:
|
|
|
207
228
|
spec: realtime/subscriber-receives-push, realtime/foreign-topic-is-isolated, realtime/disconnect-releases-subscription
|
|
208
229
|
rules: [BE_PATTERN_SPEC_MISSING]
|
|
209
230
|
optional: true
|
|
210
|
-
# Edition lite (owner
|
|
231
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports, door and rules; one instance behind them.
|
|
211
232
|
liteAdapter:
|
|
212
233
|
summary: >-
|
|
213
234
|
Under lite the realtime pattern is the full one: the socket.io gateway of be.feature.realtime.websocket
|
|
@@ -221,6 +242,7 @@ liteAdapter:
|
|
|
221
242
|
- {port: topic scope, adapter: "the room name built from @CurrentPrincipal (BE_REALTIME_TOPIC_SCOPE), as full"}
|
|
222
243
|
forbids: [redis, ioredis, "@socket.io/redis-adapter", graphql-ws, graphql-subscriptions]
|
|
223
244
|
proof: >-
|
|
224
|
-
The gateway's own unit spec (<channel>.gateway.spec.ts) and the hub adapter's spec, as full;
|
|
225
|
-
|
|
245
|
+
The gateway's own unit spec (<channel>.gateway.spec.ts) and the hub adapter's spec, as full; declaring realtime requires
|
|
246
|
+
integration specs titled `realtime/<scenario>: ...` for every declared scenario on `starci supabase start` (R284), using a
|
|
247
|
+
real socket.io client. Lite has no e2e world.
|
|
226
248
|
see: [knowledge/patterns/be/supabase-queues.yaml, knowledge/patterns/fe/realtime.yaml]
|
|
@@ -31,6 +31,14 @@ files:
|
|
|
31
31
|
slot: be.feature.saga
|
|
32
32
|
template: saga/saga.index.ts.tpl
|
|
33
33
|
role: "The public surface of the kind folder: the message module an app composes."
|
|
34
|
+
- path: src/features/saga/<saga>/<saga>.options.ts
|
|
35
|
+
slot: be.feature.saga
|
|
36
|
+
template: saga/saga.options.ts.tpl
|
|
37
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
38
|
+
- path: src/features/saga/<saga>/<saga>.module-definition.ts
|
|
39
|
+
slot: be.feature.saga
|
|
40
|
+
template: saga/saga.module-definition.ts.tpl
|
|
41
|
+
role: The configurable-module base of the module, registered as register.
|
|
34
42
|
- path: src/features/saga/<saga>/<saga>.module.ts
|
|
35
43
|
slot: be.feature.saga
|
|
36
44
|
template: saga/saga.module.ts.tpl
|
|
@@ -120,6 +128,14 @@ files:
|
|
|
120
128
|
role: "A thin door that hands the delivery of the last event, with its `eventId`, to the complete command; the saga takes it through the inbox."
|
|
121
129
|
suffix: consumer
|
|
122
130
|
rules: [R80, R88, R172]
|
|
131
|
+
- path: src/features/saga/<saga>/transport/message/<saga>-message.options.ts
|
|
132
|
+
slot: be.transport.message
|
|
133
|
+
template: saga/saga.message.options.ts.tpl
|
|
134
|
+
role: The options of the module (the configurable module base needs a type); empty until the module takes some.
|
|
135
|
+
- path: src/features/saga/<saga>/transport/message/<saga>-message.module-definition.ts
|
|
136
|
+
slot: be.transport.message
|
|
137
|
+
template: saga/saga.message.module-definition.ts.tpl
|
|
138
|
+
role: The configurable-module base of the module, registered as register.
|
|
123
139
|
- path: src/features/saga/<saga>/transport/message/<saga>-message.module.ts
|
|
124
140
|
slot: be.transport.message
|
|
125
141
|
template: saga/saga.message.module.ts.tpl
|
|
@@ -246,7 +262,7 @@ rules:
|
|
|
246
262
|
manual:
|
|
247
263
|
- Check the injected fault hits the compensation, not only the step before it.
|
|
248
264
|
relatedExamples: [saga]
|
|
249
|
-
# Edition lite (owner ruling 2026-10-
|
|
265
|
+
# Edition lite (R212, owner ruling 2026-10-14): the same ports and rules, a Supabase adapter behind them.
|
|
250
266
|
liteAdapter:
|
|
251
267
|
summary: >-
|
|
252
268
|
Under lite a saga is unchanged: the orchestrator service, the versioned state behind the fenced store, steps and their
|
|
@@ -256,6 +272,7 @@ liteAdapter:
|
|
|
256
272
|
- {port: saga events, adapter: "the lite event-bus adapter (pgmq) - see event-bus.yaml liteAdapter"}
|
|
257
273
|
- {port: saga state store, adapter: "the same table and version fence, created by a supabase migration (no TypeORM entity under lite)"}
|
|
258
274
|
proof: >-
|
|
259
|
-
The orchestrator's unit spec (<saga>.saga.service.spec.ts) as full;
|
|
260
|
-
saga
|
|
275
|
+
The orchestrator's unit spec (<saga>.saga.service.spec.ts) as full; declaring saga requires integration specs titled
|
|
276
|
+
`saga/<scenario>: ...` for every declared scenario on `starci supabase start` (R284), including each compensation path with
|
|
277
|
+
failure injection and the final state read back. The e2e world of R173 remains full-only.
|
|
261
278
|
see: [knowledge/patterns/be/supabase-queues.yaml]
|