Validates the POST /api/v1/pricing/preview payload.
Scope enforcement is handled upstream by the oauth-api / public-api middleware chain + the scope:bookings:read gate on the route itself.
extras[].id tenant ownership is NOT validated here with a custom rule because a per-element Rule instance on an array attribute causes one fail() call per element — difficult to surface cleanly. Instead, the controller resolves each Extra under the active BelongsToTenant scope and throws a ValidationException for any that come back null (same pattern as BookingController::store extras).
POL-05: optional media-policy intent so the preview can gate requires_sharing_opt_in extras the same way the create path does. Shape-only — no persistence, no route-aware capture validation (this is a stateless quote endpoint).