@starci/hfs 5.1.0 → 5.3.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 +54 -0
- package/README.md +11 -2
- package/cache/hfs-family.d.mts +2 -3
- package/cache/hfs-family.mjs +4 -9
- package/cache/secret-records.d.mts +7 -0
- package/cache/secret-records.mjs +12 -0
- package/cache/session.mjs +4 -2
- package/codemod/account-doors.d.mts +36 -0
- package/codemod/account-doors.mjs +128 -0
- package/codemod/main.mjs +31 -1
- package/codemod/module-definition.d.mts +52 -0
- package/codemod/module-definition.mjs +242 -0
- package/codemod/quality-binding.d.mts +33 -0
- package/codemod/quality-binding.mjs +38 -0
- package/codemod/secrets-cache.d.mts +35 -0
- package/codemod/secrets-cache.mjs +70 -0
- package/codemod/sops-rules.d.mts +34 -0
- package/codemod/sops-rules.mjs +69 -0
- package/codemod/theme-tokens.mjs +48 -2
- package/db/postgres.mjs +9 -1
- package/lint/run.d.mts +6 -0
- package/lint/run.mjs +63 -10
- package/package.json +1 -1
- package/runtime/knowledge/hfs/canon-pins.yaml +65 -11
- package/runtime/knowledge/hfs/fe-stack.yaml +9 -9
- package/runtime/knowledge/hfs/fork-images.yaml +7 -0
- package/runtime/knowledge/hfs/rules.yaml +67 -15
- package/runtime/knowledge/hfs/slots.yaml +174 -30
- package/runtime/modules/kernel/failure-codes.yaml +67 -4
- package/runtime/modules/schemas/application-stacks.schema.yaml +6 -0
- package/runtime/scripts/hfs/architecture/config.d.mts +4 -0
- package/runtime/scripts/hfs/architecture/config.mjs +25 -1
- package/runtime/scripts/hfs/architecture/identity.mjs +18 -83
- package/runtime/scripts/hfs/architecture/module-per-transport.d.mts +1 -1
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +6 -1
- package/runtime/scripts/hfs/architecture/root-packages.d.mts +26 -0
- package/runtime/scripts/hfs/architecture/root-packages.mjs +78 -0
- 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/architecture/type-context.d.mts +4 -1
- package/runtime/scripts/hfs/architecture/type-context.mjs +30 -0
- package/runtime/scripts/hfs/architecture/typescript.d.mts +7 -1
- package/runtime/scripts/hfs/architecture/typescript.mjs +21 -1
- package/runtime/scripts/hfs/explicit-surface-rule.mjs +1 -1
- 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/database-access.mjs +39 -1
- package/runtime/scripts/hfs/rules/monorepo.d.mts +4 -0
- package/runtime/scripts/hfs/rules/monorepo.mjs +10 -5
- package/runtime/scripts/hfs/rules/secrets.mjs +11 -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-errors.d.mts +3 -0
- package/runtime/scripts/hfs/secret-errors.mjs +8 -0
- package/runtime/scripts/hfs/secret-init.d.mts +6 -0
- package/runtime/scripts/hfs/secret-init.mjs +23 -0
- package/runtime/scripts/hfs/secret-sops.mjs +9 -1
- package/runtime/scripts/hfs/secret-standard.d.mts +20 -0
- package/runtime/scripts/hfs/secret-standard.mjs +106 -0
- package/runtime/scripts/hfs/secret.mjs +15 -8
- 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/hfs/view.d.mts +23 -0
- package/runtime/scripts/hfs/view.mjs +68 -0
- package/runtime/scripts/lib/declaration-surface.d.mts +4 -0
- package/runtime/scripts/lib/declaration-surface.mjs +55 -1
- package/runtime/scripts/lib/secret-records.d.mts +13 -0
- package/runtime/scripts/lib/secret-records.mjs +83 -0
- package/runtime/scripts/lib/swarm-stack.d.mts +2 -1
- package/runtime/scripts/lib/swarm-stack.mjs +2 -2
- package/scaffold/add-inbox-lite.mjs +2 -2
- package/scaffold/add-module.d.mts +16 -0
- package/scaffold/add-module.mjs +232 -0
- package/scaffold/add-queue-lite.mjs +50 -3
- package/scaffold/add.mjs +5 -0
- package/scaffold/app.d.mts +2 -2
- package/scaffold/app.mjs +16 -18
- package/scaffold/lite-exports.mjs +1 -15
- package/scaffold/module-registry.d.mts +19 -0
- package/scaffold/module-registry.mjs +84 -0
- package/scripts/sync-bundles.d.mts +8 -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/images/openclaw-runtime/Dockerfile +18 -0
- package/stack/images/openclaw-runtime/entrypoint.sh +23 -0
- package/stack/images/openclaw-runtime/openclaw-init.mjs +101 -0
- package/stack/images/openclaw-runtime/openclaw-relay.mjs +25 -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 +169 -0
- package/stack/local-verify.d.mts +6 -0
- package/stack/local-verify.mjs +21 -0
- package/stack/runtime-layers.d.mts +21 -0
- package/stack/runtime-layers.mjs +67 -0
- package/sync/hygiene.mjs +3 -1
- package/sync/index.d.mts +15 -12
- package/sync/index.mjs +114 -28
- package/templates/app/auth-doors.sql.partial +115 -0
- package/templates/app/ci-workflows/github/workflows/ci.yml +1 -1
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +1 -1
- 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/core.json +1 -1
- 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 +85 -70
- package/templates/app/skeleton-lite/.starcistacks/dev/README.md +24 -12
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/compose/compose.yaml +43 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +21 -26
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +6 -1
- package/templates/app/skeleton-lite/db/migrations/__timestamp___baseline.sql +76 -13
- package/templates/be/auth-lite/src/features/api/auth/application/auth.contracts.ts +44 -0
- package/templates/be/auth-lite/src/features/api/auth/application/confirm.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/confirm.handler.ts +22 -0
- package/templates/be/auth-lite/src/features/api/auth/application/forgot.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/forgot.handler.ts +22 -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/resend.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/resend.handler.ts +22 -0
- package/templates/be/auth-lite/src/features/api/auth/application/reset.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/reset.handler.ts +22 -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/application/signup.command.ts +11 -0
- package/templates/be/auth-lite/src/features/api/auth/application/signup.handler.ts +22 -0
- package/templates/be/auth-lite/src/features/api/auth/auth.module-definition.ts +6 -0
- package/templates/be/auth-lite/src/features/api/auth/auth.module.ts +21 -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 +6 -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 +145 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/dto/forgot.request.ts +16 -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/features/api/auth/transport/http/dto/resend.request.ts +16 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/dto/reset.request.ts +18 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/dto/signup.request.ts +22 -0
- package/templates/be/auth-lite/src/features/api/auth/transport/http/dto/token.request.ts +11 -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 +19 -0
- package/templates/be/auth-lite/src/modules/domain/identity/authenticator.service.spec.ts +209 -0
- package/templates/be/auth-lite/src/modules/domain/identity/authenticator.service.ts +84 -0
- package/templates/be/auth-lite/src/modules/domain/identity/identity-email.log-events.ts +6 -0
- package/templates/be/auth-lite/src/modules/domain/identity/identity-email.service.spec.ts +233 -0
- package/templates/be/auth-lite/src/modules/domain/identity/identity-email.service.ts +176 -0
- package/templates/be/auth-lite/src/modules/domain/identity/identity-sign-in.log-events.ts +6 -0
- package/templates/be/auth-lite/src/modules/domain/identity/persistence/account-doors.port.ts +98 -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-email-token.entity.ts +34 -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 +10 -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 +95 -0
- package/templates/be/auth-lite/src/modules/domain/identity/sign-in.service.ts +93 -0
- package/templates/be/auth-lite/src/tests/fixtures/builders/identity.builder.ts +40 -0
- package/templates/be/inbox/module-definition.ts.tpl +2 -9
- package/templates/be/inbox/platform/event-bus/event-bus.module-definition.ts.tpl +2 -11
- package/templates/be/inbox/platform/inbox/inbox.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/api/feature.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/api/graphql.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/cli/group.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +3 -10
- package/templates/be/patterns/idempotency/platform/inbox/inbox.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/jobs/job.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/jobs/job.queue.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +3 -10
- package/templates/be/patterns/projections/projection.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +3 -10
- package/templates/be/patterns/queues/queue.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/reactors/message.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/reactors/reactor.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/realtime/channel.graphql.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/realtime/channel.sse.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/realtime/channel.websocket.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/saga/saga.message.module-definition.ts.tpl +3 -9
- package/templates/be/patterns/saga/saga.module-definition.ts.tpl +2 -9
- package/templates/be/patterns/webhooks/webhook.http.module-definition.ts.tpl +3 -9
- package/templates/be/platform/graphql/graphql.module-definition.ts +2 -9
- package/templates/be/skeleton/src/features/api/system-health/system-health.module-definition.ts +3 -9
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.module-definition.ts +3 -9
- package/templates/be/skeleton/src/features/cli/cli.module-definition.ts +2 -9
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module-definition.ts +3 -9
- package/templates/be/skeleton/src/features/cli/seed/seed.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/domain/identity/identity.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/domain/liveness/liveness.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/platform/clock/clock.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +3 -13
- package/templates/be/skeleton/src/modules/platform/errors/errors.module-definition.ts +4 -11
- package/templates/be/skeleton/src/modules/platform/http/http.module-definition.ts +4 -9
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.module-definition.ts +5 -11
- package/templates/be/skeleton/src/modules/platform/i18n/i18n.module-definition.ts +4 -11
- package/templates/be/skeleton/src/modules/platform/ids/ids.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/platform/logging/logging.module-definition.ts +2 -9
- package/templates/be/skeleton/src/modules/platform/retry/retry.module-definition.ts +2 -9
- package/templates/be/skeleton-lite/apps/api/src/api.env.ts +4 -0
- package/templates/be/skeleton-lite/apps/api/src/api.options.ts +3 -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 +12 -5
- package/templates/be/skeleton-lite/src/modules/domain/identity/errors/identity.error.ts +40 -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 +50 -2
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +3 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/messages/identity-mail.messages.ts +65 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/messages/identity.messages.ts +28 -0
- package/templates/be/skeleton-lite/src/modules/integrations/mail/index.ts +6 -0
- package/templates/be/skeleton-lite/src/modules/integrations/mail/mail.config.ts +33 -0
- package/templates/be/skeleton-lite/src/modules/integrations/mail/mail.decorators.ts +14 -0
- package/templates/be/skeleton-lite/src/modules/integrations/mail/mail.module-definition.ts +12 -0
- package/templates/be/skeleton-lite/src/modules/integrations/mail/mail.module.ts +27 -0
- package/templates/be/skeleton-lite/src/modules/integrations/mail/mail.options.ts +22 -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 +5 -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/database/index.ts +1 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +1 -1
- package/templates/be/skeleton-lite/src/modules/platform/http-security/rate-limit.guard.spec.ts +11 -0
- package/templates/be/skeleton-lite/src/tests/fixtures/builders/api.builder.ts +22 -4
- package/templates/be/table/api/feature.module-definition.ts.tpl +3 -9
- package/templates/be/table/api/graphql.module-definition.ts.tpl +3 -9
- package/templates/be/table/module-definition.ts.tpl +2 -9
- 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/auth-lite/apps/web/src/modules/auth/email-doors.ts +16 -0
- package/templates/fe/auth-lite/apps/web/src/modules/auth/index.ts +5 -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 +30 -67
- package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +6 -21
- package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +10 -16
- 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/app/[locale]/auth/confirm/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/auth/forgot/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/auth/resend/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/auth/reset/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/auth/signup/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +5 -9
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/EmailDoorForm/component.tsx +51 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/EmailDoorForm/index.tsx +84 -0
- 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/fe/skeleton-lite/apps/web/src/features/pages/AppConfirmPage/index.tsx +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppForgotPage/index.tsx +21 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +11 -3
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +4 -1
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppResendPage/index.tsx +21 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppResetPage/index.tsx +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppSignupPage/index.tsx +21 -0
- package/templates/fe/skeleton-lite/apps/web/src/hooks/emailAuth/emailAuth.shared.ts +12 -0
- package/templates/fe/skeleton-lite/apps/web/src/hooks/emailAuth/index.ts +2 -0
- package/templates/fe/skeleton-lite/apps/web/src/hooks/emailAuth/useEmailDoor.ts +32 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +2 -2
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/en.json +50 -1
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +50 -1
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +7 -30
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +13 -14
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +5 -0
- package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +4 -17
- 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
|
@@ -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.17.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).
|
|
@@ -58,6 +58,9 @@ versioning:
|
|
|
58
58
|
# 3.13.0 (rulings lite-pgmq-bus-bullmq-jobs and lite-db-image-in-stacks, 2026-10-29) is a change for lite only: ruleParams.db.extensions
|
|
59
59
|
# admits pgmq, the event bus, ruleParams.db.queueOutbox is retired with the pg_cron half of R258, the lite event-bus functions replace
|
|
60
60
|
# event_bus_write in ruleParams.be.dbFunctions, and app.db.image moves to .starcistacks/images/db/Dockerfile (db/ keeps schema and data).
|
|
61
|
+
# 3.17.0 (ruling auth-oidc-package, 2026-11-03) adds the optional full-edition be.integrations.keycloak, the glue of @starci/auth-oidc (the OIDC client of the
|
|
62
|
+
# identity provider behind the PrincipalVerifier of @starci/auth), and gives @starci/auth-oidc to it in ruleParams.be.infraOwners.
|
|
63
|
+
# 3.17.0 (ruling module-packages, 2026-11-03) adds the optional app.packages and app.module-registry: the workspace packages of the app root (the agent SDK, the module packages, the managed registry).
|
|
61
64
|
# 3.15.0 (ruling app-check-cache, 2026-10-31) adds the optional app.starcistacks.cache, the committed check cache of the app (.starcistacks/cache/, both editions).
|
|
62
65
|
# 3.14.0 (ruling app-secrets-one-standard, 2026-10-29) adds the optional app.ci-stack-key-restore, the managed workflow that writes the
|
|
63
66
|
# deploy server's age identity back from its GitHub Environment backup.
|
|
@@ -117,6 +120,8 @@ versioning:
|
|
|
117
120
|
# liteManagedBy is managed only in lite; its effective lite.path still lists literal files.
|
|
118
121
|
# the managed file list lives here and nowhere in code. A difference is HFS_MANAGED_FILE_DRIFT (a
|
|
119
122
|
# back end's tsconfig.json: HFS_TS_STRICT when a flag or an option was added).
|
|
123
|
+
# managedOnly true: the slot only lists files sync renders (needs managedBy); the path is judged by the slot that owns it, so the rendered
|
|
124
|
+
# file keeps the rules and the tier of its folder (a sign-in service is a domain service)
|
|
120
125
|
# rules rule codes from knowledge/hfs/rules.yaml.
|
|
121
126
|
# editions the editions (below) the slot exists in; default all of them. A slot outside the declared edition owns
|
|
122
127
|
# no path - under lite, what full keeps absent is removed, and what lite forbids is a finding.
|
|
@@ -250,17 +255,29 @@ ruleParams:
|
|
|
250
255
|
"node:https": [platform/http]
|
|
251
256
|
http: [platform/http]
|
|
252
257
|
https: [platform/http]
|
|
253
|
-
"@aws-sdk/client-s3": [
|
|
254
|
-
"@aws-sdk/s3-request-presigner": [
|
|
255
|
-
|
|
258
|
+
"@aws-sdk/client-s3": [] # the S3 client is a dependency of @starci/object-storage, imported by no app file (R331)
|
|
259
|
+
"@aws-sdk/s3-request-presigner": []
|
|
260
|
+
"@starci/object-storage": [integrations/object-storage] # the ObjectStorage port: one S3 adapter for MinIO, S3 and Spaces (R331)
|
|
261
|
+
minio: [] # storage goes through @starci/object-storage
|
|
262
|
+
nodemailer: [] # the SMTP client is a dependency of @starci/mail alone; no app file imports it
|
|
263
|
+
"@starci/mail": [integrations/mail] # outgoing mail: the Mailer port, parsed and registered by its one glue
|
|
256
264
|
"@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: [
|
|
265
|
+
"@nestjs/passport": [] # the identity libraries are @starci/auth's dependencies, never an app's (R328)
|
|
266
|
+
passport: []
|
|
267
|
+
passport-google-oauth20: []
|
|
268
|
+
passport-local: []
|
|
269
|
+
"@nestjs/jwt": []
|
|
270
|
+
jose: []
|
|
271
|
+
bcryptjs: []
|
|
272
|
+
jsonwebtoken: [] # no other JWT or OIDC client library in a back end: the tokens of an identity provider are verified by @starci/auth-oidc (R328)
|
|
273
|
+
jwks-rsa: []
|
|
274
|
+
jwt-decode: []
|
|
275
|
+
passport-jwt: []
|
|
276
|
+
openid-client: []
|
|
277
|
+
"@starci/auth": [integrations/passport] # the lite sign-in package: its server entry is reached only through integrations/passport (R328)
|
|
278
|
+
"@starci/auth/testing": [integrations/passport] # its test doubles, for the glue's specs
|
|
279
|
+
"@starci/auth-oidc": [integrations/keycloak] # the full sign-in package (jose is its dependency, imported by no app file): its server entry is reached only through integrations/keycloak (R328)
|
|
280
|
+
"@starci/auth-oidc/testing": [integrations/keycloak] # its fake issuer, for the glue's specs
|
|
264
281
|
bcrypt: []
|
|
265
282
|
cache-manager: [integrations/cache, integrations/redis]
|
|
266
283
|
"@nestjs/cache-manager": [integrations/cache, integrations/redis] # the CACHE_MANAGER token: caching goes through the cache capability
|
|
@@ -474,6 +491,14 @@ ruleParams:
|
|
|
474
491
|
- {name: public.event_bus_bury, reason: "platform/event-bus (add webhook, lite): the move of an exhausted or malformed message to its consumer's dead-letter queue"}
|
|
475
492
|
- {name: public.event_bus_dead_letters, reason: "platform/event-bus (add webhook, lite): the operator read of a consumer's dead-letter queue"}
|
|
476
493
|
- {name: public.event_bus_requeue, reason: "platform/event-bus (add webhook, lite): the operator requeue of one dead letter"}
|
|
494
|
+
- {name: public.be_auth_user_by_email, reason: "domain/identity (lite sign-in): the account of an exact sign-in address with its bcrypt hash, through the account-doors definer of the baseline"}
|
|
495
|
+
- {name: public.be_auth_user_by_id, reason: "domain/identity (lite sign-in): the standing of one account by id (a refresh), through the account-doors definer"}
|
|
496
|
+
- {name: public.be_auth_user_by_google, reason: "domain/identity (lite sign-in): the account a Google subject is linked to, through the account-doors definer"}
|
|
497
|
+
- {name: public.be_auth_create_user, reason: "domain/identity (lite sign-in): the account a first Google sign-in creates, through the account-doors definer"}
|
|
498
|
+
- {name: public.be_auth_link_google, reason: "domain/identity (lite sign-in): the link of a Google subject to an account, through the account-doors definer"}
|
|
499
|
+
- {name: public.be_auth_touch_user, reason: "domain/identity (lite sign-in): the sign-in record of an account and its profile keys, through the account-doors definer"}
|
|
500
|
+
- {name: public.be_auth_confirm_user, reason: "domain/identity (lite sign-in): the confirmation stamp of a mailbox whose link was spent, through the account-doors definer"}
|
|
501
|
+
- {name: public.be_auth_set_password, reason: "domain/identity (lite sign-in): the new password hash of a spent reset link (and the mailbox it proved), through the account-doors definer"}
|
|
477
502
|
# R334 (lite): the only `.query(` outside platform/database's composer and the test world is the pass-through of a file listed here
|
|
478
503
|
# (or in hfs.json sides.be.sqlPassThrough), whose SQL text is not the app's own. Paths are relative to the side folder.
|
|
479
504
|
sqlPassThrough:
|
|
@@ -601,13 +626,24 @@ slots:
|
|
|
601
626
|
- id: app.tool-config-local
|
|
602
627
|
since: 3.1.0
|
|
603
628
|
profiles: [app]
|
|
604
|
-
path: "{tsconfig.json,.eslintrc,.eslintrc.*,.eslintignore,eslint.config
|
|
629
|
+
path: "{tsconfig.json,.eslintrc,.eslintrc.*,.eslintignore,eslint.config.js,eslint.config.cjs,eslint.config.ts,eslint.config.mts,eslint.config.cts,.stylelintrc,.stylelintrc.*,.stylelintignore,stylelint.config.*,.prettierrc.*,prettier.config.*,jest.config.*,lint-staged.config.*,.lintstagedrc*}"
|
|
605
630
|
presence: forbidden
|
|
606
631
|
tracked: external
|
|
607
632
|
tier: none
|
|
608
633
|
tests: none
|
|
609
|
-
goesTo: "nowhere at the app root: each side holds exactly its managed tool configuration (be.tool-config, fe.tool-config) and the root only the formatter (app.format-config)"
|
|
634
|
+
goesTo: "nowhere at the app root: each side holds exactly its managed tool configuration (be.tool-config, fe.tool-config) and the root only the formatter (app.format-config) and the eslint config of its root packages (app.packages-lint)"
|
|
610
635
|
rules: [HFS_TOOL_CONFIG_LOCAL]
|
|
636
|
+
- id: app.packages-lint
|
|
637
|
+
since: 3.17.0
|
|
638
|
+
profiles: [app]
|
|
639
|
+
# The one eslint config at the app root: `starci app sync` renders it when the app has root workspace packages (app.packages), and it lints their
|
|
640
|
+
# source by subpath (the back-end canon, the front-end canon and the Grammar family each over their own subpaths). No other tool config lives here.
|
|
641
|
+
path: eslint.config.mjs
|
|
642
|
+
presence: optional
|
|
643
|
+
tracked: tracked
|
|
644
|
+
tier: none
|
|
645
|
+
tests: none
|
|
646
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
611
647
|
- id: app.quality-config
|
|
612
648
|
since: 3.1.0
|
|
613
649
|
profiles: [app]
|
|
@@ -852,6 +888,31 @@ slots:
|
|
|
852
888
|
rules: [HFS_PLAINTEXT_SECRET, HFS_SCRIPT_ONE_OFF, BE_SPEC_PLACEMENT, HFS_REPO_LOCAL_CHECK]
|
|
853
889
|
exemplifiedBy:
|
|
854
890
|
- {path: packages/hfs/src/hfs-slot-ownership.spec.mjs, editions: [lite, full]}
|
|
891
|
+
- id: app.packages
|
|
892
|
+
since: 3.17.0
|
|
893
|
+
profiles: [app]
|
|
894
|
+
editionWhy: Lite and full share the slot; a product's agent SDK and its agent modules are workspace packages in both.
|
|
895
|
+
# A workspace package of the app ROOT (packages/agent-sdk, packages/module-<name>): first-party source that both sides import through its
|
|
896
|
+
# package entry points and never past them (ARCH_INTERNAL_IMPORT_OUTSIDE), linted by the root eslint config by subpath.
|
|
897
|
+
path: "packages/{agent-sdk,module-<name>}/"
|
|
898
|
+
presence: optional
|
|
899
|
+
tracked: tracked
|
|
900
|
+
tier: none
|
|
901
|
+
requires: [package.json, tsconfig.json, src/index.ts]
|
|
902
|
+
tests: unit-beside
|
|
903
|
+
rules: [HFS_UNUSED_EXPORT]
|
|
904
|
+
- id: app.module-registry
|
|
905
|
+
since: 3.17.0
|
|
906
|
+
profiles: [app]
|
|
907
|
+
editionWhy: Lite and full share the slot; the registry lists the module packages of the app.
|
|
908
|
+
path: packages/modules/
|
|
909
|
+
presence: optional
|
|
910
|
+
tracked: tracked
|
|
911
|
+
tier: none
|
|
912
|
+
requires: [package.json, src/index.ts]
|
|
913
|
+
allows: [package.json, tsconfig.json, tsconfig.build.json, src/index.ts, src/template/index.ts, src/manifest/index.ts]
|
|
914
|
+
tests: none
|
|
915
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
855
916
|
- id: app.sides
|
|
856
917
|
since: 3.1.0
|
|
857
918
|
profiles: [app]
|
|
@@ -909,7 +970,7 @@ slots:
|
|
|
909
970
|
# The db service supplies the database; schedules are platform/jobs ticks (R335); production has no Compose or host cron.
|
|
910
971
|
lite:
|
|
911
972
|
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",
|
|
973
|
+
allows: [application-stacks.yaml, images/db/Dockerfile, "<env>/README.md", "<env>/environment.json", "<env>/infra/{compose,swarm}/**", "<env>/infra/metadata.json",
|
|
913
974
|
"<env>/runtime/{config,env}/**", "<env>/runtime/env/KEYS.md", "<env>/secrets/<slug>.{enc.yaml,enc}", "<env>/secrets/.gitkeep", "<env>/seeds/**"]
|
|
914
975
|
forbids: ["<env>/runtime/files/**", "**/*.enc outside <env>/secrets/", DESIGN.md, deployment.json, "k8s/ at root"]
|
|
915
976
|
rules: [HFS_STACKS_SHAPE, HFS_STACKS_IN_SIDE, HFS_PLAINTEXT_SECRET, HFS_IDENTITY_CUSTODY]
|
|
@@ -2028,40 +2089,109 @@ slots:
|
|
|
2028
2089
|
editions: [lite]
|
|
2029
2090
|
exemplifiedBy:
|
|
2030
2091
|
- packages/hfs/templates/be/skeleton-lite/src/modules/integrations/passport/
|
|
2031
|
-
# The
|
|
2032
|
-
#
|
|
2033
|
-
#
|
|
2034
|
-
#
|
|
2092
|
+
# The glue of @starci/auth, the lite sign-in package (Google OAuth with state and PKCE, email and password, EdDSA access tokens with
|
|
2093
|
+
# their JWKS, rotating refresh sessions): the one importer of the package (ruleParams.be.infraOwners), which owns the identity
|
|
2094
|
+
# libraries (@nestjs/passport, passport, passport-google-oauth20, passport-local, @nestjs/jwt, jose, bcryptjs) that no app imports.
|
|
2095
|
+
# It parses the typed options, builds the verifier and names the injectors; domain/identity verifies a token through the kit and
|
|
2096
|
+
# builds the principal (contexts/code/be/api-auth.md).
|
|
2035
2097
|
path: "src/modules/integrations/passport/"
|
|
2036
2098
|
presence: required
|
|
2037
2099
|
tracked: tracked
|
|
2038
2100
|
tier: integrations
|
|
2039
2101
|
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.
|
|
2102
|
+
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
|
|
2103
|
+
allows: [index.ts, passport.config.ts, passport.options.ts, passport.decorators.ts, passport.kit.ts, passport.registration.ts, errors/]
|
|
2104
|
+
logic: [passport.kit.ts] # the verifier mapping over the package: measured at 100 per file
|
|
2043
2105
|
tests: unit-beside
|
|
2044
2106
|
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
2107
|
coverage: required
|
|
2046
2108
|
since: 3.9.0
|
|
2109
|
+
- id: be.identity.sign-in
|
|
2110
|
+
since: 3.16.0
|
|
2111
|
+
profiles: [be]
|
|
2112
|
+
editions: [lite]
|
|
2113
|
+
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."
|
|
2114
|
+
# The identity capability's sign-in glue over @starci/auth: the entities of the session, attempt, refresh-token and email-token tables, the account doors over auth.users and auth.identities, 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.
|
|
2115
|
+
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/identity-email.log-events.ts,src/modules/domain/identity/identity-email.service.spec.ts,src/modules/domain/identity/identity-email.service.ts,src/modules/domain/identity/identity-sign-in.log-events.ts,src/modules/domain/identity/persistence/account-doors.port.ts,src/modules/domain/identity/persistence/entities/identity-attempt.entity.ts,src/modules/domain/identity/persistence/entities/identity-email-token.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}"
|
|
2116
|
+
presence: optional
|
|
2117
|
+
tracked: tracked
|
|
2118
|
+
tier: inherit
|
|
2119
|
+
tests: unit-beside
|
|
2120
|
+
coverage: none
|
|
2121
|
+
managedBy: auth-lite
|
|
2122
|
+
managedOnly: true # lists files sync renders; the slot owning the path judges them
|
|
2123
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
2124
|
+
- id: be.feature.auth
|
|
2125
|
+
since: 3.16.0
|
|
2126
|
+
profiles: [be]
|
|
2127
|
+
editions: [lite]
|
|
2128
|
+
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."
|
|
2129
|
+
# 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.
|
|
2130
|
+
path: "{src/features/api/auth/application/auth.contracts.ts,src/features/api/auth/application/confirm.command.ts,src/features/api/auth/application/confirm.handler.ts,src/features/api/auth/application/forgot.command.ts,src/features/api/auth/application/forgot.handler.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/resend.command.ts,src/features/api/auth/application/resend.handler.ts,src/features/api/auth/application/reset.command.ts,src/features/api/auth/application/reset.handler.ts,src/features/api/auth/application/session.command.ts,src/features/api/auth/application/session.handler.ts,src/features/api/auth/application/signup.command.ts,src/features/api/auth/application/signup.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/forgot.request.ts,src/features/api/auth/transport/http/dto/google-start.request.ts,src/features/api/auth/transport/http/dto/login.request.ts,src/features/api/auth/transport/http/dto/resend.request.ts,src/features/api/auth/transport/http/dto/reset.request.ts,src/features/api/auth/transport/http/dto/signup.request.ts,src/features/api/auth/transport/http/dto/token.request.ts}"
|
|
2131
|
+
presence: optional
|
|
2132
|
+
tracked: tracked
|
|
2133
|
+
tier: inherit
|
|
2134
|
+
tests: none
|
|
2135
|
+
coverage: none
|
|
2136
|
+
managedBy: auth-lite
|
|
2137
|
+
managedOnly: true # lists files sync renders; the slot owning the path judges them
|
|
2138
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
2139
|
+
- id: be.integrations.mail
|
|
2140
|
+
profiles: [be]
|
|
2141
|
+
editions: [lite]
|
|
2142
|
+
exemplifiedBy:
|
|
2143
|
+
- packages/hfs/templates/be/skeleton-lite/src/modules/integrations/mail/
|
|
2144
|
+
# The glue of @starci/mail, the owner of the SMTP client (nodemailer): this folder parses the settings (the server, the sender and the
|
|
2145
|
+
# link lifetimes of the confirmation and reset mails), registers the module and names the injectors; no app file imports nodemailer,
|
|
2146
|
+
# and no other module imports the package. The words and layout of each mail belong to the domain that sends it.
|
|
2147
|
+
path: "src/modules/integrations/mail/"
|
|
2148
|
+
presence: required
|
|
2149
|
+
tracked: tracked
|
|
2150
|
+
tier: integrations
|
|
2151
|
+
owner: true
|
|
2152
|
+
requires: [index.ts, mail.config.ts, mail.options.ts, mail.decorators.ts, mail.module-definition.ts, mail.module.ts]
|
|
2153
|
+
allows: [index.ts, mail.config.ts, mail.options.ts, mail.decorators.ts, mail.module-definition.ts, mail.module.ts, errors/]
|
|
2154
|
+
tests: unit-beside
|
|
2155
|
+
rules: [BE_TIER_DIRECTION, BE_ERROR_HOME, BE_SECRET_DEFAULT, BE_INFRA_OWNER]
|
|
2156
|
+
coverage: required
|
|
2157
|
+
since: 5.3.0
|
|
2047
2158
|
- id: be.integrations.object-storage
|
|
2048
2159
|
profiles: [be]
|
|
2049
2160
|
exemplifiedBy:
|
|
2050
2161
|
- packages/hfs/templates/be/skeleton-lite/src/modules/integrations/object-storage/
|
|
2051
|
-
# The
|
|
2052
|
-
# lite): the
|
|
2162
|
+
# The glue of @starci/object-storage, the owner of the S3 client (@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner) over
|
|
2163
|
+
# S3-compatible storage (MinIO in lite): this folder keeps the bucket, parses the settings and registers the module; no app
|
|
2164
|
+
# file imports an S3 SDK or minio, and no other module imports the package.
|
|
2053
2165
|
path: "src/modules/integrations/object-storage/"
|
|
2054
2166
|
presence: optional
|
|
2055
2167
|
litePresence: required
|
|
2056
2168
|
tracked: tracked
|
|
2057
2169
|
tier: integrations
|
|
2058
2170
|
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.
|
|
2171
|
+
requires: [index.ts, object-storage.config.ts, object-storage.options.ts, object-storage.decorators.ts, object-storage.module-definition.ts, object-storage.module.ts]
|
|
2172
|
+
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
2173
|
tests: unit-beside
|
|
2062
2174
|
rules: [BE_TIER_DIRECTION, BE_ERROR_HOME, BE_SECRET_DEFAULT, BE_INFRA_OWNER, BE_STORAGE_OWNER]
|
|
2063
2175
|
coverage: required
|
|
2064
2176
|
since: 3.9.0
|
|
2177
|
+
- id: be.integrations.keycloak
|
|
2178
|
+
profiles: [be]
|
|
2179
|
+
editions: [full]
|
|
2180
|
+
# The glue of @starci/auth-oidc, the OIDC client of the full edition's identity provider (Keycloak): discovery, the provider's JWKS,
|
|
2181
|
+
# algorithm-pinned token checks and the authorization code flow with PKCE and nonce behind the PrincipalVerifier of @starci/auth.
|
|
2182
|
+
# This folder parses the typed options, hands the package the app's bounded HTTP client and clock, and names the injectors;
|
|
2183
|
+
# no app file imports jose, and no other module imports the package (ruleParams.be.infraOwners).
|
|
2184
|
+
path: "src/modules/integrations/keycloak/"
|
|
2185
|
+
presence: optional
|
|
2186
|
+
tracked: tracked
|
|
2187
|
+
tier: integrations
|
|
2188
|
+
owner: true
|
|
2189
|
+
requires: [index.ts, keycloak.config.ts, keycloak.options.ts, keycloak.decorators.ts, keycloak.registration.ts]
|
|
2190
|
+
allows: [index.ts, keycloak.config.ts, keycloak.options.ts, keycloak.decorators.ts, keycloak.registration.ts, errors/, messages/]
|
|
2191
|
+
tests: unit-beside
|
|
2192
|
+
rules: [BE_TIER_DIRECTION, BE_ERROR_HOME, BE_SECRET_DEFAULT, BE_INFRA_OWNER, BE_AUTH_PASSPORT_OWNER, BE_INTEGRATION_SPEC_MISSING]
|
|
2193
|
+
coverage: required
|
|
2194
|
+
since: 3.17.0
|
|
2065
2195
|
|
|
2066
2196
|
# ----- BE: tests (owner test layout 2026-09-30). Unit specs are <name>.service.spec.ts beside their service and nothing else; everything else
|
|
2067
2197
|
# lives under src/tests/, one folder per kind, and the folder and the file suffix always agree (a file whose suffix does
|
|
@@ -2535,9 +2665,9 @@ slots:
|
|
|
2535
2665
|
presence: required
|
|
2536
2666
|
tracked: tracked
|
|
2537
2667
|
tier: foundation
|
|
2538
|
-
# The app's
|
|
2539
|
-
#
|
|
2540
|
-
#
|
|
2668
|
+
# The app's description of its languages (defineI18n of @starci/next-i18n), its request config and catalogs, or its adapter to the
|
|
2669
|
+
# shared i18n workspace package. A single app builds its navigation (createI18nNavigation) in fe.modules.routes, keeping this
|
|
2670
|
+
# public entry safe for its proxy. A description shared by several apps belongs to fe.package.i18n.
|
|
2541
2671
|
requires: [index.ts]
|
|
2542
2672
|
tests: none
|
|
2543
2673
|
rules: [FE_I18N_PLACEMENT, FE_I18N_CATALOG]
|
|
@@ -2591,7 +2721,7 @@ slots:
|
|
|
2591
2721
|
profiles: [fe]
|
|
2592
2722
|
# The identity-provider client (fe-stack auth, FE-AUTH): the session, the access token the Apollo link attaches and the
|
|
2593
2723
|
# 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).
|
|
2724
|
+
# 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
2725
|
path: "apps/<app>/src/modules/auth/"
|
|
2596
2726
|
presence: optional
|
|
2597
2727
|
tracked: tracked
|
|
@@ -2601,6 +2731,20 @@ slots:
|
|
|
2601
2731
|
tests: none
|
|
2602
2732
|
since: 3.0.0
|
|
2603
2733
|
rules: [FE_STACK_FORBIDDEN]
|
|
2734
|
+
- id: fe.modules.auth.client
|
|
2735
|
+
since: 3.16.0
|
|
2736
|
+
profiles: [fe]
|
|
2737
|
+
editions: [lite]
|
|
2738
|
+
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."
|
|
2739
|
+
# The AuthClient every edition shares, implemented by one @starci/auth/client instance over the app's own back-end auth doors. email-doors.ts is the lite-only call of the five email doors (sign up, resend, confirm, forgot, reset), kept off the shared AuthClient interface because the full edition identity provider owns its own recovery flows; index.ts is the module entry that exports both.
|
|
2740
|
+
path: "apps/web/src/modules/auth/{client.ts,email-doors.ts,index.ts}"
|
|
2741
|
+
presence: optional
|
|
2742
|
+
tracked: tracked
|
|
2743
|
+
tier: inherit
|
|
2744
|
+
tests: none
|
|
2745
|
+
managedBy: auth-lite
|
|
2746
|
+
managedOnly: true # lists files sync renders; the slot owning the path judges them
|
|
2747
|
+
rules: [HFS_MANAGED_FILE_DRIFT]
|
|
2604
2748
|
- id: fe.modules.toast
|
|
2605
2749
|
profiles: [fe]
|
|
2606
2750
|
# Mutation feedback (fe-stack toast, FE-TOAST): the HeroUI toast wrapper, showGraphQLToast over a GraphQLResponse and the
|
|
@@ -2675,7 +2819,7 @@ slots:
|
|
|
2675
2819
|
owner: true
|
|
2676
2820
|
requires: [package.json, src/index.ts, tsconfig.json]
|
|
2677
2821
|
tests: none
|
|
2678
|
-
why: the
|
|
2822
|
+
why: the product's languages (defineI18n of @starci/next-i18n) written once and composed into the createAppI18n factory every app calls; the next-intl stack itself is the package's
|
|
2679
2823
|
rules: [FE_I18N_PLACEMENT, FE_PACKAGE_SHAPE, HFS_UNUSED_EXPORT]
|
|
2680
2824
|
|
|
2681
2825
|
# Checks that read this manifest (all ship from .claude; none keeps its own path list)
|
|
@@ -980,7 +980,7 @@ BE_MODULE_DEFINITION_MISSING:
|
|
|
980
980
|
- "Có <x>.module.ts nhưng thiếu <x>.module-definition.ts hoặc <x>.options.ts bên cạnh"
|
|
981
981
|
- "Lớp module không kế thừa ConfigurableModuleClass lấy từ ./<x>.module-definition"
|
|
982
982
|
- "Module sản phẩm nằm trong mảng imports (hoặc nhóm compose của app) như một tên lớp trần thay vì XModule.register({...})"
|
|
983
|
-
nextStep_vi: "Tạo <x>.module-definition.ts (
|
|
983
|
+
nextStep_vi: "Tạo <x>.module-definition.ts (export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE } = defineConfigurableModule<XOptions>() từ @starci/nest-kit; capability dùng defineCapabilityModule) và <x>.options.ts (export type XOptions = Record<string, never> nếu chưa có tùy chọn), cho lớp kế thừa ConfigurableModuleClass, và đăng ký bằng XModule.register({}); op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra."
|
|
984
984
|
owner: op-retry
|
|
985
985
|
kind: check-finding
|
|
986
986
|
|
|
@@ -1013,7 +1013,7 @@ BE_MODULE_SHAPE:
|
|
|
1013
1013
|
- "@Global() trên bất kỳ module nào (kể cả trong spec)"
|
|
1014
1014
|
- "isGlobal: true ở ngoài app.module.ts của app"
|
|
1015
1015
|
- "Module của một capability khác bị import vào imports thay vì dùng qua Inject<Thing>()"
|
|
1016
|
-
- "new ConfigurableModuleBuilder() không có kiểu options"
|
|
1016
|
+
- "defineConfigurableModule() hay new ConfigurableModuleBuilder() không có kiểu options"
|
|
1017
1017
|
- "register không static, hoặc có forRoot, forFeature, registerAsync"
|
|
1018
1018
|
- "new XService() hoặc let ở cấp module tạo trạng thái toàn cục"
|
|
1019
1019
|
- "Feature có hai module trong một thư mục transport (một module cho mỗi thao tác), module-definition không nằm cạnh module của nó, hoặc @Module ngoài `<f>.module.ts` và `<f>-<protocol>.module.ts`; app import module ứng dụng của feature hoặc module transport không thuộc loại app cho phép (api: graphql/http/websocket; worker: schedule/message; cli: cli)"
|
|
@@ -1797,11 +1797,12 @@ CLI_ONLY_ENTRY:
|
|
|
1797
1797
|
DB_APP_ROLE:
|
|
1798
1798
|
title: "The back-end database role has explicit least privileges"
|
|
1799
1799
|
title_vi: "Role cơ sở dữ liệu của back end có quyền quá rộng"
|
|
1800
|
-
meaning_vi: "Migration tại <path> tạo hoặc sửa role của ứng dụng với superuser, bypassrls hay thuộc tính thiếu an toàn, hoặc cấp all thay cho các quyền cần thiết; role mặc định là app_be và có thể khai báo bằng supabase.appRole."
|
|
1800
|
+
meaning_vi: "Migration tại <path> tạo hoặc sửa role của ứng dụng với superuser, bypassrls hay thuộc tính thiếu an toàn, hoặc cấp all thay cho các quyền cần thiết, hoặc cấp cho role quyền trên schema auth (schema, bảng hay sequence trong đó, hay default privileges của nó) mà không có migration sau đó thu hồi; role mặc định là app_be và có thể khai báo bằng supabase.appRole."
|
|
1801
1801
|
causes_vi:
|
|
1802
1802
|
- "Vi phạm R255: app role vượt qua RLS hoặc được cấp quyền rộng hơn công việc của back end."
|
|
1803
1803
|
- "Role không khai báo rõ noinherit và nobypassrls, hoặc nhận grant all trên schema hay bảng."
|
|
1804
|
-
|
|
1804
|
+
- "Role nhận grant trên schema auth: tài khoản chỉ được truy cập qua các hàm SECURITY DEFINER be_auth_* (account doors) của baseline."
|
|
1805
|
+
nextStep_vi: "Khai báo app role với noinherit, nobypassrls và các thuộc tính không đặc quyền; bỏ superuser, bypassrls và grant all, rồi cấp từng quyền cần thiết. Với grant trên schema auth: chạy `starci app codemod account-doors --execute`, `starci app sync --execute`, rồi `starci app codemod account-doors --contract --execute`."
|
|
1805
1806
|
owner: op-retry
|
|
1806
1807
|
kind: check-finding
|
|
1807
1808
|
|
|
@@ -5347,6 +5348,36 @@ SEALED_FILE_IN_WORK:
|
|
|
5347
5348
|
|
|
5348
5349
|
# --- HFS rule catalog (knowledge/hfs/rules.yaml): one code per rule, from R01 up ---
|
|
5349
5350
|
|
|
5351
|
+
STACKS_LOCAL_CONFIG_INVALID:
|
|
5352
|
+
title: "The local block of a docker-compose environment is not coherent"
|
|
5353
|
+
title_vi: "Khối local của môi trường docker-compose không nhất quán"
|
|
5354
|
+
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."
|
|
5355
|
+
causes_vi:
|
|
5356
|
+
- "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."
|
|
5357
|
+
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."
|
|
5358
|
+
owner: op-retry
|
|
5359
|
+
kind: check-finding
|
|
5360
|
+
|
|
5361
|
+
STACKS_DEV_UNDECLARED:
|
|
5362
|
+
title: "A lite app declares no runnable dev environment"
|
|
5363
|
+
title_vi: "Ứng dụng lite chưa khai báo môi trường dev chạy được"
|
|
5364
|
+
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."
|
|
5365
|
+
causes_vi:
|
|
5366
|
+
- "Vi phạm R372: môi trường dev vẫn là Swarm hoặc chưa được khai báo."
|
|
5367
|
+
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."
|
|
5368
|
+
owner: op-retry
|
|
5369
|
+
kind: check-finding
|
|
5370
|
+
|
|
5371
|
+
STACKS_RUNBOOK_DOCKER_COMMAND:
|
|
5372
|
+
title: "A dev runbook carries a docker command or omits the one-command start"
|
|
5373
|
+
title_vi: "Runbook dev chứa lệnh docker hoặc không nêu lệnh khởi động duy nhất"
|
|
5374
|
+
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>."
|
|
5375
|
+
causes_vi:
|
|
5376
|
+
- "Vi phạm R373 và quy tắc cứng 8: Docker do harness chạy, tác tử không chạy tay."
|
|
5377
|
+
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ó."
|
|
5378
|
+
owner: op-retry
|
|
5379
|
+
kind: check-finding
|
|
5380
|
+
|
|
5350
5381
|
STACKS_DEPLOY_CONFIG_INVALID:
|
|
5351
5382
|
title: "A deploy block of application-stacks.yaml is not coherent"
|
|
5352
5383
|
title_vi: "Khối deploy trong application-stacks.yaml không nhất quán"
|
|
@@ -5674,3 +5705,35 @@ BE_JOBS_SCHEDULER_OWNER:
|
|
|
5674
5705
|
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
5706
|
owner: op-retry
|
|
5676
5707
|
kind: check-finding
|
|
5708
|
+
|
|
5709
|
+
STACKS_CODE_BIND_MOUNT:
|
|
5710
|
+
title: "A stack or compose file bind-mounts code into a service container"
|
|
5711
|
+
title_vi: "Tệp stack hoặc compose gắn (bind-mount) mã vào container của dịch vụ"
|
|
5712
|
+
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."
|
|
5713
|
+
causes_vi:
|
|
5714
|
+
- "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."
|
|
5715
|
+
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."
|
|
5716
|
+
|
|
5717
|
+
STACKS_IMAGE_BASE_UNPINNED:
|
|
5718
|
+
title: "A service image folder has a FROM that is not digest-pinned"
|
|
5719
|
+
title_vi: "Thư mục image của dịch vụ có FROM chưa ghim digest"
|
|
5720
|
+
meaning_vi: "Dockerfile trong .starcistacks/images/<tên>/ dùng FROM theo tag, không theo name@sha256:..."
|
|
5721
|
+
causes_vi:
|
|
5722
|
+
- "Vi phạm R374: mọi image nền phải ghim digest."
|
|
5723
|
+
nextStep_vi: "Ghim FROM bằng name@sha256:<digest>."
|
|
5724
|
+
|
|
5725
|
+
STACKS_IMAGE_BASE_NOT_FORK:
|
|
5726
|
+
title: "A service image folder does not build on the harness fork image"
|
|
5727
|
+
title_vi: "Thư mục image của dịch vụ không dựng trên image fork của harness"
|
|
5728
|
+
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 đó."
|
|
5729
|
+
causes_vi:
|
|
5730
|
+
- "Vi phạm R374: dịch vụ tùy biến phải dựng trên image fork do harness ghim."
|
|
5731
|
+
nextStep_vi: "Đặt FROM <repository fork>@sha256:<digest> ở giai đoạn cuối."
|
|
5732
|
+
|
|
5733
|
+
STACKS_IMAGE_ENV_DIVERGES:
|
|
5734
|
+
title: "A service with an image folder runs a third-party image in an environment"
|
|
5735
|
+
title_vi: "Dịch vụ có thư mục image chạy image bên thứ ba ở một môi trường"
|
|
5736
|
+
meaning_vi: "Dev và production phải cùng chạy một image dựng từ .starcistacks/images/<tên>/."
|
|
5737
|
+
causes_vi:
|
|
5738
|
+
- "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."
|
|
5739
|
+
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
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { slash } from '../../lib/path-key.mjs';
|
|
2
2
|
import { isInside } from '../../lib/walk.mjs';
|
|
3
3
|
import { openHfs } from '../slots.mjs';
|
|
4
|
+
import type { RootPackage } from './root-packages.mjs';
|
|
4
5
|
/** The compiler API the checkers receive as their `ts` argument (the target repository's own installed TypeScript). */
|
|
5
6
|
export type TypeScriptApi = typeof import('typescript');
|
|
6
7
|
/** One owner derived from the slot manifest: an owner directory with its entry file. */
|
|
@@ -28,6 +29,8 @@ export interface ArchitectureConfig {
|
|
|
28
29
|
kinds: string[];
|
|
29
30
|
projects: string[];
|
|
30
31
|
workspaces: string[];
|
|
32
|
+
/** The app's own root workspace packages (empty at the app root itself, whose workspaces already hold them). */
|
|
33
|
+
rootPackages?: RootPackage[];
|
|
31
34
|
apps: {
|
|
32
35
|
name: string;
|
|
33
36
|
kind: string;
|
|
@@ -72,3 +75,4 @@ export declare function loadArchitectureConfig(repositoryRoot: string, { hfs }?:
|
|
|
72
75
|
hfs?: ArchitectureConfig['hfs'] | undefined;
|
|
73
76
|
}): ArchitectureConfig;
|
|
74
77
|
export { canonical, exactKeys, isInside, slash };
|
|
78
|
+
export type { RootPackage };
|
|
@@ -3,7 +3,8 @@ import path from 'node:path';
|
|
|
3
3
|
import { slash } from '../../lib/path-key.mjs';
|
|
4
4
|
import { readJsonFile as readJson } from '../../lib/json.mjs';
|
|
5
5
|
import { isInside } from '../../lib/walk.mjs';
|
|
6
|
-
import { openHfs } from '../slots.mjs';
|
|
6
|
+
import { createSlotResolver, openHfs, readRepoDeclaration } from '../slots.mjs';
|
|
7
|
+
import { ROOT_PACKAGE_SLOTS, rootPackageRecord, rootWorkspaceDirectories } from './root-packages.mjs';
|
|
7
8
|
import { byCodeUnit } from '../../lib/list.mjs';
|
|
8
9
|
import { grammarContractFor } from '../../lib/grammar-lint.mjs';
|
|
9
10
|
/** A file's identity: its resolved real path, or the resolved path when it does not exist. */
|
|
@@ -182,6 +183,28 @@ function workspaceDirectories(root, { packageRoot: appPackageRoot = root, side =
|
|
|
182
183
|
}
|
|
183
184
|
return [...directories].sort(byCodeUnit);
|
|
184
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* The workspace packages of the app root that no side owns: the `workspaces` patterns of the app's one package.json that do not start
|
|
188
|
+
* with a side folder (`packages/*`), and the directories the slots `app.packages` and `app.module-registry` place under `packages/`
|
|
189
|
+
* even when the manifest forgot to list them. A side imports them as first-party packages (through their entry points), never as
|
|
190
|
+
* "outside the side". A side of the app is judged here; the app root itself already counts them among its workspaces.
|
|
191
|
+
*/
|
|
192
|
+
function rootPackageRecords(root, packageRoot, side, opened) {
|
|
193
|
+
if (side === null)
|
|
194
|
+
return [];
|
|
195
|
+
const candidates = new Set(rootWorkspaceDirectories(packageRoot));
|
|
196
|
+
if (opened.manifest && existingDirectory(packageRoot, 'packages')) {
|
|
197
|
+
const resolver = createSlotResolver(opened.manifest, readRepoDeclaration(opened.manifest, packageRoot));
|
|
198
|
+
const container = path.join(packageRoot, 'packages');
|
|
199
|
+
for (const entry of fs.readdirSync(container, { withFileTypes: true }).filter(item => item.isDirectory())) {
|
|
200
|
+
const slot = resolver.classifyPath(`packages/${entry.name}`).slot;
|
|
201
|
+
if (slot !== undefined && ROOT_PACKAGE_SLOTS.has(slot))
|
|
202
|
+
candidates.add(path.join(container, entry.name));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return [...candidates].sort(byCodeUnit).filter(candidate => !isInside(root, candidate))
|
|
206
|
+
.flatMap(candidate => rootPackageRecord(packageRoot, candidate, canonical) ?? []);
|
|
207
|
+
}
|
|
185
208
|
function discoveredProjects(root, workspaces) {
|
|
186
209
|
const projects = [];
|
|
187
210
|
if (fs.existsSync(path.join(root, 'tsconfig.json')))
|
|
@@ -373,6 +396,7 @@ export function loadArchitectureConfig(repositoryRoot, { hfs } = {}) {
|
|
|
373
396
|
kinds,
|
|
374
397
|
projects,
|
|
375
398
|
workspaces,
|
|
399
|
+
rootPackages: rootPackageRecords(root, packageRoot, side, opened),
|
|
376
400
|
apps: apps.map(app => ({ name: app.name, kind: app.kind })),
|
|
377
401
|
hfs: opened,
|
|
378
402
|
owners: derivedOwners(root, opened),
|