Skip to content

feat(api): add feature-flagged /rest/v1/health endpoint#936

Merged
Pa04rth merged 3 commits into
OWASP:mainfrom
skypank-coder:feat/health-endpoint
Jun 20, 2026
Merged

feat(api): add feature-flagged /rest/v1/health endpoint#936
Pa04rth merged 3 commits into
OWASP:mainfrom
skypank-coder:feat/health-endpoint

Conversation

@skypank-coder

Copy link
Copy Markdown
Contributor

Closes #935

What

Thin v1 deploy/uptime health probe at GET /rest/v1/health, off by default behind the CRE_ENABLE_HEALTH feature flag.

Behavior

  • 404 when the flag is off (default) — endpoint behaves as if it doesn't exist.
  • 200 when the DB is reachable AND the dataset is non-empty (cre_count > 0 and standards_count > 0), returning {ok, db_reachable, cre_count, standards_count}.
  • 503 when the DB is unreachable or the dataset is empty/broken (reason explains which).

How

Node_collection.health_check() runs two cheap COUNT queries (over CRE and Node), never raises — connectivity errors are reported as ok=False so the route can return the right status code.

Scope

DB reachability + data sanity only. No Neo4j / Redis. No GA / mapping completeness — those are deliberately excluded and stay in ops tooling (verify_ga_completeness, monitor_ga_health, weekly automation). A heavier "deep health" can be added separately later.

Testing

  • 4 new tests in web_main_test.py: disabled→404, enabled+empty→503, enabled+populated→200, DB unreachable→503. All green.
  • black==24.4.2 --check clean on all changed files.

Files changed

  • application/feature_flags.pyis_health_endpoint_enabled()
  • application/database/db.pyNode_collection.health_check()
  • application/web/web_main.py/rest/v1/health route
  • application/tests/web_main_test.py — tests

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@skypank-coder, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 29 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

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

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

🚦 How do rate limits work?

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

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: c653e0fb-90af-45b7-bfe6-50ed215a634b

📥 Commits

Reviewing files that changed from the base of the PR and between 64e5934 and ceb189c.

📒 Files selected for processing (6)
  • .env.example
  • README.md
  • application/database/db.py
  • application/feature_flags.py
  • application/tests/web_main_test.py
  • application/web/web_main.py

Walkthrough

Adds a feature-flagged GET /rest/v1/health endpoint. A new is_health_endpoint_enabled() function reads the CRE_ENABLE_HEALTH environment variable. Node_collection.health_check() runs two COUNT queries against the DB and returns a structured result with database reachability and data sanity status. The Flask route returns 404 when disabled, 200 on success, or 503 on failure. Four unit tests cover all branches, and documentation updates describe the configuration.

Changes

Health probe endpoint

Layer / File(s) Summary
Feature flag and DB health_check() implementation
application/feature_flags.py, application/database/db.py
.env file loading is configured with optional python-dotenv import. is_health_endpoint_enabled() reads CRE_ENABLE_HEALTH against TRUE_VALUES. Node_collection.health_check() runs COUNT queries for CRE rows and Node/standard rows, handles OperationalError separately from other exceptions, and returns ok, db_reachable, cre_count, standards_count, and reason.
Flask route wiring
application/web/web_main.py
Imports is_health_endpoint_enabled, registers GET /rest/v1/health, aborts with 404 when the flag is off, calls database.health_check(), and returns the JSON payload with HTTP 200 or 503 based on result["ok"].
Unit tests
application/tests/web_main_test.py
Four tests cover: 404 when CRE_ENABLE_HEALTH is unset, 503 with reason="empty dataset" when enabled but no data, 200 with counts when data is seeded, and 503 with db_reachable=false when health_check is patched to simulate an unreachable DB.
Documentation
.env.example, README.md
.env.example documents CRE_ENABLE_HEALTH=false as the default and explains the endpoint is off by default. README environment variables section documents the same behavior and feature flag.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% 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
Title check ✅ Passed The title 'feat(api): add feature-flagged /rest/v1/health endpoint' clearly summarizes the main change: a new API endpoint with feature flag control.
Description check ✅ Passed The description comprehensively explains the feature, behavior, implementation, scope, and testing, all directly related to the changeset.
Linked Issues check ✅ Passed The PR fully addresses issue #935 requirements: feature-flagged /rest/v1/health endpoint with 404/200/503 responses, DB+data sanity checks only, excluding Neo4j/Redis/GA completeness.
Out of Scope Changes check ✅ Passed All changes are scoped to the health endpoint feature: DB health check method, feature flag function, API route, tests, and documentation—no unrelated modifications.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@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)
application/database/db.py (1)

2292-2297: ⚡ Quick win

Consider narrowing the broad Exception handler to SQLAlchemy exception types.

The bare except Exception: on line 2292 is caught by static analysis (Ruff BLE001). While the defensive intent is clear from the comment, you could make this more precise by catching sqlalchemy.exc.DatabaseError (which is the base class for all SQLAlchemy database exceptions, including OperationalError) or a tuple of specific exceptions like (OperationalError, ProgrammingError, DatabaseError). This would maintain the defensive posture while being more explicit about what you're guarding against.

♻️ Proposed refinement
+from sqlalchemy.exc import DatabaseError
+
 def health_check(self) -> Dict[str, Any]:
     try:
         cre_count = self.session.query(func.count(CRE.id)).scalar() or 0
         standards_count = self.session.query(func.count(Node.id)).scalar() or 0
     except OperationalError:
         return {
             "ok": False,
             "db_reachable": False,
             "reason": "database unreachable",
         }
-    except Exception:  # pragma: no cover - defensive, never fail open
+    except DatabaseError:  # pragma: no cover - defensive, catch all DB errors
         return {
             "ok": False,
             "db_reachable": False,
             "reason": "database health query failed",
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@application/database/db.py` around lines 2292 - 2297, The broad `except
Exception:` handler in the database health check function should be narrowed to
catch specific SQLAlchemy exceptions instead. Replace the bare Exception catch
with either `sqlalchemy.exc.DatabaseError` (which is the base class for all
SQLAlchemy database exceptions) or a tuple of specific exceptions like
`(OperationalError, ProgrammingError, DatabaseError)`. This maintains the
defensive error handling while being more explicit about what database-related
errors are being guarded against, which will satisfy the Ruff BLE001 static
analysis check.

Source: Linters/SAST tools

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

Nitpick comments:
In `@application/database/db.py`:
- Around line 2292-2297: The broad `except Exception:` handler in the database
health check function should be narrowed to catch specific SQLAlchemy exceptions
instead. Replace the bare Exception catch with either
`sqlalchemy.exc.DatabaseError` (which is the base class for all SQLAlchemy
database exceptions) or a tuple of specific exceptions like `(OperationalError,
ProgrammingError, DatabaseError)`. This maintains the defensive error handling
while being more explicit about what database-related errors are being guarded
against, which will satisfy the Ruff BLE001 static analysis check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: dde30f7c-1450-4218-9931-ccaaa7a18f56

📥 Commits

Reviewing files that changed from the base of the PR and between e853cd3 and ec908bb.

📒 Files selected for processing (4)
  • application/database/db.py
  • application/feature_flags.py
  • application/tests/web_main_test.py
  • application/web/web_main.py

Comment thread application/feature_flags.py

@Pa04rth Pa04rth left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Add the new env variable in .env.example and readme

@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: 1

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

Inline comments:
In @.env.example:
- Around line 28-29: The comment for the CRE_ENABLE_HEALTH environment variable
setting describes when the endpoint returns 404 but does not explicitly document
how to enable the feature. Update the comment to clarify that users should set
CRE_ENABLE_HEALTH=1 to enable the health probe endpoint at GET /rest/v1/health.
This will make it clear to users what value is required to activate this
functionality.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 07c4bd4f-70bc-4f33-908b-c00d22cfc48e

📥 Commits

Reviewing files that changed from the base of the PR and between ec908bb and 769fc4f.

📒 Files selected for processing (3)
  • .env.example
  • README.md
  • application/feature_flags.py
✅ Files skipped from review due to trivial changes (1)
  • README.md

Comment thread .env.example Outdated
@Pa04rth Pa04rth self-requested a review June 20, 2026 14:08
Adds a lightweight deploy/uptime health probe at GET /rest/v1/health, gated behind the CRE_ENABLE_HEALTH feature flag (off by default).

Behavior:
- Flag off (default): endpoint returns 404, as if it does not exist.
- Flag on, healthy: 200 with {ok, db_reachable, cre_count, standards_count} when the serving DB is reachable and holds a non-empty dataset.
- Flag on, unhealthy: 503 when the DB is unreachable or the dataset is empty/broken (reason explains which).

Node_collection.health_check() runs cheap COUNT queries over CRE and Node, never raises (connectivity errors are reported as ok=False), and treats a zero count for either as an empty dataset.

Scope is intentionally limited to DB reachability + data sanity. Deeper checks (gap-analysis completeness, mapping coverage, Neo4j, Redis) are deliberately excluded by design and belong in ops tooling.
@skypank-coder skypank-coder force-pushed the feat/health-endpoint branch from 64e5934 to ceb189c Compare June 20, 2026 14:19
@Pa04rth Pa04rth merged commit 13d2f04 into OWASP:main Jun 20, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a feature-flagged /rest/v1/health endpoint (thin v1: DB + data sanity)

2 participants