diff --git a/src/site/markdown/about-checksums.md b/src/site/markdown/about-checksums.md index cb7aec521..6cb5e3f2d 100644 --- a/src/site/markdown/about-checksums.md +++ b/src/site/markdown/about-checksums.md @@ -18,65 +18,62 @@ specific language governing permissions and limitations under the License. --> -Maven Resolver uses checksums to verify the integrity of downloaded artifacts and -metadata. Checksums are usually placed in repositories next to the file in question, with the file -extension indicating the checksum algorithm that produced the given file. Currently, -most Maven repositories contain SHA-1 and MD5 checksums as they are produced by Resolver by default. - -Historically, Maven Resolver used `java.security.MessageDigest` to implement checksums. Secure one-way -hashes provided by the Java Cryptography Architecture were (mis)used to implement checksums for transport integrity -validation. Secure hashes MAY be used as checksums, as there is quite some -overlap between checksums and hashes in general. But this simplicity comes at a price: cryptographically safe -algorithms require way more CPU cycles to compute than a simple checksum. However, the purpose of a checksum is just -integrity validation, nothing more. There is no security or trust implied or expected from -them. Checksums do not protect against man-in-the-middle or supply chain attacks. - -To actually trust that artifacts have not been tampered with, you need signatures such as +Maven Resolver uses checksums to verify the integrity of downloaded artifacts and metadata. +Checksums exist in repositories next to the target file. +The file extension identifies the checksum algorithm that produced the checksum. +Most Maven repositories contain SHA-1 and MD5 checksums by default. +Maven Resolver also produces these checksums by default. +Checksums only provide integrity verification. They do not provide security or trust. +They do not protect against man-in-the-middle or supply chain attacks. + +In the past, Maven Resolver used `java.security.MessageDigest` to calculate checksums. +The Java Cryptography Architecture provides secure one-way hashes. +Maven Resolver used these secure hashes to verify transport integrity. +Secure hashes work as checksums, but cryptographically safe algorithms +require many more CPU cycles to calculate than a simple checksum. + +Some users state that specific algorithms are unsafe or deprecated. +This argument does not apply to Maven Resolver because checksums do not provide security. +This fact is true for the SHA-1 algorithm and the MD5 algorithm. +Industry still uses both algorithms today to verify transport integrity and to detect errors. + +To prove that artifacts have not been tampered with, you need signatures such as those provided by the [Maven GPG Plugin](https://maven.apache.org/plugins/maven-gpg-plugin/). -Hence, the usual argument that "XXX algorithm is unsafe, deprecated, not secure anymore" does not apply in the case -of Maven Resolver. Moreover, this is true not only for SHA-1 -algorithm, but even for its "elder brother" MD5. A checksum is not intended to be secure. Both algorithms are still widely used today as "transport integrity -validation" or "error detection" (a.k.a. "bit-rot detection"). +## Checksum Algorithms Service Provider Interface (SPI) -## Checksum Algorithms SPI +System properties enable users to specify arbitrary checksum algorithms, +even if they are not part of the standard Maven process. +Users can also register an alternate provider for Java Cryptography that +supplies a broader set of message digests for checksums. +The Maven Resolver team discourages this. -From a technical perspective, the above facts imply the following consequences: because checksum algorithms are exposed -to the user, one can set them via configuration, and thus users are not prevented from asking for SHA-256 or even SHA-512, even if -these algorithms are not part of standard Maven process. Moreover, nothing prevents users (integrating -Maven Resolver) registering an alternate Java Cryptography Provider and using even broader (or exotic) -message digest algorithms for checksums. While this is not wrong, we do consider this as a -bad use case. The notion of transport validation and secure hashes are being constantly mixed up due to historical -reasons explained above. - -Hence, the Maven Resolver team decided to make the supported set of checksum algorithms more controlled. Instead of directly exposing -`MessageDigest` algorithms, we introduced an SPI around checksums. This not only prevents incorrect use cases by not -exposing all supported algorithms of `MessageDigest` to users, but also makes it possible to introduce real checksum -algorithms. Finally, the set of supported checksum algorithms remains extensible: if some required algorithm is -not provided by Resolver, it can easily be added by creating a factory component for it. - -We are aware that users started using "better SHA" algorithms, and we do not want to break them. Nothing for them -changes (configuration and everything basically remains the same). But we do want to prevent any possible further -proliferation of non-standard checksums. - -## Implemented Checksum Algorithms - -Resolver out of the box provides the following checksum algorithms (important: algorithm names are case sensitive): +To control the supported set of checksums, the Maven Resolver team introduced an SPI for checksums. +We no longer expose `MessageDigest` algorithms directly. +Instead, the SPI supports four checksum algorithms: * MD5 * SHA-1 * SHA-256 * SHA-512 -The algorithms above are provided by Resolver, by default. Still, using the SPI, anyone can extend -Resolver with new types of Checksum Algorithms. -To see how and when checksums are used in Resolver, continue on [Expected Checksums](expected-checksums.html) -page. +The names of these algorithms are case-sensitive. + +You can use the SPI to extend Maven Resolver with other checksum algorithms. +If Maven Resolver does not provide a required algorithm, you can create a +factory component for the new algorithm to add it. + +We know that users use stronger SHA algorithms. +We do not want to break these configurations. +Configuration and operations remain the same for these users. +However, we want to prevent the future addition of non-standard checksums. + +The [Expected Checksums](expected-checksums.html) page explains how and when Maven Resolver uses checksums. Links: -* [SHA-1](https://en.wikipedia.org/wiki/SHA-1) (see "Data Integrity" section) -* [MD5](https://en.wikipedia.org/wiki/MD5) (see "Applications" section, especially about error checking functionality) +* [SHA-1](https://en.wikipedia.org/wiki/SHA-1) (The "Data Integrity" section explains this concept.) +* [MD5](https://en.wikipedia.org/wiki/MD5) (The "Applications" section explains the error verification function.) diff --git a/src/site/markdown/api-compatibility.md b/src/site/markdown/api-compatibility.md index 432c27721..9301eeb76 100644 --- a/src/site/markdown/api-compatibility.md +++ b/src/site/markdown/api-compatibility.md @@ -19,93 +19,83 @@ specific language governing permissions and limitations under the License. --> -Maven Resolver exposes three modules for clients and those extending Maven Resolver: -* maven-resolver-api (in short API) -- for clients and those extending it -* maven-resolver-spi (in short SPI) -- for those extending it -* maven-resolver-util (in short Util) -- for client and those extending it +Maven Resolver exposes three modules for client applications and extensions. +Client applications invoke methods in these modules. +Extensions inherit from classes and implement interfaces. -Each module guarantees non-breaking (source and binary) compatibility, as long -clients and extenders obey some rules. If you break any of these rules, you are -prone to breakage, and you are on your own. +* `maven-resolver-api` (API) - Client applications and extensions use this module. +* `maven-resolver-spi` (SPI) - Extensions use this module. +* `maven-resolver-util` (Util) - Client applications and extensions use this module. -## Interface And (Abstract) Class Level Contracts +If you obey specific rules, these modules will be source and binary compatible across minor releases. +If you break these rules, your code can break when you update these modules. -In source, we use two important Javadoc tags to mark intent: -* `@noextend` -- classes (or interfaces) carrying this tag MUST NOT be extended -* `@noimplement` -- interfaces carrying this tag MUST NOT be directly or indirectly implemented, - UNLESS the Javadoc of given interface points to an abstract support class that makes indirect - implementation possible. +## Interface And (Abstract) Class Level Contracts -Examples: +We use two Javadoc tags in the source code to mark intent: +* `@noextend` - You must not extend classes or interfaces with this tag. +* `@noimplement` - You must not implement interfaces with this tag directly or indirectly. -* `RepositorySystem` interface. It carries both `@noextend` and `@noimplement` tags. This interface - MUST NOT be extended nor implemented. This is a component interface, that is usually injected into - client application. -* `TransferListener` interface. It carries both `@noextend` and `@noimplement` tags, but Javadoc - points at `AbstractTransferListener` as extension point. Hence, clients are NOT allowed to extend - this interface, nor to directly implement it, but, if custom listener is needed, it is warmly - advised to extend the given abstract class. This way we can protect you from future breakage. +If the Javadoc points to an abstract support class, you can implement the `@noimplement` interface indirectly. -## Package Level Contracts +Examples: -Maven Resolver implements customary habit to name packages NOT meant to be accessed by clients. -If a Java package contains following names: +The `RepositorySystem` interface has the `@noextend` tag and the `@noimplement` tag. +You must not extend or implement this interface. +The `RepositorySystem` interface is a component interface. +Client applications usually receive this interface through dependency injection. -* `impl` -* `internal` +The `TransferListener` interface has the `@noextend` tag and the `@noimplement` tag. +The Javadoc points to the `AbstractTransferListener` abstract class. +You must not extend or implement the `TransferListener` interface directly. +If you need a custom listener, extend the `AbstractTransferListener` abstract class. +This abstract class protects your code from future breakages. -That Java package is meant as "internal" and does NOT offer guarantees of compatibility as API is. You -may use classes from these packages, but again, you are on your own to deal with (binary or source) -breakages. If you think a class from such package should be "pulled out" and made part of SPI or -maybe API, better inform us via [JIRA](https://issues.apache.org/jira/projects/MRESOLVER): create a -ticket and let's discuss. +## Package Level Contracts -As a side note, the count of those names in Java package is directly proportional to possibility of -breaking changes: the more, the larger the possibility of breakage even in minor releases. +Maven Resolver identifies internal Java packages with the words `impl` and `internal`. +These internal packages do not guarantee compatibility between releases. +If you use classes from these packages, you must fix source breakages and binary breakages yourself. +You can request to move a class to the API or the SPI through a ticket on [GitHub](https://github.com/apache/maven-resolver/issues). ## Version Level Contracts -Maven Resolver does NOT use "semantic versioning", but still tries at best to reflect contained -changes using version number. We use "major.minor.patch" versioning on resolver with following -semantics: - -* On major version change, one should NOT expect any backward compatibility. -* On minor version change, we ENSURE backward compatibility for those "exposed" 3 modules: API, - SPI and Util. Still, there are examples when we failed to do so, usually driven by new - features. +Maven Resolver does not use "semantic versioning". +However, Maven Resolver uses a "major.minor.patch" version format to indicate changes. +Major version changes do not provide backward compatibility. +The API, SPI, and Util modules should be backwards compatible across minor version changes. +However, we have violated this rule in the past, usually to support new features. -In any of three version changes above, in areas where we do not offer guarantees, everything -can happen. +Maven Resolver does not guarantee compatibility for internal modules. +Internal modules can change in any version update. ## Outside of Maven -Applications integrating Maven Resolver outside of Maven has really simple job: all they have to -ensure is that API, SPI, Util and the rest of resolver (impl, basic-connector and transports) -have all same versions, and they can rely on these backward compatibility contracts as explained -above. +Applications can use Maven Resolver outside of Maven. +These applications must use the same version for all Maven Resolver modules. +For example, the API, SPI, Util, `impl`, `basic-connector`, and transports must share the same version. +If the versions match, the applications can rely on the compatibility guarantees. ## Inside of Maven -Historically, Maven 3.1 provided API, SPI -and Impl from its own embedded resolver, while Util and Connector, if some plugin or extension -depended on them, were resolved separately. This meant that a plugin could work with different versions -of API, SPI, Impl or Connector. Because the Resolver API was "frozen" for too long a time, this was essentially -not a problem, but still weird. +In the past, Maven 3.1 provided the API, SPI, and `impl` modules from an embedded resolver. +Plugins resolved the Util and Connector modules separately. +Therefore, plugins used different versions of these modules. +The static API prevented major problems. -This changes in Maven 3.9+: Maven starting with version 3.9.0 will provide API, SPI, Impl, -**and Util and Connector**. Reason for this change is that Impl and Connector bundled in Maven -implement things from both API and SPI, and there was a binary incompatible change between -Resolver 1.8.0 and previous versions. +Maven 3.9.0 provides the API, SPI, `impl`, Util, and Connector modules. +The bundled `impl` and Connector modules implement the API and the SPI. +A binary incompatibility occurred between Maven Resolver 1.8.0 and previous versions. +Because of this incompatibility, Maven 3.9.0 bundles all modules to ensure stability. -Most Resolver users should not be affected by this change. +This change does not affect most Maven Resolver users. -The binary incompatible change happened in the SPI class `RepositoryLayout` as part of work done for -[MRESOLVER-230](https://issues.apache.org/jira/browse/MRESOLVER-230), and affects both, Connector -and Impl. +The binary incompatibility occurred in the `RepositoryLayout` SPI class for [MRESOLVER-230](https://issues.apache.org/jira/browse/MRESOLVER-230). +This incompatibility affects the Connector module and the `impl` module. ## Backward Compatibility Checks -To ensure backward compatibility, starting from 1.9.0 Maven Resolver uses -[JApiCmp](https://siom79.github.io/japicmp/MavenPlugin.html), -with two executions (for source and binary level checks). The plugin is enabled on 3 modules of -Resolver mentioned at page top: API, SPI and Util. For "baseline" we use version 1.8.0. +Maven Resolver uses [JApiCmp](https://siom79.github.io/japicmp/MavenPlugin.html) to verify backward compatibility. +Starting with version 1.9.0, Maven Resolver runs this plugin twice to verify source compatibility and binary compatibility. +The plugin runs on the API, SPI, and Util modules. +The compatibility baseline is version 1.8.0.