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.
- package/CHANGELOG.md +22 -0
- package/README.md +34 -22
- package/ROADMAP.md +43 -16
- package/bin/cli +12 -1
- package/bin/gina-init +15 -1
- package/framework/v0.6.0/VERSION +1 -0
- package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.js +36 -1
- package/framework/v0.6.0/core/asset/plugin/dist/vendor/gina/js/gina.min.js +601 -0
- package/framework/v0.6.0/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
- package/framework/v0.6.0/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
- package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/session-store.v3.js +52 -84
- package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/session-store.v4.js +58 -84
- package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/session-store.js +5 -2
- package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/session-store.js +5 -2
- package/framework/{v0.5.26 → v0.6.0}/core/connectors/scylladb/lib/session-store.js +5 -2
- package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/lib/session-store.js +17 -3
- package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/session/src/main.js +142 -9
- package/framework/{v0.5.26 → v0.6.0}/core/router.js +101 -11
- package/framework/{v0.5.26 → v0.6.0}/core/server.js +91 -1
- package/framework/{v0.5.26 → v0.6.0}/core/template/conf/settings.json +3 -0
- package/framework/v0.6.0/lib/audit/src/main.js +916 -0
- package/framework/v0.6.0/lib/authn/package.json +7 -0
- package/framework/v0.6.0/lib/authn/src/lockout.js +615 -0
- package/framework/v0.6.0/lib/authn/src/main.js +899 -0
- package/framework/v0.6.0/lib/authn/src/totp.js +418 -0
- package/framework/v0.6.0/lib/cmd/audit/arguments.json +5 -0
- package/framework/v0.6.0/lib/cmd/audit/help.txt +50 -0
- package/framework/v0.6.0/lib/cmd/audit/verify.js +294 -0
- package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/init.js +11 -0
- package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/tail.js +5 -1
- package/framework/{v0.5.26 → v0.6.0}/lib/cmd/gina.1.md +1 -0
- package/framework/{v0.5.26 → v0.6.0}/lib/index.js +13 -0
- package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/file/index.js +11 -1
- package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/mq/speaker.js +8 -1
- package/framework/v0.6.0/lib/net-locality/package.json +17 -0
- package/framework/v0.6.0/lib/net-locality/src/main.js +174 -0
- package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-filters/src/main.js +13 -0
- package/framework/{v0.5.26 → v0.6.0}/lib/routing/src/main.js +36 -1
- package/framework/{v0.5.26 → v0.6.0}/lib/swig-filters/src/main.js +13 -0
- package/framework/{v0.5.26 → v0.6.0}/package.json +1 -1
- package/gna.js +4 -4
- package/llms.txt +19 -2
- package/package.json +3 -3
- package/schema/connectors.json +2 -3
- package/schema/settings.json +101 -0
- package/types/index.d.ts +4 -0
- package/framework/v0.5.26/VERSION +0 -1
- package/framework/v0.5.26/core/asset/plugin/dist/vendor/gina/js/gina.min.js +0 -599
- package/framework/v0.5.26/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
- package/framework/v0.5.26/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
- package/framework/v0.5.26/lib/audit/src/main.js +0 -456
- /package/framework/{v0.5.26 → v0.6.0}/AUTHORS +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/LICENSE +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/html/nolayout.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/html/static.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/android-chrome-192x192.png +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/android-chrome-512x512.png +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/apple-touch-icon.png +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/favicon-16x16.png +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/favicon-32x32.png +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/img/favicon.ico +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.css +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/beemaster/index.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/css/gina.min.css +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.br +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.gz +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/html/statusbar.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.br +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.gz +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/have_heart_one-webfont.woff2 +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/index.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/inspector.css +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/inspector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/inspector/logo.svg +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.br +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.gz +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/config.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/ai/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/ai/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/connector.v3.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/connector.v4.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/n1ql.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/couchbase/lib/session-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/job-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mongodb/lib/pipeline-loader.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mysql/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/mysql/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/postgresql/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/postgresql/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/job-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/redis/lib/render-cache-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/scylladb/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/scylladb/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sql-parser.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/lib/connector.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/connectors/sqlite/lib/job-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/content.encoding +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.framework.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-json.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-nunjucks-async.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-nunjucks.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-stream.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-swig-async.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-swig.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/controller.render-v1.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/inspector-window-emit.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/controller/release-banner.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/dev/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/dev/lib/class.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/dev/lib/factory.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/dev/lib/tools.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/gna.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/currency.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/language/en.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/language/fr.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/region/en.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/dist/region/fr.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/locales/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/mime.types +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/model/entity.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/model/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/model/template/entityFactory.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/model/template/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/csrf/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/csrf/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/csrf/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coep/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coep/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coep/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coop/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coop/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/coop/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/corp/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/corp/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/corp/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/csp/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/csp/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/csp/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hide-powered-by/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hide-powered-by/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hide-powered-by/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hsts/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hsts/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/hsts/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/origin-agent-cluster/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/origin-agent-cluster/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/origin-agent-cluster/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/referrer-policy/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/referrer-policy/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/referrer-policy/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-content-type-options/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-content-type-options/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-content-type-options/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-dns-prefetch-control/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-dns-prefetch-control/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-dns-prefetch-control/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-download-options/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-download-options/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-download-options/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-frame-options/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-frame-options/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-frame-options/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-xss-protection/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-xss-protection/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/security-headers/x-xss-protection/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/session/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/session/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/build.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/storage/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/build.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/src/form-validator.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/plugins/lib/validator/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/server.express.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/server.isaac.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/status.codes +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/_gitignore +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/app.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/connectors.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/routing.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/settings.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/settings.server.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/templates.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/config/watchers.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/controllers/controller.content.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/controllers/controller.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/controllers/setup.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle/locales/en.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_namespace/controllers/controller.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/css/default.css +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/css/home.css +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/css/vendor/readme.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/favicon.ico +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/js/components/x-checklist.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/js/vendor/readme.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/manifest.webmanifest +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/readme.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_public/sw.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/handlers/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/content/homepage.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/includes/error-msg-noscript.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/includes/error-msg-outdated-browser.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/includes/x-checklist.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/boilerplate/bundle_templates/html/layouts/main.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/command/gina.bat.tpl +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/command/gina.tpl +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/env.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/manifest.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/statics.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/conf/templates.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/error/client/json/401.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/error/client/json/403.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/error/client/json/404.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/error/server/html/50x.html +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/error/server/json/500.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/error/server/json/503.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/core/template/extensions/logger/config.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/console.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/context.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/data/LICENSE +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/data/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/data/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/data/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/dateFormat.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/json/LICENSE +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/json/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/json/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/json/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/path.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/src/api-error.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/plugins/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/prototypes.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/task.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/helpers/text.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/admin/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/admin/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/build.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/src/dep/jszip.min.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/archiver/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/async/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/async/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/audit/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/audit-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/authz-gate/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/authz-gate/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cache/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cache/build.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cache/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cache/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/aliases.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/build.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/copy.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/cp.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/inc/name-rewrite.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/man.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/mcp-start.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/mcp.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/oas.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/openapi.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/rename.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/restart.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/start.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/status.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/stop.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/bundle/types.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/clear.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/cache/stats.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/infer.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/migrate.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/models.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/connector/test.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/man.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/ps.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/container/stop.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/args.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/namespace.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/reference-rewrite.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/reference-scan.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/inc/scaffold.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/rename.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/controller/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/get.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/link-dev.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/set.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/unset.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/env/use.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/build.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/dot.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/get.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/link-node-modules.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/link.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/man.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/msg.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/open.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/reset.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/restart.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/set.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/start.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/status.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/stop.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/update.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/framework/version.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/gina-dev.1.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/gina-framework.1.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/helper.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/export.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/import.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/i18n/scan.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/_host.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/build.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/man.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/image/run.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/inspector/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/inspector/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/inspector/open.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/man-render.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/kill.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/minion/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/msg.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/inc/scan.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/reset.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/port/set.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/backup.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/build.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/import.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/man.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/move.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/rename.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/restart.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/restore.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/start.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/status.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/project/stop.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/protocol/set.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/link-local.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/link-production.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/remove.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/rm.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/scope/use.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/arguments.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/check.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/secrets/scan.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/help.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/help.txt +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/list.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/man.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/service/start.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd/view/add.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd-status-format/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cmd-status-format/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/collection/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/collection/build.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/collection/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/collection/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/config.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/connector-config/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/connector-config/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/connector-error/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/connector-error/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/connector-registry/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/connector-registry/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cron/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cron/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/cron/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/domain/LICENSE +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/domain/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/domain/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/domain/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/dto/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/dto/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/dto-pipe/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/dto-pipe/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/dto-types/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/dto-types/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/generator/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/i18n/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/i18n/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/image-build/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/image-build/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/LICENSE +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inherits/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-events/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-events/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-redact/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/inspector-redact/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/instrument/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/instrument/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/job/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/job/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/job-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/json-config-header/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/json-config-header/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/default/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/file/lib/logrotator/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/file/lib/logrotator/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/mq/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/containers/mq/listener.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/helper.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/logger/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/math/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-dispatch/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-dispatch/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-http/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-http/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-server/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/mcp-server/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/merge/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/merge/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/merge/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/metrics/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/metrics/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/model.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-filters/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-filters/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-resolver/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/nunjucks-resolver/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/proc.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/release-watch/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/release-watch/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/render-cache/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/render-cache/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/render-cache-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/routing/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/routing/build.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/routing/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/routing/src/radix.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/routing-introspect/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/routing-introspect/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/secrets/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/secrets/src/backends/env.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/secrets/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/session-store.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/shell.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/state.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/swig-filters/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/swig-filters/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/swig-resolver/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/swig-resolver/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/src/loaders/http.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/src/loaders/memory.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/template-loaders/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/url/README.md +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/url/index.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/url/routing.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/uuid/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/uuid/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/validator.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/watcher/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/watcher/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/ws-framing/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/ws-framing/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/ws-query/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/ws-query/src/main.js +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/ws-session/package.json +0 -0
- /package/framework/{v0.5.26 → v0.6.0}/lib/ws-session/src/main.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
|
|
6
6
|
and is generated by [Changie](https://github.com/miniscruff/changie).
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
## 0.6.0 - 2026-07-28
|
|
10
|
+
### Added
|
|
11
|
+
* The audit trail can now carry a tamper-evidence hash chain. Opt in with `audit.chain.enabled: true` and a signing key (`audit.chain.secret`, a literal or a `${secret:VAR}` placeholder, or the `GINA_AUDIT_SECRET` environment variable) and every record gains a `hash` that chains from its predecessor — `HMAC-SHA256(secret, previousHash + canonical(record))`. The new offline command `gina audit:verify <bundle> @<project>` walks the trail and reports either the intact totals or the first break with its line and reason, exiting non-zero when the chain is broken. This detects any post-hoc edit, deletion, insertion or reordering of the trail by someone who does not hold the signing key. It is deliberately NOT a defence against the process that writes the records: that process holds the key and could forge a whole chain, so for that stronger adversary stream the trail to write-once (WORM / Object-Lock) storage, as the compliance guide already describes. Two boundaries are stated rather than implied: truncation at the exact tail is invisible to the chain (read the record count), and an empty trail verifies trivially. A crash mid-write leaves a torn tail that the next boot acknowledges with a chained break record and a loud warning rather than a crash loop. The boot refuses the deployment shapes a single linear chain cannot hold — no signing key, a connector `store` backend (whose seam carries no ordering guarantee), or two bundles chaining into the same `audit.file` — so a chain that cannot be trusted never starts silently. Server-side only; enabling the chain needs a bundle restart.
|
|
12
|
+
* `req.login(user, done)` now works for gina-native bundles and rotates the session id before binding the user — the session-fixation defense. Previously the framework's login shim only served Passport bundles; without Passport it threw `passport.initialize() middleware not in use`, so native bundles bound the user by hand with no rotation. The native branch now regenerates the session (destroying the pre-login record), binds the principal at `req.session.user`, stamps the absolute-timeout anchor, persists, and reports through the required callback; when the session provider exposes no `regenerate()` it binds without rotation and warns. Passport bundles are untouched — Passport's own `req.login` still wins, and the shim's Passport branch is byte-identical. Outstanding CSRF tokens survive the rotation: they are re-derived from the current session id on the next response.
|
|
13
|
+
* Opt-in absolute session timeout — `session({ absoluteTimeout: <ms> })` on the Session plugin, or `settings.json > session.absoluteTimeout` as the deployment default with bundle code winning (`absoluteTimeout: false` disables it). An authenticated session older than the cap — measured from login, the anchor `req.login()` stamps at session-id rotation; manually-bound sessions are anchored one request later — is destroyed on its next request regardless of activity, and the request proceeds with a fresh anonymous session, exactly as a naturally-expired record behaves. Fail-closed: when the record cannot be destroyed the authentication is still dropped. This is the fixed-cap half of session-lifetime control; idle expiry already existed (the cookie maxAge and the store-record TTL both roll with activity) and composes with it. Anonymous sessions are never touched, preserving `saveUninitialized: false` semantics, and without the option the plugin returns express-session's middleware unchanged. Declared in the published settings.json schema.
|
|
14
|
+
* `lib.authn` adds the password primitives that are dangerous to hand-roll. `hashPassword` mints a scrypt hash encoded as a self-describing PHC string (`$scrypt$ln=17,r=8,p=1$<salt>$<key>`), so the cost parameters travel with the hash and can be raised later without a flag day. `verifyPassword` compares in constant time and ALSO verifies existing `$argon2*$` and `$2a/2b/2y$` (bcrypt) hashes through your own project's `argon2` / `bcrypt` package, so a bundle arriving with credentials already hashed — including one that followed gina's own published interim guidance — keeps working; gina never mints those formats, so there is one mint path and one set of parameters to reason about. `needsRehash` reports which stored hashes are below current policy, and a successful login can upgrade them transparently — the one moment the plaintext is in hand. `dummyVerify` spends a matching amount of work on the account-not-found branch to close the user-enumeration oracle; always pass `{like: <a stored hash>}` so the cost is read from real data rather than drifting from it. `validatePasswordPolicy` checks length first per NIST SP 800-63B — a 12-character minimum with no mandatory character classes by default — with composition rules and a `deny` substring list available, and returns stable machine-readable error codes. Passwords are normalised to Unicode NFC on both sides, so a user who registers on one device and signs in from another is not locked out by an encoding difference. Gina still owns no user record, credential store or login route: these are helpers, not an identity provider.
|
|
15
|
+
* `lib.authn.createLockout()` adds an account-lockout engine — the credential-stuffing brake. Call `check(key, cb)` before spending a KDF so a locked account never reaches one, `recordFailure(key, cb)` on a failed attempt and `recordSuccess(key, cb)` on a good one; `reset(key, cb)` lifts a lock administratively. Defaults follow PCI-DSS v4.0.1 §8.3.4 — lock after 10 consecutive failures, for 30 minutes. The key is yours to choose (a user id, an email, an `email:ip` pair) because gina does not own the user record; pass `normalizeKey` whenever it comes from user input, or case variants of the same address each get their own counter and multiply the threshold. State lives in memory by default, which is per-process — pass a shared `store` (the same callback-shaped `get` / `set` / `del` contract the job and audit seams already use) for multi-replica correctness. Operations on a key are serialized, so failures arriving concurrently cannot each read the same counter and lose the count. Crossing the threshold writes one `auth.lockout` audit record on the transition, not one per attempt. Lockout is per-ACCOUNT and counts credential failures; it is not request-rate limiting, which is per-CLIENT and is tracked separately on the roadmap — the two defend different axes and neither substitutes for the other.
|
|
16
|
+
* `lib.authn` adds RFC 6238 TOTP helpers for a second factor, implemented against the RFC rather than taking a dependency. `generateTotpSecret()` mints a base32 secret, `otpauthURL({ secret, account, issuer })` builds the `otpauth://` URI every standard authenticator app scans as a QR code, `generateTotp(secret)` produces a code, and `verifyTotp(token, secret)` checks the current step plus one either side in constant time, returning `{ valid, counter }`. Replay defence is yours, and `counter` is what it needs: persist the accepted counter per user and refuse anything not strictly greater, or an observed code stays usable for its whole acceptance window — the RFC makes this the verifier's job and gina has no place to write it. Storing the secret is yours too; treat it as a credential and encrypt it at rest. A malformed code returns `{ valid: false }` rather than throwing, so an attacker learns nothing from the difference, while an unusable secret does throw — that is a configuration fault, not a login attempt. Recovery codes are deliberately not built: they are single-use random strings, so `hashPassword` plus your own table already expresses them.
|
|
17
|
+
### Fixed
|
|
18
|
+
* The `settings.json` schema now describes the `audit` block, so the audit trail configuration gets the same editor support as the rest of the file. All five keys — `enabled`, `file`, `store`, `actorKey` and `events.authz` — were undeclared, so an editor offered no completion, no type checking and no description on hover, and a mistyped key or a wrong type surfaced only as a boot refusal at the next restart. The declaration mirrors the boot lint rather than merely permitting the keys: `enabled` and `events.authz` are strictly boolean (a truthy string such as "true" would leave the trail silently off), `file` and `store` are non-empty strings and mutually exclusive, and unknown keys are rejected — so an editor now flags the same shapes the boot would refuse. Runtime behaviour is unchanged; the schemas are editor tooling, never enforced at boot.
|
|
19
|
+
* Fixed the control-plane dial regression introduced by the 0.5.26 loopback bind default: CLI-side clients (the command socket, the MQ speaker and file log containers, and `gina tail`) dialled `host_v4` while the daemon binds `bind_host`, so any deployment whose `host_v4` is a non-loopback address of the same machine — the common containerized shape — could not reach its own daemon and `bundle:start` aborted before the HTTP server ever bound. Clients now resolve the dial host through a locality check: a `host_v4` naming one of the machine's own interfaces dials the bind address (loopback by default, or `bind_host` when it is a concrete non-wildcard address), while a genuinely remote `host_v4` is dialled unchanged. The bind side is untouched, and the connection-refused error now names the dial target and the `bind_host` knob.
|
|
20
|
+
* Fixed `bind_host` persistence: a value written by `gina framework:set --bind-host=` was silently reverted to the loopback default by the very next CLI invocation (the settings regeneration had a disk-to-env read-back for every connection key except `bind_host`) and by every container bootstrap (`gina-init` rewrote settings.json with a hardcoded loopback value). The persisted value now survives both paths; `GINA_BIND_HOST` still takes precedence when set, and unresolved template placeholders are skipped rather than preserved.
|
|
21
|
+
* Fixed the Couchbase session store's `touch()`: an internal idle-check compared an elapsed value in milliseconds against a TTL in seconds, so it fired roughly 1000x sooner than intended and left `lastModified` un-refreshed on most calls — even though every `touch()` extends the document's expiry regardless. The stamp now tracks each extension, which keeps the client-side session countdown measuring from the right origin. The SDK 4 store additionally writes `lastModified` as an ISO 8601 UTC string, matching the redis, sqlite, mongodb and scylladb session stores; it previously wrote a zone-less local-time value that the browser re-parsed in its own timezone, skewing the countdown by the offset between them.
|
|
22
|
+
* Fixed session-record TTL resolution in the redis, sqlite, mongodb and scylladb session stores: an implicit one-day default made the cookie-`maxAge` fallback in `set()`/`touch()` unreachable, so the stored record's lifetime ignored the session cookie unless a `ttl` was configured explicitly — a 1-hour cookie left its record alive server-side for 24 hours, and a 7-day cookie was silently cut to 24 hours. When neither the store options nor the connectors.json `ttl` is set, the record TTL now follows the cookie's `maxAge` (one day only when the cookie has none), matching the Couchbase session stores. An explicitly configured `ttl` still wins over `maxAge`. Note this moves record lifetimes in BOTH directions relative to the old accidental 24-hour cap.
|
|
23
|
+
* The `settings.json` schema now describes the `session` block, so the session plugin's configuration gets the same editor support as the rest of the file. The three consumed keys — `session.cookie.sameSite`, `session.cookie.httpOnly` and `session.cookie.secure` — were undeclared, so an editor offered no completion, no type checking and no hover description for a documented configuration surface. The declaration mirrors the plugin's own factory-time validation (`sameSite` one of lax/strict/none, `httpOnly` boolean, `secure` true, false or "auto") and rejects unread keys — putting `maxAge` or a store `ttl` under `settings.json > session` has never had any effect, and an editor now says so. Runtime behaviour is unchanged; the schemas are editor tooling, never enforced at boot.
|
|
24
|
+
* Fixed the SQLite session store expiring the very session it was asked to refresh. `touch()` stamped `now + ttl` without first checking the resolved ttl, so as a session neared its expiry — express-session's `cookie.maxAge` is a decaying remainder, which truncates to zero in the final second and turns negative once expired — the store wrote an already-past expiry and ended the session early. It now performs no write and returns cleanly on a non-positive ttl, matching the Redis, MongoDB and ScyllaDB stores, which already guarded this. Sessions with a positive ttl are refreshed exactly as before.
|
|
25
|
+
* Corrected the published `connectors.json` JSON-schema declarations for the session-store `ttl` and `prefix` keys. Both were labelled "Redis only" while `ttl` is in fact read by the Redis, SQLite, MongoDB and ScyllaDB stores and `prefix` by Redis and SQLite, so editors steered you away from keys that do work. The `ttl` entry also still advertised a default of 86400, which stopped being true when an unset ttl began deferring to the cookie's `maxAge`; that stale default is gone and both descriptions now name the stores that read them, plus the Couchbase stores which take these as constructor options instead.
|
|
26
|
+
* The Couchbase session store now requires `options.db` — the already-open bucket the model layer creates from the `session` connector entry (`getModel('session').getConnection()`) — and fails fast with an actionable error when it is missing or not a bucket, instead of crashing at bundle init inside a dead self-connect path that called the SDK v2 `openBucket()` API, absent from the supported v3/v4 SDKs. The connection options that only fed that dead path (`host`, `hosts`, `username`, `password`, `bucket`, `cachefile`) were removed with it.
|
|
27
|
+
* Server-side getRoute() no longer crashes when a proxied context is active while no proxy hostname is resolvable (worker global and envConf fallback both unset): the route degrades to its direct hostname (route.isProxyHost flips false so toUrl() cannot stringify an unset value into the emitted URL) and a once-per-process warning names the degraded state; the url template filters hold getRoute's own resolution so their per-request override can never force an unset value over it, and the non-proxied branch now requires a truthy worker global (its typeof gate admitted null).
|
|
28
|
+
### Security
|
|
29
|
+
* The gina-native `logout()` shim now destroys the persisted session record instead of only clearing `req.session.user`: previously the store record, the session id and every other session key survived to TTL after logout — a leaked or intercepted session id stayed valid server-side long after the user logged out. `logout()` calls the session's own `destroy()` when it exposes one (express-session), degrades gracefully when it does not, and accepts an optional callback — `req.logout(function(err) { ... })`. Review flows that relied on other session keys surviving logout: the whole record is gone afterwards. The session cookie stays the consumer's to expire (its name is not discoverable by the framework), and Passport bundles are unaffected — the shim never installs when Passport is initialized.
|
|
30
|
+
|
|
9
31
|
## 0.5.26 - 2026-07-25
|
|
10
32
|
### Added
|
|
11
33
|
* Bundles can now invert their authorization posture with `settings.json > auth.requireAuthByDefault: true`: every route requires an authenticated session unless its `routing.json` `param` block carries `"public": true`. It composes with the existing `requireAuth` / `roles` / `policy` keys rather than replacing them — an explicitly gated route behaves exactly as before, and `public` can never un-gate one. The mode is strictly opt-in and strictly boolean (a truthy string refuses to boot rather than leaving every route silently ungated), and it is keyed per bundle, so one bundle enabling it never changes the posture of a sibling in a merged-mode process. The injected routes the framework adds for you — the site root, the custom error page, `/_status` and the upload endpoints — ship `"public": true`, so enabling the mode does not take them offline. The boot refuses three configurations the mode would otherwise make dangerous: `"public": true` on a route that also declares an explicit gate key; a login route the mode would gate, which would bounce to itself in an infinite redirect; and a mode-gated route that also declares `cache`, because the render cache is read before authorization runs and its key carries no user identity. `gina bundle:openapi` reflects the mode, so the emitted specification never declares a newly gated route as unauthenticated. Enable it in a non-production environment first and read the boot line, which reports how many routes it just gated.
|
package/README.md
CHANGED
|
@@ -27,12 +27,13 @@ MVC framework for Node.js and Bun with built-in HTTP/2, multi-bundle architectur
|
|
|
27
27
|
| Template engine | [`@rhinostone/swig`](https://github.com/gina-io/swig) — maintained fork with CVE-2023-25345 patched; streaming SSE/chunked via `renderStream()`. Nunjucks supported as opt-in via `render.engine = "nunjucks"` or per-section `"ext": ".njk"` |
|
|
28
28
|
| Forms & validation | One rule engine for client and server — live checks, cross-field rules, ARIA states, localised messages; the server enforces the same rules on submit |
|
|
29
29
|
| DTOs | `gina.dto` schema builder — request validation with localised 422s (`param.dto`), response shaping (`param.responseDto`), JSON Schema export |
|
|
30
|
-
| Sessions | Hardened session plugin (SameSite / HttpOnly / Secure defaults) — Redis, SQLite, MongoDB, Couchbase, and ScyllaDB stores |
|
|
30
|
+
| Sessions | Hardened session plugin (SameSite / HttpOnly / Secure defaults) — Redis, SQLite, MongoDB, Couchbase, and ScyllaDB stores; session-id rotation on login, opt-in absolute timeout, record destroyed on logout |
|
|
31
31
|
| File uploads | Multipart via the maintained [`@rhinostone/busboy`](https://github.com/gina-io/busboy) fork — named upload groups with per-group extension allow-lists, size / count limits, and target dirs |
|
|
32
32
|
| Async jobs | `self.startJob()` background jobs — durable SQLite / MongoDB / Redis stores, retries with backoff, HMAC-signed completion webhooks, `/_gina/jobs/:id` status endpoint |
|
|
33
33
|
| Response caching | Per-route render cache — memory / fs / Redis tiers, cross-replica warm start, event-driven invalidation, RFC 9211 `Cache-Status` |
|
|
34
|
-
|
|
|
35
|
-
|
|
|
34
|
+
| Authentication | `lib.authn` primitives — scrypt password hashing as self-describing PHC strings (argon2 / bcrypt verify-only for migration), NIST SP 800-63B policy, enumeration-safe `dummyVerify`, PCI-DSS account lockout, RFC 6238 TOTP |
|
|
35
|
+
| Route authorization | `requireAuth` / `roles` / `policy` per route or deny-by-default, login bounce with `resumeRequest()`, `self.hasRole()` |
|
|
36
|
+
| Audit trail | Opt-in append-only JSONL audit log (`self.audit()`), authorization denials auto-recorded, always-on request ids; opt-in HMAC hash chain verified offline by `gina audit:verify` |
|
|
36
37
|
| CSRF protection | Signed double-submit token middleware + Origin/Referer pre-filter + hardened session cookie |
|
|
37
38
|
| Security headers | CSP with per-response nonces, HSTS, COOP / COEP / CORP, Referrer-Policy and the X-* family — per-header plugins or one `SecurityHeaders` wrapper |
|
|
38
39
|
| Secrets | `${secret:KEY}` placeholders in bundle config — fail-closed, env-backed; `secrets:scan` / `secrets:check` CLI |
|
|
@@ -59,28 +60,39 @@ open https://localhost:3100
|
|
|
59
60
|
|
|
60
61
|
> **npm 12+** blocks install scripts by default, and gina's post-install bootstraps `~/.gina` and the framework dependencies. Install with `npm install -g gina@latest --allow-scripts=gina`, or allow it once for all global installs with `npm config set allow-scripts=gina --location=user`. (Not needed on npm ≤ 11.)
|
|
61
62
|
|
|
62
|
-
## What's in 0.
|
|
63
|
+
## What's in 0.6.0
|
|
63
64
|
|
|
64
|
-
> **
|
|
65
|
-
>
|
|
66
|
-
>
|
|
67
|
-
>
|
|
68
|
-
>
|
|
69
|
-
>
|
|
65
|
+
> **Two behaviour changes to check before upgrading.** Neither refuses a boot,
|
|
66
|
+
> but both change how an untouched bundle behaves. Session records in the redis,
|
|
67
|
+
> sqlite, mongodb and scylladb stores now follow the session cookie's `maxAge`
|
|
68
|
+
> when no `ttl` is configured, instead of an implicit one-day cap — lifetimes
|
|
69
|
+
> move in **both** directions, so set an explicit `ttl` if you relied on the old
|
|
70
|
+
> 24-hour behaviour. And `req.logout()` now destroys the whole session record
|
|
71
|
+
> rather than only clearing `req.session.user`, so review any flow that expected
|
|
72
|
+
> other session keys to survive logout. See the
|
|
70
73
|
> [migration guide](https://gina.io/docs/migration) for each.
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
- **
|
|
81
|
-
- **
|
|
82
|
-
- **
|
|
83
|
-
- **
|
|
75
|
+
> **Action required — settings reset.** `0.6.0` is a shortVersion bump (`0.5` →
|
|
76
|
+
> `0.6`), so on install the framework creates a fresh `~/.gina/0.6/settings.json`
|
|
77
|
+
> from defaults — your `~/.gina/0.5/settings.json` customizations (log level,
|
|
78
|
+
> port, culture, timezone, etc.) are **not** carried forward. Re-apply them with
|
|
79
|
+
> `gina framework:set`, or copy the values across. Root-level state
|
|
80
|
+
> (`~/.gina/main.json`, `projects.json`, `ports.json`, `gina.db`) is shared
|
|
81
|
+
> across short versions and is unaffected.
|
|
82
|
+
|
|
83
|
+
- **Added — a tamper-evidence hash chain for the audit trail.** Opt in with `audit.chain.enabled: true` and a signing key (`audit.chain.secret`, a literal or a `${secret:VAR}` placeholder, or `GINA_AUDIT_SECRET`) and every record gains a `hash` chaining from its predecessor — `HMAC-SHA256(secret, previousHash + canonical(record))`. The new offline `gina audit:verify <bundle> @<project>` walks the trail and reports either the intact totals or the first break with its line and reason, exiting non-zero when the chain is broken. This detects any post-hoc edit, deletion, insertion or reordering by someone who does not hold the signing key; it is deliberately *not* a defence against the process that writes the records, which holds the key — for that adversary, stream the trail to WORM / Object-Lock storage as the compliance guide describes. Two boundaries are stated rather than implied: truncation at the exact tail is invisible to the chain (read the record count), and an empty trail verifies trivially. The boot refuses the deployment shapes a single linear chain cannot hold — no signing key, a connector `store` backend, or two bundles chaining into the same `audit.file` — so a chain that cannot be trusted never starts silently. Server-side — restart your bundles. (#COMPLY2)
|
|
84
|
+
- **Added — `lib.authn`, the authentication primitives that are dangerous to hand-roll.** `hashPassword` mints scrypt hashes as self-describing PHC strings (`$scrypt$ln=17,r=8,p=1$<salt>$<key>`), so the cost travels with the hash and can be raised later without a flag day. `verifyPassword` compares in constant time and *also* verifies existing `$argon2*$` and `$2a/2b/2y$` (bcrypt) hashes through your own project's package, so a bundle arriving with credentials already hashed keeps working; paired with `needsRehash`, a successful login upgrades them transparently and the store migrates itself with no password resets. `dummyVerify` spends matching work on the account-not-found branch to close the user-enumeration oracle — always pass `{like: <a stored hash>}` so the cost is read from real data. `validatePasswordPolicy` checks length first per NIST SP 800-63B (12 characters, no mandatory character classes by default). `createLockout()` adds the credential-stuffing brake, defaulting to PCI-DSS v4.0.1 §8.3.4 — 10 consecutive failures, 30 minutes — serialized per key so concurrent failures cannot lose the count, with one `auth.lockout` audit record on the transition. And `generateTotpSecret` / `otpauthURL` / `generateTotp` / `verifyTotp` implement RFC 6238 for a second factor; replay defence is yours, and the returned `counter` is what it needs. Gina still owns no user record, credential store or login route — these are helpers, not an identity provider. Server-side — restart your bundles. (#COMPLY3)
|
|
85
|
+
- **Added — `req.login()` works for gina-native bundles and rotates the session id.** Previously the login shim only served Passport bundles; without Passport it threw, so native bundles bound the user by hand with no rotation at all. The native branch now regenerates the session — destroying the pre-login record, the session-fixation defence — binds the principal at `req.session.user`, stamps the absolute-timeout anchor, persists, and reports through the required callback; where the session provider exposes no `regenerate()` it binds without rotation and warns. Anything stored in the pre-login session is destroyed by the rotation: read it before the call and re-set it in the callback if it must survive. Outstanding CSRF tokens re-derive from the current session id on the next response, and Passport bundles are untouched. Server-side — restart your bundles. (#COMPLY4)
|
|
86
|
+
- **Added — an opt-in absolute session timeout.** `session({ absoluteTimeout: <ms> })` on the Session plugin, or `settings.json > session.absoluteTimeout` as the deployment default with bundle code winning (`absoluteTimeout: false` disables it). An authenticated session older than the cap — measured from login, not from last activity — is destroyed on its next request and the request proceeds with a fresh anonymous session, exactly as a naturally-expired record behaves. Fail-closed: when the record cannot be destroyed the authentication is still dropped. This is the fixed-cap half of session-lifetime control; idle expiry already existed (the cookie `maxAge` and the store-record TTL both roll with activity) and composes with it. Anonymous sessions are never touched, preserving `saveUninitialized: false` semantics. Declared in the published settings.json schema. Server-side — restart your bundles. (#COMPLY4)
|
|
87
|
+
- **Security — `req.logout()` destroys the persisted session record.** It previously only cleared `req.session.user`: the store record, the session id and every other session key survived to TTL, so a leaked or intercepted session id stayed valid server-side long after the user logged out. It now calls the session's own `destroy()` when one is exposed, degrades gracefully when it is not, and accepts an optional callback — `req.logout(function (err) { … })`. **Review flows that relied on other session keys surviving logout: the whole record is gone afterwards.** The session cookie stays yours to expire (its name is not discoverable by the framework), and Passport bundles are unaffected — the shim never installs when Passport is initialized.
|
|
88
|
+
- **Fixed — co-located CLIs reach the control plane again.** 0.5.26's loopback bind default carried a dial-side regression: CLI-side clients (the command socket, the MQ speaker and file log containers, and `gina tail`) dialled `host_v4` while the daemon binds `bind_host`, so any deployment whose `host_v4` is a non-loopback address of the same machine — the common containerized shape — could not reach its own daemon, and `bundle:start` aborted before the HTTP server ever bound. Clients now resolve the dial host through a locality check: a `host_v4` naming one of the machine's own interfaces dials the bind address, while a genuinely remote `host_v4` is dialled unchanged. The bind side is untouched, so nothing is newly exposed, and the connection-refused error now names both the dial target and the `bind_host` knob. If you applied the `GINA_BIND_HOST=0.0.0.0` workaround purely to un-break co-located CLIs, you can drop it after upgrading. (#B160)
|
|
89
|
+
- **Fixed — `gina framework:set --bind-host=` now persists.** The value was silently reverted to the loopback default by the very next CLI invocation — the settings regeneration had a disk-to-env read-back for every connection key except `bind_host` — and again by every container bootstrap, which rewrote settings.json with a hardcoded value. The persisted value now survives both paths; `GINA_BIND_HOST` still takes precedence when set. (#B161)
|
|
90
|
+
- **Fixed — session records honour the cookie `maxAge`.** In the redis, sqlite, mongodb and scylladb stores an implicit one-day default made the cookie-`maxAge` fallback in `set()` / `touch()` unreachable, so a record's lifetime ignored the session cookie unless a `ttl` was configured explicitly — a 1-hour cookie left its record alive server-side for 24 hours, and a 7-day cookie was silently cut to 24 hours. When neither the store options nor the connectors.json entry sets a `ttl`, the record TTL now follows the cookie's `maxAge` (one day only when the cookie has none), matching the Couchbase stores. An explicitly configured `ttl` still wins. **Note this moves record lifetimes in both directions** relative to the old accidental 24-hour cap. (#B163)
|
|
91
|
+
- **Fixed — the SQLite session store no longer expires the session it was asked to refresh.** `touch()` stamped `now + ttl` without first checking the resolved ttl — and express-session's `cookie.maxAge` is a decaying remainder, which truncates to zero in the final second and turns negative once expired — so a session near its expiry had an already-past expiry written to it and ended early. It now performs no write and returns cleanly on a non-positive ttl, matching the redis, mongodb and scylladb stores which already guarded this. (#B166)
|
|
92
|
+
- **Fixed — the Couchbase session store's `lastModified` is refreshed and UTC.** An internal idle check compared an elapsed value in milliseconds against a TTL in seconds, so it fired roughly 1000× sooner than intended and left `lastModified` un-refreshed on most calls — even though every `touch()` extends the document's expiry regardless. The stamp now tracks each extension, keeping the client-side session countdown measuring from the right origin. The SDK 4 store additionally writes it as an ISO 8601 UTC string, matching the redis, sqlite, mongodb and scylladb stores; it previously wrote a zone-less local-time value that the browser re-parsed in its own timezone. (#B165)
|
|
93
|
+
- **Fixed — the Couchbase session store requires its open bucket explicitly.** It now takes `options.db` — the already-open bucket the model layer creates from the `session` connector entry (`getModel('session').getConnection()`) — and fails fast with an actionable error when it is missing or is not a bucket, instead of crashing at bundle init inside a dead self-connect path that called the SDK v2 `openBucket()` API, absent from the supported v3 and v4 SDKs. The connection options that only fed that dead path (`host`, `hosts`, `username`, `password`, `bucket`, `cachefile`) were removed with it. No working deployment is affected — the path they fed could not succeed on a supported SDK. (#B167)
|
|
94
|
+
- **Fixed — server-side `getRoute()` no longer crashes when no proxy hostname is resolvable.** With the worker-wide proxied latch set but both proxy-hostname sources unset — the boot-time global and the per-render `envConf` fallback, each of which the framework itself can legitimately leave empty — every `getRoute()` call threw a `TypeError`, taking down any render or readiness probe that resolved a route. The route now degrades to its direct hostname and `route.isProxyHost` flips false, so `toUrl()` cannot stringify an unset value into the emitted URL; a once-per-process warning names the degraded state. The `url` template filters hold `getRoute()`'s own resolution so their per-request override can never replace a usable value with an unset one. Server-side — restart your bundles. (#B168)
|
|
95
|
+
- **Fixed — the JSON schemas now describe the `audit` and `session` blocks.** All five audit keys (`enabled`, `file`, `store`, `actorKey`, `events.authz`) and the three consumed session-cookie keys (`sameSite`, `httpOnly`, `secure`) were undeclared, so an editor offered no completion, no type checking and no description on hover, and a mistyped key surfaced only as a boot refusal at the next restart. Each declaration mirrors the corresponding boot lint or factory-time validation rather than merely permitting the keys, and rejects unread keys — putting `maxAge` or a store `ttl` under `settings.json > session` has never had any effect, and an editor now says so. Separately, the `connectors.json` schema no longer labels the session-store `ttl` and `prefix` keys "Redis only" — `ttl` is read by the redis, sqlite, mongodb and scylladb stores and `prefix` by redis and sqlite — and its stale `86400` default is gone. Runtime behaviour is unchanged; the schemas are editor tooling, never enforced at boot.
|
|
84
96
|
|
|
85
97
|
See the full [Changelog](./CHANGELOG.md) and [Roadmap](./ROADMAP.md).
|
|
86
98
|
|
package/ROADMAP.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Gina — Roadmap
|
|
2
2
|
|
|
3
|
-
This roadmap covers planned features, architectural improvements, new connectors, and AI integration. Items marked ✅ are shipped. All planned items are open to community contribution — see [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|
3
|
+
This roadmap covers planned features, architectural improvements, new connectors, and AI integration. Items marked ✅ are shipped; **⏸ marks work that is scoped and measured but deliberately deferred** — it gets built when someone asks for it, and every deferred row names an interim pattern to use in the meantime. All planned items are open to community contribution — see [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|
4
4
|
|
|
5
5
|
> **Docs:** [gina.io/docs](https://gina.io/docs/) · **Issues:** [github.com/gina-io/gina/issues](https://github.com/gina-io/gina/issues)
|
|
6
6
|
|
|
@@ -51,8 +51,11 @@ This roadmap covers planned features, architectural improvements, new connectors
|
|
|
51
51
|
| **Q3 2026** | `0.5.24` ✅ | **Added**: upload progress for the staged upload client layer — the staging POST reports real client-to-server wire progress via a new `uploadProgress.<id>` form event and an opt-in declarative `<progress>` / percent indicator (#R8, slice 1) · drag-and-drop — a file input binds a named element as a dropzone that routes dropped files through the exact same staging pipeline as the native picker, opt-in and explicit-id-only with `idle`/`over`/`dropped` CSS state hooks (#R8, slice 2) · an incident `ref` on every error response — a short voice-relayable correlation code (present in all scopes) that a server-side log line pairs with the full error detail before the wire copy is stripped, so support can resolve a user-relayed ref to the exact failure even in production (#ERRREF) · a per-upload-group `simulateWriteError` flag (non-production only) to verify the upload write-error crash-guard on your own surface after an upgrade (#B144) · **Fixed**: the staged upload client layer no longer corrupts binary uploads — the multipart body is now a Blob of raw file bytes instead of a UTF-8-inflating DOMString, so images / PDFs / archives are stored byte-identical (the defect only surfaced on gina ≥ 0.5.22; corrupted files are losslessly recoverable) (#B148) · a misconfigured upload group whose destination directory cannot be created answers a guarded 500 instead of crashing the bundle (#B145) · a file input declaring only its upload action is no longer silently repointed at the reset/delete route (#B146) · an upload no longer throws in its success handler when no preview element is present (#B147) |
|
|
52
52
|
| **Q3 2026** | `0.5.25` ✅ | **Added**: microservices readiness — machine-caller authentication (an `Authorization: Bearer` key named in `settings.json > auth.machine.callers` satisfies route authorization without a session, opt-in and fail-closed, constant-time compared against boot-computed hashes, with an optional custom authenticator hook for JWT/HMAC/api-key schemes), cross-service request-id propagation (the always-on request id forwarded as `x-request-id` on every `self.query()` and echoed back on every response, so one logical request stays correlatable across bundles), an ungated `GET /_gina/health/check` on the express engine so container liveness probes no longer require the isaac engine, and the authorization contract in `bundle:openapi` (gated routes emit `401`/`403` entries and a `bearerAuth` security scheme, never role or policy names) · the `controller:` CLI group — `controller:add` scaffolds a namespace controller with per-action stubs and prints paste-ready routing rules, `controller:remove`/`rm` deletes only after a reference-aware scan that refuses while any routing rule or `requireController()` still points at it, and `controller:rename` rewrites the references it can resolve safely and reports the rest (#R9) · transient-vs-permanent classification for datastore connector errors — `err.isTransient` + a normalized `err.transientReason` on every connector query failure across all six datastore connectors, so an application can render an honest retry response without string-matching vendor error text; conservative by design, an unrecognized or genuinely permanent error classifies as permanent (#CE1) · `settings.swig.autoescape` to opt in to Swig output escaping (default unchanged; a non-boolean now refuses boot) · `server.proxy.requireForwardedHeaders` to require `X-Forwarded-Host` for proxy classification, the deterministic alternative to the port-less-Host heuristic · a `processing` state on the staged upload progress indicator, covering the server post-processing window so a full bar reads as working rather than stuck (#R8) · **Fixed**: absolute URLs poisoned by port-less internal calls — a health probe, service-mesh hop or service-DNS sibling call could rewrite the worker's proxy-host context and leak the internal host into later renders' `getUrl`/`url` output and cross-bundle redirect targets; emitting requests now prefer their own classification on both engines (#B152) · the Couchbase connector no longer hangs a request when an N1QL query fails at the socket level with no query-error envelope — the callback went un-fired and the request never settled (#B153) · a file input declaring only its staging upload action no longer emits a spurious warning-and-error pair on every bind · a staged-upload removal matching no preview now logs a diagnostic instead of silently skipping its whole cleanup path, including the temp-file delete (#B150) |
|
|
53
53
|
| **Q3 2026** | `0.5.26` ✅ | **Security**: a route pairing an authorization key (`param.requireAuth` / `param.roles` / `param.policy`) with `cache` now refuses to boot — both render-cache serve points run BEFORE the authorization gate and the cache key carries no user identity, so the first authenticated response was replayed verbatim to every later anonymous caller; as a second layer the render delegates never store a body for a gated route even if the configuration bypassed the lint (#B158) · a `method: "ws"` route declaring an authorization key now refuses to boot — a WebSocket handshake is answered by the engine's extended-CONNECT handler and never reaches the gate, so those keys could never be enforced while the boot line still counted the route as protected; authenticate inside the `wsHandler`, which receives the full request (#B159) · the framework control-plane listeners now bind an explicit host defaulting to loopback — a new `bind_host` setting (env `GINA_BIND_HOST`, `gina framework:set --bind-host=`), separate from `host_v4`, so exposing the command socket and MQ listener beyond the local host is a deliberate opt-in · a command name arriving over the framework socket is constrained to the shipped `lib/cmd/` namespace before it resolves, and an unresolvable name is answered on the connection instead of ending the daemon for every other client · the MCP Streamable HTTP transport refuses to start without a bearer token once an ambient protection is removed (a non-loopback bind, or `allowedOrigins: ["*"]`), with a new `allowInsecure` waiver for deployments that restrict access upstream · **Added**: deny-by-default authorization — `settings.json > auth.requireAuthByDefault: true` requires an authenticated session on every route unless its `param` block carries `"public": true`; opt-in, strictly boolean, keyed per bundle so one bundle never changes a sibling's posture in merged mode, with the framework-injected routes shipping exempt and boot refusals for the login-route lockout, the `public`-plus-explicit-key contradiction, and a mode-gated route that also declares `cache`; `bundle:openapi` follows the mode (#COMPLY10) · a boot-time production transport posture guard — a cleartext scheme outside the `local` scope warns once at boot, `server.requireHttps` refuses to start instead (pre-listen, so the port is never reachable), and `server.allowInsecure` acknowledges that TLS terminates upstream (#COMPLY9) · **Fixed**: Couchbase client-side query timeouts classify as transient and keep their message — the connector rebuilt the error from the query `cause` envelope the SDK attaches to every query error, so a client-side timeout became an empty-message `Error` that had lost the typed class name the classifier matches on (#B153) · `gina bundle:mcp-start --transport=http` now actually applies `GINA_MCP_AUTH_TOKEN` — the resolver read `process.env` directly while the CLI had already moved every `GINA_*` variable into the framework environment, so a deployment supplying the token only that way ran with no authentication · a `.sql` `@options` annotation that silently did nothing now warns, naming the ignored keys and showing the working form (#B155) · the `settings.json` and `routing.json` schemas now describe the route-authorization vocabulary, so an editor no longer flags a valid deny-by-default configuration as invalid · `lib/merge`'s JSDoc no longer documents an inverted `override` default |
|
|
54
|
-
| **Q4 2026** | `0.6.0` | Security
|
|
55
|
-
| **Q1 2027** | `0.
|
|
54
|
+
| **Q4 2026** | `0.6.0` ✅ | **Security**: `req.logout()` now destroys the persisted session record instead of only clearing `req.session.user` — the store record, the session id and every other session key previously survived to TTL, so a leaked or intercepted session id stayed valid server-side long after the user logged out; it now accepts an optional callback, and Passport bundles are unaffected · **Added**: an opt-in tamper-evidence hash chain for the audit trail — `audit.chain` plus a signing key gives every record an HMAC that chains from its predecessor, and the new offline `gina audit:verify <bundle> @<project>` walks the trail and reports either the intact totals or the first break, so any post-hoc edit, deletion, insertion or reordering by someone who does not hold the key is detectable; the boot refuses the deployment shapes a single linear chain cannot hold rather than starting a chain that cannot be trusted (#COMPLY2) · `lib.authn` — the authentication primitives that are dangerous to hand-roll: scrypt password hashing encoded as self-describing PHC strings so the cost can be raised without a flag day, with argon2 and bcrypt verify-only routing through the project's own package so a store arriving with existing credentials keeps working and migrates itself on the next successful login, a `dummyVerify` that closes the user-enumeration oracle, NIST SP 800-63B password policy, a PCI-DSS v4.0.1 §8.3.4 account-lockout engine, and RFC 6238 TOTP; gina still owns no user record, credential store or login route (#COMPLY3) · `req.login(user, done)` now works for gina-native bundles and rotates the session id before binding the user — the session-fixation defence; it previously threw without Passport, so native bundles bound the user by hand with no rotation at all (#COMPLY4) · an opt-in absolute session timeout — `session({ absoluteTimeout })` or `settings.json > session.absoluteTimeout` — caps an authenticated session's total lifetime measured from login regardless of activity, composing with the idle expiry that already existed (#COMPLY4) · **Fixed**: co-located CLIs reach the control plane again — 0.5.26's loopback bind default left CLI-side clients dialling `host_v4` while the daemon binds `bind_host`, so any deployment whose `host_v4` is a non-loopback address of the same machine could not reach its own daemon and `bundle:start` aborted before the HTTP server ever bound (#B160) · `gina framework:set --bind-host=` now persists across the settings regeneration that runs on every command and across container bootstraps (#B161) · session records in the redis, sqlite, mongodb and scylladb stores now honour the cookie `maxAge` when no `ttl` is configured, instead of an implicit one-day default that made the fallback unreachable — record lifetimes move in both directions relative to the old 24-hour cap (#B163) · the SQLite store no longer expires the very session it was asked to refresh, guarding a non-positive resolved ttl as its siblings already did (#B166) · the Couchbase store's `touch()` re-stamps `lastModified` on every extension — an internal idle check compared milliseconds against seconds — and the SDK 4 store writes it as an ISO 8601 UTC string, matching the other stores (#B165) · the Couchbase session store now requires the already-open bucket as `options.db` and fails fast with an actionable error instead of crashing at bundle init inside a dead SDK v2 self-connect path (#B167) · server-side `getRoute()` no longer crashes when a proxied context is active while no proxy hostname is resolvable — the route degrades to its direct hostname instead of throwing, so a render or readiness probe that resolves a route survives the state (#B168) · the `settings.json` schema now describes the `audit` and `session` blocks, and the `connectors.json` schema no longer labels the session-store `ttl` and `prefix` keys "Redis only" nor advertises a stale 86400 default — editor tooling only, runtime behaviour unchanged |
|
|
55
|
+
| **Q1 2027** | `0.6.x` | HTTP/2 priorities (blocked on Node scheduler hooks) · Beemaster admin + visual translation editor |
|
|
56
|
+
| **2027** | `0.7.0` | Performance — runtime CPU profiling baseline · multipart & WebSocket hot-path acceleration · render/log hot-path cleanups (SIMD scanner deferred, measure-gated) |
|
|
57
|
+
| **2027** | `0.8.0` | Financial-messaging foundations — XML request/response handling · pluggable message-schema validation · IBAN/BIC validation rules · money & ISO 4217 minor-unit utilities · idempotency keys · sequence primitive · OAuth2 client-credentials egress |
|
|
58
|
+
| **2027** | `0.9.0` | Financial-integration heavyweights — entity-layer datastore transaction seam · message-queue connector family (AMQP / Kafka / IBM MQ) |
|
|
56
59
|
| **Q3 2027** | `1.0.0` | First stable release — Windows alpha compatibility is a hard gate |
|
|
57
60
|
|
|
58
61
|
---
|
|
@@ -110,7 +113,7 @@ Stub commands confirmed in source — handler files exist but are empty or comme
|
|
|
110
113
|
| ✅ | **`protocol:remove`** — Revert a bundle to the project's default protocol/scheme by removing its `settings.json` override (no shared `ports*.json` mutation), with `--dry-run` / `--force`. | `0.4.1-alpha.2` | 2026-05-31 |
|
|
111
114
|
| ✅ | **`minion:list`** — List the running bundle child-processes ("minions") of a project, or of every project, grouped by project. `--format=json` supported. | `0.4.1-alpha.2` | 2026-05-31 |
|
|
112
115
|
| ✅ | **`minion:kill`** — Reap a project's running bundle child-processes ("minions") — both pidfile-tracked and `ps`-discovered orphans — with a graceful SIGTERM/SIGKILL escalation and a `--dry-run` preview. | `0.4.1-alpha.2` | 2026-05-31 |
|
|
113
|
-
| 📋 | **`gina --status` / `-t`** — Top-level health check: print whether the framework daemon is running, its version, and active bundle count. Requires adding `--status`/`-t` entries to `aliases.json` and implementing `framework/status.js`. | `0.
|
|
116
|
+
| 📋 | **`gina --status` / `-t`** — Top-level health check: print whether the framework daemon is running, its version, and active bundle count. Requires adding `--status`/`-t` entries to `aliases.json` and implementing `framework/status.js`. | `0.6.x` | Q4 2026 |
|
|
114
117
|
| ✅ | **`bundle:copy` / `bundle:cp`** — Duplicate a bundle (source files + config) under a new name within the same project, with a word-boundary name rewrite, a fresh full protocol/scheme/env port matrix, and `--dry-run` / `--force`. | `0.4.1-alpha.2` | 2026-05-31 |
|
|
115
118
|
| ✅ | **`project:status`** — Show the running/stopped state of each bundle in a project with PID and port info. | `0.4.1-alpha.2` | 2026-05-30 |
|
|
116
119
|
|
|
@@ -166,7 +169,7 @@ Stub commands confirmed in source — handler files exist but are empty or comme
|
|
|
166
169
|
| ✅ | **Explicit exports for global helpers** — `getContext`, `setContext`, `_`, `requireJSON` etc. available as explicit `require('gina/gna').getContext` imports alongside the existing global injection. Enables IDE navigation and static analysis. | `0.3.3-alpha.3` | 2026-04-09 |
|
|
167
170
|
| ✅ | **TypeScript declaration files** — `.d.ts` declarations for the public surface: `SuperController`, `EntitySuper`, connector config shapes, `routing.json` schema, `PathObject`, `uuid`, all config file interfaces, `GinaRequest`/`GinaResponse`. No TS migration of internals — just declarations for consumer projects. `package.json` wired with `"types"` and `"typesVersions"`. | `0.3.3-alpha.3` | 2026-04-09 |
|
|
168
171
|
| ✅ | **Auto-generated `types/gna.d.ts` from JSDoc** (#M9) — `script/generate_gna_types.js` reads the `GLOBAL_EXPORTS` inventory from the gna-exports unit test plus the JSDoc on `framework/v*/core/gna.js` and emits `types/gna.d.ts` with one entry per global export. Two npm scripts: `npm run types:gen` regenerates, `npm run types:check` exits non-zero if drifted. A `gna-types-drift.test.js` unit test re-runs the generator in memory on every test pass — the JSDoc on `core/gna.js` is the single source of truth. Closes the #M8 → #M9 loop and removes the hand-written declaration. | `0.3.7-alpha.2` | 2026-04-18 |
|
|
169
|
-
| 📋 | **`gina connector:audit [@project]`** — reads `connectors.json`, maps each declared connector to its npm peer package (`mysql2`, `pg`, `ioredis`, `couchbase`, `openai`, `@anthropic-ai/sdk`, etc.), and runs `npm audit --json` scoped to those packages in the project's `node_modules`. Reports CVEs with severity and fix availability. If `socket` is installed in the project, delegates to it for supply-chain analysis (malware, typosquatting, protestware) instead of `npm audit`. Exit code 1 on any high/critical finding — CI-friendly. Only audits packages actually declared in `connectors.json`, not the full dependency tree. | `0.
|
|
172
|
+
| 📋 | **`gina connector:audit [@project]`** — reads `connectors.json`, maps each declared connector to its npm peer package (`mysql2`, `pg`, `ioredis`, `couchbase`, `openai`, `@anthropic-ai/sdk`, etc.), and runs `npm audit --json` scoped to those packages in the project's `node_modules`. Reports CVEs with severity and fix availability. If `socket` is installed in the project, delegates to it for supply-chain analysis (malware, typosquatting, protestware) instead of `npm audit`. Exit code 1 on any high/critical finding — CI-friendly. Only audits packages actually declared in `connectors.json`, not the full dependency tree. | `0.6.x` | Q4 2026 |
|
|
170
173
|
|
|
171
174
|
### Phase 5 — Future
|
|
172
175
|
|
|
@@ -264,19 +267,38 @@ Technical-safeguard primitives that map to the **PCI-DSS**, **SOC2**, and **HIPA
|
|
|
264
267
|
| Status | Feature | Version | Target |
|
|
265
268
|
| --- | --- | --- | --- |
|
|
266
269
|
| ✅ | **Authorization / RBAC** — Per-route authorization declared in `routing.json`: `param.requireAuth` requires an authenticated session, `param.roles: ["admin","editor"]` requires any one of a set of roles, and `param.policy: "ownsInvoice"` delegates to a per-bundle function for the record/attribute checks roles cannot express (evaluation order: authentication → roles → policy). Unauthenticated callers get a 401, or a non-cacheable login bounce when `settings.json > auth.loginRoute` is set (the paused request replays after sign-in); authorized-but-denied callers get a 403 whose body stays generic — the required roles and the policy name are never echoed to the wire. `self.hasRole(role)` covers actions that authorize mid-logic. A route that declares nothing is untouched, and any declaration that would leave a route silently ungated refuses to boot. Maps to PCI-DSS req 7, HIPAA §164.312(a)(1), SOC2 CC6 (least privilege). | `0.5.19-alpha.2` | shipped |
|
|
267
|
-
|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
|
|
|
273
|
-
|
|
|
270
|
+
| ✅ | **Tamper-evident audit trail** — A user-attributed, append-only, integrity-protected record of who did what to which record when, distinct from application logging. The audit trail (`settings.json > audit.enabled` + `self.audit(action, data)` writing an append-only JSONL record — actor, action, resource, request id, ip, route, timestamp — with route-authorization denials recorded automatically) shipped first; the **tamper-evidence** now ships too: an opt-in HMAC hash chain (`audit.chain`) makes any edited, deleted, inserted, or reordered record detectable, verified offline with `gina audit:verify`. Detects tampering by anyone without the signing key (as change-detection it maps to PCI-DSS v4.0.1 §10.3.4); for the process that holds the key, stream the trail to a WORM/Object-Lock store (§10.3.2/§10.3.3). Maps to PCI-DSS req 10, HIPAA §164.312(b), SOC2 CC7. | `0.6.0` | shipped |
|
|
271
|
+
| ✅ | **Authentication hardening** — `lib.authn` supplies the primitives that are dangerous to hand-roll, without becoming an identity provider: Gina still owns no user record, credential store, or login route, and the module ends where `req.login()` begins. `hashPassword` mints scrypt hashes encoded as self-describing PHC strings, so the cost parameters travel with the hash and can be raised later without a flag day — `needsRehash` reports which stored hashes are below policy and the next successful login upgrades them transparently, the one moment the plaintext is in hand. `verifyPassword` compares in constant time and also verifies existing argon2 and bcrypt hashes through your own project's package, so a bundle arriving with credentials already hashed keeps working; `dummyVerify` spends matching work on the account-not-found branch to close the user-enumeration oracle; `validatePasswordPolicy` checks length first per NIST SP 800-63B, with composition rules and a deny-list available. `createLockout()` adds the credential-stuffing brake — PCI-DSS §8.3.4 defaults of 10 consecutive failures and a 30-minute lock, a caller-chosen key with optional normalisation, per-key serialization so failures arriving concurrently cannot lose the count, a pluggable shared store for multi-replica correctness, and one `auth.lockout` audit record on the transition into locked; it is per-account credential lockout, not per-client request-rate limiting, which remains a separate roadmap item. RFC 6238 TOTP completes the set: secret generation, the `otpauth://` enrolment URI every standard authenticator scans, and constant-time verification returning the matched step as an absolute `counter` so your application can enforce replay defence. Maps to PCI-DSS req 8 (8.3.2 authentication-factor storage, 8.3.4 lockout, 8.4 MFA), HIPAA §164.312(d). | `0.6.0` | shipped |
|
|
272
|
+
| ✅ | **Session lifecycle hardening** — `req.login(user, done)` now works without Passport and rotates the session id BEFORE binding the user (the session-fixation defense): the pre-login record is destroyed, the principal lands at `req.session.user`, and the absolute-timeout anchor is stamped — with a graceful bind-and-warn when the session provider exposes no `regenerate()`, and Passport bundles untouched. The Session plugin gained an opt-in absolute session cap: `session({ absoluteTimeout: <ms> })` or `settings.json > session.absoluteTimeout` (bundle code wins, `false` disables) destroys an authenticated session older than the cap on its next request — regardless of activity — and the request proceeds anonymously, exactly like a naturally-expired record; fail-closed when the record cannot be destroyed, anonymous sessions never touched so `saveUninitialized: false` keeps its meaning. Composes with the existing idle expiry (cookie `maxAge` + store-record TTL, both rolling with activity). Declared in the published settings.json schema. Maps to PCI-DSS req 8.2. | `0.6.0` | shipped |
|
|
273
|
+
| ⏸ | **PII/PHI protection** — Production log-field redaction, data classification, and retention helpers (today's redaction is a dev-only inspector tool). **Deferred — built on request.** *Interim:* keep credentials and identifiers out of query strings, since the always-on access log records full request URLs. Maps to HIPAA and SOC2 Privacy. | — | on demand |
|
|
274
|
+
| ⏸ | **Application-level rate limiting** — Per-endpoint / per-client throttling at the route layer (today only an HTTP/2 rapid-reset limiter exists). **Deferred — built on request.** *Interim:* throttle at your reverse proxy or ingress. Distinct from `lib.authn` account lockout, which brakes credential failures per account, not requests per client. Maps to PCI-DSS anti-automation and SOC2 availability. | — | on demand |
|
|
275
|
+
| ⏸ | **Data-at-rest / field-level encryption helpers** — Field-level encryption + key-management utilities. **Deferred — built on request.** *Interim:* encrypt at the application layer with your platform's KMS SDK; `${secret:KEY}` delivers the key material. Maps to PCI-DSS req 3 and HIPAA §164.312(a)(2)(iv). | — | on demand |
|
|
276
|
+
| ✅ | **Compliance control-mapping guide** — [Compliance control mapping](https://gina.io/docs/guides/compliance) maps every control Gina ships to the PCI-DSS v4.0.1, SOC 2 (2017 TSC), and HIPAA §164.312 requirement it supports, and states plainly where a framework's responsibility ends. Controls still on the roadmap are listed separately as unavailable, each with the interim pattern to use until it ships, so a planned control can never be mistaken for one you have. An explicit "what Gina does not — and cannot — cover" section names what no framework provides: the certification itself, legal instruments, network and physical security, personnel and process, operations, key-management infrastructure, and vendor risk. A living reference — rows move from planned to available as controls ship. | `0.5.26-alpha.2` | shipped |
|
|
274
277
|
| ✅ | **Transport-security posture** — A bundle resolving a cleartext scheme outside the local scope warns once at boot, naming the bundle, scheme, and scope alongside both remediations. `server.requireHttps: true` refuses the boot instead — the throw lands pre-listen, so the cleartext port is never reachable at all. `server.allowInsecure: true` is the "TLS terminates upstream" acknowledgment for the mesh / ingress / reverse-proxy topology, turning the warning into a single info line; declaring both is a boot-refused contradiction. Both are strict booleans resolved exactly like `scheme` itself — the bundle's settings win and `env.json`'s `server` block fills — and a non-boolean value refuses the boot in every scope. Terminating mTLS stays a mesh/ingress concern by design. Maps to the "encrypt everywhere / no implicit network trust" principle of NIST SP 800-207 (Zero Trust). | `0.5.26-alpha.2` | shipped |
|
|
275
278
|
| ✅ | **Deny-by-default authorization mode** — `settings.json > auth.requireAuthByDefault: true` inverts a bundle's posture: a route declaring no authorization key is gated rather than open, and opts back out with `param.public: true`. The mode is keyed per bundle, so one bundle's posture can never un-gate a sibling's in a merged process. The existing `requireAuth` / `roles` / `policy` keys are unaffected — only the un-annotated route changes — and `public` is evaluated inside the un-annotated branch, so a route carrying it alongside an explicit gate key stays gated even in a hand-edited config. The boot refuses the three shapes the mode makes dangerous: `public` beside an explicit gate key, a login route the mode would gate (an infinite self-bounce), and a mode-gated route that also declares `cache` (the render cache is read before authorization and its key carries no identity). The five framework-injected routes ship exempt, so enabling the mode cannot take the site root or the error renderer offline. Complements the shipped Authorization / RBAC control. Maps to NIST SP 800-207 least-privilege / deny-by-default. | `0.5.26-alpha.2` | shipped |
|
|
276
279
|
| ✅ | **Zero-Trust deployment guide** — [Running Gina zero-trust](https://gina.io/docs/guides/zero-trust) walks the NIST SP 800-207 tenets against the controls Gina actually ships: deny-by-default authorization, the transport-posture knobs, terminating mTLS at the mesh or ingress, network default-deny between services, keeping the framework control sockets on loopback, and shipping the built-in audit / metrics / request-correlation telemetry to a SOC. An honest-boundary companion to the compliance control-mapping guide — the framework supplies the enforcement point, identity, and telemetry; the deployment supplies transport identity and segmentation. | `0.5.26-alpha.2` | shipped |
|
|
277
280
|
|
|
278
281
|
---
|
|
279
282
|
|
|
283
|
+
## Financial Messaging & Ledger Enablers
|
|
284
|
+
|
|
285
|
+
Plumbing for financial-messaging (ISO 20022-class XML flows) and ledger-grade applications, targeted at the `0.8.0` (foundations) and `0.9.0` (integration heavyweights) milestones. Same honesty rule as the compliance controls above: these are enablers, and "compliant" never attaches to a framework — ISO 20022 compliance attaches to the messages an institution exchanges under a scheme's usage guidelines, SWIFT compliance to the institution itself (membership, certified interfaces, the annual CSP attestation), and ledger correctness to the application. Gina supplies the building blocks an application uses to get there.
|
|
286
|
+
|
|
287
|
+
| Status | Feature | Version | Target |
|
|
288
|
+
| --- | --- | --- | --- |
|
|
289
|
+
| 📋 | **XML request handling** — `application/xml` / `text/xml` request bodies reach the application verbatim (alongside `req.rawBody`) instead of being run through the form-encoded decode path; the application parses with the XML library of its choice. | `0.8.x` | 2027 |
|
|
290
|
+
| 📋 | **`renderXML` delegate** — first-class XML responses (content type + charset), mirroring `renderJSON`. | `0.8.x` | 2027 |
|
|
291
|
+
| 📋 | **Pluggable message-schema validation** — a seam for validating inbound/outbound messages against the XSDs or usage-guideline validators the application supplies, with a fail-closed 400/422 shape — kept pluggable so the framework never takes on a native-addon dependency. | `0.8.x` | 2027 |
|
|
292
|
+
| 📋 | **IBAN / BIC validation rules** — ISO 13616 (MOD-97) and ISO 9362 shape checks as built-in FormValidator rules, client and server. | `0.8.x` | 2027 |
|
|
293
|
+
| 📋 | **Money & minor-unit utilities** — an ISO 4217 minor-unit exponent table plus a documented exact-money pattern (amounts as strings on the wire, integer minor units internally) and helpers, so monetary values never ride IEEE-754 float arithmetic. | `0.8.x` | 2027 |
|
|
294
|
+
| 📋 | **Idempotency keys** — store-backed request deduplication: a client-supplied idempotency key makes a retried mutation return the recorded first response instead of executing twice. | `0.8.x` | 2027 |
|
|
295
|
+
| 📋 | **Sequence primitive** — monotonic (optionally gapless) reference-number allocation backed by a durable store. | `0.8.x` | 2027 |
|
|
296
|
+
| 📋 | **Datastore transaction seam** — a uniform entity-layer transaction surface with per-connector capability flags; until it ships, the documented per-connector native escape hatches remain the supported answer. | `0.9.x` | 2027 |
|
|
297
|
+
| 📋 | **OAuth2 client-credentials egress** — token acquisition and refresh (including signed-JWT client assertions) for outbound `self.query()` calls to OAuth2-protected APIs. | `0.8.x` | 2027 |
|
|
298
|
+
| 📋 | **Message-queue connector family** — first-class messaging connectors (AMQP / Kafka / IBM MQ) in the `connectors.json` model, for integration with message-based platforms. | `0.9.x` | 2027 |
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
280
302
|
## Connectors
|
|
281
303
|
|
|
282
304
|
New database connectors follow the same interface as the existing Couchbase connector: declared in `connectors.json`, acquired via `getConnection()`.
|
|
@@ -296,7 +318,7 @@ New database connectors follow the same interface as the existing Couchbase conn
|
|
|
296
318
|
| ✅ | **`connector:infer` — one-off AI inference CLI** | `0.5.6-alpha.3` | Q2 2026 | Runs a single inference against a configured `ai` connector **outside a request** — the runtime sibling of the config-only `connector:list`/`add`/`rm`/`migrate` tooling. Resolves the project's shared (or shared+bundle merged) `connectors.json`, resolves `${secret:KEY}` credentials from the CLI's own environment (the resolved value is never echoed), instantiates the connector directly (no bundle boot, no framework socket), and prints the normalised result. `gina connector:infer <connector> [<bundle>] @<project> --message="..."`, with `--system` / `--model` / `--max-tokens` / `--temperature` per-call overrides; `--message` takes precedence over a messages JSON array piped on stdin. `--format=json` (matched strictly — `jsonl`/`json5` fall back to the text output) emits `{ content, model, usage }`, with `--raw` adding the full provider response as a `raw` field (omitted by default for CLI use); text mode writes the content to stdout and a model/usage footer to stderr. `--stream` streams the inference as newline-delimited JSON (NDJSON) — one frame per line on stdout: a `start` frame, a `delta` frame per token, then a terminal `done` (content, model, usage, latency; plus the provider `raw` object under `--raw` — `null` for OpenAI-family streams) or `error` frame; token counters are passed through verbatim and are `null` (never fabricated) when a provider does not report them. Errors cleanly on a non-`ai` connector, and surfaces missing-SDK / credential / transport failures with a non-zero exit and the reason on stderr. Useful for smoke-testing connectivity + credentials from CI/automation, or scripting a one-off inference from a shell; offline providers such as `ollama://` work with no paid-API key. Implemented 2026-06-30 (`connector:infer` + the `--stream` NDJSON mode; a later output-hardening pass added `--raw`, pipe-safe synchronous writes, and `--message`-over-stdin precedence). |
|
|
297
319
|
| ✅ | **`connector:test` — connector readiness probe CLI** | `0.5.6-alpha.3` | Q2 2026 | Probes a project's configured connectors for readiness **outside a request** — the CI-friendly sibling of `connector:list` (driver-install status only) and `secrets:check` (env presence only), answering "is this connector ready to use?". Default is validate-only and offline: per connector it checks the `connector` type / `ai` protocol is recognised, the npm driver is installed at `<project>/node_modules`, and every `${secret:KEY}` placeholder resolves from the environment — no network, no connector instantiated — exiting non-zero when any connector fails so it can gate a deploy. `gina connector:test [<connector> [<bundle>]] @<project>` tests one connector or every connector in a project (bare → every registered project), mirroring `connector:infer`'s positional grammar and `secrets:check`'s all-mode; `--format=json` emits a machine-readable readiness report. The `--connect` opt-in adds a live connectivity probe: for `ai` connectors it calls the provider's `models.list` (a credentialed request that authenticates with **zero generation tokens**; `ollama://` confirms the local server is up), resolving `${secret:KEY}` the way `connector:infer` does (the value is never printed). For DB/cache connectors the live `--connect` probe is reported as **skipped** for now (config / driver / secrets are still validated) — the live DB/cache probe is a follow-up, since those connector classes load `core/gna` (which exits the process outside a booted bundle) and cannot be instantiated the way the AI connector is. Implemented 2026-06-30. |
|
|
298
320
|
| ✅ | **`connector:models` — list an AI connector's provider models** | `0.5.8` | Q2 2026 | Lists the model catalogue a configured `ai` connector's provider can serve — the read sibling of `connector:test --connect` (which makes the same `models.list()` call but keeps only the count). `gina connector:models <connector> @<project> [<bundle>]` prints one model id per line (a count footer on stderr), or `--format=json` emits `{ project, connector, provider, count, models }` with each entry passed through verbatim from the provider (only `id` is guaranteed across providers — Anthropic and OpenAI-family return different fields). Reuses the direct-`AIConnector` bootstrap of `connector:infer` / `connector:test` (no bundle boot, no framework socket); resolves config only and never prints credentials; offline providers such as `ollama://` work with no internet. `isAIConnector`-gated (a non-AI connector is rejected cleanly), and a provider client without `models.list` reports `supported:false` with a non-zero exit rather than a fabricated empty list. Implemented 2026-07-03. |
|
|
299
|
-
| 📋 | **DuckDB** | `0.
|
|
321
|
+
| 📋 | **DuckDB** | `0.6.x` | Q3 2026 | ORM / entity connector for DuckDB — an embedded **analytical** (columnar, OLAP) store: the analytics-side sibling of the SQLite connector's embedded OLTP role. Planned shape follows the MySQL / PostgreSQL architecture: entity wiring, `sql/` layout, positional placeholders (DuckDB accepts `?` and `$name`), `@param`/`@return` annotations, native Promise + `.onComplete()`, driver loaded from the project's `node_modules` as an optional peer dependency. Client: `@duckdb/node-api` (DuckDB's current-generation Node client). Use cases: in-process analytics and reporting bundles over app data, querying Parquet / CSV / JSON files directly without an ETL hop, larger-than-memory local aggregation; both `:memory:` and file-backed databases. Session store is a non-goal — DuckDB is a single-writer analytics engine (Redis / SQLite cover session storage). |
|
|
300
322
|
|
|
301
323
|
---
|
|
302
324
|
|
|
@@ -365,7 +387,7 @@ A cold audit of the Couchbase connector identified two critical security vulnera
|
|
|
365
387
|
| ✅ | **Application-level rapid reset rate limiter** (CVE-2023-44487) — per-session stream creation counter | `0.3.13` | 2026-05-14 | The Isaac HTTP/2 session handler counts new streams in a rolling 1s window per session; over `maxStreamsPerSecond` (default 200) it sends a GOAWAY and closes the session. More targeted than `maxSessionRejectedStreams` (which counts refused streams, not created ones). Configurable via `settings.json` `http2Options.maxStreamsPerSecond`; `/_gina/info` exposes a `rapidResetBlocked` counter. |
|
|
366
388
|
| ✅ | **Trailer support** — `stream.sendTrailers()` + `waitForTrailers: true` | `0.4.0` | 2026-05-22 | Opt-in HTTP/2 response trailers via `self.sendTrailers(fields)`. The render pipeline sets `waitForTrailers` and emits the trailing headers after the body (in the `wantTrailers` event), across all render delegates. Activated only when a controller calls `self.sendTrailers(fields)`; HTTP/1.1 and the no-trailers path are unchanged. For gRPC-style streaming (`grpc-status`) and content-integrity (`Digest`) use cases. |
|
|
367
389
|
| ✅ | **Alt-Svc header** — advertise HTTP/3 availability | `0.4.2` | 2026-06-02 | Set `Alt-Svc: h3=":443"; ma=86400` response header to advertise HTTP/3 (QUIC) availability via a QUIC-capable reverse proxy (nginx, Caddy, Cloudflare). Gina does not need to implement QUIC — just announce it. Opt-in via `settings.server.json`. Native HTTP/3 is out of scope: Node.js has no stable QUIC API, and the standard deployment topology (Gina → proxy → client) already delivers HTTP/3 at the edge. |
|
|
368
|
-
| 📋 | **RFC 9218 Extensible Priorities** — read `Priority: u=N, i` request header | `0.
|
|
390
|
+
| 📋 | **RFC 9218 Extensible Priorities** — read `Priority: u=N, i` request header | `0.6.x` | Q1 2027 | Use the RFC 9218 priority header to order response writes for multiplexed API clients. Low value for typical HTML page loads; high value for parallel API requests with declared urgency. |
|
|
369
391
|
| ✅ | **WebSocket over HTTP/2** (RFC 8441 extended CONNECT) — opt-in via `http2Options.enableConnectProtocol` (default off; https and cleartext h2c HTTP/2 bundles). From `onInitialize`, `app.onWebSocket(path, handler)` registers per-path WebSocket handlers; accepted streams arrive as full sessions backed by a built-in dependency-free RFC 6455 codec (auto-pong, timed close handshake, UTF-8 + close-code validation, payload/fragment DoS caps, backpressure passthrough, graceful shutdown drain). Unknown paths are refused with 404, plain CONNECT keeps its 405, and default-off deployments are byte-identical. **Extended in `0.5.5`:** endpoints are declarable in `routing.json` (`method: "ws"` + `param.wsHandler` → `channels/<name>.js`, `:param` paths, per-route `param.wsOptions`), and handlers can call other bundles over HTTP with `session.query()`. | `0.4.7` | 2026-06-11 |
|
|
370
392
|
|
|
371
393
|
---
|
|
@@ -406,6 +428,11 @@ A cold audit of the Couchbase connector identified two critical security vulnera
|
|
|
406
428
|
| ✅ | **Route radix trie — compile `routing.json` at startup** | `0.3.0-alpha.1` | 2026-04-01 | `lib/routing/src/radix.js` builds a segment-level trie once at startup. O(m) candidate lookup per request (m = segment count). `Set.has()` check skips non-candidates in the `for…in` loop. Internal change — no user-facing API change. |
|
|
407
429
|
| ✅ | **Bun runtime support** | `0.5.5` | 2026-06-21 | Gina runs on the [Bun](https://bun.sh) runtime (Bun `>= 1.2`) as a supported, CI-gated target — `bun add -g gina` installs and boots end-to-end, validated by a blocking CI Bun smoke. Both investigated blockers cleared: dev-mode `require.cache` hot-reload and `node:http2` work under Bun (one upstream gap remains: RFC 8441 extended-CONNECT advertisement, affecting only opt-in WebSocket-over-HTTP/2). Gina self-bootstraps on first run; Node `>= 22 < 27` remains fully supported. |
|
|
408
430
|
| ✅ | **V8 pointer compression support** | `0.2.0` | Q2 2026 | Node.js built with `--experimental-enable-pointer-compression` (e.g. [node-caged](https://github.com/platformatic/node-caged) or a custom build) delivers ~50% heap memory reduction across all pointer-heavy structures. Gina is pure JS — compatible out of the box. Adds: startup detection + `GINA_V8_POINTER_COMPRESSED` env var, Dockerfile guide with custom build recipe (full-icu + pointer compression), 4 GB ceiling documentation, N-API-only connector policy. |
|
|
431
|
+
| 📋 | **Runtime CPU profiling baseline** | `0.7.x` | 2027 | Flame-graph profiles of representative bundles under load — render, concurrent-upload, and WebSocket arms — so every hot-path candidate below is convicted or acquitted by measurement before it is optimised. "No further acceleration needed" is a valid verdict. |
|
|
432
|
+
| 📋 | **Multipart boundary-scan fast path** | `0.7.x` | 2027 | The multipart parser's boundary search is the one unbounded byte-by-byte JS loop on a request path. Delegating the in-chunk needle search to the runtime's native `Buffer.indexOf` (JS keeps only the chunk-boundary carry) relieves the event loop under large concurrent uploads. Wire and event contract unchanged; validated by differential tests against the current matcher. |
|
|
433
|
+
| 📋 | **WebSocket unmask fast path** | `0.7.x` | 2027 | Every inbound client frame must be unmasked, and that XOR currently runs byte-by-byte in JS. Word-at-a-time unmasking in the built-in RFC 6455 codec, with the `ws` engine path picking up `bufferutil` acceleration where it is installed — optional only; the pure-JS behaviour remains the permanent fallback. |
|
|
434
|
+
| 📋 | **Render & logging hot-path cleanups** | `0.7.x` | 2027 | Repair the per-render asset-scan memoization (the cache guard can never hit as written, so the full document is re-scanned every HTTP/2 render), precompile the logger's per-line token regexes, and consolidate whole-document render passes where the profiling baseline convicts them. |
|
|
435
|
+
| ⏸ | **SIMD boundary scanner (Rust → WebAssembly)** | — | on demand | **Deferred — measure-gated.** Built only if the profiling baseline still convicts the multipart scan after the JS fast path lands. WebAssembly first: sandboxed, a single artifact for every platform including Bun, no process crash surface. Native N-API prebuilds — published as separate per-platform packages so the framework tarball never carries a compiled binary — only if WASM leaves measured headroom. No install scripts ever; the JS implementation remains the permanent fallback. *Interim:* the JS fast path above. |
|
|
409
436
|
|
|
410
437
|
---
|
|
411
438
|
|
|
@@ -467,7 +494,7 @@ Gina's built-in per-bundle inspector. Phases 1–2 ship as an embedded SPA at `/
|
|
|
467
494
|
| ✅ | **Beginner — Notes API** — Your first REST API: scaffold a project, define 3 routes in `routing.json`, write synchronous controller actions, read `req.post` / `req.params`, return JSON with `renderJSON()`, handle errors with `throwError()`. In-memory store — no database needed. | ~15 min | `0.3.0` | 2026-04-01 |
|
|
468
495
|
| ✅ | **Tutorial locale detection** — `LocaleSettings` React component detects the reader's locale and timezone via `navigator.language` + `Intl` APIs and pre-fills the `settings.json` scaffold example. Inserted after the scaffold step in both tutorials. Falls back to `en_US`. | — | `0.3.0` | 2026-04-06 |
|
|
469
496
|
| ✅ | **Intermediate — Link Shortener** — SQLite ORM connector, async controller actions, `render()` + `renderJSON()` in same bundle, HTTP 302 redirect, route `requirements` guard. Includes downloadable project ZIP. | ~30 min | `0.3.0` | 2026-04-01 |
|
|
470
|
-
| 📋 | **Advanced** — Full production project: authentication, scoped data isolation, async/await, HTTP/2, structured logging, Docker/K8s deployment. Starts from the intermediate tutorial's finished state. | ~60 min | `0.
|
|
497
|
+
| 📋 | **Advanced** — Full production project: authentication, scoped data isolation, async/await, HTTP/2, structured logging, Docker/K8s deployment. Starts from the intermediate tutorial's finished state. | ~60 min | `0.6.x` | Q4 2026 |
|
|
471
498
|
|
|
472
499
|
---
|
|
473
500
|
|
|
@@ -475,7 +502,7 @@ Gina's built-in per-bundle inspector. Phases 1–2 ship as an embedded SPA at `/
|
|
|
475
502
|
|
|
476
503
|
| Status | Feature | Version | Target |
|
|
477
504
|
| --- | --- | --- | --- |
|
|
478
|
-
| 📋 | **Official website redesign + docs integration** — Refactor gina.io as a proper project homepage (landing page, feature highlights, showcase) with the documentation fully integrated. Single coherent web presence. Prerequisite: tutorials complete. | `0.
|
|
505
|
+
| 📋 | **Official website redesign + docs integration** — Refactor gina.io as a proper project homepage (landing page, feature highlights, showcase) with the documentation fully integrated. Single coherent web presence. Prerequisite: tutorials complete. | `0.6.x` | Q4 2026 |
|
|
479
506
|
| ✅ | **Docs offline ZIP** — One-click download of the complete gina.io documentation as a static HTML ZIP archive. Generated at deploy time by the Docusaurus build pipeline — no server-side logic required. Targeted at users in regions with limited or expensive internet access (offline-first for the African market). | `0.4.0` | 2026-05-22 |
|
|
480
507
|
| ✅ | **Security & CVE compliance page** — Dedicated docs page listing the HTTP/2 CVEs addressed by Gina and the Node.js version required for each mitigation. Covers CVE-2023-44487 (Rapid Reset), CVE-2024-27316 / CVE-2024-27983 (CONTINUATION flood), CVE-2019-9514 (RST flood), HPACK bomb, and server push abuse. Docs only — no code changes. | `0.3.0-alpha.1` | 2026-04-01 |
|
|
481
508
|
|
package/bin/cli
CHANGED
|
@@ -356,6 +356,7 @@ async function onExec() {
|
|
|
356
356
|
|
|
357
357
|
// |-> framework/{version}/lib/cmd
|
|
358
358
|
var allowedOffline = [
|
|
359
|
+
'audit:',
|
|
359
360
|
'build:',
|
|
360
361
|
'bundle:',
|
|
361
362
|
'cache:',
|
|
@@ -456,7 +457,13 @@ async function onExec() {
|
|
|
456
457
|
} else {
|
|
457
458
|
|
|
458
459
|
//Connect to framework.
|
|
459
|
-
|
|
460
|
+
// #B160 — the daemon binds `bind_host` (loopback by default) while
|
|
461
|
+
// `host_v4` is the address EXTERNAL clients use. When host_v4 names
|
|
462
|
+
// one of this machine's own interfaces, the daemon is local: dial the
|
|
463
|
+
// bind address, not the external one. A remote host_v4 is dialled
|
|
464
|
+
// unchanged.
|
|
465
|
+
var dialHost = lib.netLocality.resolveDialHost(hostV4, bindHost);
|
|
466
|
+
var client = net.connect({port: port, host: dialHost},
|
|
460
467
|
function() {
|
|
461
468
|
//Forwarding cmd.
|
|
462
469
|
// retieving debug infos
|
|
@@ -504,6 +511,10 @@ async function onExec() {
|
|
|
504
511
|
} else {
|
|
505
512
|
console.log('[ gina ] not started, try to start framework with :\n$ sudo gina start')
|
|
506
513
|
}
|
|
514
|
+
// #B160 — name the dial target and the bind knob: a refused
|
|
515
|
+
// connection here is either a daemon that is not running, or one
|
|
516
|
+
// bound to a different address than the one dialled.
|
|
517
|
+
console.log('Could not reach the framework command socket at `'+ dialHost +':'+ port +'`.\nThe daemon binds `bind_host` (default `127.0.0.1` — see ~/.gina/'+ shortVersion +'/settings.json, or the GINA_BIND_HOST env var).');
|
|
507
518
|
|
|
508
519
|
console.debug(err.stack||err);
|
|
509
520
|
|
package/bin/gina-init
CHANGED
|
@@ -353,6 +353,20 @@ projectsOut[projectName] = projectEntry;
|
|
|
353
353
|
var userInfo = { username: 'node', uid: -1, gid: -1 };
|
|
354
354
|
try { userInfo = os.userInfo(); } catch(e) { /* running as unresolvable uid (e.g. scratch image) */ }
|
|
355
355
|
|
|
356
|
+
// #B161 — honour an operator-set bind_host instead of discarding it: this file
|
|
357
|
+
// overwrites settings.json unconditionally on every container start, so a
|
|
358
|
+
// value written by `gina framework:set --bind-host=` (or a previous bootstrap)
|
|
359
|
+
// was silently reverted to loopback. Env first (this script reads raw
|
|
360
|
+
// process.env by design — see the note near the top), then the value already
|
|
361
|
+
// persisted in settings.json, then the loopback default. The `${` guard skips
|
|
362
|
+
// an unresolved template placeholder.
|
|
363
|
+
var prevBindHost = null;
|
|
364
|
+
try {
|
|
365
|
+
var _prevSettingsRaw = fs.readFileSync(ginaHome + '/' + shortVersion + '/settings.json', 'utf8');
|
|
366
|
+
prevBindHost = JSON.parse(_prevSettingsRaw).bind_host || null;
|
|
367
|
+
if (prevBindHost && String(prevBindHost).indexOf('${') > -1) { prevBindHost = null; }
|
|
368
|
+
} catch (e) { /* absent or unreadable — defaults apply */ }
|
|
369
|
+
|
|
356
370
|
var settingsOut = {
|
|
357
371
|
version : version,
|
|
358
372
|
def_framework : version,
|
|
@@ -368,7 +382,7 @@ var settingsOut = {
|
|
|
368
382
|
debug_port : '9229',
|
|
369
383
|
mq_port : '8125',
|
|
370
384
|
host_v4 : '127.0.0.1',
|
|
371
|
-
bind_host : '127.0.0.1',
|
|
385
|
+
bind_host : process.env.GINA_BIND_HOST || prevBindHost || '127.0.0.1',
|
|
372
386
|
hostname : os.hostname(),
|
|
373
387
|
user : userInfo.username,
|
|
374
388
|
uid : String(userInfo.uid),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.6.0
|
|
@@ -6284,9 +6284,23 @@ function Routing() {
|
|
|
6284
6284
|
return route;
|
|
6285
6285
|
}
|
|
6286
6286
|
|
|
6287
|
+
/**
|
|
6288
|
+
* #B168 — once-per-process latch for the proxied-context degrade warning in
|
|
6289
|
+
* getRoute(): the resolver sits on the per-request hot path, so the abnormal
|
|
6290
|
+
* state is reported once rather than per call (under dev-mode hot-reload the
|
|
6291
|
+
* module re-evaluates, so the warning may reappear per reload cycle).
|
|
6292
|
+
* @private
|
|
6293
|
+
*/
|
|
6294
|
+
var _proxyHostDegradeWarned = false;
|
|
6295
|
+
|
|
6287
6296
|
/**
|
|
6288
6297
|
* @function getRoute
|
|
6289
6298
|
*
|
|
6299
|
+
* On the server, a proxied-context call resolves the route's proxy hostname
|
|
6300
|
+
* from the worker global with an envConf fallback; when neither holds a value
|
|
6301
|
+
* the route degrades to its direct hostname (route.isProxyHost is flipped
|
|
6302
|
+
* false) instead of failing, and a once-per-process warning is emitted.
|
|
6303
|
+
*
|
|
6290
6304
|
* @param {string} rule e.g.: [ <scheme>:// ]<name>[ @<bundle> ][ /<environment> ]
|
|
6291
6305
|
* @param {object} params - substituted into the route's `:placeholders`; on a GET route, leftover keys that are neither reserved nor declared in the rule's `requirements` are appended to `route.url` as query parameters (a rule with no `requirements` block is safe — the block is optional)
|
|
6292
6306
|
* @param {number} [urlIndex] in case you have more than one url registered for the current route, you can select the one you want to use. Default is 0.
|
|
@@ -6377,11 +6391,32 @@ function Routing() {
|
|
|
6377
6391
|
route.proxy_hostname = process.gina.PROXY_HOSTNAME || config.envConf._proxyHostname;
|
|
6378
6392
|
// console.debug("[getRoute#1]["+isProxyHost+"] process.gina.PROXY_HOSTNAME ("+ process.gina.PROXY_HOSTNAME +") VS config.envConf._proxyHostname ("+ config.envConf._proxyHostname +")");
|
|
6379
6393
|
}
|
|
6380
|
-
|
|
6394
|
+
// #B168 — on the server, BOTH sources above are framework-produced falsy
|
|
6395
|
+
// states: the worker global is boot-set only from a proxy config carrying a
|
|
6396
|
+
// hostname (and otherwise first written by a proxied request), while the
|
|
6397
|
+
// envConf fallback is deliberately written null for a request classified
|
|
6398
|
+
// direct. With the worker-wide proxied latch true and both unset, the
|
|
6399
|
+
// unguarded rewrite below crashed every server-side getRoute() while the
|
|
6400
|
+
// state lasted. Degrade to the route's direct hostname instead — and flip
|
|
6401
|
+
// route.isProxyHost too: toUrl() keys on it, so leaving it true would
|
|
6402
|
+
// stringify the unset value straight into the emitted URL.
|
|
6403
|
+
if (route.proxy_hostname) {
|
|
6404
|
+
route.proxy_host = route.proxy_hostname.replace(/^(https|http)\:\/\//, '');
|
|
6405
|
+
} else {
|
|
6406
|
+
delete route.proxy_hostname;
|
|
6407
|
+
route.isProxyHost = false;
|
|
6408
|
+
if (!_proxyHostDegradeWarned) {
|
|
6409
|
+
_proxyHostDegradeWarned = true;
|
|
6410
|
+
console.warn('[ RoutingHelper::getRoute() ] Proxied context is active but no proxy hostname is resolvable (worker global and envConf fallback both unset) - falling back to the route direct hostname. Warned once per process.');
|
|
6411
|
+
}
|
|
6412
|
+
}
|
|
6381
6413
|
|
|
6382
6414
|
} else if (
|
|
6383
6415
|
!isGFFCtx
|
|
6384
6416
|
&& typeof(process.gina.PROXY_HOSTNAME) != 'undefined'
|
|
6417
|
+
// #B168 — the typeof gate admits a defined-but-falsy value (typeof null is
|
|
6418
|
+
// 'object'); require a truthy hostname before the rewrite below
|
|
6419
|
+
&& process.gina.PROXY_HOSTNAME
|
|
6385
6420
|
) {
|
|
6386
6421
|
route.proxy_hostname = process.gina.PROXY_HOSTNAME;
|
|
6387
6422
|
route.proxy_host = route.proxy_hostname.replace(/^(https|http)\:\/\//, '');
|