This is a known trade-off in Flask's design philosophy (simplicity over strict SRP). For a mature framework this is acceptable, but further decomposition of concerns (e.g., extracting request dispatch into a separate handler class, or moving CLI integration out of the app class) could improve maintainability. Given Flask's stability and backward compatibility requirements, this is informational rather than actionable.
This is a fundamental Flask design decision and changing it would break the entire ecosystem. However, for new code paths, consider supporting explicit context passing as an alternative (as partially done in the sansio layer). Document the context lifecycle more prominently for extension developers.
Consider whether some of these concerns could be separated into mixins or composition objects (e.g., a `RouteRegistrar` mixin, a `HookRegistrar` mixin). This would make the architecture more modular without breaking the public API, since the Flask and Blueprint classes could still compose these mixins.
Consider adding a startup warning when no SECRET_KEY is set and debug mode is off, similar to Django's system checks framework. This helps prevent accidental deployment without proper secret key configuration.
While Flask's micro-framework philosophy is understood, consider providing a minimal built-in CSRF token utility or at minimum a more prominent warning in the quickstart documentation about CSRF risks for form-handling applications.