Skip to content

fix(server): add CHECK constraint on practice_finding.target_type - #953

Merged
FelixTJDietrich merged 4 commits into
mainfrom
fix/issue-930-practice-finding-target-type-constraint
Mar 26, 2026
Merged

fix(server): add CHECK constraint on practice_finding.target_type#953
FelixTJDietrich merged 4 commits into
mainfrom
fix/issue-930-practice-finding-target-type-constraint

Conversation

@FelixTJDietrich

@FelixTJDietrich FelixTJDietrich commented Mar 26, 2026

Copy link
Copy Markdown
Collaborator

Description

Closes the gap identified in PE Audit #4: practice_finding.target_type (VARCHAR(32)) had no CHECK constraint, despite every other enum-like column on the same table (verdict, severity, guidance_method, action) having one. The only production value is "pull_request", hardcoded as a raw string — meaning a casing typo or unknown value would silently create invisible findings.

This PR:

  • Introduces PracticeFindingTargetType enum using bare @Enumerated(EnumType.STRING), consistent with Verdict, Severity, and CaMethod on the same entity (no @Convert, no @JsonValue, no AttributeConverter — the simplest pattern already used by 20+ enums in the codebase).
  • Adds a two-step Liquibase migration: (1) normalises existing 'pull_request' rows to 'PULL_REQUEST' with a precondition guard that HALTs if unexpected values exist, (2) adds CHECK (target_type IN ('PULL_REQUEST')).
  • Types targetType as enum throughout: entity field, DTOs, event record, repository JPQL query (parameterised instead of hardcoded string), delivery service, and all tests.
  • Regenerates OpenAPI spec and webapp TypeScript types (targetType: 'PULL_REQUEST' literal type).

Files changed (17)

Area Files What
Enum PracticeFindingTargetType.java (new) Bare enum, single PULL_REQUEST constant
Migration 1774700000000_changelog.xml (new), master.xml Data normalisation + CHECK constraint
Entity PracticeFinding.java String@Enumerated(STRING) PracticeFindingTargetType
Service PracticeDetectionDeliveryService.java, PracticeFindingService.java Use enum .name() for native queries, enum constant for JPQL
DTOs/Events PracticeFindingDetailDTO, PracticeFindingListDTO, PracticeDetectionCompletedEvent String → enum
Repository PracticeFindingRepository.java Parameterised findByPullRequestAndWorkspace query
Generated openapi.yaml, types.gen.ts enum: [PULL_REQUEST]
Tests 5 test files All native SQL and assertions updated to PULL_REQUEST

Migration details

Changeset 1774700000000-1: Precondition + data migration
  - HALT if any target_type NOT IN ('pull_request', 'PULL_REQUEST')
  - UPDATE pull_request → PULL_REQUEST
  
Changeset 1774700000000-2: CHECK constraint
  - ADD CONSTRAINT chk_practice_finding_target_type CHECK (target_type IN ('PULL_REQUEST'))

Safe deployment order: deploy code first (writes PULL_REQUEST via enum), then run migration (normalises old data, adds constraint).

API change

targetType in PracticeFindingList and PracticeFindingDetail responses changes from free-form string to enum: ["PULL_REQUEST"]. This is intentionally breaking — the field was already de-facto enum-like with a single value, and is now properly constrained. Consistent with how verdict, severity, and guidanceMethod are already returned as UPPER_CASE enum strings.

Fixes #930

How to test

  1. Unit tests pass: mvn test -Dsurefire.includedGroups="unit"
  2. Architecture tests pass: mvn test -Dsurefire.includedGroups="architecture" (112 tests)
  3. Integration tests pass: all 63 integration tests for affected areas (PracticeFindingRepository, DeliveryService, Controller, FeedbackController)
  4. OpenAPI sync: npm run generate:api produces no diff
  5. Migration on empty DB: Liquibase applies cleanly (precondition passes, no rows to update)
  6. Migration on production DB: normalises existing pull_requestPULL_REQUEST, then constrains

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Refactor

    • Standardized the targetType field to use uppercase format (PULL_REQUEST) across API responses and database storage.
    • Added validation to restrict targetType to supported values at the database level for improved data integrity.
  • Chores

    • Applied database migration to normalize existing data values to the new uppercase format.

Closes the gap from PE Audit #4: every other enum-like column on
practice_finding has a CHECK constraint except target_type.

- Add PracticeFindingTargetType enum with @Enumerated(STRING), matching
  the Verdict/Severity/CaMethod pattern used across the entity
- Liquibase migration: normalise existing 'pull_request' rows to
  'PULL_REQUEST', then add CHECK constraint with precondition guard
- Type the targetType field as enum throughout: entity, DTOs, event
  record, repository queries, and delivery service
- Regenerate OpenAPI spec and webapp TypeScript types

Closes #930

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 26, 2026 21:55
@FelixTJDietrich
FelixTJDietrich requested a review from a team as a code owner March 26, 2026 21:55
@coderabbitai

coderabbitai Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@FelixTJDietrich has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 11 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b6bedba6-2fcb-49c7-9fee-548b274716e4

📥 Commits

Reviewing files that changed from the base of the PR and between 9d0e9ad and 74e6be4.

📒 Files selected for processing (2)
  • server/application-server/src/main/resources/db/changelog/1774563725885_changelog.xml
  • server/application-server/src/main/resources/db/master.xml
📝 Walkthrough

Walkthrough

This pull request introduces type safety for the targetType field by converting it from untyped strings to a strongly-typed PracticeFindingTargetType enum. It normalizes existing data to uppercase, adds a database CHECK constraint to enforce valid values, and updates all related code layers accordingly.

Changes

Cohort / File(s) Summary
Type Definition & JPA Mapping
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFindingTargetType.java, server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFinding.java
New enum created with PULL_REQUEST constant; PracticeFinding.targetType field converted from String to enum with @Enumerated(EnumType.STRING) mapping.
Data Transfer Objects
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingDetailDTO.java, server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingListDTO.java
targetType field type changed from String to PracticeFindingTargetType; schema metadata updated to reference uppercase enum constant.
Domain Events
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeDetectionCompletedEvent.java
targetType record field converted from String to PracticeFindingTargetType; Javadoc example updated.
Service & Repository Layer
server/application-server/src/main/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryService.java, server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepository.java, server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingService.java
Repository query updated to use named parameter :targetType; method signatures updated to accept enum value; hardcoded string replaced with targetType.name() in idempotency key construction.
OpenAPI Schema
server/application-server/openapi.yaml
targetType descriptions in PracticeFindingDetail and PracticeFindingList updated with uppercase example and enum constraint restricting to ["PULL_REQUEST"].
Database Migrations
server/application-server/src/main/resources/db/changelog/1774700000000_changelog.xml, server/application-server/src/main/resources/db/master.xml
New Liquibase changelog normalizes existing pull_request values to PULL_REQUEST; adds CHECK constraint chk_practice_finding_target_type restricting values to 'PULL_REQUEST'; master changelog updated to include new migration.
Frontend Type Definitions
webapp/src/api/types.gen.ts, server/intelligence-service/src/shared/db/schema.ts
TypeScript types for PracticeFindingList.targetType and PracticeFindingDetail.targetType narrowed from generic string to string literal 'PULL_REQUEST'; database schema constraint added.
Test Updates
server/application-server/src/test/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryServiceTest.java, server/application-server/src/test/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryServiceIntegrationTest.java, server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepositoryIntegrationTest.java, server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java, server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/feedback/FindingFeedbackControllerIntegrationTest.java
Test assertions and setup updated from lowercase "pull_request" to uppercase "PULL_REQUEST"; enum constant expectations added where applicable; new TargetTypeTests nested class added for enum round-trip validation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Through the codebase, one rabbit did bound,
Where strings became enums, type-safety found!
PULL_REQUEST in capitals, shining so bright,
With constraints in place, the data sits tight.
No more ambiguous values to hide,
Strong typing now guards every practice inside!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive The PR includes changes beyond the minimal scope in issue #930 (which requested only a Liquibase changeset) by introducing enum typing and refactoring throughout codebase, though these changes support the core objective. While enum typing strengthens type safety and supports the constraint, verify that these extensions align with team standards and architectural patterns rather than introducing unnecessary refactoring.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: adding a CHECK constraint to practice_finding.target_type, which is the primary objective of the PR.
Linked Issues check ✅ Passed The PR fully implements issue #930 requirements: adds CHECK constraint on practice_finding.target_type, adds enum typing throughout codebase, and includes verification steps.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-930-practice-finding-target-type-constraint

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 and usage tips.

@github-actions github-actions Bot added bug Something isn't working application-server Spring Boot server: APIs, business logic, database webapp React app: UI components, routes, state management labels Mar 26, 2026
@github-actions github-actions Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a first-class enum + database constraint for practice_finding.target_type to prevent invalid/casing-typo values and align the column with the other enum-like fields on practice_finding.

Changes:

  • Introduces PracticeFindingTargetType and switches PracticeFinding.targetType from String to @Enumerated(EnumType.STRING).
  • Adds a Liquibase changelog to normalize existing target_type values and add a CHECK constraint.
  • Updates repository/service/event/DTO layers plus OpenAPI + generated webapp types and test fixtures to use PULL_REQUEST.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
webapp/src/api/types.gen.ts Updates generated TS types so targetType is the 'PULL_REQUEST' literal.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/feedback/FindingFeedbackControllerIntegrationTest.java Updates test setup to use PracticeFindingTargetType.PULL_REQUEST.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepositoryIntegrationTest.java Updates inserts/assertions to PULL_REQUEST and adds an enum mapping test.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java Updates controller integration tests to expect PULL_REQUEST.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryServiceTest.java Updates unit test expectations for idempotency key and event typing.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryServiceIntegrationTest.java Updates integration test assertions for enum-typed event field.
server/application-server/src/main/resources/db/master.xml Includes the new Liquibase changelog in the master list.
server/application-server/src/main/resources/db/changelog/1774700000000_changelog.xml Normalizes target_type values and adds chk_practice_finding_target_type.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFindingTargetType.java Adds the new enum with PULL_REQUEST.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFinding.java Changes targetType to an @Enumerated enum field.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingListDTO.java Changes DTO field type from String to PracticeFindingTargetType.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingDetailDTO.java Changes DTO field type from String to PracticeFindingTargetType.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingService.java Uses enum constant when querying PR findings.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepository.java Parameterizes PR findings query by enum target type.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeDetectionCompletedEvent.java Changes event field type from String to PracticeFindingTargetType.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryService.java Uses enum for target type and writes .name() to DB/idempotency key.
server/application-server/openapi.yaml Updates OpenAPI schema to constrain targetType to enum [PULL_REQUEST].

// Build idempotency key — index disambiguates multiple findings for the same practice
String idempotencyKey =
finding.practiceSlug() + ":" + targetType + ":" + targetId + ":" + job.getId() + ":" + i;
finding.practiceSlug() + ":" + targetType.name() + ":" + targetId + ":" + job.getId() + ":" + i;

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

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

Changing the idempotency key to include targetType.name() (now PULL_REQUEST instead of the previous pull_request) breaks cross-version idempotency: if a job delivery is retried after a deployment/rollback, inserts will use a different idempotency_key and bypass the unique constraint, creating duplicate findings. Consider keeping the idempotency key format stable (e.g., continue using the legacy lowercase token) or add a migration step that rewrites existing practice_finding.idempotency_key values to the new format in lockstep with the target_type normalisation.

Suggested change
finding.practiceSlug() + ":" + targetType.name() + ":" + targetId + ":" + job.getId() + ":" + i;
finding.practiceSlug()
+ ":"
+ targetType.name().toLowerCase()
+ ":"
+ targetId
+ ":"
+ job.getId()
+ ":"
+ i;

Copilot uses AI. Check for mistakes.
Comment on lines +185 to +192
WHERE f.targetType = :targetType
AND f.targetId = :pullRequestId
AND p.workspace.id = :workspaceId
ORDER BY f.detectedAt DESC
"""
)
List<PracticeFinding> findByPullRequestAndWorkspace(
@Param("targetType") PracticeFindingTargetType targetType,

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

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

findByPullRequestAndWorkspace is PR-specific by name, but now takes a generic targetType parameter. This makes the API easy to misuse and forces callers to pass a redundant constant. Prefer hardcoding the enum in JPQL (e.g., compare to the PracticeFindingTargetType.PULL_REQUEST enum constant) and drop the parameter, or rename the method/query to reflect the generalized signature (e.g., findByTargetTypeAndTargetIdAndWorkspace).

Suggested change
WHERE f.targetType = :targetType
AND f.targetId = :pullRequestId
AND p.workspace.id = :workspaceId
ORDER BY f.detectedAt DESC
"""
)
List<PracticeFinding> findByPullRequestAndWorkspace(
@Param("targetType") PracticeFindingTargetType targetType,
WHERE f.targetType = de.tum.in.www1.hephaestus.practices.model.PracticeFindingTargetType.PULL_REQUEST
AND f.targetId = :pullRequestId
AND p.workspace.id = :workspaceId
ORDER BY f.detectedAt DESC
"""
)
List<PracticeFinding> findByPullRequestAndWorkspace(

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +31
<rollback>
UPDATE practice_finding SET target_type = 'pull_request' WHERE target_type = 'PULL_REQUEST';
</rollback>

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

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

The rollback for changeSet 1774700000000-1 will downcase all PULL_REQUEST rows back to pull_request, including rows inserted after this migration runs (by the new enum-based code). If rollbacks are ever executed, this can corrupt data; consider removing this rollback or constraining it to only rows updated by this changeset.

Suggested change
<rollback>
UPDATE practice_finding SET target_type = 'pull_request' WHERE target_type = 'PULL_REQUEST';
</rollback>

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +39
<!-- Step 2: CHECK constraint on practice_finding.target_type -->
<changeSet author="practice-target-type-constraint" id="1774700000000-2">
<sql>
ALTER TABLE practice_finding
ADD CONSTRAINT chk_practice_finding_target_type
CHECK (target_type IN ('PULL_REQUEST'));

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

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

These two changeSets aren’t compatible with a rolling/zero-downtime deploy: code needs the data normalized to PULL_REQUEST to read rows, but the CHECK constraint will reject pull_request for any still-running old writers. Consider an intermediate migration (e.g., allow both values in the CHECK constraint first, then tighten to only PULL_REQUEST in a later release once all instances write the new value).

Suggested change
<!-- Step 2: CHECK constraint on practice_finding.target_type -->
<changeSet author="practice-target-type-constraint" id="1774700000000-2">
<sql>
ALTER TABLE practice_finding
ADD CONSTRAINT chk_practice_finding_target_type
CHECK (target_type IN ('PULL_REQUEST'));
<!-- Step 2: CHECK constraint on practice_finding.target_type (allow legacy and normalized values) -->
<changeSet author="practice-target-type-constraint" id="1774700000000-2">
<sql>
ALTER TABLE practice_finding
ADD CONSTRAINT chk_practice_finding_target_type
CHECK (target_type IN ('pull_request', 'PULL_REQUEST'));

Copilot uses AI. Check for mistakes.
Comment on lines 96 to +99
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "target_type", length = 32, nullable = false)
private String targetType;
private PracticeFindingTargetType targetType;

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

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

Switching targetType to @Enumerated(EnumType.STRING) will cause Hibernate to throw when reading any existing practice_finding.target_type rows still stored as pull_request (lowercase). This also makes existing rows invisible to JPQL filters comparing against PULL_REQUEST. To avoid a production outage, either run a data-normalisation migration (at least changeSet -1) before deploying this code, or make the mapping temporarily tolerant (e.g., an AttributeConverter that maps both pull_request and PULL_REQUEST) until after the migration has been applied everywhere.

Copilot uses AI. Check for mistakes.
The intelligence-service Drizzle schema must include the new
chk_practice_finding_target_type constraint added by the migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added the intelligence-service TypeScript AI service: LLM orchestration, mentor chat label Mar 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFinding.java (1)

97-99: Consider typing the targetType parameter in PracticeFindingRepository.insertIfAbsent() as PracticeFindingTargetType instead of String.

The entity field is properly typed with @Enumerated(EnumType.STRING), but the native query method signature still accepts String targetType, allowing invalid values to bypass compile-time type checking. Changing the parameter to PracticeFindingTargetType would enforce enum validation at the call site and prevent accidental typos in targetType values.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFinding.java`
around lines 97 - 99, Change the insertIfAbsent method signature in
PracticeFindingRepository to accept PracticeFindingTargetType instead of String
(i.e., replace the String targetType parameter with PracticeFindingTargetType
targetType) so callers get compile-time enum checking; inside the repository
implementation or native query binding, convert the enum to its String
representation (e.g., targetType.name() or targetType.toString()) when binding
to the database column that uses `@Enumerated`(EnumType.STRING) on the
PracticeFinding.targetType field, and update any `@Param` or query parameter names
accordingly.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepositoryIntegrationTest.java (1)

619-644: Add a negative-path assertion for the new target_type CHECK constraint.

Line 620 currently validates only the happy-path enum round-trip. Please also assert that a non-canonical value (e.g. pull_request) is rejected, so constraint behavior is covered by integration tests.

✅ Suggested test addition
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import org.springframework.dao.DataIntegrityViolationException;
...
     `@Nested`
     `@DisplayName`("target_type enum mapping")
     class TargetTypeTests {
@@
         void enumRoundTrip() {
@@
             PracticeFinding found = practiceFindingRepository.findById(id).orElseThrow();
             assertThat(found.getTargetType()).isEqualTo(PracticeFindingTargetType.PULL_REQUEST);
         }
+
+        `@Test`
+        `@DisplayName`("rejects non-canonical target_type values")
+        void shouldRejectLowercaseTargetTypeWhenConstraintApplied() {
+            assertThatThrownBy(() ->
+                practiceFindingRepository.insertIfAbsent(
+                    UUID.randomUUID(),
+                    "tt-invalid",
+                    agentJob.getId(),
+                    practice.getId(),
+                    "pull_request",
+                    1L,
+                    contributor.getId(),
+                    "Invalid target type",
+                    "POSITIVE",
+                    "INFO",
+                    0.9f,
+                    null,
+                    null,
+                    null,
+                    null,
+                    Instant.now()
+                )
+            ).isInstanceOf(DataIntegrityViolationException.class);
+        }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepositoryIntegrationTest.java`
around lines 619 - 644, Add a negative-path assertion to
PracticeFindingRepositoryIntegrationTest (near the enumRoundTrip test) that
verifies the new target_type CHECK rejects non-canonical values: attempt to call
practiceFindingRepository.insertIfAbsent with the same parameters but using a
lowercase string like "pull_request" for the targetType, and assert that the
insertion throws the appropriate exception (e.g., SQLException /
DataAccessException / ConstraintViolation) instead of succeeding; ensure the
test asserts absence of a persisted entity for that id and that the exception
message or type indicates the CHECK constraint violation so the constraint
behavior is covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFinding.java`:
- Around line 97-99: Change the insertIfAbsent method signature in
PracticeFindingRepository to accept PracticeFindingTargetType instead of String
(i.e., replace the String targetType parameter with PracticeFindingTargetType
targetType) so callers get compile-time enum checking; inside the repository
implementation or native query binding, convert the enum to its String
representation (e.g., targetType.name() or targetType.toString()) when binding
to the database column that uses `@Enumerated`(EnumType.STRING) on the
PracticeFinding.targetType field, and update any `@Param` or query parameter names
accordingly.

In
`@server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepositoryIntegrationTest.java`:
- Around line 619-644: Add a negative-path assertion to
PracticeFindingRepositoryIntegrationTest (near the enumRoundTrip test) that
verifies the new target_type CHECK rejects non-canonical values: attempt to call
practiceFindingRepository.insertIfAbsent with the same parameters but using a
lowercase string like "pull_request" for the targetType, and assert that the
insertion throws the appropriate exception (e.g., SQLException /
DataAccessException / ConstraintViolation) instead of succeeding; ensure the
test asserts absence of a persisted entity for that id and that the exception
message or type indicates the CHECK constraint violation so the constraint
behavior is covered.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7bc68ab8-e3c3-4117-9eba-3bc4d94f3671

📥 Commits

Reviewing files that changed from the base of the PR and between 90aae67 and 9d0e9ad.

📒 Files selected for processing (18)
  • server/application-server/openapi.yaml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryService.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeDetectionCompletedEvent.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepository.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingService.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingDetailDTO.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingListDTO.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFinding.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/model/PracticeFindingTargetType.java
  • server/application-server/src/main/resources/db/changelog/1774700000000_changelog.xml
  • server/application-server/src/main/resources/db/master.xml
  • server/application-server/src/test/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryServiceIntegrationTest.java
  • server/application-server/src/test/java/de/tum/in/www1/hephaestus/agent/handler/PracticeDetectionDeliveryServiceTest.java
  • server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java
  • server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepositoryIntegrationTest.java
  • server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/feedback/FindingFeedbackControllerIntegrationTest.java
  • server/intelligence-service/src/shared/db/schema.ts
  • webapp/src/api/types.gen.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@FelixTJDietrich
FelixTJDietrich merged commit 3299754 into main Mar 26, 2026
42 checks passed
@FelixTJDietrich
FelixTJDietrich deleted the fix/issue-930-practice-finding-target-type-constraint branch March 26, 2026 22:41
@github-actions

Copy link
Copy Markdown
Contributor

📚 Documentation Preview

Preview has been removed (PR closed)

@FelixTJDietrich

Copy link
Copy Markdown
Collaborator Author

🎉 This PR is included in version 0.52.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@FelixTJDietrich FelixTJDietrich added the released Included in a published release label Mar 26, 2026
FelixTJDietrich added a commit that referenced this pull request Mar 30, 2026
The PracticeFindingTargetType enum→String refactor from #953 changed
the DTO serialization but the OpenAPI spec was not regenerated.
CI correctly caught the drift.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

application-server Spring Boot server: APIs, business logic, database bug Something isn't working intelligence-service TypeScript AI service: LLM orchestration, mentor chat released Included in a published release size:L This PR changes 100-499 lines, ignoring generated files. webapp React app: UI components, routes, state management

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(application-server): add CHECK constraint on practice_finding.target_type

2 participants