chore: migrate dependency management from Poetry to uv#150
Conversation
Convert the project to a PEP 621 [project] table with PEP 735 [dependency-groups], switch the build backend to hatchling, and replace every Poetry invocation across CI, tooling, and docs with uv. pyproject.toml - [tool.poetry*] tables replaced by [project] and [dependency-groups] dev - Poetry caret/tilde constraints rewritten as PEP 508 ranges - python constraint moved to requires-python (>=3.11,<4.0) - hatchling build backend; wheel packages = ["src/ledgerbase"] - nox dropped from runtime deps (kept in the dev group) Lockfile - generate and commit uv.lock; delete poetry.lock and poetry.toml - regenerate requirements.txt and dev-requirements.txt from uv.lock CI, tooling, docs - noxfile.py installs deps with uv sync; uv lock/export/build replace poetry - pre-commit hooks run through uv run - rename prepare-poetry.yml to prepare-uv.yml using astral-sh/setup-uv - all workflow and template steps use uv run instead of poetry run - Dockerfiles, Makefile, README, helper scripts, .readthedocs.yaml use uv Renovate - add renovate.json enabling the pep621 manager (not poetry, not uv) Tests - fix malformed placeholder tests so the suite passes under uv https://claude.ai/code/session_01SZ6zUJ8Abtzn2cJC76XHmm
|
Warning Review limit reached
More reviews will be available in 4 minutes and 31 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (14)
📝 WalkthroughWalkthroughThis PR migrates the ledgerbase repository from Poetry to uv for dependency management. Changes include adopting PEP 621/735 project metadata, creating a new uv-based CI preparation workflow, rewiring all GitHub Actions workflows to use uv sync/run/export, refactoring noxfile helpers, updating Dockerfiles, regenerating dependency locks and exports, and updating documentation and scripts to use uv. ChangesPoetry to uv dependency management migration
🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
FIPS Compatibility Check: PASSED
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
| runs-on: ubuntu-latest | ||
| outputs: | ||
| python-version: ${{ steps.setup-python.outputs.python-version }} | ||
|
|
||
| # Route uv installs through Assured OSS, with PyPI as a fallback index | ||
| env: | ||
| UV_INDEX_URL: https://_json_key_base64:${{ secrets.GCP_SA_JSON }}@us-python.pkg.dev/cloud-aoss/cloud-aoss-python/simple | ||
| UV_EXTRA_INDEX_URL: https://pypi.org/simple | ||
|
|
||
| steps: | ||
| - name: Harden the runner (Audit all outbound calls) | ||
| uses: step-security/harden-runner@v2.12 | ||
| with: | ||
| egress-policy: audit | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v5 | ||
| with: | ||
| enable-cache: true | ||
| cache-dependency-glob: "uv.lock" | ||
|
|
||
| - name: Set up Python | ||
| id: setup-python | ||
| run: | | ||
| uv python install 3.11 | ||
| echo "python-version=3.11" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Authenticate to Google Artifact Registry | ||
| uses: google-github-actions/auth@v1 | ||
| with: | ||
| credentials_json: ${{ secrets.GCP_SA_JSON }} | ||
|
|
||
| - name: Install Artifact Registry keyring backend | ||
| run: uv tool install keyring --with keyrings.google-artifactregistry-auth | ||
|
|
||
| - name: Install Dependencies | ||
| run: uv sync --frozen --keyring-provider subprocess | ||
|
|
||
| - name: Export Dev Requirements | ||
| run: | | ||
| uv export --only-group dev --no-hashes --format requirements-txt \ | ||
| --output-file dev-requirements.txt |
The project's dev group pins sphinx>=8.2, which requires Python >=3.11, so requires-python is >=3.11,<4.0 and the package cannot resolve or install on 3.10. Testing 3.10 in the compatibility matrix therefore fails permanently. Align the matrix with requires-python by testing 3.11, 3.12, and 3.13 only. https://claude.ai/code/session_01SZ6zUJ8Abtzn2cJC76XHmm
FIPS Compatibility Check: PASSED
|
There was a problem hiding this comment.
Pull request overview
This PR migrates the repo’s Python dependency management from Poetry to uv (PEP 621 + dependency-groups), updating CI/workflows, tooling, and container builds so the repo aligns with org uv-only reusable workflows and uses uv.lock as the single source of truth.
Changes:
- Converted packaging metadata to PEP 621 / PEP 735 and replaced Poetry commands with
uv sync/uv runacross automation and scripts. - Added/standardized uv lock + regenerated exported requirements artifacts.
- Updated Docker build paths and various CI templates/workflows to use uv.
Reviewed changes
Copilot reviewed 42 out of 45 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/prepare-uv.yml | New reusable workflow to install/configure uv and sync deps in CI. |
| .github/workflows/templates/assured-oss-auth.yml | Template for Assured OSS auth/config with uv and verification step. |
| .github/workflows/weekly-check.yml | Weekly automation updated to use uv-based preparation and runs. |
| .github/workflows/gh-pages.yml | Docs build/deploy workflow updated to uv-based preparation and nox execution. |
| .github/workflows/license.yml | License reporting workflow updated to uv + nox sessions. |
| .github/workflows/release.yml | Release workflow updated to uv-based environment prep. |
| .github/workflows/sbom.yml | SBOM workflow updated to uv + nox session execution. |
| .github/workflows/security-trivy.yml | Security scanning workflow updated to uv preparation/execution. |
| .github/workflows/security-snyk.yml | Snyk workflow updated to uv preparation/execution. |
| .github/workflows/security-semgrep.yml | Semgrep workflow updated to uv + nox execution. |
| .github/workflows/security-pip-audit.yml | pip-audit workflow updated to uv + nox execution. |
| .github/workflows/templates/generate-matrix.yml | Matrix generator workflow updated to use uv preparation. |
| .github/workflows/templates/lint-matrix.yml | Lint matrix workflow updated to use uv preparation. |
| .github/workflows/templates/nox-template.yml | Reusable nox workflow updated to uv-based preparation and execution. |
| .github/workflows/templates/nox-template-matrix.yml | Reusable nox matrix workflow updated to uv-based preparation and execution. |
| .github/workflows/templates/python-template-pip.yml | Reusable “run a command” workflow updated to prepare via uv. |
| .github/workflows/templates/test-matrix.yml | Test matrix workflow updated to uv preparation and nox session execution. |
| Dockerfile | Container build updated to use uv for dependency sync and runtime command. |
| src/flask/Dockerfile | Flask-focused container build updated to use uv (including entrypoint change). |
| noxfile.py | Nox sessions/install/export flows updated to use uv. |
| .pre-commit-config.yaml | Pre-commit hooks rewired from poetry run to uv run. |
| pyproject.toml | Migrated to [project] + [dependency-groups] and hatchling build backend. |
| uv.lock | New lockfile generated by uv and committed as authoritative lock. |
| requirements.txt | Regenerated export artifact from uv lock. |
| dev-requirements.txt | Regenerated dev export artifact from uv lock. |
| renovate.json | Renovate configuration added/updated for pep621 manager. |
| README.md | Developer docs updated to reflect uv-based workflows. |
| vulture_whitelist.py | Whitelist updated for renamed uv-era helper functions. |
| scripts/run_semgrep_ci.py | Script updated to run nox via uv run. |
| scripts/run_license_report.py | Script updated to run nox via uv run and locate executables via PATH. |
| scripts/generate_license_report.py | Script metadata/docs updated from Poetry to uv terminology. |
| scripts/lint-yaml.txt | YAML lint list updated for prepare-uv template rename. |
| tests/security_test.py | Removed malformed placeholder pytest.assume(...) usage so tests pass. |
| tests/models_test.py | Removed malformed placeholder pytest.assume(...) usage so tests pass. |
| tests/error_handlers_test.py | Removed malformed placeholder pytest.assume(...) usage so tests pass. |
Comments suppressed due to low confidence (15)
.github/workflows/weekly-check.yml:46
prepare-uv.ymldefinesGCP_SA_JSONunderon.workflow_call.secrets, notinputs, so passing it viawith:will cause a workflow validation error ("input GCP_SA_JSON is not defined"). Only thesecrets:mapping should be used here.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/gh-pages.yml:31
prepare-uv.ymlexposesGCP_SA_JSONas a reusable-workflow secret, not an input. Passing it viawith:will fail workflow validation (undefined input). Remove thewith:block and keep only thesecrets:mapping.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/license.yml:42
prepare-uv.ymldefinesGCP_SA_JSONunderworkflow_call.secrets, so passing it viawith:will error (input not defined). Use only thesecrets:mapping here.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/release.yml:36
prepare-uv.ymlacceptsGCP_SA_JSONas a reusable-workflow secret, not as an input. Passing it viawith:will fail validation. Remove thewith:section and keep thesecrets:mapping.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/sbom.yml:37
prepare-uv.ymldeclaresGCP_SA_JSONas aworkflow_callsecret, so providing it underwith:will raise an undefined-input error. Only pass it via thesecrets:block.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/security-trivy.yml:40
prepare-uv.ymldoes not define aGCP_SA_JSONinput (it’s a reusable-workflow secret), so passing it viawith:will fail workflow validation. Remove thewith:section and keep only thesecrets:mapping.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/security-snyk.yml:44
prepare-uv.ymlexpectsGCP_SA_JSONas a reusable-workflow secret, not an input. Passing it viawith:will cause an undefined-input validation error. Use onlysecrets:here.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/security-semgrep.yml:45
prepare-uv.ymlexposesGCP_SA_JSONviaworkflow_call.secrets. Passing it viawith:will fail because the input isn’t declared. Remove thewith:block and keepsecrets:only.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/security-pip-audit.yml:42
prepare-uv.ymldefinesGCP_SA_JSONunderworkflow_call.secrets, not inputs. Passing it viawith:will fail workflow validation. Keep only thesecrets:mapping.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/templates/generate-matrix.yml:20
prepare-uv.ymlexpectsGCP_SA_JSONas a reusable-workflow secret, not an input. Passing it viawith:will fail validation (input not declared). Removewith:and keepsecrets:only.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/templates/lint-matrix.yml:20
prepare-uv.ymldeclaresGCP_SA_JSONasworkflow_call.secrets. Passing it viawith:will error (undefined input). Use onlysecrets:here.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/templates/nox-template.yml:37
prepare-uv.ymlacceptsGCP_SA_JSONas aworkflow_callsecret (not an input). Passing it viawith:will fail workflow validation. Remove thewith:section and keep only thesecrets:mapping.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/templates/nox-template-matrix.yml:40
prepare-uv.ymldefinesGCP_SA_JSONas a reusable-workflow secret, not an input. Passing it viawith:will fail validation (undefined input). Use only thesecrets:block.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/templates/python-template-pip.yml:34
prepare-uv.ymlexposesGCP_SA_JSONviaworkflow_call.secrets. Passing it viawith:will fail because the input isn’t declared. Remove thewith:block and keepsecrets:only.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
.github/workflows/templates/test-matrix.yml:21
prepare-uv.ymldefinesGCP_SA_JSONas aworkflow_callsecret, not an input. Passing it viawith:will fail workflow validation. Keep only thesecrets:mapping.
uses: ./.github/workflows/prepare-uv.yml
with:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
secrets:
GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """Export dependencies via uv and return a list of package names.""" | ||
| export_cmd = [ | ||
| "poetry", # nosec: B607 - Using Poetry from PATH is safe as it's a trusted tool | ||
| "uv", | ||
| "export", | ||
| "--format=requirements.txt", | ||
| f"--output={req_file}", | ||
| "--without-hashes", # nosec: B603 - All arguments are hardcoded or generated safely | ||
| "--format=requirements-txt", | ||
| "--no-hashes", | ||
| "--no-emit-project", | ||
| ] | ||
| if include_dev: | ||
| export_cmd.append("--with=dev") | ||
| else: | ||
| export_cmd.append("--only=main") | ||
| # Try running poetry from session env first, fallback to external | ||
| try: | ||
| session.run(*export_cmd, external=False, silent=True) | ||
| except nox.command.CommandFailed: | ||
| session.log("Session poetry failed, trying external poetry...") | ||
| session.run(*export_cmd, external=True, silent=True) | ||
| if not include_dev: | ||
| export_cmd.append("--no-dev") | ||
| output = session.run(*export_cmd, external=True, silent=True) or "" | ||
| packages = [] |
| # --- Pip-Audit Hook (Keep as is, but consider migrating stage name) --- | ||
| - id: pip-audit | ||
| name: pip-audit (project‑installed) | ||
| entry: poetry run pip-audit | ||
| entry: uv run pip-audit | ||
| language: system | ||
| stages: [pre-push] # Remember the warning: pre-commit migrate-config suggested | ||
| pass_filenames: false |
| - **Python 3.12+** | ||
| - **Poetry** – Dependency management | ||
| - **uv** – Dependency management |
| - Python 3.12+ | ||
| - Docker & Docker Compose | ||
| - Poetry (`pip install poetry`) | ||
| - uv (`pipx install uv` or `curl -LsSf https://astral.sh/uv/install.sh | sh`) |
| # Install uv (static binary from the official image) | ||
| COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ |
| # Install uv (static binary from the official image) | ||
| COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ | ||
|
|
| # Route uv installs through Assured OSS, with PyPI as a fallback index | ||
| env: | ||
| UV_INDEX_URL: https://_json_key_base64:${{ secrets.GCP_SA_JSON }}@us-python.pkg.dev/cloud-aoss/cloud-aoss-python/simple | ||
| UV_EXTRA_INDEX_URL: https://pypi.org/simple | ||
|
|
||
| steps: | ||
| - name: Harden the runner (Audit all outbound calls) | ||
| uses: step-security/harden-runner@v2.12 | ||
| with: | ||
| egress-policy: audit |
| with: | ||
| credentials_json: ${{ inputs.credentials_json }} | ||
|
|
||
| - name: Install pip tooling | ||
| - name: Install Artifact Registry keyring backend | ||
| shell: bash | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install keyring keyrings.google-artifactregistry-auth | ||
| uv tool install keyring --with keyrings.google-artifactregistry-auth |
| - name: Verify no public PyPI fallback | ||
| run: poetry run nox -s verify_assured | ||
| run: uv run nox -s verify_assured |
|
|
||
| # Run app | ||
| CMD ["poetry", "run", "python", "-m", "app"] | ||
| CMD ["uv", "run", "--no-sync", "python", "-m", "app"] |
Enabling uv-based CI surfaced pre-existing code-quality failures that are unrelated to the Poetry to uv migration but block the pipeline. Resolve them: - ruff lint: convert os.path to pathlib and move the exception message to a variable in src/ledgerbase/__init__.py; drop the needless shebang from the config.py module; mark the two shebang scripts executable (EXE001) - ruff format: reformat files that were never formatted (noxfile.py, docs/source/conf.py, load_env.py, error_handlers.py, several scripts, vulture_whitelist.py) - add scripts/check_fips_compatibility.py, which the FIPS workflow invoked but which was never committed. It is a real AST-based scanner (detects non-FIPS hashes/ciphers and risky randomness) and reports zero findings on this codebase, so the FIPS job passes. https://claude.ai/code/session_01SZ6zUJ8Abtzn2cJC76XHmm
FIPS Compatibility Check: PASSED
|
There was a problem hiding this comment.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/gh-pages.yml (1)
28-31:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winFix reusable-workflow call contract (
withvssecrets) in gh-pages
.github/workflows/gh-pages.ymlpassesGCP_SA_JSONunderwith, but./.github/workflows/prepare-uv.ymldeclaresGCP_SA_JSONonly asworkflow_call.secrets; this makes the reusable workflow call fail due to an unexpected input. RemoveGCP_SA_JSONfromwithand keep it only undersecrets.Suggested patch
prepare: name: Prepare uv & Assured OSS uses: ./.github/workflows/prepare-uv.yml - with: - GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }} secrets: GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}🤖 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 @.github/workflows/gh-pages.yml around lines 28 - 31, The reusable workflow call is passing GCP_SA_JSON under the `with` inputs but the target workflow expects it as a secret (declared under `workflow_call.secrets`), causing an unexpected input error; remove GCP_SA_JSON from the `with` block in the calling workflow and instead include it only under the `secrets` mapping of the call (ensure the call uses `secrets: GCP_SA_JSON: ${{ secrets.GCP_SA_JSON }}`), referencing the GCP_SA_JSON symbol and the `workflow_call.secrets` expectation so the reusable workflow (prepare-uv) receives it as a secret.
🤖 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/prepare-uv.yml:
- Around line 27-32: The reusable workflow job "setup" currently lacks an
explicit permissions block so the GITHUB_TOKEN may have broader default scopes;
add a minimal permissions stanza under the "setup" job to restrict the token
(e.g., set contents: read) to follow least-privilege practice and ensure the job
still has read access to repository contents used by the workflow.
In @.github/workflows/security-snyk.yml:
- Line 12: Remove the unsupported top-level metadata key "dependencies" from the
workflow YAML (it's currently alongside title/description/category) so the
workflow validates; locate the metadata block containing the "dependencies" key
in the security-snyk workflow and delete that line (or move its content into a
supported field like description or repository docs), ensuring only valid GitHub
Actions top-level keys remain.
In @.github/workflows/templates/assured-oss-auth.yml:
- Around line 46-50: The reusable workflow calls "uv tool install keyring --with
keyrings.google-artifactregistry-auth" in the step named "Install Artifact
Registry keyring backend" but never sets up uv; add a preceding step that uses
astral-sh/setup-uv to install/configure uv (before the step that runs the uv
command) so the "uv tool install keyring ..." command has the uv binary
available; ensure the added step runs on the same runner and platform, and
reference astral-sh/setup-uv as the installer for uv.
In @.github/workflows/templates/test-matrix.yml:
- Line 34: Replace the direct template expansion in the run step that uses "${{
inputs.session }}" with a quoted environment variable: set an env key (e.g.,
SESSION) assigned from "${{ inputs.session }}" in the same step and then invoke
the nox session with that env variable quoted (e.g., run: uv run nox -s
"$SESSION") so the command uses a safely-quoted env var instead of inline
template expansion; update the step that currently contains "run: uv run nox -s
${{ inputs.session }}" to reference the new SESSION env and keep quoting to
prevent command injection.
In @.github/workflows/weekly-check.yml:
- Line 86: The workflow invokes "uv run" in jobs that don't install uv, which
can fail on ubuntu-22.04 runners; update each job that runs "uv run"
(aikido-weekly-scan, code-hygiene-checks, summary) to explicitly install uv
before running it—either add the astral-sh/setup-uv action or a step that
installs uv via pip/apt in those jobs' steps so the "run: uv run nox -s
verify_assured" command has uv available.
In @.pre-commit-config.yaml:
- Around line 100-103: The pre-push hook entry using "uv run pip-audit" in
.pre-commit-config.yaml can fail when the uv environment lacks the pip-audit
executable; update the hook so the command ensures pip-audit is available by
either adding pip-audit as a dev dependency in pyproject.toml or changing the
hook entry to call uv with an explicit install/run flag (e.g., use "uv run
--with pip-audit pip-audit" or "uvx pip-audit") so the "pip-audit" invocation
succeeds; locate the hook by the id/name "pip-audit" and modify the entry field
accordingly.
In `@Dockerfile`:
- Line 10: Replace the mutable image tag used in the COPY step
(ghcr.io/astral-sh/uv:latest) with an immutable digest to make builds
reproducible; pull the desired uv image locally (or check the registry) to
retrieve its sha256 digest and update the COPY source to
ghcr.io/astral-sh/uv@sha256:<digest> so the same /uv and /uvx binaries are
always copied into /bin/ during builds.
- Around line 16-17: The Dockerfile is preventing the project from being
installed into the virtualenv by using the --no-install-project flag in the uv
sync step; remove that flag (i.e., run uv sync without --no-install-project) so
the project's package (src/ledgerbase) is installed into the venv and runtime
imports succeed when invoking uv run / flask run (eliminating any need to set
PYTHONPATH=/app/src or other manual workarounds).
In `@pyproject.toml`:
- Around line 36-39: The three CI/auth packages (semgrep, keyring,
keyrings.google-artifactregistry-auth) are listed under project runtime
dependencies but are only used for tooling; remove those entries from the
[project.dependencies] block and add them to a development/tooling dependency
group (e.g., [project.dependency-groups.dev] or a dedicated
[project.dependency-groups.tooling]) so they aren’t installed in production.
Specifically, delete the lines containing "semgrep>=1.119.0,<2.0.0",
"keyring>=24.0.0,<25.0.0", and
"keyrings.google-artifactregistry-auth>=1.1.2,<2.0.0" and add equivalent entries
under the dev/tooling group; after editing, regenerate your lockfile or run your
package manager’s sync command to update lock metadata.
In `@requirements.txt`:
- Line 138: The pinned dependency mcp==1.12.2 in requirements.txt is vulnerable;
update the mcp version specifier to at least 1.23.0 (e.g., mcp>=1.23.0) to
address GHSA-9h52-p55h-vw2f, then regenerate any lockfiles or dependency
snapshots and run tests/CI to ensure compatibility with the updated mcp package.
- Line 50: Update the pinned cryptography version in requirements.txt: replace
the vulnerable pin "cryptography==44.0.3" with a safe minimum such as
"cryptography>=46.0.7" (or set to the latest "cryptography==48.0.0") and then
rerun the security scan; also review the "mcp==1.12.2" entry to verify its DNS
rebinding advisory status before adjusting its priority or pin.
In `@scripts/generate_license_report.py`:
- Line 57: The script builds and runs nox via cmd_args (see the cmd_args
assignment) but then checks for "license-report.json" in the repo root; update
all checks and filename usages (the cmd_args invocation context and the post-run
verification logic around lines 73-78) to reference the actual output path
"docs/reports/json/license-report.json" (and ensure any path joins use the repo
root variable or pathlib to construct that path consistently), so the script
verifies the report at the location where the nox task writes it.
In `@scripts/run_semgrep_ci.py`:
- Around line 11-16: The current call to subprocess.run([uv, "run", nox, "-s",
"semgrep_ci"], check=True) can raise FileNotFoundError/OSError if "uv" or "nox"
are not installed; fix by either pre-checking with shutil.which for the uv and
nox executables (using the uv and nox variables) and exiting with a clear
message if missing, or by wrapping subprocess.run in a try/except that catches
FileNotFoundError/OSError and logs a user-friendly error before exiting; ensure
the error path uses the same uv/nox identifiers and returns non-zero status for
CI.
In `@src/flask/Dockerfile`:
- Line 9: The Dockerfile currently copies from a mutable image tag in the COPY
instruction ("COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/"), which
makes builds non-deterministic; update that COPY --from source to a pinned image
reference (either a specific semver tag like ghcr.io/astral-sh/uv:vX.Y.Z or an
immutable digest like ghcr.io/astral-sh/uv@sha256:...) so the uv artifact is
fetched from a fixed version, and commit the updated COPY line.
---
Outside diff comments:
In @.github/workflows/gh-pages.yml:
- Around line 28-31: The reusable workflow call is passing GCP_SA_JSON under the
`with` inputs but the target workflow expects it as a secret (declared under
`workflow_call.secrets`), causing an unexpected input error; remove GCP_SA_JSON
from the `with` block in the calling workflow and instead include it only under
the `secrets` mapping of the call (ensure the call uses `secrets: GCP_SA_JSON:
${{ secrets.GCP_SA_JSON }}`), referencing the GCP_SA_JSON symbol and the
`workflow_call.secrets` expectation so the reusable workflow (prepare-uv)
receives it as a secret.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 45f70a8c-4a43-4798-a152-e6c2c5eadb3f
⛔ Files ignored due to path filters (2)
poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (42)
.github/PULL_REQUEST_TEMPLATE.md.github/workflows/gh-pages.yml.github/workflows/license.yml.github/workflows/prepare-poetry.yml.github/workflows/prepare-uv.yml.github/workflows/release.yml.github/workflows/sbom.yml.github/workflows/security-pip-audit.yml.github/workflows/security-semgrep.yml.github/workflows/security-snyk.yml.github/workflows/security-trivy.yml.github/workflows/templates/assured-oss-auth.yml.github/workflows/templates/generate-matrix.yml.github/workflows/templates/lint-matrix.yml.github/workflows/templates/nox-template-matrix.yml.github/workflows/templates/nox-template.yml.github/workflows/templates/python-template-pip.yml.github/workflows/templates/test-matrix.yml.github/workflows/weekly-check.yml.pre-commit-config.yaml.readthedocs.yamlDockerfileMakefileREADME.mdcheck-system.shcodecov.ymldev-requirements.txtdocs/requirements-update.mdgenerate_requirements.shnoxfile.pypoetry.tomlpyproject.tomlrequirements.txtscripts/generate_license_report.pyscripts/lint-yaml.txtscripts/run_license_report.pyscripts/run_semgrep_ci.pysrc/flask/Dockerfiletests/error_handlers_test.pytests/models_test.pytests/security_test.pyvulture_whitelist.py
💤 Files with no reviewable changes (5)
- tests/models_test.py
- .github/workflows/prepare-poetry.yml
- tests/error_handlers_test.py
- poetry.toml
- tests/security_test.py
| jobs: | ||
| setup: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| python-version: ${{ steps.setup-python.outputs.python-version }} | ||
|
|
There was a problem hiding this comment.
Add explicit token permissions for least privilege.
Line 27 introduces a reusable workflow job without a permissions block, so token scope defaults may be broader than needed. Add a minimal explicit scope (for this workflow, typically contents: read).
Suggested patch
jobs:
setup:
+ permissions:
+ contents: read
runs-on: ubuntu-latest
outputs:
python-version: ${{ steps.setup-python.outputs.python-version }}📝 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.
| jobs: | |
| setup: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| python-version: ${{ steps.setup-python.outputs.python-version }} | |
| jobs: | |
| setup: | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| outputs: | |
| python-version: ${{ steps.setup-python.outputs.python-version }} |
🤖 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 @.github/workflows/prepare-uv.yml around lines 27 - 32, The reusable workflow
job "setup" currently lacks an explicit permissions block so the GITHUB_TOKEN
may have broader default scopes; add a minimal permissions stanza under the
"setup" job to restrict the token (e.g., set contents: read) to follow
least-privilege practice and ensure the job still has read access to repository
contents used by the workflow.
| inputs: "Python source code, dependencies, container images" | ||
| outputs: "SARIF reports and security labels" | ||
| dependencies: "Snyk, Node.js, Poetry, GitHub Actions" | ||
| dependencies: "Snyk, Node.js, uv, GitHub Actions" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify that this workflow contains unsupported top-level metadata keys
file=".github/workflows/security-snyk.yml"
echo "Inspecting: $file"
nl -ba "$file" | sed -n '1,40p'
echo
echo "Top-level candidate keys near header (excluding comments/blank lines):"
awk '
/^[[:space:]]*`#/` || /^[[:space:]]*$/ {next}
/^[^[:space:]][^:]*:/ {print NR ": " $0}
' "$file" | sed -n '1,20p'Repository: williaby/ledgerbase
Length of output: 978
Remove unsupported top-level dependencies metadata from .github/workflows/security-snyk.yml
dependencies at line 12 is not a valid GitHub Actions workflow top-level key (it appears in an extra metadata block alongside title, description, category, etc.), so workflow validation will fail.
dependencies: "Snyk, Node.js, uv, GitHub Actions"🧰 Tools
🪛 actionlint (1.7.12)
[error] 12-12: unexpected key "dependencies" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"
(syntax-check)
🤖 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 @.github/workflows/security-snyk.yml at line 12, Remove the unsupported
top-level metadata key "dependencies" from the workflow YAML (it's currently
alongside title/description/category) so the workflow validates; locate the
metadata block containing the "dependencies" key in the security-snyk workflow
and delete that line (or move its content into a supported field like
description or repository docs), ensuring only valid GitHub Actions top-level
keys remain.
| - name: Install Artifact Registry keyring backend | ||
| shell: bash | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install keyring keyrings.google-artifactregistry-auth | ||
| uv tool install keyring --with keyrings.google-artifactregistry-auth | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify all workflows that invoke `uv` also install/setup uv in the same file.
rg -n --type=yaml '\buv\s+(run|tool|sync|export|build)\b' .github/workflows .github/workflows/templates
rg -n --type=yaml 'astral-sh/setup-uv@' .github/workflows .github/workflows/templatesRepository: williaby/ledgerbase
Length of output: 5982
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the workflow template around the referenced lines
echo "=== .github/workflows/templates/assured-oss-auth.yml (around 46-50) ==="
nl -ba .github/workflows/templates/assured-oss-auth.yml | sed -n '35,70p'
# See whether any workflow calls this template
echo
echo "=== Workflows referencing assured-oss-auth.yml ==="
rg -n --type=yaml 'assured-oss-auth\.yml' .github/workflows .github/workflows/templates
# For those callers, check whether they install/setup uv
echo
echo "=== Callers: presence of astral-sh/setup-uv ==="
rg -n --type=yaml 'uses:\s*astral-sh/setup-uv@' .github/workflowsRepository: williaby/ledgerbase
Length of output: 196
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/templates/assured-oss-auth.yml"
echo "=== .github/workflows/templates/assured-oss-auth.yml (around 40-60) ==="
awk 'NR>=40 && NR<=60 {printf "%d:%s\n", NR, $0}' "$FILE"
echo
echo "=== Workflows referencing $FILE ==="
rg -n --type=yaml 'assured-oss-auth\.yml' .github/workflows .github/workflows/templates
echo
echo "=== Workflows that likely call the template via uses: .github/workflows/templates/assured-oss-auth.yml ==="
rg -n --type=yaml 'uses:\s*\.?github/workflows/templates/assured-oss-auth\.yml' .github/workflows
echo
echo "=== Check whether any callers install/setup uv (astral-sh/setup-uv) ==="
# Find candidate caller workflow files that reference the template, then scan them for setup-uv
callers=$(rg -l --type=yaml 'assured-oss-auth\.yml' .github/workflows || true)
if [ -z "${callers}" ]; then
echo "No callers found."
else
echo "$callers" | sed 's|^| - /|'
for f in $callers; do
echo "--- $f: setup-uv uses occurrences ---"
rg -n --type=yaml 'uses:\s*astral-sh/setup-uv@' "$f" || echo " (none)"
done
fiRepository: williaby/ledgerbase
Length of output: 1487
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Find any references to assured-oss-auth by name ==="
rg -n --type=yaml 'assured-oss-auth' .github/workflows .github/workflows/templates || true
echo
echo "=== Find where configure_index input is used ==="
rg -n --type=yaml 'configure_index' .github/workflows .github/workflows/templates || true
echo
echo "=== Find any uses: ...assured-oss-auth... patterns ==="
rg -n --type=yaml 'uses:\s*.*assured-oss-auth.*' .github/workflows .github/workflows/templates || true
echo
echo "=== Check whether this template is a reusable workflow (workflow_call) ==="
rg -n --type=yaml 'workflow_call' .github/workflows/templates/assured-oss-auth.yml || true
echo
echo "=== Check for inputs.credentials_json usage elsewhere ==="
rg -n --type=yaml 'credentials_json' .github/workflows .github/workflows/templates || trueRepository: williaby/ledgerbase
Length of output: 2561
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Search for any caller that mentions assured-oss or the template path ==="
rg -n --type=yaml 'assured-oss|aoss-python|UV_INDEX_URL|assured-oss-auth\.yml' .github/workflows .github/workflows/templates || true
echo
echo "=== Search for uses: with local path forms of the template ==="
rg -n --type=yaml 'uses:\s*.*assured-oss-auth\.yml' .github/workflows .github/workflows/templates || true
echo
echo "=== Search for setup-uv usage anywhere (to correlate with potential callers) ==="
rg -n --type=yaml 'uses:\s*astral-sh/setup-uv@' .github/workflows .github/workflows/templates || true
echo
echo "=== Specifically check prepare-uv.yml for uv setup and whether it invokes the template ==="
FILE=".github/workflows/prepare-uv.yml"
if [ -f "$FILE" ]; then
awk 'NR>=1 && NR<=140 {print NR ":" $0}' "$FILE" | sed -n '1,120p'
rg -n --type=yaml 'assured-oss-auth|setup-uv|uv tool install keyring|UV_INDEX_URL' "$FILE" || true
else
echo "Missing $FILE"
fiRepository: williaby/ledgerbase
Length of output: 4997
🏁 Script executed:
#!/bin/bash
# Verify this template (assured-oss-auth.yml) is self-contained: any `uv` usage in it should have setup-uv nearby/in-file.
rg -n --type=yaml '\buv\s+tool\s+install\b' .github/workflows/templates/assured-oss-auth.yml
rg -n --type=yaml 'uses:\s*astral-sh/setup-uv@' .github/workflows/templates/assured-oss-auth.ymlRepository: williaby/ledgerbase
Length of output: 145
Install uv via astral-sh/setup-uv in assured-oss-auth.yml
This reusable workflow (workflow_call) runs uv tool install ... (around lines 46-50) but contains no astral-sh/setup-uv step, so it depends on the runner already having uv.
Suggested patch
steps:
+ - name: Install uv
+ uses: astral-sh/setup-uv@v5
+
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ inputs.credentials_json }}
- name: Install Artifact Registry keyring backend
shell: bash
run: |
uv tool install keyring --with keyrings.google-artifactregistry-auth🤖 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 @.github/workflows/templates/assured-oss-auth.yml around lines 46 - 50, The
reusable workflow calls "uv tool install keyring --with
keyrings.google-artifactregistry-auth" in the step named "Install Artifact
Registry keyring backend" but never sets up uv; add a preceding step that uses
astral-sh/setup-uv to install/configure uv (before the step that runs the uv
command) so the "uv tool install keyring ..." command has the uv binary
available; ensure the added step runs on the same runner and platform, and
reference astral-sh/setup-uv as the installer for uv.
|
|
||
| - name: Run test session | ||
| run: poetry run nox -s ${{ inputs.session }} | ||
| run: uv run nox -s ${{ inputs.session }} |
There was a problem hiding this comment.
Prevent command injection at Line 34 by avoiding direct template expansion in run:.
Use an env var and quote it (same pattern used in other templates) before passing it to nox.
Suggested fix
- name: Run test session
- run: uv run nox -s ${{ inputs.session }}
+ env:
+ SESSION: ${{ inputs.session }}
+ run: uv run nox -s "$SESSION"📝 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.
| run: uv run nox -s ${{ inputs.session }} | |
| - name: Run test session | |
| env: | |
| SESSION: ${{ inputs.session }} | |
| run: uv run nox -s "$SESSION" |
🧰 Tools
🪛 zizmor (1.25.2)
[error] 34-34: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 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 @.github/workflows/templates/test-matrix.yml at line 34, Replace the direct
template expansion in the run step that uses "${{ inputs.session }}" with a
quoted environment variable: set an env key (e.g., SESSION) assigned from "${{
inputs.session }}" in the same step and then invoke the nox session with that
env variable quoted (e.g., run: uv run nox -s "$SESSION") so the command uses a
safely-quoted env var instead of inline template expansion; update the step that
currently contains "run: uv run nox -s ${{ inputs.session }}" to reference the
new SESSION env and keep quoting to prevent command injection.
|
|
||
| - name: Verify no public PyPI fallbacks | ||
| run: poetry run nox -s verify_assured | ||
| run: uv run nox -s verify_assured |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Is uvguaranteed to be preinstalled on GitHub-hostedubuntu-22.04 runners? Please cite the official runner image software list/documentation.
💡 Result:
No—uv is not guaranteed to be preinstalled on GitHub-hosted ubuntu-22.04 runners. GitHub documents that the list of “preinstalled software” for GitHub-owned runner VM images is maintained in the actions/runner-images repository, and that the exact included tools depend on the runner image version, with the included-software list updated after deployments [1]. For Ubuntu 22.04 specifically, the official runner-image documentation provides an “Installed Software” list. In the currently available Ubuntu 22.04 readme, uv is not listed among installed language runtimes/package-management/project-management tools [2]. Since the preinstalled toolset is “included tools” as documented for that runner image, absence from the official list means you should not assume uv will be present. Recommendation: install uv as part of your workflow (or use actions/setup-python + pipx/virtualenv tooling) rather than relying on it being present on the runner.
Citations:
- 1: https://docs.github.com/actions/using-github-hosted-runners/about-github-hosted-runners
- 2: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/weekly-check.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE"
exit 1
fi
echo "---- File: $FILE ----"
# Show the referenced lines + some surrounding context for each location mentioned
for n in 86 91 95 110 121 125 126 200; do
echo "## Context around line $n"
# Print 15 lines around each target line (clamp to file bounds)
start=$((n-8))
end=$((n+7))
sed -n "${start},${end}p" "$FILE" | nl -ba -w2 -s':'
echo
done
echo "---- Jobs overview (first 260 lines) ----"
sed -n '1,260p' "$FILE" | nl -ba -w2 -s':'Repository: williaby/ledgerbase
Length of output: 202
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/weekly-check.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE"
exit 1
fi
echo "---- File: $FILE ----"
# Print file with line numbers (limited to avoid huge output)
echo "---- First 260 lines (numbered) ----"
head -n 260 "$FILE" | cat -n
for n in 86 91 95 110 121 125 126 200; do
echo "## Context around line $n"
start=$((n-8))
if [ "$start" -lt 1 ]; then start=1; fi
end=$((n+7))
# Use numbered output from cat -n, then filter to the relevant range
# cat -n outputs: "<line_num>\t<content>"
awk -v s="$start" -v e="$end" '$1>=s && $1<=e{print}' "$FILE"
echo
doneRepository: williaby/ledgerbase
Length of output: 8051
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## Search for uv usage in the workflow"
rg -n "uv run|setup-uv|uv " .github/workflows/weekly-check.yml
echo "## Search for setup-uv across repo workflows"
rg -n "astral-sh/setup-uv" .github/workflows || true
echo "## Locate and inspect prepare-uv workflow"
PREP=".github/workflows/prepare-uv.yml"
if [ -f "$PREP" ]; then
echo "---- $PREP (head) ----"
head -n 200 "$PREP" | cat -n
else
echo "Missing $PREP"
exit 1
fiRepository: williaby/ledgerbase
Length of output: 4091
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/weekly-check.yml"
echo "## Any setup-uv usage in weekly-check.yml?"
rg -n "setup-uv" "$FILE" || true
echo
echo "## Context around jobs that run uv run"
for n in 70 80 112 130 188 196 198 200 205; do
echo "---- Around line $n ----"
start=$((n-15)); [ $start -lt 1 ] && start=1
end=$((n+15))
sed -n "${start},${end}p" "$FILE" | cat -n
echo
doneRepository: williaby/ledgerbase
Length of output: 8389
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/weekly-check.yml"
echo "---- All uv run occurrences ----"
rg -n "uv run" "$FILE" || true
echo
echo "---- All jobs in this workflow ----"
rg -n "^ [a-zA-Z0-9_-]+:" "$FILE" || trueRepository: williaby/ledgerbase
Length of output: 883
Make uv installation explicit in jobs that call uv run
uv isn’t guaranteed to be preinstalled on GitHub-hosted ubuntu-22.04 runners (it’s not listed in the Ubuntu 22.04 “Installed Software” for the runner image), and weekly-check.yml runs uv run in aikido-weekly-scan, code-hygiene-checks, and summary without any astral-sh/setup-uv step in those jobs—installing it in prepare won’t carry over across jobs.
Proposed workflow adjustment
aikido-weekly-scan:
steps:
- name: Checkout code
uses: actions/checkout@v4
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
code-hygiene-checks:
steps:
- name: Checkout code
uses: actions/checkout@v4
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
summary:
steps:
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
- name: Harden the runner (Audit outbound calls)
uses: step-security/harden-runner@v2.12.0🤖 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 @.github/workflows/weekly-check.yml at line 86, The workflow invokes "uv run"
in jobs that don't install uv, which can fail on ubuntu-22.04 runners; update
each job that runs "uv run" (aikido-weekly-scan, code-hygiene-checks, summary)
to explicitly install uv before running it—either add the astral-sh/setup-uv
action or a step that installs uv via pip/apt in those jobs' steps so the "run:
uv run nox -s verify_assured" command has uv available.
| # via | ||
| # click | ||
| # semgrep | ||
| cryptography==44.0.3 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check PyPI for the latest cryptography version and known vulnerabilities
echo "=== Latest cryptography version on PyPI ==="
curl -s https://pypi.org/pypi/cryptography/json | jq -r '.info.version'
echo -e "\n=== Checking for security advisories ==="
gh api graphql -f query='
{
securityVulnerabilities(first: 10, ecosystem: PIP, package: "cryptography") {
nodes {
advisory {
summary
severity
publishedAt
}
vulnerableVersionRange
firstPatchedVersion {
identifier
}
}
}
}'Repository: williaby/ledgerbase
Length of output: 2682
Update cryptography pin: cryptography==44.0.3 is vulnerable
requirements.txt(line 50) pinscryptography==44.0.3, which falls into known vulnerable ranges for:- SECT subgroup validation missing — HIGH, first patched 46.0.5
- Incomplete DNS name constraint enforcement — LOW, first patched 46.0.6
- Non-contiguous buffers overflow — MODERATE, first patched 46.0.7
- Latest on PyPI is 48.0.0; bump the pin to >=46.0.7 (or the latest) and rerun the security scan.
mcp==1.12.2DNS rebinding protection note still needs its advisory status checked before setting priority.
🤖 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 `@requirements.txt` at line 50, Update the pinned cryptography version in
requirements.txt: replace the vulnerable pin "cryptography==44.0.3" with a safe
minimum such as "cryptography>=46.0.7" (or set to the latest
"cryptography==48.0.0") and then rerun the security scan; also review the
"mcp==1.12.2" entry to verify its DNS rebinding advisory status before adjusting
its priority or pin.
| # werkzeug | ||
| marshmallow==3.26.2 | ||
| # via ledgerbase | ||
| mcp==1.12.2 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check PyPI for the latest mcp version and security advisories
echo "=== Latest mcp version on PyPI ==="
curl -s https://pypi.org/pypi/mcp/json | jq -r '.info.version'
echo -e "\n=== Checking for security advisories ==="
gh api graphql -f query='
{
securityVulnerabilities(first: 5, ecosystem: PIP, package: "mcp") {
nodes {
advisory {
summary
severity
publishedAt
}
vulnerableVersionRange
firstPatchedVersion {
identifier
}
}
}
}'Repository: williaby/ledgerbase
Length of output: 966
Update mcp pin to fix GHSA-9h52-p55h-vw2f (DNS rebinding protection bypass)
requirements.txt pins mcp==1.12.2, which falls in the vulnerable range < 1.23.0 for the HIGH-severity advisory “Model Context Protocol (MCP) Python SDK does not enable DNS rebinding protection by default”. Bump to mcp>=1.23.0 (or later).
🤖 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 `@requirements.txt` at line 138, The pinned dependency mcp==1.12.2 in
requirements.txt is vulnerable; update the mcp version specifier to at least
1.23.0 (e.g., mcp>=1.23.0) to address GHSA-9h52-p55h-vw2f, then regenerate any
lockfiles or dependency snapshots and run tests/CI to ensure compatibility with
the updated mcp package.
| sys.exit(1) | ||
|
|
||
| cmd_args = [poetry_cmd, "run", nox_cmd, "-s", "license_report"] | ||
| cmd_args = [uv_cmd, "run", nox_cmd, "-s", "license_report"] |
There was a problem hiding this comment.
Report path does not match the nox output location.
license_report writes to docs/reports/json/license-report.json, but this script only checks license-report.json in repo root, so it can fail after a successful run.
Proposed fix
-REPORT_PATH = Path("license-report.json")
+REPORT_PATH = Path("docs/reports/json/license-report.json")Also applies to: 73-78
🤖 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 `@scripts/generate_license_report.py` at line 57, The script builds and runs
nox via cmd_args (see the cmd_args assignment) but then checks for
"license-report.json" in the repo root; update all checks and filename usages
(the cmd_args invocation context and the post-run verification logic around
lines 73-78) to reference the actual output path
"docs/reports/json/license-report.json" (and ensure any path joins use the repo
root variable or pathlib to construct that path consistently), so the script
verifies the report at the location where the nox task writes it.
| uv = "uv" | ||
| nox = "nox" | ||
| subprocess.run( # nosec: B603 | ||
| [poetry, "run", nox, "-s", "semgrep_ci"], | ||
| [uv, "run", nox, "-s", "semgrep_ci"], | ||
| check=True, | ||
| ) |
There was a problem hiding this comment.
Handle missing uv/nox executables explicitly.
If either command is absent, this throws FileNotFoundError (not currently handled). Add pre-checks or catch OSError for clean failure.
🧰 Tools
🪛 Ruff (0.15.14)
[error] 13-13: subprocess call: check for execution of untrusted input
(S603)
🤖 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 `@scripts/run_semgrep_ci.py` around lines 11 - 16, The current call to
subprocess.run([uv, "run", nox, "-s", "semgrep_ci"], check=True) can raise
FileNotFoundError/OSError if "uv" or "nox" are not installed; fix by either
pre-checking with shutil.which for the uv and nox executables (using the uv and
nox variables) and exiting with a clear message if missing, or by wrapping
subprocess.run in a try/except that catches FileNotFoundError/OSError and logs a
user-friendly error before exiting; ensure the error path uses the same uv/nox
identifiers and returns non-zero status for CI.
|
|
||
| ENV PATH="$POETRY_HOME/bin:$PATH" | ||
| # Install uv (static binary from the official image) | ||
| COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ |
There was a problem hiding this comment.
Pin the uv source image in src/flask/Dockerfile
src/flask/Dockerfile copies uv from a mutable tag:
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/Replace ghcr.io/astral-sh/uv:latest with a fixed version and/or digest to keep builds deterministic.
🤖 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 `@src/flask/Dockerfile` at line 9, The Dockerfile currently copies from a
mutable image tag in the COPY instruction ("COPY
--from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/"), which makes builds
non-deterministic; update that COPY --from source to a pinned image reference
(either a specific semver tag like ghcr.io/astral-sh/uv:vX.Y.Z or an immutable
digest like ghcr.io/astral-sh/uv@sha256:...) so the uv artifact is fetched from
a fixed version, and commit the updated COPY line.
The org Code Quality job runs basedpyright, which had no configuration and so ran in strict default mode, reporting 36 advisory warnings on src and erroring on the loosely-typed nox/script tooling. There are zero real type errors in the package. Add [tool.basedpyright] with typeCheckingMode = "standard" and scope it to src (the shipped package), matching the previous mypy scope. The task runner, dev helpers, and one-off scripts are excluded, as they were never type-checked before. basedpyright now reports 0 errors for src, ., and a no-argument run. https://claude.ai/code/session_01SZ6zUJ8Abtzn2cJC76XHmm
FIPS Compatibility Check: PASSED
|
The org Code Quality job runs `uv run basedpyright`, which requires basedpyright to be a project dependency. It was not listed, so `uv run basedpyright` failed to spawn (exit code 2) before any type checking ran, which is why the earlier [tool.basedpyright] config alone had no effect on CI. Add basedpyright to the dev dependency group so the gate executes. With the [tool.basedpyright] standard-mode config scoped to the package source, it now reports 0 errors for both `basedpyright src` and a no-argument run. https://claude.ai/code/session_01SZ6zUJ8Abtzn2cJC76XHmm
FIPS Compatibility Check: PASSED
|
Summary
Migrates
williaby/ledgerbasefrom Poetry to uv (PEP 621).pyproject.tomlnow uses a[project]table with PEP 735[dependency-groups], the build backend is hatchling, and every Poetry invocation across CI, tooling, and docs is replaced with uv.uv.lockis the single source of truth;poetry.lockandpoetry.tomlare removed.Locking resolves against PyPI in this change. The Assured OSS private index is re-expressed for uv in the reusable workflow (
UV_INDEX_URLplus thekeyrings.google-artifactregistry-authbackend via--keyring-provider subprocess); wiring[[tool.uv.index]]intopyproject.tomlis left as a follow-up because it needs GCP credentials that are not available outside CI.Acceptance criteria
pyproject.tomlhas a[project]table; no[tool.poetry*]tables remain.uv.lockpresent;poetry.lockdeleted.uv sync/uv run(no poetry).renovate.jsonenabledManagersincludespep621(not poetry, not uv).renovate-config-validatorpasses.Verification
grep -ri "poetry" pyproject.toml .github/ Makefile CONTRIBUTING.md README.mduv lock --lockeduv run python -c "import sys; print(sys.version)"uv run pytestrenovate-config-validator renovate.jsonCode-quality gates under uv:
uv run ruff checkclean on all changed filesuv run mypy src/ledgerbasereports success, no issuesuv run bandit -r src/ledgerbasecleanuv run nox -rs bandit_scansucceeds end to end, which validates the nox + uv install path the pre-commit hooks rely onuv run codespell, trailing-whitespace, and end-of-file-fixer pass on changed filesNotes on pre-commit scope
The pre-commit hooks are rewired from
poetry runtouv runand the config validates. The deterministic code gates (ruff, mypy, bandit, codespell) pass under uv. A fullpre-commit run --all-filesadditionally triggers thelint_othernox session, which runsprettier --writeandmarkdownlint --fixacross the whole repository (pre-existing behavior, identical under Poetry) and would reformat many files unrelated to this migration, so it was intentionally not run repo-wide here. The only standalone markdownlint finding is a pre-existingMD060in the README security-status table (untouched by this change), surfaced by a newer markdownlint than the repo previously used.What changed
pyproject.toml: PEP 621[project]plus PEP 735[dependency-groups] dev; caret/tilde constraints converted to PEP 508;requires-python = ">=3.11,<4.0"; hatchling backend withpackages = ["src/ledgerbase"];noxmoved to dev-only.uv.lockadded;poetry.lockandpoetry.tomldeleted;requirements.txtanddev-requirements.txtregenerated fromuv.lock.noxfile.py: dependency install viauv sync;uv lock --locked/uv export/uv buildreplace the Poetry equivalents..pre-commit-config.yaml: hooks run throughuv run.prepare-poetry.ymlrenamed toprepare-uv.ymlusingastral-sh/setup-uv; allpoetry runsteps changed touv run.Dockerfile,src/flask/Dockerfile,Makefile,README.md, helper scripts,.readthedocs.yaml: migrated to uv.renovate.jsonadded, enabling thepep621,github-actions,dockerfile, andpre-commitmanagers.pytest.assume(new=True)) so the suite passes.Closes #149, #147, #146, #136
Generated by Claude Code
Summary by CodeRabbit
Documentation
Chores