candor · for the JVM · case studies

Real code.
No configuration.

Five runs of candor-java against real, third-party JVM projects — no config, no annotations, no source changes. Each is candor <compiled-classes> plus, where shown, a short arch.policy wired to fail the build. The point of the set is breadth: two Spring styles, a Kotlin app, a non-Spring framework, a library supply-chain audit, and what candor does at the edge of what it models.

Every study is reproducible. Build the project (JDK 17), then:

jbang candor@tombaldwin/candor-java path/to/classes

01 RealWorld “Conduit” — Spring, DDD + MyBatis

A genuine layered Spring Boot app (93 Java files; api / application / core / infrastructure / graphql). candor derived the layer map from bytecode: Db is 100% contained in infrastructure, and the DDD domain (io.spring.core) performs zero Db/Net/Fs/Exec.

The gate then bit on a real architecture decision: all five aggregate roots mint their own IDs with UUID.randomUUID(), which a team practising strict DI would forbid.

candor also named the 13 third-party packages it doesn’t model as invisible rather than “no effect”: disclosure over silence, even on a clean run.

02 Spring PetClinic — the smell review missed

The canonical Spring sample resolves cleanly — 47 functions, Db ×21 + Clock ×6, zero Unknown — and candor correctly attributes Db to the Spring Data repository interfaces, whose implementations only exist at runtime. The interesting result is a real cross-layer smell the gate catches:

PetTypeFormatter is a presentation-layer Spring Formatter, yet parse reaches the database directly. It looks up pet types to convert a form field. Exactly the layering drift an architecture gate exists to catch: surfaced from bytecode, pinned to the method, with no annotations.

03 PetClinic in Kotlin — language-agnostic

The same app rebuilt in Kotlin. candor reads the compiled classes, so the source language is irrelevant: 47 functions, Db ×21, the same repository→controller shape, Db 80% contained in the owner layer. The architecture signal survives the language change because the analysis is on bytecode, not source. One engine covers Java, Kotlin, Scala and Groovy.

04 Quarkus + Jakarta Data — not Spring

The Hibernate ORM / Jakarta Data quickstart — deliberately not Spring. FruitRepository is a jakarta.data.repository.CrudRepository interface, and the REST endpoints go through it into Hibernate’s Jakarta-Data-era API. candor reads that boundary and Db lands on all five endpoints, fully contained:

Two things make this the most telling study of the set. The analysis crosses frameworks: the same engine that maps Spring Data and MyBatis models the Jakarta Data / Hibernate 6 persistence path, so Db lands without a single annotation. And look at the residual invisible: the pure criteria-builder packages candor doesn’t model are still disclosed, not silently dropped. candor never reports “pure” for a call it hasn’t actually understood, so a gate built on it is never silently wrong, even at the edge of what it models.

This study drove a real engine change: an earlier run disclosed the whole org.hibernate surface as invisible, and that disclosure became the worklist that added the Hibernate 6 / Jakarta Data model to the classifier. A blind spot the tool names is a blind spot that gets fixed.

05 gson — a supply-chain audit

“What does this dependency actually touch?” candor scanned the gson 2.11.0 jar: 386 functions, exactly one Net

javap confirms it: that class is TypeAdapter<java.net.InetAddress>, and read calls InetAddress.getByName — a DNS lookup performed while deserializing JSON. A real, non-obvious network touch in a library most people file under “pure parsing”, found with zero fabrication. That is the supply-chain question candor answers directly: not “is this library popular” but “what can it reach”.

06 Run it on your repo

The adopt starter is three steps to the gate on every push: a one-command scaffold proposes a policy from what your code already does, and the GitHub Action surfaces violations inline on the PR diff and in the Security tab. A live demo repo shows the whole loop, alert and all.

Add the CI gate Full write-ups →

Disclosure, not a completeness proof: candor catches more than review, and tells you where it’s unsure (an explicit Unknown) rather than guessing.

Work with the team behind candor

candor is built and run by Polymorphism — a small senior team that designs, builds and runs large systems for enterprise and government. The judgement we put into AI-code safety here is what we’d bring to your platform.

How we work Talk to the team