Skip to content

Commit 21881ed

Browse files
committed
Remove Python fallback paths
Signed-off-by: lucarlig <luca.carlig@ibm.com>
1 parent bbb0eb2 commit 21881ed

26 files changed

Lines changed: 227 additions & 688 deletions

File tree

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Monorepo for managed CPEX plugins that are implemented in Rust and published as Python packages.
44

5+
## Runtime Requirements
6+
7+
These packages target the CPEX release-candidate framework API and intentionally depend on `cpex>=0.1.0rc1,<0.2`. The RC dependency is the migration target for this repository; it is not an accidental pre-stable dependency.
8+
9+
Rust plugin packages require their compiled PyO3 extension at import/runtime. They do not ship Python fallback implementations for missing Rust extensions.
10+
511
## Layout
612

713
Managed plugins live under `plugins/rust/python-package/<slug>/`.
@@ -41,7 +47,7 @@ See [TESTING.md](TESTING.md) for detailed testing guidelines and cross-repositor
4147

4248
### Current Architecture (Transitional)
4349

44-
Plugins are implemented as **pure Python** or **pure Rust** — each plugin uses one language for its logic. There is no dual-path where a plugin ships both Rust and Python implementations with a Rust fallback.
50+
Plugins are implemented as **pure Python** or **pure Rust** — each plugin uses one language for its logic. There is no dual-path where a plugin ships both Rust and Python implementations with a Python fallback for a missing Rust extension.
4551

4652
For Rust plugins, the current approach wraps the Rust implementation with PyO3/maturin bindings as a packaging layer:
4753
- Plugin logic implemented entirely in Rust
@@ -145,4 +151,4 @@ See [TESTING.md](TESTING.md) for cross-repository testing workflow.
145151
- [DEVELOPING.md](DEVELOPING.md) - Plugin development workflows
146152
- [TESTING.md](TESTING.md) - Testing strategy and guidelines
147153
- [CONTRIBUTING.md](CONTRIBUTING.md) - Contribution guidelines
148-
- [SECURITY.md](SECURITY.md) - Security policy
154+
- [SECURITY.md](SECURITY.md) - Security policy

plugins/rust/python-package/encoded_exfil_detection/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ High-performance encoded exfiltration detection for ContextForge and MCP Gateway
2323
make install
2424
```
2525

26+
## Runtime Requirements
27+
28+
This plugin depends on `cpex>=0.1.0rc1,<0.2` and imports hook models from `cpex.framework`. The compiled Rust extension is mandatory; there is no Python fallback implementation.
29+
2630
## Usage
2731

2832
The plugin scans these hooks:

plugins/rust/python-package/pii_filter/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ High-performance PII detection and masking library for ContextForge.
2020
make install
2121
```
2222

23+
## Runtime Requirements
24+
25+
This plugin depends on `cpex>=0.1.0rc1,<0.2` and imports hook models from `cpex.framework`. The compiled Rust extension is mandatory; there is no Python fallback implementation.
26+
2327
## Usage
2428

2529
The Python plugin requires the compiled Rust extension and uses it for all detection and masking operations.

plugins/rust/python-package/pii_filter/cpex_pii_filter/pii_filter.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,7 @@
33

44
from __future__ import annotations
55

6-
try:
7-
from cpex.framework import Plugin
8-
except ModuleNotFoundError:
9-
class Plugin: # type: ignore[no-redef]
10-
def __init__(self, config) -> None:
11-
self.config = config
12-
6+
from cpex.framework import Plugin
137
from cpex_pii_filter.pii_filter_rust import PIIDetectorRust, PIIFilterPluginCore
148

159

plugins/rust/python-package/rate_limiter/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
55
Enforces rate limits per user, tenant, and tool across `tool_pre_invoke` and `prompt_pre_fetch` hooks. Supports pluggable counting algorithms (fixed window, sliding window, token bucket), an in-process memory backend (single-instance), and a Redis backend (shared across all gateway instances).
66

7+
## Runtime Requirements
8+
9+
This plugin depends on `cpex>=0.1.0rc1,<0.2` and imports hook models from `cpex.framework`. The compiled Rust extension is mandatory; there is no Python fallback implementation.
10+
711
## Hooks
812

913
| Hook | When it runs |

plugins/rust/python-package/rate_limiter/cpex_rate_limiter/rate_limiter.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,7 @@
55

66
import logging
77

8-
try:
9-
from cpex.framework import Plugin, PromptPrehookResult, ToolPreInvokeResult
10-
except ModuleNotFoundError:
11-
class Plugin: # type: ignore[no-redef]
12-
def __init__(self, config) -> None:
13-
self.config = config
14-
15-
class PromptPrehookResult: # type: ignore[no-redef]
16-
def __init__(self, continue_processing=True, violation=None, metadata=None, http_headers=None):
17-
self.continue_processing = continue_processing
18-
self.violation = violation
19-
self.metadata = metadata
20-
self.http_headers = http_headers
21-
22-
class ToolPreInvokeResult: # type: ignore[no-redef]
23-
def __init__(self, continue_processing=True, violation=None, metadata=None, http_headers=None):
24-
self.continue_processing = continue_processing
25-
self.violation = violation
26-
self.metadata = metadata
27-
self.http_headers = http_headers
28-
8+
from cpex.framework import Plugin, PromptPrehookResult, ToolPreInvokeResult
299
from cpex_rate_limiter.rate_limiter_rust import (
3010
RateLimiterPluginCore,
3111
compat_default_config as _compat_default_config,

plugins/rust/python-package/rate_limiter/src/redis_backend.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
// Uses EVALSHA with NOSCRIPT fallback to EVAL (REDIS-02).
1010
//
1111
// Key format: `{prefix}:{dimension_key}:{window_seconds}`
12-
// This matches the Python RedisBackend key format exactly so that instances
13-
// running the Rust backend and instances running the Python fallback share the
14-
// same Redis counters during a rolling upgrade.
12+
// This preserves the existing Redis counter namespace during rolling upgrades.
1513

1614
use std::cmp::max;
1715
use std::sync::OnceLock;

plugins/rust/python-package/retry_with_backoff/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ High-performance retry and backoff policy engine for ContextForge and MCP Gatewa
1818
make install
1919
```
2020

21+
## Runtime Requirements
22+
23+
This plugin depends on `cpex>=0.1.0rc1,<0.2` and imports hook models from `cpex.framework`. The compiled Rust extension is mandatory; there is no Python fallback implementation.
24+
2125
## Usage
2226

2327
The plugin runs on `tool_post_invoke` and `resource_post_fetch`.
@@ -54,7 +58,7 @@ Use `tool_overrides` to change retry behavior for a specific tool:
5458
- Successful responses clear retry state for the `(tool, request_id)` pair.
5559
- Retry state expires after a short TTL so abandoned request state does not accumulate indefinitely.
5660
- If `check_text_content` is disabled, the hot path uses the Rust state manager directly.
57-
- If `check_text_content` is enabled, the plugin falls back to Python-side payload inspection before applying retry policy.
61+
- If `check_text_content` is enabled, Python-side payload inspection supplements the Rust state manager before applying retry policy.
5862

5963
## Returned Metadata
6064

plugins/rust/python-package/retry_with_backoff/cpex_retry_with_backoff/retry_with_backoff.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from cpex_retry_with_backoff.retry_with_backoff_rust import RetryStateManager
2828

2929
log = logging.getLogger(__name__)
30-
_RUST_AVAILABLE = True
3130

3231

3332
@dataclass
@@ -205,7 +204,7 @@ async def tool_post_invoke(
205204
}
206205
}
207206

208-
if self._rust is not None and not cfg.check_text_content:
207+
if not cfg.check_text_content:
209208
is_error = isinstance(result, dict) and result.get("isError") is True
210209
status_code: int | None = None
211210
if isinstance(result, dict):

plugins/rust/python-package/secrets_detection/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
Rust-backed secrets detection plugin for MCP Gateway / CPEX.
44

5+
## Runtime Requirements
6+
7+
This plugin depends on `cpex>=0.1.0rc1,<0.2` and imports hook models from `cpex.framework`. The compiled Rust extension is mandatory; there is no Python fallback implementation.
8+
59
## What it does
610

711
This plugin scans hook payloads for likely secrets and can either:

0 commit comments

Comments
 (0)