cabloy 5.1.203 → 5.1.205

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.
Files changed (127) hide show
  1. package/.cabloy-version +1 -1
  2. package/.gitignore +2 -0
  3. package/CHANGELOG.md +21 -0
  4. package/lint-staged.config.mjs +2 -0
  5. package/oxfmt.config.ts +2 -0
  6. package/oxlint.config.ts +2 -0
  7. package/package.json +6 -5
  8. package/repo-agent-governance/managed-assets.json +9 -9
  9. package/repo-agent-governance/policies/repository.md +5 -2
  10. package/repo-agent-governance/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +2 -2
  11. package/repo-agent-governance/skills/cabloy-workflow/SKILL.md +2 -0
  12. package/repo-docs/backend/migration-and-changes.md +13 -12
  13. package/repo-docs/backend/orm-select-guide.md +6 -0
  14. package/repo-docs/backend/runtime-and-flavors.md +2 -1
  15. package/repo-docs/backend/transaction-guide.md +12 -0
  16. package/repo-docs/backend/unit-testing.md +12 -8
  17. package/repo-docs/blogs/ai-coding-one-prompt-crud-ssr-multitasking/cover-en-v1.png +0 -0
  18. package/repo-docs/blogs/ai-coding-one-prompt-crud-ssr-multitasking/images/completion-summary.jpg +0 -0
  19. package/repo-docs/blogs/ai-coding-one-prompt-crud-ssr-multitasking/images/multitasking-draft.jpg +0 -0
  20. package/repo-docs/blogs/ai-coding-one-prompt-crud-ssr-multitasking/images/ssr-refresh.jpg +0 -0
  21. package/repo-docs/blogs/ai-coding-one-prompt-crud-ssr-multitasking/index.md +216 -0
  22. package/repo-docs/blogs/index.md +15 -0
  23. package/repo-docs/frontend/scripts.md +1 -1
  24. package/repo-docs/fullstack/parallel-worktree-environment.md +6 -6
  25. package/repo-docs/fullstack/ssr-entry-modes.md +19 -0
  26. package/repo-docs/index.md +2 -0
  27. package/repo-docs/reference/repo-scripts.md +22 -1
  28. package/repo-e2e/config/playwright.config.ts +32 -14
  29. package/repo-e2e/docs/specs/blogs-index.spec.ts +23 -6
  30. package/repo-e2e/scripts/e2e.test.ts +39 -0
  31. package/repo-e2e/scripts/e2e.ts +19 -1
  32. package/repo-e2e/scripts/managedTest.test.ts +389 -0
  33. package/repo-e2e/scripts/managedTest.ts +210 -0
  34. package/repo-e2e/scripts/managedTestImports.test.ts +74 -0
  35. package/repo-e2e/scripts/managedTestImports.ts +110 -0
  36. package/repo-e2e/scripts/runE2e.ts +12 -1
  37. package/repo-e2e/scripts/startE2eVona.ts +37 -5
  38. package/repo-e2e/specs/a-commerce.spec.ts +1 -1
  39. package/repo-e2e/specs/cabloy-basic.spec.ts +1 -1
  40. package/repo-e2e/specs/controller-boundary.spec.ts +1 -1
  41. package/repo-e2e/specs/home-user-account.spec.ts +2 -1
  42. package/repo-e2e/specs/markdown.spec.ts +1 -1
  43. package/repo-e2e/specs/routed-dialog.spec.ts +1 -1
  44. package/scripts/runIsolatedTest.test.ts +426 -0
  45. package/scripts/runIsolatedTest.ts +454 -0
  46. package/scripts/testClaimCleanup.test.ts +346 -0
  47. package/scripts/testClaimCleanup.ts +375 -0
  48. package/scripts/testClaimProcesses.test.ts +106 -0
  49. package/scripts/testClaimProcesses.ts +129 -0
  50. package/scripts/testProcessGuardian.ts +163 -0
  51. package/scripts/upgrade.ts +1 -16
  52. package/vona/oxfmt.config.ts +2 -0
  53. package/vona/oxlint.config.ts +2 -0
  54. package/vona/package.original.json +2 -2
  55. package/vona/packages-cli/cli/package.json +1 -1
  56. package/vona/packages-cli/cli/src/play.test.ts +37 -0
  57. package/vona/packages-cli/cli/src/play.ts +23 -1
  58. package/vona/packages-cli/cli-set-api/package.json +1 -1
  59. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dbReset.ts +16 -7
  60. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +13 -7
  61. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.play.ts +5 -1
  62. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.test.ts +12 -7
  63. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/configUtils.ts +21 -2
  64. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateVonaMeta.ts +10 -0
  65. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/resolveTestCleanupConfig.test.ts +153 -0
  66. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/resolveTestCleanupConfig.ts +141 -0
  67. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupAdapters.test.ts +148 -0
  68. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupAdapters.ts +127 -0
  69. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupProcess.test.ts +47 -0
  70. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupProcess.ts +139 -0
  71. package/vona/packages-cli/cli-set-api/src/lib/utils.ts +2 -3
  72. package/vona/packages-cli/cli-set-api/templates/config/_tsconfig_project.json +1 -0
  73. package/vona/packages-cli/cli-set-api/templates/config/_tsconfig_source.json +1 -0
  74. package/vona/packages-cli/cli-set-api/test/binDevMode.test.ts +18 -0
  75. package/vona/packages-cli/cli-set-api/toolsIsolate/dbReset.ts +15 -2
  76. package/vona/packages-cli/cli-set-api/tsconfig.build.json +2 -1
  77. package/vona/packages-utils/babel-plugin-vona-bean-module/package.json +1 -1
  78. package/vona/packages-utils/babel-plugin-vona-bean-module/src/index.test.ts +16 -0
  79. package/vona/packages-utils/babel-plugin-vona-bean-module/src/index.ts +3 -2
  80. package/vona/packages-vona/vona/package.json +1 -1
  81. package/vona/packages-vona/vona-core/package.json +1 -1
  82. package/vona/packages-vona/vona-core/src/lib/addon/sqlite3.ts +1 -1
  83. package/vona/packages-vona/vona-core/src/lib/core/config.ts +44 -6
  84. package/vona/packages-vona/vona-core/src/lib/core/configCleanup.test.ts +40 -0
  85. package/vona/packages-vona/vona-core/src/lib/core/index.ts +3 -0
  86. package/vona/packages-vona/vona-core/src/lib/core/isolationGuard.test.ts +301 -0
  87. package/vona/packages-vona/vona-core/src/lib/core/isolationGuard.ts +312 -0
  88. package/vona/packages-vona/vona-core/src/lib/core/testClaim.test.ts +577 -0
  89. package/vona/packages-vona/vona-core/src/lib/core/testClaim.ts +985 -0
  90. package/vona/packages-vona/vona-core/src/lib/core/testIsolation.ts +129 -0
  91. package/vona/packages-vona/vona-core/src/lib/framework/createApp.ts +2 -0
  92. package/vona/packages-vona/vona-core/src/lib/framework/start.ts +4 -0
  93. package/vona/packages-vona/vona-core/src/lib/framework/useApp.ts +5 -1
  94. package/vona/packages-vona/vona-core/src/types/application/app.ts +2 -0
  95. package/vona/packages-vona/vona-core/src/types/utils/env.ts +1 -0
  96. package/vona/packages-vona/vona-mock/package.json +1 -1
  97. package/vona/pnpm-lock.yaml +40 -40
  98. package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentIndexes.test.ts +73 -10
  99. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/package.json +1 -1
  100. package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
  101. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  102. package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
  103. package/vona/src/suite-vendor/a-vona/modules/a-logger/src/bean/middlewareSystem.httpLog.ts +15 -1
  104. package/vona/src/suite-vendor/a-vona/modules/a-logger/src/lib/redactIsolatedReadyHeader.test.ts +24 -0
  105. package/vona/src/suite-vendor/a-vona/modules/a-logger/src/lib/redactIsolatedReadyHeader.ts +11 -0
  106. package/vona/src/suite-vendor/a-vona/modules/a-metrics/package.json +1 -1
  107. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/bean/middlewareSystem.health.ts +15 -0
  108. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  109. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/extend/schemaBuilder.ts +11 -4
  110. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/databaseClient_.ts +6 -1
  111. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
  112. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.betterSqlite3.ts +41 -1
  113. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.mysql.ts +4 -1
  114. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.pg.ts +2 -1
  115. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  116. package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
  117. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/lib/redis.ts +8 -0
  118. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redis.ts +23 -6
  119. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redisClient_.ts +18 -1
  120. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  121. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +43 -15
  122. package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
  123. package/vona/src/suite-vendor/a-vona/modules/a-version/src/lib/databaseTestName.ts +3 -37
  124. package/vona/src/suite-vendor/a-vona/modules/a-version/src/service/database.ts +93 -15
  125. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  126. package/vona/tsconfig.json +1 -0
  127. package/scripts/initTestData.ts +0 -25
package/.cabloy-version CHANGED
@@ -1 +1 @@
1
- 5.1.203
1
+ 5.1.205
package/.gitignore CHANGED
@@ -37,6 +37,8 @@ blob-report/
37
37
  # vona core related directories
38
38
  vona/.vona
39
39
  vona/.app
40
+ vona/.vona-test-*
41
+ vona/.app-test-*
40
42
  vona/.zova-rest
41
43
 
42
44
  **/.temp-dynamic-*
package/CHANGELOG.md CHANGED
@@ -1,11 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.1.205
4
+
5
+ ### Features
6
+
7
+ - Update functionality.
8
+
9
+ ### Bug Fixes
10
+
11
+ - Respect CLI publish boundaries.
12
+ - Preserve test claim identities.
13
+
14
+ ## 5.1.204
15
+
16
+ ### Improvements
17
+
18
+ - Document model relations and transaction rules.
19
+ - Add a blog post on using AI coding for CRUD, SSR, and multitasking.
20
+ - Update the pnpm lockfile.
21
+
3
22
  ## 5.1.203
4
23
 
5
24
  ### Features
25
+
6
26
  - Update application features.
7
27
 
8
28
  ### Improvements
29
+
9
30
  - Refactor end-to-end tests.
10
31
  - Clarify managed E2E resource authorization documentation.
11
32
  - Add a video demonstrating second-level tabs for admin multitasking.
@@ -22,6 +22,8 @@ const OXFMT_IGNORE_PATTERNS = [
22
22
  '**/quasar.config.ts.temporary.*',
23
23
  // common directory patterns
24
24
  '**/.vona',
25
+ '**/.vona-test-*',
26
+ '**/.app-test-*',
25
27
  '**/.assets',
26
28
  '**/.app',
27
29
  '**/.zova-rest',
package/oxfmt.config.ts CHANGED
@@ -24,6 +24,8 @@ export default defineConfig(
24
24
  '**/quasar.config.ts.temporary.*',
25
25
  // common directory patterns (from vona & zova, converted to **/)
26
26
  '**/.vona',
27
+ '**/.vona-test-*',
28
+ '**/.app-test-*',
27
29
  '**/.assets',
28
30
  '**/.app',
29
31
  '**/.zova-rest',
package/oxlint.config.ts CHANGED
@@ -49,6 +49,8 @@ export default defineConfig(
49
49
  '**/postcss.config.cjs',
50
50
  // common directory patterns (from vona & zova, converted to **/)
51
51
  '**/.vona',
52
+ '**/.vona-test-*',
53
+ '**/.app-test-*',
52
54
  '**/.assets',
53
55
  '**/.zova',
54
56
  '**/docker-compose',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cabloy",
3
- "version": "5.1.203",
3
+ "version": "5.1.205",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A Node.js fullstack framework",
6
6
  "keywords": [
@@ -22,7 +22,6 @@
22
22
  "type": "module",
23
23
  "scripts": {
24
24
  "init": "node scripts/init.ts",
25
- "init:test-data": "node scripts/initTestData.ts",
26
25
  "upgrade": "node scripts/upgrade.ts",
27
26
  "upgrade:dry-run": "node scripts/upgrade.ts --dry-run",
28
27
  "vona": "node ./vona/packages-cli/cli/src/bin/vona.ts --projectPath=vona",
@@ -33,8 +32,10 @@
33
32
  "dev:zova:web": "cd zova && npm run dev:ssr:cabloyBasicWeb",
34
33
  "dev:zova:commerce:web": "cd zova && npm run dev:ssr:cabloyCommerce",
35
34
  "dev:zova:commerce:admin": "cd zova && npm run dev:ssr:cabloyCommerceAdmin",
36
- "build": "npm run build:zova && pnpm --dir vona run build",
37
- "build:docker": "npm run build:zova && pnpm --dir vona run build:docker",
35
+ "build": "npm run build:zova:all && npm run build:vona",
36
+ "build:docker": "npm run build:zova:all && npm run build:vona:docker",
37
+ "build:vona": "pnpm --dir vona run build",
38
+ "build:vona:docker": "pnpm --dir vona run build:docker",
38
39
  "build:zova:all": "npm run build:zova && npm run build:zova:commerce",
39
40
  "build:zova": "pnpm --dir zova run build:ssr:cabloyBasicBatch",
40
41
  "build:zova:admin": "pnpm --dir zova run build:ssr:cabloyBasicAdmin && pnpm --dir zova run build:rest:cabloyBasicAdmin",
@@ -45,7 +46,7 @@
45
46
  "start": "cd vona && npm run start",
46
47
  "start:one": "cd vona && npm run start:one",
47
48
  "test": "cd vona && npm run test",
48
- "test:e2e": "node repo-e2e/scripts/runE2e.ts",
49
+ "test:e2e": "node scripts/runIsolatedTest.ts e2e",
49
50
  "test:docs:e2e": "npm run docs:build && playwright test --config repo-e2e/docs/playwright.config.ts",
50
51
  "db:reset": "cd vona && npm run db:reset",
51
52
  "tsc": "npm run tsc:zova && pnpm --dir vona run tsc",
@@ -18,7 +18,7 @@
18
18
  {
19
19
  "adapter": "codex",
20
20
  "category": "skill",
21
- "sha256": "88e6ca8c60d8caeb68ab932f2a7e22810a31911400b4428fd0756d076dbc78e8",
21
+ "sha256": "73e068093dfc88d57dc484582e0c20b1dd5d48bdbe12e860ac6343a64883cf5e",
22
22
  "source": "skills/cabloy-backend-scaffold/references/follow-up-checklist.md",
23
23
  "target": ".agents/skills/cabloy-backend-scaffold/references/follow-up-checklist.md"
24
24
  },
@@ -277,7 +277,7 @@
277
277
  {
278
278
  "adapter": "codex",
279
279
  "category": "skill",
280
- "sha256": "ff0760f6fa7c24f561fdcfa07094d9d6e8d82fcef358458a36ff0c38a30ea89e",
280
+ "sha256": "eccad69c3969f97e80a3766fc2149b9f3e0bf2acd0c8586ed7bed0418f6878a9",
281
281
  "source": "skills/cabloy-workflow/SKILL.md",
282
282
  "target": ".agents/skills/cabloy-workflow/SKILL.md"
283
283
  },
@@ -354,7 +354,7 @@
354
354
  {
355
355
  "adapter": "claude",
356
356
  "category": "skill",
357
- "sha256": "88e6ca8c60d8caeb68ab932f2a7e22810a31911400b4428fd0756d076dbc78e8",
357
+ "sha256": "73e068093dfc88d57dc484582e0c20b1dd5d48bdbe12e860ac6343a64883cf5e",
358
358
  "source": "skills/cabloy-backend-scaffold/references/follow-up-checklist.md",
359
359
  "target": ".claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md"
360
360
  },
@@ -613,7 +613,7 @@
613
613
  {
614
614
  "adapter": "claude",
615
615
  "category": "skill",
616
- "sha256": "ff0760f6fa7c24f561fdcfa07094d9d6e8d82fcef358458a36ff0c38a30ea89e",
616
+ "sha256": "eccad69c3969f97e80a3766fc2149b9f3e0bf2acd0c8586ed7bed0418f6878a9",
617
617
  "source": "skills/cabloy-workflow/SKILL.md",
618
618
  "target": ".claude/skills/cabloy-workflow/SKILL.md"
619
619
  },
@@ -683,7 +683,7 @@
683
683
  {
684
684
  "adapter": "cursor",
685
685
  "category": "policy",
686
- "sha256": "db2467e225f30b74efb312c45572324f75a6a81077e19b7723ffd640a45793f9",
686
+ "sha256": "539fa24fc49fa8402ea0d9ab89c058762c441d5b3ed87af34a16235d1f8251a0",
687
687
  "source": "policies/repository.md",
688
688
  "target": ".cursor/rules/cabloy-governance.mdc"
689
689
  },
@@ -704,7 +704,7 @@
704
704
  {
705
705
  "adapter": "cursor",
706
706
  "category": "skill",
707
- "sha256": "88e6ca8c60d8caeb68ab932f2a7e22810a31911400b4428fd0756d076dbc78e8",
707
+ "sha256": "73e068093dfc88d57dc484582e0c20b1dd5d48bdbe12e860ac6343a64883cf5e",
708
708
  "source": "skills/cabloy-backend-scaffold/references/follow-up-checklist.md",
709
709
  "target": ".cursor/skills/cabloy-backend-scaffold/references/follow-up-checklist.md"
710
710
  },
@@ -963,7 +963,7 @@
963
963
  {
964
964
  "adapter": "cursor",
965
965
  "category": "skill",
966
- "sha256": "ff0760f6fa7c24f561fdcfa07094d9d6e8d82fcef358458a36ff0c38a30ea89e",
966
+ "sha256": "eccad69c3969f97e80a3766fc2149b9f3e0bf2acd0c8586ed7bed0418f6878a9",
967
967
  "source": "skills/cabloy-workflow/SKILL.md",
968
968
  "target": ".cursor/skills/cabloy-workflow/SKILL.md"
969
969
  },
@@ -1005,14 +1005,14 @@
1005
1005
  {
1006
1006
  "adapter": "codex",
1007
1007
  "category": "policy",
1008
- "sha256": "307edb0409d7d723c213c534713d2477ba000f19571e054d5498aeb9578b22bb",
1008
+ "sha256": "f8172d4e80dc8b84bf99a0e926184eb78af5bd1fdfcdeebe63b02160f459afce",
1009
1009
  "source": "policies/repository.md",
1010
1010
  "target": "AGENTS.md"
1011
1011
  },
1012
1012
  {
1013
1013
  "adapter": "claude",
1014
1014
  "category": "policy",
1015
- "sha256": "307edb0409d7d723c213c534713d2477ba000f19571e054d5498aeb9578b22bb",
1015
+ "sha256": "f8172d4e80dc8b84bf99a0e926184eb78af5bd1fdfcdeebe63b02160f459afce",
1016
1016
  "source": "policies/repository.md",
1017
1017
  "target": "CLAUDE.md"
1018
1018
  }
@@ -71,7 +71,8 @@ Before inventing a custom implementation path:
71
71
  - Treat hooks, permissions, local settings, credentials, MCP registration, command discovery, and automatic command execution as platform-specific integrations, not portable rule or skill capabilities.
72
72
  - After implementation, do not launch broad reviews automatically; when review is needed, scope it to the current diff and report only high-confidence issues.
73
73
  - Do not modify shared environment identity or ports merely to bypass a busy resource. For intentional parallel worktree setup, follow `repo-docs/fullstack/parallel-worktree-environment.md`; otherwise wait for the shared resource or ask the user. Create or change worktree-local environment overrides only through the explicitly invoked `cabloy-worktree-environment` skill and its confirmation phase, and only in `vona/env/.env.local` and `zova/env/.env.local`; never modify flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files. The skill derives the standard `APP_NAME`, `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, `DEV_SERVER_HMR_PORT`, and API-derived `API_BASE_URL` tuple only from Git worktree metadata and fixed port baselines; never read or expose `.env*` content while recommending values. Admin and Web are alternative commands using this shared tuple and must not run concurrently in one worktree; use another linked worktree for concurrent use. Detect the active edition before choosing scripts, and never run `npm run init` as an automatic follow-up.
74
- - Before `npm run test:e2e`, verify exclusive use of the effective test-database cleanup scope, Redis cleanup namespace, public/runtime paths, and listener; a free port or separate worktree alone is insufficient. If a standing authorization covers this checkout and its resources remain exclusively assigned with no conflicting process, do not repeatedly ask to run the managed suite; if scope or ownership changes or is uncertain, wait or ask. This does not authorize manual resets, broader cleanup, or changing shared configuration. See `repo-docs/reference/repo-scripts.md`.
74
+ - In Cabloy Basic, root `npm run test` and `npm run test:e2e` always allocate an isolated same-checkout test run: disposable run-specific database and Redis namespaces, runtime/public paths, and listener. This protects ordinary development business data, including when a dev server is active in the same checkout. Shared preparation writes (such as builds or dependency generation) are separate accepted prerequisites, not test cleanup of dev business data; do not treat the test isolation as permission to run manual resets or change shared configuration. Check the active edition's scripts before extending this guarantee to Cabloy Start. See `repo-docs/reference/repo-scripts.md`.
75
+ - For isolated E2E through Vona integrated SSR, do not edit Zova `API_BASE_URL` environment values or rebuild solely to match the test port: Vona supplies runtime server/browser API origins. On an origin mismatch, check explicit SSR Site and module-specific API URL overrides first; follow the active repository's scripts for changed SSR/REST artifacts and dependency synchronization. Do not generalize this handoff to Zova standalone SSR or SPA. See [Runtime API origins](repo-docs/fullstack/ssr-entry-modes.md#runtime-api-origins-in-vona-integrated-ssr).
75
76
  - For SSR theme-sensitive frontend work, detect the active edition marker and UI library before making assumptions. Cabloy Basic currently means DaisyUI + Tailwind CSS assumptions; Cabloy Start currently means Vuetify assumptions.
76
77
  - In Web SSR without cookie-backed theme resolution, do not treat server reads of `$theme.dark`, `$theme.darkMode`, or `$token` as final browser truth. Keep theme-sensitive SSR branching hydration-tolerant or defer final theme-sensitive decisions to the client.
77
78
  - Do not assume Cabloy Basic and Cabloy Start use the same adapter-level SSR theme handoff. Verify the active theme handler and client hydration path before changing SSR theme behavior.
@@ -85,15 +86,17 @@ Before inventing a custom implementation path:
85
86
  - When adding a persisted field to an existing backend resource, ask the user whether `vonaModule.fileVersion` should be incremented before changing `meta.version.ts` or the module schema path. If yes, add a new migration version and bump `fileVersion`. If no, keep the current `fileVersion` and fold the schema change into the current version path. Do not assume the versioning strategy without confirmation.
86
87
  - In shared-database multitenancy, do not use `table.unique(...)` for business uniqueness. Keep ordinary indexes for lookup performance and enforce tenant-scoped uniqueness in the business layer.
87
88
  - In Vona, a tenant corresponds to an instance. Ordinary resource-model CRUD is automatically scoped to the active instance; treat records absent from that scope as absent, and do not use raw cross-instance probes merely to choose between `403` and not-found behavior. Model future multi-merchant boundaries explicitly inside an instance.
89
+ - For stable, reusable Vona relationships, prefer Model relations; load declared relations with targeted ORM `include` in CRUD reads, not by default on every query. Prefer `$Dto.*` inference from Entity/Model and relation truth with deliberate read/write projections; `include` is relation loading, not a SQL join or an authorization/response-filtering boundary. Use dynamic `with`, explicit joins, or explicit DTOs when the contract requires them. See [Relations Guide](repo-docs/backend/relations-guide.md), [ORM Select Guide](repo-docs/backend/orm-select-guide.md), and [DTO Infer and Generation](repo-docs/backend/dto-infer-generation.md).
88
90
  - Model cross-Model query-cache dependencies as one directed, acyclic `modelsClear` / `modelsClearedBy` graph, and verify source mutations refresh warmed dependent queries; follow [Cross-model query-cache dependencies](repo-docs/backend/cache-guide.md#cross-model-query-cache-dependencies) before designing a nontrivial graph.
89
91
  - For `@Api.field(...)` and related schemaLike composition, framework guards now preserve previously attached OpenAPI metadata across schema rebuilds, but structure-shaping schemaLike is still order-sensitive. Treat `v.object(...)`, `v.array(...)`, `v.optional()`, `v.nullable()`, `v.default(...)`, and preprocess/transform wrappers as structure-shaping; keep the final structure-defining schemaLike last and verify emitted schema/OpenAPI output after such edits.
92
+ - Keep ordinary, independent CRUD writes simple: do not add an explicit transaction or pessimistic update lock by default. Add a transaction when a business operation requires multiple writes to commit or roll back together; add concurrency control only for a defined invariant or contention requirement, using no more locking than that guarantee needs. A transaction alone does not prevent write races, and an update method name alone does not justify a lock. See [Transaction Guide](repo-docs/backend/transaction-guide.md).
90
93
  - `@Core.transaction(...)` defaults to `REQUIRED`: it starts a transaction only when none exists and otherwise joins the current datasource transaction without upgrading its isolation. Prefer it over manual `inTransaction` wrappers for atomic service methods; use `REQUIRES_NEW` only when an independently committed boundary is explicitly required.
91
94
  - For replay-safe transient failures, use `@Core.retryable(...)` with an explicit `errorCodes` allowlist. It retries the downstream AOP suffix, so place it closest to the method when it must wrap and retry a `@Core.transaction(...)` boundary; use `ownerOnly: true` for dual-role leaves that must not retry inside a caller-owned transaction; do not retry external side effects or infer retryability from isolation level.
92
95
  - Backend tests that use scoped Vona state must own an `app.bean.executor.mockCtx(...)` boundary; every intentionally competing operation must run in a separate `mockCtx(...)`.
93
96
  - Do not set `TEST_CONCURRENCY=false` for normal `npm run test` or CI runs: an unset value defaults to concurrent execution. For stateful `node:test` suites, declare `{ concurrency: false }` explicitly. Prove business contention by explicitly launching competing operations and asserting their combined durable outcome, never through runner parallelism or scheduling.
94
97
  - Unit tests must not temporarily mutate process-global origin or proxy configuration, including `app.config.server.serve.protocol`, `app.config.server.serve.host`, and `app.proxy`. Model request-origin cases with an explicit `req` fixture, and use the established `AppUtil` loopback fallback for requestless local URLs. Do not introduce a broad origin lock to serialize such tests; retain narrowly scoped locks only for genuinely shared domain state.
95
98
  - Unit tests must delete every test-owned persisted resource in `finally`, using precise owned identities and reverse dependency order.
96
- - Shared durable test or local-development fixtures must be created through the owning module's `meta.version.ts` `seed()` hook and treated as read-only by tests; the managed seed path starts from a newly recreated database rather than repeating against one database.
99
+ - Shared durable test or local-development fixtures must be created through the owning module's `meta.version.ts` `seed()` hook and treated as read-only by tests; seeds run on isolated test-mode startup or after an explicit dev-mode `npm run db:reset` against a newly recreated disposable database, not on ordinary dev startup or repeatedly against one database.
97
100
 
98
101
  ## Verification expectations
99
102
 
@@ -44,7 +44,7 @@ When the active edition and installed modules provide `@Passport.rbac(...)` and
44
44
  - `meta.version`
45
45
  - field indexes; in shared-database multitenancy, preserve ordinary lookup indexes and enforce business uniqueness in tenant-aware business logic rather than with `table.unique(...)`
46
46
  - when editing or generating `meta.index`, consolidate each table's specifications into one declaration instead of adding another same-table `$tableColumns` spread; check for leading-column name collisions, effective metadata, and physical index definitions using the [Field Indexes guide](../../../../repo-docs/backend/field-indexes.md)
47
- - relations
47
+ - relations: define stable, reusable business relationships on the Model (`hasOne`, `belongsTo`, `hasMany`, `belongsToMany`); for CRUD reads, load only the relations the endpoint needs via `include`, and align the `$Dto.*` relation projection with the ORM query. Use dynamic `with` for situational relations; when related rows determine which parents appear, filter the parent query rather than relying on `include`. See [Relations Guide](../../../../repo-docs/backend/relations-guide.md) and [ORM Select Guide](../../../../repo-docs/backend/orm-select-guide.md).
48
48
  - datasource choice
49
49
  - cache behavior
50
50
  - cross-Model query-cache dependencies: when a source mutation can change another Model's cached query members, totals, projections, includes, or visibility, declare exactly one directed `modelsClear` / `modelsClearedBy` edge
@@ -52,7 +52,7 @@ When the active edition and installed modules provide `@Passport.rbac(...)` and
52
52
  - when `modelsClearedByFn` is required, treat it as replacement behavior and explicitly own the target clear and any necessary downstream propagation
53
53
  - prefer normal Model/service mutation paths so source invalidation, commit-time re-clear, and configured double-delete remain active
54
54
  - add a warm-query → mutate-source → repeat-query regression test for each new dependency path; follow [Cross-model query-cache dependencies](../../../../repo-docs/backend/cache-guide.md#cross-model-query-cache-dependencies) for the portable decision rules
55
- - transaction behavior
55
+ - transaction and concurrency requirements: leave independent CRUD writes without an explicit transaction or pessimistic lock by default; identify any multi-write atomicity or contention-sensitive invariant before choosing a transaction and the minimum necessary concurrency control. See [Transaction Guide](../../../../repo-docs/backend/transaction-guide.md).
56
56
 
57
57
  ## Test resource lifecycle follow-up
58
58
 
@@ -113,6 +113,8 @@ This routing skill provides read-only guidance only. Do not infer an `APP_NAME`
113
113
 
114
114
  The invoked skill detects Basic or Start to select the active root scripts and managed E2E command. It uses Git worktree metadata, fixed Vona/Zova port baselines, and the worktree basename to recommend the complete standard tuple for confirmation: `APP_NAME`, `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, `DEV_SERVER_HMR_PORT`, and an `API_BASE_URL` derived from the Vona port. After confirmation, it writes both `vona/env/.env.local` and `zova/env/.env.local`; never use flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files. It does not inspect environment-file content or allocate/reserve a live port. The shared environment is Vona + Zova development: Admin and Web are alternative commands using the same configuration, and they must not run concurrently in one worktree. Concurrent use requires separately configured linked worktrees.
115
115
 
116
+ For isolated E2E through Vona integrated SSR, use the [runtime API-origin guidance](../../../repo-docs/fullstack/ssr-entry-modes.md#runtime-api-origins-in-vona-integrated-ssr): a dynamic test port alone requires neither a Zova `.env` edit nor a frontend rebuild. This is separate from explicitly requested worktree development configuration; check the active scripts for artifact preparation and explicit API URL overrides.
117
+
116
118
  ## Step 4: Prefer CLI-first workflows
117
119
 
118
120
  Whenever the task maps to an existing generator, initializer, refactor, or metadata command, prefer the CLI.
@@ -94,11 +94,11 @@ export class MetaVersion extends BeanBase {}
94
94
 
95
95
  Three migration scenarios are defined:
96
96
 
97
- | Scenario | Purpose |
98
- | -------- | ------------------------------------------------ |
99
- | `update` | schema evolution such as tables and fields |
100
- | `init` | instance- or tenant-specific initialization data |
101
- | `seed` | shared baseline data for the test environment |
97
+ | Scenario | Purpose |
98
+ | -------- | --------------------------------------------------- |
99
+ | `update` | schema evolution such as tables and fields |
100
+ | `init` | instance- or tenant-specific initialization data |
101
+ | `seed` | baseline data for test runs and explicit dev resets |
102
102
 
103
103
  This split is one of the most important Vona migration ideas because it separates:
104
104
 
@@ -110,7 +110,7 @@ A practical generated-thread interpretation is:
110
110
 
111
111
  - `update` follows schema and entity/model evolution
112
112
  - `init` follows instance-aware initialization needs introduced by the backend feature
113
- - `seed` provides shared baseline data while the application starts in test mode
113
+ - `seed` provides shared baseline data during test-mode startup or an explicit development database reset
114
114
 
115
115
  ## Update: schema migration
116
116
 
@@ -153,7 +153,7 @@ export class MetaVersion extends BeanBase implements IMetaVersionInit {
153
153
 
154
154
  The important point is that initialization can run per instance or tenant, which keeps tenant data isolated.
155
155
 
156
- ## Seed: test-environment baseline data
156
+ ## Seed: test and reset baseline data
157
157
 
158
158
  Representative pattern:
159
159
 
@@ -171,9 +171,9 @@ export class MetaVersion extends BeanBase implements IMetaVersionSeed {
171
171
 
172
172
  This is valuable because shared baseline data becomes part of the structured version lifecycle instead of being scattered across unrelated setup code.
173
173
 
174
- Vona invokes `seed()` while the application starts in test mode. Use it for durable baseline fixtures shared by multiple tests, E2E tests, or the managed local-development test-data workflow. The seed path starts from a newly recreated managed database; it is not a repeatable, same-database data-import mechanism.
174
+ Vona invokes `seed()` while the application starts in test mode (`npm run test` or managed E2E), and during an explicit `npm run db:reset` in dev mode. Ordinary development startup and framework upgrades do not seed or reset development data automatically. Use `seed()` for durable baseline fixtures shared by tests or for freshly prepared local development data. Both paths seed after instance initialization on a newly recreated disposable database; `seed()` is not a repeatable, same-database data-import mechanism.
175
175
 
176
- Treat shared `seed()` records as read-only in ordinary tests. A scenario that needs different state must create independent, test-owned data and clean it up in `finally`; it must not mutate or delete the shared baseline. `seed()` remains distinct from `init()`: use `init()` for instance-aware initialization data and reserve `seed()` for shared test-environment baseline data.
176
+ Treat shared `seed()` records as read-only in ordinary tests. A scenario that needs different state must create independent, test-owned data and clean it up in `finally`; it must not mutate or delete the shared baseline. `seed()` remains distinct from `init()`: use `init()` for instance-aware initialization data and reserve `seed()` for baseline data in test runs or explicit development resets.
177
177
 
178
178
  ## Version changes across the generated backend thread
179
179
 
@@ -199,13 +199,14 @@ Representative commands:
199
199
 
200
200
  ```bash
201
201
  npm run test
202
- cd vona && npm run db:reset
202
+ npm run db:reset
203
203
  ```
204
204
 
205
205
  A practical decision rule is:
206
206
 
207
- - use `db:reset` when you mainly need to replay migration/database setup locally
208
- - use `test` when you need to verify that migration, controller behavior, and the broader generated contract thread still work together
207
+ - use `db:reset` to recreate the disposable **dev-mode** databases, rerun migrations and instance initialization, and then invoke module `seed()` hooks; it deletes existing matching development databases, so do not run it against data you need to keep
208
+ - `db:reset` requires `database.testDatabase: true` in dev config and a connection outside the disposable database; it refuses to reset a configured non-disposable database
209
+ - use `test` when you need **test-mode** verification of migration, controller behavior, and the broader generated contract thread; E2E also remains test-mode
209
210
 
210
211
  ## Implementation checks for migration-sensitive changes
211
212
 
@@ -83,6 +83,12 @@ A useful distinction is:
83
83
 
84
84
  That means joins are not floating SQL trivia. They are part of a model-aware query system that can move between table-level control and relation-level convenience.
85
85
 
86
+ For stable, reusable business relationships, declare the appropriate `hasOne`, `belongsTo`, `hasMany`, or `belongsToMany` relation on the Model and prefer `include` when a CRUD read needs its related data. Use `with` for a situational relation instead of adding every one-off lookup to Model metadata. See [Relations Guide](/backend/relations-guide#static-relations-vs-dynamic-relations). An `include` loads and attaches related records after the parent query; it is **not** automatically a SQL `JOIN` between the parent and related tables. In list reads, the ordinary relation loader batches related lookups, but this still adds queries and may load large collections. Select only the relations and fields needed by that endpoint.
87
+
88
+ A relation's `where` filters the related rows that are attached; it does not remove parent rows or change a parent's `selectAndCount` total. If the presence of a matching child determines which parents belong in a list, put that condition in the parent query, for example with `_exists_` or a deliberately chosen `joins` predicate. Paginate the parent results explicitly and load bounded relation projections. A `hasMany` relation `limit` on a multi-parent list applies to the shared child query, not separately to each parent; for per-parent top-N requirements, design a query for that contract rather than assuming `include` provides it. Direct joins to collections can multiply parent rows and distort pagination or counts, so verify those semantics before using them.
89
+
90
+ Match the read's selected relations to its `$Dto.*` projection when inferring an API contract; inference describes the shape, but does not trigger ORM loading or strip extra response fields by itself. See [DTO Infer and Generation](/backend/dto-infer-generation#default-first-three-layer-dto-authoring).
91
+
86
92
  ## Type-guided joins
87
93
 
88
94
  A key insight is that joinable tables often come from relationships already declared on the model.
@@ -57,7 +57,8 @@ cd vona && npm run start:one
57
57
  In the current repo, those scripts map naturally to:
58
58
 
59
59
  - `dev` commands -> development mode
60
- - `test` / `cov` / `db:reset` -> test mode
60
+ - `test` / `cov` -> test mode through the same per-run isolated runner as root `npm run test` (root `npm run test:e2e` also uses an isolated test mode); raw `:bin:test` bypasses the wrapper
61
+ - `db:reset` -> development mode (explicitly recreates disposable development databases and runs module seeds)
61
62
  - `build` / `start` -> production mode
62
63
 
63
64
  ## Flavors
@@ -29,6 +29,18 @@ async transaction() {
29
29
 
30
30
  This matters because it makes transaction behavior explicit at the business-method level.
31
31
 
32
+ ## Choose atomicity and concurrency guarantees separately
33
+
34
+ Keep ordinary, independent CRUD writes simple: do not add an explicit transaction or pessimistic update lock just because a method is named `create`, `update`, or `delete`. A Model mutation participates in an existing transaction on its datasource, but ordinary CRUD does not automatically start a transaction around the entire service method. A single Model call can also perform more than one write, so do not assume that a compound call is an all-or-nothing business operation without checking its behavior.
35
+
36
+ Ask what the business operation must guarantee:
37
+
38
+ - **Multiple writes must succeed or fail together:** put a transaction around the business unit of work. Parent/companion writes and all-or-nothing bulk commands are examples. A transaction gives atomicity, not automatic protection against every concurrent write race.
39
+ - **A shared invariant depends on previously read state:** define the competing operations and required outcome, then select a concurrency strategy. Depending on the operation, that may be an atomic conditional update, optimistic version check, suitable isolation with retry, or a pessimistic row lock inside a transaction. For a read-modify-write balance or a check-then-insert path, a transaction alone may still allow a lost update or duplicate first insert.
40
+ - **No cross-write or contention guarantee is required:** leave the CRUD operation without an additional explicit transaction or pessimistic lock. This is a decision about application-level guarantees, not a claim that the database never locks rows while executing writes.
41
+
42
+ For an optional one-to-one companion, updating parent fields and companion content together can justify a transaction. If concurrent first writes must leave exactly one companion, locking an existing companion row cannot protect its first insertion: a parent-row serialization point or another deliberate strategy is needed. Once all competing writers use the same parent-row serialization point, an additional companion-row lock on that path may be redundant; verify that no writer bypasses the serialization point before removing it. Test the required combined durable outcome under competing operations. See [One-to-One Companion Resource Guide](/fullstack/one-to-one-companion-resource-guide#consistency-modes-and-concurrency) and [Unit Testing](/backend/unit-testing).
43
+
32
44
  ## Manual transactions
33
45
 
34
46
  Vona also supports manual transaction control using either:
@@ -47,12 +47,14 @@ npm run test
47
47
  A typical Vona test flow includes:
48
48
 
49
49
  1. create one shared global `app` object for the test run
50
- 2. clean Redis data
51
- 3. recreate the database
52
- 4. execute migration code
50
+ 2. clean the run's Redis namespace and run-specific public/runtime paths
51
+ 3. recreate the run's disposable test database
52
+ 4. execute migration and instance initialization code, then module `seed()` hooks
53
53
  5. run the test files
54
54
  6. close the shared application after the test run
55
55
 
56
+ In Cabloy Basic, root `npm run test` delegates to `vona/`'s `npm run test`; both allocate an isolated test identity, database and Redis namespace, Vona generated/runtime/public paths, and loopback listener. They can run in the same checkout as an ordinary development server without resetting or mutating that server's business data. Even a targeted run performs the test-mode setup. The Vona `npm run cov` script uses the same isolation; raw `:bin:test` commands do not. Shared build/dependency preparation may still write to shared artifacts, and custom external resources need separate isolation. See [Repo Scripts](/reference/repo-scripts#test-isolation-and-development-data-in-cabloy-basic).
57
+
56
58
  The runner owns this application lifecycle. Test files import the shared app from `vona-mock` and must not create or close it themselves:
57
59
 
58
60
  ```typescript
@@ -61,15 +63,15 @@ import { app } from 'vona-mock';
61
63
 
62
64
  This is one of the most important distinctions from ordinary app flow: test execution rebuilds and verifies the framework lifecycle, not only the target function.
63
65
 
64
- ## Reset database without running tests
66
+ ## Reset development database without running tests
65
67
 
66
- Representative command:
68
+ From the repository root:
67
69
 
68
70
  ```bash
69
- cd vona && npm run db:reset
71
+ npm run db:reset
70
72
  ```
71
73
 
72
- This is useful when you want to reapply migration logic without running the entire test suite.
74
+ This is an explicit, destructive **dev-mode** command, not test isolation: it recreates matching disposable development databases, reapplies migration and instance initialization, and runs module `seed()` hooks. It requires `database.testDatabase: true` in dev configuration and a connection outside the disposable database. Ordinary dev startup does not seed; do not reset if you need to keep its existing business data. See [Migration and Changes](/backend/migration-and-changes#local-development-workflow).
73
75
 
74
76
  ## Coverage
75
77
 
@@ -79,6 +81,8 @@ Representative command:
79
81
  cd vona && npm run cov
80
82
  ```
81
83
 
84
+ This script runs under the same isolated test environment as Vona's `npm run test`. It writes `vona/coverage/lcov.info` and, unless `--ci` is supplied, `vona/coverage/report`. These reports are shared checkout-level artifacts rather than per-run test data; do not run coverage jobs simultaneously in one checkout. Use `npm run cov -- --ci` to skip the viewer in CI.
85
+
82
86
  ## Runner concurrency
83
87
 
84
88
  The Vona runner uses Node's built-in test runner with one shared application and process isolation disabled. `TEST_CONCURRENCY` controls runner scheduling:
@@ -129,7 +133,7 @@ Locale-sensitive variants and additional request-context helpers are also availa
129
133
  Classify persisted test data before creating it:
130
134
 
131
135
  - use a **test-local fixture** for a single test or scenario;
132
- - use an owning module's `meta.version.ts` `seed()` hook only for stable baseline data shared across tests or intentionally used by the local-development test-data workflow.
136
+ - use an owning module's `meta.version.ts` `seed()` hook only for stable baseline data shared across isolated test runs or intentionally prepared by an explicit dev-mode database reset.
133
137
 
134
138
  A test owns every persisted resource it creates. Keep the returned entity or exact ID and delete owned records from `finally`, including when an assertion or action fails. Delete dependents before their owners and use the same active tenant/instance context that created them. Do not discover cleanup targets through broad table queries, time-based prefixes, or business conditions when the test already knows the exact identity.
135
139