cerone 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.
- cerone-1.0.0/LICENSE +51 -0
- cerone-1.0.0/MANIFEST.in +8 -0
- cerone-1.0.0/PKG-INFO +168 -0
- cerone-1.0.0/README.md +79 -0
- cerone-1.0.0/TERMS_OF_SERVICE.md +75 -0
- cerone-1.0.0/cerone/__init__.py +527 -0
- cerone-1.0.0/cerone.egg-info/PKG-INFO +168 -0
- cerone-1.0.0/cerone.egg-info/SOURCES.txt +12 -0
- cerone-1.0.0/cerone.egg-info/dependency_links.txt +1 -0
- cerone-1.0.0/cerone.egg-info/requires.txt +9 -0
- cerone-1.0.0/cerone.egg-info/top_level.txt +1 -0
- cerone-1.0.0/pyproject.toml +51 -0
- cerone-1.0.0/setup.cfg +4 -0
- cerone-1.0.0/setup.py +60 -0
cerone-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Cerone SDK Commercial License
|
|
2
|
+
Version 1.0
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Anant Dhavale and Homer Semantics. All rights reserved.
|
|
5
|
+
|
|
6
|
+
This license governs use of the Cerone Software Development Kit ("SDK") and any associated source code, binaries, examples, and documentation made available by Homer Semantics ("Licensor").
|
|
7
|
+
|
|
8
|
+
1. Grant of License
|
|
9
|
+
Subject to compliance with this License, Licensor grants you a limited, non-exclusive, non-transferable, revocable license to:
|
|
10
|
+
(a) use the SDK solely to develop, test, and operate integrations with Licensor's Cerone services;
|
|
11
|
+
(b) reproduce and distribute the SDK only as embedded within your application in object form, where end users cannot reasonably extract the SDK as a standalone developer tool.
|
|
12
|
+
|
|
13
|
+
2. Ownership and Intellectual Property
|
|
14
|
+
The SDK is licensed, not sold. Licensor retains all right, title, and interest in and to the SDK, including all intellectual property rights, trade secrets, and derivative works.
|
|
15
|
+
|
|
16
|
+
3. Restrictions
|
|
17
|
+
You may not, and may not permit others to:
|
|
18
|
+
(a) sell, sublicense, rent, lease, or provide the SDK as a standalone product or service;
|
|
19
|
+
(b) modify, create derivative works of, or redistribute the SDK source code, except with Licensor's prior written permission;
|
|
20
|
+
(c) remove, alter, or obscure any copyright, trademark, or proprietary notices;
|
|
21
|
+
(d) use the SDK or Cerone services to build, train, benchmark, validate, or improve any competing product or service, including competitive analysis intended for publication or commercialization;
|
|
22
|
+
(e) reverse engineer, decompile, disassemble, translate, decode, or otherwise attempt to derive source code, underlying ideas, algorithms, model behavior, scoring logic, thresholds, prompts, or non-public APIs, except to the limited extent such restriction is expressly prohibited by applicable law;
|
|
23
|
+
(f) attempt model extraction, prompt extraction, dataset extraction, or systematic output analysis intended to replicate Cerone functionality;
|
|
24
|
+
(g) attempt to discover or reconstruct non-public service internals, infrastructure, security controls, or backend implementation details through unauthorized means, including probing, scraping, fuzzing, or penetration activity without prior written authorization from Licensor;
|
|
25
|
+
(h) circumvent or attempt to circumvent usage limits, authentication controls, billing controls, access restrictions, anti-abuse controls, or monitoring controls.
|
|
26
|
+
|
|
27
|
+
4. Service Terms and Quotas
|
|
28
|
+
Use of the Cerone service APIs is subject to separate service terms, usage quotas, and pricing published by Licensor. Licensor may suspend or terminate API access for abuse, non-payment, security risk, or license breach. Current introductory quota is described in the Terms of Service and may change from time to time.
|
|
29
|
+
|
|
30
|
+
5. Confidentiality
|
|
31
|
+
Any non-public technical information, performance information, keys, or implementation details disclosed by Licensor are confidential and must not be disclosed to third parties.
|
|
32
|
+
|
|
33
|
+
6. Feedback
|
|
34
|
+
If you provide feedback, suggestions, or improvement ideas, you grant Licensor a perpetual, irrevocable, worldwide, royalty-free right to use them without restriction or compensation.
|
|
35
|
+
|
|
36
|
+
7. Disclaimer
|
|
37
|
+
THE SDK IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
38
|
+
|
|
39
|
+
8. Limitation of Liability
|
|
40
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, LICENSOR WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR ANY LOSS OF DATA, PROFITS, OR REVENUE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LICENSOR'S AGGREGATE LIABILITY FOR ALL CLAIMS RELATING TO THE SDK WILL NOT EXCEED USD $100.
|
|
41
|
+
|
|
42
|
+
9. Termination
|
|
43
|
+
This License is effective until terminated. It terminates automatically if you breach any term. Upon termination, you must cease use of the SDK and destroy all copies in your possession or control.
|
|
44
|
+
|
|
45
|
+
10. Governing Law
|
|
46
|
+
This License is governed by the laws of Western Australia, without regard to conflict of laws principles. Any dispute shall be subject to the exclusive jurisdiction of the courts of Western Australia.
|
|
47
|
+
|
|
48
|
+
11. Contact
|
|
49
|
+
Licensing requests: info@homersemantics.com , anantdhavale@gmail.com
|
|
50
|
+
|
|
51
|
+
By using the SDK, you agree to this License.
|
cerone-1.0.0/MANIFEST.in
ADDED
cerone-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cerone
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Zero Trust Security for AI Agents
|
|
5
|
+
Home-page: https://github.com/AnantDhavale/cerone
|
|
6
|
+
Author: Anant Dhavale for Homer Semantics
|
|
7
|
+
Author-email: Homer Semantics <info@homersemantics.com>
|
|
8
|
+
License: Cerone SDK Commercial License
|
|
9
|
+
Version 1.0
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Anant Dhavale and Homer Semantics. All rights reserved.
|
|
12
|
+
|
|
13
|
+
This license governs use of the Cerone Software Development Kit ("SDK") and any associated source code, binaries, examples, and documentation made available by Homer Semantics ("Licensor").
|
|
14
|
+
|
|
15
|
+
1. Grant of License
|
|
16
|
+
Subject to compliance with this License, Licensor grants you a limited, non-exclusive, non-transferable, revocable license to:
|
|
17
|
+
(a) use the SDK solely to develop, test, and operate integrations with Licensor's Cerone services;
|
|
18
|
+
(b) reproduce and distribute the SDK only as embedded within your application in object form, where end users cannot reasonably extract the SDK as a standalone developer tool.
|
|
19
|
+
|
|
20
|
+
2. Ownership and Intellectual Property
|
|
21
|
+
The SDK is licensed, not sold. Licensor retains all right, title, and interest in and to the SDK, including all intellectual property rights, trade secrets, and derivative works.
|
|
22
|
+
|
|
23
|
+
3. Restrictions
|
|
24
|
+
You may not, and may not permit others to:
|
|
25
|
+
(a) sell, sublicense, rent, lease, or provide the SDK as a standalone product or service;
|
|
26
|
+
(b) modify, create derivative works of, or redistribute the SDK source code, except with Licensor's prior written permission;
|
|
27
|
+
(c) remove, alter, or obscure any copyright, trademark, or proprietary notices;
|
|
28
|
+
(d) use the SDK or Cerone services to build, train, benchmark, validate, or improve any competing product or service, including competitive analysis intended for publication or commercialization;
|
|
29
|
+
(e) reverse engineer, decompile, disassemble, translate, decode, or otherwise attempt to derive source code, underlying ideas, algorithms, model behavior, scoring logic, thresholds, prompts, or non-public APIs, except to the limited extent such restriction is expressly prohibited by applicable law;
|
|
30
|
+
(f) attempt model extraction, prompt extraction, dataset extraction, or systematic output analysis intended to replicate Cerone functionality;
|
|
31
|
+
(g) attempt to discover or reconstruct non-public service internals, infrastructure, security controls, or backend implementation details through unauthorized means, including probing, scraping, fuzzing, or penetration activity without prior written authorization from Licensor;
|
|
32
|
+
(h) circumvent or attempt to circumvent usage limits, authentication controls, billing controls, access restrictions, anti-abuse controls, or monitoring controls.
|
|
33
|
+
|
|
34
|
+
4. Service Terms and Quotas
|
|
35
|
+
Use of the Cerone service APIs is subject to separate service terms, usage quotas, and pricing published by Licensor. Licensor may suspend or terminate API access for abuse, non-payment, security risk, or license breach. Current introductory quota is described in the Terms of Service and may change from time to time.
|
|
36
|
+
|
|
37
|
+
5. Confidentiality
|
|
38
|
+
Any non-public technical information, performance information, keys, or implementation details disclosed by Licensor are confidential and must not be disclosed to third parties.
|
|
39
|
+
|
|
40
|
+
6. Feedback
|
|
41
|
+
If you provide feedback, suggestions, or improvement ideas, you grant Licensor a perpetual, irrevocable, worldwide, royalty-free right to use them without restriction or compensation.
|
|
42
|
+
|
|
43
|
+
7. Disclaimer
|
|
44
|
+
THE SDK IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
45
|
+
|
|
46
|
+
8. Limitation of Liability
|
|
47
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, LICENSOR WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR ANY LOSS OF DATA, PROFITS, OR REVENUE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LICENSOR'S AGGREGATE LIABILITY FOR ALL CLAIMS RELATING TO THE SDK WILL NOT EXCEED USD $100.
|
|
48
|
+
|
|
49
|
+
9. Termination
|
|
50
|
+
This License is effective until terminated. It terminates automatically if you breach any term. Upon termination, you must cease use of the SDK and destroy all copies in your possession or control.
|
|
51
|
+
|
|
52
|
+
10. Governing Law
|
|
53
|
+
This License is governed by the laws of Western Australia, without regard to conflict of laws principles. Any dispute shall be subject to the exclusive jurisdiction of the courts of Western Australia.
|
|
54
|
+
|
|
55
|
+
11. Contact
|
|
56
|
+
Licensing requests: info@homersemantics.com , anantdhavale@gmail.com
|
|
57
|
+
|
|
58
|
+
By using the SDK, you agree to this License.
|
|
59
|
+
|
|
60
|
+
Project-URL: Homepage, https://aztp.homersemantics.com
|
|
61
|
+
Project-URL: Repository, https://github.com/AnantDhavale/cerone
|
|
62
|
+
Project-URL: Bug Tracker, https://github.com/AnantDhavale/cerone/issues
|
|
63
|
+
Keywords: ai,agents,security,zero-trust,validation,llm
|
|
64
|
+
Classifier: Development Status :: 4 - Beta
|
|
65
|
+
Classifier: Intended Audience :: Developers
|
|
66
|
+
Classifier: License :: Other/Proprietary License
|
|
67
|
+
Classifier: Programming Language :: Python :: 3
|
|
68
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
69
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
70
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
71
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
72
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
73
|
+
Classifier: Topic :: Security
|
|
74
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
75
|
+
Requires-Python: >=3.8
|
|
76
|
+
Description-Content-Type: text/markdown
|
|
77
|
+
License-File: LICENSE
|
|
78
|
+
Requires-Dist: requests>=2.28
|
|
79
|
+
Provides-Extra: async
|
|
80
|
+
Requires-Dist: aiohttp>=3.8; extra == "async"
|
|
81
|
+
Provides-Extra: dev
|
|
82
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
83
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
84
|
+
Requires-Dist: aiohttp>=3.8; extra == "dev"
|
|
85
|
+
Dynamic: author
|
|
86
|
+
Dynamic: home-page
|
|
87
|
+
Dynamic: license-file
|
|
88
|
+
Dynamic: requires-python
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Cerone Python SDK (Beta)
|
|
92
|
+
|
|
93
|
+
Zero Trust security and production governance for AI agents.
|
|
94
|
+
Cryptographic identity and run-time validation for AI agents in production.
|
|
95
|
+
|
|
96
|
+
AI agents are being deployed into production systems that handle real decisions, real data, and real consequences, yet most teams have no
|
|
97
|
+
runtime control over what those agents actually do. Cerone fixes that.
|
|
98
|
+
|
|
99
|
+
Cerone enforces cryptographic identity, semantic intent validation, and continuous trust scoring on every agent action; ensuring agents only
|
|
100
|
+
do what they were authorized to do, and nothing else. Deploying AI agents in production without this layer of protection is an unacceptable
|
|
101
|
+
operational and security risk.
|
|
102
|
+
|
|
103
|
+
The SDK is currently in early-access beta for selected teams building production AI systems that require accountability, auditability, and
|
|
104
|
+
control.
|
|
105
|
+
|
|
106
|
+
## Install
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install cerone
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Access (Beta)
|
|
113
|
+
|
|
114
|
+
API access is currently managed through early access:
|
|
115
|
+
|
|
116
|
+
- Request access: https://aztp.homersemantics.com/
|
|
117
|
+
- Receive approval and API credentials
|
|
118
|
+
- Review terms in `TERMS_OF_SERVICE.md`
|
|
119
|
+
|
|
120
|
+
## Quick Start
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from cerone import CeroneClient
|
|
124
|
+
import os
|
|
125
|
+
|
|
126
|
+
client = CeroneClient(api_key=os.getenv("CERONE_API_KEY"))
|
|
127
|
+
|
|
128
|
+
# Create agent
|
|
129
|
+
agent = client.create_agent(
|
|
130
|
+
purpose="Email classifier",
|
|
131
|
+
capabilities=["read_email", "move_email", "send_reply"]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Validate action before executing
|
|
135
|
+
response = client.validate(
|
|
136
|
+
agent_id=agent.agent_id,
|
|
137
|
+
action="move_email",
|
|
138
|
+
parameters={"email_id": "123", "folder": "spam"}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if response.result.value == "approved":
|
|
142
|
+
mailbox.move_email("123", "spam")
|
|
143
|
+
else:
|
|
144
|
+
print(f"Action rejected: {response.violations}")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## What the SDK Provides
|
|
148
|
+
|
|
149
|
+
- Authenticated client access to Cerone services
|
|
150
|
+
- Agent registration and identity-bound operations
|
|
151
|
+
- Sync and async validation calls
|
|
152
|
+
- Batch validation support
|
|
153
|
+
- Governance-oriented telemetry surfaces
|
|
154
|
+
|
|
155
|
+
## Usage Terms
|
|
156
|
+
|
|
157
|
+
Usage limits and commercial terms are defined in `TERMS_OF_SERVICE.md`.
|
|
158
|
+
|
|
159
|
+
Current free trial: up to 25 validations in the first 5 days.
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
Proprietary commercial license. See `LICENSE`.
|
|
164
|
+
|
|
165
|
+
## Contact
|
|
166
|
+
anantdhavale@gmail.com
|
|
167
|
+
info@homersemantics.com
|
|
168
|
+
```
|
cerone-1.0.0/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
|
|
2
|
+
# Cerone Python SDK (Beta)
|
|
3
|
+
|
|
4
|
+
Zero Trust security and production governance for AI agents.
|
|
5
|
+
Cryptographic identity and run-time validation for AI agents in production.
|
|
6
|
+
|
|
7
|
+
AI agents are being deployed into production systems that handle real decisions, real data, and real consequences, yet most teams have no
|
|
8
|
+
runtime control over what those agents actually do. Cerone fixes that.
|
|
9
|
+
|
|
10
|
+
Cerone enforces cryptographic identity, semantic intent validation, and continuous trust scoring on every agent action; ensuring agents only
|
|
11
|
+
do what they were authorized to do, and nothing else. Deploying AI agents in production without this layer of protection is an unacceptable
|
|
12
|
+
operational and security risk.
|
|
13
|
+
|
|
14
|
+
The SDK is currently in early-access beta for selected teams building production AI systems that require accountability, auditability, and
|
|
15
|
+
control.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install cerone
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Access (Beta)
|
|
24
|
+
|
|
25
|
+
API access is currently managed through early access:
|
|
26
|
+
|
|
27
|
+
- Request access: https://aztp.homersemantics.com/
|
|
28
|
+
- Receive approval and API credentials
|
|
29
|
+
- Review terms in `TERMS_OF_SERVICE.md`
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from cerone import CeroneClient
|
|
35
|
+
import os
|
|
36
|
+
|
|
37
|
+
client = CeroneClient(api_key=os.getenv("CERONE_API_KEY"))
|
|
38
|
+
|
|
39
|
+
# Create agent
|
|
40
|
+
agent = client.create_agent(
|
|
41
|
+
purpose="Email classifier",
|
|
42
|
+
capabilities=["read_email", "move_email", "send_reply"]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Validate action before executing
|
|
46
|
+
response = client.validate(
|
|
47
|
+
agent_id=agent.agent_id,
|
|
48
|
+
action="move_email",
|
|
49
|
+
parameters={"email_id": "123", "folder": "spam"}
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if response.result.value == "approved":
|
|
53
|
+
mailbox.move_email("123", "spam")
|
|
54
|
+
else:
|
|
55
|
+
print(f"Action rejected: {response.violations}")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## What the SDK Provides
|
|
59
|
+
|
|
60
|
+
- Authenticated client access to Cerone services
|
|
61
|
+
- Agent registration and identity-bound operations
|
|
62
|
+
- Sync and async validation calls
|
|
63
|
+
- Batch validation support
|
|
64
|
+
- Governance-oriented telemetry surfaces
|
|
65
|
+
|
|
66
|
+
## Usage Terms
|
|
67
|
+
|
|
68
|
+
Usage limits and commercial terms are defined in `TERMS_OF_SERVICE.md`.
|
|
69
|
+
|
|
70
|
+
Current free trial: up to 25 validations in the first 5 days.
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
Proprietary commercial license. See `LICENSE`.
|
|
75
|
+
|
|
76
|
+
## Contact
|
|
77
|
+
anantdhavale@gmail.com
|
|
78
|
+
info@homersemantics.com
|
|
79
|
+
```
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Cerone API Terms of Service
|
|
2
|
+
|
|
3
|
+
Effective date: March 5, 2026
|
|
4
|
+
|
|
5
|
+
These Terms of Service ("Terms") govern access to and use of the Cerone APIs, SDK, website, and related services (collectively, the "Services") provided by Homer Semantics ("we", "us", "our"). By creating an account, using an API key, installing the SDK, or otherwise using the Services, you agree to these Terms.
|
|
6
|
+
## Beta Service Notice
|
|
7
|
+
|
|
8
|
+
The Services are currently offered as a beta version. Beta services may contain bugs, errors, or instabilities and are provided for evaluation and early-access purposes only. Features, APIs, quotas, and pricing are subject to change without notice during the beta period. Homer Semantics and Anant Dhavale make no commitment to maintain beta features in future releases. By using the Services during beta, you acknowledge and accept these limitations and agree not to rely on the Services for mission-critical or production workloads without appropriate independent safeguards.
|
|
9
|
+
## 1. Eligibility and Account Responsibilities
|
|
10
|
+
|
|
11
|
+
You must be legally able to enter into these Terms. You are responsible for all activity under your account and API keys. You must keep credentials secure and notify us promptly of unauthorized use.
|
|
12
|
+
|
|
13
|
+
## 2. License and Service Access
|
|
14
|
+
|
|
15
|
+
Your use of the SDK is subject to the Cerone SDK Commercial License in the `LICENSE` file. We grant you a limited, revocable, non-exclusive right to access and use the Services in accordance with these Terms, your plan limits, and applicable law.
|
|
16
|
+
|
|
17
|
+
## 3. Acceptable Use and Restrictions
|
|
18
|
+
|
|
19
|
+
You may not, and may not permit others to:
|
|
20
|
+
|
|
21
|
+
1. Reverse engineer, decompile, disassemble, decode, or otherwise attempt to derive non-public source code, algorithms, models, scoring logic, prompts, or internal APIs, except to the limited extent prohibited by applicable law.
|
|
22
|
+
2. Use the Services or SDK to build, benchmark, validate, or improve a competing product or service, including competitive publications intended for commercialization.
|
|
23
|
+
3. Attempt model, prompt, or dataset extraction, or systematic output analysis intended to replicate Cerone functionality.
|
|
24
|
+
4. Circumvent plan limits, usage quotas, authentication, billing, anti-abuse controls, monitoring controls, or any access restrictions.
|
|
25
|
+
5. Probe, scrape, fuzz, or penetration-test the Services without our prior written authorization.
|
|
26
|
+
6. Use the Services in a way that violates law, infringes third-party rights, or materially degrades service reliability or security.
|
|
27
|
+
|
|
28
|
+
## 4. Plans, Quotas, and Billing
|
|
29
|
+
|
|
30
|
+
Free and paid plans, quotas, and pricing are described on our website or order form and may be updated from time to time. Exceeding usage limits may result in throttling, overage charges, suspension, or requirement to upgrade. Fees are non-refundable except where required by law or expressly stated.
|
|
31
|
+
|
|
32
|
+
## Free Tier and Trial Usage
|
|
33
|
+
|
|
34
|
+
The Cerone free tier includes up to 25 validations during the first 5 days from account activation ("Trial Period").
|
|
35
|
+
|
|
36
|
+
After the Trial Period ends, continued API usage may require an active paid plan or may be subject to reduced or zero quota, at Cerone's discretion unless otherwise stated in a signed commercial agreement.
|
|
37
|
+
|
|
38
|
+
Unused trial validations do not roll over. Cerone may modify, suspend, or discontinue free-tier/trial offerings at any time.
|
|
39
|
+
|
|
40
|
+
## 5. Data Handling
|
|
41
|
+
|
|
42
|
+
You are responsible for ensuring you have rights to submit data to the Services and for configuring your own redaction and data governance controls. We may process submitted data to provide, secure, and improve the Services consistent with our privacy commitments and legal obligations, including India's Digital Personal Data Protection Act (DPDPA 2023).
|
|
43
|
+
|
|
44
|
+
## 6. Confidentiality
|
|
45
|
+
|
|
46
|
+
Non-public technical, security, pricing, and product information we provide is confidential and must not be disclosed to third parties without our written permission.
|
|
47
|
+
|
|
48
|
+
## 7. Feedback
|
|
49
|
+
|
|
50
|
+
If you provide feedback, suggestions, or ideas, you grant us a perpetual, irrevocable, worldwide, royalty-free right to use them without restriction.
|
|
51
|
+
|
|
52
|
+
## 8. Suspension and Termination
|
|
53
|
+
|
|
54
|
+
We may suspend or terminate access immediately for suspected abuse, security risk, non-payment, legal risk, or breach of these Terms or the SDK license. On termination, your right to use the Services ceases immediately.
|
|
55
|
+
|
|
56
|
+
## 9. Disclaimers
|
|
57
|
+
|
|
58
|
+
THE SERVICES ARE PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
59
|
+
|
|
60
|
+
## 10. Limitation of Liability
|
|
61
|
+
|
|
62
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, HOMER SEMANTICS and ANANT DHAVALE WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR ANY LOSS OF DATA, PROFITS, OR REVENUE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. OUR AGGREGATE LIABILITY FOR ALL CLAIMS ARISING OUT OF OR RELATED TO THE SERVICES WILL NOT EXCEED THE GREATER OF (A) USD $100 OR (B) FEES PAID BY YOU TO US IN THE THREE (3) MONTHS PRECEDING THE EVENT GIVING RISE TO LIABILITY.
|
|
63
|
+
|
|
64
|
+
## 11. Governing Law and Venue
|
|
65
|
+
|
|
66
|
+
These Terms are governed by the laws of India, without regard to conflict-of-laws principles. Any dispute arising out of or relating to these Terms shall be subject to the exclusive jurisdiction of the courts of Pune, Maharashtra, India. Notwithstanding the foregoing, we may elect, at our sole discretion, to bring any dispute in the courts of the jurisdiction where you are domiciled or incorporated.
|
|
67
|
+
|
|
68
|
+
## 12. Changes to Terms
|
|
69
|
+
|
|
70
|
+
We may update these Terms from time to time. Updated Terms become effective when posted. Continued use after the effective date constitutes acceptance of the updated Terms.
|
|
71
|
+
|
|
72
|
+
## 13. Contact
|
|
73
|
+
|
|
74
|
+
Questions / Support: info@homersemantics.com anantdhavale@gmail.com
|
|
75
|
+
copyright © Anant Dhavale 2026
|
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cerone Python SDK
|
|
3
|
+
Zero Trust Security for AI Agents
|
|
4
|
+
|
|
5
|
+
Installation:
|
|
6
|
+
pip install cerone
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from cerone import CeroneClient
|
|
10
|
+
|
|
11
|
+
client = CeroneClient(api_key="your_api_key")
|
|
12
|
+
result = client.validate(agent_id="agt_123", action="trade_execute", parameters={...})
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import asyncio
|
|
16
|
+
import hashlib
|
|
17
|
+
import json
|
|
18
|
+
import logging
|
|
19
|
+
import time
|
|
20
|
+
from collections import OrderedDict
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from enum import Enum
|
|
23
|
+
from functools import wraps
|
|
24
|
+
from typing import Any, Callable, Dict, List, Optional, TypeVar, cast
|
|
25
|
+
|
|
26
|
+
import requests
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
import aiohttp
|
|
30
|
+
|
|
31
|
+
_AIOHTTP_AVAILABLE = True
|
|
32
|
+
_AIOHTTP_CLIENT_ERROR = aiohttp.ClientError
|
|
33
|
+
except ModuleNotFoundError:
|
|
34
|
+
aiohttp = None
|
|
35
|
+
_AIOHTTP_AVAILABLE = False
|
|
36
|
+
|
|
37
|
+
class _AiohttpClientError(Exception):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
_AIOHTTP_CLIENT_ERROR = _AiohttpClientError
|
|
41
|
+
|
|
42
|
+
# F23: version set to 0.2.0 (product is early-access beta, not stable 1.x)
|
|
43
|
+
__version__ = "0.2.0"
|
|
44
|
+
__author__ = "Homer Semantics"
|
|
45
|
+
EARLY_ACCESS_URL = "https://aztp.homersemantics.com/"
|
|
46
|
+
|
|
47
|
+
logger = logging.getLogger(__name__)
|
|
48
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
|
49
|
+
|
|
50
|
+
# F18: maximum entries in the in-process validation cache (prevents unbounded growth)
|
|
51
|
+
_CACHE_MAX_SIZE = 1000
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ValidationResult(Enum):
|
|
55
|
+
"""Validation result enum."""
|
|
56
|
+
APPROVED = "approved"
|
|
57
|
+
REJECTED = "rejected"
|
|
58
|
+
ERROR = "error"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class CeroneResponse:
|
|
63
|
+
"""Response from Cerone validation."""
|
|
64
|
+
result: ValidationResult
|
|
65
|
+
semantic_alignment: float
|
|
66
|
+
trust_score: float
|
|
67
|
+
violations: List[str]
|
|
68
|
+
agent_id: str
|
|
69
|
+
action: str
|
|
70
|
+
timestamp: str
|
|
71
|
+
latency_ms: int
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class AgentCertificate:
|
|
76
|
+
"""Agent identity certificate."""
|
|
77
|
+
agent_id: str
|
|
78
|
+
purpose: str
|
|
79
|
+
capabilities: List[str]
|
|
80
|
+
trust_score: float
|
|
81
|
+
signature: str
|
|
82
|
+
created_at: str
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class CeroneException(Exception):
|
|
86
|
+
"""Base exception for Cerone SDK."""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class AuthenticationError(CeroneException):
|
|
90
|
+
"""Raised when API key is invalid."""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class ValidationError(CeroneException):
|
|
94
|
+
"""Raised when validation fails."""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class RateLimitError(CeroneException):
|
|
98
|
+
"""Raised when rate limit is exceeded."""
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class _ClientRequestError(ValidationError):
|
|
102
|
+
"""Raised for non-retryable 4xx request errors."""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class _ServerError(ValidationError):
|
|
106
|
+
"""Raised for retryable 5xx server errors."""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class CeroneClient:
|
|
110
|
+
"""Cerone API client for validating AI agent actions."""
|
|
111
|
+
|
|
112
|
+
_IDEMPOTENT_METHODS = {"GET", "HEAD", "OPTIONS"}
|
|
113
|
+
|
|
114
|
+
def __init__(
|
|
115
|
+
self,
|
|
116
|
+
api_key: str,
|
|
117
|
+
base_url: str = "https://api.homersemantics.com",
|
|
118
|
+
timeout: int = 30,
|
|
119
|
+
max_retries: int = 3,
|
|
120
|
+
enable_cache: bool = False,
|
|
121
|
+
retry_non_idempotent: bool = False,
|
|
122
|
+
):
|
|
123
|
+
"""
|
|
124
|
+
Initialize Cerone client.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
api_key: Your Cerone API key.
|
|
128
|
+
base_url: API endpoint (default: production).
|
|
129
|
+
timeout: Request timeout in seconds.
|
|
130
|
+
max_retries: Number of retry attempts for eligible requests.
|
|
131
|
+
enable_cache: Enable local caching of high-trust validations.
|
|
132
|
+
Cache is bounded to 1,000 entries (LRU eviction).
|
|
133
|
+
retry_non_idempotent: Retry POST/PUT/PATCH/DELETE on transport
|
|
134
|
+
errors. Defaults to False to avoid duplicate side effects.
|
|
135
|
+
"""
|
|
136
|
+
self.api_key = api_key
|
|
137
|
+
self.base_url = base_url.rstrip("/")
|
|
138
|
+
self.timeout = timeout
|
|
139
|
+
self.max_retries = max(0, max_retries)
|
|
140
|
+
self.enable_cache = enable_cache
|
|
141
|
+
self.retry_non_idempotent = retry_non_idempotent
|
|
142
|
+
|
|
143
|
+
# F18: bounded LRU cache — plain dict grows unboundedly in long-running
|
|
144
|
+
# processes; OrderedDict with a size cap gives O(1) eviction.
|
|
145
|
+
self._cache: Optional[OrderedDict] = OrderedDict() if enable_cache else None
|
|
146
|
+
|
|
147
|
+
self._session = requests.Session()
|
|
148
|
+
self._session.headers.update(
|
|
149
|
+
{
|
|
150
|
+
"X-API-Key": api_key,
|
|
151
|
+
"Content-Type": "application/json",
|
|
152
|
+
"User-Agent": f"cerone-python-sdk/{__version__}",
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
self._async_session: Optional[Any] = None
|
|
157
|
+
|
|
158
|
+
# ------------------------------------------------------------------
|
|
159
|
+
# Certificate / agent management
|
|
160
|
+
# ------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
def create_agent(
|
|
163
|
+
self,
|
|
164
|
+
purpose: str,
|
|
165
|
+
capabilities: Optional[List[str]] = None,
|
|
166
|
+
) -> AgentCertificate:
|
|
167
|
+
"""Create a new agent with cryptographic identity."""
|
|
168
|
+
payload = {"purpose": purpose, "capabilities": capabilities or []}
|
|
169
|
+
response = self._request("POST", "/v1/certificates", json=payload)
|
|
170
|
+
|
|
171
|
+
return AgentCertificate(
|
|
172
|
+
agent_id=response["agent_id"],
|
|
173
|
+
purpose=purpose,
|
|
174
|
+
capabilities=capabilities or [],
|
|
175
|
+
trust_score=response["trust_score"],
|
|
176
|
+
signature=response["signature"],
|
|
177
|
+
created_at=response["created_at"],
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# ------------------------------------------------------------------
|
|
181
|
+
# Validation
|
|
182
|
+
# ------------------------------------------------------------------
|
|
183
|
+
|
|
184
|
+
def validate(
|
|
185
|
+
self,
|
|
186
|
+
agent_id: str,
|
|
187
|
+
action: str,
|
|
188
|
+
parameters: Dict[str, Any],
|
|
189
|
+
) -> CeroneResponse:
|
|
190
|
+
"""Validate an agent action in real-time."""
|
|
191
|
+
if self._cache is not None:
|
|
192
|
+
cache_key = self._cache_key(agent_id, action, parameters)
|
|
193
|
+
cached = self._cache.get(cache_key)
|
|
194
|
+
if cached and time.time() - cached["timestamp"] < 300:
|
|
195
|
+
if cached["trust_score"] > 0.95:
|
|
196
|
+
logger.debug("Cache hit for %s", cache_key)
|
|
197
|
+
# Move to end (most recently used)
|
|
198
|
+
self._cache.move_to_end(cache_key)
|
|
199
|
+
return cast(CeroneResponse, cached["response"])
|
|
200
|
+
|
|
201
|
+
start_time = time.time()
|
|
202
|
+
payload = {"agent_id": agent_id, "action": action, "parameters": parameters}
|
|
203
|
+
response = self._request("POST", "/v1/validate", json=payload)
|
|
204
|
+
latency_ms = int((time.time() - start_time) * 1000)
|
|
205
|
+
|
|
206
|
+
cerone_response = CeroneResponse(
|
|
207
|
+
result=ValidationResult(response["result"]),
|
|
208
|
+
semantic_alignment=response["semantic_alignment"],
|
|
209
|
+
trust_score=response["trust_score"],
|
|
210
|
+
violations=response.get("violations", []),
|
|
211
|
+
agent_id=agent_id,
|
|
212
|
+
action=action,
|
|
213
|
+
timestamp=response["timestamp"],
|
|
214
|
+
latency_ms=latency_ms,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
if (
|
|
218
|
+
self._cache is not None
|
|
219
|
+
and cerone_response.result == ValidationResult.APPROVED
|
|
220
|
+
and cerone_response.trust_score > 0.95
|
|
221
|
+
):
|
|
222
|
+
cache_key = self._cache_key(agent_id, action, parameters)
|
|
223
|
+
self._cache[cache_key] = {
|
|
224
|
+
"response": cerone_response,
|
|
225
|
+
"trust_score": cerone_response.trust_score,
|
|
226
|
+
"timestamp": time.time(),
|
|
227
|
+
}
|
|
228
|
+
self._cache.move_to_end(cache_key)
|
|
229
|
+
# F18: evict oldest entries if cache is full
|
|
230
|
+
while len(self._cache) > _CACHE_MAX_SIZE:
|
|
231
|
+
self._cache.popitem(last=False)
|
|
232
|
+
|
|
233
|
+
return cerone_response
|
|
234
|
+
|
|
235
|
+
async def validate_async(
|
|
236
|
+
self,
|
|
237
|
+
agent_id: str,
|
|
238
|
+
action: str,
|
|
239
|
+
parameters: Dict[str, Any],
|
|
240
|
+
) -> CeroneResponse:
|
|
241
|
+
"""Async version of validate() for high-throughput scenarios."""
|
|
242
|
+
if not _AIOHTTP_AVAILABLE:
|
|
243
|
+
raise ValidationError(
|
|
244
|
+
"aiohttp is required for async methods. "
|
|
245
|
+
"Install with: pip install aiohttp"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
start_time = time.time()
|
|
249
|
+
payload = {"agent_id": agent_id, "action": action, "parameters": parameters}
|
|
250
|
+
data = await self._request_async("POST", "/v1/validate", json=payload)
|
|
251
|
+
latency_ms = int((time.time() - start_time) * 1000)
|
|
252
|
+
|
|
253
|
+
return CeroneResponse(
|
|
254
|
+
result=ValidationResult(data["result"]),
|
|
255
|
+
semantic_alignment=data["semantic_alignment"],
|
|
256
|
+
trust_score=data["trust_score"],
|
|
257
|
+
violations=data.get("violations", []),
|
|
258
|
+
agent_id=agent_id,
|
|
259
|
+
action=action,
|
|
260
|
+
timestamp=data["timestamp"],
|
|
261
|
+
latency_ms=latency_ms,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def validate_batch(self, validations: List[Dict[str, Any]]) -> List[CeroneResponse]:
|
|
265
|
+
"""
|
|
266
|
+
Validate multiple actions in a single request.
|
|
267
|
+
|
|
268
|
+
Each dict in ``validations`` must contain:
|
|
269
|
+
agent_id (str)
|
|
270
|
+
action (dict with ``tool`` and ``parameters`` keys)
|
|
271
|
+
"""
|
|
272
|
+
# F3: build properly shaped ValidationRequest objects for the backend
|
|
273
|
+
requests_payload = []
|
|
274
|
+
for v in validations:
|
|
275
|
+
requests_payload.append({
|
|
276
|
+
"agent_id": v["agent_id"],
|
|
277
|
+
"action": v["action"], # must be {"tool": str, "parameters": dict}
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
response = self._request(
|
|
281
|
+
"POST", "/v1/validate/batch", json={"validations": requests_payload}
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
return [
|
|
285
|
+
CeroneResponse(
|
|
286
|
+
result=ValidationResult(r.get("result", "error")),
|
|
287
|
+
semantic_alignment=r.get("semantic_alignment", 0.0),
|
|
288
|
+
trust_score=r.get("trust_score", 0.0),
|
|
289
|
+
violations=r.get("violations", []),
|
|
290
|
+
agent_id=r.get("agent_id", ""),
|
|
291
|
+
action=r.get("action", {}).get("tool", "") if isinstance(r.get("action"), dict) else str(r.get("action", "")),
|
|
292
|
+
timestamp=r.get("timestamp", ""),
|
|
293
|
+
latency_ms=r.get("latency_ms", 0),
|
|
294
|
+
)
|
|
295
|
+
for r in response["results"]
|
|
296
|
+
]
|
|
297
|
+
|
|
298
|
+
# ------------------------------------------------------------------
|
|
299
|
+
# Trust / audit
|
|
300
|
+
# ------------------------------------------------------------------
|
|
301
|
+
|
|
302
|
+
def get_trust_score(self, agent_id: str) -> Dict[str, Any]:
|
|
303
|
+
"""Get current trust score and history for an agent."""
|
|
304
|
+
return self._request("GET", f"/v1/trust/{agent_id}")
|
|
305
|
+
|
|
306
|
+
def get_audit_log(
|
|
307
|
+
self,
|
|
308
|
+
agent_id: str,
|
|
309
|
+
limit: int = 100,
|
|
310
|
+
offset: int = 0,
|
|
311
|
+
) -> List[Dict[str, Any]]:
|
|
312
|
+
"""
|
|
313
|
+
Retrieve audit log events for an agent.
|
|
314
|
+
|
|
315
|
+
Returns a list of event dicts. Each dict contains at minimum:
|
|
316
|
+
timestamp, agent_id, action, result, change_reason
|
|
317
|
+
"""
|
|
318
|
+
# F4: backend returns {"events": [...], ...} — read the correct key
|
|
319
|
+
params = {"limit": limit, "offset": offset}
|
|
320
|
+
response = self._request("GET", f"/v1/audit/agent/{agent_id}", params=params)
|
|
321
|
+
return response["events"]
|
|
322
|
+
|
|
323
|
+
# ------------------------------------------------------------------
|
|
324
|
+
# Health / lifecycle
|
|
325
|
+
# ------------------------------------------------------------------
|
|
326
|
+
|
|
327
|
+
def health_check(self) -> Dict[str, Any]:
|
|
328
|
+
"""Check API health status."""
|
|
329
|
+
try:
|
|
330
|
+
response = requests.get(f"{self.base_url}/health", timeout=5)
|
|
331
|
+
return response.json()
|
|
332
|
+
except Exception as exc:
|
|
333
|
+
return {"status": "error", "message": str(exc)}
|
|
334
|
+
|
|
335
|
+
def close(self) -> None:
|
|
336
|
+
"""Close the underlying synchronous HTTP session."""
|
|
337
|
+
self._session.close()
|
|
338
|
+
|
|
339
|
+
async def aclose(self) -> None:
|
|
340
|
+
"""Close the underlying asynchronous HTTP session if initialized."""
|
|
341
|
+
if self._async_session is not None and not self._async_session.closed:
|
|
342
|
+
await self._async_session.close()
|
|
343
|
+
|
|
344
|
+
# ------------------------------------------------------------------
|
|
345
|
+
# Internal helpers
|
|
346
|
+
# ------------------------------------------------------------------
|
|
347
|
+
|
|
348
|
+
def _cache_key(self, agent_id: str, action: str, parameters: Dict[str, Any]) -> str:
|
|
349
|
+
serialized = json.dumps(parameters, sort_keys=True, default=str, separators=(",", ":"))
|
|
350
|
+
digest = hashlib.sha256(serialized.encode("utf-8")).hexdigest()
|
|
351
|
+
return f"{agent_id}:{action}:{digest}"
|
|
352
|
+
|
|
353
|
+
def _can_retry(self, method: str) -> bool:
|
|
354
|
+
return method.upper() in self._IDEMPOTENT_METHODS or self.retry_non_idempotent
|
|
355
|
+
|
|
356
|
+
@staticmethod
|
|
357
|
+
def _raise_for_status(status_code: int, body_text: str) -> None:
|
|
358
|
+
if 200 <= status_code < 300:
|
|
359
|
+
return
|
|
360
|
+
if status_code == 401:
|
|
361
|
+
raise AuthenticationError(
|
|
362
|
+
f"Invalid or missing API key. Request early access at {EARLY_ACCESS_URL}"
|
|
363
|
+
)
|
|
364
|
+
if status_code == 429:
|
|
365
|
+
raise RateLimitError(
|
|
366
|
+
f"Rate limit exceeded. Upgrade your plan at {EARLY_ACCESS_URL}"
|
|
367
|
+
)
|
|
368
|
+
if status_code >= 500:
|
|
369
|
+
raise _ServerError(f"Server error: {status_code}")
|
|
370
|
+
raise _ClientRequestError(f"Request failed: {status_code} - {body_text}")
|
|
371
|
+
|
|
372
|
+
def _request(self, method: str, endpoint: str, **kwargs: Any) -> Dict[str, Any]:
|
|
373
|
+
"""Internal request with bounded retries."""
|
|
374
|
+
url = f"{self.base_url}{endpoint}"
|
|
375
|
+
can_retry = self._can_retry(method)
|
|
376
|
+
attempts = (self.max_retries + 1) if can_retry else 1
|
|
377
|
+
|
|
378
|
+
for attempt in range(attempts):
|
|
379
|
+
try:
|
|
380
|
+
response = self._session.request(method, url, timeout=self.timeout, **kwargs)
|
|
381
|
+
self._raise_for_status(response.status_code, response.text)
|
|
382
|
+
try:
|
|
383
|
+
return response.json()
|
|
384
|
+
except ValueError as exc:
|
|
385
|
+
raise ValidationError("Invalid JSON response from server") from exc
|
|
386
|
+
except (AuthenticationError, RateLimitError, _ClientRequestError):
|
|
387
|
+
raise
|
|
388
|
+
except _ServerError:
|
|
389
|
+
if attempt < attempts - 1:
|
|
390
|
+
wait = 2 ** attempt
|
|
391
|
+
logger.warning("Server error, retrying in %ss…", wait)
|
|
392
|
+
time.sleep(wait)
|
|
393
|
+
continue
|
|
394
|
+
raise
|
|
395
|
+
except requests.exceptions.Timeout:
|
|
396
|
+
if attempt < attempts - 1:
|
|
397
|
+
logger.warning("Request timeout, retrying…")
|
|
398
|
+
continue
|
|
399
|
+
raise ValidationError("Request timeout")
|
|
400
|
+
except requests.exceptions.RequestException as exc:
|
|
401
|
+
if attempt < attempts - 1:
|
|
402
|
+
logger.warning("Request failed: %s, retrying…", exc)
|
|
403
|
+
continue
|
|
404
|
+
raise ValidationError(f"Request failed: {exc}")
|
|
405
|
+
|
|
406
|
+
raise ValidationError("Max retries exceeded")
|
|
407
|
+
|
|
408
|
+
async def _get_async_session(self) -> Any:
|
|
409
|
+
if not _AIOHTTP_AVAILABLE:
|
|
410
|
+
raise ValidationError(
|
|
411
|
+
"aiohttp is required for async methods. "
|
|
412
|
+
"Install with: pip install aiohttp"
|
|
413
|
+
)
|
|
414
|
+
if self._async_session is None or self._async_session.closed:
|
|
415
|
+
self._async_session = aiohttp.ClientSession(
|
|
416
|
+
headers=dict(self._session.headers),
|
|
417
|
+
timeout=aiohttp.ClientTimeout(total=self.timeout),
|
|
418
|
+
)
|
|
419
|
+
return self._async_session
|
|
420
|
+
|
|
421
|
+
async def _request_async(self, method: str, endpoint: str, **kwargs: Any) -> Dict[str, Any]:
|
|
422
|
+
"""Async request helper with bounded retries."""
|
|
423
|
+
url = f"{self.base_url}{endpoint}"
|
|
424
|
+
can_retry = self._can_retry(method)
|
|
425
|
+
attempts = (self.max_retries + 1) if can_retry else 1
|
|
426
|
+
|
|
427
|
+
for attempt in range(attempts):
|
|
428
|
+
try:
|
|
429
|
+
session = await self._get_async_session()
|
|
430
|
+
async with session.request(method, url, **kwargs) as response:
|
|
431
|
+
body_text = await response.text()
|
|
432
|
+
self._raise_for_status(response.status, body_text)
|
|
433
|
+
try:
|
|
434
|
+
return json.loads(body_text)
|
|
435
|
+
except json.JSONDecodeError as exc:
|
|
436
|
+
raise ValidationError("Invalid JSON response from server") from exc
|
|
437
|
+
except (AuthenticationError, RateLimitError, _ClientRequestError):
|
|
438
|
+
raise
|
|
439
|
+
except _ServerError:
|
|
440
|
+
if attempt < attempts - 1:
|
|
441
|
+
wait = 2 ** attempt
|
|
442
|
+
logger.warning("Async server error, retrying in %ss…", wait)
|
|
443
|
+
await asyncio.sleep(wait)
|
|
444
|
+
continue
|
|
445
|
+
raise
|
|
446
|
+
except asyncio.TimeoutError:
|
|
447
|
+
if attempt < attempts - 1:
|
|
448
|
+
logger.warning("Async timeout, retrying…")
|
|
449
|
+
continue
|
|
450
|
+
raise ValidationError("Request timeout")
|
|
451
|
+
except _AIOHTTP_CLIENT_ERROR as exc:
|
|
452
|
+
if attempt < attempts - 1:
|
|
453
|
+
logger.warning("Async request failed: %s, retrying…", exc)
|
|
454
|
+
continue
|
|
455
|
+
raise ValidationError(f"Request failed: {exc}")
|
|
456
|
+
|
|
457
|
+
raise ValidationError("Max retries exceeded")
|
|
458
|
+
|
|
459
|
+
# ------------------------------------------------------------------
|
|
460
|
+
# Context manager support
|
|
461
|
+
# ------------------------------------------------------------------
|
|
462
|
+
|
|
463
|
+
def __enter__(self):
|
|
464
|
+
return self
|
|
465
|
+
|
|
466
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
467
|
+
self.close()
|
|
468
|
+
if self._async_session is not None and not self._async_session.closed:
|
|
469
|
+
logger.warning(
|
|
470
|
+
"Async session still open. "
|
|
471
|
+
"Use 'async with CeroneClient(...)' or await client.aclose()."
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
async def __aenter__(self):
|
|
475
|
+
return self
|
|
476
|
+
|
|
477
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
478
|
+
await self.aclose()
|
|
479
|
+
self.close()
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
class AgentWrapper:
|
|
483
|
+
"""Wrapper that automatically validates all agent actions via a decorator."""
|
|
484
|
+
|
|
485
|
+
def __init__(self, cerone_client: CeroneClient, agent_id: str):
|
|
486
|
+
self.client = cerone_client
|
|
487
|
+
self.agent_id = agent_id
|
|
488
|
+
|
|
489
|
+
def validate_action(self, func: F) -> F:
|
|
490
|
+
"""Decorator that validates a function call through Cerone before executing it."""
|
|
491
|
+
|
|
492
|
+
@wraps(func)
|
|
493
|
+
def wrapper(*args: Any, **kwargs: Any):
|
|
494
|
+
action = func.__name__
|
|
495
|
+
parameters = {"args": args, "kwargs": kwargs}
|
|
496
|
+
|
|
497
|
+
result = self.client.validate(
|
|
498
|
+
agent_id=self.agent_id,
|
|
499
|
+
action=action,
|
|
500
|
+
parameters=parameters,
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
if result.result == ValidationResult.APPROVED:
|
|
504
|
+
logger.info(
|
|
505
|
+
"Action '%s' approved (alignment: %.2f)",
|
|
506
|
+
action,
|
|
507
|
+
result.semantic_alignment,
|
|
508
|
+
)
|
|
509
|
+
return func(*args, **kwargs)
|
|
510
|
+
|
|
511
|
+
logger.warning("Action '%s' blocked: %s", action, result.violations)
|
|
512
|
+
raise PermissionError(f"Cerone blocked action: {', '.join(result.violations)}")
|
|
513
|
+
|
|
514
|
+
return cast(F, wrapper)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
__all__ = [
|
|
518
|
+
"CeroneClient",
|
|
519
|
+
"AgentWrapper",
|
|
520
|
+
"CeroneResponse",
|
|
521
|
+
"AgentCertificate",
|
|
522
|
+
"ValidationResult",
|
|
523
|
+
"CeroneException",
|
|
524
|
+
"AuthenticationError",
|
|
525
|
+
"ValidationError",
|
|
526
|
+
"RateLimitError",
|
|
527
|
+
]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cerone
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Zero Trust Security for AI Agents
|
|
5
|
+
Home-page: https://github.com/AnantDhavale/cerone
|
|
6
|
+
Author: Anant Dhavale for Homer Semantics
|
|
7
|
+
Author-email: Homer Semantics <info@homersemantics.com>
|
|
8
|
+
License: Cerone SDK Commercial License
|
|
9
|
+
Version 1.0
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Anant Dhavale and Homer Semantics. All rights reserved.
|
|
12
|
+
|
|
13
|
+
This license governs use of the Cerone Software Development Kit ("SDK") and any associated source code, binaries, examples, and documentation made available by Homer Semantics ("Licensor").
|
|
14
|
+
|
|
15
|
+
1. Grant of License
|
|
16
|
+
Subject to compliance with this License, Licensor grants you a limited, non-exclusive, non-transferable, revocable license to:
|
|
17
|
+
(a) use the SDK solely to develop, test, and operate integrations with Licensor's Cerone services;
|
|
18
|
+
(b) reproduce and distribute the SDK only as embedded within your application in object form, where end users cannot reasonably extract the SDK as a standalone developer tool.
|
|
19
|
+
|
|
20
|
+
2. Ownership and Intellectual Property
|
|
21
|
+
The SDK is licensed, not sold. Licensor retains all right, title, and interest in and to the SDK, including all intellectual property rights, trade secrets, and derivative works.
|
|
22
|
+
|
|
23
|
+
3. Restrictions
|
|
24
|
+
You may not, and may not permit others to:
|
|
25
|
+
(a) sell, sublicense, rent, lease, or provide the SDK as a standalone product or service;
|
|
26
|
+
(b) modify, create derivative works of, or redistribute the SDK source code, except with Licensor's prior written permission;
|
|
27
|
+
(c) remove, alter, or obscure any copyright, trademark, or proprietary notices;
|
|
28
|
+
(d) use the SDK or Cerone services to build, train, benchmark, validate, or improve any competing product or service, including competitive analysis intended for publication or commercialization;
|
|
29
|
+
(e) reverse engineer, decompile, disassemble, translate, decode, or otherwise attempt to derive source code, underlying ideas, algorithms, model behavior, scoring logic, thresholds, prompts, or non-public APIs, except to the limited extent such restriction is expressly prohibited by applicable law;
|
|
30
|
+
(f) attempt model extraction, prompt extraction, dataset extraction, or systematic output analysis intended to replicate Cerone functionality;
|
|
31
|
+
(g) attempt to discover or reconstruct non-public service internals, infrastructure, security controls, or backend implementation details through unauthorized means, including probing, scraping, fuzzing, or penetration activity without prior written authorization from Licensor;
|
|
32
|
+
(h) circumvent or attempt to circumvent usage limits, authentication controls, billing controls, access restrictions, anti-abuse controls, or monitoring controls.
|
|
33
|
+
|
|
34
|
+
4. Service Terms and Quotas
|
|
35
|
+
Use of the Cerone service APIs is subject to separate service terms, usage quotas, and pricing published by Licensor. Licensor may suspend or terminate API access for abuse, non-payment, security risk, or license breach. Current introductory quota is described in the Terms of Service and may change from time to time.
|
|
36
|
+
|
|
37
|
+
5. Confidentiality
|
|
38
|
+
Any non-public technical information, performance information, keys, or implementation details disclosed by Licensor are confidential and must not be disclosed to third parties.
|
|
39
|
+
|
|
40
|
+
6. Feedback
|
|
41
|
+
If you provide feedback, suggestions, or improvement ideas, you grant Licensor a perpetual, irrevocable, worldwide, royalty-free right to use them without restriction or compensation.
|
|
42
|
+
|
|
43
|
+
7. Disclaimer
|
|
44
|
+
THE SDK IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
45
|
+
|
|
46
|
+
8. Limitation of Liability
|
|
47
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, LICENSOR WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR ANY LOSS OF DATA, PROFITS, OR REVENUE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LICENSOR'S AGGREGATE LIABILITY FOR ALL CLAIMS RELATING TO THE SDK WILL NOT EXCEED USD $100.
|
|
48
|
+
|
|
49
|
+
9. Termination
|
|
50
|
+
This License is effective until terminated. It terminates automatically if you breach any term. Upon termination, you must cease use of the SDK and destroy all copies in your possession or control.
|
|
51
|
+
|
|
52
|
+
10. Governing Law
|
|
53
|
+
This License is governed by the laws of Western Australia, without regard to conflict of laws principles. Any dispute shall be subject to the exclusive jurisdiction of the courts of Western Australia.
|
|
54
|
+
|
|
55
|
+
11. Contact
|
|
56
|
+
Licensing requests: info@homersemantics.com , anantdhavale@gmail.com
|
|
57
|
+
|
|
58
|
+
By using the SDK, you agree to this License.
|
|
59
|
+
|
|
60
|
+
Project-URL: Homepage, https://aztp.homersemantics.com
|
|
61
|
+
Project-URL: Repository, https://github.com/AnantDhavale/cerone
|
|
62
|
+
Project-URL: Bug Tracker, https://github.com/AnantDhavale/cerone/issues
|
|
63
|
+
Keywords: ai,agents,security,zero-trust,validation,llm
|
|
64
|
+
Classifier: Development Status :: 4 - Beta
|
|
65
|
+
Classifier: Intended Audience :: Developers
|
|
66
|
+
Classifier: License :: Other/Proprietary License
|
|
67
|
+
Classifier: Programming Language :: Python :: 3
|
|
68
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
69
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
70
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
71
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
72
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
73
|
+
Classifier: Topic :: Security
|
|
74
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
75
|
+
Requires-Python: >=3.8
|
|
76
|
+
Description-Content-Type: text/markdown
|
|
77
|
+
License-File: LICENSE
|
|
78
|
+
Requires-Dist: requests>=2.28
|
|
79
|
+
Provides-Extra: async
|
|
80
|
+
Requires-Dist: aiohttp>=3.8; extra == "async"
|
|
81
|
+
Provides-Extra: dev
|
|
82
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
83
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
84
|
+
Requires-Dist: aiohttp>=3.8; extra == "dev"
|
|
85
|
+
Dynamic: author
|
|
86
|
+
Dynamic: home-page
|
|
87
|
+
Dynamic: license-file
|
|
88
|
+
Dynamic: requires-python
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Cerone Python SDK (Beta)
|
|
92
|
+
|
|
93
|
+
Zero Trust security and production governance for AI agents.
|
|
94
|
+
Cryptographic identity and run-time validation for AI agents in production.
|
|
95
|
+
|
|
96
|
+
AI agents are being deployed into production systems that handle real decisions, real data, and real consequences, yet most teams have no
|
|
97
|
+
runtime control over what those agents actually do. Cerone fixes that.
|
|
98
|
+
|
|
99
|
+
Cerone enforces cryptographic identity, semantic intent validation, and continuous trust scoring on every agent action; ensuring agents only
|
|
100
|
+
do what they were authorized to do, and nothing else. Deploying AI agents in production without this layer of protection is an unacceptable
|
|
101
|
+
operational and security risk.
|
|
102
|
+
|
|
103
|
+
The SDK is currently in early-access beta for selected teams building production AI systems that require accountability, auditability, and
|
|
104
|
+
control.
|
|
105
|
+
|
|
106
|
+
## Install
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install cerone
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Access (Beta)
|
|
113
|
+
|
|
114
|
+
API access is currently managed through early access:
|
|
115
|
+
|
|
116
|
+
- Request access: https://aztp.homersemantics.com/
|
|
117
|
+
- Receive approval and API credentials
|
|
118
|
+
- Review terms in `TERMS_OF_SERVICE.md`
|
|
119
|
+
|
|
120
|
+
## Quick Start
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from cerone import CeroneClient
|
|
124
|
+
import os
|
|
125
|
+
|
|
126
|
+
client = CeroneClient(api_key=os.getenv("CERONE_API_KEY"))
|
|
127
|
+
|
|
128
|
+
# Create agent
|
|
129
|
+
agent = client.create_agent(
|
|
130
|
+
purpose="Email classifier",
|
|
131
|
+
capabilities=["read_email", "move_email", "send_reply"]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Validate action before executing
|
|
135
|
+
response = client.validate(
|
|
136
|
+
agent_id=agent.agent_id,
|
|
137
|
+
action="move_email",
|
|
138
|
+
parameters={"email_id": "123", "folder": "spam"}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if response.result.value == "approved":
|
|
142
|
+
mailbox.move_email("123", "spam")
|
|
143
|
+
else:
|
|
144
|
+
print(f"Action rejected: {response.violations}")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## What the SDK Provides
|
|
148
|
+
|
|
149
|
+
- Authenticated client access to Cerone services
|
|
150
|
+
- Agent registration and identity-bound operations
|
|
151
|
+
- Sync and async validation calls
|
|
152
|
+
- Batch validation support
|
|
153
|
+
- Governance-oriented telemetry surfaces
|
|
154
|
+
|
|
155
|
+
## Usage Terms
|
|
156
|
+
|
|
157
|
+
Usage limits and commercial terms are defined in `TERMS_OF_SERVICE.md`.
|
|
158
|
+
|
|
159
|
+
Current free trial: up to 25 validations in the first 5 days.
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
Proprietary commercial license. See `LICENSE`.
|
|
164
|
+
|
|
165
|
+
## Contact
|
|
166
|
+
anantdhavale@gmail.com
|
|
167
|
+
info@homersemantics.com
|
|
168
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
TERMS_OF_SERVICE.md
|
|
5
|
+
pyproject.toml
|
|
6
|
+
setup.py
|
|
7
|
+
cerone/__init__.py
|
|
8
|
+
cerone.egg-info/PKG-INFO
|
|
9
|
+
cerone.egg-info/SOURCES.txt
|
|
10
|
+
cerone.egg-info/dependency_links.txt
|
|
11
|
+
cerone.egg-info/requires.txt
|
|
12
|
+
cerone.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cerone
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cerone"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Zero Trust Security for AI Agents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Homer Semantics", email = "info@homersemantics.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ai", "agents", "security", "zero-trust", "validation", "llm"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: Other/Proprietary License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Security",
|
|
27
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
dependencies = [
|
|
31
|
+
"requests>=2.28",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
async = [
|
|
36
|
+
"aiohttp>=3.8",
|
|
37
|
+
]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest>=7.0",
|
|
40
|
+
"pytest-asyncio>=0.21",
|
|
41
|
+
"aiohttp>=3.8",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://aztp.homersemantics.com"
|
|
46
|
+
Repository = "https://github.com/AnantDhavale/cerone"
|
|
47
|
+
"Bug Tracker" = "https://github.com/AnantDhavale/cerone/issues"
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.packages.find]
|
|
50
|
+
where = ["."]
|
|
51
|
+
include = ["cerone*"]
|
cerone-1.0.0/setup.cfg
ADDED
cerone-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Setup configuration for Cerone Python SDK."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from setuptools import find_packages, setup
|
|
7
|
+
|
|
8
|
+
ROOT = Path(__file__).parent
|
|
9
|
+
README = ROOT / "README.md"
|
|
10
|
+
os.chdir(ROOT)
|
|
11
|
+
|
|
12
|
+
setup(
|
|
13
|
+
name="cerone",
|
|
14
|
+
version="1.0.0",
|
|
15
|
+
author="Anant Dhavale for Homer Semantics",
|
|
16
|
+
author_email="info@homersemantics.com",
|
|
17
|
+
description="Zero Trust Security for AI Agents",
|
|
18
|
+
license="Proprietary - see LICENSE file",
|
|
19
|
+
long_description=README.read_text(encoding="utf-8"),
|
|
20
|
+
long_description_content_type="text/markdown",
|
|
21
|
+
url="https://github.com/AnantDhavale/cerone",
|
|
22
|
+
project_urls={
|
|
23
|
+
"Documentation": "https://aztp.homersemantics.com/",
|
|
24
|
+
"Bug Tracker": "https://github.com/AnantDhavale/cerone/issues",
|
|
25
|
+
"Homepage": "https://aztp.homersemantics.com/",
|
|
26
|
+
},
|
|
27
|
+
packages=["cerone"],
|
|
28
|
+
include_package_data=True,
|
|
29
|
+
classifiers=[
|
|
30
|
+
"Development Status :: 4 - Beta",
|
|
31
|
+
"Intended Audience :: Developers",
|
|
32
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
33
|
+
"Topic :: Security",
|
|
34
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
35
|
+
"License :: Other/Proprietary License",
|
|
36
|
+
"Programming Language :: Python :: 3",
|
|
37
|
+
"Programming Language :: Python :: 3.8",
|
|
38
|
+
"Programming Language :: Python :: 3.9",
|
|
39
|
+
"Programming Language :: Python :: 3.10",
|
|
40
|
+
"Programming Language :: Python :: 3.11",
|
|
41
|
+
"Programming Language :: Python :: 3.12",
|
|
42
|
+
],
|
|
43
|
+
python_requires=">=3.8",
|
|
44
|
+
install_requires=[
|
|
45
|
+
"requests>=2.28.0",
|
|
46
|
+
],
|
|
47
|
+
extras_require={
|
|
48
|
+
"async": [
|
|
49
|
+
"aiohttp>=3.8.0",
|
|
50
|
+
],
|
|
51
|
+
"dev": [
|
|
52
|
+
"pytest>=7.0.0",
|
|
53
|
+
"pytest-asyncio>=0.21.0",
|
|
54
|
+
"black>=23.0.0",
|
|
55
|
+
"flake8>=6.0.0",
|
|
56
|
+
"mypy>=1.0.0",
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
keywords="ai agent security zero-trust governance semantic-validation",
|
|
60
|
+
)
|