@starci/hfs 5.1.0 → 5.2.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 +20 -0
- package/README.md +10 -1
- package/db/postgres.mjs +9 -1
- package/package.json +1 -1
- package/runtime/knowledge/hfs/canon-pins.yaml +30 -9
- package/runtime/knowledge/hfs/fe-stack.yaml +7 -7
- package/runtime/knowledge/hfs/fork-images.yaml +7 -0
- package/runtime/knowledge/hfs/rules.yaml +55 -7
- package/runtime/knowledge/hfs/slots.yaml +75 -24
- package/runtime/modules/kernel/failure-codes.yaml +62 -0
- package/runtime/modules/schemas/application-stacks.schema.yaml +6 -0
- package/runtime/scripts/hfs/architecture/identity.mjs +18 -83
- package/runtime/scripts/hfs/architecture/transport-owner.d.mts +1 -2
- package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -6
- package/runtime/scripts/hfs/manifest-shape.d.mts +1 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +3 -1
- package/runtime/scripts/hfs/rules/a15-findings.mjs +5 -0
- package/runtime/scripts/hfs/rules/stacks-local.d.mts +7 -0
- package/runtime/scripts/hfs/rules/stacks-local.mjs +71 -0
- package/runtime/scripts/hfs/rules/stacks-runtime.mjs +6 -1
- package/runtime/scripts/hfs/rules/stacks-service-images.d.mts +12 -0
- package/runtime/scripts/hfs/rules/stacks-service-images.mjs +120 -0
- package/runtime/scripts/hfs/secret-dev-init.d.mts +11 -0
- package/runtime/scripts/hfs/secret-dev-init.mjs +79 -0
- package/runtime/scripts/hfs/secret.mjs +10 -7
- package/runtime/scripts/hfs/slots.mjs +1 -1
- package/runtime/scripts/hfs/stack-local-config.d.mts +101 -0
- package/runtime/scripts/hfs/stack-local-config.mjs +320 -0
- package/runtime/scripts/hfs/stacks-gate.mjs +1 -1
- package/runtime/scripts/lib/swarm-stack.d.mts +2 -1
- package/runtime/scripts/lib/swarm-stack.mjs +2 -2
- package/scaffold/add-module.d.mts +16 -0
- package/scaffold/add-module.mjs +232 -0
- package/scaffold/add-queue-lite.mjs +49 -0
- package/scaffold/add.mjs +5 -0
- package/scaffold/app.mjs +7 -7
- package/scaffold/module-registry.d.mts +19 -0
- package/scaffold/module-registry.mjs +84 -0
- package/src/main.mjs +23 -2
- package/stack/cli.mjs +6 -1
- package/stack/context.d.mts +15 -0
- package/stack/context.mjs +1 -0
- package/stack/local-cli.d.mts +25 -0
- package/stack/local-cli.mjs +89 -0
- package/stack/local-config.d.mts +17 -0
- package/stack/local-config.mjs +37 -0
- package/stack/local-custody.d.mts +24 -0
- package/stack/local-custody.mjs +109 -0
- package/stack/local-doctor.d.mts +6 -0
- package/stack/local-doctor.mjs +49 -0
- package/stack/local-down.d.mts +8 -0
- package/stack/local-down.mjs +20 -0
- package/stack/local-host.d.mts +42 -0
- package/stack/local-host.mjs +163 -0
- package/stack/local-logs.d.mts +8 -0
- package/stack/local-logs.mjs +32 -0
- package/stack/local-ports.d.mts +7 -0
- package/stack/local-ports.mjs +39 -0
- package/stack/local-prepare.d.mts +22 -0
- package/stack/local-prepare.mjs +62 -0
- package/stack/local-run.d.mts +71 -0
- package/stack/local-run.mjs +200 -0
- package/stack/local-state.d.mts +35 -0
- package/stack/local-state.mjs +29 -0
- package/stack/local-status.d.mts +6 -0
- package/stack/local-status.mjs +36 -0
- package/stack/local-up.d.mts +11 -0
- package/stack/local-up.mjs +166 -0
- package/stack/local-verify.d.mts +6 -0
- package/stack/local-verify.mjs +21 -0
- package/sync/index.d.mts +13 -12
- package/sync/index.mjs +83 -28
- package/templates/app/module/jest.config.js.tpl +8 -0
- package/templates/app/module/src/index.ts.tpl +2 -0
- package/templates/app/module/src/manifest/declaration.spec.ts.tpl +11 -0
- package/templates/app/module/src/manifest/declaration.ts.tpl +13 -0
- package/templates/app/module/src/manifest/index.ts.tpl +1 -0
- package/templates/app/module/src/public/index.ts.tpl +2 -0
- package/templates/app/module/src/template/__name__.template.spec.ts.tpl +13 -0
- package/templates/app/module/src/template/__name__.template.ts.tpl +41 -0
- package/templates/app/module/src/template/index.ts.tpl +1 -0
- package/templates/app/module/src/workbench/components/__pascal__WorkbenchView.tsx.tpl +16 -0
- package/templates/app/module/src/workbench/index.ts.tpl +2 -0
- package/templates/app/package-scripts/package.json +1 -1
- package/templates/app/package-scripts-lite/package.json +1 -1
- package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +76 -70
- package/templates/app/skeleton-lite/.starcistacks/dev/README.md +23 -13
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/compose/compose.yaml +25 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +18 -26
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +1 -0
- package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +2 -1
- package/templates/app/skeleton-lite/db/migrations/__timestamp___baseline.sql +57 -14
- package/templates/be/auth-lite/src/features/api/auth/application/auth.contracts.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/get-jwks.handler.ts +23 -0
- package/templates/be/auth-lite/src/features/api/auth/application/get-jwks.query.ts +12 -0
- package/templates/be/auth-lite/src/features/api/auth/application/google-begin.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/google-begin.handler.ts +22 -0
- package/templates/be/auth-lite/src/features/api/auth/application/google-complete.command.ts +12 -0
- package/templates/be/auth-lite/src/features/api/auth/application/google-complete.handler.ts +23 -0
- package/templates/be/auth-lite/src/features/api/auth/application/login.command.ts +12 -0
- package/templates/be/auth-lite/src/features/api/auth/application/login.handler.ts +23 -0
- package/templates/be/auth-lite/src/features/api/auth/application/logout.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/logout.handler.ts +22 -0
- package/templates/be/auth-lite/src/features/api/auth/application/refresh.command.ts +12 -0
- package/templates/be/auth-lite/src/features/api/auth/application/refresh.handler.ts +23 -0
- package/templates/be/auth-lite/src/features/api/auth/application/session.command.ts +12 -0
- package/templates/be/auth-lite/src/features/api/auth/application/session.handler.ts +23 -0
- package/templates/be/auth-lite/src/features/api/auth/auth.module-definition.ts +13 -0
- package/templates/be/auth-lite/src/features/api/auth/auth.module.ts +16 -0
- package/templates/be/auth-lite/src/features/api/auth/auth.options.ts +3 -0
- package/templates/be/auth-lite/src/features/api/auth/index.ts +2 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/auth-http.module-definition.ts +13 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/auth-http.module.ts +9 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/auth-http.options.ts +3 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/auth.controller.ts +90 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/dto/google-start.request.ts +17 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/dto/login.request.ts +16 -0
- package/templates/be/auth-lite/src/modules/domain/identity/account-directory.service.spec.ts +46 -0
- package/templates/be/auth-lite/src/modules/domain/identity/account-directory.service.ts +28 -0
- package/templates/be/auth-lite/src/modules/domain/identity/authenticator.service.spec.ts +145 -0
- package/templates/be/auth-lite/src/modules/domain/identity/authenticator.service.ts +95 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/entities/auth-identity.entity.ts +38 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/entities/auth-user.entity.ts +54 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/entities/identity-attempt.entity.ts +18 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/entities/identity-refresh-token.entity.ts +34 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/entities/identity-session.entity.ts +30 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/entities/index.ts +17 -0
- package/templates/be/auth-lite/src/modules/domain/identity/rate-counter.service.spec.ts +86 -0
- package/templates/be/auth-lite/src/modules/domain/identity/rate-counter.service.ts +45 -0
- package/templates/be/auth-lite/src/modules/domain/identity/session-store.service.spec.ts +97 -0
- package/templates/be/auth-lite/src/modules/domain/identity/session-store.service.ts +81 -0
- package/templates/be/auth-lite/src/modules/domain/identity/sign-in.service.spec.ts +78 -0
- package/templates/be/auth-lite/src/modules/domain/identity/sign-in.service.ts +87 -0
- package/templates/be/auth-lite/src/tests/fixtures/builders/identity.builder.ts +44 -0
- package/templates/be/skeleton-lite/apps/api/src/app.module.ts +6 -5
- package/templates/be/skeleton-lite/apps/api/src/compose/api.ts +3 -2
- package/templates/be/skeleton-lite/apps/api/src/compose/integrations.ts +10 -5
- package/templates/be/skeleton-lite/src/modules/domain/identity/errors/identity.error.ts +34 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +22 -1
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +47 -2
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +2 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/messages/identity.messages.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/index.ts +3 -3
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.config.ts +3 -1
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.decorators.ts +8 -4
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.module-definition.ts +12 -0
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.module.ts +29 -0
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.options.ts +6 -31
- package/templates/be/skeleton-lite/src/modules/integrations/passport/errors/passport.error.ts +18 -9
- package/templates/be/skeleton-lite/src/modules/integrations/passport/index.ts +35 -11
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.spec.ts +44 -8
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.config.ts +40 -18
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.decorators.ts +18 -6
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.kit.spec.ts +73 -0
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.kit.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.options.ts +24 -53
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.registration.ts +31 -0
- package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +1 -1
- package/templates/be/skeleton-lite/src/modules/platform/database/entities.ts +2 -1
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +1 -1
- package/templates/be/skeleton-lite/src/tests/fixtures/builders/api.builder.ts +11 -4
- package/templates/be/test-world/e2e/serves-once-migrated.e2e-spec.ts.tpl +9 -9
- package/templates/be/test-world/fixtures/migrations.sql.ts.tpl +4 -4
- package/templates/fe/auth-lite/apps/web/src/modules/auth/client.ts +26 -0
- package/templates/fe/common/site-shell.tsx.partial +3 -3
- package/templates/fe/skeleton/apps/__app__/src/components/providers/AppProviders/index.tsx +33 -10
- package/templates/fe/skeleton/apps/__app__/src/hooks/auth/index.ts +1 -0
- package/templates/fe/skeleton/apps/__app__/src/hooks/auth/useViewerId.ts +11 -0
- package/templates/fe/skeleton/apps/__app__/src/modules/toast/toast.tsx +15 -12
- package/templates/fe/skeleton/apps/__app__/src/modules/viewer-cache/index.ts +5 -0
- package/templates/fe/skeleton/apps/__app__/src/redux/slices/session.ts +1 -1
- package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +1 -1
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +4 -7
- package/templates/fe/skeleton/packages/__project__-ui/src/frames/SiteShell/index.tsx +2 -3
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +4 -7
- package/templates/fe/skeleton-lite/apps/web/src/components/frames/SiteShell/index.tsx +1 -2
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/Caddyfile +0 -16
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/owner-actions.md +0 -11
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/recovery/restore-proof.md +0 -7
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/current.yaml +0 -6
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/images.lock.yaml +0 -8
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/previous.yaml +0 -6
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +0 -186
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.client.spec.ts +0 -22
- package/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.client.ts +0 -25
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.spec.ts +0 -104
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.cookie.ts +0 -34
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.password.spec.ts +0 -28
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.password.ts +0 -11
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.tokens.spec.ts +0 -88
- package/templates/be/skeleton-lite/src/modules/integrations/passport/passport.tokens.ts +0 -69
- package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/google.strategy.ts +0 -41
- package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/local.strategy.ts +0 -40
- package/templates/be/skeleton-lite/src/modules/integrations/passport/strategies/oauth-state.store.ts +0 -63
- package/templates/fe/skeleton/packages/__project__-ui/src/frames/SiteShell/classNames.ts +0 -4
- package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/auth-door.ts +0 -30
- package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/client.ts +0 -50
- package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/token-store.ts +0 -31
- package/templates/fe/skeleton-lite/apps/web/src/components/frames/SiteShell/classNames.ts +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.2.0 - 2026-11-03
|
|
4
|
+
|
|
5
|
+
- Added: a scaffolded app of each edition type-checks and builds on every side (`scaffold-type-check.spec.mts`: one install per edition, `tsc` of the back end and its specs, the back-end build, the workspace packages, `tsc` and `next build` of each front-end app). The templates follow the Grammar contract: `Link` and `Page` for `SiteShell` and `NotFoundNotice`, a callable `toast`, the session reducers as a type, explicit next-intl navigation generics, optional access to the test world's apps and connections, no unused import in the migrations fixture. The lite dev api process no longer runs `--transpile-only`.
|
|
6
|
+
- Added: the custody kind `ed25519-pem` of `local.custody` (the dev sign-in key is EdDSA); the lite dev environment names `AUTH_WEB_ORIGIN`.
|
|
7
|
+
- Added: `starci app add module <name>` and `starci app remove module <name>`: a module package `packages/module-<name>` of the product's agent SDK (`./template`, `./manifest`, `./workbench`, `./public`), registered in the root `workspaces` and the back-end and front-end dependencies, listed in the managed registry package `packages/modules` that `starci app sync` renders and drift-checks. Slots `app.packages` and `app.module-registry` (manifest 3.17.0). The module packages enter the Sonar sources, the Codecov paths and a `build:modules` / `test:modules` script pair that the typecheck, the lint and the build run first.
|
|
8
|
+
- Added: rule R374 (`STACKS_CODE_BIND_MOUNT`, `STACKS_IMAGE_BASE_UNPINNED`, `STACKS_IMAGE_BASE_NOT_FORK`, `STACKS_IMAGE_ENV_DIVERGES`): a customised service is an image built from `.starcistacks/images/<name>/` on the harness's pinned base, no bind-mounted code, the same image in every environment (PROJECT-STACKS-11).
|
|
9
|
+
- Changed: FE-PACKAGES-2 (a shared package, a module's workbench included, draws only with Grammar) and BE-TEST-13 (a module package's logic is inside the 100 per file scope).
|
|
10
|
+
- Added: the lite starter composes `@starci/auth`: it depends on the package and on none of the identity libraries, `integrations/passport` is the glue the slot lists (`passport.config.ts`, `passport.options.ts`, `passport.decorators.ts`, `passport.kit.ts`, `errors/`), the web app keeps one `@starci/auth/client` instance in `modules/auth/client.ts`, and the baseline migration holds the package's session tables (`identity_sessions`, `identity_refresh_tokens`) byte for byte.
|
|
11
|
+
- Changed: `infraOwners` own `@nestjs/passport`, `passport*`, `@nestjs/jwt`, `jose` and `bcryptjs` by nobody and `@starci/auth` by `integrations/passport` alone (R328); the `own-jwks-principal` machine refuses a `jwtVerify` call anywhere in the app and requires the `@starci/auth/server` import in the passport integration (R329); `transport-owner` no longer admits an auth door in `modules/auth`; the `auth` stack concern names `@starci/auth` and forbids `jose`, `jwt-decode`, `next-auth`, `@auth/core`, `keycloak-js` and `oidc-client-ts`.
|
|
12
|
+
- Changed: the lite stack templates name `AUTH_WEB_ORIGIN` and the Ed25519 signing key; `AUTH_JWT_PRIVATE_KEY` is an EdDSA key and the public key is derived from it.
|
|
13
|
+
- Added: the lite starter signs in with no hand-written auth code. The managed slots `be.identity.sign-in`, `be.feature.auth` and `fe.modules.auth.client` render, from `templates/be/auth-lite` and `templates/fe/auth-lite`, the `/auth` doors (login, refresh, session, logout, Google start and callback, jwks), the entities of the session, attempt, user and identity tables, the session, account and rate stores, the authenticator, `IdentitySignInService`, their specs and the web app's `createAuthClient` client; an edit is `HFS_MANAGED_FILE_DRIFT`. The identity error family gains the sign-in codes, the passport family keeps its `PASSPORT_` codes.
|
|
14
|
+
- Added: the slot field `managedOnly` (a slot that only lists files sync renders; the slot owning the path judges them). Manifest 3.16.0.
|
|
15
|
+
- Changed: the sync and the scaffold count the back-end source files their own targets render, so the CI shard count and the coverage scope are the same before and after the targets are written (one sync leaves the app in sync).
|
|
16
|
+
- Added: the canon pin of `@starci/auth` 0.1.0.
|
|
17
|
+
- Added: `starci app stack prepare|doctor|up|status|logs|down|verify --env <env>` for a docker-compose (dev) environment, driven by the new `environments.<env>.local` block of application-stacks.yaml: ports, compose services and their health, the environment's own database role (the migrations run as it and the app role gets its own password), dev-only custody generators, least grants (`STACK_GRANT_<NAME>`), data directories (`STACK_DATA_DIR`, `${data}`), setup and seed commands (a seed runs after the migration or after readiness), native app processes, readiness and verification probes. `up --execute` is the one command (host table, custody, setup, services, database, migrate with a receipt, seed once, processes, readiness, origins); `prepare`, `up` and `down` are dry runs until `--execute`, `down` never removes a volume, `doctor` prints the owner-run install step per OS for each missing prerequisite and installs nothing. A swarm environment keeps the swarm verbs and refuses the dev-only ones.
|
|
18
|
+
- Added: `starci app secret init --env <dev env> [--execute]` creates the dev-only values `local.custody` declares (hex, base64, password, uuid, rsa-pem, ec-pem), once: a sealed value is kept, a half-present pair is refused, a vps or production environment is refused.
|
|
19
|
+
- Added: `db migrate` runs its client tools inside the database container named by `STARCI_DB_CONTAINER`, so a host without PostgreSQL client tools migrates a dev database.
|
|
20
|
+
- Added: rules R372 (`STACKS_LOCAL_CONFIG_INVALID`, `STACKS_DEV_UNDECLARED`: a coherent local block, and a lite app declares its dev environment) and R373 (`STACKS_RUNBOOK_DOCKER_COMMAND`: the dev runbook names `starci app stack up --env <env>` and carries no docker command).
|
|
21
|
+
- Changed: the lite skeleton's dev environment is `docker-compose` with a local block, a compose file and a runbook of the new verbs (it was a Swarm stack with illustrative digests); slot `app.starcistacks` admits `<env>/infra/compose/**` in lite; `add queue` in lite adds the Redis to the dev compose file and the queue settings to the dev processes.
|
|
22
|
+
|
|
3
23
|
## 5.1.0
|
|
4
24
|
|
|
5
25
|
- Added: `starci app codemod explicit-surface` writes the inferred type of every export the classifier counts as open (R368): return types, variable, parameter and property types, from the app's own TypeScript program. It prefers a named type the program exports, writes `ReactElement` for components and Next's `Metadata` for `generateMetadata`, adds merged type-only imports after a directive prologue, compiles the result beside the original and writes a file only when it gains no diagnostic, and reports (with a suggested fix) destructured exports and anonymous, computed, too long, `any`, unnameable and predicate types. Prettier of the app formats what is written.
|
package/README.md
CHANGED
|
@@ -24,10 +24,19 @@ starci app world <up|down|status> [--stack <dir>] [--services <list>] [--k3d] [-
|
|
|
24
24
|
starci app slot <path> [--cwd <dir>] [--json]
|
|
25
25
|
starci app emit [--cwd <dir>]
|
|
26
26
|
starci app db drift [--db-url-env <NAME>] [--json] [--cwd <dir>]
|
|
27
|
-
starci app
|
|
27
|
+
starci app stack <prepare|up|down> --env <dev env> [--execute] | <doctor|status|verify> --env <dev env> | logs --env <dev env> --service <name> [--lines <n>]
|
|
28
|
+
starci app secret init [--env <dev env> [--execute]] | <set|get|unset|rename|remove|materialize|list|verify|recipients|migrate|split|audit|server-key> --env <env> ... [--cwd <dir>]
|
|
28
29
|
starci app ci secret set <NAME> [--from-custody] [--env <env>] [--repo <owner/name>] [--execute]
|
|
29
30
|
```
|
|
30
31
|
|
|
32
|
+
**The dev environment in one command.** `starci app stack up --env dev --execute` brings a docker-compose environment up from its `local` block of
|
|
33
|
+
`.starcistacks/application-stacks.yaml` (PROJECT-STACKS-6 of `contexts/project/stacks.md`): the host table (`doctor` prints the owner-run install
|
|
34
|
+
step per OS for each missing prerequisite and installs nothing), the dev custody (`secret init --env dev --execute` creates the dev-only values once),
|
|
35
|
+
the setup commands, the compose services and their health, the environment's own database role, the migrations with a receipt (`db migrate` runs its
|
|
36
|
+
client tools in the database container named by `STARCI_DB_CONTAINER`, so the host needs no PostgreSQL client), the seed once, the native app
|
|
37
|
+
processes, readiness and the origins. `prepare`, `up` and `down` are dry runs until `--execute`; `down` never removes a volume. State (process ids,
|
|
38
|
+
logs, receipts) is under the state base (`STARCI_LOCAL_ROOT`), the opened custody under the private secrets directory outside the checkout.
|
|
39
|
+
|
|
31
40
|
`starci app add` writes every front-end unit, in either edition, already in the shape of the harness's `contexts/code/fe`
|
|
32
41
|
and `contexts/ui`, from `templates/fe/units`, with its copy in every catalog; nothing that exists is overwritten.
|
|
33
42
|
|
package/db/postgres.mjs
CHANGED
|
@@ -35,7 +35,15 @@ export function dbTarget(ctx, name = DEFAULT_DB_URL_ENV) {
|
|
|
35
35
|
const parsed = parseConnection(value);
|
|
36
36
|
if (!parsed)
|
|
37
37
|
throw refusal('DB_URL_INVALID', `${name} is not a postgres connection URL`);
|
|
38
|
-
|
|
38
|
+
const target = { kind: 'url', how: `connection string from ${name}`, urlEnv: name, url: parsed.url, env: parsed.password ? { PGPASSWORD: parsed.password } : {}, secrets: [value, parsed.password].filter(Boolean) };
|
|
39
|
+
// A dev environment's database runs in its own container (starci app stack up): STARCI_DB_CONTAINER runs the client tools inside it, so the host needs no PostgreSQL client.
|
|
40
|
+
const container = ctx.env.STARCI_DB_CONTAINER;
|
|
41
|
+
if (!container)
|
|
42
|
+
return target;
|
|
43
|
+
const inside = inContainer(target, container);
|
|
44
|
+
const url = new URL(inside.url);
|
|
45
|
+
url.port = '5432';
|
|
46
|
+
return { ...target, ...inside, kind: 'url', urlEnv: name, url: url.toString() };
|
|
39
47
|
}
|
|
40
48
|
/** Where a `-f` file of an in-container target is copied before the client reads it. */
|
|
41
49
|
const CONTAINER_DIR = '/tmp/starci-db';
|
package/package.json
CHANGED
|
@@ -30,36 +30,43 @@ pins:
|
|
|
30
30
|
side: fe
|
|
31
31
|
source: packages/event-stream/package.json
|
|
32
32
|
why: 'the one server-sent-events client of every front end (fe-stack event-stream, owner:event-stream-package): the transport client layer (modules/api/sse/clients) creates one instance for the app with the bearer token source and the stream operations follow on it; it carries Last-Event-ID resume, the capped doubling backoff, the heartbeat timeout, the single 401 renewal and the useSWRSubscription adapter, so no app keeps a hand-written reader.'
|
|
33
|
+
'@starci/next-data':
|
|
34
|
+
version: 0.1.0
|
|
35
|
+
group: starci
|
|
36
|
+
install: registry
|
|
37
|
+
side: fe
|
|
38
|
+
source: packages/next-data/package.json
|
|
39
|
+
why: 'the SWR data helpers of every front end (fe-stack data, owner:next-data-package): pollingRestart, the viewer and tenant key helpers, viewerSwrConfig and the viewer cache; each operation hook stays in the app and the package holds no component.'
|
|
33
40
|
'@starci/grammar':
|
|
34
|
-
version: 0.21.
|
|
41
|
+
version: 0.21.14
|
|
35
42
|
group: starci
|
|
36
43
|
install: registry
|
|
37
44
|
side: fe
|
|
38
45
|
source: packages/grammar/package.json
|
|
39
46
|
why: 'the grammar front ends read: the brand layer sets `--font-sans` and `--font-mono` and the grammar reads them; it carries the Input tel kind, the copyable and read-only Input, the IconButton disclosure props and count badge, ChatBubble, FillViewport, Textarea mentions and Enter-to-send, the leading PrimaryRailLayout rail, the plate-less Image, ListRow, the soft Alert, Progress steps, the floating primary IconButton, FlowGraph, the STATE-8 loading views and the bordered selectable TagGroup chips. The runtime source version wins for a @starci package.'
|
|
40
47
|
'@starci/eslint-canon-be':
|
|
41
|
-
version: 3.
|
|
48
|
+
version: 3.13.0
|
|
42
49
|
group: starci
|
|
43
50
|
install: registry
|
|
44
51
|
side: be
|
|
45
52
|
source: packages/eslint-canon-be/package.json
|
|
46
53
|
why: 'the back-end ESLint canon: `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, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; `starciBeConfig({ hfs: loadHfs(import.meta.url) })` is the typed factory and the BE-CONVENTION laws are its rules.'
|
|
47
54
|
'@starci/eslint-canon-fe':
|
|
48
|
-
version: 9.
|
|
55
|
+
version: 9.11.0
|
|
49
56
|
group: starci
|
|
50
57
|
install: registry
|
|
51
58
|
side: fe
|
|
52
59
|
source: packages/eslint-canon-fe/package.json
|
|
53
60
|
why: 'the front-end ESLint canon: `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, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; the front end has no tests (FE_NO_TESTS R97 in hfs) and no-vietnamese-in-source (R91) applies.'
|
|
54
61
|
'@starci/eslint-grammar-core':
|
|
55
|
-
version: 0.21.
|
|
62
|
+
version: 0.21.14
|
|
56
63
|
group: starci
|
|
57
64
|
install: registry
|
|
58
65
|
side: fe
|
|
59
66
|
source: packages/eslint-grammar-core/package.json
|
|
60
67
|
why: 'the StarCi Grammar component API lint, versioned with @starci/grammar; front ends compose this family package with the universal FE canon.'
|
|
61
68
|
'@starci/eslint-grammar-offset-pop':
|
|
62
|
-
version: 0.21.
|
|
69
|
+
version: 0.21.14
|
|
63
70
|
group: starci
|
|
64
71
|
install: registry
|
|
65
72
|
side: fe
|
|
@@ -85,7 +92,7 @@ pins:
|
|
|
85
92
|
side: both
|
|
86
93
|
source: packages/prettier-config/package.json
|
|
87
94
|
'@starci/jest-preset':
|
|
88
|
-
version: 2.6.
|
|
95
|
+
version: 2.6.1
|
|
89
96
|
group: starci
|
|
90
97
|
install: registry
|
|
91
98
|
side: be
|
|
@@ -105,8 +112,22 @@ pins:
|
|
|
105
112
|
side: be
|
|
106
113
|
source: packages/ai-router/package.json
|
|
107
114
|
why: 'the AI pool router of a back end: a NestJS module that routes OpenAI-compatible chat, stream and embeddings calls across keys, models and providers, with @starci/ai-router/testing for its specs; @starci/jest-preset compiles it as an ESM-only dependency.'
|
|
115
|
+
'@starci/auth':
|
|
116
|
+
version: 0.1.0
|
|
117
|
+
group: starci
|
|
118
|
+
install: registry
|
|
119
|
+
side: both
|
|
120
|
+
source: packages/auth/package.json
|
|
121
|
+
why: 'the lite sign-in: the NestJS module (EdDSA access tokens with a multi-key JWKS, passwords, Google OAuth with state and PKCE, rotating refresh sessions, the sign-in budget, the refresh cookie), the front-end client and its React bindings, the door contracts and test doubles; the one importer of the identity libraries, reached by a back end only through integrations/passport; @starci/jest-preset compiles it as an ESM-only dependency.'
|
|
122
|
+
'@starci/object-storage':
|
|
123
|
+
version: 0.1.0
|
|
124
|
+
group: starci
|
|
125
|
+
install: registry
|
|
126
|
+
side: be
|
|
127
|
+
source: packages/object-storage/package.json
|
|
128
|
+
why: 'object storage of a back end: a NestJS module and the ObjectStorage port over S3-compatible storage (presigned PUT and GET that sign the content type and size, head, get, put, list, delete, bucket setup, size and content-type limits, coded errors), with @starci/object-storage/testing for its specs; the only importer of @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner (R331).'
|
|
108
129
|
'@starci/hfs':
|
|
109
|
-
version: 5.
|
|
130
|
+
version: 5.2.0
|
|
110
131
|
group: starci
|
|
111
132
|
install: registry
|
|
112
133
|
side: both
|
|
@@ -543,12 +564,12 @@ pins:
|
|
|
543
564
|
version: 3.1150.0
|
|
544
565
|
group: framework
|
|
545
566
|
side: be
|
|
546
|
-
why: 'the S3 transport
|
|
567
|
+
why: 'the S3 transport inside @starci/object-storage, the one ObjectStorage adapter of both editions (MinIO, S3, Spaces), which depends on it at exactly this version and which no app file imports; 3.1150.0 is the release of 2026-10-12, chosen over newer ones that had not aged two weeks.'
|
|
547
568
|
'@aws-sdk/s3-request-presigner':
|
|
548
569
|
version: 3.1150.0
|
|
549
570
|
group: framework
|
|
550
571
|
side: be
|
|
551
|
-
why: 'signs the presigned PUT and GET
|
|
572
|
+
why: 'signs the presigned PUT and GET inside @starci/object-storage locally, the same release as client-s3; no app file imports it.'
|
|
552
573
|
'@apollo/server':
|
|
553
574
|
version: 5.5.1
|
|
554
575
|
group: framework
|
|
@@ -37,17 +37,17 @@ concerns:
|
|
|
37
37
|
- id: rest
|
|
38
38
|
tier: core
|
|
39
39
|
packages: [axios]
|
|
40
|
-
home: [fe.modules.api
|
|
40
|
+
home: [fe.modules.api]
|
|
41
41
|
pattern: FE-API-REST
|
|
42
42
|
forbids: [ky, superagent, node-fetch, cross-fetch, isomorphic-fetch]
|
|
43
|
-
why: modules/api/rest/<area>/*.ts for uploads and presigned URLs,
|
|
43
|
+
why: modules/api/rest/<area>/*.ts for uploads and presigned URLs, only; GraphQL carries every other call.
|
|
44
44
|
- id: data
|
|
45
45
|
tier: core
|
|
46
|
-
packages: [swr]
|
|
46
|
+
packages: [swr, '@starci/next-data']
|
|
47
47
|
home: [fe.hooks.swr]
|
|
48
48
|
pattern: FE-DATA-SWR
|
|
49
49
|
forbids: ['@tanstack/react-query', react-query]
|
|
50
|
-
why: hooks/swr/api/{graphql,rest}/{queries,mutations}/use*Swr.ts wrap one operation each; components call hooks only.
|
|
50
|
+
why: hooks/swr/api/{graphql,rest}/{queries,mutations}/use*Swr.ts wrap one operation each; components call hooks only. The polling-restart middleware (pollingRestart), the key helpers, the viewer-keyed config and the viewer cache are @starci/next-data's (owner next-data-package); an app imports no Middleware or ScopedMutator type of swr and writes none of them.
|
|
51
51
|
- id: toast
|
|
52
52
|
tier: core
|
|
53
53
|
packages: ['@heroui/react']
|
|
@@ -96,11 +96,11 @@ concerns:
|
|
|
96
96
|
hand-written reader (read-event-stream.ts) and no second SSE library is installed.
|
|
97
97
|
- id: auth
|
|
98
98
|
tier: core
|
|
99
|
-
packages: []
|
|
99
|
+
packages: ['@starci/auth']
|
|
100
100
|
home: [fe.modules.auth]
|
|
101
101
|
pattern: FE-AUTH
|
|
102
|
-
forbids: ['@supabase/supabase-js', '@supabase/ssr', '@supabase/auth-js']
|
|
103
|
-
why: modules/auth is the session issuer's client (
|
|
102
|
+
forbids: ['@supabase/supabase-js', '@supabase/ssr', '@supabase/auth-js', jose, jwt-decode, next-auth, '@auth/core', keycloak-js, oidc-client-ts]
|
|
103
|
+
why: modules/auth is the session issuer's client (one @starci/auth client instance over the app's own back-end auth doors, the access token in its memory; full - the app's IdP client); it yields the session and the access token for the Apollo link and never reads data.
|
|
104
104
|
- id: i18n
|
|
105
105
|
tier: core
|
|
106
106
|
packages: [next-intl]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# The images the harness owns as StarCi forks (the harness repository's images/sources.json is their owner; stacks-service-images.spec.mts keeps this list
|
|
2
|
+
# equal to it). A service of an app that has an image folder named like a key here is built FROM that repository (R374 STACKS_IMAGE_BASE_NOT_FORK):
|
|
3
|
+
# the fork itself, or the harness runtime layer built on it (openclaw-runtime, images/README.md).
|
|
4
|
+
schema: starci/fork-images@1
|
|
5
|
+
images:
|
|
6
|
+
minio: ghcr.io/starci183/minio
|
|
7
|
+
openclaw: ghcr.io/starci183/openclaw-runtime
|
|
@@ -4084,6 +4084,7 @@ rules:
|
|
|
4084
4084
|
enforcers:
|
|
4085
4085
|
- {kind: hfs, id: fe-stack, at: scripts/hfs/rules/fe-stack.mjs}
|
|
4086
4086
|
- {kind: eslint-fe, id: fe-stack-import}
|
|
4087
|
+
- {kind: eslint-fe, id: swr-extension-from-package}
|
|
4087
4088
|
proves:
|
|
4088
4089
|
- {path: packages/eslint/fe/frontend-boundary-coverage.spec.mjs, editions: [lite, full], codes: [FE_STACK_FORBIDDEN]}
|
|
4089
4090
|
- {path: packages/hfs/src/frontend-boundary-coverage.spec.mjs, editions: [lite, full], codes: [FE_STACK_FORBIDDEN]}
|
|
@@ -5696,7 +5697,7 @@ rules:
|
|
|
5696
5697
|
ruling: "A model call made straight from code uses LangChain with retrieved context, through the ai-router gateway (owner ruling be-ai-langchain-gateway): the LangChain clients point at the gateway's base URL with its virtual key."
|
|
5697
5698
|
- id: R328
|
|
5698
5699
|
code: "BE_AUTH_PASSPORT_OWNER"
|
|
5699
|
-
law: "The identity libraries (@nestjs/passport, passport, passport-google-oauth20, passport-local, @nestjs/jwt, jose and bcryptjs) are
|
|
5700
|
+
law: "The identity libraries (@nestjs/passport, passport, passport-google-oauth20, passport-local, @nestjs/jwt, jose and bcryptjs) are the dependencies of @starci/auth and are imported by no app file; @starci/auth/server is imported only by integrations/passport, its one glue. bcrypt and every Supabase client are owned nowhere."
|
|
5700
5701
|
kinds: [lint]
|
|
5701
5702
|
gates: [pre-commit, settle, land, ci]
|
|
5702
5703
|
failureCodes: ["BE_AUTH_PASSPORT_OWNER"]
|
|
@@ -5718,7 +5719,7 @@ rules:
|
|
|
5718
5719
|
ruling: "Lite leaves Supabase: its identity is the app own Passport integration (Google OAuth and email/password) on its self-hosted PostgreSQL; full keeps Keycloak."
|
|
5719
5720
|
- id: R329
|
|
5720
5721
|
code: "BE_AUTH_JWT_OWN_JWKS"
|
|
5721
|
-
law: "A lite back-end principal comes only from the app's own access token verified by
|
|
5722
|
+
law: "A lite back-end principal comes only from the app's own access token, verified by @starci/auth (EdDSA pinned, issuer and audience checked, a local key set that may hold several keys), never from a remote JWKS, a token decoded without its signature check, a jwtVerify call in the app or a body claim."
|
|
5722
5723
|
kinds: [check, lint]
|
|
5723
5724
|
gates: [pre-commit, settle, land, ci]
|
|
5724
5725
|
failureCodes: ["BE_AUTH_JWT_OWN_JWKS"]
|
|
@@ -5742,7 +5743,7 @@ rules:
|
|
|
5742
5743
|
ruling: "The lite back end verifies its own asymmetric access tokens against its own JWKS; it trusts no remote identity provider."
|
|
5743
5744
|
- id: R330
|
|
5744
5745
|
code: "BE_AUTH_REFRESH_COOKIE"
|
|
5745
|
-
law: "A refresh token travels only in
|
|
5746
|
+
law: "A refresh token travels only in the httpOnly, Secure cookie that @starci/auth sets, rotates (with a reuse grace window and reuse detection) and clears; no app file writes that cookie, and the token never appears as a field of a request or response body."
|
|
5746
5747
|
kinds: [lint]
|
|
5747
5748
|
gates: [pre-commit, settle, land, ci]
|
|
5748
5749
|
failureCodes: ["BE_AUTH_REFRESH_COOKIE"]
|
|
@@ -5764,7 +5765,7 @@ rules:
|
|
|
5764
5765
|
ruling: "The refresh token of the lite identity rotates and lives only in an httpOnly cookie; the browser holds no credential."
|
|
5765
5766
|
- id: R331
|
|
5766
5767
|
code: "BE_STORAGE_OWNER"
|
|
5767
|
-
law: "The S3 client (@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner)
|
|
5768
|
+
law: "The S3 client libraries (@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner) are the dependencies of @starci/object-storage, the ObjectStorage port over S3-compatible storage (MinIO in lite) with presigned PUT and GET, and are imported by no app file; @starci/object-storage is imported only by integrations/object-storage, its one glue; no module imports minio."
|
|
5768
5769
|
kinds: [lint]
|
|
5769
5770
|
gates: [pre-commit, settle, land, ci]
|
|
5770
5771
|
failureCodes: ["BE_STORAGE_OWNER"]
|
|
@@ -5773,11 +5774,11 @@ rules:
|
|
|
5773
5774
|
editions: [lite, full]
|
|
5774
5775
|
docs: [contexts/code/be/infra.md]
|
|
5775
5776
|
proves:
|
|
5776
|
-
- packages/eslint-canon-be/src/
|
|
5777
|
+
- packages/eslint-canon-be/src/object-storage-package.spec.ts
|
|
5777
5778
|
exemplifiedBy:
|
|
5778
|
-
- {path: packages/hfs/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.
|
|
5779
|
+
- {path: packages/hfs/templates/be/skeleton-lite/src/modules/integrations/object-storage/object-storage.module.ts, edition: lite}
|
|
5779
5780
|
witness:
|
|
5780
|
-
- {path: packages/eslint-canon-be/src/
|
|
5781
|
+
- {path: packages/eslint-canon-be/src/object-storage-package.spec.ts, editions: [lite, full], codes: [BE_STORAGE_OWNER]}
|
|
5781
5782
|
cases:
|
|
5782
5783
|
- id: case-1
|
|
5783
5784
|
date: "2026-10-29"
|
|
@@ -6576,3 +6577,50 @@ rules:
|
|
|
6576
6577
|
source: owner
|
|
6577
6578
|
quote: "no lint caught it"
|
|
6578
6579
|
ruling: "A directive below an import broke Nivo's CI build on 2026-11-02; the directive is the first statement of its module and a lint reports it elsewhere."
|
|
6580
|
+
- id: R372
|
|
6581
|
+
code: "STACKS_LOCAL_CONFIG_INVALID"
|
|
6582
|
+
law: "In lite and full apps, every docker-compose environment of .starcistacks/application-stacks.yaml declares a coherent `local` block, judged by the same normalizeLocal the dev verbs of `starci app stack` (doctor, prepare, up, status, logs, verify, down) use: closed fields, one loopback port each, compose services that exist in the compose files, an environment-owned database role (never postgres, never the app role), dev-only custody generators and loopback probes; and a lite app declares at least one such dev environment, so `starci app stack up --env dev` has something to run."
|
|
6583
|
+
kinds: [check]
|
|
6584
|
+
gates: [settle, land, ci]
|
|
6585
|
+
failureCodes: ["STACKS_LOCAL_CONFIG_INVALID", "STACKS_DEV_UNDECLARED"]
|
|
6586
|
+
enforcers:
|
|
6587
|
+
- {kind: hfs, id: stacks-local, at: scripts/hfs/rules/stacks-local.mjs}
|
|
6588
|
+
editions: [lite, full]
|
|
6589
|
+
docs:
|
|
6590
|
+
- {path: contexts/project/stacks.md#project-stacks-6-every-runbook-declares-the-same-operations, editions: [lite, full]}
|
|
6591
|
+
proves:
|
|
6592
|
+
- {path: packages/hfs/src/stack-local.spec.mjs, editions: [lite, full]}
|
|
6593
|
+
exemplifiedBy:
|
|
6594
|
+
- {path: packages/hfs/templates/app/skeleton-lite/.starcistacks, edition: lite}
|
|
6595
|
+
witness:
|
|
6596
|
+
- {path: packages/hfs/src/stack-local.spec.mjs, editions: [lite, full]}
|
|
6597
|
+
- id: R373
|
|
6598
|
+
code: "STACKS_RUNBOOK_DOCKER_COMMAND"
|
|
6599
|
+
law: "The runbook of a docker-compose environment names `starci app stack up --env <env>` and carries no `docker build|run|compose|create|start|stop|pull|push` or `docker stack deploy` command: Docker is run by the harness verb, never by hand (hard rule 8)."
|
|
6600
|
+
kinds: [check]
|
|
6601
|
+
gates: [settle, land, ci]
|
|
6602
|
+
failureCodes: ["STACKS_RUNBOOK_DOCKER_COMMAND"]
|
|
6603
|
+
enforcers:
|
|
6604
|
+
- {kind: hfs, id: stacks-local, at: scripts/hfs/rules/stacks-local.mjs}
|
|
6605
|
+
editions: [lite, full]
|
|
6606
|
+
docs:
|
|
6607
|
+
- {path: contexts/project/stacks.md#project-stacks-10-local-runs, editions: [lite, full]}
|
|
6608
|
+
proves:
|
|
6609
|
+
- {path: packages/hfs/src/stack-local.spec.mjs, editions: [lite, full]}
|
|
6610
|
+
exemplifiedBy:
|
|
6611
|
+
- {path: packages/hfs/templates/app/skeleton-lite/.starcistacks, edition: lite}
|
|
6612
|
+
witness:
|
|
6613
|
+
- {path: packages/hfs/src/stack-local.spec.mjs, editions: [lite, full]}
|
|
6614
|
+
- id: R374
|
|
6615
|
+
code: "STACKS_CODE_BIND_MOUNT"
|
|
6616
|
+
law: "A service the app customises runs from an image built out of `.starcistacks/images/<name>/` (a Dockerfile whose every FROM is digest-pinned and whose final stage is the harness's image for that service, the fork or its runtime layer, when the harness owns one), the same image in every environment; no stack or compose file bind-mounts code, plugins or scripts into a service container (data volumes, secrets, least grants and read-only plain config data files stay allowed)."
|
|
6617
|
+
kinds: [check]
|
|
6618
|
+
gates: [settle, land, ci]
|
|
6619
|
+
failureCodes: ["STACKS_CODE_BIND_MOUNT", "STACKS_IMAGE_BASE_UNPINNED", "STACKS_IMAGE_BASE_NOT_FORK", "STACKS_IMAGE_ENV_DIVERGES"]
|
|
6620
|
+
enforcers:
|
|
6621
|
+
- {kind: hfs, id: stacks-service-images, at: scripts/hfs/rules/stacks-service-images.mjs}
|
|
6622
|
+
editions: [lite, full]
|
|
6623
|
+
docs:
|
|
6624
|
+
- {path: contexts/project/stacks.md#project-stacks-11-a-customised-service-is-an-image-the-app-builds-the-same-in-every-environment, editions: [lite, full]}
|
|
6625
|
+
proves:
|
|
6626
|
+
- {path: packages/hfs/src/stacks-service-images.spec.mjs, editions: [lite, full]}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# catalog READ this file through scripts/hfs/slots.mjs; none of them hardcodes a path.
|
|
8
8
|
# Shape: modules/schemas/hfs-slots.schema.yaml. The repository side is hfs.json: modules/schemas/hfs-repo.schema.yaml.
|
|
9
9
|
schema: starci/hfs-slots@3
|
|
10
|
-
version: 3.
|
|
10
|
+
version: 3.16.0
|
|
11
11
|
|
|
12
12
|
versioning:
|
|
13
13
|
# MAJOR.MINOR.PATCH of this manifest. A repository pins only the MAJOR in hfs.json ("hfs": 3).
|
|
@@ -117,6 +117,8 @@ versioning:
|
|
|
117
117
|
# liteManagedBy is managed only in lite; its effective lite.path still lists literal files.
|
|
118
118
|
# the managed file list lives here and nowhere in code. A difference is HFS_MANAGED_FILE_DRIFT (a
|
|
119
119
|
# back end's tsconfig.json: HFS_TS_STRICT when a flag or an option was added).
|
|
120
|
+
# managedOnly true: the slot only lists files sync renders (needs managedBy); the path is judged by the slot that owns it, so the rendered
|
|
121
|
+
# file keeps the rules and the tier of its folder (a sign-in service is a domain service)
|
|
120
122
|
# rules rule codes from knowledge/hfs/rules.yaml.
|
|
121
123
|
# editions the editions (below) the slot exists in; default all of them. A slot outside the declared edition owns
|
|
122
124
|
# no path - under lite, what full keeps absent is removed, and what lite forbids is a finding.
|
|
@@ -250,17 +252,20 @@ ruleParams:
|
|
|
250
252
|
"node:https": [platform/http]
|
|
251
253
|
http: [platform/http]
|
|
252
254
|
https: [platform/http]
|
|
253
|
-
"@aws-sdk/client-s3": [
|
|
254
|
-
"@aws-sdk/s3-request-presigner": [
|
|
255
|
-
|
|
255
|
+
"@aws-sdk/client-s3": [] # the S3 client is a dependency of @starci/object-storage, imported by no app file (R331)
|
|
256
|
+
"@aws-sdk/s3-request-presigner": []
|
|
257
|
+
"@starci/object-storage": [integrations/object-storage] # the ObjectStorage port: one S3 adapter for MinIO, S3 and Spaces (R331)
|
|
258
|
+
minio: [] # storage goes through @starci/object-storage
|
|
256
259
|
"@supabase": [] # no Supabase client in a back end
|
|
257
|
-
"@nestjs/passport": [
|
|
258
|
-
passport: [
|
|
259
|
-
passport-google-oauth20: [
|
|
260
|
-
passport-local: [
|
|
261
|
-
"@nestjs/jwt": [
|
|
262
|
-
jose: [
|
|
263
|
-
bcryptjs: [
|
|
260
|
+
"@nestjs/passport": [] # the identity libraries are @starci/auth's dependencies, never an app's (R328)
|
|
261
|
+
passport: []
|
|
262
|
+
passport-google-oauth20: []
|
|
263
|
+
passport-local: []
|
|
264
|
+
"@nestjs/jwt": []
|
|
265
|
+
jose: []
|
|
266
|
+
bcryptjs: []
|
|
267
|
+
"@starci/auth": [integrations/passport] # the lite sign-in package: its server entry is reached only through integrations/passport (R328)
|
|
268
|
+
"@starci/auth/testing": [integrations/passport] # its test doubles, for the glue's specs
|
|
264
269
|
bcrypt: []
|
|
265
270
|
cache-manager: [integrations/cache, integrations/redis]
|
|
266
271
|
"@nestjs/cache-manager": [integrations/cache, integrations/redis] # the CACHE_MANAGER token: caching goes through the cache capability
|
|
@@ -909,7 +914,7 @@ slots:
|
|
|
909
914
|
# The db service supplies the database; schedules are platform/jobs ticks (R335); production has no Compose or host cron.
|
|
910
915
|
lite:
|
|
911
916
|
requires: [application-stacks.yaml]
|
|
912
|
-
allows: [application-stacks.yaml, images/db/Dockerfile, "<env>/README.md", "<env>/environment.json", "<env>/infra/swarm/**", "<env>/infra/metadata.json",
|
|
917
|
+
allows: [application-stacks.yaml, images/db/Dockerfile, "<env>/README.md", "<env>/environment.json", "<env>/infra/{compose,swarm}/**", "<env>/infra/metadata.json",
|
|
913
918
|
"<env>/runtime/{config,env}/**", "<env>/runtime/env/KEYS.md", "<env>/secrets/<slug>.{enc.yaml,enc}", "<env>/secrets/.gitkeep", "<env>/seeds/**"]
|
|
914
919
|
forbids: ["<env>/runtime/files/**", "**/*.enc outside <env>/secrets/", DESIGN.md, deployment.json, "k8s/ at root"]
|
|
915
920
|
rules: [HFS_STACKS_SHAPE, HFS_STACKS_IN_SIDE, HFS_PLAINTEXT_SECRET, HFS_IDENTITY_CUSTODY]
|
|
@@ -2028,36 +2033,68 @@ slots:
|
|
|
2028
2033
|
editions: [lite]
|
|
2029
2034
|
exemplifiedBy:
|
|
2030
2035
|
- packages/hfs/templates/be/skeleton-lite/src/modules/integrations/passport/
|
|
2031
|
-
# The
|
|
2032
|
-
#
|
|
2033
|
-
#
|
|
2034
|
-
#
|
|
2036
|
+
# The glue of @starci/auth, the lite sign-in package (Google OAuth with state and PKCE, email and password, EdDSA access tokens with
|
|
2037
|
+
# their JWKS, rotating refresh sessions): the one importer of the package (ruleParams.be.infraOwners), which owns the identity
|
|
2038
|
+
# libraries (@nestjs/passport, passport, passport-google-oauth20, passport-local, @nestjs/jwt, jose, bcryptjs) that no app imports.
|
|
2039
|
+
# It parses the typed options, builds the verifier and names the injectors; domain/identity verifies a token through the kit and
|
|
2040
|
+
# builds the principal (contexts/code/be/api-auth.md).
|
|
2035
2041
|
path: "src/modules/integrations/passport/"
|
|
2036
2042
|
presence: required
|
|
2037
2043
|
tracked: tracked
|
|
2038
2044
|
tier: integrations
|
|
2039
2045
|
owner: true
|
|
2040
|
-
requires: [index.ts, passport.config.ts, passport.options.ts, passport.decorators.ts, passport.
|
|
2041
|
-
allows: [index.ts, passport.config.ts, passport.options.ts, passport.decorators.ts, passport.
|
|
2042
|
-
logic: [passport.
|
|
2046
|
+
requires: [index.ts, passport.config.ts, passport.options.ts, passport.decorators.ts, passport.kit.ts, passport.registration.ts] # Secrets, no defaults (R44); options and named injectors (R83); the kit and the module over @starci/auth
|
|
2047
|
+
allows: [index.ts, passport.config.ts, passport.options.ts, passport.decorators.ts, passport.kit.ts, passport.registration.ts, errors/]
|
|
2048
|
+
logic: [passport.kit.ts] # the verifier mapping over the package: measured at 100 per file
|
|
2043
2049
|
tests: unit-beside
|
|
2044
2050
|
rules: [BE_TIER_DIRECTION, BE_ERROR_HOME, BE_SECRET_DEFAULT, BE_INFRA_OWNER, BE_AUTH_PASSPORT_OWNER, BE_AUTH_JWT_OWN_JWKS, BE_AUTH_REFRESH_COOKIE]
|
|
2045
2051
|
coverage: required
|
|
2046
2052
|
since: 3.9.0
|
|
2053
|
+
- id: be.identity.sign-in
|
|
2054
|
+
since: 3.16.0
|
|
2055
|
+
profiles: [be]
|
|
2056
|
+
editions: [lite]
|
|
2057
|
+
editionWhy: "lite signs people in with the package @starci/auth, so its sign-in glue is rendered, not written (owner ruling auth-package); full uses its identity provider."
|
|
2058
|
+
# The identity capability's sign-in glue over @starci/auth: the entities of the session, attempt and user tables, the stores the package asks for (sessions, accounts, rate counter), the authenticator and the service the doors call, with their specs. `starci app sync` renders them; a hand edit is drift.
|
|
2059
|
+
path: "{src/modules/domain/identity/account-directory.service.spec.ts,src/modules/domain/identity/account-directory.service.ts,src/modules/domain/identity/authenticator.service.spec.ts,src/modules/domain/identity/authenticator.service.ts,src/modules/domain/identity/persistence/entities/auth-identity.entity.ts,src/modules/domain/identity/persistence/entities/auth-user.entity.ts,src/modules/domain/identity/persistence/entities/identity-attempt.entity.ts,src/modules/domain/identity/persistence/entities/identity-refresh-token.entity.ts,src/modules/domain/identity/persistence/entities/identity-session.entity.ts,src/modules/domain/identity/persistence/entities/index.ts,src/modules/domain/identity/rate-counter.service.spec.ts,src/modules/domain/identity/rate-counter.service.ts,src/modules/domain/identity/session-store.service.spec.ts,src/modules/domain/identity/session-store.service.ts,src/modules/domain/identity/sign-in.service.spec.ts,src/modules/domain/identity/sign-in.service.ts,src/tests/fixtures/builders/identity.builder.ts}"
|
|
2060
|
+
presence: optional
|
|
2061
|
+
tracked: tracked
|
|
2062
|
+
tier: inherit
|
|
2063
|
+
tests: unit-beside
|
|
2064
|
+
coverage: none
|
|
2065
|
+
managedBy: auth-lite
|
|
2066
|
+
managedOnly: true # lists files sync renders; the slot owning the path judges them
|
|
2067
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
2068
|
+
- id: be.feature.auth
|
|
2069
|
+
since: 3.16.0
|
|
2070
|
+
profiles: [be]
|
|
2071
|
+
editions: [lite]
|
|
2072
|
+
editionWhy: "lite signs people in with the package @starci/auth, so its sign-in glue is rendered, not written (owner ruling auth-package); full uses its identity provider."
|
|
2073
|
+
# The auth feature: the REST doors under /auth (login, refresh, session, logout, Google start and callback, jwks) over IdentitySignInService, one command or query and handler per door.
|
|
2074
|
+
path: "{src/features/api/auth/application/auth.contracts.ts,src/features/api/auth/application/get-jwks.handler.ts,src/features/api/auth/application/get-jwks.query.ts,src/features/api/auth/application/google-begin.command.ts,src/features/api/auth/application/google-begin.handler.ts,src/features/api/auth/application/google-complete.command.ts,src/features/api/auth/application/google-complete.handler.ts,src/features/api/auth/application/login.command.ts,src/features/api/auth/application/login.handler.ts,src/features/api/auth/application/logout.command.ts,src/features/api/auth/application/logout.handler.ts,src/features/api/auth/application/refresh.command.ts,src/features/api/auth/application/refresh.handler.ts,src/features/api/auth/application/session.command.ts,src/features/api/auth/application/session.handler.ts,src/features/api/auth/auth.module-definition.ts,src/features/api/auth/auth.module.ts,src/features/api/auth/auth.options.ts,src/features/api/auth/index.ts,src/features/api/auth/transport/http/auth-http.module-definition.ts,src/features/api/auth/transport/http/auth-http.module.ts,src/features/api/auth/transport/http/auth-http.options.ts,src/features/api/auth/transport/http/auth.controller.ts,src/features/api/auth/transport/http/dto/google-start.request.ts,src/features/api/auth/transport/http/dto/login.request.ts}"
|
|
2075
|
+
presence: optional
|
|
2076
|
+
tracked: tracked
|
|
2077
|
+
tier: inherit
|
|
2078
|
+
tests: none
|
|
2079
|
+
coverage: none
|
|
2080
|
+
managedBy: auth-lite
|
|
2081
|
+
managedOnly: true # lists files sync renders; the slot owning the path judges them
|
|
2082
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
2047
2083
|
- id: be.integrations.object-storage
|
|
2048
2084
|
profiles: [be]
|
|
2049
2085
|
exemplifiedBy:
|
|
2050
2086
|
- packages/hfs/templates/be/skeleton-lite/src/modules/integrations/object-storage/
|
|
2051
|
-
# The
|
|
2052
|
-
# lite): the
|
|
2087
|
+
# The glue of @starci/object-storage, the owner of the S3 client (@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner) over
|
|
2088
|
+
# S3-compatible storage (MinIO in lite): this folder keeps the bucket, parses the settings and registers the module; no app
|
|
2089
|
+
# file imports an S3 SDK or minio, and no other module imports the package.
|
|
2053
2090
|
path: "src/modules/integrations/object-storage/"
|
|
2054
2091
|
presence: optional
|
|
2055
2092
|
litePresence: required
|
|
2056
2093
|
tracked: tracked
|
|
2057
2094
|
tier: integrations
|
|
2058
2095
|
owner: true
|
|
2059
|
-
requires: [index.ts, object-storage.config.ts, object-storage.options.ts, object-storage.decorators.ts, object-storage.
|
|
2060
|
-
allows: [index.ts, object-storage.
|
|
2096
|
+
requires: [index.ts, object-storage.config.ts, object-storage.options.ts, object-storage.decorators.ts, object-storage.module-definition.ts, object-storage.module.ts]
|
|
2097
|
+
allows: [index.ts, object-storage.config.ts, object-storage.options.ts, object-storage.decorators.ts, object-storage.module-definition.ts, object-storage.module.ts, errors/]
|
|
2061
2098
|
tests: unit-beside
|
|
2062
2099
|
rules: [BE_TIER_DIRECTION, BE_ERROR_HOME, BE_SECRET_DEFAULT, BE_INFRA_OWNER, BE_STORAGE_OWNER]
|
|
2063
2100
|
coverage: required
|
|
@@ -2591,7 +2628,7 @@ slots:
|
|
|
2591
2628
|
profiles: [fe]
|
|
2592
2629
|
# The identity-provider client (fe-stack auth, FE-AUTH): the session, the access token the Apollo link attaches and the
|
|
2593
2630
|
# sign-in/sign-out calls. It talks only to the app's own back-end auth doors and holds no credential: the refresh token lives in
|
|
2594
|
-
# the back end's httpOnly cookie and the access token in memory (ruling:lite-self-hosted-postgres-passport-minio).
|
|
2631
|
+
# the back end's httpOnly cookie and the access token in the memory of the one @starci/auth client (ruling:lite-self-hosted-postgres-passport-minio).
|
|
2595
2632
|
path: "apps/<app>/src/modules/auth/"
|
|
2596
2633
|
presence: optional
|
|
2597
2634
|
tracked: tracked
|
|
@@ -2601,6 +2638,20 @@ slots:
|
|
|
2601
2638
|
tests: none
|
|
2602
2639
|
since: 3.0.0
|
|
2603
2640
|
rules: [FE_STACK_FORBIDDEN]
|
|
2641
|
+
- id: fe.modules.auth.client
|
|
2642
|
+
since: 3.16.0
|
|
2643
|
+
profiles: [fe]
|
|
2644
|
+
editions: [lite]
|
|
2645
|
+
editionWhy: "lite signs people in with the package @starci/auth, so its auth client is rendered, not written (owner ruling auth-package); full wires its identity provider."
|
|
2646
|
+
# The AuthClient every edition shares, implemented by one @starci/auth/client instance over the app's own back-end auth doors.
|
|
2647
|
+
path: "apps/web/src/modules/auth/client.ts"
|
|
2648
|
+
presence: optional
|
|
2649
|
+
tracked: tracked
|
|
2650
|
+
tier: inherit
|
|
2651
|
+
tests: none
|
|
2652
|
+
managedBy: auth-lite
|
|
2653
|
+
managedOnly: true # lists files sync renders; the slot owning the path judges them
|
|
2654
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
2604
2655
|
- id: fe.modules.toast
|
|
2605
2656
|
profiles: [fe]
|
|
2606
2657
|
# Mutation feedback (fe-stack toast, FE-TOAST): the HeroUI toast wrapper, showGraphQLToast over a GraphQLResponse and the
|
|
@@ -5347,6 +5347,36 @@ SEALED_FILE_IN_WORK:
|
|
|
5347
5347
|
|
|
5348
5348
|
# --- HFS rule catalog (knowledge/hfs/rules.yaml): one code per rule, from R01 up ---
|
|
5349
5349
|
|
|
5350
|
+
STACKS_LOCAL_CONFIG_INVALID:
|
|
5351
|
+
title: "The local block of a docker-compose environment is not coherent"
|
|
5352
|
+
title_vi: "Khối local của môi trường docker-compose không nhất quán"
|
|
5353
|
+
meaning_vi: "environments.<env>.local thiếu hoặc có trường lạ, cổng trùng, dịch vụ không có trong tệp compose, vai trò cơ sở dữ liệu dùng chung, hoặc thăm dò không nằm trên loopback."
|
|
5354
|
+
causes_vi:
|
|
5355
|
+
- "Vi phạm R372: khối local được kiểm bằng đúng normalizeLocal mà các động từ starci app stack up, down, doctor dùng."
|
|
5356
|
+
nextStep_vi: "Sửa đúng trường nêu trong thông báo (environments.<env>.local.<đường dẫn>), rồi chạy lại starci app check."
|
|
5357
|
+
owner: op-retry
|
|
5358
|
+
kind: check-finding
|
|
5359
|
+
|
|
5360
|
+
STACKS_DEV_UNDECLARED:
|
|
5361
|
+
title: "A lite app declares no runnable dev environment"
|
|
5362
|
+
title_vi: "Ứng dụng lite chưa khai báo môi trường dev chạy được"
|
|
5363
|
+
meaning_vi: "Không có environment nào có runtime docker-compose và khối local, nên starci app stack up --env dev không có gì để chạy."
|
|
5364
|
+
causes_vi:
|
|
5365
|
+
- "Vi phạm R372: môi trường dev vẫn là Swarm hoặc chưa được khai báo."
|
|
5366
|
+
nextStep_vi: "Khai báo environments.dev với runtime docker-compose, composeFiles và khối local; runbook của nó nêu starci app stack up --env dev."
|
|
5367
|
+
owner: op-retry
|
|
5368
|
+
kind: check-finding
|
|
5369
|
+
|
|
5370
|
+
STACKS_RUNBOOK_DOCKER_COMMAND:
|
|
5371
|
+
title: "A dev runbook carries a docker command or omits the one-command start"
|
|
5372
|
+
title_vi: "Runbook dev chứa lệnh docker hoặc không nêu lệnh khởi động duy nhất"
|
|
5373
|
+
meaning_vi: "README của môi trường docker-compose có dòng docker build, run, compose hay stack deploy, hoặc không nêu starci app stack up --env <env>."
|
|
5374
|
+
causes_vi:
|
|
5375
|
+
- "Vi phạm R373 và quy tắc cứng 8: Docker do harness chạy, tác tử không chạy tay."
|
|
5376
|
+
nextStep_vi: "Thay các lệnh docker bằng starci app stack up --env <env> --execute và các động từ down, status, logs của nó."
|
|
5377
|
+
owner: op-retry
|
|
5378
|
+
kind: check-finding
|
|
5379
|
+
|
|
5350
5380
|
STACKS_DEPLOY_CONFIG_INVALID:
|
|
5351
5381
|
title: "A deploy block of application-stacks.yaml is not coherent"
|
|
5352
5382
|
title_vi: "Khối deploy trong application-stacks.yaml không nhất quán"
|
|
@@ -5674,3 +5704,35 @@ BE_JOBS_SCHEDULER_OWNER:
|
|
|
5674
5704
|
nextStep_vi: "Khai tick vào JOB_TICKS của platform/jobs/job-ticks.contracts.ts (name, cron, timeZone UTC, queue, payload) và xoá lịch tự viết; giữ advisoryXactLock và job_tick_claim trong JobTickService."
|
|
5675
5705
|
owner: op-retry
|
|
5676
5706
|
kind: check-finding
|
|
5707
|
+
|
|
5708
|
+
STACKS_CODE_BIND_MOUNT:
|
|
5709
|
+
title: "A stack or compose file bind-mounts code into a service container"
|
|
5710
|
+
title_vi: "Tệp stack hoặc compose gắn (bind-mount) mã vào container của dịch vụ"
|
|
5711
|
+
meaning_vi: "Một dịch vụ gắn thư mục hoặc tệp mã, plugin, script hay đường dẫn ghi được của repository từ máy chủ vào container."
|
|
5712
|
+
causes_vi:
|
|
5713
|
+
- "Vi phạm R374: mã của dịch vụ phải nằm trong image dựng từ .starcistacks/images/<tên>/, không gắn lúc chạy."
|
|
5714
|
+
nextStep_vi: "Đưa mã vào Dockerfile của .starcistacks/images/<tên>/ (FROM image đã ghim digest, hoặc image fork của harness) và bỏ bind-mount; chỉ giữ volume dữ liệu, secret và tệp cấu hình thuần dữ liệu chỉ đọc."
|
|
5715
|
+
|
|
5716
|
+
STACKS_IMAGE_BASE_UNPINNED:
|
|
5717
|
+
title: "A service image folder has a FROM that is not digest-pinned"
|
|
5718
|
+
title_vi: "Thư mục image của dịch vụ có FROM chưa ghim digest"
|
|
5719
|
+
meaning_vi: "Dockerfile trong .starcistacks/images/<tên>/ dùng FROM theo tag, không theo name@sha256:..."
|
|
5720
|
+
causes_vi:
|
|
5721
|
+
- "Vi phạm R374: mọi image nền phải ghim digest."
|
|
5722
|
+
nextStep_vi: "Ghim FROM bằng name@sha256:<digest>."
|
|
5723
|
+
|
|
5724
|
+
STACKS_IMAGE_BASE_NOT_FORK:
|
|
5725
|
+
title: "A service image folder does not build on the harness fork image"
|
|
5726
|
+
title_vi: "Thư mục image của dịch vụ không dựng trên image fork của harness"
|
|
5727
|
+
meaning_vi: "Harness sở hữu image fork StarCi cho dịch vụ này (images/sources.json) nhưng giai đoạn cuối của Dockerfile không FROM image đó."
|
|
5728
|
+
causes_vi:
|
|
5729
|
+
- "Vi phạm R374: dịch vụ tùy biến phải dựng trên image fork do harness ghim."
|
|
5730
|
+
nextStep_vi: "Đặt FROM <repository fork>@sha256:<digest> ở giai đoạn cuối."
|
|
5731
|
+
|
|
5732
|
+
STACKS_IMAGE_ENV_DIVERGES:
|
|
5733
|
+
title: "A service with an image folder runs a third-party image in an environment"
|
|
5734
|
+
title_vi: "Dịch vụ có thư mục image chạy image bên thứ ba ở một môi trường"
|
|
5735
|
+
meaning_vi: "Dev và production phải cùng chạy một image dựng từ .starcistacks/images/<tên>/."
|
|
5736
|
+
causes_vi:
|
|
5737
|
+
- "Vi phạm R374: một môi trường dùng image upstream hoặc image nước ngoài thay vì image dựng từ thư mục."
|
|
5738
|
+
nextStep_vi: "Dùng build.context trỏ tới thư mục image (compose) hoặc tham chiếu image của dự án (stack)."
|
|
@@ -510,6 +510,12 @@ $defs:
|
|
|
510
510
|
runbook: {type: string, minLength: 1}
|
|
511
511
|
secrets: {type: array, items: {$ref: '#/$defs/secret'}}
|
|
512
512
|
deploy: {$ref: '#/$defs/deploy'}
|
|
513
|
+
local:
|
|
514
|
+
description: >-
|
|
515
|
+
The dev declaration `starci app stack up|down|doctor|prepare|status|logs|verify` runs for a docker-compose environment (PROJECT-STACKS-6):
|
|
516
|
+
ports, compose services, the environment's own database role, dev-only custody to generate once, setup and seed commands, native app
|
|
517
|
+
processes, readiness and verification probes. Names, ports and argv lists only, never a value. The authority is scripts/hfs/stack-local-config.mjs; rule R340 judges it.
|
|
518
|
+
type: object
|
|
513
519
|
ingress:
|
|
514
520
|
description: "The one selected ingress component and the hosts it routes, or external with the stack name when the ingress is a shared stack outside this one (then no component; rule R275 judges which of the two is declared)."
|
|
515
521
|
type: object
|