- Imagine that in my project, I have a "FOO" function, which is called by many others
- I've decide to change type of one parameter of FOO function. This would be a breaking change in regular language, but in Unison, nothing breaks - I push the new definition, but every caller is still using old version.
- New callers come up, and they use new version. So far so good.
- Some times later, I've discovered a critical business-logic bug in FOO function! So I fix it, and I have to update all the callers to use the latest version... except for half of them I can not, because the parameter types do not match. Seems like I cannot ship the fix to the customer until I spend a bunch of time rewriting the existing code to accommodate argument type change.
As long as there are functions, there are always some kinds changes to them that require one to fix up the callers. How this is enforced can be different - in strictly typed languages, code may fail to compile; in dynamic languages, you may see runtime failures; and in Unison, things will work until you try to edit the caller, at which case it'll fail to compile (unison docs call that operation, converting from text to internal language's representation, "typecheck").
I am not convinced that the "postpone failure until you edit the caller" is the best approach here. When I refactor, I normally want to see any problems surface right away, while I still have the context for the change.
I agree that attitudes towards security are generally very poor, but breaking working infrastructure sounds like a crazy practice. Like any sensible system, a good/robust design should allow staged upgrades / hot reloading for anything but a very tiny core of critical functionality. Erlang/BEAM is a great example; it just requires software engineering to adopt a different mindset.
Yes, breaking infrastructure is bad. But letting already broken infrastructure continue can be worse.
The point is that we want a better way to detect when breaking changes happen so that security fixes can be applied without breaking anything, while permitting optional upgrades on our own schedule for other features. There doesn't seem to be a great solution yet, it's either "it never breaks but you're possibly vulnerable to security issues that can't be easily patched", or "things can break at any time due to updates so we have to manually verify this doesn't happen".
I don't think it's fundamentally incompatible with a secure design though, you just need to reify the authority to do those things so you can explicitly grant them to specific programs as appropriate.
The most used desktop OS on the planet has allowed this since forever and the world hasn't ended
It's not a good model, and that's why this only forced in commercial software or in particularly obnoxious projects, like earlier versions of Ubuntu Snap. Every other case is user's choice - package managers have lock files; automated updates can be disabled; docker images can be referenced by SHA; etc...
That's not to say that infrastructure does not break - there plenty of horrible setups out there... but if you discover you "must drop every other priority and upgrade", then maybe spend some time making your infra more stable? Commit that lockfile (or start saving dev docker containers, if you can't), stop auto-deploying latest changes and make sure you keep previous builds around, instead of blaming software ecosystem and upstream authors.