Skip to content

ITs and archetype updates for more audits#17

Merged
jeffjensen merged 5 commits into
mainfrom
feat/more-audits
Jul 8, 2026
Merged

ITs and archetype updates for more audits#17
jeffjensen merged 5 commits into
mainfrom
feat/more-audits

Conversation

@jeffjensen

@jeffjensen jeffjensen commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added more database audit checks for schema quality, JPA mapping, versioning, pagination, repeated statements, and unused indexes.
    • Expanded fix guidance for several new audit findings, including clearer remediation suggestions.
  • Bug Fixes

    • Improved handling of duplicate foreign-key relationships and broader database mapping issues.
    • Added optimistic locking support to generated entities.
  • Documentation

    • Updated audit and exclusion guides to cover the new checks and how to configure exceptions.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jeffjensen, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 18 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b86443b-a14a-46f1-a6ea-2345fe301348

📥 Commits

Reviewing files that changed from the base of the PR and between a48aa98 and e5b3b92.

📒 Files selected for processing (31)
  • archetype/src/main/resources/META-INF/archetype-post-generate.groovy
  • archetype/src/main/resources/archetype-resources/src/test/java/app/Child.java
  • archetype/src/main/resources/archetype-resources/src/test/java/app/Parent.java
  • archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/catalog/PrimaryKeyTypeAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/catalog/UniqueIndexNotNullAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/jpa/EagerCollectionFetchAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/jpa/MissingVersionAttributeAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/jpa/UnmappedDatabaseObjectAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/runtime/RepeatedStatementAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/runtime/UnusedIndexAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/resources/db/changelog/db.changelog-master.xml
  • integration/pom.xml
  • integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DuplicateForeignKeyAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/EagerCollectionFetchAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/MissingVersionAttributeAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/OffsetPaginationAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/PrimaryKeyTypeAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RepeatedStatementAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UniqueIndexNotNullAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnmappedDatabaseObjectAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnusedIndexAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java
  • integration/src/site/asciidoc/audits.adoc
  • integration/src/site/asciidoc/exclusions.adoc
  • integration/src/site/asciidoc/usage.adoc
  • integration/src/test/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludesTest.java
  • integration/src/test/java/io/github/databaseaudits/spring/boot/report/FixRendererTest.java
📝 Walkthrough

Walkthrough

This PR adds nine new database audits (catalog, JPA, and runtime families) with corresponding assertion classes, exclusion configuration, and suite wiring. It extends FixRenderer with remediation guidance for the new finding types, adds archetype integration test templates with entity version fields, updates documentation, and bumps a dependency version.

Changes

New Audit Assertions and Integration

Layer / File(s) Summary
Exclusion configuration
integration/.../assertion/DatabaseAuditExcludes.java
Adds immutable fields, accessors, and Builder methods for new exclusion categories across catalog, JPA, and runtime audits, including a repeated-statement threshold default.
New assertion classes
integration/.../assertion/DuplicateForeignKeyAuditAssertion.java, EagerCollectionFetchAuditAssertion.java, MissingVersionAttributeAuditAssertion.java, OffsetPaginationAuditAssertion.java, PrimaryKeyTypeAuditAssertion.java, RepeatedStatementAuditAssertion.java, UniqueIndexNotNullAuditAssertion.java, UnmappedDatabaseObjectAuditAssertion.java, UnusedIndexAuditAssertion.java
Nine new AbstractAuditAssertion implementations wrap underlying audits, expose assertClean overloads (with and without exclusions), declare an AuditFamily, and support AuditScope-derived exclusion resolution.
Suite roster wiring
integration/.../DatabaseAuditSuite.java
Constructs a ForeignKeyCatalog and expands the roster with the new catalog/JPA assertions plus PostgreSQL-only and all-platform runtime assertions.
FixRenderer remediation
integration/.../report/FixRenderer.java, integration/src/test/.../FixRendererTest.java
Extends fixFor and liquibaseChangeSet with branches for the ten new finding kinds, adds duplicate-FK drop DDL/XML helpers, and adds corresponding test coverage.
Archetype IT templates
archetype/.../test/java/catalog/*.java, .../jpa/*.java, .../runtime/*.java, META-INF/archetype-post-generate.groovy
Adds new generated integration test templates for each audit and updates the post-generate cleanup list for non-PostgreSQL projects.
Entity versioning
archetype/.../test/java/app/Parent.java, Child.java, .../db.changelog-master.xml
Adds @Version fields and accessors to Parent/Child, plus matching non-null version columns in the test changelog.
Documentation and version bump
integration/src/site/asciidoc/audits.adoc, exclusions.adoc, usage.adoc, integration/pom.xml
Documents new audits/exclusions and bumps database-audits-core.version to 3.0.1-SNAPSHOT.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DatabaseAuditSuite
  participant AuditAssertion
  participant AuditScope
  participant Audit
  DatabaseAuditSuite->>AuditAssertion: construct with audit + platform
  AuditScope->>AuditAssertion: assertClean(scope)
  AuditAssertion->>AuditScope: excludes()
  AuditAssertion->>Audit: audit(schema/params, excludedSet)
  Audit-->>AuditAssertion: violations
  AuditAssertion->>AuditAssertion: failOnViolations(message)
Loading

Possibly related PRs

Suggested labels: enhancement, documentation

Suggested reviewers: database-audits maintainers familiar with audit assertion internals and archetype templates

🐰 A rabbit hopped through catalogs deep,
Nine new audits woke from sleep,
Foreign keys twinned, indexes bare,
Versions missing here and there,
Now every schema's secrets keep.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding new audits with integration-test and archetype updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/more-audits

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Wire nine new audits into integration suite, archetype ITs, and fix rendering

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add nine new catalog/JPA/runtime audit assertions and exclusions to integration suite.
• Extend FixRenderer and tests for new sealed Finding types and fix guidance.
• Update archetype templates and docs to generate new ITs and version columns.
Diagram

graph TD
  core{{"database-audits-core 3.0.1-SNAPSHOT"}} --> suite["DatabaseAuditSuite"] --> assertions["\"*AuditAssertion\" beans"] --> renderer["FixRenderer"]
  suite --> excludes["DatabaseAuditExcludes"] --> assertions
  assertions --> archetype["Archetype IT templates"] --> docs["Asciidoc docs"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. ServiceLoader/auto-discovery for audit roster
  • ➕ Avoids manual roster edits when adding new audits
  • ➕ Potentially simplifies wiring across modules
  • ➖ Harder to guarantee stable ordering and family grouping in reports
  • ➖ Complicates platform-specific gating (PostgreSQL-only plan audits)
  • ➖ Still leaves sealed Finding rendering needing explicit handling
2. Visitor/registry-based FixRenderer dispatch
  • ➕ Can decouple FixRenderer from a growing switch statement
  • ➕ Allows per-finding renderer classes and easier unit targeting
  • ➖ More types/boilerplate; must still be exhaustively kept in sync with sealed Finding set
  • ➖ Harder to follow end-to-end behavior than a single exhaustive switch

Recommendation: Keep the current explicit roster wiring and exhaustive sealed-type switches. Given platform gating requirements and the deliberate compile-time signal provided by sealed Finding exhaustiveness, the PR’s approach optimizes correctness and maintainability, while the added tests ensure each new Finding renders with the intended fidelity (PRECISE/TEMPLATE/ADVISORY).

Files changed (30) +1781 / -22

Enhancement (12) +989 / -9
DatabaseAuditSuite.javaWire nine new audits/assertions into the central roster +58/-3

Wire nine new audits/assertions into the central roster

• Adds new catalog/JPA/runtime audits and their assertion beans to the suite roster, including new ForeignKeyCatalog construction. Introduces an explicit List<AuditAssertion> type witness to avoid javac inferring an inaccessible common supertype. Gates UnusedIndexAudit with other plan-based audits for PostgreSQL-only execution, while adding token-scan audits for all platforms.

integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.java

DatabaseAuditExcludes.javaExpand facade exclusions for new audits (plus repeated-statement threshold) +229/-6

Expand facade exclusions for new audits (plus repeated-statement threshold)

• Adds new exclusion fields and builder methods covering duplicate FKs, PK type, unique index nullability, unmapped objects, missing @Version, eager collections, unused indexes, and capture-scan audits. Introduces a default repeated-statement threshold (50) and exposes it via the scope API for assertion beans.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java

DuplicateForeignKeyAuditAssertion.javaNew assertion bean for DuplicateForeignKeyAudit +71/-0

New assertion bean for DuplicateForeignKeyAudit

• Adds a catalog-family assertion wrapper with overloads for schema-only and schema+excluded-constraints usage. Integrates with AuditScope to pull exclusions from DatabaseAuditExcludes.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DuplicateForeignKeyAuditAssertion.java

EagerCollectionFetchAuditAssertion.javaNew assertion bean for EagerCollectionFetchAudit +63/-0

New assertion bean for EagerCollectionFetchAudit

• Adds a JPA-family assertion wrapper to flag eagerly fetched collections, with an exclusion set for deliberate eager roles. Integrates with AuditScope excludes.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/EagerCollectionFetchAuditAssertion.java

MissingVersionAttributeAuditAssertion.javaNew assertion bean for MissingVersionAttributeAudit +66/-0

New assertion bean for MissingVersionAttributeAudit

• Adds a JPA-family assertion wrapper to require @Version on mutable root entities, with an exclusion hook for append-only/single-writer entities. Integrates with AuditScope excludes.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/MissingVersionAttributeAuditAssertion.java

OffsetPaginationAuditAssertion.javaNew assertion bean for OffsetPaginationAudit +62/-0

New assertion bean for OffsetPaginationAudit

• Adds a runtime-family assertion wrapper to detect offset-based pagination in captured SQL. Supports excluding statements by SQL fragment via DatabaseAuditExcludes.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/OffsetPaginationAuditAssertion.java

PrimaryKeyTypeAuditAssertion.javaNew assertion bean for PrimaryKeyTypeAudit +69/-0

New assertion bean for PrimaryKeyTypeAudit

• Adds a catalog-family assertion wrapper ensuring primary keys are at least BIGINT wide. Supports excluding genuinely bounded PK columns via table.column strings and integrates with AuditScope.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/PrimaryKeyTypeAuditAssertion.java

RepeatedStatementAuditAssertion.javaNew assertion bean for RepeatedStatementAudit (threshold + exclusions) +77/-0

New assertion bean for RepeatedStatementAudit (threshold + exclusions)

• Adds a runtime-family assertion wrapper for repeated SELECT shapes indicating potential N+1 bursts. Exposes API to set a threshold and exclusion fragments, and integrates with the facade default threshold.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RepeatedStatementAuditAssertion.java

UniqueIndexNotNullAuditAssertion.javaNew assertion bean for UniqueIndexNotNullAudit +69/-0

New assertion bean for UniqueIndexNotNullAudit

• Adds a catalog-family assertion wrapper asserting UNIQUE indexes do not include nullable columns. Allows excluding indexes whose partial-uniqueness semantics are deliberate.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UniqueIndexNotNullAuditAssertion.java

UnmappedDatabaseObjectAuditAssertion.javaNew assertion bean for UnmappedDatabaseObjectAudit +68/-0

New assertion bean for UnmappedDatabaseObjectAudit

• Adds a JPA-family assertion wrapper asserting all physical schema tables/columns are mapped by entities. Provides an exclusion set for known acceptable unmapped objects like migration bookkeeping.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnmappedDatabaseObjectAuditAssertion.java

UnusedIndexAuditAssertion.javaNew assertion bean for UnusedIndexAudit +69/-0

New assertion bean for UnusedIndexAudit

• Adds a runtime-family assertion wrapper asserting indexes appear in at least one captured query plan (PostgreSQL-only). Supports excluding indexes kept for workloads outside the capture and integrates with AuditScope schema/excludes.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnusedIndexAuditAssertion.java

FixRenderer.javaRender fixes for nine new sealed Finding types +88/-0

Render fixes for nine new sealed Finding types

• Extends both exhaustive sealed switches (DDL and Liquibase rendering) to cover the new core Finding types. Adds precise drops for duplicate FKs (DDL + dropForeignKeyConstraint XML) and template/advisory guidance for PK widening, unused indexes, pagination strategy, N+1 bursts, @Version, eager fetching, and unmapped objects.

integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java

Tests (13) +686 / -2
Child.javaAdd @Version field to demo Child entity +16/-1

Add @Version field to demo Child entity

• Introduces an optimistic-locking @Version column and getter in the archetype demo entity. Updates Javadoc to explain concurrency protection rather than silent overwrite behavior.

archetype/src/main/resources/archetype-resources/src/test/java/app/Child.java

Parent.javaAdd @Version field to demo Parent entity +16/-1

Add @Version field to demo Parent entity

• Adds an optimistic-locking @Version column and getter to the Parent demo entity. Updates class documentation to reflect versioning expectations used by the missing-version audit.

archetype/src/main/resources/archetype-resources/src/test/java/app/Parent.java

DuplicateForeignKeyAuditIT.javaNew archetype IT for duplicate foreign key constraints +45/-0

New archetype IT for duplicate foreign key constraints

• Adds an integration test template that asserts no relationship is enforced by multiple FK constraints. Provides an exclusion set hook for intentional duplicates.

archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java

PrimaryKeyTypeAuditIT.javaNew archetype IT for primary key width (BIGINT minimum) +46/-0

New archetype IT for primary key width (BIGINT minimum)

• Adds an IT template for PrimaryKeyTypeAuditAssertion. Includes a default exclusion for Liquibase's databasechangeloglock.id and a hook for genuinely bounded tables.

archetype/src/main/resources/archetype-resources/src/test/java/catalog/PrimaryKeyTypeAuditIT.java

UniqueIndexNotNullAuditIT.javaNew archetype IT for UNIQUE indexes over nullable columns +45/-0

New archetype IT for UNIQUE indexes over nullable columns

• Adds an IT template ensuring UNIQUE indexes do not include nullable columns. Supports excluding deliberately partial-uniqueness indexes by name.

archetype/src/main/resources/archetype-resources/src/test/java/catalog/UniqueIndexNotNullAuditIT.java

EagerCollectionFetchAuditIT.javaNew archetype IT for eager collection fetch mappings +40/-0

New archetype IT for eager collection fetch mappings

• Adds an IT template asserting no mapped collections are fetched eagerly. Provides an exclusion hook for deliberate eager roles.

archetype/src/main/resources/archetype-resources/src/test/java/jpa/EagerCollectionFetchAuditIT.java

MissingVersionAttributeAuditIT.javaNew archetype IT for missing @Version attributes +41/-0

New archetype IT for missing @Version attributes

• Adds an IT template asserting every mutable root entity has a @Version attribute. Includes an exclusion hook for append-only or single-writer entities.

archetype/src/main/resources/archetype-resources/src/test/java/jpa/MissingVersionAttributeAuditIT.java

UnmappedDatabaseObjectAuditIT.javaNew archetype IT for unmapped tables/columns +43/-0

New archetype IT for unmapped tables/columns

• Adds an IT template asserting all physical base tables/columns are entity-mapped. Defaults to excluding Liquibase bookkeeping tables from the unmapped-object check.

archetype/src/main/resources/archetype-resources/src/test/java/jpa/UnmappedDatabaseObjectAuditIT.java

OffsetPaginationAuditIT.javaNew archetype IT for offset-based pagination detection +43/-0

New archetype IT for offset-based pagination detection

• Adds a capture-based runtime IT asserting no captured query paginates using OFFSET. Orders the test last so the SQL capturer has been primed by workload ITs.

archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java

RepeatedStatementAuditIT.javaNew archetype IT for repeated SELECT shapes (N+1 bursts) +47/-0

New archetype IT for repeated SELECT shapes (N+1 bursts)

• Adds a capture-based runtime IT to flag repeated SELECT statement shapes above a threshold. Runs last and documents the threshold as a regression tripwire rather than a precise count.

archetype/src/main/resources/archetype-resources/src/test/java/runtime/RepeatedStatementAuditIT.java

UnusedIndexAuditIT.javaNew archetype IT for unused indexes (PostgreSQL-only plan audit) +48/-0

New archetype IT for unused indexes (PostgreSQL-only plan audit)

• Adds a PostgreSQL-only plan-based runtime IT asserting every index is used by at least one captured statement plan. Includes schema wiring and an exclusion hook with guidance to validate via production stats.

archetype/src/main/resources/archetype-resources/src/test/java/runtime/UnusedIndexAuditIT.java

db.changelog-master.xmlAdd version columns to archetype demo schema +6/-0

Add version columns to archetype demo schema

• Extends the demo Liquibase changelog to add NOT NULL INT version columns on parent and child tables with default 0. Aligns the generated schema with the new @Version mapping expectations.

archetype/src/main/resources/archetype-resources/src/test/resources/db/changelog/db.changelog-master.xml

FixRendererTest.javaAdd FixRenderer coverage for all new Finding types +250/-0

Add FixRenderer coverage for all new Finding types

• Adds a comprehensive test suite validating fix fidelity and rendered content for each new Finding type, including Liquibase XML expectations for duplicate FK drops. Ensures template fixes degrade to comments for changeSet rendering and that advisory comments avoid invalid XML content.

integration/src/test/java/io/github/databaseaudits/spring/boot/report/FixRendererTest.java

Documentation (3) +100 / -7
audits.adocDocument new audits across catalog/JPA/runtime families +43/-4

Document new audits across catalog/JPA/runtime families

• Expands the audit roster tables to include PrimaryKeyType, DuplicateForeignKey, UniqueIndexNotNull, UnmappedDatabaseObject, MissingVersionAttribute, EagerCollectionFetch, OffsetPagination, RepeatedStatement, and UnusedIndex. Updates headings and clarifies token-scan audits as cross-platform.

integration/src/site/asciidoc/audits.adoc

exclusions.adocAdd new exclusion builder options and guidance +53/-0

Add new exclusion builder options and guidance

• Updates examples and reference tables to include exclusions for all new audits, including repeated-statement threshold and SQL fragment lists. Adds notes on explicitly excluding Liquibase bookkeeping objects for PK-type and unmapped-object audits.

integration/src/site/asciidoc/exclusions.adoc

usage.adocClarify runtime audit families and platform applicability +4/-3

Clarify runtime audit families and platform applicability

• Updates runtime audit documentation to include UnusedIndexAudit among PostgreSQL-only plan-based audits and OffsetPagination/RepeatedStatement among cross-platform token-scan audits. Improves conceptual grouping to match the new roster.

integration/src/site/asciidoc/usage.adoc

Other (2) +6 / -4
archetype-post-generate.groovyTreat UnusedIndexAuditIT as PostgreSQL-only in archetype cleanup +5/-3

Treat UnusedIndexAuditIT as PostgreSQL-only in archetype cleanup

• Updates the post-generate script comments and deletion list to include UnusedIndexAuditIT among PostgreSQL-only plan-based runtime audits. Ensures non-PostgreSQL archetype generations remove the new IT alongside Join/OrderBy/WhereClause plan audits.

archetype/src/main/resources/META-INF/archetype-post-generate.groovy

pom.xmlBump database-audits-core to 3.0.1-SNAPSHOT +1/-1

Bump database-audits-core to 3.0.1-SNAPSHOT

• Updates the integration module's core dependency version to consume the new audits and sealed Finding types. Keeps integration wiring in lockstep with core additions.

integration/pom.xml

@qodo-code-review

qodo-code-review Bot commented Jul 8, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 35 rules

Grey Divider


Action required

1. Test method name lacks underscores 📘 Rule violation ▣ Testability
Description
New test methods (e.g., testNoDuplicateForeignKeyConstraints) do not match the required naming
pattern with exactly two underscores separating state and outcome segments. This violates the
enforced descriptive test method naming convention.
Code

archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[42]

+    void testNoDuplicateForeignKeyConstraints() {
Evidence
PR Compliance ID 1492971 requires test method names to include two underscores separating
behavior/state/outcome segments; the newly added methods use single-segment names without
underscores.

Rule 1492971: Enforce descriptive test method naming pattern
archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[42-43]
archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java[40-41]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New test method names do not follow the required pattern `^test[A-Z][A-Za-z0-9]*_[A-Za-z0-9]+_[A-Za-z0-9]+$`.

## Issue Context
The archetype adds multiple new `*AuditIT` templates whose test methods are named without the required state/outcome underscore segments.

## Fix Focus Areas
- archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[42-44]
- archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java[40-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Spring imports in archetype ITs 📘 Rule violation § Compliance
Description
New archetype-generated integration test templates import Spring types (e.g., @Autowired,
@Value), which violates the rule restricting archetype-generated code imports to only JUnit,
java.*/javax.*, and database-audits namespaces. This increases third-party coupling in generated
projects and breaks the stated dependency constraints.
Code

archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[R8-11]

+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
Evidence
PR Compliance ID 1493006 disallows third-party imports such as Spring in archetype-generated
classes. The added archetype templates explicitly import
org.springframework.beans.factory.annotation.Autowired/Value.

Rule 1493006: Archetype-generated classes restrict dependencies to JUnit and database-audits
archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[8-11]
archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java[9-11]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Archetype-generated test templates import Spring classes (`org.springframework.*`), but the compliance rule allows only JUnit + database-audits (plus `java.*`/`javax.*`) in generated classes.

## Issue Context
This affects newly-added archetype test templates and makes generated projects depend on disallowed third-party packages.

## Fix Focus Areas
- archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[8-11]
- archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java[9-11]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Unvalidated repeated threshold 🐞 Bug ☼ Reliability
Description
DatabaseAuditExcludes.Builder.repeatedStatementThreshold() and RepeatedStatementAuditAssertion
document that the threshold “must be at least 2” but do not enforce it. This allows invalid
configuration (0/1) that violates the API contract and can make the audit behavior
nonsensical/noisy.
Code

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java[R383-396]

+        /**
+         * Sets the minimum capture count (inclusive) for a SELECT shape to be
+         * reported by the repeated-statement (N+1) audit; must be at least 2.
+         * Defaults to {@value #DEFAULT_REPEATED_STATEMENT_THRESHOLD}, a
+         * generous regression tripwire rather than a precise count.
+         *
+         * @param threshold
+         *                      the minimum capture count.
+         * @return this builder.
+         */
+        public Builder repeatedStatementThreshold(final int threshold) {
+            this.repeatedStatementThreshold = threshold;
+            return this;
+        }
Evidence
Both the excludes builder and the assertion methods explicitly claim a minimum threshold of 2, but
neither validates inputs and both pass them through directly.

integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java[383-396]
integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RepeatedStatementAuditAssertion.java[36-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The public API states `repeatedStatementThreshold` must be at least 2, but both the excludes builder and the assertion entry points accept any integer. This creates a contract mismatch and allows misconfiguration.

### Issue Context
- The Javadoc for both the excludes builder and the assertion methods explicitly says the threshold must be >= 2.
- The current implementation simply assigns/forwards the value.

### Fix Focus Areas
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java[383-396]
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RepeatedStatementAuditAssertion.java[36-65]

### Acceptance criteria
- Reject thresholds < 2 with a clear `IllegalArgumentException` (or clamp to 2, but then update docs accordingly).
- Add a small unit test (new test class is fine) proving the validation behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Wrong FK drop DDL ✓ Resolved 🐞 Bug ≡ Correctness
Description
FixRenderer renders duplicate-FK remediation using ALTER TABLE ... DROP CONSTRAINT ...
regardless of database platform, which is incorrect for MySQL/MariaDB. This yields misleading/broken
fix output for supported non-PostgreSQL users who copy/paste the rendered DDL.
Code

integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java[R247-252]

+    private static String dropDuplicateConstraintsDdl(
+            final DuplicateForeignKeyFinding finding) {
+        return finding.constraints().stream().skip(1)
+                .map(constraint -> "ALTER TABLE " + finding.table()
+                        + " DROP CONSTRAINT " + constraint + ";")
+                .collect(Collectors.joining("\n"));
Evidence
The suite is explicitly intended to support MySQL/MariaDB by omitting PostgreSQL-only plan audits,
but the new duplicate-FK fix generator emits PostgreSQL-only DDL and does not use the platform
branching that exists elsewhere in FixRenderer.

integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.java[68-73]
integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.java[171-176]
integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java[69-105]
integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java[243-253]
integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java[294-328]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`FixRenderer.dropDuplicateConstraintsDdl(...)` hardcodes PostgreSQL-style `DROP CONSTRAINT` for duplicate foreign keys. The integration suite is designed to run on MySQL/MariaDB as well, so the rendered fix DDL must either:
- emit the correct dialect per platform (e.g., `DROP FOREIGN KEY` on MySQL/MariaDB), or
- degrade to advisory output / prefer Liquibase change output for non-PostgreSQL.

### Issue Context
- The facade and suite explicitly aim to “stay clean on MySQL/MariaDB” by omitting PostgreSQL-only audits.
- `FixRenderer` already contains platform branching helpers (`isMysqlFamily`, `dropIndex`, etc.), but the new duplicate-FK remediation ignores `platform` entirely.

### Fix Focus Areas
- integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java[69-143]
- integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java[243-263]
- integration/src/test/java/io/github/databaseaudits/spring/boot/report/FixRendererTest.java[315-338]

### Acceptance criteria
- `fixFor(DuplicateForeignKeyFinding, MYSQL|MARIADB)` produces valid MySQL/MariaDB DDL (or is explicitly downgraded to advisory/commentary).
- Add/adjust unit tests to cover at least one MySQL-family expectation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +8 to +11
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Spring imports in archetype its 📘 Rule violation § Compliance

New archetype-generated integration test templates import Spring types (e.g., @Autowired,
@Value), which violates the rule restricting archetype-generated code imports to only JUnit,
java.*/javax.*, and database-audits namespaces. This increases third-party coupling in generated
projects and breaks the stated dependency constraints.
Agent Prompt
## Issue description
Archetype-generated test templates import Spring classes (`org.springframework.*`), but the compliance rule allows only JUnit + database-audits (plus `java.*`/`javax.*`) in generated classes.

## Issue Context
This affects newly-added archetype test templates and makes generated projects depend on disallowed third-party packages.

## Fix Focus Areas
- archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[8-11]
- archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java[9-11]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

#if($disabledTests == 'true')
@Disabled("Generated as disabled; remove @Disabled to enable")
#end
void testNoDuplicateForeignKeyConstraints() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Test method name lacks underscores 📘 Rule violation ▣ Testability

New test methods (e.g., testNoDuplicateForeignKeyConstraints) do not match the required naming
pattern with exactly two underscores separating state and outcome segments. This violates the
enforced descriptive test method naming convention.
Agent Prompt
## Issue description
New test method names do not follow the required pattern `^test[A-Z][A-Za-z0-9]*_[A-Za-z0-9]+_[A-Za-z0-9]+$`.

## Issue Context
The archetype adds multiple new `*AuditIT` templates whose test methods are named without the required state/outcome underscore segments.

## Fix Focus Areas
- archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java[42-44]
- archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java[40-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +383 to +396
/**
* Sets the minimum capture count (inclusive) for a SELECT shape to be
* reported by the repeated-statement (N+1) audit; must be at least 2.
* Defaults to {@value #DEFAULT_REPEATED_STATEMENT_THRESHOLD}, a
* generous regression tripwire rather than a precise count.
*
* @param threshold
* the minimum capture count.
* @return this builder.
*/
public Builder repeatedStatementThreshold(final int threshold) {
this.repeatedStatementThreshold = threshold;
return this;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. Unvalidated repeated threshold 🐞 Bug ☼ Reliability

DatabaseAuditExcludes.Builder.repeatedStatementThreshold() and RepeatedStatementAuditAssertion
document that the threshold “must be at least 2” but do not enforce it. This allows invalid
configuration (0/1) that violates the API contract and can make the audit behavior
nonsensical/noisy.
Agent Prompt
### Issue description
The public API states `repeatedStatementThreshold` must be at least 2, but both the excludes builder and the assertion entry points accept any integer. This creates a contract mismatch and allows misconfiguration.

### Issue Context
- The Javadoc for both the excludes builder and the assertion methods explicitly says the threshold must be >= 2.
- The current implementation simply assigns/forwards the value.

### Fix Focus Areas
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java[383-396]
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RepeatedStatementAuditAssertion.java[36-65]

### Acceptance criteria
- Reject thresholds < 2 with a clear `IllegalArgumentException` (or clamp to 2, but then update docs accordingly).
- Add a small unit test (new test class is fine) proving the validation behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@jeffjensen

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java`:
- Around line 383-396: The repeatedStatementThreshold setter in Builder
currently accepts any int even though its Javadoc says the minimum is 2; update
this method to validate the input and fail fast for values below 2 with a clear
error message. Keep the change localized to repeatedStatementThreshold in
DatabaseAuditExcludes.Builder, and preserve the existing assignment/return flow
for valid values.

In
`@integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java`:
- Around line 100-101: The PRECISE fix for DuplicateForeignKeyFinding in
FixRenderer currently always uses dropDuplicateConstraintsDdl(), which emits
DROP CONSTRAINT even for MariaDB. Update FixRenderer and
dropDuplicateConstraintsDdl() to accept platform context and branch by database
family so MySQL 8.0.19+ keeps DROP CONSTRAINT while MariaDB emits DROP FOREIGN
KEY. Use the existing platform value passed into the renderer and the
DuplicateForeignKeyFinding case to route to the correct DDL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0606402a-7207-47fc-a35f-b9e23842fdb3

📥 Commits

Reviewing files that changed from the base of the PR and between 1c76f58 and a48aa98.

📒 Files selected for processing (30)
  • archetype/src/main/resources/META-INF/archetype-post-generate.groovy
  • archetype/src/main/resources/archetype-resources/src/test/java/app/Child.java
  • archetype/src/main/resources/archetype-resources/src/test/java/app/Parent.java
  • archetype/src/main/resources/archetype-resources/src/test/java/catalog/DuplicateForeignKeyAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/catalog/PrimaryKeyTypeAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/catalog/UniqueIndexNotNullAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/jpa/EagerCollectionFetchAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/jpa/MissingVersionAttributeAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/jpa/UnmappedDatabaseObjectAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/runtime/OffsetPaginationAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/runtime/RepeatedStatementAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/java/runtime/UnusedIndexAuditIT.java
  • archetype/src/main/resources/archetype-resources/src/test/resources/db/changelog/db.changelog-master.xml
  • integration/pom.xml
  • integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DuplicateForeignKeyAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/EagerCollectionFetchAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/MissingVersionAttributeAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/OffsetPaginationAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/PrimaryKeyTypeAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RepeatedStatementAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UniqueIndexNotNullAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnmappedDatabaseObjectAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnusedIndexAuditAssertion.java
  • integration/src/main/java/io/github/databaseaudits/spring/boot/report/FixRenderer.java
  • integration/src/site/asciidoc/audits.adoc
  • integration/src/site/asciidoc/exclusions.adoc
  • integration/src/site/asciidoc/usage.adoc
  • integration/src/test/java/io/github/databaseaudits/spring/boot/report/FixRendererTest.java

…g types

Finding is sealed, so FixRenderer's two exhaustive switches (fixFor,
liquibaseChangeSet) failed to compile the moment core's SNAPSHOT
carried DuplicateForeignKeyFinding, NarrowPrimaryKeyFinding,
UniqueIndexNullableColumnFinding, OffsetPaginationFinding,
RepeatedStatementFinding, MissingVersionAttributeFinding,
EagerCollectionFetchFinding, UnmappedTableFinding/UnmappedColumnFinding,
and UnusedIndexFinding - the intended signal to add a case for each.

Only DuplicateForeignKeyFinding is PRECISE (drop every duplicate
constraint but the first, via a real dropForeignKeyConstraint
changeset); NarrowPrimaryKeyFinding and UnusedIndexFinding are
TEMPLATE (concrete DDL but a human must complete a TODO first - widen
referencing FKs, or confirm against production pg_stat_user_indexes);
the rest are ADVISORY (a mapping or code change, no DDL to emit).
Bundled with this since one audit alone can't compile against the
sealed type - the whole roster of new findings had to land together.
Adds a *AuditAssertion for each new core audit (DuplicateForeignKey,
PrimaryKeyType, UniqueIndexNotNull in the catalog family;
EagerCollectionFetch, MissingVersionAttribute, UnmappedDatabaseObject
in the JPA family; OffsetPagination, RepeatedStatement, UnusedIndex in
the runtime family - the last one PostgreSQL-only alongside
Join/OrderBy/WhereClause) and wires each into DatabaseAuditSuite's
roster in family order, plus a matching DatabaseAuditExcludes
field/builder method for each (RepeatedStatementAudit also gets a
repeatedStatementThreshold, defaulting to a generous 50 as a
regression tripwire rather than a precise N+1 count).

DatabaseAuditSuite now also constructs a ForeignKeyCatalog collaborator
alongside the existing IndexCatalog, needed by DuplicateForeignKeyAudit
and UnusedIndexAudit. The roster's List.of(...) needed an explicit
<AuditAssertion> type witness - without it javac's common-supertype
inference across nine assertion types picked the package-private
AbstractAuditAssertion instead of the public AuditAssertion interface,
which fails to compile from a different package.

The roster-guard test (testSuiteAll_WiresAnAssertionForEveryCoreAudit)
now passes again: every core *Audit has a wired *AuditAssertion.
One <Audit>AuditIT template per new audit, under its family directory
(catalog/jpa/runtime), following the existing pattern: extends
AbstractDatabaseAuditIT (or the user's parentClass), @Autowired the
assertion bean, and demonstrate the exclusion constant. UnusedIndexAuditIT
is plan-based (PostgreSQL-only), so it joins Join/OrderBy/WhereClause in
archetype-post-generate.groovy's deletion list for non-PostgreSQL engines.

Fixing the demo schema to pass all three new catalog/JPA audits cleanly
surfaced two real gaps:
* Liquibase's own bookkeeping tables (databasechangelog,
  databasechangeloglock) are unmapped by design, and
  databasechangeloglock's PK is a narrow INT - both genuine findings
  PrimaryKeyTypeAuditIT and UnmappedDatabaseObjectAuditIT now exclude,
  the same way PrimaryKeyPresenceAuditAssertion already special-cases
  them for the presence audit.
* The demo's Parent/Child entities had no @Version attribute. Rather
  than excluding them, added a genuine version column (Liquibase +
  entity + getter) to both, since a versioned entity is worth
  demonstrating rather than suppressing - Spring Data's save() handles
  it transparently, so RepositoryWorkloadIT needed no change.

Full reactor `clean install` (which drives archetype:integration-test
against Testcontainers PostgreSQL/MySQL) is green: 20/20 in the full
and targeted-datasource projects, 16/16 in full-mysql.
Adds each new audit's row to audits.adoc's per-family tables
(DuplicateForeignKey/PrimaryKeyType/UniqueIndexNotNull in catalog;
EagerCollectionFetch/MissingVersionAttribute/UnmappedDatabaseObject in
JPA, renaming the "JPA audit" heading to plural; OffsetPagination/
RepeatedStatement/UnusedIndex in runtime, splitting the "token-scan"
heading to plural and fixing usage.adoc's stale plan-based/token-scan
audit lists) and each new DatabaseAuditExcludes builder method to
exclusions.adoc's per-family reference tables, noting that
PrimaryKeyTypeAuditAssertion and UnmappedDatabaseObjectAuditAssertion -
unlike PrimaryKeyPresenceAuditAssertion - do not auto-exclude the
Liquibase bookkeeping tables.
@jeffjensen jeffjensen merged commit 456f180 into main Jul 8, 2026
5 checks passed
@jeffjensen jeffjensen deleted the feat/more-audits branch July 8, 2026 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant