Summary

  • LACNIC’s public pai-auth-ws-client README says Java 8 or later and demonstrates version 1.0.0. The README has not changed since its single November 2024 commit.
  • The release line changed underneath it. Version 1.5.0 moved the Maven source and target to Java 17; 1.5.1 retained that floor, and its public workflow builds on JDK 17.
  • JitPack does serve the 1.5.1 artifact. All twelve class files in the observed JAR have major version 61, and its manifest names JDK 17.0.12. This is a compatibility mismatch, not a missing-artifact story.
  • A small release-compatibility receipt could bind each version to its minimum and tested runtimes, documentation revision and service scope without turning LACNIC into the operator of anyone else’s application.

Twelve class files, one answer

A README is a promise addressed to a person. A class-file header is a requirement addressed to a machine. In LACNIC’s public PAI Authentication Web Service Client, those two audiences now receive different answers.

The repository describes a Java client for consuming LACNIC’s PAI authentication web service. Its requirements section says “Java 8 or later.” The Maven and Gradle snippets both name version 1.0.0 and tell the reader to replace that number with a version published on JitPack. The badge immediately above those instructions currently advertises 1.5.1. A reasonable integrator can therefore read the minimum requirement, follow the distribution path and select the advertised current release without encountering a sentence that says the runtime floor changed. LACNIC client repository README at tag 1.5.1 JitPack project page

The artifact is available. A direct request to JitPack returned the 1.5.1 POM and a 20,580-byte JAR. The archive contains twelve .class files. In every one, the two-byte major_version field is 61. Its manifest says it was built by JitPack with JDK 17.0.12. The Java Virtual Machine Specification’s compatibility table maps major 52 to Java SE 8 and major 61 to Java SE 17. The shipped code is not ambiguous about the runtime generation for which it was compiled. JitPack 1.5.1 POM JitPack 1.5.1 JAR JVM Specification, class-file format

That observation does not prove that a customer tried to load the library on Java 8. It does not establish a failed login, an unavailable PAI service, a broken production integration or a security defect. It establishes a narrower fact: the generic minimum-runtime statement on the public entry page does not describe the bytecode served for the latest advertised release.

The strongest defence is the current build

There is a good engineering case for Java 17. Maintaining an authentication client on a newer long-term-support runtime can reduce exposure to obsolete tooling and make dependency work less fragile. A library does not owe permanent compatibility to every runtime it once supported. Raising the floor can be the more responsible choice.

The latest public technical records are also internally coherent. The 1.5.1 POM sets java.version, maven.compiler.source and maven.compiler.target to 17. Its tagged GitHub Actions workflow installs the Zulu distribution of JDK 17 and runs Maven verification. The downloaded classes are major 61. POM, continuous-integration environment and artifact agree. POM at tag 1.5.1 Build workflow at tag 1.5.1

The README’s examples contain another fair defence. They do not silently declare 1.0.0 to be latest; their comments tell the reader to substitute a published JitPack version. Someone who deliberately stays on 1.0.0 can point to that release’s POM, where source and target are both 1.8. The document began as an accurate guide to that first release. POM at tag 1.0.0

Those defences explain how the split arose. They do not close it. “Replace this with a published version” is an instruction to cross a version boundary. “Java 8 or later” is a statement about what lies on the other side. Once later versions change the class-file floor, the version-selection instruction needs a compatibility map.

The floor moved at 1.5.0

The release history makes the transition visible when the files are placed side by side. Version 1.0.0 sets the Java and compiler properties to 1.8. Releases 1.1.0 through 1.4.0 preserve explicit compiler source and target values of 1.8 while their build workflow runs on JDK 17. Those intermediate POMs also contain a duplicated java.version property—first 1.8, then 17—so they should not be compressed into a story of perfectly aligned metadata. The explicit source and target remain 1.8.

Version 1.5.0 is the decisive change. Its POM sets the Java property, source and target to 17. Version 1.5.1 retains that configuration. This is not a forensic guess based on file dates; it is a comparison among immutable release tags. POM at tag 1.4.0 POM at tag 1.5.0

The public prose does not move with it. GitHub’s history shows one README commit, on 1 November 2024. The checked README bytes are identical at every release from 1.0.0 through 1.5.1 and on the current main branch. GitHub lists 1.5.0 as released on 29 October 2025 and 1.5.1 on 14 April 2026. The 1.5.0 and 1.5.1 release bodies are empty; neither supplies a compatibility note. README history GitHub releases Release 1.5.1

This is what documentation drift looks like before it becomes an incident: no dramatic outage, just two truthful records from different moments. The first release’s guide still speaks. The latest release’s bytes have moved on.

Six records that should not be collapsed

The easiest mistake is to call the README “wrong” and stop. That loses the evidence needed to make the correction durable. At least six records are in play.

The first is the documentation promise: a generic minimum runtime. The second is the dependency example: a specific library version. The third is the release identity: a tag and commit. The fourth is the build environment: the JDK used by the public workflow. The fifth is the artifact target: the class-file version actually distributed. The sixth is service compatibility: which PAI API behaviour the client version is designed and tested to consume.

These records answer different questions. Building on JDK 17 does not by itself prove that output requires Java 17; a compiler can run on a newer JDK and target an older class-file level. Maven’s own guide distinguishes the source and target settings and warns that target selection alone is not a complete API-compatibility guarantee. That is why the JAR matters. Conversely, major version 61 proves the class-file generation but says nothing about which PAI server revisions were tested, what credentials are accepted or whether a particular authentication succeeds. Maven Compiler Plugin guide

Likewise, a GitHub release with zero attached assets is not evidence that no artifact exists. The repository explicitly directs users to JitPack, and the artifact resolves there. JitPack’s build API returns an odd combination—an ok status alongside a “Not found” message and no build URL—but direct POM and JAR retrieval controls the availability finding. A confusing metadata endpoint should not be promoted into a stronger claim than the bytes allow.

Separating the records also separates responsibilities. LACNIC controls the repository, tags and public documentation. GitHub exposes repository and release records. JitPack builds and distributes a derivative Maven artifact from the tag. Oracle’s JVM specification defines the class-file compatibility rule. An integrator chooses a library version, runtime and deployment policy. No one record can substitute for all the others.

A compatibility failure is not an authentication incident

The subject matter raises the temperature. This is an authentication client, so it is tempting to move directly from version drift to a security conclusion. The evidence does not support that move.

Nothing in the checked public record shows a credential leak, bypass, exploit, failed authentication or service outage. The code’s Java 17 target may be entirely intentional. The PAI server’s own runtime is not disclosed by the client’s class files. A client that cannot load on an older JVM fails before it can say anything about the correctness or availability of the remote authentication service.

The right boundary is therefore operational but modest. An integrator needs to know whether a selected artifact can enter its runtime at all. After that, it needs separate evidence for API compatibility, configuration, credentials, network access, response handling and the application outcome. A compatibility receipt is the first gate, not the final verdict.

The same boundary keeps this inquiry separate from LACNIC’s other software evidence questions. It is not an audit of detached signatures or signer authority. It is not a reproducible-build claim. It does not bind a live election service to a source commit. It does not ask whether an ASPA or RTR capability is enabled. Those are different joins. Here the missing join is release version to runtime floor.

The small record that would repair the chain

LACNIC does not need a new review board or a large software bill of materials to answer this question. A compact, versioned compatibility record beside each release would be enough.

It should name the project, tag and exact commit; the Maven group, artifact and version; the class-file target; the build JDK; the minimum supported runtime; and the runtimes actually tested. It should state the PAI service or API compatibility scope, link to the documentation revision that applies, identify material runtime or dependency changes, and provide a support or deprecation window. A digest can bind the record to the inspected artifact. A correction or supersession link can preserve history when a statement changes.

The record should not claim more than it knows. “Built on JDK 17” is not the same as “requires Java 17.” “Class target 17” does not prove every library API call is safe under every installation. “Tested on 17 and 21” is not a guarantee for all vendors or future updates. “Compatible with PAI API revision X” does not prove a login in a customer environment. Each field should keep its evidence boundary.

The current repository already holds most of the inputs. The POM names the version and compiler target. The workflow names the JDK. The tag names the commit. JitPack exposes the artifact. The missing work is not collecting new truth; it is publishing the join so an operator does not have to reconstruct it from five surfaces.

A runtime floor is a governance fact

Why treat this as more than housekeeping? Because a registry’s authentication client sits at a boundary between institutional service and local automation. A runtime change can affect who can adopt a release, how quickly a security update can travel, and whether an operator must first replace its own platform. The registry does not control those local choices. It does control the public evidence on which they begin.

Clear versioning protects both sides. It lets LACNIC raise the floor without appearing to promise obsolete compatibility. It lets an integrator remain on an older line knowingly, plan a runtime migration or test a later artifact before adoption. It also prevents support conversations from beginning with a disagreement about what “Java 8 or later” meant for a release created eighteen months after that sentence was written.

The fix is not to keep every release on Java 8. It is to let each release state its own bargain. Code may move. The compatibility promise has to move with it.

Sources

  1. LACNIC: PAI Authentication Web Service Client repository
  2. LACNIC: README at release 1.5.1
  3. LACNIC: POM at release 1.0.0
  4. LACNIC: POM at release 1.4.0
  5. LACNIC: POM at release 1.5.0
  6. LACNIC: POM at release 1.5.1
  7. LACNIC: build workflow at release 1.5.1
  8. LACNIC: GitHub release list
  9. LACNIC: release 1.5.1
  10. LACNIC: README commit history
  11. JitPack: LACNIC PAI client project
  12. JitPack: generated POM for version 1.5.1
  13. JitPack: version 1.5.1 JAR
  14. Oracle: Java Virtual Machine Specification, class-file format
  15. Apache Maven: setting compiler source and target