# Ladill POS — deploy runbook Standalone **in-store register** at `pos.ladill.com`. Charges via Ladill Pay (`source_service: pos`, `fee_tier: sales`). ## Platform wiring 1. OIDC client: `php artisan passport:client` on monolith — redirect `https://pos.ladill.com/sso/callback` 2. Env keys on monolith: `BILLING_API_KEY_POS`, `PAY_API_KEY_POS`, `IDENTITY_API_KEY_POS` 3. Env on POS app: matching consumer keys + `LADILL_SSO_CLIENT_*` 4. Database: `ladill_pos` (MySQL) — migrations via deploy script 5. Marketing: `php scripts/ensure-app-entry-routes.php` (includes `ladill-pos`) ## Deploy Same release model as Mini/Merchant — see `deploy/deploy.sh`. Pushing to `main` triggers `.gitea/workflows/deploy.yml` on the host `deploy` runner, which builds a release and deploys into `/var/www/ladill-pos`. ## ⚠️ Forking this pipeline (read before copying to a new service) This workflow was bootstrapped by copying Mini's. **If you copy `.gitea/workflows/deploy.yml`, `deploy/deploy.sh`, or `DEPLOY.md` to a new service, retarget EVERY `mini`/`pos` reference**, or the new repo's pipeline will deploy its code on top of the service you copied from. Things that must match the new service (search for the old slug and replace all): - `deploy.yml`: `name:`, `concurrency.group`, `RELEASE_ARCHIVE`, `WORKSPACE`, `LADILL_APP_ROOT`, the nginx step subdomain (`pos --app /var/www/ladill-pos/current`) - `deploy.sh`: `APP_ROOT` default and the `supervisorctl restart -worker:*` name A **guard step** in `deploy.yml` enforces `basename(LADILL_APP_ROOT) == ` and fails the run on a mismatch — keep repo name and app dir name identical (`ladill-pos` → `/var/www/ladill-pos`). > **Incident 2026-06-24:** the initial POS pipeline still pointed at `/var/www/ladill-mini`, > so the first POS push overwrote mini.ladill.com (POS code + a stray `create_pos_tables` > migration against the `ladill_mini` DB). Remediated by repointing mini's `current` symlink > to the last genuine Mini release and dropping the 4 stray `pos_*` tables. The guard step > above exists to make this impossible to repeat. ## Server prerequisites (one-time, as root) Done for `pos.ladill.com`; replicate for any new service: 1. MySQL: `CREATE DATABASE ladill_pos` + user `ladill_pos@127.0.0.1` (`ALL` on its own db; `SELECT` on `ladill_merchant` + `ladilldb` for commerce links) 2. `/var/www/ladill-pos/{releases,shared}` owned `deploy:www-data` 3. `shared/.env` (mode 640, `deploy:www-data`) with generated `APP_KEY`, DB creds, and the integration keys from the monolith (see "Platform wiring") 4. nginx vhost via `deployment/setup-service-subdomain-nginx.sh pos --app /var/www/ladill-pos/current` ```bash php artisan migrate --force php artisan config:cache && php artisan route:cache && php artisan view:cache ``` ## Commerce links - **CRM** — `CRM_API_KEY_POS` on CRM + `CRM_API_URL` / `CRM_API_KEY_POS` on POS; timeline on paid sales; product import from CRM API - **Invoice** — "Create invoice" on paid sale receipt (`kind: pos_sale` prefill) - **Merchant** — `MERCHANT_DB_*` read-only connection; import storefront catalog into `pos_products`