# Core Module A Laravel module providing authentication, localization, product search/catalog, privacy/GDPR tooling, notifications, activity logging, CLI tooling, and functional types on top of the [Lunar](https://lunarphp.io) e-commerce package. Designed to be consumed as a standalone Composer package by any Lunar-based e-shop. --- ## What's Inside ### OTP Authentication Passwordless login for both staff (Lunar panel) and customers via 6-digit codes delivered by email. Codes expire after 10 minutes, rate-limited to 5 attempts. The Lunar panel login page is a two-step flow (email → OTP) with a back button to return from the code step to the email step. See [`docs/otp-auth.md`](docs/otp-auth.md). ### Localization Locale-prefixed routing (`Modules\Core\Localization\LocaleMiddleware`) — a `locale` route middleware, opt-in per shop, that resolves and redirects to the correct language segment (`/el/...`, `/en/...`) based on Lunar's own language list, with caching and rename-safe translation migration. Also brings in storefront UI label translations (`spatie/laravel-translation-loader`) with an admin-editable `LanguageLine` resource. See [`docs/localization.md`](docs/localization.md). ### Product Search & Catalog Two complementary services on top of Meilisearch: - **`Modules\Core\Search\ProductSearchService`** — locale-aware full-text product search. - **`Modules\Core\Catalog\ProductService`** — listing/filtering (by collection, brand, price range) and single-product lookup by id or slug, reading directly from the Meilisearch index rather than the database. Both are backed by `Modules\Core\Search\ProductIndexer`, which extends Lunar's own indexer with collections, price, variants, media, tags, and reviews — everything needed for both a listing page and a full product detail page from one index. See [`docs/product-search.md`](docs/product-search.md) and [`docs/product-listing.md`](docs/product-listing.md). ### Product Reviews `Modules\Core\Review\ProductReview` — ratings/reviews with staff replies, a Filament sub-navigation page on the product edit screen, and automatic re-indexing (via `ReviewServiceProvider`) whenever a review is created, updated, or deleted, so a product's Meilisearch document never goes stale. ### Privacy / GDPR Data-Subject Requests Right of access (export) and right of erasure, built as an extensible contract (`Modules\Core\Privacy\Contracts\PersonalDataProvider`) rather than a fixed table list — any module can register its own data without core knowing it exists. - **Two independent scopes**: erasing/exporting a Lunar `Customer` (business account) is never the same operation as erasing/exporting a `User` (individual login) — a `Customer` erasure never touches any linked `User`'s login, and a `User` erasure never touches a `Customer` account's own data. See `docs/privacy.md` "User-scope vs Customer-scope". - **Cancellable grace period** (default 30 days, configurable) before anything is actually erased — logging back in during the window automatically reverts the request, mirroring Shopify's own account-deletion flow. Immediate erasure exists but is staff-only by type, never reachable from a self-service flow. - **Sole-owner cascade**: erasing the last remaining `User` on a `Customer` also opens a (grace period) erasure request for that now-orphaned `Customer`, so its PII doesn't sit unreachable forever — traced back to the triggering request so login-reactivation can revert exactly that cascade. - **Queued export**: gathering data and writing a CSV-per-provider zip (via the generic, reusable `Modules\Core\Export\CsvWriter`) runs as a background job; a consuming app hooks its own notification onto the completion event via the Notification Registry (below). See [`docs/privacy.md`](docs/privacy.md). ### Shopify Migration `Modules\Core\MigrateImport\Shopify\ShopifyExportImporter` — imports a Shopify CSV product export (products, variants, images, collections, tags, prices) into Lunar, idempotently re-runnable via an `import_mappings` table. Part of a source-agnostic import framework (`boboko:migrate:import`) designed to support additional sources later. See [`docs/shopify-import.md`](docs/shopify-import.md). ### Notification Registry An event-driven notification system. Each notification class declares which event it listens to and who to notify — the registry wires up the listener automatically. All notifications extend `BaseNotification`, which implements `ShouldQueue`, so delivery is async. Supports optional delays. **Creating a notification:** ```php class MyNotification extends BaseNotification { public function __construct(private readonly MyEvent $event) {} public static function getKey(): string { return 'my.notification.key'; } public static function listensTo(): string { return MyEvent::class; } public function via(object $notifiable): array { return ['mail']; } public function notifiable(): AnonymousNotifiable { ... } } // Register in a service provider: NotificationRegistry::get()->register([MyNotification::class]); ``` See [`docs/notifications.md`](docs/notifications.md). ### Activity Logging Thin wrapper around [Spatie Laravel Activity Log](https://github.com/spatie/laravel-activitylog). Four standardized methods: `created()`, `updated()`, `failed()`, `deleted()`. Logs to the `lunar` channel and auto-resolves the actor from the staff session. See [`docs/activity-log.md`](docs/activity-log.md). ### Lunar Panel Integration - Custom OTP login page replacing the default Lunar panel login - `StaffResourceExtension` — removes password field from Lunar's staff resource - `CustomerResourceExtension` — replaces default address relation manager with a custom implementation - Table-rate shipping (`ShippingPlugin`) registered by default - `CorePlugin` — configures panel path, branding, logos, navigation items, and activity log field exclusions for staff Register the plugin in your Lunar panel provider: ```php ->plugin(\Modules\Core\CorePlugin::make()) ``` See [`docs/lunar.md`](docs/lunar.md) for the full Lunar reference and non-obvious gotchas hit while building against it. ### CLI Commands | Command | Description | |---|---| | `boboko:anonymize` | Dummy-scrub personal data in `users`/`lunar_customers` for local dev safety (local environment only — **not** the GDPR erasure tool; see Privacy above for that) | | `boboko:export` | Dump database + storage files to a timestamped zip | | `boboko:import` | Restore from a `boboko:export` zip archive | | `boboko:export:cleanup` | Delete old export zips, keep N most recent | | `boboko:migrate:import` | Import a vendor product catalog (Shopify, etc.) into Lunar | | `boboko:privacy:process-erasure-requests` | Dispatch an erasure job for every due GDPR erasure request (wire into your own scheduler) | | `lunar:create-admin` | Create a Lunar admin user (overrides Lunar's own command) | | `lunar:install` | Seed default Lunar store data — countries, channel, currency, tax zone, attributes, product type (overrides Lunar's own command) | ### Functional Types Result and Option types for explicit error handling without exceptions. ```php // Result $result = Success::create($value); $result = Error::create('something went wrong'); $result->map(fn($v) => ...)->flatMap(fn($v) => ...); // Option $option = Some::create($value); $option = None::create(); $option->map(fn($v) => ...); ``` --- ## Installation Add the repository to your project's `composer.json`: ```json { "repositories": [ { "type": "vcs", "url": "https://code.radical-elements.com/boboko/core.git" } ], "require": { "boboko/core": "^1.0" } } ``` Then run: ```bash composer require boboko/core php artisan vendor:publish --tag=core-config php artisan vendor:publish --tag=core-assets php artisan migrate ``` For local core development alongside a consuming app (path-repo symlink + Docker mount), see [`docs/modules.md`](docs/modules.md) "Docker Compose: the local-core mount". --- ## Requirements - PHP 8.5+ - Laravel 12+ - Lunar 1.3 (`lunarphp/lunar`) - Meilisearch (for product search/listing/catalog) - Spatie Laravel Activity Log --- ## Documentation - [`docs/otp-auth.md`](docs/otp-auth.md) — OTP authentication flow - [`docs/localization.md`](docs/localization.md) — Locale-prefixed routing and storefront translations - [`docs/product-search.md`](docs/product-search.md) — Full-text product search - [`docs/product-listing.md`](docs/product-listing.md) — Product listing/filtering/detail catalog service - [`docs/privacy.md`](docs/privacy.md) — GDPR right of access/erasure, User-scope vs Customer-scope - [`docs/shopify-import.md`](docs/shopify-import.md) — Shopify CSV → Lunar field mapping and import design - [`docs/activity-log.md`](docs/activity-log.md) — Activity logging - [`docs/notifications.md`](docs/notifications.md) — Notification registry - [`docs/lunar.md`](docs/lunar.md) — Lunar framework reference and gotchas - [`docs/modules.md`](docs/modules.md) — Module architecture, Customer/User pairing, provider registration pitfalls