Here’s a first draft. It still needs testing, possibly further development, and docs.
https://github.com/frappe/frappe/pull/12264