== Changelog ==


= 2.0.0 (September 15, 2026) =
Core and Pro are published together as 2.0. The version is now read from the
plugin header alone, instead of being written a second time as a constant.

* Removed: two public AJAX endpoints, `attrua_check_username` and
  `attrua_check_email`, that answered "does this account exist?" to anyone who
  asked, over `wp_ajax_nopriv_`, with no rate limit of any kind. The nonce was
  no obstacle — it is printed on the public registration page. Nothing called
  them: the registration form makes no AJAX request, and a comment claiming
  "used by inline JS in the form template" had outlived the script it described.
  The Pro extension had already dropped its own copies of these two names for
  the same reason. The cheapest fix for enumeration is the one that leaves
  nothing to defend.
* Fixed: the emergency access link that always reaches `wp-login.php` no longer
  carries its secret in the address on every request. A secret in a query
  string does not stay there — it lands in the server's access log, browser
  history and the Referer sent to anything the page loads — and this link is
  bookmarked and pasted about precisely because it is for emergencies. It is now
  exchanged once for a short-lived cookie and removed from the URL by a
  redirect; the bookmark keeps working. When Pro is active, every use and every
  refused attempt is written to the audit log, and guesses are rate limited. The
  link declines the redirect to a custom login page and nothing more: a second
  factor still applies on `wp-login.php`, as it should.
* Changed: the nonce-refresh endpoint — which hands a fresh sign-in nonce to a
  cached login page so a visitor does not meet "Security check failed" for doing
  nothing wrong — is registered for signed-out visitors only. For someone logged
  out the nonce is generic and reveals nothing a page load would not. Its
  logged-in registration returned a nonce tied to that person's session to any
  page that could get their browser to ask, and served nobody: someone already
  signed in is not looking at a sign-in form.
* Removed: a decorative nonce on the settings tabs. The active tab was already
  read and sanitised before the nonce was checked, so the check only ever
  re-assigned the same value and the page rendered identically whether it passed
  or failed. It was not free either — nonces expire, so a bookmarked tab URL
  stopped working after a day, and a security control that does nothing is worse
  than none because the next reader counts it as protection already in place.
* Fixed: the transient key that carries a specific sign-in error is generated
  from an alphabet the reader lowercases, so it now survives the round trip.
  `wp_generate_password` includes capitals; `sanitize_key` forces lowercase, so
  the key matched only when all twenty characters happened to come out lowercase
  or numeric — about three times in a hundred thousand. Every failed sign-in
  therefore showed the generic "Invalid username or password" regardless of the
  real reason, and left an orphaned transient behind for its two-minute life.
* Added: the plugin speaks five languages. French, Spanish, Simplified Chinese,
  Japanese and Traditional Chinese (Taiwan) ship compiled. The Traditional
  Chinese was translated from English with Taiwanese WordPress terminology
  rather than converted from the Simplified characters — the vocabulary differs,
  not only the glyphs.
* Fixed: the Form Builder screen was in French on every site. Around forty of
  its labels — "Réglages rapides", "Affichage colonne", "Position des onglets" —
  had been written in French in the source itself, so no translation could
  reach them and an English site read them in French. They are English now, and
  translatable, using the same wording as the Pro screen they mirror.
* Changed: the footer of the plugin's own admin screens reports the state of
  the site instead of asking for a review. How many authentication pages are
  live, whether wp-login.php still answers, whether registration is open —
  three facts that otherwise take three screens to check, each linking to the
  screen that changes it.
* Changed: the download is a third of the size. The icon font shipped in three
  formats; browsers only ever requested one of them. WOFF2 has been universal
  since 2016, so TTF and WOFF cost 3.2 MB and no bandwidth. The package goes
  from 3.31 MB to 1.14 MB.
* Changed: translation source files (.po) stay in the repository instead of
  travelling in the package. WordPress reads only the compiled .mo at runtime,
  and the .pot a translator starts from is still included.
* Fixed: an updated site is no longer served the previous version's admin
  script. It was registered with an empty version, which WordPress replaces
  with its own, so its address stayed `admin.min.js?ver=<WordPress version>`
  through every update of the plugin, and a browser, cache plugin or CDN kept
  replaying the copy it held. That copy binds the old class of the page
  manager's buttons, so after updating, "Create Page" did nothing and reported
  nothing. Every script and stylesheet the plugin registers now carries the
  modification time of its file, which moves with each package.

* Fixed: a broken installation no longer takes the site down. The plugin loaded
  Composer's autoloader without checking it was there — the docblock above the
  line had promised that check for a long time — and the one branch meant to
  handle a failure called a function that was never defined. An upload that
  stopped halfway now switches the plugin off with a notice naming the missing
  file, dashboard included, instead of a white screen.
* Changed: ATTRUA_VERSION is derived from the plugin header. The two used to be
  maintained by hand and could disagree — the screens show the constant while
  WordPress compares the header.
* Fixed: a refused sign-in says why. attrua_handle_failed_login() read only the
  error *code* and looked it up in a small table; anything not in that table —
  which is every validation error raised by Pro, all carrying the code
  "validation_failed" — reached the form as "An unknown error occurred". A
  reCAPTCHA challenge, a password policy or a second-factor refusal now shows
  the sentence it was given. Codes the table knows keep their own wording,
  since WordPress's own messages carry markup and a "Lost your password?" link
  that does not belong on this form.
* Changed: the admin screens no longer advertise the Elite plan. The
  "WooCommerce Pages" rows in the page manager and the Elite card of the
  "Unlock More with Attributes User Access" section are held back for 2.0.0 —
  they promised a tier that does not ship yet. Nothing was deleted: both hang
  from one switch in Admin (SHOW_ELITE_PROMOTION) and come back together. The
  Pro half of that section is not held back with them: it points at a plugin
  that exists, so it still appears on a site running Core alone.

Everything else in this release is on the Pro side; see its changelog.

* Changed: the four Elementor widgets — Login, Registration, Lost Password,
  Reset Password — are now one widget, "Attributes Login Form", with a Form Type
  control at the top of its panel. The controls under it follow that choice:
  Remember Me only appears for the login form, Intro Text only for the lost
  password form, and the reset form, which reads neither, is no longer offered
  settings it ignores. The four Gutenberg blocks became one block the same way.
* Changed: the widget and the block are registered whether or not the matching
  page exists in the page manager. The shortcodes behind them never were
  conditioned on it — a site that had not created a "Login page" could write
  [attributes_login_form] anywhere but could not find the widget that does the
  same thing.
* Removed: the widgets attrua_login, attrua_lost, attrua_reset and
  attrua_register, and the blocks attrua/login, attrua/lost, attrua/reset and
  attrua/register. A page built with one of them loses it — insert "Attributes
  Login Form" and pick the form. The four shortcodes are untouched.
* Added: the block can be styled properly. Forty-two settings across eight
  panels — layout, container, labels, fields, submit button, links, messages —
  with real colour pickers offering the theme's own palette, where the block
  used to ask for hex codes to be typed into text boxes. Six presets give a
  starting point, and anything set by hand wins over the preset. A setting left
  alone emits no CSS at all, so the theme keeps showing through wherever
  nothing was asked for.
* Added: the field labels and the submit button of each form can be reworded
  from the widget, each shown only for the form that carries it. The
  shortcodes have accepted these as attributes for a long time; the widget had
  no way to reach them. Each control starts empty and shows the current
  wording as a hint rather than a value, so a translated site stays translated
  until someone types over it.
* Changed: the "passwords do not match" check runs only when the form asked
  for a confirmation. It compared the password against an empty string as soon
  as a form stopped showing the second field, which made registering
  impossible on such a form. Nothing is weakened: the confirmation guards
  against a typo by the person registering, who supplies both values either
  way, and the password policy still applies.
* Added: the destination after a successful sign-in can be picked from the
  site's own pages, in the block and in the Elementor widget both. It was a
  free-text URL field: the address had to be typed, and typing it is how it
  gets typed wrong. A widget that already had a URL keeps it.
* Changed: the panels, the block's attributes and the CSS that applies them are
  now one table (src/Blocks/FormStyle.php) rather than three lists in three
  files, which is what let a control exist that the renderer ignored. Pro's
  block styles its own templates through the same table.
* Fixed: the widget's Max Width setting caps the form at any value. The form
  wrapper carried `min-width: 380px`, and CSS lets a minimum win over a maximum,
  so every width at or below 380px was silently ignored. The wrapper now fills
  its column, and Max Width is the only thing that narrows it.


= 1.3.2 (June 26, 2026) =
* Feature: Added "Rafraîchir la page après sauvegarde" toggle in Form Builder Configurations panel
* Enhancement: reload_after_save stored in attrua_form_builder_options[{target}] alongside other flow settings
* Enhancement: Sanitized as boolean in sanitize_form_builder_settings() — safe fallback to false when unset

= 1.3.1 (May 26, 2026) =
* Developer: Documented three registration extension points used by Pro add-ons (attrua_validate_registration, attrua_registration_user_data, attrua_user_registered)
* Developer: Documented registration shortcode parameters and AJAX availability hooks in README

= 1.3.0 (March 30, 2026) =
* Feature: Lost password, reset password, and registration forms integrated as core (no Pro required)
* Feature: Admin Page Management table now includes Lost Password, Reset Password, and Register rows
* Feature: Redirect toggle for lost/reset/register now shows correct native WordPress URLs
* Feature: Register row is visually disabled (with badge) when "Anyone can register" is off
* Enhancement: Native WordPress URLs stripped of protocol in redirect column display
* Enhancement: Redirect URL display uses left-side ellipsis for long URLs
* Enhancement: Register row hides shortcode copy button, action buttons, and redirect toggle when registration is disabled
* Fix: attrua-redirect-toggle input properly hidden (position absolute, zero dimensions)

= 1.2.3 (March 20, 2026) =
* Fix: render_page_row now correctly accepts optional $page_id and $options from Pro callbacks
* Fix: settings->get('pages') bug in handle_create_page replaced with direct get_option call
* Fix: add_post_state now displays page type in post state label (e.g. "Attributes Login Page")
* Security: handle_delete_page now verifies the target page is managed by Attributes before deletion
* Enhancement: AJAX create-page response now includes wp_url for immediate redirect toggle display
* Enhancement: Added <tbody> wrapper in admin settings table for valid HTML
* Cleanup: Removed dead $wp_filter debug loop from get_page_defaults()

= 1.2.2 (February 10, 2026) =
* Security: Removed PHP sessions in favor of WordPress transients (WordPress.org compliance)
* Security: Enhanced transient-based error message handling with automatic expiration
* Security: Improved nonce verification and security implementation
* Enhancement: Added quick Settings link in plugins list page
* Enhancement: Added Documentation and Support links in plugin row meta
* Enhancement: One-time use error messages prevent replay issues
* Enhancement: Error messages now expire after 2 minutes
* Enhancement: Better compatibility with load-balanced environments
* Enhancement: Improved cache plugin compatibility
* Developer: Added attrua_action_links filter for plugin action links
* Developer: Added attrua_row_meta filter for plugin row meta links
* Documentation: Updated NONCE-FIX-SOLUTION.md with implementation status
* Documentation: Enhanced code documentation and inline comments
* Documentation: Added WordPress.org compliance checklist

= 1.2.1 (December 15, 2025) =
* Fix: Regenerated all minified assets from original sources
* Fix: Improved asset loading consistency across admin and frontend
* Fix: Added smart asset path resolution with fallback system
* Fix: Resolved missing admin.min.js file causing asset loading issues
* Enhancement: Optimized file sizes for better performance
* Enhancement: Enhanced production deployment readiness

= 1.2.0 (September 17, 2025) =
* Enhancement: Improved plugin performance and stability
* Enhancement: Optimized codebase for better security
* Enhancement: Enhanced production readiness
* Update: Comprehensive documentation updates
* Update: Improved user experience and reliability

= 1.1.0 =
* Enhancement: Added template override system for themes
* Enhancement: Improved security with better nonce validation
* Enhancement: Added custom logout handling endpoint
* Feature: New Extension Manager for add-on support
* Feature: Enhanced settings management with dot notation
* Feature: Added password visibility toggle
* Feature: Improved admin interface with notifications
* Feature: Added shortcode copying functionality
* Improvement: Better accessibility with ARIA support
* Improvement: Added dark mode support
* Improvement: Enhanced responsive design
* Improvement: Better error handling and user feedback

= 1.0.0 =
* Initial release
* Custom login page generation
* Role-based redirection system
* Basic shortcode functionality
* Core authentication features
* Developer hooks and filters
* Template system foundation
