Skip to content

Vacuum openapi#195

Draft
zendern wants to merge 28 commits into
mainfrom
vacuum
Draft

Vacuum openapi#195
zendern wants to merge 28 commits into
mainfrom
vacuum

Conversation

@zendern

@zendern zendern commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Link to Issue or Message thread

https://lab-sync.atlassian.net/wiki/spaces/LSE/pages/165642247/Software+Development+Team+Weekly

Why is this change necessary?

We want to start to run our apis through vacuum to keep things consistent across all them.

How does this change address the issue?

Adds vacuum as a pre-commit hook, installs it in devcontainer and sets up base rule and ignore set files.

What side effects does this change have?

Will break downstream repos on next pull of the template. We can decide at that time on a per repo basis to just disable it or keep it and fix the issues.

How is this change tested?

  • Downstream sensor-montior
  • Will pick another repo to try it on

Other

Summary by CodeRabbit

  • New Features
    • Added configurable REST API descriptions and OpenAPI tags, including clearer GraphQL tagging.
    • Added a GraphQL system query that reports the application version.
    • Improved API documentation with richer response field descriptions, examples, and validation metadata.
  • Quality Improvements
    • Added automated OpenAPI schema linting and validation.
    • OpenAPI snapshots are now generated automatically when needed.
    • Improved handling of generated validation-error documentation.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@zendern, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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

How do review limits work?

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

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, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e9f10a18-ea15-48c8-9262-e5137b0e3b97

📥 Commits

Reviewing files that changed from the base of the PR and between 87e0dc4 and 2b636e9.

📒 Files selected for processing (1)
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja
📝 Walkthrough

Walkthrough

The template adds configurable REST API descriptions and OpenAPI tags, documents validation and response schemas, introduces a GraphQL system query, and adds Copier snapshot generation plus Vacuum pre-commit and CI support.

Changes

OpenAPI metadata and linting

Layer / File(s) Summary
Backend OpenAPI metadata
copier.yml, tests/copier_data/*, template/.../app_def.py.jinja
Adds the backend REST API description prompt and data, configures OpenAPI descriptions and tags, documents response models, and tags GraphQL routes.
GraphQL system query
template/.../graphql.../schema.py
Defines a system query returning the application version and makes Query the Strawberry schema root.
Error schema and OpenAPI generation
template/.../fast_api_exception_handlers.py
Adds field metadata and constraints to ProblemDetails, passes application metadata to OpenAPI generation, and documents generated validation error components.
Snapshot generation and Vacuum execution
copier.yml, extensions/context.py, template/.config/*, template/.pre-commit-config.yaml.jinja, template/.gitignore, .github/workflows/ci.yaml
Adds conditional snapshot generation, Vacuum rules and ignores, templated Vacuum versioning, pre-commit execution, report ignores, and CI cleanup of stale virtual environments.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CopierTask
  participant OpenAPISnapshot
  participant VacuumPreCommit
  CopierTask->>OpenAPISnapshot: Generate missing schema snapshot
  VacuumPreCommit->>OpenAPISnapshot: Lint snapshot with configured rules
  VacuumPreCommit->>CopierTask: Return lint status
Loading

Possibly related PRs

Suggested reviewers: idonaldson

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 is related to the change, but it is too terse and generic to clearly convey the main update. Use a specific title such as "Add Vacuum OpenAPI linting to the template".
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description includes all required sections and explains the change, side effects, and testing, with only minor testing details left incomplete.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@zendern zendern changed the title Vacuum Vacuum openapi Jul 11, 2026

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

🤖 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 `@extensions/context.py`:
- Line 67: Update the hardcoded Vacuum version in the pre-commit hook
configuration to match context["vacuum_openapi_version"] ("0.29.9"), or safely
interpolate that template variable by exiting the raw block; ensure devcontainer
installs and pre-commit use the same Vacuum version.

In `@template/.devcontainer/install-ci-tooling.py.jinja`:
- Around line 122-135: Extract the duplicated command execution logic from the
pnpm_install_sequence and vacuum_install_sequence loops into a shared helper
function. The helper should accept a command string, construct the Windows pwsh
or non-Windows invocation based on is_windows, and call subprocess.run with
shell=True and check=True; update both loops to invoke this helper while
preserving existing behavior and comments.

In `@template/.pre-commit-config.yaml.jinja`:
- Around line 344-362: The vacuum-openapi hook should only be generated for
backend projects. Wrap the entire local hook block identified by id
“vacuum-openapi” in a Jinja `{% if has_backend %}` conditional, placing it after
the existing raw transition and closing it after the hook, while preserving the
current raw/template handling.

In `@template/`{% if has_backend %}backend{% endif
%}/src/backend_api/app_def.py.jinja:
- Around line 83-85: Replace the `// Insert app specific openapi tags here`
placeholder inside `OPENAPI_APP_SPECIFIC_TAGS` with a valid Python `#` comment
so generated backend code parses successfully.
🪄 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.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 966101fc-2c6f-4266-93ae-0daeaf76796f

📥 Commits

Reviewing files that changed from the base of the PR and between ea2f32f and c1139fb.

📒 Files selected for processing (13)
  • .github/workflows/ci.yaml
  • copier.yml
  • extensions/context.py
  • template/.config/vacuum-ignore.yaml
  • template/.config/vacuum-ruleset.yaml
  • template/.devcontainer/install-ci-tooling.py.jinja
  • template/.gitignore
  • template/.pre-commit-config.yaml.jinja
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja
  • tests/copier_data/data1.yaml
  • tests/copier_data/data3.yaml
  • tests/copier_data/data4.yaml
  • tests/copier_data/data5.yaml

Comment thread extensions/context.py
Comment thread template/.devcontainer/install-ci-tooling.py.jinja Outdated
Comment thread template/.pre-commit-config.yaml.jinja Outdated
Comment thread template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja Outdated
zendern and others added 3 commits July 10, 2026 22:51
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Comment thread template/.config/vacuum-ruleset.yaml Outdated
# (multi-tagging duplicates operations across groups and confuses codegen). We already tag singly.
operation-singular-tag:
given: $
severity: warn

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.

Does "warn" mean pre-commit will still pass?thought we tended towards "hard fail if we care or suppress if we don't a, because nobody ever looks at linter warnings"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No this is setting the severity level of this specific rule. pre-commit vacuum run is set to fail on warn and above level.

Comment thread .github/workflows/ci.yaml Outdated
run: |
# skip devcontainer context hash because the template instantiation may make it different every time
SKIP=git-dirty,compute-devcontainer-context-hash pre-commit run -a || PRE_COMMIT_EXIT_CODE=$?
# skip vacuum-openapi because the new template will not have an OpenAPI spec yet, so it will always fail

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.

I thought there was a boilerplate one that instantiated with the template, with healthcheck and shutdown API routes

COPIER_VERSION = "{% endraw %}{{ copier_version }}{% raw %}"
COPIER_TEMPLATE_EXTENSIONS_VERSION = "{% endraw %}{{ copier_template_extensions_version }}{% raw %}"
PRE_COMMIT_VERSION = "{% endraw %}{{ pre_commit_version }}{% raw %}"
VACUUM_OPENAPI_VERSION = "{% endraw %}{{ vacuum_openapi_version }}{% raw %}"

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.

It doesn't just install as a pre-commit hook? We have to install it in the main environment ourselves with more configuration outside of pre-commit config yaml?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correct this was cruft when i first thought i needed to install it there e0ae863

Comment thread template/.gitignore Outdated

# vacuum OpenAPI lint reports (generated ad-hoc; the linter runs against the committed snapshot)
vacuum-report-*.json
/report.html

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.

This seems like it could potentially bite us at the same point. Is there a CLI arg we can pass to the pre-commit hook to point the report into a more explicit folder

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dropped b8bab3b. Left the vacuum-report-*.json at least. Those are default paths for when you run the vacuum cli to see other things they do not generate when we run pre-commit so they are more just cya that we dont accidentally add them to a repo if we did run them

Comment thread template/.pre-commit-config.yaml.jinja Outdated
hooks:
- id: vacuum-openapi
name: vacuum OpenAPI schema lint
# Lints the generated OpenAPI snapshot (the canonical spec fed to Kiota) against the curated

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.

Is asleep this mention of Kiota in the comments a Zender decision or Claude? Seems like it might not be adding much value. Kiota isn't really the primary reason we're doing this, is it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed 0d0861f

app = FastAPIOffline(
title=HUMAN_FRIENDLY_APP_NAME,
description=API_DESCRIPTION,
openapi_tags=OPENAPI_TAGS,

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.

FastAPI doesn't do this automatically from the tags on each of the decorated routes?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This enables defining tags with helpful descriptions of what they actually are. But yes by default fast api will at least just give you the tag grouppings. I didn't see a way to add a description anywhere else on the tags themselves

image

zendern added 6 commits July 11, 2026 10:53
Space was misplaced in '{ %raw %}', making it invalid jinja syntax. Left the raw block unopened, so the later endraw tag had nothing to close, breaking template rendering for downstream copier consumers.

@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 @.github/workflows/ci.yaml:
- Around line 209-210: Add vacuum-openapi to the SKIP variable in the pre-commit
command alongside git-dirty and compute-devcontainer-context-hash, ensuring the
vacuum hook is skipped for the new template as intended by the surrounding
comment.
🪄 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.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: dbdcc2f1-132d-4646-a9b8-a1ba9c02e1de

📥 Commits

Reviewing files that changed from the base of the PR and between c1139fb and 827a518.

📒 Files selected for processing (6)
  • .github/workflows/ci.yaml
  • template/.config/vacuum-ruleset.yaml
  • template/.gitignore
  • template/.pre-commit-config.yaml.jinja
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/fast_api_exception_handlers.py
💤 Files with no reviewable changes (1)
  • template/.gitignore

Comment thread .github/workflows/ci.yaml Outdated
zendern added 5 commits July 11, 2026 11:16
Combining OPENAPI_TAGS via += reassignment tripped pyright's
reportConstantRedefinition, the untyped empty OPENAPI_APP_SPECIFIC_TAGS
list tripped pyrefly's implicit-any-empty-container check, and the
multi-line dict literal got collapsed by ruff-format since it fits
under the 120-char line length. Build the list in one assignment with
an explicit type annotation, pre-formatted to match ruff's output, so
freshly generated projects pass pre-commit without needing a
reformat pass.
…d-authoring it

The OpenAPI schema snapshot was hand-authored as a jinja template, which
had to be manually kept in sync with the actual schema for every
combination of template flags (graphql, circuit python, etc). It was
already drifting on fresh generations, requiring a manual
--snapshot-update before pre-commit would pass.

Drop the templated snapshot and add a copier task that runs the actual
test_openapi_schema test with --snapshot-update right after generation,
guarded on the snapshot file not already existing (so `copier update`
never clobbers a snapshot the repo has since evolved, consistent with
the existing _skip_if_exists entry for this file). Coverage enforcement
is disabled for this one-off run since it only exercises one test.

Also fix RUF005: build OPENAPI_TAGS with iterable unpacking instead of
list concatenation, which ruff flags as non-idiomatic.
…ription

HealthcheckResponse and ShutdownResponse had no docstring, so FastAPI
emitted their component schemas without a description, tripping
vacuum's component-description rule on every fresh generation.
…ion field

The graphql schema used query=int as a placeholder Query type, which
crashed strawberry.Schema() at import time. This was previously masked
in CI because the hand-authored openapi snapshot skipped the codepath
that actually imports the schema; removing that snapshot in a prior
commit exposed the crash.

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

🤖 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 `@template/`{% if has_backend %}backend{% endif
%}/src/backend_api/app_def.py.jinja:
- Around line 80-87: Update OPENAPI_TAGS to include metadata entries for both
the debug and mDNS tags used by the circuit-python backend, alongside the
existing system entry and app-specific tags. Do not add tags for graphql_app or
driver_router.
- Line 78: Update the API_DESCRIPTION assignment in the app_def.py.jinja
template to escape backend_rest_api_description for a valid quoted Python
string, including embedded double quotes and newline characters. Preserve the
configured description content while preventing raw interpolation from breaking
the generated Python source.
🪄 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.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 782ae758-0d97-42b9-b49f-d55c58428b68

📥 Commits

Reviewing files that changed from the base of the PR and between 827a518 and 955887a.

📒 Files selected for processing (4)
  • copier.yml
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/{% if backend_uses_graphql %}graphql{% endif %}/schema.py
  • template/{% if has_backend %}backend{% endif %}/tests/unit/__snapshots__/test_basic_server_functionality/test_openapi_schema.json.jinja
💤 Files with no reviewable changes (1)
  • template/{% if has_backend %}backend{% endif %}/tests/unit/snapshots/test_basic_server_functionality/test_openapi_schema.json.jinja


{% endraw %}{% endif %}{% raw %}

API_DESCRIPTION = "{% endraw %}{{ backend_rest_api_description }}{% raw %}"

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the template around the referenced line and nearby raw/Jinja delimiters.
FILE='template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja'
wc -l "$FILE"
sed -n '1,140p' "$FILE"

Repository: LabAutomationAndScreening/copier-nuxt-python-intranet-app

Length of output: 6581


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where backend_rest_api_description is defined/used and whether it may contain arbitrary text.
rg -n "backend_rest_api_description|API_DESCRIPTION|rest_api_description" -S .

Repository: LabAutomationAndScreening/copier-nuxt-python-intranet-app

Length of output: 874


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the template context to see how backend_rest_api_description is sourced.
rg -n "backend_rest_api_description|rest_api_description|description" template . -g '!**/.git/**'

Repository: LabAutomationAndScreening/copier-nuxt-python-intranet-app

Length of output: 50414


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the copier question definition and whether the template already uses tojson elsewhere.
sed -n '125,145p' copier.yml
printf '\n-- tojson usages --\n'
rg -n "\| *tojson\b" template copier.yml -S

printf '\n-- Python syntax probe --\n'
python3 - <<'PY'
import json

samples = [
    'Simple API',
    'Has "quotes"',
    'Has\nnewline',
]
for s in samples:
    bad = f'API_DESCRIPTION = "{s}"'
    good = f'API_DESCRIPTION = {json.dumps(s)}'
    print("\nSOURCE:", repr(s))
    for label, src in [("bad", bad), ("good", good)]:
        try:
            compile(src, "<probe>", "exec")
            print(label, "ok", src)
        except SyntaxError as e:
            print(label, "syntaxerror", e.msg)
PY

Repository: LabAutomationAndScreening/copier-nuxt-python-intranet-app

Length of output: 818


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the backend_rest_api_description prompt/constraint directly.
sed -n '132,142p' copier.yml

Repository: LabAutomationAndScreening/copier-nuxt-python-intranet-app

Length of output: 606


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check if the template is using a raw Python string literal pattern elsewhere for comparison.
rg -n '="[{][%] endraw [%]}][{][{] .* [|] raw [}][}][{][%] raw [%]}"' template -S

Repository: LabAutomationAndScreening/copier-nuxt-python-intranet-app

Length of output: 195


Escape backend_rest_api_description in the Python literal
Raw interpolation into a quoted Python string will break on " or newlines from this copier prompt.

Proposed fix
-API_DESCRIPTION = "{% endraw %}{{ backend_rest_api_description }}{% raw %}"
+API_DESCRIPTION = {% endraw %}{{ backend_rest_api_description | tojson }}{% raw %}
📝 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
API_DESCRIPTION = "{% endraw %}{{ backend_rest_api_description }}{% raw %}"
API_DESCRIPTION = {% endraw %}{{ backend_rest_api_description | tojson }}{% raw %}
🤖 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 `@template/`{% if has_backend %}backend{% endif
%}/src/backend_api/app_def.py.jinja at line 78, Update the API_DESCRIPTION
assignment in the app_def.py.jinja template to escape
backend_rest_api_description for a valid quoted Python string, including
embedded double quotes and newline characters. Preserve the configured
description content while preventing raw interpolation from breaking the
generated Python source.

zendern added 4 commits July 11, 2026 13:34
…w-template subfolder

Copier _tasks runs uv sync/pytest while the template still lives under
new-template/backend, baking console-script shebangs with that path.
After the move to repo root, those shebangs point nowhere, breaking any
python-wrapper console script (pyright) with ENOENT on exec.
…rules

- tag the graphql router so /api/graphql operations aren't untagged
- add examples to HealthcheckResponse.version and ShutdownResponse.message
zendern added 2 commits July 11, 2026 14:14
…xample for graphql

- register the "graphql" tag in OPENAPI_TAGS so the tagged /api/graphql
  operations resolve against a defined tag
- ignore oas3-missing-example on /api/graphql's 200 responses: the body is
  arbitrary JSON shaped by the caller's query/GraphiQL page, so there is no
  honest single example to attach
…_graphql

vacuum-ignore.yaml referenced /api/graphql paths unconditionally even
though that endpoint only exists when backend_uses_graphql is true.
Convert to a .jinja template and wrap those entries in the same
{% if backend_uses_graphql %} check used in app_def.py.jinja.

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

♻️ Duplicate comments (2)
template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja (2)

78-78: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Escape backend_rest_api_description in the Python literal

Raw interpolation into a quoted Python string will produce invalid Python if the value contains " or newlines. Use | tojson to emit a properly escaped string literal.

Proposed fix
-API_DESCRIPTION = "{% endraw %}{{ backend_rest_api_description }}{% raw %}"
+API_DESCRIPTION = {% endraw %}{{ backend_rest_api_description | tojson }}{% raw %}
🤖 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 `@template/`{% if has_backend %}backend{% endif
%}/src/backend_api/app_def.py.jinja at line 78, Update the API_DESCRIPTION
assignment in the backend template to render backend_rest_api_description
through the Jinja tojson filter, preserving a valid escaped Python string
literal for quotes, newlines, and other special characters.

84-88: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Declare the debug and mDNS OpenAPI tags

OPENAPI_TAGS defines system and graphql but the circuit-python backend uses tags=["debug"] and tags=["mDNS"] on router includes (lines 183–184). Without corresponding tag metadata, the openapi-tags Vacuum rule will fail when has_circuit_python_backend_template_been_instantiated is true. Add both entries conditionally, mirroring the graphql pattern.

Proposed fix
 OPENAPI_TAGS = [
     {"name": "system", "description": "Server health and lifecycle operations."},{% endraw %}{% if backend_uses_graphql %}{% raw %}
     {"name": "graphql", "description": "GraphQL endpoint (GraphiQL IDE on GET, queries/mutations on POST)."},{% endraw %}{% endif %}{% raw %}{% endraw %}{% if has_circuit_python_backend_template_been_instantiated %}{% raw %}
+    {"name": "debug", "description": "Debug endpoints for bridge inspection."},
+    {"name": "mDNS", "description": "mDNS service discovery endpoints."},{% endraw %}{% endif %}{% raw %}
     *OPENAPI_APP_SPECIFIC_TAGS,
 ]
🤖 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 `@template/`{% if has_backend %}backend{% endif
%}/src/backend_api/app_def.py.jinja around lines 84 - 88, Update the
OPENAPI_TAGS declaration to conditionally add metadata entries for the debug and
mDNS tags, following the existing backend_uses_graphql Jinja conditional
pattern. Ensure the entries are emitted when
has_circuit_python_backend_template_been_instantiated is enabled, alongside the
existing system, optional graphql, and OPENAPI_APP_SPECIFIC_TAGS entries.
🤖 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.

Duplicate comments:
In `@template/`{% if has_backend %}backend{% endif
%}/src/backend_api/app_def.py.jinja:
- Line 78: Update the API_DESCRIPTION assignment in the backend template to
render backend_rest_api_description through the Jinja tojson filter, preserving
a valid escaped Python string literal for quotes, newlines, and other special
characters.
- Around line 84-88: Update the OPENAPI_TAGS declaration to conditionally add
metadata entries for the debug and mDNS tags, following the existing
backend_uses_graphql Jinja conditional pattern. Ensure the entries are emitted
when has_circuit_python_backend_template_been_instantiated is enabled, alongside
the existing system, optional graphql, and OPENAPI_APP_SPECIFIC_TAGS entries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1152c383-8477-42a8-a494-5deb546a7d5f

📥 Commits

Reviewing files that changed from the base of the PR and between 955887a and 87e0dc4.

📒 Files selected for processing (3)
  • .github/workflows/ci.yaml
  • template/.config/vacuum-ignore.yaml.jinja
  • template/{% if has_backend %}backend{% endif %}/src/backend_api/app_def.py.jinja

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.

2 participants