Unfortunately, I do not see the point in abstracting framework away the way you do it.
All abstractions leak and if you need to abstract your framework away it means you should just choose a microframework, which does not insist on certain way of doing things.
What you have shown here is creating your own framework, which in itself is not a problem (I also think there should be domain specific mini/micro frameworks in almost every project). In the ideal web-framework one should not do it. In good frameworks there is a place for business (domain) logic as such. And what is around that "layer" is application, persistence, utilities, etc. See DDD (domain-driven design).
Login is a bad example because it's an auxiliary domain which web frameworks should handle - unless you are building such a framework, it's something you should use, not rewrite.
It's the domain logic which should not even mention any web-related names at all (unless your core domain is web-server and such). It should speak the language of your problem domain entirely. Tests should speak that same language too.
Unfortunately, it's usually hard to decouple persistence totally out of the domain because some data integrity constraints leak into the database, plus sometime there are practical benefits from using ORM, but other places can be mostly kept clean.
Also abstract and compose is nothing new. What matters is what you abstract. Unless you deal with some really ugly application framework and cant change it, most of the abstraction focus should be on the domain logic.
You are mentioning "hooks" and such - those are probably recent hype bringing aspect-oriented approach to certain JavaScript-based frameworks. Does not sound like something generic (=lasting) to me.