This is essentially how the module system works by itself already. Unfortunately most of that is still undocumented. Check recent discussion on the topic.
Here’s an example of modifying module arguments.
Modifying the effect of one module declaration happens somewhat behind the scenes, and the allowed transformations are determined by option types. Modifying the end result of evalModules
can be done directly by working on the attribute set. It’s likely not exactly what you’re looking for. But just in case, literally anything you can think of can be achieved in the module system: It’s only syntactic sugar for fixed-point computation on attribute sets, with some type checking and automatic merging of multiple definitions added on top.