New Features
Mail Proxy and Email Queue
A complete email dispatch subsystem has been introduced:
A
message_to_sendqueue table stores outgoing emails together with their sending status. A dedicated dashboard lets operators monitor the queue in real time.A mail-proxy integration layer routes messages through the queue, using the
message_to_sendformula as the single gatekeeper that decides whether a message is actually sent.The new architecture decouples email generation from delivery, making retry logic and auditing straightforward.
GnrListener - event-driven handler system
A new GnrListener class (gnr.app.gnrlistener) provides a
declarative, database-backed publish/subscribe mechanism:
Handlers are registered with the
@listendecorator and are auto-discovered at start-up both at module level and on package classes.An optional thread-pool executor enables parallel handler execution for high-throughput workloads.
Notification payloads are automatically enriched with
user,page_id, andtsfields and serialised withtoTypedJSON.The polling loop has been delegated to the adapter layer, keeping the core listener free of database-specific code.
Centralised Error Handler
A new centralised errorHandler (PR #677) replaces the scattered
per-page error handling:
Errors are broadcast via
pkgBroadcastso every open page is notified simultaneously.Toast notifications provide immediate, non-intrusive feedback.
A traceback viewer allows developers to inspect the full Python stack trace directly in the browser.
REST API Dispatcher (_api)
A new _api dispatcher has been added to the web layer, providing
first-class routing for REST API endpoints without requiring a dedicated
WSGI application.
ExpandBox Widget
A new expandbox widget based on the HTML5 <details>/<summary>
elements has been added to the grouplet system. It provides
zero-JavaScript collapsible sections and integrates with the existing
grouplet panel infrastructure.
GnrToast Improvements
GnrToast has been extended with two new options:
persistent - the toast stays visible until the user explicitly dismisses it.
copyable - a copy-to-clipboard button is added to the toast body, useful for error messages or reference codes.
gnr.web.widgets Package
A new Python package gnr.web.widgets has been introduced. Every
widget exposes an @element method that returns its Bag-based
descriptor, providing a programmatic API for widget introspection and
documentation generation.
Sourcerer Integration
GenroPy now ships a built-in service adapter for Sourcerer, registered through the standard service declaration mechanism.
Improvements and Refactoring
CSS / Theme System Modernisation
An extensive CSS overhaul (PR #671 and follow-up commits) affects the entire UI:
A design-token system replaces ad-hoc colour literals. All colours are now expressed through a numbered seven-step gray scale (
--gray-1---gray-7) and semantic aliases (--border-light,--border-strong, etc.).Border-radius values are centralised in CSS custom properties; the
--palette-*namespace has been retired in favour of the new tokens.color-mix()calls have been replaced with explicit hex values to maximise browser compatibility.The theme selection mechanism is unified: the
GNR_CSS_THEMEenvironment variable now controls the default theme consistently in bothdefault.xmland the Dockerfile.CSS variables have been added for
--multibutton-selected-bg,--button-in-grid-bg,--frameindex-tablist-*sizing, and thedeletingButtonspecialisation.
Grid Enhancements
Flex grid columns now enforce an automatic minimum width so that column headers are never truncated below their natural size.
Widget-in-cell rendering has been overhauled: text centering, the invalid-cell icon, and style-attribute conflicts have all been fixed.
The
required_columnsparameter is now honoured in print-resource grid queries.drawFillerwidth calculation has been restored to its pre-PR #749 behaviour.
Grouplet Panel
GroupletFormnow maintains a strict datapath separation between the grouplet's own data and the host page's store, preventing cross-page data leaks.The error indicator is now shown only when there are actual validation errors, not on every field change.
The inline
_onRemotepattern has been replaced with a propergnrwdgmethod, improving reusability.A double-load on the preference page has been eliminated.
Authentication Module
Auth verifiers have been extracted from gnrwebpage into a dedicated
module (PR #700), improving separation of concerns and making it easier
to swap or extend the verification strategy.
Daemon Package
Daemon initialisation logic has been moved into gnr.web.daemon.service
(PR #695, #688), reducing coupling between the CLI entry points and the
runtime service objects. The DataCollector (register analyser) has
similarly been moved out of the CLI layer.
gnrdeploy Refactoring
The deployment helper has been refactored (PR #706) to separate
configuration parsing from execution. A typo that mapped column.type
instead of column.dtype was fixed as part of this work.
Siteregisters Module Organisation
Siteregisters modules have been reorganised (PR #733) to follow a clearer package structure, making it easier to locate and extend individual register implementations.
Database Migration Extensions
The gnr db migrate command now accepts a -e/--extension
option with possible values txt, json, or sql, giving
operators control over the format of generated migration scripts.
PostgreSQL Extension Handling
The gnr database layer now uses CREATE EXTENSION IF NOT EXISTS
instead of the previous DROP - CREATE sequence, making migrations
idempotent and safe to re-run.
Werkzeug ProxyFix
The ProxyFix WSGI middleware is now automatically applied when the
application is running inside Kubernetes, ensuring that REMOTE_ADDR,
HTTP_HOST, and scheme headers are correctly resolved behind a
reverse proxy.
Frameindex Top Hook
The frameindex top hook is now decorated with @customizable,
allowing projects to override the default rendering without monkey-patching.
functools.wraps is applied so that the decorated function retains its
original __name__.
K8S Generator
K8SGenerator now accepts an optional initContainers argument for
providing accessory init containers to the generated Kubernetes manifests.
Services Declarations
Missing name and protocol fields in service declarations have been
added, and last_refresh_ts availability in new connections has been
fixed.
Autoreload Browser-Open Fix
When Werkzeug autoreload is active together with the -o (open browser)
option, the browser is now opened only once by the main monitor process,
preventing duplicate tabs on every file change.
Removals and Clean-up
Legacy Dojo 1.8 library (
dojo_libs/dojo_18) has been removed. The framework now targets a new Dojo internal fork in a non-exclusive way, coexisting with old Dojo 11.``legacy_packages/gnr`` has been removed.
``example_configuration/demo_site`` has been removed.
Dead WSGI code has been deleted (PR #739).
The
name_fullfallback from preference caption resolution has been removed; callers must supply an explicit caption.Tree branch PNG icons have been replaced by pure-CSS triangles, eliminating several image assets.
Bug Fixes
The
sendMessagemethod now consultsmessage_to_sendas its sole gating condition, preventing duplicate sends and race conditions.
Storage / S3
S3multipart upload ETags (which contain a-<partcount>suffix) are now correctly detected via alencheck rather than a fragile string scan. Themd5hashhelper returnsNonefor multipart ETags instead of raising.
CKEditor
The
disabled vs readOnlyregression introduced in a previous release has been fixed. Disabled CKEditor instances are now visually distinct from read-only ones.
DateTimeTextBox
DateTimeTextBoxno longer clears its value on blur when the field contains a valid date/time.
Login Form
The
login_newUserform has been converted fromframeFormtoboxFormso that it auto-sizes correctly on all viewport sizes.
Document Store
The custom
rpcmethodinload_documentand the handler rpcmethod chain inload_record,save_record, andsave_documenthave been restored after being lost in a previous refactoring.
Web Page
userLocalTagsnow returns a safe empty value instead ofNonewhen called from aremoteBuildercontext, preventingAttributeErrordownstream.The
--nodebugcommand-line flag is now correctly evaluated and no longer silently ignored.Debug-level evaluation order has been corrected so that the intended log level is applied from the very first log statement.
Record / BoxForm
The
recordproperty has been extended to be compatible withBoxForm, removing an incompatibility introduced when grouplet panels were redesigned.
Batch Handler
Schedulable batches that do not define a
table_script_parameters_panenow correctly show their parameters dialog (PR #679).Batch handler CSS now uses
emunits and CSS custom properties for consistent scaling; the thermoline label is flex-centred.
Theme / CSS Fixes
css_themedefault value is now consistent betweendefault.xmland the Dockerfile entry point.The theme editor has been fixed after the CSS variable renaming.
Obsolete
--radius-*and--palette-*variable references in project and resource CSS files have been updated to the new token names.The
framedindex_tablistnow usesmin-heightinstead ofpaddingto avoid layout collisions.hiderLayerandhiderMessagereadability has been improved.The draft-marker ribbon position is now configurable via a
draftMarkeroption.Duplicate CSS triangle chevrons in the mobile menu are hidden when
branchiconrightis active.Toolbar background and
border-strongcolours have been darkened for better contrast.grouplet_chunk_boxposition: relativehas been moved from hardcoded Python into the CSS file.NumberTextBoxand other right-aligned inputs now have symmetricpadding-right.The quickgrid toolbar
contentPanenow has a base height so it is always visible.TabContainerborder-radius is applied only to the top-right corner to preserve the visual tab-line continuation.The linker error tooltip is now always visible and the scrollable-table header sync issue has been resolved.
XSS sanitisation has been added to the dojo_20 toast output.
ping_semaphoreCSS visibility andTimeTextBoxpopup styling have been corrected.The
ext_column handler mechanism now correctly supports multiple handlers on the same column (PR #698).
mkthresource
Cross-package foreign key relation errors in
mkthresourcehave been fixed (PR #684).
Wizard / Formlet
Wizard
onLoadingof the main form has been fixed.Formlet fields now correctly display error, focus, and disabled visual states.
Preferences
The preference page no longer triggers a double load on initialisation.
GroupletFormpreference indicator now shows only on error conditions.
Miscellaneous
_th_mixinResourcenow operates in safe mode for tables that have noth_resource, and multidomain error URLs are handled correctly (PR #716).display: flexhas been removed fromcellContentto restore correct template grid column widths.inline-flexis now used for formbuilder cells inside toolbars.Minor hider background fix removing an unwanted box shadow.
