correctover 2.0.2__tar.gz → 2.2.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.
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: correctover
3
+ Version: 2.2.0
4
+ Summary: Correctover - AI Agent Runtime Assurance. CCS standard + GuardrailProvider + MCP Security Scanner.
5
+ Author-email: Guigui Wang <wangguigui@correctover.com>
6
+ License: Proprietary Commercial License
7
+ Project-URL: Homepage, https://correctover.com
8
+ Project-URL: CCS Standard, https://correctover.com/ccs
9
+ Project-URL: GitHub, https://github.com/Correctover
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: pydantic>=1.10
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "correctover"
7
+ version = "2.2.0"
8
+ authors = [{name="Guigui Wang", email="wangguigui@correctover.com"}]
9
+ description = "Correctover - AI Agent Runtime Assurance. CCS standard + GuardrailProvider + MCP Security Scanner."
10
+ readme = "README.md"
11
+ license = {text = "Proprietary Commercial License"}
12
+ requires-python = ">=3.8"
13
+ dependencies = ["pydantic>=1.10"]
14
+
15
+ [project.urls]
16
+ Homepage = "https://correctover.com"
17
+ "CCS Standard" = "https://correctover.com/ccs"
18
+ GitHub = "https://github.com/Correctover"
19
+
20
+ [tool.setuptools.packages.find]
21
+ where = ["src"]
@@ -0,0 +1,22 @@
1
+ """Correctover v2.2.0 - AI Agent Runtime Assurance"""
2
+ __version__ = "2.2.0"
3
+ __author__ = "Guigui Wang"
4
+ __email__ = "wangguigui@correctover.com"
5
+ from .validator import CCSValidator, ValidationResult
6
+ from .guardrail import (
7
+ GuardrailDecisionV1, ActionEnvelopeV1, ToolCallContext,
8
+ GuardrailProvider, AllowAllGuardrailProvider, DenyAllGuardrailProvider,
9
+ ToolListGuardrailProvider, CKGGuardrailProvider, EnvProtectionProvider,
10
+ CompositeGuardrailProvider, AuditTrail, GuardrailContext,
11
+ make_guardrail_hook, detect_missing_guardrail, compute_decision_id,
12
+ canonical_json, MCPSecurityValidator,
13
+ )
14
+ __all__ = [
15
+ "CCSValidator","ValidationResult",
16
+ "GuardrailDecisionV1","ActionEnvelopeV1","ToolCallContext",
17
+ "GuardrailProvider","AllowAllGuardrailProvider","DenyAllGuardrailProvider",
18
+ "ToolListGuardrailProvider","CKGGuardrailProvider","EnvProtectionProvider",
19
+ "CompositeGuardrailProvider","AuditTrail","GuardrailContext",
20
+ "make_guardrail_hook","detect_missing_guardrail","compute_decision_id",
21
+ "canonical_json","MCPSecurityValidator",
22
+ ]
@@ -0,0 +1,211 @@
1
+ """
2
+ correctover.guardrail - Framework-agnostic runtime security guardrail system.
3
+ CCS reference implementation.
4
+ """
5
+ import hashlib, json, time
6
+ from abc import ABC, abstractmethod
7
+ from dataclasses import dataclass, field
8
+ from typing import Any, Callable, Dict, List, Optional, Set
9
+
10
+ def canonical_json(obj):
11
+ return json.dumps(obj, sort_keys=True, separators=(",",":"), default=str)
12
+
13
+ def compute_decision_id(claims, expires_at=None):
14
+ preimage = claims.copy()
15
+ if expires_at is not None:
16
+ preimage["_expires_at"] = expires_at
17
+ return hashlib.sha256(canonical_json(preimage).encode("utf-8")).hexdigest()
18
+
19
+ @dataclass(frozen=True)
20
+ class GuardrailDecisionV1:
21
+ decision_id: str
22
+ authorized: bool
23
+ claims: Dict[str, Any]
24
+ expires_at: Optional[float] = None
25
+ def is_expired(self):
26
+ if self.expires_at is None: return False
27
+ return time.time() > self.expires_at
28
+ def verify_integrity(self):
29
+ return self.decision_id == compute_decision_id(self.claims, self.expires_at)
30
+ def to_dict(self):
31
+ return {"decision_id":self.decision_id,"authorized":self.authorized,"claims":self.claims,"expires_at":self.expires_at}
32
+
33
+ @dataclass(frozen=True)
34
+ class ActionEnvelopeV1:
35
+ decision_id: str
36
+ tool_result_digest: str
37
+ executed_at: float
38
+ duration_ms: float
39
+ @staticmethod
40
+ def digest_result(result):
41
+ raw = canonical_json(result) if result is not None else ""
42
+ return hashlib.sha256(raw.encode("utf-8")).hexdigest()
43
+ def to_dict(self):
44
+ return {"decision_id":self.decision_id,"tool_result_digest":self.tool_result_digest,"executed_at":self.executed_at,"duration_ms":self.duration_ms}
45
+
46
+ @dataclass
47
+ class ToolCallContext:
48
+ tool_name: str
49
+ tool_args: Dict[str, Any] = field(default_factory=dict)
50
+ agent_id: str = "unknown"
51
+ metadata: Dict[str, Any] = field(default_factory=dict)
52
+
53
+ class GuardrailProvider(ABC):
54
+ @abstractmethod
55
+ def authorize(self, context: ToolCallContext) -> GuardrailDecisionV1: ...
56
+
57
+ class AllowAllGuardrailProvider(GuardrailProvider):
58
+ def authorize(self, context):
59
+ claims = {"provider":"AllowAllGuardrailProvider","tool_name":context.tool_name,"agent_id":context.agent_id}
60
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=True, claims=claims)
61
+
62
+ class DenyAllGuardrailProvider(GuardrailProvider):
63
+ def authorize(self, context):
64
+ claims = {"provider":"DenyAllGuardrailProvider","tool_name":context.tool_name,"reason":"deny-all safety lock active"}
65
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=False, claims=claims)
66
+
67
+ class ToolListGuardrailProvider(GuardrailProvider):
68
+ def __init__(self, allowed_tools=None, denied_tools=None):
69
+ self.allowed_tools = allowed_tools
70
+ self.denied_tools = denied_tools or set()
71
+ def authorize(self, context):
72
+ claims = {"provider":"ToolListGuardrailProvider","tool_name":context.tool_name,"agent_id":context.agent_id}
73
+ if self.allowed_tools is not None:
74
+ authorized = context.tool_name in self.allowed_tools
75
+ claims["policy"] = "allowlist"
76
+ claims["allowed_tools"] = sorted(self.allowed_tools)
77
+ elif context.tool_name in self.denied_tools:
78
+ authorized = False
79
+ claims["policy"] = "denylist"
80
+ claims["denied_tools"] = sorted(self.denied_tools)
81
+ else:
82
+ authorized = True
83
+ claims["policy"] = "default-allow"
84
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=authorized, claims=claims)
85
+
86
+ class CKGGuardrailProvider(GuardrailProvider):
87
+ def __init__(self):
88
+ self._constraints = []
89
+ def add_constraint(self, predicate, **kwargs):
90
+ self._constraints.append({"predicate":predicate, **kwargs})
91
+ return self
92
+ def authorize(self, context):
93
+ claims = {"provider":"CKGGuardrailProvider","tool_name":context.tool_name,"agent_id":context.agent_id}
94
+ satisfied, failed_predicate = True, None
95
+ for c in self._constraints:
96
+ p = c["predicate"]
97
+ if p=="tool_name_in" and context.tool_name not in c["tools"]: satisfied,failed_predicate=False,p
98
+ elif p=="tool_name_not_in" and context.tool_name in c["tools"]: satisfied,failed_predicate=False,p
99
+ elif p=="agent_id_in" and context.agent_id not in c["agents"]: satisfied,failed_predicate=False,p
100
+ elif p=="param_matches" and context.tool_args.get(c["name"])!=c["value"]: satisfied,failed_predicate=False,p
101
+ elif p=="has_param" and c["name"] not in context.tool_args: satisfied,failed_predicate=False,p
102
+ elif p=="no_param" and c["name"] in context.tool_args: satisfied,failed_predicate=False,p
103
+ if not satisfied: claims["failed_predicate"]=failed_predicate
104
+ claims["constraints_count"]=len(self._constraints)
105
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=satisfied, claims=claims)
106
+
107
+ class EnvProtectionProvider(GuardrailProvider):
108
+ DANGEROUS_PATTERNS = {
109
+ "env_vars":["API_KEY","API_SECRET","SECRET_KEY","PRIVATE_KEY","ACCESS_TOKEN","AUTH_TOKEN","DB_PASSWORD","DATABASE_URL","AWS_SECRET","AWS_ACCESS_KEY","GITHUB_TOKEN","OPENAI_API_KEY","ANTHROPIC_API_KEY"],
110
+ "env_commands":["os.environ","process.env","getenv","env ","printenv","echo $","${"],
111
+ "file_paths":[".env",".env.local",".env.production","credentials.json","service-account.json"],
112
+ }
113
+ def __init__(self, extra_patterns=None):
114
+ self.extra_patterns = extra_patterns or []
115
+ def authorize(self, context):
116
+ claims = {"provider":"EnvProtectionProvider","tool_name":context.tool_name,"agent_id":context.agent_id}
117
+ args_str = canonical_json(context.tool_args).lower()
118
+ matched = [f"{cat}:{p}" for cat,pats in self.DANGEROUS_PATTERNS.items() for p in pats if p.lower() in args_str]
119
+ matched += [f"custom:{p}" for p in self.extra_patterns if p.lower() in args_str]
120
+ if matched:
121
+ claims["matched_patterns"]=matched
122
+ claims["reason"]="Environment variable access attempt detected"
123
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=False, claims=claims)
124
+ claims["reason"]="No environment variable access detected"
125
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=True, claims=claims)
126
+
127
+ class CompositeGuardrailProvider(GuardrailProvider):
128
+ def __init__(self, providers, mode="AND"):
129
+ if mode not in ("AND","OR"): raise ValueError(f"mode must be AND or OR, got {mode}")
130
+ self.providers = providers
131
+ self.mode = mode
132
+ def authorize(self, context):
133
+ results = [p.authorize(context) for p in self.providers]
134
+ authorized = all(d.authorized for d in results) if self.mode=="AND" else any(d.authorized for d in results)
135
+ claims = {"provider":"CompositeGuardrailProvider","mode":self.mode,"tool_name":context.tool_name,"agent_id":context.agent_id,"sub_decisions":[d.decision_id for d in results],"sub_providers":[d.claims.get("provider","unknown") for d in results]}
136
+ return GuardrailDecisionV1(decision_id=compute_decision_id(claims), authorized=authorized, claims=claims)
137
+
138
+ class AuditTrail:
139
+ def __init__(self):
140
+ self._decisions = {}
141
+ self._envelopes = {}
142
+ def record_decision(self, decision): self._decisions[decision.decision_id] = decision
143
+ def record_envelope(self, envelope): self._envelopes[envelope.decision_id] = envelope
144
+ def get_decision(self, did): return self._decisions.get(did)
145
+ def get_envelope(self, did): return self._envelopes.get(did)
146
+ def get_all_decisions(self): return list(self._decisions.values())
147
+ def get_all_envelopes(self): return list(self._envelopes.values())
148
+ def clear(self): self._decisions.clear(); self._envelopes.clear()
149
+ @property
150
+ def decision_count(self): return len(self._decisions)
151
+ @property
152
+ def envelope_count(self): return len(self._envelopes)
153
+ def verify_all(self): return all(d.verify_integrity() for d in self._decisions.values())
154
+ def export(self): return {"decisions":[d.to_dict() for d in self._decisions.values()],"envelopes":[e.to_dict() for e in self._envelopes.values()],"verified":self.verify_all()}
155
+
156
+ class GuardrailContext:
157
+ def __init__(self, provider, trail=None, on_deny=None):
158
+ self.provider = provider; self.trail = trail or AuditTrail(); self.on_deny = on_deny
159
+ def authorize(self, context):
160
+ decision = self.provider.authorize(context)
161
+ self.trail.record_decision(decision)
162
+ if not decision.authorized and self.on_deny: self.on_deny(decision)
163
+ return decision
164
+ def after_tool_call(self, decision, result, start_time):
165
+ duration_ms = (time.time()-start_time)*1000
166
+ envelope = ActionEnvelopeV1(decision_id=decision.decision_id, tool_result_digest=ActionEnvelopeV1.digest_result(result), executed_at=time.time(), duration_ms=duration_ms)
167
+ self.trail.record_envelope(envelope)
168
+ return envelope
169
+
170
+ def make_guardrail_hook(provider, trail=None, on_deny=None):
171
+ ctx = GuardrailContext(provider=provider, trail=trail, on_deny=on_deny)
172
+ def _hook(tool_name, tool_args=None, agent_id="unknown", **kwargs):
173
+ context = ToolCallContext(tool_name=tool_name, tool_args=tool_args or {}, agent_id=agent_id, metadata=kwargs)
174
+ decision = ctx.authorize(context)
175
+ if not decision.authorized: return False
176
+ return None
177
+ _hook._guardrail_context = ctx
178
+ return _hook
179
+
180
+ def detect_missing_guardrail(agents):
181
+ findings = []
182
+ for agent in agents:
183
+ agent_name = getattr(agent,"role",getattr(agent,"name",getattr(agent,"id","unknown")))
184
+ has_hooks = getattr(agent,"_before_tool_call_hooks",None) or getattr(agent,"before_tool_call",None) or getattr(agent,"_guardrails",None) or getattr(agent,"guardrail_provider",None)
185
+ if not has_hooks:
186
+ findings.append({"severity":"CRITICAL","pattern":"AS-GUARDRAIL-MISS-001","agent":agent_name,"message":f"Agent '{agent_name}' has no registered GuardrailProvider","remediation":"Register a GuardrailProvider via make_guardrail_hook()","ccs_ref":"https://correctover.com/ccs"})
187
+ return findings
188
+
189
+ class MCPSecurityValidator:
190
+ DANGEROUS_COMMANDS = ["rm -rf","curl | sh","wget | bash","eval(","exec(","os.system","subprocess.call"]
191
+ SENSITIVE_ENV_PATTERNS = ["API_KEY","SECRET","TOKEN","PASSWORD","PRIVATE_KEY","CREDENTIALS","AUTH"]
192
+ @staticmethod
193
+ def validate_tool_definition(tool_def):
194
+ issues = []
195
+ impl = str(tool_def.get("implementation",""))
196
+ for cmd in MCPSecurityValidator.DANGEROUS_COMMANDS:
197
+ if cmd in impl: issues.append({"severity":"CRITICAL","type":"command_injection","pattern":cmd,"cve_ref":"CVE-2026-42271"})
198
+ env_section = str(tool_def.get("env",{}))
199
+ for pattern in MCPSecurityValidator.SENSITIVE_ENV_PATTERNS:
200
+ if pattern.upper() in env_section.upper(): issues.append({"severity":"HIGH","type":"env_exposure","pattern":pattern,"cve_ref":"CVE-2026-12957"})
201
+ return {"safe":len(issues)==0,"issues":issues,"tool_name":tool_def.get("name","unknown")}
202
+ @staticmethod
203
+ def validate_mcp_config(config):
204
+ issues = []
205
+ transport = config.get("transport","stdio")
206
+ if transport == "stdio":
207
+ env = config.get("env",{})
208
+ if env: issues.append({"severity":"HIGH","type":"stdio_env_exposure","message":"stdio transport with env variables","cve_ref":"CVE-2026-12957","remediation":"Use env_isolation or switch to sse/http transport"})
209
+ for tool in config.get("tools",[]):
210
+ issues.extend(MCPSecurityValidator.validate_tool_definition(tool)["issues"])
211
+ return {"safe":len(issues)==0,"issues":issues,"config_name":config.get("name","unknown")}
@@ -0,0 +1,37 @@
1
+ from typing import Dict, List, Any, Optional
2
+ from pydantic import BaseModel, Field
3
+ from datetime import datetime
4
+ import hashlib, hmac, json
5
+
6
+ class ValidationResult(BaseModel):
7
+ is_valid: bool
8
+ errors: List[str] = Field(default_factory=list)
9
+ warnings: List[str] = Field(default_factory=list)
10
+ validated_at: str = Field(default_factory=lambda: datetime.utcnow().isoformat())
11
+ trace_id: Optional[str] = None
12
+
13
+ class CCSValidator:
14
+ def __init__(self, required_fields=None, supported_fields=None, forbidden_fields=None, enable_integrity=False, integrity_key=None):
15
+ self.required_fields = set(required_fields or [])
16
+ self.supported_fields = set(supported_fields or [])
17
+ self.forbidden_fields = set(forbidden_fields or [])
18
+ self.enable_integrity = enable_integrity
19
+ self.integrity_key = integrity_key or "default-key"
20
+ def validate(self, output, trace_id=None):
21
+ errors, warnings = [], []
22
+ for f in self.required_fields:
23
+ if f not in output: errors.append(f"Missing required field: {f}")
24
+ for f in self.forbidden_fields:
25
+ if f in output: errors.append(f"Forbidden field present: {f}")
26
+ unexpected = set(output.keys()) - self.required_fields - self.supported_fields - self.forbidden_fields
27
+ for f in unexpected: warnings.append(f"Unexpected field: {f}")
28
+ if self.enable_integrity:
29
+ stored_hash = output.get("integrity_hash")
30
+ computed = self._compute_integrity(output)
31
+ if stored_hash is None: warnings.append("No integrity hash in output")
32
+ elif stored_hash != computed: errors.append("Integrity hash mismatch")
33
+ return ValidationResult(is_valid=len(errors)==0, errors=errors, warnings=warnings, trace_id=trace_id)
34
+ def _compute_integrity(self, output):
35
+ data = {k:v for k,v in output.items() if k != "integrity_hash"}
36
+ canonical = json.dumps(data, sort_keys=True, separators=(",",":"))
37
+ return hmac.new(self.integrity_key.encode(), canonical.encode(), hashlib.sha256).hexdigest()
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: correctover
3
+ Version: 2.2.0
4
+ Summary: Correctover - AI Agent Runtime Assurance. CCS standard + GuardrailProvider + MCP Security Scanner.
5
+ Author-email: Guigui Wang <wangguigui@correctover.com>
6
+ License: Proprietary Commercial License
7
+ Project-URL: Homepage, https://correctover.com
8
+ Project-URL: CCS Standard, https://correctover.com/ccs
9
+ Project-URL: GitHub, https://github.com/Correctover
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: pydantic>=1.10
@@ -0,0 +1,9 @@
1
+ pyproject.toml
2
+ src/correctover/__init__.py
3
+ src/correctover/guardrail.py
4
+ src/correctover/validator.py
5
+ src/correctover.egg-info/PKG-INFO
6
+ src/correctover.egg-info/SOURCES.txt
7
+ src/correctover.egg-info/dependency_links.txt
8
+ src/correctover.egg-info/requires.txt
9
+ src/correctover.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ pydantic>=1.10
correctover-2.0.2/LICENSE DELETED
@@ -1,8 +0,0 @@
1
- Proprietary Commercial License
2
-
3
- Copyright (c) 2026 Guigui Wang
4
-
5
- This software is proprietary and confidential. Unauthorized copying,
6
- distribution, or use is strictly prohibited.
7
-
8
- For licensing inquiries, contact: wangguigui@correctover.com
@@ -1,94 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: correctover
3
- Version: 2.0.2
4
- Summary: CCS v1.0 - Conformance Protocol for Agentic Runtime Systems
5
- Home-page: https://correctover.github.io
6
- Author: Guigui Wang
7
- Author-email: wangguigui@correctover.com
8
- Project-URL: Bug Tracker, https://github.com/Correctover/standards/issues
9
- Project-URL: Documentation, https://correctover.github.io
10
- Project-URL: Source, https://github.com/Correctover/standards
11
- Project-URL: DOI, https://doi.org/10.5281/zenodo.21234580
12
- Keywords: llm,validation,conformance,compliance,hipaa,gdpr,soc2,agent,mcp
13
- Classifier: Development Status :: 5 - Production/Stable
14
- Classifier: Intended Audience :: Developers
15
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
- Classifier: License :: Other/Proprietary License
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
- Classifier: Programming Language :: Python :: 3.10
21
- Classifier: Programming Language :: Python :: 3.11
22
- Classifier: Operating System :: OS Independent
23
- Requires-Python: >=3.8
24
- Description-Content-Type: text/markdown
25
- License-File: LICENSE
26
- Requires-Dist: pydantic>=2.0.0
27
- Dynamic: author
28
- Dynamic: author-email
29
- Dynamic: classifier
30
- Dynamic: description
31
- Dynamic: description-content-type
32
- Dynamic: home-page
33
- Dynamic: keywords
34
- Dynamic: license-file
35
- Dynamic: project-url
36
- Dynamic: requires-dist
37
- Dynamic: requires-python
38
- Dynamic: summary
39
-
40
- # Correctover - CCS v1.0
41
-
42
- **Conformance Protocol for Agentic Runtime Systems**
43
-
44
- DOI: [10.5281/zenodo.21234580](https://doi.org/10.5281/zenodo.21234580)
45
-
46
- ## Overview
47
-
48
- Correctover implements the CCS v1.0 standard for validating LLM outputs in agentic systems. It provides provider-agnostic, framework-agnostic conformance verification.
49
-
50
- ## Quick Start
51
-
52
- ```python
53
- from correctover import CCSValidator
54
-
55
- validator = CCSValidator(
56
- required_fields=["decision", "confidence", "trace_id"],
57
- supported_fields=["reasoning", "metadata"],
58
- forbidden_fields=["pii", "credentials"]
59
- )
60
-
61
- result = validator.validate({
62
- "decision": "approve",
63
- "confidence": 0.95,
64
- "trace_id": "abc-123"
65
- })
66
-
67
- print(f"Valid: {result.is_valid}")
68
- ```
69
-
70
- ## Components
71
-
72
- - **CCS-Core**: Schema validation (Required/Supported/Forbidden)
73
- - **CCS-Compliance**: HIPAA, GDPR, SOC2 mapping
74
- - **CCS-Cost-Flow-Analysis**: Token budget enforcement
75
- - **CCS-Integrity**: HMAC-based output binding
76
- - **CCS-Audit**: Comprehensive audit logging
77
-
78
- ## Integration
79
-
80
- Framework adapters available:
81
- - LangChain
82
- - CrewAI
83
- - AutoGen
84
- - LlamaIndex
85
-
86
- ## License
87
-
88
- Proprietary Commercial License — see LICENSE file
89
-
90
- ## Resources
91
-
92
- - Website: https://correctover.github.io
93
- - Specification: https://github.com/Correctover/standards
94
- - DOI: https://doi.org/10.5281/zenodo.21234580
@@ -1,55 +0,0 @@
1
- # Correctover - CCS v1.0
2
-
3
- **Conformance Protocol for Agentic Runtime Systems**
4
-
5
- DOI: [10.5281/zenodo.21234580](https://doi.org/10.5281/zenodo.21234580)
6
-
7
- ## Overview
8
-
9
- Correctover implements the CCS v1.0 standard for validating LLM outputs in agentic systems. It provides provider-agnostic, framework-agnostic conformance verification.
10
-
11
- ## Quick Start
12
-
13
- ```python
14
- from correctover import CCSValidator
15
-
16
- validator = CCSValidator(
17
- required_fields=["decision", "confidence", "trace_id"],
18
- supported_fields=["reasoning", "metadata"],
19
- forbidden_fields=["pii", "credentials"]
20
- )
21
-
22
- result = validator.validate({
23
- "decision": "approve",
24
- "confidence": 0.95,
25
- "trace_id": "abc-123"
26
- })
27
-
28
- print(f"Valid: {result.is_valid}")
29
- ```
30
-
31
- ## Components
32
-
33
- - **CCS-Core**: Schema validation (Required/Supported/Forbidden)
34
- - **CCS-Compliance**: HIPAA, GDPR, SOC2 mapping
35
- - **CCS-Cost-Flow-Analysis**: Token budget enforcement
36
- - **CCS-Integrity**: HMAC-based output binding
37
- - **CCS-Audit**: Comprehensive audit logging
38
-
39
- ## Integration
40
-
41
- Framework adapters available:
42
- - LangChain
43
- - CrewAI
44
- - AutoGen
45
- - LlamaIndex
46
-
47
- ## License
48
-
49
- Proprietary Commercial License — see LICENSE file
50
-
51
- ## Resources
52
-
53
- - Website: https://correctover.github.io
54
- - Specification: https://github.com/Correctover/standards
55
- - DOI: https://doi.org/10.5281/zenodo.21234580
@@ -1,12 +0,0 @@
1
- """
2
- Correctover - CCS v1.0
3
- Conformance Protocol for Agentic Runtime Systems
4
- """
5
-
6
- __version__ = "2.0.2"
7
- __author__ = "Guigui Wang"
8
- __email__ = "wangguigui@correctover.com"
9
-
10
- from .validator import CCSValidator, ValidationResult
11
-
12
- __all__ = ["CCSValidator", "ValidationResult"]
@@ -1,98 +0,0 @@
1
- """
2
- CCS v1.0 Validator
3
- Validates LLM outputs against Required/Supported/Forbidden schemas
4
- """
5
-
6
- from typing import Dict, List, Any, Optional
7
- from pydantic import BaseModel, Field
8
- from datetime import datetime
9
- import hashlib
10
- import hmac
11
- import json
12
-
13
-
14
- class ValidationResult(BaseModel):
15
- """Result of CCS validation"""
16
- is_valid: bool
17
- errors: List[str] = Field(default_factory=list)
18
- warnings: List[str] = Field(default_factory=list)
19
- validated_at: str = Field(default_factory=lambda: datetime.utcnow().isoformat())
20
- trace_id: Optional[str] = None
21
-
22
-
23
- class CCSValidator:
24
- """
25
- CCS v1.0 Validator
26
-
27
- Validates LLM outputs against Required/Supported/Forbidden schemas.
28
- """
29
-
30
- def __init__(
31
- self,
32
- required_fields: List[str] = None,
33
- supported_fields: List[str] = None,
34
- forbidden_fields: List[str] = None,
35
- enable_integrity: bool = False,
36
- integrity_key: str = None
37
- ):
38
- self.required_fields = set(required_fields or [])
39
- self.supported_fields = set(supported_fields or [])
40
- self.forbidden_fields = set(forbidden_fields or [])
41
- self.enable_integrity = enable_integrity
42
- self.integrity_key = integrity_key or "default-key"
43
-
44
- def validate(self, output: Dict[str, Any], trace_id: str = None) -> ValidationResult:
45
- """Validate LLM output against CCS schema"""
46
- errors = []
47
- warnings = []
48
-
49
- for field in self.required_fields:
50
- if field not in output:
51
- errors.append(f"Missing required field: {field}")
52
-
53
- for field in self.forbidden_fields:
54
- if field in output:
55
- errors.append(f"Forbidden field present: {field}")
56
-
57
- output_fields = set(output.keys())
58
- all_allowed = self.required_fields | self.supported_fields
59
- unexpected = output_fields - all_allowed - self.forbidden_fields
60
- for field in unexpected:
61
- warnings.append(f"Unexpected field: {field}")
62
-
63
- if self.enable_integrity:
64
- stored_hash = output.get("integrity_hash")
65
- computed_hash = self._compute_integrity(output)
66
-
67
- if stored_hash is None:
68
- warnings.append("No integrity hash in output")
69
- elif stored_hash != computed_hash:
70
- errors.append("Integrity hash mismatch")
71
-
72
- return ValidationResult(
73
- is_valid=len(errors) == 0,
74
- errors=errors,
75
- warnings=warnings,
76
- trace_id=trace_id
77
- )
78
-
79
- def _compute_integrity(self, output: Dict[str, Any]) -> str:
80
- """Compute HMAC-based integrity hash using JSON serialization"""
81
- # Exclude integrity_hash from computation
82
- filtered = {k: v for k, v in output.items() if k != "integrity_hash"}
83
- # Use JSON serialization (sorted keys, no extra spaces)
84
- data_str = json.dumps(filtered, sort_keys=True, separators=(',', ':'))
85
-
86
- signature = hmac.new(
87
- self.integrity_key.encode(),
88
- data_str.encode(),
89
- hashlib.sha256
90
- ).hexdigest()
91
-
92
- return signature
93
-
94
- def add_integrity_hash(self, output: Dict[str, Any]) -> Dict[str, Any]:
95
- """Add integrity hash to output"""
96
- output_copy = output.copy()
97
- output_copy["integrity_hash"] = self._compute_integrity(output_copy)
98
- return output_copy
@@ -1,94 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: correctover
3
- Version: 2.0.2
4
- Summary: CCS v1.0 - Conformance Protocol for Agentic Runtime Systems
5
- Home-page: https://correctover.github.io
6
- Author: Guigui Wang
7
- Author-email: wangguigui@correctover.com
8
- Project-URL: Bug Tracker, https://github.com/Correctover/standards/issues
9
- Project-URL: Documentation, https://correctover.github.io
10
- Project-URL: Source, https://github.com/Correctover/standards
11
- Project-URL: DOI, https://doi.org/10.5281/zenodo.21234580
12
- Keywords: llm,validation,conformance,compliance,hipaa,gdpr,soc2,agent,mcp
13
- Classifier: Development Status :: 5 - Production/Stable
14
- Classifier: Intended Audience :: Developers
15
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
- Classifier: License :: Other/Proprietary License
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
- Classifier: Programming Language :: Python :: 3.10
21
- Classifier: Programming Language :: Python :: 3.11
22
- Classifier: Operating System :: OS Independent
23
- Requires-Python: >=3.8
24
- Description-Content-Type: text/markdown
25
- License-File: LICENSE
26
- Requires-Dist: pydantic>=2.0.0
27
- Dynamic: author
28
- Dynamic: author-email
29
- Dynamic: classifier
30
- Dynamic: description
31
- Dynamic: description-content-type
32
- Dynamic: home-page
33
- Dynamic: keywords
34
- Dynamic: license-file
35
- Dynamic: project-url
36
- Dynamic: requires-dist
37
- Dynamic: requires-python
38
- Dynamic: summary
39
-
40
- # Correctover - CCS v1.0
41
-
42
- **Conformance Protocol for Agentic Runtime Systems**
43
-
44
- DOI: [10.5281/zenodo.21234580](https://doi.org/10.5281/zenodo.21234580)
45
-
46
- ## Overview
47
-
48
- Correctover implements the CCS v1.0 standard for validating LLM outputs in agentic systems. It provides provider-agnostic, framework-agnostic conformance verification.
49
-
50
- ## Quick Start
51
-
52
- ```python
53
- from correctover import CCSValidator
54
-
55
- validator = CCSValidator(
56
- required_fields=["decision", "confidence", "trace_id"],
57
- supported_fields=["reasoning", "metadata"],
58
- forbidden_fields=["pii", "credentials"]
59
- )
60
-
61
- result = validator.validate({
62
- "decision": "approve",
63
- "confidence": 0.95,
64
- "trace_id": "abc-123"
65
- })
66
-
67
- print(f"Valid: {result.is_valid}")
68
- ```
69
-
70
- ## Components
71
-
72
- - **CCS-Core**: Schema validation (Required/Supported/Forbidden)
73
- - **CCS-Compliance**: HIPAA, GDPR, SOC2 mapping
74
- - **CCS-Cost-Flow-Analysis**: Token budget enforcement
75
- - **CCS-Integrity**: HMAC-based output binding
76
- - **CCS-Audit**: Comprehensive audit logging
77
-
78
- ## Integration
79
-
80
- Framework adapters available:
81
- - LangChain
82
- - CrewAI
83
- - AutoGen
84
- - LlamaIndex
85
-
86
- ## License
87
-
88
- Proprietary Commercial License — see LICENSE file
89
-
90
- ## Resources
91
-
92
- - Website: https://correctover.github.io
93
- - Specification: https://github.com/Correctover/standards
94
- - DOI: https://doi.org/10.5281/zenodo.21234580
@@ -1,10 +0,0 @@
1
- LICENSE
2
- README.md
3
- setup.py
4
- correctover/__init__.py
5
- correctover/validator.py
6
- correctover.egg-info/PKG-INFO
7
- correctover.egg-info/SOURCES.txt
8
- correctover.egg-info/dependency_links.txt
9
- correctover.egg-info/requires.txt
10
- correctover.egg-info/top_level.txt
@@ -1 +0,0 @@
1
- pydantic>=2.0.0
@@ -1,39 +0,0 @@
1
- from setuptools import setup, find_packages
2
-
3
- with open("README.md", "r", encoding="utf-8") as fh:
4
- long_description = fh.read()
5
-
6
- setup(
7
- name="correctover",
8
- version="2.0.2",
9
- author="Guigui Wang",
10
- author_email="wangguigui@correctover.com",
11
- description="CCS v1.0 - Conformance Protocol for Agentic Runtime Systems",
12
- long_description=long_description,
13
- long_description_content_type="text/markdown",
14
- url="https://correctover.github.io",
15
- project_urls={
16
- "Bug Tracker": "https://github.com/Correctover/standards/issues",
17
- "Documentation": "https://correctover.github.io",
18
- "Source": "https://github.com/Correctover/standards",
19
- "DOI": "https://doi.org/10.5281/zenodo.21234580",
20
- },
21
- packages=find_packages(),
22
- classifiers=[
23
- "Development Status :: 5 - Production/Stable",
24
- "Intended Audience :: Developers",
25
- "Topic :: Software Development :: Libraries :: Python Modules",
26
- "License :: Other/Proprietary License",
27
- "Programming Language :: Python :: 3",
28
- "Programming Language :: Python :: 3.8",
29
- "Programming Language :: Python :: 3.9",
30
- "Programming Language :: Python :: 3.10",
31
- "Programming Language :: Python :: 3.11",
32
- "Operating System :: OS Independent",
33
- ],
34
- python_requires=">=3.8",
35
- install_requires=[
36
- "pydantic>=2.0.0",
37
- ],
38
- keywords="llm, validation, conformance, compliance, hipaa, gdpr, soc2, agent, mcp",
39
- )
File without changes