# Zavvion Events MVP Handoff Runbook

Prepared: 2026-05-07

Audience: senior architect, launch owner, and final QA lead taking the current MVP through local rehearsal, Stripe validation, client demo, and go/no-go review.

This is a documentation-only handoff. It describes the current MVP shape and the launch checks that still need human sign-off; it does not claim production readiness.

## Local Install And XAMPP Setup

Recommended local path:

```text
C:\xampp9\htdocs\e\zavvion-events
```

Older local path used in previous handoffs:

```text
C:\xampp\htdocs\zavvion-events
```

Current Git workspace:

```text
C:\xampp9\htdocs\e\zavvion-events
```

Local base URL:

```text
http://localhost/zavvion-events/public/
```

Use XAMPP with PHP 8.2+ and MySQL/MariaDB. If `php` is not available on `PATH`, run commands through:

```powershell
C:\xampp9\php\php.exe
```

Install steps:

1. Copy or symlink the project to the active XAMPP web root, currently `C:\xampp9\htdocs\e\zavvion-events`.
2. Copy `.env.example` to `.env`.
3. Keep local database defaults unless changed intentionally:
   `DB_DSN=mysql:host=127.0.0.1;port=3306;dbname=zavvion_events;charset=utf8mb4`,
   `DB_USERNAME=root`, `DB_PASSWORD=`.
4. Install Composer packages if `vendor/` is absent:

```powershell
composer install
```

5. Install or reset the local MVP database:

```powershell
Set-Location C:\xampp9\htdocs\e\zavvion-events
C:\xampp9\php\php.exe bin\install-database --fresh --yes
```

The database installer reads `.env`, creates the database from `DB_DSN`, imports `docs/schema.sql`, applies MVP runtime defaults, and seeds demo users, organiser, event, venue, reserved seats, adult/child ticket types, fees, tax, promo, merchandise, donation settings, and featured placement packages. See `docs/database-install.md` for options such as `--dry-run`, `--no-seed`, and `--database`.

## Multi-Agent Development Setup

Future Codex sessions should use specialist agents when it shortens safe delivery time. This is recommended for broad MVP work, frontend/backend integration, QA passes, security-sensitive changes, and deployment readiness, but it must stay dependency-aware:

- The lead architect session owns the plan, file ownership, integration, and final sign-off.
- Use parallel agents only for independent work streams, for example frontend polish, backend service tests, API contract review, security review, and QA smoke testing.
- Give each implementation agent a clear write scope and tell it not to edit or revert files owned by another agent.
- Sequence dependent work: schema/API/service changes first, then UI integration, then tests, then security/final review.
- Use `security_reviewer` for payments, auth, permissions, uploads, privacy, personal data, finance, Stripe, deployment, and dependency changes.
- Use `qa_test_engineer` for feature work, bug fixes, refactors, and critical checkout/scanner/finance flows.
- Do not let agents add production dependencies, change `.env`, insert real Stripe keys, or modify deployment/security settings without explicit approval.
- Every agent must report files read, files changed, tests/checks run, risks, and unresolved dependencies.

This keeps the project moving faster without losing traceability or letting parallel work create merge conflicts.

Before changing organiser seat blocking, ticket delivery, QR rendering, or SenMail payloads, read `docs/AI_DEVELOPMENT_NOTES.md`. It records the latest service boundaries, payload contracts, validation commands, and risks from the 2026-06-09 coding-agent work.

Before a walkthrough, run lightweight readiness checks:

```powershell
Set-Location C:\xampp9\htdocs\e\zavvion-events
C:\xampp9\php\php.exe bin\check-mvp-smoke --base-url=http://localhost/zavvion-events/public
C:\xampp9\php\php.exe bin\check-local-live-run --base-url=http://localhost/zavvion-events/public
```

## Demo Credentials

Use only for local or staging review:

- Platform super admin: `admin@zavvion.test` / `ChangeMe123!`
- Platform admin: `platform.admin@zavvion.test` / `ChangeMe123!`
- Organiser owner: `organiser@zavvion.test` / `ChangeMe123!`
- Organiser admin: `organiser.admin@zavvion.test` / `ChangeMe123!`
- Event manager: `event.manager@zavvion.test` / `ChangeMe123!`
- Cashier: `cashier@zavvion.test` / `ChangeMe123!`
- Ticket scanner: `scanner@zavvion.test` / `ChangeMe123!`
- Customer: `customer@zavvion.test` / `ChangeMe123!`

The installer seeds these in `bin/install-database`; the Yii seed path also documents the same local password in `migrations/M260502175000SeedDevelopmentData.php`. Change or remove these accounts before any public deployment.

## Primary Review URLs

- Public home: `http://localhost/zavvion-events/public/home.html`
- Public events: `http://localhost/zavvion-events/public/events.html`
- Demo event: `http://localhost/zavvion-events/public/event.html?slug=demo-gala`
- Checkout: `http://localhost/zavvion-events/public/checkout.html`
- Customer account/wallet: `http://localhost/zavvion-events/public/account.html`
- Organiser console: `http://localhost/zavvion-events/public/organiser.html`
- Admin console: `http://localhost/zavvion-events/public/admin.html`
- Scanner: `http://localhost/zavvion-events/public/scanner.html`
- Product map: `http://localhost/zavvion-events/public/product-map.html`
- Profile walkthrough: `http://localhost/zavvion-events/public/mvp-profiles.html`
- MVP showcase: `http://localhost/zavvion-events/public/mvp-showcase.html`

## Live Run Checklist

Public event browse:

- Open home and event listing.
- Confirm the `demo-gala` event loads from the live API with title, venue, date, media, ticket types, age policy, pricing, and seat data.
- Confirm mock fallback is not silently hiding broken API routes. Mock data should only be used when explicitly configured by query/local preview state.

Seat hold and ticket selection:

- Select reserved seats from the event detail page.
- Confirm the 15-minute hold countdown appears.
- Confirm ticket quantity must match selected reserved seats.
- Select adult and child ticket types.
- Confirm child-only checkout is blocked when the event/ticket rule requires an adult.
- Reduce/remove ticket lines and confirm removed seats are released or no longer checkout-eligible.

Public online checkout:

- For paid orders, use Stripe Checkout card payments only.
- Confirm `PAYMENT_MOCK_ENABLED=false` for production-like rehearsals.
- If a local mock walkthrough is explicitly approved, set `PAYMENT_MOCK_ENABLED=true` only in local/dev/test and record that the evidence is mock-only.
- Confirm public online sale issues tickets only after one trusted completion path: Stripe success/webhook processing, zero-total free-checkout confirmation, or explicitly configured local mock confirmation.
- Confirm failed or expired Stripe sessions leave drafts unpaid and release held seats.

Ticket QR and scanner:

- After a completed order, log in as the customer and open the wallet.
- Open the printable ticket and pass-ready ticket JSON.
- Confirm QR tokens are opaque and do not expose raw internal ticket/order IDs.
- Use scanner online validation for a fresh ticket.
- Scan the same ticket again and confirm duplicate/already-scanned handling.
- Test malformed, unknown, wrong-event, cancelled/refunded, and already-scanned tokens.
- Test manual scanner entry where camera `BarcodeDetector` support is unavailable.

Organiser box office:

- Log in as organiser owner.
- Open Organiser > Box Office.
- Issue a counter sale for cash.
- Issue a counter sale for external card.
- Confirm tickets are created through the box-office path and appear in scanner/customer ticket evidence where applicable.
- Confirm box office is counter-only: it is not a public online cash payment option.

Organiser build/edit controls:

- Open Organiser > Venues and edit a venue name, address, country, and floor-plan image.
- Create a selectable seat grid from rows/seats-per-row and attach it to an event.
- Open Organiser > Ticketing and edit an existing ticket type, including Adult/Child category, age range, price, quantity, max/order, ID/adult/parental-consent rules, and checkout terms.
- Try reducing ticket quantity below held/sold inventory and confirm the server rejects the change.
- Open Organiser > Merchandise, edit a product, change stock/status/price, and switch between selected events and all current/future events.
- Open Organiser > Ticketing promo panel, edit an existing promo code, usage limits, per-customer limit, minimum order, discount type/value, status, and event assignment.

Admin featured package setup:

- Log in as platform admin.
- Open Admin > Featured.
- Review seeded featured placement packages.
- Create or update an active package with name, duration days, price, currency, active flag, and sort order.
- Save manual featured event selection where needed.

Organiser featured placement purchase:

- Log in as organiser owner.
- Open Organiser > Marketing.
- Select a published event and active featured package.
- Start the featured placement checkout.
- Complete Stripe checkout when real Stripe test credentials are configured.
- Confirm the event appears as paid featured only after payment confirmation. If local mock is used, record the result as a mock-only validation.

## Stripe Readiness

Required environment review:

- Generate production-only local secrets with `php bin/generate-production-secrets` and paste them into the target server secret store or non-Git `.env`.
- `STRIPE_MODE=test` until a real go-live decision.
- `STRIPE_SECRET_KEY` set to a test secret key in staging/local Stripe validation.
- `STRIPE_PUBLISHABLE_KEY` set to the matching test publishable key.
- `STRIPE_WEBHOOK_SECRET` copied from the exact webhook endpoint configured for this environment.
- `STRIPE_PLATFORM_ACCOUNT_ID` reviewed by the payment owner when Connect platform identity is needed.
- `STRIPE_CONNECT_CHARGE_MODEL=destination_charge` for launch so the platform keeps the service fee and transfers organiser gross only. Do not use `direct_charge` unless the payment owner signs off on connected-account full-charge dashboard visibility and accounting.
- `PAYMENT_MOCK_ENABLED=false` outside local/dev/test.

Current code-side guardrails before handover:

- Paid online events can be published only when the organiser has a complete, charge-enabled connected account.
- Paid counter-only events may be published without Stripe only when online payments are disabled for that event.
- Public paid checkout will not create a platform-only Stripe charge for organiser ticket sales; without a complete charge-enabled connected account it stays payment-unavailable, or uses explicit local mock mode only in local/dev/test.
- Each organiser is limited to one connected account by the canonical schema and the local runtime adds the unique organiser index when existing data is clean.
- A Stripe account ID already assigned to another organiser is rejected instead of updating another organiser's account row.
- Platform fee rules are launch-scoped to one active global policy per country or one active event override. Create/update paths now run conflict checks inside a transaction with row locking where the database supports it.

Webhook setup:

- Configure Stripe to send webhooks to `POST /api/v1/webhooks/stripe`.
- Include Checkout Session completion and terminal failure/expiry events used by the current payment webhook controller.
- Verify signed webhook delivery in the same environment that created the Checkout Session.
- Record Stripe Checkout Session ID, PaymentIntent ID where present, webhook event ID, order ID, and issued ticket references.

Ticket issuance rule:

Public paid online sales must not issue tickets on browser redirect alone. Tickets are issued only after Stripe success/webhook handling or an explicitly configured local mock confirmation. Zero-total complimentary/free orders use the separate free-confirmation path.

## Cash And Counter Policy

- Cash is box-office only.
- External-card is box-office only for counter/card-terminal payments recorded outside Stripe Checkout.
- Public online checkout does not support cash.
- Public online paid checkout should use Stripe Checkout card payments only.
- Box-office sales create order/payment/ticket records for operational evidence, scanner validation, and finance review.
- Platform fee payable/invoice handling is a business/accounting concept for organiser-side settlement where cash or external-card counter sales occur; the MVP records the sale but does not provide full till-shift, cash drawer, cashier reconciliation, or automated invoice collection control.
- There is no till-shift open/close, float, cash-up, or cashier variance workflow in the MVP.

## No-Refund MVP Policy And Corrections

Current launch policy is no public self-service refunds and no automatic Stripe-originated refund workflow in the MVP.

- Refund features are platform feature-gated and disabled for organisers by default.
- Public legal/checkout copy should state organiser responsibility for refund decisions under the published event policy.
- Stripe disputes, automated Stripe refunds, and production refund automation are out of scope for this MVP launch.
- Corrections should be role-controlled and auditable:
  - Organisers handle operational correction requests for their own orders/events where their feature gates and permissions allow it.
  - Platform admins handle policy exceptions, feature-gate changes, compliance review, and finance/audit correction oversight.
  - Scanner/cashier roles should not be treated as refund approvers.
- If a correction changes attendance, ticket state, payment state, or settlement numbers, record the order ID, ticket references, reason, approver, and finance impact for manual reconciliation.

## Known Remaining Launch Risks

- Real Stripe test credentials, webhook signature validation, connected-account readiness, featured-placement checkout, and end-to-end reconciliation still require environment-specific human validation.
- Destination-charge Connect checkout must still be proven with real Stripe test keys, a transfer-ready connected organiser account, organiser-gross transfer amount, platform-retained service fee, and signed webhook completion before payment launch.
- Strict production launch currently blocks on environment setup rather than missing PHP business logic: `APP_ENV=prod`, `APP_DEBUG=false`, real non-Git `COOKIE_SECRET` and `QR_SIGNING_SECRET`, PHP GD, media validation hardening, and Stripe test/live credentials with webhook signing.
- Production outbound providers for ticket delivery, SMS OTP, finance exports, and alerts may still be local-log only unless configured.
- Production media still needs GD/crop/WebP support, storage/CDN policy, and a later decision on managed malware scanning.
- Local public uploads are acceptable for local MVP review but should not be treated as the final commercial media architecture without explicit approval.
- The large MVP router remains intentionally preserved for launch stability; Yii/controller/repository extraction is still a post-MVP architecture task.
- Real-device scanner QA is required, especially on devices without native `BarcodeDetector`.
- Seat-hold expiry requires the scheduler command to run every minute outside purely manual local testing.
- Backup/restore, rollback, DNS, TLS, log routing, and support escalation need named owners before launch.
- Legal copy for terms, privacy, refund/cancellation, age policy, cookie/consent, and organiser responsibility still needs final human sign-off.

## Manual Test Evidence To Capture

For each rehearsal, capture:

- Environment URL and commit/hash/release label.
- `.env` payment mode summary without secrets.
- Database install or migration command used.
- Smoke and local live-run command output.
- Public event browse screenshots.
- Seat hold checkout draft ID and expiry result.
- Adult/child validation evidence.
- Stripe Checkout Session ID, Connect charge model, connected account ID, Application Fee evidence, webhook event ID, and order/ticket IDs.
- Mock confirmation evidence if mock was used.
- Ticket QR screenshot or token reference, without exposing secrets.
- Scanner device ID and scan-log result for fresh and duplicate scans.
- Box-office cash/external-card order IDs and payment references.
- Admin featured package ID and organiser featured purchase ID.
- Accepted warnings, launch owner sign-off, and follow-up owner for each unresolved risk.

## Related Documents

- `docs/database-install.md`
- `docs/local-xampp-setup.md`
- `docs/human-architect-handoff.md`
- `docs/launch-handoff.md`
- `docs/mvp-launch-checklist.md`
- `docs/payments.md`
- `docs/stripe-connect.md`
- `docs/implementation-status.md`
