504 Commits
Author SHA1 Message Date
Thomas VincentandTheWitness 769c59ec9e fix(forms): encode form action URLs and configured attributes (#8437)
* fix(forms): preserve action URLs in HTML and JavaScript

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

* docs(changelog): record form action URL fix for issue 8438

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

* fix(forms): encode configured form name and enctype attributes

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-20 13:18:37 -07:00
dependabot[bot]andTheWitness 281e8e28f2 deps(deps-dev): bump @playwright/test in /tests/e2e in the npm-e2e group (#8435)
Bumps the npm-e2e group in /tests/e2e with 1 update: [@playwright/test](https://github.com/microsoft/playwright).


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

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.64.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>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-10-20 00:50:25 -07:00
Thomas Vincent 2d58b2477f fix(spikekill): preserve valid reference samples during repair (#8427)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-19 09:32:59 -04:00
Thomas Vincent 57c0fe63d4 Fix restrictive graph permission display for default-deny templates (#8422)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-18 10:39:20 -04:00
1997691de0 Render RRDtool Tune Info as balanced div boxes and POST the Data Source repair actions (#8412)
* data_sources: render RRDtool Tune Info as balanced div boxes

rrdtool_tune() emitted an unbalanced mix of html_header() and
html_end_box() calls wrapped around raw table rows inside the single
box opened by data_sources.php.  The premature and extra closing tags
corrupted the DOM, which (depending on theme) clipped the Save button
at the bottom of the Data Source edit page while in Data Source Info
mode.

- Separate the execute, CLI and HTML code paths in rrdtool_tune() and,
  for HTML, render each section as a self contained, balanced div box.
- Extract and rename the helper print_leaves() to the standalone
  rrdtool_tune_print_leaves(), matching the rrdtool_tune_* naming
  convention, and emit div rows instead of table rows.
- Switch the data_sources.php wrapper box to div mode to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* data_debug: require POST for the Data Source repair actions

Applying RRDfile repairs and rerunning the debugger are state changing
operations, so they should not be reachable with a GET.  Driving them
through a GET also meant the follow up redirect was pulled into the
content area as a full page, losing the theme and navigation on
rerender.

Register data_debug.php run_repair and run_debug in the
cactiIsPostActionUrl() allowlist so loadUrl() upgrades them to a
token-bearing POST, and add the matching csrf_require_post() guard so
the browser transport and server side guard stay in sync.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* rrd: split rrdtool_tune into testable render and execute helpers

Break rrdtool_tune() into small single-purpose helpers so each path can
be exercised directly by unit tests (the web display path is otherwise
unreachable under CACTI_CLI):

- rrdtool_tune_print_leaves() takes an explicit $html flag instead of
  branching on CACTI_CLI, so both the div and plain-text branches are
  testable.
- rrdtool_tune_execute() applies the tune/resize commands for a repair.
- rrdtool_tune_print_cli() prints the source commands as plain text.
- rrdtool_tune_print_html() renders the balanced div boxes.
- rrdtool_tune() becomes a thin dispatcher over the three.

Add tests/Unit/RrdTuneRenderTest.php covering the leaf printer, the HTML
and CLI printers, the execute path and the dispatcher, asserting the
output is balanced div markup with no table rows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* review: post Data Source Troubleshooter actions via cactiPostAction

Address PR review feedback:

- Switch the Apply Suggested Fixes and Rerun Analysis links to the
  existing cactiPostAction/data-url idiom (as data_sources.php already
  does for ds_repair) instead of upgrading a loadUrl() GET through the
  cactiIsPostActionUrl allowlist. The allowlist path replayed the
  query-free mutation URL into browser history, so a refresh reopened
  the list instead of the selected Data Source; a full cactiPostAction
  submission follows the server redirect to the read-only view URL and
  records that in history. The run_repair / run_debug csrf_require_post
  guards are retained, and the data_debug.php allowlist entry (and its
  now redundant click handlers) are removed.

- Add a callable $executor test seam to rrdtool_tune_execute() (matching
  rrdtool_dump_document) so the unit tests assert the tune and resize
  commands are actually executed, with resize.rrd produced only when the
  resize command runs, rather than passing on the rename alone.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* review: move RrdTuneRenderTest into the Unit/Core/Rrd category folder

Per AGENTS.md, new unit tests belong in a category subfolder rather than
directly under tests/Unit. Move RrdTuneRenderTest there and update the
UnitStubs include depth accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: TheWitness <copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-16 11:23:07 -04:00
TheWitness c226f2a1a5 Add a right scrollbar gutter to the console content area in legacy themes (#8403)
.cactiConsoleContentArea scrolls vertically, and with no right padding the
scrollbar sat flush against the right-aligned cells (for example the Data
Source Info values on data_sources.php), hiding the last digits. Give it a
15px right gutter in every legacy theme (cacti, carrot, dark, deepness,
hollyberry, modern, paper-plane, paw, raspberry, sunrise). midwinter already
reserves a scrollbar gutter and is unchanged.

Cover each changed rule with a develop-theme-correctness targeted test.
2026-10-16 08:16:58 -04:00
TheWitness b2ed6ec337 Legacy filter rendering: show only the classic inline filter (#8404)
The page_filter_format setting is meant to be either/or: Modern shows the
Layouts selector with its Edit dialog, Legacy shows the classic inline
filter. Legacy also rendered the Layouts selector row (and its JavaScript),
so the new and the classic filters appeared together.

Stop rendering the Layouts selector in Legacy mode: create_filter() no
longer appends create_layouts(), and create_javascript() only emits the
layouts script in modern mode. The now-unused create_layouts() and
create_layouts_javascript() helpers are removed, and the setting help text
is updated to say the Layouts selector is available in Modern only.
2026-10-16 08:11:50 -04:00
TheWitnessandCopilot 5afe0f8f68 Add one-click RRDfile repair (Apply Suggested Fixes) to Data Source Info mode (#8401)
* Add one-click RRDfile repair to Data Source Info mode

The Data Source Info mode already compares the RRDfile against the Cacti
definition and prints the rrdtool tune recommendations (add a missing Data
Source with DS:name:type:heartbeat:min:max, remove an extra one with DEL:name,
and correct the type, heartbeat, minimum and maximum). It did not, however,
offer a way to apply them from the page the way data_debug.php does.

- Add an "Apply Suggested Fixes" link to the "RRDtool Tune Info" box header when
  the web server can write the RRDfile; when it cannot, the header falls back to
  "Run Fix from Command Line" and the commands remain listed for manual use.
- Add a ds_repair action that runs the same tune recommendations server-side
  (gated on data_source_authorized() and on the RRDfile being writable, and
  skipping any recommendation carrying control characters), logs each command to
  DSDEBUG, then reloads the Data Source so the result is visible. This mirrors
  data_debug.php's run_repair / "Apply Suggested Fixes".
- Harden the Info-mode guard so a missing/unreadable RRDfile (rrdtool info
  returning false) no longer triggers an array-offset warning.

* Address review: POST-guard ds_repair and harden repair result check

- Route the "Apply Suggested Fixes" action through a CSRF-protected POST: the
  link now uses the cactiPostAction handler (href="#", data-url) instead of a
  GET navigation, and ds_repair is added to the $bad_actions guard in
  include/global.php so a tokenless request fails closed with 405. ds_repair is
  added to the curated CSRF action test for regression coverage.
- Use a strict comparison on the rrdtool_execute() result: it can return null
  on a failed exec/proxy connection, and null == '' would have reported a failed
  repair as "All RRDfile repairs succeeded."
- Refresh the sink inventory baseline for the new header redirects in ds_repair.

* Add request-coverage probe for the ds_repair RRDfile repair handler

The Data Source Info mode repair handler ds_repair() is a POST action that the
page-level e2e suites do not drive (it needs a Data Source whose RRDfile
mismatches its Cacti definition). Add a request-coverage fixture that loads the
handler in isolation via cacti_fixture_source_function(), stubs its I/O
boundaries, and drives every branch (unauthorized, unreadable RRDfile, no RRA,
nothing to tune, not writable, a control-character recommendation that is
skipped, and both tune success and failure). Register it in
run_request_coverage.sh for data_sources.php changes so the changed-line
coverage gate sees the handler exercised.

* Address review: use defined helpers and boolean repair result

- Replace the undefined cacti_has_control_chars() check with a comparison
  against rrd_strip_control_chars() (loaded from lib/rrd.php) to skip any
  tune recommendation that carries control characters.
- Execute each tune with RRDTOOL_OUTPUT_BOOLEAN and treat a strict true as
  success so proxy storage (which returns the raw 'OK u:...' status under
  RRDTOOL_OUTPUT_RETURN_STDERR) is not misreported as a failure.
- Add the new translatable strings to locales/po/cacti.pot and reuse the
  existing failure msgid.
- Update the request-coverage fixture to the new boundary contract.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-15 20:47:31 -04:00
Thomas Vincent 3bcb4e4f49 fix(graphs): [develop] clear empty query fields in rendered text (#8349)
* fix(graphs): clear empty query fields in rendered text

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

* ci(coverage): enforce changed PHP statement 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-15 20:38:03 -04:00
TheWitness aee10ba74e Pass the changed-coverage gate when no files of the language changed (#8399)
report_changed_coverage.py failed closed on an empty report: a pull request
that changes no files of the gated language produced {} and the redundant
'report and all(...)' guard made that falsy, so the gate returned 1. This
failed the chromium 'changed CSS lines' step (and the equivalent PHP/JS
gates) for any PR that does not touch that language.

Drop the 'report and' guard. all() over no rows is already True, so an empty
report is complete and passes via the existing total == 0 clause, while a
genuinely changed but uninstrumented file still fails closed through all().
2026-10-15 14:42:25 -04:00
TheWitness 433af99661 Fix plugin archive restore skipping not-yet-created nested directories (#8398)
Restoring a plugin from an archive, or installing one downloaded from
GitHub into the database, extracts the tgz to a temp file and writes each
entry under plugins/<name>/. validate_relative_path_within() anchored a
not-yet-created entry on its immediate parent directory, so every entry in
a subdirectory the restore had not created yet (includes/, css/, tests/,
docs/, ...) resolved against a missing path, failed the containment check
and was skipped. The plugin was left with only its top-level files and
setup.php then fatally required the missing includes/database.php.

Judge a not-yet-created entry by its deepest existing ancestor instead,
mirroring data_source_path_within_rra(). Every path segment is already a
validated plain name and no walked segment may be a symlink, so the full
candidate still stays within the base; traversal, absolute, drive-letter,
null-byte and symlink entries remain rejected.
2026-10-15 14:14:19 -04:00
TheWitnessandCopilot 4e09327660 deepness: fix unreadable search-result highlight color (#8396)
* deepness: make search-result highlight readable and on-theme

The .filteredValue search highlight set a neon yellow (#F8D93D) background
with no text color, so the emerald link text (--dp-link) rendered on bright
yellow was effectively unreadable and clashed with the dark emerald theme.

Use a warm gold background that complements the emerald palette and a
near-black (--dp-page) text color for high-contrast, readable matches.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* tests: cover deepness .filteredValue highlight computed styles

Assert the deepness search-highlight background and text colors in the
theme-correctness suite so the changed .filteredValue CSS lines are
exercised and meet the changed-CSS coverage gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-15 14:09:23 -04:00
TheWitness 5c1577a382 Force plugins.php action icons over POST and enlarge Tabler icons (#8394)
The install, enable, remote enable, load and dialog-confirmed actions on
plugins.php are guarded by csrf_require_post() on the server. The anchors
were still activated by the generic GET anchor handler, so clicking them
returned a 405 on the develop branch. Submit these actions over POST:

- The dialog Continue button and the Check Latest control now post.
- A capture-phase document click listener intercepts the install, enable,
  remote enable and load icons before the bubble-phase generic handler, so
  they post, keep working after Ajax table refreshes, and bind only once.

Tabler (i.ti) icons rendered smaller than the FontAwesome glyphs used on
the 1.2.x branch, so give them an explicit 16px rule matching the fa
layout in each bundled theme, and cover the new rule with
develop-theme-correctness targeted tests.
2026-10-15 13:39:18 -04:00
Thomas Vincent cf70ba4cf2 fix(plugins): [develop] restore lifecycle diagnostics, compatibility and error attribution (#8297)
* fix(plugins): honor version range boundaries and compatibility status

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

* fix(plugins): preserve null hook diagnostics and enforce dependency versions

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

* fix(plugins): report config failures and confine error attribution

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

* fix(plugins): guard entrypoint frames and bind realm filenames

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

* fix(plugins): propagate install hook failures on develop

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

* fix(plugins): match realm filenames literally

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>

* test(plugins): add standard GPL headers

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

* ci(coverage): require 80 percent of changed PHP statements

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 22:53:44 -04:00
Thomas Vincent e2a5f32ee9 fix(ci): [develop] harden dependency installs and Docker build boundaries (#8294)
* security(ci): constrain dependency installs and container build boundaries

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

* fix(docker): retain shipped runtime libraries in build context

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

* fix(tooling): quote gettext paths and honor Docker base selection

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>

* fix(tooling): finish Docker layer and regex scan findings

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

* fix(ci): preserve documentation badge anchors without alternation

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

* test(ci): preserve contributor badges and enforce Python 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): enforce private review files and run path regressions

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

* test: measure changed gettext shell coverage

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

* test: pin coverage to the reviewed PR revision

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

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 22:52:37 -04:00
Thomas Vincent 62063a29e0 fix(theme): [develop] correct CSS cascade, invalid values and responsive selectors (#8293)
* fix(themes): correct CSS cascade, font fallbacks and responsive selectors

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

* fix(themes): remove validated empty and redundant CSS rules

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

* style(css): remove reviewed inactive rules and redundant separators

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

* style(themes): consolidate two reviewed duplicate selectors

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

* fix(themes): remove identical whitespace declaration after consolidation

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

* fix(theme): keep context menu fallbacks in Cacti overrides

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

* test(theme): measure native CSS and header coverage

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>

* test: cover Midwinter and graph heading CSS repairs in Chromium

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

* ci: take the theme coverage base from the merge commit parent

- github.event.pull_request.base.sha can predate the develop tip the checkout was merged onto, which counted develop's own CSS lines as the PR's.

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

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 22:51:15 -04:00
315964cae8 Log administrative user-account actions on develop (#8281)
* 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>

* 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: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-10-14 22:50:14 -04:00
32467ddcab perf: reuse graph option arrays and document validation results (#8361)
* perf: reuse bootstrapped graph option arrays and document validation

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

* test: record the installed RRDtool version in profiles

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

* docs: record final validation scope and profiling runtime limits

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

* docs: clarify the scope of changed-code coverage

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

* ci: repair relocated PHPUnit configs and the deletion-only coverage gate

- Point the five relocated configs that still carried a contributor's local
  autoload path (#8376) at ../include/vendor/autoload.php.
- Pass --configuration=tests/phpunit.xml to the CSV window workflow and the
  README example now that phpunit.xml no longer lives in the repository root.
- Let the changed-lines gate pass deletion-only PHP changes. Without added
  lines the generated config has no source filter, PHPUnit writes no clover
  report, and the gate failed on the missing file instead of reporting zero
  executable changed lines.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: TheWitness <thewitness@cacti.net>

* ci: keep the missing request-report check for deletion-only changes

Only short-circuit the changed-lines gate when there are no added PHP lines
and PHPUnit wrote no clover report, so an empty request-coverage directory
is still rejected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: TheWitness <thewitness@cacti.net>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: TheWitness <thewitness@cacti.net>
Co-authored-by: TheWitness <thewitness@cacti.net>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-14 22:45:42 -04:00
Thomas Vincent ebd16105c5 fix: drop backslash and line breaks in sanitize_uri (#8388)
* fix: drop backslash and line breaks in sanitize_uri

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

* docs: add changelog entry for sanitize_uri fix

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

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 22:39:32 -04:00
Thomas Vincent 0f06608175 fix: reject dangling symlinks in validate_relative_path_within (#8389)
* fix: reject dangling symlinks in validate_relative_path_within

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

* docs: add changelog entry for dangling symlink fix

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

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 22:38:41 -04:00
dependabot[bot]andThomas Vincent 5229064a22 deps: update hotkeys-js to 4.0.8 with compatible browser assets (#8343)
* deps(deps): bump hotkeys-js from 3.10.1 to 4.0.8

Bumps [hotkeys-js](https://github.com/jaywcjlove/hotkeys-js) from 3.10.1 to 4.0.8.
- [Release notes](https://github.com/jaywcjlove/hotkeys-js/releases)
- [Commits](https://github.com/jaywcjlove/hotkeys-js/compare/v3.10.1...v4.0.8)

---
updated-dependencies:
- dependency-name: hotkeys-js
  dependency-version: 4.0.8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(build): use hotkeys v4 browser artifact paths

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 21:28:58 -04:00
TheWitnessandCopilot 76a916cf03 fix(boost): never re-stage poller output when boost_redirect is on (#8374)
* fix(boost): never re-stage poller output when boost_redirect is on

#8332 gated the boost_redirect bypass in boost_poller_on_demand() on the
caller not passing $staged. process_poller_output() always passes it, so
the bypass never fired and the main poller re-inserted every row spine or
cmd.php had already written to poller_output_boost, flooding the log with
"Boost staging ignored N of N duplicate sample keys" warnings.

When boost_redirect is enabled the poller now never inserts into
poller_output_boost and reports the rows as staged so they are cleared
from poller_output. poller_recovery.php writes recovered remote rows via
boost_flush_output_batch() directly and is unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: TheWitness <thewitness@cacti.net>

* chore(changelog): use changelog.d fragment for #8374

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: TheWitness <thewitness@cacti.net>

* fix(boost): log failed poller_output_boost staging as an ERROR

boost_flush_output_batch() returned false silently when the database did
not acknowledge a chunk. cmd.php's boost_redirect staging ignores that
return, so a failed collector-side write left no trace. Log a BOOST ERROR
with the sample count from the helper so every caller's failure is visible.

Adds in-process coverage for the failure log and for boost_poller_on_demand()
never re-staging rows when boost_redirect is on.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: TheWitness <thewitness@cacti.net>

---------

Signed-off-by: TheWitness <thewitness@cacti.net>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-14 21:13:43 -04:00
TheWitness ffd7a81109 Scope the tree Graph Templates filter to the drilled Device Template (#8370)
* Scope the tree Graph Templates filter to the drilled Device Template

When drilling a Site Branch into a Device Template (host_id=-1, host_template_id set), create_tree_filter() fell through to listing every Graph Template. Scope the dropdown to the Graph Templates present on that Device Template's devices (within the drilled Site when set), matching the graphs the branch actually shows.

* docs(CHANGELOG): add issue#8370 entry

* test: cover the tree Device Template graph-template scope; fix CHANGELOG ordering

Add an isolated source-slice probe that drives create_tree_filter()'s new host_template_id branch so the changed lines meet the >=80% changed-line coverage gate, wired into run_request_coverage.sh. Move the issue#8370 CHANGELOG entry into the issue block so it no longer precedes the security entries.

* docs(CHANGELOG): append issue#8370 at the end of the issue block
2026-10-14 20:56:12 -04:00
TheWitness 75f92c2d86 Detect and repair RRDfile Data Source count mismatches via RRDtune (#8368)
* Detect and repair RRDfile Data Source count mismatches via RRDtune

Report when a Graph requires more or fewer Data Sources than its RRDfile
contains, generate the rrdtool tune DS:/DEL: command to correct it, and run
it when the RRDfile is writable.  Applies to data_debug (rrdtool_cacti_compare)
and the RRDchecker batch process (do_rrdcheck).  The decision logic lives in
pure helpers (rrdtool_cacti_compare_ds, rrdcheck_ds_findings) with unit tests.

Resolves #8366

* rrdcheck: only probe local writability for local storage

Under the storage proxy the RRDfile is remote, so is_resource_writable()
checks the wrong filesystem.  Skip the local probe when using the proxy and
let it enforce remote permissions and report failures via its response.

* rrdcheck: validate tune args, enforce RRA containment, fix failure detection

Validate every tune specification against RRDtool's documented DS grammar
(ds-name 1-19 [a-zA-Z0-9_], known DST, integer heartbeat, numeric-or-U min/max)
and escape it before use.  For local storage require the RRDfile to resolve
inside the RRA directory via data_source_path_within_rra().  Detect failures
from the real return value (false/null/empty or missing OK) instead of casting
to string, so a failed tune is no longer logged as success.

* rrd: normalize a 0/0 data source range to 0:U when building a tune add spec

rrdtool_function_info_from_ds() passes min/max through unchanged, so a source
stored as 0/0 produced DS:name:type:hb:0:0 which RRDtool rejects.  Mirror RRD
creation and emit 0:U so the repair paths can restore those sources.
2026-10-14 20:55:52 -04:00
Thomas Vincent 8d02ed0860 test: normalize relocated PHPUnit paths for Pest discovery (#8379)
(cherry picked from commit 15a4999ee6)

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 19:34:50 -04:00
Thomas Vincent 5ab64dc058 test: move PHPUnit configuration into the tests directory (#8376)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-10-14 18:55:26 -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
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
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