gina 0.5.26 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (560) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +34 -22
  3. package/ROADMAP.md +43 -16
  4. package/bin/cli +12 -1
  5. package/bin/gina-init +15 -1
  6. package/framework/v0.6.0/VERSION +1 -0
  7. package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.js +36 -1
  8. package/framework/v0.6.0/core/asset/plugin/dist/vendor/gina/js/gina.min.js +601 -0
  9. package/framework/v0.6.0/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
  10. package/framework/v0.6.0/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
  11. package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/session-store.v3.js +52 -84
  12. package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/session-store.v4.js +58 -84
  13. package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/session-store.js +5 -2
  14. package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/session-store.js +5 -2
  15. package/framework/{v0.5.26 → v0.6.0}/core/connectors/scylladb/lib/session-store.js +5 -2
  16. package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/lib/session-store.js +17 -3
  17. package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/session/src/main.js +142 -9
  18. package/framework/{v0.5.26 → v0.6.0}/core/router.js +101 -11
  19. package/framework/{v0.5.26 → v0.6.0}/core/server.js +91 -1
  20. package/framework/{v0.5.26 → v0.6.0}/core/template/conf/settings.json +3 -0
  21. package/framework/v0.6.0/lib/audit/src/main.js +916 -0
  22. package/framework/v0.6.0/lib/authn/package.json +7 -0
  23. package/framework/v0.6.0/lib/authn/src/lockout.js +615 -0
  24. package/framework/v0.6.0/lib/authn/src/main.js +899 -0
  25. package/framework/v0.6.0/lib/authn/src/totp.js +418 -0
  26. package/framework/v0.6.0/lib/cmd/audit/arguments.json +5 -0
  27. package/framework/v0.6.0/lib/cmd/audit/help.txt +50 -0
  28. package/framework/v0.6.0/lib/cmd/audit/verify.js +294 -0
  29. package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/init.js +11 -0
  30. package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/tail.js +5 -1
  31. package/framework/{v0.5.26 → v0.6.0}/lib/cmd/gina.1.md +1 -0
  32. package/framework/{v0.5.26 → v0.6.0}/lib/index.js +13 -0
  33. package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/file/index.js +11 -1
  34. package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/mq/speaker.js +8 -1
  35. package/framework/v0.6.0/lib/net-locality/package.json +17 -0
  36. package/framework/v0.6.0/lib/net-locality/src/main.js +174 -0
  37. package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-filters/src/main.js +13 -0
  38. package/framework/{v0.5.26 → v0.6.0}/lib/routing/src/main.js +36 -1
  39. package/framework/{v0.5.26 → v0.6.0}/lib/swig-filters/src/main.js +13 -0
  40. package/framework/{v0.5.26 → v0.6.0}/package.json +1 -1
  41. package/gna.js +4 -4
  42. package/llms.txt +19 -2
  43. package/package.json +3 -3
  44. package/schema/connectors.json +2 -3
  45. package/schema/settings.json +101 -0
  46. package/types/index.d.ts +4 -0
  47. package/framework/v0.5.26/VERSION +0 -1
  48. package/framework/v0.5.26/core/asset/plugin/dist/vendor/gina/js/gina.min.js +0 -599
  49. package/framework/v0.5.26/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
  50. package/framework/v0.5.26/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
  51. package/framework/v0.5.26/lib/audit/src/main.js +0 -456
  52. /package/framework/{v0.5.26 → v0.6.0}/AUTHORS +0 -0
  53. /package/framework/{v0.5.26 → v0.6.0}/LICENSE +0 -0
  54. /package/framework/{v0.5.26 → v0.6.0}/core/asset/html/nolayout.html +0 -0
  55. /package/framework/{v0.5.26 → v0.6.0}/core/asset/html/static.html +0 -0
  56. /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/android-chrome-192x192.png +0 -0
  57. /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/android-chrome-512x512.png +0 -0
  58. /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/apple-touch-icon.png +0 -0
  59. /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/favicon-16x16.png +0 -0
  60. /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/favicon-32x32.png +0 -0
  61. /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/favicon.ico +0 -0
  62. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/README.md +0 -0
  63. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.css +0 -0
  64. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.js +0 -0
  65. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/beemaster/index.html +0 -0
  66. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/css/gina.min.css +0 -0
  67. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.br +0 -0
  68. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.gz +0 -0
  69. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/html/statusbar.html +0 -0
  70. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.br +0 -0
  71. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.gz +0 -0
  72. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/have_heart_one-webfont.woff2 +0 -0
  73. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/index.html +0 -0
  74. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/inspector.css +0 -0
  75. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/inspector.js +0 -0
  76. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/logo.svg +0 -0
  77. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js +0 -0
  78. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.br +0 -0
  79. /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.gz +0 -0
  80. /package/framework/{v0.5.26 → v0.6.0}/core/config.js +0 -0
  81. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/ai/index.js +0 -0
  82. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/ai/lib/connector.js +0 -0
  83. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/index.js +0 -0
  84. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/connector.js +0 -0
  85. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/connector.v3.js +0 -0
  86. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/connector.v4.js +0 -0
  87. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/n1ql.js +0 -0
  88. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/session-store.js +0 -0
  89. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/index.js +0 -0
  90. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/connector.js +0 -0
  91. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/job-store.js +0 -0
  92. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/pipeline-loader.js +0 -0
  93. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mysql/index.js +0 -0
  94. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mysql/lib/connector.js +0 -0
  95. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/postgresql/index.js +0 -0
  96. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/postgresql/lib/connector.js +0 -0
  97. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/index.js +0 -0
  98. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/connector.js +0 -0
  99. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/job-store.js +0 -0
  100. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/render-cache-store.js +0 -0
  101. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/scylladb/index.js +0 -0
  102. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/scylladb/lib/connector.js +0 -0
  103. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sql-parser.js +0 -0
  104. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/index.js +0 -0
  105. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/lib/connector.js +0 -0
  106. /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/lib/job-store.js +0 -0
  107. /package/framework/{v0.5.26 → v0.6.0}/core/content.encoding +0 -0
  108. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.framework.js +0 -0
  109. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.js +0 -0
  110. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-json.js +0 -0
  111. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-nunjucks-async.js +0 -0
  112. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-nunjucks.js +0 -0
  113. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-stream.js +0 -0
  114. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-swig-async.js +0 -0
  115. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-swig.js +0 -0
  116. /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-v1.js +0 -0
  117. /package/framework/{v0.5.26 → v0.6.0}/core/controller/index.js +0 -0
  118. /package/framework/{v0.5.26 → v0.6.0}/core/controller/inspector-window-emit.js +0 -0
  119. /package/framework/{v0.5.26 → v0.6.0}/core/controller/release-banner.js +0 -0
  120. /package/framework/{v0.5.26 → v0.6.0}/core/dev/index.js +0 -0
  121. /package/framework/{v0.5.26 → v0.6.0}/core/dev/lib/class.js +0 -0
  122. /package/framework/{v0.5.26 → v0.6.0}/core/dev/lib/factory.js +0 -0
  123. /package/framework/{v0.5.26 → v0.6.0}/core/dev/lib/tools.js +0 -0
  124. /package/framework/{v0.5.26 → v0.6.0}/core/gna.js +0 -0
  125. /package/framework/{v0.5.26 → v0.6.0}/core/locales/README.md +0 -0
  126. /package/framework/{v0.5.26 → v0.6.0}/core/locales/currency.json +0 -0
  127. /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/language/en.json +0 -0
  128. /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/language/fr.json +0 -0
  129. /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/region/en.json +0 -0
  130. /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/region/fr.json +0 -0
  131. /package/framework/{v0.5.26 → v0.6.0}/core/locales/index.js +0 -0
  132. /package/framework/{v0.5.26 → v0.6.0}/core/mime.types +0 -0
  133. /package/framework/{v0.5.26 → v0.6.0}/core/model/entity.js +0 -0
  134. /package/framework/{v0.5.26 → v0.6.0}/core/model/index.js +0 -0
  135. /package/framework/{v0.5.26 → v0.6.0}/core/model/template/entityFactory.js +0 -0
  136. /package/framework/{v0.5.26 → v0.6.0}/core/model/template/index.js +0 -0
  137. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/README.md +0 -0
  138. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/index.js +0 -0
  139. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/csrf/README.md +0 -0
  140. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/csrf/package.json +0 -0
  141. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/csrf/src/main.js +0 -0
  142. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/README.md +0 -0
  143. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coep/README.md +0 -0
  144. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coep/package.json +0 -0
  145. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coep/src/main.js +0 -0
  146. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coop/README.md +0 -0
  147. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coop/package.json +0 -0
  148. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coop/src/main.js +0 -0
  149. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/corp/README.md +0 -0
  150. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/corp/package.json +0 -0
  151. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/corp/src/main.js +0 -0
  152. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/csp/README.md +0 -0
  153. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/csp/package.json +0 -0
  154. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/csp/src/main.js +0 -0
  155. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hide-powered-by/README.md +0 -0
  156. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hide-powered-by/package.json +0 -0
  157. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hide-powered-by/src/main.js +0 -0
  158. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hsts/README.md +0 -0
  159. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hsts/package.json +0 -0
  160. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hsts/src/main.js +0 -0
  161. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/origin-agent-cluster/README.md +0 -0
  162. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/origin-agent-cluster/package.json +0 -0
  163. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/origin-agent-cluster/src/main.js +0 -0
  164. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/package.json +0 -0
  165. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/referrer-policy/README.md +0 -0
  166. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/referrer-policy/package.json +0 -0
  167. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/referrer-policy/src/main.js +0 -0
  168. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/src/main.js +0 -0
  169. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-content-type-options/README.md +0 -0
  170. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-content-type-options/package.json +0 -0
  171. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-content-type-options/src/main.js +0 -0
  172. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-dns-prefetch-control/README.md +0 -0
  173. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-dns-prefetch-control/package.json +0 -0
  174. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-dns-prefetch-control/src/main.js +0 -0
  175. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-download-options/README.md +0 -0
  176. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-download-options/package.json +0 -0
  177. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-download-options/src/main.js +0 -0
  178. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-frame-options/README.md +0 -0
  179. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-frame-options/package.json +0 -0
  180. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-frame-options/src/main.js +0 -0
  181. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/README.md +0 -0
  182. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/package.json +0 -0
  183. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/src/main.js +0 -0
  184. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-xss-protection/README.md +0 -0
  185. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-xss-protection/package.json +0 -0
  186. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-xss-protection/src/main.js +0 -0
  187. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/session/README.md +0 -0
  188. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/session/package.json +0 -0
  189. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/README.md +0 -0
  190. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/build.json +0 -0
  191. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/package.json +0 -0
  192. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/src/main.js +0 -0
  193. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/README.md +0 -0
  194. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/build.json +0 -0
  195. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/package.json +0 -0
  196. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/src/form-validator.js +0 -0
  197. /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/src/main.js +0 -0
  198. /package/framework/{v0.5.26 → v0.6.0}/core/server.express.js +0 -0
  199. /package/framework/{v0.5.26 → v0.6.0}/core/server.isaac.js +0 -0
  200. /package/framework/{v0.5.26 → v0.6.0}/core/status.codes +0 -0
  201. /package/framework/{v0.5.26 → v0.6.0}/core/template/_gitignore +0 -0
  202. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/app.json +0 -0
  203. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/connectors.json +0 -0
  204. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/routing.json +0 -0
  205. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/settings.json +0 -0
  206. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/settings.server.json +0 -0
  207. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/templates.json +0 -0
  208. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/watchers.json +0 -0
  209. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/controllers/controller.content.js +0 -0
  210. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/controllers/controller.js +0 -0
  211. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/controllers/setup.js +0 -0
  212. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/index.js +0 -0
  213. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/locales/en.json +0 -0
  214. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_namespace/controllers/controller.js +0 -0
  215. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/css/default.css +0 -0
  216. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/css/home.css +0 -0
  217. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/css/vendor/readme.md +0 -0
  218. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/favicon.ico +0 -0
  219. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/js/components/x-checklist.js +0 -0
  220. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/js/vendor/readme.md +0 -0
  221. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/manifest.webmanifest +0 -0
  222. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/readme.md +0 -0
  223. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/sw.js +0 -0
  224. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/handlers/main.js +0 -0
  225. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/content/homepage.html +0 -0
  226. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/includes/error-msg-noscript.html +0 -0
  227. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/includes/error-msg-outdated-browser.html +0 -0
  228. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/includes/x-checklist.html +0 -0
  229. /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/layouts/main.html +0 -0
  230. /package/framework/{v0.5.26 → v0.6.0}/core/template/command/gina.bat.tpl +0 -0
  231. /package/framework/{v0.5.26 → v0.6.0}/core/template/command/gina.tpl +0 -0
  232. /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/env.json +0 -0
  233. /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/manifest.json +0 -0
  234. /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/package.json +0 -0
  235. /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/statics.json +0 -0
  236. /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/templates.json +0 -0
  237. /package/framework/{v0.5.26 → v0.6.0}/core/template/error/client/json/401.json +0 -0
  238. /package/framework/{v0.5.26 → v0.6.0}/core/template/error/client/json/403.json +0 -0
  239. /package/framework/{v0.5.26 → v0.6.0}/core/template/error/client/json/404.json +0 -0
  240. /package/framework/{v0.5.26 → v0.6.0}/core/template/error/server/html/50x.html +0 -0
  241. /package/framework/{v0.5.26 → v0.6.0}/core/template/error/server/json/500.json +0 -0
  242. /package/framework/{v0.5.26 → v0.6.0}/core/template/error/server/json/503.json +0 -0
  243. /package/framework/{v0.5.26 → v0.6.0}/core/template/extensions/logger/config.json +0 -0
  244. /package/framework/{v0.5.26 → v0.6.0}/helpers/console.js +0 -0
  245. /package/framework/{v0.5.26 → v0.6.0}/helpers/context.js +0 -0
  246. /package/framework/{v0.5.26 → v0.6.0}/helpers/data/LICENSE +0 -0
  247. /package/framework/{v0.5.26 → v0.6.0}/helpers/data/README.md +0 -0
  248. /package/framework/{v0.5.26 → v0.6.0}/helpers/data/package.json +0 -0
  249. /package/framework/{v0.5.26 → v0.6.0}/helpers/data/src/main.js +0 -0
  250. /package/framework/{v0.5.26 → v0.6.0}/helpers/dateFormat.js +0 -0
  251. /package/framework/{v0.5.26 → v0.6.0}/helpers/index.js +0 -0
  252. /package/framework/{v0.5.26 → v0.6.0}/helpers/json/LICENSE +0 -0
  253. /package/framework/{v0.5.26 → v0.6.0}/helpers/json/README.md +0 -0
  254. /package/framework/{v0.5.26 → v0.6.0}/helpers/json/package.json +0 -0
  255. /package/framework/{v0.5.26 → v0.6.0}/helpers/json/src/main.js +0 -0
  256. /package/framework/{v0.5.26 → v0.6.0}/helpers/path.js +0 -0
  257. /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/README.md +0 -0
  258. /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/package.json +0 -0
  259. /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/src/api-error.js +0 -0
  260. /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/src/main.js +0 -0
  261. /package/framework/{v0.5.26 → v0.6.0}/helpers/prototypes.js +0 -0
  262. /package/framework/{v0.5.26 → v0.6.0}/helpers/task.js +0 -0
  263. /package/framework/{v0.5.26 → v0.6.0}/helpers/text.js +0 -0
  264. /package/framework/{v0.5.26 → v0.6.0}/lib/admin/package.json +0 -0
  265. /package/framework/{v0.5.26 → v0.6.0}/lib/admin/src/main.js +0 -0
  266. /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/README.md +0 -0
  267. /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/build.json +0 -0
  268. /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/package.json +0 -0
  269. /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/src/dep/jszip.min.js +0 -0
  270. /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/src/main.js +0 -0
  271. /package/framework/{v0.5.26 → v0.6.0}/lib/async/package.json +0 -0
  272. /package/framework/{v0.5.26 → v0.6.0}/lib/async/src/main.js +0 -0
  273. /package/framework/{v0.5.26 → v0.6.0}/lib/audit/package.json +0 -0
  274. /package/framework/{v0.5.26 → v0.6.0}/lib/audit-store.js +0 -0
  275. /package/framework/{v0.5.26 → v0.6.0}/lib/authz-gate/package.json +0 -0
  276. /package/framework/{v0.5.26 → v0.6.0}/lib/authz-gate/src/main.js +0 -0
  277. /package/framework/{v0.5.26 → v0.6.0}/lib/cache/README.md +0 -0
  278. /package/framework/{v0.5.26 → v0.6.0}/lib/cache/build.json +0 -0
  279. /package/framework/{v0.5.26 → v0.6.0}/lib/cache/package.json +0 -0
  280. /package/framework/{v0.5.26 → v0.6.0}/lib/cache/src/main.js +0 -0
  281. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/aliases.json +0 -0
  282. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/add.js +0 -0
  283. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/arguments.json +0 -0
  284. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/build.js +0 -0
  285. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/copy.js +0 -0
  286. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/cp.js +0 -0
  287. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/help.js +0 -0
  288. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/help.txt +0 -0
  289. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/inc/name-rewrite.js +0 -0
  290. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/list.js +0 -0
  291. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/man.js +0 -0
  292. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/mcp-start.js +0 -0
  293. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/mcp.js +0 -0
  294. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/oas.js +0 -0
  295. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/openapi.js +0 -0
  296. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/remove.js +0 -0
  297. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/rename.js +0 -0
  298. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/restart.js +0 -0
  299. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/rm.js +0 -0
  300. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/start.js +0 -0
  301. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/status.js +0 -0
  302. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/stop.js +0 -0
  303. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/types.js +0 -0
  304. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/arguments.json +0 -0
  305. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/clear.js +0 -0
  306. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/help.txt +0 -0
  307. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/stats.js +0 -0
  308. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/add.js +0 -0
  309. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/arguments.json +0 -0
  310. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/help.js +0 -0
  311. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/help.txt +0 -0
  312. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/infer.js +0 -0
  313. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/list.js +0 -0
  314. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/migrate.js +0 -0
  315. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/models.js +0 -0
  316. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/remove.js +0 -0
  317. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/rm.js +0 -0
  318. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/test.js +0 -0
  319. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/arguments.json +0 -0
  320. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/help.js +0 -0
  321. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/help.txt +0 -0
  322. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/man.js +0 -0
  323. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/ps.js +0 -0
  324. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/stop.js +0 -0
  325. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/add.js +0 -0
  326. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/arguments.json +0 -0
  327. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/help.txt +0 -0
  328. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/args.js +0 -0
  329. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/namespace.js +0 -0
  330. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/reference-rewrite.js +0 -0
  331. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/reference-scan.js +0 -0
  332. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/scaffold.js +0 -0
  333. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/remove.js +0 -0
  334. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/rename.js +0 -0
  335. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/rm.js +0 -0
  336. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/add.js +0 -0
  337. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/get.js +0 -0
  338. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/help.js +0 -0
  339. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/help.txt +0 -0
  340. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/link-dev.js +0 -0
  341. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/list.js +0 -0
  342. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/remove.js +0 -0
  343. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/rm.js +0 -0
  344. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/set.js +0 -0
  345. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/unset.js +0 -0
  346. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/use.js +0 -0
  347. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/add.js +0 -0
  348. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/arguments.json +0 -0
  349. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/build.js +0 -0
  350. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/dot.js +0 -0
  351. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/get.js +0 -0
  352. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/help.js +0 -0
  353. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/help.txt +0 -0
  354. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/link-node-modules.js +0 -0
  355. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/link.js +0 -0
  356. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/list.js +0 -0
  357. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/man.js +0 -0
  358. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/msg.json +0 -0
  359. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/open.js +0 -0
  360. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/remove.js +0 -0
  361. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/reset.js +0 -0
  362. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/restart.js +0 -0
  363. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/set.js +0 -0
  364. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/start.js +0 -0
  365. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/status.js +0 -0
  366. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/stop.js +0 -0
  367. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/update.js +0 -0
  368. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/version.js +0 -0
  369. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/gina-dev.1.md +0 -0
  370. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/gina-framework.1.md +0 -0
  371. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/helper.js +0 -0
  372. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/add.js +0 -0
  373. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/arguments.json +0 -0
  374. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/export.js +0 -0
  375. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/help.js +0 -0
  376. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/help.txt +0 -0
  377. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/import.js +0 -0
  378. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/scan.js +0 -0
  379. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/_host.js +0 -0
  380. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/arguments.json +0 -0
  381. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/build.js +0 -0
  382. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/help.js +0 -0
  383. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/help.txt +0 -0
  384. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/list.js +0 -0
  385. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/man.js +0 -0
  386. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/rm.js +0 -0
  387. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/run.js +0 -0
  388. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/index.js +0 -0
  389. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/inspector/help.js +0 -0
  390. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/inspector/help.txt +0 -0
  391. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/inspector/open.js +0 -0
  392. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/man-render.js +0 -0
  393. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/arguments.json +0 -0
  394. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/help.js +0 -0
  395. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/help.txt +0 -0
  396. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/kill.js +0 -0
  397. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/list.js +0 -0
  398. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/msg.json +0 -0
  399. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/help.js +0 -0
  400. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/help.txt +0 -0
  401. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/inc/scan.js +0 -0
  402. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/list.js +0 -0
  403. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/reset.js +0 -0
  404. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/set.js +0 -0
  405. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/add.js +0 -0
  406. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/arguments.json +0 -0
  407. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/backup.js +0 -0
  408. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/build.js +0 -0
  409. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/help.js +0 -0
  410. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/help.txt +0 -0
  411. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/import.js +0 -0
  412. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/list.js +0 -0
  413. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/man.js +0 -0
  414. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/move.js +0 -0
  415. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/remove.js +0 -0
  416. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/rename.js +0 -0
  417. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/restart.js +0 -0
  418. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/restore.js +0 -0
  419. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/rm.js +0 -0
  420. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/start.js +0 -0
  421. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/status.js +0 -0
  422. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/stop.js +0 -0
  423. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/arguments.json +0 -0
  424. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/help.js +0 -0
  425. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/help.txt +0 -0
  426. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/list.js +0 -0
  427. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/remove.js +0 -0
  428. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/set.js +0 -0
  429. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/add.js +0 -0
  430. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/help.js +0 -0
  431. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/help.txt +0 -0
  432. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/link-local.js +0 -0
  433. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/link-production.js +0 -0
  434. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/list.js +0 -0
  435. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/remove.js +0 -0
  436. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/rm.js +0 -0
  437. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/use.js +0 -0
  438. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/arguments.json +0 -0
  439. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/check.js +0 -0
  440. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/help.js +0 -0
  441. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/help.txt +0 -0
  442. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/scan.js +0 -0
  443. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/help.js +0 -0
  444. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/help.txt +0 -0
  445. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/list.js +0 -0
  446. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/man.js +0 -0
  447. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/start.js +0 -0
  448. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/view/add.js +0 -0
  449. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd-status-format/package.json +0 -0
  450. /package/framework/{v0.5.26 → v0.6.0}/lib/cmd-status-format/src/main.js +0 -0
  451. /package/framework/{v0.5.26 → v0.6.0}/lib/collection/README.md +0 -0
  452. /package/framework/{v0.5.26 → v0.6.0}/lib/collection/build.json +0 -0
  453. /package/framework/{v0.5.26 → v0.6.0}/lib/collection/package.json +0 -0
  454. /package/framework/{v0.5.26 → v0.6.0}/lib/collection/src/main.js +0 -0
  455. /package/framework/{v0.5.26 → v0.6.0}/lib/config.js +0 -0
  456. /package/framework/{v0.5.26 → v0.6.0}/lib/connector-config/package.json +0 -0
  457. /package/framework/{v0.5.26 → v0.6.0}/lib/connector-config/src/main.js +0 -0
  458. /package/framework/{v0.5.26 → v0.6.0}/lib/connector-error/package.json +0 -0
  459. /package/framework/{v0.5.26 → v0.6.0}/lib/connector-error/src/main.js +0 -0
  460. /package/framework/{v0.5.26 → v0.6.0}/lib/connector-registry/package.json +0 -0
  461. /package/framework/{v0.5.26 → v0.6.0}/lib/connector-registry/src/main.js +0 -0
  462. /package/framework/{v0.5.26 → v0.6.0}/lib/cron/README.md +0 -0
  463. /package/framework/{v0.5.26 → v0.6.0}/lib/cron/package.json +0 -0
  464. /package/framework/{v0.5.26 → v0.6.0}/lib/cron/src/main.js +0 -0
  465. /package/framework/{v0.5.26 → v0.6.0}/lib/domain/LICENSE +0 -0
  466. /package/framework/{v0.5.26 → v0.6.0}/lib/domain/README.md +0 -0
  467. /package/framework/{v0.5.26 → v0.6.0}/lib/domain/package.json +0 -0
  468. /package/framework/{v0.5.26 → v0.6.0}/lib/domain/src/main.js +0 -0
  469. /package/framework/{v0.5.26 → v0.6.0}/lib/dto/package.json +0 -0
  470. /package/framework/{v0.5.26 → v0.6.0}/lib/dto/src/main.js +0 -0
  471. /package/framework/{v0.5.26 → v0.6.0}/lib/dto-pipe/package.json +0 -0
  472. /package/framework/{v0.5.26 → v0.6.0}/lib/dto-pipe/src/main.js +0 -0
  473. /package/framework/{v0.5.26 → v0.6.0}/lib/dto-types/package.json +0 -0
  474. /package/framework/{v0.5.26 → v0.6.0}/lib/dto-types/src/main.js +0 -0
  475. /package/framework/{v0.5.26 → v0.6.0}/lib/generator/index.js +0 -0
  476. /package/framework/{v0.5.26 → v0.6.0}/lib/i18n/package.json +0 -0
  477. /package/framework/{v0.5.26 → v0.6.0}/lib/i18n/src/main.js +0 -0
  478. /package/framework/{v0.5.26 → v0.6.0}/lib/image-build/package.json +0 -0
  479. /package/framework/{v0.5.26 → v0.6.0}/lib/image-build/src/main.js +0 -0
  480. /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/LICENSE +0 -0
  481. /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/README.md +0 -0
  482. /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/package.json +0 -0
  483. /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/src/main.js +0 -0
  484. /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-events/package.json +0 -0
  485. /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-events/src/main.js +0 -0
  486. /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-redact/package.json +0 -0
  487. /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-redact/src/main.js +0 -0
  488. /package/framework/{v0.5.26 → v0.6.0}/lib/instrument/package.json +0 -0
  489. /package/framework/{v0.5.26 → v0.6.0}/lib/instrument/src/main.js +0 -0
  490. /package/framework/{v0.5.26 → v0.6.0}/lib/job/package.json +0 -0
  491. /package/framework/{v0.5.26 → v0.6.0}/lib/job/src/main.js +0 -0
  492. /package/framework/{v0.5.26 → v0.6.0}/lib/job-store.js +0 -0
  493. /package/framework/{v0.5.26 → v0.6.0}/lib/json-config-header/package.json +0 -0
  494. /package/framework/{v0.5.26 → v0.6.0}/lib/json-config-header/src/main.js +0 -0
  495. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/README.md +0 -0
  496. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/package.json +0 -0
  497. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/default/index.js +0 -0
  498. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/file/lib/logrotator/README.md +0 -0
  499. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/file/lib/logrotator/index.js +0 -0
  500. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/mq/index.js +0 -0
  501. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/mq/listener.js +0 -0
  502. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/helper.js +0 -0
  503. /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/main.js +0 -0
  504. /package/framework/{v0.5.26 → v0.6.0}/lib/math/index.js +0 -0
  505. /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-dispatch/package.json +0 -0
  506. /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-dispatch/src/main.js +0 -0
  507. /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-http/package.json +0 -0
  508. /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-http/src/main.js +0 -0
  509. /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-server/package.json +0 -0
  510. /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-server/src/main.js +0 -0
  511. /package/framework/{v0.5.26 → v0.6.0}/lib/merge/README.md +0 -0
  512. /package/framework/{v0.5.26 → v0.6.0}/lib/merge/package.json +0 -0
  513. /package/framework/{v0.5.26 → v0.6.0}/lib/merge/src/main.js +0 -0
  514. /package/framework/{v0.5.26 → v0.6.0}/lib/metrics/package.json +0 -0
  515. /package/framework/{v0.5.26 → v0.6.0}/lib/metrics/src/main.js +0 -0
  516. /package/framework/{v0.5.26 → v0.6.0}/lib/model.js +0 -0
  517. /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-filters/README.md +0 -0
  518. /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-filters/package.json +0 -0
  519. /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-resolver/package.json +0 -0
  520. /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-resolver/src/main.js +0 -0
  521. /package/framework/{v0.5.26 → v0.6.0}/lib/proc.js +0 -0
  522. /package/framework/{v0.5.26 → v0.6.0}/lib/release-watch/package.json +0 -0
  523. /package/framework/{v0.5.26 → v0.6.0}/lib/release-watch/src/main.js +0 -0
  524. /package/framework/{v0.5.26 → v0.6.0}/lib/render-cache/package.json +0 -0
  525. /package/framework/{v0.5.26 → v0.6.0}/lib/render-cache/src/main.js +0 -0
  526. /package/framework/{v0.5.26 → v0.6.0}/lib/render-cache-store.js +0 -0
  527. /package/framework/{v0.5.26 → v0.6.0}/lib/routing/README.md +0 -0
  528. /package/framework/{v0.5.26 → v0.6.0}/lib/routing/build.json +0 -0
  529. /package/framework/{v0.5.26 → v0.6.0}/lib/routing/package.json +0 -0
  530. /package/framework/{v0.5.26 → v0.6.0}/lib/routing/src/radix.js +0 -0
  531. /package/framework/{v0.5.26 → v0.6.0}/lib/routing-introspect/package.json +0 -0
  532. /package/framework/{v0.5.26 → v0.6.0}/lib/routing-introspect/src/main.js +0 -0
  533. /package/framework/{v0.5.26 → v0.6.0}/lib/secrets/package.json +0 -0
  534. /package/framework/{v0.5.26 → v0.6.0}/lib/secrets/src/backends/env.js +0 -0
  535. /package/framework/{v0.5.26 → v0.6.0}/lib/secrets/src/main.js +0 -0
  536. /package/framework/{v0.5.26 → v0.6.0}/lib/session-store.js +0 -0
  537. /package/framework/{v0.5.26 → v0.6.0}/lib/shell.js +0 -0
  538. /package/framework/{v0.5.26 → v0.6.0}/lib/state.js +0 -0
  539. /package/framework/{v0.5.26 → v0.6.0}/lib/swig-filters/README.md +0 -0
  540. /package/framework/{v0.5.26 → v0.6.0}/lib/swig-filters/package.json +0 -0
  541. /package/framework/{v0.5.26 → v0.6.0}/lib/swig-resolver/package.json +0 -0
  542. /package/framework/{v0.5.26 → v0.6.0}/lib/swig-resolver/src/main.js +0 -0
  543. /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/package.json +0 -0
  544. /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/src/loaders/http.js +0 -0
  545. /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/src/loaders/memory.js +0 -0
  546. /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/src/main.js +0 -0
  547. /package/framework/{v0.5.26 → v0.6.0}/lib/url/README.md +0 -0
  548. /package/framework/{v0.5.26 → v0.6.0}/lib/url/index.js +0 -0
  549. /package/framework/{v0.5.26 → v0.6.0}/lib/url/routing.json +0 -0
  550. /package/framework/{v0.5.26 → v0.6.0}/lib/uuid/package.json +0 -0
  551. /package/framework/{v0.5.26 → v0.6.0}/lib/uuid/src/main.js +0 -0
  552. /package/framework/{v0.5.26 → v0.6.0}/lib/validator.js +0 -0
  553. /package/framework/{v0.5.26 → v0.6.0}/lib/watcher/package.json +0 -0
  554. /package/framework/{v0.5.26 → v0.6.0}/lib/watcher/src/main.js +0 -0
  555. /package/framework/{v0.5.26 → v0.6.0}/lib/ws-framing/package.json +0 -0
  556. /package/framework/{v0.5.26 → v0.6.0}/lib/ws-framing/src/main.js +0 -0
  557. /package/framework/{v0.5.26 → v0.6.0}/lib/ws-query/package.json +0 -0
  558. /package/framework/{v0.5.26 → v0.6.0}/lib/ws-query/src/main.js +0 -0
  559. /package/framework/{v0.5.26 → v0.6.0}/lib/ws-session/package.json +0 -0
  560. /package/framework/{v0.5.26 → v0.6.0}/lib/ws-session/src/main.js +0 -0
@@ -0,0 +1,899 @@
1
+ /*
2
+ * This file is part of the gina package.
3
+ * Copyright (c) 2009-2026 Rhinostone <contact@gina.io>
4
+ *
5
+ * For the full copyright and license information, please view the LICENSE
6
+ * file that was distributed with this source code.
7
+ */
8
+ 'use strict';
9
+
10
+ /**
11
+ * lib/authn — authentication hardening primitives (#COMPLY3).
12
+ *
13
+ * **Hooks and helpers, never an identity provider.** Gina does not own a user
14
+ * record, a credential store, a login route, or a session id — those are the
15
+ * bundle's. What this module supplies is the handful of primitives that are
16
+ * dangerous to hand-roll: a memory-hard password hash with a self-describing
17
+ * encoding, a constant-time verify, and a password policy check.
18
+ *
19
+ * It composes with what already ships rather than replacing it:
20
+ *
21
+ * 1. `validatePasswordPolicy(pw)` — at registration / password change.
22
+ * 2. `hashPassword(pw)` — store the returned PHC string.
23
+ * 3. `createLockout()` — refuse an account under attack BEFORE
24
+ * spending a KDF on it.
25
+ * 4. `verifyPassword(pw, stored)` — at login; pair it with `dummyVerify` on
26
+ * the account-not-found branch.
27
+ * 5. `req.login(user, done)` — core/router.js rotates the session id and
28
+ * binds `req.session.user` (#COMPLY4).
29
+ *
30
+ * Step 5 is where authentication ENDS and authorization begins: `lib/authz-gate`
31
+ * reads `req.session.user`, so nothing here ever touches a session.
32
+ *
33
+ * **Encoding.** Hashes are PHC strings — `$scrypt$ln=17,r=8,p=1$<salt>$<hash>`
34
+ * (base64, unpadded). Self-describing, so the parameters travel with the hash
35
+ * and can be raised later without a flag day: {@link needsRehash} reports which
36
+ * stored hashes are below the current policy, and the login action upgrades
37
+ * them transparently (it is the only moment the plaintext is in hand).
38
+ *
39
+ * **Why scrypt.** It is memory-hard and lives in node core, so a consumer needs
40
+ * no native addon to get a defensible default — the framework must work out of
41
+ * the box. Argon2id is the stronger primitive where a consumer can install it;
42
+ * {@link verifyPassword} therefore ALSO verifies `$argon2*$` and `$2a/2b/2y$`
43
+ * (bcrypt) hashes through the consumer's own `argon2` / `bcrypt` package, so a
44
+ * bundle migrating onto gina keeps its existing hashes working. Gina never
45
+ * MINTS those formats — one mint path, one set of parameters to reason about.
46
+ *
47
+ * **What this module deliberately does NOT do:** no credential storage, no user
48
+ * lookup, no login route, no session handling, no password reset or email
49
+ * flows, no breach-corpus checks (that needs a network service — see the guide
50
+ * for the k-anonymity pattern), no password history (it needs the store gina
51
+ * does not own).
52
+ *
53
+ * @module lib/authn
54
+ * @see module:lib/authz-gate — the authorization half; reads `req.session.user`
55
+ *
56
+ * @example
57
+ * // in a bundle's login action
58
+ * var authn = require('gina').lib.authn;
59
+ *
60
+ * authn.verifyPassword(self.post.password, account.passwordHash, function (err, ok) {
61
+ * if (err) { return self.throwError(500); }
62
+ * if (!ok) { return self.renderJSON({ error: 'invalid credentials' }); }
63
+ * self.req.login({ id: account.id, roles: account.roles }, function (loginErr) {
64
+ * if (loginErr) { return self.throwError(500); }
65
+ * self.redirect('/dashboard');
66
+ * });
67
+ * });
68
+ */
69
+
70
+ var crypto = require('crypto');
71
+ var lockout = require('./lockout');
72
+ var totp = require('./totp');
73
+
74
+ /**
75
+ * Current scrypt cost parameters.
76
+ *
77
+ * `ln` is the base-2 logarithm of scrypt's `N`: `N = 2^17 = 131072`, which with
78
+ * `r = 8` puts the working set at roughly 128 MiB and a single hash in the
79
+ * ~100 ms range on 2026 server hardware — the OWASP Password Storage guidance
80
+ * for scrypt. `p = 1` keeps one hash on one core so the cost is memory, not
81
+ * parallelism.
82
+ *
83
+ * Raising these is a supported change: existing hashes keep verifying (their
84
+ * own parameters are encoded in them) and {@link needsRehash} starts reporting
85
+ * `true` for them.
86
+ *
87
+ * @constant
88
+ * @type {{ln: number, r: number, p: number}}
89
+ * @inner
90
+ * @private
91
+ */
92
+ var SCRYPT_PARAMS = { ln: 17, r: 8, p: 1 };
93
+
94
+ /** @constant {number} Salt length in bytes (128 bits). @inner @private */
95
+ var SALT_BYTES = 16;
96
+ /** @constant {number} Derived-key length in bytes (256 bits). @inner @private */
97
+ var KEY_BYTES = 32;
98
+
99
+ /**
100
+ * Upper bound on an accepted password, in bytes of UTF-8.
101
+ *
102
+ * A memory-hard KDF is a denial-of-service surface: the work is paid by the
103
+ * server, and an unbounded input lets a caller choose how much. 1024 bytes is
104
+ * far above any real passphrase and far below anything that matters. Rejected
105
+ * as an ERROR rather than silently truncated — a silent truncation would make
106
+ * two different passwords authenticate each other.
107
+ *
108
+ * @constant
109
+ * @type {number}
110
+ * @inner
111
+ * @private
112
+ */
113
+ var MAX_PASSWORD_BYTES = 1024;
114
+
115
+ /**
116
+ * Default minimum password LENGTH.
117
+ *
118
+ * 12 with no composition rules, per NIST SP 800-63B: mandatory character-class
119
+ * mixing measurably pushes users toward predictable substitutions, so length is
120
+ * the requirement and composition is available but off.
121
+ *
122
+ * @constant
123
+ * @type {number}
124
+ * @inner
125
+ * @private
126
+ */
127
+ var DEFAULT_MIN_LENGTH = 12;
128
+
129
+ /**
130
+ * Concurrency ceiling for in-flight scrypt operations.
131
+ *
132
+ * Each hash reserves ~128 MiB and occupies a libuv threadpool slot (default
133
+ * size 4). Without a ceiling, a burst of login attempts is a memory-exhaustion
134
+ * vector and starves every other threadpool user — fs, zlib, dns. Two keeps a
135
+ * burst bounded while leaving threadpool capacity for the rest of the process.
136
+ *
137
+ * @constant
138
+ * @type {number}
139
+ * @inner
140
+ * @private
141
+ */
142
+ var DEFAULT_MAX_CONCURRENT = 2;
143
+
144
+ /** @type {number} In-flight scrypt operations. @inner @private */
145
+ var _inFlight = 0;
146
+ /** @type {Array<function>} FIFO of queued scrypt starters. @inner @private */
147
+ var _queue = [];
148
+ /** @type {number} Effective concurrency ceiling. @inner @private */
149
+ var _maxConcurrent = DEFAULT_MAX_CONCURRENT;
150
+
151
+ /**
152
+ * Ceiling on the number of hashes WAITING for a slot.
153
+ *
154
+ * The concurrency gauge bounds how much work runs at once; without this, it did
155
+ * not bound how much work could be PROMISED. Set generously — real login
156
+ * traffic never approaches it — so reaching it means the endpoint is under load
157
+ * that belongs to a rate limiter, not to a KDF.
158
+ *
159
+ * @constant
160
+ * @type {number}
161
+ * @inner
162
+ * @private
163
+ */
164
+ var DEFAULT_MAX_QUEUE = 100;
165
+ /** @type {number} Effective queue ceiling. @inner @private */
166
+ var _maxQueue = DEFAULT_MAX_QUEUE;
167
+
168
+ /**
169
+ * Run `fn` once a concurrency slot is free, releasing the slot when it calls
170
+ * back.
171
+ *
172
+ * FIFO, so a queued attempt cannot be starved by later arrivals. `release` is
173
+ * latched: a KDF callback that fired twice would otherwise corrupt the counter
174
+ * and permanently shrink the pool.
175
+ *
176
+ * @param {function} fn - receives `release` and must call it exactly once.
177
+ * @returns {void}
178
+ * @inner
179
+ * @private
180
+ */
181
+ function withSlot(fn, onRejected) {
182
+ function start() {
183
+ _inFlight++;
184
+ var released = false;
185
+ fn(function release() {
186
+ if (released) {
187
+ return;
188
+ }
189
+ released = true;
190
+ _inFlight--;
191
+ if (_queue.length > 0) {
192
+ var next = _queue.shift();
193
+ next();
194
+ }
195
+ });
196
+ }
197
+ if (_inFlight < _maxConcurrent) {
198
+ return start();
199
+ }
200
+ // Shed load rather than queue without limit. An unbounded queue made the
201
+ // documented account-not-found pattern an amplifier: 30 requests for
202
+ // accounts that DO NOT EXIST — no credentials, no account needed — pushed a
203
+ // legitimate login from 25 ms to 431 ms (17x), growing linearly. Bounded
204
+ // rejection is a far better failure than unbounded latency, and it applies
205
+ // to every caller equally, so it opens no enumeration difference.
206
+ if (_queue.length >= _maxQueue) {
207
+ var err = new Error('[gina authn] password-hashing queue is full (' + _maxQueue + ' waiting) — shedding load. Respond 503 and retry; if this is steady-state, the login endpoint needs request-rate limiting in front of it.');
208
+ err.code = 'AUTHN_QUEUE_FULL';
209
+ if (typeof onRejected === 'function') {
210
+ return process.nextTick(function () { onRejected(err); });
211
+ }
212
+ throw err;
213
+ }
214
+ _queue.push(start);
215
+ }
216
+
217
+ /**
218
+ * Set the scrypt concurrency ceiling.
219
+ *
220
+ * Raise it only alongside a matching threadpool size (`UV_THREADPOOL_SIZE`) and
221
+ * a memory budget. The peak is `maxConcurrent` times the working set of the
222
+ * parameters actually in use — 128 MiB each at the shipped defaults, but up to
223
+ * the `MAX_WORKING_SET_MIB` ceiling for a stored hash carrying a higher `r`,
224
+ * since a stored hash chooses its own cost.
225
+ *
226
+ * @param {number} n - positive integer.
227
+ * @returns {void}
228
+ * @throws {Error} when `n` is not a positive integer.
229
+ * @memberof module:lib/authn
230
+ *
231
+ * @example
232
+ * lib.authn.setMaxConcurrentHashes(4); // needs UV_THREADPOOL_SIZE >= 6 and ~512 MiB headroom
233
+ */
234
+ function setMaxConcurrentHashes(n) {
235
+ if (typeof n !== 'number' || !isFinite(n) || n < 1 || Math.floor(n) !== n) {
236
+ throw new Error('[gina authn] setMaxConcurrentHashes(n) expects a positive integer — got: ' + JSON.stringify(n));
237
+ }
238
+ _maxConcurrent = n;
239
+ while (_inFlight < _maxConcurrent && _queue.length > 0) {
240
+ var next = _queue.shift();
241
+ next();
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Minimum accepted lengths, in bytes, for the SALT and KEY fields of a stored
247
+ * hash.
248
+ *
249
+ * A stored hash is attacker-controlled once the credential store is — and it is
250
+ * also whatever a bad migration or a truncated column left behind. Since
251
+ * {@link verifyPassword} derives exactly as many bytes as the stored key holds,
252
+ * a SHORT key silently weakens the comparison to that many bytes: measured, a
253
+ * 1-byte stored key authenticated 1 of 60 random passwords. Anything below
254
+ * these floors was not minted here, so it is rejected rather than compared.
255
+ *
256
+ * @constant
257
+ * @type {number}
258
+ * @inner
259
+ * @private
260
+ */
261
+ var MIN_STORED_KEY_BYTES = 16;
262
+
263
+ /**
264
+ * Accepted ranges for the cost parameters, and the ceiling on the working set
265
+ * they imply.
266
+ *
267
+ * Bounding each parameter INDEPENDENTLY is not enough: scrypt's working set is
268
+ * `128 * 2^ln * r`, so the corner of the allowed box — `ln=20, r=32` — implies
269
+ * **4 GiB per verify**, 32x the documented peak, from a stored string an
270
+ * attacker controls once the credential store does. `p` multiplies CPU rather
271
+ * than memory (measured: `p=16` cost 14x the wall time of `p=1` at the same
272
+ * memory), so it is bounded separately and tightly — we mint `p=1`.
273
+ *
274
+ * `MAX_WORKING_SET_MIB` is set so the whole documented mint range stays legal at
275
+ * the standard `r=8` (`ln=20, r=8` is exactly 1024 MiB) while the pathological
276
+ * corners are refused.
277
+ *
278
+ * @constant
279
+ * @inner
280
+ * @private
281
+ */
282
+ var PARAM_BOUNDS = { lnMin: 14, lnMax: 20, rMin: 1, rMax: 32, pMin: 1, pMax: 4 };
283
+ /** @constant {number} Ceiling on `128 * 2^ln * r`, in MiB. @inner @private */
284
+ var MAX_WORKING_SET_MIB = 1024;
285
+
286
+ /**
287
+ * Validate a cost triple against the shared bounds AND the working-set ceiling.
288
+ *
289
+ * Applied identically when minting and when reading a stored hash — an
290
+ * asymmetry between the two is how {@link hashPassword} was able to mint hashes
291
+ * {@link verifyPassword} could never read.
292
+ *
293
+ * @param {number} ln
294
+ * @param {number} r
295
+ * @param {number} p
296
+ * @returns {boolean}
297
+ * @inner
298
+ * @private
299
+ */
300
+ function costWithinBounds(ln, r, p) {
301
+ if (!isFinite(ln) || !isFinite(r) || !isFinite(p)) {
302
+ return false;
303
+ }
304
+ if (Math.floor(ln) !== ln || Math.floor(r) !== r || Math.floor(p) !== p) {
305
+ return false;
306
+ }
307
+ if (ln < PARAM_BOUNDS.lnMin || ln > PARAM_BOUNDS.lnMax) {
308
+ return false;
309
+ }
310
+ if (r < PARAM_BOUNDS.rMin || r > PARAM_BOUNDS.rMax) {
311
+ return false;
312
+ }
313
+ if (p < PARAM_BOUNDS.pMin || p > PARAM_BOUNDS.pMax) {
314
+ return false;
315
+ }
316
+ return (128 * Math.pow(2, ln) * r) / (1024 * 1024) <= MAX_WORKING_SET_MIB;
317
+ }
318
+ /** @constant {number} Minimum stored salt length in bytes. @inner @private */
319
+ var MIN_STORED_SALT_BYTES = 8;
320
+
321
+ /**
322
+ * Normalise a password to Unicode NFC.
323
+ *
324
+ * The same accented character has more than one valid encoding — `é` as a
325
+ * single code point, or `e` followed by a combining acute. A keyboard, an
326
+ * operating system and a browser can each produce a different one, so a user
327
+ * who registers on one device and signs in from another otherwise submits
328
+ * bytes that will never match, and is locked out of their own account with no
329
+ * explanation. Normalising both sides of the comparison removes that.
330
+ *
331
+ * @param {string} password
332
+ * @returns {string}
333
+ * @inner
334
+ * @private
335
+ */
336
+ function normalizePassword(password) {
337
+ return password.normalize('NFC');
338
+ }
339
+
340
+ /**
341
+ * Reject anything that is not a usable password string.
342
+ *
343
+ * The byte cap is applied AFTER normalisation, since normalising can change the
344
+ * encoded length.
345
+ *
346
+ * @param {*} password
347
+ * @returns {?Error} the error, or `null` when acceptable.
348
+ * @inner
349
+ * @private
350
+ */
351
+ function checkPasswordInput(password) {
352
+ if (typeof password !== 'string') {
353
+ return new Error('[gina authn] password must be a string — got: ' + (password === null ? 'null' : typeof password));
354
+ }
355
+ if (password.length === 0) {
356
+ return new Error('[gina authn] password must not be empty');
357
+ }
358
+ if (Buffer.byteLength(normalizePassword(password), 'utf8') > MAX_PASSWORD_BYTES) {
359
+ return new Error('[gina authn] password exceeds ' + MAX_PASSWORD_BYTES + ' bytes — reject it in your form validation before hashing');
360
+ }
361
+ return null;
362
+ }
363
+
364
+ /**
365
+ * base64 without padding, for PHC fields.
366
+ *
367
+ * @param {Buffer} buf
368
+ * @returns {string}
369
+ * @inner
370
+ * @private
371
+ */
372
+ function b64(buf) {
373
+ return buf.toString('base64').replace(/=+$/, '');
374
+ }
375
+
376
+ /**
377
+ * Hash a password, producing a self-describing PHC string.
378
+ *
379
+ * Asynchronous by construction — there is no synchronous variant, because the
380
+ * work is ~100 ms and a sync KDF on the request path blocks the event loop for
381
+ * every other connection.
382
+ *
383
+ * The returned string is what you persist. It embeds the algorithm, the cost
384
+ * parameters and the salt, so nothing else needs storing and the parameters can
385
+ * be raised later without invalidating it.
386
+ *
387
+ * @param {string} password - plaintext; 1..1024 bytes UTF-8.
388
+ * @param {object} [options] - overrides.
389
+ * @param {number} [options.ln=17] - base-2 log of scrypt N (14..20).
390
+ * @param {number} [options.r=8] - block size.
391
+ * @param {number} [options.p=1] - parallelism.
392
+ * @param {function} cb - `cb(err, phcString)`. `err.code` is
393
+ * `AUTHN_QUEUE_FULL` when the hashing queue is shedding load — respond 503.
394
+ * @returns {void}
395
+ * @memberof module:lib/authn
396
+ *
397
+ * @example
398
+ * lib.authn.hashPassword('correct horse battery staple', function (err, hash) {
399
+ * // hash === '$scrypt$ln=17,r=8,p=1$<salt>$<key>' -> store it
400
+ * });
401
+ *
402
+ * @example <caption>Lower cost in a test suite</caption>
403
+ * lib.authn.hashPassword(pw, { ln: 12 }, function (err, hash) { });
404
+ */
405
+ function hashPassword(password, options, cb) {
406
+ if (typeof options === 'function') {
407
+ cb = options;
408
+ options = {};
409
+ }
410
+ if (typeof cb !== 'function') {
411
+ throw new Error('[gina authn] hashPassword(password[, options], cb) requires a callback function');
412
+ }
413
+ options = options || {};
414
+
415
+ var inputErr = checkPasswordInput(password);
416
+ if (inputErr) {
417
+ return process.nextTick(function () { cb(inputErr); });
418
+ }
419
+
420
+ var ln = (typeof options.ln === 'number') ? options.ln : SCRYPT_PARAMS.ln;
421
+ var r = (typeof options.r === 'number') ? options.r : SCRYPT_PARAMS.r;
422
+ var p = (typeof options.p === 'number') ? options.p : SCRYPT_PARAMS.p;
423
+
424
+ // Exactly the bounds parseScryptPhc enforces. They were once looser here —
425
+ // `r` and `p` had no upper bound while the parser capped them — so
426
+ // hashPassword happily minted hashes verifyPassword could not read, and the
427
+ // CORRECT password then reported "wrong password" forever, with no error
428
+ // anywhere: a silent permanent lockout. Measured with r=64.
429
+ if (!costWithinBounds(ln, r, p)) {
430
+ return process.nextTick(function () {
431
+ cb(new Error('[gina authn] hashPassword: cost out of range — `ln` '
432
+ + PARAM_BOUNDS.lnMin + '..' + PARAM_BOUNDS.lnMax
433
+ + ', `r` ' + PARAM_BOUNDS.rMin + '..' + PARAM_BOUNDS.rMax
434
+ + ', `p` ' + PARAM_BOUNDS.pMin + '..' + PARAM_BOUNDS.pMax
435
+ + ', and 128 * 2^ln * r must not exceed ' + MAX_WORKING_SET_MIB + ' MiB'
436
+ + ' — got: ln=' + JSON.stringify(ln) + ', r=' + JSON.stringify(r) + ', p=' + JSON.stringify(p)));
437
+ });
438
+ }
439
+
440
+ var salt = crypto.randomBytes(SALT_BYTES);
441
+ var N = Math.pow(2, ln);
442
+ var pw = normalizePassword(password);
443
+
444
+ withSlot(function (release) {
445
+ // node's default maxmem (32 MiB) is below what these parameters need, so
446
+ // it must be raised explicitly or scrypt throws. 128 * N * r is the
447
+ // documented working-set formula; the headroom multiplier covers node's
448
+ // own bookkeeping.
449
+ var maxmem = 128 * N * r * 2;
450
+ crypto.scrypt(pw, salt, KEY_BYTES, { N: N, r: r, p: p, maxmem: maxmem }, function (err, derived) {
451
+ release();
452
+ if (err) {
453
+ return cb(err);
454
+ }
455
+ cb(null, '$scrypt$ln=' + ln + ',r=' + r + ',p=' + p + '$' + b64(salt) + '$' + b64(derived));
456
+ });
457
+ }, cb);
458
+ }
459
+
460
+ /**
461
+ * Parse a gina scrypt PHC string.
462
+ *
463
+ * @param {string} stored
464
+ * @returns {?{ln: number, r: number, p: number, salt: Buffer, hash: Buffer}} `null` when the string is not a well-formed gina scrypt hash.
465
+ * @inner
466
+ * @private
467
+ */
468
+ function parseScryptPhc(stored) {
469
+ if (typeof stored !== 'string') {
470
+ return null;
471
+ }
472
+ var m = /^\$scrypt\$ln=(\d+),r=(\d+),p=(\d+)\$([A-Za-z0-9+/]+)\$([A-Za-z0-9+/]+)$/.exec(stored);
473
+ if (!m) {
474
+ return null;
475
+ }
476
+ var ln = parseInt(m[1], 10);
477
+ var r = parseInt(m[2], 10);
478
+ var p = parseInt(m[3], 10);
479
+ // A stored hash is attacker-controlled the moment the credential store is.
480
+ // Unbounded parameters here would let a single verify allocate arbitrary
481
+ // memory — the same DoS the input cap closes from the other side.
482
+ if (!costWithinBounds(ln, r, p)) {
483
+ return null;
484
+ }
485
+ var salt = Buffer.from(m[4], 'base64');
486
+ var hash = Buffer.from(m[5], 'base64');
487
+ // Length floors, not merely non-emptiness: verifyPassword derives exactly
488
+ // `hash.length` bytes, so a short stored key shrinks the comparison to that
489
+ // width. Measured before this guard: a 1-byte key authenticated 1 of 60
490
+ // random passwords. We mint 32/16, so anything below these floors is
491
+ // corruption or forgery either way.
492
+ if (salt.length < MIN_STORED_SALT_BYTES || hash.length < MIN_STORED_KEY_BYTES) {
493
+ return null;
494
+ }
495
+ return { ln: ln, r: r, p: p, salt: salt, hash: hash };
496
+ }
497
+
498
+ /**
499
+ * Resolve an optional verifier package from the consuming project.
500
+ *
501
+ * Same project-path resolution every gina connector uses for its driver — the
502
+ * package belongs to the bundle, not the framework.
503
+ *
504
+ * @param {string} pkg - `'argon2'` or `'bcrypt'`.
505
+ * @returns {?object} the module, or `null` when not installed.
506
+ * @inner
507
+ * @private
508
+ */
509
+ function resolveVerifier(pkg) {
510
+ if (_injectedVerifiers[pkg]) {
511
+ return _injectedVerifiers[pkg];
512
+ }
513
+ try {
514
+ var p = _(getPath('project') + '/node_modules/' + pkg, true);
515
+ return require(p);
516
+ } catch (e) {
517
+ return null;
518
+ }
519
+ }
520
+
521
+ /** @type {object} Test-injected verifier modules. @inner @private */
522
+ var _injectedVerifiers = {};
523
+
524
+ /**
525
+ * Inject a verifier module, bypassing project-path resolution.
526
+ *
527
+ * Test seam — mirrors `lib/metrics`' `opts.client`. Not part of the supported
528
+ * surface.
529
+ *
530
+ * @param {string} pkg - `'argon2'` or `'bcrypt'`.
531
+ * @param {?object} mod - the module, or `null` to clear.
532
+ * @returns {void}
533
+ * @memberof module:lib/authn
534
+ * @private
535
+ */
536
+ function _setVerifier(pkg, mod) {
537
+ if (mod === null) {
538
+ delete _injectedVerifiers[pkg];
539
+ return;
540
+ }
541
+ _injectedVerifiers[pkg] = mod;
542
+ }
543
+
544
+ /**
545
+ * Verify a password against a stored hash.
546
+ *
547
+ * Accepts gina's own `$scrypt$` hashes, and — through the consuming project's
548
+ * own `argon2` / `bcrypt` install — `$argon2i$` / `$argon2d$` / `$argon2id$`
549
+ * and `$2a$` / `$2b$` / `$2y$`. That foreign-format branch exists so a bundle
550
+ * arriving with existing hashes keeps working; pair it with {@link needsRehash}
551
+ * to migrate on login.
552
+ *
553
+ * **Never throws for a bad password.** A malformed or unrecognised stored hash
554
+ * is `cb(null, false)`, not an error — a corrupted record must not be
555
+ * distinguishable from a wrong password by an attacker watching responses. A
556
+ * genuine operational failure (KDF error, verifier package missing for a format
557
+ * that needs one) IS an error, because it needs an operator, not a login form.
558
+ *
559
+ * @param {string} password - plaintext to check.
560
+ * @param {string} stored - the persisted hash string.
561
+ * @param {function} cb - `cb(err, isValid)`. `err.code` is
562
+ * `AUTHN_QUEUE_FULL` when the hashing queue is shedding load — respond 503,
563
+ * and treat the account-not-found branch identically (see {@link dummyVerify}).
564
+ * @returns {void}
565
+ * @memberof module:lib/authn
566
+ *
567
+ * @example
568
+ * lib.authn.verifyPassword(submitted, account.passwordHash, function (err, ok) {
569
+ * if (err) { return self.throwError(500); } // operational
570
+ * if (!ok) { return deny(); } // wrong password
571
+ * });
572
+ *
573
+ * @example <caption>Unknown account — spend the same time (see dummyVerify)</caption>
574
+ * if (!account) {
575
+ * return lib.authn.dummyVerify(submitted, { like: referenceHash }, function () { deny(); });
576
+ * }
577
+ */
578
+ function verifyPassword(password, stored, cb) {
579
+ if (typeof cb !== 'function') {
580
+ throw new Error('[gina authn] verifyPassword(password, stored, cb) requires a callback function');
581
+ }
582
+ var inputErr = checkPasswordInput(password);
583
+ if (inputErr) {
584
+ return process.nextTick(function () { cb(inputErr); });
585
+ }
586
+ if (typeof stored !== 'string' || stored.length === 0) {
587
+ return process.nextTick(function () { cb(null, false); });
588
+ }
589
+
590
+ if (/^\$argon2[id]{1,2}\$/.test(stored)) {
591
+ var argon2 = resolveVerifier('argon2');
592
+ if (!argon2 || typeof argon2.verify !== 'function') {
593
+ return process.nextTick(function () {
594
+ cb(new Error('[gina authn] this hash is argon2, which gina verifies through your project\'s own package. Run: npm install argon2'));
595
+ });
596
+ }
597
+ return Promise.resolve()
598
+ .then(function () { return argon2.verify(stored, normalizePassword(password)); })
599
+ .then(function (ok) { cb(null, ok === true); })
600
+ .catch(function () { cb(null, false); });
601
+ }
602
+
603
+ if (/^\$2[aby]\$/.test(stored)) {
604
+ var bcrypt = resolveVerifier('bcrypt');
605
+ if (!bcrypt || typeof bcrypt.compare !== 'function') {
606
+ return process.nextTick(function () {
607
+ cb(new Error('[gina authn] this hash is bcrypt, which gina verifies through your project\'s own package. Run: npm install bcrypt'));
608
+ });
609
+ }
610
+ return bcrypt.compare(normalizePassword(password), stored, function (err, ok) {
611
+ if (err) {
612
+ return cb(null, false);
613
+ }
614
+ cb(null, ok === true);
615
+ });
616
+ }
617
+
618
+ var parsed = parseScryptPhc(stored);
619
+ if (!parsed) {
620
+ return process.nextTick(function () { cb(null, false); });
621
+ }
622
+
623
+ var N = Math.pow(2, parsed.ln);
624
+ var pwNorm = normalizePassword(password);
625
+ withSlot(function (release) {
626
+ var maxmem = 128 * N * parsed.r * 2;
627
+ crypto.scrypt(pwNorm, parsed.salt, parsed.hash.length, { N: N, r: parsed.r, p: parsed.p, maxmem: maxmem }, function (err, derived) {
628
+ release();
629
+ if (err) {
630
+ return cb(err);
631
+ }
632
+ // Lengths match by construction (derived is requested at the stored
633
+ // length), so timingSafeEqual cannot throw here — the try/catch is
634
+ // the house convention, and it keeps a future refactor fail-closed.
635
+ var ok = false;
636
+ try {
637
+ ok = crypto.timingSafeEqual(derived, parsed.hash);
638
+ } catch (e) {
639
+ ok = false;
640
+ }
641
+ cb(null, ok);
642
+ });
643
+ }, cb);
644
+ }
645
+
646
+ /**
647
+ * Spend a verify's worth of time without a stored hash.
648
+ *
649
+ * A login that returns instantly for an unknown account and slowly for a known
650
+ * one is a user-enumeration oracle, and it is measurable across a network. Call
651
+ * this on the account-not-found branch so both branches cost the same.
652
+ *
653
+ * **The cost must match the cost your stored hashes actually use**, and by
654
+ * default that is the shipped parameters. If your hashes were minted cheaper —
655
+ * a lowered `ln`, or legacy hashes not yet migrated by {@link needsRehash} —
656
+ * pass the same parameters, or pass `like: <a stored hash>` and the cost is read
657
+ * from it. Getting this wrong does not merely fail to close the oracle, it
658
+ * INVERTS it: measured at defaults against `ln=14` hashes, the unknown-account
659
+ * branch ran 13.9x SLOWER than the known-account one, which is a louder signal
660
+ * than doing nothing.
661
+ *
662
+ * @param {string} password - the submitted plaintext.
663
+ * @param {object|function} [options] - cost overrides, or the callback.
664
+ * @param {string} [options.like] - a stored hash to copy the cost from (wins over ln/r/p).
665
+ * @param {number} [options.ln=17]
666
+ * @param {number} [options.r=8]
667
+ * @param {number} [options.p=1]
668
+ * @param {function} cb - `cb(err)`. `err` is `null` normally; it
669
+ * carries `AUTHN_QUEUE_FULL` when the hashing queue is shedding load. Handle
670
+ * it EXACTLY as you handle {@link verifyPassword}'s error — respond 503 —
671
+ * because any divergence between the two branches under saturation is the
672
+ * enumeration signal this function exists to remove.
673
+ * @returns {void}
674
+ * @memberof module:lib/authn
675
+ *
676
+ * @example <caption>Always pass a cost — `like` reads it from a real hash</caption>
677
+ * if (!account) {
678
+ * // `referenceHash` is any hash from your store (seed one at install time).
679
+ * // Reading the cost from real data is what keeps the two branches matched
680
+ * // as you raise parameters — a separate setting silently drifts.
681
+ * return lib.authn.dummyVerify(self.post.password, { like: referenceHash }, function () {
682
+ * self.renderJSON({ error: 'invalid credentials' });
683
+ * });
684
+ * }
685
+ *
686
+ * @example <caption>Or state the cost explicitly</caption>
687
+ * lib.authn.dummyVerify(submitted, { ln: 14 }, function () { deny(); });
688
+ */
689
+ function dummyVerify(password, options, cb) {
690
+ if (typeof options === 'function') {
691
+ cb = options;
692
+ options = {};
693
+ }
694
+ if (typeof cb !== 'function') {
695
+ throw new Error('[gina authn] dummyVerify(password[, options], cb) requires a callback function');
696
+ }
697
+ options = options || {};
698
+
699
+ var ln = SCRYPT_PARAMS.ln;
700
+ var r = SCRYPT_PARAMS.r;
701
+ var p = SCRYPT_PARAMS.p;
702
+
703
+ // `like` copies the cost off a real stored hash — the most reliable way to
704
+ // stay matched, since it needs no separate configuration to keep in sync.
705
+ if (typeof options.like === 'string') {
706
+ var ref = parseScryptPhc(options.like);
707
+ if (ref) {
708
+ ln = ref.ln;
709
+ r = ref.r;
710
+ p = ref.p;
711
+ }
712
+ } else {
713
+ if (typeof options.ln === 'number') { ln = options.ln; }
714
+ if (typeof options.r === 'number') { r = options.r; }
715
+ if (typeof options.p === 'number') { p = options.p; }
716
+ }
717
+ // Silently clamp rather than throw: this runs on a failed-login path, and an
718
+ // exception there would turn a mistuned parameter into an outage.
719
+ if (!isFinite(ln) || ln < 14 || ln > 20) { ln = SCRYPT_PARAMS.ln; }
720
+ if (!isFinite(r) || r < 1 || r > 32) { r = SCRYPT_PARAMS.r; }
721
+ if (!isFinite(p) || p < 1 || p > 16) { p = SCRYPT_PARAMS.p; }
722
+
723
+ var pw = (typeof password === 'string' && password.length > 0 && Buffer.byteLength(password, 'utf8') <= MAX_PASSWORD_BYTES)
724
+ ? normalizePassword(password)
725
+ : 'x';
726
+ var salt = crypto.randomBytes(SALT_BYTES);
727
+ var N = Math.pow(2, ln);
728
+ withSlot(function (release) {
729
+ var maxmem = 128 * N * r * 2;
730
+ crypto.scrypt(pw, salt, KEY_BYTES, { N: N, r: r, p: p, maxmem: maxmem }, function () {
731
+ release();
732
+ cb(null);
733
+ });
734
+ }, function (err) {
735
+ // Surface the shed error, because verifyPassword surfaces it too. If
736
+ // this branch swallowed it, then under saturation a known account would
737
+ // 500 while an unknown one returned "invalid credentials" — saturation
738
+ // itself would become the enumeration signal this function exists to
739
+ // remove. Both branches must look identical in every regime.
740
+ cb(err);
741
+ });
742
+ }
743
+
744
+ /**
745
+ * Report whether a stored hash is below the current policy.
746
+ *
747
+ * True when the hash is not gina scrypt (a foreign argon2 / bcrypt hash, or an
748
+ * unparseable string) or when its encoded parameters are weaker than the
749
+ * current defaults. Re-hash on the next successful login — the one moment the
750
+ * plaintext is available.
751
+ *
752
+ * @param {string} stored - the persisted hash string.
753
+ * @returns {boolean}
754
+ * @memberof module:lib/authn
755
+ *
756
+ * @example
757
+ * if (ok && lib.authn.needsRehash(account.passwordHash)) {
758
+ * lib.authn.hashPassword(submitted, function (err, fresh) {
759
+ * if (!err) { account.passwordHash = fresh; account.save(); }
760
+ * });
761
+ * }
762
+ */
763
+ function needsRehash(stored) {
764
+ var parsed = parseScryptPhc(stored);
765
+ if (!parsed) {
766
+ return true;
767
+ }
768
+ // A key shorter than we mint verifies at reduced width forever otherwise —
769
+ // a record truncated by, say, a bcrypt-sized VARCHAR(60) parses (it clears
770
+ // the 16-byte floor) and would never be flagged for migration.
771
+ return parsed.hash.length !== KEY_BYTES
772
+ || parsed.ln < SCRYPT_PARAMS.ln
773
+ || parsed.r < SCRYPT_PARAMS.r
774
+ || parsed.p < SCRYPT_PARAMS.p;
775
+ }
776
+
777
+ /**
778
+ * Validate a password against a length / composition policy.
779
+ *
780
+ * Length-first, per NIST SP 800-63B: the default is a 12-character minimum with
781
+ * NO character-class requirements, because mandatory composition measurably
782
+ * degrades real-world password quality. Composition rules are available for
783
+ * consumers whose auditor requires them.
784
+ *
785
+ * @param {string} password - the candidate.
786
+ * @param {object} [options] - policy overrides.
787
+ * @param {number} [options.minLength=12] - minimum characters (code points, not bytes).
788
+ * @param {number} [options.maxLength=1024] - maximum bytes of UTF-8.
789
+ * @param {boolean} [options.requireUppercase=false]
790
+ * @param {boolean} [options.requireLowercase=false]
791
+ * @param {boolean} [options.requireDigit=false]
792
+ * @param {boolean} [options.requireSymbol=false]
793
+ * @param {string[]} [options.deny=[]] - case-insensitive substrings to reject (the user's own email, the site name, …).
794
+ * @returns {{valid: boolean, errors: string[]}} `errors` are stable machine-readable codes: `too-short`, `too-long`, `missing-uppercase`, `missing-lowercase`, `missing-digit`, `missing-symbol`, `denied-substring`, `not-a-string`.
795
+ * @memberof module:lib/authn
796
+ *
797
+ * @example
798
+ * var check = lib.authn.validatePasswordPolicy(self.post.password, {
799
+ * deny: [ self.post.email, 'gina' ]
800
+ * });
801
+ * if (!check.valid) { return self.renderJSON({ errors: check.errors }); }
802
+ */
803
+ function validatePasswordPolicy(password, options) {
804
+ options = options || {};
805
+ var errors = [];
806
+
807
+ if (typeof password !== 'string') {
808
+ return { valid: false, errors: [ 'not-a-string' ] };
809
+ }
810
+
811
+ // Validated rather than trusted: `typeof NaN === 'number'`, so a
812
+ // `parseInt` of a missing config key produced minLength NaN, every
813
+ // comparison against it went false, and an EMPTY password passed the policy.
814
+ // A negative minLength did the same. This is the one input in the module
815
+ // that was taken on faith, and it fails OPEN.
816
+ var minLength = DEFAULT_MIN_LENGTH;
817
+ if (typeof options.minLength !== 'undefined') {
818
+ if (typeof options.minLength !== 'number' || !isFinite(options.minLength)
819
+ || options.minLength < 0 || Math.floor(options.minLength) !== options.minLength) {
820
+ throw new Error('[gina authn] validatePasswordPolicy: `minLength` must be a whole number >= 0 — got: ' + JSON.stringify(options.minLength));
821
+ }
822
+ minLength = options.minLength;
823
+ }
824
+ var maxLength = MAX_PASSWORD_BYTES;
825
+ if (typeof options.maxLength !== 'undefined') {
826
+ if (typeof options.maxLength !== 'number' || !isFinite(options.maxLength)
827
+ || options.maxLength < 1 || Math.floor(options.maxLength) !== options.maxLength) {
828
+ throw new Error('[gina authn] validatePasswordPolicy: `maxLength` must be a whole number >= 1 — got: ' + JSON.stringify(options.maxLength));
829
+ }
830
+ maxLength = options.maxLength;
831
+ }
832
+
833
+ // Byte length FIRST, and return on breach: `Array.from` materialises an
834
+ // array of code points, so measuring length before enforcing the cap meant
835
+ // a 16 MiB submission allocated ~144 MiB just to conclude "too long".
836
+ if (Buffer.byteLength(password, 'utf8') > maxLength) {
837
+ return { valid: false, errors: [ 'too-long' ] };
838
+ }
839
+
840
+ // Count code points, not UTF-16 units, so an emoji or an astral character
841
+ // counts once rather than twice. NOTE this counts CODE POINTS, not grapheme
842
+ // clusters: a family emoji is one perceived character but several code
843
+ // points, so `minLength` is a floor on code points and can overstate
844
+ // strength for grapheme-rich input.
845
+ var length = Array.from(password).length;
846
+ if (length < minLength) {
847
+ errors.push('too-short');
848
+ }
849
+ if (options.requireUppercase === true && !/[A-Z]/.test(password)) {
850
+ errors.push('missing-uppercase');
851
+ }
852
+ if (options.requireLowercase === true && !/[a-z]/.test(password)) {
853
+ errors.push('missing-lowercase');
854
+ }
855
+ if (options.requireDigit === true && !/[0-9]/.test(password)) {
856
+ errors.push('missing-digit');
857
+ }
858
+ if (options.requireSymbol === true && !/[^A-Za-z0-9]/.test(password)) {
859
+ errors.push('missing-symbol');
860
+ }
861
+ if (Array.isArray(options.deny) && options.deny.length > 0) {
862
+ var lower = password.toLowerCase();
863
+ for (var i = 0; i < options.deny.length; i++) {
864
+ var needle = options.deny[i];
865
+ if (typeof needle === 'string' && needle.length > 0 && lower.indexOf(needle.toLowerCase()) > -1) {
866
+ errors.push('denied-substring');
867
+ break;
868
+ }
869
+ }
870
+ }
871
+
872
+ return { valid: errors.length === 0, errors: errors };
873
+ }
874
+
875
+ module.exports = {
876
+ hashPassword : hashPassword,
877
+ verifyPassword : verifyPassword,
878
+ dummyVerify : dummyVerify,
879
+ needsRehash : needsRehash,
880
+ validatePasswordPolicy : validatePasswordPolicy,
881
+ setMaxConcurrentHashes : setMaxConcurrentHashes,
882
+ createLockout : lockout.createLockout,
883
+ generateTotpSecret : totp.generateTotpSecret,
884
+ generateTotp : totp.generateTotp,
885
+ verifyTotp : totp.verifyTotp,
886
+ otpauthURL : totp.otpauthURL,
887
+ // test seams — may change without notice
888
+ _base32Encode : totp._base32Encode,
889
+ _base32Decode : totp._base32Decode,
890
+ _hotp : totp._hotp,
891
+ _createMemoryStore : lockout._createMemoryStore,
892
+ _DEFAULT_MAX_ATTEMPTS : lockout._DEFAULT_MAX_ATTEMPTS,
893
+ _DEFAULT_LOCK_MS : lockout._DEFAULT_LOCK_MS,
894
+ _parseScryptPhc : parseScryptPhc,
895
+ _setVerifier : _setVerifier,
896
+ _SCRYPT_PARAMS : SCRYPT_PARAMS,
897
+ _MAX_PASSWORD_BYTES : MAX_PASSWORD_BYTES,
898
+ _DEFAULT_MIN_LENGTH : DEFAULT_MIN_LENGTH
899
+ };