v0.6.0
What's Changed
This release brings the Python SDK to feature parity with the JavaScript SDK, adding local rule evaluation, sensitive info detection, and filter rules — all evaluated locally via a new embedded WebAssembly runtime.
Python SDK documentation is still in progress. The examples below cover the new rule types to get you started.
Local rule evaluation
Bot detection, shield, sensitive info, and filter rules now run locally via an embedded WebAssembly component (powered by wasmtime), giving faster decisions and reducing round-trips to the Arcjet API.
Sensitive info detection
Scan user-submitted content for PII (email addresses, credit card numbers, phone numbers, IP addresses) and block or allow by entity type:
from arcjet import arcjet, detect_sensitive_info, Mode, SensitiveInfoEntityType
aj = arcjet(
key=arcjet_key,
rules=[
detect_sensitive_info(
mode=Mode.LIVE,
deny=[
SensitiveInfoEntityType.EMAIL,
SensitiveInfoEntityType.CREDIT_CARD_NUMBER,
],
),
],
)
decision = await aj.protect(
request,
sensitive_info_value="Please email me at test@example.com",
)
if decision.is_denied():
# PII detected — block the request
...Custom detection function
Supply a detect callback to extend the built-in detectors with your own logic. The function receives a list of tokens and returns a same-length list — either the entity type name or None:
def detect_custom(tokens: list[str]) -> list[str | None]:
return [
"CUSTOM_PII" if "api_key=" in token else None
for token in tokens
]
aj = arcjet(
key=arcjet_key,
rules=[
detect_sensitive_info(
mode=Mode.LIVE,
deny=["CUSTOM_PII", SensitiveInfoEntityType.EMAIL],
detect=detect_custom,
),
],
)Filter rules
Evaluate Wireshark-style expressions against request properties (IP, headers, path, method) to allow or deny traffic:
from arcjet import arcjet, filter_request, Mode
aj = arcjet(
key=arcjet_key,
rules=[
filter_request(
mode=Mode.LIVE,
deny=[
'ip.src.vpn or ip.src.tor',
'http.request.uri.path contains "/admin"',
],
),
],
)
decision = await aj.protect(request)Local fields for filter rules
Pass dynamic, per-request values into filter expressions via filter_local:
aj = arcjet(
key=arcjet_key,
rules=[
filter_request(
mode=Mode.LIVE,
allow=['local.role eq "admin"'],
),
],
)
# In your route handler:
decision = await aj.protect(
request,
filter_local={"role": current_user.role},
)Detailed changes
Features
- Add WebAssembly component bindings & bindings generator in #70
- Wire local (WebAssembly) rule evaluation into
protect()in #71 - Add sensitive info detection in #72
- Add filter rules & global characteristics in #73
- Cache DENY decisions in #75
Bug fixes
- fix: set
skip_custom_detect=Truefor local bot detection in #76
Full Changelog: v0.5.0...v0.6.0