# Decent Billing ERP - Deployment

This document describes how to deploy Decent Billing ERP in the three
supported topologies. It also lists the release checklist that must be
completed before promoting a build to production.

## 1. Supported topologies

### 1.1 SaaS (billing.decentonline.com)

- Multi-tenant, row-scoped by `company_id` + `branch_id` (introduced in S0.3).
- One PHP-FPM pool, one MySQL primary + read replica.
- Nightly logical backups + streaming binary log to object storage.
- CDN in front of `public/build/*` (Vite outputs long-lived hashed assets).

### 1.2 On-premise (retailer LAN)

- Single-server deployment on Ubuntu 22.04 LTS / Rocky 9.
- Nginx or Apache in front of PHP-FPM 8.2+.
- Local MySQL 8 / MariaDB 10.6+.
- Optional Redis (falls back to database-backed cache/session).
- Auto-update script pulls signed releases from Decent Online update server.

### 1.3 Docker (SMB self-hosted)

- Compose stack: `app` (php-fpm), `web` (nginx), `db` (mysql 8), `redis`,
  `queue` (php-fpm worker), `scheduler` (php cron).
- Persistent volumes for `storage/app`, `storage/logs`, `db_data`.
- Health checks map to `/healthz` (liveness) and `/api/v1/ready` (readiness).

Kubernetes manifests will land in a later sprint for horizontally scalable
tenants; they are not required for S0.1.

## 2. Environment variables (S0.1 subset)

See `.env.example` for the complete list. The variables that affect
security-critical behaviour are:

| Variable                  | Purpose                                              |
|---------------------------|------------------------------------------------------|
| `APP_ENV`                 | `production` in production. Never `local`.           |
| `APP_DEBUG`               | `false` in production. Prevents stack leakage.       |
| `APP_KEY`                 | Base64, 32 bytes. Rotated per environment.           |
| `APP_URL`                 | Canonical URL used in mails and PDFs.                |
| `DECENT_FORCE_HTTPS`      | `true` in production. Enables HSTS.                  |
| `DECENT_CSP_REPORT_ONLY`  | `false` in production. `true` only during rollout.   |
| `DECENT_INSTALL_ENABLED`  | `true` when the install-guard middleware should run. |
| `SESSION_SECURE_COOKIE`   | `true` in production.                                |
| `SESSION_SAME_SITE`       | `lax`                                                |
| `LOG_CHANNEL`             | `stack`, with `daily` + `stderr` in production.      |

## 3. Zero-downtime deploy (Envoyer / Deployer style)

```
1. `composer install --no-dev --optimize-autoloader`
2. `npm ci && npm run build`
3. `php artisan config:cache`
4. `php artisan route:cache`
5. `php artisan view:cache`
6. `php artisan event:cache`
7. `php artisan migrate --force`
8. Swap the `current` symlink.
9. `php artisan queue:restart`
10. Reload PHP-FPM.
```

Rollback is a matter of pointing `current` at the previous release and
running `php artisan queue:restart`; migrations use `up`/`down` pairs to
support one-step reversal.

## 4. Health probes

- `/healthz` - liveness. Returns 200 as long as PHP-FPM is answering.
- `/api/v1/ready` - readiness. Verifies PHP version, required extensions,
  writable storage paths, and DB connectivity. Returns `503` when any check
  fails.

Configure your orchestrator to probe readiness before receiving traffic and
to fall back to liveness for restart decisions.

## 5. Backups

- Database: daily logical dump + hourly binlog snapshots to encrypted S3.
- Storage: `storage/app` synced hourly.
- Retention: 30 days rolling; 12 monthly + 7 yearly cold archives.
- Test-restore is scheduled monthly against a staging environment.

## 6. Release checklist (per sub-sprint)

Before promoting the build:

- [ ] All PHPUnit suites pass locally and in CI.
- [ ] `composer audit` and `npm audit --production` return zero highs.
- [ ] `php artisan config:cache` succeeds.
- [ ] `php artisan route:cache` succeeds.
- [ ] `.env.example` is up to date.
- [ ] Sub-sprint completion report is checked into `docs/`.
- [ ] Blueprint checklist for the sub-sprint is fully green.
