Cdk linters can 100% do this. They can operate at the various construct levels including level 1 eg generated cloud formation. At this point it's just making a linter/visitor that says "if type is taggable then it must have this tag" and bob's your uncle. The l1 stuff is generated from the cfn schema and so will have tags correctly.