### Correct Upgrade Documentation Structure (Markdown) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/integration-boundaries.md Provides a structured example of an upgrade guide section detailing breaking changes and new features for consumers. ```markdown ## Upgrading from 2.x to 3.x ### Breaking Changes 1. **LoginController@login method signature** - Old: `login(Request $request)` - New: `login(array $credentials, bool $remember)` - Migration: Controllers extending LoginController must update their method signature. 2. **Route name changes** - Old: `tyro-login.otp.form` - New: `tyro-login.otp.verify` - Migration: Update all `route()` and `redirect()->route()` calls. ### New Features - 2FA ignore cookie (disabled by default). - Config: `tyro-login.two_factor.ignore_days`. ### Deprecated (removed in 4.0) - `VerificationHelper::oldGenerateVerificationUrl()`. ``` -------------------------------- ### Run Tyro Login Installation Command Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Execute the Artisan command to install the package. ```bash php artisan tyro-login:install ``` -------------------------------- ### Install Tyro Login Package Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Install the package using Composer. ```bash composer require hasinhayder/tyro-login ``` -------------------------------- ### Correct Multi-Agent Installation with Universal Directory Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/commands.md This code demonstrates the correct approach by installing the skill to both individual agent directories and a universal directory. This ensures the skill is discoverable by any agent. ```php // Agent-specific + universal — any agent can discover the skill protected array $agentTargets = [ 'kilo' => '.kilo/skills/tyro-login', 'claude' => '.claude/skills/tyro-login', 'github copilot' => '.github/skills/tyro-login', 'codex' => '.codex/skills/tyro-login', 'gemini' => '.gemini/skills/tyro-login', 'laravel boost' => '.ai/skills/tyro-login', ]; public const UNIVERSAL_SKILL_DIR = '.agents/skills/tyro-login'; // Phase 1: install to each selected agent's directory foreach ($selectedAgents as $agent) { $this->installTo(base_path($this->agentTargets[$agent]), $sourcePath, ...); } // Phase 2: always install to universal directory $this->installTo(base_path(self::UNIVERSAL_SKILL_DIR), $sourcePath, ...); ``` -------------------------------- ### Install Tyro Login with Social Support Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Install the package with support for social login. ```bash php artisan tyro-login:install --with-social ``` -------------------------------- ### Correct Atomic Install Method Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/commands.md This method uses a staging, backup, and swap strategy for atomic installation with rollback capabilities. It ensures data integrity by first staging the new contents, backing up the existing target, and then swapping them. Rollback is handled by restoring the backup if the swap fails. ```php // Stage → backup → swap — atomic with rollback protected function installTo(string $targetPath, string $sourcePath, string $label): bool { $filesystem = new Filesystem; $staging = $targetPath.'.__installing__'; $backup = $targetPath.'.__backup__'; // Stage new contents in a temp directory $filesystem->copyDirectory($sourcePath, $staging); // Back up existing target via atomic rename @rename($targetPath, $backup); // Move staged install into place if (! @rename($staging, $targetPath)) { // Rollback — restore from backup @rename($backup, $targetPath); $filesystem->deleteDirectory($staging); return false; } // Success — discard backup $filesystem->deleteDirectory($backup); return true; } ``` -------------------------------- ### Install Tyro Login Package Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Installs the Tyro Login package and publishes its configuration files. Use the `--with-social` flag to include Laravel Socialite support. ```bash php artisan tyro-login:install ``` ```bash php artisan tyro-login:install --with-social ``` -------------------------------- ### GET for Logout (Incorrect) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md This example shows a GET request for logout, which is insecure as browser prefetching could inadvertently log the user out. State-mutating operations should not use GET. ```php // GET for logout — browser prefetching could log the user out Route::get('logout', [LoginController::class, 'logout'])->name('tyro-login.logout'); ``` -------------------------------- ### Configurable Login URIs Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md This example demonstrates how to use configuration values to define individual route paths, allowing consumers fine-grained control over URI customization. ```php // Config-driven URI paths — consumer overrides individual paths Route::get(config('tyro-login.routes.login', 'login'), ...)->name('tyro-login.login'); Route::get(config('tyro-login.routes.register', 'register'), ...)->name('tyro-login.register'); Route::get(config('tyro-login.routes.password_reset', 'password/reset'), ...)->name('tyro-login.password.request'); ``` -------------------------------- ### Confirm 2FA Setup Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/SKILL.md Confirms the setup of Two-Factor Authentication (2FA), typically with a TOTP. ```APIDOC ## POST 2fa/setup ### Description Confirms the setup of Two-Factor Authentication (2FA), often involving a Time-based One-Time Password (TOTP). ### Method POST ### Endpoint /2fa/setup ``` -------------------------------- ### Display 2FA Setup Page Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/SKILL.md Retrieves the page for setting up Two-Factor Authentication (2FA). ```APIDOC ## GET 2fa/setup ### Description Displays the page for setting up Two-Factor Authentication (2FA). ### Method GET ### Endpoint /2fa/setup ``` -------------------------------- ### Incorrect Installation to Single Directory Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/commands.md This code snippet shows an incorrect way to install a skill, as it only copies the skill to one agent's directory, making it undiscoverable by other agents. ```php // Only installs to one directory — other agents can't discover the skill $filesystem->copyDirectory($sourcePath, '.claude/skills/tyro-login'); ``` -------------------------------- ### Skip 2FA Setup Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/SKILL.md Allows the user to skip the Two-Factor Authentication (2FA) setup. ```APIDOC ## POST 2fa/skip ### Description Allows the user to skip the Two-Factor Authentication (2FA) setup process. ### Method POST ### Endpoint /2fa/skip ``` -------------------------------- ### Incorrect: Flat Configuration Keys Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/config-and-env.md This example illustrates an unmanageable configuration structure using flat keys for social provider settings. As the package grows, this approach becomes difficult to maintain and lacks organization. ```php 'social_google_enabled' => true, 'social_facebook_enabled' => true, 'social_twitter_enabled' => true, ``` -------------------------------- ### Correct Mailable with Constructor Injection Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/mailables.md This example demonstrates the correct approach using type-hinted constructor parameters for explicit dependencies, making the contract self-documenting. ```php class VerifyEmailMail extends Mailable { use Queueable, SerializesModels; public function __construct( public string $verificationUrl, public string $userName, public int $expiresInMinutes, ) {} } ``` -------------------------------- ### Namespaced Environment Variable (Correct) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/config-and-env.md This correct example demonstrates namespacing environment variables with the package prefix 'TYRO_LOGIN_' to prevent collisions and ensure predictable behavior. ```php // Namespaced with package prefix 'enabled' => (bool) env('TYRO_LOGIN_REGISTRATION_ENABLED', true), ``` -------------------------------- ### Config Key With Environment Variable and Default Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/config-and-env.md This correct example uses an environment variable with a sensible default value. Consumers can override this value per environment without modifying the config file. ```php // Env var with sensible default — consumer can override per environment 'expire' => (int) env('TYRO_LOGIN_OTP_EXPIRE', 10), ``` -------------------------------- ### Documenting Brute Force Lockout Configuration Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/config-and-env.md Shows an example of undocumented configuration versus a well-documented section for brute force lockout settings. Documentation should explain purpose, valid options, and security implications. ```php 'lockout' => [ 'max_attempts' => 5, 'duration' => 60, ], ``` ```php /* |-------------------------------------------------------------------------- | Brute Force Lockout Protection |-------------------------------------------------------------------------- | | Controls the number of failed login attempts before the user is locked | out. The duration is in minutes. Set max_attempts to 0 to disable | lockout (not recommended for production). | | show_attempts_left: When enabled, displays remaining attempts on the | login form. This helps legitimate users but also helps attackers. | Disable in production if you want to avoid leaking information. | */ 'lockout' => [ 'max_attempts' => (int) env('TYRO_LOGIN_LOCKOUT_MAX_ATTEMPTS', 5), 'duration' => (int) env('TYRO_LOGIN_LOCKOUT_DURATION', 60), 'show_attempts_left' => (bool) env('TYRO_LOGIN_SHOW_ATTEMPTS_LEFT', true), ] ``` -------------------------------- ### Tyro Login Configuration: Tyro Integration Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Enable automatic role assignment for new users when the 'hasinhayder/tyro' package is installed. Configure the default role slug. ```php 'tyro' => [ 'assign_default_role' => env('TYRO_LOGIN_ASSIGN_DEFAULT_ROLE', true), 'default_role_slug' => env('TYRO_LOGIN_DEFAULT_ROLE_SLUG', 'user'), ] ``` -------------------------------- ### Config Key Without Environment Variable Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/config-and-env.md This incorrect example shows a hardcoded configuration value. Consumers must manually edit the published config file per environment if they need to customize this value. ```php // No env var — consumer must edit config file directly 'expire' => 60, ``` -------------------------------- ### Config-Gated Registration Submission Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This correct example shows how to gate the registration submission process using a configuration setting. It aborts with a 403 error if registration is disabled, preventing bypass. ```php // Config-gated — redirects to login when disabled public function showRegistrationForm(): View|RedirectResponse { if (! config('tyro-login.registration.enabled', true)) { return redirect()->route('tyro-login.login'); } // ... show form } public function register(Request $request): RedirectResponse { if (! config('tyro-login.registration.enabled', true)) { abort(403, 'Registration is disabled.'); } // ... process registration } ``` -------------------------------- ### Run Test Suite Source: https://github.com/hasinhayder/tyro-login/blob/main/CONTRIBUTING.md Execute the project's test suite to ensure code quality and functionality before submitting changes. This command is also used during the development setup. ```bash composer test ``` -------------------------------- ### Correct Route Naming with Prefix Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md Use a namespaced prefix (e.g., 'tyro-login.') for all package routes to ensure uniqueness and prevent collisions with consuming application routes. This example demonstrates the correct approach. ```php Route::get('login', [LoginController::class, 'showLoginForm'])->name('tyro-login.login'); Route::post('login', [LoginController::class, 'login'])->name('tyro-login.login'); ``` -------------------------------- ### Correct Auto-Login with 2FA Awareness Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This snippet demonstrates the correct way to implement auto-login after registration, ensuring that if 2FA is enabled, the user is redirected to the 2FA setup flow instead of being fully authenticated. ```php // Auto-login with 2FA awareness if (config('tyro-login.registration.auto_login', true)) { if (config('tyro-login.two_factor.enabled', false)) { $request->session()->put('login.id', $user->id); $request->session()->put('login.remember', true); return redirect()->route('tyro-login.two-factor.setup'); } Auth::login($user); } return redirect(config('tyro-login.redirects.after_register', '/')); ``` -------------------------------- ### Correct Email Sending with Configurable Toggle Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/mailables.md This example implements a configuration-driven toggle for sending emails. The email is only dispatched if the corresponding configuration key is enabled, preventing unwanted dispatches. ```php // Config-driven toggle — email is only sent when enabled protected function sendOtpEmail(User $user, string $otp, int $expire): void { if (! config('tyro-login.emails.otp.enabled', true)) { return; } Mail::to($user)->send(new OtpMail($otp, $user->name, $expire)); } ``` -------------------------------- ### Incorrect Post-Registration Flow with Auto-Login Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This incorrect example shows auto-login occurring regardless of the email verification requirement, thus skipping the verification step. ```php // Auto-login regardless of verification requirement — skips verification $user = $userModel::create([...]); Auth::login($user); return redirect(config('tyro-login.redirects.after_register', '/')); ``` -------------------------------- ### Config-Gated Registration Form Display Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This correct example demonstrates how to gate the registration form display using a configuration setting. It redirects to the login page if registration is disabled. ```php // Config-gated — redirects to login when disabled public function showRegistrationForm(): View|RedirectResponse { if (! config('tyro-login.registration.enabled', true)) { return redirect()->route('tyro-login.login'); } // ... show form } ``` -------------------------------- ### Correct Post-Registration Flow with Email Verification Branching Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This correct example demonstrates branching the post-registration flow based on whether email verification is required. It handles sending verification emails and storing the user's email in the session. ```php // Branch: verification required vs auto-login if (config('tyro-login.registration.require_email_verification', false)) { VerificationController::generateVerificationUrl($user); $request->session()->put('tyro-login.verification.email', $user->email); return redirect()->route('tyro-login.verification.notice'); } // Send welcome email only when verification is NOT required if (config('tyro-login.emails.welcome.enabled', true)) { Mail::to($user->email)->send(new WelcomeMail(...)); } if (config('tyro-login.registration.auto_login', true)) { // ... handle auto-login } ``` -------------------------------- ### Configure Time-Based Two-Factor Authentication (TOTP) Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Enable and configure TOTP 2FA in the application. Control global enablement, page titles, and whether setup can be skipped. ```php 'two_factor' => [ // Enable/disable 2FA globally 'enabled' => env('TYRO_LOGIN_2FA_ENABLED', false), // Page titles and subtitles 'setup_title' => env('TYRO_LOGIN_2FA_SETUP_TITLE', 'Two Factor Authentication'), 'setup_subtitle' => env('TYRO_LOGIN_2FA_SETUP_SUBTITLE', 'Scan the QR code with your authenticator app.'), 'challenge_title' => env('TYRO_LOGIN_2FA_CHALLENGE_TITLE', 'Two Factor Authentication'), 'challenge_subtitle' => env('TYRO_LOGIN_2FA_CHALLENGE_SUBTITLE', 'Enter the code from your authenticator app.'), // Allow users to skip setup (if false, setup is mandatory) 'allow_skip' => env('TYRO_LOGIN_2FA_ALLOW_SKIP', false), ], ``` -------------------------------- ### Correct Code Example: Explicit and Maintainable Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/framework-mindset.md This snippet shows how to write clear, maintainable code using explicit types, named constants for magic numbers, and a dedicated helper method for generation. ```php // Types are explicit, intent is clear, constants are named protected const OTP_EXPIRY_MINUTES = 10; protected const OTP_LENGTH = 6; protected function generateOtp(): string { $otp = ''; for ($i = 0; $i < static::OTP_LENGTH; $i++) { $otp .= random_int(0, 9); } return $otp; } ``` -------------------------------- ### Correct User Creation with Configured Model Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md Use the configuration-driven model to ensure the correct user class is instantiated, working with any consumer setup. Defaults to 'App\Models\User' if not configured. ```php // Config-driven model — works with any consumer setup $userModel = config('tyro-login.user_model', 'App\\Models\\User'); $user = $userModel::create([ 'name' => $validated['name'], 'email' => $validated['email'], 'password' => Hash::make($validated['password']), ]); ``` -------------------------------- ### Correct Social Login Redirect (Session State) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/social-login.md This example demonstrates the correct method of storing the user's intended action in the session. This approach prevents information leakage by keeping the action invisible to external observers. ```php // Action in session — invisible to external observers public function redirect(string $provider): RedirectResponse { session()->put('tyro-login.social.action', request()->query('action', 'login')); $driver = static::PROVIDER_DRIVER_MAP[$provider] ?? $provider; return Socialite::driver($driver)->redirect(); } ``` -------------------------------- ### Correct Mailable with Configurable Subject and Fallback Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/mailables.md This example shows the correct way to define a Mailable with a configurable subject line, using a fallback value from the configuration. ```php public function build(): self { $subject = config('tyro-login.emails.verify_email.subject', 'Verify Your Email Address'); return $this->subject($subject) ->view('tyro-login::emails.verify-email'); } ``` -------------------------------- ### Correct Mailable Implementation Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/mailables.md This example demonstrates a correct, single-purpose mailable class for OTP delivery. It adheres to the single responsibility principle, uses specific type-hinted constructor parameters, and reads the email subject from configuration. ```php class OtpMail extends Mailable { use Queueable, SerializesModels; public function __construct( public string $otp, public string $userName, public int $expiresInMinutes, ) {} public function build(): self { return $this->subject( config('tyro-login.emails.otp.subject', 'Your One-Time Password') )->view('tyro-login::emails.otp'); } } ``` -------------------------------- ### Incorrect Code Example: Implicit Behavior Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/framework-mindset.md This snippet demonstrates unclear code with magic numbers and implicit operations, making it difficult to understand its purpose and context. ```php // What does this do? Why 15? What's the context? $items = collect($data)->map(function ($item) { return $item * 15; })->filter()->values(); ``` -------------------------------- ### Incorrect Backward Compatibility (New Default Applied) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/integration-boundaries.md This code applies a new default behavior to all consumers, potentially breaking existing installations that relied on the old behavior. ```php public function login(Request $request): RedirectResponse|View { if (Auth::attempt($credentials)) { $request->session()->regenerate(); // Old behavior: redirect to intended // New behavior: always redirect to dashboard — breaks existing redirects return redirect()->route('tyro-login.dashboard'); } } ``` -------------------------------- ### Correct Magic Link Token Generation Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/magic-login.md This example demonstrates generating a cryptographically secure token using `Str::random(64)`. This method ensures sufficient entropy to prevent brute-force attacks. The generated token should be stored hashed in the cache. ```php // Cryptographically secure token — sufficient entropy protected function generateMagicToken(): string { return Str::random(64); } ``` -------------------------------- ### Correct Service Provider Registration and Booting Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/service-provider.md The `register()` method should exclusively handle configuration merging. All other bootstrapping tasks, such as registering routes, views, and commands, must be performed in the `boot()` method. ```php public function register(): void { $this->mergeConfigFrom(__DIR__ . '/../../config/tyro-login.php', 'tyro-login'); } // All boot logic in boot() public function boot(): void { $this->registerRoutes(); $this->registerViews(); $this->registerMigrations(); $this->registerPublishing(); $this->registerCommands(); $this->configureAuthRedirection(); } ``` -------------------------------- ### POST-Only Logout Route Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md This example configures the logout route to accept both GET and POST, but the controller logic ensures only POST requests process the logout. GET requests redirect away or show a confirmation. ```php // POST-only for mutations — GET shows confirmation form or 405 Route::match(['get', 'post'], 'logout', [LoginController::class, 'logout'])->name('tyro-login.logout') ->middleware('auth'); ``` -------------------------------- ### Correct Service Provider Boot Order Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/service-provider.md Illustrates the strict, recommended order for registering service provider components: publishing, routes, views, commands, migrations, and auth redirection. This ensures dependencies are met. ```php public function boot(): void { $this->registerRoutes(); $this->registerViews(); $this->registerMigrations(); $this->registerPublishing(); $this->registerCommands(); $this->configureAuthRedirection(); } ``` -------------------------------- ### Correct Mailable Data Passing with `with()` Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/mailables.md This example demonstrates explicit data passing using the `with()` method, making the template contract visible in the `build()` method. It ensures all variables passed to the template are declared. ```php // Explicit data via with() — template contract is visible in build() public function build(): self { return $this->subject( config('tyro-login.emails.welcome.subject', 'Welcome!') )->view('tyro-login::emails.welcome') ->with([ 'loginUrl' => $this->loginUrl, 'userName' => $this->userName, 'currentYear' => now()->year, ]); } ``` -------------------------------- ### Add Social Login to Existing Installation Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Add social login support to an existing Tyro Login installation by installing Laravel Socialite and migrating the database. ```bash composer require laravel/socialite php artisan vendor:publish --tag=tyro-login-migrations php artisan migrate ``` -------------------------------- ### Correct Middleware Separation for Guest and Auth Routes Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md Separate guest and authenticated routes into distinct middleware groups ('guest' and 'auth') for clear separation and improved security. This example shows the correct structure. ```php // Guest group and auth group — clear separation Route::middleware(['web'])->prefix(config('tyro-login.routes.prefix', '')) ->name('tyro-login.') ->group(function () { // Guest routes — login, register, password reset, OTP, 2FA challenge Route::middleware('guest')->group(function () { Route::get('login', [LoginController::class, 'showLoginForm'])->name('login'); Route::post('login', [LoginController::class, 'login']); Route::get('register', [RegisterController::class, 'showRegistrationForm'])->name('register'); Route::post('register', [RegisterController::class, 'register']); // ... password reset, OTP, 2FA challenge, social auth, magic links }); // Authenticated routes — logout, 2FA management, recovery codes Route::middleware('auth')->group(function () { Route::match(['get', 'post'], 'logout', [LoginController::class, 'logout'])->name('logout'); Route::get('2fa/recovery-codes', [TwoFactorController::class, 'showRecoveryCodes'])->name('2fa.recovery-codes'); Route::post('2fa/setup', [TwoFactorController::class, 'confirm'])->name('2fa.confirm'); // ... etc }); }); ``` -------------------------------- ### Customize Tyro Login Route Prefix Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Configure the base URL for Tyro Login routes by setting the 'prefix' in the 'routes' configuration. This example sets the prefix to 'auth', resulting in routes like /auth/login. ```php 'routes' => [ 'prefix' => env('TYRO_LOGIN_ROUTE_PREFIX', 'auth'), // Routes will be: /auth/login, /auth/register, etc. ] ``` -------------------------------- ### Run Migrations for Invitation/Referral System Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Run migrations to set up the invitation/referral system for version 2.3.0 and later. ```bash php artisan migrate ``` -------------------------------- ### Correct HTML Email Structure with Inline Styles Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/email-templates.md This example demonstrates the correct method of applying styles directly inline to HTML elements. This ensures consistent rendering across all major email clients, as inline styles are reliably processed. ```html {{-- Inline styles — rendered by all email clients --}} Click Here ``` -------------------------------- ### Correct Backward Compatibility (Versioned Config Default) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/integration-boundaries.md This code uses versioned configuration defaults to ensure existing consumers retain old behavior while new installations adopt updated defaults, preventing unexpected changes. ```php // In config/tyro-login.php: // 'redirects' => [ // 'after_login' => env('TYRO_LOGIN_AFTER_LOGIN', 'intended'), // ], public function login(Request $request): RedirectResponse|View { if (Auth::attempt($credentials)) { $request->session()->regenerate(); $redirect = config('tyro-login.redirects.after_login', 'intended'); if ($redirect === 'intended') { return redirect()->intended(route('tyro-login.dashboard')); } return redirect()->route($redirect); } } ``` -------------------------------- ### Get Referral Count Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Use the InvitationHelper to get the number of users referred by a specific user. ```php // Get referral count for a user $count = InvitationHelper::getReferralCount($userId); ``` -------------------------------- ### Config-Driven Password Complexity Rules Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/password-policy.md This example demonstrates config-driven password complexity using Laravel's Password Rule. It allows customization of minimum length, maximum length, and complexity requirements (uppercase, lowercase, numbers, special characters) via configuration. ```php // Config-driven complexity — consumer changes config protected function getValidationRules(): array { $minLength = config('tyro-login.password.min_length', 8); $maxLength = config('tyro-login.password.max_length'); $passwordRule = Password::min($minLength); if ($maxLength) { $passwordRule = $passwordRule->max($maxLength); } $complexity = config('tyro-login.password.complexity', []); if (! empty($complexity['require_uppercase']) || ! empty($complexity['require_lowercase'])) { $passwordRule = $passwordRule->mixedCase(); } if ($complexity['require_numbers'] ?? false) { $passwordRule = $passwordRule->numbers(); } if ($complexity['require_special_chars'] ?? false) { $passwordRule = $passwordRule->symbols(); } $passwordRules = ['required', 'string', $passwordRule]; return ['password' => $passwordRules, ...]; } ``` -------------------------------- ### Incorrect GET Logout Route Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/security.md This code demonstrates an insecure logout route that uses a GET request, making it vulnerable to CSRF attacks via image sources. ```php // GET logout — no CSRF protection, vulnerable to img-src CSRF Route::get('logout', [LoginController::class, 'logout'])->name('tyro-login.logout'); public function logout(): RedirectResponse { Auth::logout(); return redirect()->route('tyro-login.login'); } ``` -------------------------------- ### Fullscreen Layout with Background Image Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Set up a fullscreen layout with a background image and a glassmorphism form overlay. The image will cover the entire screen. ```env TYRO_LOGIN_LAYOUT=fullscreen TYRO_LOGIN_BACKGROUND_IMAGE=https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=1920&q=80 ``` -------------------------------- ### Correct Command Signature with Prefix Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/commands.md Always use a package-specific prefix, such as 'tyro-login:', for command signatures to ensure uniqueness and avoid naming conflicts. ```php protected $signature = 'tyro-login:verify-user {identifier}'; ``` -------------------------------- ### Plain-Text Email Template Example Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/email-templates.md An example of a plain-text email template (`otp.blade.php`) used as a fallback for HTML emails. It includes placeholders for dynamic data like user name, OTP, and expiration time. ```html {{-- resources/views/emails/plain/otp.blade.php --}} {{ $userName }}, Your one-time password is: {{ $otp }} This code will expire in {{ $expiresInMinutes }} minutes. If you did not request this code, please ignore this email. ``` -------------------------------- ### Correct Login Route Definitions Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md This snippet demonstrates the correct approach by defining separate GET and POST routes for login. The GET route is used for displaying the login form, and the POST route is for handling form submission. ```php Route::get('login', [LoginController::class, 'showLoginForm'])->name('tyro-login.login'); Route::post('login', [LoginController::class, 'login']); ``` -------------------------------- ### Get All Referred Users Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Retrieve a list of all users who were referred by a specific user using the InvitationHelper. ```php // Get all users referred by a specific user $referredUsers = InvitationHelper::getReferredUsers($userId); ``` -------------------------------- ### Centered Layout Configuration Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Use this configuration for a simple centered form with a gradient background. No additional setup is required. ```env TYRO_LOGIN_LAYOUT=centered ``` -------------------------------- ### Incorrect Suspension Message Display Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/suspension.md This incorrect example reveals specific suspension details like duration and reason, which can aid attackers. ```php return redirect()->route('tyro-login.login') ->withErrors(['email' => __('Your account has been suspended until March 15, 2026 due to 3 failed attempts.')]); ``` -------------------------------- ### Open Tyro Login Documentation Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Opens the Tyro Login documentation in your default web browser. ```bash php artisan tyro-login:doc ``` -------------------------------- ### Incorrect API Removal Example Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/integration-boundaries.md Illustrates the consequence of removing a public API without a deprecation notice, which breaks consuming applications. ```php // Method removed without deprecation — breaks all consumers who use it // Removed in 3.0: // public function generateVerificationUrl($userId, $hash) { ... } ``` -------------------------------- ### Generic Environment Variable (Incorrect) Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/config-and-env.md This incorrect example uses a generic environment variable name that is prone to collisions with other packages or the consuming application. ```php // Too generic — likely to collide 'enabled' => env('REGISTRATION_ENABLED', true), ``` -------------------------------- ### Always Available Registration Form Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This incorrect example shows a registration form that is always available, making it impossible for the consumer to disable registration through configuration. ```php // Registration always available — consumer cannot disable public function showRegistrationForm(): View { return view('tyro-login::register'); } ``` -------------------------------- ### Hardcoded Password Complexity Rules Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/password-policy.md This example shows hardcoded password complexity rules, which are inflexible and cannot be customized by the consumer without modifying the controller code. ```php // Hardcoded complexity — consumer cannot customize $rules = [ 'password' => ['required', 'string', 'min:8', 'confirmed', 'regex:/[A-Z]/', 'regex:/[0-9]/', 'regex:/[^a-zA-Z0-9]/'], ]; ``` -------------------------------- ### Incorrect Auto-Login without 2FA Check Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/registration.md This snippet shows an incorrect implementation of auto-login after registration that bypasses the 2FA setup for new users if 2FA is enabled. ```php // Auto-login without checking 2FA — bypasses 2FA setup for new users Auth::login($user); return redirect(config('tyro-login.redirects.after_register', '/')); ``` -------------------------------- ### Incorrect Route Naming Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/routes.md Avoid generic route names like 'login' as they can collide with consuming application routes. This example shows the risk of such generic naming. ```php Route::get('login', [LoginController::class, 'showLoginForm'])->name('login'); Route::post('login', [LoginController::class, 'login'])->name('login'); ``` -------------------------------- ### Incorrect Service Provider Boot Order Source: https://github.com/hasinhayder/tyro-login/blob/main/skills/tyro-login/rules/service-provider.md Demonstrates an arbitrary order of operations in the boot() method, which can lead to unpredictable upgrades. This order registers publishing and commands before routes and views. ```php public function boot(): void { $this->registerPublishing(); $this->registerCommands(); $this->registerRoutes(); $this->registerViews(); } ``` -------------------------------- ### Tyro Login Configuration: Layout Options Source: https://github.com/hasinhayder/tyro-login/blob/main/README.md Configure the visual layout for the login pages. Available options include 'centered', 'split-left', 'split-right', 'fullscreen', 'card', 'youtube-video', 'animated-birds', 'aurora-waves', 'particle-network', 'tidal'. ```php 'layout' => env('TYRO_LOGIN_LAYOUT', 'centered'), 'background_image' => env('TYRO_LOGIN_BACKGROUND_IMAGE', 'https://...'), 'youtube_video' => [ 'url' => env('TYRO_LOGIN_YOUTUBE_URL', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'), 'blur' => env('TYRO_LOGIN_VIDEO_BLUR', '4px'), 'overlay_color' => env('TYRO_LOGIN_VIDEO_OVERLAY_COLOR', '#111827'), 'overlay_opacity' => env('TYRO_LOGIN_VIDEO_OVERLAY_OPACITY', 0.1), 'sound' => env('TYRO_LOGIN_VIDEO_SOUND', false), ] ```