I was a founder at a company that faced this problem: small company, in Australia; big company clients, mostly on other side of the planet.
We added a source-code escrow clause to our contracts, and (the much bigger and more difficult part of the commitment) a bunch of steps to our release process.
Escrow is not just the source code: we had to include full instructions for building the software, lists of dependencies and their versions, etc, etc. With modern CI and declarative DevOps, this would be a lot simpler.
We originally just arranged this with our local Intellectual Property lawyer, who (to my surprise) was pretty well set up for this. For instance, one time we accidentally failed to include some files, and they noticed and called us to get the drop resent.
We were later forced to move to using Iron Mountain by a large client who wasn't happy within anyone else.
When we later discontinued that product (due to pivoting to a more specific market niche) one customer took advantage of their escrow rights to continue to build and maintain the software in house for many years.
From memory, we didn't try to enumerate the circumstances under which the escrow would be triggered too much: just saying something like "becomes unsupported". If it's really necessary, lawyers can sort out whether that's the case or not.