For the deferring of refresh case itself, we might use something simple organized on top of normal configuration, similar to how we already handle the overall scheduling of refreshes. Strawman:
We first introduce support for having refresh.hold with a full timestamp containing the absolute timestamp before which the system must not refresh, as long as the last refresh happened within a maximum limit which matches the limit for normal refresh scheduling (60 days now, I think?).
Hold seems better than delay in this context because the latter is commonly used as a noun, which may be confused with “refresh right after this delay”, instead of “postpone for at least this delta”.
Once that works, we can trivially introduce a command that can take a delta, verify that it is within bounds, and then change the configuration setting as long as the time provided is after the currently deferred time. In other words, a defer command does not move the deadline earlier.
The command might look like:
$ snap refresh --hold=5h
Next refresh scheduled for today at 22:09.
$ snap refresh --time
With all of that working, we can change the initial logic so that it presets the hold value to, say, 6h from first startup. We can tune that as we learn more about the use cases.
As for the registration case, whatever we do we need to preserve a good user experience. So we can’t take ages to respond, and we cannot just reject sane calls. The best scenario is we do the long tasks early (key generation, etc), and then do the final store registration on first use. Are there any gotchas here, though?