Snap license metadata

What’s the status on specifying the license in snapcraft.yaml? The PR was merged but snapcraft still doesn’t recognise license key.

Issues while validating snapcraft.yaml: Additional properties are not allowed ('license' was unexpected)
1 Like

people are working on it right now :slight_smile:

Indeed, we will start with some docs (if none exist yet). While those are written though, I’d like to know where the expression parser code lives to be able to run it through snapcraft for validation (unless this is something we will relegate to the store itself).

Additionally, since this field did not exist before, what should the behavior be for when it is missing?

FTR, the store is currently using a Python lib to validate SPDX license expressions. The store implementation was checked against snapd license validation code (in Go), using the same tests.

The store allows to change license value in the web UI. By default, when no license is specified (which is always the case when pushing from snapcraft), the Proprietary value is assumed.

That’s somewhat unfortunate. It’ll surely be the source of pain due to incompatible understanding of which licenses are valid, incompatible understanding of which expressions are valid, and potential metadata around them.

This is also incorrect and unfortunate behavior for that exact reason. We’re giving no choice to people but to push snaps labeled proprietary. The store needs to classify an unknown license as such, and once we define how to push custom licenses, which is the last bit missing, we need to block snaps from being pushed into the store unless they explicitly list their licenses, so no more unknowns going forward.

1 Like

I wasn’t aware of this last bit of discussion until just now, and had filed a bug about the license being changeable in the web UI; this came up in discussion of PR#4531 cmd/snap: display snap license information.

It being tunable in the UI sounds fine. It should follow the same pattern we discussed for other textual details of the snap, such as the summary and the description. That is, snapcraft pushes the first revision, and from there on it will only warn if it diverges, and give an command line option to replace it when desired. The store holds the authoritative version of the data, and can change it via its UI.

I disagree about it being editable via the UI, because doing so increases the amount of work we need to do, not only for the snapd core team, but also for the snappy store team, and for our colleagues at canonical and our friends in the community working on integrating snapd into graphical software centres, with no benefit to our users beyond a (imho minor) convenience to our developers.

This is based on my understanding that once a user has accepted (implicitly or explicitly) a license for a software they have installed, changing that license should require they accept it again.

On the snapd side, if a license can change together with a revision, we need to add work to block refreshes that see license changes, and to notify users that this has happened so they can manually approve (implicitly or explicitly) that license change. This of course depends on warnings, and both it and them will result in more work for software centres, but it’s doable (and as I see it most of the client-side work is part of warnings, not part of this use of them).

If a license can change at any moment, and not tied to a revision, however, we need to be able to … deactivate the software until the user approves? We now have put software on their devices with a license they have not had a change to review (even if we were to remove it, which seems heavy handed, what we’re saying is that there will always be a window when the software on their device will have the new license). I think this would be bad. We need to alert the user of this, which means that the software centres need to have a way to alert the user of something that happened just now, which is a whole new workflow different from everything else these software centres are doing.

On the store side, having it editable via the web UI implies that all revisions will have the same license, as AFAIK the store doesn’t support otherwise. As I suspect this is not what we want, there’d be more work for the store here (how much I don’t know, but my understanding is that per-revision user-editable data would require significant rework).

Another reason (or maybe another way at looking at the same reason) this making them dynamic makes me uncomfortable is that if what we’re saying is that yes, licenses are per snap and not per revision, that means publishers can retroactively change the license of a snap. I can think of no example where this is reasonable and valid, and yet we’re taking on a bunch of work to make it doable.

I don’t see how it being editable in the store makes those issues any harder to deal with. All of the issues you describe seem true despite it, as you can change the content of a license shipped inside the snap (or deb, or RPM, or …) at any point.

The reason it is a good idea to allow editing it in the store was discussed in a long session a while ago in the context of summaries and descriptions, and we probably have notes somewhere. I can go over it or try to find it if you don’t have memories of it, but without trying to do the topic proper justice, the problem is precisely that in a development cycle many snaps for different revisions will be pushed to the store. Without the ability to define what the correct up-to-date value is, it becomes a mess.

In what I wrote I tried to explain exactly what’s different and why it’s harder if the license can change at any time. The key point is that, if a license is for a revision of the software, things are simpler. And the simplest way of doing that is not making them editable in the UI but getting them from the yaml.

This is different from titles and descriptions, where we decided that it’s best to just have one, per snap, and not per revision. Licenses need to be the opposite of that.

You are explaining again what was said above, but didn’t address the main point I presented. In your concerns you presented a number of tricky cases, and proposed that we’d need to block updates, warn the user when there are changes, and so forth. All of these issues are true regardless of the fact we keep an up-to-date version of the license in the store, and they are also true in every other scenario about package managers, which today are not addressed in any special way.

We need to block updates and warn the user, if the license change is related to the revision and there is thus a thing to block: the revision they are on now has a license they agreed to, and if we were to update to the new revision they’d be on a license they haven’t agreed to yet. This is work we need to do.

If the license change is not connected to a revision change, then … how do we handle that? There is nothing to block; the user now has software with a license they haven’t agreed to. There is in this scenario no path that lets the user not be potentially in violation of that license, or having or using software with a license they don’t agree with.

That sounds bad for multiple reasons:

  • We don’t want to block updates of working software; it’s unexpected and will create problems.
  • We have no interface to ask for agreements on a license.
  • Most license changes on free/open source preserve the software as free/open source.
  • Many license changes will be trivial fixes (we lack good information today).
  • No other package manager does that.

And with all that said, this is all unrelated to the original point: that issue exists whether we keep an authoritative version in the store or not, so is not good motivation for doing it one way or the other.

The approach I would recommend is this: we keep the authoritative version in the store, because we need to display something to people that want to know what the license is, and because we don’t want to overwrite that license every time a snap is pushed (again, same problem of summaries and descriptions). Locally, we display the locally installed snap license. When the local snap is refreshed to something containing a different license, we issue a warning through the upcoming warnings framework. We also warn when the just installed snap holds a license that diverges from the authoritative one in the store, which they may have read.

so, to summarise:

  • snaps will have a license field
  • the store will have a per-snap (not per-revision) license. This is taken from a snap’s yaml but can be changed online, or via re-reading any later snap, at which point that license is the one that applies to that snap irrespective of revision
  • in other words, snap license changes retroactively apply to software previously released.
  • when a snap’s license is changed, the user isn’t notified. If and when the developer pushes a revision to the channel they’re tracking, they’ll get a warning. Meanwhile they’ll still be told the license of the software is the one in the snap, despite it not being that.

The two last points disagree with the proposal made.

We’re misunderstanding each other, I fear.

We’re now in agreement. :slight_smile:

We discussed this today in the call, and we now understand each other.

The suggestion from @chipaca is that instead of requiring manual fiddling with an editable label in the store, it’s much simpler to always take the license from the stable channel. That’s a good idea and simpler in all angles. The only bit I’d amend is that we should pick the license from the most stable channel, not just stable itself, because we need to show something if there’s no snap in stable.

So, the next steps are:

  1. Implement the described logic in the store
  2. Support custom licenses
  3. Change snapcraft to warn about missing licenses
  4. Change the store to reject new snaps without licenses

Step 4 needs to wait some grace period until everybody had a chance to update their snaps.

Trying to get some extra clarifications about the suggested plan.

  • Are you proposing the store should not allow to modify the license through the web UI, or via API, but only extract the license expression as provided by each uploaded revision?

  • There is still a snap-level license, given by the current most stable released revision. This means that depending on the channel map constraints (arch, validation, epochs, etc), the snap could expose a (dynamically calculated) different license?

  • Similarly, if I’m following the beta channel, and I got a snap installed under X license, and the developer releases a new revision to stable (not affecting the beta channel) with Y license, does the license for the snap change for me?

Given the channel map is calculated on the fly given a set of constraints, I’m not sure if tying the license around that will work as expected.