# Deployment & Operations Readiness — v61

## Scope

v61 combines deployment, runtime health, queue/scheduler operations, database
backup/restore, CI hardening, request correlation, and Windows Local Agent
credential-at-rest hardening.

It does not claim that the React web POS user experience is feature-complete.

## Runtime health

- `GET /up` remains the Laravel liveness endpoint.
- `GET /up/ready` verifies:
  - PostgreSQL connectivity
  - cache read/write
  - queue connection availability
  - writable Laravel storage
  - `APP_DEBUG=false` when the application environment is production

No credentials, connection strings, or exception messages are returned.

## Request correlation

Every HTTP response receives `X-Request-ID`. A valid incoming request ID is
preserved; otherwise the application generates a UUID. The ID is also attached
to Laravel log context.

## Production baseline

Use `.env.production.example` as the deployment baseline. Generate `APP_KEY`
on the target environment and inject actual database/Redis credentials using
the deployment secret mechanism. Do not commit a populated `.env`.

Recommended production drivers:

- PostgreSQL for business truth.
- Redis for cache, queue, and sessions.
- Daily application log rotation.
- Queue failed jobs persisted in the database.

## Queue worker

A production process manager should keep `php artisan queue:work` alive.
`ops/windows/start-queue-worker.ps1` is the Windows command baseline. The worker
has a one-hour max runtime so a service manager can recycle it cleanly.

## Scheduler

Run `php artisan schedule:run` every minute using Task Scheduler, cron, or the
platform scheduler. v61 schedules:

- customer value expiry hourly
- failed queue job pruning daily

## Database backup / restore

`ops/postgres/backup-postgres.ps1` creates PostgreSQL custom-format dumps and
validates them using `pg_restore --list`, then writes a SHA-256 checksum.

Passwords are read only from the process `PGPASSWORD` environment variable.

`ops/postgres/restore-postgres.ps1` requires an exact database-name confirmation
before restore. Always perform restore drills against a disposable database
before relying on a backup policy.

## Windows Local Agent credentials

The server continues to store only the hash of the agent credential.

v61 changes the Windows side:

- agent token is encrypted using Windows DPAPI, LocalMachine scope
- encrypted token lives in `%ProgramData%\RetailPos\Agent\agent-token.dpapi`
- plaintext token is not written to `agent-config.json`
- old plaintext `agentToken` values are migrated automatically and removed
- `--pair`, `--status`, and `--clear-credential` operational commands are added

## CI

CI now runs on pushes to `main` and `master`, uses PHP 8.3, validates PostgreSQL
and Redis service health, runs Laravel Pint/tests, runs web lint/tests/build,
and compiles the Windows Agent plus receipt preview regression.

## Production deployment sequence

1. Provision PostgreSQL and Redis.
2. Create the API `.env` from `.env.production.example`.
3. Generate and inject `APP_KEY`.
4. Run `composer install --no-dev --optimize-autoloader`.
5. Run `php artisan migrate --force`.
6. Run `php artisan config:cache`, `route:cache`, and `view:cache`.
7. Start the queue worker under a service/process manager.
8. Schedule `php artisan schedule:run` every minute.
9. Verify `/up` and `/up/ready`.
10. Build/deploy `apps/web/dist`.
11. Install/pair the Windows Local Agent where printing is required.
12. Run a database backup and a restore drill before production sign-off.
