Skip to content

2_1_2

Choose a tag to compare

@fbourasse fbourasse released this 25 Jun 15:33
· 4 commits to main since this release
f4b3ffd

JCR Stats 2.1.2

Release date: 2026-06-25

A usability and robustness release for whole-site analysis: computations no
longer abort on un-representable nodes, long runs can be cancelled, branches can
be excluded, and every run is saved so it can be reopened and compared later.
Also a broad hardening pass across security, accessibility (WCAG 2.2 AAA), and
reliability. Drop-in upgrade from 2.1.x.

Highlights

  • 🌳 Whole-site computations no longer crash on nodes with names that aren't
    valid JCR paths (e.g. external mounts).
  • ⏹️ Cancel a running computation for real — it stops on the server.
  • 🚫 Exclude paths from a computation, persisted in an OSGi config file.
  • 🗂️ Saved executions — every run is auto-saved as JSON; reopen, compare, or
    delete past runs.
  • WCAG 2.2 Level AAA accessibility pass on the admin UI.

Added

Saved executions (server-side JSON history)

Every completed computation is automatically saved as a JSON snapshot in the JCR
(/sites/systemsite/files/jcr-stats/snapshots/), so a past run's flamegraph can
be reopened later — by anyone with the jcrStatsAdmin permission, and across
restarts. A Saved executions panel lists the history (most recent first) with
its date and size, and per-row View (reload into the viewer), Compare
(diff against the current result), and Delete actions. Snapshots are capped
at the 50 most recent (oldest pruned on write). New GraphQL:
jcrStats.snapshots, jcrStats.saveSnapshot, jcrStats.deleteSnapshot.

Path exclusions

Exclude a path — and its whole subtree — from the computation. Click a frame in
the flamegraph and choose Exclude this path; excluded paths are listed with a
Remove control. Exclusions are persisted as an OSGi configuration file
(${karaf.etc}/org.jahia.community.jcrstats.cfg, property
jcrStats.excludedPaths) via a ManagedService, so they survive restarts and
can be hand-edited. New GraphQL: jcrStats.exclusions,
jcrStats.addExclusion(path), jcrStats.removeExclusion(path). Exclusions take
effect on the next computation.

Server-side cancellation

A new jcrStats.cancel mutation and a cancelled flag on jcrStats.status. The
traversal polls a cooperative cancellation flag at the start of every node, so a
running job stops between nodes (never mid-JCR-operation). The Cancel button
now actually stops the server-side job.

Changed

  • "Load data" joins the history — loading a JSON file now also stores it as a
    saved execution (so loaded data is persisted alongside computed runs), and the
    standalone Compare with… button was removed; comparison is driven entirely
    from the Saved executions list.
  • Saved-executions UX — rows show date and size, with per-row Delete and a
    capped, scrollable list; Compare is gated until a current result is loaded.

Fixed

  • Whole-site traversal no longer aborts on un-listable branches. Descending
    into an external data-source mount whose child name isn't a valid JCR path
    (e.g. a cloud-dumps node named with an ISO-8601 timestamp, where : is the
    namespace-prefix separator) previously raised
    RepositoryException: Invalid path … ':' not valid name character and aborted
    the whole computation. Direct listing now falls back to an escaped
    ISCHILDNODE query, recovering the valid children; only the single
    un-representable node is omitted. The MAX_VISITED_NODES safety cap is
    unchanged.
  • The "Cancel" button now stops the computation instead of only stopping the
    client-side polling.
  • Snapshot list reflects deletes immediately — listing now iterates the
    folder's children directly instead of an index-backed query that lagged behind
    deletions.
  • Review hardening: snapshot/flamegraph writes use a dedicated system session;
    cancellation is classified by exception type; the flamegraph write aborts on a
    failed header/footer; jsonEscape handles lone surrogates; jcr:data reads
    guard multi-valued properties; assorted frontend race fixes (no stale-run result
    applied to a new run; load-as-snapshot failures surfaced).

Accessibility (WCAG 2.2 Level AAA)

Focus is no longer relocated on async completion (only on user-initiated view
changes); reduced-motion fully stops the progress-bar animation; info/success use
role="status" and errors role="alert"; list/icon buttons carry descriptive
accessible names; the flamegraph uses role="img" with the keyboard-accessible
tree-table as its alternative; the progressbar exposes aria-valuemin/max;
delete uses an accessible inline two-step confirm; borders/links meet AAA
contrast; headings reflow at 400% zoom.

Security

  • saveSnapshot validates the uploaded envelope structurally (parsed JSON
    with format = jcr-stats-flamegraph and a tree), not by substring match.
  • deleteSnapshot only deletes within the snapshots folder.
  • Excluded-path validation hardened (absolute, length-capped, segment-scoped
    ./.. rejection, no ReDoS-prone regex).
  • All GraphQL operations remain gated by the jcrStatsAdmin permission; JCR
    traversal uses a privileged system session by design.

Quality

  • Backend: 88 unit tests. Frontend: 108 Jest tests. End-to-end: 33 Cypress tests
    (admin UI, API, permissions) — all green. SonarQube quality gate passing;
    ESLint clean.

Upgrade notes

  • Drop-in from 2.1.x — no API or data migration required. The admin route is
    jcrStats (/jahia/administration/jcrStats).
  • Assign the jcr-stats-administrator role (or the jcrStatsAdmin permission)
    to users who should access the tool.
  • Saved snapshots and generated flamegraph reports accumulate in the JCR under
    /sites/systemsite/files/jcr-stats/ (snapshots are capped at 50; HTML reports
    are not — prune if needed).

Known limitations

  • The computation is a single, server-wide job — concurrent admins share one run.
  • The subtree is held in memory, bounded by the MAX_VISITED_NODES = 5,000,000
    safety cap.
  • The read-only size/nodeCount/tree GraphQL queries run synchronously on the
    request thread (use the async compute/status/result flow for large paths).

Compatibility

  • Requires Jahia 8.2.1.0 or later.