jslicense / spdx-satisfies.js

test whether SPDX expressions satisfy licensing criteria

Home Page:https://www.npmjs.com/package/spdx-satisfies

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

order matters unexpectedly

jeffmcaffer opened this issue · comments

The following examples fail only because the license ordering is different. That is unexpected

assert(satisfies('MIT AND GPL-2.0 AND ISC', 'ISC AND GPL-2.0 AND MIT'))
assert(satisfies('MIT AND ISC', '(ISC AND MIT) OR (GPL-2.0 AND ISC)'))

Related, I'm curious about the api intention here. Can you express in words how a user of the API should be thinking about the answer? For example,

  • if the user asks "If I accept MIT, is MIT AND ISC ok?" that should be no.

Does order of the arguments matter? A satisfying B does not necessarily imply the inverse.

Thanks for this @jeffmcaffer.

Let's back up and talk AND and OR in SPDX expressions. OR denotes a choice of license. (MIT OR GPL-2.0-only) means you can have MIT or GPL-2.0-only, your choice.

AND, on the other hand, expresses that both sets of terms apply to the code. For example, a single package that combines MIT and BSD-2-Clause code would be (MIT AND BSD-2-Clause).

For that reason, I think it will be extremely rare for practical use cases to express license rules with AND. More commonly, rules will be long lists of licenses joined by OR, expressing a whitelist of approved terms.

Got it. Thanks. While I agree that the second case, as written is unlikely, that is just the expansion of ISC AND (MIT OR GPL-2.0), which, IIRC is in the test data and is logically equivalent (just order difference).

The first case is, again, in the test data but just happens to have the same order. I swapped the ordering and discovered the failure.

The real scenario here is aggregating licenses found in the various files of a project. As we go through all the files and accumulate the licenses, these are AND'd together (if you use the project you are subject to all the licenses). In an effort to do smart aggregation, we "merge" the various licenses such that if a new license is already satisfied by the current accumulation, it need not be added. In this scenario, it is not a human explicitly crafting a license expression, rather they are implicitly crafted by using files of varying licenses.

To the more general question of how users should look at the API... would you expect then the second (or first?) arg to be what the user is willing to accept and the first to be what the component actually has? With the result being whether or not the component can be used under the terms (second arg) the user can manage?

The code seems to swap the order based on conjunctions but I'm having trouble understanding the semantics that that implies.

@jeffmcaffer The API here was a riff on semver.satisfies. See https://www.npmjs.com/package/semver.

There is a logic error here. As the algorithm recurses expressions, it splits apart conjunctions, rather than checking to see if the conjunction itself is part of a disjunction on the other side.

Practically, I think the question is whether chasing that bug down is worthwhile for any practical use cases. The alternative would be to release a new major version that either:

  1. requires the second argument to be a single identifier or a disjunction of identifiers
  2. requires the second argument to be an array of identifiers