=== BSM Magic Login ===
Contributors: bsmstrategy
Tags: magic link, passwordless, login, sms, otp, security, authentication
Requires at least: 6.4
Requires PHP: 8.0
Stable tag: 1.0.45
License: GPLv2 or later

Secure passwordless email magic-link and SMS one-time-code authentication for WordPress.

== Installation ==
1. Upload and activate BSM Magic Login.
2. Configure Magic Login > Settings for email magic links.
3. Configure Magic Login > SMS Providers and add/test a provider connection.
4. Configure Magic Login > SMS Login and enable SMS authentication.
5. Add a verified mobile number to eligible WordPress user profiles.
6. Add [bsm_magic_login] to the member login page.

== SMS Providers ==
* Plivo
* Twilio
* Telnyx
* AWS SNS
* Bird / MessageBird
* Provider connections can be added, edited, enabled/disabled, set as default, duplicated, tested, and deleted.
* Provider secrets are encrypted at rest using the site's WordPress security keys.

== SMS Security ==
* Cryptographically randomized six-digit OTP.
* Five-minute default expiration, configurable from 2-15 minutes.
* Single-use codes; requesting a new code supersedes previous outstanding codes.
* Five attempts per code by default.
* 60-second resend cooldown.
* Per-member and per-IP hourly limits.
* OTP values are never written to the activity log or database in plaintext.
* Only verified profile mobile numbers may receive login OTPs.
* Full email/IP audit data remains available to authorized administrators.

== Email Magic-Link Security ==
* 256-bit random single-use tokens.
* Only SHA-256 token hashes are stored; raw tokens are never logged.
* 15-minute default expiration.
* Deliberate POST confirmation prevents email security scanners from consuming links via GET.
* Per-email and per-IP request limits.
* Invalid-token throttling and optional temporary automatic IP blocking.
* Manual IPv4/IPv6 and CIDR blocks.
* Newest-link-only behavior by default.
* Atomic token consumption to prevent concurrent reuse.
* Generic responses for unknown/ineligible email addresses.
* Redirect validation prevents external open redirects.

== Changelog ==

= 1.0.0-rc.10 =
* Release candidate: fail-closed provider deletion verification, stricter credential validation, and provider restoration checks.
* Retains existing AI Connection contract v1, Free/Pro licensing, and authentication methods.
* Static package and PHP syntax regression checks added to release process; live WordPress testing still required.


= 0.9.5 =
* Added contract v1 SMS provider creation (disabled by default), credential rotation and deletion of inactive providers.
* Added lifecycle checkpoints, verification and rollback; credential fields remain excluded from read responses.
* Provider deletion requires the provider to be disabled and not the default.


= 0.9.4 =
* Fixed AI provider-default rollback to restore all affected provider states.
* Fail closed rather than persist plaintext-equivalent credentials when encryption is unavailable.
* Hardened provider default database failure handling.


= 0.9.3 =
* Added AI Connection contract v1 reversible role-policy, strong-auth, SMS settings and existing-provider configuration updates.
* Added non-secret security diagnostics and safeguards against administrator step-up lockout.
* All mutating operations declare risk, scope, checkpoint, verify and rollback.


= 0.9.2 =
* Added reversible AI security-policy updates with checkpoint, verify and rollback.
* Preserved existing BSM UX alignment and read-only diagnostics.

= 0.2.0 =
* Added SMS passwordless login using randomized six-digit one-time codes.
* Added configurable 5-minute OTP lifetime, attempt limit, resend cooldown, per-member limit, and per-IP limit.
* Added Plivo, Twilio, Telnyx, AWS SNS, and Bird / MessageBird provider adapters.
* Added SMS Provider manager with Add, Edit, Delete, Enable/Disable, Set Default, Duplicate, and Test actions.
* Added provider-specific connection fields that change based on provider type.
* Added encrypted-at-rest storage for provider credentials.
* Added WordPress user-profile mobile phone and verified-for-SMS-login fields.
* Added SMS request, send, code validation, expiration, lockout, and successful-login audit events.
* Preserved full administrator-visible email and IP addresses in audit records.
* OTP values are never stored or logged in plaintext.

= 0.1.0 =
* Initial release.
* Magic-link request, email, click, expiration, and authentication flow.
* Activity logging with full member email and IP address for authorized administrators.
* Search/filter activity by email, IP, and event.
* Manual and automatic IP blocking.
* Configurable link lifetime, cooldown, hourly limits, allowed roles, redirect, and email copy.

== Changelog ==

= 0.9.5 =
* Added contract v1 SMS provider creation (disabled by default), credential rotation and deletion of inactive providers.
* Added lifecycle checkpoints, verification and rollback; credential fields remain excluded from read responses.
* Provider deletion requires the provider to be disabled and not the default.


= 0.9.4 =
* Fixed AI provider-default rollback to restore all affected provider states.
* Fail closed rather than persist plaintext-equivalent credentials when encryption is unavailable.
* Hardened provider default database failure handling.


= 0.9.3 =
* Added AI Connection contract v1 reversible role-policy, strong-auth, SMS settings and existing-provider configuration updates.
* Added non-secret security diagnostics and safeguards against administrator step-up lockout.
* All mutating operations declare risk, scope, checkpoint, verify and rollback.


= 0.9.2 =
* Added reversible AI security-policy updates with checkpoint, verify and rollback.
* Preserved existing BSM UX alignment and read-only diagnostics.


= 0.2.2 =
* Added automatic updates through BSM Strategy Plugin Release Manager.
* Added update metadata, version checks, package delivery, plugin-information modal, product, documentation, and support links.
* Free and Pro installations both receive plugin maintenance and security updates; Pro licensing continues to control Pro feature entitlements only.
* Restricted automatic-update packages to HTTPS downloads from bsmstrategy.com and the BSM plugin-download path.

= 0.3.0 =
* Added Account Security controls for passwordless authentication.
* Added self-service mobile-number verification for Pro users.
* Added [bsm_magic_login_security] member security shortcode.
* Added member and administrator credential/session revocation.
* Added global Email and SMS authentication switches.
* Added wp-config.php emergency kill switches for all/email/SMS Magic Login methods.
* Added Pro role-based passwordless authentication policies.
* Added optional passwordless authentication UI on wp-login.php.
* Changing a mobile number requires verification before it can be used for SMS login.


== Changelog ==

= 0.9.5 =
* Added contract v1 SMS provider creation (disabled by default), credential rotation and deletion of inactive providers.
* Added lifecycle checkpoints, verification and rollback; credential fields remain excluded from read responses.
* Provider deletion requires the provider to be disabled and not the default.


= 0.9.4 =
* Fixed AI provider-default rollback to restore all affected provider states.
* Fail closed rather than persist plaintext-equivalent credentials when encryption is unavailable.
* Hardened provider default database failure handling.


= 0.9.3 =
* Added AI Connection contract v1 reversible role-policy, strong-auth, SMS settings and existing-provider configuration updates.
* Added non-secret security diagnostics and safeguards against administrator step-up lockout.
* All mutating operations declare risk, scope, checkpoint, verify and rollback.


= 0.9.2 =
* Added reversible AI security-policy updates with checkpoint, verify and rollback.
* Preserved existing BSM UX alignment and read-only diagnostics.


= 0.4.0 =
* Added Pro WooCommerce passwordless login and My Account integration.
* Added signed outbound authentication webhooks with selectable events and test delivery.
* Added Pro authentication analytics with 1/7/30-day views and CSV export.
* Expanded email template controls with button text, footer, From name, and Reply-To.
* Added a canonical internal authentication event hook for integrations.
* Preserved BSM updater, licensing, SMS, account-security, and IP protection behavior.


= 0.5.0 =
* Added SMS provider health state and operational diagnostics.
* Added conservative provider failover for transport, timeout, HTTP 429, and HTTP 5xx failures.
* Added configurable maximum fallback providers.
* Added provider success/failure timestamps and consecutive-failure tracking.
* Provider selection now prefers healthy enabled connections while preserving the configured default.
* Delivery failures caused by recipient/configuration errors do not cascade across providers.

== 0.6.0 ==
* Added WebAuthn/passkey registration and authentication (Pro).
* Added risk scoring for new IP, new browser signature, recent failures, and privileged roles.
* Added optional passkey step-up after high-risk email/SMS authentication.
* Added optional mandatory passkey step-up for selected privileged roles.
* Added passkey management to My Login Security.

== 0.7.0 ==
* Added versioned database/schema migrations that run independently of activation.
* Added multisite-aware activation and provisioning for newly created sites.
* Added WordPress personal-data exporter for Magic Login authentication activity and profile data.
* Added WordPress personal-data eraser that removes credentials and anonymizes retained audit history.
* Added Data & Privacy administration screen.
* Added explicit uninstall data-retention control; destructive cleanup is off by default.
* Added uninstall cleanup for plugin tables, settings, user metadata, and administrator capability when explicitly enabled.
* Added accessibility focus and minimum control-target hardening for front-end authentication controls.
* Preserves all 0.6.0 email, SMS, provider failover, passkey, risk-aware, WooCommerce, webhook, analytics, licensing, and updater functionality.

== 0.8.0 ==
* Added one-time emergency recovery codes for passkey step-up (Pro).
* Recovery codes are stored only as keyed hashes and are shown only once after generation.
* Added recovery-code fallback to high-risk and privileged-role step-up challenges.
* Added Security Health diagnostics for HTTPS, WordPress cron, OpenSSL, security salts, required database tables, and privileged-user recovery readiness.
* Added lockout prevention: administrators cannot enable mandatory privileged-role step-up for their own role unless they have a registered passkey or recovery codes.
* Added administrator warnings when privileged users lack both a passkey and recovery codes.
* Preserved wp-config.php emergency disable controls and all 0.7.0 privacy, migration, multisite, authentication, licensing, and updater functionality.


== 0.9.0 ==
* Pre-1.0 security hardening and regression-focused release.
* Requires WebAuthn user verification for passkey registration and authentication.
* Adds recovery-code attempt limits and challenge lockout.
* Restricts saved privileged-role policies to roles that actually exist on the site.
* Reduces passkey account-enumeration detail in public authentication responses.
* Advances the versioned database schema to 0.9.0.

= 1.0.0-rc.10 =
* Accept WordPress username or email for magic-link and passkey login.
* Normalize known accounts to canonical user IDs for shared magic-link request limits.
* Preserve generic login response to limit account enumeration.


== Emergency native login ==
Open /wp-login.php?login=normal to show the standard WordPress username/password login screen without the BSM unified login presentation. This request-only option does not disable security protections, SSO enforcement policies, or the plugin elsewhere. Keep a separate administrator session open while testing.

== 1.0.27 ==
* Restored IP Blocks admin callback and block management view.
* Corrected invalid nested authentication form markup and password form submission path.
* Improved native login control placement and link lifetime default handling.
* Emergency native login remains available at /wp-login.php?login=normal.

== 1.0.28 ==
* Prevent inactive magic-link email controls from blocking native password submission.
* Explicitly submit through the native WordPress login form and its submit control.
* Improve Remember Me discovery and native submit visibility.
* Emergency recovery: /wp-login.php?login=normal uses the native WordPress login presentation. Bookmark this URL; it does not bypass authentication or SSO policy.

== 1.0.30 ==
* Show an accessible confirmation on the unified login screen after requesting an email link.
* Preserve WordPress redirect_to when issuing a magic link, and store it with the request.
* Use the WordPress administration dashboard as the fallback when no explicit or configured destination exists.
* Emergency recovery remains /wp-login.php?login=normal (native WordPress login).


== Passkey enrollment from login ==
Click Sign in with a passkey. If no credential is available, select Create a passkey, verify your existing account using password or email link, and select Create a passkey after signing in. You can choose Not now. Registration requires HTTPS and browser/device approval. Existing credentials and account security requirements remain in force.

Emergency native WordPress login: /wp-login.php?login=normal (bypasses BSM presentation only, not authentication or security policies).

== Email six-digit codes (v1.0.31) ==
Go to Magic Login > Settings > Email Authentication & Templates. Select Magic link only, Six-digit code only, or Allow both, then Save. With both enabled, choose the preferred method. Existing sites remain on magic links by default. Email codes expire after five minutes and can be used once. If locked out, use /wp-login.php?login=normal for native recovery, subject to existing security policies.


== Version 1.0.35 ==
Passkey sign-in now invokes WebAuthn directly from the visible login button, with visible error and enrollment guidance. An administrator may enable a temporary sign-in pause link under Magic Login > Settings > Email Authentication & Templates. The link is off by default, requires an explicit confirmation, and pauses NEW account sign-ins for the configured duration; existing sessions remain active. Recovery presentation remains at /wp-login.php?login=normal, but that URL does not bypass a temporary account pause.

Security note: disable click tracking for authentication and security emails in your mail provider, including WP Mail SMTP, so sensitive authentication links are not rewritten through tracking endpoints.


== 1.0.35 ==
* Fixed fatal error when malformed or legacy passkey metadata contains strings instead of credential arrays.
* Validates AJAX email and step-up fields before use.
* Returns controlled JSON for accounts without usable passkeys.
* Displays a readable error when a server failure returns non-JSON HTML.
* Existing credentials are retained; malformed entries are ignored, not deleted.
* Emergency native WordPress login: /wp-login.php?login=normal
* Live browser and WordPress integration tests are still required.

= 1.0.37 =
* Security activity modes: Off, Essential, Full.
* Configurable retention: 30, 60, 90, 120, 180, 365 days.
* User profile: latest four retained security events.
* Activity filters: username, email, IP, event, result, UTC date range; sortable results and server-side pagination.
* Confirmed purge of retained audit records.
* Security controls continue to operate when audit writes are disabled.

= 1.0.39 =
* Standardized login notice severity: blue information, amber warnings, red errors, green success.
* Corrected expired/invalid link notices and first-time passkey guidance colors.

== Version 1.0.41 administration ==
Install the ZIP from Plugins > Add New > Upload Plugin and replace the existing BSM Magic Login version when prompted. The internal folder remains bsm-magic-login. Back up the database first. Existing settings and passkeys are retained.

Overview, Activity, Login Methods, Security, Analytics, Integrations, and License are the main menu screens. SMS settings and providers are under Login Methods > SMS. Passkey registration is under Login Methods > Passkeys; risk-based security policies are also available under Security. Setup Wizard is presented during initial setup; completed sites can revisit its direct page when reconfiguration is required.

Magic-link and email-code messages include a unique request reference in the subject and body to reduce Gmail threading. Request references are not authentication secrets. SMTP services may override mail headers; verify message grouping with your actual provider.

Analytics plots daily event counts in UTC, using the existing activity database. Charts depend on activity logging and retention settings. Choose 7/30/90 days, toggle series, hover/focus on points, or open the accessible data table. CSV export remains available.

Emergency WordPress login: /wp-login.php?login=normal

== Version 1.0.43 ==
BSM Magic Login v1.0.43

- Updated the WordPress administration menu label to BSM Magic Login.
- Today analytics now displays hourly activity in the WordPress site timezone.
- Seven-, thirty-, and ninety-day analytics remain daily.
- Chart event-count axes use whole-number labels.
- Chart tooltips appear beside the pointer and stay inside the chart area.
- Keyboard focus also reveals chart values.
- Analytics table and CSV now use the selected chart aggregation and timezone.

Upgrade: Install the ZIP over your existing BSM Magic Login installation. Existing settings and authentication data are retained.


== Emergency recovery (keep outside WordPress) ==
If locked out, use SFTP, SSH, or the hosting file manager to back up and edit wp-config.php. Insert one of the following before the WordPress stop-editing comment:

Restore native WordPress login / disable all BSM Magic Login methods:
    define('BSMML_DISABLE_ALL', true);

Disable email magic links:
    define('BSMML_DISABLE_EMAIL', true);

Disable SMS login:
    define('BSMML_DISABLE_SMS', true);

Test wp-login.php in a separate private browser session. Other plugins or hosting settings can still block native login. Once resolved, remove the temporary constant and test all intended login methods. Never delete accounts, passkeys, or plugin tables to recover access.

Save the included EMERGENCY-RECOVERY.txt file outside WordPress before an incident. Security Health also offers an administrator-only email and download action. Email acceptance does not guarantee inbox delivery. BSM product support handles plugin behavior; hosting support handles server file access and outages. Do not send credentials or authentication secrets in support reports.
