correctover-ccs 1.0.0__tar.gz
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.
- correctover_ccs-1.0.0/PKG-INFO +236 -0
- correctover_ccs-1.0.0/README.md +214 -0
- correctover_ccs-1.0.0/ccs/__init__.py +31 -0
- correctover_ccs-1.0.0/ccs/adapters.py +195 -0
- correctover_ccs-1.0.0/ccs/core.py +266 -0
- correctover_ccs-1.0.0/ccs/mcp_server/__init__.py +4 -0
- correctover_ccs-1.0.0/ccs/mcp_server/__main__.py +7 -0
- correctover_ccs-1.0.0/ccs/mcp_server/server.py +196 -0
- correctover_ccs-1.0.0/correctover_ccs.egg-info/PKG-INFO +236 -0
- correctover_ccs-1.0.0/correctover_ccs.egg-info/SOURCES.txt +13 -0
- correctover_ccs-1.0.0/correctover_ccs.egg-info/dependency_links.txt +1 -0
- correctover_ccs-1.0.0/correctover_ccs.egg-info/requires.txt +3 -0
- correctover_ccs-1.0.0/correctover_ccs.egg-info/top_level.txt +1 -0
- correctover_ccs-1.0.0/pyproject.toml +33 -0
- correctover_ccs-1.0.0/setup.cfg +4 -0
|
@@ -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,214 @@
|
|
|
1
|
+
# CCS — Correctover Conformance Standard v1.0
|
|
2
|
+
|
|
3
|
+
Synchronous interceptor-based governance for AI Agent frameworks.
|
|
4
|
+
|
|
5
|
+
## Why CCS?
|
|
6
|
+
|
|
7
|
+
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.
|
|
8
|
+
|
|
9
|
+
**This is not a bug. It's an architectural flaw.** (CWE-636, CVSS 9.1)
|
|
10
|
+
|
|
11
|
+
CCS uses **function decorators** instead of hooks. The decorator owns the execution path — if governance fails, the tool is BLOCKED. Never allowed.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Observer hooks: governance_crash → exception caught → hook_blocked=False → tool EXECUTES ❌
|
|
15
|
+
CCS decorators: governance_crash → exception caught → tool NEVER CALLED ✅
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install ccs
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start (3 lines)
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from ccs import govern
|
|
28
|
+
|
|
29
|
+
@govern(policy="default")
|
|
30
|
+
def my_tool(args: dict) -> str:
|
|
31
|
+
return "result"
|
|
32
|
+
|
|
33
|
+
# Governance evaluation happens BEFORE the function runs
|
|
34
|
+
# If denied → PermissionError, function never executes
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Framework Adapters
|
|
38
|
+
|
|
39
|
+
Adapters intercept at the framework's tool execution entry point.
|
|
40
|
+
Once installed, ALL tool calls go through CCS governance.
|
|
41
|
+
|
|
42
|
+
### CrewAI
|
|
43
|
+
```python
|
|
44
|
+
from ccs.adapters import crewai_adapter
|
|
45
|
+
crewai_adapter.install() # patches BaseTool.run globally
|
|
46
|
+
# All CrewAI tool calls now governed by CCS
|
|
47
|
+
crewai_adapter.uninstall() # restore original
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### AutoGen (async)
|
|
51
|
+
```python
|
|
52
|
+
from ccs.adapters import autogen_adapter
|
|
53
|
+
autogen_adapter.install() # patches FunctionTool.run
|
|
54
|
+
autogen_adapter.uninstall()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### LangGraph / LangChain
|
|
58
|
+
```python
|
|
59
|
+
from ccs.adapters import langgraph_adapter
|
|
60
|
+
langgraph_adapter.install() # patches LCBaseTool.run
|
|
61
|
+
langgraph_adapter.uninstall()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Verified Against
|
|
65
|
+
| Framework | Version | Interception Point | Pattern |
|
|
66
|
+
|-----------|---------|--------------------|---------|
|
|
67
|
+
| CrewAI | >= 0.1.0 | `BaseTool.run()` | sync |
|
|
68
|
+
| AutoGen | >= 0.7.0 | `FunctionTool.run()` | async |
|
|
69
|
+
| LangGraph | >= 0.2.0 | `LCBaseTool.run()` | sync |
|
|
70
|
+
|
|
71
|
+
## Custom Policies
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from ccs import CCSPolicy, GovernanceResult, govern
|
|
75
|
+
|
|
76
|
+
class CompliancePolicy(CCSPolicy):
|
|
77
|
+
def evaluate(self, tool_name: str, tool_input: dict) -> GovernanceResult:
|
|
78
|
+
if "delete" in tool_name.lower():
|
|
79
|
+
return GovernanceResult.DENY
|
|
80
|
+
return GovernanceResult.ALLOW
|
|
81
|
+
|
|
82
|
+
from ccs.core import get_runtime
|
|
83
|
+
runtime = get_runtime()
|
|
84
|
+
runtime.register_policy("compliance", CompliancePolicy())
|
|
85
|
+
|
|
86
|
+
@govern(policy="compliance")
|
|
87
|
+
def delete_user(user_id: str):
|
|
88
|
+
... # This will never execute — policy denies it
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Fail-Closed Guarantee
|
|
92
|
+
|
|
93
|
+
The fundamental difference from observer-pattern hooks:
|
|
94
|
+
|
|
95
|
+
| | Observer Hooks (AGT) | CCS Decorators |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| Integration | Framework catches hook exception | Decorator owns execution path |
|
|
98
|
+
| On governance crash | `hook_blocked` stays `False` → tool executes | Exception propagates → tool never called |
|
|
99
|
+
| Fail mode | **FAIL-OPEN** ❌ | **FAIL-CLOSED** ✅ |
|
|
100
|
+
| CWE | CWE-636 (Not Failing Securely) | Structurally immune |
|
|
101
|
+
|
|
102
|
+
## Performance
|
|
103
|
+
|
|
104
|
+
CANON benchmark (50,000 traces):
|
|
105
|
+
- **P50 latency: 22µs**
|
|
106
|
+
- **P99 latency: 99µs**
|
|
107
|
+
|
|
108
|
+
## Test Results
|
|
109
|
+
|
|
110
|
+
Verified on 2026-07-09 with real framework installations:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
CrewAI Adapter: BaseTool.run intercepted → fail-closed ✅
|
|
114
|
+
AutoGen Adapter: FunctionTool.run intercepted → fail-closed ✅
|
|
115
|
+
LangGraph Adapter: LCBaseTool.run intercepted → fail-closed ✅
|
|
116
|
+
All adapters support install/uninstall lifecycle ✅
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Performance (10,000 iterations, decorator + policy evaluation):
|
|
120
|
+
```
|
|
121
|
+
P50: 6.2µs
|
|
122
|
+
P99: 15.0µs
|
|
123
|
+
P999: 53.0µs
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## MCP Server
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pip install ccs[mcp]
|
|
132
|
+
python -m ccs.mcp_server
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Configure in Claude Desktop:
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"mcpServers": {
|
|
139
|
+
"ccs": {
|
|
140
|
+
"command": "python",
|
|
141
|
+
"args": ["-m", "ccs.mcp_server"]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### MCP Tools
|
|
148
|
+
| Tool | Description |
|
|
149
|
+
|------|-------------|
|
|
150
|
+
| `ccs_govern` | Evaluate a tool call against a policy → allow/deny |
|
|
151
|
+
| `ccs_status` | Runtime stats, policies, latency metrics |
|
|
152
|
+
| `ccs_register_deny_rule` | Register custom deny rules by tool name/pattern |
|
|
153
|
+
| `ccs_audit_log` | Recent governance audit traces |
|
|
154
|
+
|
|
155
|
+
## TypeScript SDK
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm install correctover-ccs
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { govern, GovernanceResult, CCSPolicy } from "correctover-ccs";
|
|
163
|
+
|
|
164
|
+
const governedSearch = govern(searchWeb, { policy: "default" });
|
|
165
|
+
governedSearch({ query: "test" }); // Throws PermissionError if denied
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Source: [`ts/`](./ts) | [npm package](https://www.npmjs.com/package/correctover-ccs)
|
|
169
|
+
|
|
170
|
+
## Go SDK
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
go get github.com/Correctover/ccs-sdk/go
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```go
|
|
177
|
+
rt := ccs.NewRuntime()
|
|
178
|
+
governed := ccs.Govern(searchFn, "default", rt)
|
|
179
|
+
result, err := governed(ccs.ToolInput{"query": "CCS standard"})
|
|
180
|
+
// err = *PermissionError if denied — fn NEVER called
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Source: [`go/`](./go)
|
|
184
|
+
|
|
185
|
+
## Repository Structure
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
ccs-sdk/
|
|
189
|
+
├── ccs/ # Python SDK (core + adapters + MCP server)
|
|
190
|
+
│ ├── core.py # Governance runtime
|
|
191
|
+
│ ├── adapters.py # CrewAI/AutoGen/LangGraph adapters
|
|
192
|
+
│ └── mcp_server/ # MCP server (stdio transport)
|
|
193
|
+
├── ts/ # TypeScript SDK (npm: correctover-ccs)
|
|
194
|
+
│ ├── src/ # Source
|
|
195
|
+
│ └── dist/ # Built output
|
|
196
|
+
├── go/ # Go SDK
|
|
197
|
+
│ └── ccs/ # Core package
|
|
198
|
+
├── strict_9test.py # Python 9-test verification suite
|
|
199
|
+
└── pyproject.toml
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## SDK Versions
|
|
203
|
+
|
|
204
|
+
| SDK | Version | Package |
|
|
205
|
+
|-----|---------|---------|
|
|
206
|
+
| Python | 1.0.0 | `pip install ccs` |
|
|
207
|
+
| TypeScript | 1.0.0 | `npm install correctover-ccs` |
|
|
208
|
+
| Go | 1.0.0 | `go get github.com/Correctover/ccs-sdk/go` |
|
|
209
|
+
|
|
210
|
+
## References
|
|
211
|
+
|
|
212
|
+
- CCS v1.0 Standard: https://doi.org/10.5281/zenodo.21271910
|
|
213
|
+
- CVE Audit (CWE-636 in AGT): https://gist.github.com/Correctover/9cfb97bcf374f79b793fd0bacd4e9d62
|
|
214
|
+
- Correctover: https://correctover.com
|
|
@@ -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
|
+
]
|
|
@@ -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()
|