gina 0.6.2 → 0.6.3
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 +57 -0
- package/README.md +41 -12
- package/ROADMAP.md +3 -2
- package/bin/cli +19 -2
- package/framework/v0.6.3/VERSION +1 -0
- package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/html/statusbar.html +6 -0
- package/framework/v0.6.3/core/asset/plugin/dist/vendor/gina/html/statusbar.html.br +0 -0
- package/framework/v0.6.3/core/asset/plugin/dist/vendor/gina/html/statusbar.html.gz +0 -0
- package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/inspector/index.html +1 -0
- package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/inspector/inspector.css +50 -1
- package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/inspector/inspector.js +457 -57
- package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/js/gina.js +1457 -58
- package/framework/v0.6.3/core/asset/plugin/dist/vendor/gina/js/gina.min.js +625 -0
- package/framework/v0.6.3/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
- package/framework/v0.6.3/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/index.js +114 -0
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/connector.js +14 -3
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/session-store.js +14 -3
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/session-store.v3.js +29 -2
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/session-store.v4.js +29 -2
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/mongodb/lib/session-store.js +24 -2
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/redis/lib/session-store.js +33 -9
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/scylladb/lib/session-store.js +25 -2
- package/framework/{v0.6.2 → v0.6.3}/core/connectors/sqlite/lib/session-store.js +26 -2
- package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.js +201 -21
- package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-nunjucks.js +8 -0
- package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-swig.js +85 -4
- package/framework/{v0.6.2 → v0.6.3}/core/gna.js +23 -1
- package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/csrf/src/main.js +9 -5
- package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/hide-powered-by/README.md +20 -0
- package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/validator/src/form-validator.js +119 -43
- package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/validator/src/main.js +451 -9
- package/framework/{v0.6.2 → v0.6.3}/core/server.isaac.js +50 -54
- package/framework/{v0.6.2 → v0.6.3}/core/server.js +240 -3
- package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/index.js +6 -4
- package/framework/{v0.6.2 → v0.6.3}/core/template/conf/settings.json +10 -0
- package/framework/{v0.6.2 → v0.6.3}/lib/cache/README.md +9 -1
- package/framework/{v0.6.2 → v0.6.3}/lib/cmd/audit/verify.js +11 -9
- package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/mcp-start.js +21 -12
- package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/help.txt +1 -1
- package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/init.js +13 -1
- package/framework/{v0.6.2 → v0.6.3}/lib/dto/src/main.js +18 -11
- package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/file/index.js +29 -1
- package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/mq/speaker.js +30 -1
- package/framework/{v0.6.2 → v0.6.3}/lib/math/index.js +57 -6
- package/framework/{v0.6.2 → v0.6.3}/lib/merge/src/main.js +34 -5
- package/framework/{v0.6.2 → v0.6.3}/lib/render-cache/src/main.js +77 -4
- package/framework/{v0.6.2 → v0.6.3}/lib/routing/src/main.js +13 -1
- package/framework/{v0.6.2 → v0.6.3}/lib/routing-introspect/src/main.js +64 -2
- package/framework/v0.6.3/lib/secrets/src/backends/env.js +75 -0
- package/framework/{v0.6.2 → v0.6.3}/package.json +1 -1
- package/gna.js +5 -4
- package/llms.txt +19 -17
- package/package.json +5 -4
- package/schema/connectors.json +2 -2
- package/schema/routing.json +5 -0
- package/schema/settings.json +6 -1
- package/script/generate_gna_types.js +1 -1
- package/script/soak/couchbase-soak.js +1316 -0
- package/types/globals.d.ts +2 -0
- package/types/gna.d.ts +5 -0
- package/types/index.d.ts +1 -0
- package/utils/helper.js +38 -7
- package/framework/v0.6.2/VERSION +0 -1
- package/framework/v0.6.2/core/asset/plugin/dist/vendor/gina/html/statusbar.html.br +0 -0
- package/framework/v0.6.2/core/asset/plugin/dist/vendor/gina/html/statusbar.html.gz +0 -0
- package/framework/v0.6.2/core/asset/plugin/dist/vendor/gina/js/gina.min.js +0 -603
- package/framework/v0.6.2/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
- package/framework/v0.6.2/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
- package/framework/v0.6.2/lib/secrets/src/backends/env.js +0 -60
- /package/framework/{v0.6.2 → v0.6.3}/AUTHORS +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/LICENSE +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/html/nolayout.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/html/static.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/img/android-chrome-192x192.png +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/img/android-chrome-512x512.png +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/img/apple-touch-icon.png +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/img/favicon-16x16.png +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/img/favicon-32x32.png +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/img/favicon.ico +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.css +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/beemaster/index.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/css/gina.min.css +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.br +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.gz +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/inspector/have_heart_one-webfont.woff2 +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/inspector/logo.svg +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.br +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.gz +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/config.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/ai/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/ai/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/connector.v3.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/connector.v4.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/couchbase/lib/n1ql.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/duckdb/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/duckdb/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/mongodb/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/mongodb/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/mongodb/lib/job-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/mongodb/lib/pipeline-loader.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/mysql/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/mysql/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/postgresql/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/postgresql/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/redis/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/redis/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/redis/lib/job-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/redis/lib/render-cache-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/scylladb/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/scylladb/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/sql-parser.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/sqlite/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/sqlite/lib/connector.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/connectors/sqlite/lib/job-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/content.encoding +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.framework.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-json.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-nunjucks-async.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-stream.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-swig-async.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/controller.render-v1.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/inspector-window-emit.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/controller/release-banner.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/dev/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/dev/lib/class.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/dev/lib/factory.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/dev/lib/tools.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/currency.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/dist/language/en.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/dist/language/fr.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/dist/region/en.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/dist/region/fr.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/locales/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/mime.types +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/model/entity.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/model/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/model/template/entityFactory.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/model/template/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/csrf/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/csrf/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/coep/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/coep/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/coep/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/coop/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/coop/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/coop/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/corp/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/corp/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/corp/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/csp/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/csp/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/csp/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/hide-powered-by/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/hide-powered-by/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/hsts/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/hsts/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/hsts/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/origin-agent-cluster/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/origin-agent-cluster/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/origin-agent-cluster/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/referrer-policy/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/referrer-policy/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/referrer-policy/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-content-type-options/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-content-type-options/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-content-type-options/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-dns-prefetch-control/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-dns-prefetch-control/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-dns-prefetch-control/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-download-options/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-download-options/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-download-options/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-frame-options/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-frame-options/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-frame-options/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-permitted-cross-domain-policies/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-xss-protection/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-xss-protection/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/security-headers/x-xss-protection/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/session/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/session/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/session/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/storage/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/storage/build.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/storage/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/storage/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/validator/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/validator/build.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/plugins/lib/validator/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/router.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/server.express.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/status.codes +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/_gitignore +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/app.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/connectors.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/routing.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/settings.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/settings.server.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/templates.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/config/watchers.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/controllers/controller.content.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/controllers/controller.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/controllers/setup.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle/locales/en.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_namespace/controllers/controller.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/css/default.css +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/css/home.css +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/css/vendor/readme.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/favicon.ico +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/js/components/x-checklist.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/js/vendor/readme.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/manifest.webmanifest +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/readme.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_public/sw.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_templates/handlers/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_templates/html/content/homepage.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_templates/html/includes/error-msg-noscript.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_templates/html/includes/error-msg-outdated-browser.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_templates/html/includes/x-checklist.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/boilerplate/bundle_templates/html/layouts/main.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/command/gina.bat.tpl +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/command/gina.tpl +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/conf/env.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/conf/manifest.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/conf/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/conf/statics.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/conf/templates.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/error/client/json/401.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/error/client/json/403.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/error/client/json/404.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/error/server/html/50x.html +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/error/server/json/500.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/error/server/json/503.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/core/template/extensions/logger/config.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/console.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/context.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/data/LICENSE +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/data/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/data/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/data/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/dateFormat.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/json/LICENSE +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/json/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/json/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/json/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/path.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/plugins/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/plugins/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/plugins/src/api-error.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/plugins/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/prototypes.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/task.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/helpers/text.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/admin/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/admin/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/archiver/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/archiver/build.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/archiver/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/archiver/src/dep/jszip.min.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/archiver/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/async/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/async/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/audit/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/audit/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/audit-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/authn/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/authn/src/lockout.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/authn/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/authn/src/totp.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/authz-gate/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/authz-gate/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cache/build.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cache/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cache/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/aliases.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/audit/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/audit/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/build.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/copy.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/cp.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/inc/name-rewrite.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/man.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/mcp.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/oas.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/openapi.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/rename.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/restart.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/start.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/status.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/stop.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/bundle/types.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/cache/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/cache/clear.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/cache/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/cache/stats.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/infer.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/migrate.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/models.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/connector/test.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/container/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/container/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/container/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/container/man.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/container/ps.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/container/stop.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/inc/args.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/inc/namespace.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/inc/reference-rewrite.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/inc/reference-scan.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/inc/scaffold.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/rename.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/controller/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/get.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/link-dev.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/set.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/unset.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/env/use.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/build.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/dot.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/get.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/link-node-modules.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/link.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/man.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/msg.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/open.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/reset.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/restart.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/set.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/start.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/status.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/stop.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/tail.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/update.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/framework/version.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/gina-dev.1.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/gina-framework.1.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/gina.1.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/helper.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/export.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/import.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/i18n/scan.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/_host.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/build.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/man.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/image/run.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/inspector/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/inspector/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/inspector/open.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/man-render.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/minion/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/minion/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/minion/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/minion/kill.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/minion/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/msg.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/port/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/port/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/port/inc/scan.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/port/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/port/reset.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/port/set.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/backup.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/build.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/import.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/man.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/move.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/rename.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/restart.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/restore.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/start.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/status.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/project/stop.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/protocol/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/protocol/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/protocol/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/protocol/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/protocol/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/protocol/set.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/link-local.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/link-production.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/remove.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/rm.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/scope/use.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/secrets/arguments.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/secrets/check.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/secrets/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/secrets/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/secrets/scan.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/service/help.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/service/help.txt +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/service/list.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/service/man.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/service/start.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd/view/add.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd-status-format/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cmd-status-format/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/collection/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/collection/build.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/collection/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/collection/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/config.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/connector-config/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/connector-config/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/connector-error/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/connector-error/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/connector-registry/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/connector-registry/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cron/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cron/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/cron/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/domain/LICENSE +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/domain/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/domain/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/domain/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/dto/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/dto-pipe/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/dto-pipe/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/dto-types/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/dto-types/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/generator/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/i18n/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/i18n/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/image-build/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/image-build/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inherits/LICENSE +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inherits/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inherits/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inherits/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inspector-events/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inspector-events/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inspector-redact/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/inspector-redact/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/instrument/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/instrument/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/job/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/job/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/job-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/json-config-header/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/json-config-header/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/default/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/file/lib/logrotator/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/file/lib/logrotator/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/mq/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/containers/mq/listener.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/helper.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/logger/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/mcp-dispatch/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/mcp-dispatch/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/mcp-http/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/mcp-http/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/mcp-server/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/mcp-server/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/merge/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/merge/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/metrics/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/metrics/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/model.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/net-locality/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/net-locality/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/nunjucks-filters/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/nunjucks-filters/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/nunjucks-filters/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/nunjucks-resolver/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/nunjucks-resolver/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/proc.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/release-watch/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/release-watch/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/render-cache/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/render-cache-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/routing/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/routing/build.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/routing/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/routing/src/radix.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/routing-introspect/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/secrets/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/secrets/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/session-store.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/shell.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/sqlite-driver.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/state.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/swig-filters/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/swig-filters/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/swig-filters/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/swig-resolver/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/swig-resolver/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/template-loaders/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/template-loaders/src/loaders/http.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/template-loaders/src/loaders/memory.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/template-loaders/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/url/README.md +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/url/index.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/url/routing.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/uuid/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/uuid/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/validator.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/watcher/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/watcher/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/ws-framing/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/ws-framing/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/ws-query/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/ws-query/src/main.js +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/ws-session/package.json +0 -0
- /package/framework/{v0.6.2 → v0.6.3}/lib/ws-session/src/main.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,63 @@ 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.3 - 2026-08-04
|
|
10
|
+
### Added
|
|
11
|
+
* Added a Couchbase SDK soak harness — `script/soak/couchbase-soak.js` screens a Couchbase Node SDK candidate against a caller-chosen Couchbase Server before a consuming project adopts it (#CN12). The harness scaffolds a fully isolated throwaway project (the real `~/.gina` and real projects are never touched), installs the candidate SDK into it (`--sdk=<version>` or `--sdk-path=<dir>` — the install is the version selector, since the connector resolves `couchbase` from the project node_modules), builds and boots the bundle for the prod env, then drives the three connector surfaces under sustained concurrent load for `--duration`: N1QL entity queries (including a `request_plus` scan-consistency arm), KV through the entity collection handle in both the promise and the 4-arg optional-callback form, and the couchbase express-session store. Pass criteria target the silent-death class where a process under SDK load dies without a JS stack: the bundle must survive the full duration (a premature clean exit 0 counts as FAILURE), RSS growth must stay bounded, the error rate must not drift, and every requested arm must complete real work. Exit codes 0/1/2 with a JSON + text report under `tmp/couchbase-soak-<stamp>/`; a generic soak is a screen, not proof — run it as the first filter on an SDK bump, with a workload-shaped soak of the consuming application as the second gate.
|
|
12
|
+
* Routes can opt into content negotiation with `negotiate: true` in routing.json (#SPA1). A request that then carries the `X-Gina-Navigate: fragment` header receives that route rendered without its layout — the content region alone — instead of the full page, so a client can fetch a page fragment over the same URL without a second route, a duplicated controller, or a query-string convention. Any other header value, or no header at all, renders exactly as before, so the vocabulary can be extended later without breaking existing clients. A negotiable route always advertises `Vary: X-Gina-Navigate` (appended to any existing Vary, never replacing it) so shared caches know the URL varies even on a response that did not itself vary. Deliberate limitation: a negotiable route does not participate in the render cache — the cache key carries no shape dimension and the cache is consulted before the shape is resolved, so a stored entry could otherwise replay a fragment to a browser asking for a full page; pairing `negotiate` with `cache` therefore keeps the route out of the cache rather than risking the wrong body. Routes that do not declare the flag are unaffected: no new header, no behaviour change, no cache impact.
|
|
13
|
+
* Opt-in client-side navigation module `gina/nav` (#SPA1): a page carrying a `data-gina-nav` region gets SPA-style navigation — same-origin link clicks whose URL first-matches a route declaring `negotiate: true` are fetched as layoutless fragments (`X-Gina-Navigate: fragment` + `X-Requested-With`) over a fresh XHR per navigation, swapped into the region with history/scroll/focus handling, fragment script re-injection, validator form rebinding and an optional `data-gina-nav-title` document title; every uncertainty (non-2xx, timeout, an un-negotiated answer, JSON redirects) falls back to a normal full-page navigation, links owned by the link/popin plugins are never touched, and a page without the marker stays byte-identical.
|
|
14
|
+
* Inspector: hidden tabs can now be restored one at a time. In Custom layout mode, each removed tab's dimmed preview pill becomes a click-to-restore control — a leading + glyph (amber on hover) and a native "Restore <Tab> tab" tooltip signal it; clicking brings just that tab back at the end of the tab bar, without switching to it. The Reset link still restores everything at once.
|
|
15
|
+
* The RFC 9211 Cache-Status identifier the render/output cache reports on the wire is now configurable via `server.cache.name` (settings.json `cache` block, default `gina-cache` — the wire is byte-identical when unset). The value must be a letter followed by up to 63 of [A-Za-z0-9._-] (a conservative RFC 8941 token subset); an invalid value is ignored with a boot warn, never sanitized into a name the operator did not write. When `server.hidePoweredBy` is true and the cache is enabled, leaving `name` unset now logs a boot warn naming the remaining framework disclosure — set any token (e.g. `cache`) to close it, or explicitly `gina-cache` to keep the current wire and silence the warn. The identifier is resolved once at boot and read by every mint site on both engines, hit and miss, so it can never disagree across engines or outcomes.
|
|
16
|
+
### Changed
|
|
17
|
+
* `/_gina/assets/routing.json` is now served with a per-variant weak `ETag` and `cache-control: no-cache` (was `max-age=86400`), on both engines: each page boot revalidates with one conditional GET — normally answered `304 Not Modified` — so a restart's new route table reaches returning browsers immediately instead of up to 24 hours later. The proxied variant keeps its `private` marking.
|
|
18
|
+
* Replaced the transitive `object-assign` dependency (`engine.io` → `cors` → `object-assign@4.1.1`, dormant since 2017) with `@socketregistry/object-assign` via npm `overrides` — a maintained two-line re-export of the native `Object.assign`, with zero runtime change (the replaced package already delegated to the native implementation at require time on any modern runtime). SCOPE, so nobody reads more into this than it does: npm and bun alike honor `overrides` only in a project own root manifest, so this cleans the gina tree itself and NOT your install — a project that depends on gina still resolves `object-assign@4.x` beneath `cors`, unchanged. Add the same `overrides` entry to your own root `package.json` to get it in your tree; the consumer-reaching fix is upstream (expressjs/cors#430, filed).
|
|
19
|
+
### Fixed
|
|
20
|
+
* Custom error pages are now served with their real HTTP status on every template engine. A page configured through the routing error param / errorFiles mechanism was rendered with status 200 by the nunjucks and async render delegates — only the swig and v1 delegates recompute the status from the page data downstream — because renderCustomError never stamped the response status before dispatching. It now stamps the response status from the error status code (when the code is a known status code, and never after headers are sent), so a configured 500 or 404 page answers 500 or 404 on the wire instead of 200, and a transient-failure 503 upgrade carries a coherent Retry-After alongside its custom page (#B190).
|
|
21
|
+
* Fixed the custom-error renderer discarding its resolved error template whenever the dispatch reset flag was absent — the render delegates then fell back to the failing route's own file, producing a bare-path "could not open" error and a routing-rule dump that misdirected diagnosis toward correct configuration while the real failure was upstream. The resolved template now reaches the render unconditionally, the error dispatch works on a clone of the injected route instead of mutating shared routing configuration, and a custom error template that cannot be opened falls back to the built-in error page with a message naming the template instead of a routing dump.
|
|
22
|
+
* Fixed a form's live check going permanently dead after a rejected submit attempt. The submit path arms an internal submitting latch before validating — deliberately, so live-check stays quiet while a request is in flight — but only the XHR settle cleared it, and a rejected submit renders the field errors without sending anything. One invalid submit attempt therefore latched the flag for the rest of the page's life: every later keystroke was swallowed by the live-check gate and the submit trigger kept aria-disabled="true" plus the gina-form-submit-disabled class until reload, hard-blocking keyboard and assistive-technology users while mouse users saw a disabled-looking trigger that still submitted. Because the flag lives on the form instance rather than a listener, rebinding the form did not restore the live check either. The internal validation handler now releases the latch on the rejected branch, before moving focus to the first invalid field; a genuine in-flight submit still suppresses live-check exactly as before. Browser-bundled — re-bake your bundles at pickup.
|
|
23
|
+
* Fixed the dev Inspector reporting every multi-index Couchbase query as "no index — full bucket scan". The plan walker behind the Query tab's index badges followed only the generic child containers, while the multi-index operators (IntersectScan, UnionScan, OrderedIntersectScan) nest their child scans under a dedicated scans array — and DistinctScan under a singular scan — so any query the planner served with more than one index returned an empty index list and rendered the red no-index badge and banner. That failure invited exactly the wrong response: building an additional index, with its cluster-wide build cost and permanent write amplification, for a query that was already fully indexed. The walker now visits both nested-scan containers, so such plans report every index they use; index names are still deduplicated, and single-index, primary-scan and USE KEYS reporting are unchanged. Server-side only — a bundle restart picks it up, no asset rebuild needed.
|
|
24
|
+
* Fixed the dev Inspector's tab-layout preview rendering the two newest tabs (Stream, Events) as the literal text "undefined". Both tabs were added to the layout presets when they shipped, but the preview's label and color maps were not extended, so their pills showed "undefined" with a broken pill color. The maps now cover all eight tabs, and the preview resolves labels and colors through fallbacks — a future tab missing from the maps renders its capitalized name in a neutral color instead of "undefined". Same stale-roster family, also fixed: the saved custom tab order was validated against a hardcoded six-tab maximum, so with seven or eight tabs visible a custom drag-reordered layout was silently rejected on the next load and never survived a reload; the bound now derives from the preset roster itself. Dev-tool only, served from the framework — a bundle restart picks it up, no asset rebuild needed.
|
|
25
|
+
* Fixed `${secret:GINA_*}` placeholders never resolving in CLI-process contexts — the env backend now reads the framework environment first, then `process.env`, so a shell-exported GINA_-prefixed secret resolves in `mcp.json`, in connector CLI commands, and in `audit:verify`; the CSRF plugin's `GINA_CSRF_SECRET` tier and the audit-chain boot lint message were aligned with the same two-tier read
|
|
26
|
+
* Fixed the MCP HTTP transport's dead `GINA_HOST_V4` bind tier — replaced with `GINA_BIND_HOST` read through the framework environment (the loopback default is unchanged, and a connect address can no longer become the bind), and the MCP server version banner no longer degrades to `0.0.0` under the CLI
|
|
27
|
+
* Fixed `GINA_*` variables set for a single command being invisible to the CLI's own bootstrap — `GINA_HOMEDIR=/path gina env:list` now resolves the home directory, settings file and host from that value instead of falling back to the default home and only honouring it once the handler ran; a fresh home is no longer seeded with a null-laden settings.json (and the `Cannot override Env variable` warnings that produced are gone), and the framework environment no longer leaks a junk `gina` variable into the environment of every spawned child process
|
|
28
|
+
* Fixed any gina command aborting with `EISDIR: illegal operation on a directory, read` when the configured run directory contains a sub-directory — the framework:init pid cleanup read every entry as a pidfile with no guard, so one unreadable entry threw out of the loop and failed the whole command. Unreadable entries are now skipped (and deliberately never pruned, since the stale-pidfile removal is only safe for entries whose contents were actually read), which also covers a pidfile removed by a concurrent run
|
|
29
|
+
* Fixed the MQ speaker and file logger containers ignoring `GINA_HOMEDIR` — both resolved the framework settings file from the invoking user's home unconditionally, so a process pinned to an isolated home still read the real home's MQ port and host and silently mixed the two. Both now read the framework environment first, then `process.env`, before falling back to the previous default
|
|
30
|
+
* Fixed the optional digit bounds on the `isInteger` validation rule being silently ignored whenever the value reached it as a real number rather than a string: no error was recorded, no warning was emitted, and the field was reported valid. Numbers arrive that way from JSON request bodies — including `validator::{}` routing requirements, which merge the parsed body into the validated data — and from a preceding `toInteger`, so a `toInteger` then `isInteger` chain was affected in the browser too. The bounds now measure the value's string form, matching the behaviour `isNumber` has always had. This TIGHTENS enforcement: a value that previously slipped past a declared `isInteger` bound now correctly fails, so review any rule declaring `"isInteger": N` or `"isInteger": [min, max]` on a field that can carry a numeric value. Note a negative number counts its sign toward the length, exactly as it already did when the same value arrived as a string. `isString` and `isNumber` are unchanged.
|
|
31
|
+
* Fixed the rule engine conflating loosely-empty values with the empty string: five sites tested emptiness with loose equality, and since `0`, `-0`, `false` and `[]` all compare loosely equal to `''`, those values rode the empty-value bypass. Concretely, `isEmail`, `isJsonWebToken` and `isFloat` reported such a value as VALID outright — a JSON body carrying `{"email": 0}` passed email validation — and the digit bounds on `isInteger` and `isNumber` were skipped for the number zero (for `isNumber` even the string `"0"`, which its entry cast turns into a number). All five sites now compare strictly, so only the literal empty string bypasses — exactly what the designed contract (an empty value is adjudicated by `isRequired` alone) always meant, and that contract is preserved byte-for-byte: an empty string behaves precisely as before on every rule. This TIGHTENS enforcement: review fields ruled `isEmail`, `isJsonWebToken` or `isFloat` that can legitimately receive a numeric or boolean value from a JSON body, and bounds-carrying `isInteger`/`isNumber` fields that can receive zero. `isString`, `isInList`, `isDate` and the `is` condition rule are unchanged.
|
|
32
|
+
* Fixed `bundle:openapi` and `bundle:mcp` silently dropping three declared bound forms when un-collapsing a `validator::{}` routing requirement into a parameter schema: the scalar `"isString": N` now maps to `minLength` (the engine treats it as a minimum, identical to `[N]`), and `isInteger`/`isNumber` digit bounds now reach the generated schema as an honest annotation — a human-readable `description` (e.g. `2-4 digits (string-form length; a negative sign counts)`) plus a machine-readable `x-gina-digitBounds` extension. Digit bounds constrain the length of the value's string form, not its range, so they are deliberately NOT emitted as `minimum`/`maximum` (wrong for any negative value, whose sign counts toward the length) nor as `minLength`/`maxLength` (string-only keywords, inert on numeric types). Schemas generated from bare `true` rules are byte-identical to before.
|
|
33
|
+
* The dev-mode Inspector now follows the monitored tab across the bundles of a proxy-routed multi-bundle project: each applied payload's environment.webroot re-points the server-side channels (the /_gina/logs stream and the passive /_gina/agent stream) at the bundle actually serving the page, closing the previous stream. Hitting that bundle's Inspector endpoints activates its per-process dev capture, so the Flow and Query tabs stop showing "No timeline data for this request." for every page served by a bundle the Inspector was not opened from — previously the channels stayed pinned to the open-time bundle and a sibling bundle's capture never latched; server logs also kept streaming from the wrong bundle after a crossing. The pid staleness guard now compares webroots too, so a legitimate bundle crossing is no longer swallowed as a stale snapshot. The first page rendered on a newly-visited bundle still lacks flow (it rendered before capture activated) — data appears from the next render on (#B205)
|
|
34
|
+
* Corrected the published schema/connectors.json description of the couchbase `useScopeAndCollections` option: it claimed "Enable scope and collection support (SDK v3+)" while the option is accepted but currently inert. The connector partitions data via `_scope`/`_collection` document fields (one bucket, default collection); named-collection KV access is available per call via `entity.getConnection(scope, collection)`; the option is reserved for a possible future native scope/collection routing mode.
|
|
35
|
+
* The couchbase connector and session-store SDK-major resolvers now derive the SDK major as the dependency pin's first integer: range pins like `~4.5.0` or `>=4.5` previously mangled to `~4`/`>=4`, slipped past the SDK-v2 floor and refused to boot with a misdirecting "supported couchbase SDK majors are 3 and 4" error. A digit-less pin (`*`, `latest`) now refuses with an error naming the pin, and a project package.json without a `dependencies` key no longer crashes the resolver.
|
|
36
|
+
* The scaffolded bundle template (`bundle:add`) taught an impossible session-store selection: `expressSession.name = 'myRedis'` — `Function.prototype.name` is read-only, so the assignment silently no-ops (or throws under strict mode) and the store factory always resolves the literal `"session"` connectors.json entry, meaning the template's `"myRedis"`/`"myDb"` example entries could never be found and boot failed with `[SessionStore] Could not be loaded`. The template now shows the documented shape — one connectors.json entry named `"session"` whose `connector` field selects the backend — and the four store factories' JSDoc no longer teaches the same re-key.
|
|
37
|
+
* Session stores no longer write an immortal record for an already-expired session: when the resolved ttl is <= 0 (a cookie `maxAge` of 0, or the decaying remainder truncating to zero in a session's final second), `set()` is now a no-op in every store — previously redis wrote an expiry-less plain SET, and the couchbase and scylladb stores stored the record with a ZERO expiry (never expires), leaving a zombie session that still validated if its id was replayed. The couchbase `touch()` gains the same guard. Behavior change: a configured `ttl: 0` (or any non-positive value, via store options or the connectors.json session entry) now refuses at bundle init naming the offending channel, instead of silently behaving as unset.
|
|
38
|
+
* Fixed lib/math checkSumSync misrouting data to the filesystem: any input whose serialized form ended in a dot plus 3 lowercase letters (an email domain, a URL, a filename mentioned in text) was passed to fs.readFileSync and threw ENOENT or ENAMETOOLONG instead of returning a checksum, with the error naming the caller's own data as a path. The extension-shaped tail is now only a fast-path hint: the file branch is taken solely when the path resolves to an existing regular file, and everything else - including a directory whose name looks like a domain - is hashed as data. Inputs that previously succeeded return byte-identical checksums; unreadable existing files (e.g. EACCES) still fail loudly. (#B209)
|
|
39
|
+
* Fixed lib/math checkSumSync collapsing every ARRAY input to the checksum of the empty string: the serializer assigned the JSON of the array to the wrong variable and returned an always-empty string, so all arrays produced the same constant hash regardless of content - and it also sorted the caller's array in place. Arrays now produce a real, order-insensitive content checksum (the hash of the JSON of a sorted copy), and the input array is no longer mutated. Any previously stored array checksum was the degenerate empty-string constant and will change. (#B208)
|
|
40
|
+
* Fixed lib/math checkSumSync hashing real file paths as PATH STRINGS whenever the extension was not exactly a dot plus 3 lowercase letters: the file probe now accepts any extension shape (a dot plus 1-10 alphanumerics - .js, .json, .TXT, .c, .jpeg, ...) and remains stat-gated, so the file branch is taken only when the whole input resolves to an existing regular file. Behavior change for file callers: checksums of such paths were previously hashes of the path text (never tracking content) and now hash the file bytes - stored sums for those paths change. A data string that exactly names an existing file with an extension-shaped tail now hashes that file (this ambiguity already existed for dot+3-lowercase names); data merely ending in an extension shape still hashes as data, and extension-less paths (Makefile, LICENSE) remain data. (#B210)
|
|
41
|
+
* `/_gina/assets/routing.json` now serves under every engine (#B212) — the client routing maps (the full map and the host-stripped proxied variant) were built and served by the isaac engine only, so an `engine: "express"` bundle answered the framework 404 for the URL the browser fetches at boot to populate its client routing table; the maps are now built once, engine-agnostically, and the express path serves them with the same headers and byte-identical content, including the proxied-variant selection.
|
|
42
|
+
* The browser's boot-time routing fetch now checks the HTTP status before installing the body (#B213) — `fetch` resolves on error statuses, and the framework's 404 page is valid JSON, so a non-2xx answer (an engine missing the asset, a restart window) used to be silently installed AS the client routing table, breaking every later client-side `getRoute`/`toUrl`. A non-OK status now takes the existing error path instead. Ships in the browser bundle: rebuild your bundles to pick it up.
|
|
43
|
+
* Fixed `resumeRequest()` replaying a halted GET without its query string whenever any URL-path param had been captured: the recomposed route URL only carried query keys declared in BOTH a rule's `requirements` AND `param` blocks, so a key bound in `param` only (`"mode": ":mode"` with no requirements entry) or an entirely undeclared key (`?returnTo=...`) was dropped from the replay — the replayed request then matched anyway and rendered literal `:key` template paths as a 500, including on the framework's own `requireAuth` login replay, and the `inheritedData` flash could not heal it because it merges back into `req.get` only AFTER route matching. With a live session the GET replay (plain, XHR and popin flavors alike) now redirects to the byte-exact halted URL, query string included — `pauseRequest()` has always stamped it, so snapshots taken before this fix replay correctly too, and the session key `haltedRequestUrlResumed` now records that exact URL. Session-less custom-storage replays keep the recomposed URL, where the composed query params remain the halted data's only travel channel. (#B215)
|
|
44
|
+
* Fixed negotiated fragment responses arriving content-empty for `{% extends %}` templates: the layoutless render persisted its (empty) nolayout shell over the shared cached-layout parent before compiling, so the child's blocks extended a block-less parent and were discarded — and one fragment request could transiently blank the full-page layout other renders compile from (dev). A layoutless render of an extends template now targets its own `fragments/` cache namespace, primed from the child's own block roster so its blocks render, with the shell tail (xhr inputs / scripts) composed after them, and the compiled-template cache key carries a `:fragment` shape suffix so fragment and full-page compiles never collide in cached mode. Full-page renders are byte-identical; a popin pointed at an extends-template route changes from empty to content. On the nunjucks engine the same request class instead returns the full page (layoutless is honored for asset filtering only) — tracked separately. (#SPA1)
|
|
45
|
+
* #B219 — `pauseRequest()` now snapshots the byte-exact incoming URL (`req.originalUrl || req.url`), completing the #B215 halted-GET replay: the isaac engine strips the query string from `req.url` before controllers run (the query is parsed into `req.get`), so the snapshot — and therefore the #B215 byte-exact replay — was path-only on that engine and a query-bearing halted GET still replayed without its query (500 on `:key`-substituted template paths). The engine preserves the full URL on `req.originalUrl` (stamped before the strip; express sets it natively and never strips), so replays now carry the query on both engines, verified live over HTTP/1.1 and HTTP/2. `haltedRequestUrlResumed` accordingly records the full replayed URL — middleware comparing it to `req.url` by equality should compare against `req.originalUrl || req.url` instead. Snapshots taken before this fix replay exactly as captured.
|
|
46
|
+
* Fixed the Inspector Query pane and its tab badge freezing on the first page whose queries still lacked index data: the live-index refetch re-rendered the tab by replacing the scroll wrapper's children, destroying the `#tree-query` container every later render targets — so navigating the monitored tab (or any new payload, including the refresh button's forced refetch) silently kept the previous page's queries and count on screen until the Inspector window was reloaded. The refetch now re-renders into `#tree-query` itself (#B222)
|
|
47
|
+
* Fixed client-side form validation never adjudicating an unchecked radio group: no collection arm admitted a radio without a checked member, a boolean-shaped value, or an `isBoolean` rule, so an `isRequired` rule on the group never ran -- and a form whose only named controls were radio groups skipped the whole client validation pass and submitted its XHR unvalidated (a zero field count reads as nothing-to-validate on both submit paths). Both collectors (`getFormValidationInfos` and the native-submit inline copy) now collect an unchecked non-boolean radio group whose rule declares a truthy `isRequired` as an empty value, so the standard emptiness test rejects it: the empty submit is blocked, the rule message renders, and picking a value re-enables the send. Enforcement-tightening disclosure: forms that silently submitted with nothing picked now genuinely gate on the pick; groups with no rule, `isRequired: false`, or an `isBoolean` declaration keep the legacy absent-when-unchecked shape, and checked members post exactly as before.
|
|
48
|
+
* Controller.store() now publishes each file atomically and surfaces the real move error (#B223). Failures used to be reported as a fabricated 'No file to upload' Error — masking the actual ENOSPC/EACCES/ENOENT diagnostics; a source-side stream error had no listener at all and killed the bundle process (uncaughtException -> SIGTERM); a destination failure still fired the autoDestroyed stream's close handler, which unlinked the caller's staged SOURCE file after the FAILED move and settled the callback a second time as a success; and the copy streamed straight to the final name after pre-deleting any existing destination, so a concurrent reader could observe a truncated file under the final name. Each file now streams to a temp sibling in the destination directory and is published with an atomic rename; the callback settles exactly once with the real filesystem Error; a failed move leaves both the staged source and any pre-existing destination intact; the genuinely-empty case keeps its historical 'No file to upload' message. A consumer matching that literal message on failure paths now receives the real Error instead.
|
|
49
|
+
* Fixed the dev Inspector's XHR/popin overlay churn (#B225): a preload-consumed (hover- or focus-warmed) popin open never set the toolbar's XHR overlay — its queries and data stayed invisible to the Query/Data tabs while the tab badge blinked page-count to xhr-count and back — and the Inspector's refresh button leaked a passive /_gina/agent SSE stream into statusbar-bound windows, applying bundle-wide payloads over the page-scoped ones. Both preload-consume branches now mirror the cold-click dev gate (updateToolbar right before dispatch), the refresh reopen gate skips bound windows, and the Query-pane re-renders (filters, search, live-index refetch) derive from the live payload instead of a cache that survived closed overlay eras — a refresh no longer resurrects a closed popin's badge count. Disclosed: warmed popin opens now set the badge/overlay for the open's duration, exactly like cold opens always did.
|
|
50
|
+
* Fixed the documented `setFlash` rule form `[null, "message"]` silently losing its custom message in the browser (#B226): `lib/merge` classified a `null` array element as an object (the `typeof null` trap) and refused to carry it through every no-override merge — the client-side rules path re-merges the whispered rules (the `data-gina-form-rule` bind merge, the `gina.hasValidator` instance re-merge, the `_case_` condition merges), so the engine received a one-element array, bound the message to the ignored first argument, and rendered the built-in label instead, while `["", "message"]` survived — `null` was the only casualty because empty strings, `false` and `0` are primitives. Merges now preserve `null` array elements as values framework-wide: arrays that were silently compacted keep their `null` slots (the index-merge branch also stops manufacturing `{}` from a `null` source element), the published `setFlash` example works as documented on the client, and `["", "message"]` keeps working byte-identically.
|
|
51
|
+
* Fixed the submit trigger staying disabled after a radio-group pick under default-on live checking (#B228): the radio live-check listener was registered under a `changed.<id>` event name that nothing dispatches on a user pick — the form-level click proxy short-circuits into the radio state updater (which never dispatches), and the change proxy dispatches only names that are registered — so the whole-form silent pass never re-ran and the trigger kept its bind-time `aria-disabled` + `.gina-form-submit-disabled` state, while submit-time validation (a separate call chain) accepted the checked group and let the send through. Radios now also register the proxy-dispatched `change.<id>` name, so a pick (mouse, label, or keyboard) re-runs the field and whole-form passes and the trigger re-enables. Latent until the radio-group collection fix (#B221) made required radio groups gate at bind — before that there was nothing to re-enable. Checkboxes and text-like fields are unchanged.
|
|
52
|
+
* Fixed a form field that drives its own conditional rule never having its own base rules checked in the browser (#B229). When a rule file declares both a rule for a field and a `_case_<field>` block keyed on that same field, the client validator skipped that field entirely in every whole-form pass — bind, live check and submit alike — so a required radio group that selects its own case was never adjudicated: the form did not gate, the submit trigger stayed enabled with nothing picked, and an empty submit went to the server with no client-side validation at all. The field's base rules are now checked before the conditional block is skipped, and its collected value is preserved across that check so the case it drives still resolves from what the user actually picked. Which conditions apply is unchanged, and the fix is order-independent: a driver declared before another `_case_` block was already being checked, so every driver carrying base rules is now covered. Enforcement tightening: a form built on this shape starts gating where it silently submitted before — required fields on it must now be filled to send. Server-side form-body validation is unaffected (conditional rules were already unsupported there).
|
|
53
|
+
* Fixed the dev Inspector silently rendering bundle-global data when opened without its statusbar link (#B231): a direct-URL, bookmarked, or pre-bound-mode Inspector window fell back to the shared localStorage slot plus the worker-wide `/_gina/agent` stream, so any background request to the bundle overwrote the page-scoped popin/XHR overlay within seconds — a warmed popin open never appeared to update the Query tab. Such a window now adopts the statusbar-advertised tab channel at boot (bound mode, guarded by a liveness handshake so a stale advert from a closed tab falls back cleanly to the legacy acquisition), and a new footer badge names the active data-source mode — `bound` / `agent` / warn-tinted `global` with a tooltip pointing at the statusbar link — so a degraded mode is visible instead of silent.
|
|
54
|
+
* FormValidator: a field that both carries its own rules and drives a `_case_` block now keeps its collected value through every full-form pass, whatever its declaration position. Previously any such driver except the last-declared one had its stored value dropped the moment its own rules were checked, and later readers re-read it from the DOM — for a radio group the FIRST member's value regardless of which member was picked — so conditions could match a choice the user never made (spuriously requiring the wrong flow's fields, or blocking a correctly-completed form), and the driver's own condition block matched nothing at all in the same pass. Conditions now resolve from the value the user actually picked, consistently across scan and direct-case paths, including inside condition recursions. Forms whose drivers carry no rules of their own are byte-identical. This fix is in the browser bundle: rebuild your bundles at pickup — a server restart alone will not deliver it.
|
|
55
|
+
* A required field left empty while also carrying an `is` (custom condition) rule no longer reports a second `Condition not satisfied` message beside `Cannot be left empty` (#B233). `is` was the one rule outside the empty-value contract every other data rule already follows: an empty value is adjudicated by `isRequired` alone, so a required+empty field records one message rather than two. Form validity is unchanged in BOTH directions — an empty required field was invalid and stays invalid, an optional empty field was valid and stays valid — so nothing that used to submit now fails, and nothing that used to fail now submits; only the message list a user sees changes. The empty test is strict: only the literal empty string bypasses the condition, while `0`, `false` and `null` remain real values and are still evaluated by it. A form whose UI renders every error message for a field will show one fewer line on that state; a form that renders only the first message is unaffected. Also drops a dead `isApiError` entry from the built-in error-label catalogue — nothing ever consulted it (the API-error path renders the server's own message directly), so a project that had overridden or translated that label was silently getting no effect from it.
|
|
56
|
+
* Fixed server auto-validation coercing every non-boolean string to `false` before the `isBoolean` rule could run — junk like `nope` or the HTML checkbox default `on` validated clean and persisted as `false`, and the number `1` stored as `false`. The engine is now the single adjudicator on every surface (the same contract the routing requirements surface always enforced and the reference documentation already promised): it accepts `true`/`'true'`/`1` and `false`/`'false'`/`0`, and anything else records an `isBoolean` error instead of silently becoming `false`. The boolean pre-cast survives only in dynamised-rules mode, where a referenced boolean field must splice into stringified `is` conditions as an unquoted operand.
|
|
57
|
+
* Fixed `isBoolean` deleting the `isRequired` error on a required-but-empty field (its rescue used a loose equality that also matched the empty string, so the user lost `Cannot be left empty` and got `Must be a valid boolean` instead). The rule now joins the empty-value contract: a blank field is adjudicated by `isRequired` alone, an optional blank boolean field passes instead of erroring, and a recognized `false`/`0` answer still satisfies a required toggle.
|
|
58
|
+
* Inspector footer memory gauge: the unfilled portion of the track was invisible — it shared the footer's own background color in both themes, so a low fill read as a floating green dot. The track now renders as a visible recessed groove (distinct background plus inset shadow) in dark and light themes.
|
|
59
|
+
* Fixed server auto-validation throwing a `TypeError` when a rule set still carried a `$` after field substitution — a regex end-anchor in an `is` condition (`/^(alpha|beta)$/`), a `$` inside a human-readable message string, or a `$` in any array-rule element after the first. The second substitution loop is a DOM fallback that reads each field from the live element, and the server has no DOM to read; it now skips in that case, exactly as it no-ops on the client once the first loop has consumed every known field token. Verdicts and substitutions on every rule set that already worked are unchanged. One `$` placement is deliberately out of scope and still throws: a token in an array rule's FIRST argument that names no field (`isInList: ["$100"]`), which fails further downstream at a separate substitution site.
|
|
60
|
+
* An array-form validation rule whose FIRST argument carries a `$` token that resolves to no field no longer crashes the whole validation pass — on the client AND the server, since the deref site is not DOM-dependent (#B239, the residual the #B234 fix disclosed). Such a token now stays LITERAL, so the rule's own strict comparison applies: `isInList: ['$100', '$200']` accepts the literal `$100` and rejects a non-member with the rule's own error message, where both directions previously threw a raw `TypeError: Cannot read properties of undefined`; a bare `$` element and a mixed element (a field token beside a non-field residue) are covered by the same guard. A token whose name collides with an engine METHOD (`isValid`, `constructor`) previously did NOT crash — it spliced the string "undefined" into the rule and silently mis-rejected the literal value; it now stays literal too (the guard requires a real field: an existing key carrying a defined value). Behaviour change disclosed in both directions: shapes that previously CRASHED (or silently mis-rejected) now produce verdicts, and no rule set that already validated changes verdict — cross-field `$` references in `is` conditions, `$`-free rules, and a `$` in a LATER array element are byte-identical across the fix. A REAL cross-field reference inside an array rule element remains non-functional (always-invalid, fail-closed — it is substituted upstream with quoting fit for `is`-condition splices, not array elements) and is tracked separately as #B240.
|
|
61
|
+
* A Couchbase N1QL query parameter the SDK cannot serialize no longer aborts the whole bundle process (#B243). The SDK maps JSON.stringify over the parameter list, and for a bare `undefined`, a function, or a Symbol that yields no string at all; the native driver then coerces it to an empty string, fails to parse it as JSON on an internal thread and calls abort() — which no try/catch, uncaughtException or unhandledRejection handler can intercept, so the bundle died outright instead of the request failing with a 500. The most reachable case needed no misuse of the driver: a query method called one argument short with a trailing callback put the CALLBACK itself into a parameter slot, and the arity check could not catch it because it only fires when the last argument is not a function. The connector now refuses an unserializable parameter before dispatch and surfaces a TypeError (code GINA_COUCHBASE_UNSERIALIZABLE_PARAM) naming the offending position and the likely cause, routed through the query callback when there is one and thrown otherwise. Serializable values are untouched: null, 0, empty strings, false and objects carrying undefined properties all still reach the SDK unchanged.
|
|
62
|
+
* Server-side form-body validation now enforces rules authored on bracket-notation keys (`account[username]`) and on nested rule trees — previously such fields were silently skipped with no warning (fail-open), for every rule-keyed directive alike: checks (`isRequired`, `isEmail`, …), the `exclude` drop, and value transforms. Both production wire shapes join now: flat bracket keys (the client posts its name-keyed data as JSON) and nested objects (the multipart and urlencoded parsers expand bracket names). Error keys come back under the DOM-name bracket form the client renders against, and the validated data output keeps its shape with exclusions and transforms applied. Cross-field `$` references keep resolving off the raw posted names, all-flat payloads are byte-identical in behaviour, and the no-rules path still returns the payload verbatim. Behaviour change by design: a bracket-keyed rule that never fired before now enforces — a form relying on the old silent skip will start rejecting or dropping those fields (#B241).
|
|
63
|
+
### Security
|
|
64
|
+
* The client-served routing map (`/_gina/assets/routing.json`) is now built from an ALLOWLIST instead of a denylist, and it no longer discloses server-side contracts to anonymous browsers: controller dispatch keys (`param.control`/`file`/`path`/`title`), `namespace`, `scopes`, `cache` configuration (including invalidation event names), `csrfExempt`, `middlewareIgnored` and `validator::` requirement bodies all stay server-side, and — structurally — so does every FUTURE route key until it is deliberately added to the roster (`schema/routing.json` is `additionalProperties: true`, which is how several of these reached the wire in the first place). What ships is the measured client contract: `url`, `method`, `webroot`, `bundle`, `hostname`/`host` (raw deployments only, per the existing host-stripped proxied variant), the `negotiate` capability flag, plain-regex `requirements` entries, URL-placeholder `param` bindings, and a derived `isRedirect` boolean replacing `param.control`. Client URL building (`getRoute`/`toUrl`, including cross-bundle `rule@bundle` references) is unaffected; code reading OTHER keys off `gina.config.routing` must move that logic server-side.
|
|
65
|
+
|
|
9
66
|
## 0.6.2 - 2026-08-01
|
|
10
67
|
### Added
|
|
11
68
|
* Opt-in 503 + Retry-After rendering for transient datastore failures (connector error classification, slice 2): with `server.transientErrors.enabled: true` in a bundle's settings, a connector error stamped `isTransient` that would render as HTTP 500 through `throwError` renders as 503 with a `Retry-After` header (`server.transientErrors.retryAfter`, integer seconds 1..86400, default 30) and the user-facing `error` field replaced by `server.transientErrors.message` (default: the standard 503 status text) — on both engines, JSON and HTML error surfaces alike. Explicit non-500 statuses and permanent errors are never upgraded, and the default (opt-out) behaviour is byte-identical to before. A malformed `server.transientErrors` block warns at boot and leaves the feature off — it never refuses a boot.
|
package/README.md
CHANGED
|
@@ -60,23 +60,52 @@ open https://localhost:3100
|
|
|
60
60
|
|
|
61
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.)
|
|
62
62
|
|
|
63
|
-
## What's in 0.6.
|
|
63
|
+
## What's in 0.6.3
|
|
64
64
|
|
|
65
65
|
> **Re-bake your bundles, not just restart them.** The browser bundle changed in
|
|
66
|
-
> this release
|
|
67
|
-
>
|
|
68
|
-
>
|
|
69
|
-
>
|
|
66
|
+
> this release. Several of the fixes below — the client-side validator work, the
|
|
67
|
+
> boot-time routing fetch guard, and the new navigation module — ship *only* in
|
|
68
|
+
> the bundle, so a restart alone will not deliver them. Rebuild each bundle
|
|
69
|
+
> (`gina bundle:build`) as well as restarting.
|
|
70
70
|
|
|
71
|
-
> **No settings reset.** `0.6.
|
|
71
|
+
> **No settings reset.** `0.6.3` is a patch — the `shortVersion` stays `0.6`, so
|
|
72
72
|
> your `~/.gina/0.6/settings.json` is untouched. (`0.6.0` was the reset.)
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
> **Two enforcement tightenings to review before upgrading.** Several validator
|
|
75
|
+
> fixes convert silent passes into real verdicts: rules authored on
|
|
76
|
+
> bracket-notation keys now enforce server-side, `isBoolean` and `isInteger`
|
|
77
|
+
> stop accepting values they used to coerce, and required radio groups now gate
|
|
78
|
+
> submission. Forms that relied on the old silent behaviour will start rejecting.
|
|
79
|
+
> Each bullet below discloses its direction; the [Changelog](./CHANGELOG.md) has
|
|
80
|
+
> the per-rule detail.
|
|
81
|
+
|
|
82
|
+
- **Added — opt-in SPA-style client-side navigation.** A route can now declare `negotiate: true` in `routing.json`; a request carrying `X-Gina-Navigate: fragment` then receives that route rendered **without its layout** — the content region alone — over the same URL, with no second route, duplicated controller or query-string convention. The new `gina/nav` module turns that into navigation: a page carrying a `data-gina-nav` region fetches same-origin links as fragments and swaps them in, with history, scroll, focus, title, fragment script re-injection and validator form rebinding handled for you. Every uncertainty — a non-2xx, a timeout, an un-negotiated answer, a JSON redirect — falls back to a normal full-page navigation, and a page without the marker is byte-identical. Negotiable routes advertise `Vary: X-Gina-Navigate` and deliberately opt out of the render cache (the cache key carries no shape dimension, so a stored entry could otherwise replay a fragment to a browser asking for a full page). `{% extends %}` templates render their blocks correctly as fragments via a dedicated cache namespace. Browser-bundled — **re-bake**. (#SPA1)
|
|
83
|
+
- **Security — the client-served routing map no longer discloses server-side contracts.** `/_gina/assets/routing.json` is now built from an **allowlist** instead of a denylist: controller dispatch keys (`param.control`/`file`/`path`/`title`), `namespace`, `scopes`, `cache` configuration including invalidation event names, `csrfExempt`, `middlewareIgnored` and `validator::` requirement bodies all stay server-side — and structurally, so does every *future* route key until it is deliberately added to the roster (`schema/routing.json` allows additional properties, which is how several of these reached the wire in the first place). What ships is the measured client contract: `url`, `method`, `webroot`, `bundle`, `hostname`/`host`, the `negotiate` flag, plain-regex `requirements`, URL-placeholder `param` bindings, and a derived `isRedirect` boolean. Client URL building (`getRoute`/`toUrl`, including cross-bundle `rule@bundle` references) is unaffected; **code reading other keys off `gina.config.routing` must move that logic server-side.**
|
|
84
|
+
- **Changed — a restart's new route table reaches returning browsers immediately.** `/_gina/assets/routing.json` is now served with a per-variant weak `ETag` and `cache-control: no-cache` (was `max-age=86400`) on both engines, so each page boot revalidates with one conditional GET — normally answered `304`. Previously a restart's route changes could take up to 24 hours to reach a returning browser. The proxied variant keeps its `private` marking.
|
|
85
|
+
- **Fixed — the client routing map serves under every engine, and a failed fetch is no longer installed as the route table.** The maps were built and served by the isaac engine only, so an `engine: "express"` bundle answered a 404 for the URL every browser fetches at boot (#B212). And because `fetch` resolves on error statuses and the framework's 404 page is valid JSON, that answer was silently installed *as* the client routing table, breaking every later client-side `getRoute`/`toUrl`; the boot fetch now checks the status first (#B213). Browser-bundled — **re-bake**.
|
|
86
|
+
- **Fixed — server-side validation now enforces rules authored on bracket-notation and nested keys.** Rules keyed `account[username]`, and nested rule trees, were **silently skipped** server-side — fail-open, with no warning, for checks, the `exclude` drop and value transforms alike. Both production wire shapes now join: flat bracket keys and nested objects. Error keys come back under the DOM-name bracket form the client renders against. **Enforcement tightening — a bracket-keyed rule that never fired now enforces**, so a form relying on the old silent skip will start rejecting or dropping those fields. (#B241)
|
|
87
|
+
- **Fixed — the validator's empty-value contract is now uniform across every rule.** Five sites tested emptiness with loose equality, so `0`, `-0`, `false` and `[]` all rode the empty bypass: `isEmail`, `isJsonWebToken` and `isFloat` reported such values **valid outright** (a JSON body carrying `{"email": 0}` passed email validation), and `isInteger`/`isNumber` digit bounds were skipped for zero. All five now compare strictly. Separately, `is` (custom condition) and `isBoolean` joined the same contract, so a required-but-empty field records `Cannot be left empty` once rather than a second, contradictory message beside it. **Enforcement tightening** — review `isEmail`/`isJsonWebToken`/`isFloat` fields that can receive a numeric or boolean value from a JSON body, and bounds-carrying `isInteger`/`isNumber` fields that can receive zero. (#B233, #B235)
|
|
88
|
+
- **Fixed — `isBoolean` is the single adjudicator on every surface, and `isInteger` bounds enforce on real numbers.** Server auto-validation coerced every non-boolean string to `false` *before* the rule could run, so junk like `nope`, the HTML checkbox default `on`, and the strings `"1"`/`"0"` validated clean and **persisted as `false`** — and the number `1` stored as `false`. The engine now accepts `true`/`'true'`/`1` and `false`/`'false'`/`0` and errors on anything else, matching what the routing requirements surface always enforced and the reference always promised. Likewise `isInteger`'s digit bounds were silently ignored whenever the value arrived as a real number rather than a string — from a JSON body, a `validator::{}` requirement, or a preceding `toInteger` — and now measure the string form, as `isNumber` always has. **Enforcement tightening in both cases.** (#B236)
|
|
89
|
+
- **Fixed — a `$` token in a rule no longer crashes the whole validation pass.** A rule set still carrying a `$` after field substitution — a regex end-anchor in an `is` condition (`/^(alpha|beta)$/`), a `$` inside a human-readable message, or a `$` in a later array element — threw a `TypeError` on the server, because a DOM-fallback substitution loop bare-dereferenced a DOM the server does not have (#B234). And an array-form rule whose first argument carries a `$` token resolving to no field threw on **both** client and server; such a token now stays literal, so `isInList: ['$100', '$200']` accepts the literal `$100` and rejects a non-member with the rule's own message (#B239). No rule set that already validated changes verdict.
|
|
90
|
+
- **Fixed — required radio groups now gate, and the submit trigger re-enables on a pick.** No collector admitted a radio group with no checked member, so an `isRequired` rule on the group never ran — and a form whose only named controls were radio groups **skipped client validation entirely** and submitted its XHR unvalidated (#B221). With that fixed, a second defect surfaced: the radio live-check listener was registered under an event name nothing dispatches, so picking a value never re-ran the pass and the trigger kept its `aria-disabled` state while submit-time validation let the send through anyway (#B228). **Enforcement tightening — forms that silently submitted with nothing picked now genuinely gate on the pick.** Browser-bundled — **re-bake**.
|
|
91
|
+
- **Fixed — a field that drives its own `_case_` block is validated, and keeps the value the user picked.** When a rule file declared both a rule for a field and a `_case_<field>` block keyed on that same field, the client validator skipped that field entirely in every whole-form pass, so a required radio group selecting its own case was never adjudicated (#B229). Separately, any such driver except the last-declared had its collected value dropped mid-pass, and later readers re-read it from the DOM — for a radio group, the *first* member regardless of which was picked — so conditions could match a choice the user never made (#B230). Browser-bundled — **re-bake**.
|
|
92
|
+
- **Fixed — a rejected submit no longer kills a form's live check for the rest of the page's life.** The submit path arms an internal latch before validating, but only the XHR settle cleared it — and a rejected submit renders errors without sending anything. One invalid attempt therefore swallowed every later keystroke and left the trigger `aria-disabled="true"`, hard-blocking keyboard and assistive-technology users while mouse users saw a disabled-looking trigger that still submitted. Rebinding the form did not restore it either. Browser-bundled — **re-bake**.
|
|
93
|
+
- **Fixed — the documented `setFlash` `[null, "message"]` form works in the browser.** `lib/merge` classified a `null` array element as an object (the `typeof null` trap) and refused to carry it through no-override merges, so the client received a one-element array, bound the message to the ignored first argument and rendered the built-in label instead. Merges now preserve `null` array elements framework-wide. (#B226)
|
|
94
|
+
- **Fixed — `pauseRequest()`/`resumeRequest()` replay the byte-exact halted URL, query string included.** The recomposed replay URL only carried query keys declared in *both* a rule's `requirements` and `param` blocks, so a key bound in `param` only — or an entirely undeclared one like `?returnTo=…` — was dropped; the replay then matched anyway and rendered literal `:key` template paths as a **500**, including on the framework's own `requireAuth` login replay (#B215). And on the isaac engine the snapshot itself was path-only, since the engine strips the query from `req.url` before controllers run (#B219). Both engines now replay the full URL, verified over HTTP/1.1 and HTTP/2. Middleware comparing `haltedRequestUrlResumed` to `req.url` by equality should compare against `req.originalUrl || req.url`.
|
|
95
|
+
- **Fixed — `Controller.store()` publishes each file atomically and surfaces the real error.** Failures were reported as a fabricated `No file to upload` Error, masking the actual ENOSPC/EACCES/ENOENT diagnostics; a source-side stream error had no listener at all and **killed the bundle process**; a destination failure unlinked the caller's staged source file after the failed move and settled the callback a second time as a success; and the copy streamed straight to the final name after pre-deleting any existing destination, so a concurrent reader could observe a truncated file. Each file now streams to a temp sibling and is published with an atomic rename, the callback settles exactly once with the real Error, and a failed move leaves both the staged source and any pre-existing destination intact. (#B223)
|
|
96
|
+
- **Fixed — custom error pages answer with their real HTTP status.** A page configured through the routing error param / `errorFiles` mechanism was rendered with **status 200** by the nunjucks and async render delegates, so a configured 500 or 404 answered 200 on the wire (#B190). Separately, the custom-error renderer discarded its resolved error template whenever the dispatch reset flag was absent, so the delegates fell back to the failing route's own file and produced a bare-path "could not open" error plus a routing-rule dump that misdirected diagnosis. The resolved template now reaches the render unconditionally, the dispatch works on a clone rather than mutating shared routing configuration, and an unopenable error template falls back to the built-in page naming the template.
|
|
97
|
+
- **Added — the `Cache-Status` identifier is configurable.** `server.cache.name` sets the RFC 9211 identifier the render/output cache reports on the wire (default `gina-cache`; byte-identical when unset). With `server.hidePoweredBy` true and the cache enabled, leaving it unset now logs a boot warn naming the remaining framework disclosure — set any token to close it, or explicitly `gina-cache` to keep the current wire and silence the warn. Resolved once at boot, so it can never disagree across engines or between hit and miss. (#B238)
|
|
98
|
+
- **Fixed — session stores no longer write an immortal record for an already-expired session.** When the resolved TTL is ≤ 0 — a cookie `maxAge` of 0, or the decaying remainder truncating to zero in a session's final second — `set()` is now a no-op in every store. Previously redis wrote an expiry-less `SET` and the couchbase and scylladb stores stored the record with a **zero (never-expires) expiry**, leaving a zombie session that still validated if its id was replayed. **Behaviour change:** a configured `ttl: 0` now refuses at bundle init naming the offending channel, instead of silently behaving as unset.
|
|
99
|
+
- **Fixed — Couchbase: an unserializable query parameter no longer kills the bundle, and range SDK pins resolve.** A parameter the SDK cannot serialize (a bare `undefined`, a function, a Symbol) made the native driver abort the process from an internal thread — uncatchable by `try/catch`, `uncaughtException` or `unhandledRejection` — so the bundle **died outright** instead of the request failing with a 500. The most reachable case needed no misuse: a query method called one argument short with a trailing callback put the *callback* into a parameter slot. The connector now refuses it before dispatch with a `GINA_COUCHBASE_UNSERIALIZABLE_PARAM` TypeError naming the position and likely cause (#B243). Separately, the SDK-major resolvers now take the pin's first integer, so range pins like `~4.5.0` or `>=4.5` no longer mangle, slip past the v2 floor and refuse to boot with a misdirecting error.
|
|
100
|
+
- **Added — a Couchbase SDK soak harness.** `script/soak/couchbase-soak.js` screens an SDK candidate against a caller-chosen Couchbase Server before a consuming project adopts it: it scaffolds a fully isolated throwaway project (your real `~/.gina` and projects are never touched), installs the candidate, and drives N1QL entity queries, KV through the entity collection handle, and the express-session store under sustained concurrent load — targeting the silent-death class where a process dies with no JS stack. A generic soak is a screen, not proof: run it as the first filter on an SDK bump. (#CN12) The published `schema/connectors.json` description of the couchbase `useScopeAndCollections` option was also corrected — it claimed to enable scope/collection support while the option is accepted but currently inert.
|
|
101
|
+
- **Fixed — `lib/math` `checkSumSync`, three defects.** Every **array** input collapsed to the checksum of the empty string (the serializer assigned to the wrong variable), and the caller's array was sorted in place (#B208). Any input whose serialized form ended in a dot plus three lowercase letters — an email domain, a URL, a filename mentioned in text — was passed to `fs.readFileSync` and threw ENOENT, with the error naming the caller's own data as a path (#B209). And real file paths whose extension was *not* exactly dot-plus-three-lowercase were hashed as path strings, never tracking content (#B210). **Stored checksums change** for arrays and for those file paths.
|
|
102
|
+
- **Fixed — `GINA_*` environment variables are visible everywhere they should be.** `GINA_HOMEDIR=/path gina env:list` now resolves the home directory, settings file and host from that value during the CLI's own bootstrap instead of falling back to the default home — no more null-laden seeded settings, no more `Cannot override Env variable` warnings, and no junk `gina` variable leaking into every spawned child's environment. The MQ speaker and file logger containers now honour `GINA_HOMEDIR` too, instead of silently mixing an isolated home with the real home's MQ port and host. `${secret:GINA_*}` placeholders resolve in CLI contexts (`mcp.json`, connector CLI commands, `audit:verify`). And the MCP HTTP transport's dead `GINA_HOST_V4` bind tier is replaced by `GINA_BIND_HOST` read through the framework environment, so a connect address can no longer become the bind.
|
|
103
|
+
- **Fixed — a sub-directory in the configured run directory no longer aborts every gina command.** The `framework:init` pid cleanup read every entry as a pidfile with no guard, so one unreadable entry threw `EISDIR` out of the loop and failed the whole command. Unreadable entries are skipped — and deliberately never pruned, since stale-pidfile removal is only safe for entries actually read.
|
|
104
|
+
- **Inspector — bundle-following, per-tab restore, and six scope/display fixes.** The Inspector now **follows the monitored tab across bundles** of a proxy-routed multi-bundle project, re-pointing its server-side channels at the bundle actually serving the page, so the Flow and Query tabs stop reporting "No timeline data" for every page served by a bundle it was not opened from (#B205). A window opened by direct URL or bookmark now adopts the statusbar-advertised tab channel instead of silently falling back to bundle-global data, with a new footer badge naming the active mode (#B231), and warmed (hover/focus-preloaded) popin opens now set the XHR overlay exactly as cold opens always did (#B225). Hidden tabs can be restored **one at a time** by clicking their dimmed preview pill. Also fixed: the tab-layout preview rendered the two newest tabs as literal "undefined" and silently rejected custom layouts above six tabs; the Query pane and its badge froze on the first page whose queries lacked index data (#B222); multi-index Couchbase queries were reported as "no index — full bucket scan", inviting a needless index build for an already-fully-indexed query; and the footer memory gauge's unfilled track was invisible in both themes (#B237). Dev-tool only — reopen the Inspector window.
|
|
105
|
+
- **Fixed — `bundle:openapi` and `bundle:mcp` no longer drop three declared bound forms.** Un-collapsing a `validator::{}` routing requirement into a parameter schema silently discarded them: scalar `"isString": N` now maps to `minLength`, and `isInteger`/`isNumber` digit bounds reach the schema as a human-readable `description` plus a machine-readable `x-gina-digitBounds` extension. They are deliberately *not* emitted as `minimum`/`maximum` (wrong for any negative value, whose sign counts toward the length) nor `minLength`/`maxLength` (string-only keywords, inert on numeric types). Schemas generated from bare `true` rules are byte-identical.
|
|
106
|
+
- **Fixed — the scaffolded bundle template taught an impossible session-store selection.** `bundle:add` emitted `expressSession.name = 'myRedis'` — `Function.prototype.name` is read-only, so the assignment silently no-ops and the factory always resolved the literal `"session"` entry, meaning the template's own `"myRedis"`/`"myDb"` examples could never be found and boot failed with `[SessionStore] Could not be loaded`. The template now shows the documented shape: one `connectors.json` entry named `"session"` whose `connector` field selects the backend.
|
|
107
|
+
- **Changed — the dormant transitive `object-assign` dependency is overridden.** `engine.io` → `cors` → `object-assign@4.1.1` (unmaintained since 2017) is replaced by `@socketregistry/object-assign` via npm `overrides`, with zero runtime change. **Scope, so nobody reads more into this than it does:** npm and bun alike honour `overrides` only in a project's *own root* manifest, so this cleans the gina tree and **not your install** — a project depending on gina still resolves `object-assign@4.x` beneath `cors`. Add the same `overrides` entry to your own root `package.json` to get it in your tree; the consumer-reaching fix is upstream ([expressjs/cors#430](https://github.com/expressjs/cors/pull/430), filed).
|
|
108
|
+
|
|
80
109
|
See the full [Changelog](./CHANGELOG.md) and [Roadmap](./ROADMAP.md).
|
|
81
110
|
|
|
82
111
|
## Documentation
|
package/ROADMAP.md
CHANGED
|
@@ -54,6 +54,7 @@ This roadmap covers planned features, architectural improvements, new connectors
|
|
|
54
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
55
|
| **Q4 2026** | `0.6.1` ✅ | **Security**: the dev-mode Inspector no longer serves files outside its asset root — a request to `/_gina/inspector/*` carrying a literal `../` escaped the asset directory and read any file the bundle process could reach, application config and credentials included, on both engines; only dev-mode bundles ever served the handler, and the URL-encoded `%2e%2e` form was never affected (#B179) · **Added**: DuckDB connector — embedded analytical (columnar / OLAP) SQL over the standard entity wiring, with analytical-dialect row detection (`WITH` CTEs, `SUMMARIZE`, `PIVOT`), direct Parquet / CSV / JSON querying with no ETL hop, and a `readOnly` mode so any number of processes can share one database file (#CN11) · **Added**: SQLite under the Bun runtime — the ORM connector, session store, async-job store and framework state store resolve Bun's built-in `bun:sqlite` behind a `node:sqlite`-shaped adapter whenever `node:sqlite` is absent; Node resolution is unchanged · **Fixed**: two Bun-only crashes that stopped any connector-declaring bundle from booting, both no-ops on Node by construction, with the release smoke now booting a SQLite-backed bundle on every Node leg and on Bun · **Fixed**: query files whose names collide with an inherited prototype member were silently skipped by six ORM connectors and now warn at startup with a rename hint, while Couchbase — which attaches unconditionally — warns on the overwrite or shadow instead (#B173/#B174) · **Fixed**: `renderJSON()`'s `status` key now reaches the wire over HTTP/2, where the body path hardcoded a 200 status frame and served every JSON error as HTTP 200 with the error payload in the body (#B172) · **Fixed**: FormValidator — each submit builds its own XHR with a fail-safe release, so a completed form no longer re-disables a sibling form's submit button; the live-check opt-out attribute is honored consistently; error labels for the keys an app can observe are translatable; and byte-identical messages render once, with sentence-separated screen-reader announcements (#B175/#B176/#B178) |
|
|
56
56
|
| **Q4 2026** | `0.6.2` ✅ | **Changed**: render and request-path CPU overhead sharply reduced — the per-render deep copies of the request options (template-filter configuration and render envelope) are passed by reference after each one's write surface was measured empty, per-request locale lookups are memoized with the request-local copy materialized lazily on first read, and the id generator right-sizes its entropy batch to the requested length; measured on the profiling harness at **4.4× render throughput** (10.7 → 2.4 ms per render), deep-clone CPU share 50.31% → 1.81%, GC time down ~18× — no API change, but the browser bundle changed so bundles pick the id-generator half up on rebuild (#P39) · **Added**: opt-in 503 + `Retry-After` rendering for transient datastore failures — with `server.transientErrors.enabled`, a connector error stamped `isTransient` that would render as HTTP 500 through `throwError` renders as 503 carrying `Retry-After`, with a configurable retry delay and user-facing message, on both engines across JSON and HTML error surfaces; off by default and byte-identical when off, and a malformed block warns at boot rather than refusing it (#CE1) · **Fixed**: an `env.json` block that omits `host` no longer leaves the `${host}` token unsubstituted inside the TLS credentials paths, which refused https and HTTP/2 boots with an ENOENT naming a literal `${host}` segment under an error pointing at the server settings — `host` was the only per-bundle value with no framework-side default, so a hand-written or partial block never received one (#B181) · **Fixed**: a bundle whose project `env.json` carries no block for the environment it starts in now refuses with the bundle, the environment, the resolved path and whether the file was found all named — covering the absent, empty and unlisted-bundles shapes — instead of an opaque `Cannot read properties of undefined` crash, exiting 1 so an external supervisor can retry (#B181) · **Fixed**: starting a bundle in an environment its `env.json` block does not cover refuses cleanly at exit 1 rather than dying at exit 143 on `Cannot set properties of undefined (setting 'bundlesPath')`, and a bundle declared only for other environments is now reported as skipped instead of taking every sibling bundle down with it (#B183) · **Fixed**: dead process records are removed from the `~/.gina/procs.json` registry under the right key — `removeRunningProc()` matched the entry by pid but deleted under the constructing bundle key, rewriting dead records back to disk and able to destroy a live one, degrading `gina stop`'s graceful-kill path (#B180) |
|
|
57
|
+
| **Q4 2026** | `0.6.3` ✅ | **Security**: the client-served routing map (`/_gina/assets/routing.json`) is now built from an ALLOWLIST instead of a denylist — controller dispatch keys (`param.control`/`file`/`path`/`title`), `namespace`, `scopes`, `cache` configuration including invalidation event names, `csrfExempt`, `middlewareIgnored` and `validator::` requirement bodies all stay server-side, and structurally so does every future route key until deliberately added to the roster; client URL building is unaffected, but code reading other keys off `gina.config.routing` must move server-side · **Added**: opt-in SPA-style client-side navigation — a route declares `negotiate: true` and answers `X-Gina-Navigate: fragment` layoutlessly over the same URL, while the new `gina/nav` module swaps same-origin link targets into a `data-gina-nav` region with history, scroll, focus, title, script re-injection and validator rebinding, falling back to a full-page navigation on every uncertainty; negotiable routes advertise `Vary: X-Gina-Navigate` and opt out of the render cache (#SPA1) · a configurable RFC 9211 `Cache-Status` identifier (`server.cache.name`), with a boot warn naming the residual framework disclosure when `hidePoweredBy` is set (#B238) · a Couchbase SDK soak harness that screens a candidate SDK in a fully isolated throwaway project before a consuming project adopts it (#CN12) · **Changed**: `/_gina/assets/routing.json` now revalidates on each page boot (per-variant weak `ETag` + `no-cache`, was `max-age=86400`), so a restart's new route table reaches returning browsers immediately instead of up to 24 hours later · the dormant transitive `object-assign` dependency overridden to a maintained re-export (gina's own tree only — `overrides` are root-manifest-scoped; the consumer-reaching fix is upstream) · **Fixed**: server-side form-body validation now enforces rules authored on bracket-notation (`account[username]`) and nested keys — previously skipped silently, fail-open, for checks, `exclude` and transforms alike (#B241) · the validator's empty-value contract made uniform: five loose-equality sites let `0`, `false` and `[]` ride the empty bypass so `isEmail`/`isJsonWebToken`/`isFloat` reported them VALID outright, and `is`/`isBoolean` joined the same contract (#B233, #B235) · `isBoolean` is now the single adjudicator on every surface — server auto-validation coerced junk to `false` and persisted it — and `isInteger` digit bounds enforce on real numbers, not only strings (#B236) · a `$` token in a rule no longer crashes the validation pass on either surface (#B234, #B239) · required radio groups now gate, and the submit trigger re-enables on a pick (#B221, #B228) · a field driving its own `_case_` block is validated and keeps the value the user picked (#B229, #B230) · a rejected submit no longer kills a form's live check for the rest of the page's life · the documented `setFlash` `[null, "message"]` form works in the browser (#B226) · `pauseRequest()`/`resumeRequest()` replay the byte-exact halted URL, query string included, on both engines (#B215, #B219) · `Controller.store()` publishes each file atomically and surfaces the real filesystem error instead of a fabricated `No file to upload`, where a source-stream error previously killed the bundle process (#B223) · custom error pages answer with their real HTTP status and keep their resolved template instead of falling back to the failing route's own file (#B190) · session stores no longer write an immortal record for an already-expired session (redis wrote an expiry-less SET; couchbase and scylladb stored a never-expires zero expiry) · a Couchbase N1QL parameter the SDK cannot serialize no longer aborts the whole bundle process (#B243), and range SDK pins like `~4.5.0` resolve instead of mangling past the version floor · `lib/math` `checkSumSync` — every array collapsed to the empty-string checksum, data ending in an extension shape was misrouted to the filesystem, and real file paths were hashed as path strings (#B208, #B209, #B210) · `GINA_*` environment variables are visible to the CLI's own bootstrap, the MQ and file logger containers, the MCP bind tier and `${secret:}` resolution · the client routing map serves under every engine, and a non-2xx boot fetch is no longer installed as the client routing table (#B212, #B213) · Inspector bundle-following across a proxy-routed project, per-tab restore, advertised-channel adoption and six scope/display fixes (#B205, #B222, #B225, #B231, #B237) · `bundle:openapi`/`bundle:mcp` no longer drop three declared bound forms when un-collapsing a `validator::{}` requirement · a sub-directory in the run directory no longer aborts every gina command · the scaffolded bundle template's impossible session-store selection (`expressSession.name = 'myRedis'` silently no-ops) |
|
|
57
58
|
| **Q1 2027** | `0.6.x` | HTTP/2 priorities (blocked on Node scheduler hooks) · Beemaster admin + visual translation editor |
|
|
58
59
|
| **2027** | `0.7.0` | Performance — remaining measure-gated candidates: multipart & WebSocket fast paths, render/log cleanups, SIMD scanner (the render-path deep-clone & id-mint reduction shipped early in `0.6.2` with a measured 4.4× render-throughput gain; the profiling baseline itself also shipped in `0.6.2`) |
|
|
59
60
|
| **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 |
|
|
@@ -313,9 +314,9 @@ New database connectors follow the same interface as the existing Couchbase conn
|
|
|
313
314
|
| ✅ | **PostgreSQL** | `0.3.0` | Q1 2026 | ORM connector. Client: `pg` (node-postgres). Entity wiring, `sql/` layout, `$1`/`$2` placeholders, `@param`/`@return` annotations, idle-client error guard, native Promise + `.onComplete()`. |
|
|
314
315
|
| ✅ | **ScyllaDB** | `0.4.0` | Q4 2026 | Cassandra-compatible wide-column store. Client: `cassandra-driver` (Apache Software Foundation; Node.js has no first-party shard-aware driver — token-aware routing only). ORM connector + session store via CQL `USING TTL`. Implemented 2026-05-09 (#CN5). |
|
|
315
316
|
| ✅ | **MongoDB** | `0.4.0` | Q4 2026 | Document store connector. Client: `mongodb` (official driver, `>=7.0.0`). ORM connector with `pipelines/<Entity>/*.json` files (JSON body + JSDoc-style `@param`/`@return` annotations + `{$arg: N}` positional placeholders + `{$oid: <hex>}` ObjectId literals + `$scope` substitution at load time). Session store backed by a TTL index (`createIndex({expiresAt: 1}, {expireAfterSeconds: 0})` auto-created on first `set()` with one-shot guard). `get()`/`length()`/`all()` filter on `expiresAt` to protect against MongoDB's 60s TTL monitor lag. Implemented 2026-05-09 (#CN6). |
|
|
316
|
-
| ✅ | **Couchbase SDK v2 deprecation** | `0.2.0` | 2026-03-27 | Couchbase Server SDK v2 reached end-of-life in 2021. `connector.v2.js` now logs a deprecation warning at connection time, and a fatal error when V8 pointer compression is active (NAN bindings are incompatible). Upgrade path: set `
|
|
317
|
+
| ✅ | **Couchbase SDK v2 deprecation** | `0.2.0` | 2026-03-27 | Couchbase Server SDK v2 reached end-of-life in 2021. `connector.v2.js` now logs a deprecation warning at connection time, and a fatal error when V8 pointer compression is active (NAN bindings are incompatible). Upgrade path: a driver bump — set the project's `couchbase` dependency to `^3` or `^4` (`npm install couchbase@^4`); the SDK version is derived from the installed `couchbase` major, never a `connectors.json` field. (The deprecation message originally shipped in `0.2.0` wrongly named a `sdk.version` config key that never existed — see the `0.4.0` removal row below.) |
|
|
317
318
|
| ✅ | **Couchbase SDK v2 removal** | `0.4.0` | 2026-05-22 | `connector.v2.js` and `session-store.v2.js` removed, along with every `sdkVersion`-based v2 branch in `index.js` (consistency setup, prepared-statement builder, FTS substitution, query dispatch, and the `bulkInsert` path). The connector and session-store resolvers default to SDK v3 and fail fast with an explicit upgrade message when a project still pins `couchbase@2`. Migration is a driver bump (`npm install couchbase@^4`), not a `connectors.json` edit — `sdk.version` is derived from the installed `couchbase` npm major, never a config key. |
|
|
318
|
-
| ✅ | **`peerDependencies` for connector clients** | `0.3.0` | 2026-04-01 | All connector client libraries (`ioredis`, `mysql2`, `pg`, `mongodb`, `@scylladb/scylla-driver`, `couchbase`, `openai`, `@anthropic-ai/sdk`) are declared as optional `peerDependencies`. Signals the tested version range to npm/yarn and surfaces a compatibility warning when a user pins an untested version. Zero framework runtime dependency — clients are always loaded from the project's `node_modules`. |
|
|
319
|
+
| ✅ | **`peerDependencies` for connector clients** | `0.3.0` | 2026-04-01 | All connector client libraries (`ioredis`, `mysql2`, `pg`, `mongodb`, `@scylladb/scylla-driver`, `couchbase`, `openai`, `@anthropic-ai/sdk`) are declared as optional `peerDependencies`. Signals the tested version range to npm/yarn and surfaces a compatibility warning when a user pins an untested version. Zero framework runtime dependency — clients are always loaded from the project's `node_modules`. **Superseded in `0.3.7-alpha.5` (2026-04-23):** the optional `peerDependencies` were removed from `package.json` — supply-chain analyzers (Socket, Dependabot, `npm audit`) aggregated the optional peers into gina's visible dependency surface even though gina never loads a driver itself. The tested ranges have lived in the framework's built-in connector registry ever since (today `lib/connector-registry`'s `DRIVER_MAP`, read by `connector:list` / `connector:add`); the zero-runtime-dependency property is unchanged. |
|
|
319
320
|
| ✅ | **`connector:*` CLI group + lint/fix migration** | `0.3.8` | Q2 2026 | New CLI for managing `connectors.json` at project (shared) or bundle scope: `connector:list`, `connector:add`, `connector:rm`, `connector:migrate`. Positional-absence signals scope — omit `<bundle>` to operate on `shared/config/connectors.json`, include it to operate on the bundle's own. `list` cross-references declared connectors against the project's `node_modules` and prints install status per driver. `add` writes the JSON entry and prints the exact `npm install <driver>@<range>` command (no auto-install in v1). `rm` supports `--dry-run` / `--force` and scans sibling bundles for usage before removing at project scope. `migrate` lints every `connectors.json` (or a single bundle's file) and, with `--fix`, injects missing `$schema` entries while preserving comment headers and key order — dry-run by default. Framework-side auto-migrate hook deferred to `0.4.0` alongside the Couchbase SDK v2 removal where a concrete old-shape → new-shape delta will justify touching the boot path. Adds a `version` property to the `connectors.json` schema for install-version resolution. Optional follow-up: `--install` flag with lockfile-based package manager detection. **Session 1 (`connector:list`) shipped 2026-04-21, `0.3.7-alpha.3`** — read-only lister with overlay/override detection, driver install probing, version-pin disagreement warnings, JSON output, 89 source-inspection unit tests. **Session 2 (`connector:add` + schema `version`) shipped 2026-04-21, `0.3.7-alpha.3`** — writes shared or bundle-scoped connector entries, infers type from `<name>`, preserves comment headers and key order, pins `$schema` at the top, rejects overwrites without `--force`, prints `npm install <pkg>@"<range>"` install hint (AI resolves per protocol scheme, sqlite short-circuits to built-in note), adds `version` property to `schema/connectors.json`. 94 source-inspection unit tests; 7 live smoke tests. CLI flag rename (`--connector-port=`/`--driver-version=`) avoids framework-reserved `--port`/`--version`. **Session 3 (`connector:rm`) shipped 2026-04-21, `0.3.7-alpha.3`** — removes shared or bundle-scoped entries via positional-absence scoping (`remove` alias accepted); `--dry-run` previews without writing; `--force` skips the project-level usage guard that otherwise refuses when any bundle still references the same logical name; driver-retention hint prints after every removal naming sibling bundles that still use the same driver (sqlite exempt — built-in); inherited-from-shared hint fires when rm from a bundle targets an entry declared only in shared. Never runs `npm uninstall`. 81 source-inspection unit tests. **Session 4 (`connector:migrate`) shipped 2026-04-21, `0.3.7-alpha.3`** — CLI-only linter: dry-run by default, `--fix` applies auto-fixable issues in place. Two detection types: `missing-schema` (auto-fixable, injects `"$schema": "https://gina.io/schema/connectors.json"` pinned at top while preserving comment header and key order) and `bare-key-no-connector` (entry key not in `couchbase, mysql, postgresql, sqlite, redis, ai` enum with no `connector` field — warn-only since driver cannot be inferred). Two invocation modes via positional-absence: `@<project>` scans shared + every bundle; `<bundle> @<project>` scans just that bundle. `--format=json` emits `{project, scope, bundle, fixApplied, files[]}` envelope for CI. Registered as offline — no framework socket required. Idempotent. Never modifies `core/config.js` and never runs at bundle boot — explicit and opt-in. Real framework-side hook deferred to `0.4.0` alongside Couchbase SDK v2 removal. 87 source-inspection unit tests; full write-path smoke test on a disposable sandbox (shared + two bundles), plus a no-false-positive smoke on a real 7-bundle project. |
|
|
320
321
|
| ✅ | **`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). |
|
|
321
322
|
| ✅ | **`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. |
|
package/bin/cli
CHANGED
|
@@ -160,6 +160,16 @@ async function onExec() {
|
|
|
160
160
|
shortVersion = shortVersion.join('.');
|
|
161
161
|
setEnvVar('GINA_SHORT_VERSION', shortVersion);// jshint ignore:line
|
|
162
162
|
|
|
163
|
+
// Import shell-exported GINA_*/VENDOR_*/USER_* overrides into the
|
|
164
|
+
// framework environment BEFORE the home/settings/host resolution
|
|
165
|
+
// below (keep-mode: process.env stays intact, so filterArgs()'s
|
|
166
|
+
// sweep later in bootstrap keeps its move semantics and the
|
|
167
|
+
// post-sweep precedence is unchanged). Without this pass, an
|
|
168
|
+
// exported GINA_HOMEDIR / GINA_BIND_HOST / GINA_MQ_PORT was
|
|
169
|
+
// invisible to this block and took effect one command late — via
|
|
170
|
+
// the settings regeneration — or never.
|
|
171
|
+
importEnvVars(true);// jshint ignore:line
|
|
172
|
+
|
|
163
173
|
home = getUserHome();// jshint ignore:line
|
|
164
174
|
if ( typeof(getEnvVar('GINA_HOMEDIR')) == 'undefined') {// jshint ignore:line
|
|
165
175
|
setEnvVar('GINA_HOMEDIR', home + '/.gina')// jshint ignore:line
|
|
@@ -175,7 +185,14 @@ async function onExec() {
|
|
|
175
185
|
}
|
|
176
186
|
|
|
177
187
|
settingsPath = _( homeVersionDirObj.toString() +'/settings.json', true );// jshint ignore:line
|
|
178
|
-
|
|
188
|
+
// Tracked so the bootstrap regeneration below never seeds a FRESH
|
|
189
|
+
// home: on a first-ever read (no settings file yet) its
|
|
190
|
+
// `getEnvVar(...) || settings[...] || null` chains would write a
|
|
191
|
+
// null-laden settings.json that the handler-phase init then trusts
|
|
192
|
+
// instead of seeding proper defaults. Seeding belongs to the init
|
|
193
|
+
// machinery; the regeneration is for updating an EXISTING file.
|
|
194
|
+
var settingsFileExisted = new _(settingsPath).existsSync();// jshint ignore:line
|
|
195
|
+
if ( settingsFileExisted ) {
|
|
179
196
|
settings = requireJSON(settingsPath);// jshint ignore:line
|
|
180
197
|
}
|
|
181
198
|
|
|
@@ -332,7 +349,7 @@ async function onExec() {
|
|
|
332
349
|
if (!settings) {
|
|
333
350
|
settings = requireJSON(settingsPath);// jshint ignore:line
|
|
334
351
|
}
|
|
335
|
-
if (isUpdateRequired && settings) {
|
|
352
|
+
if (isUpdateRequired && settings && settingsFileExisted) {
|
|
336
353
|
console.debug('Updating debug settings ...');// jshint ignore:line
|
|
337
354
|
settings['arch'] = getEnvVar('GINA_ARCH') || settings['arch'] || null;// jshint ignore:line
|
|
338
355
|
settings['platform'] = getEnvVar('GINA_PLATFORM') || settings['platform'] || null;// jshint ignore:line
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.6.3
|
|
@@ -29,6 +29,12 @@
|
|
|
29
29
|
} catch (e) { _ginaBC = null; }
|
|
30
30
|
function _ginaPublish() {
|
|
31
31
|
if (!_ginaBC) return;
|
|
32
|
+
// #B231 — advertise this tab's channel id so a ?ch=-less embedded
|
|
33
|
+
// Inspector (direct URL / bookmark / a window predating bound mode)
|
|
34
|
+
// can ADOPT bound mode instead of the bundle-global fallback.
|
|
35
|
+
// Last-writer-wins across tabs; adoption is guarded by a liveness
|
|
36
|
+
// handshake on the reader side (a stale advert never strands it).
|
|
37
|
+
try { localStorage.setItem('__gina_last_tab_ch', _ginaTabId); } catch (e) {}
|
|
32
38
|
try { _ginaBC.postMessage({ type: 'data', payload: window.__ginaData }); } catch (e) {}
|
|
33
39
|
}
|
|
34
40
|
// A freshly-opened Inspector posts {type:'request'} (BroadcastChannel does
|
|
Binary file
|
|
Binary file
|
|
@@ -287,6 +287,7 @@
|
|
|
287
287
|
<span class="bm-mem-text" id="bm-mem-text"></span>
|
|
288
288
|
</div>
|
|
289
289
|
<div class="bm-target">
|
|
290
|
+
<span class="bm-source-mode" id="bm-source-mode" hidden></span>
|
|
290
291
|
<span class="bm-dot" id="bm-dot"></span>
|
|
291
292
|
<span id="bm-label">connecting…</span>
|
|
292
293
|
</div>
|
package/framework/{v0.6.2 → v0.6.3}/core/asset/plugin/dist/vendor/gina/inspector/inspector.css
RENAMED
|
@@ -231,6 +231,25 @@ input:checked ~ .bm-toggle-track::after {
|
|
|
231
231
|
background: var(--err);
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
/* Data-source mode badge (#B231) — footer pill naming the active channel kind
|
|
235
|
+
(bound / agent / global); warn-tinted when the data tabs run bundle-global */
|
|
236
|
+
.bm-source-mode {
|
|
237
|
+
font-size: 9px;
|
|
238
|
+
line-height: 1;
|
|
239
|
+
padding: 2px 5px;
|
|
240
|
+
border: 1px solid var(--border);
|
|
241
|
+
border-radius: 3px;
|
|
242
|
+
color: var(--text-dim);
|
|
243
|
+
text-transform: uppercase;
|
|
244
|
+
letter-spacing: 0.04em;
|
|
245
|
+
flex-shrink: 0;
|
|
246
|
+
cursor: help;
|
|
247
|
+
}
|
|
248
|
+
.bm-source-mode.bm-source-mode-warn {
|
|
249
|
+
color: var(--warn);
|
|
250
|
+
border-color: var(--warn);
|
|
251
|
+
}
|
|
252
|
+
|
|
234
253
|
/* ── Refresh button (in target area, after bundle@env) ───────────────────── */
|
|
235
254
|
.bm-refresh-btn {
|
|
236
255
|
display: flex;
|
|
@@ -498,6 +517,26 @@ input:checked ~ .bm-toggle-track::after {
|
|
|
498
517
|
.bm-lp-pill-hidden {
|
|
499
518
|
opacity: 0.35;
|
|
500
519
|
text-decoration: line-through;
|
|
520
|
+
cursor: pointer;
|
|
521
|
+
transition: opacity 0.15s;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.bm-lp-pill-hidden:hover {
|
|
525
|
+
opacity: 0.7;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/* The + affordance on a hidden pill — inline-block escapes the parent's
|
|
529
|
+
line-through (text-decoration does not propagate into atomic inlines),
|
|
530
|
+
so the + stays unstruck while the label reads as removed. Amber on
|
|
531
|
+
hover, matching the reset-link hover idiom. */
|
|
532
|
+
.bm-lp-pill-add {
|
|
533
|
+
display: inline-block;
|
|
534
|
+
margin-right: 3px;
|
|
535
|
+
font-weight: 700;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.bm-lp-pill-hidden:hover .bm-lp-pill-add {
|
|
539
|
+
color: var(--accent);
|
|
501
540
|
}
|
|
502
541
|
|
|
503
542
|
.bm-lp-arrow {
|
|
@@ -675,9 +714,19 @@ input:checked ~ .bm-toggle-track::after {
|
|
|
675
714
|
.bm-mem-bar-wrap {
|
|
676
715
|
flex: 1;
|
|
677
716
|
height: 6px;
|
|
678
|
-
|
|
717
|
+
/* #B237 — the track was invisible: it shared .bm-footer's own background
|
|
718
|
+
token, in both themes. The groove must contrast the surface it sits on;
|
|
719
|
+
the inset shadow paints under the fill child, so it shades only the
|
|
720
|
+
empty (unfilled) region. */
|
|
721
|
+
background: var(--bg3);
|
|
679
722
|
border-radius: 3px;
|
|
680
723
|
overflow: hidden;
|
|
724
|
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
[data-theme=light] .bm-mem-bar-wrap {
|
|
728
|
+
/* 35% black on #dddde1 would read as a smudge — soften for light theme */
|
|
729
|
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12);
|
|
681
730
|
}
|
|
682
731
|
|
|
683
732
|
.bm-mem-bar {
|