dependency ordering in profile

I've read this question, but it's more specific about an 'inner' dependency than just raw profile orderings..

What is the best practice for having multiple profiles, and using an ordering scheme. Should we use stages in our profile, or should we set up explicit ordering relationships, or should we use tags and the spaceship operator to do our ordering?

We are trying to set up our 'base' profile that all of our roles inherit, and handle ordering of multiple modules within the base profile. We have a module that has to happen first, we have a series of hardening modules, and then we have the 'general' base modules that we want applied. Our hardening modules run a module which must happen last, as it creates some hardening audit reports that should include all of the configuration done by puppet.

What is the best way to order all of these modules? We used to have a bunch of 'require' statements buried inside of most of the modules that pointed back to the 'must happen first' module, and we now have a bunch of explicit Class['musthappenfirst'] -> Class['someothermodule']. The problem is that we now have a large number of them, and they become almost unmanageable.

We moved a bunch of modules over into a profile::hardening module to manage some of that, but we still need to make sure 'musthappenfirst' happens before hardening, but there are some other modules which depend on one of the modules that got moved into the hardening module.... (that should probably be refactored, but that's another story)

I don't think I can use the spaceship operator to gather up all Classes with a tag, can I? Is my best option to use run stages, and have a pre, main, post set of stages?

That works for resources, but I don't think it can be used for classes..
What I wanted to do was something like this
Class['mustcomefirst'] -> Class<| tag == 'setup'|>
I don't believe that is possible.. and to get similar behavior, I think I would have to use runstages