Scrolling causes the hook
window-scroll-functions to be executed. That lets you know when scrolling happens, but as the manual says,
Warning: don’t use this feature to alter the way the window is scrolled. It’s not designed for that, and such use probably won’t work.
It's actually possible to “lock” scrolling by saving
window-start and restoring it inside
window-scroll-functions, but that doesn't mean you should do it. It can cause the point to get out of the scrolling zone; you can fix that by manually clipping the point and the window point to the window area. But that gets really confusing when inserting text at the end of the window, as it causes the cursor to move backwards while inserting text.
You can't prevent a modification that would cause scrolling, because whether to scroll is determined after the modification is made and after things like line wrapping (whether explicit through auto fill mode or visual with visual line mode) have been processed. Once Emacs gets to the bit where it finds out whether it needs to scroll, the modification has already been carried out and the only solution would be to undo it.
A solution would be to keep two identical buffers, try out the modification in one of them, calculate the effect on scrolling (maybe by maintaining a “shadow” window in a hidden frame?), and carrying out the modification in the original buffer only if no scrolling happens. This sounds difficult for what it's worth.
Narrowing, as suggested by Wilfred Hughes, does most of what you want, but doesn't help with text insertions. You might combine narrowing with an entry in
window-scroll-functions, but you need to figure out what you want to do when the text grows too large. You need to have clear requirements before you can start implementing.
I don't think preventing edits makes sense. If you want to maintain a structure overview, do it with two windows: one where you edit text without any length restrictions, and one that shows the structure overview. See How can I get an org-mode outline in a 2nd buffer as a dynamic table of contents?