Handling user defined options in vocabularies

The use case I am trying to handle is where some content type has a vocabulary for a field where the options are defined by a site admin. The client doesn't want a free text field, but the allowed values will vary by project so the vocabulary has to be dynamic. No problems so far, Plone allows you to develop this just fine. Frequently I will store the allowed values in the registry or on a content item and it is mutable. The issue is when they want to change or remove a vocabulary term that is already in place.

The UX isn't good here. They need to find and change all existing content first. Or they will mistakenly believe that removing it from the list of allowed terms will have some effect on content where it is already assigned. This also leads to unexpected behavior when they go to edit content where it is already assigned.

I wrote a tool for doing mass edits based on schema fields https://github.com/imsweb/ims.fieldupdater but I don't want them to actually have to do a mass edit. So let's say we have a list of allowed options somewhere, and a content type with Choice field using that vocabulary. What I want is to have the Choice values really be a reference to an "allowed option" so that an option could be edited or deleted and have that action reflected on content that has selected it.

Using zc.relations where each "allowed option" is a content object would work, but this seems like overkill. These things have no other attributes than being a string so I don't want to have users go through an add/edit form like they would with regular content. Would it make sense to have it do this, but hide all of that content from navigation and provide some more streamlined form? Or would it make more sense to try to do this by assigning uids and have a dict of uid to string value stored somewhere?