Skip to content

feat(server): add practice findings REST API for contributor dashboard - #910

Merged
FelixTJDietrich merged 2 commits into
mainfrom
feat/practice-findings-rest-api
Mar 25, 2026
Merged

feat(server): add practice findings REST API for contributor dashboard#910
FelixTJDietrich merged 2 commits into
mainfrom
feat/practice-findings-rest-api

Conversation

@FelixTJDietrich

@FelixTJDietrich FelixTJDietrich commented Mar 24, 2026

Copy link
Copy Markdown
Collaborator

Description

Add 4 read-only workspace-scoped REST endpoints to expose practice detection findings to the contributor dashboard (#897). The PracticeFindingRepository previously only had write methods (insertIfAbsent, deleteAllByPracticeWorkspaceId) — this PR adds the full read layer: controller, service, DTOs, repository queries, and integration tests.

Closes #896

Endpoints

Method Path Auth Description
GET /workspaces/{slug}/practices/findings Workspace member Paginated findings for current user. Filters: practiceSlug, verdict
GET /workspaces/{slug}/practices/findings/summary Workspace member Per-practice aggregation: verdict counts, last finding date
GET /workspaces/{slug}/practices/findings/{findingId} Workspace member (own) Single finding detail with guidance, reasoning, evidence
GET /workspaces/{slug}/practices/findings/pull-request/{prId} Workspace member All findings for a PR (all contributors)

Architecture decisions

  • @WorkspaceScopedController — follows existing AgentJobController/PracticeCatalogController pattern, auto-prefixes routes with /workspaces/{workspaceSlug}
  • Ownership in SQL, not JavafindByIdAndContributorAndWorkspace pushes the contributor ownership check into the JPQL query. This avoids lazy-load fragility on getContributor() and makes the auth check atomic with the fetch. Non-owners get 404 (not 403) to avoid leaking finding existence.
  • Consistent auth via getCurrentUser() — all service methods use Optional<User> from UserRepository.getCurrentUser(). List/summary return empty for unsyncced users. Detail returns 404.
  • Evidence as Object, not JsonNode — matches AgentJobDTO pattern, produces clean OpenAPI schema (no broken $ref)
  • @NonNull Long for aggregate counts — projection and DTO use boxed Long with @NonNull to satisfy annotation conventions and produce required fields in OpenAPI contract
  • Separate countQuery — paginated query uses JOIN FETCH which is incompatible with Hibernate's count projections, so we provide an explicit countQuery per the existing codebase pattern

Files changed

File Change Purpose
PracticeFindingController.java NEW 4 REST endpoints with pagination, filtering
PracticeFindingService.java NEW Read-only service, @Transactional(readOnly=true)
PracticeFindingRepository.java MODIFIED +4 JPQL read queries
dto/PracticeFindingListDTO.java NEW List-view record, omits large text fields
dto/PracticeFindingDetailDTO.java NEW Full detail record with guidance/evidence
dto/ContributorPracticeSummaryDTO.java NEW Per-practice aggregation record
dto/ContributorPracticeSummaryProjection.java NEW Spring Data interface projection
ActivityModuleBoundaryTest.java MODIFIED Allow PracticeFindingController in arch rules
PracticeFindingControllerIntegrationTest.java NEW 28 integration tests
openapi.yaml REGENERATED 4 new endpoints, 4 new schemas
webapp/src/api/* REGENERATED TypeScript client updated

Security

  • Workspace membership enforced by WorkspaceScopedController filter
  • Contributor ownership enforced in SQL for detail endpoint (IDOR protection)
  • Internal fields never exposed: agentJobId, idempotencyKey, raw contributorId omitted from all DTOs
  • Evidence JSONB exposed only in detail view (not in list view)

Test coverage (28 tests)

List endpoint (12 tests): empty page, own-only filtering, practice slug filter, verdict filter, combined filters, pagination, page size cap, boundary normalization (page=-1,size=0), full shape assertion, no internal field leaks, sort order, workspace isolation

Summary endpoint (4 tests): empty list, aggregation with all fields, 401 unauthenticated, user isolation

Detail endpoint (6 tests): full detail with all fields, other user's finding → 404, non-existent → 404, 401 unauthenticated, evidence JSON round-trip, cross-workspace → 404

PR endpoint (6 tests): PR findings, includes other users, empty for unknown PR, sort order, 401 unauthenticated, workspace isolation

How to test

  1. Integration tests: cd server/application-server && mvn test -Dtest="PracticeFindingControllerIntegrationTest" -Dsurefire.includedGroups="integration" -DskipTests=false -Dmaven.test.skip=false
  2. Architecture tests: mvn test -Dsurefire.includedGroups="architecture" -DskipTests=false -Dmaven.test.skip=false
  3. Manual: Start server, hit GET /workspaces/{slug}/practices/findings with valid JWT — verify own findings only, no internal fields
  4. IDOR: Access another user's finding ID → expect 404
  5. Cross-workspace: Access finding via wrong workspace slug → expect 404

Summary by CodeRabbit

  • New Features
    • Added read-only practice findings API: paginated/filterable list, pull-request scoped list, per-practice contributor summaries, and detailed finding view; workspace-scoped and authenticated.
  • Client / Web
    • Frontend API client and types updated; response transformers normalize timestamps.
  • Tests
    • Integration tests added to validate listing, filtering, pagination, summary, detail, auth, and workspace isolation.

Add 4 read-only workspace-scoped endpoints to expose practice detection
findings to the contributor dashboard. Includes paginated list with
filtering, per-practice summary aggregation, single finding detail, and
per-PR finding views.

- New PracticeFindingController with @WorkspaceScopedController
- New PracticeFindingService with consistent auth via getCurrentUser()
- 4 JPQL queries with JOIN FETCH for eager loading
- Ownership enforced in SQL (not Java) for findByIdAndContributorAndWorkspace
- DTOs: PracticeFindingListDTO, PracticeFindingDetailDTO, ContributorPracticeSummaryDTO
- Evidence field uses Object (not JsonNode) matching AgentJobDTO pattern
- 28 integration tests: auth, pagination, filtering, workspace isolation, IDOR
- Architecture test updated to allow PracticeFindingController
- OpenAPI spec + client regenerated

Closes #896

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@FelixTJDietrich
FelixTJDietrich requested a review from a team as a code owner March 24, 2026 17:24
Copilot AI review requested due to automatic review settings March 24, 2026 17:24
@dosubot dosubot Bot added the feature New feature or enhancement label Mar 24, 2026
@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Added a read-only Practice Findings API: four GET endpoints for paginated contributor findings, per-practice summaries, single finding detail, and pull-request-scoped findings, plus repository queries, DTOs, service/controller, integration tests, OpenAPI specs, and generated frontend SDK/types.

Changes

Cohort / File(s) Summary
OpenAPI Spec
server/application-server/openapi.yaml
Added "Practice Findings" tag and four authenticated GET endpoints with new response schemas (PracticeFindingList, PracticeFindingDetail, PagePracticeFindingList, ContributorPracticeSummary).
Backend Controller & Service
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingController.java, .../PracticeFindingService.java
New workspace-scoped controller and read-only service exposing: list (paginated, filters practiceSlug/verdict, pagination normalization), summary (per-practice aggregation), detail (UUID-scoped, 404 when not owned), and PR-scoped findings. Service enforces contributor-scoped access where applicable.
Repository & Projection
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepository.java, .../ContributorPracticeSummaryProjection.java
Added JPA queries: paginated contributor findings with optional filters and countQuery, per-practice summary projection, contributor+workspace-scoped single-find query, and workspace-scoped pull-request findings.
Backend DTOs
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/*
Added DTO records: PracticeFindingListDTO, PracticeFindingDetailDTO, ContributorPracticeSummaryDTO with factory methods mapping entities/projections to safe API shapes (omit internal fields).
Backend Tests & Architecture
server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java, .../ActivityModuleBoundaryTest.java
New comprehensive controller integration tests covering auth, workspace isolation, filters, pagination, sorting, response shapes; updated ArchUnit rule to permit the new controller.
Frontend SDK / Types / Transformers
webapp/src/api/sdk.gen.ts, @tanstack/react-query.gen.ts, transformers.gen.ts, types.gen.ts, index.ts
Generated client additions: SDK functions and query keys for four endpoints, response transformers converting timestamps to Date (handles paginated and array/single shapes), and new TS types for list/detail/page/summary and endpoint request/response variants.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client (webapp)
  participant Controller as PracticeFindingController
  participant Service as PracticeFindingService
  participant Repo as PracticeFindingRepository
  Client->>Controller: GET /workspaces/{slug}/practices/findings?...
  Controller->>Service: getFindings(workspaceId, filters, pageable)
  Service->>Repo: findByContributorAndWorkspace(..., pageable)
  Repo-->>Service: Page<PracticeFinding>
  Service-->>Controller: Page<PracticeFindingListDTO>
  Controller-->>Client: 200 PagePracticeFindingList (JSON)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

A rabbit peeked into code tonight,
Four new paths gleamed in gentle light,
DTOs trimmed what must not show,
Summaries, lists, and details in tow,
Hopping changes, small and bright. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(server): add practice findings REST API for contributor dashboard' accurately summarizes the main change: exposing practice findings via new REST endpoints.
Linked Issues check ✅ Passed The PR implements all four required endpoints (#896: /findings, /findings/summary, /findings/{findingId}, /findings/pull-request/{prId}), uses focused DTOs omitting internal fields, enforces contributor-scoped authorization, and includes comprehensive integration tests.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the practice findings REST API. Updates to ActivityModuleBoundaryTest and auto-generated files (OpenAPI, React Query, TypeScript) are necessary supporting changes aligned with the PR objectives.

✏️ 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 feat/practice-findings-rest-api

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 application-server Spring Boot server: APIs, business logic, database webapp React app: UI components, routes, state management size:XXL This PR changes 1000+ lines, ignoring generated files. labels Mar 24, 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 read-only “practice findings” API surface to the application-server so the webapp’s contributor dashboard can list, summarize, and drill into practice detection findings in a workspace-scoped way.

Changes:

  • Introduces a new workspace-scoped PracticeFindingController + PracticeFindingService providing 4 GET endpoints (list, summary, detail, PR findings).
  • Extends PracticeFindingRepository with JPQL read queries (pagination + aggregation + ownership-scoped lookup).
  • Regenerates OpenAPI + webapp OpenAPI TS client/types/transformers to consume the new endpoints, and adds integration tests + arch rule update.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.

Show a summary per file
File Description
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingController.java New REST controller exposing 4 workspace-scoped read endpoints with pagination/filtering.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingService.java New read-only service using UserRepository.getCurrentUser() for contributor scoping and 404-on-non-owner detail access.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingRepository.java Adds read JPQL queries (paged list w/ countQuery, per-practice summary projection, ownership-scoped detail fetch, PR findings list).
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingListDTO.java New list DTO mapping from entity and omitting internal/large fields.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/PracticeFindingDetailDTO.java New detail DTO including guidance/reasoning/evidence while omitting internal fields.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/ContributorPracticeSummaryDTO.java New summary DTO for per-practice aggregates.
server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/ContributorPracticeSummaryProjection.java New Spring Data projection interface for aggregation query results.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/architecture/ActivityModuleBoundaryTest.java Updates architecture rule to allow the new controller in the practices module.
server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java Adds integration test coverage for list/summary/detail/PR endpoints incl. filtering, pagination normalization, and IDOR behavior.
server/application-server/openapi.yaml Regenerated OpenAPI spec with new paths/tags/schemas.
webapp/src/api/types.gen.ts Regenerated client types for new schemas/endpoints.
webapp/src/api/transformers.gen.ts Regenerated response transformers (notably date parsing for detectedAt / lastFindingAt).
webapp/src/api/sdk.gen.ts Regenerated SDK functions for new endpoints.
webapp/src/api/index.ts Regenerated public exports for new SDK functions and types.
webapp/src/api/@tanstack/react-query.gen.ts Regenerated TanStack Query option/key helpers for the new endpoints.

@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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/application-server/openapi.yaml`:
- Around line 3333-3367: The ContributorPracticeSummary schema is missing the
recent verdict trajectory required by the summary endpoint: update the source
DTO/projection that populates ContributorPracticeSummary (add a trajectory field
containing the recent verdict/time series data), update any mapping code that
builds ContributorPracticeSummary instances, then run the project’s
OpenAPI/client generation commands to regenerate
server/application-server/openapi.yaml and all derived client and server
artifacts rather than hand-editing the generated file; ensure the new trajectory
property is included in the generated ContributorPracticeSummary contract and
returned by the summary endpoint.
- Around line 1858-1871: Update the OpenAPI parameter metadata for the query
parameters named "page" and "size" so the contract includes bounds: add
"minimum: 0" for the "page" parameter and for "size" set "minimum: 1", "maximum:
100" while keeping the default of 20; do this in the source used to generate
server/application-server/openapi.yaml (not by hand-editing the generated file),
then run the project's OpenAPI/contract generation command to regenerate
server/application-server/openapi.yaml so clients/docs reflect the limits.
- Line 1879: Remove the empty `@SecurityRequirements` annotations that are
producing security: [] in the generated OpenAPI (seen at lines producing
security: []) so the endpoints inherit the global bearerAuth; specifically open
the controller containing the annotated endpoints and delete the
`@SecurityRequirements` annotation from each affected handler method (the methods
currently producing security: []), then regenerate the OpenAPI spec so
`@OpenAPIDefinition`'s bearerAuth is applied; ensure no other method-level
`@SecurityRequirements` remain and run the spec generation to confirm security:
bearerAuth is present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8b8531f-5c88-4884-aa8e-2af8bf1ecb8c

📥 Commits

Reviewing files that changed from the base of the PR and between 108f4cc and c7b44fe.

📒 Files selected for processing (15)
  • server/application-server/openapi.yaml
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingController.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/ContributorPracticeSummaryDTO.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/dto/ContributorPracticeSummaryProjection.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/test/java/de/tum/in/www1/hephaestus/architecture/ActivityModuleBoundaryTest.java
  • server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java
  • webapp/src/api/@tanstack/react-query.gen.ts
  • webapp/src/api/index.ts
  • webapp/src/api/sdk.gen.ts
  • webapp/src/api/transformers.gen.ts
  • webapp/src/api/types.gen.ts

Comment on lines +1858 to +1871
- in: query
name: page
required: false
schema:
type: integer
format: int32
default: 0
- in: query
name: size
required: false
schema:
type: integer
format: int32
default: 20

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.

⚠️ Potential issue | 🟡 Minor

Document the pagination bounds here too.

The PR objective calls out page >= 0 and a default size of 20 with a maximum of 100, but Lines 1858-1871 only describe the defaults. Generated clients and API docs will not reflect the actual request limits. Add the bounds in the source parameter annotations and regenerate the contract. As per coding guidelines, "Never hand-edit generated artifacts in server/application-server/openapi.yaml, webapp/src/api/**/*, server/application-server/src/main/java/de/tum/in/www1/hephaestus/intelligenceservice/**, server/intelligence-service/openapi.yaml, server/intelligence-service/src/shared/db/schema.ts, and docs/contributor/erd/schema.mmd; regenerate instead using the appropriate generation commands".

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

In `@server/application-server/openapi.yaml` around lines 1858 - 1871, Update the
OpenAPI parameter metadata for the query parameters named "page" and "size" so
the contract includes bounds: add "minimum: 0" for the "page" parameter and for
"size" set "minimum: 1", "maximum: 100" while keeping the default of 20; do this
in the source used to generate server/application-server/openapi.yaml (not by
hand-editing the generated file), then run the project's OpenAPI/contract
generation command to regenerate server/application-server/openapi.yaml so
clients/docs reflect the limits.

schema:
$ref: "#/components/schemas/PagePracticeFindingList"
description: Paginated findings returned
security: []

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check the OpenAPI file around the mentioned lines
head -n 1970 server/application-server/openapi.yaml | tail -n 100

Repository: ls1intum/Hephaestus

Length of output: 2984


🏁 Script executed:

# Search for the controller file containing these practice findings endpoints
find server -name "*.java" -type f | xargs grep -l "practices/findings" | head -5

Repository: ls1intum/Hephaestus

Length of output: 307


🏁 Script executed:

# Also look for controller files containing "PracticeFinding" references
find server -name "*.java" -type f | xargs grep -l "PracticeFinding" | head -10

Repository: ls1intum/Hephaestus

Length of output: 1208


🏁 Script executed:

# Read the PracticeFindingController.java to check security annotations
cat -n server/application-server/src/main/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingController.java

Repository: ls1intum/Hephaestus

Length of output: 6933


🏁 Script executed:

# Search for how `@SecurityRequirements` is used elsewhere in the codebase
rg -A2 "@SecurityRequirements" server/application-server/src/main/java --type java

Repository: ls1intum/Hephaestus

Length of output: 12167


🏁 Script executed:

# Check if there are any controllers that properly declare security requirements
rg -A2 "@SecurityRequirement\(" server/application-server/src/main/java --type java

Repository: ls1intum/Hephaestus

Length of output: 418


🏁 Script executed:

# Check the OpenAPIConfiguration to understand the security setup
cat -n server/application-server/src/main/java/de/tum/in/www1/hephaestus/OpenAPIConfiguration.java | head -100

Repository: ls1intum/Hephaestus

Length of output: 4931


🏁 Script executed:

# Check if there are any endpoints that properly use `@SecurityRequirement` instead of empty `@SecurityRequirements`
rg "@SecurityRequirement\(name\s*=\s*" server/application-server/src/main/java --type java | head -20

Repository: ls1intum/Hephaestus

Length of output: 215


🏁 Script executed:

# Look at the git history or comments around `@SecurityRequirements` usage to understand the pattern
rg -B5 -A2 "@SecurityRequirements" server/application-server/src/main/java/de/tum/in/www1/hephaestus/workspace/WorkspaceController.java --type java

Repository: ls1intum/Hephaestus

Length of output: 1179


🏁 Script executed:

# Check the semantics: what does `@SecurityRequirements` with no arguments do?
# Look for any comments or documentation in the codebase about this
rg -i "SecurityRequirements" server/application-server/src/main/java --type java -A5 | grep -i "comment\|doc\|clear\|override" | head -20

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Search for any controllers that DON'T use `@SecurityRequirements` to see if there's a pattern
rg "@GetMapping" server/application-server/src/main/java -A3 --type java | grep -v "@SecurityRequirements" | head -30

Repository: ls1intum/Hephaestus

Length of output: 3742


🏁 Script executed:

# Check the test file to see what auth is actually required at runtime
head -100 server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java

Repository: ls1intum/Hephaestus

Length of output: 4062


🏁 Script executed:

# Check if tests for these endpoints require authentication
grep -A 20 "listFindings\|getSummary\|getFinding" server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java | grep -E "@WithUser|webTestClient|401|403|200" | head -30

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Search for how `@SecurityRequirements` empty annotation is documented in springdoc-openapi
rg -i "empty.*security\|security.*clear\|override.*auth" server --type java | head -20

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Check the OpenAPI v3 spec to understand if empty `@SecurityRequirements` overrides global security
web_search

Repository: ls1intum/Hephaestus

Length of output: 113


🌐 Web query:

@SecurityRequirements empty annotation OpenAPI 3 swagger-annotations override global security

💡 Result:

In OpenAPI 3.0, global security requirements defined at the root level (via security in @OpenAPIDefinition or equivalent) can be overridden at the operation level. To completely disable (remove) global security for a specific operation, use an empty security array []. This overrides and removes the top-level security declaration for that operation. In swagger-annotations (io.swagger.v3.oas.annotations), use @SecurityRequirements (the container for repeatable @SecurityRequirement) with no @SecurityRequirement values, i.e., @SecurityRequirements. This generates an empty security array [] in the operation's OpenAPI definition, effectively disabling global security. Example: @SecurityRequirements // Empty - overrides global security with [] @PostMapping("/public-endpoint") public ResponseEntity<?> publicEndpoint { // No security required } This works in libraries like springdoc-openapi and swagger-core, as confirmed in multiple issues and Stack Overflow answers. For non-OAuth schemes, scopes are empty []. Recent OpenAPI spec clarifications (3.0.4+) affirm security: [] removes inherited security. Alternative: @SecurityRequirements(value = {}) explicitly sets empty value array. Note: @Operation(security = {}) may not always produce the empty array; direct @SecurityRequirements is more reliable for override.

Citations:


🏁 Script executed:

# Check other `@WorkspaceScopedController` endpoints to see if they also use empty `@SecurityRequirements`
rg -B5 "@WorkspaceScopedController" server/application-server/src/main/java --type java -A30 | grep -A20 "@GetMapping" | head -50

Repository: ls1intum/Hephaestus

Length of output: 6924


🏁 Script executed:

# Look at the actual test to see what happens without authentication
tail -200 server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java | head -100

Repository: ls1intum/Hephaestus

Length of output: 3517


🏁 Script executed:

# This is the smoking gun - check if the test actually validates 401 for unauthenticated
grep -B5 -A10 "returns 401 for unauthenticated" server/application-server/src/test/java/de/tum/in/www1/hephaestus/practices/finding/PracticeFindingControllerIntegrationTest.java

Repository: ls1intum/Hephaestus

Length of output: 2051


🏁 Script executed:

# Check if other `@WorkspaceScopedController` endpoints also have similar tests
rg "returns 401 for unauthenticated\|isUnauthorized" server/application-server/src/test --type java -B2 -A8 | head -50

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Check the WorkspaceScopedController implementation to understand the enforcement mechanism
find server -name "WorkspaceScopedController.java" -type f -exec cat -n {} \;

Repository: ls1intum/Hephaestus

Length of output: 1340


🏁 Script executed:

# Find the WorkspaceScopedWebMvcConfiguration mentioned in the annotation
find server -name "WorkspaceScopedWebMvcConfiguration.java" -type f -exec cat -n {} \;

Repository: ls1intum/Hephaestus

Length of output: 3451


🏁 Script executed:

# Check if there's a filter or interceptor that handles authentication
rg "WorkspaceContext|workspaceSlug" server/application-server/src/main/java -B3 -A3 --type java | grep -E "ArgumentResolver|HandlerInterceptor|Filter|Security" | head -30

Repository: ls1intum/Hephaestus

Length of output: 5374


🏁 Script executed:

# Check if this empty `@SecurityRequirements` pattern is intentional across the codebase
# by looking for when it was introduced
git log -p --all -S "@SecurityRequirements" -- "*.java" | head -100

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Check if there's documentation about why this pattern is used
rg "SecurityRequirements.*empty\|SecurityRequirements.*override\|filter.*authentication\|WorkspaceContextFilter" server/application-server/src/main/java --type java -B3 -A3 | head -50

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Find and inspect the WorkspaceContextFilter
find server -name "*ContextFilter*.java" -o -name "*WorkspaceFilter*.java" | xargs cat -n 2>/dev/null

Repository: ls1intum/Hephaestus

Length of output: 35341


🏁 Script executed:

# Verify this pattern is intentional by checking if there are endpoints that properly declare security
rg "@SecurityRequirement\(name\s*=.*bearerAuth" server/application-server/src/main/java --type java | head -10

Repository: ls1intum/Hephaestus

Length of output: 215


Remove @SecurityRequirements to inherit global authentication.

Lines 1879, 1910, 1935, and 1965 have security: [], which declares these endpoints as unauthenticated despite the WorkspaceContextFilter enforcing 401 for all unauthenticated requests at runtime. The empty @SecurityRequirements annotation in the controller deliberately overrides global bearerAuth, creating a spec-runtime mismatch that would generate incorrect client code. Delete the @SecurityRequirements annotation from each endpoint in the source controller so they inherit bearerAuth from @OpenAPIDefinition, then regenerate the OpenAPI spec per coding guidelines.

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

In `@server/application-server/openapi.yaml` at line 1879, Remove the empty
`@SecurityRequirements` annotations that are producing security: [] in the
generated OpenAPI (seen at lines producing security: []) so the endpoints
inherit the global bearerAuth; specifically open the controller containing the
annotated endpoints and delete the `@SecurityRequirements` annotation from each
affected handler method (the methods currently producing security: []), then
regenerate the OpenAPI spec so `@OpenAPIDefinition`'s bearerAuth is applied;
ensure no other method-level `@SecurityRequirements` remain and run the spec
generation to confirm security: bearerAuth is present.

Comment on lines +3333 to +3367
ContributorPracticeSummary:
type: object
description: Per-practice finding summary for a contributor
properties:
category:
type: string
description: Practice category
lastFindingAt:
type: string
format: date-time
description: Timestamp of most recent finding
negativeCount:
type: integer
format: int64
description: Number of NEGATIVE findings
positiveCount:
type: integer
format: int64
description: Number of POSITIVE findings
practiceName:
type: string
description: Practice name
practiceSlug:
type: string
description: Practice slug
totalFindings:
type: integer
format: int64
description: Total number of findings
required:
- negativeCount
- positiveCount
- practiceName
- practiceSlug
- totalFindings

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.

⚠️ Potential issue | 🟠 Major

ContributorPracticeSummary is still missing the dashboard trajectory data.

The linked objective requires the summary endpoint to provide a recent verdict trajectory for each practice, but this schema only exposes aggregate counts and lastFindingAt. The dashboard cannot render the promised trend data from this contract. Add the trajectory field in the source DTO/projection and regenerate the OpenAPI/client artifacts. As per coding guidelines, "Never hand-edit generated artifacts in server/application-server/openapi.yaml, webapp/src/api/**/*, server/application-server/src/main/java/de/tum/in/www1/hephaestus/intelligenceservice/**, server/intelligence-service/openapi.yaml, server/intelligence-service/src/shared/db/schema.ts, and docs/contributor/erd/schema.mmd; regenerate instead using the appropriate generation commands".

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

In `@server/application-server/openapi.yaml` around lines 3333 - 3367, The
ContributorPracticeSummary schema is missing the recent verdict trajectory
required by the summary endpoint: update the source DTO/projection that
populates ContributorPracticeSummary (add a trajectory field containing the
recent verdict/time series data), update any mapping code that builds
ContributorPracticeSummary instances, then run the project’s OpenAPI/client
generation commands to regenerate server/application-server/openapi.yaml and all
derived client and server artifacts rather than hand-editing the generated file;
ensure the new trajectory property is included in the generated
ContributorPracticeSummary contract and returned by the summary endpoint.

@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 (1)
server/application-server/openapi.yaml (1)

3984-3985: The evidence field lacks a type, producing unknown in generated clients.

The evidence property has a description but no type. Per OpenAPI 3.1, this allows any value. While the PR summary notes this is intentional ("evidence is typed as Object for clean OpenAPI schemas"), generated TypeScript clients will infer this as unknown, requiring consumers to cast or validate at runtime. Consider whether an explicit type: object or additionalProperties: true would provide slightly better client ergonomics while preserving flexibility.

This is a generated file, so any change would need to be made in the source DTO's @Schema annotation. As per coding guidelines, "Never hand-edit generated artifacts [...]; regenerate instead using the appropriate generation commands".

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

In `@server/application-server/openapi.yaml` around lines 3984 - 3985, The OpenAPI
schema's evidence property is missing a type so generated clients get unknown;
update the source DTO's `@Schema` annotation (not the generated openapi.yaml) to
include an explicit type and allow additional properties (e.g., `@Schema`(type =
"object", additionalProperties = SchemaAdditionalProperties.TRUE) or equivalent
in your codebase) so the generated openapi.yaml will emit evidence: { type:
object, additionalProperties: true } and TypeScript clients will infer a usable
object type.
🤖 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/openapi.yaml`:
- Around line 3984-3985: The OpenAPI schema's evidence property is missing a
type so generated clients get unknown; update the source DTO's `@Schema`
annotation (not the generated openapi.yaml) to include an explicit type and
allow additional properties (e.g., `@Schema`(type = "object", additionalProperties
= SchemaAdditionalProperties.TRUE) or equivalent in your codebase) so the
generated openapi.yaml will emit evidence: { type: object, additionalProperties:
true } and TypeScript clients will infer a usable object type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91961503-50be-4cad-a85f-4aa696ee0f08

📥 Commits

Reviewing files that changed from the base of the PR and between c7b44fe and ca2f158.

📒 Files selected for processing (1)
  • server/application-server/openapi.yaml

@FelixTJDietrich
FelixTJDietrich merged commit 1e46f86 into main Mar 25, 2026
40 checks passed
@FelixTJDietrich
FelixTJDietrich deleted the feat/practice-findings-rest-api branch March 25, 2026 06:31
@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.49.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@FelixTJDietrich FelixTJDietrich added the released Included in a published release label Mar 25, 2026
FelixTJDietrich added a commit that referenced this pull request Mar 25, 2026
Regenerated to include both practice findings API (#910) and finding
feedback API (#898) endpoints.

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 feature New feature or enhancement released Included in a published release size:XXL This PR changes 1000+ 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.

feat(application-server): practice findings REST API for contributor dashboard

2 participants