583e6b7ea2
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 17s
CI / security (pull_request) Successful in 36s
CI / typecheck (pull_request) Successful in 54s
CI / unit_tests (pull_request) Successful in 2m39s
CI / integration_tests (pull_request) Successful in 3m10s
CI / docker (pull_request) Successful in 40s
CI / coverage (pull_request) Successful in 5m0s
CI / lint (push) Successful in 14s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 34s
CI / typecheck (push) Successful in 35s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m23s
CI / docker (push) Successful in 38s
CI / integration_tests (push) Successful in 3m8s
CI / coverage (push) Successful in 5m10s
CI / benchmark-publish (push) Successful in 16m26s
CI / benchmark-regression (pull_request) Successful in 30m12s
Implement spec-mandated Layer 4 Predictive Error Prevention system: - ErrorPattern domain model with pattern text, historical failures, preventive checks, frequency tracking, and keyword-based matching. - ErrorPatternRepository with in-memory CRUD + context-matching query. - ErrorPatternService with record_failure(), match_patterns(), and get_statistics() methods. - Wire into plan execution via plan_lifecycle_service pre-execution hook. - Add error pattern statistics to CLI diagnostics output. Behave BDD: 11 scenarios covering recording, matching, formatting, stats. Robot Framework: 3 integration smoke tests. ASV benchmarks: pattern matching performance. ISSUES CLOSED: #571
116 lines
3.6 KiB
Python
116 lines
3.6 KiB
Python
"""Benchmarks for the permission check enforcement baseline.
|
|
|
|
Measures the overhead of permission checks in both local mode
|
|
(fast-path) and server mode with varying numbers of role bindings.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import ClassVar
|
|
|
|
from cleveragents.application.services.permission_service import (
|
|
PermissionService,
|
|
)
|
|
from cleveragents.domain.models.core.permission import (
|
|
ROLE_PERMISSIONS,
|
|
PermissionAction,
|
|
PermissionRole,
|
|
PermissionScope,
|
|
RoleBinding,
|
|
)
|
|
|
|
_SERVER_MODE_ENV = "CLEVERAGENTS_SERVER_MODE"
|
|
|
|
|
|
def _make_bindings(n: int) -> list[RoleBinding]:
|
|
"""Create *n* role bindings for distinct principals."""
|
|
return [
|
|
RoleBinding(
|
|
principal=f"user-{i}",
|
|
role=PermissionRole.EDITOR,
|
|
scope=PermissionScope.PROJECT,
|
|
scope_id="proj-bench",
|
|
)
|
|
for i in range(n)
|
|
]
|
|
|
|
|
|
class TimePermissionCheckLocal:
|
|
"""Benchmark permission checks in local mode (fast-path)."""
|
|
|
|
def setup(self) -> None:
|
|
os.environ.pop(_SERVER_MODE_ENV, None)
|
|
self.svc = PermissionService()
|
|
|
|
def time_local_check(self) -> None:
|
|
"""Single local-mode permission check."""
|
|
self.svc.check_permission(
|
|
principal="alice",
|
|
action=PermissionAction.WRITE,
|
|
scope=PermissionScope.PROJECT,
|
|
scope_id="proj-1",
|
|
)
|
|
|
|
def time_local_check_all_actions(self) -> None:
|
|
"""Check every action in local mode."""
|
|
for action in PermissionAction:
|
|
self.svc.check_permission(
|
|
principal="alice",
|
|
action=action,
|
|
scope=PermissionScope.PROJECT,
|
|
scope_id="proj-1",
|
|
)
|
|
|
|
|
|
class TimePermissionCheckServer:
|
|
"""Benchmark permission checks in server mode."""
|
|
|
|
params: ClassVar[list[int]] = [0, 10, 100]
|
|
param_names: ClassVar[list[str]] = ["num_bindings"]
|
|
|
|
def setup(self, num_bindings: int) -> None:
|
|
os.environ[_SERVER_MODE_ENV] = "true"
|
|
bindings = _make_bindings(num_bindings)
|
|
self.svc = PermissionService(bindings=bindings)
|
|
|
|
def teardown(self, num_bindings: int) -> None:
|
|
os.environ.pop(_SERVER_MODE_ENV, None)
|
|
|
|
def time_server_check_denied(self, num_bindings: int) -> None:
|
|
"""Permission check that results in denial (no matching binding)."""
|
|
self.svc.check_permission(
|
|
principal="nonexistent",
|
|
action=PermissionAction.WRITE,
|
|
scope=PermissionScope.PROJECT,
|
|
scope_id="proj-bench",
|
|
)
|
|
|
|
def time_server_check_allowed(self, num_bindings: int) -> None:
|
|
"""Permission check that matches the last binding.
|
|
|
|
When *num_bindings* is 0 no binding can match, so a denied
|
|
check is performed instead to avoid an empty benchmark body.
|
|
"""
|
|
principal = f"user-{num_bindings - 1}" if num_bindings > 0 else "nonexistent"
|
|
self.svc.check_permission(
|
|
principal=principal,
|
|
action=PermissionAction.READ,
|
|
scope=PermissionScope.PROJECT,
|
|
scope_id="proj-bench",
|
|
)
|
|
|
|
|
|
class TimeRolePermissionsLookup:
|
|
"""Benchmark ROLE_PERMISSIONS constant lookups."""
|
|
|
|
def time_lookup_all_roles(self) -> None:
|
|
"""Look up allowed actions for every role."""
|
|
for role in PermissionRole:
|
|
_ = ROLE_PERMISSIONS[role]
|
|
|
|
def time_check_action_in_role(self) -> None:
|
|
"""Check membership of an action in each role's permission set."""
|
|
for role in PermissionRole:
|
|
_ = PermissionAction.READ in ROLE_PERMISSIONS[role]
|