# Changelog

All notable changes to Limesnip Simple2FA will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [1.3.3] - 2026-05-21

### Changed
- Removed the `plugin_action_links_*` filter (`hide_deactivate_link()`) and its method from `Limesnip_Simple2FA`, restoring the default Deactivate and Delete links on the Plugins page. The original v1.2.4 lockout was overly cautious — site admins should be able to manage the plugin like any other.

## [1.3.2] - 2026-05-21

### Fixed
- Added `/* translators: ... */` comments above every internationalized string that uses a `%s` / `%d` placeholder — 10 previously-uncommented strings across `class-admin-settings.php`, `class-email-handler.php`, `templates/verify-form.php`, and `templates/email-html.php`. Resolves `WordPress.WP.I18n.MissingTranslatorsComment` notices flagged by Plugin Check, preventing failures in the upcoming WordPress.org automated PC scan
- "Tested up to" bumped to `7.0` in `readme.txt` for WordPress 7.0 compatibility

## [1.3.1] - 2026-05-17

### Changed
- Verification screen aligned to the top of the viewport (`align-items: flex-start` + `padding-top: 8vh`) so the card sits at the same vertical position as the standard WordPress login form
- Verification screen background changed from `#f5f5f5` to `#f0f0f1` to match the standard WordPress login screen background
- Verification digits set to `font-weight: 900 !important` for stronger visual weight in the input boxes
- Remember-device duration converted from a free-text number input to a fixed `<select>` allowing only 7, 14, or 30 days; sanitizer now uses an `in_array()` allowlist against `[7, 14, 30]`
- Default `remember_duration` changed from `30` to `14` (applied only on first install)
- Footer line on the settings page reduced to "Limesnip Simple2FA v{version}" — the author link to limesnip.com was removed

### Fixed
- Eliminated the layout shift that appeared after the last digit was typed: the `.limesnip-simple2fa-loading` row now uses `visibility: hidden` (with `min-height: 24px`) instead of `display: none`, so the "Verifying…" row's height is reserved in the layout from the moment the form renders

## [1.3.0] - 2026-04-21

### Added
- Full-page loading overlay shown after successful verification so users get clear visual feedback that their code was accepted while the dashboard loads (handles variable WordPress load times across sites with many plugins)
- `verified` state on digit inputs — grayed out and disabled once the code is accepted, reinforcing the "accepted" cue alongside the overlay
- Auto-redirect to the plugin settings page on first activation via a 30-second `limesnip_simple2fa_activation_redirect` transient; skipped on bulk `activate-multi` and for users without `manage_options`
- `Editor` role included in the default `enforced_roles` array alongside `administrator`
- `get_site_logo_url()` helper — pulls the site logo set in the Customizer (`get_theme_mod('custom_logo')` + `wp_get_attachment_image_url()`) and assigns it as the plugin's default logo on first activation (and on reactivation if no plugin logo is currently set)

### Changed
- `activate()` now branches between first-time install (store defaults) and reactivation (backfill logo only if empty)

## [1.2.8] - 2026-04-13

### Fixed
- Replaced `wp_create_nonce()` / `wp_verify_nonce()` on the 2FA page with a transient-stored random token compared via `hash_equals()` — eliminates all `wp_set_current_user()` calls from the 2FA flow, fixing the PHP 8.x deprecation notices (`strpos null`, `str_replace null`) and the redirect loop that was preventing the verification screen from loading

## [1.2.7] - 2026-04-13

### Fixed
- Added nonce to the 2FA page redirect URL in `intercept_login()` — created after `wp_set_current_user(0)` so it matches the anonymous context `wp_verify_nonce()` checks on the next request
- Added `wp_verify_nonce()` check at the top of `handle_2fa_page()` before reading any `$_GET` input, as required by WordPress.org
- Removed `rawurldecode()` from `$_GET['redirect_to']` — PHP already URL-decodes `$_GET` values; calling it again was a double-decode that could bypass sanitization
- Replaced remaining `sanitize_url()` calls with `esc_url_raw()` for internal URL handling
- Sanitized `$_POST['remember_device']` with `sanitize_text_field()` before comparison

## [1.2.6] - 2026-04-12

### Changed
- Restored Plugin URI to https://limesnip.com (separate from Author URI https://mdesign.co.il)

## [1.2.5] - 2026-04-12

### Changed
- Author updated to "Limesnip by mDesign" with Author URI https://mdesign.co.il to clarify brand ownership for WordPress.org review
- Removed `load_plugin_textdomain()` call — no longer needed for WordPress.org-hosted plugins since WordPress 4.6

## [1.2.4] - 2026-04-05

### Added
- Deactivate and Delete action links are now hidden on the Plugins page to prevent accidental disabling of the plugin

## [1.2.3] - 2026-03-28

### Fixed
- Removed `Author URI` from plugin header to resolve plugin/author URI conflict flagged by WordPress.org submission validator

## [1.2.2] - 2026-03-28

### Fixed
- Plugin name changed from "Limesnip Simple2FA for WordPress" to "Limesnip Simple2FA" to comply with WordPress.org naming policy (the term "WordPress" is not permitted in plugin display names)

## [1.2.1] - 2026-03-28

### Fixed
- License header corrected from `GPL v2 or later` to `GPLv2 or later` (exact string WordPress.org expects)
- `Contributors` field in `readme.txt` updated to the registered WordPress.org username (`mhason`)
- `Tested up to` bumped to 6.9
- Two inaccurate feature bullets removed from `readme.txt` Description (email template editor and screen designer were removed in v1.0.2)
- FAQ answers for email and screen customization rewritten to reflect current settings

## [1.2.0] - 2026-03-28

### Changed
- Plugin rebranded to **Limesnip Simple2FA** by Limesnip Studios
- Plugin slug changed from `wp-simple2fa` to `limesnip-simple2fa` — installs as a new plugin alongside any existing installation
- All internal identifiers updated: PHP constants, class names, DB option keys, user meta keys, transient keys, cookie name, AJAX action names, nonces, script handles, and CSS class names

## [1.1.2] - 2026-03-28

### Added
- French (`fr_FR`) translation

### Fixed
- RTL language support: HTML emails now carry `dir` and `lang` attributes, and text paragraphs carry explicit `direction` styles so punctuation renders on the correct side in Hebrew, Arabic, and other RTL locales
- Verification digit inputs now carry `direction: ltr` in CSS so the digit order is never reversed by a RTL page layout — the code always reads left-to-right regardless of locale
- "Remember for" was mistranslated in French (`"N'oubliez pas de"`) and German (`"Denken Sie daran, dass"`) — both corrected (`"Mémoriser pendant"` / `"Merken für"`)
- All affected `.mo` files recompiled

## [1.1.1] - 2026-03-26

### Added
- Hebrew (`he_IL`) and German (`de_DE`) translations

### Fixed
- Translation files renamed to include the required `limesnip-simple2fa-` prefix so WordPress loads them correctly
- `Sending&hellip;` HTML entity replaced with the literal `…` character so it renders correctly via JavaScript's `.text()`
- `.mo` binary files recompiled from corrected `.po` sources

## [1.1.0] - 2026-03-26

### Added
- Full internationalization (i18n) support — all user-facing strings in PHP and JavaScript are now translatable
- `languages/limesnip-simple2fa.pot` master translation template included for translators
- JavaScript strings (countdown timer, resend cooldown, error messages) passed through `wp_localize_script` so they are translated server-side before reaching the browser
- `load_plugin_textdomain()` registered on `plugins_loaded` to load `.mo` translation files from the `languages/` folder

## [1.0.3] - 2026-03-26

### Fixed
- Digit inputs on the verification screen now use `!important` CSS overrides to prevent theme stylesheets from clipping or overflowing the digit characters

## [1.0.2] - 2026-03-26

### Added
- Shared logo upload in General settings — used on both the verification screen and in emails, replacing the site name
- Verification emails now greet the user by first name, falling back to display name if first name is not set

### Changed
- Removed email customization editor (no longer needed)
- Removed 2FA screen design customization (colors, CSS editor)
- Settings page simplified to a single General tab
- Resend code button now shows a live 60-second countdown (e.g. "Resend code (58s)") before re-enabling
- Fixed digit input padding on the verification screen to prevent text clipping

## [1.0.1] - 2026-03-25

### Added
- Test email tool in General settings — send a real verification email to any address to confirm deliverability and preview the template

### Changed
- Plugin URI updated to https://limesnip.com

## [1.0.0] - 2026-03-25

### Added
- Email-based two-factor authentication for WordPress login
- 6-digit verification code sent to user's registered email
- Linear-inspired verification screen with auto-advancing digit inputs
- Auto-submit on last digit entry (no submit button needed)
- Paste support for verification codes
- Configurable enforced roles (select which user roles require 2FA)
- Configurable code expiration time (1-60 minutes)
- Configurable max verification attempts
- Optional "Remember this device" feature with configurable duration
- HTML and plain text email format options
- Customizable email subject with template tags
- Custom email template editor with CodeMirror, preview, and template tags
- Custom 2FA screen designer with logo upload, color pickers, and CSS editor
- Rate-limited code resend (60-second cooldown)
- Secure code storage (SHA-256 hashed with salt)
- Countdown timer showing code expiration
- Responsive design for mobile devices
- Clean uninstall removes all plugin data
- Settings link on the plugins page
