# Testing and troubleshooting

## Automated checks

Run the project checks before merging tenancy changes:

```bash
php artisan app:check-translations --locale=en --no-interaction
php artisan app:check-translations --locale=ar --no-interaction
vendor/bin/pint --dirty --format agent
php artisan test --compact
git diff --check
```

The tenancy feature suite is in `tests/Feature/Tenancy/TenantServicesTest.php`. It covers:

- central control-plane connections;
- domain token/TXT verification and primary-domain locking;
- reserved/duplicate tenant validation;
- feature navigation and relation-manager gating;
- tenant database provisioning/migration/seeding;
- tenant-local roles and hashed Admin passwords;
- two-tenant isolation with identical IDs/emails;
- context restoration after scoped work;
- stale destruction-job protection;
- serialized lifecycle transitions;
- central-domain host normalization;
- split-schema assertions (tenant databases do not contain central tables).

The panel branding contract is covered by `tests/Feature/PanelBrandingTest.php`.

## Manual schema smoke check

To verify a production-style central schema locally, use a disposable SQLite file and disable legacy mode:

```bash
APP_ENV=local LEGACY_CENTRAL_SCHEMA=false \
DB_CONNECTION=sqlite DB_DATABASE=/tmp/matjari-central.sqlite \
php artisan migrate:fresh --force --no-interaction

APP_ENV=local LEGACY_CENTRAL_SCHEMA=false \
DB_CONNECTION=sqlite DB_DATABASE=/tmp/matjari-central.sqlite \
php artisan migrate:status --no-interaction
```

Only central migrations should be listed. A real `TenantProvisioningService::provision()` run should create tenant business tables such as `products` while the tenant connection must not contain `tenants` or `tenant_features`.

## Common failures

### `Tenant cache isolation requires a taggable cache store`

Production tenancy was initialized with a non-taggable cache store. Set `CACHE_STORE=redis`, verify Redis connectivity, and clear cached configuration with `php artisan optimize:clear`.

### Store host returns 404

Check all of the following:

1. DNS points to the application edge.
2. The host exists in central `domains`.
3. The domain is `verified`/`active`.
4. The tenant is `active` (not `pending_admin`, suspended, failed, or archived).
5. The request is not using a configured central domain.
6. The platform/custom domain matches the normalized host without a trailing dot.

### Tenant provisioning remains `failed`

Inspect the latest `TenantProvisioningRun.error_message`, then run:

```bash
php artisan tenant:provision <tenant-id>
```

Confirm the central database user can create databases, tenant migrations are present under `database/migrations/tenant`, and tenant seed data can connect. Provisioning is idempotent and will not duplicate a completed tenant.

### Tenant resource is visible but access returns 404

Check the tenant feature row and the route mapping in `EnsureStoreFeatureForRequest`. Also check whether a relation manager uses `HasTenantFeatureRelationManager`; hiding only a parent navigation item is insufficient.

### Store admin is redirected repeatedly

The first administrator intentionally has `force_password_change=true`. Complete the store profile/password update. Ensure the store profile and login route remain exempted by `RequireStoreAdminPasswordChange`.

### Central `/admin` business resources are missing locally

This is expected when `LEGACY_CENTRAL_SCHEMA=false`. Set `LEGACY_CENTRAL_SCHEMA=true` only in local/testing migration-review environments and migrate the compatibility schema. Production business data belongs in `/store` tenant databases.

## Change checklist

Before merging a tenancy-related change, verify:

- the model and migration are in the correct central/tenant path;
- the connection concern is correct;
- no cross-tenant query or central fallback was introduced;
- the feature gate and direct-request behavior are covered;
- queued jobs carry tenant identity and restore context;
- domain and lifecycle authorization is preserved;
- translations, Pint, focused tests, and the full suite pass;
- deployment and rollback notes are updated when schema or lifecycle behavior changes.
