---
description: PHP modules, namespaces, DataTables registry, CORE routes
globs:
  - src/**/*.php
  - routes/**/*.php
alwaysApply: false
---

# Maestro CORE — PHP conventions

**End-to-end rollout order** (when starting a new module): see **`maestro-module-rollout-workflow.mdc`** (always applied).

## Optional modules (`src/Modules/{Pascal}`)

1. **`config('core.modules.{slug}', $default)`** — Host enables the module (for **customers**, the key **defaults to enabled** when omitted, so old published `core.php` files without `customers` still load routes). **`CoreServiceProvider::loadModules()`** registers the module’s **`{Name}ModuleServiceProvider`** when the resolved value is **`true`**. Set **`'customers' => false`** to disable.
2. **Module provider `boot()`** should **no-op early** when the resolved flag is not **`true`** (defense in depth).
3. **Concerns**: `Models/`, `Http/Controllers`, `Http/Requests`, `Http/Resources`, `database/migrations/`, **`loadMigrationsFrom`**, **`loadRoutesFrom`** for a dedicated file such as **`routes/modules/{slug}.php`**.
4. **Runtime module gate**: Customer (and future) module APIs can use middleware **`maestro.module:{slug}`** (see **`EnsureMaestroModuleEnabled`**) so **`maestro_modules.is_enabled`** matches Superadmin toggles — same source as navigation and **`enabled_module_slugs`**.
5. **Route/model binding** (Customers): resolve `{customer}` by primary key only; auth + module middleware enforce access — **not** scoped by `organization_id`.
6. **Namespace**: `Maestro\Core\Modules\{Name}\…`

## Permissions

- Prefer **`Maestro\Core\Support\PermissionGuardName::forApp()`** with Spatie guard aligned to **`auth.defaults.guard`** (and your `User::guardName()` if customized).
- Name permissions consistently with router `meta.permission` on the Vue side.

## DataTables

- Implement **`Maestro\Core\DataTables\DataTableResource`**; register in **`DataTablesServiceProvider`** with a stable **`resourceKey`** (kebab-case URL segment under `/api/datatables/`).
- Do not register a key `exports` — route regex excludes it; export/list routes live under **`exports`**.

## Where routes live

- Shared CORE: **`routes/core.php`** (web middleware, auth groups, datatables prefix).
- Per module: **`routes/modules/{slug}.php`** — keep API shape and middleware consistent with existing modules (`web`, `auth:sanctum` where used).
