How to track an unknown number of objects in a multi-module add-on
@batFINGER suggested using a custom object property instead of maintaining a list - which is a good alternative for my use case and avoids bpy.props entirely. Below are implementations written with the help of devtalk.

Adding is fairly straightforward.

# add an object to list
obj["prop_name"] = 1


Getting a list can be done in a couple different ways depending on how unassignment is handled - adjusting the prop's value...

# remove an object from list
obj["prop_name"] = 0
# get list of objects
objs_list = [
    obj for obj in bpy.data.objects
    if "prop_name" in obj and obj["prop_name"] == 1
]


... or deleting it entirely.

# remove an object from list
del obj["prop_name"]

# get list of objects
objs_list = [
    obj for obj in bpy.data.objects
    if "prop_name" in obj
]


Either way, these 'get list' implementations avoid iterating through the full list of objects.