# Diagnostics

Two surfaces answer "is this installation healthy": the **System** page in the admin panel, and `php bin/doctor.php` on the command line.

## Running the CLI check

```bash
php bin/doctor.php
```

It reports:

| Check | What it tells you |
|---|---|
| Quaeriva version, VERSION file | Which release is actually running |
| Project root, base path, `APP_ENV` | How the installation is addressed |
| PDO MySQL, database server | Whether the driver and server are usable |
| Database config source | Which file supplied the credentials |
| Applied and pending migrations | Whether the schema is current |
| Schema integrity | Missing tables, columns or foreign keys |
| Layout / sections / widgets | Whether a usable layout exists |
| File permissions | Whether storage and configuration paths are correct |
| Release manifest and build id | Whether the deployed files match a known build |

A pending-migration or schema report tells you exactly what to run next.

## The admin System page

The same class of information without shell access: database and schema state, PHP version and extensions, mail and Telegram configuration state, sitemap availability, storage permissions, and the release manifest.

Network delivery tests (send a test email, send a test Telegram message) are **explicit actions**, never automatic on page load. A diagnostics page that emails on every render is a diagnostics page that gets your domain rate-limited.

## Overview warnings

The Overview dashboard surfaces the subset that needs action today — pending moderation, open reports, pending migrations, storage warnings — and links each one to the page that fixes it.

## Interpreting results

| Result | Meaning |
|---|---|
| Pass | Verified now, not cached |
| Warning | Works, but will bite later — a missing optional extension, a permission wider than needed |
| Fail | Fix before serving traffic |

## When to run it

- After every deployment
- After any PHP or MySQL version change on the host
- Before opening registration
- First, whenever something is broken and you do not yet know why

## One service, two surfaces

Both the CLI doctor and the admin System page read `App\System\DiagnosticService`. Neither implements a check of its own, so the two surfaces cannot disagree about the same installation.

Each check is returned in one shape:

| Field | Meaning |
|---|---|
| `id` | Stable identifier, e.g. `migrations_pending` |
| `value` | Short rendered value |
| `state` | `pass`, `warn`, `fail`, or `info` |
| `detail` | Extra lines, e.g. the pending migration filenames |

`inspect()` also returns a `healthy` flag, which is false when any check failed. `bin/doctor.php` exits `0` when healthy and `3` when not, so CI can gate on it.

The database checks are always present even when the connection is down — they report `unknown` with state `fail` rather than disappearing, so a renderer never has to handle a shorter list than it was written against.

Diagnostics are **read-only and side-effect free**. Sending a test email or a test Telegram message stays an explicit admin action.

See [Troubleshooting](TROUBLESHOOTING.md) and [Logging](LOGGING.md).
