You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
[Breaking] Namespace the commanding pause configuration under config.commanding.pause. The flat config.commanding.pause_timeout setting has been removed in favor of the nested config.commanding.pause.timeout namespace, mirroring the pause configuration namespacing introduced in Karafka.
[Enhancement] Link the topic, partition and offset in the Explorer's single-message metadata table to the Explorer, matching the linking on the Errors detail view. The offset points at the message currently being viewed but is kept linked so the whole topic/partition/offset coordinate is navigable (#1179).
[Enhancement] Link the topic, partition and offsets on the Errors detail view to the Explorer, so you can jump straight from an error to the corresponding topic/partition/message. The topic links to the topic in the Explorer, the partition links to the partition, and the producer dispatch-error offset is now linked as well (previously only first_offset/last_offset/committed_offset were, and only when valid). Also linked the partition and its scanned offset range shown in the Search results metadata to the Explorer (#1179).
[Enhancement] Make assert_ok surface the actual captured exception (class, message, backtrace) on a 500, not just the generic static error page body. Subscribes to the same error.occurred monitor event the production error handler already dispatches web UI errors through, capturing the last one per test. This has been the main blocker in diagnosing rare CI-only flakes in the Pro Explorer controller specs, where a failure only ever showed the generic HTML error page with no indication of what actually broke.
[Enhancement] Remove the OSS "support Karafka Pro" banner that was rendered on every Web UI page for non-Pro users. It's no longer needed at this stage since users are already aware of the Pro offering.
[Enhancement] Migrate the Web UI topic declarations to Karafka's new standalone Karafka::App.declaratives.draw API (Karafka 2.6.0.beta1). The Web UI topics are declared as active false (Web UI manages their creation and runtime replication factor itself), replacing the deprecated routing-based config(active: false) bridge that was previously called on each routing topic.
[Enhancement] Add Warning.process block to the test helper to turn Ruby warnings originating from the project code into test failures.
[Enhancement] Enable all opt-in Ruby warning categories in the test helper via Warning.categories (available since Ruby 3.4), so any new categories added in future Ruby versions are automatically enabled without code changes.
[Enhancement] Replace sequential per-partition query_watermark_offsets consumer calls in Counters#estimate_errors_count with a single targeted topic_info metadata call followed by a batch read_watermark_offsets admin call. This eliminates the consumer connection overhead and reduces Kafka roundtrips from up to N+1 sequential calls to 3 regardless of partition count.
[Enhancement] Allow for zero value in number of workers to support dynamic scaling of Karafka workers.
[Enhancement] Align concurrency tracking with dynamic thread pool scaling. Workers count is now read from Karafka::Server.workers.size instead of the static Karafka::App.config.concurrency, so the Web UI accurately reflects runtime thread pool changes.
[Enhancement] Track poll_interval (max.poll.interval.ms) per subscription group alongside poll_age to help users monitor how close they are to the polling timeout limit. Consumer schema version bumped to 1.7.0.
[Enhancement] Replace token-based CSRF protection (route_csrf plugin) with header-based protection using Sec-Fetch-Site header (sec_fetch_site_csrf plugin). This eliminates the need for CSRF tokens by leveraging browser-enforced headers that cannot be forged from cross-origin requests. Modern browsers automatically include this header, providing simpler and more robust CSRF protection.
[Enhancement] Include a short spec file hash in generated test topic names for traceability. Topic names now follow the it-{hash}-{uuid} format, making it easy to identify which test file created a given topic in Kafka logs.
[Enhancement] Add a standardized empty_state helper/component (icon, message, optional description, and optional call-to-action) and replace the ad hoc alert_info/alert_box_info "There are no X" messages across every empty-list view (Jobs, DLQ, Explorer, Health, Errors, Consumers, Recurring Tasks, Scheduled Messages, dashboard, and paginated tables) with it, for a consistent look across the Web UI. Demoed on the internal style-guide /ux page.
[Enhancement] Expand the internal /ux style-guide page to cover every UI component actually used across the app, so upgrades (daisyUI, Tailwind, etc.) can be visually spot-checked in one place: plain .card/.card-body, .modal/dialog, .dropdown, .tooltip, the .btn-ghost/.btn-square/.btn-action/.btn-lockable/.confirm-action button modifiers, the breadcrumbs component, and the status_badge/lag_trend_badge/kafka_state_badge/lso_risk_state_badge/truncate/lag_with_label/offset_with_label helper methods (previously only their raw CSS classes were demoed). Adds a small reusable ModalOpener JS component ([data-modal-open]) since the CSP disallows the inline onclick handler style used by the existing search modal trigger.
[Enhancement] Replace the bare assert(response.ok?) pattern with a new assert_ok test helper across the whole controller test suite (381 call sites). On failure it now prints the actual response status and a body excerpt instead of a generic "Expected false to be truthy", making intermittent CI-only non-200 failures actually diagnosable.
[Change] Require Karafka >= 2.6.0.rc2 (was >= 2.6.0.beta1), which ships the nested pause routing DSL and the removal of the flat per-topic pause setters.
[Change] Require Roda >= 3.100 (previously ~> 3.69).
[Change] Switch to Karafka 2.6's new, group-type-agnostic #group/group_id accessors instead of #consumer_group/consumer_group_id when reading from Karafka's own routing and instrumentation APIs (topic.group, subscription_group.group, event[:group_id]), preparing for upcoming Kafka share group support (KIP-932). consumer_group/consumer_group_id remain as karafka-web's own internal naming (tracking payloads, commanding schema, UI labels) — only the calls into Karafka's own API surface changed. Closes #1022.
[Fix] The Explorer's time-based #closest lookup for a time beyond the last message now lands on the partition's default view (the latest page of results), which is the closest data to a future time. Adapts to Karafka 2.6's Admin#read_topic fix (a Time start offset past the high watermark now returns no messages instead of the newest).
[Fix] Declare the Web UI consumer topic pause strategy via the nested pause(...) routing DSL (Karafka Pro's Granular Backoffs) instead of the flat pause_timeout/pause_max_timeout/pause_with_exponential_backoff setters, which Karafka 2.6 removed. The custom backoff is now applied only when Karafka Pro is available; on OSS the Web UI topic falls back to the global pause defaults. Without this, enabling the Web UI on Karafka 2.6 raised an error during routing.
[Fix] Link the global Jobs view's committed offset to the Explorer. jobs/_job.erb linked the first and last offsets but the committed offset was accidentally rendered as plain text, unlike the consumer-scoped Jobs view which links all three (#1179).
[Fix] Fix two precision bugs in Aggregators::State/Aggregators::Metrics process eviction and utilization, both caught by a Copilot PR review and confirmed on the merged pipeline refactor. evict_expired_processes computed the ttl window via integer division (config.ttl / 1_000), truncating any non-multiple-of-1000 millisecond ttl and evicting processes up to ~999ms earlier than configured; it now uses float division. RefreshCurrentStats#call computed average utilization via utilization / (stats[:processes] + 0.0001), an epsilon guard against division by zero that also systematically underestimated utilization for any nonzero process count; it now divides exactly and returns 0.0 only when there are zero active processes.
[Fix] Fix the real cause of the intermittent, seemingly-unrelated CI-only Pro Explorer flakes finally surfaced by the assert_ok diagnostic below: not a Kafka broker/timing race, but Ruby's object-shape warning (a controller class crossing 8 distinct instance-variable shapes) being turned into a hard failure by the test suite's Warning.process hook. Controllers, like the Roda app classes already exempted, legitimately accumulate many shapes because they conditionally set a handful of instance variables depending on the specific request branch taken (e.g. Explorer's #show only sets @safe_key/@safe_headers/@safe_payload when the message isn't a compacted/system entry). Which controller happens to cross the threshold depends on minitest's random run order, which is why it surfaced as an unrelated-looking flake instead of a stable, reproducible failure. Widened the existing Ui::App shape-variation exception to cover controller classes too.
[Fix] Harden the wait_for_offset_visible test helper (used after a transactional produce) to also exercise the Web UI's own message-read path, not just the admin watermark offset. The admin watermark advancing only proves the broker appended the control record; the Web UI reads with a much shorter fetch.wait.max.ms than the admin client and could still intermittently raise or return stale results on that exact offset (e.g. the flaky Pro Explorer system entry spec), even after the watermark-only wait introduced previously. The helper now also polls the same Karafka::Web::Ui::Lib::Admin.read_topic call the Web UI performs and requires it to complete without error before returning.
[Fix] Fix two more flaky Pro Explorer #recent specs (when getting recent for the whole topic / when recent is on the first partition and when recent is on another partition). Both produced a message to one partition, then a fixed sleep(0.1) before producing the message that should be "most recent" to another partition and immediately requesting the endpoint, racing broker propagation under CI load the same way the already-fixed single-partition #recent spec did. Replaced the fixed sleep with a wait_for_message poll on the second produce's own offset, matching the existing pattern used by the sibling spec right below it.
[Fix] Stop a long, unbreakable page title (e.g. a long topic name on the Pro Explorer topic page) and the breadcrumbs bar above it from overflowing the page. A grid/flex item's default min-width: auto let the title and breadcrumbs blow out past the viewport instead of shrinking, which pushed layout wide enough to force an unexpected page scrollbar. The title wrapper and breadcrumbs-wrapper now set min-width: 0, the title text wraps via overflow-wrap: anywhere, and the breadcrumbs list now wraps onto multiple lines instead of relying on an easy-to-miss horizontal scroll.
[Fix] Stop long, unbreakable flash messages (e.g. a long dotted/underscored topic name in a "successfully created" notice) from overflowing their alert box. DaisyUI's .alert grid track sized the message column to its content's intrinsic width, so long single-token strings pushed past the box edge instead of wrapping. The message span now sets overflow-wrap: anywhere and min-width: 0 so it wraps within the alert instead.
[Fix] Stop long, dotted/underscored Pro Explorer, DLQ, and Topics topic-tile names from overflowing or overlapping their tile. topic-tile-text now sets overflow-wrap: anywhere so unbreakable names wrap inside the tile instead of spilling out, and the topic-tile link in those three views now carries a title attribute showing the full topic name on hover.
[Fix] Make the create_topic test helper wait until a freshly created topic's partitions are actually readable (expected partition count visible and watermark offsets queryable), not just until the topic name appears in cluster metadata. This removes a flaky failure in multi-partition specs (e.g. the topics distribution controller) that intermittently 404'd because watermark offsets were read before the partition leaders had propagated.
[Fix] Stop the array paginator from offering a "Next" link to an empty page when the last page is exactly full. Paginators::Arrays decided "is there a next page?" from whether the current page was full, so any list whose total size was an exact multiple of per_page (25/50/75/...) surfaced a Next link leading to an empty page. It now reports the last page based on whether a further slice actually exists.
[Fix] Compute the dashboard average batch size with float division so it is no longer floored. Metrics::Aggregated divided the per-window message delta by the batch delta using integer division, so e.g. 1000 messages over 47 batches charted as 21 instead of 21.28, systematically under-reporting the average. It now uses float division rounded to 2 decimals.
[Fix] Include jobs in the waiting state when aggregating the dashboard "Pending" counter. State#refresh_current_stats now resets and sums stats[:waiting] from incoming consumer reports (previously it was never aggregated and stayed 0), so Counters#pending (enqueued + waiting) no longer undercounts jobs sitting in advanced/recurring/scheduled-message schedulers. :waiting is now also validated by the AggregatedStats contract.
[Fix] Add initialize to Status::Context that defines all instance variables upfront in a consistent order, giving every instance the same Ruby object shape and eliminating the :performance shape-variation warning.
[Fix] Accept (and ignore) a block in Karafka::Web::Producer#__getobj__ to silence Ruby 3.4's strict_unused_block warning emitted via SimpleDelegator#method_missing on every delegated producer call.
[Fix] Remove cgi as no longer needed.
[Fix] Exclude test/ directory from gem releases to reduce package size.
[Fix] Update LinksValidator regexes to match the new it-{hash}-{uuid} test topic naming format, fixing test-order dependent failures in explorer controller specs.
[Fix] Fix alerts formatting for the distribution view.
[Fix] Fix 500 error in the Pro Explorer when a message payload parses as valid JSON but contains strings with invalid UTF-8 byte sequences. JSON.pretty_generate would raise JSON::GeneratorError outside of any error boundary and propagate as an unhandled 500. The pretty-print step is now wrapped in a dedicated @safe_pretty_payload SafeRunner; on failure the raw bytes are displayed alongside a deserialization warning.
[Fix] Fix 500 error in the Pro Explorer message JSON export when a payload deserializes correctly but cannot be serialized back to JSON (for example when it contains strings with invalid UTF-8 byte sequences). The export endpoint now responds with 404 in such cases and the export action button is no longer rendered for such messages.
[Fix] Normalize a batch of styling inconsistencies found while auditing #906: a data-table-wraper typo left the Cluster replication table unstyled, Cluster::_config rendered raw true/false instead of badges (unlike the identical Topics::Configs table), a Recurring Tasks "Trigger" button's disabled state was computed but never applied to its class, several views carried dead pre-Tailwind Bootstrap classes (col-sm-*, col-lg-*, row, container-wrapper) with no effect, one Topics Configs action cell was missing the options column class, a handful of breadcrumb/title labels had grammar or casing inconsistencies ("Cluster informations", "Consumers Groups Health", "Dead Letter Queue topics"), the OSS Routing topic list hand-rolled a badge-warning for inactive topics instead of the badge_secondary used by the identical Pro table, the filtered-payload notice used unstyled Bootstrap-era markup instead of the shared alert_box_warning primitive, status-row-stopping was colored red (border-l-error) while status_badge treats "stopping" as the same warning tier as "quiet"/"quieting", three Pro Topics checklist notices (before deleting a topic, increasing partitions, or editing a config value) hand-rolled a bare alert div with no severity color or icon instead of the shared alert_box_warning primitive used by their sibling warning boxes on the same pages, alert_box_primary/alert_box_secondary displayed the success checkmark icon (copy-pasted from alert_box_success) instead of matching their non-box info_circle/pause_circle siblings, the internal style-guide page demoed the wrong pencil icon for edit actions, and a scheduled message's "Cancel dispatch" button used a passive error-status icon instead of the trash icon already used for every other removal action.
[Fix] Continue normalizing styling inconsistencies from the #906 audit: Health and Recurring Tasks tab bars hand-rolled col-span-12 mb-9 instead of the shared tab-container-wrapper class, and the Scheduled Messages per-partition schedule heading used h3/.h3 where the equivalent per-group heading on Health pages uses h2/.h2.
[Fix] Retire the .row-table/.row-table-wrapper table primitive, which had drifted to a single real caller (the Pro per-topic Errors table) against 45+ real uses of .data-table, and additionally used a different button-alignment convention (text-center vs. .data-table's text-right) than every other action column in the app. Switched that one table to .data-table, removed the now fully unused CSS utilities and their style-guide demo, and fixed a stale ".row-table" label left over in an unrelated .data-table demo section.
[Fix] Fix unreadable .btn-outline.btn-active buttons (e.g. the dashboard time-range selector) in both the light and dark themes. The daisyUI 5.6 upgrade left the active state's background color computed from the same --btn-color variable as the outline's text color, so the two nearly matched; the button now switches to the color-variant's contrasting foreground color when active, matching its existing :hover behavior.
[Fix] Fix a flaky Pro Explorer spec (when requested message exists but is a system entry) caused by the produce test helper's transactional flow: it only waited a fixed sleep(0.1) for a transactional produce's commit control record to become visible before the test reads it back, which is too short under CI load and made the spec intermittently 404 or see stale content. Replaced the fixed sleep with a wait_for_offset_visible poll that waits until the control record's offset is actually part of the readable watermark range, mirroring the existing wait_for_message/create_topic readiness-polling pattern instead of a fixed delay.
[Fix] Stop a misclick on a Pro-gated OSS element from fully navigating away to the standalone "Pro Feature" upsell page. This affected the sidebar (Health, Explorer, Cron, Schedules, Dead, Topics), the Consumers tabs (Performance, Controls, Commands), the dashboard's "Data transfers" chart tab, and several unguarded links with no visual gating indicator at all: the dashboard's "Total lag"/"Dead" counters, Cluster topic/partition names, per-message Explorer offset links on the Errors detail page, and consumer process IDs on the Consumers and Jobs list pages. Gated sidebar/tab items are now truly inert disabled buttons with an "Available in Karafka Pro" hover tooltip instead of <a href> links (or, for the dashboard chart tab, a JS-clickable <span>) pointing at the real Pro-only content; the previously-unguarded inline links are now plain text in the OSS templates, with a matching Pro-only view override (dashboard/_counters, cluster/_partition, errors/_detail) restoring the links for Pro users, keeping the OSS templates free of any Karafka.pro? branching. Also fixes the sidebar's collapse/expand toggle showing the default arrow cursor instead of a pointer on hover, and hardens TabsManager (the chart-tab-switching JS) to no-op instead of throwing when a tab's target content or a previously-active tab is missing/disabled, which had broken tab-switching for the Utilization/RSS/Concurrency charts for anyone who had the now-disabled "Data transfers" tab persisted as their last-active tab. Closes #1106.
[Fix] Add rel="noopener noreferrer" to every target="_blank" link across the Web UI (docs, Slack, GitHub, and "become Pro" links in the support, status, dashboard, and Pro topic-replication warning views). Without it, the opened external page could access window.opener and redirect the original Web UI tab to an arbitrary page (reverse tabnabbing).
[Fix] Fix a flaky Pro Explorer spec (ExplorerController#recent::when getting recent for the partition) that produced a message and immediately requested the "recent" endpoint with no readiness wait, occasionally racing the broker's propagation of the just-produced message under CI load. Added a wait_for_message poll before the request, matching the existing readiness-polling pattern used elsewhere in the suite.