fix(api): add explicit @PathVariable name on transcription-block comment endpoints #473

Closed
opened 2026-05-07 17:29:14 +02:00 by marcel · 0 comments
Owner

Context

Spectral lint of the live /v3/api-docs reports two ERROR-severity findings (only ERROR-severity findings out of 244 total — the rest are documentation warnings):

[ERROR] path-params @ paths./api/documents/{documentId}/transcription-blocks/{blockId}/comments.get
        Operation must define parameter "{documentId}" as expected by the path

[ERROR] path-params @ paths./api/documents/{documentId}/transcription-blocks/{blockId}/comments/{commentId}/replies.post
        Operation must define parameter "{blockId}" as expected by the path

What this means: the OpenAPI spec for these two endpoints is missing path parameters that the URL itself contains. The cause is almost always that the Spring controller method uses an implicit @PathVariable UUID documentId (no name attribute) and SpringDoc fails to associate it with the path placeholder.

The practical impact: when npm run generate:api regenerates frontend/src/lib/generated/api.ts, the typed call signatures for these two endpoints are missing the path parameter — meaning frontend code that should be type-checked at compile time silently accepts wrong types or no types at all.

Approach

Find the affected handlers in:

  • backend/src/main/java/org/raddatz/familienarchiv/document/comment/CommentController.java (most likely location)
  • or backend/src/main/java/org/raddatz/familienarchiv/document/transcription/TranscriptionBlockController.java

Look for handlers matching the path patterns. Add the explicit name attribute:

// before (probable)
@GetMapping("/api/documents/{documentId}/transcription-blocks/{blockId}/comments")
public ... listComments(@PathVariable UUID documentId, @PathVariable UUID blockId) { ... }

// after
@GetMapping("/api/documents/{documentId}/transcription-blocks/{blockId}/comments")
public ... listComments(
    @PathVariable("documentId") UUID documentId,
    @PathVariable("blockId")    UUID blockId) { ... }

While there, also verify the /replies POST handler. Spectral specifically called out missing {blockId} on the POST — a sibling parameter problem.

Why does this happen?

Spring's @PathVariable does infer the name from the parameter name when compiled with -parameters (Java 8+). SpringDoc typically picks this up. The bug surfaces when:

  1. The build doesn't pass -parameters to javac (verify in pom.xml's maven-compiler-plugin config).
  2. The parameter is shadowed by a different variable scope.
  3. Lombok generates conflicting metadata.

If the root cause is missing -parameters, the fix is to add it to the compiler plugin and the explicit-name strategy becomes optional (defense-in-depth).

<!-- backend/pom.xml — confirm this is set -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <parameters>true</parameters>
    </configuration>
</plugin>

Critical files

  • One or both of:
    • backend/src/main/java/org/raddatz/familienarchiv/document/comment/CommentController.java
    • backend/src/main/java/org/raddatz/familienarchiv/document/transcription/TranscriptionBlockController.java
  • backend/pom.xml — verify/add <parameters>true</parameters>
  • After fix: regenerate frontend/src/lib/generated/api.ts via npm run generate:api

Verification

  1. Boot backend with dev profile: ./mvnw spring-boot:run -Dspring-boot.run.profiles=dev.
  2. Capture spec: curl http://localhost:8080/v3/api-docs > /tmp/openapi.json.
  3. Lint: npx @stoplight/spectral-cli@6.13.1 spectral lint /tmp/openapi.json --ruleset spectral:oas --fail-severity error — exit 0.
  4. Inspect spec: jq '.paths."/api/documents/{documentId}/transcription-blocks/{blockId}/comments".get.parameters' /tmp/openapi.json shows both path params with names.
  5. Regenerate types: cd frontend && npm run generate:api. Inspect new api.ts — these endpoints now have the path-param fields typed.
  6. Frontend type-check: npm run check — any code calling these endpoints will surface type errors if they were previously ignoring path params.

Acceptance criteria

  • Spectral --fail-severity error exits 0 against the live /v3/api-docs.
  • Both endpoints list documentId and blockId as path parameters in the spec.
  • frontend/src/lib/generated/api.ts regenerated with the corrected signatures.
  • npm run check passes (or surfaces real type bugs in callers, which then get fixed in the same PR).
  • <parameters>true</parameters> confirmed/set in compiler plugin.

Effort

XS — 15 minutes for the controller fix; 1 hour if it surfaces caller type errors.

Risk if not addressed

Generated TypeScript types are wrong → silent compile-time bugs in frontend code calling these endpoints. CI's planned OpenAPI lint gate (in the devops(ci) issue) will fail.

Tracked in audit doc as F-36 (Medium) — new dynamic finding from Spectral lint.

## Context Spectral lint of the live `/v3/api-docs` reports two **ERROR**-severity findings (only ERROR-severity findings out of 244 total — the rest are documentation warnings): ``` [ERROR] path-params @ paths./api/documents/{documentId}/transcription-blocks/{blockId}/comments.get Operation must define parameter "{documentId}" as expected by the path [ERROR] path-params @ paths./api/documents/{documentId}/transcription-blocks/{blockId}/comments/{commentId}/replies.post Operation must define parameter "{blockId}" as expected by the path ``` What this means: the OpenAPI spec for these two endpoints is missing path parameters that the URL itself contains. The cause is almost always that the Spring controller method uses an implicit `@PathVariable UUID documentId` (no name attribute) and SpringDoc fails to associate it with the path placeholder. The **practical impact**: when `npm run generate:api` regenerates `frontend/src/lib/generated/api.ts`, the typed call signatures for these two endpoints are missing the path parameter — meaning frontend code that should be type-checked at compile time silently accepts wrong types or no types at all. ## Approach Find the affected handlers in: - `backend/src/main/java/org/raddatz/familienarchiv/document/comment/CommentController.java` (most likely location) - or `backend/src/main/java/org/raddatz/familienarchiv/document/transcription/TranscriptionBlockController.java` Look for handlers matching the path patterns. Add the explicit `name` attribute: ```java // before (probable) @GetMapping("/api/documents/{documentId}/transcription-blocks/{blockId}/comments") public ... listComments(@PathVariable UUID documentId, @PathVariable UUID blockId) { ... } // after @GetMapping("/api/documents/{documentId}/transcription-blocks/{blockId}/comments") public ... listComments( @PathVariable("documentId") UUID documentId, @PathVariable("blockId") UUID blockId) { ... } ``` While there, also verify the `/replies` POST handler. Spectral specifically called out missing `{blockId}` on the POST — a sibling parameter problem. ### Why does this happen? Spring's `@PathVariable` *does* infer the name from the parameter name when compiled with `-parameters` (Java 8+). SpringDoc typically picks this up. The bug surfaces when: 1. The build doesn't pass `-parameters` to javac (verify in `pom.xml`'s `maven-compiler-plugin` config). 2. The parameter is shadowed by a different variable scope. 3. Lombok generates conflicting metadata. If the root cause is missing `-parameters`, the fix is to add it to the compiler plugin and the explicit-name strategy becomes optional (defense-in-depth). ```xml <!-- backend/pom.xml — confirm this is set --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <parameters>true</parameters> </configuration> </plugin> ``` ## Critical files - One or both of: - `backend/src/main/java/org/raddatz/familienarchiv/document/comment/CommentController.java` - `backend/src/main/java/org/raddatz/familienarchiv/document/transcription/TranscriptionBlockController.java` - `backend/pom.xml` — verify/add `<parameters>true</parameters>` - After fix: regenerate `frontend/src/lib/generated/api.ts` via `npm run generate:api` ## Verification 1. **Boot backend with dev profile**: `./mvnw spring-boot:run -Dspring-boot.run.profiles=dev`. 2. **Capture spec**: `curl http://localhost:8080/v3/api-docs > /tmp/openapi.json`. 3. **Lint**: `npx @stoplight/spectral-cli@6.13.1 spectral lint /tmp/openapi.json --ruleset spectral:oas --fail-severity error` — exit 0. 4. **Inspect spec**: `jq '.paths."/api/documents/{documentId}/transcription-blocks/{blockId}/comments".get.parameters' /tmp/openapi.json` shows both path params with names. 5. **Regenerate types**: `cd frontend && npm run generate:api`. Inspect new `api.ts` — these endpoints now have the path-param fields typed. 6. **Frontend type-check**: `npm run check` — any code calling these endpoints will surface type errors if they were previously ignoring path params. ## Acceptance criteria - [ ] Spectral `--fail-severity error` exits 0 against the live `/v3/api-docs`. - [ ] Both endpoints list `documentId` and `blockId` as path parameters in the spec. - [ ] `frontend/src/lib/generated/api.ts` regenerated with the corrected signatures. - [ ] `npm run check` passes (or surfaces real type bugs in callers, which then get fixed in the same PR). - [ ] `<parameters>true</parameters>` confirmed/set in compiler plugin. ## Effort XS — 15 minutes for the controller fix; 1 hour if it surfaces caller type errors. ## Risk if not addressed Generated TypeScript types are wrong → silent compile-time bugs in frontend code calling these endpoints. CI's planned OpenAPI lint gate (in the devops(ci) issue) will fail. Tracked in audit doc as **F-36** (Medium) — new dynamic finding from Spectral lint.
marcel added the P2-mediumbug labels 2026-05-07 17:29:41 +02:00
Sign in to join this conversation.
No Label P2-medium bug
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#473