Subsystem · resolver

Resolver & checksums

Curie talks to Maven Central directly. No POM you wrote, no plugin ceremony — just group:artifact = "version" in Curie.toml and a transitive closure resolved against the same ~/.m2/repository Maven uses.

Declaring dependencies

Curie.toml
[dependencies]
"com.fasterxml.jackson.core:jackson-databind" = "2.17.2"
"com.google.guava:guava"                     = "33.2.0-jre"

[test-dependencies]
"org.junit.jupiter:junit-jupiter" = "5.11.0"

Each entry is "group:artifact" = "version". An empty version ("") means the version comes from a BOM — see below.

BOM imports

A BOM (bill of materials) is a POM-packaged artifact whose <dependencyManagement> section pins versions for a family of related artifacts. List them under [bom-imports] in priority order (later wins on collision):

Curie.toml
[bom-imports]
"com.fasterxml.jackson:jackson-bom" = "2.17.2"

[dependencies]
# empty version → resolved from the BOM above
"com.fasterxml.jackson.core:jackson-databind" = ""
"com.fasterxml.jackson.core:jackson-annotations" = ""

If you declare a dependency with "" and no BOM provides it, the build fails up front — there's no silent fallback to "latest".

Transitive resolution

Curie does a breadth-first walk of every dependency's POM, applying Maven's conflict-resolution rules:

POMs are fetched serially in phase 1 (small, fast). JARs are then downloaded in parallel in phase 2 — up to eight concurrent workers — and arrive in the local cache in a stable, topologically ordered classpath.

Checksum verification

Every artifact Curie downloads is verified against its .sha256 sidecar from the same repository. The sidecar hash is then persisted next to the artifact in ~/.m2/repository/...artifact.jar.sha256, mirroring Maven Central's published layout. On the next build the cached hash is compared against the cached JAR — zero network calls, zero implicit trust.

A missing sidecar is a hard error. Every well-formed Maven repository publishes one — Maven's deploy plugin generates them, and Nexus / Artifactory generate them server-side on upload. A missing sidecar usually means a misconfigured proxy or a manually-uploaded artifact, and either way Curie refuses to install an unverifiable JAR.

Fallback to SHA-1

If a repository only publishes .sha1 sidecars (older mirrors, some private repos), Curie falls back to that. SHA-1 is cryptographically weak for authentication but still catches accidental corruption and unsophisticated substitution — adequate for the integrity-check use case.

Tamper detection

Edit a JAR in ~/.m2/repository by hand and the next build will fail with a checksum mismatch error citing the artifact and both digests. The local cache is now tamper-evident.

Offline mode

Pass --offline to forbid network calls entirely. Any cache miss is an immediate error. Useful for sealed CI environments, reproducibility checks, and incident-response builds where you want to be sure nothing on disk has changed since the last good build.

$ curie build --offline
Building greeter v0.1.0
  Compile         up to date
  Tests           up to date
  Package         up to date
  Done            target/greeter-0.1.0.jar

Extra repositories

By default the resolver hits Maven Central. Add private mirrors or company-internal Nexus instances with [repositories]:

Curie.toml
[repositories]
internal = "https://nexus.internal.example.com/repository/maven-public/"

Repositories are tried in order — Central first, then each [repositories] entry in declaration order — until an artifact resolves.