# FieldOps Cloud Testing Architect Brief

This brief gives a testing architect enough system context to design a detailed test plan for FieldOps Cloud from a cloned copy of the repository. It describes the product, current codebase, functional scope, data model, integrations, security model, current automated checks, known implementation gaps, and recommended coverage areas.

## 1. Product Summary

FieldOps Cloud is a PHP 8+ field service management SaaS platform for trade and service businesses such as plumbers, electricians, HVAC teams, contractors, facilities teams, cleaning operators, and maintenance companies.

The current build is a local XAMPP-friendly product prototype with:

- A dense operations dashboard inspired by the prior Replit UI.
- Jobs, schedule, quotes, invoices, clients, team, reports, import/export, settings, AI assistant, SaaS subscription, pricing, and platform admin screens.
- Demo/session-backed workflows for user-facing operations.
- Database schema foundations for production multi-tenant SaaS behavior.
- Provider registries and validation foundations for accounting, calendar, and LLM integrations.

The product is being shaped into a SaaS platform for trade businesses. The testing plan should therefore cover both current local behavior and the production contracts implied by the schema, services, and docs.

## 2. Local Setup Context

Primary local environment:

- Windows + XAMPP.
- Apache document path expected at `C:\xampp\htdocs\FieldOps-Cloud`.
- Local app URL: `http://localhost/FieldOps-Cloud/public/`.
- PHP requirement: `>=8.1`.
- Composer package: `fieldops/cloud`.
- MySQL database name from README: `fieldops_cloud`.

Setup from a fresh clone:

1. Copy the project to `C:\xampp\htdocs\FieldOps-Cloud`.
2. Run `composer install`.
3. Copy `.env.example` to `.env`.
4. Configure local database credentials.
5. Create the MySQL database `fieldops_cloud`.
6. Import `database/schema.sql`.
7. Import `database/seed.sql`.
8. Open `http://localhost/FieldOps-Cloud/public/`.

Local documented seed credentials:

- `owner@example.test` / `FieldOps123`
- `demo@example.test` / `FieldOps123`

Important current behavior: `public/index.php` auto-logs in a demo user if no session user exists. This keeps local demo screens accessible, but a production auth test plan must include a future mode where auto-login is disabled.

## 3. Technology and Architecture

The codebase uses a Yii3-friendly component stack but the current HTTP runtime is a simple custom front controller.

Key technologies:

- PHP 8.1+
- Composer
- Yii 3 components in dependencies
- MySQL schema for production foundations
- Bootstrap 5 templates
- Session-backed demo repositories
- Plain PHP test runner in `tests/run.php`

Repository layout:

| Path | Purpose |
| --- | --- |
| `public/index.php` | Front controller, service wiring, route table, security headers, demo login |
| `src/Application` | Simple application kernel and route dispatcher |
| `src/Infrastructure` | HTTP request/response, rendering, security, persistence |
| `src/*/Controller` | HTTP request handling and responses |
| `src/*/Service` | Business rules, validation, calculators, registries |
| `src/*/Repository` | Persistence boundaries; currently a mix of PDO repositories and session demo repositories |
| `templates` | Bootstrap 5 layouts, components, and screens |
| `database/schema.sql` | Production-oriented relational schema |
| `database/seed.sql` | Local seed data |
| `docs` | Architecture, testing, SaaS, integration, import, roadmap, XAMPP, and handover docs |
| `tests/run.php` | Current lightweight service-level regression checks |
| `tools/lint-php.php` | PHP syntax lint helper used by `composer check` |

Required architecture from project instructions:

- Controller -> Service -> Repository -> Database.
- Controllers should keep HTTP handling only.
- Services own business rules and validation.
- Repositories own persistence with prepared statements.
- Templates must not contain database queries or business logic.

## 4. Request Lifecycle

Request flow:

1. Apache routes to `public/index.php`.
2. `index.php` starts the session and sets `APP_BASE_URL` from `SCRIPT_NAME`.
3. Security headers are sent:
   - `X-Frame-Options: SAMEORIGIN`
   - `X-Content-Type-Options: nosniff`
   - `Referrer-Policy: strict-origin-when-cross-origin`
4. Autoloading uses Composer when available, or a fallback PSR-4 autoloader.
5. Services, repositories, and controllers are constructed.
6. `App` does exact method/path route matching.
7. `Request::path()` strips the XAMPP base path such as `/FieldOps-Cloud/public`.
8. Non-API POST requests are CSRF checked by `App`.
9. Controllers call `SessionAuth::requirePermission()` for protected features.
10. Controllers return `Response` objects.
11. `PhpRenderer` renders templates and prefixes root-relative links/actions with `APP_BASE_URL` for XAMPP.

Testing implications:

- Base-path routing is critical under XAMPP.
- Root-relative links and form actions must work under `/FieldOps-Cloud/public`.
- POST routes require valid CSRF tokens.
- Current permission denial throws an exception in some paths; a future production test plan should expect a proper 403 flow.

## 5. Route Map

Current route table in `public/index.php`:

| Method | Route | Controller/handler | Purpose |
| --- | --- | --- | --- |
| GET | `/` | `SiteController::landing` | Public landing page |
| GET | `/auth` | `SiteController::auth` | Demo auth/get-started page |
| GET | `/demo` | `SiteController::demo` | Demo overview page |
| GET | `/demo/company-admin` | Inline demo role handler | Switch local demo session to tenant company admin |
| GET | `/demo/platform-admin` | Inline demo role handler | Switch local demo session to platform admin |
| GET | `/pricing` | `SaasController::pricing` | Public SaaS pricing with currency selector |
| GET | `/dashboard` | `DashboardController::index` | Operations dashboard |
| GET | `/platform-admin` | `PlatformAdminController::index` | SaaS operator/admin dashboard |
| POST | `/platform-admin/tenants/login` | `PlatformAdminController::loginAsTenant` | Start support session as selected tenant admin |
| GET/POST | `/platform-admin/tenants/return` | `PlatformAdminController::returnToPlatformAdmin` | Restore original platform admin session |
| POST | `/platform-admin/billing/override` | `PlatformAdminController::applyBillingOverride` | Save/clear manual tenant invoice override |
| POST | `/platform-admin/accounting/connect` | `PlatformAdminController::connectAccounting` | Link platform accounting provider for tenant billing |
| GET | `/clients` | `OperationsController::clients` | Demo client list with search |
| GET | `/clients/create` | `ClientController::create` | Create client form |
| POST | `/clients` | `ClientController::store` | Validate/store client |
| GET | `/jobs` | `JobController::index` | Jobs list with search/status filter |
| GET | `/jobs/view` | `JobController::view` | Job drill-in by query `id` |
| GET | `/jobs/create` | `JobController::create` | Create job form |
| POST | `/jobs` | `JobController::store` | Validate/store job |
| GET | `/schedule` | `ScheduleController::index` | Week calendar, appointments, unscheduled jobs |
| POST | `/schedule/appointments` | `ScheduleController::store` | Book appointment/meeting/reminder |
| GET | `/quotes` | `OperationsController::quotes` | Quote list with search/status filter |
| GET | `/quotes/create` | `QuoteController::create` | Create quote form |
| POST | `/quotes` | `QuoteController::store` | Validate/store quote in session demo repository |
| GET | `/invoices` | `OperationsController::invoices` | Invoice list with search/status filter |
| GET | `/invoices/create` | `InvoiceController::create` | Create invoice form |
| POST | `/invoices` | `InvoiceController::store` | Validate/store invoice in session demo repository |
| GET | `/ai-assistant` | `OperationsController::aiAssistant` | Demo AI assistant UI |
| GET | `/import-data` | `OperationsController::importData` | Import type selection and validation preview |
| GET | `/import-data/sample` | `OperationsController::importSampleCsv` | Download sample CSV for selected import type |
| GET | `/export-data` | `OperationsController::exportData` | Export selection UI |
| GET | `/export-data/download` | `OperationsController::exportDownload` | CSV export endpoint |
| GET | `/team` | `OperationsController::team` | Team members demo screen |
| GET | `/reports` | `OperationsController::reports` | Analytics cards |
| GET | `/settings` | `OperationsController::settings` | Profile/preferences/security demo screen |
| POST | `/logout` | Inline handler | Logout and redirect to landing |
| GET | `/settings/accounting` | `AccountingSettingsController::index` | Accounting provider foundation |
| GET | `/settings/calendar` | `CalendarSettingsController::index` | Calendar provider/sync foundation |
| GET | `/settings/llm` | `LlmSettingsController::index` | LLM API settings foundation |
| GET | `/settings/pricing` | `PricingAdminController::index` | Platform pricing admin form |
| POST | `/settings/pricing` | `PricingAdminController::save` | Save pricing/trial/currency/discount settings |
| POST | `/settings/pricing/reset` | `PricingAdminController::reset` | Reset pricing settings |
| GET | `/workspace` | `SaasController::workspace` | Tenant workspace/subscription overview |
| GET | `/subscription` | `SaasController::subscription` | Tenant subscription and usage page |

## 6. Role and Permission Model

RBAC is implemented in `src/Infrastructure/Security/RbacService.php`. Permissions are role-based and checked server-side through `SessionAuth`.

Roles currently defined:

- `owner`
- `platform_admin`
- `manager`
- `supervisor`
- `team_member`
- `trainee`
- `demo_user`

Important permission areas:

- Core operations: dashboard, clients, jobs, quotes, invoices, schedule, team, reports, settings.
- Data movement: `import_csv`, `export_csv`.
- Integrations: accounting, calendar, LLM settings.
- SaaS tenant controls: `manage_tenant`, `manage_billing`.
- Platform owner controls: `view_platform_admin`, `manage_platform_admin`, `manage_platform_pricing`, `manage_platform_billing`, `impersonate_tenants`.
- API access: `access_api`.

Test plan needs:

- Positive and negative access tests per role.
- Server-side permission checks, not just hidden navigation.
- Tenant owners/directors must not have platform-admin or global-pricing permissions.
- Platform tenant-support sessions must restore the original platform admin and display visible support-session context while acting as a tenant admin.
- Platform billing tests must cover contract value, billed-to-date, remaining-to-bill, manual override validation, and platform accounting connection validation.
- CSRF failure tests on POST routes.
- Tenant isolation tests once DB-backed persistence is activated.

## 7. Functional Inventory by Module

### 7.1 Landing and Public Pricing

Implemented:

- Public landing page at `/`.
- Public pricing at `/pricing`.
- Pricing can select supported currencies through query parameters.
- Pricing plans are provided by `TradePlanCatalog` and `PricingConfigurationService`.

Test focus:

- Public pages load without authenticated setup.
- Currency fallback works for unsupported currencies.
- Plans display correct monthly price, effective discounted price, trial days, tax behavior, and feature lists.
- XSS safety on query-driven currency input.

### 7.2 Dashboard

Implemented:

- KPI cards for total jobs, pending quotes, unpaid invoices, and revenue.
- Recent jobs section.
- Pending quotes section.
- Quick actions to create job, quote, client, and use AI assistant.
- Uses demo data through `OperationsDemoData` and job workflow services.

Test focus:

- Dashboard loads under XAMPP base path.
- Navigation and quick actions resolve correctly.
- KPI values match demo data.
- Role access: dashboard visible to allowed roles only.
- Responsive layout on mobile/tablet/desktop.

### 7.3 Jobs

Implemented:

- Jobs list at `/jobs`.
- Search and status filter.
- Create job form at `/jobs/create`.
- POST validation through `JobWorkflowService`.
- Job drill-in at `/jobs/view?id=...`.
- Detail screen includes job summary, status, priority, customer/location, checklist, timeline, financial snapshot, and related actions.
- Demo job data includes 20 records and blocker/workflow signals.

Current persistence:

- `JobRepository` exists for PDO persistence.
- Current local wiring uses demo data through `JobWorkflowService(null, OperationsDemoData)`.

Test focus:

- Search by title, client, location, and status.
- Status filter combinations.
- Unknown job ID returns 404 behavior.
- Create job validation: required title, client, supported status, supported priority, valid dates.
- Checklist, timeline, financials, and action sections render for each job status.
- Buttons and links from list/detail do not dead-end.
- Permission tests for view/create/update/delete jobs.
- Future DB-backed tests must verify tenant ownership and prepared statements.

### 7.4 Schedule and Calendar UI

Implemented:

- Week calendar at `/schedule`.
- Monday-based week calculation.
- Time slots.
- Appointment, meeting, and reminder types.
- Booking form POSTs to `/schedule/appointments`.
- Server-side validation for title, client, date, time, duration, type, technician, and conflicts.
- Same-technician overlap detection.
- Demo mode uses session-backed appointments through `DemoAppointmentSessionRepository`; production wiring uses `DatabaseAppointmentRepository` and the `appointments` table after Gate 15.
- Unscheduled jobs list.

Current persistence:

- Demo/session only.
- Production schema has calendar-related connection/event/job/webhook tables.

Test focus:

- Week navigation.
- Today/current-week handling.
- Appointment create success and validation errors.
- Conflict detection for same technician/time.
- No false conflict for different technician or non-overlapping time.
- Meeting and reminder type handling.
- Calendar grid visual behavior at small and large viewports.
- POST CSRF.
- Future drag/drop or reschedule interactions when added.

### 7.5 Quotes

Implemented:

- Quote list at `/quotes`.
- Search and status filter.
- Create quote form at `/quotes/create`.
- POST validation through `QuoteService`.
- Line item extraction.
- Quote totals through `QuoteCalculator`.
- Session-backed newly created demo quotes.
- Existing demo quote list from `OperationsDemoData`.

Statuses:

- `draft`
- `sent`
- `approved`

Test focus:

- New Quote button link and create flow.
- Required customer, supported status, valid date, tax rate, at least one valid line item.
- Quantity and unit price numeric validation.
- Totals: subtotal, tax, total.
- Session persistence after create.
- Search/filter behavior.
- Quote cards/status badges.
- Future quote detail, approval, conversion to invoice when implemented.

### 7.6 Invoices

Implemented:

- Invoice list at `/invoices`.
- Create invoice form at `/invoices/create`.
- POST validation through `InvoiceService`.
- Line item extraction.
- Totals through `InvoiceCalculator`.
- Session-backed newly created demo invoices.
- Existing demo invoices from `OperationsDemoData`.

Statuses:

- `draft`
- `sent`
- `unpaid`
- `paid`

Test focus:

- Required customer, supported status, valid due date, tax rate, valid line items.
- Total calculations.
- Session persistence.
- Unpaid/paid display.
- CSV export values for invoices.
- Future payment reconciliation and accounting sync behavior.

### 7.7 Clients

Implemented:

- Client list at `/clients` with search.
- Create client form at `/clients/create`.
- `ClientService` validation.
- `ClientRepository` supports tenant-scoped PDO pagination/create.
- Current list is demo data through `OperationsController`.

Test focus:

- Search by client name/contact/address.
- Create validation: required name, email format.
- Links from client cards.
- Future DB-backed CRUD: tenant ownership, pagination, update/delete, duplicate handling.

### 7.8 AI Assistant

Implemented:

- Demo AI assistant UI with modes such as quote helper, schedule, and general.
- LLM provider settings foundation in `/settings/llm`.
- `LlmProviderRegistry` includes common providers.
- `LlmConnectionService` validates provider, display name, model, API key, and HTTPS custom endpoint.
- Secret masking is implemented.
- Import safety rules are documented in service output.

Not yet implemented:

- No live LLM API calls.
- No stored encrypted API keys.
- No AI-generated import mapping execution.

Test focus:

- UI modes and inputs render.
- LLM settings page lists providers and demo connections.
- Validation rejects unsupported provider, short keys, and insecure custom URLs.
- Secret masking only exposes safe prefix/suffix.
- Future tests must mock LLM responses and require human approval before data mutation.

### 7.9 Import Data

Implemented:

- Import page at `/import-data`.
- Customer chooses data type before validation.
- Supported import types:
  - `customers`
  - `jobs`
  - `quotes`
  - `invoices`
  - `team`
- Mandatory/recommended/optional field schemas through `ImportSchemaRegistry`.
- Header normalization and alias mapping.
- Validation preview through `ImportValidationService`.
- Sample CSV download at `/import-data/sample?type=...`.

Required fields:

| Type | Required fields |
| --- | --- |
| Customers | `name` |
| Jobs | `title`, `client_name`, `status` |
| Quotes | `quote_number`, `client_name`, `status`, `subtotal`, `total` |
| Invoices | `invoice_number`, `client_name`, `status`, `total`, `due_date` |
| Team | `name`, `email`, `role` |

Protocol rules:

- CSV import should use UTF-8.
- First row must contain headers.
- Required fields are mandatory before import.
- Header aliases are normalized.
- Unknown fields should be reported.
- Import should validate before mutating data.

Not yet implemented:

- No real multipart file upload processing.
- No import commit to database.
- No background import job runner.

Test focus:

- Type selector changes schemas and sample file headers.
- Required field validation.
- Alias normalization such as `Customer Name` -> `name`.
- Missing required field reporting.
- Unknown field reporting.
- Sample CSV content type and filename.
- Future file upload tests: MIME sniffing, max size, malicious CSV payloads, formula injection, duplicate rows, partial failures, rollback, and audit logs.

### 7.10 Export Data

Implemented:

- Export page at `/export-data`.
- Dataset selector for all data, clients, jobs, quotes, and invoices.
- CSV endpoint at `/export-data/download?dataset=...`.

Test focus:

- Export UI selections.
- CSV content type, filename, headers, escaping, and row counts.
- Invalid dataset falls back safely.
- Export requires `export_csv` permission.
- Future tenant isolation and large export performance.

### 7.11 Team

Implemented:

- Team screen at `/team`.
- Demo team member list.

Test focus:

- Team table/card rendering.
- Invite button/link state.
- Role display.
- Future invite workflow: email validation, token expiry, role assignment, seat limits, audit events.

### 7.12 Reports

Implemented:

- Reports screen at `/reports`.
- Jobs by status.
- Quote funnel.
- Revenue card.
- Jobs per technician placeholder.

Test focus:

- Report numbers match demo data.
- Empty state for unassigned jobs.
- Future DB-backed analytics: date ranges, saved exports, tenant isolation, permissions, and numeric accuracy.

### 7.13 Settings

Implemented:

- Settings page at `/settings`.
- Profile information.
- Appearance toggle UI.
- Notification toggles.
- Security/sign out area.

Test focus:

- Controls render and preserve expected local state where implemented.
- Logout POST works with CSRF.
- Future persistence for settings/preferences.

### 7.14 Accounting Integrations

Implemented:

- Settings page at `/settings/accounting`.
- Provider registry for:
  - Xero
  - Intuit QuickBooks Online
  - Sage Accounting
  - Zoho Books
  - MYOB
  - FreeAgent
  - Reckon
  - SMEPlus
  - FreshBooks
  - Wave Accounting
- Provider metadata includes auth type, status, regions, capabilities, docs URL, and notes.
- `AccountingConnectionService` validates supported providers and external tenant ID.
- SMEPlus is intentionally marked as requiring owner confirmation because official developer documentation was not found in current project research.

Not yet implemented:

- No live OAuth flow.
- No token exchange or refresh.
- No live sync of contacts, quotes, invoices, payments, items, or tax rates.

Test focus:

- Provider registry completeness.
- Capability matrix correctness.
- Unsupported/unconfirmed provider validation.
- Settings page visibility by role.
- Future contract tests against mocked provider APIs.
- Future OAuth callback, token storage, refresh, disconnect, retry, rate limit, idempotency, and audit logging.

### 7.15 Calendar Integrations

Implemented:

- Settings page at `/settings/calendar`.
- Provider registry for Google Calendar and Outlook/Microsoft 365 Calendar.
- Two-way sync strategy metadata.
- Demo connections and event links.
- Validation for provider, sync direction, external account ID, and external calendar ID.
- Conflict rule: queue conflict when FieldOps and external provider both changed.

Not yet implemented:

- No live OAuth.
- No Google push channel handling.
- No Microsoft Graph change notification handling.
- No actual event mutation in external calendars.

Test focus:

- Provider registry completeness.
- Two-way sync option display.
- Validation errors.
- Conflict logic.
- Future event create/update/delete mapping, recurrence, timezone, daylight saving time, webhook signatures, replay protection, and sync idempotency.

### 7.16 SaaS Workspace and Subscription

Implemented:

- Tenant workspace at `/workspace`.
- Subscription/usage page at `/subscription`.
- Trade plan catalog through `TradePlanCatalog`.
- Usage snapshot through `TenantSubscriptionService`.
- Seat limit checks.
- Trade segments and onboarding checklist.

Plans:

- Starter
- Growth
- Scale

Plan dimensions:

- Included seats.
- Job limit.
- AI credits.
- Storage GB.
- Feature flags.
- Multi-currency prices.

Test focus:

- Plan display by currency.
- Usage percentage calculations.
- Seat add limits.
- Feature support gates.
- Onboarding checklist rendering.
- Future billing provider integration and entitlement enforcement.

### 7.17 Platform Admin and Global Pricing

Implemented:

- Platform admin dashboard at `/platform-admin`.
- Read-only SaaS operator overview with tenants, MRR/ARR/trials, risk, billing health, integration health, incidents, audit events, quick actions, and security checklist.
- Global pricing admin at `/settings/pricing`.
- Platform owner/admin can configure:
  - Default currency
  - Supported currencies
  - Supported regions
  - Trial period
  - Global discount percent
  - Discount label
  - Discount expiry
  - Tax behavior
  - Per-plan currency prices
- Demo settings are session-backed through `DemoPricingSettingsRepository`.

Supported currencies:

- USD, GBP, EUR, AUD, CAD, NZD, SGD, INR, LKR, ZAR, AED

Supported regions:

- North America
- United Kingdom
- Europe
- Australia and New Zealand
- Asia Pacific
- Middle East and Africa
- South Asia

Tax behaviors:

- `exclusive`
- `inclusive`
- `not_collected`

Test focus:

- Platform admin access restricted to `platform_admin`, `owner`, or `demo_user` where configured.
- Pricing form validation:
  - Default currency must be supported and enabled.
  - At least one supported currency.
  - At least one operating region.
  - Trial days between 0 and 365.
  - Discount percent between 0 and 95.
  - Discount expiry in `YYYY-MM-DD`.
  - Positive prices for every plan/currency.
  - Valid tax behavior.
- Save/reset flows with CSRF.
- Session persistence.
- Public pricing reflects saved settings and discount.
- Future production tests: audit logs, billing event impact, tenant grandfathering, tax compliance, Stripe/webhook integration.

## 8. Data and Persistence Model

Current implementation has three persistence levels:

1. Demo data arrays:
   - `OperationsDemoData` provides jobs, clients, quotes, invoices, dashboard stats, reports, schedule seed data, unscheduled jobs, and team members.
2. Session-backed demo repositories:
   - `DemoQuoteSessionRepository`
   - `DemoInvoiceSessionRepository`
   - `DemoAppointmentSessionRepository`
   - `DatabaseAppointmentRepository`
   - `DemoPricingSettingsRepository`
3. Production-oriented PDO/schema foundations:
   - `ClientRepository`
   - `JobRepository`
   - `AccountingConnectionRepository`
   - `database/schema.sql`

Production schema groups in `database/schema.sql`:

- Tenant and SaaS billing:
  - `tenants`
  - `subscription_plans`
  - `tenant_subscriptions`
  - `tenant_usage_counters`
  - `tenant_invitations`
  - `tenant_feature_flags`
  - `billing_events`
- Users and RBAC-adjacent data:
  - `users`
  - `api_tokens`
  - `audit_logs`
- Field operations:
  - `clients`
  - `jobs`
  - `job_checklist_items`
  - `job_timeline_events`
  - `quotes`
  - `quote_items`
  - `invoices`
  - `invoice_items`
- Inventory and truck stock foundations:
  - `inventory_items`
  - `truck_stock`
- Customer portal and automation foundations:
  - `customer_portal_tokens`
  - `automation_rules`
  - `saved_reports`
- Accounting integration foundations:
  - `accounting_connections`
  - `accounting_sync_jobs`
  - `accounting_sync_logs`
- Calendar integration foundations:
  - `calendar_connections`
  - `calendar_event_links`
  - `calendar_sync_jobs`
  - `calendar_webhook_events`
- LLM/import/export foundations:
  - `llm_connections`
  - `llm_usage_logs`
  - `import_jobs`
  - `import_mapping_profiles`
  - `import_validation_reports`
  - `export_jobs`
  - `demo_data_registry`
- Generic settings:
  - `settings`

Testing implication: the test plan must clearly distinguish current behavior tests from schema contract tests. Many schema-backed production capabilities are foundations only until controllers/services are wired to the database.

## 9. Current Automated Coverage

Current commands:

- `composer test`
- `composer check`
- `php tests/run.php`
- `php tools/lint-php.php`

`composer.json` scripts:

- `test`: `php tests/run.php`
- `check`: `php tests/run.php && php tools/lint-php.php`

Current `tests/run.php` coverage includes:

- Password hashing and password policy.
- Auth registration hash and login verification.
- RBAC permissions for operations, integrations, SaaS billing, pricing, and platform admin.
- XAMPP request path stripping.
- Client validation.
- Job validation, search, status filtering, detail lookup, checklist, timeline, financials, actions, workflow stats.
- Demo data scale for Replit-derived operations data.
- SaaS plan catalog and feature support.
- Pricing settings validation, persistence, selected currency fallback, discount calculation.
- Platform admin overview, billing health, quick actions, and security checklist.
- Subscription usage percentages and seat limits.
- Quote totals, validation, line item extraction, demo quote mapping.
- Invoice totals, validation, line item extraction, demo invoice mapping.
- Demo reset scoping.
- JSON responder construction.
- Accounting provider registry and connection validation.
- Calendar provider registry, sync validation, strategies, and conflict logic.
- Schedule week calculation, time slots, validation, appointment building, and conflict detection.
- Import schemas, required fields, header normalization, validation preview, protocol rules.
- LLM provider registry, connection validation, secret masking, and import safety rules.

Current automated coverage gaps:

- No browser/e2e suite.
- No full controller integration tests.
- No real database integration tests.
- No live XAMPP/Apache smoke test in the automated suite.
- No accessibility tests.
- No visual regression tests.
- No live OAuth/provider tests.
- No upload/import commit tests.
- Gate 5 billing provider/webhook foundations now have tests for manual defaults, provider readiness, signed webhook verification, stale/invalid signature rejection, tenant metadata, duplicate replay handling, payload-hash conflict rejection, and database-backed billing overrides/events.
- No tenant-isolation integration tests against real persistence.

## 10. Recommended Testing Strategy

The test plan should use a layered model.

### 10.1 Static and Build Checks

Purpose: catch syntax, autoload, and standards regressions.

Recommended checks:

- `composer validate --no-check-publish`
- `composer test`
- `composer check`
- PHP lint over `src`, `public`, `tests`, `config`, and templates.
- Future: add PHPStan/Psalm only after owner approval because it adds tooling and baseline decisions.

### 10.2 Unit and Service Tests

Purpose: validate deterministic business logic.

Priority services:

- `RbacService`
- `CsrfService`
- `PasswordHasher`
- `Request`
- `PhpRenderer` base URL rewriting
- `JobWorkflowService`
- `ScheduleService`
- `QuoteService`
- `QuoteCalculator`
- `InvoiceService`
- `InvoiceCalculator`
- `ImportSchemaRegistry`
- `ImportValidationService`
- `AccountingProviderRegistry`
- `AccountingConnectionService`
- `CalendarProviderRegistry`
- `CalendarSyncService`
- `LlmProviderRegistry`
- `LlmConnectionService`
- `TradePlanCatalog`
- `TenantSubscriptionService`
- `PricingConfigurationService`
- `PlatformAdminService`

Minimum unit test themes:

- Required-field validation.
- Boundary values.
- Invalid enum/status values.
- Numeric precision for money/tax.
- Date parsing.
- Time overlap logic.
- Currency fallback.
- Discount math.
- Permission allow/deny.
- Secret masking.
- Header normalization.

### 10.3 Controller and HTTP Integration Tests

Purpose: prove routes, permissions, CSRF, redirects, and templates work together.

Recommended coverage:

- Every route in the route map returns the correct status for an authorized user.
- Unknown route returns 404.
- Unauthorized role receives a 403-style response.
- POST without CSRF is rejected.
- POST with invalid data returns form with validation errors.
- POST with valid data redirects to the correct list/detail screen.
- XAMPP base path is preserved in generated links and redirects.
- HTML responses contain escaped user-provided values.

Current gap: the app does not yet have a proper controller test harness. The testing architect can recommend either direct construction of controllers with fake `Request` objects or a small HTTP runner around `App`.

### 10.4 Browser End-to-End Tests

Purpose: catch broken buttons, links, forms, navigation, and layout regressions.

Recommended tool:

- Playwright or an equivalent browser automation tool.
- Do not add the dependency without owner approval if this plan is only documentation.

Core E2E smoke flows:

1. Open `/`.
2. Navigate to `/dashboard`.
3. Use sidebar links to visit every primary screen.
4. Create a quote and verify it appears in `/quotes`.
5. Create an invoice and verify it appears in `/invoices`.
6. Create an appointment and verify it appears on `/schedule`.
7. Search/filter jobs.
8. Open a job detail page from `/jobs`.
9. Download a sample import CSV for each import type.
10. Download an export CSV for each dataset.
11. Save pricing settings as platform admin/demo user and verify `/pricing` reflects changes.
12. Reset pricing settings.
13. Logout.

Browser viewports:

- Mobile: 390 x 844
- Tablet: 768 x 1024
- Desktop: 1366 x 768
- Wide desktop: 1920 x 1080

Browser assertions:

- No horizontal overflow.
- Text does not overlap.
- Buttons are visible and clickable.
- Forms retain values after validation errors.
- Primary navigation highlights current page.
- Dropdowns, selects, and links work under the XAMPP base path.

### 10.5 Security Tests

Purpose: protect user, tenant, financial, integration, AI, and imported data.

Required security coverage:

- Authentication:
  - Production mode must not auto-login.
  - Password policy.
  - Password hashing.
  - Logout invalidates session.
- Authorization:
  - Every protected route enforces permission server-side.
  - Platform admin routes are inaccessible to tenant roles.
  - Tenant users cannot access another tenant's records once DB persistence is enabled.
- CSRF:
  - All non-API POST routes require CSRF token.
  - Invalid/missing token fails safely.
- Input validation:
  - Every create/update route rejects malformed input.
  - Search/filter inputs are escaped and cannot inject HTML.
- Output encoding:
  - User-controlled values render escaped in templates.
- Secrets:
  - LLM/accounting/calendar credentials are never logged or rendered raw.
  - Future tokens must be encrypted or hashed as appropriate.
- Upload/import:
  - Only expected CSV files.
  - Size limits.
  - Formula injection mitigation.
  - Safe error reports.
- External integrations:
  - OAuth state/nonce validation.
  - Webhook signature validation.
  - Replay protection.
  - Idempotency.
- Audit:
  - Pricing changes, connection changes, imports, exports, billing changes, and admin actions should create audit logs once persistence is wired.

### 10.6 Data and Database Tests

Purpose: verify production schema and repository contracts.

Recommended coverage:

- Schema can import cleanly into MySQL.
- Seed data imports cleanly.
- Required indexes and foreign keys exist.
- Repositories use tenant-scoped queries.
- Create/list/update/delete flows do not cross tenants.
- Money fields preserve precision.
- Date/time fields handle timezone assumptions.
- Soft-delete or status transitions work as designed when added.
- Migration tests for future SQL changes.

### 10.7 Integration Contract Tests

Purpose: validate provider abstractions without requiring live third-party credentials.

Accounting:

- Provider metadata matches supported provider list.
- Capabilities are correctly exposed per provider.
- Connection request validation rejects unsupported providers and missing external tenant IDs.
- Future mocked sync:
  - contact/customer sync
  - quote/estimate sync
  - invoice sync
  - payment sync
  - tax/item sync
  - provider rate limits
  - provider downtime
  - retry and idempotency

Calendar:

- Google and Outlook provider metadata exists.
- Two-way sync settings validate.
- Conflict detection queues conflicts when both sides changed.
- Future mocked sync:
  - FieldOps appointment creates external event
  - External event creates FieldOps appointment
  - Edits in either direction
  - Deletes/cancellations
  - Recurring events
  - Timezones and daylight saving changes

LLM:

- Provider validation.
- HTTPS-only custom endpoint.
- Key masking.
- Future mocked import mapping:
  - successful mapping suggestion
  - low-confidence mapping requiring human review
  - malicious prompt in CSV header
  - overlong input
  - provider timeout
  - rate limit response
  - no data mutation without validation approval

### 10.8 SaaS and Billing Tests

Purpose: validate platform owner/admin and tenant subscription behavior.

Current tests should cover:

- Plan catalog in each supported currency.
- Feature gates by plan.
- Usage percentage.
- Seat limit checks.
- Pricing settings save/reset.
- Trial days.
- Discounts.
- Tax behavior display.
- Platform admin overview visibility.

Future production tests should cover:

- Stripe or chosen billing provider Checkout flow.
- Subscription create/update/cancel.
- Trial conversion.
- Failed payment handling.
- Invoice/payment webhook idempotency.
- Customer portal.
- Entitlement changes after plan upgrade/downgrade.
- Multi-currency rounding and tax behavior.
- Billing audit logs.

### 10.9 Accessibility and Usability Tests

Purpose: make the product usable for office staff, managers, and technicians.

Coverage:

- Keyboard navigation.
- Focus states.
- Form labels and error text associations.
- Contrast.
- Button names and icon labels.
- Responsive behavior.
- Tables/cards readable on mobile.
- Long customer/job names do not overflow.
- Status badges remain understandable without color alone.

### 10.10 Performance and Reliability Tests

Purpose: prepare for production SaaS scale.

Current local prototype tests:

- Pages load quickly with demo data.
- CSV export works for demo-sized datasets.
- Search/filter does not noticeably lag.

Future production tests:

- 10,000+ clients.
- 50,000+ jobs.
- Large CSV imports with validation preview.
- Long-running import/export background jobs.
- Schedule calendar with many events.
- Report generation under load.
- Provider sync retries.
- Database query performance with tenant filters and indexes.

## 11. Suggested Functional Test Case Matrix

The testing architect should convert this into executable cases with IDs, preconditions, data, steps, expected results, priority, automation suitability, and traceability to requirements.

| Area | High-priority cases |
| --- | --- |
| Routing | Every GET route loads; unknown route 404; XAMPP base path works |
| Navigation | Sidebar links, quick actions, create buttons, settings links, logout |
| Auth/RBAC | Each role allowed/denied for core, admin, integration, import/export routes |
| CSRF | Missing/invalid token rejected on each POST |
| Dashboard | KPI consistency, recent jobs, pending quotes, quick actions |
| Jobs | Search/filter, create validation, detail by ID, missing ID/unknown ID, checklist/timeline/financials |
| Schedule | Week navigation, appointment create, conflict detection, invalid time/date/duration |
| Quotes | Create valid quote, invalid quote, totals, session persistence, filter/search |
| Invoices | Create valid invoice, invalid invoice, totals, session persistence, filter/search |
| Clients | Search, create validation, future DB CRUD and tenant scope |
| Import | Type selection, required fields, aliases, sample CSV, unknown fields, future upload validation |
| Export | Dataset selection, CSV headers, invalid dataset fallback, permission checks |
| AI/LLM | Settings validation, custom HTTPS endpoint, secret masking, future mocked mapping |
| Accounting | Provider list, capability matrix, unsupported provider handling, future OAuth/sync mocks |
| Calendar | Google/Outlook metadata, two-way settings, conflict logic, future webhook/sync mocks |
| SaaS | Plan features, usage, seat limits, workspace/subscription UI |
| Pricing Admin | Save/reset, currencies, regions, trial, discount, tax behavior, invalid values |
| Platform Admin | Operator dashboard data, restricted access, security checklist |
| Security | XSS, CSRF, auth, permissions, tenant isolation, secret handling, audit readiness |
| Accessibility | Keyboard, labels, focus, contrast, responsive layouts |
| Performance | Large data, import/export, reports, calendar density |

## 12. Known Current Limitations

These are important so the testing architect does not design tests as if all foundations are fully production-ready today.

| Area | Current state |
| --- | --- |
| Authentication | Demo auto-login exists in `public/index.php`; production login flow is not the current focus |
| Persistence | Many screens are demo/session-backed rather than fully DB-backed |
| Tenant isolation | Schema and service intent exist; full DB-backed enforcement needs more integration tests once wired |
| Import | Type/schema validation and sample CSV exist; real file upload and commit are not implemented |
| Accounting | Provider registry and validation exist; live OAuth and sync are not implemented |
| Calendar | Provider registry and conflict rules exist; live OAuth, webhooks, and event mutations are not implemented |
| LLM | Provider settings and validation exist; live API calls and encrypted key storage are not implemented |
| Billing | SaaS plans/pricing/admin foundations exist; Gate 5 signed webhook/idempotency foundations exist; live payment capture, Checkout/Customer Portal, and subscription-state mutation are not implemented |
| Platform admin | Read-only demo dashboard; operational mutation actions are not implemented |
| Browser tests | No automated Playwright/Selenium suite yet |
| Database tests | No MySQL integration test suite yet |
| Error handling | Some permission failures throw exceptions rather than rendering a polished 403 response |
| Background jobs | Import/export/sync job schemas exist; no worker runner yet |

## 13. Critical Risks to Target Early

1. Broken links/forms under the XAMPP base path.
2. Buttons that render but do not navigate or submit correctly.
3. Permission checks missing on newly added routes.
4. CSRF failures on valid forms or missing CSRF checks on new POST routes.
5. Session demo data disappearing unexpectedly or leaking between flows.
6. Money/tax rounding errors in quote, invoice, and pricing calculations.
7. Schedule conflicts not detected correctly.
8. Import validation accepting incomplete or unsafe files.
9. Provider settings implying live integration where only foundation exists.
10. Tenant isolation gaps when moving from demo data to database-backed records.
11. Secrets accidentally displayed in LLM/accounting/calendar screens.
12. Platform admin controls accessible to tenant users.

## 14. Recommended Test Deliverables

The testing architect should produce:

1. Master test plan.
2. Requirements/feature traceability matrix.
3. Test environment setup guide for XAMPP and CI.
4. Smoke test suite.
5. Service/unit test suite expansion plan.
6. HTTP/controller integration suite plan.
7. Browser E2E suite plan.
8. Security test plan.
9. Integration contract test plan for accounting, calendar, and LLM providers.
10. Data/import/export test plan.
11. SaaS billing/admin test plan.
12. Accessibility/responsive test checklist.
13. Regression suite and release gate definition.
14. Defect taxonomy and severity definitions.
15. Test data strategy with demo, tenant-isolated, and malicious datasets.

## 15. Suggested Release Gates

Minimum gate for local prototype:

- `composer validate --no-check-publish` passes.
- `composer test` passes.
- `composer check` passes.
- Browser smoke test passes for all primary routes.
- Create quote, invoice, job, and appointment flows manually verified.
- CSV sample/export endpoints manually verified.
- Pricing admin save/reset manually verified.
- No obvious broken buttons or dead links on primary screens.

Minimum gate for production SaaS beta:

- Automated unit, integration, and browser smoke suites pass.
- MySQL schema and seed import pass in a clean environment.
- Auth auto-login is disabled in production mode.
- RBAC and CSRF tests pass.
- Tenant isolation tests pass for all DB-backed records.
- Import upload validation is hardened.
- Secrets are encrypted/masked and never logged.
- OAuth/webhook flows are mocked and contract-tested.
- Billing webhooks are idempotent and audit logged.
- Accessibility smoke checks pass.
- Security review completed for auth, permissions, financial data, integrations, uploads, AI, and secrets.

## 16. Source Files to Read First

For a testing architect cloning the code, read these files first:

- `README.md`
- `AGENTS.md`
- `public/index.php`
- `composer.json`
- `tests/run.php`
- `database/schema.sql`
- `docs/ARCHITECTURE.md`
- `docs/SAAS_PLATFORM.md`
- `docs/IMPORT_AND_LLM.md`
- `docs/ACCOUNTING_INTEGRATIONS.md`
- `docs/CALENDAR_INTEGRATIONS.md`
- `docs/TESTING.md`
- `src/Infrastructure/Security/RbacService.php`
- `src/Application/App.php`
- `src/Infrastructure/Http/Request.php`
- `src/Infrastructure/View/PhpRenderer.php`
- `src/Demo/Service/OperationsDemoData.php`
- `src/Job/Service/JobWorkflowService.php`
- `src/Schedule/Service/ScheduleService.php`
- `src/Quote/Service/QuoteService.php`
- `src/Invoice/Service/InvoiceService.php`
- `src/Importing/Service/ImportSchemaRegistry.php`
- `src/Saas/Service/PricingConfigurationService.php`
- `src/Saas/Service/PlatformAdminService.php`

## 17. Final Notes for the Test Plan Author

Design the plan around current behavior first, then add future contract sections for foundations that are present in schema/services but not yet live. Avoid assuming live credentials or real third-party provider behavior. Use mocks for accounting, calendar, LLM, and billing integrations until credentials, provider apps, and production secrets management are confirmed.

The most valuable early automation will be:

1. A browser smoke suite that clicks every visible button/link and submits the key forms.
2. Controller-level tests for route/CSRF/RBAC behavior.
3. Service-level expansion around pricing, schedule conflicts, import validation, quote/invoice math, and provider validation.
4. MySQL schema import and tenant-isolation tests once database-backed controllers are wired.
