Skip to content

Opt api router tags#118

Merged
touale merged 3 commits intomasterfrom
opt-api-router-tags
Apr 9, 2026
Merged

Opt api router tags#118
touale merged 3 commits intomasterfrom
opt-api-router-tags

Conversation

@touale
Copy link
Copy Markdown
Owner

@touale touale commented Apr 9, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • OpenAPI specification now includes tag metadata in API documentation.
    • Plugin descriptions are now displayed in API documentation.
  • Updates

    • Authentication cookie configuration is now externalized for consistency.
    • Proxy plugin updated to version 0.3.0.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Walkthrough

This change introduces configurable authentication cookie naming, extends API registration to support OpenAPI metadata (tags and descriptions), adds plugin description field support, and creates a utility function for formatting plugin metadata. Changes are coordinated across authentication, ingress routing, and plugin systems to enable enhanced API documentation.

Changes

Cohort / File(s) Summary
Authentication Cookie Configuration
src/framex/consts.py, src/framex/driver/auth.py, tests/driver/test_auth.py
Introduced AUTH_COOKIE_NAME constant for JWT cookie handling; switched authentication flow from hard-coded "token" string to use the new constant across request read and response write operations.
OpenAPI & Ingress Metadata Support
src/framex/driver/application.py, src/framex/driver/ingress.py, tests/driver/test_ingress.py
Initialized tags_metadata_map in application state for OpenAPI generation; extended register_route() and add_api_route() to accept optional description, tags, and include_in_schema parameters, wiring them into the FastAPI metadata system.
Plugin Description & Metadata Building
src/framex/plugin/base.py, src/framex/plugin/model.py, src/framex/plugin/on.py
Added build_plugin_description() utility function for Markdown-formatted plugin metadata; extended PluginApi model with optional description field; refactored plugin tag/description construction to separate concerns and use the new utility.
Proxy Plugin Configuration
src/framex/plugins/proxy/__init__.py, src/framex/plugins/proxy/config.py
Extracted plugin VERSION into dedicated config module; updated proxy metadata description; integrated build_plugin_description() when registering proxy routes with metadata.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through metadata streams,
Building descriptions in Markdown dreams,
Tags flow freely, descriptions align,
The auth cookie sweetens, the APIs shine! 🌟
Metadata magic, from plugin to scheme! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Opt api router tags' is vague and uses abbreviated/unclear terminology that doesn't convey what changes are actually implemented. Clarify the title to describe the actual changes, such as 'Add OpenAPI metadata support for routes' or 'Enable configurable route tags and descriptions'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 opt-api-router-tags

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.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

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

🧹 Nitpick comments (2)
tests/driver/test_auth.py (1)

14-14: Use AUTH_COOKIE_NAME in the callback Set-Cookie assertion too.

Line 186 still checks "token=", which is a loose substring check. Prefer exact key matching with the constant.

Proposed test tightening
-            assert "token=" in res.headers.get("set-cookie", "")
+            assert f"{AUTH_COOKIE_NAME}=" in res.headers.get("set-cookie", "")

Also applies to: 222-222

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

In `@tests/driver/test_auth.py` at line 14, The Set-Cookie assertions in the
callback tests use the loose substring "token="; update those assertions to use
the AUTH_COOKIE_NAME constant instead so the cookie key is matched exactly. Find
the assertions that inspect response.headers["Set-Cookie"] (currently checking
for "token=" at the callback test locations) and replace the literal with a
check for f"{AUTH_COOKIE_NAME}=" (or otherwise ensure the header contains the
AUTH_COOKIE_NAME key) so the tests assert the exact cookie name.
src/framex/driver/ingress.py (1)

219-227: Consider updating existing tag metadata when description becomes available.

If a tag is first registered without description, later routes cannot enrich it. Updating existing entries (when empty) would make tag docs stable regardless of registration order.

♻️ Suggested refinement
         if include_in_schema and tags:
-            names = list({tag["name"] for tag in app.state.tags_metadata_map})
-            for tag in tags:
-                if tag not in names:
-                    app.state.tags_metadata_map.append(
-                        {
-                            "name": tag,
-                            "description": description,
-                        },
-                    )
+            metadata_by_name = {item["name"]: item for item in app.state.tags_metadata_map}
+            for tag in tags:
+                entry = metadata_by_name.get(tag)
+                if entry is None:
+                    entry = {"name": tag, "description": description}
+                    app.state.tags_metadata_map.append(entry)
+                    metadata_by_name[tag] = entry
+                elif description and not entry.get("description"):
+                    entry["description"] = description
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/driver/ingress.py` around lines 219 - 227, The current logic in
the include_in_schema branch appends a new tag dict unconditionally when a tag
name isn't in names, which prevents enriching an existing entry's description
later; update the code that manipulates app.state.tags_metadata_map so that for
each tag in tags you first search for an existing entry by name (using the same
identity as names), and if found and its "description" is missing/empty,
set/overwrite it with the provided description; only append a new dict when no
existing entry exists; reference the include_in_schema condition, the tags loop,
names set, and app.state.tags_metadata_map when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/framex/driver/ingress.py`:
- Around line 210-217: The route registration call in app.add_api_route (inside
the ingress setup) drops the operation-level docs because the description
argument is not forwarded; update the app.add_api_route invocation that
currently passes path, endpoint, methods=list(method_set), tags=tags,
include_in_schema=include_in_schema, **kwargs to also include
description=description so the route’s OpenAPI/operation description is
preserved (ensure the local variable description is defined/available where
add_api_route is called).

In `@src/framex/plugins/proxy/__init__.py`:
- Around line 173-178: The code always prefixes the version with "v" when
calling build_plugin_description which can yield duplicated "v" if
__plugin_meta__.version already starts with one; modify the call site to
normalize the version first (e.g., read __plugin_meta__.version, strip any
leading "v" or "V", then format with a single "v" prefix) and pass that
normalized string to build_plugin_description (affecting the description
variable and the call that references __plugin_meta__.version and
build_plugin_description).

---

Nitpick comments:
In `@src/framex/driver/ingress.py`:
- Around line 219-227: The current logic in the include_in_schema branch appends
a new tag dict unconditionally when a tag name isn't in names, which prevents
enriching an existing entry's description later; update the code that
manipulates app.state.tags_metadata_map so that for each tag in tags you first
search for an existing entry by name (using the same identity as names), and if
found and its "description" is missing/empty, set/overwrite it with the provided
description; only append a new dict when no existing entry exists; reference the
include_in_schema condition, the tags loop, names set, and
app.state.tags_metadata_map when making this change.

In `@tests/driver/test_auth.py`:
- Line 14: The Set-Cookie assertions in the callback tests use the loose
substring "token="; update those assertions to use the AUTH_COOKIE_NAME constant
instead so the cookie key is matched exactly. Find the assertions that inspect
response.headers["Set-Cookie"] (currently checking for "token=" at the callback
test locations) and replace the literal with a check for f"{AUTH_COOKIE_NAME}="
(or otherwise ensure the header contains the AUTH_COOKIE_NAME key) so the tests
assert the exact cookie name.
🪄 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: de594b2a-c13c-4df0-bc67-86d39c249e38

📥 Commits

Reviewing files that changed from the base of the PR and between 51b8094 and d7f98dc.

📒 Files selected for processing (11)
  • src/framex/consts.py
  • src/framex/driver/application.py
  • src/framex/driver/auth.py
  • src/framex/driver/ingress.py
  • src/framex/plugin/base.py
  • src/framex/plugin/model.py
  • src/framex/plugin/on.py
  • src/framex/plugins/proxy/__init__.py
  • src/framex/plugins/proxy/config.py
  • tests/driver/test_auth.py
  • tests/driver/test_ingress.py

Comment on lines +210 to +217
app.add_api_route(
path,
endpoint,
methods=list(method_set), # type: ignore
tags=tags, # type: ignore
include_in_schema=include_in_schema,
**kwargs,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

description is dropped before FastAPI route registration.

Line 210-217 calls app.add_api_route(...) without passing the description argument, so operation-level docs metadata is never applied.

✅ Proposed fix
         app.add_api_route(
             path,
             endpoint,
             methods=list(method_set),  # type: ignore
             tags=tags,  # type: ignore
+            description=description,
             include_in_schema=include_in_schema,
             **kwargs,
         )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.add_api_route(
path,
endpoint,
methods=list(method_set), # type: ignore
tags=tags, # type: ignore
include_in_schema=include_in_schema,
**kwargs,
)
app.add_api_route(
path,
endpoint,
methods=list(method_set), # type: ignore
tags=tags, # type: ignore
description=description,
include_in_schema=include_in_schema,
**kwargs,
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/driver/ingress.py` around lines 210 - 217, The route registration
call in app.add_api_route (inside the ingress setup) drops the operation-level
docs because the description argument is not forwarded; update the
app.add_api_route invocation that currently passes path, endpoint,
methods=list(method_set), tags=tags, include_in_schema=include_in_schema,
**kwargs to also include description=description so the route’s
OpenAPI/operation description is preserved (ensure the local variable
description is defined/available where add_api_route is called).

Comment on lines +173 to +178
description = build_plugin_description(
__plugin_meta__.author,
f"v{__plugin_meta__.version}",
__plugin_meta__.description,
__plugin_meta__.url,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Normalize version prefix before building description.

Line 175 always prepends "v", which can produce vv... if the configured version already includes a prefix. Normalize once before passing it to build_plugin_description.

💡 Proposed fix
-                description = build_plugin_description(
+                version = __plugin_meta__.version
+                version = version if version.startswith("v") else f"v{version}"
+                description = build_plugin_description(
                     __plugin_meta__.author,
-                    f"v{__plugin_meta__.version}",
+                    version,
                     __plugin_meta__.description,
                     __plugin_meta__.url,
                 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
description = build_plugin_description(
__plugin_meta__.author,
f"v{__plugin_meta__.version}",
__plugin_meta__.description,
__plugin_meta__.url,
)
version = __plugin_meta__.version
version = version if version.startswith("v") else f"v{version}"
description = build_plugin_description(
__plugin_meta__.author,
version,
__plugin_meta__.description,
__plugin_meta__.url,
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/framex/plugins/proxy/__init__.py` around lines 173 - 178, The code always
prefixes the version with "v" when calling build_plugin_description which can
yield duplicated "v" if __plugin_meta__.version already starts with one; modify
the call site to normalize the version first (e.g., read
__plugin_meta__.version, strip any leading "v" or "V", then format with a single
"v" prefix) and pass that normalized string to build_plugin_description
(affecting the description variable and the call that references
__plugin_meta__.version and build_plugin_description).

@touale touale merged commit 46f9c28 into master Apr 9, 2026
9 checks passed
@touale touale deleted the opt-api-router-tags branch April 9, 2026 04:37
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.

1 participant