ciris-verify 0.1.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.
- ciris_verify-0.1.0/PKG-INFO +152 -0
- ciris_verify-0.1.0/README.md +121 -0
- ciris_verify-0.1.0/ciris_verify/__init__.py +63 -0
- ciris_verify-0.1.0/ciris_verify/client.py +770 -0
- ciris_verify-0.1.0/ciris_verify/exceptions.py +45 -0
- ciris_verify-0.1.0/ciris_verify/libciris_verify_ffi.dylib +0 -0
- ciris_verify-0.1.0/ciris_verify/py.typed +0 -0
- ciris_verify-0.1.0/ciris_verify/types.py +246 -0
- ciris_verify-0.1.0/ciris_verify.egg-info/PKG-INFO +152 -0
- ciris_verify-0.1.0/ciris_verify.egg-info/SOURCES.txt +16 -0
- ciris_verify-0.1.0/ciris_verify.egg-info/dependency_links.txt +1 -0
- ciris_verify-0.1.0/ciris_verify.egg-info/requires.txt +6 -0
- ciris_verify-0.1.0/ciris_verify.egg-info/top_level.txt +1 -0
- ciris_verify-0.1.0/pyproject.toml +56 -0
- ciris_verify-0.1.0/setup.cfg +4 -0
- ciris_verify-0.1.0/tests/__init__.py +1 -0
- ciris_verify-0.1.0/tests/test_client.py +148 -0
- ciris_verify-0.1.0/tests/test_types.py +216 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ciris-verify
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python bindings for CIRISVerify hardware-rooted license verification
|
|
5
|
+
Author-email: CIRIS Engineering <engineering@ciris.ai>
|
|
6
|
+
License-Expression: AGPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/CIRISAI/CIRISVerify
|
|
8
|
+
Project-URL: Repository, https://github.com/CIRISAI/CIRISVerify
|
|
9
|
+
Project-URL: Documentation, https://github.com/CIRISAI/CIRISVerify/tree/main/bindings/python
|
|
10
|
+
Project-URL: Issues, https://github.com/CIRISAI/CIRISVerify/issues
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Rust
|
|
22
|
+
Classifier: Topic :: Security :: Cryptography
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
31
|
+
|
|
32
|
+
# CIRISVerify Python Bindings
|
|
33
|
+
|
|
34
|
+
Python bindings for CIRISVerify, the hardware-rooted license verification module for the CIRIS ecosystem.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install ciris-verify
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Note:** The CIRISVerify binary must be installed separately. See the [CIRISVerify documentation](https://github.com/CIRISAI/CIRISVerify) for installation instructions.
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import os
|
|
48
|
+
from ciris_verify import CIRISVerify, LicenseStatus
|
|
49
|
+
|
|
50
|
+
# Initialize the verifier
|
|
51
|
+
verifier = CIRISVerify()
|
|
52
|
+
|
|
53
|
+
# Get license status with a fresh nonce
|
|
54
|
+
status = await verifier.get_license_status(
|
|
55
|
+
challenge_nonce=os.urandom(32)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Check if professional capabilities are available
|
|
59
|
+
if status.allows_licensed_operation():
|
|
60
|
+
print("Professional license verified!")
|
|
61
|
+
print(f"Tier: {status.license.tier}")
|
|
62
|
+
print(f"Capabilities: {status.license.capabilities}")
|
|
63
|
+
else:
|
|
64
|
+
print("Running in community mode")
|
|
65
|
+
|
|
66
|
+
# IMPORTANT: Always display the mandatory disclosure
|
|
67
|
+
print(status.mandatory_disclosure.text)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Mandatory Disclosure
|
|
71
|
+
|
|
72
|
+
Per the CIRIS ecosystem rules, agents **MUST** display the `mandatory_disclosure.text` to users. This ensures transparency about the agent's capabilities and licensing status.
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# The disclosure MUST be shown to users
|
|
76
|
+
disclosure = status.mandatory_disclosure
|
|
77
|
+
print(f"[{disclosure.severity.upper()}] {disclosure.text}")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Capability Checking
|
|
81
|
+
|
|
82
|
+
For frequent capability checks, use the fast path:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
result = await verifier.check_capability("medical:diagnosis")
|
|
86
|
+
if result.allowed:
|
|
87
|
+
# Capability is available
|
|
88
|
+
pass
|
|
89
|
+
else:
|
|
90
|
+
print(f"Capability denied: {result.reason}")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Testing
|
|
94
|
+
|
|
95
|
+
For testing without the actual binary, use `MockCIRISVerify`:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from ciris_verify import MockCIRISVerify, LicenseStatus
|
|
99
|
+
|
|
100
|
+
# Create a mock that returns community mode
|
|
101
|
+
verifier = MockCIRISVerify(
|
|
102
|
+
mock_status=LicenseStatus.UNLICENSED_COMMUNITY
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Use exactly like the real client
|
|
106
|
+
status = await verifier.get_license_status(os.urandom(32))
|
|
107
|
+
assert status.status == LicenseStatus.UNLICENSED_COMMUNITY
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Error Handling
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from ciris_verify import (
|
|
114
|
+
CIRISVerifyError,
|
|
115
|
+
BinaryNotFoundError,
|
|
116
|
+
BinaryTamperedError,
|
|
117
|
+
VerificationFailedError,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
verifier = CIRISVerify()
|
|
122
|
+
status = await verifier.get_license_status(os.urandom(32))
|
|
123
|
+
except BinaryNotFoundError as e:
|
|
124
|
+
# Binary not installed
|
|
125
|
+
print(f"CIRISVerify not found: {e.path}")
|
|
126
|
+
except BinaryTamperedError:
|
|
127
|
+
# CRITICAL: Binary has been modified
|
|
128
|
+
# Halt all operations immediately
|
|
129
|
+
raise SystemExit("SECURITY ALERT: Binary integrity compromised")
|
|
130
|
+
except VerificationFailedError as e:
|
|
131
|
+
# Verification failed - operate in restricted mode
|
|
132
|
+
print(f"Verification failed: {e}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## License Status Codes
|
|
136
|
+
|
|
137
|
+
| Status | Code | Description |
|
|
138
|
+
|--------|------|-------------|
|
|
139
|
+
| `LICENSED_PROFESSIONAL` | 100 | Full professional license active |
|
|
140
|
+
| `LICENSED_PROFESSIONAL_GRACE` | 101 | License valid, in offline grace period |
|
|
141
|
+
| `UNLICENSED_COMMUNITY` | 200 | Community mode, no professional capabilities |
|
|
142
|
+
| `RESTRICTED_*` | 300-399 | Restricted mode due to verification issues |
|
|
143
|
+
| `ERROR_*` | 400-499 | Error states (revoked, expired, etc.) |
|
|
144
|
+
| `LOCKDOWN_*` | 500+ | Critical security failure, halt operations |
|
|
145
|
+
|
|
146
|
+
## Thread Safety
|
|
147
|
+
|
|
148
|
+
The client is thread-safe and can be used from multiple threads or async tasks concurrently.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
AGPL-3.0-or-later - See LICENSE file in the CIRISVerify repository.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# CIRISVerify Python Bindings
|
|
2
|
+
|
|
3
|
+
Python bindings for CIRISVerify, the hardware-rooted license verification module for the CIRIS ecosystem.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install ciris-verify
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Note:** The CIRISVerify binary must be installed separately. See the [CIRISVerify documentation](https://github.com/CIRISAI/CIRISVerify) for installation instructions.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import os
|
|
17
|
+
from ciris_verify import CIRISVerify, LicenseStatus
|
|
18
|
+
|
|
19
|
+
# Initialize the verifier
|
|
20
|
+
verifier = CIRISVerify()
|
|
21
|
+
|
|
22
|
+
# Get license status with a fresh nonce
|
|
23
|
+
status = await verifier.get_license_status(
|
|
24
|
+
challenge_nonce=os.urandom(32)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# Check if professional capabilities are available
|
|
28
|
+
if status.allows_licensed_operation():
|
|
29
|
+
print("Professional license verified!")
|
|
30
|
+
print(f"Tier: {status.license.tier}")
|
|
31
|
+
print(f"Capabilities: {status.license.capabilities}")
|
|
32
|
+
else:
|
|
33
|
+
print("Running in community mode")
|
|
34
|
+
|
|
35
|
+
# IMPORTANT: Always display the mandatory disclosure
|
|
36
|
+
print(status.mandatory_disclosure.text)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Mandatory Disclosure
|
|
40
|
+
|
|
41
|
+
Per the CIRIS ecosystem rules, agents **MUST** display the `mandatory_disclosure.text` to users. This ensures transparency about the agent's capabilities and licensing status.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
# The disclosure MUST be shown to users
|
|
45
|
+
disclosure = status.mandatory_disclosure
|
|
46
|
+
print(f"[{disclosure.severity.upper()}] {disclosure.text}")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Capability Checking
|
|
50
|
+
|
|
51
|
+
For frequent capability checks, use the fast path:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
result = await verifier.check_capability("medical:diagnosis")
|
|
55
|
+
if result.allowed:
|
|
56
|
+
# Capability is available
|
|
57
|
+
pass
|
|
58
|
+
else:
|
|
59
|
+
print(f"Capability denied: {result.reason}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Testing
|
|
63
|
+
|
|
64
|
+
For testing without the actual binary, use `MockCIRISVerify`:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from ciris_verify import MockCIRISVerify, LicenseStatus
|
|
68
|
+
|
|
69
|
+
# Create a mock that returns community mode
|
|
70
|
+
verifier = MockCIRISVerify(
|
|
71
|
+
mock_status=LicenseStatus.UNLICENSED_COMMUNITY
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Use exactly like the real client
|
|
75
|
+
status = await verifier.get_license_status(os.urandom(32))
|
|
76
|
+
assert status.status == LicenseStatus.UNLICENSED_COMMUNITY
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Error Handling
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from ciris_verify import (
|
|
83
|
+
CIRISVerifyError,
|
|
84
|
+
BinaryNotFoundError,
|
|
85
|
+
BinaryTamperedError,
|
|
86
|
+
VerificationFailedError,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
verifier = CIRISVerify()
|
|
91
|
+
status = await verifier.get_license_status(os.urandom(32))
|
|
92
|
+
except BinaryNotFoundError as e:
|
|
93
|
+
# Binary not installed
|
|
94
|
+
print(f"CIRISVerify not found: {e.path}")
|
|
95
|
+
except BinaryTamperedError:
|
|
96
|
+
# CRITICAL: Binary has been modified
|
|
97
|
+
# Halt all operations immediately
|
|
98
|
+
raise SystemExit("SECURITY ALERT: Binary integrity compromised")
|
|
99
|
+
except VerificationFailedError as e:
|
|
100
|
+
# Verification failed - operate in restricted mode
|
|
101
|
+
print(f"Verification failed: {e}")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## License Status Codes
|
|
105
|
+
|
|
106
|
+
| Status | Code | Description |
|
|
107
|
+
|--------|------|-------------|
|
|
108
|
+
| `LICENSED_PROFESSIONAL` | 100 | Full professional license active |
|
|
109
|
+
| `LICENSED_PROFESSIONAL_GRACE` | 101 | License valid, in offline grace period |
|
|
110
|
+
| `UNLICENSED_COMMUNITY` | 200 | Community mode, no professional capabilities |
|
|
111
|
+
| `RESTRICTED_*` | 300-399 | Restricted mode due to verification issues |
|
|
112
|
+
| `ERROR_*` | 400-499 | Error states (revoked, expired, etc.) |
|
|
113
|
+
| `LOCKDOWN_*` | 500+ | Critical security failure, halt operations |
|
|
114
|
+
|
|
115
|
+
## Thread Safety
|
|
116
|
+
|
|
117
|
+
The client is thread-safe and can be used from multiple threads or async tasks concurrently.
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
AGPL-3.0-or-later - See LICENSE file in the CIRISVerify repository.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""CIRISVerify Python bindings.
|
|
2
|
+
|
|
3
|
+
Hardware-rooted license verification for the CIRIS ecosystem.
|
|
4
|
+
Provides cryptographic proof of license status to prevent capability spoofing.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from ciris_verify import CIRISVerify, LicenseStatus
|
|
8
|
+
|
|
9
|
+
verifier = CIRISVerify()
|
|
10
|
+
status = verifier.get_license_status(challenge_nonce=os.urandom(32))
|
|
11
|
+
|
|
12
|
+
if status.allows_licensed_operation():
|
|
13
|
+
# Professional capabilities available
|
|
14
|
+
pass
|
|
15
|
+
else:
|
|
16
|
+
# Community mode only
|
|
17
|
+
disclosure = status.mandatory_disclosure
|
|
18
|
+
print(disclosure.text)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from .client import CIRISVerify, MockCIRISVerify
|
|
22
|
+
from .types import (
|
|
23
|
+
LicenseStatus,
|
|
24
|
+
LicenseTier,
|
|
25
|
+
LicenseDetails,
|
|
26
|
+
MandatoryDisclosure,
|
|
27
|
+
DisclosureSeverity,
|
|
28
|
+
LicenseStatusResponse,
|
|
29
|
+
CapabilityCheckResult,
|
|
30
|
+
FileIntegrityResult,
|
|
31
|
+
HardwareType,
|
|
32
|
+
ValidationStatus,
|
|
33
|
+
)
|
|
34
|
+
from .exceptions import (
|
|
35
|
+
CIRISVerifyError,
|
|
36
|
+
BinaryNotFoundError,
|
|
37
|
+
BinaryTamperedError,
|
|
38
|
+
VerificationFailedError,
|
|
39
|
+
TimeoutError,
|
|
40
|
+
CommunicationError,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__version__ = "0.1.0"
|
|
44
|
+
__all__ = [
|
|
45
|
+
"CIRISVerify",
|
|
46
|
+
"MockCIRISVerify",
|
|
47
|
+
"LicenseStatus",
|
|
48
|
+
"LicenseTier",
|
|
49
|
+
"LicenseDetails",
|
|
50
|
+
"MandatoryDisclosure",
|
|
51
|
+
"DisclosureSeverity",
|
|
52
|
+
"LicenseStatusResponse",
|
|
53
|
+
"CapabilityCheckResult",
|
|
54
|
+
"FileIntegrityResult",
|
|
55
|
+
"HardwareType",
|
|
56
|
+
"ValidationStatus",
|
|
57
|
+
"CIRISVerifyError",
|
|
58
|
+
"BinaryNotFoundError",
|
|
59
|
+
"BinaryTamperedError",
|
|
60
|
+
"VerificationFailedError",
|
|
61
|
+
"TimeoutError",
|
|
62
|
+
"CommunicationError",
|
|
63
|
+
]
|