Security Gateway¶
security_gateway — mvp.security_gateway
Cluster: Uncategorised | Type: component | MCP Tools: None
Overview¶
Centralised security enforcement pipeline: authentication (API key), RBAC role checking, CBRN (chemical/biological/radiological/nuclear) content classification, per-tier rate limiting, CSF safety gating, and tamper-evident audit logging. Returns a structured SecurityVerdict with decision, stage evidence, warning card, and canonical completion_state (verified, qualified-draft, or blocked-escalated).
When to use:
- Enforcing a single security boundary across all G6 server surfaces
- Classifying requests for harmful content before routing to downstream agents
- Generating a compliance-ready audit log of all security decisions
Example:
from mvp.security_gateway import APIKeyStore, Role, SecurityGatewayBlock, SecurityRequest, Tier
keys = APIKeyStore()
api_key = keys.create_key("user_123", Role.USER, Tier.BASIC)
block = SecurityGatewayBlock(name="security", key_store=keys)
result = block.infer(SecurityRequest(
api_key=api_key,
target_component="grounding",
operation="infer",
params_hash="...",
content_summary="Verify this workflow output.",
source_ip="127.0.0.1",
transport="rest",
))
verdict = result.value
# verdict.decision, verdict.reason, verdict.risk_score
# verdict.completion_state, verdict.warning_card, verdict.evidence
Diagnostics: gateway_health, gateway_capabilities, and MCP gateway_dry_run are read-only/dry-run surfaces. They do not expose API-key creation, RBAC mutation, audit deletion, or policy writes.
CBRN sessions: the default CBRN session accumulator is process-local memory. Set SECURITY_CBRN_SESSION_BACKEND=redis with Redis configuration for shared multi-worker accumulation.
Works well with: middleware, csf_gate, csf_audit
Public API¶
SecurityAuditLogger¶
Append-only security event log backed by SQLite.
Constructor:
| Parameter | Type | Default |
|---|---|---|
db_path | str | ':memory:' |
Methods:
log_event(event_type: str, detail: dict, caller_id: str | None = None, source_ip: str | None = None, transport: str | None = None) -> None¶
Append a structured event to the audit log (hash-chained).
verify_hash_chain() -> tuple[bool, int | None]¶
Walk the chain and detect tampering.
query(event_type: str | None = None, limit: int = 100) -> list[dict]¶
Return recent events, optionally filtered by event_type.
prune_old_events(retention_days: int = 365) -> int¶
Delete events older than retention_days. Returns count deleted.
Authenticator¶
Verify caller identity from API keys.
Constructor:
| Parameter | Type | Default |
|---|---|---|
key_store | APIKeyStore | required |
api_key_verifier | ApiKeyVerifier \| None | None |
Methods:
authenticate(request: SecurityRequest) -> Result[CallerIdentity]¶
Return a CallerIdentity or an error Result.
Authorizer¶
RBAC authoriser backed by SQLite.
Constructor:
| Parameter | Type | Default |
|---|---|---|
db_path | str | ':memory:' |
Methods:
reload() -> None¶
Load rules from SQLite into memory.
authorize(caller: CallerIdentity, component: str, operation: str) -> Result[bool]¶
Check if caller may invoke component/operation.
authorize_pipeline(caller: CallerIdentity, steps: list[tuple[str, str]]) -> Result[bool]¶
Check RBAC for every step and enforce tier pipeline-step limits.
CBRNSessionBackend(Protocol)¶
Rolling CBRN session accumulation backend.
Methods:
accumulate(caller_id: str, score: float, window_seconds: float) -> float¶
Record score and return cumulative score within the rolling window.
MemoryCBRNSessionBackend¶
Process-local CBRN session backend.
Methods:
accumulate(caller_id: str, score: float, window_seconds: float) -> float¶
RedisCBRNSessionBackend¶
Redis sorted-set backend for shared multi-worker CBRN accumulation.
Constructor:
| Parameter | Type | Default |
|---|---|---|
client | object | required |
key_prefix | str | 'g6:cbrn:session:' |
Methods:
accumulate(caller_id: str, score: float, window_seconds: float) -> float¶
CBRNRuleEngine¶
Regex-based additive scoring against a configurable rule set.
Constructor:
| Parameter | Type | Default |
|---|---|---|
rules_path | str \| None | None |
Methods:
score(content: str, component: str, operation: str) -> CBRNResult¶
Score content against all rules, apply context multiplier.
score_pipeline(content: str, steps: list[tuple[str, str]]) -> CBRNResult¶
Score content using the highest-risk component in steps, then add pipeline bonus.
LLMSafetyJudge¶
Optional Tier 2 judge backed by an Anthropic Claude model.
Constructor:
| Parameter | Type | Default |
|---|---|---|
client | Any \| None | None |
Methods:
evaluate(content: str, component: str, operation: str) -> CBRNResult¶
Call the LLM and parse a structured safety verdict. Fail-closed on error.
CBRNClassifier¶
Two-tier classifier with optional session-level accumulation.
Constructor:
| Parameter | Type | Default |
|---|---|---|
rule_engine | CBRNRuleEngine \| None | None |
llm_judge | LLMSafetyJudge \| None | None |
session_window | float \| None | None |
cumulative_threshold | float \| None | None |
session_backend | str \| CBRNSessionBackend \| None | None |
Methods:
session_backend_kind() -> str¶
session_scope() -> str¶
classify(content: str, component: str, operation: str, caller_id: str = '') -> CBRNResult¶
Classify content. Escalate to LLM if rule engine is ambiguous.
classify_pipeline(content: str, steps: list[tuple[str, str]], caller_id: str = '') -> CBRNResult¶
Composition-aware classification across pipeline steps.
CSFChecker¶
Check operations against the G6 Computational Safety Framework.
Methods:
check(component: str, operation: str) -> Result[bool]¶
Check a single operation against the CSF safety budget.
check_pipeline(steps: list[tuple[str, str]]) -> Result[bool]¶
Check a pipeline of operations against the cumulative CSF budget.
SecurityGatewayBlock(AIBlock[SecurityRequest, SecurityVerdict, None])¶
Centralised 6-stage security pipeline for all G6 transports.
| Field | Type | Default |
|---|---|---|
name | str | 'security_gateway' |
key_store | APIKeyStore | field(default_factory=APIKeyStore) |
audit_db_path | str | ':memory:' |
enable_csf_gate | bool | False |
csf_gate_epsilon | float | 0.2 |
api_key_verifier | ApiKeyVerifier \| None | None |
audit_logger | SecurityAuditLogger | field(init=False, repr=False) |
Methods:
infer(data: SecurityRequest) -> Result[SecurityVerdict]¶
Run the 6-stage security pipeline. Always returns Result.ok(SecurityVerdict).
reload_policy() -> None¶
Reload RBAC policy from database.
dry_run(data: SecurityRequest) -> SecurityVerdict¶
Run diagnostics without mutating this gateway's audit, limiter, or CBRN session state.
gateway_health() -> dict¶
Return read-only runtime diagnostics without executing gateway stages.
gateway_capabilities() -> dict¶
Return diagnostic capabilities; mutation operations are intentionally absent.
APIKeyStore¶
Manages API keys in a SQLite database. Keys are stored as SHA-256 hashes.
Constructor:
| Parameter | Type | Default |
|---|---|---|
db_path | str | ':memory:' |
Methods:
create_key(caller_id: str, role: Role, tier: Tier) -> str¶
Generate a new API key. Returns the plaintext key (store it safely).
verify_key(key: str) -> CallerIdentity | None¶
Return CallerIdentity if key is valid and not revoked, else None.
revoke_key(key: str) -> None¶
Soft-revoke a key by its plaintext value.
revoke_by_caller_id(caller_id: str) -> None¶
Revoke all keys belonging to caller_id.
list_keys() -> list[dict]¶
Return metadata for all active (non-revoked) keys. No plaintext or hash.
RateLimiterBackend(Protocol)¶
Backend contract for sliding-window rate limiters.
Methods:
check(key: str, limit: int, window_seconds: float) -> tuple[bool, int]¶
Attempt to record one hit for
key.
MemoryBackend¶
In-process sliding-window backend.
Methods:
check(key: str, limit: int, window_seconds: float) -> tuple[bool, int]¶
RedisBackend¶
Redis-backed sliding-window backend.
Constructor:
| Parameter | Type | Default |
|---|---|---|
client | object | required |
key_prefix | str | 'g6:ratelimit:' |
use_lua | bool | True |
Methods:
check(key: str, limit: int, window_seconds: float) -> tuple[bool, int]¶
SlidingWindowRateLimiter¶
Sliding window rate limiter facade over a pluggable backend.
Constructor:
| Parameter | Type | Default |
|---|---|---|
window_seconds | float | 60.0 |
backend | str \| RateLimiterBackend | 'memory' |
redis_url | str | '' |
key_prefix | str | 'g6:ratelimit:' |
fail_closed | bool | True |
Methods:
check(caller_id: str, tier: Tier) -> Result[bool]¶
Return
Result.ok(True)if allowed,Result.fail(...)if over limit.
Role(Enum)¶
Caller privilege level.
Tier(Enum)¶
Subscription tier with associated rate limits.
Methods:
rate_limit() -> int¶
Requests per minute.
max_pipeline_steps() -> int | None¶
Max pipeline steps (None = unlimited).
CallerIdentity¶
Authenticated caller metadata.
| Field | Type | Default |
|---|---|---|
caller_id | str | required |
role | Role | required |
tier | Tier | required |
user_token | str | '' |
SecurityRequest¶
Inbound request to be checked by the security pipeline.
| Field | Type | Default |
|---|---|---|
target_component | str | required |
operation | str | required |
params_hash | str | required |
content_summary | str | required |
source_ip | str | required |
transport | Literal['rest', 'mcp', 'grpc', 'soap', 'erlang', 'cli'] | required |
caller_id | str \| None | None |
api_key | str \| None | None |
timestamp | datetime | field(default_factory=lambda: datetime.now(timezone.utc)) |
pipeline_steps | list[tuple[str, str]] \| None | None |
request_id | str | field(default_factory=lambda: uuid4().hex) |
SecurityVerdict¶
Output of a security pipeline stage.
| Field | Type | Default |
|---|---|---|
decision | Literal['allow', 'deny', 'escalate'] | required |
reason | str | required |
stage | str | required |
risk_score | float | 0.0 |
request_id | str | field(default_factory=lambda: uuid4().hex) |
deny_reason | DenyReason \| None | None |
completion_state | Literal['verified', 'qualified-draft', 'blocked-escalated'] | 'qualified-draft' |
warning_card | str \| None | None |
evidence | dict | field(default_factory=dict) |
task_id | str \| None | None |
run_id | str \| None | None |
Functions¶
make_session_backend(backend: str | CBRNSessionBackend = 'memory', redis_url: str = '', key_prefix: str = 'g6:cbrn:session:') -> CBRNSessionBackend¶
Factory for CBRN rolling-session accumulation backends.
make_backend(backend: str = 'memory', redis_url: str = '', key_prefix: str = 'g6:ratelimit:', use_lua: bool = True) -> RateLimiterBackend¶
Factory.
backendin {"memory", "redis"}.