This has been implemented at Galileo's .LRN instance, hacking db_dml & db_exec_plsql to abort the execution if the context for the original caller (top parent) of the function have a given permission (like "view_only_mode") to a set of users.
For db_dml we block everything that has such permission.
For db_exec_plsql we block also based on the naming convention (i.e. if you are executing something called .new or __new, then that is blocked, the same for .del / __delete) in combination with the permission.
Also we added extra stuff to handle those cases when the db_dml is called from a scheduled proc in order to avoid the check of a permission.
This functionality has been on production for more than 6 months, working fine and no performance penalties has been detected. And it is a general purpouse feature, not just for .LRN.
Unless we as a community want to refactor the whole bunch of applications we don't see a straightforward way to "freeze" an application in a view only mode. As you can see, this is a feature that we need to support.
We would like to go ahead on this and contribute, any comments for a better approach?