# Pre-Deployment Audit Report

**Updated:** 2026-10-11  
**Deployment status:** Not ready for production

## Project scope and audit context

The application is a PHP 8.2/MySQL 8 ordering and point-of-sale system. PHP routes and browser assets are under `public/`; shared authentication/configuration code is under `includes/` and `config/`; schemas and seed logic are under `database/`; operational guides are under `docs/`. It uses server-rendered PHP with CSS and JavaScript; no Composer/npm dependency manifest or bundled automated test suite is present.

The earlier read-only project inspection found implemented customer registration/contact verification, login, menu browsing, cart/checkout, delivery details, order history, Administrator and Customer pages, order/payment records, reporting, and audit logging. Their complete end-to-end behavior and production role enforcement were not re-tested during that payment update. Syntax and UI presence are not proof that external services or deployed database workflows work.

Previously identified deployment gaps remain relevant:

- Production SMS delivery and password-reset delivery need compatible, configured providers; local-only OTP/reset support is not production delivery.
- Login requires the arithmetic CAPTCHA on every sign-in attempt when `ENABLE_CAPTCHA` is enabled. There is no automatic account/IP lockout; failed attempts are recorded. Add host/edge rate limiting and assess the accepted risk before launch.
- Authentication, Administrator/Customer role checks, customer-data isolation, and the complete workflows still need authenticated staging tests against a restored database copy.
- HTTPS, production secret management, backup/restore, monitoring, and operational recovery have not been verified on the target host.
- The project has no comprehensive automated test suite; the tests listed below are focused checks, not full regression or production-readiness certification.

## Feature status

**Implemented in the application (presence confirmed, end-to-end behavior not re-certified here):**

- Customer accounts and contact verification, menu/category browsing, cart, order checkout, delivery-address capture, order history, and order tracking.
- Administrator and Customer interfaces, order/payment records, reports, and activity/audit logging. Historical cashier/staff order records remain stored but those roles are no longer active.
- A secure Xendit GCash payment-request path, customer-scoped status polling, callback-token-checked webhook handling, and paid-order retry logic. Provider behavior remains unverified until sandbox tests are run.

**Incomplete, blocked, or awaiting verification:**

- Customer online checkout stays disabled until Xendit is configured and migration 07 is applied.
- Production SMS and password-reset delivery, end-to-end order/payment lifecycle tests, account/role/data-isolation tests, and deployment-host verification are still required.
- Static QR payments cannot be verified automatically. The saved static QR is not used in new Xendit checkouts; do not treat it, a screenshot, or a browser redirect as payment proof.

## Database and data safety

Existing order, payment, account, and other database records were not read or changed during this update. The new `payment_checkouts` table is an additive InnoDB migration with unique provider references and customer/order foreign keys. It was not applied to any database. Back up existing data and rehearse the migration on a separate restored staging copy before applying it. Do not run the local installer or seed routine against production/valuable data.

## Payment architecture

New customer GCash checkout uses Xendit's one-time GCash payment-request flow. The application creates a server-priced checkout snapshot, redirects the customer to Xendit's payment action, and checks status server-to-server. The return URL is not treated as proof of payment. Webhooks require the configured Xendit callback token, and payment data is checked against the saved business, reference, amount, currency, country, and channel before a checkout can become paid.

The static image at `gcash/qr_gcash.jpg` is retained as an existing project asset, but it is not shown for this automated flow: a static QR alone cannot identify or verify an individual payment. The Xendit GCash action is a provider/GCash redirect. Historical manual-GCash orders and cashier/staff cash records remain preserved; only Administrators can verify payments in the current application.

The implementation is based on Xendit's official documentation:

- [Payment Requests API](https://docs.xendit.co/api-reference/payment-requests)
- [GCash payment channel](https://docs.xendit.co/docs/gcash)
- [Webhook notifications](https://docs.xendit.co/docs/webhooks)

## Changes in this update

- Added the Xendit client and server-side payment/reference validation in `includes/xendit.php`.
- Added authenticated checkout, status polling, and webhook endpoints.
- Gated customer GCash order creation on a server-verified successful payment. Paid checkouts can retry order creation from their saved checkout snapshot without creating another payment request.
- Added the additive `database/07_payment_checkouts.sql` migration and included it in fresh local installation.
- Added Xendit configuration placeholders and updated the README, payment setup/deployment, database, and security documentation.
- Left existing data and database schema untouched during this update. The migration was **not** applied.

## Validation performed

- PHP syntax checks passed for the changed PHP files.
- JavaScript syntax check passed for the changed application script.
- Editor diagnostics reported no errors in the changed implementation.
- An offline synthetic validation script passed 14 checks for payment matching, mismatched amount/reference/business/channel/status rejection, state transitions, late success, and redirect URL scheme validation. This is not an Xendit sandbox test.
- Local HTTP checks confirmed anonymous requests to checkout, payment status, and POS redirect to login. The webhook returns HTTP 503 while Xendit is disabled.
- Runtime readiness was checked without printing secret values: Xendit is disabled, required API key, callback token, and business ID are not configured, and PHP cURL is available.
- No Xendit payment was initiated; no database migration or database write was performed.

## Deployment blockers and required setup

Production deployment must wait until all of the following are completed:

1. Create/verify the merchant's Xendit business account, complete required business verification, and activate the GCash payment channel. Test Mode may be used for staging; live GCash availability is subject to Xendit's approval.
2. Set `XENDIT_ENABLED`, `XENDIT_SECRET_API_KEY`, `XENDIT_WEBHOOK_TOKEN`, and `XENDIT_BUSINESS_ID` in the server's private environment configuration. Never commit or log the secret key or callback token.
3. Set a public HTTPS `APP_URL` and configure the Xendit webhook URL as `https://<your-domain>/xendit-webhook.php`. Localhost cannot receive provider callbacks.
4. Back up the existing database, rehearse the additive migration on a staging copy, then apply `database/07_payment_checkouts.sql` to the target database. Do not reset or replace existing tables.
5. On HTTPS staging with Xendit Test Mode, verify successful, pending, failed, expired, duplicate-webhook, delayed-webhook, invalid-signature, mismatched-amount/reference, payment-status polling, and order-retry behavior.
6. Test authenticated Administrator and Customer roles against the deployed database, including direct unauthorized payment-verification attempts, direct unpaid order-submission attempts, recovery after a paid payment with a failed order insert, and denial of legacy cashier/staff accounts.
7. Only after staging results and merchant approval are verified should live credentials be configured and a controlled live payment test be performed.

## Remaining limitations

- The requested full checkout/payment lifecycle has not been exercised with an authenticated user or Xendit sandbox/live credentials in this environment.
- Provider callbacks and provider-side status lookups have not been tested against Xendit. No real automatic GCash verification has been demonstrated here.
- Existing accounts, role enforcement against production data, historical order behavior, and the migration's compatibility with the deployed database still require staging verification.
- Production SMS/password-reset delivery, login rate limiting, production HTTPS, backups/restores, monitoring, and rollback procedures remain unverified or unconfigured.
- Until credentials, business activation, migration, and staging tests are complete, customer online GCash checkout correctly remains unavailable; the application does not fabricate a successful payment.
