* 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>
* chore: resolve concurrent CHANGELOG appends with a union merge
Every PR lands on the same two anchors, so merging one reliably conflicts
the others on CHANGELOG alone.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
(cherry picked from commit 6bc8e63ecb)
* feat(changelog): take entries as fragment files instead of CHANGELOG edits
Every pull request edited one of two lines, so merging one conflicted the
rest. A file per change gives concurrent PRs nothing to collide over.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
(cherry picked from commit a8a0bfa29a)
* chore(security): drop line numbers from the tracked sink baselines
Both verifiers already strip the line before comparing, so the tracked
numbers carried no signal and rewrote 212 lines of baseline on any edit that
shifted code, conflicting every open pull request.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
(cherry picked from commit ccfd3d374b)
* fix(ci): rebase stale pull request branches instead of merging them
A merge update adds a commit per run, so branches accumulate snapshots of
old develop and re-conflict on every shared file they carry.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
(cherry picked from commit e9e33c77cd)
* test: match the escaping call rather than the exact source line
The literal assertions here required the uncast form while
PhpBinaryPathNullCoercionTest required the cast, so the two could not both
pass and whichever landed second broke the other.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
(cherry picked from commit 98cfc84756)
* fix(changelog): handle security entries in fragments and validation
Review caught the missing type. Security entries also take GHSA identifiers
and open a release section ahead of issue and feature entries, none of which
the first pass handled.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: require Composer-managed dependencies
Prevent agents from committing third-party package trees and require composer.json plus composer.lock updates instead.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Make PHP 8.1 dependency builds reproducible
* Tighten integration runner permissions
* Harden and standardize GitHub Actions
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Restore ripgrep for security guards
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Wait for Cacti daemon readiness in CI
* Satisfy strict shell policy in diagnostics
* Preserve Cacti config group ownership
* Run stateful Cacti checks as the web user
* Run privileged page-crawl harness as root
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(readme): add all-contributors recognition and daily update job
- Add .all-contributorsrc and a Contributors section to README.md, badges
derived from git log path analysis and PR review history
- Add a scheduled workflow that refreshes both from the GitHub API daily
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(contributors): resolve founder name aliases in daily refresh script
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(ci): correct contributors workflow YAML and script encoding
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: refresh sink and hotspot baselines for upstream line shifts
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* ci: add AI security review workflow for PRs
Adds a GitHub Actions workflow that runs on every PR targeting develop.
The job collects the PR diff, grep hits on changed PHP files (SQL sinks,
superglobal access, command execution, dynamic includes, file writes,
archive extraction), and 120-line excerpts from historically vulnerable
hotspot files. It feeds all of this to claude-opus-4-6 using a
structured security review prompt and posts the model's findings as a
PR comment.
The job fails (blocking merge) when the model returns "BLOCK PR". API
or infrastructure errors are non-fatal so they do not block unrelated
PRs.
Requires the ANTHROPIC_API_KEY repository secret. Fork PRs skip
gracefully when the secret is absent.
Closes #6936-related CI gap — continuous variant-class hunting on every
PR without manual triage overhead.
Signed-off-by: Thomas Vincent <thomasvincent@somethingwithproof.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: remove AI branding from security review workflow
Signed-off-by: Thomas Vincent <thomasvincent@somethingwithproof.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: add security posture and perf regression workflows
Add PHP-oriented parity guardrails similar to Spine modernization:
- new security posture workflow (TruffleHog, Semgrep SARIF, Scorecard,
Composer audit, workflow policy checks)
- new performance regression workflow with hyperfine + RSS thresholds
- workflow policy checker script for pinned-action/strict-shell validation
- versioned CLI performance baseline file
Fixes#6822
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: address copilot feedback on security and perf workflows
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: fix scorecard install, sarif upload pin, and perf baseline bootstrap
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: avoid github context interpolation in security review run steps
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: gate secret-dependent steps and fix composer audit, sarif, artifact pins
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: generate composer lock without --lock for audit
The --lock flag needs an existing composer.lock; Cacti ships none, so the audit step exited 3.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: report composer audit advisories as non-blocking
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: use a valid model id for the security review and cover security-review.yml in policy lint
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: address review feedback on security and perf workflows
- grant issues:write so the security review can post PR comments
- harden i18n run step by passing github context via env vars
- fail the security gate when the API returns no usable text
- fetch origin/<base> before reading the trusted perf baseline
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: harden review gate, workflow policy, and perf job
- security_review.py: gate on the model's parsed final-decision marker
instead of a "BLOCK PR" substring match, which misfired on prose
("I would not BLOCK PR") and on the attacker-controlled diff echoing the
instruction text back into the review body
- check-workflow-policy.py: also validate job-level reusable-workflow `uses:`
and require docker:// references to be pinned by an @sha256 digest
- perf-regression.yml: skip the benchmark job on fork PRs so an untrusted
fork cannot run baseline-defined commands during the bootstrap window
Co-Authored-By: Oz <oz-agent@warp.dev>
* ci: scope security review write permissions to the job
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@somethingwithproof.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Thomas Vincent <thomas@vincent.dev>
Co-authored-by: Oz <oz-agent@warp.dev>
Co-authored-by: TheWitness <thewitness@cacti.net>