I partially expected the virus check to be written into the model as a before_save callback -- one that checks whether the content datastream has changed and reruns the virus_check as necessary.