Commit Graph
16188 Commits
Author SHA1 Message Date
Thomas Vincent 15a4999ee6 test: normalize relocated PHPUnit paths for Pest discovery
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 15:55:17 -07:00
Thomas Vincent 03f97012a3 test: move PHPUnit configuration into the tests directory
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 15:43:03 -07:00
TheWitness 356f4ae813 fix(graphs): tree content reveal, filter dialog columns, single-column centering (#8365)
* fix(graphs): reveal graph content area after tree branch loads

The jstree select_node handler hides .cactiGraphContentArea (#navigation_right) before loading a branch's graphs via AJAX to avoid flashing the previous branch, but the only re-show was coupled to a window resize event that does not fire after the AJAX load. On themes that hide .cactiGraphContentArea by default (e.g. Deepness) the content area stayed display:none and the graphs/filters were invisible. Re-show it on loadUrl completion.

* fix(filter): keep the Edit Filter dialog columns from collapsing

The modern filter Edit dialog is created with jQuery UI width:'auto'. Its body is a table-based label/field grid, which jQuery UI measures at min-content, collapsing the dialog content to a sliver and pushing the fields off to the right. Floor the content min-width so the columns lay out. Validated in Deepness and Dark.

* fix(graphs): centre single-column graphs in the graph view

graphWrapperOuter > div:first-child is width:fit-content inside a (full-width for one column) flex wrapper, so the graph rendered flush-left. Add auto horizontal margins so it centres; the absolutely-positioned drilldown toggle continues to track the graph.

* fix(graphs): don't re-show content area on aborted branch load

A superseding tree branch click aborts the in-flight loadUrl; its .always() must not re-show the content area the new selection just hid, or stale graphs flash while the new branch loads. Skip completions whose textStatus is 'abort'.
2026-10-14 17:16:42 -04:00
TheWitness 2fdc8747af Cross-filter Device and Graph Template on Preview and List views (#8363)
* Cross-filter Device and Graph Template on Preview and List views

Forward the selected Graph Template(s) to the ajax_hosts Device callback and filter the device list accordingly, so choosing a Graph Template narrows the Device list. Device-to-template narrowing already exists on these views.

* Use line comment style to satisfy php-cs-fixer

* fix(graph_view): validate raw graph_template_id against filter allowlist in html_make_device_where

The ajax_hosts endpoint calls html_make_device_where() before the graph filter is sanitized, so gnrv('graph_template_id') is raw request data. An array value such as graph_template_id[]=cg_1 reached html_transform_graph_template_ids()'s str_contains() and raised a TypeError (HTTP 500). Reject non-string input and validate against the same regexp allowlist the filter uses before transforming.

* test(graph_view): add request-coverage probe for the device/template cross-filter

The pr-php-coverage gate requires >=80 percent of changed executable PHP lines to be exercised. The new html_make_device_where() graph_template_id branch and the request_vars changes in create_graphs_preview_filter()/create_listview_filter() are only reached when a graph_template_id filter is present, which the page-level e2e suites do not drive. Add an isolated source-slice probe that runs those production functions with stubbed I/O boundaries and wire it into run_request_coverage.sh so the changed lines are covered.
2026-10-14 13:21:22 -04:00
Thomas Vincent 4d11070ced feat: expose RRDtool 1.11 graph axis controls (#8356)
* feat: expose RRDtool 1.11 graph axis controls

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix: constrain axis template inheritance checkboxes

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(rrd): exercise native aggregate validation and enforce coverage

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: share changed-code coverage contracts and enforce shell policy

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(ci): run request coverage with portable path matching

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: retain bootstrap coverage and validate request dispatch

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: synchronize native coverage fixture dispatch

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: measure coverage at the exact PR revision

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 12:10:28 -04:00
Thomas VincentandPetr Macek 930b085703 feat(auth): log administrative account actions after confirmed writes (#8360)
* log user action (create, delete, locked, ..)

* change log

* update changelog

* style(auth): apply coding standards to user action logging

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* Audit password changes only after successful account saves

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(auth): sanitize audit fields and confirm account removals

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: cover native account audit state transitions

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: synchronize native coverage fixture dispatch

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(auth): audit only confirmed account persistence

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: measure coverage at the exact PR revision

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Petr Macek <petr.macek@kostax.cz>
2026-10-14 09:54:14 -04:00
dependabot[bot] a634323d1d ci(deps): bump the github-actions group with 3 updates (#8358)
Bumps the github-actions group with 3 updates: [actions/setup-node](https://github.com/actions/setup-node), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [trufflesecurity/trufflehog](https://github.com/trufflesecurity/trufflehog).


Updates `actions/setup-node` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1)

Updates `actions/upload-artifact` from 7.0.1 to 7.0.2
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/043fb46d1a93c77aae656e7c1c64a875d1fc6a0a...cf430e030ddbb5b0abf93d22962f4752f3646cd9)

Updates `trufflesecurity/trufflehog` from 3.98.0 to 3.99.0
- [Release notes](https://github.com/trufflesecurity/trufflehog/releases)
- [Commits](https://github.com/trufflesecurity/trufflehog/compare/0186870afd2c4a90def791d80260923ba583d076...b2b0a92070f206ab7b5a1105d82a7f2f48d92341)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: trufflesecurity/trufflehog
  dependency-version: 3.99.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 01:11:43 -07:00
Thomas Vincent 8221a941a7 test(performance): [develop] add disposable browser and SQL/RRD profiling (#8336)
* perf: add disposable browser and SQL/RRD profiling

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs: record profiling harness in the changelog

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 00:01:32 -07:00
Thomas Vincent 2b6e96b23a style(php): [develop] wrap CLI and poller calls without changing execution (#8303)
* style(php): wrap CLI and poller calls without changing execution

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(ci): review security inventories after poller wrapping

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(boost): compare handoff source contracts by PHP tokens

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* style(php): wrap poller constant strings without changing values

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* style(php): wrap poller concatenations with token-preserving source contracts

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(cli): assert CDEF repair queries after constant folding

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: verify PHP formatting preserves parsed behavior

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 00:01:26 -07:00
Thomas Vincent f3ff777992 ci: install locked shared plugin test dependencies (#8345)
* ci: install locked shared plugin test dependencies

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs: explain pinned tooling checkout for plugin CI

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 00:01:08 -07:00
TheWitnessandTheWitness 8acc5ec916 feature: theme-aware graph drilldown action menu (per-theme CSS palette) (#8355)
Label the open graph drilldown strip (layout.js labelGraphDrilldownIcons), shorten the action titles, and restyle the strip as a table menu. Each theme's main.css declares the --cacti-dd-* custom properties (foreground, hamburger/panel backgrounds, hairline border, hover accent) that include/css/graph_drilldown.css consumes via var() with a dark fallback, so each theme gets an appropriate light or dark look with its own accent and the hamburger reads correctly on light themes. Themes without a block (e.g. midwinter) use the dark fallback. Regenerates the affected locales/po/cacti.pot entries for the shortened titles.

Co-authored-by: TheWitness <1439914+TheWitness@users.noreply.github.com>
2026-10-13 12:33:14 -04:00
Thomas Vincent c749790d84 fix(security): [develop] require CSRF-protected POST for link and plugin reordering (#8278)
* security: require CSRF-protected POST for link and plugin reordering (#7454)

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(csrf): share POST and token guards for reorder actions

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-13 07:52:20 -04:00
Thomas Vincent ce6ab6e0b3 fix(auth): [develop] preserve SAML POST callback sessions (#8333)
* fix(auth): preserve SAML POST callback sessions

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(auth): filter SAML inputs before bootstrap

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:42:00 -07:00
Thomas Vincent a12fe59627 fix(poller): [develop] retain output until bounded storage batches succeed (#8332)
* fix(poller): retain output until bounded storage batches succeed

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(poller): refresh SQL audit after exact-key acknowledgements

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(boost): preserve handoff contracts with explicit acknowledgements

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): retain failed timestamp ordering across batches

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): acknowledge complete timestamp groups together

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): retry failed source metadata reads on develop

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): preload standalone script exclusions once per process

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): bound metadata failures and validate acknowledgement queries

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:41:53 -07:00
Thomas Vincent 5f72f1a03c fix(security): [develop] require protected POSTs for administrative mutation endpoints (#8331)
* fix(csrf): require POST for administrative mutation endpoints

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(csrf): support token-checking mutation helper

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:41:29 -07:00
Thomas Vincent 49c95bef63 fix(deps): track legacy browser assets and remove patch-package (#8330)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:41:22 -07:00
Thomas Vincent ac50e0e0d0 fix(csrf): restrict XHR tokens to same-origin requests (#8329)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:41:16 -07:00
Thomas Vincent 9a3a7dfce0 fix(graphs): [develop] correct opacity, redraw and realtime retries (#8328)
* fix(theme): enable graph opacity without selectmenu

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): describe theme fix

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(graph): restore redraw URLs and retry realtime failures

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:41:10 -07:00
Thomas Vincent 6e5078c929 fix(theme): [develop] restore Midwinter navigation, search and filter controls (#8327)
* fix(theme): restore Midwinter navigation and kiosk controls

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): describe theme fix

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(navigation): preserve filters and restore search and keyboard controls

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:41:04 -07:00
Thomas Vincent f28071eb67 fix(theme): [develop] restore Midwinter login controls, form state and notifications (#8326)
* fix(theme): preserve Midwinter authentication controls

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): describe theme fix

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(ui): preserve form state and notification lifecycles

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix: replace the blinking timer during skin setup

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 15:40:56 -07:00
TheWitnessandThomas Vincent f39e74c65c Graph drilldown: keep hamburger fixed, icons reachable, hide on graph leave (#8315)
* Graph drilldown: keep hamburger fixed, icons reachable, hide on graph leave

The action-icon strip now slides down below the hamburger (flex column) instead
of the hamburger dropping to the bottom of the icons. Closing is driven by
leaving the whole graph rather than the small icon strip, so the mouse can move
from the hamburger onto the icons without the strip closing. Leaving the graph
also blurs the hamburger so it no longer lingers after interacting with it.

* changelog: graph drilldown interaction fixes (#8315)

* Graph drilldown: tolerate tooltip-induced mouseleave, drop hamburger title

A native tooltip appearing over a drilldown icon fires a spurious mouseleave on
the graph (relatedTarget null), which closed the strip. Defer the close and
re-check the graph is genuinely not hovered first, so the icon tooltips no longer
destabilize it. Also drop the hamburger's redundant title (its aria-label stays).

* Graph drilldown: widen the close grace period to 500ms

* Graph drilldown: tie hamburger visibility to the graph image

Reveal the hamburger while the pointer is over the graph image (or the toggle
overlaid on it) rather than anywhere in the graph cell, so moving off the image
hides it after the grace period.  Entering a different graph now immediately
hides and closes any other graph's open strip.

* Graph drilldown: lift the open graph so its strip clears thumbnails below

With thumbnails a short graph's open icon strip overflows onto the graph below;
sibling graphs paint in DOM order, so that graph rendered on top of the strip,
making the icons unclickable and stealing the hover (which closed the strip).
Raise the open graph (.graphDrillActive, position:relative; z-index) so its
overflowing strip stays on top and the graph beneath is not hovered.

* Graph drilldown: reveal via :focus-visible and stop blurring to preserve keyboard focus

* fix(ui): preserve graph action focus during pointer navigation

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(ui): cover graph drilldown interactions and gate PR coverage

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: measure committed PR changes on a policy-compliant runner

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 06:29:12 -04:00
TheWitnessandThomas Vincent 34fc3f8642 Stop flagging a not-yet-created RRA subdirectory as a data_source_path escape (#8313)
* Stop data_source_path_within_rra() flagging a not-yet-created intermediate directory as an RRA escape

get_data_source_path() routed a legitimate <path_rra>/<host_id>/<local_data_id>.rrd through the generated-path fallback and logged a bogus 'SECURITY: ... escapes the RRA directory' message whenever the host_id subdirectory did not exist yet (first poll, or host_id 0). data_source_path_within_rra() only tolerated a missing final RRD file: for a missing file it resolved realpath(dirname(path)), which returns false when that parent directory has not been created, so the lexically-contained path was wrongly rejected.

Walk to the deepest ancestor that actually exists and confirm it resolves inside the RRA root instead. Lexical containment (no .., '.', or empty segments) and per-segment symlink rejection are unchanged, so traversal, lookalike-prefix, absolute, and symlink-pivot paths are still rejected. Adds a regression test for a not-yet-created intermediate directory.

* Drop explanatory comments from the RRA containment fix

* Add CHANGELOG fragment for the RRA containment fix

* Reject a dangling-symlink segment independently of file_exists()

* test(paths): cover RRA filesystem boundaries and gate PR coverage

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: measure committed PR changes on a policy-compliant runner

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 06:28:45 -04:00
TheWitnessandThomas Vincent 49e14c9785 Filter dialog: theme-aware close glyph, titlebar height matches table header, Deepness input theming (#8312)
* Filter dialog: theme-aware close glyph, titlebar height matches tableHeader, Deepness input theming

- Replace the non-theme-aware inverted sprite close icon with a theme-coloured x glyph (color: inherit) across all 10 themes that style cactiFilterDialog.
- Set the titlebar height/line-height to match each theme's cactiTableTitleRow height instead of 10px padding that made the dialog header taller than table headers.
- Deepness: re-apply theme field colours to dialog inputs/selects/textareas with higher specificity so jQuery UI .ui-widget-content .ui-state-default no longer overrides them.

* changelog: filter dialog theme consistency (#8312)

* Filter dialog: theme select focus border; raspberry titlebar 28px to match table header box

* test(ui): cover filter dialogs across all changed themes

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: measure committed PR changes on a policy-compliant runner

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-12 06:28:25 -04:00
dependabot[bot] 7d8cdfdef4 ci(deps): bump trufflesecurity/trufflehog (#8323)
Bumps the github-actions group with 1 update: [trufflesecurity/trufflehog](https://github.com/trufflesecurity/trufflehog).


Updates `trufflesecurity/trufflehog` from 3.97.9 to 3.98.0
- [Release notes](https://github.com/trufflesecurity/trufflehog/releases)
- [Commits](https://github.com/trufflesecurity/trufflehog/compare/4dd8831c5f12599465d4d45c3c447b4018a34c85...0186870afd2c4a90def791d80260923ba583d076)

---
updated-dependencies:
- dependency-name: trufflesecurity/trufflehog
  dependency-version: 3.98.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-11 22:28:22 -04:00
dependabot[bot] 9078730c8e ci(deps): bump actions/upload-artifact from 4.6.2 to 7.0.1 (#8324)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.6.2...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-11 22:27:18 -04:00
dependabot[bot] ba92ae89a0 deps(deps-dev): bump phpstan/phpstan (#8322)
Bumps the composer group with 1 update: [phpstan/phpstan](https://github.com/phpstan/phpstan-phar-composer-source).


Updates `phpstan/phpstan` from 2.2.16 to 2.2.17
- [Commits](https://github.com/phpstan/phpstan-phar-composer-source/commits)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-version: 2.2.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: composer
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-11 22:23:58 -04:00
Thomas Vincent 3d3032a726 fix(deps): block ESM-only screenfull updates on 1.2.x (#8321)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 22:21:57 -04:00
Thomas Vincent 76579e6292 Fix dsstats partition dispatch and profile retention fallbacks (#8304)
* fix(core): preserve dsstats type and render retention fallbacks

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(auth): use certificate expiry truth in rendering assertions

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 21:32:00 -04:00
Thomas Vincent af9d1591a3 fix(aggregate): honor skipped item sequences in totals and percentiles (#8300)
* fix(aggregate): honor skipped item sequences in totals and percentiles

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: tighten SQL baseline for aggregate prepared queries

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): defer release entries to final backlog PR

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 21:27:25 -04:00
Thomas VincentandTheWitness 97e67c6777 security: harden browser rendering and review CodeQL boundaries (#8298)
* security: harden browser history and dependency option merging

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs: record CodeQL triage decisions and follow-up scope

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: wait for history reload before inspecting browser storage

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* security: isolate HTMX history from the legacy navigation handler

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: build CodeQL assets through controlled dependency installs

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* security: render form validation messages as plain text

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: verify drag rows and color input security boundaries

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: verify tree navigation rename and datetime input boundaries

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* security: harden menu rendering and complete CodeQL caller review

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* security: centralize menu rendering and stabilize certificate CI

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: align certificate expectation with parallel web PR

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-10-11 21:26:38 -04:00
Thomas VincentandTheWitness 3bb7002d2d fix(plugins): report CLI install failures and apply requested realm grants (#8296)
* fix(plugins): grant existing realms for CLI allperms

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci(plugins): pin database images and enforce strict shell mode

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(plugins): stop automatic grants after CLI setup failures

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): defer release entries to final backlog PR

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-10-11 21:23:27 -04:00
Thomas Vincent 08d0f94f24 Fix develop client behavior, popup isolation and PHP method visibility (#8292)
* fix(core): correct client state and declare public method contracts

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(security): isolate Midwinter external homepage popup

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(client): isolate menu state and simplify validated JavaScript guards

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(auth): use certificate expiry truth in rendering assertions

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* refactor(js): remove unused local storage while retaining initializer calls

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(js): encode inline translated values through the shared JSON boundary

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* style(js): wrap encoded translation literals without changing messages

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(client): remove unused checkbox reads from graph resizing

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* refactor(client): declare repeated function locals once

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(ui): run column width regression in browser CI

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 21:15:39 -04:00
Thomas VincentandTheWitness 391c6ead18 Add scoped poller regressions and weekly branch backstop (develop) (#8286)
* test(poller): gate regressions by changes and run weekly scale checks

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(poller): satisfy workflow policy and bound cold-cache queries

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): retry failed template metadata reads

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): defer release entries to final backlog PR

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-10-11 21:15:06 -04:00
Thomas VincentandTheWitness 72ddd59cdc fix(automation): render new Graph and Tree rule items without TypeErrors (#8283)
* fix(automation): normalize empty IDs in rule item editors

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): defer release entries to final backlog PR

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-10-11 21:14:26 -04:00
Thomas Vincent 71f2d55b6a refactor(html): share sortable header state resolution (#8307)
* refactor(html): share sortable column state and sort history

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* refactor(html): normalize sortable metadata before resolving state

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 20:32:37 -04:00
Thomas Vincent 9899fdf221 fix(installer): allow forced replays after LDAP migration (#8317)
* fix(installer): preserve forced replay on already upgraded schemas

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): record forced upgrade replay repair

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 18:57:46 -04:00
TheWitness d7ec67c4cf Persist table column widths across request actions (#8309)
* Persist table column widths across request actions

Column widths are stored in localStorage keyed by the table id, but
html_start_box() derives that id from the request action/report/tab, so a
filter refresh (action change/go) reloads the same table under a different
id and the saved widths are not restored. Emit a stable, action-independent
data-colsizing key on each cactiTable and use it in saveTableWidths(), while
keeping the DOM id unchanged.

* changelog: 8309 table column width persistence

* Column width persist: keep per-view key, normalize only filter-refresh actions

The previous key dropped the action/report/tab entirely, so distinct table schemas at the same page+ordinal (e.g. support.php processes vs background tabs, utilities.php view_snmp_cache vs view_poller_cache) collapsed into one localStorage entry and applied widths from the wrong schema.

Retain the stable logical-view discriminator (tab/report, or a non-transient action) in the data-colsizing key and normalize only the transient filter-refresh actions (go/change/clear/reset), so widths still survive a filter change but never cross unrelated schemas.

* Use short array syntax for the colsizing normalization list (php-cs-fixer)
2026-10-11 17:26:48 -04:00
TheWitness e25a67c31f Common graph drilldown hamburger toggle across all themes (#8308)
* Graph drilldown: common hamburger toggle across all themes

The graph action icons were revealed by hovering to the right of the graph, implemented per-theme (dark/midwinter/sunrise main.js) and always-on elsewhere.

Hide the icons by default behind a small fa-bars hamburger overlaid on the graph's top-right. Clicking it opens the icon strip, which stays until a second click, leaving the strip, or an outside click. The behaviour is now centralized in include/layout.js (initGraphDrilldown) and include/css/graph_drilldown.css, and the per-theme hover JS is removed.

* changelog: 8308 feature fragment

* Graph drilldown: address review (a11y, positioning, spikekill, POT)

- Anchor the toggle to the shrink-wrapped graph holder (width:fit-content) so the hamburger sits on the graph's top-right, not the full-width column edge.

- Keep the hamburger focusable while visually hidden (opacity instead of display:none); reveal on hover, keyboard focus, open, and hover-less devices.

- Expose aria-expanded on the toggle and update it in every open/close path; add aria-haspopup/aria-label.

- Close any open SpikeKill submenu (spikeKillClose) when the strip closes or switches, matching the removed per-theme handlers.

- Remove the now-duplicate Midwinter top-right ellipsis pseudo-element.

- Add the new 'Graph Actions' msgid to locales/po/cacti.pot.
2026-10-11 17:20:06 -04:00
Thomas Vincent 06c32ab13f fix(installer): preserve upgrade state and propagate failures (#8266)
* fix(installer): preserve upgrade state and propagate failures

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs(changelog): record installer recovery fixes for #8266

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(security): refresh installer sink inventories

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(installer): retain merge precedence for browser parameters

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(installer): defer debug settings until the process lock is held

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(installer): enforce table conversion failures and postconditions

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(installer): refresh SQL audit baseline after clause refactor

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 17:08:12 -04:00
Thomas Vincent 8ebc7e8a1a test(e2e): resolve browser smoke assets from the configured base URL (#8260)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-11 17:06:13 -04:00
TheWitness 533f3b5a04 Harmonize DateTimePicker styling with each theme palette (#8287)
* Harmonize DateTimePicker styling with each theme palette

The jQuery UI datepicker and timepicker addon rendered with the stock ThemeRoller texture-image backgrounds and a generic gray/green look that did not match any theme (most visible in the deepness dark theme). Add per-theme, picker-scoped overrides to every theme's jquery.timepicker.css so the popup surface, header, weekday labels, day cells, selected/hover/today states, Now/Done buttons, and the time sliders use each theme's own accent and content colors. Rules are scoped to .ui-datepicker so other jQuery UI widgets are unaffected.

* Address DateTimePicker a11y review (develop)

- Reset the nav-icon filter on prev/next hover (cacti, paw, raspberry) so the dark jQuery UI sprite stays visible on the pale hover tint.

- Give carrot and hollyberry a dark header title + dark nav icons so the month/year text clears AA on the light-ish accent header.

- Carrot: move to the theme's darker orange (#d2691e) for the today outline and sliders, and use a dark foreground on the orange selected-day/button fills.

- cacti and hollyberry: dark foreground on the accent selected-day/button fills to clear 4.5:1.

- paper-plane and sunrise: invert the icon sprite to white so the arrows are visible on their dark headers.

- dark and modern: add an explicit focus outline on the time-slider handles (both themes suppress the browser outline globally).

- midwinter: rebuild the override on the theme palette variables so the picker follows dark/light mode, with the theme blue as a fixed AA accent.
2026-10-11 13:32:41 -04:00
Thomas Vincent bcb4aaf4ae fix(auth): render password reset links outside login error text (#8289)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-10 20:24:49 -04:00
Thomas Vincent 54251fd2fc docs: establish polling performance rules for coding agents (#8291)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-10 20:23:18 -04:00
TheWitness bfa3efb7a9 Add a jQuery rebind() helper and roll it out across the core UI (#8279)
* Add a jQuery rebind() helper and roll it out across the core UI

Add $.fn.rebind(events[, selector], handler...) to include/layout.js as a
shorthand for the common off(events).on(events, ...) re-attach idiom, then
convert the matching chained calls across the core JavaScript and inline
PHP handlers to use it. Only pairs whose off() and on() events (and
delegated selector) match are converted; off() with no arguments is left
as-is since it intentionally clears every handler.

* changelog: add 8279.feature fragment

* tests: update layout.js JS tests for the rebind() helper

* tests: assert the cactiPostAction handler via rebind()

* rebind: preserve the delegated selector for the two-argument event-map overload; add helper tests
2026-10-10 17:01:49 -04:00
Thomas Vincent d49126df58 ci: use public registry caches for installer and security jobs (#8268)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-09 17:57:24 -04:00
TheWitnessandTheWitness ce707ccd79 Fix false-positive RRA-escape warning when path_rra has a trailing slash (#8258)
* Fix false-positive RRA-escape warning when path_rra has a trailing slash

A path_rra setting saved with a trailing slash makes CACTI_PATH_RRA end in
'/', so the '<path_rra>/' -> CACTI_PATH_RRA . '/' expansion that every data
source consumer performs yields a doubled slash ('<rra>//0/1457.rrd').

data_source_path_within_rra() split the expanded path on '/' and rejected any
empty segment, so the doubled slash was read as a traversal and a perfectly
legitimate RRD file was reported as escaping the RRA directory:

  SECURITY: Data source 1457 has a data_source_path that escapes the RRA
  directory (<path_rra>/0/1457.rrd).  Using the generated path instead.

get_data_source_path() then returned the generated fallback path, which the
poller had never created, producing the follow-on 'RRD file does not exist'
graph warnings (note the tell-tale 'rra//0' doubled slash in those lines).

Collapse repeated slashes and strip a trailing slash from the RRA root before
the containment comparison. A '//' is an empty segment, not a parent
reference, so normalising it keeps the file contained while '..' traversal,
absolute paths elsewhere, lookalike prefixes and symlink pivots are still
rejected (asserted by the expanded regression test).

* Keep data_source_path_within_rra() normalisation strictly string-typed

preg_replace() is typed array<string>|string|null, so feeding its result to
rtrim()/strlen() tripped PHPStan (level 6/8). Cast CACTI_PATH_RRA and both
preg_replace() results to string; runtime behaviour is unchanged.

* Cover the trailing-slash CACTI_PATH_RRA half of the fix in an isolated process

The existing cases insert '//' into the target only; data_source_path_test_base()
uses realpath(), which strips the trailing slash, so they never exercise the
rtrim() on \. CACTI_PATH_RRA is immutable, so define it with a trailing
slash in a fresh PHP process and assert a clean/doubled-slash file stays
contained while a traversal is still rejected.

---------

Co-authored-by: TheWitness <1439914+TheWitness@users.noreply.github.com>
2026-10-09 17:05:11 -04:00
Daniel Nylander 94bc31c4b1 Translated using Weblate (Swedish)
Currently translated at 100.0% (5204 of 5204 strings)

Translation: Cacti/core
Translate-URL: https://translate.cacti.net/projects/cacti/core/sv/
2026-10-09 12:18:16 -05:00
dependabot[bot] 0821439917 deps(deps-dev): bump @playwright/test in /tests/e2e in the npm-e2e group (#8251)
Bumps the npm-e2e group in /tests/e2e with 1 update: [@playwright/test](https://github.com/microsoft/playwright).


Updates `@playwright/test` from 1.62.1 to 1.63.0
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.62.1...v1.63.0)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.63.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-e2e
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-09 09:29:09 -04:00
dependabot[bot] f713597624 deps(deps): bump firebase/php-jwt (#8250)
Bumps the composer group with 1 update: [firebase/php-jwt](https://github.com/googleapis/php-jwt).


Updates `firebase/php-jwt` from 7.2.0 to 7.2.1
- [Release notes](https://github.com/googleapis/php-jwt/releases)
- [Changelog](https://github.com/googleapis/php-jwt/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/php-jwt/compare/v7.2.0...v7.2.1)

---
updated-dependencies:
- dependency-name: firebase/php-jwt
  dependency-version: 7.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: composer
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-09 09:27:58 -04:00
dependabot[bot] 9dc98656a2 deps(deps): bump billboard.js from 4.1.0 to 4.1.1 in the npm group (#8252)
Bumps the npm group with 1 update: [billboard.js](https://github.com/naver/billboard.js).


Updates `billboard.js` from 4.1.0 to 4.1.1
- [Release notes](https://github.com/naver/billboard.js/releases)
- [Changelog](https://github.com/naver/billboard.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/naver/billboard.js/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: billboard.js
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-09 09:26:41 -04:00