* fix(a11y): [develop] correct labels, document semantics and duplicate IDs
Associates form controls with their labels, replaces obsolete tt markup, removes duplicate element IDs, and adds a native accessibility browser suite with its database fixture.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(a11y): validate label IDs and recognize attribute escaping
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(security): treat grv() and gnrv() as Semgrep request sources
The gating XSS rule missed the short request helpers, the header() rule trusted HTML escapers that do not stop an off-site redirect, and the advisory taint rules missed get_request_var().
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(security): gate Semgrep on new findings for every event
The new sources also match values an earlier gfrv() validated, so a whole-tree result cannot gate pushes; a single job keeps results stable run to run.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(hooks): check staged blobs and fail closed in the changelog tools
The pre-commit hooks read working-tree files while claiming to check staged content, check-changelog.py passed when its base diff failed, and fold-changelog.py deleted fragments it had not validated.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(tests): make CI helper scripts fail when they check nothing
check_all_pages.sh passed without logging in or crawling, the sink inventory accepted ripgrep errors, install_packages.sh and copyright_year.sh lost their failures, and the LDAP spec asserted before navigation finished.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(i18n): audit only changed .po entries and keep contributor badges separate
audit_po.py failed every translation PR on pre-existing errors and matched non-printf text as conversions; update-contributors.py leaked badges between aliased contributors.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs(changelog): add fragment for #8457
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(e2e): move the pointer off the Deepness multiselect button
Deepness sets a zero body margin, so the unhovered #ms-button sits at the viewport origin and headless Chromium on Linux intermittently applies :hover to it.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: pull pinned integration database from authenticated mirror
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* 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>
* 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>
- The job ran pest with no --configuration after the configs moved under tests/, so it found no config and exited 2.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: copy pinned CI images to GHCR
- Service containers pull before any step runs, so the registry mirror cannot help them; a digest-preserving copy under ghcr.io/cacti/ci-images lets jobs pull with GITHUB_TOKEN.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: pull database and Rocky Linux images from GHCR
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* test(cdef): enforce resolver coverage
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(cdef): pin cache action correctly
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: isolate CDEF coverage bootstrap
* fix(cdef): fail closed on invalid recursive definitions
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): log corrupt resolver records
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): bound and isolate recursive resolution
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): preserve resolver failure state
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): isolate invalid graph expressions
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): abort unsafe consumer operations
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): close consumer failure paths
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): make aggregate updates atomic
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): keep repair queries auditable
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): bind bulk deletes and escape item types
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): guard corrupt types and repair reporting
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(aggregate): propagate push-out failures
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(aggregate): document mutable message checks
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* build: add symfony/security-csrf
Backs the CSRF token core that replaces the vendored csrf-magic fork.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: fix security-csrf package path assertion
symfony/security-csrf ships CsrfTokenManager.php at the package root, not under src/.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* refactor: register the composer autoloader before the CSRF include
CSRF validation ran before the autoloader existed, which blocks any class-based guard.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(csrf): add CactiCsrfGuard over symfony/security-csrf
Issues and validates session-scoped tokens; not yet wired into the request path.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(csrf): accept pre-upgrade csrf-magic tokens during the grace window
Legacy tokens carry their own expiry, so the fallback closes itself without a config flag.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(csrf): port the output buffer rewriter to CactiCsrfGuard
Keeps the hidden field name and JS globals that third-party plugins rely on.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): use json_encode for the JS script context in rewriteBuffer
htmlspecialchars() protects the HTML attribute context but not the
<script> string literal, which relied on Symfony's token generator
never emitting a quote rather than being safe by construction.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* refactor(csrf): move the XHR shim to include/js as Cacti-owned code
It has been maintained by the Cacti Group since 2020 and is not an upstream package.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* refactor(csrf): retire the vendored csrf-magic fork
The procedural csrf_* surface stays as a deprecated shim so plugins keep working.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(csrf): validate requests through CactiCsrfGuard
csrf-magic self-invoked from its own file; the guard is called explicitly.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(install): stop gating the permission step on the csrf secret
Retiring csrf-magic removed the directory its default path lives in, and setStep() clamps to the first errored step, so no fresh install could advance.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): key the legacy fallback on the raw secret bytes
refresh_csrf.php writes PHP source with a trailing newline, and trimming that yields a different HMAC key than csrf-magic used.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): log when the guard degrades to disabled in a web context
The installer is the only web path that can reach it, and failing open in silence is not something csrf-magic could do.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: changelog for the CSRF library replacement
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): mint the token before the session write callback closes it
csrf_startup() minted lazily from the output buffer callback, which runs after session_write_close()'s shutdown-function registration, so a token minted there on a legacy-fallback POST was silently dropped.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): make refresh_csrf.php a no-op
Its default secret path no longer ships and live tokens are session-bound, not HMACs over the secret, so rotation neither worked nor did anything meaningful; running it during the upgrade grace window used to delete the legacy secret and kill validation for pre-upgrade tokens outright.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): fall back to the old default secret path when reading it
csrf-magic tried its own directory as a second candidate regardless of $path_csrf_secret; the new reader only tried the configured path, so a site pointing $path_csrf_secret at a file that was never created lost the legacy-token grace window entirely.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs(csrf): point the JS header at its BSD license sidecar
The header reduces the original BSD terms to prose and the actual text sits in an unreferenced csrf.js.LICENSE, so add a pointer to it.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): restore csrf_check()'s bool return and $fatal contract
The shim ignored $fatal and always returned void, so audit/audit.php's `!csrf_check(false)` evaluated `!null` (always true) and denied every request instead of getting a real pass/fail result back.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: reference the pull request number in the changelog entry
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: resolve includes through Cacti path constants
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(csrf): enforce full coverage
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Harden CSRF fallback handling
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(csrf): assert the component stays out of the index
Committing it would leave a second copy to drift against the lock.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: align CSRF checks with PHP 8.2
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: normalize the CSRF changelog entry
* Fix CHANGELOG entry ordering
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(csrf): support constrained test environments
* fix(csrf): narrow nullable guard state
* test: place CSRF coverage in security domain
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* security(test): match disabled exec exactly
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: run CSRF coverage on PHP 8.3
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* fix(auth): reject malformed remember cookies
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: load cookie contracts lazily
* test(cookie): fail clearly when contract markers move
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(auth): align persistent credential lifecycle
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(auth): find cookie function boundaries robustly
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* hardening: validate the login realm and escape the LDAP username per context
domains_login_process() now rejects a realm get_auth_realms() does not list and
fails closed on one that is listed but has no domain behind it, and the Ldap
class escapes the username for the DN and the search filter separately rather
than relying on a filter-only blocklist.
- an unlisted realm sent with a non-empty password used to match no branch at
all and returned an empty user with no error, which auth_login.php reads as
an authenticated user and provisions from the template account
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* security: reject LDAP logins that skip a domain bind
Posted realms outside user_domains no longer fall through to template or guest login.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(ldap): align escaping contract with username lookup
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: cover LDAP domain login through OpenLDAP
The e2e stack now binds a real directory user and checks that a forged realm cannot skip that bind.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(ldap): address Copilot review feedback
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix: substitute LDAP filter placeholders in one pass
LDAP_ESCAPE_FILTER leaves angle brackets intact, so a looped str_replace can rescan one value as another key.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Change realm retrieval function from gnrv to gfrv
* tests: add gfrv() stub to harnesses that exercise gfrv()-calling code
domains_login_process() and api_aggregate_convert_template() call gfrv() for
realm/aggregate_template_id, but their test harnesses only stubbed gnrv(),
so Pest failed with 'Call to undefined function gfrv()'.
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* fix(csv): align export and graph sample windows
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(csv): satisfy release policy checks
* test(csv): align legacy capacity contract
* test(csv): add standard license headers
* fix(rrd): infer step from trailing fetch row
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(csv): trigger on resolution query coverage
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(rrd): mirror fetch helper arguments
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(rrd): isolate percentile globals
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(rrd): annotate intentional eval
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(rrd): restore integration config
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(rrd): enable strict types
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(rrd): restore font config
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: align CSV coverage with supported PHP versions
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* fix(csrf): require POST tokens for item actions
* test(csrf): cover every guarded action path
* test(csrf): keep legacy guard contract extensible
* fix(csrf): hide POST-only targets from crawlers
* test(csrf): reject every crawlable state-action link
* fix(csrf): fail closed without logging crawler probes
* fix(csrf): post data-query item actions safely
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): normalize stripped token separators
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): distinguish method and token failures
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): escape POST action URL attributes
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): delegate POST action events
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(csrf): post data template add action
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* style(html): align POST button class
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(cli): add unified command frontend and normalize legacy failures
Add the Symfony-backed bin/cacti entry point while preserving legacy argument, terminal, signal, and exit-status behavior. Fold in the focused legacy CLI correctness fixes from #7906 without adding its unused parser abstraction.
Keep path containment and the PHP 8.3 floor out of this review; the latter remains in #7939.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cli): enforce PHP floor and deny web dispatch
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* build: raise the 1.3 floor to PHP 8.3
RHEL 10 ships 8.3 in AppStream and dropped modularity, so an 8.4 floor would
put every RHEL, Alma and Rocky 10 install on Remi. Ubuntu 24.04 is 8.3 as
well, which makes it the lowest common denominator of the current LTS fleet.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: raise the documented PHP floor to 8.3
The 1.2.x column keeps 8.1, which still matches that branch's composer constraint.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: run process lock coverage on PHP 8.3
* fix: finish PHP 8.3 floor cleanup
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
process-only was empty, so lock-threads walked discussions as well, and the
job has no discussions permission. The exempt lists also matched only the
flat label names, which would have exposed 238 open enhancements to the
stale closer once those labels are retired.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Serialize process registry admission with Symfony Lock
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Fix PDO process lock mode handling
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: run process lock coverage on PHP 8.2
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix: confirm a pid is still ours before signalling it
#7574 added the still-running guard to dsstats but left six byte-identical
siblings signalling a pid straight out of the processes table. After a crash or
a power loss the row survives, the pid is recycled by an unrelated daemon, and
the next start SIGTERMs a stranger. That is issue #7425, still live in rrdcheck,
boost, poller_commands, float_rrdfiles, poller_reindex_hosts and
rebuild_poller_cache.
Wrap each kill in cacti_process_still_running(), matching the dsstats shape, and
leave unregister_process() outside the guard so a stale row is still cleaned up.
Cover all seven with a test that walks every kill site, so a new variant cannot
reintroduce it.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: assert the guard plainly
toContain() takes needles rather than a failure message, so the file name was
being asserted as a second required substring and the test always failed.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs(poller): describe required lock parameters
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: share one body across the per-script coverage workflows
Eight of the coverage workflows were the same file with four things changed:
the PHPUnit configuration, the job name, occasionally the PHP version, and
occasionally the snmp extension. Everything else, the triggers, permissions,
concurrency, checkout, dependency setup and the Pest invocation, was copied
between them, so a change to any of it meant eight edits and eight chances to
miss one.
They now call a reusable workflow and supply only what differs. Each caller
keeps its own path filters and concurrency group, since those are genuinely
per-script.
installer, snmp and rrd-graph-item are left alone. They run more than one
suite or produce clover output, so folding them in would mean parameterising
the shared body until it stopped being shared.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: rebuild the callers when the shared coverage body changes
Each caller watched its own file but not the reusable one, so editing the
shared body would not have run any of the suites it drives.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
There was no root CONTRIBUTING.md and no way to run the CI gates locally in one
step, so reproducing a CI failure meant reading workflow YAML. Add a
'composer check' target that chains the gates, expose the sink and hotspot
guards, the changelog validator and the JavaScript tests as their own targets,
and document setup and the changelog.d fragment workflow.
Pin Node in .nvmrc to the version CI uses, and move the one remaining
setup-node still on 20 to 22 so every workflow agrees.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>