Skip to content

v6.12.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 01:47
· 17 commits to main since this release
79f2c09

Security

  • IP geolocation debug logging — hardened to never store a raw client IP, even with debug_geofence enabled. A security audit found IpGeolocation::get_location() wrote the raw IP into the ActivityLog LEVEL_DEBUG trail on the cache-hit and service-success paths (and via the returned location.ip field echoed into the log), inconsistently with the already-hashed fetch_from_service path and the salted-hash treatment in PreflightTelemetry. All debug-log call sites now emit a truncated SHA-256 (hash_ip()) and redact the ip field of any logged location array via a new redact_location_ip() helper; the value returned to callers and the cache entry are unchanged (the contract location['ip'] is preserved). Low severity — the path is gated behind the off-by-default debug toggle and an IP is low-sensitivity operational data — but it removes a residual LGPD/GDPR exposure and aligns the module with the plugin's IP-hashing convention. No behavior change for callers. (#596)

Changed

  • Internal refactor (#563 — modular-monolith hardening) — decomposed the largest god-classes and the shared static hubs, behavior-preserving throughout (characterization tests first; markup/queries/hooks unchanged): the FormProcessor submission flow → a pipeline of testable guard/stage classes (~1047→85 lines); CapabilityManagerCapabilityMigrator / RoleRegistrar + a slim runtime manager; the Core\Utils god-utility dismantled into focused homes (FilenameHelper, RequestInput, AssetHelper, HtmlPolicy, Capabilities, SuccessHtmlRenderer, …), leaving only generic primitives; RateLimitChecker → per-dimension strategy classes; RecruitmentCsvImporterCsvParser / CsvValidator / CsvStagingService / CandidatePersister (~1554→310); the monolithic Activator → per-module activators; the five large repositories → *Reader / *Writer behind a delegating façade; admin-renderer view/logic separation; and typed per-option-group settings readers GeolocationSettingsReader / RateLimitSettingsReader. Full suite green; PHPStan L8 + WPCS clean. (Detail in the linked PRs.)
  • Internal refactor (#589) — retired the UserManagerCapabilityManager and ActivityLogActivityLogQuery back-compat delegations (all call sites repointed); split RecruitmentCandidateRepository into reader/writer; decomposed the public-CSV classes and the ReregistrationAdmin / RecruitmentAdminPage god-classes into controller + renderer; extracted the large inline admin markup into templates/ partials; and split PdfGenerator into renderer + data-assembly. Behavior-preserving — byte-identical markup, hooks unchanged.
  • Internal refactor (#591) — split the remaining admin/handler god-classes behind same-signature delegators (FormEditorSaveHandler, AudienceAdminAudience, PrivacyHandler, AdminAssetsManager, and the critical-path SubmissionHandlerSubmissionLifecycleService); read/write-split the smaller repositories (recruitment notice/adjutancy/reason/call, url-shortener, reregistration-submission); extracted SettingsActionHandler from Settings; removed the lone dead DateFormatter::flush_cache() shim and dead back-compat entry points. The remaining migration-tail shims (Encryption plaintext fallback, cpf_rf_encrypted, ficha generation_date) stay — evidence-gated, not dead code. Behavior-preserving.
  • Internal architecture (#563 — module boundaries) — added a dependency-free module-boundary guard (tests/Unit/ModuleBoundaryTest.php + committed baseline, 130 edges) that fails CI on any new cross-module coupling and can only shrink — regenerate with FFC_UPDATE_BOUNDARY_BASELINE=1 vendor/bin/phpunit --filter ModuleBoundary (#593). Then retired the nine static repository façades, migrating every caller to the *Reader / *Writer classes directly (row-shape types + public constants rehomed onto the readers; class_exists() availability guards and @phpstan-import-type consumers repointed). The three instance façades (AppointmentRepository, SubmissionRepository, UrlShortenerRepository) are kept by design — they are the transactional aggregate root (begin_transaction()FOR UPDATE read → write → commit() on one $wpdb), not dead delegators. Graph unchanged at 130 edges; full suite green (5513 tests); PHPStan L8 + WPCS clean. (#594)
  • Internal architecture (#563 — per-module bootstrap loaders) — introduced single bootstrap entry points (AdminLoader, then ReregistrationLoader / SelfSchedulingLoader) so the orchestrator (Loader) wires each module through one symbol instead of newing up its internals inline, narrowing the Root → <module> surface. UserDashboard was deliberately left without a loader — its Root edge is capability/role lifecycle (orchestrator responsibility), not module bootstrap, so a loader would add indirection without shrinking the edge (decision documented in CLAUDE.md). Behavior-preserving; each loader pinned by a wiring test. (#600, #601)