Skip to content

feat(api-docs): reintroduce API doc generation#289

Merged
zachyale merged 1 commit intodevelopfrom
feat/reintroduce-openapi-and-api-docs
Mar 31, 2026
Merged

feat(api-docs): reintroduce API doc generation#289
zachyale merged 1 commit intodevelopfrom
feat/reintroduce-openapi-and-api-docs

Conversation

@zachyale
Copy link
Copy Markdown
Member

@zachyale zachyale commented Mar 30, 2026

Description

This PR reintroduces API reference documentation. It does so by introducing a new env variable, API_DOCS_ENABLED (default false).

When enabled, docs are available publicly at .../api/docs, and the JSON spec at .../api/openapi.json.

Linked Issue: #288

Changes

  • Populates app.api-docs.enabled the value of a new env var, API_DOCS_ENABLED, or defaults to false
  • Populates springdoc.api-docs.enabled to use the value of app.api-docs.enabled
    • Exports the OpenAPI json to /api/openapi.json
  • Adds a new ScalarController to server Scalar API docs via /api/docs (if enabled) using the generated OpenAPI json
    • Includes a new test for the controller
  • Adds the routes /api/openapi.json and "/api/docs to the common public routes list in SecurityConfig
  • Updates readme/contributor docs w/ new env var + API reference doc access details

Summary by CodeRabbit

  • New Features

    • API docs UI available at /api/docs and OpenAPI JSON at /api/openapi.json (can be enabled via env flag)
  • Documentation

    • Added guidance and examples for enabling API docs; updated dev and Docker Compose examples to include the API_DOCS_ENABLED flag and local access URLs
  • Tests

    • Added tests validating the docs endpoint behavior and static docs page configuration

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9209d41b-023d-431a-8dea-3c1dacb049cd

📥 Commits

Reviewing files that changed from the base of the PR and between fada371 and b184c8f.

📒 Files selected for processing (9)
  • CONTRIBUTING.md
  • README.md
  • booklore-api/CONTRIBUTING.md
  • booklore-api/build.gradle.kts
  • booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java
  • booklore-api/src/main/java/org/booklore/controller/ScalarController.java
  • booklore-api/src/main/resources/application.yaml
  • booklore-api/src/main/resources/static/scalar.html
  • booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java
✅ Files skipped from review due to trivial changes (6)
  • CONTRIBUTING.md
  • booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java
  • booklore-api/src/main/resources/static/scalar.html
  • README.md
  • booklore-api/CONTRIBUTING.md
  • booklore-api/build.gradle.kts
🚧 Files skipped from review as they are similar to previous changes (3)
  • booklore-api/src/main/java/org/booklore/controller/ScalarController.java
  • booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java
  • booklore-api/src/main/resources/application.yaml
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Analyze (java-kotlin)

📝 Walkthrough

Walkthrough

Adds an opt-in API documentation feature: a conditional controller serving a Scalar UI at /api/docs, an OpenAPI JSON at /api/openapi.json, configuration flags and Springdoc dependency adjustment, and security changes to allow unauthenticated access to the docs endpoints.

Changes

Cohort / File(s) Summary
Docs & examples
CONTRIBUTING.md, README.md, booklore-api/CONTRIBUTING.md
Documented API docs feature, added API_DOCS_ENABLED env example, and documented local endpoints /api/docs and /api/openapi.json.
Controller & static UI
booklore-api/src/main/java/org/booklore/controller/ScalarController.java, booklore-api/src/main/resources/static/scalar.html
Added ScalarController (conditional on app.api-docs.enabled=true) forwarding /api/docs to the new scalar.html Scalar-based API reference that loads /api/openapi.json.
Configuration & build
booklore-api/src/main/resources/application.yaml, booklore-api/build.gradle.kts
Introduced app.api-docs.enabled wired from API_DOCS_ENABLED, made springdoc.api-docs.enabled follow it, set springdoc.api-docs.path: /api/openapi.json, and swapped Springdoc starter from -webmvc-ui to -webmvc-api (v3.0.2).
Security
booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java
Added "/api/docs" and "/api/openapi.json" to the public endpoints list so those routes are permitted without authentication.
Tests
booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java
Added unit test verifying ScalarController.scalar() forwards to /scalar.html and that the static scalar.html references /api/openapi.json and disables telemetry.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant WebApp as Server
  participant Springdoc
  Client->>WebApp: GET /api/docs
  WebApp->>WebApp: SecurityConfig permits public access
  WebApp->>WebApp: ScalarController forwards to /scalar.html
  Client->>WebApp: GET /scalar.html (static asset)
  Client->>WebApp: GET /api/openapi.json
  WebApp->>Springdoc: serve OpenAPI JSON (springdoc.api-docs.path)
  Springdoc-->>Client: OpenAPI JSON
  Client->>Client: Scalar UI renders API reference
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A tiny hop, the docs appear,
/api/docs welcomes far and near,
OpenAPI served, telemetry low,
Forwarded pages let the devs know,
A rabbit cheers — the spec will show! 🎉📜

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title follows conventional commit format with type 'feat' and scope 'api-docs', clearly summarizing the main change of reintroducing API documentation.
Description check ✅ Passed The PR description includes a clear description of changes and links to the related GitHub issue, covering the implementation details and modified files comprehensively.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/reintroduce-openapi-and-api-docs
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/reintroduce-openapi-and-api-docs

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java`:
- Around line 53-54: The security config currently always permits "/api/docs"
and "/api/openapi.json"; change SecurityConfig so those two endpoints are only
added to the permitAll set when the app.api-docs.enabled property is true (e.g.,
inject the boolean property into SecurityConfig as apiDocsEnabled and
conditionally include the paths in the public endpoints list or in the
configure(HttpSecurity http) permitAll call). Update the code that builds the
array/list of public endpoints (or the configure method) to branch on
apiDocsEnabled so the endpoints are not publicly permitted when
app.api-docs.enabled is false.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 451bc3c2-2101-4a9a-8568-91f12dcc7007

📥 Commits

Reviewing files that changed from the base of the PR and between f1cbcf3 and fada371.

📒 Files selected for processing (9)
  • CONTRIBUTING.md
  • README.md
  • booklore-api/CONTRIBUTING.md
  • booklore-api/build.gradle.kts
  • booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java
  • booklore-api/src/main/java/org/booklore/controller/ScalarController.java
  • booklore-api/src/main/resources/application.yaml
  • booklore-api/src/main/resources/static/scalar.html
  • booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (2)
booklore-api/src/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

booklore-api/src/**/*.java: Use 4-space indentation in Java files and match surrounding Java style
Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce @Autowired field injection
Use MapStruct for entity/DTO mapping

Files:

  • booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java
  • booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java
  • booklore-api/src/main/java/org/booklore/controller/ScalarController.java
booklore-api/src/test/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

Prefer focused unit tests; use @SpringBootTest only when the Spring context is required

Files:

  • booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java
🧠 Learnings (2)
📚 Learning: 2026-03-26T01:46:48.863Z
Learnt from: CR
Repo: grimmory-tools/grimmory PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-26T01:46:48.863Z
Learning: Applies to booklore-api/src/**/*.java : Use MapStruct for entity/DTO mapping

Applied to files:

  • booklore-api/build.gradle.kts
📚 Learning: 2026-03-26T01:46:48.863Z
Learnt from: CR
Repo: grimmory-tools/grimmory PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-26T01:46:48.863Z
Learning: Applies to booklore-api/src/**/*.java : Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce `Autowired` field injection

Applied to files:

  • booklore-api/build.gradle.kts
🔇 Additional comments (9)
CONTRIBUTING.md (1)

216-221: Nice documentation addition for API docs discovery.

Clear endpoint docs and enablement wording; this aligns well with the feature-flag rollout.

booklore-api/build.gradle.kts (1)

100-100: Dependency swap is aligned with the new docs delivery approach.

Using springdoc-openapi-starter-webmvc-api fits the custom /api/docs UI path and keeps only OpenAPI generation on the backend.

booklore-api/src/main/resources/application.yaml (1)

5-6: Config wiring for docs enablement and custom OpenAPI path looks solid.

The flag default and springdoc binding are consistent with controlled exposure of API docs.

Also applies to: 98-99

booklore-api/src/main/java/org/booklore/controller/ScalarController.java (1)

7-14: Controller gating and forwarding behavior are cleanly implemented.

@ConditionalOnProperty correctly prevents endpoint registration when docs are disabled.

README.md (1)

78-80: README updates are clear and operationally useful.

The env var, compose passthrough, and endpoint docs are consistent and easy to follow.

Also applies to: 123-123, 201-205

booklore-api/CONTRIBUTING.md (1)

27-35: Good contributor guidance for API docs feature flag behavior.

This section accurately communicates default-off behavior and explicit runtime enablement.

booklore-api/src/test/java/org/booklore/controller/ScalarControllerTest.java (1)

16-29: Focused tests with meaningful assertions — nice coverage for the new docs surface.

These checks validate both controller forwarding and key Scalar page configuration.

booklore-api/src/main/resources/static/scalar.html (2)

12-16: Good default config for public docs embed.

data-url and telemetry:false are set cleanly and align with exposing /api/openapi.json while minimizing analytics leakage.


17-17: and

@zachyale zachyale requested review from balazs-szucs and imajes March 30, 2026 22:52
@zachyale zachyale linked an issue Mar 30, 2026 that may be closed by this pull request
@imajes
Copy link
Copy Markdown
Member

imajes commented Mar 30, 2026

@zachyale can you address the coderabbit note? That seems valid

- reintroduces API doc generation via API_DOCS_ENABLED
- accessible publicly via /api/docs and /api/openapi.json
@zachyale zachyale force-pushed the feat/reintroduce-openapi-and-api-docs branch from fada371 to b184c8f Compare March 31, 2026 00:16
@zachyale
Copy link
Copy Markdown
Member Author

@zachyale can you address the coderabbit note? That seems valid

Some context:

  • COMMON_PUBLIC_ENDPOINTS is an array of some string regexes for public endpoints that do not require any form of auth to access them
  • This array is used by jwtApiSecurityChain within SecurityConfig to identify which endpoints can be marked as authenticated calls without a valid JWT
  • While OPDS related public endpoints are within COMMON_UNAUTHENTICATED_ENDPOINTS and not that array, the usage of COMMON_UNAUTHENTICATED_ENDPOINTS in opdsBasicAuthSecurityChain is the same logic as that within the JWT chain

RE: the coderabbit note:

  1. It is out of the scope of the Security Config class to be enforcing feature flag or settings related limitations on endpoint access

    • Security Config is for enforcing security related concerns for URLs. It is outside the scope of this class to have conditional logic for whether or not an endpoint is available or not based on ENV vars or user settings (enabling/disabling kobo or OPDS support). We should always strive to retain healthy separation of concerns
  2. More importantly: feature flag enforcement already happens earlier in the execution flow at the endpoint registration level

    • /api/docs is served by ScalarController, which is behind @ConditionalOnProperty(app.api-docs.enabled=true)
    • openapi.json is controlled by springdoc.api-docs.enabled, which inherits it's value from app.api-docs.enabled
    • When these vars are false (their default) those handlers are never registered, so requests don't have a chance to hit any of the security chains
    • Similarly, other setting related endpoint availability logic is kept upstream of SecurityConfig via the interceptors used in WebMvcConfig. However, in our case of /api/docs, it's better practice to use ConditionalOnProperty. This is because it is checked on startup only, and our ENV var can't change during runtime, so we can leave this as a one line check instead of having to implement another interceptor that we'd have to maintain
  3. On top of all of that, we're also deprecating most of this class in the next PR so the logic can be consolidated and reused for smarter API doc generation, so it didn't make sense to add a 4 line if statement that will be deleted in one PR but also cannot ever be hit due to the execution order

@balazs-szucs
Copy link
Copy Markdown
Member

I think we would want to enable this in the dev-docker by default.

As well as giving some UI hints towards access.

image

I always liked that. The latter is just an idea, but the former would be great if we could implement it here.

Copy link
Copy Markdown
Member

@imajes imajes left a comment

Choose a reason for hiding this comment

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

looks good, thanks @zachyale

Copy link
Copy Markdown
Member

@balazs-szucs balazs-szucs left a comment

Choose a reason for hiding this comment

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

Thanks!

@zachyale zachyale merged commit a2fc326 into develop Mar 31, 2026
14 checks passed
@zachyale zachyale deleted the feat/reintroduce-openapi-and-api-docs branch March 31, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce OpenAPI spec generation + surface Scalar docs

3 participants