The Vidocq ecosystem is composed of fifteen independent modules — seven Jakarta EE foundations plus eight MicroProfile implementations. This page describes their boundaries, their interfaces, and the cross-cutting choices that apply uniformly to all of them.

C4 view — Container level

Diagram

Quick reading:

  • Chappe is the only HTTP entry point. Foy and Cassini never talk to a ServerSocketChannel directly — they consume the Chappe exchange SPI.

  • Vauban is wired into every module that needs @Inject (Cassini, Foy, Mansart, Vidocq Runtime), but depends on no one.

  • Champollion is a leaf on the JSON side: Cassini uses it as the default entity provider, but Champollion does not know about Cassini.

  • Mansart knows nothing about HTTP or REST. It only consumes Vauban (@Transactional interceptor) and JDBC.

  • Vidocq Runtime orchestrates everything through an extension SPI (BuildStep, BuildItem, Recorder).

Dependency matrix

Diagram

Three notable properties:

  1. The graph is acyclic — no foundational module depends on a downstream one.

  2. Chappe, Vauban and Champollion are foundational bricks: no dependency on any other Vidocq module.

  3. Foy and Cassini are interchangeable as far as Vidocq Runtime is concerned: an application can run without Servlet (Cassini directly on Chappe) or without REST (Foy directly on Chappe).

  4. The MicroProfile layer (Ravel, Knock, Dirac, Heisenberg, Cervantes, Cyrano, Humboldt, Grimm) sits on top of the foundations: each module is an independent implementation, wired into Vidocq Runtime through the extension SPI and, where relevant, exposed over Cassini.

Cross-cutting choices

Four invariants apply across the whole ecosystem.

1. Zero or very few dependencies

Only the relevant Jakarta / MicroProfile specs are allowed at runtime. No Tomcat, Jetty, Netty, Weld, ArC, Yasson, Hibernate, RESTEasy. Any new runtime dependency must be explicitly justified in the PR.

2. Strict Java Modules

Every module ships its own module-info.java. Minimal exports. No unjustified opens. No classpath. No add-opens at launch. The integrity of the module graph is checked by the workspace java-modules-guardian agent.

3. Static codegen instead of runtime reflection

Anything that would otherwise be done by reflection or dynamic proxy is generated at compile time:

  • APT (Annotation Processor) — Vauban (injection graph), Champollion (JSON-B bindings), Mansart (*RepositoryImpl, metamodel).

  • Class-File API (JEP 484) — Vauban (interceptors), Mansart (Connection proxy).

  • No ASM, no Byte Buddy, no JDK dynamic proxy.

Direct payoff: compatible with GraalVM native-image and Project Leyden CDS without reflection configuration.

4. Virtual threads everywhere for I/O

Every I/O module uses Executors.newVirtualThreadPerTaskExecutor(). No platform pool by default. Context propagation (transaction, security) goes through ScopedValue rather than ThreadLocal whenever possible.