You are right, with this kind of approach, extensibility/flexibility is the central question - we want to make Wasp really easy and simple to use, but on the other hand, complexity is needed to provide the flexibility to produce complex applications.
Right now, Wasp is already leaving big gaps to be filled in by JS/TS (Node, React), but there is also a big part that is abstracted away and hidden by Wasp. For that part, our main idea is to offer abstractions of different levels that you can choose from. For example, you can choose Wasp's RPC to communicate between backend and frontend, but nothing is stopping you to directly access request and response in your expressJS middleware if you want and write your own REST API or use GraphQL. Or, you can use our authentication system completely, or use just part of it, or completely ditch it. So there should always be a "lid" that you can remove and access the system beneath.
That said, we are still figuring this out - where to offer escape mechanisms, how to organize them, how much to abstract certain parts - there is certainly some limit to flexibility that we can offer. What is cool that having our own DSL gives us a lot of freedom here (although it is also a lot of work!).
One thing we do have in the meantime is ability to eject the code and continue with it if you get stuck with Wasp at this alpha stage -> it is actually human readable! I am not sure if we will be able to maintain that property as Wasp grows though, but we are not giving up on it for now.