gina 0.5.21 → 0.5.22

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 (535) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +30 -12
  3. package/ROADMAP.md +2 -1
  4. package/framework/v0.5.22/VERSION +1 -0
  5. package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/js/gina.js +281 -83
  6. package/framework/v0.5.22/core/asset/plugin/dist/vendor/gina/js/gina.min.js +593 -0
  7. package/framework/v0.5.22/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
  8. package/framework/v0.5.22/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
  9. package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.js +10 -1
  10. package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/validator/src/form-validator.js +75 -15
  11. package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/validator/src/main.js +51 -5
  12. package/framework/{v0.5.21 → v0.5.22}/core/server.js +68 -11
  13. package/framework/{v0.5.21 → v0.5.22}/core/template/conf/package.json +3 -3
  14. package/framework/{v0.5.21 → v0.5.22}/core/template/conf/settings.json +6 -2
  15. package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/build.js +1 -1
  16. package/framework/{v0.5.21 → v0.5.22}/package.json +1 -1
  17. package/gna.js +4 -4
  18. package/llms.txt +15 -5
  19. package/package.json +8 -5
  20. package/schema/settings.json +29 -0
  21. package/script/post_install.js +20 -4
  22. package/script/pre_install.js +16 -1
  23. package/framework/v0.5.21/VERSION +0 -1
  24. package/framework/v0.5.21/core/asset/plugin/dist/vendor/gina/js/gina.min.js +0 -589
  25. package/framework/v0.5.21/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
  26. package/framework/v0.5.21/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
  27. /package/framework/{v0.5.21 → v0.5.22}/AUTHORS +0 -0
  28. /package/framework/{v0.5.21 → v0.5.22}/LICENSE +0 -0
  29. /package/framework/{v0.5.21 → v0.5.22}/core/asset/html/nolayout.html +0 -0
  30. /package/framework/{v0.5.21 → v0.5.22}/core/asset/html/static.html +0 -0
  31. /package/framework/{v0.5.21 → v0.5.22}/core/asset/img/android-chrome-192x192.png +0 -0
  32. /package/framework/{v0.5.21 → v0.5.22}/core/asset/img/android-chrome-512x512.png +0 -0
  33. /package/framework/{v0.5.21 → v0.5.22}/core/asset/img/apple-touch-icon.png +0 -0
  34. /package/framework/{v0.5.21 → v0.5.22}/core/asset/img/favicon-16x16.png +0 -0
  35. /package/framework/{v0.5.21 → v0.5.22}/core/asset/img/favicon-32x32.png +0 -0
  36. /package/framework/{v0.5.21 → v0.5.22}/core/asset/img/favicon.ico +0 -0
  37. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/README.md +0 -0
  38. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.css +0 -0
  39. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.js +0 -0
  40. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/beemaster/index.html +0 -0
  41. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/css/gina.min.css +0 -0
  42. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.br +0 -0
  43. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.gz +0 -0
  44. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/html/statusbar.html +0 -0
  45. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.br +0 -0
  46. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.gz +0 -0
  47. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/inspector/have_heart_one-webfont.woff2 +0 -0
  48. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/inspector/index.html +0 -0
  49. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/inspector/inspector.css +0 -0
  50. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/inspector/inspector.js +0 -0
  51. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/inspector/logo.svg +0 -0
  52. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js +0 -0
  53. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.br +0 -0
  54. /package/framework/{v0.5.21 → v0.5.22}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.gz +0 -0
  55. /package/framework/{v0.5.21 → v0.5.22}/core/config.js +0 -0
  56. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/ai/index.js +0 -0
  57. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/ai/lib/connector.js +0 -0
  58. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/index.js +0 -0
  59. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/connector.js +0 -0
  60. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/connector.v3.js +0 -0
  61. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/connector.v4.js +0 -0
  62. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/n1ql.js +0 -0
  63. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/session-store.js +0 -0
  64. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/session-store.v3.js +0 -0
  65. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/couchbase/lib/session-store.v4.js +0 -0
  66. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mongodb/index.js +0 -0
  67. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mongodb/lib/connector.js +0 -0
  68. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mongodb/lib/job-store.js +0 -0
  69. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mongodb/lib/pipeline-loader.js +0 -0
  70. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mongodb/lib/session-store.js +0 -0
  71. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mysql/index.js +0 -0
  72. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/mysql/lib/connector.js +0 -0
  73. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/postgresql/index.js +0 -0
  74. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/postgresql/lib/connector.js +0 -0
  75. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/redis/index.js +0 -0
  76. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/redis/lib/connector.js +0 -0
  77. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/redis/lib/job-store.js +0 -0
  78. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/redis/lib/render-cache-store.js +0 -0
  79. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/redis/lib/session-store.js +0 -0
  80. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/scylladb/index.js +0 -0
  81. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/scylladb/lib/connector.js +0 -0
  82. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/scylladb/lib/session-store.js +0 -0
  83. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/sql-parser.js +0 -0
  84. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/sqlite/index.js +0 -0
  85. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/sqlite/lib/connector.js +0 -0
  86. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/sqlite/lib/job-store.js +0 -0
  87. /package/framework/{v0.5.21 → v0.5.22}/core/connectors/sqlite/lib/session-store.js +0 -0
  88. /package/framework/{v0.5.21 → v0.5.22}/core/content.encoding +0 -0
  89. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.framework.js +0 -0
  90. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-json.js +0 -0
  91. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-nunjucks-async.js +0 -0
  92. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-nunjucks.js +0 -0
  93. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-stream.js +0 -0
  94. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-swig-async.js +0 -0
  95. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-swig.js +0 -0
  96. /package/framework/{v0.5.21 → v0.5.22}/core/controller/controller.render-v1.js +0 -0
  97. /package/framework/{v0.5.21 → v0.5.22}/core/controller/index.js +0 -0
  98. /package/framework/{v0.5.21 → v0.5.22}/core/controller/inspector-window-emit.js +0 -0
  99. /package/framework/{v0.5.21 → v0.5.22}/core/controller/release-banner.js +0 -0
  100. /package/framework/{v0.5.21 → v0.5.22}/core/dev/index.js +0 -0
  101. /package/framework/{v0.5.21 → v0.5.22}/core/dev/lib/class.js +0 -0
  102. /package/framework/{v0.5.21 → v0.5.22}/core/dev/lib/factory.js +0 -0
  103. /package/framework/{v0.5.21 → v0.5.22}/core/dev/lib/tools.js +0 -0
  104. /package/framework/{v0.5.21 → v0.5.22}/core/gna.js +0 -0
  105. /package/framework/{v0.5.21 → v0.5.22}/core/locales/README.md +0 -0
  106. /package/framework/{v0.5.21 → v0.5.22}/core/locales/currency.json +0 -0
  107. /package/framework/{v0.5.21 → v0.5.22}/core/locales/dist/language/en.json +0 -0
  108. /package/framework/{v0.5.21 → v0.5.22}/core/locales/dist/language/fr.json +0 -0
  109. /package/framework/{v0.5.21 → v0.5.22}/core/locales/dist/region/en.json +0 -0
  110. /package/framework/{v0.5.21 → v0.5.22}/core/locales/dist/region/fr.json +0 -0
  111. /package/framework/{v0.5.21 → v0.5.22}/core/locales/index.js +0 -0
  112. /package/framework/{v0.5.21 → v0.5.22}/core/mime.types +0 -0
  113. /package/framework/{v0.5.21 → v0.5.22}/core/model/entity.js +0 -0
  114. /package/framework/{v0.5.21 → v0.5.22}/core/model/index.js +0 -0
  115. /package/framework/{v0.5.21 → v0.5.22}/core/model/template/entityFactory.js +0 -0
  116. /package/framework/{v0.5.21 → v0.5.22}/core/model/template/index.js +0 -0
  117. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/README.md +0 -0
  118. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/index.js +0 -0
  119. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/csrf/README.md +0 -0
  120. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/csrf/package.json +0 -0
  121. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/csrf/src/main.js +0 -0
  122. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/README.md +0 -0
  123. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/coep/README.md +0 -0
  124. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/coep/package.json +0 -0
  125. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/coep/src/main.js +0 -0
  126. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/coop/README.md +0 -0
  127. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/coop/package.json +0 -0
  128. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/coop/src/main.js +0 -0
  129. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/corp/README.md +0 -0
  130. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/corp/package.json +0 -0
  131. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/corp/src/main.js +0 -0
  132. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/csp/README.md +0 -0
  133. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/csp/package.json +0 -0
  134. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/csp/src/main.js +0 -0
  135. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/hide-powered-by/README.md +0 -0
  136. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/hide-powered-by/package.json +0 -0
  137. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/hide-powered-by/src/main.js +0 -0
  138. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/hsts/README.md +0 -0
  139. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/hsts/package.json +0 -0
  140. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/hsts/src/main.js +0 -0
  141. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/origin-agent-cluster/README.md +0 -0
  142. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/origin-agent-cluster/package.json +0 -0
  143. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/origin-agent-cluster/src/main.js +0 -0
  144. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/package.json +0 -0
  145. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/referrer-policy/README.md +0 -0
  146. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/referrer-policy/package.json +0 -0
  147. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/referrer-policy/src/main.js +0 -0
  148. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/src/main.js +0 -0
  149. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-content-type-options/README.md +0 -0
  150. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-content-type-options/package.json +0 -0
  151. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-content-type-options/src/main.js +0 -0
  152. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-dns-prefetch-control/README.md +0 -0
  153. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-dns-prefetch-control/package.json +0 -0
  154. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-dns-prefetch-control/src/main.js +0 -0
  155. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-download-options/README.md +0 -0
  156. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-download-options/package.json +0 -0
  157. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-download-options/src/main.js +0 -0
  158. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-frame-options/README.md +0 -0
  159. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-frame-options/package.json +0 -0
  160. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-frame-options/src/main.js +0 -0
  161. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/README.md +0 -0
  162. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/package.json +0 -0
  163. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/src/main.js +0 -0
  164. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-xss-protection/README.md +0 -0
  165. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-xss-protection/package.json +0 -0
  166. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/security-headers/x-xss-protection/src/main.js +0 -0
  167. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/session/README.md +0 -0
  168. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/session/package.json +0 -0
  169. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/session/src/main.js +0 -0
  170. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/storage/README.md +0 -0
  171. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/storage/build.json +0 -0
  172. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/storage/package.json +0 -0
  173. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/storage/src/main.js +0 -0
  174. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/validator/README.md +0 -0
  175. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/validator/build.json +0 -0
  176. /package/framework/{v0.5.21 → v0.5.22}/core/plugins/lib/validator/package.json +0 -0
  177. /package/framework/{v0.5.21 → v0.5.22}/core/router.js +0 -0
  178. /package/framework/{v0.5.21 → v0.5.22}/core/server.express.js +0 -0
  179. /package/framework/{v0.5.21 → v0.5.22}/core/server.isaac.js +0 -0
  180. /package/framework/{v0.5.21 → v0.5.22}/core/status.codes +0 -0
  181. /package/framework/{v0.5.21 → v0.5.22}/core/template/_gitignore +0 -0
  182. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/app.json +0 -0
  183. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/connectors.json +0 -0
  184. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/routing.json +0 -0
  185. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/settings.json +0 -0
  186. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/settings.server.json +0 -0
  187. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/templates.json +0 -0
  188. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/config/watchers.json +0 -0
  189. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/controllers/controller.content.js +0 -0
  190. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/controllers/controller.js +0 -0
  191. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/controllers/setup.js +0 -0
  192. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/index.js +0 -0
  193. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle/locales/en.json +0 -0
  194. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_namespace/controllers/controller.js +0 -0
  195. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/css/default.css +0 -0
  196. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/css/home.css +0 -0
  197. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/css/vendor/readme.md +0 -0
  198. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/favicon.ico +0 -0
  199. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/js/components/x-checklist.js +0 -0
  200. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/js/vendor/readme.md +0 -0
  201. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/manifest.webmanifest +0 -0
  202. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/readme.md +0 -0
  203. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_public/sw.js +0 -0
  204. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_templates/handlers/main.js +0 -0
  205. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_templates/html/content/homepage.html +0 -0
  206. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_templates/html/includes/error-msg-noscript.html +0 -0
  207. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_templates/html/includes/error-msg-outdated-browser.html +0 -0
  208. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_templates/html/includes/x-checklist.html +0 -0
  209. /package/framework/{v0.5.21 → v0.5.22}/core/template/boilerplate/bundle_templates/html/layouts/main.html +0 -0
  210. /package/framework/{v0.5.21 → v0.5.22}/core/template/command/gina.bat.tpl +0 -0
  211. /package/framework/{v0.5.21 → v0.5.22}/core/template/command/gina.tpl +0 -0
  212. /package/framework/{v0.5.21 → v0.5.22}/core/template/conf/env.json +0 -0
  213. /package/framework/{v0.5.21 → v0.5.22}/core/template/conf/manifest.json +0 -0
  214. /package/framework/{v0.5.21 → v0.5.22}/core/template/conf/statics.json +0 -0
  215. /package/framework/{v0.5.21 → v0.5.22}/core/template/conf/templates.json +0 -0
  216. /package/framework/{v0.5.21 → v0.5.22}/core/template/error/client/json/401.json +0 -0
  217. /package/framework/{v0.5.21 → v0.5.22}/core/template/error/client/json/403.json +0 -0
  218. /package/framework/{v0.5.21 → v0.5.22}/core/template/error/client/json/404.json +0 -0
  219. /package/framework/{v0.5.21 → v0.5.22}/core/template/error/server/html/50x.html +0 -0
  220. /package/framework/{v0.5.21 → v0.5.22}/core/template/error/server/json/500.json +0 -0
  221. /package/framework/{v0.5.21 → v0.5.22}/core/template/error/server/json/503.json +0 -0
  222. /package/framework/{v0.5.21 → v0.5.22}/core/template/extensions/logger/config.json +0 -0
  223. /package/framework/{v0.5.21 → v0.5.22}/helpers/console.js +0 -0
  224. /package/framework/{v0.5.21 → v0.5.22}/helpers/context.js +0 -0
  225. /package/framework/{v0.5.21 → v0.5.22}/helpers/data/LICENSE +0 -0
  226. /package/framework/{v0.5.21 → v0.5.22}/helpers/data/README.md +0 -0
  227. /package/framework/{v0.5.21 → v0.5.22}/helpers/data/package.json +0 -0
  228. /package/framework/{v0.5.21 → v0.5.22}/helpers/data/src/main.js +0 -0
  229. /package/framework/{v0.5.21 → v0.5.22}/helpers/dateFormat.js +0 -0
  230. /package/framework/{v0.5.21 → v0.5.22}/helpers/index.js +0 -0
  231. /package/framework/{v0.5.21 → v0.5.22}/helpers/json/LICENSE +0 -0
  232. /package/framework/{v0.5.21 → v0.5.22}/helpers/json/README.md +0 -0
  233. /package/framework/{v0.5.21 → v0.5.22}/helpers/json/package.json +0 -0
  234. /package/framework/{v0.5.21 → v0.5.22}/helpers/json/src/main.js +0 -0
  235. /package/framework/{v0.5.21 → v0.5.22}/helpers/path.js +0 -0
  236. /package/framework/{v0.5.21 → v0.5.22}/helpers/plugins/README.md +0 -0
  237. /package/framework/{v0.5.21 → v0.5.22}/helpers/plugins/package.json +0 -0
  238. /package/framework/{v0.5.21 → v0.5.22}/helpers/plugins/src/api-error.js +0 -0
  239. /package/framework/{v0.5.21 → v0.5.22}/helpers/plugins/src/main.js +0 -0
  240. /package/framework/{v0.5.21 → v0.5.22}/helpers/prototypes.js +0 -0
  241. /package/framework/{v0.5.21 → v0.5.22}/helpers/task.js +0 -0
  242. /package/framework/{v0.5.21 → v0.5.22}/helpers/text.js +0 -0
  243. /package/framework/{v0.5.21 → v0.5.22}/lib/admin/package.json +0 -0
  244. /package/framework/{v0.5.21 → v0.5.22}/lib/admin/src/main.js +0 -0
  245. /package/framework/{v0.5.21 → v0.5.22}/lib/archiver/README.md +0 -0
  246. /package/framework/{v0.5.21 → v0.5.22}/lib/archiver/build.json +0 -0
  247. /package/framework/{v0.5.21 → v0.5.22}/lib/archiver/package.json +0 -0
  248. /package/framework/{v0.5.21 → v0.5.22}/lib/archiver/src/dep/jszip.min.js +0 -0
  249. /package/framework/{v0.5.21 → v0.5.22}/lib/archiver/src/main.js +0 -0
  250. /package/framework/{v0.5.21 → v0.5.22}/lib/async/package.json +0 -0
  251. /package/framework/{v0.5.21 → v0.5.22}/lib/async/src/main.js +0 -0
  252. /package/framework/{v0.5.21 → v0.5.22}/lib/audit/package.json +0 -0
  253. /package/framework/{v0.5.21 → v0.5.22}/lib/audit/src/main.js +0 -0
  254. /package/framework/{v0.5.21 → v0.5.22}/lib/audit-store.js +0 -0
  255. /package/framework/{v0.5.21 → v0.5.22}/lib/authz-gate/package.json +0 -0
  256. /package/framework/{v0.5.21 → v0.5.22}/lib/authz-gate/src/main.js +0 -0
  257. /package/framework/{v0.5.21 → v0.5.22}/lib/cache/README.md +0 -0
  258. /package/framework/{v0.5.21 → v0.5.22}/lib/cache/build.json +0 -0
  259. /package/framework/{v0.5.21 → v0.5.22}/lib/cache/package.json +0 -0
  260. /package/framework/{v0.5.21 → v0.5.22}/lib/cache/src/main.js +0 -0
  261. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/aliases.json +0 -0
  262. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/add.js +0 -0
  263. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/arguments.json +0 -0
  264. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/build.js +0 -0
  265. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/copy.js +0 -0
  266. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/cp.js +0 -0
  267. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/help.js +0 -0
  268. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/help.txt +0 -0
  269. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/inc/name-rewrite.js +0 -0
  270. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/list.js +0 -0
  271. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/man.js +0 -0
  272. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/mcp-start.js +0 -0
  273. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/mcp.js +0 -0
  274. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/oas.js +0 -0
  275. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/openapi.js +0 -0
  276. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/remove.js +0 -0
  277. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/rename.js +0 -0
  278. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/restart.js +0 -0
  279. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/rm.js +0 -0
  280. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/start.js +0 -0
  281. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/status.js +0 -0
  282. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/stop.js +0 -0
  283. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/bundle/types.js +0 -0
  284. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/cache/arguments.json +0 -0
  285. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/cache/clear.js +0 -0
  286. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/cache/help.txt +0 -0
  287. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/cache/stats.js +0 -0
  288. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/add.js +0 -0
  289. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/arguments.json +0 -0
  290. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/help.js +0 -0
  291. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/help.txt +0 -0
  292. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/infer.js +0 -0
  293. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/list.js +0 -0
  294. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/migrate.js +0 -0
  295. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/models.js +0 -0
  296. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/remove.js +0 -0
  297. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/rm.js +0 -0
  298. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/connector/test.js +0 -0
  299. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/container/arguments.json +0 -0
  300. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/container/help.js +0 -0
  301. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/container/help.txt +0 -0
  302. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/container/man.js +0 -0
  303. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/container/ps.js +0 -0
  304. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/container/stop.js +0 -0
  305. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/add.js +0 -0
  306. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/get.js +0 -0
  307. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/help.js +0 -0
  308. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/help.txt +0 -0
  309. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/link-dev.js +0 -0
  310. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/list.js +0 -0
  311. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/remove.js +0 -0
  312. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/rm.js +0 -0
  313. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/set.js +0 -0
  314. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/unset.js +0 -0
  315. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/env/use.js +0 -0
  316. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/add.js +0 -0
  317. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/arguments.json +0 -0
  318. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/build.js +0 -0
  319. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/dot.js +0 -0
  320. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/get.js +0 -0
  321. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/help.js +0 -0
  322. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/help.txt +0 -0
  323. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/init.js +0 -0
  324. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/link-node-modules.js +0 -0
  325. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/link.js +0 -0
  326. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/list.js +0 -0
  327. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/man.js +0 -0
  328. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/msg.json +0 -0
  329. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/open.js +0 -0
  330. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/remove.js +0 -0
  331. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/reset.js +0 -0
  332. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/restart.js +0 -0
  333. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/set.js +0 -0
  334. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/start.js +0 -0
  335. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/status.js +0 -0
  336. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/stop.js +0 -0
  337. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/tail.js +0 -0
  338. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/update.js +0 -0
  339. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/framework/version.js +0 -0
  340. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/gina-dev.1.md +0 -0
  341. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/gina-framework.1.md +0 -0
  342. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/gina.1.md +0 -0
  343. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/helper.js +0 -0
  344. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/add.js +0 -0
  345. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/arguments.json +0 -0
  346. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/export.js +0 -0
  347. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/help.js +0 -0
  348. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/help.txt +0 -0
  349. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/import.js +0 -0
  350. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/i18n/scan.js +0 -0
  351. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/_host.js +0 -0
  352. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/arguments.json +0 -0
  353. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/help.js +0 -0
  354. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/help.txt +0 -0
  355. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/list.js +0 -0
  356. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/man.js +0 -0
  357. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/rm.js +0 -0
  358. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/image/run.js +0 -0
  359. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/index.js +0 -0
  360. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/inspector/help.js +0 -0
  361. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/inspector/help.txt +0 -0
  362. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/inspector/open.js +0 -0
  363. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/man-render.js +0 -0
  364. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/minion/arguments.json +0 -0
  365. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/minion/help.js +0 -0
  366. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/minion/help.txt +0 -0
  367. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/minion/kill.js +0 -0
  368. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/minion/list.js +0 -0
  369. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/msg.json +0 -0
  370. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/port/help.js +0 -0
  371. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/port/help.txt +0 -0
  372. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/port/inc/scan.js +0 -0
  373. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/port/list.js +0 -0
  374. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/port/reset.js +0 -0
  375. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/port/set.js +0 -0
  376. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/add.js +0 -0
  377. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/arguments.json +0 -0
  378. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/backup.js +0 -0
  379. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/build.js +0 -0
  380. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/help.js +0 -0
  381. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/help.txt +0 -0
  382. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/import.js +0 -0
  383. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/list.js +0 -0
  384. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/man.js +0 -0
  385. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/move.js +0 -0
  386. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/remove.js +0 -0
  387. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/rename.js +0 -0
  388. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/restart.js +0 -0
  389. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/restore.js +0 -0
  390. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/rm.js +0 -0
  391. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/start.js +0 -0
  392. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/status.js +0 -0
  393. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/project/stop.js +0 -0
  394. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/protocol/arguments.json +0 -0
  395. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/protocol/help.js +0 -0
  396. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/protocol/help.txt +0 -0
  397. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/protocol/list.js +0 -0
  398. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/protocol/remove.js +0 -0
  399. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/protocol/set.js +0 -0
  400. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/add.js +0 -0
  401. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/help.js +0 -0
  402. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/help.txt +0 -0
  403. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/link-local.js +0 -0
  404. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/link-production.js +0 -0
  405. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/list.js +0 -0
  406. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/remove.js +0 -0
  407. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/rm.js +0 -0
  408. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/scope/use.js +0 -0
  409. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/secrets/arguments.json +0 -0
  410. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/secrets/check.js +0 -0
  411. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/secrets/help.js +0 -0
  412. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/secrets/help.txt +0 -0
  413. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/secrets/scan.js +0 -0
  414. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/service/help.js +0 -0
  415. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/service/help.txt +0 -0
  416. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/service/list.js +0 -0
  417. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/service/man.js +0 -0
  418. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/service/start.js +0 -0
  419. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd/view/add.js +0 -0
  420. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd-status-format/package.json +0 -0
  421. /package/framework/{v0.5.21 → v0.5.22}/lib/cmd-status-format/src/main.js +0 -0
  422. /package/framework/{v0.5.21 → v0.5.22}/lib/collection/README.md +0 -0
  423. /package/framework/{v0.5.21 → v0.5.22}/lib/collection/build.json +0 -0
  424. /package/framework/{v0.5.21 → v0.5.22}/lib/collection/package.json +0 -0
  425. /package/framework/{v0.5.21 → v0.5.22}/lib/collection/src/main.js +0 -0
  426. /package/framework/{v0.5.21 → v0.5.22}/lib/config.js +0 -0
  427. /package/framework/{v0.5.21 → v0.5.22}/lib/connector-config/package.json +0 -0
  428. /package/framework/{v0.5.21 → v0.5.22}/lib/connector-config/src/main.js +0 -0
  429. /package/framework/{v0.5.21 → v0.5.22}/lib/connector-registry/package.json +0 -0
  430. /package/framework/{v0.5.21 → v0.5.22}/lib/connector-registry/src/main.js +0 -0
  431. /package/framework/{v0.5.21 → v0.5.22}/lib/cron/README.md +0 -0
  432. /package/framework/{v0.5.21 → v0.5.22}/lib/cron/package.json +0 -0
  433. /package/framework/{v0.5.21 → v0.5.22}/lib/cron/src/main.js +0 -0
  434. /package/framework/{v0.5.21 → v0.5.22}/lib/domain/LICENSE +0 -0
  435. /package/framework/{v0.5.21 → v0.5.22}/lib/domain/README.md +0 -0
  436. /package/framework/{v0.5.21 → v0.5.22}/lib/domain/package.json +0 -0
  437. /package/framework/{v0.5.21 → v0.5.22}/lib/domain/src/main.js +0 -0
  438. /package/framework/{v0.5.21 → v0.5.22}/lib/dto/package.json +0 -0
  439. /package/framework/{v0.5.21 → v0.5.22}/lib/dto/src/main.js +0 -0
  440. /package/framework/{v0.5.21 → v0.5.22}/lib/dto-pipe/package.json +0 -0
  441. /package/framework/{v0.5.21 → v0.5.22}/lib/dto-pipe/src/main.js +0 -0
  442. /package/framework/{v0.5.21 → v0.5.22}/lib/dto-types/package.json +0 -0
  443. /package/framework/{v0.5.21 → v0.5.22}/lib/dto-types/src/main.js +0 -0
  444. /package/framework/{v0.5.21 → v0.5.22}/lib/generator/index.js +0 -0
  445. /package/framework/{v0.5.21 → v0.5.22}/lib/i18n/package.json +0 -0
  446. /package/framework/{v0.5.21 → v0.5.22}/lib/i18n/src/main.js +0 -0
  447. /package/framework/{v0.5.21 → v0.5.22}/lib/image-build/package.json +0 -0
  448. /package/framework/{v0.5.21 → v0.5.22}/lib/image-build/src/main.js +0 -0
  449. /package/framework/{v0.5.21 → v0.5.22}/lib/index.js +0 -0
  450. /package/framework/{v0.5.21 → v0.5.22}/lib/inherits/LICENSE +0 -0
  451. /package/framework/{v0.5.21 → v0.5.22}/lib/inherits/README.md +0 -0
  452. /package/framework/{v0.5.21 → v0.5.22}/lib/inherits/package.json +0 -0
  453. /package/framework/{v0.5.21 → v0.5.22}/lib/inherits/src/main.js +0 -0
  454. /package/framework/{v0.5.21 → v0.5.22}/lib/inspector-events/package.json +0 -0
  455. /package/framework/{v0.5.21 → v0.5.22}/lib/inspector-events/src/main.js +0 -0
  456. /package/framework/{v0.5.21 → v0.5.22}/lib/inspector-redact/package.json +0 -0
  457. /package/framework/{v0.5.21 → v0.5.22}/lib/inspector-redact/src/main.js +0 -0
  458. /package/framework/{v0.5.21 → v0.5.22}/lib/instrument/package.json +0 -0
  459. /package/framework/{v0.5.21 → v0.5.22}/lib/instrument/src/main.js +0 -0
  460. /package/framework/{v0.5.21 → v0.5.22}/lib/job/package.json +0 -0
  461. /package/framework/{v0.5.21 → v0.5.22}/lib/job/src/main.js +0 -0
  462. /package/framework/{v0.5.21 → v0.5.22}/lib/job-store.js +0 -0
  463. /package/framework/{v0.5.21 → v0.5.22}/lib/json-config-header/package.json +0 -0
  464. /package/framework/{v0.5.21 → v0.5.22}/lib/json-config-header/src/main.js +0 -0
  465. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/README.md +0 -0
  466. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/package.json +0 -0
  467. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/default/index.js +0 -0
  468. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/file/index.js +0 -0
  469. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/file/lib/logrotator/README.md +0 -0
  470. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/file/lib/logrotator/index.js +0 -0
  471. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/mq/index.js +0 -0
  472. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/mq/listener.js +0 -0
  473. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/containers/mq/speaker.js +0 -0
  474. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/helper.js +0 -0
  475. /package/framework/{v0.5.21 → v0.5.22}/lib/logger/src/main.js +0 -0
  476. /package/framework/{v0.5.21 → v0.5.22}/lib/math/index.js +0 -0
  477. /package/framework/{v0.5.21 → v0.5.22}/lib/mcp-dispatch/package.json +0 -0
  478. /package/framework/{v0.5.21 → v0.5.22}/lib/mcp-dispatch/src/main.js +0 -0
  479. /package/framework/{v0.5.21 → v0.5.22}/lib/mcp-http/package.json +0 -0
  480. /package/framework/{v0.5.21 → v0.5.22}/lib/mcp-http/src/main.js +0 -0
  481. /package/framework/{v0.5.21 → v0.5.22}/lib/mcp-server/package.json +0 -0
  482. /package/framework/{v0.5.21 → v0.5.22}/lib/mcp-server/src/main.js +0 -0
  483. /package/framework/{v0.5.21 → v0.5.22}/lib/merge/README.md +0 -0
  484. /package/framework/{v0.5.21 → v0.5.22}/lib/merge/package.json +0 -0
  485. /package/framework/{v0.5.21 → v0.5.22}/lib/merge/src/main.js +0 -0
  486. /package/framework/{v0.5.21 → v0.5.22}/lib/metrics/package.json +0 -0
  487. /package/framework/{v0.5.21 → v0.5.22}/lib/metrics/src/main.js +0 -0
  488. /package/framework/{v0.5.21 → v0.5.22}/lib/model.js +0 -0
  489. /package/framework/{v0.5.21 → v0.5.22}/lib/nunjucks-filters/README.md +0 -0
  490. /package/framework/{v0.5.21 → v0.5.22}/lib/nunjucks-filters/package.json +0 -0
  491. /package/framework/{v0.5.21 → v0.5.22}/lib/nunjucks-filters/src/main.js +0 -0
  492. /package/framework/{v0.5.21 → v0.5.22}/lib/nunjucks-resolver/package.json +0 -0
  493. /package/framework/{v0.5.21 → v0.5.22}/lib/nunjucks-resolver/src/main.js +0 -0
  494. /package/framework/{v0.5.21 → v0.5.22}/lib/proc.js +0 -0
  495. /package/framework/{v0.5.21 → v0.5.22}/lib/release-watch/package.json +0 -0
  496. /package/framework/{v0.5.21 → v0.5.22}/lib/release-watch/src/main.js +0 -0
  497. /package/framework/{v0.5.21 → v0.5.22}/lib/render-cache/package.json +0 -0
  498. /package/framework/{v0.5.21 → v0.5.22}/lib/render-cache/src/main.js +0 -0
  499. /package/framework/{v0.5.21 → v0.5.22}/lib/render-cache-store.js +0 -0
  500. /package/framework/{v0.5.21 → v0.5.22}/lib/routing/README.md +0 -0
  501. /package/framework/{v0.5.21 → v0.5.22}/lib/routing/build.json +0 -0
  502. /package/framework/{v0.5.21 → v0.5.22}/lib/routing/package.json +0 -0
  503. /package/framework/{v0.5.21 → v0.5.22}/lib/routing/src/main.js +0 -0
  504. /package/framework/{v0.5.21 → v0.5.22}/lib/routing/src/radix.js +0 -0
  505. /package/framework/{v0.5.21 → v0.5.22}/lib/routing-introspect/package.json +0 -0
  506. /package/framework/{v0.5.21 → v0.5.22}/lib/routing-introspect/src/main.js +0 -0
  507. /package/framework/{v0.5.21 → v0.5.22}/lib/secrets/package.json +0 -0
  508. /package/framework/{v0.5.21 → v0.5.22}/lib/secrets/src/backends/env.js +0 -0
  509. /package/framework/{v0.5.21 → v0.5.22}/lib/secrets/src/main.js +0 -0
  510. /package/framework/{v0.5.21 → v0.5.22}/lib/session-store.js +0 -0
  511. /package/framework/{v0.5.21 → v0.5.22}/lib/shell.js +0 -0
  512. /package/framework/{v0.5.21 → v0.5.22}/lib/state.js +0 -0
  513. /package/framework/{v0.5.21 → v0.5.22}/lib/swig-filters/README.md +0 -0
  514. /package/framework/{v0.5.21 → v0.5.22}/lib/swig-filters/package.json +0 -0
  515. /package/framework/{v0.5.21 → v0.5.22}/lib/swig-filters/src/main.js +0 -0
  516. /package/framework/{v0.5.21 → v0.5.22}/lib/swig-resolver/package.json +0 -0
  517. /package/framework/{v0.5.21 → v0.5.22}/lib/swig-resolver/src/main.js +0 -0
  518. /package/framework/{v0.5.21 → v0.5.22}/lib/template-loaders/package.json +0 -0
  519. /package/framework/{v0.5.21 → v0.5.22}/lib/template-loaders/src/loaders/http.js +0 -0
  520. /package/framework/{v0.5.21 → v0.5.22}/lib/template-loaders/src/loaders/memory.js +0 -0
  521. /package/framework/{v0.5.21 → v0.5.22}/lib/template-loaders/src/main.js +0 -0
  522. /package/framework/{v0.5.21 → v0.5.22}/lib/url/README.md +0 -0
  523. /package/framework/{v0.5.21 → v0.5.22}/lib/url/index.js +0 -0
  524. /package/framework/{v0.5.21 → v0.5.22}/lib/url/routing.json +0 -0
  525. /package/framework/{v0.5.21 → v0.5.22}/lib/uuid/package.json +0 -0
  526. /package/framework/{v0.5.21 → v0.5.22}/lib/uuid/src/main.js +0 -0
  527. /package/framework/{v0.5.21 → v0.5.22}/lib/validator.js +0 -0
  528. /package/framework/{v0.5.21 → v0.5.22}/lib/watcher/package.json +0 -0
  529. /package/framework/{v0.5.21 → v0.5.22}/lib/watcher/src/main.js +0 -0
  530. /package/framework/{v0.5.21 → v0.5.22}/lib/ws-framing/package.json +0 -0
  531. /package/framework/{v0.5.21 → v0.5.22}/lib/ws-framing/src/main.js +0 -0
  532. /package/framework/{v0.5.21 → v0.5.22}/lib/ws-query/package.json +0 -0
  533. /package/framework/{v0.5.21 → v0.5.22}/lib/ws-query/src/main.js +0 -0
  534. /package/framework/{v0.5.21 → v0.5.22}/lib/ws-session/package.json +0 -0
  535. /package/framework/{v0.5.21 → v0.5.22}/lib/ws-session/src/main.js +0 -0
package/llms.txt CHANGED
@@ -449,6 +449,8 @@ Counters are live — no restart required. `activeSessions` is bounded by ≥ 0.
449
449
  }
450
450
  ```
451
451
 
452
+ **Global routing (`routing.global.json`)** — lives at bundle `config/routing.global.json` or project-wide `shared/config/routing.global.json`. The framework reads exactly ONE key from this file: `middleware` — an array of middleware references prepended to every route's own `middleware` list. Every other key in the file is ignored; do not put caching or header configuration there. For response caching / `Cache-Control`, use the per-route `cache` field in `routing.json`; for a static header on every response, declare it under `server.response.header` in `env.json`.
453
+
452
454
  ---
453
455
 
454
456
  ## OpenAPI spec generation
@@ -916,7 +918,7 @@ Dev-mode query instrumentation captures every database query tied to the current
916
918
 
917
919
  212. **Structured (JSON) logging — `GINA_LOG_FORMAT=json` + per-request `requestId`/`durationMs` (consolidates former #152/#155; #M12a/#M12b).** The logger resolves its render format ONCE at init into `opt.format` (precedence `GINA_LOG_FORMAT=json|text` > `GINA_LOG_STDOUT` truthy ⇒ json > `text` default) BEFORE containers are cloned; a JSON line is `{ts, level, bundle, message, group, msg}` — `bundle`/`message` canonical, `group`/`msg` retained as additive back-compat aliases — and the raw `console.log` path honours the format too (otherwise JSON mode would interleave plain lines and break a collector); the `text` default keeps container logs byte-identical. Per-request `requestId` + `durationMs` ride JSON logs via a NARROW `AsyncLocalStorage` (`process.gina._reqALS`, parked on `process.gina` so it survives dev require-cache busting), gated on JSON logging ONLY (text renders no id field, so the ALS would be pure overhead — the text path stays byte-identical/zero-cost): the id resolver honours a SANITISED inbound `X-Request-Id` (`/^[\w.\-]{1,128}$/`, regenerate-on-violation kills log forging) else `crypto.randomUUID()`; the `.run({requestId, startMs})` wrap sits at `handle()` — NOT the request-entry handler — because the `request.on('end')` boundary between them loses async context while `handle()`'s awaits preserve it (the original body became `_handleDispatch`; `handle` is a thin wrapper); HTTP/2 gets per-stream scoping free via Node's per-stream compat `'request'` event, NOT `session.on('stream')`; the JSON-assembly sites read `getStore()` and add `requestId` + per-line `durationMs`, gracefully absent for CLI/boot/off-request logs. `.run()`, never `enterWith()` (enterWith bleeds sideways across siblings).
918
920
 
919
- 213. **Client-plugin discipline — CSP-safe listeners, native-dialog parity, preload coalescing (consolidates former #149/#159/#200).** (1) Client-bundle plugins must NOT inject inline event-handler attributes (`setAttribute('onclick', …)`, `el.onX = …`) — they trip CSP `script-src-attr` under nonce-based policies; suppress defaults with `addEventListener('click', e => e.preventDefault())`, and keep it `preventDefault`-ONLY (no stopPropagation) when the element participates in event delegation other handlers depend on — a `preventDefault`-only listener still sets `event.defaultPrevented` exactly as the inline handler did. (2) Dialog popins open as native modals (`$el.showModal()`) in EVERY env — the dev-only non-modal downgrade + manual overlay are gone for dialog mode (native `::backdrop`); a consumer that PRE-OPENS the dialog (skeleton loading) must also use `showModal()` or it is born non-modal with nothing positioning it; the opt-in `preOpen`/`loadingShell` skeleton is idempotent via `hasAttribute('open')` — NOT getAttribute truthiness, because `showModal()` sets `open` to the EMPTY string; a native UA close (Escape, `<form method="dialog">`) fires the element's `close` event WITHOUT the plugin's own close path, so a once-per-element `close` listener (the event is `close`, not `cancel` — `cancel` is Escape-only) routes it through the plugin close, keeping open-state/listeners/toolbar consistent — a UA-closed shared popin otherwise re-opens "one render behind" (#B58). (3) A popin/dialog click fired TWO identical GETs because the hover/`focusin` preload — `focusin` is part of the click gesture — was never reused: an in-flight preload registry lets the click-time consume ADOPT the in-flight fetch (waiter woken with the body, caller's own load on failure) instead of fetching again, and the legacy click path consumes preloads at all now (#B54); only the initial GET is ever preloaded. The consume path bypassing the full load tail (redirect/JSON handling) was ASSUMED acceptable — but a hover/focus-WARMED trigger whose GET returns a redirect/JSON response (`application/json` `{isXhrRedirect,location}`) had that raw JSON blind-injected as the popin body via `applyContent` (`$el.innerHTML`), the `_self` tunnel never firing — IDENTICAL symptom to the #B77 `_self` timer race but a DIFFERENT mechanism (the consume path, regression `2c61c494` v0.5.5), so #B77 fixed only the UNWARMED click-time path and the WARMED path persisted until #B80 (2026-07-06, `37e6829c`): `preloadFetch`'s `onreadystatechange` now caches a 2xx response ONLY when its Content-Type is NOT `application/json` (mirrors `popinLoad`'s own `isJsonContent` detection), firing the in-flight waiters with `null` (→ `consumePreload`'s `onMiss` = the click-time `doLoad`) and leaving the cache empty (→ a ready consume returns false → `doLoad`), so a JSON-returning trigger falls through to the click-time `popinLoad`'s full redirect/JSON tail exactly as a non-preloaded click (one extra GET on click — the hover-warm GET is not reused; measured 2 GETs). Only a genuine HTML fragment is preloaded+injected. Browser-bundled → prod dist rebuilt; VERIFIED in a real browser (a warmed legacy `data-gina-popin-url` redirect trigger now shows the tunnel target, not the raw JSON; the decline path positively exercised via resource-timing) — jsdom is falsely green. That residual — the GET itself still fired on hover for side-effecting triggers, authenticated (same-origin cookies) and CSRF-token-less (GET) — is CLOSED by the #B91 per-trigger opt-out (2026-07-10): `data-gina-dialog-preload="false"` on the trigger (honored on legacy `data-gina-popin-url` triggers too — the gate reads the attribute off the closest-matched intent target; case-INSENSITIVE `/^false$/i` on purpose, so a templated "False" cannot fail open and fire the GET anyway — deliberately safer than data-gina-dialog-modal's case-sensitive parse) suppresses BOTH the hover warm and the focusin-on-click warm at the shared intent handler; the opted-out click loads normally at click time (undefined cache slot → consume returns false → the caller's click-time load; exactly one GET per click). Default stays preload-ON: GET is presumed safe to fire early per HTTP semantics — a side-effecting trigger declares itself (the hover-prefetch ecosystem's convention, live-verified). (4) A proxied/tunnelled redirect JSON response (`isXhrRedirect`+`location`, default `_self`) used to `$popin.load()` then arm a blind `setTimeout(50, () => !$popin.isOpen && $popin.open())`; a follow-up load slower than 50 ms opened the popin against a not-yet-injected (skeleton/empty) target → intermittent unhandled-deref crash. Removed as vestigial (v0.1.0, 2021) — the already-armed `loaded.<id>` listener opens CONTENT-FIRST (injects the body via popinBind/handleLoadedBody, THEN popinOpen), so the load alone suffices; the `_self` branch's `return;` still guards the `window.open` fall-through (non-`_self` targets only) (#B77). Event contract: `open.<id>` = a fresh open, `loaded.<id>` = reload/redirect content injected — a consumer needing "content ready on every load" must listen to BOTH. A structurally identical blind timer lived in the SIBLING validator `Validator::Popin now redirecting` path (`core/plugins/lib/validator/src/main.js`), removed by #B79 (2026-07-10): the validator DISCARDED popinLoad's return, and that return IS the `{open}` handle whose `open()` arms the content-first `loaded.<id>` listener — so the timer was papering over a race the discarded handle created (an XHR faster than 50 ms fired `loaded` into the void and the body was lost, a slower one opened an empty popin first). It now captures the handle and calls `open()` inside the same not-open gate, guarding the `undefined` popinLoad returns when the request cannot start (CORS unsupported) so a failed load never blind-opens an empty popin; and the cross-popin branch resets `isRedirecting` before closing the ORIGINAL popin, because `popinClose` early-bails on a redirecting popin — that close was a silent no-op, leaving the original open behind the new one (browser-verified: pre-fix stays open, post-fix closes). MEASURED CORRECTION: the timer was NOT load-bearing for the different-popin branch as long assumed — that branch threw first, because the published `gina.popin` WAS re-assembled with a target-wins merge on every `new Popin()`, so its `getPopinByName`/`getPopinById` stayed bound to the FIRST instance's registry and resolved ONLY the boot popin, while `$popins` + `getActivePopin` saw every popin and `gina.popin.activePopinId` never updated (so `getActivePopin()` returned null once nothing was open) — and popins registered AFTER an instance's publish (click-time in-page dialog registrations) never reached the published registry at all, with destroyed popins lingering in it. FIXED as #B90 (2026-07-10): ONE module-scoped registry (`_sharedPopins`) aliased by every instance's `$popins`; a publish-ONCE `gina.popin = instance` (the published object IS the first instance, LIVE — re-publishing was both the freeze defect and, with a shared registry, a self-merge recursion hazard: gina's merge deep-recurses plain objects and `$popin.eventData` can hold the $popin itself); and a `setActivePopinId` write-through helper at all 7 write sites keeping the published `activePopinId` truthful no matter which instance opens or closes a popin. Browser-verified both ways on the built bundle (pre-fix: accessors blind + the validator cross-popin redirect 422-throws `not found`; fixed: accessors resolve every instance's popins and a form submit redirecting into a DIFFERENT popin works end-to-end — the original closes, the target loads content-first, `activePopinId` follows). Generalises: an accessor published through a target-wins `merge()` silently keeps the first instance's closure — publish a live instance once and share module-scoped state instead of re-merging per construction; and never infer a code path is reachable from the fact that it exists. (5) EAGER content warm — `data-gina-dialog-preload="eager"` (case-insensitive) opts a trigger into a one-shot idle warm-all pass: after `window` load, on requestIdleCallback (setTimeout fallback), serialized one GET at a time, routed through the SAME shared per-trigger gate as the hover warm (`warmTrigger`: disabled skip → the `"false"` opt-out → URL-cache dedup → in-flight reserve + fetch) so the two warm paths cannot drift and whichever fires second is a no-op; skipped entirely under Save-Data; triggers injected after the pass keep the delegated hover warm; staleness matches the shipped no-TTL hover semantics — the opt-in accepts the wider warm→open window. Content preload deliberately does NOT ride 103 Early Hints: popin responses vary on `X-Requested-With` (a non-XHR GET of a fragment layout gets the iframe-wrap variant and misses the scripts append), and a browser `Link rel=preload` fetch never carries that header — wrong-variant bytes or a double GET, with no success branch; `self.setEarlyHints()` remains the right tool for a popin's STATIC subassets (the CSS/JS it injects via getScript/getStyle). All five are browser-bundled — prod dist rebuild required; verify (2), (3), (4) and (5) with a REAL preemptive-open / preload / redirect-tunnel consumer — a minimal smoke page is falsely green.
921
+ 213. **Client-plugin discipline — CSP-safe listeners, native-dialog parity, preload coalescing (consolidates former #149/#159/#200).** (1) Client-bundle plugins must NOT inject inline event-handler attributes (`setAttribute('onclick', …)`, `el.onX = …`) — they trip CSP `script-src-attr` under nonce-based policies; suppress defaults with `addEventListener('click', e => e.preventDefault())`, and keep it `preventDefault`-ONLY (no stopPropagation) when the element participates in event delegation other handlers depend on — a `preventDefault`-only listener still sets `event.defaultPrevented` exactly as the inline handler did. (2) Dialog popins open as native modals (`$el.showModal()`) in EVERY env — the dev-only non-modal downgrade + manual overlay are gone for dialog mode (native `::backdrop`); a consumer that PRE-OPENS the dialog (skeleton loading) must also use `showModal()` or it is born non-modal with nothing positioning it; the opt-in `preOpen`/`loadingShell` skeleton is idempotent via `hasAttribute('open')` — NOT getAttribute truthiness, because `showModal()` sets `open` to the EMPTY string; a native UA close (Escape, `<form method="dialog">`) fires the element's `close` event WITHOUT the plugin's own close path, so a once-per-element `close` listener (the event is `close`, not `cancel` — `cancel` is Escape-only) routes it through the plugin close, keeping open-state/listeners/toolbar consistent — a UA-closed shared popin otherwise re-opens "one render behind" (#B58). (3) A popin/dialog click fired TWO identical GETs because the hover/`focusin` preload — `focusin` is part of the click gesture — was never reused: an in-flight preload registry lets the click-time consume ADOPT the in-flight fetch (waiter woken with the body, caller's own load on failure) instead of fetching again, and the legacy click path consumes preloads at all now (#B54); only the initial GET is ever preloaded. The consume path bypassing the full load tail (redirect/JSON handling) was ASSUMED acceptable — but a hover/focus-WARMED trigger whose GET returns a redirect/JSON response (`application/json` `{isXhrRedirect,location}`) had that raw JSON blind-injected as the popin body via `applyContent` (`$el.innerHTML`), the `_self` tunnel never firing — IDENTICAL symptom to the #B77 `_self` timer race but a DIFFERENT mechanism (the consume path, regression `2c61c494` v0.5.5), so #B77 fixed only the UNWARMED click-time path and the WARMED path persisted until #B80 (2026-07-06, `37e6829c`): `preloadFetch`'s `onreadystatechange` now caches a 2xx response ONLY when its Content-Type is NOT `application/json` (mirrors `popinLoad`'s own `isJsonContent` detection), firing the in-flight waiters with `null` (→ `consumePreload`'s `onMiss` = the click-time `doLoad`) and leaving the cache empty (→ a ready consume returns false → `doLoad`), so a JSON-returning trigger falls through to the click-time `popinLoad`'s full redirect/JSON tail exactly as a non-preloaded click (one extra GET on click — the hover-warm GET is not reused; measured 2 GETs). Only a genuine HTML fragment is preloaded+injected. Browser-bundled → prod dist rebuilt; VERIFIED in a real browser (a warmed legacy `data-gina-popin-url` redirect trigger now shows the tunnel target, not the raw JSON; the decline path positively exercised via resource-timing) — jsdom is falsely green. That residual — the GET itself still fired on hover for side-effecting triggers, authenticated (same-origin cookies) and CSRF-token-less (GET) — is CLOSED by the #B91 per-trigger opt-out (2026-07-10): `data-gina-dialog-preload="false"` on the trigger (honored on legacy `data-gina-popin-url` triggers too — the gate reads the attribute off the closest-matched intent target; case-INSENSITIVE `/^false$/i` on purpose, so a templated "False" cannot fail open and fire the GET anyway — deliberately safer than data-gina-dialog-modal's case-sensitive parse) suppresses BOTH the hover warm and the focusin-on-click warm at the shared intent handler; the opted-out click loads normally at click time (undefined cache slot → consume returns false → the caller's click-time load; exactly one GET per click). Default stays preload-ON: GET is presumed safe to fire early per HTTP semantics — a side-effecting trigger declares itself (the hover-prefetch ecosystem's convention, live-verified). (4) A proxied/tunnelled redirect JSON response (`isXhrRedirect`+`location`, default `_self`) used to `$popin.load()` then arm a blind `setTimeout(50, () => !$popin.isOpen && $popin.open())`; a follow-up load slower than 50 ms opened the popin against a not-yet-injected (skeleton/empty) target → intermittent unhandled-deref crash. Removed as vestigial (v0.1.0, 2021) — the already-armed `loaded.<id>` listener opens CONTENT-FIRST (injects the body via popinBind/handleLoadedBody, THEN popinOpen), so the load alone suffices; the `_self` branch's `return;` still guards the `window.open` fall-through (non-`_self` targets only) (#B77). Event contract: `open.<id>` = a fresh open, `loaded.<id>` = reload/redirect content injected — a consumer needing "content ready on every load" must listen to BOTH. A structurally identical blind timer lived in the SIBLING validator `Validator::Popin now redirecting` path (`core/plugins/lib/validator/src/main.js`), removed by #B79 (2026-07-10): the validator DISCARDED popinLoad's return, and that return IS the `{open}` handle whose `open()` arms the content-first `loaded.<id>` listener — so the timer was papering over a race the discarded handle created (an XHR faster than 50 ms fired `loaded` into the void and the body was lost, a slower one opened an empty popin first). It now captures the handle and calls `open()` inside the same not-open gate, guarding the `undefined` popinLoad returns when the request cannot start (CORS unsupported) so a failed load never blind-opens an empty popin; and the cross-popin branch resets `isRedirecting` before closing the ORIGINAL popin, because `popinClose` early-bails on a redirecting popin — that close was a silent no-op, leaving the original open behind the new one (browser-verified: pre-fix stays open, post-fix closes). MEASURED CORRECTION: the timer was NOT load-bearing for the different-popin branch as long assumed — that branch threw first, because the published `gina.popin` WAS re-assembled with a target-wins merge on every `new Popin()`, so its `getPopinByName`/`getPopinById` stayed bound to the FIRST instance's registry and resolved ONLY the boot popin, while `$popins` + `getActivePopin` saw every popin and `gina.popin.activePopinId` never updated (so `getActivePopin()` returned null once nothing was open) — and popins registered AFTER an instance's publish (click-time in-page dialog registrations) never reached the published registry at all, with destroyed popins lingering in it. FIXED as #B90 (2026-07-10): ONE module-scoped registry (`_sharedPopins`) aliased by every instance's `$popins`; a publish-ONCE `gina.popin = instance` (the published object IS the first instance, LIVE — re-publishing was both the freeze defect and, with a shared registry, a self-merge recursion hazard: gina's merge deep-recurses plain objects and `$popin.eventData` can hold the $popin itself); and a `setActivePopinId` write-through helper at all 7 write sites keeping the published `activePopinId` truthful no matter which instance opens or closes a popin. Browser-verified both ways on the built bundle (pre-fix: accessors blind + the validator cross-popin redirect 422-throws `not found`; fixed: accessors resolve every instance's popins and a form submit redirecting into a DIFFERENT popin works end-to-end — the original closes, the target loads content-first, `activePopinId` follows). Generalises: an accessor published through a target-wins `merge()` silently keeps the first instance's closure — publish a live instance once and share module-scoped state instead of re-merging per construction; and never infer a code path is reachable from the fact that it exists. (5) EAGER content warm — `data-gina-dialog-preload="eager"` (case-insensitive) opts a trigger into a one-shot idle warm-all pass: after `window` load, on requestIdleCallback (setTimeout fallback), serialized one GET at a time, routed through the SAME shared per-trigger gate as the hover warm (`warmTrigger`: disabled skip → the `"false"` opt-out → URL-cache dedup → in-flight reserve + fetch) so the two warm paths cannot drift and whichever fires second is a no-op; skipped entirely under Save-Data; triggers injected after the pass keep the delegated hover warm; staleness matches the shipped no-TTL hover semantics — the opt-in accepts the wider warm→open window. (6) #B139 (2026-07-20, rides the next cut): the content cache no longer outlives the open it warmed — measured pre-fix it was a ONE-GENERATION-LAGGING store (every open after the first paid ~1 GET yet rendered the PREVIOUS open's fetch: the leftover entry — the #B54 in-flight adoption's repopulated body, or the around-open re-warm — blocked the fresh warm's dedup; NO invalidation path existed, close/unbind/destroy never touched the cache; reproduced back to 0.5.4, so it predates #B54 and the eager pass). Fix: close clears the popin's content-URL slot (stamped at consumePreload both branches + popinLoad) AND re-sweeps the same slot ~120ms later, because the close-time a11y focus-return and pointer re-hover fire TRUSTED synthetic intents that re-warm the slot with close-era content within 1ms of the close (measured; a raced sweep is benign by construction — at most one extra fetch, never staleness, since an adopted in-flight body still reaches its open through the waiter chain). AND `preload="false"` triggers now skip the cache READ at open on both open paths — `false` is the hard always-refetch spelling for volatile popins (its GET always happens at open, never from a same-URL sibling's warm); no new annotation vocabulary. Warmed-never-opened entries keep the page-lifetime eager semantics above; default triggers pay at most one extra idempotent GET per close (the swept synthetic warm). Content preload deliberately does NOT ride 103 Early Hints: popin responses vary on `X-Requested-With` (a non-XHR GET of a fragment layout gets the iframe-wrap variant and misses the scripts append), and a browser `Link rel=preload` fetch never carries that header — wrong-variant bytes or a double GET, with no success branch; `self.setEarlyHints()` remains the right tool for a popin's STATIC subassets (the CSS/JS it injects via getScript/getStyle). All five are browser-bundled — prod dist rebuild required; verify (2), (3), (4) and (5) with a REAL preemptive-open / preload / redirect-tunnel consumer — a minimal smoke page is falsely green.
920
922
 
921
923
  214. **Per-request routing-clone correctness — narrow the defensive clone, and propagate mutations onto returned clones (consolidates former #194/#195; #B52-residual, 2026-06-18).** The router's per-request `options.conf = JSON.clone(conf)` — a multi-MB deep clone of the ENTIRE bundle config per matched request, held for the request's whole query+render window — was narrowed to: shallow-copy the top level + `conf.content`, deep-clone ONLY `conf.content.routing`, the one subtree actually MUTATED per request (audited: every other per-request write is a whole-subtree REASSIGNMENT a shallow copy isolates, and plugins/connectors/models read config via their own clones, never through the request's) — removing a dev/high-load heap high-water-mark proportional to config size (measured 163→62 MB peak under 150 concurrent slow requests, drains on idle). Rule: clone only the subtrees mutated per request and share the immutable remainder by reference — but audit EVERY per-request writer first, or a missed mutate-into-a-shared-subtree reintroduces cross-request contamination. Sibling: `getRouteByUrl` (server-side redirect/relative-route resolution AND browser-bundled) aliased the shared route config's `param` by REFERENCE while the matcher rewrites `param.{path,namespace,file,title}` in place for `:placeholder` routes — request A's substitution contaminated request B (server) and repeat navigations (client). The fix is TWO coordinated edits, not just "clone the alias": clone `param` per request AND propagate the substituted param onto the returned route object — the function returns a fresh clone of the SINGLETON, so cloning alone returns the un-substituted `:placeholder` and regresses even the first request. Rule: when a matcher both aliases a shared config object and returns a re-clone of that object, isolating the alias is insufficient — propagate the per-request mutations onto the returned clone. The sibling is browser-bundled → prod dist rebuild.
922
924
 
@@ -932,7 +934,7 @@ Dev-mode query instrumentation captures every database query tied to the current
932
934
 
933
935
  222. **FormValidator built-in rule labels localise per culture from ONE per-bundle catalog on BOTH client and server — app-owned, the framework ships NO translations (0.5.x, validator i18n Slices 1–3).** The 26 English defaults live in `form-validator.js` as `_defaultErrorLabels`; each rule resolves `this.error || local.errorLabels[rule]` (per-field app override wins, else the default), and the engine seeds `local.errorLabels` from the defaults then overlays the negotiated culture's labels from the same `_validator.<rule>` catalog namespace both sides read. **CLIENT overlay** (`isGFFCtx`-gated) applies two layers over English with precedence **app `setErrorLabels()` > server-whispered bundle catalog > English**: layer 3 reads the `setErrorLabels()` registry `gina.validator._errorLabelsByCulture[gina.config.culture]` (exact `fr_FR` → base `fr` fallback); layer 2 reads `gina.config.validatorLabels` — the culture's `_validator` subset from `bundle/locales/<culture>.json` whispered by the render path (`controller.js` resolves it via `lib.i18n` walkFallback→getCatalog→resolveKey, `encodeRFC5987ValueChars`-encoded into `page.environment.validatorLabels`; `loader.js` reads it into `gina.config.validatorLabels` with a GUARDED `JSON.parse(decodeURIComponent(…))` IIFE — NOT a bare parse like `routing`, an empty whisper would throw and kill `onGinaLoaded` → whole-page JS dead — plus `@js_externs validatorLabels`). Each layer is `merge(JSON.clone(layer), local.errorLabels)` (lib/merge is target-wins/source-fills, so a higher layer wins per key and lower layers fill), catalog applied FIRST then registry; an empty `{}` catalog is skipped (own-key guard) so it degrades to registry/English. **SERVER overlay** (`!isGFFCtx`): passing a string `culture` to `gina.plugins.Validator` resolves the same `_validator` node (same walkFallback→getCatalog→resolveKey chain) and merges it over English. Apps register client overrides through the public `gina.validator.setErrorLabels(labels[, culture])`. Matches the framework's per-bundle "app owns catalogs" i18n stance (`bundle/locales` + `t()`); custom user rules already carry app messages and are untouched; a per-field/rule `error` still wins. **Two SERVER constraints (measured — the second RESOLVED, 0.5.x):** routing.json `validator::{}` requirement labels stay English (those validators run during route-matching, BEFORE culture negotiation → `req.culture` undefined there). The auto-validation path (pass a rules object) used to null-deref `$fields` at `forEachField` — the DOM `getAttribute('type')` read sat one line ABOVE its own missing-field guard while the server auto path passes `$fields = null` — so it had never worked server-side, and a rule field missing from the client collection threw instead of reaching the intended warn+continue. Fixed with a guarded ternary (null/missing → `localFieldType = null`, inert server-side: every consumer of it is client-gated): plain rules now validate server-side and return `{ isValid(), error, data }`, the trailing culture localises the labels on the auto path too (measured: a seeded catalog resolves, no culture → English), and the client missing-field warn is reachable. Conditional (`_case_`) rules retain deeper server-unsafe `$fields` reads and remain client-only; the MANUAL path (`new gina.plugins.Validator({}, data, formId, req.culture)` + `v.field.rule(...)`) remains valid and is what routing uses. **`%`-token contract (measured 2026-07-08).** `replace()` substitutes tokens in the MERGED `local.errorLabels`, so a CATALOG label interpolates exactly like an English default — load-bearing because length bounds arrive as ARRAY args (`"isString": [5]`, spread through `apply()` in `main.js`) and therefore reach `isStringMinLength`/`isStringMaxLength`, keys no rule file ever names (grepping rule files for them returns 0 and wrongly reads as dead). The vocabulary is CLOSED and CASE-SENSITIVE: `replace()` matches `/%[a-z]+/gi` GREEDILY and looks each hit up verbatim in `local.keys` (`%l`→label, `%n`→name, `%s`→size), so an unknown token (`%d`, `%L`) — or a literal percent glued to letters (`20%sur le prix` matches `%sur`) — splices the literal string `undefined` into user-facing copy. **A NON-STRING label FAIL-SOFTS (0.5.14).** `replace(target, fieldObj, rule)` takes the rule name as an OPTIONAL 3rd argument — optional because `replace` is re-exported to app-defined validators through `getValidationContext()`, which call it with two — and when `target` is not a string it warns once per rule per engine instance (per-instance, NOT module-scoped: the module is shared across bundles + requests on the server) and falls back **resolved label → that rule's English default → empty string**. All 26 call sites pass the same key they read from `local.errorLabels`, and every one of those keys has an English default, so "degrade to English" holds at 26/26; the dynamic `is()` site passes `alias`, which is always `'is'` (the `is<N>` alias branch in the plugin's `main.js` is unreachable — its `continue` on non-function rules precedes it). Pre-0.5.14 this threw `target.match is not a function`, and NOTHING on the path catches it (`main.js`'s only `try` rethrows as `[ ginaFormValidator ] could not evaluate …`): measured in a real browser, the validator instance never finished initialising, the first form bound only partially, **every later form on the page was never bound at all** (the `bindForm` loop is unguarded), no error message rendered, and the page fell back to NATIVE browser submits with zero client-side validation. Note the submit trigger is never natively `disabled` — `updateSubmitTriggerState` only ever CLEARS `disabled`, using `aria-disabled` + `.gina-form-submit-disabled` for the invalid state — so "the button looks alive" is not evidence the pass ran. `%l` is frontend-only (it reads the DOM `data-gina-form-field-label`), so a catalog label using it renders EMPTY server-side rather than `undefined`. `lib/i18n loadCatalogs` LINTS the `_validator` node at boot (warns per offending label, never throws, catalog still loads); it covers the client too (the whisper is a subset of the same boot-loaded catalog) but NOT runtime `setErrorLabels()` labels, NOR a rule's `errorMessage` argument (`is: ["$a === $b", <non-string>]` — the lint never reads form-rule JSON), NOR a field's `error` — for those three the engine's own fail-soft guard is the only net, which is why it warns at the point of degradation. **`compileError()` is one line UPSTREAM of `replace()` on the `query` path** and carried the same class of defect: `error.match(/\{\{…\}\}/g)` returns `null` (not `[]`) when a backend field error carries no `{{placeholder}}` — the ordinary shape, e.g. `"Already taken"` — so `varArr.length` threw before any label could render; it now returns the error verbatim, and the `query` call site only compiles a string (a non-string backend field error keeps the resolved label instead of reaching `compileError`). **Labels are LATE-BOUND per validation pass (measured).** The overlay lives in the `FormValidatorUtil` CONSTRUCTOR, and `validate()` builds a FRESH engine on every pass (`main.js` ~`:7145`/`:7154`/`:7157`) — not once at bind time — so `setErrorLabels()` called AFTER `new FormValidator(...)`, canonically inside a `ready` handler (which fires immediately after `gina.validator = instance`), applies from the NEXT pass; it does NOT retroactively change a pass already in flight, since the message string is interpolated at rule-evaluation time. **Catalog-load signal (measured correction).** A `locales/*.json` filename failing `CULTURE_FILENAME` (`fr-FR.json`, `fr_fr.json`) DOES warn and is skipped; the genuinely SILENT case is a MISSING `locales/` dir (`config.js` `fs.existsSync` with no `else`) — opt-in by design. Catalogs are boot-loaded with no hot reload, so a catalog edit needs a bundle restart. Closure keeps the cross-module property names via the quoted-literal-decl + dot-read + `@js_externs` pattern; both validator files browser-bundled → any edit needs a prod dist rebuild (the 4 `gina.*` + 3 `gina.onload.*`), but `lib/i18n` is server-only so the boot lint needs none. Tests: `test/lib/validator-label-i18n.test.js` (client registry layer) + `test/lib/validator-label-i18n-server.test.js` (server) + `test/lib/validator-label-i18n-client-catalog.test.js` (client catalog + 3-layer precedence) + `test/lib/validator-label-i18n-runtime.test.js` (%-token interpolation from a catalog label, the boot lint, late binding). **#B88 fields-slot stack disclosure (0.5.14).** The reachability that renders a backend `fields[<field>]` value is FRAMEWORK-produced, not app-specific: `gna.ApiError` (`helpers/plugins/src/api-error.js`) merges `{tag,fields,path}` over the error so `error`+`fields` land at the response root — a consumer hits `compileError`'s gate with NO literal `fields:` in its source (grep = structural false negative). A raw stack enters that slot via ApiError's own `e.message || e.stack` fallback on a message-less Error, or an app passing a stack string; post-#B86 `compileError` returned it VERBATIM → it rendered into the user-facing field message (info disclosure — the DOM write is `createTextNode`, NOT XSS). FIXED AT THE SOURCE, not `compileError`: `formatClientError` scope-gates a stack-shape (`/\n\s+at\s/`) strip on `fields[fieldName]` (generic message outside local scope, full stack kept in local; call-time `NODE_SCOPE_IS_LOCAL` read, fail-closed), the sibling of `controller.js`'s fail-closed root-`stack` wire strip — which CANNOT reach the fields slot (merge drops the non-enumerable root `.stack`, so the slot is the sole carrier). One source site covers BOTH browser render paths, which each read `result.fields[<field>]`: the live-check `compileError`→`replace` path AND the form-submit `main.js` `isApiError`→`handleErrorsDisplay` path (renders verbatim, pre-dates #B86). Server-side → NO dist rebuild. The same commit scope-gates the `formatClientError` catch-branch root `.stack` (it serialises via renderJSON, which does no stripping). DEFERRED (unreported): a `{error,fields}` response hand-built WITHOUT ApiError bypasses the source strip → escalation is the same strip at the render chokepoint `handleErrorsDisplay` (browser, needs a dist rebuild). Tests: `test/lib/api-error-field-stack.test.js` (real ApiError, both sub-cases × scope, catch-branch gate, subtract). **#B89 aria-live re-announce on message refresh (0.5.14).** `handleErrorsDisplay` has three per-field branches: first-error (parent not yet marked) builds the message div AND announces via the form's `aria-live=polite` region; clear (field valid) removes it; refresh (still-errored, `data-gina-form-errors` truthy) REBUILDS the message div from the fresh `errors[name]`. The refresh branch updated the VISIBLE text but never re-announced, so a screen reader kept announcing the FIRST message when a continuously-errored field's message changed (a different failing rule, a value-dependent message, or a late `setErrorLabels()`). FIXED: a guarded `announceA11yError($form, $err.textContent)` on the refresh branch (same guard as the first-error branch — committed not soft-warning, per-field/blur path, once focus has left the field) + an `e != 'stack'` skip on its message loop (parity with the first-error branch — no stray stack `<p>` feeding the announce). `announceA11yError` writes `_live.textContent` (a REPLACE) on the form's one `gina-aria-live-<formId>` polite region, so a CHANGED string re-announces. On a blur the live-check runs a per-field validate (first-error → Branch A announce) THEN a global pass that sets `data-gina-form-errors` truthy and re-calls `handleErrorsDisplay` for the touched field (Branch C), so a second blur with a different message reliably hits the refresh branch. Browser-bundled → prod dist rebuilt; live-verified in a real headless browser (subtract: the pre-fix bundle keeps the stale announce while the visible text updates, the post-fix re-announces). DEFERRED (message-timing, LOW): which field a per-field pass refreshes is `errAttr`-gated (reset then set only after a completed pass), so a late `setErrorLabels()` before a field's first validation — or with `gina.config.culture` unset (the client culture overlay is skipped on a falsy culture) — can leave an already-errored field's message stale until it clears; register culture-keyed labels before first validation. Test: `test/core/validator-a11y-reannounce.test.js`.
934
936
 
935
- 223. **Per-request culture negotiation was INERT framework-wide until 0.5.x — `req.culture` / the whispered `gina.config.culture` always `'en'`/`''` regardless of bundle or environment culture, and `t()` / the `t` template filter returned keys — now activated (#I18N Slice 1).** The #I18N1 catalog + negotiation machinery shipped but three legs were dead: `lib/i18n loadCatalogs` had ZERO runtime callers (so `process.gina._i18nCatalogs` stayed empty → `core/server.js availableCultures` `[]` → `matchAvailable` null on an empty list → URL-prefix / cookie / `Accept-Language` never matched); the per-request `negotiateCulture` call passed `defaultCulture: null` (step-4 bundle default skipped); and 8 sites read `process.env.GINA_CULTURE`, which `utils/helper.js` moves into `process.gina` and DELETEs from `process.env` at init (`getEnvVar` reads `process.gina`), so `negotiateCulture` step 5, the `server.js` catch, both swig + both nunjucks `t`/`tIcu` filter fallbacks, and the `i18n:add` CLI all read an always-undefined var → negotiation fell to step 6 = `'en'`. Fix (server-side, NO dist rebuild): `config.js loadBundleConfig` (after the `secrets.resolve` seam) calls `i18n.loadCatalogs(bundle, <bundleRoot>/locales)` guarded by `fs.existsSync` (opt-in; also avoids loadCatalogs' empty-entry + background ICU-loader side effects) + `try/catch`→`console.warn` (a malformed catalog is warned, not boot-fatal — loadCatalogs THROWS on bad JSON); `server.js` reads the matched bundle `content.settings.region.culture` (format-guarded vs an unresolved `${culture}`) as `defaultCulture`; the 8 dead reads → the live `getEnvVar('GINA_CULTURE')` (`typeof getEnvVar === 'function'`-guarded in the strict global-free `lib/i18n` + the filter modules so an isolated unit-require never ReferenceErrors). Precedence now live: URL / cookie / `Accept-Language` > bundle `settings.region.culture` > operator `GINA_CULTURE` > `'en'`. **`settings.region.culture` is the REAL per-bundle culture key** — bundle scaffold `core/template/boilerplate/bundle/config/settings.json` `"culture":"${culture}"` (full underscore culture resolved at `bundle:add`; the merged config carries it — `server.js`/`controller.js` already read `content.settings.region.{timeZone,isoShort}`), NOT `settings.locale.region` (a country code in the framework `settings.json`'s separate CLDR `locale` block). Blast radius: framework-wide — `req.culture`/`gina.config.culture` now reflect the configured culture, `t()` resolves real strings for any bundle shipping a `locales/` dir (others unaffected via the `existsSync` guard). Makes the #222 client validator-label overlay (gated on a truthy `gina.config.culture`) actually reachable; Slice 1 of the validator + i18n unification. **#B84 (same day) completes the activation on the WARM route path:** Slice 1 negotiated `req.culture` only on the COLD (uncached) path — `core/server.js handle()`'s cached-route fast-path (`if ( hasCachedRoute ) { isRoute = hasCachedRoute; … break; }` ~`:4964`) breaks the routing loop BEFORE the cold-path negotiation site (~`:5115`), and the route cache persists across requests (the module-scoped `routingLib` at `:91` is a stable gen-0 binding — server.js is load-once; `Routing._cached` is set at `:5198` on the cold request and read at `:4964` on every later hit to the same `method:pathname`), so the SECOND hit to any URL is warm and left `req.culture` unset → `controller.js` embeds `''` into `page.environment.culture` → `gina.config.culture === ''` → the #222 client overlay inert on warm reloads (a warm BROWSER reload reproduces; `curl` masks it — a fresh cold-only hit after a restart still negotiates). Fixed by extracting the negotiation into a per-request `var _negotiateReqCulture = function(req, routeBundle)` closure in `handle()` scope, called on BOTH the warm (`( req.routing && req.routing.bundle ) || bundle` — `getCached` already ran `compareUrls`→`checkRouteParams`, so `req.routing` incl. `bundle`/`culturePrefix` is populated) and cold (`routing[name].bundle`) paths. **The resolved culture is NEVER cached with the shared route entry** — it's per-request (cookie / Accept-Language), so pinning it would cross-request-bleed (the #B65/#B66 per-request-vs-worker-global class); the consumer's first suggestion "cache `req.culture` with the route" was rejected for exactly this, their second "re-negotiate on the warm path" shipped. **Rule: any per-request state derived after a route match must be re-derived on the cached fast-path too — `if ( hasCachedRoute ) { … break; }` bypasses everything below it in the loop.** Server-side, NO dist rebuild; surfaced by a consumer report-back that Slice 1's cold-only activation had missed. Tests: `test/core/server-culture-negotiation.test.js` (two-path source pins + a behavioural replica of the fast-path-breaks-before-cold-site structure driving the real `negotiateCulture` + a subtract proving the warm-path call is load-bearing) + a daemonless cold→warm `gina-container` boot (`req.culture === 'xx_XX'` on cold AND warm over real HTTP; `''` pre-fix). Established 2026-07-07. **#B99 (0.5.16) closes the last unwired negotiation input: `settings.i18n.cookieName` is now honoured at the SAME negotiate call** — a guarded read beside the `region.culture` default (explicit `null` passes through and disables the cookie step, since `negotiateCulture` already gates on a falsy name; absent/empty/non-string keeps the historical `gina_culture`), closing the 0.3.11 slice-3 known limitation ("cookie name is hardcoded … a follow-up wires bundle-settings access"). The framework never WRITES the cookie (bundle authors set it in middleware), so only the read name changes; the sibling `i18n.cultures` key remains RESERVED/unwired. Live-verified in an isolated daemonless boot: a renamed cookie (`my_lang=xx`) resolves the culture on cold AND warm hits while the old name is ignored. Tests: §0304 of the same file.
937
+ 223. **Per-request culture negotiation was INERT framework-wide until 0.5.x — `req.culture` / the whispered `gina.config.culture` always `'en'`/`''` regardless of bundle or environment culture, and `t()` / the `t` template filter returned keys — now activated (#I18N Slice 1).** The #I18N1 catalog + negotiation machinery shipped but three legs were dead: `lib/i18n loadCatalogs` had ZERO runtime callers (so `process.gina._i18nCatalogs` stayed empty → `core/server.js availableCultures` `[]` → `matchAvailable` null on an empty list → URL-prefix / cookie / `Accept-Language` never matched); the per-request `negotiateCulture` call passed `defaultCulture: null` (step-4 bundle default skipped); and 8 sites read `process.env.GINA_CULTURE`, which `utils/helper.js` moves into `process.gina` and DELETEs from `process.env` at init (`getEnvVar` reads `process.gina`), so `negotiateCulture` step 5, the `server.js` catch, both swig + both nunjucks `t`/`tIcu` filter fallbacks, and the `i18n:add` CLI all read an always-undefined var → negotiation fell to step 6 = `'en'`. Fix (server-side, NO dist rebuild): `config.js loadBundleConfig` (after the `secrets.resolve` seam) calls `i18n.loadCatalogs(bundle, <bundleRoot>/locales)` guarded by `fs.existsSync` (opt-in; also avoids loadCatalogs' empty-entry + background ICU-loader side effects) + `try/catch`→`console.warn` (a malformed catalog is warned, not boot-fatal — loadCatalogs THROWS on bad JSON); `server.js` reads the matched bundle `content.settings.region.culture` (format-guarded vs an unresolved `${culture}`) as `defaultCulture`; the 8 dead reads → the live `getEnvVar('GINA_CULTURE')` (`typeof getEnvVar === 'function'`-guarded in the strict global-free `lib/i18n` + the filter modules so an isolated unit-require never ReferenceErrors). Precedence now live: URL / cookie / `Accept-Language` > bundle `settings.region.culture` > operator `GINA_CULTURE` > `'en'`. **`settings.region.culture` is the REAL per-bundle culture key** — bundle scaffold `core/template/boilerplate/bundle/config/settings.json` `"culture":"${culture}"` (full underscore culture resolved at `bundle:add`; the merged config carries it — `server.js`/`controller.js` already read `content.settings.region.{timeZone,isoShort}`), NOT `settings.locale.region` (a country code in the framework `settings.json`'s separate CLDR `locale` block). Blast radius: framework-wide — `req.culture`/`gina.config.culture` now reflect the configured culture, `t()` resolves real strings for any bundle shipping a `locales/` dir (others unaffected via the `existsSync` guard). Makes the #222 client validator-label overlay (gated on a truthy `gina.config.culture`) actually reachable; Slice 1 of the validator + i18n unification. **#B84 (same day) completes the activation on the WARM route path:** Slice 1 negotiated `req.culture` only on the COLD (uncached) path — `core/server.js handle()`'s cached-route fast-path (`if ( hasCachedRoute ) { isRoute = hasCachedRoute; … break; }` ~`:4964`) breaks the routing loop BEFORE the cold-path negotiation site (~`:5115`), and the route cache persists across requests (the module-scoped `routingLib` at `:91` is a stable gen-0 binding — server.js is load-once; `Routing._cached` is set at `:5198` on the cold request and read at `:4964` on every later hit to the same `method:pathname`), so the SECOND hit to any URL is warm and left `req.culture` unset → `controller.js` embeds `''` into `page.environment.culture` → `gina.config.culture === ''` → the #222 client overlay inert on warm reloads (a warm BROWSER reload reproduces; `curl` masks it — a fresh cold-only hit after a restart still negotiates). Fixed by extracting the negotiation into a per-request `var _negotiateReqCulture = function(req, routeBundle)` closure in `handle()` scope, called on BOTH the warm (`( req.routing && req.routing.bundle ) || bundle` — `getCached` already ran `compareUrls`→`checkRouteParams`, so `req.routing` incl. `bundle`/`culturePrefix` is populated) and cold (`routing[name].bundle`) paths. **The resolved culture is NEVER cached with the shared route entry** — it's per-request (cookie / Accept-Language), so pinning it would cross-request-bleed (the #B65/#B66 per-request-vs-worker-global class); the consumer's first suggestion "cache `req.culture` with the route" was rejected for exactly this, their second "re-negotiate on the warm path" shipped. **Rule: any per-request state derived after a route match must be re-derived on the cached fast-path too — `if ( hasCachedRoute ) { … break; }` bypasses everything below it in the loop.** Server-side, NO dist rebuild; surfaced by a consumer report-back that Slice 1's cold-only activation had missed. Tests: `test/core/server-culture-negotiation.test.js` (two-path source pins + a behavioural replica of the fast-path-breaks-before-cold-site structure driving the real `negotiateCulture` + a subtract proving the warm-path call is load-bearing) + a daemonless cold→warm `gina-container` boot (`req.culture === 'xx_XX'` on cold AND warm over real HTTP; `''` pre-fix). Established 2026-07-07. **#B99 (0.5.16) closes the last unwired negotiation input: `settings.i18n.cookieName` is now honoured at the SAME negotiate call** — a guarded read beside the `region.culture` default (explicit `null` passes through and disables the cookie step, since `negotiateCulture` already gates on a falsy name; absent/empty/non-string keeps the historical `gina_culture`), closing the 0.3.11 slice-3 known limitation ("cookie name is hardcoded … a follow-up wires bundle-settings access"). The framework never WRITES the cookie (bundle authors set it in middleware), so only the read name changes; live-verified in an isolated daemonless boot: a renamed cookie (`my_lang=xx`) resolves the culture on cold AND warm hits while the old name is ignored; tests §03/§04 of the same file. **#B102 (0.5.22) wires the sibling — and last RESERVED — key, `settings.i18n.cultures`:** a NON-EMPTY array now constrains the user-signal steps (URL prefix / cookie / Accept-Language) by INTERSECTION with the loaded-catalog set — a staged rollout keeps a shipped-but-unlaunched catalog out of negotiation while its file ships; `null` / `[]` / non-array keep the historical derive-from-loaded-catalogs behavior (an existing bundle changes nothing at pickup), and the bundle-default step (`settings.region.culture`) is deliberately never constrained — the operator's fallback needs no catalog match. The whole `i18n` block (cookieName / devMissingKey / fallbackChain / cultures — the first three were already wired) is now declared in the published `schema/settings.json`, which previously had no `i18n` block at all. Restart-to-apply (server.js is load-once); no dist rebuild. Tests: §0506 of the same file.
936
938
 
937
939
  224. **The client FormValidator now AUTO-BOOTS at page load — a form declaring `data-gina-form-rule` + a matching `gina.forms.rules` entry validates in the browser with NO bundle JS (2026-07-07).** `core/asset/plugin/src/vendor/gina/core.js`'s plugin-loading `require([...])` callback previously ran only `bootPopinHandler()` (the `data-gina-dialog` popin auto-boot); it now also runs a sibling `bootValidator()` that constructs `new (require('gina/validator'))(gina.forms.rules).on('ready', function(){})` when `gina.forms.rules` is non-empty — closing the popin/validator asymmetry (both declarative attribute APIs now work with no per-element handler code). The trailing `.on('ready')` is load-bearing: validator `init()` only REGISTERS `on('init', onValidatorInit)` + sets `initialized=true`; the form-scan/bind + `gina.validator` publish live inside that handler, fired by the `events.js` self-fire that ANY post-`initialized` `.on()` triggers (`initialized && !isReady → triggerEvent('init.'+id)`). IDEMPOTENT: a later explicit bundle construction (a bundle `main.js` + a per-page handler both `new V(...)`) takes the `if (gina.hasValidator) { instance = merge(instance, gina.validator) }` merge path — its `.on('ready')` STILL fires and the already-`binded` forms are not re-scanned (auto-boot just prepends construction #1 to the re-construction path bundles already relied on). Gated on NON-EMPTY `gina.forms.rules` so a rules-less page is byte-identical (no scan, no `gina.validator` publish). The `isFrameworkLoaded` poll (bounded ≤100, `setTimeout`) is race-safe: `onGinaLoaded` sets `isFrameworkLoaded` (`loader.js:232`) THEN `gina.forms` (`:236`) in ONE synchronous whisper, so a truthy `isFrameworkLoaded` observed from a poll guarantees `gina.forms` is already populated (JS run-to-completion — no yield splits the whisper). `core.js` is browser-bundled → a prod dist rebuild is required (freshness anchor: the `[gina] validator boot failed` string literal, which survives Closure SIMPLE minification unlike the renamed `bootValidator` identifier). MEASURED via a daemonless `gina-container` render smoke (2/2 deterministic): a rule-bound form auto-validates with zero app JS (`gina.hasValidator===true`, `$forms.<id>` bound, live-check gate toggles invalid→valid→invalid), and a later `new V(gina.forms.rules).on('ready', fn)` runs `fn` with the form still bound. Tests: `test/core/validator-auto-boot.test.js`.
938
940
 
@@ -978,7 +980,7 @@ Dev-mode query instrumentation captures every database query tied to the current
978
980
 
979
981
  245. **TypeScript types from a DTO — `gina bundle:types` and the TWO-type rule (#DTO3a, 0.5.18-alpha.2).** `gina bundle:types <bundle> @<project>` walks the bundle's `dtos/<Name>.js` factories and emits TypeScript declarations to `<bundle>/dtos/index.d.ts` (`--output` overrides) — a DTO's fourth projection, alongside runtime validation, response shaping and the OpenAPI/MCP schemas, so the wire, the spec and the editor cannot drift. Sibling of `bundle:openapi`/`bundle:mcp`: same inputs, same offline `dto.load` resolver, same flag. **⚠️ Each DTO emits TWO types, and that is measured, not stylistic.** An `.exclude()`d field IS carried in the canonical JSON Schema (in `properties`, and in `required[]` when declared required) but is ABSENT from what the server actually holds — the validator engine drops it from its coerced output and `DtoObject.apply()` deletes it — so a single schema-derived type would LIE about `req.dto`. Hence `<Name>` = the DECLARED shape (what the client sends, what OpenAPI documents) and `<Name>Projected` = `Omit<<Name>, …excluded>` (what the action reads on `req.dto`, and what a `param.responseDto` puts on the wire); a plain alias when nothing is excluded. **⚠️ The scalar mapping describes the COERCED payload, not the raw wire string:** `integer`/`number` → `number` (`'30'`→`30`), `boolean` → `boolean`, `enum` → a literal union, and **`date` → `string`, NOT `Date`** — `isDate` coerces to an ISO string AND shifts the value (`'2020-01-02'` → `'2020-01-01T23:00:00.000Z'`). Value bounds ride as `@minimum`/`@maximum` JSDoc explicitly labelled schema-only (they are not runtime-enforced). **⚠️ The excluded set is read off the DTO's SHAPE, never off `toRules()`** — `toRules()` reports `exclude:true` too, but it THROWS on an authored `$` (server-fatal in the validator engine), so a currency-style DTO (`dto.enum(['$ 10'])`) can never be compiled to rules yet still documents and still needs a type; the emitter has to be TOTAL where `toRules()` is not. The emit is pure + deterministic (DTOs sorted, no clock, no path), so a committed artifact is drift-checkable by re-running the emitter in memory — the same generator→artifact→drift-test triad `types/gna.d.ts` uses. A DTO that fails to load ABORTS the command rather than being skipped (unlike `bundle:openapi`, whose spec degrades usefully): a type surface emitted minus a broken DTO would ship an incomplete contract silently, and the bundle would refuse to boot on it anyway. Server/CLI-side — NO dist rebuild. Verified end-to-end against the real offline CLI on a scaffolded bundle, and the emitted declarations compiled with `tsc --strict` to confirm both that they are valid TypeScript and that an excluded field really is absent from the projection. Tests: `test/lib/dto-types.test.js` (38) + `test/lib/dto-types-drift.test.js`.
980
982
 
981
- 246. **Checkbox `checked` state is decided by the `checked` attribute, never by `value` (#49, 0.5.18-alpha.2):** FormValidator historically treated a checkbox's `value` as the STATE carrier — `value="true"` was auto-ticked at bind, a value-less box (whose DOM `.value` defaults to `"on"`) cached `defaultChecked=true` so a form RESET ticked it (bind itself never ticked value-less boxes), `value="false"` un-ticked a server-checked box, and the posted boolean came from the live `.value` string through gates that skipped `.checked` (consumer script setting `el.checked = false` still posted `true` off the stale value; a neutral `value="1"` box could never post `true`). Fixed: the HTML `checked` attribute (IDL `defaultChecked`) alone decides the initial state; both serialization collectors short-circuit boolean-classified checkboxes (no `value` attribute, `value` reading `true`/`false`, or an `isBoolean` rule) to post the live `.checked` as a real boolean — wire bytes identical for every previously-correct path; value-CARRYING checkboxes (payload values like ids/emails + `checked` attr) keep posting their value string when checked, absent when not, and must never be boolean-coerced. Per-form legacy opt-in `data-gina-form-checkbox-value-as-state="true"` (deprecated, transitional) restores value-driven ticking for un-migrated markup; a once-per-field console warn (one shared once-map) flags BOTH migration directions in spec mode: `value="true|on"`-without-`checked` markup (used to render ticked), and — 0.5.19-alpha.2 — `checked`-attr markup whose old resolution chain (`data-value` attr, else `value` attr, else DOM `.value`, `''`→false) reads false/empty (used to render UNTICKED, now stays ticked; `data-value="false"` wins the chain). The change-time value/`data-value`/`checked`-attr mirroring is kept (no longer state-authoritative). The dead `$`-anchored boolean-coercion regexes (never matched since 2021) were removed, not "fixed" — activating them would silently change cached value types for no gain. **The `"on"` handling is DELIBERATE jQuery interop and is UNTOUCHED by this fix** — it is INPUT-side (gina reading a DOM jQuery wrote): `main.js` neutralises a jQuery-set `on` on an unchecked box (`if (isInit && /^(on)$/i.test($el.value) && !$el.checked) { $el.value = false }`) and normalises `/^(true|on)$/` to boolean `true`. So the wire delta below is NOT the removal of a compat feature: the pre-fix collector's boolean-shape test was `/^(true|false)$/`, which OMITS `on`, so a CHECKED-at-load value-less box (DOM `.value` defaults to `"on"`; the jQuery-era init neutralisation is `!checked`-gated, so only the checked shape still read `on` at submit) failed it and fell through to the generic VALUE-CARRYING branch (`fields[name] = $el.value`) that has no `on` knowledge and shipped the browser default verbatim — a classifier gap, not a designed contract, and one the bind layer had contradicted for years. The fix ALIGNS the collector with that long-standing `on`-means-true position; no serialization opt-out is owed (and the legacy opt-in deliberately gates ticking only). Residual, not a regression: an explicitly authored `value="on"` attribute stays value-carrying and still posts `"on"` (the classifier inherits the same omission) — NOT the jQuery shape, since `.val()` sets the property, leaving `getAttribute('value')` null and the box already boolean-classified. Radios, FACE bindings, and the validation engine are untouched. `main.js` is browser-bundled: a fix here needs the prod dist rebuild AND each consumer bundle re-baked before browsers see it. Follow-up (same version): the collectors' forced rule self-injection appends `isRequired` BEFORE `isBoolean` — rules run in key insertion order and the engine's isBoolean rescue only clears an isRequired error recorded before it (a real boolean `false` reads as empty under the engine's loose `!= ''` check) — so an unchecked box whose rule declared neither key no longer hard-fails validation; the fix made this reachable by posting `false` where the field was previously ABSENT (the rule never ran) and by widening the injection to value-less boxes. Two wire deltas are deliberate contract, not regressions, and survive the legacy opt-in (it gates only ticking): a checked-at-load untouched value-less box posts `true` (was the string `"on"`), and an unchecked boolean box posts a present `false` (was absent ONLY when a rule WITHOUT `isBoolean` was declared for it — a rule-less or `isBoolean`-declared bound box already posted a coerced `false`, since the bind-init neutralisation had rewritten its value to `"false"`, so the pre-#49 wire was never uniform checked-`"on"`/unchecked-absent native parity) — servers reading `"on"` or testing mere presence must read the boolean.
983
+ 246. **Checkbox `checked` state is decided by the `checked` attribute, never by `value` (#49, 0.5.18-alpha.2):** FormValidator historically treated a checkbox's `value` as the STATE carrier — `value="true"` was auto-ticked at bind, a value-less box (whose DOM `.value` defaults to `"on"`) cached `defaultChecked=true` so a form RESET ticked it (bind itself never ticked value-less boxes), `value="false"` un-ticked a server-checked box, and the posted boolean came from the live `.value` string through gates that skipped `.checked` (consumer script setting `el.checked = false` still posted `true` off the stale value; a neutral `value="1"` box could never post `true`). Fixed: the HTML `checked` attribute (IDL `defaultChecked`) alone decides the initial state; both serialization collectors short-circuit boolean-classified checkboxes (no `value` attribute, `value` reading `true`/`false`, or an `isBoolean` rule) to post the live `.checked` as a real boolean — wire bytes identical for every previously-correct path; value-CARRYING checkboxes (payload values like ids/emails + `checked` attr) keep posting their value string when checked, absent when not, and must never be boolean-coerced. Per-form legacy opt-in `data-gina-form-checkbox-value-as-state="true"` (deprecated, transitional) restores value-driven ticking for un-migrated markup; a once-per-field console warn (one shared once-map) flags BOTH migration directions in spec mode: `value="true|on"`-without-`checked` markup (used to render ticked), and — 0.5.19-alpha.2 — `checked`-attr markup whose old resolution chain (`data-value` attr, else `value` attr, else DOM `.value`, `''`→false) reads false/empty (used to render UNTICKED, now stays ticked; `data-value="false"` wins the chain). The change-time value/`data-value`/`checked`-attr mirroring is kept (no longer state-authoritative). The dead `$`-anchored boolean-coercion regexes (never matched since 2021) were removed, not "fixed" — activating them would silently change cached value types for no gain. **The `"on"` handling is DELIBERATE jQuery interop and is UNTOUCHED by this fix** — it is INPUT-side (gina reading a DOM jQuery wrote): `main.js` neutralises a jQuery-set `on` on an unchecked box (`if (isInit && /^(on)$/i.test($el.value) && !$el.checked) { $el.value = false }`) and normalises `/^(true|on)$/` to boolean `true`. So the wire delta below is NOT the removal of a compat feature: the pre-fix collector's boolean-shape test was `/^(true|false)$/`, which OMITS `on`, so a CHECKED-at-load value-less box (DOM `.value` defaults to `"on"`; the jQuery-era init neutralisation is `!checked`-gated, so only the checked shape still read `on` at submit) failed it and fell through to the generic VALUE-CARRYING branch (`fields[name] = $el.value`) that has no `on` knowledge and shipped the browser default verbatim — a classifier gap, not a designed contract, and one the bind layer had contradicted for years. The fix ALIGNS the collector with that long-standing `on`-means-true position; no serialization opt-out is owed (and the legacy opt-in deliberately gates ticking only). Residual, not a regression: an explicitly authored `value="on"` attribute stays value-carrying and still posts `"on"` (the classifier inherits the same omission) — NOT the jQuery shape, since `.val()` sets the property, leaving `getAttribute('value')` null and the box already boolean-classified. Radios, FACE bindings, and the validation engine are untouched. `main.js` is browser-bundled: a fix here needs the prod dist rebuild AND each consumer bundle re-baked before browsers see it. Follow-up (same version): the collectors' forced rule self-injection appends `isRequired` BEFORE `isBoolean` — rules run in key insertion order and the engine's isBoolean rescue only clears an isRequired error recorded before it (a real boolean `false` reads as empty under the engine's loose `!= ''` check) — so an unchecked box whose rule declared neither key no longer hard-fails validation; the fix made this reachable by posting `false` where the field was previously ABSENT (the rule never ran) and by widening the injection to value-less boxes. Two wire deltas are deliberate contract, not regressions, and survive the legacy opt-in (it gates only ticking): a checked-at-load untouched value-less box posts `true` (was the string `"on"`), and an unchecked boolean box posts a present `false` (was absent ONLY when a rule WITHOUT `isBoolean` was declared for it — a rule-less or `isBoolean`-declared bound box already posted a coerced `false`, since the bind-init neutralisation had rewritten its value to `"false"`, so the pre-#49 wire was never uniform checked-`"on"`/unchecked-absent native parity) — servers reading `"on"` or testing mere presence must read the boolean. **#B125 (0.5.22-alpha.2) — the migration warns are opt-out-able and name the payload-only remedy:** the tick-direction warn false-positived on legitimate post-#49 payload-only markup (`value="true"`, no `checked`, intended unticked — byte-identical to pre-#49 markup at the attribute level, so no predicate can distinguish intent, and both listed remedies did the wrong thing for that shape). Measured through both serialization collectors: every warned shape (unchecked, `value` reading true/on) posts the live checked-state boolean regardless of the `value` attribute — bind-init even rewrites the attribute to the state mirror — so both messages now name the third remedy (remove the `value` attribute; the posted wire is identical), and an explicit form-level `data-gina-form-checkbox-value-as-state` declaration of ANY value (canonically `"false"`, which is otherwise behavior-inert — its only reader tests `/^true$/i`) silences both migration warns for that form: an author who declares the state model has read it, so the migration aid has nothing left to teach.
982
984
 
983
985
  247. **Published TypeScript declarations repaired + the two-part types gate (#DTO3b, 0.5.18-alpha.2): a `tsc` pass proves declarations are well-FORMED, never that they are TRUE.** The shipped `types/*.d.ts` compiled clean at strict while wrong 15 ways — the headline: `types/index.d.ts` declared NO value, so `import gina from 'gina'; gina.lib` was a type error for every consumer; plus silent lies that typecheck then crash at runtime (`Gna extends EventEmitter` on a plain object literal; `String.prototype.ltrim/rtrim/gtrim` pure fiction; `export class SuperController` for a constructor the main entry never exports — the constructors live on `require('gina/gna')`). The repair shape is namespace-as-module — `declare namespace gina { ... } export = gina` — the only shape describing BOTH `import gina = require('gina')` (the primary CJS form) and the ESM default import: `export default` alone half-fixes, `export =` cannot coexist with sibling `export type/class` statements nor merge with a `declare const`, so every public type moves INSIDE the namespace and the constructors demote to `SuperControllerConstructor`/`EntitySuperConstructor` interfaces. Ambient-namespace `const` members cannot be optional — conditionally-assigned members (`gina.getConfig`, which only exists once models have loaded; the proxy host quartet) are typed `| undefined` to force narrowing. The route-DTO payoff rides along: `GinaRequest<TDto>` types `req.dto` (strict projection) and the method payloads as `TDto & Record<string, any>` (the intersection PRESERVES declared field types while URL params stay reachable), and `RouteParam` gains `dto`/`responseDto`. The gate is two-part because a compile catches neither lie class: (a) `script/check_types_consumer.js` compiles a consumer fixture BY PACKAGE NAME through the exports map (`moduleResolution: node16`; a by-path probe is structurally blind to a missing `export =`) with `skipLibCheck: false` (with `true`, a deliberately-garbage `.d.ts` reports clean), `@ts-expect-error` tripwires that fail the build if a removed lie returns, and a MUST-FAIL control program whose TS2339+TS2304 prove the instrument can fire; (b) `test/lib/types-runtime-parity.test.js` reflects the real runtime — the framework lib registry keys, a real `createTestInstance()` instance, the UNANCHORED `gna.<name> =` source enumeration (a line-anchored variant missed 22 indented members, `onInitialize` included), and the injected-globals diff — and diffs it two-way against the declarations, every deliberate exception carrying its reason inline (e.g. the injected `paths` global is an accidental sloppy-mode leak and stays deliberately UNdeclared). Wired as `npm run types:check` + a `Check published types` CI step; devDeps `typescript@^7.0.2` + `@types/node@^26.1.1`.
984
986
 
@@ -998,9 +1000,9 @@ Dev-mode query instrumentation captures every database query tied to the current
998
1000
 
999
1001
  255. **`redirect()` is ASYNC, and its relative-path form resolves again — an unresolvable target 404s the request instead of killing the bundle (2026-07-17, unreleased).** Three coordinated fixes. (1) `getRouteByUrl` (lib/routing) is async and awaits its internal `compareUrls` (async since the `validator::` requirements support): the historical un-awaited call read `.past` off a pending Promise, so NO rule could EVER match server-side — the documented-primary `self.redirect('/path')` relative form had been dead for years (the ignoreWebRoot form only worked because it bypasses resolution entirely). The fix also mirrors the engine loop's exact-url fast-path (`pathname == routing[name].url || isRoute.past`) — the two matchers are declared byte-parallel ("must remain identical to server.js") and any behaviour added to one must land in the other. (2) The resolution lands in a LOCAL first and is adopted onto `req.routing` only on success: a miss or resolver rejection keeps the route that dispatched the action. This no-clobber shape is load-bearing twice over — the matcher itself reads and stamps `request.routing` on the request it is handed (a `false` there silently voids the writes), and the error reporters' diagnostics deref `req.routing.param` (with the old `false` sentinel the designed 404 turned into a crash-derived 500 from inside the reporter). A double miss now throws a clean 404 (`redirect target not found`); a resolver rejection is contained as a 500 — either way one request, never the process. (3) The response-header composer guards `!request.routing` (falsy-aware; the old `typeof == 'undefined'` guard passed the boolean `false` through to a strict-mode primitive-property write that threw from inside the error path itself — a double-fault the router's catch could not contain, ending in SIGTERM). `redirect()` being async means: prefer `return self.redirect(...)` from controller actions so a rejection threads to the framework's thenable backstop; all other forms (URL, route-name, ignoreWebRoot) complete synchronously — their promise settles same-tick. `getRouteByUrl` ships in the browser bundle with zero client callers: the async declaration rides the next per-bundle re-bake with no client behaviour change expected.
1000
1002
 
1001
- 256. **Region locale data (`core/locales`) — standalone per-language files, localized `countryName`, additive `getCountries(code)` projection (#50, 2026-07-18, unreleased).** The region generator (`node src/make --target=region --region=en,fr`; CSV `resources/region.csv` = datahub country-codes, `;`-separated) emits ONE STANDALONE `dist/region/<lang>.json` per requested language: the row accumulator is reset per pass (it used to APPEND each language's rows to the previous output, so every `isoShort` was duplicated with the English copy FIRST and `findOne({isoShort})` always matched English), the requireJSON-cached column mapping is cloned per pass (a mutating pass used to leak into the next language's build — a `fr,en` order lost `officialStateName` for en), and rows without an ISO 3166 alpha-2 code are dropped (2 M49 aggregates with empty `isoShort` AND empty `countryName`; `en.json` 251→249). Non-en passes overlay `countryName` from `resources/region.names.<lang>.json` beside the CSV (French ships with the framework) and FAIL FAST when that file is missing for a requested language — never silently shipping English names under a non-en filename. The names files use PLAIN CLDR territory names: the fr `-alt-short` variants are abbreviations (`É.-U.`, `R.-U.`), not display names, so plain deliberately wins — a knowing style asymmetry with the CSV's own English column, which prefers `-alt-short` (`US`, `UK`). `--outdir=<path>` overrides the target dir; `require.main === module` gates the CLI so the module is require-safe/testable. Controller side: `getCountries(code)` honors its documented projection arg ADDITIVELY — a valid string field (`capital`, `continent`, `tld`) is added to each returned row, the 4 historical fields stay untouched, no-arg output is byte-identical, unknown/dotted codes warn and are ignored — and `getLocales()` on a bundle with no locale set degrades to an empty list instead of throwing. Composition: the per-request negotiated `req.culture` selects which language's region set a request sees through the setOptions locale bridge (#B100 guarded fallback to the bundle default then `en` when the resolved language has no region file), so an `Accept-Language` flip changes `countryName` per request — warm cached routes included (#B84: the cached fast-path re-negotiates). Region files are read ONCE at boot (`core/locales/index.js` loads ALL `dist/region/*.json` onto the gina context) — regenerated data needs a bundle restart; dev hot-reload does not deliver it.
1003
+ 256. **Region locale data (`core/locales`) — standalone per-language files, localized `countryName`, additive `getCountries(code)` projection (#50, 2026-07-18, unreleased).** The region generator (`node src/make --target=region --region=en,fr`; CSV `resources/region.csv` = datahub country-codes, `;`-separated) emits ONE STANDALONE `dist/region/<lang>.json` per requested language: the row accumulator is reset per pass (it used to APPEND each language's rows to the previous output, so every `isoShort` was duplicated with the English copy FIRST and `findOne({isoShort})` always matched English), the requireJSON-cached column mapping is cloned per pass (a mutating pass used to leak into the next language's build — a `fr,en` order lost `officialStateName` for en), and rows without an ISO 3166 alpha-2 code are dropped (2 M49 aggregates with empty `isoShort` AND empty `countryName`; `en.json` 251→249). Non-en passes overlay `countryName` from `resources/region.names.<lang>.json` beside the CSV (French ships with the framework) and FAIL FAST when that file is missing for a requested language — never silently shipping English names under a non-en filename. The names files use PLAIN CLDR territory names: the fr `-alt-short` variants are abbreviations (`É.-U.`, `R.-U.`), not display names, so plain deliberately wins — a knowing style asymmetry with the CSV's own English column, which prefers `-alt-short` (`US`, `UK`). `--outdir=<path>` overrides the target dir; `require.main === module` gates the CLI so the module is require-safe/testable. Controller side: `getCountries(code)` honors its documented projection arg ADDITIVELY — a valid string field (`capital`, `continent`, `tld`) is added to each returned row, the 4 historical fields stay untouched, no-arg output is byte-identical, unknown/dotted codes warn and are ignored — and `getLocales()` on a bundle with no locale set degrades to an empty list instead of throwing. Composition: the per-request negotiated `req.culture` selects which language's region set a request sees through the setOptions locale bridge (#B100 guarded fallback to the bundle default then `en` when the resolved language has no region file), so an `Accept-Language` flip changes `countryName` per request — warm cached routes included (#B84: the cached fast-path re-negotiates). Region files are read ONCE at boot (`core/locales/index.js` loads ALL `dist/region/*.json` onto the gina context) — regenerated data needs a bundle restart; dev hot-reload does not deliver it. **#B101 (2026-07-20) completes the bridge's last dead leg:** the setOptions country lookup filtered on a `short` key the rows never carried, so `page.view.locale` was ALWAYS `{}` (+ the date stamp) with a country code present — and an arbitrary first record without one (an undefined-valued filter key serializes away and match-alls). Now `findOne({ isoShort: userCountryCode.toUpperCase() })` (the rows are uppercase; the normalization makes a lowercase Accept-Language country segment resolve too), gated on a non-empty country code so a country-less culture (bare `en`) resolves an explicit `{}` — `page.view.locale` carries the real record (countryName / currency / capital / …) for the first time. Measured zero framework consumers pre-fix (the set site was the object's only reference), so nothing shifts under existing templates — they simply gain a working surface.
1002
1004
 
1003
- 257. **FormValidator #B127/#B128/#B129 (2026-07-19, ride the next cut) — numbered `is` aliases enforce, injected forms resolve their declared rule, `_case_` boolean coercion reads the case value.** (1) Numbered `is` aliases (`is0`, `is1`, … — multiple `is` conditions per field) were NEVER installed: the per-rule function typecheck `continue`d on exactly the undefined state the lazy installer required, silently skipping any `is<N>` key on client AND server. They now install (anchored `/^is\d+$/`) with a DISTINCT error key per alias on BOTH sides (client via the `window._currentValidatorAlias` handshake, server via a Node-`global` alias-root — key parity, both-fail → both keys present; previously the shared server key let a later PASSING alias erase an earlier FAILING alias's error — a silent bypass). ⚠️ Enforcement-tightening: `is<N>` rules that silently skipped START ENFORCING at pickup — sweep rule JSONs for `is<N>` keys before upgrading. Also fixed alongside: the server auto path no longer crashes on a `$`-bearing rule set (`$fields` null-guard), so server-side cross-field `$` conditions work; the `is` grammar remains ONE binary comparison (`=== !== == != < > <= >=`), no `&&` compounds, failing loudly with a warn. (2) `validateFormById(id)` (the popin/injected-form bind path) resolved the rule by FORM ID only — the `data-gina-form-rule` attribute read was unreachable — so a form injected after boot bound `{}` rules and live-check was stamped `"false"` while submit resolved the same attribute fine; the branch is attribute-first now (the id-derived name stays the fallback for attribute-less forms whose id names the rule). Live-check gate precedence: an AUTHOR-set `data-gina-form-live-check-enabled` always wins; the gate decides only when the attribute is absent (rules bound → true, none → false). (3) The cross-field `_case_` scan coerced the WRONG variable (the field being validated instead of the case value): a boolean `case: false` never matched a case field's raw "false" DOM string in single-element/live-check passes, and an outer field valued "true"/"false" clobbered string case matching for its pass. The case value itself now coerces (unconditional, matching the direct-case site's semantics) — declare boolean cases as JSON booleans; `case` values written as the strings "true"/"false" coerce to booleans consistently across sites. Worth knowing: a MATCHING case application replaces that field's rule set in the bound form's rules store persistently for the page, and there are NO standalone `maxLength`/`minLength` engine rules — length constraints are `isString`/`isNumber`/`isInteger` parameters; unknown rule keys are silently skipped.
1005
+ 257. **FormValidator #B127/#B128/#B129 (2026-07-19, ride the next cut) — numbered `is` aliases enforce, injected forms resolve their declared rule, `_case_` boolean coercion reads the case value.** (1) Numbered `is` aliases (`is0`, `is1`, … — multiple `is` conditions per field) were NEVER installed: the per-rule function typecheck `continue`d on exactly the undefined state the lazy installer required, silently skipping any `is<N>` key on client AND server. They now install (anchored `/^is\d+$/`) with a DISTINCT error key per alias on BOTH sides (client via the `window._currentValidatorAlias` handshake, server via a Node-`global` alias-root — key parity, both-fail → both keys present; previously the shared server key let a later PASSING alias erase an earlier FAILING alias's error — a silent bypass). ⚠️ Enforcement-tightening: `is<N>` rules that silently skipped START ENFORCING at pickup — sweep rule JSONs for `is<N>` keys before upgrading. Also fixed alongside: the server auto path no longer crashes on a `$`-bearing rule set (`$fields` null-guard), so server-side cross-field `$` conditions work; the `is` grammar remains ONE binary comparison (`=== !== == != < > <= >=`), no `&&` compounds, failing loudly with a warn. (2) `validateFormById(id)` (the popin/injected-form bind path) resolved the rule by FORM ID only — the `data-gina-form-rule` attribute read was unreachable — so a form injected after boot bound `{}` rules and live-check was stamped `"false"` while submit resolved the same attribute fine; the branch is attribute-first now (the id-derived name stays the fallback for attribute-less forms whose id names the rule). Live-check gate precedence: an AUTHOR-set `data-gina-form-live-check-enabled` always wins; the gate decides only when the attribute is absent (rules bound → true, none → false). (3) The cross-field `_case_` scan coerced the WRONG variable (the field being validated instead of the case value): a boolean `case: false` never matched a case field's raw "false" DOM string in single-element/live-check passes, and an outer field valued "true"/"false" clobbered string case matching for its pass. The case value itself now coerces (unconditional, matching the direct-case site's semantics) — declare boolean cases as JSON booleans; `case` values written as the strings "true"/"false" coerce to booleans consistently across sites. Worth knowing: a MATCHING case application replaces that field's rule set in the bound form's rules store persistently for the page, and there are NO standalone `maxLength`/`minLength` engine rules — length constraints are `isString`/`isNumber`/`isInteger` parameters; unknown rule keys are silently skipped. **#B138 follow-up (2026-07-20, rides the next cut):** #B127's enforcement exposed a pre-existing alias-handshake collapse — the shared `_currentValidatorAlias` slot was armed ONCE at install (the installer is gated once-per-instance) while `is()` consumes it with a delete on every call, so any RE-application against the same instance (a `conditions`/`_case_` re-evaluation, `forEachField` recursion) collapsed every numbered rule onto the bare key `is`, where the LAST-DECLARED rule overwrote its siblings and its message rendered TWICE (its own key + the collapsed key — the error-display loop has no message dedup; the digit is irrelevant — `is0` was spared only by declaration order). The alias wrapper now re-arms the slot immediately before every delegation, so `is<N>` keys stay distinct on every application; a bare `is` key never accompanies numbered aliases. Browser-bundled → consumers re-bake.
1004
1006
 
1005
1007
  258. **CSP useNonce × server cache (#B130, 2026-07-19, rides the next cut) — the bootstrap-script nonce is render-time, and cache hits re-mint.** With `Csp({useNonce:true})` + `server.cache.enable:true`, the framework-injected onGinaLoaded bootstrap `<script>` used to carry a nonce frozen at first compile (baked into the per-view compiled-template cache AND the persisted layout-cache file, which is only re-primed when missing), while the middleware minted a fresh header nonce per request — so header != markup on every later response of a cached route (misses included), breaking enforce-mode CSP. Now: (1) the loader injection is a swig conditional evaluated per execute against `page.cspNonce` (assigned pre-execute on both the compiled-cache-hit and compile branches), so cached compiled templates are nonce-agnostic; (2) stale layout-cache files written by pre-fix builds are normalized in place on the next compile (anchored on the loader's own comment-wrapper idiom + the dev Inspector script openers; idempotent; app-authored tags untouched); (3) output-cache HITS mint fresh per response — both engines' serve paths rewrite the stored CSP header (enforce and report-only) and swap the old nonce values in the stored body (exact-string split/join, base64-safe) without ever mutating the stored entry; the isaac fs read-back buffers instead of streaming only when a re-nonce applies. Verify on a live route: header nonce == every markup nonce AND rotating across responses on miss + hit. Dev/cacheless was never affected (layout re-primed every request).
1006
1008
 
@@ -1011,3 +1013,11 @@ Dev-mode query instrumentation captures every database query tied to the current
1011
1013
  261. **FormValidator autocomplete interception + live-check stale-error clear (#B134/#B135/#B136).** The Safari-autocomplete keydown interception (fields with autocomplete="off" on a live-check form: preventDefault + programmatic value rebuild behind a transient readonly) now (a) bails on modifier chords — e.metaKey/e.ctrlKey returns BEFORE preventDefault so the native select-all/copy/paste/cut/undo defaults run; pre-fix Cmd+A typed the chord letter into the field and keyboard paste was dead (execCommand("paste") is inert in unprivileged web content; the whole chord-case block is commented out, incl. the undo case that wiped input back to defaultValue) — and (b) gates on REAL Safari only (/safari/i && !/chrom(e|ium)/i): every Chromium UA carries the Safari/537.36 token, so the workaround ran on Chrome/Edge/Brave where it was never intended; WebKit-on-iOS browsers (CriOS/FxiOS) stay matched by design. And (c) the live-check whole-form pass, when it turns VALID, now clears every previously-errored field' rendered error in BOTH copies (the input/checkbox/radio processEvent pass and updateSelect') instead of leaving a stale blocking-error paragraph beside the re-enabled submit trigger — the old clear branch was gated on the stored errors map being ALREADY empty and cleared only the touched field; the pass still never renders NEW errors on untouched fields. All three are browser-bundled (dist rebuilt). Tests: validator-autocomplete-interception.test.js + validator-livecheck-stale-error-clear.test.js — extracted-real-bytes execution (brace-walked handler + branch blocks, a real-UA matrix) with red-first dist pins (Closure De-Morgans the chord bail and folds the clear loop into a brace-less for-in, so minified pins target property-name shapes, never var names).
1012
1014
 
1013
1015
  262. **Merged-process cross-bundle routing clobber (#B137).** In a merged-process project (several bundles sharing ONE port — `isStandalone` stays true and one process serves the project), `Env.getConf`'s merged branch permanently reassigned the TARGET bundle's `content.routing` to the STARTING app's table (a reference assignment surviving for the process lifetime, a 2015 single-table-era fossil). Under per-bundle `rule@bundle` keying the starting app's table cannot hold a sibling's keys, so the FIRST cross-bundle getUrl both inflicted the clobber and failed: every cross-bundle link rendered the literal `404:[<METHOD>]<rule>@<bundle>` marker (the not-found message betrays it — the sibling "holds N rules" where N is the STARTING app's count), and merged-mode inbound statics dispatch (which resolves a statics-prefix-matched sibling's table through the same slot) could match requests against the wrong bundle's table. Fixed by dropping the reassignment: each bundle keeps its own table (the hostname share stays — same host:port in merged mode by definition); the merged view of all bundles' rules lives in the global `envConf.routing`. Distinct-port projects always took the clean branch and were never affected; single-bundle projects saw only a benign self-assign. Server-side only — no browser-bundle rebuild.
1016
+
1017
+ 263. **Multipart binary-upload integrity — a multipart body must stay RAW end-to-end (#B103, 0.5.22-alpha.2).** Uploaded file bytes were string-decoded at TWO layers: the request prologue's unconditional `request.setEncoding(<conf.encoding>)` utf8-decoded the whole multipart stream BEFORE busboy parsed it (invalid sequences → U+FFFD, re-encoded 1.5–2x larger), and the per-file write pipeline round-tripped every chunk through `chunk.toString()` plus a charCode-mod-256 re-encoder, shrinking/mutating the payload chunk-boundary-dependently and making `req.files[].size` a UTF-16 char count. Pure-ASCII payloads survive both layers byte-identical — which is why text uploads always worked and the corruption stayed hidden; real binaries (images, PDFs, archives — a PNG's 0x89 magic byte landed as 0xFD) corrupted on every native multipart client (browser FormData, curl -F, hand-built SDK bodies alike). Fixed by computing `request.isMultipart` ONCE at the request prologue, gating the request-stream decode on NOT-multipart (a multipart body reaches busboy as raw Buffers — its documented input; the decode remains for the text-body branches, which accumulate `request.body` as text), and passing write-pipeline chunks through verbatim while counting BYTES, so `req.files[].size` is the real on-disk size. Rule: never `setEncoding` a stream that carries binary payloads, and any byte-counting Transform must count `chunk.length`, never a decoded string's length. Tests: `test/core/upload-binary-integrity.test.js` (comment-stripped source pins red-first-validated against the pre-fix blob, extracted-live-body identity, frozen pre-fix subtract controls). Server-side only — no browser-bundle rebuild; running bundles pick it up at restart.
1018
+
1019
+ 264. **FormValidator `query` rule — the async result path is blanket-guarded; a throw can never hang the submit pass (#B87, 0.5.22-alpha.2).** The `query` rule's XHR result lands asynchronously: by processing time the form may be unbound or the field detached (e.g. a popin closed mid-flight), and the response body is backend-controlled — any throw while processing it (a detached target's null `.form`, a malformed JSON body under a JSON content-type, a boolean checkbox value hitting the unconditional `.toLowerCase()`) left `asyncCompleted.<id>` unfired, and the submit path's async waiter hung for the whole pass (the pre-existing no-op `catch (err) { throw err; }` in `xhr.onload` rethrew instead of releasing). Fixed defensively end-to-end: the result handler is a thin guarded wrapper (`onResult` delegating to `processQueryResult`) whose catch routes to `releaseQueryWaiter` — warn + release the waiter with the field state as-is (fail-open by design: the query verdict is unknown and the server re-validates on submit) — `xhr.onload`'s catch and the now-wrapped `xhr.onerror` route to the same release, the query value normalisation lowercases only strings, and `compileError()` tolerates a non-string error (returned verbatim — nothing to compile; its only caller is string-gated, so the guard is the function's own contract, and a non-string label downstream hits the established fail-soft that degrades to the English default with a warn). The release helper is itself try-guarded (a catch handler must never throw) and names the field in its warn. Browser-bundled (form-validator.js) — consumers pick it up at their next bundle re-bake.
1020
+
1021
+ 265. **npm refuses `config get prefix` whenever the RESOLVED VALUE trips its redactor — a UUID-shaped path segment is enough — killing any install script that probes it unguarded (#B126, fixed 2026-07-20: both gina install scripts guard the probe).** npm's `config get` gates every read on isPrivate(key, value) = protected-key OR redact(value) !== value, so a prefix like `/tmp/<uuid>/x` (CI sandboxes, generated workspace dirs) makes `npm config get prefix` exit 1 with "The prefix option is protected, and cannot be retrieved in this way" — measured on npm 10.9.8 / 11.6.2 / 11.18.0 / 12.0.1 (every current generation refuses; plain-path controls all pass), and the option's SOURCE (flag, env, npmrc) is irrelevant — only the VALUE matters. A consumer datapoint had framed this as "env-sourced protected reads, npm 11.6.2 only, 11.17 unaffected"; both axes were artifacts of WHICH PATHS each version happened to be tested with. `script/pre_install.js` and `script/post_install.js` both ran the probe unguarded at configure() start, so `npm install -g --prefix=<such-a-path> gina` died in pre_install (reproduced end-to-end in a real -g --prefix lifecycle, exact field error; fixing only one script would move the crash to the other). Fix: try/catch around the probe in BOTH scripts, falling back to the lifecycle-exported `npm_config_prefix` (npm exports the effective prefix to script children — measured present in the lifecycle env) then the node-derived default prefix (`path.resolve(process.execPath, '..', '..')`). Reusable rule: any script probing npm config must treat `npm config get <key>` as fallible — the refusal depends on the runtime VALUE, not the key list or the npm version. Install-side only — the fix ships inside the tarball, so pickup is the next cut; older tarballs cannot be retro-fixed. Tests: test/lib/pre-install-prefix-probe.test.js (probe-inside-try + fallback-chain source pins on BOTH scripts; a deterministic refusing-shim replica; the pre-fix subtract reproducing the crash).
1022
+
1023
+ 266. **The link plugin's HTML-callback attributes (`data-gina-link-event-on-success` / `data-gina-link-event-on-error`) were dead AND deadly — carrying either killed the link's XHR with an uncaught ReferenceError before xhr.open (#B141, fixed 2026-07-21).** Three stacked layers, all live-verified in a real browser render (real clicks; the attribute-less control link on the same page fetched normally both runs): (1) SCOPE — the only live `listenToXhrEvents` definition sat INSIDE `on()` in utils/events.js (a brace slip; the adjacent "Nothing can be added after on()" comment shows it was meant to follow on() as a top-level shim global like handleXhr), so link/main.js's call resolved nothing and threw; (2) ARITY — the call passed one arg, so a reachable definition would read `data-gina-undefined-event-on-*` and silently register nothing; (3) PLUMBING — handleXhr fired the `.hlink` events named by the link INSTANCE id and dispatched them on document, while registration binds the PER-LINK id on the anchor element — name and target could never match. Fix: the definition is a top-level global in utils/events.js (body byte-preserved incl. the function-call-shape refusal warn), link/main.js passes ($link, 'link') and drops its stale commented-out local copy, and the six .hlink triggers address $link.target + $link.id. Deliberately untouched: the plain programmatic channel (gina.link.on('success'/'error') — instance id + document on BOTH sides, always aligned) and the forms' .hform path (the form validator is self-contained and coherent). Registration is per-link idempotent (gina.events dedup by event name). Browser-bundled — consumers re-bake at pickup. Tests: link-xhr-events.test.js (18 — src+dist pins incl. the column-0 top-level scope invariant, extracted-real-definition behaviour incl. the one-arg pre-fix subtract, registration/trigger alignment replica incl. the instance-id-mismatch subtract; all discriminators red-first-validated against the pre-fix blobs).
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "gina",
3
- "version": "0.5.21",
4
- "description": "Node.js MVC framework with built-in HTTP/2, multi-bundle architecture, and scope-based data isolation — no Express dependency",
3
+ "version": "0.5.22",
4
+ "description": "MVC framework for Node.js and Bun with built-in HTTP/2, multi-bundle architecture, and scope-based data isolation — no Express dependency",
5
5
  "keywords": [
6
6
  "nodejs",
7
+ "bun",
7
8
  "framework",
8
9
  "mvc",
9
10
  "http2",
10
11
  "rest-api",
12
+ "openapi",
13
+ "websocket",
11
14
  "full-stack",
12
15
  "server-side-rendering",
13
16
  "event-driven",
@@ -59,7 +62,7 @@
59
62
  }
60
63
  ],
61
64
  "copyright": "Copyright (c) 2009-2026 Rhinostone <contact@gina.io>",
62
- "engine": {
65
+ "engines": {
63
66
  "node": ">= 22 <27",
64
67
  "bun": ">= 1.2"
65
68
  },
@@ -73,12 +76,12 @@
73
76
  "gina-container": "bin/gina-container",
74
77
  "gina-init": "bin/gina-init"
75
78
  },
76
- "main": "./framework/v0.5.21/core/gna",
79
+ "main": "./framework/v0.5.22/core/gna",
77
80
  "exports": {
78
81
  ".": {
79
82
  "types": "./types/index.d.ts",
80
83
  "import": "./index.mjs",
81
- "require": "./framework/v0.5.21/core/gna.js"
84
+ "require": "./framework/v0.5.22/core/gna.js"
82
85
  },
83
86
  "./gna": {
84
87
  "types": "./types/gna.d.ts",
@@ -33,6 +33,35 @@
33
33
  }
34
34
  }
35
35
  },
36
+ "i18n": {
37
+ "type": "object",
38
+ "description": "Runtime i18n configuration for the per-bundle message catalogs (bundle/locales/<culture>.json). All keys are read from the bundle's merged settings.",
39
+ "additionalProperties": false,
40
+ "properties": {
41
+ "cookieName": {
42
+ "type": ["string", "null"],
43
+ "description": "Locale-persistence cookie name read by the per-request locale negotiation (honoured since 0.5.16). null disables cookie-based negotiation; absent or empty keeps \"gina_culture\".",
44
+ "default": "gina_culture"
45
+ },
46
+ "devMissingKey": {
47
+ "type": ["string", "null"],
48
+ "description": "Dev-mode prefix marker for missing catalog keys (only applied when NODE_ENV_IS_DEV is \"true\"). null disables the marker.",
49
+ "default": "[MISSING]"
50
+ },
51
+ "fallbackChain": {
52
+ "type": ["array", "null"],
53
+ "items": { "type": "string" },
54
+ "description": "Optional override of the default catalog-lookup fallback chain (specific culture, then base language, then settings.region.culture, then GINA_CULTURE, then \"en\"). null uses the default.",
55
+ "default": null
56
+ },
57
+ "cultures": {
58
+ "type": ["array", "null"],
59
+ "items": { "type": "string" },
60
+ "description": "Explicit culture allowlist for the user-signal negotiation steps (URL prefix, cookie, Accept-Language), honoured since 0.5.22: a non-empty array constrains matching to the listed cultures (staged rollouts). null or [] derives from the bundle's loaded catalogs. The bundle-default step (settings.region.culture) is never constrained.",
61
+ "default": null
62
+ }
63
+ }
64
+ },
36
65
  "server": {
37
66
  "type": "object",
38
67
  "description": "HTTP server engine and protocol configuration.",
@@ -125,7 +125,23 @@ function PostInstall() {
125
125
  self.isResetNeeded = ( typeof(process.env.npm_config_reset) != 'undefined' && /^(true|false)$/i.test(process.env.npm_config_reset) )
126
126
  ? (/^true$/i.test(process.env.npm_config_reset) ? true: false)
127
127
  : false;
128
- self.defaultPrefix = execSync('$(which npm) config get prefix --quiet').toString().replace(/\n$/g, '');
128
+ // #B126 — `npm config get prefix` REFUSES the read (exit 1: "The
129
+ // prefix option is protected, and cannot be retrieved in this way")
130
+ // whenever the RESOLVED VALUE trips npm's redactor (npm config.js
131
+ // isPrivate(): redact(value) !== value — e.g. a path containing a
132
+ // UUID-shaped segment). Measured on npm 10.9.8 / 11.6.2 / 11.18.0 /
133
+ // 12.0.1 — every current generation; the option's SOURCE (flag, env,
134
+ // npmrc) is irrelevant. Unguarded, the refusal killed the install at
135
+ // whichever lifecycle phase ran the probe first. npm exports the
136
+ // effective prefix to the lifecycle env, so fall back to it; last
137
+ // resort: the node-derived default prefix.
138
+ try {
139
+ self.defaultPrefix = execSync('$(which npm) config get prefix --quiet').toString().replace(/\n$/g, '');
140
+ } catch (probeErr) {
141
+ self.defaultPrefix = process.env.npm_config_prefix
142
+ || require('path').resolve(process.execPath, '..', '..');
143
+ console.warn('`npm config get prefix` was refused (protected/redacted value); falling back to `'+ self.defaultPrefix +'`');
144
+ }
129
145
  // var pkg = null;
130
146
  // try {
131
147
  // if (self.isGlobalInstall) {
@@ -205,9 +221,9 @@ function PostInstall() {
205
221
  "name": ""+ projectName,
206
222
  "version": "0.0.1",
207
223
  "description": projectName+ " is a nice project !",
208
- "engine": [
209
- "node >=" + process.version.substring(1)
210
- ]
224
+ "engines": {
225
+ "node": ">=" + process.version.substring(1)
226
+ }
211
227
  };
212
228
  console.warn('No `package.json` found for your project, creating one to avoid install exceptions');
213
229
  // Inlined to avoid loading the framework lib registry at install time.
@@ -75,7 +75,22 @@ function PreInstall() {
75
75
  self.isResetNeeded = ( typeof(process.env.npm_config_reset) != 'undefined' && /^(true|false)$/i.test(process.env.npm_config_reset) )
76
76
  ? (/^true$/i.test(process.env.npm_config_reset) ? true: false)
77
77
  : false;
78
- self.defaultPrefix = execSync('$(which npm) config get prefix --quiet').toString().replace(/\n$/g, '');
78
+ // #B126 — `npm config get prefix` REFUSES the read (exit 1: "The
79
+ // prefix option is protected, and cannot be retrieved in this way")
80
+ // whenever the RESOLVED VALUE trips npm's redactor (npm config.js
81
+ // isPrivate(): redact(value) !== value — e.g. a path containing a
82
+ // UUID-shaped segment). Measured on npm 10.9.8 / 11.6.2 / 11.18.0 /
83
+ // 12.0.1 — every current generation; the option's SOURCE (flag, env,
84
+ // npmrc) is irrelevant. Unguarded, the refusal killed the whole
85
+ // install. npm exports the effective prefix to the lifecycle env, so
86
+ // fall back to it; last resort: the node-derived default prefix.
87
+ try {
88
+ self.defaultPrefix = execSync('$(which npm) config get prefix --quiet').toString().replace(/\n$/g, '');
89
+ } catch (probeErr) {
90
+ self.defaultPrefix = process.env.npm_config_prefix
91
+ || require('path').resolve(process.execPath, '..', '..');
92
+ console.warn('`npm config get prefix` was refused (protected/redacted value); falling back to `'+ self.defaultPrefix +'`');
93
+ }
79
94
 
80
95
 
81
96
  // `process.env.npm_config_prefix` is only retrieved on `npm install gina`
@@ -1 +0,0 @@
1
- 0.5.21