# Domain Health Diagnostic Tool

The Domain Health tool simulates the middleware resolution pipeline for every configured store access method, verifying that each domain, subdomain, and path-based route resolves to the expected store.

## Overview

| Aspect | Detail |
|--------|--------|
| Location | Admin > Diagnostics > Resolution > Domain Health |
| URL | `/admin/platform-debug` (select "Domain Health" in sidebar) |
| API Endpoint | `GET /api/v1/admin/debug/domain-health` |
| Access | Super admin only |

## What It Checks

The tool runs four categories of checks against the **live database**:

### 1. Custom Subdomains (StorePlatform)

Checks every active `StorePlatform` entry that has a `custom_subdomain` set.

| Example | What It Tests |
|---------|--------------|
| `acme-rewards.rewardflow.lu` | Does `detection_method=subdomain` with `custom_subdomain` + platform context resolve to the expected store? |

This is the most critical check because the fail-closed routing policy means a custom subdomain that doesn't resolve will return a 404 rather than falling back to a global lookup.

### 2. Default Subdomains per Platform

Checks every active store's default `subdomain` on each platform it belongs to.

| Example | What It Tests |
|---------|--------------|
| `acme.omsflow.lu` | Does `detection_method=subdomain` with `Store.subdomain` + platform context resolve to the expected store? |

The middleware first tries `StorePlatform.custom_subdomain`, then falls back to `Store.subdomain` — but **only** if the store has an active `StorePlatform` membership on the detected platform. A store with no membership on that platform will be blocked (fail-closed, prevents cross-tenant leaks).

Entries where `custom_subdomain` already equals the store's `subdomain` are de-duplicated (covered by check #1).

### 3. Custom Domains (StoreDomain)

Checks every active, verified `StoreDomain` entry.

| Example | What It Tests |
|---------|--------------|
| `wizatech.shop` | Does `detection_method=custom_domain` resolve to the store that owns the domain? |

The Platform column shows the platform associated with the `StoreDomain.platform_id` relationship.

### 4. Path-Based Routes

Checks every active store's `subdomain` field via path-based resolution.

| Example | What It Tests |
|---------|--------------|
| `/storefront/luxweb/` | Does `detection_method=path` with `subdomain=luxweb` resolve to the correct store? |
| `/store/luxweb/` | Same check for the store dashboard path |

The Platform column shows all platforms the store is a member of (via `StorePlatform`).

!!! note "Path segments use Store.subdomain"
    Path-based URLs use the store's `subdomain` field, **not** `store_code`. For example, a store with `store_code=LUXWEBSITES` and `subdomain=luxweb` is accessed at `/storefront/luxweb/`, not `/storefront/LUXWEBSITES/`.

## How It Works

The tool calls the **same resolution functions** that the live middleware uses:

```mermaid
graph LR
    A[Health Check] -->|builds context dict| B[StoreContextManager.get_store_from_context]
    B -->|queries DB| C[Store resolved?]
    C -->|id matches expected| D[PASS]
    C -->|mismatch or None| E[FAIL]
```

It does **not** make actual HTTP requests. This means it validates database configuration and resolution logic, but cannot detect:

- DNS misconfigurations
- Reverse proxy / Cloudflare routing issues
- SSL certificate problems
- Network-level failures

## Reading the Results

### Summary Bar

| Counter | Meaning |
|---------|---------|
| Total Checked | Number of access methods tested |
| Passed | Resolved to the expected store |
| Failed | Resolution mismatch or store not found |

### Results Table

| Column | Description |
|--------|-------------|
| Status | `pass` or `fail` badge |
| Domain | The domain, subdomain, or path being tested |
| Type | `custom subdomain`, `default subdomain`, `custom domain`, `path (storefront)`, or `path (store)` |
| Platform | Platform code(s) the entry belongs to |
| Expected Store | The store code we expect to resolve |
| Resolved Store | The store code that actually resolved (or `--` if none) |
| Note | Error description for failed entries |

### Common Failure Scenarios

| Symptom | Likely Cause |
|---------|-------------|
| Custom subdomain fails | `StorePlatform.custom_subdomain` doesn't match or `StorePlatform.is_active=false` |
| Default subdomain fails | Store has no active `StorePlatform` membership on the detected platform (cross-tenant blocked) |
| Custom domain fails | `StoreDomain` not verified, inactive, or store is inactive |
| Path-based fails | Store's `subdomain` field is empty or store is inactive |
| Resolved store differs from expected | Two stores have conflicting subdomain/domain entries |

## API Response

```
GET /api/v1/admin/debug/domain-health
```

```json
{
  "total": 36,
  "passed": 30,
  "failed": 6,
  "details": [
    {
      "domain": "acme-rewards.rewardflow.lu",
      "type": "custom subdomain",
      "platform_code": "loyalty",
      "expected_store": "ACME",
      "resolved_store": "ACME",
      "status": "pass",
      "note": ""
    },
    {
      "domain": "acme.omsflow.lu",
      "type": "default subdomain",
      "platform_code": "oms",
      "expected_store": "ACME",
      "resolved_store": "ACME",
      "status": "pass",
      "note": ""
    },
    {
      "domain": "/storefront/acme/",
      "type": "path (storefront)",
      "platform_code": "oms, loyalty",
      "expected_store": "ACME",
      "resolved_store": "ACME",
      "status": "pass",
      "note": ""
    }
  ]
}
```

## Related Documentation

- [Middleware Stack](../../architecture/middleware.md) - Full middleware pipeline reference
- [Dev Tools Module](../../modules/dev_tools/index.md) - Other diagnostic tools
- [Multi-Tenant System](../../architecture/multi-tenant.md) - Tenant detection architecture
