You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
ffc_administrator aggregator role — every FFC capability (admin + end-user), but not manage_options, so the whole plugin can be delegated without WP super-admin (GAP F).
Settings → User Access: a role-capability editor for FFC roles (per-toggle AJAX, global/retroactive, audit-logged).
Per-user capability editor on the user-edit screen redesigned: grouped cards, search, copyable slug chips, origin (User/Role) badges, assignable role chips, inline audience membership; fixes a latent bug that stripped uncheckable caps on save.
Recruitment: admin "Undo decision" — send a hired/withdrew/not_shown candidate back to the queue (audited, reason-required, WARNING-level).
Appointments: login-free cancellation page reached from the e-mail link (token-validated, noindex, nonce-guarded).
Changed
⚠ Plugin-wide capability naming standard + 3-state model (breaking for integrations on old slugs): 10 caps renamed, 8 read-only view caps added (26 → 34); one-shot migration rewrites grants on every user + role.
Three previously-inert admin caps now enforced: ffc_manage_certificates (Submissions + dashboard), ffc_manage_custom_fields, and the recruitment Settings tab (view/manage_recruitment_settings) — delegation without manage_options.
More blanket manage_options gates replaced with delegable caps (GAP B): Settings page, admin submission REST, reregistration Custom Fields, and a new Short URLs domain (ffc_view/manage_url_shortener); 34 → 36 caps.
Read-only "só vê" admin tier across modules (GAP C, 3-state): reregistration / appointments / audiences / recruitment open read-only on the view cap; writes stay manage-gated; RecruitmentAdminActions::dispatch hardened to re-check on every destructive action.
ffc_operator is now a complete cross-module read-only auditor (GAP D) — gains view_custom_fields / view_recruitment_settings / view_recruitment_reasons / view_url_shortener.
⚠ Deletion is its own strict tier (GAP E): seven ffc_delete_<domain> caps; delete handlers no longer fall back to manage; migration seeds onto manage holders.
⚠ Bulk CSV export is its own strict tier (GAP G): ffc_export_appointments / _reregistration / _audiences; migration seeds onto manage holders.
⚠ Bulk CSV import is its own strict tier (GAP H): new ffc_import_audiences + ffc_import_recruitment tightened (no umbrella fallback); migration seeds onto manage holders.
⚠ Recruitment Reasons is a strict 3-state tier (GAP I): ffc_view/manage_recruitment_reasons; closes a bulk-delete cap gap (was nonce-only); migration preserves access.
Capability editors: the permission list is organized by module (one card per module) with a Self-service / Administration divider, all groups collapsed by default, and surface badges on the exceptions (API on forms_api, frontend on scheduling_bypass).
Dropped a stray cross-domain ffc_export_certificates grant from ffc_self_scheduling_manager (definition only; no upgrade behavior change).
Settings page is now a real read-only surface for the ffc_view_settings tier (G3): the active tab is wrapped in a disabled <fieldset> + a read-only banner.
Internal frontend audit: inline admin JS extracted to dedicated lint-tested asset files (no behavior change).
Internal frontend audit: large maintainability refactor splitting the monolithic frontend scripts + oversized PHP classes behind their existing APIs (no behavior change).
Fixed
User permissions card now spans the full content width on both editor surfaces.
Schedule exception (operator exit-time override) is now truly single-use — a jti replay ledger claims the token atomically and the banner clears after use.
Recruitment notice editor: "call out of order" now prompts for a justification even when the classification list is filtered or paginated (authoritative empties map, not the DOM).
User dashboard: untrusted values escaped + rel="noopener noreferrer" on external links (XSS / tabnabbing).
Geofence: the location cache stores a short-lived "validated" pass token instead of raw GPS coordinates.