correctover-ccs 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccs/__init__.py +31 -0
- ccs/adapters.py +195 -0
- ccs/core.py +266 -0
- ccs/mcp_server/__init__.py +4 -0
- ccs/mcp_server/__main__.py +7 -0
- ccs/mcp_server/server.py +196 -0
- correctover_ccs-1.0.0.dist-info/METADATA +236 -0
- correctover_ccs-1.0.0.dist-info/RECORD +10 -0
- correctover_ccs-1.0.0.dist-info/WHEEL +5 -0
- correctover_ccs-1.0.0.dist-info/top_level.txt +1 -0
ccs/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Correctover Conformance Standard (CCS) v1.0 — Python SDK
|
|
3
|
+
|
|
4
|
+
Synchronous interceptor-based governance for AI Agent frameworks.
|
|
5
|
+
Eliminates architectural fail-open bypasses inherent to observer-pattern hooks.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from ccs import govern
|
|
9
|
+
|
|
10
|
+
@govern(policy="default")
|
|
11
|
+
def my_tool(args):
|
|
12
|
+
...
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__version__ = "1.0.0"
|
|
16
|
+
__author__ = "Correctover Standards"
|
|
17
|
+
|
|
18
|
+
from ccs.core import govern, GovernanceResult, CCSConfig, CCSPolicy, CCSRuntime, get_runtime
|
|
19
|
+
from ccs.adapters import crewai_adapter, autogen_adapter, langgraph_adapter
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"govern",
|
|
23
|
+
"GovernanceResult",
|
|
24
|
+
"CCSConfig",
|
|
25
|
+
"CCSPolicy",
|
|
26
|
+
"CCSRuntime",
|
|
27
|
+
"get_runtime",
|
|
28
|
+
"crewai_adapter",
|
|
29
|
+
"autogen_adapter",
|
|
30
|
+
"langgraph_adapter",
|
|
31
|
+
]
|
ccs/adapters.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CCS Framework Adapters — Verified interception for CrewAI, AutoGen, LangGraph.
|
|
3
|
+
|
|
4
|
+
Each adapter replaces the framework's observer-pattern hooks with CCS
|
|
5
|
+
synchronous interceptor decorators, eliminating CWE-636 fail-open vulnerabilities.
|
|
6
|
+
|
|
7
|
+
Verified against:
|
|
8
|
+
- CrewAI >= 0.1.0 (BaseTool.run sync interception)
|
|
9
|
+
- AutoGen >= 0.7.0 (FunctionTool.run async interception)
|
|
10
|
+
- LangGraph >= 0.2.0 (LCBaseTool.run sync interception)
|
|
11
|
+
|
|
12
|
+
Reference: CCS v1.0 Standard, Section 3 — Formal Framework
|
|
13
|
+
DOI: 10.5281/zenodo.21271910
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CrewAIAdapter:
|
|
20
|
+
"""
|
|
21
|
+
CCS adapter for CrewAI.
|
|
22
|
+
|
|
23
|
+
Intercepts crewai.tools.base_tool.BaseTool.run() — the single
|
|
24
|
+
entry point for ALL CrewAI tool executions. If CCS governance
|
|
25
|
+
denies or crashes, the tool is NEVER invoked (fail-closed).
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
from ccs.adapters import crewai_adapter
|
|
29
|
+
crewai_adapter.install() # patches BaseTool.run globally
|
|
30
|
+
crewai_adapter.uninstall() # restores original
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
_original_run = None
|
|
34
|
+
_installed = False
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def install(policy: str = "default"):
|
|
38
|
+
"""Install CCS governance on CrewAI's BaseTool.run."""
|
|
39
|
+
from crewai.tools.base_tool import BaseTool
|
|
40
|
+
from ccs.core import get_runtime, GovernanceResult
|
|
41
|
+
|
|
42
|
+
if CrewAIAdapter._installed:
|
|
43
|
+
return # Already installed
|
|
44
|
+
|
|
45
|
+
runtime = get_runtime()
|
|
46
|
+
CrewAIAdapter._original_run = BaseTool.run
|
|
47
|
+
|
|
48
|
+
def ccs_governed_run(self, *args, **kwargs):
|
|
49
|
+
tool_input = {"args": args, "kwargs": kwargs}
|
|
50
|
+
result, latency = runtime.evaluate(
|
|
51
|
+
tool_name=getattr(self, "name", type(self).__name__),
|
|
52
|
+
tool_input=tool_input,
|
|
53
|
+
policy_name=policy,
|
|
54
|
+
)
|
|
55
|
+
if result != GovernanceResult.ALLOW:
|
|
56
|
+
raise PermissionError(
|
|
57
|
+
f"CCS DENIED: {getattr(self, 'name', 'unknown')} "
|
|
58
|
+
f"(policy={policy}, latency={latency}µs)"
|
|
59
|
+
)
|
|
60
|
+
return CrewAIAdapter._original_run(self, *args, **kwargs)
|
|
61
|
+
|
|
62
|
+
BaseTool.run = ccs_governed_run
|
|
63
|
+
CrewAIAdapter._installed = True
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def uninstall():
|
|
67
|
+
"""Restore original CrewAI BaseTool.run."""
|
|
68
|
+
if not CrewAIAdapter._installed:
|
|
69
|
+
return
|
|
70
|
+
from crewai.tools.base_tool import BaseTool
|
|
71
|
+
BaseTool.run = CrewAIAdapter._original_run
|
|
72
|
+
CrewAIAdapter._installed = False
|
|
73
|
+
CrewAIAdapter._original_run = None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class AutoGenAdapter:
|
|
77
|
+
"""
|
|
78
|
+
CCS adapter for Microsoft AutoGen.
|
|
79
|
+
|
|
80
|
+
Intercepts autogen_core.tools.FunctionTool.run() — the async
|
|
81
|
+
entry point for all AutoGen function tool executions.
|
|
82
|
+
|
|
83
|
+
Note: AutoGen 0.7+ uses async run(args, cancellation_token).
|
|
84
|
+
The adapter preserves this async signature.
|
|
85
|
+
|
|
86
|
+
Usage:
|
|
87
|
+
from ccs.adapters import autogen_adapter
|
|
88
|
+
autogen_adapter.install()
|
|
89
|
+
autogen_adapter.uninstall()
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
_original_run = None
|
|
93
|
+
_installed = False
|
|
94
|
+
|
|
95
|
+
@staticmethod
|
|
96
|
+
def install(policy: str = "default"):
|
|
97
|
+
"""Install CCS governance on AutoGen's FunctionTool.run."""
|
|
98
|
+
from autogen_core.tools import FunctionTool
|
|
99
|
+
from ccs.core import get_runtime, GovernanceResult
|
|
100
|
+
|
|
101
|
+
if AutoGenAdapter._installed:
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
runtime = get_runtime()
|
|
105
|
+
AutoGenAdapter._original_run = FunctionTool.run
|
|
106
|
+
|
|
107
|
+
async def ccs_governed_run(self, args, cancellation_token):
|
|
108
|
+
tool_input = {"args": str(args), "tool": self.name}
|
|
109
|
+
result, latency = runtime.evaluate(
|
|
110
|
+
tool_name=self.name,
|
|
111
|
+
tool_input=tool_input,
|
|
112
|
+
policy_name=policy,
|
|
113
|
+
)
|
|
114
|
+
if result != GovernanceResult.ALLOW:
|
|
115
|
+
raise PermissionError(
|
|
116
|
+
f"CCS DENIED: {self.name} "
|
|
117
|
+
f"(policy={policy}, latency={latency}µs)"
|
|
118
|
+
)
|
|
119
|
+
return await AutoGenAdapter._original_run(self, args, cancellation_token)
|
|
120
|
+
|
|
121
|
+
FunctionTool.run = ccs_governed_run
|
|
122
|
+
AutoGenAdapter._installed = True
|
|
123
|
+
|
|
124
|
+
@staticmethod
|
|
125
|
+
def uninstall():
|
|
126
|
+
"""Restore original AutoGen FunctionTool.run."""
|
|
127
|
+
if not AutoGenAdapter._installed:
|
|
128
|
+
return
|
|
129
|
+
from autogen_core.tools import FunctionTool
|
|
130
|
+
FunctionTool.run = AutoGenAdapter._original_run
|
|
131
|
+
AutoGenAdapter._installed = False
|
|
132
|
+
AutoGenAdapter._original_run = None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class LangGraphAdapter:
|
|
136
|
+
"""
|
|
137
|
+
CCS adapter for LangGraph / LangChain.
|
|
138
|
+
|
|
139
|
+
Intercepts langchain_core.tools.BaseTool.run() — the sync
|
|
140
|
+
entry point for all LangChain/LangGraph tool executions.
|
|
141
|
+
Also covers invoke() since it delegates to run().
|
|
142
|
+
|
|
143
|
+
Usage:
|
|
144
|
+
from ccs.adapters import langgraph_adapter
|
|
145
|
+
langgraph_adapter.install()
|
|
146
|
+
langgraph_adapter.uninstall()
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
_original_run = None
|
|
150
|
+
_installed = False
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def install(policy: str = "default"):
|
|
154
|
+
"""Install CCS governance on LangChain's BaseTool.run."""
|
|
155
|
+
from langchain_core.tools import BaseTool as LCBaseTool
|
|
156
|
+
from ccs.core import get_runtime, GovernanceResult
|
|
157
|
+
|
|
158
|
+
if LangGraphAdapter._installed:
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
runtime = get_runtime()
|
|
162
|
+
LangGraphAdapter._original_run = LCBaseTool.run
|
|
163
|
+
|
|
164
|
+
def ccs_governed_run(self, tool_input, *args, **kwargs):
|
|
165
|
+
governance_input = {"tool_input": tool_input, "kwargs": kwargs}
|
|
166
|
+
result, latency = runtime.evaluate(
|
|
167
|
+
tool_name=getattr(self, "name", type(self).__name__),
|
|
168
|
+
tool_input=governance_input,
|
|
169
|
+
policy_name=policy,
|
|
170
|
+
)
|
|
171
|
+
if result != GovernanceResult.ALLOW:
|
|
172
|
+
raise PermissionError(
|
|
173
|
+
f"CCS DENIED: {getattr(self, 'name', 'unknown')} "
|
|
174
|
+
f"(policy={policy}, latency={latency}µs)"
|
|
175
|
+
)
|
|
176
|
+
return LangGraphAdapter._original_run(self, tool_input, *args, **kwargs)
|
|
177
|
+
|
|
178
|
+
LCBaseTool.run = ccs_governed_run
|
|
179
|
+
LangGraphAdapter._installed = True
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def uninstall():
|
|
183
|
+
"""Restore original LangChain BaseTool.run."""
|
|
184
|
+
if not LangGraphAdapter._installed:
|
|
185
|
+
return
|
|
186
|
+
from langchain_core.tools import BaseTool as LCBaseTool
|
|
187
|
+
LCBaseTool.run = LangGraphAdapter._original_run
|
|
188
|
+
LangGraphAdapter._installed = False
|
|
189
|
+
LangGraphAdapter._original_run = None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# Convenience instances
|
|
193
|
+
crewai_adapter = CrewAIAdapter()
|
|
194
|
+
autogen_adapter = AutoGenAdapter()
|
|
195
|
+
langgraph_adapter = LangGraphAdapter()
|
ccs/core.py
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CCS Core: Synchronous Interceptor Decorator Architecture
|
|
3
|
+
|
|
4
|
+
Unlike observer-pattern hooks that can fail-open, CCS decorators
|
|
5
|
+
OWN the execution control flow. If verification fails or raises,
|
|
6
|
+
the wrapped tool function is NEVER invoked. This provides
|
|
7
|
+
structural fail-closed guarantee.
|
|
8
|
+
|
|
9
|
+
Reference: CCS v1.0 Standard, Section 3 — Formal Framework
|
|
10
|
+
DOI: 10.5281/zenodo.21271910
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import functools
|
|
14
|
+
import time
|
|
15
|
+
import hashlib
|
|
16
|
+
import json
|
|
17
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from enum import Enum
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class GovernanceResult(Enum):
|
|
23
|
+
"""Governance evaluation result."""
|
|
24
|
+
ALLOW = "allow"
|
|
25
|
+
DENY = "deny"
|
|
26
|
+
ERROR = "error" # Error in evaluation → ALWAYS DENY (fail-closed)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class CCSConfig:
|
|
31
|
+
"""Configuration for CCS governance."""
|
|
32
|
+
policy_name: str = "default"
|
|
33
|
+
max_tool_input_size: int = 1_000_000 # 1MB max input
|
|
34
|
+
timeout_ms: int = 50 # 50ms timeout for governance evaluation
|
|
35
|
+
fail_mode: str = "closed" # Only "closed" is valid — fail-open is structurally forbidden
|
|
36
|
+
audit_log: bool = True
|
|
37
|
+
# Performance targets (CANON benchmark)
|
|
38
|
+
target_p50_us: float = 22.0
|
|
39
|
+
target_p99_us: float = 99.0
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class GovernanceTrace:
|
|
44
|
+
"""Immutable audit trace for a single governance decision."""
|
|
45
|
+
timestamp: float
|
|
46
|
+
tool_name: str
|
|
47
|
+
input_hash: str
|
|
48
|
+
result: GovernanceResult
|
|
49
|
+
latency_us: float
|
|
50
|
+
policy_name: str
|
|
51
|
+
rule_evaluated: str
|
|
52
|
+
detail: str = ""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class CCSPolicy:
|
|
56
|
+
"""
|
|
57
|
+
Base class for CCS governance policies.
|
|
58
|
+
|
|
59
|
+
Subclass this to define custom governance rules.
|
|
60
|
+
All evaluation methods MUST return GovernanceResult.
|
|
61
|
+
If evaluation raises → fail-closed (DENY), never ALLOW.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def evaluate(self, tool_name: str, tool_input: Dict[str, Any]) -> GovernanceResult:
|
|
65
|
+
"""
|
|
66
|
+
Evaluate whether a tool call should be allowed.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
tool_name: Name of the tool being called
|
|
70
|
+
tool_input: Arguments to the tool
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
GovernanceResult.ALLOW or GovernanceResult.DENY
|
|
74
|
+
|
|
75
|
+
Note:
|
|
76
|
+
If this method raises an exception, the decorator will
|
|
77
|
+
catch it and return DENY (fail-closed). This is the
|
|
78
|
+
fundamental guarantee that distinguishes CCS from
|
|
79
|
+
observer-pattern hooks.
|
|
80
|
+
"""
|
|
81
|
+
raise NotImplementedError
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class DefaultPolicy(CCSPolicy):
|
|
85
|
+
"""Default CCS policy: validates input structure and size."""
|
|
86
|
+
|
|
87
|
+
def __init__(self, config: CCSConfig):
|
|
88
|
+
self.config = config
|
|
89
|
+
|
|
90
|
+
def evaluate(self, tool_name: str, tool_input: Dict[str, Any]) -> GovernanceResult:
|
|
91
|
+
# Size check
|
|
92
|
+
try:
|
|
93
|
+
serialized = json.dumps(tool_input, default=str)
|
|
94
|
+
if len(serialized) > self.config.max_tool_input_size:
|
|
95
|
+
return GovernanceResult.DENY
|
|
96
|
+
except (TypeError, ValueError, OverflowError):
|
|
97
|
+
# Non-serializable input → DENY (fail-closed)
|
|
98
|
+
return GovernanceResult.DENY
|
|
99
|
+
|
|
100
|
+
# Type check
|
|
101
|
+
if not isinstance(tool_input, dict):
|
|
102
|
+
return GovernanceResult.DENY
|
|
103
|
+
|
|
104
|
+
return GovernanceResult.ALLOW
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class CCSRuntime:
|
|
108
|
+
"""
|
|
109
|
+
CCS Governance Runtime — synchronous interceptor engine.
|
|
110
|
+
|
|
111
|
+
This is the core of the CCS architecture. Unlike framework hooks
|
|
112
|
+
that observe events, the runtime INTERCEPTS tool calls and
|
|
113
|
+
controls execution flow. If the runtime fails, the tool is BLOCKED.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self, config: Optional[CCSConfig] = None):
|
|
117
|
+
self.config = config or CCSConfig()
|
|
118
|
+
self.policies: Dict[str, CCSPolicy] = {}
|
|
119
|
+
self.traces: List[GovernanceTrace] = []
|
|
120
|
+
self._latencies: List[float] = []
|
|
121
|
+
|
|
122
|
+
# Register default policy
|
|
123
|
+
self.policies["default"] = DefaultPolicy(self.config)
|
|
124
|
+
|
|
125
|
+
def register_policy(self, name: str, policy: CCSPolicy):
|
|
126
|
+
"""Register a named governance policy."""
|
|
127
|
+
self.policies[name] = policy
|
|
128
|
+
|
|
129
|
+
def evaluate(self, tool_name: str, tool_input: Dict[str, Any],
|
|
130
|
+
policy_name: str = "default") -> Tuple[GovernanceResult, float]:
|
|
131
|
+
"""
|
|
132
|
+
Synchronously evaluate a tool call against the named policy.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Tuple of (GovernanceResult, latency_microseconds)
|
|
136
|
+
|
|
137
|
+
Guarantee:
|
|
138
|
+
This method NEVER raises. Any exception is caught and
|
|
139
|
+
converted to GovernanceResult.DENY. This is the fail-closed
|
|
140
|
+
guarantee that observer-pattern hooks cannot provide.
|
|
141
|
+
"""
|
|
142
|
+
start = time.perf_counter()
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
policy = self.policies.get(policy_name)
|
|
146
|
+
if policy is None:
|
|
147
|
+
result = GovernanceResult.DENY
|
|
148
|
+
detail = f"Unknown policy: {policy_name}"
|
|
149
|
+
else:
|
|
150
|
+
result = policy.evaluate(tool_name, tool_input)
|
|
151
|
+
detail = f"Policy '{policy_name}' evaluated"
|
|
152
|
+
except Exception as e:
|
|
153
|
+
# FAIL-CLOSED: Any exception → DENY
|
|
154
|
+
# This is the critical difference from observer hooks
|
|
155
|
+
result = GovernanceResult.DENY
|
|
156
|
+
detail = f"Exception caught, fail-closed: {type(e).__name__}: {e}"
|
|
157
|
+
|
|
158
|
+
latency_us = (time.perf_counter() - start) * 1_000_000
|
|
159
|
+
self._latencies.append(latency_us)
|
|
160
|
+
|
|
161
|
+
# Compute input hash for audit trail
|
|
162
|
+
try:
|
|
163
|
+
input_hash = hashlib.sha256(
|
|
164
|
+
json.dumps(tool_input, default=str, sort_keys=True).encode()
|
|
165
|
+
).hexdigest()[:16]
|
|
166
|
+
except Exception:
|
|
167
|
+
input_hash = "unhashable"
|
|
168
|
+
|
|
169
|
+
if self.config.audit_log:
|
|
170
|
+
trace = GovernanceTrace(
|
|
171
|
+
timestamp=time.time(),
|
|
172
|
+
tool_name=tool_name,
|
|
173
|
+
input_hash=input_hash,
|
|
174
|
+
result=result,
|
|
175
|
+
latency_us=round(latency_us, 2),
|
|
176
|
+
policy_name=policy_name,
|
|
177
|
+
rule_evaluated=policy_name,
|
|
178
|
+
detail=detail,
|
|
179
|
+
)
|
|
180
|
+
self.traces.append(trace)
|
|
181
|
+
|
|
182
|
+
return result, round(latency_us, 2)
|
|
183
|
+
|
|
184
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
185
|
+
"""Get runtime performance statistics."""
|
|
186
|
+
if not self._latencies:
|
|
187
|
+
return {"total_evaluations": 0}
|
|
188
|
+
|
|
189
|
+
sorted_lat = sorted(self._latencies)
|
|
190
|
+
n = len(sorted_lat)
|
|
191
|
+
return {
|
|
192
|
+
"total_evaluations": n,
|
|
193
|
+
"total_denied": sum(1 for t in self.traces if t.result == GovernanceResult.DENY),
|
|
194
|
+
"total_allowed": sum(1 for t in self.traces if t.result == GovernanceResult.ALLOW),
|
|
195
|
+
"latency_p50_us": round(sorted_lat[n // 2], 2),
|
|
196
|
+
"latency_p99_us": round(sorted_lat[int(n * 0.99)], 2) if n >= 100 else round(sorted_lat[-1], 2),
|
|
197
|
+
"latency_max_us": round(sorted_lat[-1], 2),
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# Global runtime singleton
|
|
202
|
+
_runtime: Optional[CCSRuntime] = None
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def get_runtime(config: Optional[CCSConfig] = None) -> CCSRuntime:
|
|
206
|
+
"""Get or create the global CCS runtime."""
|
|
207
|
+
global _runtime
|
|
208
|
+
if _runtime is None:
|
|
209
|
+
_runtime = CCSRuntime(config)
|
|
210
|
+
return _runtime
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def govern(policy: str = "default", config: Optional[CCSConfig] = None):
|
|
214
|
+
"""
|
|
215
|
+
CCS governance decorator — the core of the interceptor pattern.
|
|
216
|
+
|
|
217
|
+
Usage:
|
|
218
|
+
@govern(policy="default")
|
|
219
|
+
def my_tool(args: dict) -> str:
|
|
220
|
+
return "result"
|
|
221
|
+
|
|
222
|
+
Guarantee:
|
|
223
|
+
If governance evaluation raises ANY exception, the decorated
|
|
224
|
+
function is NEVER called. This provides structural fail-closed
|
|
225
|
+
behavior that observer-pattern hooks cannot achieve.
|
|
226
|
+
|
|
227
|
+
Example (CrewAI):
|
|
228
|
+
from ccs import govern
|
|
229
|
+
|
|
230
|
+
@govern(policy="compliance")
|
|
231
|
+
def search_web(query: str):
|
|
232
|
+
# This function will NEVER execute if governance denies
|
|
233
|
+
return search_engine(query)
|
|
234
|
+
"""
|
|
235
|
+
def decorator(func: Callable) -> Callable:
|
|
236
|
+
@functools.wraps(func)
|
|
237
|
+
def wrapper(*args, **kwargs):
|
|
238
|
+
runtime = get_runtime(config)
|
|
239
|
+
|
|
240
|
+
# Build tool input for governance evaluation
|
|
241
|
+
tool_input = {"args": args, "kwargs": kwargs}
|
|
242
|
+
|
|
243
|
+
# SYNCHRONOUS INTERCEPTION — not observation
|
|
244
|
+
result, latency_us = runtime.evaluate(
|
|
245
|
+
tool_name=func.__name__,
|
|
246
|
+
tool_input=tool_input,
|
|
247
|
+
policy_name=policy,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
# FAIL-CLOSED: Only proceed if explicitly ALLOWED
|
|
251
|
+
if result != GovernanceResult.ALLOW:
|
|
252
|
+
raise PermissionError(
|
|
253
|
+
f"CCS governance DENIED tool '{func.__name__}' "
|
|
254
|
+
f"(policy={policy}, latency={latency_us}µs)"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# Only reached if governance explicitly ALLOWED
|
|
258
|
+
return func(*args, **kwargs)
|
|
259
|
+
|
|
260
|
+
# Attach CCS metadata
|
|
261
|
+
wrapper.__ccs_governed__ = True
|
|
262
|
+
wrapper.__ccs_policy__ = policy
|
|
263
|
+
wrapper.__ccs_runtime__ = get_runtime(config)
|
|
264
|
+
|
|
265
|
+
return wrapper
|
|
266
|
+
return decorator
|
ccs/mcp_server/server.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CCS MCP Server — Model Context Protocol governance for AI Agents.
|
|
3
|
+
|
|
4
|
+
Exposes CCS governance as an MCP tool, allowing any MCP-compatible
|
|
5
|
+
agent (Claude Desktop, Cursor, Cline, etc.) to validate tool calls
|
|
6
|
+
against CCS policies before execution.
|
|
7
|
+
|
|
8
|
+
Transport: stdio (default for MCP)
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
python -m ccs_sdk.mcp_server.server
|
|
12
|
+
|
|
13
|
+
Or configure in Claude Desktop:
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"ccs": {
|
|
17
|
+
"command": "python",
|
|
18
|
+
"args": ["-m", "ccs_sdk.mcp_server.server"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from mcp.server.fastmcp import FastMCP
|
|
25
|
+
from ccs.core import (
|
|
26
|
+
CCSConfig, CCSPolicy, GovernanceResult,
|
|
27
|
+
get_runtime,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# ============================================================
|
|
31
|
+
# MCP Server
|
|
32
|
+
# ============================================================
|
|
33
|
+
mcp = FastMCP(
|
|
34
|
+
"CCS Governance",
|
|
35
|
+
instructions="Correctover Conformance Standard (CCS) v1.0 — "
|
|
36
|
+
"Synchronous interceptor governance for AI Agent tool calls. "
|
|
37
|
+
"Validates tool invocations against governance policies with "
|
|
38
|
+
"structural fail-closed guarantee (CWE-636). "
|
|
39
|
+
"DOI: 10.5281/zenodo.21271910"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@mcp.tool()
|
|
44
|
+
def ccs_govern(
|
|
45
|
+
tool_name: str,
|
|
46
|
+
tool_input: dict,
|
|
47
|
+
policy_name: str = "default",
|
|
48
|
+
) -> dict:
|
|
49
|
+
"""
|
|
50
|
+
Evaluate a tool call against CCS governance policy.
|
|
51
|
+
|
|
52
|
+
Returns ALLOW or DENY with latency metrics. If the policy engine
|
|
53
|
+
crashes, returns DENY (fail-closed guarantee).
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
tool_name: Name of the tool being called (e.g., "search_web")
|
|
57
|
+
tool_input: Arguments dict for the tool (e.g., {"query": "..."})
|
|
58
|
+
policy_name: CCS policy to evaluate against (default: "default")
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
dict with:
|
|
62
|
+
- result: "allow" | "deny" | "error"
|
|
63
|
+
- latency_us: governance evaluation latency in microseconds
|
|
64
|
+
- tool_name: echo of the tool name
|
|
65
|
+
- policy_name: echo of the policy used
|
|
66
|
+
- fail_closed: True if denied due to error (not policy logic)
|
|
67
|
+
"""
|
|
68
|
+
runtime = get_runtime()
|
|
69
|
+
result, latency_us = runtime.evaluate(
|
|
70
|
+
tool_name=tool_name,
|
|
71
|
+
tool_input=tool_input,
|
|
72
|
+
policy_name=policy_name,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
is_error = result == GovernanceResult.ERROR
|
|
76
|
+
return {
|
|
77
|
+
"result": result.value,
|
|
78
|
+
"latency_us": latency_us,
|
|
79
|
+
"tool_name": tool_name,
|
|
80
|
+
"policy_name": policy_name,
|
|
81
|
+
"fail_closed": is_error,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@mcp.tool()
|
|
86
|
+
def ccs_status() -> dict:
|
|
87
|
+
"""
|
|
88
|
+
Get CCS governance runtime status and performance metrics.
|
|
89
|
+
|
|
90
|
+
Returns total evaluations, deny/allow counts, and latency
|
|
91
|
+
percentiles (P50, P99, max).
|
|
92
|
+
"""
|
|
93
|
+
runtime = get_runtime()
|
|
94
|
+
stats = runtime.get_stats()
|
|
95
|
+
|
|
96
|
+
# Add registered policies info
|
|
97
|
+
stats["registered_policies"] = list(runtime.policies.keys())
|
|
98
|
+
stats["total_traces"] = len(runtime.traces)
|
|
99
|
+
stats["version"] = "1.0.0"
|
|
100
|
+
stats["standard"] = "CCS v1.0"
|
|
101
|
+
stats["doi"] = "10.5281/zenodo.21271910"
|
|
102
|
+
|
|
103
|
+
return stats
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@mcp.tool()
|
|
107
|
+
def ccs_register_deny_rule(
|
|
108
|
+
rule_name: str,
|
|
109
|
+
denied_tools: list[str] | None = None,
|
|
110
|
+
denied_patterns: list[str] | None = None,
|
|
111
|
+
) -> dict:
|
|
112
|
+
"""
|
|
113
|
+
Register a custom deny policy. Tools matching the denied list
|
|
114
|
+
or patterns will be blocked; all others pass through.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
rule_name: Name for this policy (e.g., "block_dangerous_tools")
|
|
118
|
+
denied_tools: Exact tool names to deny (e.g., ["rm", "delete_file"])
|
|
119
|
+
denied_patterns: Substring patterns to deny (e.g., ["delete", "destroy"])
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
dict confirming registration with rule details
|
|
123
|
+
"""
|
|
124
|
+
denied_tools = denied_tools or []
|
|
125
|
+
denied_patterns = denied_patterns or []
|
|
126
|
+
|
|
127
|
+
class DenyRulePolicy(CCSPolicy):
|
|
128
|
+
def __init__(self, tools, patterns):
|
|
129
|
+
self.tools = set(tools)
|
|
130
|
+
self.patterns = patterns
|
|
131
|
+
|
|
132
|
+
def evaluate(self, tool_name, tool_input):
|
|
133
|
+
# Exact match
|
|
134
|
+
if tool_name in self.tools:
|
|
135
|
+
return GovernanceResult.DENY
|
|
136
|
+
# Pattern match
|
|
137
|
+
for pattern in self.patterns:
|
|
138
|
+
if pattern.lower() in tool_name.lower():
|
|
139
|
+
return GovernanceResult.DENY
|
|
140
|
+
# Also check tool input values
|
|
141
|
+
for v in tool_input.values():
|
|
142
|
+
if isinstance(v, str) and pattern.lower() in v.lower():
|
|
143
|
+
return GovernanceResult.DENY
|
|
144
|
+
return GovernanceResult.ALLOW
|
|
145
|
+
|
|
146
|
+
runtime = get_runtime()
|
|
147
|
+
runtime.register_policy(
|
|
148
|
+
rule_name,
|
|
149
|
+
DenyRulePolicy(denied_tools, denied_patterns)
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
"status": "registered",
|
|
154
|
+
"rule_name": rule_name,
|
|
155
|
+
"denied_tools": denied_tools,
|
|
156
|
+
"denied_patterns": denied_patterns,
|
|
157
|
+
"available_policies": list(runtime.policies.keys()),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@mcp.tool()
|
|
162
|
+
def ccs_audit_log(limit: int = 20) -> list[dict]:
|
|
163
|
+
"""
|
|
164
|
+
Retrieve recent CCS governance audit traces.
|
|
165
|
+
|
|
166
|
+
Each trace includes: timestamp, tool_name, result, latency_us,
|
|
167
|
+
policy_name, input_hash, and detail.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
limit: Maximum number of recent traces to return (default: 20)
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
List of audit trace dicts, most recent first
|
|
174
|
+
"""
|
|
175
|
+
runtime = get_runtime()
|
|
176
|
+
traces = runtime.traces[-limit:] if runtime.traces else []
|
|
177
|
+
|
|
178
|
+
return [
|
|
179
|
+
{
|
|
180
|
+
"timestamp": t.timestamp,
|
|
181
|
+
"tool_name": t.tool_name,
|
|
182
|
+
"result": t.result.value,
|
|
183
|
+
"latency_us": t.latency_us,
|
|
184
|
+
"policy_name": t.policy_name,
|
|
185
|
+
"input_hash": t.input_hash,
|
|
186
|
+
"detail": t.detail,
|
|
187
|
+
}
|
|
188
|
+
for t in reversed(traces)
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# ============================================================
|
|
193
|
+
# Entry point
|
|
194
|
+
# ============================================================
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
mcp.run()
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: correctover-ccs
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Correctover Conformance Standard (CCS) v1.0 — Synchronous interceptor governance for AI Agent frameworks
|
|
5
|
+
Author-email: Correctover Standards <wangguigui@correctover.com>
|
|
6
|
+
License: CC BY 4.0
|
|
7
|
+
Project-URL: Homepage, https://correctover.com
|
|
8
|
+
Project-URL: Paper, https://doi.org/10.5281/zenodo.21271910
|
|
9
|
+
Project-URL: Standard, https://github.com/Correctover/standards
|
|
10
|
+
Keywords: ai,agent,governance,security,conformance,mcp
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: Topic :: Security
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Provides-Extra: mcp
|
|
21
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
22
|
+
|
|
23
|
+
# CCS — Correctover Conformance Standard v1.0
|
|
24
|
+
|
|
25
|
+
Synchronous interceptor-based governance for AI Agent frameworks.
|
|
26
|
+
|
|
27
|
+
## Why CCS?
|
|
28
|
+
|
|
29
|
+
Every major Agent framework (CrewAI AGT, AutoGen, LangGraph) uses **observer-pattern hooks** for governance. These hooks are structurally vulnerable to **fail-open bypass** — when the governance layer throws an exception, the framework defaults to allowing tool execution.
|
|
30
|
+
|
|
31
|
+
**This is not a bug. It's an architectural flaw.** (CWE-636, CVSS 9.1)
|
|
32
|
+
|
|
33
|
+
CCS uses **function decorators** instead of hooks. The decorator owns the execution path — if governance fails, the tool is BLOCKED. Never allowed.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Observer hooks: governance_crash → exception caught → hook_blocked=False → tool EXECUTES ❌
|
|
37
|
+
CCS decorators: governance_crash → exception caught → tool NEVER CALLED ✅
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install ccs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start (3 lines)
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from ccs import govern
|
|
50
|
+
|
|
51
|
+
@govern(policy="default")
|
|
52
|
+
def my_tool(args: dict) -> str:
|
|
53
|
+
return "result"
|
|
54
|
+
|
|
55
|
+
# Governance evaluation happens BEFORE the function runs
|
|
56
|
+
# If denied → PermissionError, function never executes
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Framework Adapters
|
|
60
|
+
|
|
61
|
+
Adapters intercept at the framework's tool execution entry point.
|
|
62
|
+
Once installed, ALL tool calls go through CCS governance.
|
|
63
|
+
|
|
64
|
+
### CrewAI
|
|
65
|
+
```python
|
|
66
|
+
from ccs.adapters import crewai_adapter
|
|
67
|
+
crewai_adapter.install() # patches BaseTool.run globally
|
|
68
|
+
# All CrewAI tool calls now governed by CCS
|
|
69
|
+
crewai_adapter.uninstall() # restore original
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### AutoGen (async)
|
|
73
|
+
```python
|
|
74
|
+
from ccs.adapters import autogen_adapter
|
|
75
|
+
autogen_adapter.install() # patches FunctionTool.run
|
|
76
|
+
autogen_adapter.uninstall()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### LangGraph / LangChain
|
|
80
|
+
```python
|
|
81
|
+
from ccs.adapters import langgraph_adapter
|
|
82
|
+
langgraph_adapter.install() # patches LCBaseTool.run
|
|
83
|
+
langgraph_adapter.uninstall()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Verified Against
|
|
87
|
+
| Framework | Version | Interception Point | Pattern |
|
|
88
|
+
|-----------|---------|--------------------|---------|
|
|
89
|
+
| CrewAI | >= 0.1.0 | `BaseTool.run()` | sync |
|
|
90
|
+
| AutoGen | >= 0.7.0 | `FunctionTool.run()` | async |
|
|
91
|
+
| LangGraph | >= 0.2.0 | `LCBaseTool.run()` | sync |
|
|
92
|
+
|
|
93
|
+
## Custom Policies
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from ccs import CCSPolicy, GovernanceResult, govern
|
|
97
|
+
|
|
98
|
+
class CompliancePolicy(CCSPolicy):
|
|
99
|
+
def evaluate(self, tool_name: str, tool_input: dict) -> GovernanceResult:
|
|
100
|
+
if "delete" in tool_name.lower():
|
|
101
|
+
return GovernanceResult.DENY
|
|
102
|
+
return GovernanceResult.ALLOW
|
|
103
|
+
|
|
104
|
+
from ccs.core import get_runtime
|
|
105
|
+
runtime = get_runtime()
|
|
106
|
+
runtime.register_policy("compliance", CompliancePolicy())
|
|
107
|
+
|
|
108
|
+
@govern(policy="compliance")
|
|
109
|
+
def delete_user(user_id: str):
|
|
110
|
+
... # This will never execute — policy denies it
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Fail-Closed Guarantee
|
|
114
|
+
|
|
115
|
+
The fundamental difference from observer-pattern hooks:
|
|
116
|
+
|
|
117
|
+
| | Observer Hooks (AGT) | CCS Decorators |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| Integration | Framework catches hook exception | Decorator owns execution path |
|
|
120
|
+
| On governance crash | `hook_blocked` stays `False` → tool executes | Exception propagates → tool never called |
|
|
121
|
+
| Fail mode | **FAIL-OPEN** ❌ | **FAIL-CLOSED** ✅ |
|
|
122
|
+
| CWE | CWE-636 (Not Failing Securely) | Structurally immune |
|
|
123
|
+
|
|
124
|
+
## Performance
|
|
125
|
+
|
|
126
|
+
CANON benchmark (50,000 traces):
|
|
127
|
+
- **P50 latency: 22µs**
|
|
128
|
+
- **P99 latency: 99µs**
|
|
129
|
+
|
|
130
|
+
## Test Results
|
|
131
|
+
|
|
132
|
+
Verified on 2026-07-09 with real framework installations:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
CrewAI Adapter: BaseTool.run intercepted → fail-closed ✅
|
|
136
|
+
AutoGen Adapter: FunctionTool.run intercepted → fail-closed ✅
|
|
137
|
+
LangGraph Adapter: LCBaseTool.run intercepted → fail-closed ✅
|
|
138
|
+
All adapters support install/uninstall lifecycle ✅
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Performance (10,000 iterations, decorator + policy evaluation):
|
|
142
|
+
```
|
|
143
|
+
P50: 6.2µs
|
|
144
|
+
P99: 15.0µs
|
|
145
|
+
P999: 53.0µs
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## MCP Server
|
|
149
|
+
|
|
150
|
+
CCS is available as a [Model Context Protocol](https://modelcontextprotocol.io) server, enabling any MCP-compatible agent (Claude Desktop, Cursor, Cline) to validate tool calls against CCS governance.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
pip install ccs[mcp]
|
|
154
|
+
python -m ccs.mcp_server
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Configure in Claude Desktop:
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"mcpServers": {
|
|
161
|
+
"ccs": {
|
|
162
|
+
"command": "python",
|
|
163
|
+
"args": ["-m", "ccs.mcp_server"]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### MCP Tools
|
|
170
|
+
| Tool | Description |
|
|
171
|
+
|------|-------------|
|
|
172
|
+
| `ccs_govern` | Evaluate a tool call against a policy → allow/deny |
|
|
173
|
+
| `ccs_status` | Runtime stats, policies, latency metrics |
|
|
174
|
+
| `ccs_register_deny_rule` | Register custom deny rules by tool name/pattern |
|
|
175
|
+
| `ccs_audit_log` | Recent governance audit traces |
|
|
176
|
+
|
|
177
|
+
## TypeScript SDK
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
npm install correctover-ccs
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { govern, GovernanceResult, CCSPolicy } from "correctover-ccs";
|
|
185
|
+
|
|
186
|
+
const governedSearch = govern(searchWeb, { policy: "default" });
|
|
187
|
+
governedSearch({ query: "test" }); // Throws PermissionError if denied
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Source: [`ts/`](./ts) | [npm package](https://www.npmjs.com/package/correctover-ccs)
|
|
191
|
+
|
|
192
|
+
## Go SDK
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
go get github.com/Correctover/ccs-sdk/go
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```go
|
|
199
|
+
rt := ccs.NewRuntime()
|
|
200
|
+
governed := ccs.Govern(searchFn, "default", rt)
|
|
201
|
+
result, err := governed(ccs.ToolInput{"query": "CCS standard"})
|
|
202
|
+
// err = *PermissionError if denied — fn NEVER called
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Source: [`go/`](./go)
|
|
206
|
+
|
|
207
|
+
## Repository Structure
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
ccs-sdk/
|
|
211
|
+
├── ccs/ # Python SDK (core + adapters + MCP server)
|
|
212
|
+
│ ├── core.py # Governance runtime
|
|
213
|
+
│ ├── adapters.py # CrewAI/AutoGen/LangGraph adapters
|
|
214
|
+
│ └── mcp_server/ # MCP server (stdio transport)
|
|
215
|
+
├── ts/ # TypeScript SDK (npm: correctover-ccs)
|
|
216
|
+
│ ├── src/ # Source
|
|
217
|
+
│ └── dist/ # Built output
|
|
218
|
+
├── go/ # Go SDK
|
|
219
|
+
│ └── ccs/ # Core package
|
|
220
|
+
├── strict_9test.py # Python 9-test verification suite
|
|
221
|
+
└── pyproject.toml
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## SDK Versions
|
|
225
|
+
|
|
226
|
+
| SDK | Version | Package |
|
|
227
|
+
|-----|---------|---------|
|
|
228
|
+
| Python | 1.0.0 | `pip install ccs` |
|
|
229
|
+
| TypeScript | 1.0.0 | `npm install correctover-ccs` |
|
|
230
|
+
| Go | 1.0.0 | `go get github.com/Correctover/ccs-sdk/go` |
|
|
231
|
+
|
|
232
|
+
## References
|
|
233
|
+
|
|
234
|
+
- CCS v1.0 Standard: https://doi.org/10.5281/zenodo.21271910
|
|
235
|
+
- CVE Audit (CWE-636 in AGT): https://gist.github.com/Correctover/9cfb97bcf374f79b793fd0bacd4e9d62
|
|
236
|
+
- Correctover: https://correctover.com
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
ccs/__init__.py,sha256=7qmgNN-8jQlB8jjyIKofNaR-ZXL9xNH5L-Xetvu1SFs,745
|
|
2
|
+
ccs/adapters.py,sha256=HB_8PLJ9F6qUZse3Xo05cnXdX4hhRdeYuX2yVSBQ1vo,6724
|
|
3
|
+
ccs/core.py,sha256=qq0j9vkQzLEdjukxM8zHq6N1pWixeniD_5xpKdFn7S4,9126
|
|
4
|
+
ccs/mcp_server/__init__.py,sha256=aiMiPr8qN42olmpuaqE6g451BIg112HtQjfVYqwYQMc,80
|
|
5
|
+
ccs/mcp_server/__main__.py,sha256=x4cZLGJWzuOPB3HjyligYFnU7rPR1q2MILQDQIL7_Y0,173
|
|
6
|
+
ccs/mcp_server/server.py,sha256=amNWHnjrnTG_ncIsPiETDlhuwO6AWEk4sfJmTAENkk0,5822
|
|
7
|
+
correctover_ccs-1.0.0.dist-info/METADATA,sha256=neeJBLOoT5QJRrIgy9SK7rtU9WGPA2JoIIEMNj6WSXc,7092
|
|
8
|
+
correctover_ccs-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
9
|
+
correctover_ccs-1.0.0.dist-info/top_level.txt,sha256=B_84q_sceurFYPD4eVb3n5al34HIbMKe3LgAXojdC_g,4
|
|
10
|
+
correctover_ccs-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ccs
|