How do I override the user’s input when updating a custom post type’s permalink?

The publish_{post-type} action is triggered only when the post change from any post status (not published) to published; for example, if the post is already published and you edit it, the publish_{post-type} action is not triggered. I think you need to hook your function to save_post_{post_type} action, which is triggered every time a post is saved, not matter the status:

add_action('save_post_course-variation', 'update_course_variation_permalink', 10, 3);

function update_course_variation_permalink($course_variation_id){

  $cv_meta = get_post_meta($course_variation_id);
  $desired_permalink_value = "my/custom/permalink";

  if( isset($cv_meta['custom_permalink']) ){
      //HAS PERMALINK = CHECK AND UPDATE IF REQUIRED
      if( get_post_meta($course_variation_id, 'custom_permalink', true) != $desired_permalink_value ){
        update_post_meta($course_variation_id, 'custom_permalink', $desired_permalink_value); 
        $results = "UPDATED";
      }else{
        $results = "UNTOUCHED/ALREADY SET CORRECTLY";
      }
  }else{
    //DOESNT HAVE PERMALINK = ADD
    add_post_meta($course_variation_id, 'custom_permalink', $desired_permalink_value, true); 
    $results = "NEW CUSTOM PERMALINK CREATED";
  }

}//end function

Note: storing data in custom_permalink meta field doens’t affect to the permalink. Not sure how you are handling the post permalink. I just answered your question about how to trigger the function when a post is updated. If you want to truly override permalink (not a meta field), you could use this (based on this answer):

add_filter('wp_insert_post_data', 'wpse_wp_insert_post_data', 10, 2);
function wpse_wp_insert_post_data($data, $post_attr) {

    $desired_permalink_value = "my/custom/permalink";

    if( ( isset( $data['post_name'] ) && $data['post_name'] != $desired_permalink_value ) || empty( $data['post_name'] ) ) {
        $data['post_name'] = $desired_permalink_value;
    }

    return $data;
}