Output:
Chunk ID: af2260
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 5193
Output:
routes/settings.php
<?php

use App\Livewire\Settings\Appearance;
use App\Livewire\Settings\Password;
use App\Livewire\Settings\Profile;
use App\Livewire\Settings\TwoFactor;
use Illuminate\Support\Facades\Route;
use Laravel\Fortify\Features;

Route::middleware(['auth'])->group(function () {
    Route::redirect('settings', 'settings/profile');

    Route::livewire('settings/profile', Profile::class)->name('profile.edit');
});

Route::middleware(['auth', 'verified'])->group(function () {
    Route::livewire('settings/password', Password::class)->name('user-password.edit');
    Route::livewire('settings/appearance', Appearance::class)->name('appearance.edit');

    Route::livewire('settings/two-factor', TwoFactor::class)
        ->middleware(
            when(
                Features::canManageTwoFactorAuthentication()
                && Features::optionEnabled(Features::twoFactorAuthentication(), 'confirmPassword'),
                ['password.confirm'],
                [],
            ),
        )
        ->name('two-factor.show');
});
routes/console.php
<?php

use App\Jobs\AggregateAnalytics;
use App\Jobs\CancelUnpaidBankTransferOrders;
use App\Jobs\CleanupAbandonedCarts;
use App\Jobs\ExpireAbandonedCheckouts;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;

Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

Schedule::job(new ExpireAbandonedCheckouts)->everyFifteenMinutes();
Schedule::job(new CleanupAbandonedCarts)->daily();
Schedule::job(new CancelUnpaidBankTransferOrders)->daily();
Schedule::job(new AggregateAnalytics)->dailyAt('01:00')->timezone('UTC');
routes/web.php
<?php

use App\Http\Controllers\Api\OAuthController;
use App\Http\Middleware\EnsureUserEmailIsVerified;
use App\Livewire\Admin\Analytics\Index as AdminAnalyticsIndex;
use App\Livewire\Admin\Apps\Index as AdminAppsIndex;
use App\Livewire\Admin\Apps\Show as AdminAppShow;
use App\Livewire\Admin\Auth\Login as AdminLogin;
use App\Livewire\Admin\Collections\Form as AdminCollectionForm;
use App\Livewire\Admin\Collections\Index as AdminCollectionsIndex;
use App\Livewire\Admin\Customers\Index as AdminCustomersIndex;
use App\Livewire\Admin\Customers\Show as AdminCustomerShow;
use App\Livewire\Admin\Dashboard as AdminDashboard;
use App\Livewire\Admin\Developers\Index as AdminDevelopersIndex;
use App\Livewire\Admin\Discounts\Form as AdminDiscountForm;
use App\Livewire\Admin\Discounts\Index as AdminDiscountsIndex;
use App\Livewire\Admin\Inventory\Index as AdminInventoryIndex;
use App\Livewire\Admin\Navigation\Index as AdminNavigationIndex;
use App\Livewire\Admin\Orders\Index as AdminOrdersIndex;
use App\Livewire\Admin\Orders\Show as AdminOrderShow;
use App\Livewire\Admin\Pages\Form as AdminPageForm;
use App\Livewire\Admin\Pages\Index as AdminPagesIndex;
use App\Livewire\Admin\Products\Form as AdminProductForm;
use App\Livewire\Admin\Products\Index as AdminProductsIndex;
use App\Livewire\Admin\Search\Settings as AdminSearchSettings;
use App\Livewire\Admin\Settings\Checkout as AdminSettingsCheckout;
use App\Livewire\Admin\Settings\Index as AdminSettingsIndex;
use App\Livewire\Admin\Settings\Notifications as AdminSettingsNotifications;
use App\Livewire\Admin\Settings\Shipping as AdminSettingsShipping;
use App\Livewire\Admin\Settings\Taxes as AdminSettingsTaxes;
use App\Livewire\Admin\Themes\Editor as AdminThemeEditor;
use App\Livewire\Admin\Themes\Index as AdminThemesIndex;
use App\Livewire\Storefront\Account\Auth\ForgotPassword as CustomerForgotPassword;
use App\Livewire\Storefront\Account\Auth\Login as CustomerLogin;
use App\Livewire\Storefront\Account\Auth\Register as CustomerRegister;
use App\Livewire\Storefront\Account\Auth\ResetPassword as CustomerResetPassword;
use App\Livewire\Storefront\Account\Orders\Index as CustomerOrdersIndex;
use App\Livewire\Storefront\Account\Orders\Show as CustomerOrderShow;
use App\Livewire\Storefront\Cart\Show as StorefrontCartShow;
use App\Livewire\Storefront\Checkout\Confirmation as StorefrontCheckoutConfirmation;
use App\Livewire\Storefront\Checkout\Show as StorefrontCheckoutShow;
use App\Livewire\Storefront\Collections\Index as StorefrontCollectionsIndex;
use App\Livewire\Storefront\Collections\Show as StorefrontCollectionShow;
use App\Livewire\Storefront\Home as StorefrontHome;
use App\Livewire\Storefront\Pages\Show as StorefrontPageShow;
use App\Livewire\Storefront\Products\Show as StorefrontProductShow;
use App\Livewire\Storefront\Search\Index as StorefrontSearchIndex;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('/', StorefrontHome::class)->name('home');
    Route::livewire('collections', StorefrontCollectionsIndex::class)->name('collections.index');
    Route::livewire('collections/{handle}', StorefrontCollectionShow::class)->name('collections.show');
    Route::livewire('products/{handle}', StorefrontProductShow::class)->name('products.show');
    Route::livewire('cart', StorefrontCartShow::class)->name('cart.show');
    Route::livewire('checkout', StorefrontCheckoutShow::class)->name('checkout.show');
    Route::livewire('checkout/confirmation/{order}', StorefrontCheckoutConfirmation::class)->name('checkout.confirmation');
    Route::livewire('search', StorefrontSearchIndex::class)->name('search.index');
    Route::livewire('pages/{handle}', StorefrontPageShow::class)->name('pages.show');
});

Route::livewire('admin/login', AdminLogin::class)
    ->middleware('guest')
    ->name('admin.login');

Route::post('admin/logout', function () {
    Auth::guard('web')->logout();

    request()->session()->invalidate();
    request()->session()->regenerateToken();

    return redirect()->route('admin.login');
})->middleware('auth')->name('admin.logout');

Route::get('oauth/authorize', [OAuthController::class, 'authorize'])
    ->middleware('auth')
    ->name('oauth.authorize');

Route::post('oauth/token', [OAuthController::class, 'token'])
    ->name('oauth.token');

Route::middleware(['auth', EnsureUserEmailIsVerified::class, 'admin'])->prefix('admin')->name('admin.')->group(function (): void {
    Route::livewire('/', AdminDashboard::class)->name('dashboard');
    Route::livewire('analytics', AdminAnalyticsIndex::class)->name('analytics.index');
    Route::livewire('apps', AdminAppsIndex::class)->name('apps.index');
    Route::livewire('apps/{installation}', AdminAppShow::class)->name('apps.show');
    Route::livewire('developers', AdminDevelopersIndex::class)->name('developers.index');
    Route::livewire('products', AdminProductsIndex::class)->name('products.index');
    Route::livewire('products/create', AdminProductForm::class)->name('products.create');
    Route::livewire('products/{product}/edit', AdminProductForm::class)->name('products.edit');
    Route::livewire('inventory', AdminInventoryIndex::class)->name('inventory.index');
    Route::livewire('orders', AdminOrdersIndex::class)->name('orders.index');
    Route::livewire('orders/{order}', AdminOrderShow::class)->name('orders.show');
    Route::livewire('customers', AdminCustomersIndex::class)->name('customers.index');
    Route::livewire('customers/{customer}', AdminCustomerShow::class)->name('customers.show');
    Route::livewire('discounts', AdminDiscountsIndex::class)->name('discounts.index');
    Route::livewire('discounts/create', AdminDiscountForm::class)->name('discounts.create');
    Route::livewire('discounts/{discount}/edit', AdminDiscountForm::class)->name('discounts.edit');
    Route::livewire('pages', AdminPagesIndex::class)->name('pages.index');
    Route::livewire('pages/create', AdminPageForm::class)->name('pages.create');
    Route::livewire('pages/{page}/edit', AdminPageForm::class)->name('pages.edit');
    Route::livewire('navigation', AdminNavigationIndex::class)->name('navigation.index');
    Route::livewire('themes', AdminThemesIndex::class)->name('themes.index');
    Route::livewire('themes/{theme}/editor', AdminThemeEditor::class)->name('themes.editor');
    Route::livewire('settings', AdminSettingsIndex::class)->name('settings.index');
    Route::livewire('settings/shipping', AdminSettingsShipping::class)->name('settings.shipping');
    Route::livewire('settings/taxes', AdminSettingsTaxes::class)->name('settings.taxes');
    Route::livewire('settings/checkout', AdminSettingsCheckout::class)->name('settings.checkout');
    Route::livewire('settings/notifications', AdminSettingsNotifications::class)->name('settings.notifications');
    Route::livewire('search/settings', AdminSearchSettings::class)->name('search.settings');
    Route::livewire('collections', AdminCollectionsIndex::class)->name('collections.index');
    Route::livewire('collections/create', AdminCollectionForm::class)->name('collections.create');
    Route::livewire('collections/{collection}/edit', AdminCollectionForm::class)->name('collections.edit');
});

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('account/login', CustomerLogin::class)
        ->middleware('guest:customer')
        ->name('account.login');

    Route::livewire('account/register', CustomerRegister::class)
        ->middleware('guest:customer')
        ->name('account.register');

    Route::livewire('account/forgot-password', CustomerForgotPassword::class)
        ->middleware('guest:customer')
        ->name('account.password.request');

    Route::livewire('account/reset-password/{token}', CustomerResetPassword::class)
        ->middleware('guest:customer')
        ->name('account.password.reset');

    Route::livewire('account', CustomerOrdersIndex::class)
        ->middleware('auth:customer')
        ->name('account.dashboard');

    Route::livewire('account/orders/{order}', CustomerOrderShow::class)
        ->middleware('auth:customer')
        ->name('account.orders.show');
});

Route::redirect('dashboard', 'admin')
    ->middleware(['auth', 'verified'])
    ->name('dashboard');

require __DIR__.'/settings.php';
routes/api.php
<?php

use App\Http\Controllers\Api\Admin\V1\AnalyticsSummaryController as AdminAnalyticsSummaryController;
use App\Http\Controllers\Api\Admin\V1\CollectionController as AdminCollectionController;
use App\Http\Controllers\Api\Admin\V1\CustomerController as AdminCustomerController;
use App\Http\Controllers\Api\Admin\V1\DiscountController as AdminDiscountController;
use App\Http\Controllers\Api\Admin\V1\OrderController as AdminOrderController;
use App\Http\Controllers\Api\Admin\V1\OrderExportController as AdminOrderExportController;
use App\Http\Controllers\Api\Admin\V1\OrderFulfillmentController as AdminOrderFulfillmentController;
use App\Http\Controllers\Api\Admin\V1\OrderRefundController as AdminOrderRefundController;
use App\Http\Controllers\Api\Admin\V1\PageController as AdminPageController;
use App\Http\Controllers\Api\Admin\V1\ProductController as AdminProductController;
use App\Http\Controllers\Api\Admin\V1\SearchIndexController as AdminSearchIndexController;
use App\Http\Controllers\Api\Admin\V1\ShippingRateController as AdminShippingRateController;
use App\Http\Controllers\Api\Admin\V1\ShippingZoneController as AdminShippingZoneController;
use App\Http\Controllers\Api\Admin\V1\StoreSettingsController as AdminStoreSettingsController;
use App\Http\Controllers\Api\Admin\V1\TaxSettingsController as AdminTaxSettingsController;
use App\Http\Controllers\Api\Admin\V1\ThemeController as AdminThemeController;
use App\Http\Controllers\Api\Admin\V1\ThemeSettingsController as AdminThemeSettingsController;
use App\Http\Controllers\Api\Apps\V1\DeferredEndpointController as DeferredAppEndpointController;
use App\Http\Controllers\Api\Storefront\V1\AnalyticsEventController as StorefrontAnalyticsEventController;
use App\Http\Controllers\Api\Storefront\V1\CartController;
use App\Http\Controllers\Api\Storefront\V1\CartLineController;
use App\Http\Controllers\Api\Storefront\V1\CheckoutController;
use App\Http\Controllers\Api\Storefront\V1\OrderController as StorefrontOrderController;
use App\Http\Controllers\Api\Storefront\V1\SearchController as StorefrontSearchController;
use Illuminate\Support\Facades\Route;

Route::middleware('store.resolve')
    ->prefix('storefront/v1')
    ->name('api.storefront.v1.')
    ->group(function (): void {
        Route::middleware('throttle:api.storefront')->group(function (): void {
            Route::post('carts', [CartController::class, 'store'])->name('carts.store');
            Route::get('carts/{cart}', [CartController::class, 'show'])->name('carts.show');
            Route::post('carts/{cart}/lines', [CartLineController::class, 'store'])->name('carts.lines.store');
            Route::put('carts/{cart}/lines/{cartLine}', [CartLineController::class, 'update'])->name('carts.lines.update');
            Route::delete('carts/{cart}/lines/{cartLine}', [CartLineController::class, 'destroy'])->name('carts.lines.destroy');
        });

        Route::middleware('throttle:search')->group(function (): void {
            Route::get('search', [StorefrontSearchController::class, 'index'])->name('search.index');
            Route::get('search/suggest', [StorefrontSearchController::class, 'suggest'])->name('search.suggest');
        });

        Route::middleware('throttle:analytics')->group(function (): void {
            Route::post('analytics/events', [StorefrontAnalyticsEventController::class, 'store'])->name('analytics.events.store');
        });

        Route::middleware('throttle:checkout')->group(function (): void {
            Route::post('checkouts', [CheckoutController::class, 'store'])->name('checkouts.store');
            Route::get('checkouts/{checkout}', [CheckoutController::class, 'show'])->name('checkouts.show');
            Route::put('checkouts/{checkout}/address', [CheckoutController::class, 'address'])->name('checkouts.address');
            Route::put('checkouts/{checkout}/shipping-method', [CheckoutController::class, 'shippingMethod'])->name('checkouts.shipping-method');
            Route::post('checkouts/{checkout}/apply-discount', [CheckoutController::class, 'applyDiscount'])->name('checkouts.apply-discount');
            Route::delete('checkouts/{checkout}/discount', [CheckoutController::class, 'destroyDiscount'])->name('checkouts.discount.destroy');
            Route::put('checkouts/{checkout}/payment-method', [CheckoutController::class, 'paymentMethod'])->name('checkouts.payment-method');
            Route::post('checkouts/{checkout}/pay', [CheckoutController::class, 'pay'])->name('checkouts.pay');
            Route::get('orders/{orderNumber}', [StorefrontOrderController::class, 'show'])->name('orders.show');
        });
    });

Route::middleware('throttle:60,1')
    ->prefix('admin/v1/stores/{store}')
    ->name('api.admin.v1.')
    ->group(function (): void {
        Route::middleware('admin.api:read-products')->group(function (): void {
            Route::get('products', [AdminProductController::class, 'index'])->name('products.index');
            Route::get('products/{product}', [AdminProductController::class, 'show'])->name('products.show');
        });

        Route::middleware('admin.api:read-customers')->group(function (): void {
            Route::get('customers', [AdminCustomerController::class, 'index'])->name('customers.index');
            Route::get('customers/{customer}', [AdminCustomerController::class, 'show'])->name('customers.show');
        });

        Route::middleware('admin.api:read-collections')->group(function (): void {
            Route::get('collections', [AdminCollectionController::class, 'index'])->name('collections.index');
        });

        Route::middleware('admin.api:write-collections')->group(function (): void {
            Route::post('collections', [AdminCollectionController::class, 'store'])->name('collections.store');
            Route::put('collections/{collection}', [AdminCollectionController::class, 'update'])->name('collections.update');
            Route::delete('collections/{collection}', [AdminCollectionController::class, 'destroy'])->name('collections.destroy');
        });

        Route::middleware('admin.api:read-discounts')->group(function (): void {
            Route::get('discounts', [AdminDiscountController::class, 'index'])->name('discounts.index');
        });

        Route::middleware('admin.api:write-discounts')->group(function (): void {
            Route::post('discounts', [AdminDiscountController::class, 'store'])->name('discounts.store');
            Route::put('discounts/{discount}', [AdminDiscountController::class, 'update'])->name('discounts.update');
            Route::delete('discounts/{discount}', [AdminDiscountController::class, 'destroy'])->name('discounts.destroy');
        });

        Route::middleware('admin.api:read-content')->group(function (): void {
            Route::get('pages', [AdminPageController::class, 'index'])->name('pages.index');
        });

        Route::middleware('admin.api:write-content')->group(function (): void {
            Route::post('pages', [AdminPageController::class, 'store'])->name('pages.store');
            Route::put('pages/{page}', [AdminPageController::class, 'update'])->name('pages.update');
            Route::delete('pages/{page}', [AdminPageController::class, 'destroy'])->name('pages.destroy');
        });

        Route::middleware('admin.api:read-settings')->group(function (): void {
            Route::get('search/status', [AdminSearchIndexController::class, 'status'])->name('search.status');
            Route::get('settings', [AdminStoreSettingsController::class, 'show'])->name('settings.show');
            Route::get('shipping/zones', [AdminShippingZoneController::class, 'index'])->name('shipping.zones.index');
            Route::get('tax/settings', [AdminTaxSettingsController::class, 'show'])->name('tax.settings.show');
        });

        Route::middleware('admin.api:write-settings')->group(function (): void {
            Route::post('search/reindex', [AdminSearchIndexController::class, 'reindex'])->name('search.reindex');
            Route::put('settings', [AdminStoreSettingsController::class, 'update'])->name('settings.update');
            Route::post('shipping/zones', [AdminShippingZoneController::class, 'store'])->name('shipping.zones.store');
            Route::put('shipping/zones/{shippingZone}', [AdminShippingZoneController::class, 'update'])->name('shipping.zones.update');
            Route::post('shipping/zones/{shippingZone}/rates', [AdminShippingRateController::class, 'store'])->name('shipping.zones.rates.store');
            Route::put('tax/settings', [AdminTaxSettingsController::class, 'update'])->name('tax.settings.update');
        });

        Route::middleware('admin.api:write-themes')->group(function (): void {
            Route::post('themes', [AdminThemeController::class, 'store'])->name('themes.store');
            Route::post('themes/{theme}/publish', [AdminThemeController::class, 'publish'])->name('themes.publish');
            Route::put('themes/{theme}/settings', [AdminThemeSettingsController::class, 'update'])->name('themes.settings.update');
        });

        Route::middleware('admin.api:read-analytics')->group(function (): void {
            Route::get('analytics/summary', [AdminAnalyticsSummaryController::class, 'show'])->name('analytics.summary');
        });

        Route::middleware('admin.api:read-orders')->group(function (): void {
            Route::post('exports/orders', [AdminOrderExportController::class, 'store'])->name('exports.orders.store');
            Route::get('exports/{dataExport}', [AdminOrderExportController::class, 'show'])->name('exports.show');
            Route::get('orders', [AdminOrderController::class, 'index'])->name('orders.index');
            Route::get('orders/{order}', [AdminOrderController::class, 'show'])->name('orders.show');
        });

        Route::middleware('admin.api:write-orders')->group(function (): void {
            Route::post('orders/{order}/fulfillments', [AdminOrderFulfillmentController::class, 'store'])->name('orders.fulfillments.store');
            Route::post('orders/{order}/refunds', [AdminOrderRefundController::class, 'store'])->name('orders.refunds.store');
        });
    });

Route::middleware('throttle:60,1')
    ->prefix('apps/v1/stores/{store}')
    ->name('api.apps.v1.')
    ->group(function (): void {
        Route::get('products', DeferredAppEndpointController::class)->name('products.index');
        Route::get('orders', DeferredAppEndpointController::class)->name('orders.index');
        Route::get('customers', DeferredAppEndpointController::class)->name('customers.index');
    });


Output:
Chunk ID: 32d4a5
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2557
Output:
routes/web.php:126:    Route::livewire('account/forgot-password', CustomerForgotPassword::class)
routes/web.php:128:        ->name('account.password.request');
routes/web.php:130:    Route::livewire('account/reset-password/{token}', CustomerResetPassword::class)
routes/web.php:132:        ->name('account.password.reset');
routes/settings.php:8:use Laravel\Fortify\Features;
config/auth.php:98:    | generating more password reset tokens. This prevents the user from
config/auth.php:99:    | quickly generating a very large amount of password reset tokens.
config/auth.php:106:            'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
config/auth.php:113:            'table' => 'customer_password_reset_tokens',
config/fortify.php:3:use Laravel\Fortify\Features;
config/fortify.php:9:    | Fortify Guard
config/fortify.php:12:    | Here you may specify which authentication guard Fortify will use while
config/fortify.php:22:    | Fortify Password Broker
config/fortify.php:25:    | Here you may specify which password broker Fortify can use when a user
config/fortify.php:42:    | Out of the box, Fortify expects forgot password and reset password
config/fortify.php:71:    | authentication or password reset when the operations are successful
config/fortify.php:80:    | Fortify Routes Prefix / Subdomain
config/fortify.php:83:    | Here you may specify which prefix Fortify will assign to all the routes
config/fortify.php:85:    | subdomain under which all of the Fortify routes will be available.
config/fortify.php:95:    | Fortify Routes Middleware
config/fortify.php:98:    | Here you may specify which middleware Fortify will assign to the routes
config/fortify.php:111:    | By default, Fortify will throttle logins to five requests per minute for
config/fortify.php:140:    | Some of the Fortify features are optional. You may disable the features
tests/Feature/Catalog/CatalogUiTest.php:51:test('admin catalog routes require authentication and render for store admins', function () {
tests/Feature/Auth/PasswordResetTest.php:10:    $response = $this->get(route('password.request'));
tests/Feature/Auth/PasswordResetTest.php:20:    $this->post(route('password.request'), ['email' => $user->email]);
tests/Feature/Auth/PasswordResetTest.php:30:    $this->post(route('password.request'), ['email' => $user->email]);
tests/Feature/Auth/PasswordResetTest.php:33:        $response = $this->get(route('password.reset', $notification->token));
tests/Feature/Auth/PasswordResetTest.php:45:    $this->post(route('password.request'), ['email' => $user->email]);
tests/Feature/Settings/TwoFactorAuthenticationTest.php:4:use Laravel\Fortify\Features;
tests/Feature/Auth/CustomerPasswordResetTest.php:25:test('customer password reset pages render for the resolved storefront store', function (): void {
tests/Feature/Auth/CustomerPasswordResetTest.php:32:    $this->get('http://customer-reset.test/account/forgot-password')
tests/Feature/Auth/CustomerPasswordResetTest.php:37:    $this->get('http://customer-reset.test/account/reset-password/test-token?email=customer@example.test')
tests/Feature/Auth/CustomerPasswordResetTest.php:76:    $this->assertDatabaseHas('customer_password_reset_tokens', [
tests/Feature/Auth/CustomerPasswordResetTest.php:81:    $this->assertDatabaseMissing('customer_password_reset_tokens', [
tests/Feature/Auth/CustomerPasswordResetTest.php:102:    expect(DB::table('customer_password_reset_tokens')->count())->toBe(0);
tests/Feature/Auth/CustomerPasswordResetTest.php:105:test('customer password reset updates the password and deletes the token', function (): void {
tests/Feature/Auth/CustomerPasswordResetTest.php:141:    $this->assertDatabaseMissing('customer_password_reset_tokens', [
tests/Feature/Auth/CustomerPasswordResetTest.php:170:    DB::table('customer_password_reset_tokens')->insert([
tests/Feature/Auth/CustomerPasswordResetTest.php:188:    DB::table('customer_password_reset_tokens')
tests/Feature/Auth/AuthenticationTest.php:4:use Laravel\Fortify\Features;
app/Services/CustomerPasswordResetService.php:113:        return 'customer-password-reset:'.$store->getKey().':'.sha1($email);
app/Services/CustomerPasswordResetService.php:118:        return config('auth.passwords.customers.table', 'customer_password_reset_tokens');
tests/Feature/Auth/TwoFactorChallengeTest.php:4:use Laravel\Fortify\Features;
tests/Feature/Admin/CustomerManagementTest.php:57:test('admin customer routes require authentication and render store scoped customers', function (): void {
tests/Feature/Admin/OrderManagementTest.php:94:test('admin order routes require authentication and render scoped orders', function () {
tests/Feature/Admin/DiscountManagementTest.php:59:test('admin discount routes require authentication and render store scoped discounts', function (): void {
app/Notifications/CustomerResetPassword.php:34:        $resetUrl = route('account.password.reset', [
app/Notifications/CustomerResetPassword.php:41:            ->line(__('You are receiving this email because we received a password reset request for your account.'))
app/Notifications/CustomerResetPassword.php:43:            ->line(__('This password reset link will expire in :count minutes.', [
app/Notifications/CustomerResetPassword.php:46:            ->line(__('If you did not request a password reset, no further action is required.'));
tests/Feature/Admin/DashboardTest.php:69:test('admin dashboard route requires authentication and renders store scoped metrics', function (): void {
app/Actions/Fortify/CreateNewUser.php:3:namespace App\Actions\Fortify;
app/Actions/Fortify/CreateNewUser.php:9:use Laravel\Fortify\Contracts\CreatesNewUsers;
app/Actions/Fortify/ResetUserPassword.php:3:namespace App\Actions\Fortify;
app/Actions/Fortify/ResetUserPassword.php:8:use Laravel\Fortify\Contracts\ResetsUserPasswords;
resources/views/components/settings/layout.blade.php:6:            @if (Laravel\Fortify\Features::canManageTwoFactorAuthentication())
resources/views/livewire/auth/login.blade.php:35:                @if (Route::has('password.request'))
resources/views/livewire/auth/login.blade.php:36:                    <flux:link class="absolute top-0 text-sm end-0" :href="route('password.request')" wire:navigate>
resources/views/livewire/auth/reset-password.blade.php:46:                <flux:button type="submit" variant="primary" class="w-full" data-test="reset-password-button">
resources/views/livewire/auth/forgot-password.blade.php:3:        <x-auth-header :title="__('Forgot password')" :description="__('Enter your email to receive a password reset link')" />
resources/views/livewire/auth/forgot-password.blade.php:21:            <flux:button variant="primary" type="submit" class="w-full" data-test="email-password-reset-link-button">
resources/views/livewire/auth/forgot-password.blade.php:22:                {{ __('Email password reset link') }}
app/Models/User.php:13:use Laravel\Fortify\TwoFactorAuthenticatable;
resources/views/livewire/storefront/account/auth/login.blade.php:26:            <flux:link :href="route('account.password.request')" wire:navigate>{{ __('Forgot your password?') }}</flux:link>
resources/views/livewire/storefront/account/auth/forgot-password.blade.php:21:        <flux:button variant="primary" type="submit" class="w-full" data-test="customer-forgot-password-button">
resources/views/livewire/storefront/account/auth/reset-password.blade.php:33:        <flux:button variant="primary" type="submit" class="w-full" data-test="customer-reset-password-button">
app/Livewire/Settings/TwoFactor.php:6:use Laravel\Fortify\Actions\ConfirmTwoFactorAuthentication;
app/Livewire/Settings/TwoFactor.php:7:use Laravel\Fortify\Actions\DisableTwoFactorAuthentication;
app/Livewire/Settings/TwoFactor.php:8:use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
app/Livewire/Settings/TwoFactor.php:9:use Laravel\Fortify\Features;
app/Livewire/Settings/TwoFactor.php:10:use Laravel\Fortify\Fortify;
app/Livewire/Settings/TwoFactor.php:44:        if (Fortify::confirmsTwoFactorAuthentication() && is_null(auth()->user()->two_factor_confirmed_at)) {
app/Livewire/Settings/TwoFactor/RecoveryCodes.php:6:use Laravel\Fortify\Actions\GenerateNewRecoveryCodes;
app/Providers/FortifyServiceProvider.php:5:use App\Actions\Fortify\CreateNewUser;
app/Providers/FortifyServiceProvider.php:6:use App\Actions\Fortify\ResetUserPassword;
app/Providers/FortifyServiceProvider.php:11:use Laravel\Fortify\Fortify;
app/Providers/FortifyServiceProvider.php:13:class FortifyServiceProvider extends ServiceProvider
app/Providers/FortifyServiceProvider.php:34:     * Configure Fortify actions.
app/Providers/FortifyServiceProvider.php:38:        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
app/Providers/FortifyServiceProvider.php:39:        Fortify::createUsersUsing(CreateNewUser::class);
app/Providers/FortifyServiceProvider.php:43:     * Configure Fortify views.
app/Providers/FortifyServiceProvider.php:47:        Fortify::loginView(fn () => view('livewire.auth.login'));
app/Providers/FortifyServiceProvider.php:48:        Fortify::verifyEmailView(fn () => view('livewire.auth.verify-email'));
app/Providers/FortifyServiceProvider.php:49:        Fortify::twoFactorChallengeView(fn () => view('livewire.auth.two-factor-challenge'));
app/Providers/FortifyServiceProvider.php:50:        Fortify::confirmPasswordView(fn () => view('livewire.auth.confirm-password'));
app/Providers/FortifyServiceProvider.php:51:        Fortify::registerView(fn () => view('livewire.auth.register'));
app/Providers/FortifyServiceProvider.php:52:        Fortify::resetPasswordView(fn () => view('livewire.auth.reset-password'));
app/Providers/FortifyServiceProvider.php:53:        Fortify::requestPasswordResetLinkView(fn () => view('livewire.auth.forgot-password'));
app/Livewire/Storefront/Account/Auth/ForgotPassword.php:42:        return view('livewire.storefront.account.auth.forgot-password')
app/Livewire/Storefront/Account/Auth/ResetPassword.php:50:            $this->addError('email', __('This password reset link is invalid or has expired.'));
app/Livewire/Storefront/Account/Auth/ResetPassword.php:62:        return view('livewire.storefront.account.auth.reset-password')


Output:
Chunk ID: 59d21b
Wall time: 0.1912 seconds
Process exited with code 0
Original token count: 42
Output:

   ERROR  Your application doesn't have any routes matching the given criteria.

   ERROR  Your application doesn't have any routes matching the given criteria.


php artisan route:list --path=forgot-password --except-vendor && php artisan route:list --path=reset-password --except-vendor

   ERROR  Your application doesn't have any routes matching the given criteria.

   ERROR  Your application doesn't have any routes matching the given criteria.


find tests/Browser -type f -maxdepth 2 -print -exec sed -n '1,220p' {} \;


find tests/Browser -type f -maxdepth 2 -print -exec sed -n '1,220p' {} \;

find tests/Browser -type f -maxdepth 2 -print -exec sed -n '1,220p' '{}' "\\;"

tests/Browser/SmokeTest.php
<?php

use App\Models\Collection as ProductCollection;
use App\Models\Page;
use App\Models\Product;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    $this->seed(DatabaseSeeder::class);
});

function browserSmokeStore(): Store
{
    return Store::query()->where('handle', 'acme-fashion')->firstOrFail();
}

function browserSmokeHost(): array
{
    return ['host' => 'shop.test'];
}

test('storefront core pages render without javascript errors', function (): void {
    $store = browserSmokeStore();
    $product = Product::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('status', 'active')
        ->firstOrFail();
    $collection = ProductCollection::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('status', 'active')
        ->firstOrFail();
    $page = Page::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('status', 'published')
        ->firstOrFail();

    $pages = visit([
        '/',
        '/collections',
        "/collections/{$collection->handle}",
        "/products/{$product->handle}",
        '/search?q=shirt',
        "/pages/{$page->handle}",
        '/cart',
    ], browserSmokeHost());

    $pages->assertNoJavaScriptErrors();

    [$home, $collections, $collectionPage, $productPage, $search, $contentPage, $cart] = $pages;

    $home->assertSee($store->name);
    $collections->assertSee('Collections');
    $collectionPage->assertSee($collection->title);
    $productPage->assertSee($product->title);
    $search->assertSee('Search');
    $contentPage->assertSee($page->title);
    $cart->assertSee('Cart');
});

test('admin core pages render for an authenticated store user', function (): void {
    $store = browserSmokeStore();
    $user = User::query()->where('email', 'admin@acme.test')->firstOrFail();

    $this->actingAs($user);
    $this->withSession(['current_store_id' => $store->getKey()]);

    $pages = visit([
        '/admin',
        '/admin/products',
        '/admin/orders',
        '/admin/customers',
        '/admin/navigation',
    ], browserSmokeHost());

    $pages->assertNoJavaScriptErrors();

    [$dashboard, $products, $orders, $customers, $navigation] = $pages;

    $dashboard->assertSee('Dashboard');
    $products->assertSee('Products');
    $orders->assertSee('Orders');
    $customers->assertSee('Customers');
    $navigation->assertSee('Navigation');
});

test('storefront home renders on a mobile viewport', function (): void {
    $store = browserSmokeStore();

    visit('/', browserSmokeHost())
        ->on()
        ->mobile()
        ->assertSee($store->name)
        ->assertNoJavaScriptErrors();
});


Output:
Chunk ID: 2ae240
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 715
Output:
tests/Browser/SmokeTest.php
<?php

use App\Models\Collection as ProductCollection;
use App\Models\Page;
use App\Models\Product;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    $this->seed(DatabaseSeeder::class);
});

function browserSmokeStore(): Store
{
    return Store::query()->where('handle', 'acme-fashion')->firstOrFail();
}

function browserSmokeHost(): array
{
    return ['host' => 'shop.test'];
}

test('storefront core pages render without javascript errors', function (): void {
    $store = browserSmokeStore();
    $product = Product::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('status', 'active')
        ->firstOrFail();
    $collection = ProductCollection::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('status', 'active')
        ->firstOrFail();
    $page = Page::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('status', 'published')
        ->firstOrFail();

    $pages = visit([
        '/',
        '/collections',
        "/collections/{$collection->handle}",
        "/products/{$product->handle}",
        '/search?q=shirt',
        "/pages/{$page->handle}",
        '/cart',
    ], browserSmokeHost());

    $pages->assertNoJavaScriptErrors();

    [$home, $collections, $collectionPage, $productPage, $search, $contentPage, $cart] = $pages;

    $home->assertSee($store->name);
    $collections->assertSee('Collections');
    $collectionPage->assertSee($collection->title);
    $productPage->assertSee($product->title);
    $search->assertSee('Search');
    $contentPage->assertSee($page->title);
    $cart->assertSee('Cart');
});

test('admin core pages render for an authenticated store user', function (): void {
    $store = browserSmokeStore();
    $user = User::query()->where('email', 'admin@acme.test')->firstOrFail();

    $this->actingAs($user);
    $this->withSession(['current_store_id' => $store->getKey()]);

    $pages = visit([
        '/admin',
        '/admin/products',
        '/admin/orders',
        '/admin/customers',
        '/admin/navigation',
    ], browserSmokeHost());

    $pages->assertNoJavaScriptErrors();

    [$dashboard, $products, $orders, $customers, $navigation] = $pages;

    $dashboard->assertSee('Dashboard');
    $products->assertSee('Products');
    $orders->assertSee('Orders');
    $customers->assertSee('Customers');
    $navigation->assertSee('Navigation');
});

test('storefront home renders on a mobile viewport', function (): void {
    $store = browserSmokeStore();

    visit('/', browserSmokeHost())
        ->on()
        ->mobile()
        ->assertSee($store->name)
        ->assertNoJavaScriptErrors();
});


Question: SELECT name, sql FROM sqlite_master WHERE type = 'table' AND name IN ('stores','orders','discounts','themes','products','data_exports') ORDER BY name


Question: SELECT name, sql FROM sqlite_master WHERE type = 'table' AND name IN ('stores','orders','discounts','themes','products','data_exports') ORDER BY name

CREATE TABLE "data_exports" ("id" integer primary key autoincrement not null, "store_id" integer not null, "type" varchar not null default 'orders', "format" varchar not null default 'csv', "status" varchar check ("status" in ('queued', 'processing', 'completed', 'failed')) not null default 'queued', "filters_json" text not null default '{}', "row_count" integer not null default '0', "storage_key" varchar, "error_message" text, "download_expires_at" datetime, "completed_at" datetime, "failed_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)

discounts

CREATE TABLE "discounts" ("id" integer primary key autoincrement not null, "store_id" integer not null, "type" varchar check ("type" in ('code', 'automatic')) not null default 'code', "code" varchar, "value_type" varchar check ("value_type" in ('fixed', 'percent', 'free_shipping')) not null, "value_amount" integer not null default '0', "starts_at" datetime not null, "ends_at" datetime, "usage_limit" integer, "usage_count" integer not null default '0', "rules_json" text not null default '{}', "status" varchar check ("status" in ('draft', 'active', 'expired', 'disabled')) not null default 'active', "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)

orders

CREATE TABLE "orders" ("id" integer primary key autoincrement not null, "store_id" integer not null, "checkout_id" integer, "customer_id" integer, "order_number" varchar not null, "payment_method" varchar check ("payment_method" in ('credit_card', 'paypal', 'bank_transfer')) not null, "status" varchar check ("status" in ('pending', 'paid', 'fulfilled', 'cancelled', 'refunded')) not null default 'pending', "financial_status" varchar check ("financial_status" in ('pending', 'authorized', 'paid', 'partially_refunded', 'refunded', 'voided')) not null default 'pending', "fulfillment_status" varchar check ("fulfillment_status" in ('unfulfilled', 'partial', 'fulfilled')) not null default 'unfulfilled', "currency" varchar not null default 'USD', "subtotal_amount" integer not null default '0', "discount_amount" integer not null default '0', "shipping_amount" integer not null default '0', "tax_amount" integer not null default '0', "total_amount" integer not null default '0', "email" varchar, "billing_address_json" text, "shipping_address_json" text, "placed_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade, foreign key("checkout_id") references "checkouts"("id") on delete set null, foreign key("customer_id") references "customers"("id") on delete set null)

products

CREATE TABLE "products" ("id" integer primary key autoincrement not null, "store_id" integer not null, "title" varchar not null, "handle" varchar not null, "status" varchar check ("status" in ('draft', 'active', 'archived')) not null default 'draft', "description_html" text, "vendor" varchar, "product_type" varchar, "tags" text not null default '[]', "published_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)

stores

CREATE TABLE "stores" ("id" integer primary key autoincrement not null, "organization_id" integer not null, "name" varchar not null, "handle" varchar not null, "status" varchar check ("status" in ('active', 'suspended')) not null default 'active', "default_currency" varchar not null default 'USD', "default_locale" varchar not null default 'en', "timezone" varchar not null default 'UTC', "created_at" datetime, "updated_at" datetime, foreign key("organization_id") references "organizations"("id") on delete cascade)

themes

CREATE TABLE "themes" ("id" integer primary key autoincrement not null, "store_id" integer not null, "name" varchar not null, "version" varchar, "status" varchar check ("status" in ('draft', 'published')) not null default 'draft', "published_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)


Output:
Wall time: 0.1903 seconds
Output:
[{"type":"text","text":"[{\"name\":\"data_exports\",\"sql\":\"CREATE TABLE \\\"data_exports\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"type\\\" varchar not null default 'orders', \\\"format\\\" varchar not null default 'csv', \\\"status\\\" varchar check (\\\"status\\\" in ('queued', 'processing', 'completed', 'failed')) not null default 'queued', \\\"filters_json\\\" text not null default '{}', \\\"row_count\\\" integer not null default '0', \\\"storage_key\\\" varchar, \\\"error_message\\\" text, \\\"download_expires_at\\\" datetime, \\\"completed_at\\\" datetime, \\\"failed_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"discounts\",\"sql\":\"CREATE TABLE \\\"discounts\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"type\\\" varchar check (\\\"type\\\" in ('code', 'automatic')) not null default 'code', \\\"code\\\" varchar, \\\"value_type\\\" varchar check (\\\"value_type\\\" in ('fixed', 'percent', 'free_shipping')) not null, \\\"value_amount\\\" integer not null default '0', \\\"starts_at\\\" datetime not null, \\\"ends_at\\\" datetime, \\\"usage_limit\\\" integer, \\\"usage_count\\\" integer not null default '0', \\\"rules_json\\\" text not null default '{}', \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'active', 'expired', 'disabled')) not null default 'active', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"orders\",\"sql\":\"CREATE TABLE \\\"orders\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"checkout_id\\\" integer, \\\"customer_id\\\" integer, \\\"order_number\\\" varchar not null, \\\"payment_method\\\" varchar check (\\\"payment_method\\\" in ('credit_card', 'paypal', 'bank_transfer')) not null, \\\"status\\\" varchar check (\\\"status\\\" in ('pending', 'paid', 'fulfilled', 'cancelled', 'refunded')) not null default 'pending', \\\"financial_status\\\" varchar check (\\\"financial_status\\\" in ('pending', 'authorized', 'paid', 'partially_refunded', 'refunded', 'voided')) not null default 'pending', \\\"fulfillment_status\\\" varchar check (\\\"fulfillment_status\\\" in ('unfulfilled', 'partial', 'fulfilled')) not null default 'unfulfilled', \\\"currency\\\" varchar not null default 'USD', \\\"subtotal_amount\\\" integer not null default '0', \\\"discount_amount\\\" integer not null default '0', \\\"shipping_amount\\\" integer not null default '0', \\\"tax_amount\\\" integer not null default '0', \\\"total_amount\\\" integer not null default '0', \\\"email\\\" varchar, \\\"billing_address_json\\\" text, \\\"shipping_address_json\\\" text, \\\"placed_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"checkout_id\\\") references \\\"checkouts\\\"(\\\"id\\\") on delete set null, foreign key(\\\"customer_id\\\") references \\\"customers\\\"(\\\"id\\\") on delete set null)\"},{\"name\":\"products\",\"sql\":\"CREATE TABLE \\\"products\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"title\\\" varchar not null, \\\"handle\\\" varchar not null, \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'active', 'archived')) not null default 'draft', \\\"description_html\\\" text, \\\"vendor\\\" varchar, \\\"product_type\\\" varchar, \\\"tags\\\" text not null default '[]', \\\"published_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"stores\",\"sql\":\"CREATE TABLE \\\"stores\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"organization_id\\\" integer not null, \\\"name\\\" varchar not null, \\\"handle\\\" varchar not null, \\\"status\\\" varchar check (\\\"status\\\" in ('active', 'suspended')) not null default 'active', \\\"default_currency\\\" varchar not null default 'USD', \\\"default_locale\\\" varchar not null default 'en', \\\"timezone\\\" varchar not null default 'UTC', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"organization_id\\\") references \\\"organizations\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"themes\",\"sql\":\"CREATE TABLE \\\"themes\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"name\\\" varchar not null, \\\"version\\\" varchar, \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'published')) not null default 'draft', \\\"published_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"}]"}]


Question: SELECT name, sql FROM sqlite_master WHERE type = 'table' AND sql LIKE '%check (%' ORDER BY name


Question: SELECT name, sql FROM sqlite_master WHERE type = 'table' AND sql LIKE '%check (%' ORDER BY name

carts

CREATE TABLE "carts" ("id" integer primary key autoincrement not null, "store_id" integer not null, "customer_id" integer, "currency" varchar not null default 'USD', "cart_version" integer not null default '1', "status" varchar check ("status" in ('active', 'converted', 'abandoned')) not null default 'active', "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade, foreign key("customer_id") references "customers"("id") on delete set null)

checkouts

CREATE TABLE "checkouts" ("id" integer primary key autoincrement not null, "store_id" integer not null, "cart_id" integer not null, "customer_id" integer, "status" varchar check ("status" in ('started', 'addressed', 'shipping_selected', 'payment_selected', 'completed', 'expired')) not null default 'started', "payment_method" varchar check ("payment_method" in ('credit_card', 'paypal', 'bank_transfer')), "email" varchar, "shipping_address_json" text, "billing_address_json" text, "shipping_method_id" integer, "discount_code" varchar, "tax_provider_snapshot_json" text, "totals_json" text, "expires_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade, foreign key("cart_id") references "carts"("id") on delete cascade, foreign key("customer_id") references "customers"("id") on delete set null)

collections

CREATE TABLE "collections" ("id" integer primary key autoincrement not null, "store_id" integer not null, "title" varchar not null, "handle" varchar not null, "description_html" text, "type" varchar check ("type" in ('manual', 'automated')) not null default 'manual', "status" varchar check ("status" in ('draft', 'active', 'archived')) not null default 'active', "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)

fulfillments

CREATE TABLE "fulfillments" ("id" integer primary key autoincrement not null, "order_id" integer not null, "status" varchar check ("status" in ('pending', 'shipped', 'delivered')) not null default 'pending', "tracking_company" varchar, "tracking_number" varchar, "tracking_url" varchar, "shipped_at" datetime, "delivered_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("order_id") references "orders"("id") on delete cascade)

CREATE TABLE "inventory_items" ("id" integer primary key autoincrement not null, "store_id" integer not null, "variant_id" integer not null, "quantity_on_hand" integer not null default '0', "quantity_reserved" integer not null default '0', "policy" varchar check ("policy" in ('deny', 'continue')) not null default 'deny', foreign key("store_id") references "stores"("id") on delete cascade, foreign key("variant_id") references "product_variants"("id") on delete cascade)

pages

CREATE TABLE "pages" ("id" integer primary key autoincrement not null, "store_id" integer not null, "title" varchar not null, "handle" varchar not null, "body_html" text, "status" varchar check ("status" in ('draft', 'published', 'archived')) not null default 'draft', "published_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)

payments

CREATE TABLE "payments" ("id" integer primary key autoincrement not null, "order_id" integer not null, "provider" varchar check ("provider" in ('mock')) not null default 'mock', "method" varchar check ("method" in ('credit_card', 'paypal', 'bank_transfer')) not null, "provider_payment_id" varchar, "status" varchar check ("status" in ('pending', 'captured', 'failed', 'refunded')) not null default 'pending', "amount" integer not null default '0', "currency" varchar not null default 'USD', "raw_json_encrypted" text, "created_at" datetime, "updated_at" datetime, foreign key("order_id") references "orders"("id") on delete cascade)

CREATE TABLE "product_media" ("id" integer primary key autoincrement not null, "product_id" integer not null, "type" varchar check ("type" in ('image', 'video')) not null default 'image', "storage_key" varchar not null, "alt_text" varchar, "width" integer, "height" integer, "mime_type" varchar, "byte_size" integer, "position" integer not null default '0', "status" varchar check ("status" in ('processing', 'ready', 'failed')) not null default 'processing', "created_at" datetime, foreign key("product_id") references "products"("id") on delete cascade)

CREATE TABLE "product_variants" ("id" integer primary key autoincrement not null, "product_id" integer not null, "sku" varchar, "barcode" varchar, "price_amount" integer not null default '0', "compare_at_amount" integer, "currency" varchar not null default 'USD', "weight_g" integer, "requires_shipping" tinyint(1) not null default '1', "is_default" tinyint(1) not null default '0', "position" integer not null default '0', "status" varchar check ("status" in ('active', 'archived')) not null default 'active', "created_at" datetime, "updated_at" datetime, foreign key("product_id") references "products"("id") on delete cascade)

refunds

CREATE TABLE "refunds" ("id" integer primary key autoincrement not null, "order_id" integer not null, "payment_id" integer not null, "amount" integer not null default '0', "reason" varchar, "status" varchar check ("status" in ('pending', 'processed', 'failed')) not null default 'pending', "provider_refund_id" varchar, "created_at" datetime, "updated_at" datetime, foreign key("order_id") references "orders"("id") on delete cascade, foreign key("payment_id") references "payments"("id") on delete cascade)

CREATE TABLE "shipping_rates" ("id" integer primary key autoincrement not null, "zone_id" integer not null, "name" varchar not null, "type" varchar check ("type" in ('flat', 'weight', 'price', 'carrier')) not null default 'flat', "config_json" text not null default '{}', "is_active" tinyint(1) not null default '1', foreign key("zone_id") references "shipping_zones"("id") on delete cascade)

CREATE TABLE "store_domains" ("id" integer primary key autoincrement not null, "store_id" integer not null, "hostname" varchar not null, "type" varchar check ("type" in ('storefront', 'admin', 'api')) not null default 'storefront', "is_primary" tinyint(1) not null default '0', "tls_mode" varchar check ("tls_mode" in ('managed', 'bring_your_own')) not null default 'managed', "created_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade)

CREATE TABLE "store_users" ("store_id" integer not null, "user_id" integer not null, "role" varchar check ("role" in ('owner', 'admin', 'staff', 'support')) not null default 'staff', "created_at" datetime, foreign key("store_id") references "stores"("id") on delete cascade, foreign key("user_id") references "users"("id") on delete cascade, primary key ("store_id", "user_id"))

CREATE TABLE "tax_settings" ("store_id" integer not null, "mode" varchar check ("mode" in ('manual', 'provider')) not null default 'manual', "provider" varchar check ("provider" in ('stripe_tax', 'none')) not null default 'none', "prices_include_tax" tinyint(1) not null default '0', "config_json" text not null default '{}', foreign key("store_id") references "stores"("id") on delete cascade, primary key ("store_id"))

users

CREATE TABLE "users" ("id" integer primary key autoincrement not null, "email" varchar not null, "password_hash" varchar not null, "name" varchar not null, "status" varchar check ("status" in ('active', 'disabled')) not null default 'active', "email_verified_at" datetime, "last_login_at" datetime, "two_factor_secret" text, "two_factor_recovery_codes" text, "two_factor_confirmed_at" datetime, "remember_token" varchar, "created_at" datetime, "updated_at" datetime)


Output:
Wall time: 0.1792 seconds
Output:
[{"type":"text","text":"[{\"name\":\"carts\",\"sql\":\"CREATE TABLE \\\"carts\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"customer_id\\\" integer, \\\"currency\\\" varchar not null default 'USD', \\\"cart_version\\\" integer not null default '1', \\\"status\\\" varchar check (\\\"status\\\" in ('active', 'converted', 'abandoned')) not null default 'active', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"customer_id\\\") references \\\"customers\\\"(\\\"id\\\") on delete set null)\"},{\"name\":\"checkouts\",\"sql\":\"CREATE TABLE \\\"checkouts\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"cart_id\\\" integer not null, \\\"customer_id\\\" integer, \\\"status\\\" varchar check (\\\"status\\\" in ('started', 'addressed', 'shipping_selected', 'payment_selected', 'completed', 'expired')) not null default 'started', \\\"payment_method\\\" varchar check (\\\"payment_method\\\" in ('credit_card', 'paypal', 'bank_transfer')), \\\"email\\\" varchar, \\\"shipping_address_json\\\" text, \\\"billing_address_json\\\" text, \\\"shipping_method_id\\\" integer, \\\"discount_code\\\" varchar, \\\"tax_provider_snapshot_json\\\" text, \\\"totals_json\\\" text, \\\"expires_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"cart_id\\\") references \\\"carts\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"customer_id\\\") references \\\"customers\\\"(\\\"id\\\") on delete set null)\"},{\"name\":\"collections\",\"sql\":\"CREATE TABLE \\\"collections\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"title\\\" varchar not null, \\\"handle\\\" varchar not null, \\\"description_html\\\" text, \\\"type\\\" varchar check (\\\"type\\\" in ('manual', 'automated')) not null default 'manual', \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'active', 'archived')) not null default 'active', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"data_exports\",\"sql\":\"CREATE TABLE \\\"data_exports\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"type\\\" varchar not null default 'orders', \\\"format\\\" varchar not null default 'csv', \\\"status\\\" varchar check (\\\"status\\\" in ('queued', 'processing', 'completed', 'failed')) not null default 'queued', \\\"filters_json\\\" text not null default '{}', \\\"row_count\\\" integer not null default '0', \\\"storage_key\\\" varchar, \\\"error_message\\\" text, \\\"download_expires_at\\\" datetime, \\\"completed_at\\\" datetime, \\\"failed_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"discounts\",\"sql\":\"CREATE TABLE \\\"discounts\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"type\\\" varchar check (\\\"type\\\" in ('code', 'automatic')) not null default 'code', \\\"code\\\" varchar, \\\"value_type\\\" varchar check (\\\"value_type\\\" in ('fixed', 'percent', 'free_shipping')) not null, \\\"value_amount\\\" integer not null default '0', \\\"starts_at\\\" datetime not null, \\\"ends_at\\\" datetime, \\\"usage_limit\\\" integer, \\\"usage_count\\\" integer not null default '0', \\\"rules_json\\\" text not null default '{}', \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'active', 'expired', 'disabled')) not null default 'active', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"fulfillments\",\"sql\":\"CREATE TABLE \\\"fulfillments\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"order_id\\\" integer not null, \\\"status\\\" varchar check (\\\"status\\\" in ('pending', 'shipped', 'delivered')) not null default 'pending', \\\"tracking_company\\\" varchar, \\\"tracking_number\\\" varchar, \\\"tracking_url\\\" varchar, \\\"shipped_at\\\" datetime, \\\"delivered_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"order_id\\\") references \\\"orders\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"inventory_items\",\"sql\":\"CREATE TABLE \\\"inventory_items\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"variant_id\\\" integer not null, \\\"quantity_on_hand\\\" integer not null default '0', \\\"quantity_reserved\\\" integer not null default '0', \\\"policy\\\" varchar check (\\\"policy\\\" in ('deny', 'continue')) not null default 'deny', foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"variant_id\\\") references \\\"product_variants\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"orders\",\"sql\":\"CREATE TABLE \\\"orders\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"checkout_id\\\" integer, \\\"customer_id\\\" integer, \\\"order_number\\\" varchar not null, \\\"payment_method\\\" varchar check (\\\"payment_method\\\" in ('credit_card', 'paypal', 'bank_transfer')) not null, \\\"status\\\" varchar check (\\\"status\\\" in ('pending', 'paid', 'fulfilled', 'cancelled', 'refunded')) not null default 'pending', \\\"financial_status\\\" varchar check (\\\"financial_status\\\" in ('pending', 'authorized', 'paid', 'partially_refunded', 'refunded', 'voided')) not null default 'pending', \\\"fulfillment_status\\\" varchar check (\\\"fulfillment_status\\\" in ('unfulfilled', 'partial', 'fulfilled')) not null default 'unfulfilled', \\\"currency\\\" varchar not null default 'USD', \\\"subtotal_amount\\\" integer not null default '0', \\\"discount_amount\\\" integer not null default '0', \\\"shipping_amount\\\" integer not null default '0', \\\"tax_amount\\\" integer not null default '0', \\\"total_amount\\\" integer not null default '0', \\\"email\\\" varchar, \\\"billing_address_json\\\" text, \\\"shipping_address_json\\\" text, \\\"placed_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"checkout_id\\\") references \\\"checkouts\\\"(\\\"id\\\") on delete set null, foreign key(\\\"customer_id\\\") references \\\"customers\\\"(\\\"id\\\") on delete set null)\"},{\"name\":\"pages\",\"sql\":\"CREATE TABLE \\\"pages\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"title\\\" varchar not null, \\\"handle\\\" varchar not null, \\\"body_html\\\" text, \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'published', 'archived')) not null default 'draft', \\\"published_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"payments\",\"sql\":\"CREATE TABLE \\\"payments\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"order_id\\\" integer not null, \\\"provider\\\" varchar check (\\\"provider\\\" in ('mock')) not null default 'mock', \\\"method\\\" varchar check (\\\"method\\\" in ('credit_card', 'paypal', 'bank_transfer')) not null, \\\"provider_payment_id\\\" varchar, \\\"status\\\" varchar check (\\\"status\\\" in ('pending', 'captured', 'failed', 'refunded')) not null default 'pending', \\\"amount\\\" integer not null default '0', \\\"currency\\\" varchar not null default 'USD', \\\"raw_json_encrypted\\\" text, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"order_id\\\") references \\\"orders\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"product_media\",\"sql\":\"CREATE TABLE \\\"product_media\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"product_id\\\" integer not null, \\\"type\\\" varchar check (\\\"type\\\" in ('image', 'video')) not null default 'image', \\\"storage_key\\\" varchar not null, \\\"alt_text\\\" varchar, \\\"width\\\" integer, \\\"height\\\" integer, \\\"mime_type\\\" varchar, \\\"byte_size\\\" integer, \\\"position\\\" integer not null default '0', \\\"status\\\" varchar check (\\\"status\\\" in ('processing', 'ready', 'failed')) not null default 'processing', \\\"created_at\\\" datetime, foreign key(\\\"product_id\\\") references \\\"products\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"product_variants\",\"sql\":\"CREATE TABLE \\\"product_variants\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"product_id\\\" integer not null, \\\"sku\\\" varchar, \\\"barcode\\\" varchar, \\\"price_amount\\\" integer not null default '0', \\\"compare_at_amount\\\" integer, \\\"currency\\\" varchar not null default 'USD', \\\"weight_g\\\" integer, \\\"requires_shipping\\\" tinyint(1) not null default '1', \\\"is_default\\\" tinyint(1) not null default '0', \\\"position\\\" integer not null default '0', \\\"status\\\" varchar check (\\\"status\\\" in ('active', 'archived')) not null default 'active', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"product_id\\\") references \\\"products\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"products\",\"sql\":\"CREATE TABLE \\\"products\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"title\\\" varchar not null, \\\"handle\\\" varchar not null, \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'active', 'archived')) not null default 'draft', \\\"description_html\\\" text, \\\"vendor\\\" varchar, \\\"product_type\\\" varchar, \\\"tags\\\" text not null default '[]', \\\"published_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"refunds\",\"sql\":\"CREATE TABLE \\\"refunds\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"order_id\\\" integer not null, \\\"payment_id\\\" integer not null, \\\"amount\\\" integer not null default '0', \\\"reason\\\" varchar, \\\"status\\\" varchar check (\\\"status\\\" in ('pending', 'processed', 'failed')) not null default 'pending', \\\"provider_refund_id\\\" varchar, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"order_id\\\") references \\\"orders\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"payment_id\\\") references \\\"payments\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"shipping_rates\",\"sql\":\"CREATE TABLE \\\"shipping_rates\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"zone_id\\\" integer not null, \\\"name\\\" varchar not null, \\\"type\\\" varchar check (\\\"type\\\" in ('flat', 'weight', 'price', 'carrier')) not null default 'flat', \\\"config_json\\\" text not null default '{}', \\\"is_active\\\" tinyint(1) not null default '1', foreign key(\\\"zone_id\\\") references \\\"shipping_zones\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"store_domains\",\"sql\":\"CREATE TABLE \\\"store_domains\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"hostname\\\" varchar not null, \\\"type\\\" varchar check (\\\"type\\\" in ('storefront', 'admin', 'api')) not null default 'storefront', \\\"is_primary\\\" tinyint(1) not null default '0', \\\"tls_mode\\\" varchar check (\\\"tls_mode\\\" in ('managed', 'bring_your_own')) not null default 'managed', \\\"created_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"store_users\",\"sql\":\"CREATE TABLE \\\"store_users\\\" (\\\"store_id\\\" integer not null, \\\"user_id\\\" integer not null, \\\"role\\\" varchar check (\\\"role\\\" in ('owner', 'admin', 'staff', 'support')) not null default 'staff', \\\"created_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, foreign key(\\\"user_id\\\") references \\\"users\\\"(\\\"id\\\") on delete cascade, primary key (\\\"store_id\\\", \\\"user_id\\\"))\"},{\"name\":\"stores\",\"sql\":\"CREATE TABLE \\\"stores\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"organization_id\\\" integer not null, \\\"name\\\" varchar not null, \\\"handle\\\" varchar not null, \\\"status\\\" varchar check (\\\"status\\\" in ('active', 'suspended')) not null default 'active', \\\"default_currency\\\" varchar not null default 'USD', \\\"default_locale\\\" varchar not null default 'en', \\\"timezone\\\" varchar not null default 'UTC', \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"organization_id\\\") references \\\"organizations\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"tax_settings\",\"sql\":\"CREATE TABLE \\\"tax_settings\\\" (\\\"store_id\\\" integer not null, \\\"mode\\\" varchar check (\\\"mode\\\" in ('manual', 'provider')) not null default 'manual', \\\"provider\\\" varchar check (\\\"provider\\\" in ('stripe_tax', 'none')) not null default 'none', \\\"prices_include_tax\\\" tinyint(1) not null default '0', \\\"config_json\\\" text not null default '{}', foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade, primary key (\\\"store_id\\\"))\"},{\"name\":\"themes\",\"sql\":\"CREATE TABLE \\\"themes\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"store_id\\\" integer not null, \\\"name\\\" varchar not null, \\\"version\\\" varchar, \\\"status\\\" varchar check (\\\"status\\\" in ('draft', 'published')) not null default 'draft', \\\"published_at\\\" datetime, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime, foreign key(\\\"store_id\\\") references \\\"stores\\\"(\\\"id\\\") on delete cascade)\"},{\"name\":\"users\",\"sql\":\"CREATE TABLE \\\"users\\\" (\\\"id\\\" integer primary key autoincrement not null, \\\"email\\\" varchar not null, \\\"password_hash\\\" varchar not null, \\\"name\\\" varchar not null, \\\"status\\\" varchar check (\\\"status\\\" in ('active', 'disabled')) not null default 'active', \\\"email_verified_at\\\" datetime, \\\"last_login_at\\\" datetime, \\\"two_factor_secret\\\" text, \\\"two_factor_recovery_codes\\\" text, \\\"two_factor_confirmed_at\\\" datetime, \\\"remember_token\\\" varchar, \\\"created_at\\\" datetime, \\\"updated_at\\\" datetime)\"}]"}]


rg -n "forgot-password|reset-password|account/forgot|account/reset" specs/02-API-ROUTES.md specs/04-STOREFRONT-UI.md specs/06-AUTH-AND-SECURITY.md specs/09-IMPLEMENTATION-ROADMAP.md


rg -n "forgot-password|reset-password|account/forgot|account/reset" specs/02-API-ROUTES.md specs/04-STOREFRONT-UI.md specs/06-AUTH-AND-SECURITY.md specs/09-IMPLEMENTATION-ROADMAP.md

rg -n 'forgot-password|reset-password|account/forgot|account/reset' specs/02-API-ROUTES.md specs/04-STOREFRONT-UI.md specs/06-AUTH-AND-SECURITY.md specs/09-IMPLEMENTATION-ROADMAP.md

Question: forgot-password|reset-password|account/forgot|account/reset

specs/06-AUTH-AND-SECURITY.md:75:    B->>App: GET /admin/forgot-password
specs/06-AUTH-AND-SECURITY.md:76:    App-->>B: Render forgot-password form
specs/06-AUTH-AND-SECURITY.md:77:    B->>App: POST /admin/forgot-password (email)
specs/06-AUTH-AND-SECURITY.md:84:    B->>App: GET /admin/reset-password/{token}
specs/06-AUTH-AND-SECURITY.md:85:    App-->>B: Render reset-password form
specs/06-AUTH-AND-SECURITY.md:86:    B->>App: POST /admin/reset-password (token, email, password, password_confirmation)
specs/06-AUTH-AND-SECURITY.md:199:- Routes: `GET /forgot-password`, `POST /forgot-password`, `GET /reset-password/{token}`, `POST /reset-password`.
specs/06-AUTH-AND-SECURITY.md:611:| Admin web (auth pages) | `web` | Login, forgot-password, reset-password |
specs/02-API-ROUTES.md:20:| GET | `/admin/forgot-password` | Show forgot password form | `Livewire: Admin\Auth\ForgotPassword` |
specs/02-API-ROUTES.md:21:| POST | `/admin/forgot-password` | Send password reset link | Handled by Livewire action |
specs/02-API-ROUTES.md:22:| GET | `/admin/reset-password/{token}` | Show reset password form | `Livewire: Admin\Auth\ResetPassword` |
specs/02-API-ROUTES.md:23:| POST | `/admin/reset-password` | Reset password with token | Handled by Livewire action |
specs/02-API-ROUTES.md:179:| GET | `/forgot-password` | Forgot password page | `Storefront\Account\Auth\ForgotPassword` |
specs/02-API-ROUTES.md:180:| POST | `/forgot-password` | Send reset link | Handled by Livewire action |
specs/02-API-ROUTES.md:181:| GET | `/reset-password/{token}` | Reset password form | `Storefront\Account\Auth\ResetPassword` |
specs/02-API-ROUTES.md:182:| POST | `/reset-password` | Reset password | Handled by Livewire action |


Output:
Chunk ID: eb5b5b
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 430
Output:
specs/06-AUTH-AND-SECURITY.md:75:    B->>App: GET /admin/forgot-password
specs/06-AUTH-AND-SECURITY.md:76:    App-->>B: Render forgot-password form
specs/06-AUTH-AND-SECURITY.md:77:    B->>App: POST /admin/forgot-password (email)
specs/06-AUTH-AND-SECURITY.md:84:    B->>App: GET /admin/reset-password/{token}
specs/06-AUTH-AND-SECURITY.md:85:    App-->>B: Render reset-password form
specs/06-AUTH-AND-SECURITY.md:86:    B->>App: POST /admin/reset-password (token, email, password, password_confirmation)
specs/06-AUTH-AND-SECURITY.md:199:- Routes: `GET /forgot-password`, `POST /forgot-password`, `GET /reset-password/{token}`, `POST /reset-password`.
specs/06-AUTH-AND-SECURITY.md:611:| Admin web (auth pages) | `web` | Login, forgot-password, reset-password |
specs/02-API-ROUTES.md:20:| GET | `/admin/forgot-password` | Show forgot password form | `Livewire: Admin\Auth\ForgotPassword` |
specs/02-API-ROUTES.md:21:| POST | `/admin/forgot-password` | Send password reset link | Handled by Livewire action |
specs/02-API-ROUTES.md:22:| GET | `/admin/reset-password/{token}` | Show reset password form | `Livewire: Admin\Auth\ResetPassword` |
specs/02-API-ROUTES.md:23:| POST | `/admin/reset-password` | Reset password with token | Handled by Livewire action |
specs/02-API-ROUTES.md:179:| GET | `/forgot-password` | Forgot password page | `Storefront\Account\Auth\ForgotPassword` |
specs/02-API-ROUTES.md:180:| POST | `/forgot-password` | Send reset link | Handled by Livewire action |
specs/02-API-ROUTES.md:181:| GET | `/reset-password/{token}` | Reset password form | `Storefront\Account\Auth\ResetPassword` |
specs/02-API-ROUTES.md:182:| POST | `/reset-password` | Reset password | Handled by Livewire action |


find app/Livewire/Auth app/Livewire/Admin/Auth -type f -maxdepth 2 -print -exec sed -n '1,200p' {} \;


sed -n '1,140p' tests/Feature/Auth/PasswordResetTest.php


sed -n '1,220p' app/Providers/FortifyServiceProvider.php


find app/Livewire/Auth app/Livewire/Admin/Auth -type f -maxdepth 2 -print -exec sed -n '1,200p' {} \;

find app/Livewire/Auth app/Livewire/Admin/Auth -type f -maxdepth 2 -print -exec sed -n '1,200p' '{}' "\\;"

find: app/Livewire/Auth: No such file or directory
app/Livewire/Admin/Auth/Login.php
<?php

namespace App\Livewire\Admin\Auth;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function login(): void
    {
        $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'remember' => ['boolean'],
        ]);

        $key = 'admin-login:'.request()->ip();

        if (RateLimiter::tooManyAttempts($key, 5)) {
            throw ValidationException::withMessages([
                'email' => __('Too many attempts. Try again in :seconds seconds.', [
                    'seconds' => RateLimiter::availableIn($key),
                ]),
            ]);
        }

        if (! Auth::guard('web')->attempt([
            'email' => $this->email,
            'password' => $this->password,
            'status' => 'active',
        ], $this->remember)) {
            RateLimiter::hit($key, 60);

            throw ValidationException::withMessages([
                'email' => __('Invalid credentials'),
            ]);
        }

        RateLimiter::clear($key);

        if (request()->hasSession()) {
            request()->session()->regenerate();
        }

        Auth::user()?->forceFill(['last_login_at' => now()])->save();

        $this->redirectRoute('admin.dashboard', navigate: true);
    }

    public function render(): mixed
    {
        return view('livewire.admin.auth.login')
            ->layout('layouts.auth');
    }
}


sed -n '1,140p' tests/Feature/Auth/PasswordResetTest.php

<?php

use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Notification;

uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);

test('reset password link screen can be rendered', function () {
    $response = $this->get(route('password.request'));

    $response->assertOk();
});

test('reset password link can be requested', function () {
    Notification::fake();

    $user = User::factory()->create();

    $this->post(route('password.request'), ['email' => $user->email]);

    Notification::assertSentTo($user, ResetPassword::class);
});

test('reset password screen can be rendered', function () {
    Notification::fake();

    $user = User::factory()->create();

    $this->post(route('password.request'), ['email' => $user->email]);

    Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
        $response = $this->get(route('password.reset', $notification->token));
        $response->assertOk();

        return true;
    });
});

test('password can be reset with valid token', function () {
    Notification::fake();

    $user = User::factory()->create();

    $this->post(route('password.request'), ['email' => $user->email]);

    Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
        $response = $this->post(route('password.update'), [
            'token' => $notification->token,
            'email' => $user->email,
            'password' => 'password',
            'password_confirmation' => 'password',
        ]);

        $response
            ->assertSessionHasNoErrors()
            ->assertRedirect(route('login', absolute: false));

        return true;
    });
});


sed -n '1,220p' app/Providers/FortifyServiceProvider.php

<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->configureActions();
        $this->configureViews();
        $this->configureRateLimiting();
    }

    /**
     * Configure Fortify actions.
     */
    private function configureActions(): void
    {
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
        Fortify::createUsersUsing(CreateNewUser::class);
    }

    /**
     * Configure Fortify views.
     */
    private function configureViews(): void
    {
        Fortify::loginView(fn () => view('livewire.auth.login'));
        Fortify::verifyEmailView(fn () => view('livewire.auth.verify-email'));
        Fortify::twoFactorChallengeView(fn () => view('livewire.auth.two-factor-challenge'));
        Fortify::confirmPasswordView(fn () => view('livewire.auth.confirm-password'));
        Fortify::registerView(fn () => view('livewire.auth.register'));
        Fortify::resetPasswordView(fn () => view('livewire.auth.reset-password'));
        Fortify::requestPasswordResetLinkView(fn () => view('livewire.auth.forgot-password'));
    }

    /**
     * Configure rate limiting.
     */
    private function configureRateLimiting(): void
    {
        RateLimiter::for('two-factor', function (Request $request) {
            return Limit::perMinute(5)->by($request->session()->get('login.id'));
        });

        RateLimiter::for('login', function (Request $request) {
            return Limit::perMinute(5)->by($request->ip());
        });
    }
}


/bin/zsh
-lc
sed -n '35,112p' config/fortify.php

    | Username / Email
    |--------------------------------------------------------------------------
    |
    | This value defines which model attribute should be considered as your
    | application's "username" field. Typically, this might be the email
    | address of the users but you are free to change this value here.
    |
    | Out of the box, Fortify expects forgot password and reset password
    | requests to have a field named 'email'. If the application uses
    | another name for the field you may define it below as needed.
    |
    */

    'username' => 'email',

    'email' => 'email',

    /*
    |--------------------------------------------------------------------------
    | Lowercase Usernames
    |--------------------------------------------------------------------------
    |
    | This value defines whether usernames should be lowercased before saving
    | them in the database, as some database system string fields are case
    | sensitive. You may disable this for your application if necessary.
    |
    */

    'lowercase_usernames' => true,

    /*
    |--------------------------------------------------------------------------
    | Home Path
    |--------------------------------------------------------------------------
    |
    | Here you may configure the path where users will get redirected during
    | authentication or password reset when the operations are successful
    | and the user is authenticated. You are free to change this value.
    |
    */

    'home' => '/admin',

    /*
    |--------------------------------------------------------------------------
    | Fortify Routes Prefix / Subdomain
    |--------------------------------------------------------------------------
    |
    | Here you may specify which prefix Fortify will assign to all the routes
    | that it registers with the application. If necessary, you may change
    | subdomain under which all of the Fortify routes will be available.
    |
    */

    'prefix' => '',

    'domain' => null,

    /*
    |--------------------------------------------------------------------------
    | Fortify Routes Middleware
    |--------------------------------------------------------------------------
    |
    | Here you may specify which middleware Fortify will assign to the routes
    | that it registers with the application. If necessary, you may change
    | these middleware but typically this provided default is preferred.
    |
    */

    'middleware' => ['web'],

    /*
    |--------------------------------------------------------------------------
    | Rate Limiting
    |--------------------------------------------------------------------------
    |
    | By default, Fortify will throttle logins to five requests per minute for
    | every email and IP address combination. However, if you would like to


Output:
Chunk ID: 3dc834
Wall time: 0.0000 seconds
Process exited with code 1
Original token count: 440
Output:
find: app/Livewire/Auth: No such file or directory
app/Livewire/Admin/Auth/Login.php
<?php

namespace App\Livewire\Admin\Auth;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function login(): void
    {
        $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'remember' => ['boolean'],
        ]);

        $key = 'admin-login:'.request()->ip();

        if (RateLimiter::tooManyAttempts($key, 5)) {
            throw ValidationException::withMessages([
                'email' => __('Too many attempts. Try again in :seconds seconds.', [
                    'seconds' => RateLimiter::availableIn($key),
                ]),
            ]);
        }

        if (! Auth::guard('web')->attempt([
            'email' => $this->email,
            'password' => $this->password,
            'status' => 'active',
        ], $this->remember)) {
            RateLimiter::hit($key, 60);

            throw ValidationException::withMessages([
                'email' => __('Invalid credentials'),
            ]);
        }

        RateLimiter::clear($key);

        if (request()->hasSession()) {
            request()->session()->regenerate();
        }

        Auth::user()?->forceFill(['last_login_at' => now()])->save();

        $this->redirectRoute('admin.dashboard', navigate: true);
    }

    public function render(): mixed
    {
        return view('livewire.admin.auth.login')
            ->layout('layouts.auth');
    }
}


Output:
Chunk ID: b1d972
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 433
Output:
<?php

use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Notification;

uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);

test('reset password link screen can be rendered', function () {
    $response = $this->get(route('password.request'));

    $response->assertOk();
});

test('reset password link can be requested', function () {
    Notification::fake();

    $user = User::factory()->create();

    $this->post(route('password.request'), ['email' => $user->email]);

    Notification::assertSentTo($user, ResetPassword::class);
});

test('reset password screen can be rendered', function () {
    Notification::fake();

    $user = User::factory()->create();

    $this->post(route('password.request'), ['email' => $user->email]);

    Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
        $response = $this->get(route('password.reset', $notification->token));
        $response->assertOk();

        return true;
    });
});

test('password can be reset with valid token', function () {
    Notification::fake();

    $user = User::factory()->create();

    $this->post(route('password.request'), ['email' => $user->email]);

    Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
        $response = $this->post(route('password.update'), [
            'token' => $notification->token,
            'email' => $user->email,
            'password' => 'password',
            'password_confirmation' => 'password',
        ]);

        $response
            ->assertSessionHasNoErrors()
            ->assertRedirect(route('login', absolute: false));

        return true;
    });
});


Output:
Chunk ID: 819dcb
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 504
Output:
<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->configureActions();
        $this->configureViews();
        $this->configureRateLimiting();
    }

    /**
     * Configure Fortify actions.
     */
    private function configureActions(): void
    {
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
        Fortify::createUsersUsing(CreateNewUser::class);
    }

    /**
     * Configure Fortify views.
     */
    private function configureViews(): void
    {
        Fortify::loginView(fn () => view('livewire.auth.login'));
        Fortify::verifyEmailView(fn () => view('livewire.auth.verify-email'));
        Fortify::twoFactorChallengeView(fn () => view('livewire.auth.two-factor-challenge'));
        Fortify::confirmPasswordView(fn () => view('livewire.auth.confirm-password'));
        Fortify::registerView(fn () => view('livewire.auth.register'));
        Fortify::resetPasswordView(fn () => view('livewire.auth.reset-password'));
        Fortify::requestPasswordResetLinkView(fn () => view('livewire.auth.forgot-password'));
    }

    /**
     * Configure rate limiting.
     */
    private function configureRateLimiting(): void
    {
        RateLimiter::for('two-factor', function (Request $request) {
            return Limit::perMinute(5)->by($request->session()->get('login.id'));
        });

        RateLimiter::for('login', function (Request $request) {
            return Limit::perMinute(5)->by($request->ip());
        });
    }
}


Output:
Chunk ID: be123d
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 715
Output:
    | Username / Email
    |--------------------------------------------------------------------------
    |
    | This value defines which model attribute should be considered as your
    | application's "username" field. Typically, this might be the email
    | address of the users but you are free to change this value here.
    |
    | Out of the box, Fortify expects forgot password and reset password
    | requests to have a field named 'email'. If the application uses
    | another name for the field you may define it below as needed.
    |
    */

    'username' => 'email',

    'email' => 'email',

    /*
    |--------------------------------------------------------------------------
    | Lowercase Usernames
    |--------------------------------------------------------------------------
    |
    | This value defines whether usernames should be lowercased before saving
    | them in the database, as some database system string fields are case
    | sensitive. You may disable this for your application if necessary.
    |
    */

    'lowercase_usernames' => true,

    /*
    |--------------------------------------------------------------------------
    | Home Path
    |--------------------------------------------------------------------------
    |
    | Here you may configure the path where users will get redirected during
    | authentication or password reset when the operations are successful
    | and the user is authenticated. You are free to change this value.
    |
    */

    'home' => '/admin',

    /*
    |--------------------------------------------------------------------------
    | Fortify Routes Prefix / Subdomain
    |--------------------------------------------------------------------------
    |
    | Here you may specify which prefix Fortify will assign to all the routes
    | that it registers with the application. If necessary, you may change
    | subdomain under which all of the Fortify routes will be available.
    |
    */

    'prefix' => '',

    'domain' => null,

    /*
    |--------------------------------------------------------------------------
    | Fortify Routes Middleware
    |--------------------------------------------------------------------------
    |
    | Here you may specify which middleware Fortify will assign to the routes
    | that it registers with the application. If necessary, you may change
    | these middleware but typically this provided default is preferred.
    |
    */

    'middleware' => ['web'],

    /*
    |--------------------------------------------------------------------------
    | Rate Limiting
    |--------------------------------------------------------------------------
    |
    | By default, Fortify will throttle logins to five requests per minute for
    | every email and IP address combination. However, if you would like to


assert database schema column check constraint