Skip to content

Performance improvements and harden crypto - #190

Merged
pbrassel merged 25 commits into
mainfrom
develop
Aug 7, 2026
Merged

Performance improvements and harden crypto#190
pbrassel merged 25 commits into
mainfrom
develop

Conversation

@pbrassel

@pbrassel pbrassel commented Aug 7, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added a service version endpoint.
    • Added improved project metadata and README-based version information.
  • Improvements
    • Simplified Hub authentication to use client credentials.
    • Strengthened encrypted data handling and key validation.
    • Improved responsiveness and resource cleanup during storage and network operations.
  • Documentation
    • Updated setup instructions, configuration examples, badges, and authentication guidance.
  • Release
    • Updated the release version to 0.2.0.

pbrassel added 16 commits July 28, 2026 13:48
* feat: raise a type error if non ecdh keys are loaded via the helper functions

* docs: add comments on initialization vectors

* build(deps): update dependencies

* test(fix): adapt fixtures to the hub's new camel case naming convention

* test: close clients on fixture teardown

* refactor: do not make the chunk size configurable

* refactor: use a kdf instead of the raw shared secret
…in up and save them in the app's state

Clients used to be initialized inside dependencies for every request without being properly closed. This commit also addresses the new camel case Hub API.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR simplifies Hub authentication, centralizes initialized services in AppState, updates cryptographic processing, manages database and client lifecycles, moves blocking storage work to thread pools, adds version metadata, and updates test infrastructure and project tooling.

Changes

Service architecture and integration update

Layer / File(s) Summary
Configuration, cryptography, and project metadata
project/config.py, project/crypto.py, project/models.py, project/utils.py, project/version.py, pyproject.toml
Sensitive fields use secret types. Password authentication and configurable chunk sizing are removed. ECDH validation, PEM normalization, HKDF derivation, project metadata models, and version metadata are added.
Application state and resource lifecycle
project/server.py, project/dependencies.py, project/migrations/scripts/*, project/main.py
Startup initializes application resources and stores them in AppState. Dependency providers retrieve those resources. Migration scripts use managed router lifecycles.
Storage, encryption, and result routing
project/routers/final.py, project/routers/intermediate.py, project/routers/local.py
Storage queries use updated filter names. Blocking storage operations run in thread pools. Intermediate streaming uses crypto.CHUNK_SIZE, and external responses close explicitly.
Test environment and validation coverage
tests/common/*, tests/conftest.py, tests/test_crypto.py, tests/test_final.py, tests/test_intermediate.py, tests/test_local.py, tests/test_local_tagged.py, tests/test_main.py, tests/test_version.py
Fixtures configure containers, clients, timeouts, dependency overrides, and OpenDP features. Tests cover updated authentication, filters, encryption, ECDH validation, and the version endpoint.
Tooling and project configuration
.env.example, .github/actions/setup-poetry/action.yml, Dockerfile, README.md, docker-compose.yml, pyproject.toml
Poetry and dependency versions are updated. Test variables and authentication documentation are revised. Docker configuration removes the client-flow setting.

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

Sequence Diagram(s)

sequenceDiagram
  participant Server
  participant AppState
  participant DependencyProvider
  participant StorageRouter
  participant Hub
  Server->>AppState: initialize configured clients and database
  StorageRouter->>DependencyProvider: request storage and Hub clients
  DependencyProvider->>AppState: retrieve initialized services
  StorageRouter->>StorageRouter: execute blocking storage work in thread pool
  StorageRouter->>Hub: upload or retrieve result data
  Server->>AppState: close resources during shutdown
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes performance changes and cryptographic hardening included in the pull request.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 (2)
.env.example (1)

6-7: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Provide the required Hub client credentials for the test migration service.

Settings() requires HUB__AUTH__ID and HUB__AUTH__SECRET; tests/docker-compose.yml only defines the old HUB__AUTH__FLOW / HUB__AUTH__USERNAME / HUB__AUTH__PASSWORD values. Add the required credentials or use a migration-specific settings/model path that does not require Hub client 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 @.env.example around lines 6 - 7, Update the test migration configuration
represented by Settings() and tests/docker-compose.yml to provide HUB__AUTH__ID
and HUB__AUTH__SECRET, replacing or supplementing the obsolete HUB__AUTH__FLOW,
HUB__AUTH__USERNAME, and HUB__AUTH__PASSWORD values so the migration service has
the required Hub client credentials.

Source: MCP tools

project/routers/final.py (1)

66-73: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Both final-result uploads still block the event loop.

project/routers/intermediate.py moved storage_client.upload_to_bucket into run_in_threadpool. These two routes did not get the same treatment. Both handlers are async def, and find_analysis_buckets and upload_to_bucket are synchronous network calls.

Line 113 passes file.file directly. The whole upload therefore runs on the event loop and stalls every other request for its duration. This contradicts the stated performance goal of the PR.

Apply the same run_in_threadpool treatment used in project/routers/intermediate.py lines 90-102.

♻️ Proposed change for `submit_final_result_to_hub`
+from fastapi.concurrency import run_in_threadpool
+
     # upload to remote
-    bucket_file_lst = storage_client.upload_to_bucket(
+    bucket_file_lst = await run_in_threadpool(
+        storage_client.upload_to_bucket,
         analysis_bucket.bucket_id,
         {
             "file_name": file.filename,
             "content": file.file,
             "content_type": file.content_type or "application/octet-stream",
         },
     )

Also applies to: 109-116

🤖 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 `@project/routers/final.py` around lines 66 - 73, Update both final-result
upload paths in the async handlers, including submit_final_result_to_hub, to
invoke the synchronous storage_client.upload_to_bucket through run_in_threadpool
as done in intermediate.py. Ensure all upload arguments, including file.file in
the second path, are passed to the threadpool call so no synchronous network
upload runs on the event loop.
🧹 Nitpick comments (6)
tests/test_intermediate.py (1)

37-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert that the blob spans several chunks.

The patch sets CHUNK_SIZE to 64 so the test exercises multi-chunk encryption and decryption. AESGCMEncryptingStream subtracts the IV and tag overhead, so each record carries roughly 36 plaintext bytes.

The test does not check the size of blob. If the blob fixture later returns a small value, the multi-chunk path stops being covered and the test still passes. Add an explicit assertion to lock the intent.

💚 Proposed addition
     monkeypatch.setattr(crypto, "CHUNK_SIZE", 64)
+    assert len(blob) > 64 * 3, "Blob must span several chunks to exercise chunked encryption."
🤖 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 `@tests/test_intermediate.py` around lines 37 - 38, Add an explicit assertion
in the test using the blob fixture to verify its length exceeds the effective
per-record plaintext capacity, ensuring encryption and decryption exercise
multiple chunks. Keep the existing CHUNK_SIZE monkeypatch and assertions
unchanged.
project/dependencies.py (1)

57-58: 🚀 Performance & Scalability | 🔵 Trivial

Offer: cache the JWKS fetch.

The TODO is correct. Every authenticated request now performs an outbound HTTPS round trip to the auth provider before the route runs. This adds latency to each request and couples request availability to the auth provider.

A time-bounded cache with refresh on unknown kid removes the per-request fetch. Do you want me to open an issue or draft the cached provider?

🤖 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 `@project/dependencies.py` around lines 57 - 58, Update get_auth_jwks to cache
the fetched JWKS for a bounded duration instead of requesting it on every
authenticated request, while preserving access to current keys. Ensure unknown
kid handling triggers a refresh before rejecting the token, and remove the
obsolete TODO once caching is implemented.
project/server.py (2)

153-156: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the module logger.

Line 156 calls logging.info, which writes to the root logger. The rest of lifespan uses logger. The message can be dropped or formatted differently because of this.

♻️ Proposed fix
-    logging.info("Enabled OpenDP's 'floating-point' and 'contrib' features.")
+    logger.info("Enabled OpenDP's 'floating-point' and 'contrib' features.")
🤖 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 `@project/server.py` around lines 153 - 156, Update the feature-enablement log
in lifespan to call the module’s existing logger instead of the root logging
module, preserving the current message and surrounding enable_features calls.

53-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

A single proxy setting is applied to both schemes.

If only s.proxy.http_url is set, the code also routes https:// traffic through it, and the reverse case applies too. This is a valid convention, but it is not obvious from the configuration names. A user who sets only an HTTP proxy may not expect HTTPS traffic to use it.

Add a short comment that states this fallback, and confirm the README describes it.

🤖 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 `@project/server.py` around lines 53 - 56, Add a concise comment beside the
proxy selection in the http/https transport setup explaining that when only one
of s.proxy.http_url or s.proxy.https_url is configured, that proxy is used for
both schemes. Update the README’s proxy configuration documentation to
explicitly describe this fallback behavior.
project/migrations/scripts/router.py (1)

10-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Importing init_db from project.server pulls the whole application into the migration entrypoint.

project/server.py imports FastAPI, the routers, MinIO, truststore, OpenDP, and project.version. project.version reads pyproject.toml at import time. A migration run therefore fails if any of those imports fails, even though a migration needs only the Peewee proxy.

Move init_db to a neutral module such as project/crud.py or a new project/db.py, and import it from there in both project/server.py and this file.

🤖 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 `@project/migrations/scripts/router.py` around lines 10 - 12, Move the init_db
definition out of project.server into a neutral database module such as
project.db or project.crud, then update both the server module and the migration
entrypoint to import init_db from that module. Ensure the migration script no
longer imports project.server or its application dependencies.
tests/test_crypto.py (1)

19-24: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Generate the non-EC keys lazily.

Lines 20-23 run at module import. dsa.generate_private_key(key_size=2_048) generates new DSA parameters and is slow, often several seconds. rsa.generate_private_key adds more time. This cost applies to every collection of the test suite, even when no test in this module is selected.

Parametrize over factory callables and build the key inside the test instead.

♻️ Proposed refactor
-NON_ECDH_PRIVATE_KEYS = (
-    rsa.generate_private_key(public_exponent=65_537, key_size=2_048),
-    ed448.Ed448PrivateKey.generate(),
-    dsa.generate_private_key(key_size=2_048),
-    x448.X448PrivateKey.generate(),
-)
+NON_ECDH_PRIVATE_KEY_FACTORIES = (
+    pytest.param(lambda: rsa.generate_private_key(public_exponent=65_537, key_size=2_048), id="rsa"),
+    pytest.param(ed448.Ed448PrivateKey.generate, id="ed448"),
+    pytest.param(lambda: dsa.generate_private_key(key_size=2_048), id="dsa"),
+    pytest.param(x448.X448PrivateKey.generate, id="x448"),
+)

Then update both parametrized tests:

-@pytest.mark.parametrize("private_key", NON_ECDH_PRIVATE_KEYS)
-def test_load_ecdh_private_key_type_error(private_key):
+@pytest.mark.parametrize("private_key_factory", NON_ECDH_PRIVATE_KEY_FACTORIES)
+def test_load_ecdh_private_key_type_error(private_key_factory):
     with pytest.raises(TypeError) as e:
-        load_ecdh_private_key(_get_private_key_in_pem_format(private_key))
+        load_ecdh_private_key(_get_private_key_in_pem_format(private_key_factory()))
 
     assert str(e.value) == "Expected an EC private key."

This also produces readable test ids instead of private_key0.

🤖 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 `@tests/test_crypto.py` around lines 19 - 24, Replace eager key instances in
NON_ECDH_PRIVATE_KEYS with factory callables that generate each private key
lazily. Update both parametrized tests to invoke the selected factory inside the
test, and assign descriptive parameter IDs so test output names identify the key
type instead of using default indices.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.env.example:
- Around line 28-29: Remove the duplicate PYTEST__USE_TESTCONTAINERS setup path
by keeping the setting in .env.example and updating the README setup
instructions to stop appending the same key after copying the file.

In @.github/actions/setup-poetry/action.yml:
- Line 12: Update the Poetry setup configuration around the default version
value so the documented poetry shell workflow remains supported: retain or
install poetry-plugin-shell alongside Poetry, or revise the README instructions
to use a supported poetry run flame-storage command. Keep the setup and
documentation behavior consistent.

In `@project/crypto.py`:
- Around line 87-94: Make the crypto-format change backward-compatible across
exchange_ecdh_shared_secret(), encrypt_default(), decrypt_default(), and
AESGCMEncryptingStream: either require coordinated upgrades for every encrypting
and decrypting node, or add a format/version marker to encrypted streams so
readers select the legacy raw ECDH key material versus the new HKDF-derived key
material. Ensure both one-shot and streaming paths preserve interoperability
with existing ciphertext.

In `@project/dependencies.py`:
- Around line 72-75: Update the HTTPException raise in the dependency error
handler to explicitly chain from None, hiding the transport exception from the
client response while preserving the traceback captured by logger.exception.
- Around line 65-68: Update get_auth_jwks to construct the JWKS httpx client
through the shared client-building helper, passing settings so it applies
_build_ssl_context()/extra_ca_certs and _build_proxy_mounts()/settings.proxy.
Configure an explicit timeout on the client or request, while preserving the
existing JWKS fetch and error handling.
- Around line 25-26: Update get_app_state to read the application-level
app_state assigned by the server through request.app instead of
request.state.app_state, preserving the AppState return contract for dependent
routes.

In `@project/migrations/scripts/router.py`:
- Around line 32-43: Move the init_db(db) call inside the try block in the
router setup so db.close() in the finally clause runs even when initialization
raises. Keep the existing Router construction and migration configuration
unchanged.

In `@project/routers/final.py`:
- Line 56: The Hub bucket filters use the wrong camelCase field; update the
filter dictionaries in project/routers/final.py lines 56-56 and 98-98 and
project/routers/intermediate.py line 77-77 to use analysis_id for the analysis
identifier, preserving the existing client_id values and RESULT type filter.

In `@project/routers/intermediate.py`:
- Around line 150-151: Update the async handler around get_bucket_file,
stream_bucket_file, and get_remote_node_public_key to execute all synchronous
network calls via run_in_threadpool. For the stream_bucket_file probe, create
and consume the generator within the worker and explicitly close it after
retrieving the first chunk, including cleanup when retrieval raises.
- Around line 163-164: Update the chunked download/decryption loop in the
intermediate router to buffer data from stream_bucket_file until a complete
crypto.CHUNK_SIZE encryption record is assembled before calling
crypto.decrypt_default. Preserve leftover bytes across iterations, decrypt the
final partial record separately after the stream ends, and yield decrypted
output without truncating valid ciphertext.

In `@project/routers/local.py`:
- Around line 466-479: Move the try/finally in the surrounding request handler
to begin immediately after _get_object_from_s3 returns, keeping the filename
lookup and UploadFile creation inside the try block. Preserve the existing
submit_intermediate_result_to_hub call, and ensure s3_response.close() and
s3_response.release_conn() execute for failures in result.count(), result.get(),
or subsequent processing.
- Around line 392-413: Update the _iter_response generator to call response.read
with a fixed chunk size, yielding each bounded chunk until the stream is
exhausted; retain the existing cleanup of close and release_conn. Add coverage
using an object larger than the chosen chunk size to verify multiple
StreamingResponse chunks are produced without reading the full body at once.

In `@project/server.py`:
- Around line 91-96: Update the application lifespan resource management around
auth_flow_client and the existing shutdown block to use a single ExitStack,
registering auth_flow_client, postgres, core_client, and storage_client for
cleanup. Wrap startup work before yield in try/finally so resources are closed
both on normal shutdown and when minio.bucket_exists, init_db,
_get_ecdh_private_key, or _get_node_id raises; preserve the existing yielded
application behavior.

In `@project/version.py`:
- Around line 4-5: Remove the __version_info__ assignment unless it is required
by existing callers; otherwise replace its integer-splitting logic with a PEP
440-aware version parser so valid local and dev versions loaded by __version__
do not raise ValueError.

---

Outside diff comments:
In @.env.example:
- Around line 6-7: Update the test migration configuration represented by
Settings() and tests/docker-compose.yml to provide HUB__AUTH__ID and
HUB__AUTH__SECRET, replacing or supplementing the obsolete HUB__AUTH__FLOW,
HUB__AUTH__USERNAME, and HUB__AUTH__PASSWORD values so the migration service has
the required Hub client credentials.

In `@project/routers/final.py`:
- Around line 66-73: Update both final-result upload paths in the async
handlers, including submit_final_result_to_hub, to invoke the synchronous
storage_client.upload_to_bucket through run_in_threadpool as done in
intermediate.py. Ensure all upload arguments, including file.file in the second
path, are passed to the threadpool call so no synchronous network upload runs on
the event loop.

---

Nitpick comments:
In `@project/dependencies.py`:
- Around line 57-58: Update get_auth_jwks to cache the fetched JWKS for a
bounded duration instead of requesting it on every authenticated request, while
preserving access to current keys. Ensure unknown kid handling triggers a
refresh before rejecting the token, and remove the obsolete TODO once caching is
implemented.

In `@project/migrations/scripts/router.py`:
- Around line 10-12: Move the init_db definition out of project.server into a
neutral database module such as project.db or project.crud, then update both the
server module and the migration entrypoint to import init_db from that module.
Ensure the migration script no longer imports project.server or its application
dependencies.

In `@project/server.py`:
- Around line 153-156: Update the feature-enablement log in lifespan to call the
module’s existing logger instead of the root logging module, preserving the
current message and surrounding enable_features calls.
- Around line 53-56: Add a concise comment beside the proxy selection in the
http/https transport setup explaining that when only one of s.proxy.http_url or
s.proxy.https_url is configured, that proxy is used for both schemes. Update the
README’s proxy configuration documentation to explicitly describe this fallback
behavior.

In `@tests/test_crypto.py`:
- Around line 19-24: Replace eager key instances in NON_ECDH_PRIVATE_KEYS with
factory callables that generate each private key lazily. Update both
parametrized tests to invoke the selected factory inside the test, and assign
descriptive parameter IDs so test output names identify the key type instead of
using default indices.

In `@tests/test_intermediate.py`:
- Around line 37-38: Add an explicit assertion in the test using the blob
fixture to verify its length exceeds the effective per-record plaintext
capacity, ensuring encryption and decryption exercise multiple chunks. Keep the
existing CHUNK_SIZE monkeypatch and assertions unchanged.
🪄 Autofix

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 Plus

Run ID: 21b35dd9-cf32-4fc4-b052-9ef5ff492441

📥 Commits

Reviewing files that changed from the base of the PR and between 98e2db9 and 77ff4a0.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • .env.example
  • .github/actions/setup-poetry/action.yml
  • Dockerfile
  • README.md
  • docker-compose.yml
  • project/config.py
  • project/crypto.py
  • project/dependencies.py
  • project/main.py
  • project/migrations/scripts/create_migration.py
  • project/migrations/scripts/migrate.py
  • project/migrations/scripts/router.py
  • project/models.py
  • project/routers/final.py
  • project/routers/intermediate.py
  • project/routers/local.py
  • project/server.py
  • project/utils.py
  • project/version.py
  • pyproject.toml
  • tests/common/auth.py
  • tests/common/env.py
  • tests/common/helpers.py
  • tests/common/rest.py
  • tests/conftest.py
  • tests/test_config.py
  • tests/test_crypto.py
  • tests/test_final.py
  • tests/test_intermediate.py
  • tests/test_local.py
  • tests/test_local_tagged.py
  • tests/test_main.py
  • tests/test_version.py
💤 Files with no reviewable changes (3)
  • tests/common/env.py
  • tests/test_config.py
  • docker-compose.yml

Comment thread .env.example
Comment thread .github/actions/setup-poetry/action.yml
Comment thread project/crypto.py
Comment thread project/dependencies.py Outdated
Comment thread project/dependencies.py
Comment thread project/routers/intermediate.py
Comment thread project/routers/local.py
Comment thread project/routers/local.py
Comment thread project/server.py Outdated
Comment thread project/version.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

80-94: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fix the non-Testcontainers test setup before merging.

When PYTEST__USE_TESTCONTAINERS=0, the README directs users to the compose-based setup below. The migrate service in tests/docker-compose.yml still supplies HUB__AUTH__FLOW, HUB__AUTH__USERNAME, and HUB__AUTH__PASSWORD, but the current Settings model requires HUB__AUTH__ID and HUB__AUTH__SECRET. init_router() creates Settings() before migrations run, so this documented path fails with missing Hub authentication settings. Update tests/docker-compose.yml or make migrations independent of Hub authentication. (raw.githubusercontent.com)

🤖 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 `@README.md` around lines 80 - 94, Fix the non-Testcontainers setup by updating
the migrate service configuration in tests/docker-compose.yml to provide the
HUB__AUTH__ID and HUB__AUTH__SECRET values required by Settings during
init_router(), or change the migration initialization path to avoid requiring
Hub authentication. Ensure the documented PYTEST__USE_TESTCONTAINERS=0 flow
completes migrations without missing Hub settings.

Source: MCP tools

🧹 Nitpick comments (1)
README.md (1)

26-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clear the MD014 warning in the command block.

Line 26 uses a $ prompt, but the block shows no command output. Remove the $ prompts from the commands, or add representative output.

🤖 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 `@README.md` at line 26, Remove the "$ " shell prompts from the command block
containing "poetry run flame-storage" in README.md, since no command output is
shown.

Source: Linters/SAST tools

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

Outside diff comments:
In `@README.md`:
- Around line 80-94: Fix the non-Testcontainers setup by updating the migrate
service configuration in tests/docker-compose.yml to provide the HUB__AUTH__ID
and HUB__AUTH__SECRET values required by Settings during init_router(), or
change the migration initialization path to avoid requiring Hub authentication.
Ensure the documented PYTEST__USE_TESTCONTAINERS=0 flow completes migrations
without missing Hub settings.

---

Nitpick comments:
In `@README.md`:
- Line 26: Remove the "$ " shell prompts from the command block containing
"poetry run flame-storage" in README.md, since no command output is shown.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d82064e8-2579-4eba-8303-d38a93f98ded

📥 Commits

Reviewing files that changed from the base of the PR and between 77ff4a0 and 93ce766.

📒 Files selected for processing (6)
  • README.md
  • project/dependencies.py
  • project/migrations/scripts/router.py
  • project/routers/local.py
  • project/server.py
  • project/version.py
💤 Files with no reviewable changes (1)
  • project/version.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • project/migrations/scripts/router.py
  • project/server.py
  • project/routers/local.py
  • project/dependencies.py

@pbrassel
pbrassel merged commit 0788b83 into main Aug 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant