2026-07-01 18:35:39 +03:00
# Core Module
2026-08-24 21:44:10 +03:00
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.
2026-07-01 18:35:39 +03:00
---
## What's Inside
### OTP Authentication
2026-08-24 21:44:10 +03:00
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.
2026-07-01 18:35:39 +03:00
See [`docs/otp-auth.md` ](docs/otp-auth.md ).
2026-08-24 21:44:10 +03:00
### 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 ).
2026-07-01 18:35:39 +03:00
### Notification Registry
2026-08-24 21:44:10 +03:00
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.
2026-07-01 18:35:39 +03:00
**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 ]);
```
2026-08-24 21:44:10 +03:00
See [`docs/notifications.md` ](docs/notifications.md ).
2026-07-01 18:35:39 +03:00
### Activity Logging
2026-08-24 21:44:10 +03:00
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.
2026-07-01 18:35:39 +03:00
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
2026-08-24 21:44:10 +03:00
- `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
2026-07-01 18:35:39 +03:00
Register the plugin in your Lunar panel provider:
```php
-> plugin ( \Modules\Core\CorePlugin :: make ())
```
2026-08-24 21:44:10 +03:00
See [`docs/lunar.md` ](docs/lunar.md ) for the full Lunar reference and non-obvious gotchas hit
while building against it.
2026-07-01 18:35:39 +03:00
### CLI Commands
| Command | Description |
|---|---|
2026-08-24 21:44:10 +03:00
| `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) |
2026-07-01 18:35:39 +03:00
### Functional Types
2026-08-24 21:44:10 +03:00
Result and Option types for explicit error handling without exceptions.
2026-07-01 18:35:39 +03:00
```php
// Result<T, E>
2026-08-24 21:44:10 +03:00
$result = Success :: create ( $value );
$result = Error :: create ( 'something went wrong' );
2026-07-01 18:35:39 +03:00
$result -> map ( fn ( $v ) => ... ) -> flatMap ( fn ( $v ) => ... );
// Option<T>
2026-08-24 21:44:10 +03:00
$option = Some :: create ( $value );
$option = None :: create ();
$option -> map ( fn ( $v ) => ... );
2026-07-01 18:35:39 +03:00
```
---
## 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
2026-07-02 19:38:05 +03:00
composer require boboko/core
2026-08-24 21:44:10 +03:00
php artisan vendor:publish --tag= core-config
2026-07-01 18:35:39 +03:00
php artisan vendor:publish --tag= core-assets
php artisan migrate
```
2026-08-24 21:44:10 +03:00
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".
2026-07-01 18:35:39 +03:00
---
## Requirements
2026-08-24 21:44:10 +03:00
- PHP 8.5+
- Laravel 12+
- Lunar 1.3 (`lunarphp/lunar` )
- Meilisearch (for product search/listing/catalog)
2026-07-01 18:35:39 +03:00
- Spatie Laravel Activity Log
---
## Documentation
- [`docs/otp-auth.md` ](docs/otp-auth.md ) — OTP authentication flow
2026-08-24 21:44:10 +03:00
- [`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
2026-07-01 18:35:39 +03:00
- [`docs/activity-log.md` ](docs/activity-log.md ) — Activity logging
2026-07-03 02:15:31 +03:00
- [`docs/notifications.md` ](docs/notifications.md ) — Notification registry
2026-08-24 21:44:10 +03:00
- [`docs/lunar.md` ](docs/lunar.md ) — Lunar framework reference and gotchas
2026-07-03 02:15:31 +03:00
- [`docs/modules.md` ](docs/modules.md ) — Module architecture, Customer/User pairing, provider registration pitfalls