Skip to content

[ENG-46628] refactor: invert rules engine order arrows so down moves rule up - #3652

Merged
paulo-sobrinho-azion merged 33 commits into
devfrom
fix/ENG-46628-rules-engine-application-firewall-sort-arrows
Aug 13, 2026
Merged

[ENG-46628] refactor: invert rules engine order arrows so down moves rule up#3652
paulo-sobrinho-azion merged 33 commits into
devfrom
fix/ENG-46628-rules-engine-application-firewall-sort-arrows

Conversation

@paulo-sobrinho-azion

@paulo-sobrinho-azion paulo-sobrinho-azion commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Feature

Description

Adjust the sort arrows behavior of the position spinner in the Rules Engine lists (Application and Edge Firewall).

Previously, clicking the down arrow moved the rule down and the up arrow moved it up. Now the direction is inverted to match the requested behavior:

  • Down arrow → rule moves up (lower position)
  • Up arrow → rule moves down (higher position)

This is done via :step="-1" on the InputNumber, which inverts only the spinner buttons and keyboard arrows. Typed position input and min/max clamping remain unchanged.

Applied to:

  • src/views/EdgeApplicationsRulesEngine/ListView.vue
  • src/views/EdgeFirewallRulesEngine/ListView.vue

How to test

  1. Go to an Edge Application → Rules Engine tab (with at least 2 rules in the Request or Response phase).
  2. On a rule, click the down arrow on the position spinner → the rule should move up in the list.
  3. Click the up arrow → the rule should move down in the list.
  4. Confirm that:
    • Typing a position number directly still moves the rule to that exact position.
    • A rule at the top can't move further up, and a rule at the bottom can't move further down (min/max respected).
    • Drag-and-drop reordering still works as before.
  5. Repeat the same steps on an Edge Firewall → Rules Engine list.

UI Changes (if applicable)

Gravacao.de.Tela.2026-07-10.as.10.40.44.mov

Vídeo feito 30/07

Gravacao.de.Tela.2026-07-30.as.09.29.54.mov

No visual changes — the arrow icons remain the same. Only the movement behavior when clicking the arrows was inverted.

paulo-sobrinho-azion and others added 4 commits July 1, 2026 11:38
…val, vitest 4) (#3648)

* fix: azion@1.20.23

* chore: dependencie remove cypress and  sonar config

* chore: vitest@4

* chore: remove check dependencie only
…3651)

* fix: correct overly permissive regex range in full name validation

* fix: correct overly permissive regex range in full name validation
@paulo-sobrinho-azion paulo-sobrinho-azion self-assigned this Jul 10, 2026
@paulo-sobrinho-azion paulo-sobrinho-azion added the code-refactor A tag for Pull Requests focusing on code refactoring, improving code structure, readability, and mai label Jul 10, 2026

@isaquebock isaquebock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como haviamos falado anteriormente. Vamos deixar a funcao impactada nesse PR atomica e testa-la em unidade.

paulo-sobrinho-azion and others added 16 commits July 14, 2026 10:59
* fix: prevent long email overflow in profile menu

* fix: truncate long email in profile menu
… truth for account identity) (#3658)

* fix: prevent switch account from keeping the stale account

Account identity had two sources of truth: it was fetched via TanStack Query
(persisted account/info) and copied once into the Pinia account store that the
whole app reads. After a switch reload, a surviving persisted account/info could
be served stale, seeding the store with the old account, and the one-shot,
non-reactive copy never re-synced.

Make account identity a single source of truth:
- fetchAccountIdentity/getAccountIdentity compose account/info + user/me + job-role
  into one hardened query (persist:false, staleTime:0) so nothing stale survives
  the switch reload
- useAccountSync mirrors that query into the store through a single reactive writer
- setIdentity replaces identity (no cross-account bleed) while preserving additive
  billing/contract extras; setAccountData stays as a patch
- cancel any pending throttled persist during session cleanup so a stale write
  cannot re-populate IndexedDB after removeClient
- remove dead v1 getAccountInfoService and makeAccountBaseUrl

Adds a regression suite (src/tests/regression/switch-account-stale-state.test.js)
plus unit coverage for the identity query, store, reactive mirror and persister.

* test: broaden switch-account regression coverage

Exercise more of the real flow instead of mocks:
- sessionManager.switchAccount clears the account store, runtime cache and
  persisted cache, and cancels the pending throttled persist before
  removeClient; it does not broadcast until notifySwitchAccountComplete
- getAccountIdentity through the real query client returns the freshly
  fetched account after a switch clears the cache, never the stale one
- the merged identity exposes every field the account store getters depend on
- useAccountSync enables the query only when a session exists
* fix: exclude test files from architecture governance lint

Test files import services directly to mock/drive them and are never
composables, so the TanStack rules (require-vue-query,
no-direct-http-in-components) don't apply. They were being flagged only
because they live under governed dirs (src/views, src/services, ...),
producing false-positive CI failures.

Skip *.test.*, *.spec.* and __tests__/ paths in isGovernedFile so the
architecture lint only evaluates production code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: exempt pure colocated utilities from require-vue-query

The require-vue-query rule flags any composable importing from a service
dir, using location as a proxy for 'performs HTTP'. Pure utilities that
happen to live under services/ (no server call, direct or transitive)
were flagged as false positives.

Extend SERVICE_EXCEPTIONS in the import resolver to treat these as
utilities, not service entry points:
- -normalize / -operators filename suffixes (pure data transforms, e.g.
  ts-normalize, aggregation-operators)
- chart-api-router (pure API-selection logic by time range, no HTTP)
- panels-service (client-side panel/session state in local storage)

Verified against the codebase that these patterns match only the pure
modules; real data services in the same dirs (make-list-service,
graphql/*, users/workloads services) stay classified as services. Adds
rule tests covering each exemption plus a guard that a colocated HTTP
service is still flagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: bump fast-uri resolution to ^3.1.4 to resolve high-severity audit

The existing resolution (^3.1.2) resolved to 3.1.3, still below the
patched 3.1.4, so yarn audit kept reporting advisory 1124064 (fast-uri
host confusion) via ajv under azion, @jsonforms/core and @commitlint/cli.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…modifications (#3655)

* fix: prevent unsaved changes false positive on domain edit view

* fix: prevent unsaved changes false positive on workload edit view

* fix: prevent unsaved changes false positive on workload domain inputs

Blurring the domain/subdomain fields without editing them ran the
letEncrypt sync, writing recomputed commonName/alternativeNames and
bumping tls.certificate, which flipped the form dirty. Skip the sync
unless the domains field is actually dirty.

* fix: pass useField initial values in the options argument

useField('tls.certificate', { initialValue: 0 }) placed the options
object in the rules position, so vee-validate treated it as a rules
schema and threw "No such validator 'initialValue' exists" on every
validation, and the intended initial values never applied. Move them to
the third (options) argument.
* feat(real-time-events): improve chart aggregation, fix duplicate row IDs, and refactor UI

- Fix chart histogram: replace truncated groupBy:[ts] with bucketed GraphQL alias queries
- Fix chart rendering: increase container height, optimize bar width ratio
- Fix skeleton loading state overlapping with empty state
- Fix duplicate row IDs: generateCurrentTimestamp() now uses monotonic counter
- Add new RTE components: detail-sidebar, event-chart, field-selector, field-sidebar
- Add bucketed aggregation service and GQL aggregation helper

* fix: improve RTE filter bar, inline expansion, detail sidebar and tab aesthetics

- Fix filter bar font rendering uppercase (replace Tailwind font-mono with explicit monospace font-family)
- Fix AQL suggestion list font-mono uppercase issue
- Fix click-to-filter from badge: add missing field label property
- Add toast warning when filter field not found
- Improve TabView (Table/JSON) tab styling and spacing
- Fix detail sidebar to stretch with screen height (align-self: stretch)
- Pagination support with offset in convert-gql and list-http-request

* feat(real-time-events): histogram aggregation fix and discover-style document loading

- Replace bucketed aliased sub-queries with single groupBy:[ts] aggregation query
- Add FillResultQuery-equivalent resampling for Events (minute/hour/day intervals)
- Decouple chart aggregation from document list (independent failure handling)
- Implement hybrid pagination: offset for short ranges, temporal for long ranges
- Add page size selector (50/100/1000/2000) with localStorage persistence
- Update load more button with document count and Portuguese labels
- Fix event-chart.vue re-init when isLoading transitions to false

* feat(real-time-events): chart via Metrics API, layout Discover-style, dataset in filter bar

- Chart histogram now uses Metrics API (v4/metrics/graphql) for accurate aggregation
- Removed getTotalRecords call — total comes from Metrics API via chart emit
- Layout restructured: sidebar + chart + toolbar + table in single splitter
- Dataset selector moved from sidebar to filter bar with full description
- Client-side bucketing with Kibana-style auto interval (30 bars target)
- Timezone: uses accountStore.accountData.timezone with hour12:false (24h format)
- Colors: Azion brand orange #F3652B from azion-theme
- Removed duplicate dataset selector from FieldSidebar

* chore: add .kiro to gitignore, remove from tracking

* fix(real-time-events): remove unused code and add .kiro to gitignore

* feat(real-time-events): refactor module architecture with sessions, panels and composables

- Replace monolithic Drawer components with composable-based architecture
- Add session management (useSessionManager, session-browser, session-creator, session-tab-header)
- Add panels service with CRUD and localStorage persistence
- Add filter-loaders module with introspection-based dynamic field loading
- Add dataset-fields shared layer and aggregation operators
- Refactor event-chart with useChartBuilder, useChartBucketing and useChartConfig
- Add useEventsData, useDetailView, useDocumentSearch, useFieldStats, useFilterActions
- Add useMetricsChart and useMetricsDashboardResolver for metrics integration
- Add useExportData, usePageSize, useSeverityClassifier composables
- Add events-summary-bar, dashboard-panel components
- Replace static query-fields constants with dynamic field loading via introspection
- Add predefined-panels constants for investigation workflows
- Refactor TabsView and tab-panel-block to use new composables
- Remove legacy Drawer components and FormFieldsCreateEdgeApplications
- Update tests to reflect new buildSummary priority-based field ordering
- Add .kilo to .gitignore

* feat: improve real-time events data loading and aggregation

- Update event services to handle data aggregation properly
- Fix histogram bucketing and field statistics
- Improve advanced filter system components
- Update and fix tests for event services
- Clean up spec files

* fix: finalize real-time events implementation

- Ensure all chart scaling and document loading fixes are in place
- Validate filter data before loading events
- Apply filters on tab reactivation with proper async handling
- Update page size options and add OR operator support
- All implementation-related code corrections applied

* fix: improve chart rendering and UI polish

- Add 30-minute threshold for Events vs Metrics API routing (centralized in chart-api-router.js)
- Implement Metrics API fallback for WAF charts on ranges > 30 minutes
- Truncate long series names in chart legend (24 chars max) with full names in tooltip
- Fix chart tooltip z-index to render above other elements
- Change chart wrapper overflow from hidden to visible for tooltip visibility

* feat: compact timestamp format and documents found badge

- Add compact timestamp formatter for RealTimeEvents: 'Apr 22, 2026 at 18:47:53.832'
- Create service wrapper to apply compact format to all list services
- Add 'documents found' badge in table toolbar showing total document count
- Timestamp now includes milliseconds for better precision
- Format is localized to user's timezone

* fix: refine timestamp format and documents found badge styling

- Remove milliseconds from timestamp format (server returns only second precision)
- Adjust badge styling: smaller font (0.8125rem), subtle border and background
- Add 'documents found' badge in table toolbar with proper spacing and contrast
- Badge uses semi-transparent background for discretion

* feat(real-time-events): enhance metrics visualization and data handling

- Add support for direct-field queries in metrics API fallback to handle
  multiple independent GraphQL aliases per field, improving data fetching
  for services with column-level restrictions

- Implement new performance metrics charts (cache hit/miss, hit rate,
  request time, bandwidth) with custom colors and configurations

- Fix imageProcessor dataset name from 'imageProcessedEvents' to
  'imagesProcessedEvents' for correct API alignment

- Enhance chart builder with better data merging logic for per-field
  alias responses, consolidating rows by timestamp

- Improve advanced filter system with better content-editable handling
  and AQL filter support

- Update dataset fields configuration across all real-time event services
  (activity-history, data-stream, edge-dns, edge-functions, image-processor,
  tiered-cache) for consistency

- Add new chart types and series ordering for cache performance visualization
  with semantic color coding (green for HIT, red for MISS, etc.)

- Refactor event chart and summary bar components for better metrics display

- Update corresponding unit tests to reflect new data structures and behaviors

- Fix linting issues: rename single-letter variables to descriptive names
  (k->kilobyte, i->sizeIndex, a/b->rowA/rowB) for better code readability

This improves the overall user experience when visualizing real-time events
and metrics, especially for services with complex data access patterns.

* feat(real-time-events): fix Bot/WAF/Performance charts and tooltip

- Fix Bot Traffic and Bot CAPTCHA charts: use metricsApiSeries with
  per-category filtered queries (classifiedEq, challengeSolved groupByPivot)
  to eliminate senoidal artifact from groupBy + pivot approach

- Fix tooltip positioning: remove position:fixed CSS override on
  c3-tooltip-container that caused tooltip to render outside chart area

- Convert all metrics charts to spline timeseries: WAF (XSS, RFI, SQL,
  Other, Threats by Host), Bot (Traffic, CAPTCHA), Performance (Cache
  Hit/Miss, Tiered Cache, Requests Saved/Missed)

- Fix Y-axis scale for small values (Avg charts): formatCompact now
  preserves decimal places for values < 10

- Respect maxYAxis from chart config (Cache Hit Rate capped at 100%)

- Fix buildMultiSeries bucketing: use detectNativeInterval to prevent
  empty slots between real data points; average collapsed slots instead
  of summing to avoid inflated percentages

- Add distinct cache status colors: HIT(green), MISS(red), STALE(yellow),
  BYPASS(orange), EXPIRED(purple), REVALIDATED(cyan), UPDATING(slate)

- Add Bot CAPTCHA label mapping: challengeSolved 0/1/true/false mapped
  to Resolved/Unresolved via labelMap in groupByPivot config

- Convert stacked histograms (Events stack-by) to spline timeseries

* fix(real-time-events): fix chart range truncation on long time ranges

- Cap detectNativeInterval to max 2x autoBucket to prevent sparse API
  data from inflating the bucket interval and truncating the chart range

- Use Math.ceil for alignedEnd to ensure the last bucket covers the
  full rangeEnd instead of truncating before it

* feat(real-time-events): UI polish and layout improvements

- Align Fields sidebar header with chart header (same height/padding)
- Fix sidebar detail panel layout: scoped to discover-layout, full height
- Fix chevron toggle: closes sidebar when row already active
- Remove orange border on selected row
- Freeze Time column and chevron column in data table
- Optimize chart resize: use c3.resize() instead of full rebuild (50ms debounce)
- Standardize all filterbar element heights to 2rem
- Fix LoadMoreFooter border color to use surface-border token
- Remove duplicate border in EventsSummaryBar
- Add spacing between tab bar and filter bar
- Improve detail sidebar aesthetics: compact header, two-layer card content
- Fix DataTimeRange QuickSelect icon height (2.125rem -> 2rem)
- Standardize discover toolbar search input and button heights
- Add margin to field sidebar search input

* feat(real-time-events): chart improvements, bug fixes and field sidebar polish

- Fix status/proxyStatus showing '-' for falsy values (0) in buildSummary
- Fix chunk merge fallback by position when requestId is null
- Fix MULTI_SERIES_TIMESERIES bypassing bucketing (plot Metrics API data directly)
- Change spline charts to area-spline with monotone interpolation for richer visuals
- Add area fill opacity (15%) and thicker line stroke (2px)
- Improve bar chart ratio (0.7) for better spacing
- Add row dividers in data table (subtle 50% opacity border)
- Fix Time column width to 185px to prevent truncation
- Rename 'Log Explorer' to 'Events' in session browser
- Delete obsolete files: field-selector.vue, discover-data-table.css, REFACTORING_PLAN.md
- Field sidebar: pixel-perfect alignment, responsive from mobile to 4K
- Fix isValidValue helper to correctly handle 0 and empty strings in document view

* fix(real-time-events): fix chart rendering for tieredCache and other datasets

- Fix edgeFunctionsMetrics using wrong aggregate field (sum: requests → count: rows)
- Add METRICS_AGGREGATE_MAP for correct aggregate per Metrics dataset
- Add loadCacheStatusChartFromMetricsApi for upstreamCacheStatus groupBy
- Route upstreamCacheStatus to Metrics API (full 24h range, no bucketing)
- Fix chunk merge fallback by position when requestId is null
- Use area-spline with 5% opacity fill for multi-series charts
- Use monotone interpolation to smooth jagged lines
- Line stroke 1.5px, Y-axis padding top 24px for breathing room

* refactor: melhorias no sistema de eventos em tempo real

- Refatoração do sistema de filtros AQL com melhor estrutura
- Otimização da agregação de dados em tempo real
- Melhorias na composição de gráficos e configurações
- Ajustes nas ações de filtro para melhor performance
- Atualização do painel de abas com novos componentes
- Correção de erros de linting (identificadores curtos e variáveis não utilizadas)

* refactor(real-time-events): add accurate record count with chunked fallback and fix filter state

- useEventsData: add loadTotalCount that queries the API for an exact count
  when filters are active; falls back to 24h chunked requests (newest→oldest)
  when the full-range query hits the system limit
- useEventsData: replace currentOffset with currentWindowOffset to track
  pagination state per time window correctly
- useEventsData: initialise recordsFound as '—' instead of 0 so the UI
  shows a dash before the first load completes
- useFilterActions: fix defaultFilter to build timestamps at call-time and
  remove the isLoading guard that was blocking filter re-applies
- useViewSync: skip the initial watcher trigger on mount to avoid a
  duplicate load alongside the onMounted call
- useFieldStats: switch watcher source to data.value.length to avoid
  re-running stats on unrelated reactive updates
- load-events-aggregation: make orderBy optional in the GraphQL query
  string to avoid sending an empty orderBy clause
- convert-gql-aggregation: build orderBy string conditionally

* fix(real-time-events): fix metrics fallback for avg charts and count refresh on view change

- metrics-chart-service: add avg aggregation support to loadMetricsFallback
  via new aggregation + aggregationType fields in metricsApiFallback config;
  also add aggregationType support to loadMetricsAggregation so both paths
  can produce avg instead of only sum
- useMetricsChart: add metricsApiFallback to avgRequestTime and
  avgUpstreamResponseTime using aggregate: { avg: field } against httpMetrics,
  matching how Real-Time Metrics loads these charts — enables 7-day range
  instead of being capped at 30 min; avgConnectTime has no fallback because
  upstreamConnectTime does not exist in httpMetrics aggregated fields
- useEventsData: remove redundant isLoading guard at the start of load() so
  view changes always trigger a fresh load and count reset; loadCallId already
  cancels in-flight requests making the guard unnecessary

* feat(real-time-events): collapsible chart panel with flick-free expand

- event-chart: add collapsed prop and toggle-collapse emit; chevron toggle
  sits at the left of the header (same pattern as EventsSummaryBar); when
  collapsed shows CHART label instead of the count to identify what is hidden;
  chart body uses v-show to preserve the c3 instance across collapse/expand
- event-chart: add expandAndResize helper that sets visibility:hidden during
  the c3 resize() call and clears it on the next animation frame, eliminating
  the flick/flash when expanding
- tab-panel-block: wire collapsed state with localStorage persistence
  (rte:chart-collapsed); auto-collapse on fullscreen entry; pass collapsed
  prop and toggle-collapse handler to EventChart

* fix(real-time-events): wire GraphQL playground with live query from listService

- useEventsData: import useGraphQLStore and pass an onQuery callback to every
  listService call; the callback saves the last executed query+variables into
  the store so eventsPlaygroundOpener can read them — fixes the playground
  opening with query=undefined&variables=undefined for workloadEvents
- Other datasets (edgeFunctions, tieredCache, etc.) already call
  graphqlStore.setQuery() directly inside their service functions, so they
  were already working; only listHttpRequest used the onQuery callback pattern

* feat(real-time-events): enhancements — multi-tab, click-to-filter, KPI fix, tooltip, document details

- Multiple Events tabs: open/close/rename via session drawer, persist/restore on reload, share-link includes tab label and dataset (useEventsTabs, useTabLimit composables)
- Click-to-filter: single-click adds filter, Alt+click excludes, text-selection preserved (useClickToFilter composable wired into log-field-badges and event-document-view)
- Summary KPIs independent of Chart_View: loadSummaryKpis fallback service, useEventsData loadChart fallback path, tab-panel-block drops !isMetricsView guard
- Chart tooltip edge-flip: custom position callback in buildC3Config, diagonal offset from cursor (32px H / 28px V) so tooltip never covers bars or lines
- Document details: sticky header, single scroll container, JSON pre grows to fit, long-value wrapping, reset-scroll on tab switch
- Document column: 2-line badge grid with +N more indicator, proportional spacing, DS token-compliant row separation (stripedRows + surface-border)
- Remove New Events tab toolbar button — new tabs opened from session drawer
- Remove rounded prop from all PrimeButtons in RTE module (DS compliance)
- Detail sidebar: compact Kibana-style key/value grid, action buttons on hover, responsive width breakpoints

* feat: improve RealTimeEvents responsiveness, layout and UX

- filter-bar: fix AQL input taking full width by setting flex-wrap: nowrap
  and flex: 1 1 0% on query section; DateRange stays inline at all sizes
- date-range: compact display format 'May 10 @ 04:43' to save horizontal space
- detail-sidebar-panel: responsive width using 30vw with min/max bounds
- discover-toolbar: rewrite with scoped CSS, clamp() for proportional sizing,
  hide secondary buttons at <=1100px, hide search at <=900px
- event-chart: smaller legend tile size to reduce overflow
- event-document-view: fixed-height rows (1.625rem), actions visible on hover
  without layout shift, value truncates correctly with ellipsis
- events-summary-bar: always expanded by default; add percentage in collapsed
  inline view (e.g. '4xx 309M (0.61%)'); add formatPctShort helper
- log-field-badges: reduce maxFields default from 10 to 5 so '+N more' badge
  appears consistently; style more badge with dashed border
- tab-panel-block: wrap ResizableSplitter in discover-layout__main flex
  container so detail sidebar pushes table instead of overlapping it
- useChartBucketing: tighter niceYMax steps (1, 1.5, 2, 3, 5, 7) for better
  bar scale proportions
- useChartBuilder: remove Y-axis top padding so bars use full vertical space
- useEventsData: trigger KPI fallback when chart returns incomplete KPIs
  (supportsStatusBreakdown: false); merge fallback over chart KPIs
- load-events-aggregation: add loadSummaryKpisFromMetrics for large time
  ranges (>30min) that exceed Events API 2h window; routes loadSummaryKpis
  through Metrics API (Beholder) for status breakdown on any range

* feat(real-time-events): multi-bug fix sweep + UX polish + tenant-scoped history

Bug fixes
- Bug 1: `like`/`ilike` wildcards now honor user-placed `%` byte-for-byte
  in `convert-gql.js` (no double-wrap). `host like app%` → starts-with.
- Bug 3: extract `formatPillDateCompact` helper; date pills now preserve
  seconds (`MMM d @ HH:mm:ss`).
- Bug 4: discover-toolbar search no longer dominates the row — replaced
  rigid `clamp(8rem, 14vw, 14rem)` with shrinkable `flex: 0 1 14rem` and
  `flex-shrink: 1` on the right cluster.
- Bug 5: 45 previously-failing RTE Vitest suites green — per-suite
  `globalThis.localStorage` edits, complete mock-event factories in
  `useClickToFilter`, tightened `useEventsData` properties (P3 `min:1`,
  P6 relaxed bound), `fc.date` invalid-date filter, extra `nextTick` in
  `useViewSync`.

UX polish (date-range picker)
- Fluid responsive popover width: `width: min(25rem, 95vw); min-width: 23rem`
  (368-400px range) — no arbitrary breakpoints.
- Calendar cells overridden via PT inline style to win over Azion theme's
  `width: 32px !important` — now 28×28 with 12px font, consistent
  typography with time slots.
- Quick tab vertical spacing compacted (`mt-4` → `mt-3`, `pt-4` → `pt-3`,
  section labels `text-sm` → `text-xs`, grid buttons `!py-1 text-xs`).

Tenant-scoped filter history
- `useQueryHistory` and `useSavedSearches` now persist under
  `rte-query-history:<client_id>:<user_id>` and
  `rte-saved-searches:<client_id>:<user_id>` (read from
  `accountStore.account`). Watch reactive over the scoped key so account
  switches rehydrate naturally.
- Legacy unscoped keys removed on first load (contents were cross-tenant
  contaminated).
- Composables become no-op without account context (no leakage on
  pre-auth / logout windows).

Layout-only fixes
- Document detail's `.doc-search__field` capped at 20rem (was full-width).
- `LogFieldBadges` renders all fields and uses `ResizeObserver` to
  compute an accurate `+N more` count, replacing the arbitrary
  `maxFields: 5` cap and flex-grow hack.

Tests added
- `convert-gql-like-wildcard.prop.test.js` — PBT 1.A/1.B/1.C covering
  wildcard pass-through + chip-builder contract.
- `aql-like-wildcard.prop.test.js` — parser preserves `%` byte-for-byte.
- `aql-preservation.prop.test.js` + `aql-unsupported-operator.prop.test.js`.
- `useEventsData-buildApiFilters.prop.test.js` +
  `useEventsData-buildApiFilters.likeWildcard.prop.test.js`.
- `discover-toolbar.layout.test.js` — toolbar CSS + emit contract.
- `DiscoverToolbar.stories.js` — 5 viewports (`Mobile_360` …
  `WideDesktop_1920`).

Preservation
- `azion-query-language.js` parser, `queryValidator`, unresolved-operator
  early-return, and `useEventsData.buildApiFilters` operator-string guard
  unchanged.

* feat(real-time-events): apply production-code edits for multi-bug sweep

Completes commit 095f028 (test/story scaffolding) with the corresponding
source-file edits. Same scope; split happened only because `git stash pop`
unstaged the modified files between staging and commit.

- `convert-gql.js`: `wrapLikeValue` honors user-placed `%` (Bug 1).
- `format-timestamp.js`: new `formatPillDateCompact` helper (Bug 3).
- `inputDateRange/index.vue`: delegate compact formatter via alias;
  responsive Calendar PT (28×28 cells, text-xs); items-stretch row.
- `dataTimeRange/index.vue`: popover `min(25rem, 95vw); min-width: 23rem`.
- `quickSelect/index.vue`: vertical spacing compacted (`mt-3`/`pt-3`).
- `discover-toolbar.vue`: shrinkable right cluster, search not dominating.
- `event-document-view.vue`: doc-search field capped at 20rem.
- `log-field-badges.vue`: render all fields + ResizeObserver-driven
  `+N more` count.
- `useQueryHistory.js`, `useSavedSearches.js`: persist under
  `<key>:<client_id>:<user_id>` so filter history is tenant-isolated.
- `regression.test.js`: account-store mock exposes `client_id`/`user_id`
  so scoped composables work in tests.
- Bug 5 test edits across 8 RTE suites (globalThis.localStorage,
  mock-event hardening, property tightening, nextTick flush).

* feat(real-time-events): v1/v2 coexistence with user-controlled view toggle (#3523)

* feat: introduce v1/v2 coexistence with user-controlled view toggle

 - Allow users to switch between the classic Real-Time Events (v1, current production) and the redesigned Discover-style view (v2) via a button in the page header. Preference is persisted per browser, so clients can opt in to v2 at their own pace without disrupting existing workflows

* feat: update components for v2 compatibility and enhance filter functionality

* Revert "feat(real-time-events): v1/v2 coexistence with user-controlled view t…" (#3531)

This reverts commit fff6451.

* feat: introduce v1/v2 coexistence with user-controlled view toggle

 - Allow users to switch between the classic Real-Time Events (v1, current production) and the redesigned Discover-style view (v2) via a button in the page header. Preference is persisted per browser, so clients can opt in to v2 at their own pace without disrupting existing workflows

* feat: update components for v2 compatibility and enhance filter functionality

* feat: add version guard for real-time events navigation

* refactor: improve test code readability and maintainability

- Added eslint-disable comments for id-length rule in various test files to enhance clarity.
- Updated variable names in several functions for better understanding (e.g., changed loop variables from single letters to descriptive names).
- Removed unnecessary parameters and comments to streamline code.
- Ensured consistent formatting and structure across test files for improved readability.

* feat(real-time-events-v2): prefer events api and fix chart/filter display

* feat(real-time-events-v2): polish filter modal, dataset-aware chart UX

- Fix Add Filter modal layout: responsive width via CSS vars, box-sizing border-box, overflow-hidden
- Fix select-filter regressions: remove MultiSelect-only props, conditional search, restore max-w-lg
- Fix multiselect-lazy-loader: replace custom header with native filter, hide toggleAll
- Convert ArrayObject+Eq operators to StringObject for proper single-select rendering
- Restrict chart View selector to HTTP Requests dataset only
- Preserve "Drag to zoom" hint across all datasets
- Reduce chart height (clamp 140px/22dvh/240px) for better screen utilization at 1920px+
- Add saved searches with localStorage persistence and graceful quota handling
- Add share URL functionality with awaited clipboard API and fallback dialog
- Add GraphQL dataset guard to prevent invalid groupBy queries on unsupported datasets
- Add ESLint rule enforcing awaited clipboard.writeText() calls
- Add E2E tests and PBT/integration tests for the above

* fix: fix tests

* fix: corrige comportamento e layout do filtro AQL

* fix: sincroniza FilterFields com AQL e endurece o pipeline de filtro

* feat: improve toogle to new layout

* feat: suporta or no filtro avançado

* fix: permite espaço ao renomear tab

* refactor: code refactor

* refactor: code refactor

* feat: performance and stability overhaul of real-time events v2

Full refactor of the RTE v2 screen driven by adversarially-verified audits
(spec: specs/real-time-events-v2-refactor). Highlights:

- virtual table: fix "Page Unresponsive" loop (integer height dedupe +
  memoized window range), id->index map, O(1) observer lookups, exact
  spacer/expansion colspan (fixes fullscreen blank Document column)
- memory: bounded KeepAlive tab cache, height-cache pruning under eviction,
  observer cleanup on column toggle, native title tooltips (removes PrimeVue
  tooltip listener leak), c3 guard while deactivated, capped custom sessions
- data flow: list fetch no longer serialized behind chart aggregation,
  superseded window walks cancel, incremental evict/search-index/field-stats,
  loadMore replaces the array so prop-fed consumers (field stats) update
- UX: content-aware responsive column widths (wide fields absorb space),
  container-query toolbar, chunked non-blocking export with re-entry latch,
  activation reload guard (0 fetches when inputs unchanged), Top 10 values
- tests: 119 files / 1108 passing, incl. new regression locks for the render
  loop, colspan, loadMore identity and export concurrency

* refactor: structural hardening and responsive fixes for events v2

Second pass over the RTE v2 screen driven by an adversarially-verified
structural review (patterns, webkit compliance, simplicity):

- business logic out of components: chart-collapse persistence, share
  state, row-height observer and column-resize drag now live in
  composables; useSessionManager split into orchestrator + persistence
  + URL-sync modules
- dead code removed: drop-in shim chain (exportCSV/dataTableRef), dead
  props/bindings, legacy resetToken fallbacks, dead export surface,
  DiscoverDataTable renamed to VirtualEventTable
- duplication collapsed: makeListService factory for 7 copy-paste list
  services (byte-parity proven), shared rowKey/highlightMatch utils,
  single FieldRow in the sidebar, TabsView branches merged, single
  emits convention for add/exclude-filter across the tree
- responsiveness: fields sidebar becomes an overlay drawer on phones,
  AQL input no longer overflows the card (is-stack width pin +
  min-width chain), y-axis padding sized by tick content, heading
  stacks on mobile, container-query toolbar
- design system: --font-code replaces 6 local mono stacks, hardcoded
  rgba/palette classes replaced with theme tokens
- perf: per-render closures/ref factories memoized, stable badge keys,
  clone-free activate-guard snapshot, field stats gain resetToken
- tests follow the intentional summary-priority reorder (V1+V2) and
  account-guard is hermetic to local VITE_DEBUG_LOGIN; full repo suite
  green: 395 files / 2593 tests

* fix: stop empty-window walk storm and surface aggregate divergence

Brushing into a period where raw events expired (but aggregate tables
still hold totals) walked every 2h window to the range start — ~96
sequential empty requests that froze the list for minutes with a
misleading aggregate count on the badge.

- windowed walk: the FIRST empty window stops the walk; one wide probe
  over the remaining range answers sparse data in a single request, so
  a truly empty tail resolves in 2 requests total
- badge: an empty list is the authoritative truth — writes an exact
  "0 Documents found" and supersedes any in-flight aggregate count
- divergence indicator: amber icon inside the badge pill when the chart
  has aggregated data but no raw documents remain; DivergenceIndicator
  now owns its popover (teleported, fixed, surface-toned) instead of
  the PrimeVue tooltip that rendered unstyled for body-teleported tips
  and got trapped behind the summary bar by container-type stacking
- tests: empty-window spec locks the 2-request contract + zero badge +
  divergence flag; count-path specs updated to non-empty list mocks

* fix: keep AQL validation message under the suggestions dropdown

The errors tooltip (z-51) painted over the suggestions panel (z-50),
blocking option picking while a validation error was visible. Lower the
message below the dropdown: covered while the user picks a suggestion,
fully visible once the dropdown closes.

* perf: cut events scan cost via geometric windows, ts-cursor paging and rollup count

The list walk grows exhausted windows x4 (bounded-scan ladder) instead of
falling back to one full-range query; pages descend by ts cursor with
multiset dedupe instead of offset (offset kept only as the bounded
same-instant fallback); and the raw full-range count is skipped whenever the
Metrics rollup total covers the range+filter, with automatic raw re-fire when
the chart summary fails. Contract specs updated deliberately; new specs lock
the count-source matrix and the same-instant pagination fallback.

* feat: filter event attributes only via explicit icons

Clicking an attribute value no longer applies a filter anywhere (table
badges, document view, detail sidebar): values are plain selectable text
and filtering happens only through the hover icons, mirroring the copy
action. Unifies the filter pattern across surfaces (pi-filter and
pi-filter-slash icons, same tooltips and hover colors) and fixes the
badge action icons overflowing a width-clamped pill and overlapping the
attribute value. Retires the useClickToFilter composable and its
selection/drag guards, no longer needed.

* fix: keep action icons off the attribute value and gate stacktrace filtering

The compact document view value is now a real flex item (anonymous flex text
never ellipsizes and overflow clips at the padding edge, so the previous
reserve was ineffective) with the action icons as in-flow siblings — overlap
is structurally impossible, verified by geometry probe on the rendered
component. New filterable-fields domain contract removes add/exclude icons
for stacktrace (copy stays) across table badges, compact view and sidebar.

* feat: cap the events time filter at 7 days of raw retention

Sets filterDateRangeMaxDays to 7 on the RTE v2 filter bar (presets over
7 days disappear and the calendar gains a min date via the existing
maxDays plumbing), clamps the typed "Last N" quick-select to the cap
before the label is built so it never lies, and adds a final guard in
updatedTime() clamping any materialized tsRange span to the cap with the
range end preserved. The prop has no default, so Metrics and other
consumers keep their current behavior, locked by spec.

* refactor: replace scoped CSS with Tailwind utilities in advanced-filter-system-v2

Move component styling from <style> blocks to Tailwind utility classes so
sizing/typography values sit on the token scale, making the design-token
migration more precise and consistent with the rest of the codebase.

- content-editable.vue: drop the entire <style> block map layout/sizing to
  utilities (whitespace-pre, font-mono, min-h-9, max-h-24, overflow-*) and the
  :empty::before placeholder to empty:before:* variants. Keep the
  .contenteditable class as a styling hook for filter-bars :deep().
- filterRow/index.vue: drop <style scoped> move the control wrap-floor to
  min-w-44 and the operator overlay containment to inset-x-0. Replace the dead
  min-w-0 (always overridden by the scoped 11rem min-width) with the real
  min-w-44 floor. Keep .filter-row__control as a test query hook.
- filter-row-responsive.spec.js: assert the real min-w-44 wrap floor instead of
  the never-effective min-w-0.

Functional rationale comments (whitespace-pre for AQL trailing-space, overlay
containment) preserved as template comments. No behavior change.

* fix: bump fast-uri resolution to ^3.1.4 to resolve high-severity audit

* chore: remove RTE v2 planning specs (v2-fixes, v2-refactor) from PR

* fix: route advanced-filter HTTP through a Vue Query composable

Add useAdvancedFilterServices (queryClient.fetchQuery wrappers for the
workload-fields and timezone calls) and consume it from azion-query-language.vue
and advanced-filter-system-v2/index.vue, so components no longer import services
directly. Same call signatures; adds caching/dedup. Fixes the 2 real
architecture-lint violations.

* chore: remove inline comment from AQL content-editable

* chore: exempt bespoke RTE data-loading composables from require-vue-query

---------

Co-authored-by: Rafael N. Garbinatto <rafael.garbinatto@azion.com>
Co-authored-by: Guilherme Santana <44853071+gdsantana@users.noreply.github.com>
Co-authored-by: Guilherme Santana <guilherme30santana@gmail.com>
Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com>
fix: resolve CodeQL incomplete-sanitization alert and merge main into dev (unblock deploy #3662)
* ci: adding ci-ossf.yml

* fix: update postcss and brace-expansion dependencies

* fix: remove postcss dependency from resolutions in package.json

---------

Co-authored-by: Guilherme Santana <guilherme30santana@gmail.com>
…3670)

Switching back to the built-in Azion SSO sent the synthetic
`azion-default-sso` identifier instead of the active federated provider's
UUID, so the request returned 404 and the rollback never happened.

Extract `resolveRollbackTarget` as a pure resolver that picks the active,
non-synthetic provider from the list and use it in ListView, with unit
tests for the resolver and the view behavior.
…pagination (#3668)

* fix: harden real-time-events filters and WAF domain pagination

Address three findings from the PR #3662 security/robustness review:

- SEC (high): GraphQL structure injection via ?filters=. Filter clauses are
  rehydrated from a base64 URL hash without validation, and buildFilterGroup
  forms the query key as `valueField + operator`, spliced verbatim into the
  GraphQL query downstream. A crafted link could inject query structure. Guard
  the pure builder with an operator allow-list (VALID_OPERATORS) and an
  identifier-shaped field check (SAFE_FIELD_NAME), dropping any clause that is
  not UI-producible. Closes the breakout on all paths (count, aggregation,
  metrics-inline) regardless of prune timing.

- SEC (medium): toGraphQLScalar only escaped `"`, so a value ending in `\`
  escaped the closing quote and broke out of the inline metrics string literal.
  Escape via JSON.stringify so `\`, `"` and control chars are all handled.

- ROBUSTNESS (medium): WAF #fetchWafDomains used Promise.all for pages 2..N, so
  a single failing page wiped the whole domain listing. Switch to
  Promise.allSettled, keep the pages that resolved, and surface the skipped ones
  via console.error instead of failing all-or-nothing.

Tests: add injection guard specs (unit + end-to-end through buildFilterParts),
backslash/control-char escaping cases, and WAF partial-failure coverage.
No behavior change on legitimate inputs; full RTE + WAF suites green.

* feat: remove comments

* chore: bump postcss and brace-expansion to patched versions

yarn package-audit (yarn audit) started failing with exit code 8 after two
high-severity advisories published 2026-07-24:

- postcss (GHSA-r28c-9q8g-f849): path traversal via sourceMappingURL
  auto-loading. Vulnerable <=8.5.17, patched >=8.5.18. Lockfile had 8.5.16.
- brace-expansion (advisory 1124334): ReDoS/DoS via unbounded expansion.
  Vulnerable <=5.0.7, patched >=5.0.8. Lockfile had 2.1.2 (still in range).

Bump the `postcss` dependency and the `postcss`/`brace-expansion` resolutions
to the patched floors and regenerate yarn.lock (postcss 8.5.23,
brace-expansion 5.0.8, collapsed to a single version by the resolution).

brace-expansion 5.x ships as an ESM package with a CommonJS build exposed via
the `require` export condition, so minimatch/glob in the build tooling keep
working. Verified: yarn audit reports 0 vulnerabilities, `yarn build` succeeds,
and the unit suite passes.

* fix: fix teste

* feat: removed comments

@isaquebock isaquebock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revisando

@CLAassistant

CLAassistant commented Aug 4, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
5 out of 6 committers have signed the CLA.

✅ robsongajunior
✅ paulo-sobrinho-azion
✅ herbert-julio-azion
✅ gdsantana
✅ isaquebock
❌ mrmessa
You have signed the CLA already but the status is still pending? Let us recheck it.

@paulo-sobrinho-azion
paulo-sobrinho-azion requested a review from a team as a code owner August 10, 2026 12:13
The Package Audit workflow was failing with 5 high-severity findings, all
pointing at the same package: nanoid 3.3.16 is affected by advisory 1138813
(custom generators can loop indefinitely when size is zero), patched in
>=3.3.17. The 5 entries are a single vulnerability reached through 5 paths —
postcss, tailwindcss, vue, lottie-web-vue and @vitejs/plugin-vue-jsx — all
converging on `postcss > nanoid`.

postcss 8.5.25 is the only real consumer and already declares `nanoid: ^3.3.16`,
so the patched release was in range and only yarn.lock was holding it back. Add
an explicit floor to `resolutions`, following the convention already used in
that block for transitive security patches (esbuild, rollup, qs, js-yaml).

Stay on the 3.x line deliberately: nanoid latest is 6.0.1 and every major from 4
on is ESM-only, which would break postcss. 3.3.18 is the `legacy` dist-tag and
the newest patched release of the compatible line.

- yarn package-audit: 0 vulnerabilities (1225 packages audited)
- yarn install --frozen-lockfile: clean, so the CI install:lock step resolves
- yarn build: passes (nanoid is a build-time dependency through postcss)
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

SCC Complexity Analysis

  • Title: ENG-46628 refactor: invert rules engine order arrows so down moves rule up
  • Author: paulo-sobrinho-azion
Metric Source Branch (fix/ENG-46628-rules-engine-application-firewall-sort-arrows) Target Branch (dev) Difference
Complexity 11143 11140 3
Code 339382 339284 98

@aziontech aziontech deleted a comment from github-actions Bot Aug 11, 2026
guilherme-santana-azion

This comment was marked as resolved.

specs/real-time-events-responsividade/ and specs/real-time-events-v2-improvements/
were removed from dev in 4747c4c (feat: versioning #3647) and are blocked by
.gitignore, both via the `/specs` rule and by the two named entries that carry a
comment explaining exactly this: the drafts are kept locally by the Real-Time
Events team, edited on dev, and must not be versioned here to avoid a recurring
modify/delete conflict on every merge.

They came back anyway through 59a7942 (Feat: real time events improvements
#3660) and 574a6dd (fix: fix conflict), because .gitignore has no effect on
files that are already tracked — once those commits put them back in the index,
the ignore rules stopped applying.

Remove them with `git rm -r --cached`, so the local copies survive and .gitignore
takes over again. They are unrelated to ENG-46628 and would be reintroduced into
dev on merge, since dev no longer has them.
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

SCC Complexity Analysis

  • Title: ENG-46628 refactor: invert rules engine order arrows so down moves rule up
  • Author: paulo-sobrinho-azion
Metric Source Branch (fix/ENG-46628-rules-engine-application-firewall-sort-arrows) Target Branch (dev) Difference
Complexity 11152 11149 3
Code 339534 339436 98

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

SCC Complexity Analysis

  • Title: ENG-46628 refactor: invert rules engine order arrows so down moves rule up
  • Author: paulo-sobrinho-azion
Metric Source Branch (fix/ENG-46628-rules-engine-application-firewall-sort-arrows) Target Branch (dev) Difference
Complexity 11152 11149 3
Code 339652 339554 98

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

SCC Complexity Analysis

  • Title: ENG-46628 refactor: invert rules engine order arrows so down moves rule up
  • Author: paulo-sobrinho-azion
Metric Source Branch (fix/ENG-46628-rules-engine-application-firewall-sort-arrows) Target Branch (dev) Difference
Complexity 11160 11157 3
Code 339661 339563 98

@isaque-bock-azion

Copy link
Copy Markdown
Contributor

Ao clicar no disabled do button, ele deveria estar de fato disabled (com o ícone de disabled no cursor talvez, confirma com o @gablisb0a). Mas nao deveria abrir a edicao da rule.
https://github.com/user-attachments/assets/9786135a-5737-4306-99b2-21a932223483

@isaque-bock-azion isaque-bock-azion left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug visual.

Clicking a disabled increment/decrement arrow in the Rules Engine position
column was opening the rule drawer. Chrome does not deliver the click to a
disabled <button>; it retargets the event to the parent element, so
PrimeVues DomHandler.isClickable() check fails and the DataTable emits
row-click.

Stop click propagation on the reorder/position cell wrapper so no click in
that column reaches the row handler. Drag reordering is unaffected since it
relies on mousedown/dragstart.

Applies to both Edge Application and Edge Firewall Rules Engine lists.
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

SCC Complexity Analysis

  • Title: ENG-46628 refactor: invert rules engine order arrows so down moves rule up
  • Author: paulo-sobrinho-azion
Metric Source Branch (fix/ENG-46628-rules-engine-application-firewall-sort-arrows) Target Branch (dev) Difference
Complexity 11160 11157 3
Code 339667 339563 104

The disabled arrows in the Rules Engine position column kept the rows
pointer cursor, giving no hint the control is unavailable.

PrimeVue sets `cursor: default !important; pointer-events: none` on
`.p-disabled` inside the `primevue` cascade layer. Tailwind utilities are
unlayered and important declarations invert layer order, so a class on the
element always loses — the override has to live in the same layer.

Applies to both Edge Application and Edge Firewall Rules Engine lists.
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

SCC Complexity Analysis

  • Title: ENG-46628 refactor: invert rules engine order arrows so down moves rule up
  • Author: paulo-sobrinho-azion
Metric Source Branch (fix/ENG-46628-rules-engine-application-firewall-sort-arrows) Target Branch (dev) Difference
Complexity 11160 11157 3
Code 339677 339563 114

@paulo-sobrinho-azion
paulo-sobrinho-azion merged commit 27a67f3 into dev Aug 13, 2026
30 checks passed
@paulo-sobrinho-azion
paulo-sobrinho-azion deleted the fix/ENG-46628-rules-engine-application-firewall-sort-arrows branch August 13, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code-refactor A tag for Pull Requests focusing on code refactoring, improving code structure, readability, and mai

Development

Successfully merging this pull request may close these issues.

9 participants