# CareLite deployment runbook

Written for the person doing the install, not for a project file. Work top to bottom.
Deployments happen inside working hours so a failure is noticed and fixed the same day.

---

## 1. Server

| | Minimum | Comfortable for 30 beds |
|---|---|---|
| PHP | 8.1 | 8.3 |
| MySQL / MariaDB | 8.0 / 10.6 | 10.11 |
| RAM | 2 GB | 4 GB |
| Disk | 20 GB | 40 GB, with backups going off-box |

Required PHP extensions: `pdo_mysql`, `openssl`, `mbstring`.
Recommended: `curl` (WhatsApp, email, ABDM), `zip` and `simplexml` (.xlsx import — CSV works without them).

Two vhosts, one document root each:

- application → the CareLite folder
- public site → `carelite/web`

The site reads `config.php` one level up, so keep the folders together.

---

## 2. Database

```sql
CREATE DATABASE carelite CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'carelite_app'@'localhost' IDENTIFIED BY '<strong password>';
GRANT SELECT, INSERT, UPDATE, DELETE ON carelite.* TO 'carelite_app'@'localhost';
```

No DDL rights for the application user, deliberately. Schema changes are a DBA action, and
pre-flight warns if this grant is too wide.

Optional, so backups can be proved by restoring them:

```sql
CREATE USER 'carelite_backup'@'localhost' IDENTIFIED BY '<strong password>';
GRANT ALL ON `carelite_verify`.* TO 'carelite_backup'@'localhost';
GRANT SELECT ON carelite.* TO 'carelite_backup'@'localhost';
```

---

## 3. Configure

```bash
cp config/config.sample.php config/config.php
openssl rand -base64 32            # paste into APP_KEY
chmod 640 config/config.php        # web server group only
mkdir -p storage/backups && chmod 750 storage storage/backups
```

Set `DB_*`, `APP_URL`, `WEB_URL`, `APP_ENV=production`, `SUPPORT_PHONE`, `SUPPORT_EMAIL`.

`APP_KEY` encrypts the WhatsApp, SES and ABDM credentials. Lose it and those must be re-entered;
nothing else is affected. Keep a copy wherever you keep the database password.

---

## 4. Install

The application account cannot create tables — that is deliberate — so the installer asks for a
database account that can. It is used once and never stored.

```bash
php setup/install.php --user=root --pass='<dba password>'
```

Or open `/setup/install.php` in a browser and fill in the same two fields. Either way it loads
`sql/01_schema.sql`, `sql/02_seed.sql` and `sql/03_content.sql` in order. You can equally load those
three files yourself with the mysql client and skip the installer.

Then, always:

```bash
rm -rf setup/
```

Sign in as `superadmin` / `CareLite@2026` and change the password immediately. Pre-flight fails
until you do.

---

## 5. Cron

```
* * * * *   php /path/to/carelite/bin/comm_worker.php
5 13 * * *  php /path/to/carelite/bin/bed_charges.php
30 13 * * * php /path/to/carelite/bin/backup.php
0 14 * * 6  php /path/to/carelite/bin/backup.php --verify
```

All four are safe to re-run. Bed charges post from `last_bed_charge_date`, so running twice never
double-charges. The daytime schedule is intentional — a backup that fails at 02:00 is discovered a
day late.

---

## 6. Pre-flight

```bash
php bin/preflight.php
```

Clear every FAIL before anyone signs in. Read the warnings; most of them become incidents later.
Use `--strict` in a deploy script to stop on warnings too.

---

## 7. Onboard the hospital

1. Platform console → Onboard hospital. Fill the profile, set the plan, bed and user limits, enable
   modules, and create the Client Admin. The one-time password is shown **once** — copy it then.
2. Sign in as the Client Admin and change it.
3. Masters, in this order, because each depends on the one before:
   departments and specialities → doctors → wards → rooms → beds → service groups → services →
   companies → tariffs → tariff rates.
   Use Excel import for anything over about twenty rows. Download the template first; headings must
   match, order does not.
4. Settings: bed-charge basis, discount approval threshold, invoice and receipt header lines.
5. Users and roles. Give each person their own login — a shared account destroys the audit trail,
   which is the one thing that cannot be reconstructed later.
6. Communication: switch on WhatsApp or email only after credentials are set, or messages queue and
   then fail.

---

## 8. Before go-live

- [ ] Pre-flight clean
- [ ] UAT signed off (`docs/UAT.md`)
- [ ] A backup taken, verified, and **copied off this server**
- [ ] A restore rehearsed onto a spare box, timed and written down
- [ ] Every user has their own login and has changed their password
- [ ] `setup/` deleted, HTTPS enforced on both vhosts
- [ ] Somebody named as the person who checks the failed-message queue each morning

---

## 9. Rollback

Nothing in Phase 1 destroys data, so a rollback is a restore:

```bash
gzip -dc storage/backups/carelite-<stamp>.sql.gz | mysql carelite
```

Take a fresh backup **before** restoring an old one — the current state is also evidence.
If the problem is a bad configuration rather than bad data, restore `config.php` from your copy
instead; the database is usually fine.
