Edge case scenarios for snap validations

Hello folks!

We’re working on improving the way the Store sends information about validations when refreshing, so snapd can decide which revision to refresh to. In the course of doing this, we came up with some “deadlock” scenarios and I wanted to bring them to wider attention and ask what the desired behavior should be.

Example 1:

Two gating and one gated snap are released (2 revisions for the gated). Next, the validations specifying valid gating-gated combinations are added. One of the gating snaps will want revision 1 of the gated. The other gating snap will want revision 2. Then, both gating snaps and the gated are installed. Since both gating snaps are installed, it means whichever version of gated is installed will satisfy one gating but not the other. What should a refresh do in this case?

snapcraft release GATING-1 1 stable
snapcraft release GATING-2 1 stable
snapcraft release GATED 1 stable
snapcraft release GATED 2 stable
snapcraft validate GATING-1 GATED=1
snapcraft validate GATING-2 GATED=2
snap install GATING-1 <-- 1
snap install GATING-2 <-- 1
snap install GATED <-- 2 # Maybe install with --ignore-validation
snap refresh <-- ???

Example 2:

Two gating snaps control two gated snaps with two versions each. Validations are set up in such a way that no combination of gated versions will satisfy both gating snaps’ constraints.

snapcraft release GATING-1 1 stable
snapcraft release GATING-2 1 stable
snapcraft release GATED-A 21 stable
snapcraft release GATED-A 23 stable
snapcraft release GATED-B 56 stable
snapcraft release GATED-B 58 stable
snapcraft validate GATING-1 GATED-A=23 GATED-B=56
snapcraft validate GATING-2 GATED-A=21 GATED-B=58
snap install GATING-1 <-- 1
snap install GATING-2 <-- 1
snap install GATED-A <-- 23
snap install GATED-B <-- 58
snap refresh <-- ???

Any thoughts on what the correct behavior is here would be appreciated, I hope at least these little mind-benders prove interesting.

Note that --ignore-validation is not really helping in the first example, as the same situation arises post-installation:

snapcraft release GATING-1 1 stable
snapcraft release GATING-2 1 stable
snapcraft release GATED 1 stable
snapcraft release GATED 2 stable
snap install GATING-1 <-- 1
snap install GATING-2 <-- 1

So far so good: no one of the previous commands is wrong, but then…

snapcraft validate GATING-1 GATED=1
snapcraft validate GATING-2 GATED=2
snap install GATED <-- 2
snap refresh <-- ???

IMO, if the intersection of validated revisions is empty, there should be no response for the gated snap (no revision available at all)

There is another specific case to consider: what if the channel is closed? Example:

snapcraft release GATING 1 stable
snapcraft release GATED 1 stable
snapcraft release GATED 2 stable
snap install GATING   <-- 1
snap install GATED   <-- 2
snapcraft validated GATING GATED=1
snapcraft close GATED stable
snap refresh <-- ???

IMO, the response to the refresh should be empty (like if no validation was issued)

We shortly discussed these scenarios when designing the validation feature, but we couldn’t see them as controversial. If an authority is telling the system that a particular revision isn’t blessed, game over. The fact someone else said it was fine is not relevant. The system shouldn’t proceed until the recognized parties say so.

Am I missing something?

Perfect, so we’ll be returning empty responses for all the cases specified here, thanks!