command: rg "CustomerAddress|customer_addresses|Address" app resources tests database -n

cmd: rg 'CustomerAddress|customer_addresses|Address' app resources tests database -n

query: CustomerAddress|customer_addresses|Address

path: app

aggregated_output:
database/factories/OrderFactory.php:145:            'address1' => fake()->streetAddress(),
database/factories/CustomerAddressFactory.php:9: * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CustomerAddress>
database/factories/CustomerAddressFactory.php:11:class CustomerAddressFactory extends Factory
database/factories/CustomerAddressFactory.php:26:                'address1' => fake()->streetAddress(),
tests/Feature/Api/StorefrontCheckoutApiTest.php:50:function storefrontApiCheckoutAddress(string $country = 'DE'): array
tests/Feature/Api/StorefrontCheckoutApiTest.php:97:            'shipping_address' => storefrontApiCheckoutAddress(),
tests/Feature/Api/StorefrontCheckoutApiTest.php:169:            'shipping_address' => array_diff_key(storefrontApiCheckoutAddress(), ['first_name' => true]),
tests/Feature/Api/StorefrontCheckoutApiTest.php:176:            'shipping_address' => storefrontApiCheckoutAddress(),
tests/Feature/Orders/OrderServiceTest.php:122:    $checkout = app(CheckoutService::class)->setAddress($checkout, [
tests/Feature/Checkout/CheckoutServiceTest.php:5:use App\Exceptions\UnserviceableShippingAddressException;
tests/Feature/Checkout/CheckoutServiceTest.php:60:function checkoutAddress(string $country = 'DE'): array
tests/Feature/Checkout/CheckoutServiceTest.php:95:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Checkout/CheckoutServiceTest.php:96:    expect($checkout->status)->toBe(CheckoutStatus::Addressed)
tests/Feature/Checkout/CheckoutServiceTest.php:128:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress('FR'));
tests/Feature/Checkout/CheckoutServiceTest.php:131:        ->toThrow(UnserviceableShippingAddressException::class);
tests/Feature/Checkout/CheckoutServiceTest.php:140:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Checkout/CheckoutServiceTest.php:167:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Checkout/CheckoutServiceTest.php:197:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Api/AdminCatalogApiTest.php:4:use App\Models\CustomerAddress;
tests/Feature/Api/AdminCatalogApiTest.php:88:    CustomerAddress::factory()->default()->create(['customer_id' => $customer->getKey()]);
tests/Browser/Storefront/CheckoutTest.php:44:function storefrontCheckoutFillAddress(mixed $page, array $overrides = []): mixed
tests/Browser/Storefront/CheckoutTest.php:60:        ->fill('input[wire\\:model="shippingAddress.first_name"]', $address['first_name'])
tests/Browser/Storefront/CheckoutTest.php:61:        ->fill('input[wire\\:model="shippingAddress.last_name"]', $address['last_name'])
tests/Browser/Storefront/CheckoutTest.php:62:        ->fill('input[wire\\:model="shippingAddress.address1"]', $address['address1'])
tests/Browser/Storefront/CheckoutTest.php:63:        ->fill('input[wire\\:model="shippingAddress.city"]', $address['city'])
tests/Browser/Storefront/CheckoutTest.php:64:        ->fill('input[wire\\:model="shippingAddress.postal_code"]', $address['postal_code'])
tests/Browser/Storefront/CheckoutTest.php:65:        ->select('select[wire\\:model="shippingAddress.country"]', $address['country']);
tests/Browser/Storefront/CheckoutTest.php:68:function storefrontCheckoutSubmitAddress(mixed $page): mixed
tests/Browser/Storefront/CheckoutTest.php:71:        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
tests/Browser/Storefront/CheckoutTest.php:77:    return storefrontCheckoutSubmitAddress(
tests/Browser/Storefront/CheckoutTest.php:78:        storefrontCheckoutFillAddress(storefrontCheckoutStart(), $address),
tests/Browser/Storefront/CheckoutTest.php:166:    storefrontCheckoutSubmitAddress(storefrontCheckoutFillAddress($page))
tests/Browser/Storefront/CheckoutTest.php:179:        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
tests/Browser/Storefront/CheckoutTest.php:188:        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
tests/Browser/Storefront/CheckoutTest.php:199:    storefrontCheckoutSubmitAddress(storefrontCheckoutFillAddress(storefrontCheckoutStart(), [
database/seeders/CustomerAddressSeeder.php:7:class CustomerAddressSeeder extends Seeder
tests/Feature/Storefront/OrderViewsTest.php:68:        ->set('shippingAddress.first_name', 'Test')
tests/Feature/Storefront/OrderViewsTest.php:69:        ->set('shippingAddress.last_name', 'Buyer')
tests/Feature/Storefront/OrderViewsTest.php:70:        ->set('shippingAddress.address1', 'Main Street 1')
tests/Feature/Storefront/OrderViewsTest.php:71:        ->set('shippingAddress.city', 'Berlin')
tests/Feature/Storefront/OrderViewsTest.php:72:        ->set('shippingAddress.country', 'DE')
tests/Feature/Storefront/OrderViewsTest.php:73:        ->set('shippingAddress.postal_code', '10115')
tests/Feature/Storefront/OrderViewsTest.php:74:      …11878 chars truncated…json ?? []);
app/Livewire/Admin/Customers/Show.php:69:            $this->resetAddressForm();
app/Livewire/Admin/Customers/Show.php:75:    public function saveAddress(): void
app/Livewire/Admin/Customers/Show.php:89:        $address = $this->editingAddressId
app/Livewire/Admin/Customers/Show.php:90:            ? $this->address($this->editingAddressId)
app/Livewire/Admin/Customers/Show.php:91:            : new CustomerAddress(['customer_id' => $this->customerId]);
app/Livewire/Admin/Customers/Show.php:100:        $this->resetAddressForm();
app/Livewire/Admin/Customers/Show.php:102:        $this->dispatch('toast', type: 'success', message: __('Address saved'));
app/Livewire/Admin/Customers/Show.php:105:    public function deleteAddress(int $addressId): void
app/Livewire/Admin/Customers/Show.php:112:            $this->setFirstAddressAsDefault();
app/Livewire/Admin/Customers/Show.php:115:        $this->dispatch('toast', type: 'success', message: __('Address deleted'));
app/Livewire/Admin/Customers/Show.php:118:    public function setDefaultAddress(int $addressId): void
app/Livewire/Admin/Customers/Show.php:123:            CustomerAddress::query()
app/Livewire/Admin/Customers/Show.php:164:    private function address(int $addressId): CustomerAddress
app/Livewire/Admin/Customers/Show.php:166:        return CustomerAddress::query()
app/Livewire/Admin/Customers/Show.php:172:    private function setFirstAddressAsDefault(): void
app/Livewire/Admin/Customers/Show.php:174:        $nextAddress = CustomerAddress::query()
app/Livewire/Admin/Customers/Show.php:179:        if ($nextAddress instanceof CustomerAddress) {
app/Livewire/Admin/Customers/Show.php:180:            $nextAddress->forceFill(['is_default' => true])->save();
app/Livewire/Admin/Customers/Show.php:184:    private function resetAddressForm(): void
app/Livewire/Admin/Customers/Show.php:186:        $this->editingAddressId = null;
app/Livewire/Admin/Customers/Show.php:188:        $this->addressJson = $this->emptyAddressJson();
app/Livewire/Admin/Customers/Show.php:194:    private function emptyAddressJson(): array
database/migrations/2026_05_04_000408_create_customer_addresses_table.php:14:        Schema::create('customer_addresses', function (Blueprint $table) {
database/migrations/2026_05_04_000408_create_customer_addresses_table.php:31:        Schema::dropIfExists('customer_addresses');
app/Livewire/Storefront/Cart/Show.php:193:        return app(ShippingCalculator::class)->getAvailableRates($this->store(), $this->shippingAddress());
app/Livewire/Storefront/Cart/Show.php:301:    private function shippingAddress(): array
app/Livewire/Storefront/Checkout/Show.php:9:use App\Exceptions\UnserviceableShippingAddressException;
app/Livewire/Storefront/Checkout/Show.php:39:    public array $shippingAddress = [
app/Livewire/Storefront/Checkout/Show.php:53:    public array $billingAddress = [
app/Livewire/Storefront/Checkout/Show.php:88:    public function saveAddress(): void
app/Livewire/Storefront/Checkout/Show.php:92:            'shippingAddress.first_name' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:93:            'shippingAddress.last_name' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:94:            'shippingAddress.address1' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:95:            'shippingAddress.city' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:96:            'shippingAddress.country' => ['required', 'string', 'size:2'],
app/Livewire/Storefront/Checkout/Show.php:97:            'shippingAddress.postal_code' => [
app/Livewire/Storefront/Checkout/Show.php:101:                    if (strtoupper($this->shippingAddress['country']) === 'DE' && preg_match('/^\d{5}$/', (string) $value) !== 1) {
app/Livewire/Storefront/Checkout/Show.php:116:            $checkout = app(CheckoutService::class)->setAddress($checkout, [
app/Livewire/Storefront/Checkout/Show.php:118:                'shipping_address' => $this->shippingAddress,
app/Livewire/Storefront/Checkout/Show.php:119:                'billing_address' => $this->billingSame ? $this->shippingAddress : $this->billingAddress,
app/Livewire/Storefront/Checkout/Show.php:156:        } catch (InvalidCheckoutTransitionException|UnserviceableShippingAddressException $exception) {
app/Livewire/Storefront/Checkout/Show.php:324:        if ($this->shippingAddress['country'] === '') {
app/Livewire/Storefront/Checkout/Show.php:328:        return app(ShippingCalculator::class)->getAvailableRates($this->store(), $this->shippingAddress);
app/Livewire/Storefront/Checkout/Show.php:413:        $this->shippingAddress = array_replace($this->shippingAddress, $checkout->shipping_address_json ?? []);
app/Livewire/Storefront/Checkout/Show.php:414:        $this->billingAddress = array_replace($this->billingAddress, $checkout->billing_address_json ?? []);
app/Livewire/Storefront/Checkout/Show.php:420:            CheckoutStatus::Addressed => 'shipping',


output:
Chunk ID: 0d9371
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 5470
Output:
database/factories/OrderFactory.php:145:            'address1' => fake()->streetAddress(),
database/factories/CustomerAddressFactory.php:9: * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CustomerAddress>
database/factories/CustomerAddressFactory.php:11:class CustomerAddressFactory extends Factory
database/factories/CustomerAddressFactory.php:26:                'address1' => fake()->streetAddress(),
tests/Feature/Api/StorefrontCheckoutApiTest.php:50:function storefrontApiCheckoutAddress(string $country = 'DE'): array
tests/Feature/Api/StorefrontCheckoutApiTest.php:97:            'shipping_address' => storefrontApiCheckoutAddress(),
tests/Feature/Api/StorefrontCheckoutApiTest.php:169:            'shipping_address' => array_diff_key(storefrontApiCheckoutAddress(), ['first_name' => true]),
tests/Feature/Api/StorefrontCheckoutApiTest.php:176:            'shipping_address' => storefrontApiCheckoutAddress(),
tests/Feature/Orders/OrderServiceTest.php:122:    $checkout = app(CheckoutService::class)->setAddress($checkout, [
tests/Feature/Checkout/CheckoutServiceTest.php:5:use App\Exceptions\UnserviceableShippingAddressException;
tests/Feature/Checkout/CheckoutServiceTest.php:60:function checkoutAddress(string $country = 'DE'): array
tests/Feature/Checkout/CheckoutServiceTest.php:95:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Checkout/CheckoutServiceTest.php:96:    expect($checkout->status)->toBe(CheckoutStatus::Addressed)
tests/Feature/Checkout/CheckoutServiceTest.php:128:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress('FR'));
tests/Feature/Checkout/CheckoutServiceTest.php:131:        ->toThrow(UnserviceableShippingAddressException::class);
tests/Feature/Checkout/CheckoutServiceTest.php:140:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Checkout/CheckoutServiceTest.php:167:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Checkout/CheckoutServiceTest.php:197:    $checkout = app(CheckoutService::class)->setAddress($checkout, checkoutAddress());
tests/Feature/Api/AdminCatalogApiTest.php:4:use App\Models\CustomerAddress;
tests/Feature/Api/AdminCatalogApiTest.php:88:    CustomerAddress::factory()->default()->create(['customer_id' => $customer->getKey()]);
tests/Browser/Storefront/CheckoutTest.php:44:function storefrontCheckoutFillAddress(mixed $page, array $overrides = []): mixed
tests/Browser/Storefront/CheckoutTest.php:60:        ->fill('input[wire\\:model="shippingAddress.first_name"]', $address['first_name'])
tests/Browser/Storefront/CheckoutTest.php:61:        ->fill('input[wire\\:model="shippingAddress.last_name"]', $address['last_name'])
tests/Browser/Storefront/CheckoutTest.php:62:        ->fill('input[wire\\:model="shippingAddress.address1"]', $address['address1'])
tests/Browser/Storefront/CheckoutTest.php:63:        ->fill('input[wire\\:model="shippingAddress.city"]', $address['city'])
tests/Browser/Storefront/CheckoutTest.php:64:        ->fill('input[wire\\:model="shippingAddress.postal_code"]', $address['postal_code'])
tests/Browser/Storefront/CheckoutTest.php:65:        ->select('select[wire\\:model="shippingAddress.country"]', $address['country']);
tests/Browser/Storefront/CheckoutTest.php:68:function storefrontCheckoutSubmitAddress(mixed $page): mixed
tests/Browser/Storefront/CheckoutTest.php:71:        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
tests/Browser/Storefront/CheckoutTest.php:77:    return storefrontCheckoutSubmitAddress(
tests/Browser/Storefront/CheckoutTest.php:78:        storefrontCheckoutFillAddress(storefrontCheckoutStart(), $address),
tests/Browser/Storefront/CheckoutTest.php:166:    storefrontCheckoutSubmitAddress(storefrontCheckoutFillAddress($page))
tests/Browser/Storefront/CheckoutTest.php:179:        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
tests/Browser/Storefront/CheckoutTest.php:188:        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
tests/Browser/Storefront/CheckoutTest.php:199:    storefrontCheckoutSubmitAddress(storefrontCheckoutFillAddress(storefrontCheckoutStart(), [
database/seeders/CustomerAddressSeeder.php:7:class CustomerAddressSeeder extends Seeder
tests/Feature/Storefront/OrderViewsTest.php:68:        ->set('shippingAddress.first_name', 'Test')
tests/Feature/Storefront/OrderViewsTest.php:69:        ->set('shippingAddress.last_name', 'Buyer')
tests/Feature/Storefront/OrderViewsTest.php:70:        ->set('shippingAddress.address1', 'Main Street 1')
tests/Feature/Storefront/OrderViewsTest.php:71:        ->set('shippingAddress.city', 'Berlin')
tests/Feature/Storefront/OrderViewsTest.php:72:        ->set('shippingAddress.country', 'DE')
tests/Feature/Storefront/OrderViewsTest.php:73:        ->set('shippingAddress.postal_code', '10115')
tests/Feature/Storefront/OrderViewsTest.php:74:        ->call('saveAddress')
tests/Feature/Storefront/OrderViewsTest.php:102:        ->set('shippingAddress.first_name', 'Test')
tests/Feature/Storefront/OrderViewsTest.php:103:        ->set('shippingAddress.last_name', 'Buyer')
tests/Feature/Storefront/OrderViewsTest.php:104:        ->set('shippingAddress.address1', 'Main Street 1')
tests/Feature/Storefront/OrderViewsTest.php:105:        ->set('shippingAddress.city', 'Berlin')
tests/Feature/Storefront/OrderViewsTest.php:106:        ->set('shippingAddress.country', 'DE')
tests/Feature/Storefront/OrderViewsTest.php:107:        ->set('shippingAddress.postal_code', '10115')
tests/Feature/Storefront/OrderViewsTest.php:108:        ->call('saveAddress')
tests/Feature/Storefront/CartCheckoutUiTest.php:156:        ->set('shippingAddress.first_name', 'Test')
tests/Feature/Storefront/CartCheckoutUiTest.php:157:        ->set('shippingAddress.last_name', 'Buyer')
tests/Feature/Storefront/CartCheckoutUiTest.php:158:        ->set('shippingAddress.address1', 'Main Street 1')
tests/Feature/Storefront/CartCheckoutUiTest.php:159:        ->set('shippingAddress.city', 'Berlin')
tests/Feature/Storefront/CartCheckoutUiTest.php:160:        ->set('shippingAddress.country', 'DE')
tests/Feature/Storefront/CartCheckoutUiTest.php:161:        ->set('shippingAddress.postal_code', '10115')
tests/Feature/Storefront/CartCheckoutUiTest.php:162:        ->call('saveAddress')
tests/Feature/Admin/CustomerManagementTest.php:6:use App\Models\CustomerAddress;
tests/Feature/Admin/CustomerManagementTest.php:61:    CustomerAddress::factory()->default()->create([
tests/Feature/Admin/CustomerManagementTest.php:115:    $home = CustomerAddress::factory()->default()->create([
tests/Feature/Admin/CustomerManagementTest.php:122:        ->call('openAddressForm')
tests/Feature/Admin/CustomerManagementTest.php:128:        ->call('saveAddress')
tests/Feature/Admin/CustomerManagementTest.php:131:    $office = CustomerAddress::query()
tests/Feature/Admin/CustomerManagementTest.php:140:        ->call('setDefaultAddress', $office->getKey())
tests/Feature/Admin/CustomerManagementTest.php:142:        ->call('openAddressForm', $office->getKey())
tests/Feature/Admin/CustomerManagementTest.php:144:        ->call('saveAddress')
tests/Feature/Admin/CustomerManagementTest.php:146:        ->call('deleteAddress', $home->getKey())
tests/Feature/Admin/CustomerManagementTest.php:151:        ->and(CustomerAddress::query()->whereKey($home->getKey())->exists())->toBeFalse();
tests/Feature/Api/StorefrontOrderApiTest.php:49:function storefrontOrderApiCheckout(object $testCase, string $remoteAddress = '10.0.0.41'): array
tests/Feature/Api/StorefrontOrderApiTest.php:53:    $api = fn () => $testCase->withServerVariables(['REMOTE_ADDR' => $remoteAddress])->withHeader('Host', 'shop.test');
tests/Feature/Admin/SettingsManagementTest.php:126:        ->call('testShippingAddress')
tests/Feature/Admin/SettingsManagementTest.php:148:        ->set('billingAddressEnabled', false)
app/Http/Controllers/Api/Storefront/V1/CheckoutController.php:9:use App\Exceptions\UnserviceableShippingAddressException;
app/Http/Controllers/Api/Storefront/V1/CheckoutController.php:14:use App\Http\Requests\Api\Storefront\V1\SetCheckoutAddressRequest;
app/Http/Controllers/Api/Storefront/V1/CheckoutController.php:55:    public function address(SetCheckoutAddressRequest $request, Checkout $checkout, CheckoutService $checkouts): CheckoutResource|JsonResponse
app/Http/Controllers/Api/Storefront/V1/CheckoutController.php:61:            return CheckoutResource::make($this->loadCheckout($checkouts->setAddress($checkout, $addressData)));
app/Http/Controllers/Api/Storefront/V1/CheckoutController.php:74:        } catch (InvalidCheckoutTransitionException|UnserviceableShippingAddressException $exception) {
resources/views/livewire/auth/login.blade.php:11:
resources/views/livewire/admin/settings/checkout.blade.php:33:                    <flux:switch wire:model="billingAddressEnabled" label="Separate billing address enabled" align="left" />
resources/views/livewire/admin/settings/shipping.blade.php:145:                    <flux:button type="button" wire:click="testShippingAddress" variant="filled">Test</flux:button>
resources/views/livewire/auth/forgot-password.blade.php:11:
resources/views/livewire/auth/forgot-password.blade.php:14:                :label="__('Email Address')"
app/Services/CheckoutService.php:8:use App\Exceptions\UnserviceableShippingAddressException;
app/Services/CheckoutService.php:51:    public function setAddress(Checkout $checkout, array $addressData): Checkout
app/Services/CheckoutService.php:55:            $this->assertStatus($checkout, [CheckoutStatus::Started, CheckoutStatus::Addressed]);
app/Services/CheckoutService.php:58:            $shippingAddress = data_get($addressData, 'shipping_address', $addressData);
app/Services/CheckoutService.php:62:                'shipping_address' => $shippingAddress,
app/Services/CheckoutService.php:75:                'shipping_address_json' => $shippingAddress,
app/Services/CheckoutService.php:76:                'billing_address_json' => data_get($addressData, 'billing_address', $shippingAddress),
app/Services/CheckoutService.php:77:                'status' => CheckoutStatus::Addressed,
app/Services/CheckoutService.php:90:            $this->assertStatus($checkout, [CheckoutStatus::Addressed, CheckoutStatus::ShippingSelected]);
app/Services/CheckoutService.php:106:                throw UnserviceableShippingAddressException::forAddress();
resources/views/livewire/admin/customers/show.blade.php:97:                <flux:heading size="lg">Addresses</flux:heading>
resources/views/livewire/admin/customers/show.blade.php:98:                <flux:button wire:click="openAddressForm" variant="primary" icon="plus" size="sm">Add</flux:button>
resources/views/livewire/admin/customers/show.blade.php:109:
{{ $address->label ?: 'Address' }}

resources/views/livewire/admin/customers/show.blade.php:126:                            <flux:button wire:click="openAddressForm({{ $address->getKey() }})" size="sm" variant="filled">Edit</flux:button>
resources/views/livewire/admin/customers/show.blade.php:128:                                <flux:button wire:click="setDefaultAddress({{ $address->getKey() }})" size="sm" variant="ghost">Set default</flux:button>
resources/views/livewire/admin/customers/show.blade.php:130:                            <flux:button wire:click="deleteAddress({{ $address->getKey() }})" wire:confirm="Delete this address?" size="sm" variant="danger">Delete</flux:button>
resources/views/livewire/admin/customers/show.blade.php:144:        <form wire:submit="saveAddress" class="space-y-6">
resources/views/livewire/admin/customers/show.blade.php:146:                <flux:heading size="lg">{{ $editingAddressId ? 'Edit address' : 'Add address' }}</flux:heading>
resources/views/livewire/admin/customers/show.blade.php:155:                    <flux:input wire:model="addressJson.address1" label="Address line 1" />
resources/views/livewire/admin/customers/show.blade.php:159:                    <flux:input wire:model="addressJson.address2" label="Address line 2" />
resources/views/livewire/auth/register.blade.php:22:
resources/views/livewire/auth/reset-password.blade.php:13:
app/Exceptions/UnserviceableShippingAddressException.php:7:class UnserviceableShippingAddressException extends RuntimeException
app/Exceptions/UnserviceableShippingAddressException.php:9:    public static function forAddress(): self
app/Enums/CheckoutStatus.php:8:    case Addressed = 'addressed';
app/Models/CustomerAddress.php:9:class CustomerAddress extends Model
app/Models/CustomerAddress.php:11:    /** @use HasFactory<\Database\Factories\CustomerAddressFactory> */
app/Http/Requests/Api/Storefront/V1/SetCheckoutAddressRequest.php:7:class SetCheckoutAddressRequest extends FormRequest
resources/views/livewire/storefront/checkout/show.blade.php:12:                    @foreach (['address' => 'Address', 'shipping' => 'Shipping', 'payment' => 'Payment'] as $key => $label)
resources/views/livewire/storefront/checkout/show.blade.php:34:                <form wire:submit="saveAddress" class="rounded-lg border border-zinc-200 bg-white p-5 dark:border-zinc-800 dark:bg-zinc-950">
resources/views/livewire/storefront/checkout/show.blade.php:53:                            <flux:input wire:model="shippingAddress.first_name" label="First name" />
resources/views/livewire/storefront/checkout/show.blade.php:54:                            <flux:error name="shippingAddress.first_name" />
resources/views/livewire/storefront/checkout/show.blade.php:57:                            <flux:input wire:model="shippingAddress.last_name" label="Last name" />
resources/views/livewire/storefront/checkout/show.blade.php:58:                            <flux:error name="shippingAddress.last_name" />
resources/views/livewire/storefront/checkout/show.blade.php:62:                            <flux:input wire:model="shippingAddress.address1" label="Address" />
resources/views/livewire/storefront/checkout/show.blade.php:63:                            <flux:error name="shippingAddress.address1" />
resources/views/livewire/storefront/checkout/show.blade.php:67:                            <flux:input wire:model="shippingAddress.address2" label="Apartment, suite, etc." />
resources/views/livewire/storefront/checkout/show.blade.php:71:                            <flux:input wire:model="shippingAddress.city" label="City" />
resources/views/livewire/storefront/checkout/show.blade.php:72:                            <flux:error name="shippingAddress.city" />
resources/views/livewire/storefront/checkout/show.blade.php:75:                            <flux:input wire:model="shippingAddress.postal_code" label="Postal code" />
resources/views/livewire/storefront/checkout/show.blade.php:76:                            <flux:error name="shippingAddress.postal_code" />
resources/views/livewire/storefront/checkout/show.blade.php:79:                        <flux:input wire:model="shippingAddress.province_code" label="Region code" placeholder="DE-BE" />
resources/views/livewire/storefront/checkout/show.blade.php:81:                            <flux:select wire:model="shippingAddress.country" label="Country">
resources/views/livewire/storefront/checkout/show.blade.php:87:                            <flux:error name="shippingAddress.country" />
app/Models/Customer.php:68:     * @return HasMany<CustomerAddress, $this>
app/Models/Customer.php:72:        return $this->hasMany(CustomerAddress::class);
app/Livewire/Admin/Settings/Checkout.php:24:    public bool $billingAddressEnabled = true;
app/Livewire/Admin/Settings/Checkout.php:58:            'billingAddressEnabled' => ['boolean'],
app/Livewire/Admin/Settings/Checkout.php:74:                    'billing_address_enabled' => $validated['billingAddressEnabled'],
app/Livewire/Admin/Settings/Checkout.php:106:        $this->billingAddressEnabled = (bool) data_get($settings, 'checkout.billing_address_enabled', true);
app/Livewire/Admin/Settings/Shipping.php:213:    public function testShippingAddress(ShippingCalculator $shipping): void
app/Livewire/Admin/Customers/Show.php:6:use App\Models\CustomerAddress;
app/Livewire/Admin/Customers/Show.php:25:    public ?int $editingAddressId = null;
app/Livewire/Admin/Customers/Show.php:60:    public function openAddressForm(?int $addressId = null): void
app/Livewire/Admin/Customers/Show.php:62:        $this->editingAddressId = $addressId;
app/Livewire/Admin/Customers/Show.php:67:            $this->addressJson = array_merge($this->emptyAddressJson(), $address->address_json ?? []);
app/Livewire/Admin/Customers/Show.php:69:            $this->resetAddressForm();
app/Livewire/Admin/Customers/Show.php:75:    public function saveAddress(): void
app/Livewire/Admin/Customers/Show.php:89:        $address = $this->editingAddressId
app/Livewire/Admin/Customers/Show.php:90:            ? $this->address($this->editingAddressId)
app/Livewire/Admin/Customers/Show.php:91:            : new CustomerAddress(['customer_id' => $this->customerId]);
app/Livewire/Admin/Customers/Show.php:100:        $this->resetAddressForm();
app/Livewire/Admin/Customers/Show.php:102:        $this->dispatch('toast', type: 'success', message: __('Address saved'));
app/Livewire/Admin/Customers/Show.php:105:    public function deleteAddress(int $addressId): void
app/Livewire/Admin/Customers/Show.php:112:            $this->setFirstAddressAsDefault();
app/Livewire/Admin/Customers/Show.php:115:        $this->dispatch('toast', type: 'success', message: __('Address deleted'));
app/Livewire/Admin/Customers/Show.php:118:    public function setDefaultAddress(int $addressId): void
app/Livewire/Admin/Customers/Show.php:123:            CustomerAddress::query()
app/Livewire/Admin/Customers/Show.php:164:    private function address(int $addressId): CustomerAddress
app/Livewire/Admin/Customers/Show.php:166:        return CustomerAddress::query()
app/Livewire/Admin/Customers/Show.php:172:    private function setFirstAddressAsDefault(): void
app/Livewire/Admin/Customers/Show.php:174:        $nextAddress = CustomerAddress::query()
app/Livewire/Admin/Customers/Show.php:179:        if ($nextAddress instanceof CustomerAddress) {
app/Livewire/Admin/Customers/Show.php:180:            $nextAddress->forceFill(['is_default' => true])->save();
app/Livewire/Admin/Customers/Show.php:184:    private function resetAddressForm(): void
app/Livewire/Admin/Customers/Show.php:186:        $this->editingAddressId = null;
app/Livewire/Admin/Customers/Show.php:188:        $this->addressJson = $this->emptyAddressJson();
app/Livewire/Admin/Customers/Show.php:194:    private function emptyAddressJson(): array
database/migrations/2026_05_04_000408_create_customer_addresses_table.php:14:        Schema::create('customer_addresses', function (Blueprint $table) {
database/migrations/2026_05_04_000408_create_customer_addresses_table.php:31:        Schema::dropIfExists('customer_addresses');
app/Livewire/Storefront/Cart/Show.php:193:        return app(ShippingCalculator::class)->getAvailableRates($this->store(), $this->shippingAddress());
app/Livewire/Storefront/Cart/Show.php:301:    private function shippingAddress(): array
app/Livewire/Storefront/Checkout/Show.php:9:use App\Exceptions\UnserviceableShippingAddressException;
app/Livewire/Storefront/Checkout/Show.php:39:    public array $shippingAddress = [
app/Livewire/Storefront/Checkout/Show.php:53:    public array $billingAddress = [
app/Livewire/Storefront/Checkout/Show.php:88:    public function saveAddress(): void
app/Livewire/Storefront/Checkout/Show.php:92:            'shippingAddress.first_name' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:93:            'shippingAddress.last_name' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:94:            'shippingAddress.address1' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:95:            'shippingAddress.city' => ['required', 'string'],
app/Livewire/Storefront/Checkout/Show.php:96:            'shippingAddress.country' => ['required', 'string', 'size:2'],
app/Livewire/Storefront/Checkout/Show.php:97:            'shippingAddress.postal_code' => [
app/Livewire/Storefront/Checkout/Show.php:101:                    if (strtoupper($this->shippingAddress['country']) === 'DE' && preg_match('/^\d{5}$/', (string) $value) !== 1) {
app/Livewire/Storefront/Checkout/Show.php:116:            $checkout = app(CheckoutService::class)->setAddress($checkout, [
app/Livewire/Storefront/Checkout/Show.php:118:                'shipping_address' => $this->shippingAddress,
app/Livewire/Storefront/Checkout/Show.php:119:                'billing_address' => $this->billingSame ? $this->shippingAddress : $this->billingAddress,
app/Livewire/Storefront/Checkout/Show.php:156:        } catch (InvalidCheckoutTransitionException|UnserviceableShippingAddressException $exception) {
app/Livewire/Storefront/Checkout/Show.php:324:        if ($this->shippingAddress['country'] === '') {
app/Livewire/Storefront/Checkout/Show.php:328:        return app(ShippingCalculator::class)->getAvailableRates($this->store(), $this->shippingAddress);
app/Livewire/Storefront/Checkout/Show.php:413:        $this->shippingAddress = array_replace($this->shippingAddress, $checkout->shipping_address_json ?? []);
app/Livewire/Storefront/Checkout/Show.php:414:        $this->billingAddress = array_replace($this->billingAddress, $checkout->billing_address_json ?? []);
app/Livewire/Storefront/Checkout/Show.php:420:            CheckoutStatus::Addressed => 'shipping',


cmd: sed -n '1,200p' database/seeders/CustomerAddressSeeder.php && sed -n '1,120p' database/factories/CustomerAddressFactory.php && sed -n '1,120p' app/Models/CustomerAddress.php


command: sed -n '1,200p' database/seeders/CustomerAddressSeeder.php && sed -n '1,120p' database/factories/CustomerAddressFactory.php && sed -n '1,120p' app/Models/CustomerAddress.php

CustomerAddressSeeder.php

type: read

CustomerAddress.php

aggregated_output:
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class CustomerAddressSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        //
    }
}
<?php

namespace Database\Factories;

use App\Models\Customer;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CustomerAddress>
 */
class CustomerAddressFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'customer_id' => Customer::factory(),
            'label' => fake()->randomElement(['Shipping', 'Billing', 'Home', 'Office']),
            'address_json' => [
                'first_name' => fake()->firstName(),
                'last_name' => fake()->lastName(),
                'address1' => fake()->streetAddress(),
                'address2' => null,
                'city' => fake()->city(),
                'province_code' => null,
                'country' => 'DE',
                'postal_code' => fake()->postcode(),
            ],
            'is_default' => false,
        ];
    }

    public function default(): static
    {
        return $this->state(fn (array $attributes): array => [
            'is_default' => true,
        ]);
    }
}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class CustomerAddress extends Model
{
    /** @use HasFactory<\Database\Factories\CustomerAddressFactory> */
    use HasFactory;

    public $timestamps = false;

    /**
     * @var list<string>
     */
    protected $fillable = [
        'customer_id',
        'label',
        'address_json',
        'is_default',
    ];

    /**
     * @return BelongsTo<Customer, $this>
     */
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'address_json' => 'array',
            'is_default' => 'bool',
        ];
    }
}

status: completed


output:
Chunk ID: 2564bf
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 571
Output:
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class CustomerAddressSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        //
    }
}
<?php

namespace Database\Factories;

use App\Models\Customer;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CustomerAddress>
 */
class CustomerAddressFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'customer_id' => Customer::factory(),
            'label' => fake()->randomElement(['Shipping', 'Billing', 'Home', 'Office']),
            'address_json' => [
                'first_name' => fake()->firstName(),
                'last_name' => fake()->lastName(),
                'address1' => fake()->streetAddress(),
                'address2' => null,
                'city' => fake()->city(),
                'province_code' => null,
                'country' => 'DE',
                'postal_code' => fake()->postcode(),
            ],
            'is_default' => false,
        ];
    }

    public function default(): static
    {
        return $this->state(fn (array $attributes): array => [
            'is_default' => true,
        ]);
    }
}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class CustomerAddress extends Model
{
    /** @use HasFactory<\Database\Factories\CustomerAddressFactory> */
    use HasFactory;

    public $timestamps = false;

    /**
     * @var list<string>
     */
    protected $fillable = [
        'customer_id',
        'label',
        'address_json',
        'is_default',
    ];

    /**
     * @return BelongsTo<Customer, $this>
     */
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'address_json' => 'array',
            'is_default' => 'bool',
        ];
    }
}


cmd: sed -n '1,200p' app/Livewire/Storefront/Account/Orders/Index.php && sed -n '1,220p' app/Livewire/Storefront/Account/Orders/Show.php && sed -n '1,180p' app/Livewire/Storefront/Account/Auth/Login.php && sed -n '1,180p' app/Livewire/Storefront/Account/Auth/Register.php


command: sed -n '1,200p' app/Livewire/Storefront/Account/Orders/Index.php && sed -n '1,220p' app/Livewire/Storefront/Account/Orders/Show.php && sed -n '1,180p' app/Livewire/Storefront/Account/Auth/Login.php && sed -n '1,180p' app/Livewire/Storefront/Account/Auth/Register.php

Register.php

aggregated_output:
<?php

namespace App\Livewire\Storefront\Account\Orders;

use App\Models\Customer;
use App\Models\Order;
use App\Models\Store;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Locked;
use Livewire\Component;

class Index extends Component
{
    #[Locked]
    public int $storeId;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function render(): mixed
    {
        return view('livewire.storefront.account.orders.index', [
            'orders' => $this->orders(),
        ])->layout('layouts.storefront', [
            'title' => 'Account',
        ]);
    }

    /**
     * @return Collection<int, Order>
     */
    private function orders(): Collection
    {
        $customer = Auth::guard('customer')->user();

        abort_unless($customer instanceof Customer, 403);

        return Order::withoutGlobalScopes()
            ->where('store_id', $this->storeId)
            ->where('customer_id', $customer->getKey())
            ->latest('placed_at')
            ->limit(20)
            ->get();
    }
}
<?php

namespace App\Livewire\Storefront\Account\Orders;

use App\Models\Customer;
use App\Models\Order;
use App\Models\Store;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Locked;
use Livewire\Component;

class Show extends Component
{
    #[Locked]
    public int $storeId;

    #[Locked]
    public int $orderId;

    public function mount(Order $order): void
    {
        $store = app('current_store');
        $customer = Auth::guard('customer')->user();

        abort_unless($store instanceof Store && $customer instanceof Customer, 404);

        $order = Order::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('customer_id', $customer->getKey())
            ->whereKey($order->getKey())
            ->first();

        abort_unless($order instanceof Order, 404);

        $this->storeId = $store->getKey();
        $this->orderId = $order->getKey();
    }

    public function render(): mixed
    {
        return view('livewire.storefront.account.orders.show', [
            'order' => $this->order(),
        ])->layout('layouts.storefront', [
            'title' => 'Order details',
        ]);
    }

    private function order(): Order
    {
        return Order::withoutGlobalScopes()
            ->with(['lines', 'payments', 'refunds', 'fulfillments.lines'])
            ->where('store_id', $this->storeId)
            ->where('customer_id', Auth::guard('customer')->id())
            ->findOrFail($this->orderId);
    }
}
<?php

namespace App\Livewire\Storefront\Account\Auth;

use App\Models\Customer;
use App\Models\Store;
use App\Services\CartService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public int $storeId;

    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

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

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

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

        app()->instance('current_store', Store::query()->findOrFail($this->storeId));

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

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

        RateLimiter::clear($key);

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

        $customer = Auth::guard('customer')->user();

        if ($customer instanceof Customer && session()->has('cart_id')) {
            app(CartService::class)->getOrCreateForSession(Store::query()->findOrFail($this->storeId), $customer);
        }

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

    public function render(): mixed
    {
        return view('livewire.storefront.account.auth.login')
            ->layout('layouts.auth');
    }
}
<?php

namespace App\Livewire\Storefront\Account\Auth;

use App\Models\Customer;
use App\Models\Store;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
use Livewire\Component;

class Register extends Component
{
    public string $name = '';

    public string $email = '';

    public string $password = '';

    public string $password_confirmation = '';

    public bool $marketing_opt_in = false;

    public int $storeId;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function register(): void
    {
        $store = Store::query()->findOrFail($this->storeId);

        app()->instance('current_store', $store);

        $validated = $this->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => [
                'required',
                'email',
                'max:255',
                Rule::unique('customers', 'email')->where('store_id', $store->getKey()),
            ],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'marketing_opt_in' => ['boolean'],
        ]);

        $customer = Customer::withoutGlobalScopes()->create([
            'store_id' => $store->getKey(),
            'name' => $validated['name'],
            'email' => $validated['email'],
            'password' => $validated['password'],
            'marketing_opt_in' => $validated['marketing_opt_in'],
        ]);

        Auth::guard('customer')->login($customer);

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

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

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


output:
Chunk ID: fbe497
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1715
Output:
<?php

namespace App\Livewire\Storefront\Account\Orders;

use App\Models\Customer;
use App\Models\Order;
use App\Models\Store;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Locked;
use Livewire\Component;

class Index extends Component
{
    #[Locked]
    public int $storeId;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function render(): mixed
    {
        return view('livewire.storefront.account.orders.index', [
            'orders' => $this->orders(),
        ])->layout('layouts.storefront', [
            'title' => 'Account',
        ]);
    }

    /**
     * @return Collection<int, Order>
     */
    private function orders(): Collection
    {
        $customer = Auth::guard('customer')->user();

        abort_unless($customer instanceof Customer, 403);

        return Order::withoutGlobalScopes()
            ->where('store_id', $this->storeId)
            ->where('customer_id', $customer->getKey())
            ->latest('placed_at')
            ->limit(20)
            ->get();
    }
}
<?php

namespace App\Livewire\Storefront\Account\Orders;

use App\Models\Customer;
use App\Models\Order;
use App\Models\Store;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Locked;
use Livewire\Component;

class Show extends Component
{
    #[Locked]
    public int $storeId;

    #[Locked]
    public int $orderId;

    public function mount(Order $order): void
    {
        $store = app('current_store');
        $customer = Auth::guard('customer')->user();

        abort_unless($store instanceof Store && $customer instanceof Customer, 404);

        $order = Order::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('customer_id', $customer->getKey())
            ->whereKey($order->getKey())
            ->first();

        abort_unless($order instanceof Order, 404);

        $this->storeId = $store->getKey();
        $this->orderId = $order->getKey();
    }

    public function render(): mixed
    {
        return view('livewire.storefront.account.orders.show', [
            'order' => $this->order(),
        ])->layout('layouts.storefront', [
            'title' => 'Order details',
        ]);
    }

    private function order(): Order
    {
        return Order::withoutGlobalScopes()
            ->with(['lines', 'payments', 'refunds', 'fulfillments.lines'])
            ->where('store_id', $this->storeId)
            ->where('customer_id', Auth::guard('customer')->id())
            ->findOrFail($this->orderId);
    }
}
<?php

namespace App\Livewire\Storefront\Account\Auth;

use App\Models\Customer;
use App\Models\Store;
use App\Services\CartService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public int $storeId;

    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

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

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

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

        app()->instance('current_store', Store::query()->findOrFail($this->storeId));

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

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

        RateLimiter::clear($key);

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

        $customer = Auth::guard('customer')->user();

        if ($customer instanceof Customer && session()->has('cart_id')) {
            app(CartService::class)->getOrCreateForSession(Store::query()->findOrFail($this->storeId), $customer);
        }

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

    public function render(): mixed
    {
        return view('livewire.storefront.account.auth.login')
            ->layout('layouts.auth');
    }
}
<?php

namespace App\Livewire\Storefront\Account\Auth;

use App\Models\Customer;
use App\Models\Store;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
use Livewire\Component;

class Register extends Component
{
    public string $name = '';

    public string $email = '';

    public string $password = '';

    public string $password_confirmation = '';

    public bool $marketing_opt_in = false;

    public int $storeId;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function register(): void
    {
        $store = Store::query()->findOrFail($this->storeId);

        app()->instance('current_store', $store);

        $validated = $this->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => [
                'required',
                'email',
                'max:255',
                Rule::unique('customers', 'email')->where('store_id', $store->getKey()),
            ],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'marketing_opt_in' => ['boolean'],
        ]);

        $customer = Customer::withoutGlobalScopes()->create([
            'store_id' => $store->getKey(),
            'name' => $validated['name'],
            'email' => $validated['email'],
            'password' => $validated['password'],
            'marketing_opt_in' => $validated['marketing_opt_in'],
        ]);

        Auth::guard('customer')->login($customer);

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

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

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


message: Suite 10 needs a small customer-account surface that is currently missing: `/account/addresses`, a customer logout route, and clearer account navigation/header. I’m adding those with Livewire/Flux patterns already used by the app, then I’ll write the browser suite.

phase: commentary


type: message

role: assistant

text: Suite 10 needs a small customer-account surface that is currently missing: `/account/addresses`, a customer logout route, and clearer account navigation/header. I’m adding those with Livewire/Flux patterns already used by the app, then I’ll write the browser suite.


cmd: sed -n '1,180p' /Users/fabianwesner/Herd/shop/.agents/skills/livewire-development/SKILL.md


cmd: sed -n '1,120p' /Users/fabianwesner/Herd/shop/.agents/skills/developing-with-fortify/SKILL.md


command: sed -n '1,180p' /Users/fabianwesner/Herd/shop/.agents/skills/livewire-development/SKILL.md

aggregated_output:
---
name: livewire-development
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
license: MIT
metadata:
  author: laravel
---

# Livewire Development

## Documentation

Use `search-docs` for detailed Livewire 4 patterns and documentation.

## Basic Usage

### Creating Components

```bash

# Single-file component (SFC - default in v4)

# Creates: resources/views/components/⚡create-post.blade.php

php artisan make:livewire create-post

# Page component (SFC - Full Page in v4)

# Creates: resources/views/pages/⚡create-post.blade.php

php artisan make:livewire pages::create-post

# Multi-file component (MFC)

# Creates: resources/views/components/⚡create-post/create-post.php

#          resources/views/components/⚡create-post/create-post.blade.php

php artisan make:livewire create-post --mfc

# Class-based component (v3 style)

# Creates: app/Livewire/CreatePost.php AND resources/views/livewire/create-post.blade.php

php artisan make:livewire create-post --class

# With namespace

php artisan make:livewire Posts/CreatePost
```

### Converting Between Formats

Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.

### Choosing a Component Format

> **Always follow the project's existing conventions first.** Before creating any component, inspect the project's existing Livewire components to determine the established format (SFC, MFC, or class-based) and directory structure. Check `app/Livewire/`, `resources/views/components/`, and `resources/views/livewire/` for existing components. If the project already uses a consistent format, **use that same format** — even if it differs from the Livewire v4 defaults below. Only fall back to the v4 defaults (SFC in `resources/views/components/`) when no existing convention is established.

Also check `config/livewire.php` for `make_command.type`, `make_command.emoji`, `component_locations`, and `component_namespaces` overrides, which change the default format and where files are stored.

### Component Format Reference

| Format | Flag | Class Path | View Path |
|--------|------|------------|-----------|
| Single-file (SFC) | default | — | `resources/views/components/⚡create-post.blade.php` (PHP + Blade in one file) |
| Full Page SFC | `pages::name` | — | `resources/views/pages/⚡create-post.blade.php` |
| Multi-file (MFC) | `--mfc` | `resources/views/components/⚡create-post/create-post.php` | `resources/views/components/⚡create-post/create-post.blade.php` |
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
| View-based | default (Blade-only) | — | `resources/views/components/⚡create-post.blade.php` (Blade-only with functional state) |

> **Important:** The ⚡ prefix shown above is the **default** behavior in Livewire v4 — it is **configurable**. Check `config/livewire.php` for the `make_command.emoji` setting. When `true` (default), always include the ⚡ prefix in filenames you create. When `false`, omit the ⚡ prefix from all paths above.

Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates `resources/views/components/posts/⚡create-post.blade.php` (single-file by default). Use `make:livewire Posts/CreatePost --mfc` for multi-file output at `resources/views/components/posts/⚡create-post/create-post.php` and `resources/views/components/posts/⚡create-post/create-post.blade.php`.

### Single-File Component Example

<!-- Single-File Component Example -->
```php
<?php
use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }
};
?>

<div>
    <button wire:click="increment">Count: @{{ $count }}</button>
</div>
```

## Livewire 4 Specifics

### Key Changes From Livewire 3

These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.

- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.

### New Features

- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.

| Feature | Usage | Purpose |
|---------|-------|---------|
| Islands | `@island(name: 'stats')` | Isolated update regions |
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
| Deferred | `defer` attribute | Load after page render |
| Bundled | `lazy.bundle` | Load multiple together |

### New Directives

- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
- `data-loading` attribute automatically added to elements triggering network requests.

| Directive | Purpose |
|-----------|---------|
| `wire:sort` | Drag-and-drop sorting |
| `wire:intersect` | Viewport intersection detection |
| `wire:ref` | Element references for JS |
| `.renderless` | Component without rendering |
| `.preserve-scroll` | Preserve scroll position |

## Best Practices

- Always use `wire:key` in loops
- Use `wire:loading` for loading states
- Use `wire:model.live` for instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)

## Configuration

- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.

## Alpine & JavaScript

- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.

For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).

## Testing

<!-- Testing Example -->
```php
Livewire::test(Counter::class)
    ->assertSet('count', 0)
    ->call('increment')
    ->assertSet('count', 1);
```

## Verification

1. Browser console: Check for JS errors
2. Network tab: Verify Livewire requests return 200
3. Ensure `wire:key` on all `@foreach` loops

## Common Pitfalls

- Missing `wire:key` in loops → unexpected re-rendering
- Expecting `wire:model` real-time → use `wire:model.live`
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)


command: sed -n '1,120p' /Users/fabianwesner/Herd/shop/.agents/skills/developing-with-fortify/SKILL.md

aggregated_output:
---
name: developing-with-fortify
description: Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications.
---

# Laravel Fortify Development

Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications.

## Documentation

Use `search-docs` for detailed Laravel Fortify patterns and documentation.

## Usage

- **Routes**: Use `list-routes` with `only_vendor: true` and `action: "Fortify"` to see all registered endpoints
- **Actions**: Check `app/Actions/Fortify/` for customizable business logic (user creation, password validation, etc.)
- **Config**: See `config/fortify.php` for all options including features, guards, rate limiters, and username field
- **Contracts**: Look in `Laravel\Fortify\Contracts\` for overridable response classes (`LoginResponse`, `LogoutResponse`, etc.)
- **Views**: All view callbacks are set in `FortifyServiceProvider::boot()` using `Fortify::loginView()`, `Fortify::registerView()`, etc.

## Available Features

Enable in `config/fortify.php` features array:

- `Features::registration()` - User registration
- `Features::resetPasswords()` - Password reset via email
- `Features::emailVerification()` - Requires User to implement `MustVerifyEmail`
- `Features::updateProfileInformation()` - Profile updates
- `Features::updatePasswords()` - Password changes
- `Features::twoFactorAuthentication()` - 2FA with QR codes and recovery codes

> Use `search-docs` for feature configuration options and customization patterns.

## Setup Workflows

### Two-Factor Authentication Setup

```
- [ ] Add TwoFactorAuthenticatable trait to User model
- [ ] Enable feature in config/fortify.php
- [ ] Run migrations for 2FA columns
- [ ] Set up view callbacks in FortifyServiceProvider
- [ ] Create 2FA management UI
- [ ] Test QR code and recovery codes
```

> Use `search-docs` for TOTP implementation and recovery code handling patterns.

### Email Verification Setup

```
- [ ] Enable emailVerification feature in config
- [ ] Implement MustVerifyEmail interface on User model
- [ ] Set up verifyEmailView callback
- [ ] Add verified middleware to protected routes
- [ ] Test verification email flow
```

> Use `search-docs` for MustVerifyEmail implementation patterns.

### Password Reset Setup

```
- [ ] Enable resetPasswords feature in config
- [ ] Set up requestPasswordResetLinkView callback
- [ ] Set up resetPasswordView callback
- [ ] Define password.reset named route (if views disabled)
- [ ] Test reset email and link flow
```

> Use `search-docs` for custom password reset flow patterns.

### SPA Authentication Setup

```
- [ ] Set 'views' => false in config/fortify.php
- [ ] Install and configure Laravel Sanctum
- [ ] Use 'web' guard in fortify config
- [ ] Set up CSRF token handling
- [ ] Test XHR authentication flows
```

> Use `search-docs` for integration and SPA authentication patterns.

## Best Practices

### Custom Authentication Logic

Override authentication behavior using `Fortify::authenticateUsing()` for custom user retrieval or `Fortify::authenticateThrough()` to customize the authentication pipeline. Override response contracts in `AppServiceProvider` for custom redirects.

### Registration Customization

Modify `app/Actions/Fortify/CreateNewUser.php` to customize user creation logic, validation rules, and additional fields.

### Rate Limiting

Configure via `fortify.limiters.login` in config. Default configuration throttles by username + IP combination.

## Key Endpoints

| Feature                | Method   | Endpoint                                    |
|------------------------|----------|---------------------------------------------|
| Login                  | POST     | `/login`                                    |
| Logout                 | POST     | `/logout`                                   |
| Register               | POST     | `/register`                                 |
| Password Reset Request | POST     | `/forgot-password`                          |
| Password Reset         | POST     | `/reset-password`                           |
| Email Verify Notice    | GET      | `/email/verify`                             |
| Resend Verification    | POST     | `/email/verification-notification`          |
| Password Confirm       | POST     | `/user/confirm-password`                    |
| Enable 2FA             | POST     | `/user/two-factor-authentication`           |
| Confirm 2FA            | POST     | `/user/confirmed-two-factor-authentication` |
| 2FA Challenge          | POST     | `/two-factor-challenge`                     |
| Get QR Code            | GET      | `/user/two-factor-qr-code`                  |
| Recovery Codes         | GET/POST | `/user/two-factor-recovery-codes`           |


output:
Chunk ID: 5ca9ec
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1888
Output:
---
name: livewire-development
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
license: MIT
metadata:
  author: laravel
---

# Livewire Development

## Documentation

Use `search-docs` for detailed Livewire 4 patterns and documentation.

## Basic Usage

### Creating Components

```bash

# Single-file component (SFC - default in v4)

# Creates: resources/views/components/⚡create-post.blade.php

php artisan make:livewire create-post

# Page component (SFC - Full Page in v4)

# Creates: resources/views/pages/⚡create-post.blade.php

php artisan make:livewire pages::create-post

# Multi-file component (MFC)

# Creates: resources/views/components/⚡create-post/create-post.php

#          resources/views/components/⚡create-post/create-post.blade.php

php artisan make:livewire create-post --mfc

# Class-based component (v3 style)

# Creates: app/Livewire/CreatePost.php AND resources/views/livewire/create-post.blade.php

php artisan make:livewire create-post --class

# With namespace

php artisan make:livewire Posts/CreatePost
```

### Converting Between Formats

Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.

### Choosing a Component Format

> **Always follow the project's existing conventions first.** Before creating any component, inspect the project's existing Livewire components to determine the established format (SFC, MFC, or class-based) and directory structure. Check `app/Livewire/`, `resources/views/components/`, and `resources/views/livewire/` for existing components. If the project already uses a consistent format, **use that same format** — even if it differs from the Livewire v4 defaults below. Only fall back to the v4 defaults (SFC in `resources/views/components/`) when no existing convention is established.

Also check `config/livewire.php` for `make_command.type`, `make_command.emoji`, `component_locations`, and `component_namespaces` overrides, which change the default format and where files are stored.

### Component Format Reference

| Format | Flag | Class Path | View Path |
|--------|------|------------|-----------|
| Single-file (SFC) | default | — | `resources/views/components/⚡create-post.blade.php` (PHP + Blade in one file) |
| Full Page SFC | `pages::name` | — | `resources/views/pages/⚡create-post.blade.php` |
| Multi-file (MFC) | `--mfc` | `resources/views/components/⚡create-post/create-post.php` | `resources/views/components/⚡create-post/create-post.blade.php` |
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
| View-based | default (Blade-only) | — | `resources/views/components/⚡create-post.blade.php` (Blade-only with functional state) |

> **Important:** The ⚡ prefix shown above is the **default** behavior in Livewire v4 — it is **configurable**. Check `config/livewire.php` for the `make_command.emoji` setting. When `true` (default), always include the ⚡ prefix in filenames you create. When `false`, omit the ⚡ prefix from all paths above.

Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates `resources/views/components/posts/⚡create-post.blade.php` (single-file by default). Use `make:livewire Posts/CreatePost --mfc` for multi-file output at `resources/views/components/posts/⚡create-post/create-post.php` and `resources/views/components/posts/⚡create-post/create-post.blade.php`.

### Single-File Component Example

<!-- Single-File Component Example -->
```php
<?php
use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }
};
?>

<div>
    <button wire:click="increment">Count: @{{ $count }}</button>
</div>
```

## Livewire 4 Specifics

### Key Changes From Livewire 3

These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.

- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.

### New Features

- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.

| Feature | Usage | Purpose |
|---------|-------|---------|
| Islands | `@island(name: 'stats')` | Isolated update regions |
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
| Deferred | `defer` attribute | Load after page render |
| Bundled | `lazy.bundle` | Load multiple together |

### New Directives

- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
- `data-loading` attribute automatically added to elements triggering network requests.

| Directive | Purpose |
|-----------|---------|
| `wire:sort` | Drag-and-drop sorting |
| `wire:intersect` | Viewport intersection detection |
| `wire:ref` | Element references for JS |
| `.renderless` | Component without rendering |
| `.preserve-scroll` | Preserve scroll position |

## Best Practices

- Always use `wire:key` in loops
- Use `wire:loading` for loading states
- Use `wire:model.live` for instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)

## Configuration

- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.

## Alpine & JavaScript

- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.

For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).

## Testing

<!-- Testing Example -->
```php
Livewire::test(Counter::class)
    ->assertSet('count', 0)
    ->call('increment')
    ->assertSet('count', 1);
```

## Verification

1. Browser console: Check for JS errors
2. Network tab: Verify Livewire requests return 200
3. Ensure `wire:key` on all `@foreach` loops

## Common Pitfalls

- Missing `wire:key` in loops → unexpected re-rendering
- Expecting `wire:model` real-time → use `wire:model.live`
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)


output:
Chunk ID: 8551a6
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1256
Output:
---
name: developing-with-fortify
description: Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications.
---

# Laravel Fortify Development

Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications.

## Documentation

Use `search-docs` for detailed Laravel Fortify patterns and documentation.

## Usage

- **Routes**: Use `list-routes` with `only_vendor: true` and `action: "Fortify"` to see all registered endpoints
- **Actions**: Check `app/Actions/Fortify/` for customizable business logic (user creation, password validation, etc.)
- **Config**: See `config/fortify.php` for all options including features, guards, rate limiters, and username field
- **Contracts**: Look in `Laravel\Fortify\Contracts\` for overridable response classes (`LoginResponse`, `LogoutResponse`, etc.)
- **Views**: All view callbacks are set in `FortifyServiceProvider::boot()` using `Fortify::loginView()`, `Fortify::registerView()`, etc.

## Available Features

Enable in `config/fortify.php` features array:

- `Features::registration()` - User registration
- `Features::resetPasswords()` - Password reset via email
- `Features::emailVerification()` - Requires User to implement `MustVerifyEmail`
- `Features::updateProfileInformation()` - Profile updates
- `Features::updatePasswords()` - Password changes
- `Features::twoFactorAuthentication()` - 2FA with QR codes and recovery codes

> Use `search-docs` for feature configuration options and customization patterns.

## Setup Workflows

### Two-Factor Authentication Setup

```
- [ ] Add TwoFactorAuthenticatable trait to User model
- [ ] Enable feature in config/fortify.php
- [ ] Run migrations for 2FA columns
- [ ] Set up view callbacks in FortifyServiceProvider
- [ ] Create 2FA management UI
- [ ] Test QR code and recovery codes
```

> Use `search-docs` for TOTP implementation and recovery code handling patterns.

### Email Verification Setup

```
- [ ] Enable emailVerification feature in config
- [ ] Implement MustVerifyEmail interface on User model
- [ ] Set up verifyEmailView callback
- [ ] Add verified middleware to protected routes
- [ ] Test verification email flow
```

> Use `search-docs` for MustVerifyEmail implementation patterns.

### Password Reset Setup

```
- [ ] Enable resetPasswords feature in config
- [ ] Set up requestPasswordResetLinkView callback
- [ ] Set up resetPasswordView callback
- [ ] Define password.reset named route (if views disabled)
- [ ] Test reset email and link flow
```

> Use `search-docs` for custom password reset flow patterns.

### SPA Authentication Setup

```
- [ ] Set 'views' => false in config/fortify.php
- [ ] Install and configure Laravel Sanctum
- [ ] Use 'web' guard in fortify config
- [ ] Set up CSRF token handling
- [ ] Test XHR authentication flows
```

> Use `search-docs` for integration and SPA authentication patterns.

## Best Practices

### Custom Authentication Logic

Override authentication behavior using `Fortify::authenticateUsing()` for custom user retrieval or `Fortify::authenticateThrough()` to customize the authentication pipeline. Override response contracts in `AppServiceProvider` for custom redirects.

### Registration Customization

Modify `app/Actions/Fortify/CreateNewUser.php` to customize user creation logic, validation rules, and additional fields.

### Rate Limiting

Configure via `fortify.limiters.login` in config. Default configuration throttles by username + IP combination.

## Key Endpoints

| Feature                | Method   | Endpoint                                    |
|------------------------|----------|---------------------------------------------|
| Login                  | POST     | `/login`                                    |
| Logout                 | POST     | `/logout`                                   |
| Register               | POST     | `/register`                                 |
| Password Reset Request | POST     | `/forgot-password`                          |
| Password Reset         | POST     | `/reset-password`                           |
| Email Verify Notice    | GET      | `/email/verify`                             |
| Resend Verification    | POST     | `/email/verification-notification`          |
| Password Confirm       | POST     | `/user/confirm-password`                    |
| Enable 2FA             | POST     | `/user/two-factor-authentication`           |
| Confirm 2FA            | POST     | `/user/confirmed-two-factor-authentication` |
| 2FA Challenge          | POST     | `/two-factor-challenge`                     |
| Get QR Code            | GET      | `/user/two-factor-qr-code`                  |
| Recovery Codes         | GET/POST | `/user/two-factor-recovery-codes`           |