Bump v0.8.2: harden SPARQL queries, add circuit breakers, strengthen …#9
Conversation
…draft audit chain, and add ontology drift scaffold Security & resilience hardening based on ToxMCP Audit Reviewed v2: - Phase 1 (AOP-01): TemplateCatalog.render_safe() with escaped literals, validated URIs, and separated trusted structural fragments. All adapters migrated from unsafe .format() interpolation. - Phase 2 (AOP-02): Per-endpoint circuit breaker + exponential backoff with jitter in SparqlClient._dispatch(). - Phase 3 (AOP-03/AOP-04): Mandatory checksums, checksum_algorithm field, ElectronicSignature support, and hardened verify_audit_chain(). - Phase 4 (AOP-05): Configurable CurieResolver, AOP_CURIE_RESOLVER, and OntologyMigrator scaffold for version-driven migrations. README updated with v0.8.2 changelog. 231 unit tests passing.
There was a problem hiding this comment.
Pull request overview
This PR bumps the project to v0.8.2 and implements security/resilience hardening across SPARQL query construction, endpoint dispatch reliability, draft audit-chain verification, and semantic identifier/migration scaffolding.
Changes:
- Introduces
TemplateCatalog.render_safe()and migrates adapters/templates away from unsafe string interpolation. - Adds per-endpoint circuit breaker behavior and exponential backoff retry logic to the SPARQL client.
- Strengthens draft audit-chain metadata (checksums + algorithm + signatures) and adds CURIE resolution + ontology migration scaffolding.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_sparql_client.py | Adds unit tests for safe template rendering, circuit breaker behavior, retry backoff, and failover. |
| tests/unit/test_curie_resolver.py | Adds tests for CurieResolver and OntologyMigrator behavior. |
| tests/unit/test_audit_utils.py | Extends audit-chain tests for algorithm support, chain integrity, and signatures. |
| src/services/draft_store/repository.py | Ensures checksum_algorithm defaults are set during version initialization/appends. |
| src/services/draft_store/model.py | Adds ElectronicSignature; makes checksum fields mandatory strings; adds checksum_algorithm + signatures. |
| src/services/draft_store/init.py | Exports ElectronicSignature from the draft_store package. |
| src/server/version.py | Updates fallback application version to 0.8.2. |
| src/semantic/migration.py | Adds OntologyMigrator + migration pathfinding and term mapping. |
| src/semantic/curie_service.py | Adds CurieResolver, AOP_CURIE_RESOLVER, and CurieService.normalize_safe(). |
| src/semantic/init.py | Re-exports new semantic utilities (CurieResolver, AOP_CURIE_RESOLVER). |
| src/instrumentation/audit.py | Hardens verify_audit_chain() with algorithm support checks and stricter chain validation. |
| src/adapters/templates/aop_db/map_chemical_to_aops.sparql | Updates template placeholders to support safe URI/literal binding for CAS queries. |
| src/adapters/sparql_client.py | Implements circuit breaker + retry backoff; adds safe template rendering helpers. |
| src/adapters/aop_wiki.py | Switches template rendering to render_safe() and replaces hardcoded IRI→CURIE logic with resolver. |
| src/adapters/aop_db.py | Switches template rendering to render_safe(), adds CAS URI quoting, and uses resolver for CURIEs. |
| src/adapters/init.py | Exposes circuit breaker types via adapters package exports. |
| pyproject.toml | Bumps package version to 0.8.2. |
| README.md | Adds v0.8.2 changelog describing the new security/resilience features. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| failure_threshold: int = 5 | ||
| recovery_timeout: float = 30.0 | ||
| half_open_max_calls: int = 1 | ||
| success_threshold: int = 2 |
There was a problem hiding this comment.
The default circuit breaker config appears internally inconsistent: half_open_max_calls=1 but success_threshold=2. With these defaults, a breaker that transitions to HALF_OPEN can never accumulate enough successes to close (the 2nd HALF_OPEN call is rejected), so it may get stuck HALF_OPEN. Consider setting success_threshold <= half_open_max_calls (e.g., default success_threshold=1) or resetting half_open_calls after each HALF_OPEN attempt.
| success_threshold: int = 2 | |
| success_threshold: int = 1 |
- Fix circuit breaker defaults: success_threshold=1 to match half_open_max_calls=1. - Reset success_count when transitioning OPEN -> HALF_OPEN. - Exclude SparqlQueryError (4xx) from circuit breaker failure counting. - Strengthen URI validation to reject SPARQL-breaking characters. - Escape newline, carriage return, and tab in SPARQL literal rendering. - Remove dangling inchikey parameter from map_chemical_to_aops. - Make backoff test deterministic with monkeypatched sleep and random.uniform. - All 231 unit tests passing.
…draft audit chain, and add ontology drift scaffold
Security & resilience hardening based on ToxMCP Audit Reviewed v2:
README updated with v0.8.2 changelog. 231 unit tests passing.