<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!--
        The release-only aggregator. Inheriting it gives this module the shared metadata
        (organization/licenses/developers/scm/url), <distributionManagement> and the `release`
        profile without duplicating them. NOTE for consumers: set YOUR <parent> to
        eu.virtualparadox:parent (this artifact), NOT to vp-build.
    -->
    <parent>
        <groupId>eu.virtualparadox</groupId>
        <artifactId>vp-build</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>parent</artifactId>
    <packaging>pom</packaging>

    <name>Virtual Paradox Parent</name>
    <description>Shared Maven parent: quality gates and dependency/plugin management for eu.virtualparadox projects. Consumers set this as their &lt;parent&gt;.</description>

    <properties>
        <java.version>21</java.version>
        <maven.compiler.release>${java.version}</maven.compiler.release>
        <!--
            The build-config artifact is put on the analysis plugins' classpath and unpacked for
            the rule files. This MUST be a literal published version (never ${project.version}),
            otherwise it would re-evaluate to the CONSUMER's version and fail to resolve. Consumers
            inherit this literal and resolve build-config from Central; the reactor build resolves
            the same version from the sibling module.
        -->
        <build.config.version>1.0.0</build.config.version>

        <!-- Build plugin versions -->
        <maven.compiler.plugin.version>3.15.0</maven.compiler.plugin.version>
        <maven.enforcer.plugin.version>3.6.3</maven.enforcer.plugin.version>
        <maven.surefire.plugin.version>3.5.5</maven.surefire.plugin.version>
        <maven.failsafe.plugin.version>3.5.5</maven.failsafe.plugin.version>
        <maven.javadoc.plugin.version>3.12.0</maven.javadoc.plugin.version>
        <maven.source.plugin.version>3.3.1</maven.source.plugin.version>
        <maven.clean.plugin.version>3.5.0</maven.clean.plugin.version>
        <maven.resources.plugin.version>3.4.0</maven.resources.plugin.version>
        <maven.jar.plugin.version>3.5.0</maven.jar.plugin.version>
        <maven.install.plugin.version>3.1.4</maven.install.plugin.version>
        <maven.deploy.plugin.version>3.1.4</maven.deploy.plugin.version>
        <maven.site.plugin.version>3.12.1</maven.site.plugin.version>
        <maven.min.version>3.9.6</maven.min.version>

        <!-- Static-analysis / quality-gate plugin versions -->
        <maven.checkstyle.plugin.version>3.6.0</maven.checkstyle.plugin.version>
        <checkstyle.version>13.4.2</checkstyle.version>
        <maven.pmd.plugin.version>3.28.0</maven.pmd.plugin.version>
        <pmd.version>7.24.0</pmd.version>
        <spotbugs.maven.plugin.version>4.9.8.3</spotbugs.maven.plugin.version>
        <findsecbugs.plugin.version>1.14.0</findsecbugs.plugin.version>
        <forbiddenapis.version>3.10</forbiddenapis.version>
        <errorprone.version>2.49.0</errorprone.version>
        <nullaway.version>0.13.4</nullaway.version>
        <jacoco.version>0.8.14</jacoco.version>
        <spotless.maven.plugin.version>2.43.0</spotless.maven.plugin.version>
        <maven.antrun.plugin.version>3.2.0</maven.antrun.plugin.version>
        <maven.dependency.plugin.version>3.8.1</maven.dependency.plugin.version>
        <license.maven.plugin.version>2.7.1</license.maven.plugin.version>
        <dependency.check.version>12.2.2</dependency.check.version>
        <cyclonedx.version>2.9.1</cyclonedx.version>

        <!-- JaCoCo wires these in; declared empty so surefire/failsafe argLine resolves without the agent. -->
        <surefireArgLine/>
        <failsafeArgLine/>
        <!-- OWASP dependency-check toggle (the gate lives in the `security` profile). -->
        <dependency.check.skip>false</dependency.check.skip>

        <!--
            Source-analysis gate toggles. Default false (every real library module is gated).
            The `no-sources` profile below flips them on for source-less aggregator POMs, which
            have nothing to analyze. These are NOT a way to weaken gates on code-bearing modules.
        -->
        <checkstyle.skip>false</checkstyle.skip>
        <pmd.skip>false</pmd.skip>
        <cpd.skip>false</cpd.skip>
        <spotbugs.skip>false</spotbugs.skip>
        <forbiddenapis.skip>false</forbiddenapis.skip>
        <spotless.check.skip>false</spotless.check.skip>
        <jacoco.skip>false</jacoco.skip>
        <!--
            License-scan toggle. Default false (active on every code-bearing module). The
            `no-sources` profile flips it on for source-less aggregator POMs only.
        -->
        <license.skip>false</license.skip>

        <!--
            Location of the optional per-project suppression files. Defaults to the module dir,
            which suits single-module consumers. A multi-module reactor that keeps suppressions at
            the reactor root can override this (e.g. to ${maven.multiModuleProjectDirectory}) so
            every submodule resolves the shared config/checkstyle-suppressions.xml and
            config/owasp-suppressions.xml without re-declaring any plugin configuration.
        -->
        <vp.suppressions.dir>${project.basedir}</vp.suppressions.dir>
        <!--
            SpotBugs exclude filter. Defaults to the shared base shipped in build-config (resolved
            from the plugin classpath). A consumer that needs its own exclusions can override this to
            a project file (which should also carry the base generated-sources entry).
        -->
        <vp.spotbugs.excludeFilterFile>spotbugs/exclude.xml</vp.spotbugs.excludeFilterFile>

        <!-- Managed library versions -->
        <junit.version>6.1.0</junit.version>
        <assertj.version>3.27.7</assertj.version>
        <mockito.version>5.23.0</mockito.version>
        <archunit.version>1.4.2</archunit.version>
        <bytebuddy.version>1.18.3</bytebuddy.version>
        <slf4j.version>2.0.18</slf4j.version>
        <logback.version>1.5.32</logback.version>
        <logstash.logback.encoder.version>8.0</logstash.logback.encoder.version>
        <commons.lang3.version>3.20.0</commons.lang3.version>
        <commons.collections4.version>4.5.0</commons.collections4.version>
        <commons.io.version>2.18.0</commons.io.version>
        <commons.text.version>1.13.0</commons.text.version>
        <commons.math3.version>3.6.1</commons.math3.version>
        <fastutil.version>8.5.15</fastutil.version>
        <lombok.version>1.18.46</lombok.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.junit</groupId>
                <artifactId>junit-bom</artifactId>
                <version>${junit.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.assertj</groupId>
                <artifactId>assertj-core</artifactId>
                <version>${assertj.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>${mockito.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-junit-jupiter</artifactId>
                <version>${mockito.version}</version>
            </dependency>
            <dependency>
                <groupId>com.tngtech.archunit</groupId>
                <artifactId>archunit-junit5</artifactId>
                <version>${archunit.version}</version>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy</artifactId>
                <version>${bytebuddy.version}</version>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy-agent</artifactId>
                <version>${bytebuddy.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback.version}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>${logback.version}</version>
            </dependency>
            <dependency>
                <groupId>net.logstash.logback</groupId>
                <artifactId>logstash-logback-encoder</artifactId>
                <version>${logstash.logback.encoder.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons.lang3.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-collections4</artifactId>
                <version>${commons.collections4.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons.io.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-text</artifactId>
                <version>${commons.text.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-math3</artifactId>
                <version>${commons.math3.version}</version>
            </dependency>
            <dependency>
                <groupId>it.unimi.dsi</groupId>
                <artifactId>fastutil</artifactId>
                <version>${fastutil.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>${maven.clean.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>${maven.resources.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>${maven.jar.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>${maven.install.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>${maven.deploy.plugin.version}</version>
                    <!-- Defer deploys to the end so a multi-module release never half-publishes. -->
                    <configuration>
                        <deployAtEnd>true</deployAtEnd>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>${maven.site.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven.compiler.plugin.version}</version>
                    <configuration>
                        <release>${maven.compiler.release}</release>
                        <!--
                            fork=true so ErrorProne's required JDK-internal add-exports/add-opens
                            flags can be passed INLINE as -J args below, instead of via a per-project
                            .mvn/jvm.config that every consumer/forker would have to copy. With a
                            forked compiler, -J flags are forwarded to the compiler JVM.
                        -->
                        <fork>true</fork>
                        <showWarnings>true</showWarnings>
                        <failOnWarning>true</failOnWarning>
                        <compilerArgs>
                            <!-- ErrorProne needs these JDK compiler internals opened; forwarded to the forked javac JVM. -->
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
                            <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
                            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
                            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
                            <arg>-parameters</arg>
                            <arg>-Xlint:all,-processing</arg>
                            <arg>-Xmaxerrs</arg>
                            <arg>10000</arg>
                            <arg>-Xmaxwarns</arg>
                            <arg>10000</arg>
                            <arg>-XDcompilePolicy=simple</arg>
                            <arg>--should-stop=ifError=FLOW</arg>
                            <arg>-XDaddTypeAnnotationsToSymbol=true</arg>
                            <arg>-Xplugin:ErrorProne -Xep:MissingOverride:ERROR -Xep:ReturnValueIgnored:ERROR -Xep:FutureReturnValueIgnored:ERROR -Xep:ReferenceEquality:ERROR -Xep:EqualsGetClass:ERROR -Xep:CatchAndPrintStackTrace:ERROR -Xep:NullAway:ERROR -XepOpt:NullAway:AnnotatedPackages=eu.virtualparadox -XepExcludedPaths:.*/target/generated-sources/.*</arg>
                        </compilerArgs>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>com.google.errorprone</groupId>
                                <artifactId>error_prone_core</artifactId>
                                <version>${errorprone.version}</version>
                            </path>
                            <path>
                                <groupId>com.uber.nullaway</groupId>
                                <artifactId>nullaway</artifactId>
                                <version>${nullaway.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${lombok.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${maven.surefire.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>${maven.failsafe.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-enforcer-plugin</artifactId>
                    <version>${maven.enforcer.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>${maven.source.plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <version>${maven.javadoc.plugin.version}</version>
                    <!-- Strict Javadoc quality gate (ported from managed-postgres): doclint=all, fail on any warning. -->
                    <configuration>
                        <source>${java.version}</source>
                        <failOnError>true</failOnError>
                        <failOnWarnings>true</failOnWarnings>
                        <doclint>all</doclint>
                        <quiet>false</quiet>
                        <show>protected</show>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <!--
                Unpack the shared rule files from build-config to target/vp-config. Bound to
                `validate` and declared first so the files exist before Checkstyle (also at
                `validate`, but resolved by Checkstyle core against the project classloader,
                which does not carry the build-config jar) and before license-maven-plugin at
                verify. The same copy is reused by the OWASP gate in the `security` profile.
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>${maven.dependency.plugin.version}</version>
                <executions>
                    <execution>
                        <id>unpack-build-config</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>eu.virtualparadox</groupId>
                                    <artifactId>build-config</artifactId>
                                    <version>${build.config.version}</version>
                                    <type>jar</type>
                                    <outputDirectory>${project.build.directory}/vp-config</outputDirectory>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <executions>
                    <execution>
                        <id>enforce</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <requireJavaVersion>
                                    <version>[${java.version},)</version>
                                </requireJavaVersion>
                                <requireMavenVersion>
                                    <version>[${maven.min.version},)</version>
                                </requireMavenVersion>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!--
                Spotless (palantir-java-format + unused-import removal) runs first as a fast
                formatting gate, before the heavier static analysis below.
            -->
            <plugin>
                <groupId>com.diffplug.spotless</groupId>
                <artifactId>spotless-maven-plugin</artifactId>
                <version>${spotless.maven.plugin.version}</version>
                <configuration>
                    <skip>${spotless.check.skip}</skip>
                    <java>
                        <includes>
                            <include>src/main/java/**/*.java</include>
                            <include>src/test/java/**/*.java</include>
                        </includes>
                        <palantirJavaFormat/>
                        <removeUnusedImports/>
                    </java>
                </configuration>
                <executions>
                    <execution>
                        <id>spotless-check</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>${maven.checkstyle.plugin.version}</version>
                <!-- build-config carries the rule files; reference them by classpath resource name. -->
                <dependencies>
                    <dependency>
                        <groupId>com.puppycrawl.tools</groupId>
                        <artifactId>checkstyle</artifactId>
                        <version>${checkstyle.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>eu.virtualparadox</groupId>
                        <artifactId>build-config</artifactId>
                        <version>${build.config.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <configLocation>checkstyle/checkstyle.xml</configLocation>
                    <!--
                        configLocation resolves off the plugin classpath (build-config jar), but the
                        SuppressionFilter inside it is resolved by Checkstyle core against the PROJECT
                        classloader, which does not carry build-config. So the base suppressions file is
                        referenced from the vp-config copy unpacked at the `initialize` phase. The
                        optional per-project local suppressions stay a plain project path.
                    -->
                    <propertyExpansion>checkstyle.suppressions.file=${project.build.directory}/vp-config/checkstyle/suppressions.xml
checkstyle.local.suppressions.file=${vp.suppressions.dir}/config/checkstyle-suppressions.xml</propertyExpansion>
                    <includeTestSourceDirectory>true</includeTestSourceDirectory>
                    <consoleOutput>true</consoleOutput>
                    <failsOnError>false</failsOnError>
                    <failOnViolation>false</failOnViolation>
                    <maxAllowedViolations>0</maxAllowedViolations>
                    <logViolationCountToConsole>true</logViolationCountToConsole>
                    <logViolationsToConsole>true</logViolationsToConsole>
                    <violationSeverity>error</violationSeverity>
                </configuration>
                <executions>
                    <execution>
                        <id>checkstyle</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>${maven.pmd.plugin.version}</version>
                <configuration>
                    <rulesets>
                        <ruleset>pmd/ruleset.xml</ruleset>
                    </rulesets>
                    <targetJdk>${java.version}</targetJdk>
                    <includeTests>true</includeTests>
                    <printFailingErrors>true</printFailingErrors>
                    <failOnViolation>false</failOnViolation>
                    <failurePriority>5</failurePriority>
                    <maxAllowedViolations>0</maxAllowedViolations>
                    <linkXRef>false</linkXRef>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>net.sourceforge.pmd</groupId>
                        <artifactId>pmd-core</artifactId>
                        <version>${pmd.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>net.sourceforge.pmd</groupId>
                        <artifactId>pmd-java</artifactId>
                        <version>${pmd.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>net.sourceforge.pmd</groupId>
                        <artifactId>pmd-javascript</artifactId>
                        <version>${pmd.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>net.sourceforge.pmd</groupId>
                        <artifactId>pmd-jsp</artifactId>
                        <version>${pmd.version}</version>
                    </dependency>
                    <!-- build-config carries pmd/ruleset.xml; put it on the plugin classpath. -->
                    <dependency>
                        <groupId>eu.virtualparadox</groupId>
                        <artifactId>build-config</artifactId>
                        <version>${build.config.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>pmd</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                            <goal>cpd-check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.github.spotbugs</groupId>
                <artifactId>spotbugs-maven-plugin</artifactId>
                <version>${spotbugs.maven.plugin.version}</version>
                <!-- build-config carries spotbugs/exclude.xml; put it on the plugin classpath. -->
                <dependencies>
                    <dependency>
                        <groupId>eu.virtualparadox</groupId>
                        <artifactId>build-config</artifactId>
                        <version>${build.config.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <effort>Max</effort>
                    <threshold>Low</threshold>
                    <excludeFilterFile>${vp.spotbugs.excludeFilterFile}</excludeFilterFile>
                    <includeTests>true</includeTests>
                    <failOnError>false</failOnError>
                    <maxAllowedViolations>0</maxAllowedViolations>
                    <plugins>
                        <plugin>
                            <groupId>com.h3xstream.findsecbugs</groupId>
                            <artifactId>findsecbugs-plugin</artifactId>
                            <version>${findsecbugs.plugin.version}</version>
                        </plugin>
                    </plugins>
                </configuration>
                <executions>
                    <execution>
                        <id>spotbugs</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>de.thetaphi</groupId>
                <artifactId>forbiddenapis</artifactId>
                <version>${forbiddenapis.version}</version>
                <configuration>
                    <failOnViolation>true</failOnViolation>
                    <failOnUnsupportedJava>true</failOnUnsupportedJava>
                    <!--
                        Load the signatures file straight out of the build-config jar
                        (signaturesArtifacts is the supported element in forbiddenapis 3.10).
                    -->
                    <signaturesArtifacts>
                        <signaturesArtifact>
                            <groupId>eu.virtualparadox</groupId>
                            <artifactId>build-config</artifactId>
                            <version>${build.config.version}</version>
                            <type>jar</type>
                            <path>forbidden-apis/signatures.txt</path>
                        </signaturesArtifact>
                    </signaturesArtifacts>
                </configuration>
                <executions>
                    <execution>
                        <id>forbidden-apis</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                            <goal>testCheck</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>@{surefireArgLine}</argLine>
                    <includes>
                        <include>**/*Test.java</include>
                        <include>**/*Tests.java</include>
                    </includes>
                    <failIfNoTests>false</failIfNoTests>
                    <skipAfterFailureCount>0</skipAfterFailureCount>
                    <rerunFailingTestsCount>0</rerunFailingTestsCount>
                    <printSummary>true</printSummary>
                    <trimStackTrace>false</trimStackTrace>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <configuration>
                    <argLine>@{failsafeArgLine}</argLine>
                    <includes>
                        <include>**/*IT.java</include>
                        <include>**/*IntegrationTest.java</include>
                    </includes>
                    <skipAfterFailureCount>0</skipAfterFailureCount>
                    <rerunFailingTestsCount>0</rerunFailingTestsCount>
                    <printSummary>true</printSummary>
                    <trimStackTrace>false</trimStackTrace>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.version}</version>
                <executions>
                    <execution>
                        <id>prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <propertyName>surefireArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>prepare-agent-integration</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                        <configuration>
                            <propertyName>failsafeArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>report</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>report</goal>
                            <goal>report-integration</goal>
                        </goals>
                        <configuration>
                            <haltOnFailure>true</haltOnFailure>
                            <excludes>
                                <!-- Generic DTO/Entity/model/record carriers with no meaningful behavior to cover. -->
                                <exclude>**/*Dto.class</exclude>
                                <exclude>**/*DTO.class</exclude>
                                <exclude>**/dto/**</exclude>
                                <exclude>**/*Entity.class</exclude>
                                <exclude>**/entity/**</exclude>
                                <exclude>**/*Record.class</exclude>
                                <exclude>**/model/**</exclude>
                                <exclude>**/*Request.class</exclude>
                                <exclude>**/*Response.class</exclude>
                            </excludes>
                        </configuration>
                    </execution>
                    <execution>
                        <id>merge</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>merge</goal>
                        </goals>
                        <configuration>
                            <destFile>${project.build.directory}/jacoco-merged.exec</destFile>
                            <fileSets>
                                <fileSet>
                                    <directory>${project.build.directory}</directory>
                                    <includes>
                                        <include>*.exec</include>
                                    </includes>
                                </fileSet>
                            </fileSets>
                        </configuration>
                    </execution>
                    <execution>
                        <id>check</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <excludes>
                                <!-- Generic DTO/Entity/model/record carriers with no meaningful behavior to cover. -->
                                <exclude>**/*Dto.class</exclude>
                                <exclude>**/*DTO.class</exclude>
                                <exclude>**/dto/**</exclude>
                                <exclude>**/*Entity.class</exclude>
                                <exclude>**/entity/**</exclude>
                                <exclude>**/*Record.class</exclude>
                                <exclude>**/model/**</exclude>
                                <exclude>**/*Request.class</exclude>
                                <exclude>**/*Response.class</exclude>
                            </excludes>
                            <rules>
                                <rule>
                                    <element>BUNDLE</element>
                                    <limits>
                                        <limit>
                                            <counter>BRANCH</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.90</minimum>
                                        </limit>
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.90</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <configuration>
                    <forceCreation>true</forceCreation>
                </configuration>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <executions>
                    <execution>
                        <id>javadoc</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>javadoc</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>attach-javadocs</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>license-maven-plugin</artifactId>
                <version>${license.maven.plugin.version}</version>
                <configuration>
                    <skip>${license.skip}</skip>
                    <failOnBlacklist>true</failOnBlacklist>
                    <failOnMissing>true</failOnMissing>
                    <force>true</force>
                    <!--
                        license-maven-plugin 2.7.1 does not resolve a classpath:// URL for
                        includedLicenses, so the allowlist is unpacked from build-config to
                        target/vp-config (see maven-dependency-plugin below) and referenced via file://.
                    -->
                    <includedLicenses>file://${project.build.directory}/vp-config/license/license-allowlist.txt</includedLicenses>
                    <excludedLicenses>
                        <excludedLicense>GNU General Public License</excludedLicense>
                        <excludedLicense>GNU Affero General Public License</excludedLicense>
                        <excludedLicense>Server Side Public License</excludedLicense>
                    </excludedLicenses>
                </configuration>
                <executions>
                    <execution>
                        <id>license-check</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>aggregate-add-third-party</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>${maven.antrun.plugin.version}</version>
                <executions>
                    <execution>
                        <id>static-analysis-gate</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target name="static-analysis-gate">
                                <condition property="checkstyle.failed">
                                    <and>
                                        <available file="${project.build.directory}/checkstyle-result.xml"/>
                                        <resourcecontains resource="${project.build.directory}/checkstyle-result.xml"
                                                          substring="&lt;error "/>
                                    </and>
                                </condition>
                                <condition property="pmd.failed">
                                    <and>
                                        <available file="${project.build.directory}/pmd.xml"/>
                                        <resourcecontains resource="${project.build.directory}/pmd.xml"
                                                          substring="&lt;violation "/>
                                    </and>
                                </condition>
                                <condition property="cpd.failed">
                                    <and>
                                        <available file="${project.build.directory}/cpd.xml"/>
                                        <resourcecontains resource="${project.build.directory}/cpd.xml"
                                                          substring="&lt;duplication "/>
                                    </and>
                                </condition>
                                <condition property="spotbugs.failed">
                                    <and>
                                        <available file="${project.build.directory}/spotbugsXml.xml"/>
                                        <resourcecontains resource="${project.build.directory}/spotbugsXml.xml"
                                                          substring="&lt;BugInstance "/>
                                    </and>
                                </condition>
                                <fail message="Static analysis violations were collected. See checkstyle-result.xml, pmd.xml, cpd.xml, and spotbugsXml.xml under ${project.build.directory}.">
                                    <condition>
                                        <or>
                                            <isset property="checkstyle.failed"/>
                                            <isset property="pmd.failed"/>
                                            <isset property="cpd.failed"/>
                                            <isset property="spotbugs.failed"/>
                                        </or>
                                    </condition>
                                </fail>
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <!--
            Source-less modules (the aggregator parent POM) have nothing for the source-analysis
            gates to inspect, so the gates would either fail on config init or run vacuously.
            Auto-activated when src/main/java is absent; never active on code-bearing modules.
            This skips analysis on empty aggregators only - it does not relax any threshold.
        -->
        <profile>
            <id>no-sources</id>
            <activation>
                <file>
                    <missing>src/main/java</missing>
                </file>
            </activation>
            <properties>
                <checkstyle.skip>true</checkstyle.skip>
                <pmd.skip>true</pmd.skip>
                <cpd.skip>true</cpd.skip>
                <spotbugs.skip>true</spotbugs.skip>
                <forbiddenapis.skip>true</forbiddenapis.skip>
                <spotless.check.skip>true</spotless.check.skip>
                <jacoco.skip>true</jacoco.skip>
                <!--
                    Source-less modules have no third-party deps to license-scan. We skip the
                    license CHECK (default false; flipped here only), but we still UNPACK the rule
                    files: license-maven-plugin parses its includedLicenses file:// URL during
                    parameter injection (before honoring skip), so the allowlist must physically
                    exist even on a skipped run. The unpack is cheap and harmless on aggregators.
                -->
                <license.skip>true</license.skip>
            </properties>
        </profile>
        <!--
            Opt-in OWASP dependency-check security gate: ./mvnw -Psecurity verify
            Kept out of the default build because an NVD sync is slow and needs NVD_API_KEY.
        -->
        <profile>
            <id>security</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-dependency-plugin</artifactId>
                        <version>${maven.dependency.plugin.version}</version>
                        <executions>
                            <!-- Unpack the shared OWASP suppression file from build-config for the check below. -->
                            <execution>
                                <id>unpack-build-config-security</id>
                                <phase>initialize</phase>
                                <goals>
                                    <goal>unpack</goal>
                                </goals>
                                <configuration>
                                    <artifactItems>
                                        <artifactItem>
                                            <groupId>eu.virtualparadox</groupId>
                                            <artifactId>build-config</artifactId>
                                            <version>${build.config.version}</version>
                                            <type>jar</type>
                                            <outputDirectory>${project.build.directory}/vp-config</outputDirectory>
                                        </artifactItem>
                                    </artifactItems>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.owasp</groupId>
                        <artifactId>dependency-check-maven</artifactId>
                        <version>${dependency.check.version}</version>
                        <configuration>
                            <skip>${dependency.check.skip}</skip>
                            <failBuildOnCVSS>0</failBuildOnCVSS>
                            <nvdApiKeyEnvironmentVariable>NVD_API_KEY</nvdApiKeyEnvironmentVariable>
                            <suppressionFiles>
                                <suppressionFile>${project.build.directory}/vp-config/owasp/dependency-check-suppressions.xml</suppressionFile>
                                <!-- Optional project-local suppressions; justify each CVE there. -->
                                <suppressionFile>${vp.suppressions.dir}/config/owasp-suppressions.xml</suppressionFile>
                            </suppressionFiles>
                            <formats>
                                <format>HTML</format>
                                <format>JSON</format>
                                <format>JUNIT</format>
                            </formats>
                            <junitFailOnCVSS>0</junitFailOnCVSS>
                            <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
                        </configuration>
                        <executions>
                            <execution>
                                <id>dependency-check</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>check</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <!--
            Opt-in CycloneDX SBOM generation: ./mvnw -Psbom verify
        -->
        <profile>
            <id>sbom</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.cyclonedx</groupId>
                        <artifactId>cyclonedx-maven-plugin</artifactId>
                        <version>${cyclonedx.version}</version>
                        <configuration>
                            <projectType>library</projectType>
                            <schemaVersion>1.6</schemaVersion>
                            <includeBomSerialNumber>true</includeBomSerialNumber>
                            <includeCompileScope>true</includeCompileScope>
                            <includeProvidedScope>true</includeProvidedScope>
                            <includeRuntimeScope>true</includeRuntimeScope>
                            <includeSystemScope>false</includeSystemScope>
                            <includeTestScope>false</includeTestScope>
                            <outputFormat>all</outputFormat>
                        </configuration>
                        <executions>
                            <execution>
                                <id>make-sbom</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>makeBom</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>
