a2aclear 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ """
2
+ a2aclear.integrations.crewai
3
+ CrewAI Multi-Agent Swarm Financial Settlement Adapter
4
+ Enables autonomous financial settlements between members of a CrewAI swarm.
5
+ """
6
+
7
+ import json
8
+ from typing import Dict, Any, List, Optional
9
+ from ..identity import AgentIdentity
10
+ from ..contract import TaskContract
11
+ from ..escrow import MicroEscrowVault
12
+
13
+ class A2ACrewSettlementHandler:
14
+ """
15
+ Financial manager for CrewAI swarms.
16
+ Assigns Ed25519 identities to each crew agent and manages inter-agent micropayments.
17
+ """
18
+
19
+ def __init__(self, crew_name: str = "UnnatEnterpriseSwarm"):
20
+ self.crew_name = crew_name
21
+ self.vault = MicroEscrowVault()
22
+ self.agent_identities: Dict[str, AgentIdentity] = {}
23
+
24
+ def register_crew_agent(self, agent_role: str, initial_deposit_paise: int = 10000) -> AgentIdentity:
25
+ """Assign an Ed25519 identity to a crew agent and fund its balance."""
26
+ identity = AgentIdentity.generate()
27
+ self.agent_identities[agent_role] = identity
28
+ if initial_deposit_paise > 0:
29
+ self.vault.deposit(identity.did, initial_deposit_paise)
30
+ return identity
31
+
32
+ def settle_crew_step(
33
+ self,
34
+ from_role: str,
35
+ to_role: str,
36
+ task_name: str,
37
+ step_cost_paise: int,
38
+ task_output: Any
39
+ ) -> Dict[str, Any]:
40
+ """
41
+ Executes an atomic micro-settlement when one crew agent hands off work to another.
42
+ """
43
+ buyer = self.agent_identities.get(from_role) or self.register_crew_agent(from_role)
44
+ seller = self.agent_identities.get(to_role) or self.register_crew_agent(to_role, initial_deposit_paise=0)
45
+
46
+ contract = TaskContract(
47
+ task_id=f"crew_{from_role}_{to_role}_{task_name}",
48
+ originator_did=buyer.did,
49
+ provider_did=seller.did,
50
+ amount_paise=step_cost_paise,
51
+ currency="INR"
52
+ )
53
+
54
+ self.vault.lock_escrow(contract)
55
+ receipt = self.vault.verify_and_settle(contract, task_output)
56
+
57
+ return {
58
+ "success": True,
59
+ "task": task_name,
60
+ "from": from_role,
61
+ "to": to_role,
62
+ "settled_hash": receipt["settlement_hash"],
63
+ "worker_received_paise": receipt["provider_received_paise"],
64
+ "protocol_fee_paise": receipt["protocol_fee_paise"]
65
+ }
@@ -0,0 +1,87 @@
1
+ """
2
+ a2aclear.integrations.langchain
3
+ LangChain & LangGraph Integration Adapter for A2AClear Protocol
4
+ Allows autonomous LangChain agents to contract, lock escrow, and settle with peer agents.
5
+ """
6
+
7
+ import json
8
+ from typing import Dict, Any, Optional
9
+ from ..identity import AgentIdentity
10
+ from ..negotiator import AutonomousNegotiator
11
+ from ..escrow import MicroEscrowVault
12
+
13
+ class A2AClearLangChainTool:
14
+ """
15
+ LangChain compatible tool for autonomous financial delegation and micro-escrow settlement.
16
+ """
17
+
18
+ name: str = "a2aclear_settlement"
19
+ description: str = (
20
+ "Use this tool to autonomously hire, lock micro-escrow, and pay another AI agent "
21
+ "for a specific subtask using the A2AClear sovereign clearinghouse protocol."
22
+ )
23
+
24
+ def __init__(self, identity: Optional[AgentIdentity] = None, vault: Optional[MicroEscrowVault] = None):
25
+ self.identity = identity or AgentIdentity.generate()
26
+ self.vault = vault or MicroEscrowVault()
27
+ self.negotiator = AutonomousNegotiator(self.identity)
28
+
29
+ def run(self, action: str, **kwargs) -> str:
30
+ """Execute settlement actions from a LangChain agent turn."""
31
+ action = action.upper()
32
+
33
+ if action == "GET_BALANCE":
34
+ balance = self.vault.get_balance(self.identity.did)
35
+ return json.dumps({
36
+ "agent_did": self.identity.did,
37
+ "balance_inr": f"₹{balance / 100:.2f}",
38
+ "balance_paise": balance
39
+ })
40
+
41
+ elif action == "HIRE_AND_LOCK_ESCROW":
42
+ task_id = kwargs.get("task_id", f"lc_task_{int(self.identity.did[-8:], 16)}")
43
+ provider_did = kwargs.get("provider_did")
44
+ amount_paise = int(kwargs.get("amount_paise", 5000))
45
+ task_spec = kwargs.get("task_spec", {})
46
+
47
+ if not provider_did:
48
+ return json.dumps({"error": "provider_did is required to delegate task"})
49
+
50
+ proposal = self.negotiator.propose_contract(
51
+ task_id=task_id,
52
+ provider_did=provider_did,
53
+ initial_bid_paise=amount_paise,
54
+ currency="INR",
55
+ task_spec=task_spec
56
+ )
57
+
58
+ contract = self.negotiator.active_contracts[task_id]
59
+ try:
60
+ escrow_record = self.vault.lock_escrow(contract)
61
+ return json.dumps({
62
+ "status": "ESCROW_LOCKED",
63
+ "escrow_id": escrow_record["escrow_id"],
64
+ "task_id": task_id,
65
+ "locked_amount_inr": f"₹{amount_paise / 100:.2f}",
66
+ "protocol_fee_inr": f"₹{contract.protocol_fee_paise / 100:.2f} (0.50%)"
67
+ })
68
+ except Exception as e:
69
+ return json.dumps({"error": f"Failed to lock escrow: {str(e)}"})
70
+
71
+ elif action == "SETTLE_DELIVERABLE":
72
+ task_id = kwargs.get("task_id")
73
+ deliverable = kwargs.get("deliverable", {})
74
+ contract = self.negotiator.active_contracts.get(task_id)
75
+ if not contract:
76
+ return json.dumps({"error": f"Contract {task_id} not found"})
77
+
78
+ receipt = self.vault.verify_and_settle(contract, deliverable)
79
+ return json.dumps({
80
+ "status": "SETTLED",
81
+ "settlement_hash": receipt["settlement_hash"],
82
+ "provider_payout_inr": f"₹{receipt['provider_received_paise'] / 100:.2f}",
83
+ "protocol_fee_inr": f"₹{receipt['protocol_fee_paise'] / 100:.2f}"
84
+ })
85
+
86
+ else:
87
+ return json.dumps({"error": f"Unknown A2AClear action: {action}"})
a2aclear/negotiator.py ADDED
@@ -0,0 +1,111 @@
1
+ """
2
+ a2aclear.negotiator
3
+ Autonomous Agent Negotiation Protocol (ANP) Finite-State Machine
4
+ """
5
+
6
+ import time
7
+ import json
8
+ from typing import Dict, Any, Optional, Tuple
9
+ from .identity import AgentIdentity
10
+ from .contract import TaskContract, ContractState
11
+
12
+ class AutonomousNegotiator:
13
+ """
14
+ Autonomous Negotiation Protocol (ANP) Engine.
15
+ Handles bilateral SLA negotiation, automated counter-offers, and Ed25519 countersigning.
16
+ """
17
+
18
+ def __init__(self, identity: AgentIdentity, max_budget_paise: int = 1000000):
19
+ self.identity = identity
20
+ self.max_budget_paise = max_budget_paise
21
+ self.active_contracts: Dict[str, TaskContract] = {}
22
+
23
+ def propose_contract(
24
+ self,
25
+ task_id: str,
26
+ provider_did: str,
27
+ initial_bid_paise: int,
28
+ currency: str = "INR",
29
+ sla_timeout_seconds: int = 300,
30
+ task_spec: Dict[str, Any] = None
31
+ ) -> Dict[str, Any]:
32
+ """
33
+ Agent Originator proposes a task contract to a provider agent.
34
+ """
35
+ spec_str = json.dumps(task_spec or {}, sort_keys=True)
36
+ import hashlib
37
+ spec_hash = hashlib.sha256(spec_str.encode("utf-8")).hexdigest()
38
+
39
+ contract = TaskContract(
40
+ task_id=task_id,
41
+ originator_did=self.identity.did,
42
+ provider_did=provider_did,
43
+ amount_paise=initial_bid_paise,
44
+ currency=currency,
45
+ sla_timeout_seconds=sla_timeout_seconds,
46
+ task_spec_hash=spec_hash
47
+ )
48
+
49
+ contract_hash = contract.compute_contract_hash()
50
+ contract.originator_signature = self.identity.sign(contract_hash.encode("utf-8")).hex()
51
+ contract.state = ContractState.PROPOSED
52
+ self.active_contracts[task_id] = contract
53
+
54
+ return self.identity.sign_envelope(
55
+ payload=contract.to_dict(),
56
+ action="PROPOSE_CONTRACT",
57
+ recipient_did=provider_did
58
+ )
59
+
60
+ def evaluate_proposal(
61
+ self,
62
+ envelope: Dict[str, Any],
63
+ minimum_acceptable_paise: int
64
+ ) -> Tuple[str, Dict[str, Any]]:
65
+ """
66
+ Agent Provider evaluates an incoming proposal envelope.
67
+ Returns ("ACCEPT" | "COUNTER" | "REJECT", response_envelope).
68
+ """
69
+ if not AgentIdentity.verify_envelope(envelope):
70
+ raise ValueError("Cryptographic envelope signature verification failed.")
71
+
72
+ payload = envelope["payload"]
73
+ task_id = payload["task_id"]
74
+ offered_amount = payload["amount_paise"]
75
+ originator_did = envelope["sender_did"]
76
+
77
+ if offered_amount >= minimum_acceptable_paise:
78
+ # Accept and countersign
79
+ contract = TaskContract(
80
+ task_id=task_id,
81
+ originator_did=originator_did,
82
+ provider_did=self.identity.did,
83
+ amount_paise=offered_amount,
84
+ currency=payload.get("currency", "INR"),
85
+ sla_timeout_seconds=payload.get("sla_timeout_seconds", 300),
86
+ task_spec_hash=payload.get("task_spec_hash", "")
87
+ )
88
+ contract_hash = contract.compute_contract_hash()
89
+ contract.originator_signature = payload.get("originator_signature")
90
+ contract.provider_signature = self.identity.sign(contract_hash.encode("utf-8")).hex()
91
+ contract.state = ContractState.AGREED
92
+ self.active_contracts[task_id] = contract
93
+
94
+ resp_env = self.identity.sign_envelope(
95
+ payload=contract.to_dict(),
96
+ action="ACCEPT_CONTRACT",
97
+ recipient_did=originator_did
98
+ )
99
+ return "ACCEPT", resp_env
100
+ else:
101
+ # Counter-offer with minimum price
102
+ counter_payload = dict(payload)
103
+ counter_payload["amount_paise"] = minimum_acceptable_paise
104
+ counter_payload["counter_reason"] = "Requested price below compute/inference margin threshold."
105
+
106
+ resp_env = self.identity.sign_envelope(
107
+ payload=counter_payload,
108
+ action="COUNTER_BID",
109
+ recipient_did=originator_did
110
+ )
111
+ return "COUNTER", resp_env
a2aclear/reputation.py ADDED
@@ -0,0 +1,95 @@
1
+ """
2
+ a2aclear.reputation
3
+ Sovereign Reputation Ledger & Collateral Staking Defense System
4
+ Maintains mathematical agent reputation, trust scores, and anti-sybil collateral slashing.
5
+ """
6
+
7
+ import time
8
+ import math
9
+ from typing import Dict, Any, Optional
10
+
11
+ class AgentReputationLedger:
12
+ """
13
+ Sovereign Decentralized Reputation & Collateral Staking Engine.
14
+ Computes deterministic reputation metrics based on historical contract execution proofs.
15
+ """
16
+
17
+ def __init__(self):
18
+ # did -> record
19
+ self.records: Dict[str, Dict[str, Any]] = {}
20
+
21
+ def get_or_create(self, did: str) -> Dict[str, Any]:
22
+ if did not in self.records:
23
+ self.records[did] = {
24
+ "did": did,
25
+ "created_at": int(time.time()),
26
+ "total_tasks_attempted": 0,
27
+ "total_tasks_completed": 0,
28
+ "total_volume_settled_paise": 0,
29
+ "sla_breaches": 0,
30
+ "slashed_count": 0,
31
+ "collateral_staked_paise": 0,
32
+ "is_blacklisted": False,
33
+ "reputation_score": 100.0 # Base score for authenticated Ed25519 node
34
+ }
35
+ return self.records[did]
36
+
37
+ def stake_collateral(self, did: str, amount_paise: int):
38
+ """Stake bonding collateral to unlock high-tier B2B agent contracts."""
39
+ record = self.get_or_create(did)
40
+ if record["is_blacklisted"]:
41
+ raise PermissionError("Blacklisted agent node cannot stake collateral.")
42
+ record["collateral_staked_paise"] += amount_paise
43
+ self.recompute_score(did)
44
+
45
+ def record_settlement(self, did: str, volume_paise: int, latency_ms: float, sla_target_ms: float):
46
+ """Record a successful atomic settlement proof."""
47
+ record = self.get_or_create(did)
48
+ if record["is_blacklisted"]:
49
+ return
50
+
51
+ record["total_tasks_attempted"] += 1
52
+ record["total_tasks_completed"] += 1
53
+ record["total_volume_settled_paise"] += volume_paise
54
+
55
+ if latency_ms > sla_target_ms:
56
+ record["sla_breaches"] += 1
57
+
58
+ self.recompute_score(did)
59
+
60
+ def record_slash(self, did: str, reason: str) -> int:
61
+ """Slash 100% of collateral upon malicious behavior or cryptographic forgery."""
62
+ record = self.get_or_create(did)
63
+ record["slashed_count"] += 1
64
+ record["is_blacklisted"] = True
65
+ record["reputation_score"] = 0.0
66
+ slashed_amount = record["collateral_staked_paise"]
67
+ record["collateral_staked_paise"] = 0
68
+ record["slash_reason"] = reason
69
+ return slashed_amount
70
+
71
+ def recompute_score(self, did: str) -> float:
72
+ """
73
+ Mathematical Reputation Formula:
74
+ R = 0.50 * CompletionRatio + 0.30 * SLARatio + 0.20 * VolumeLog - SlashedPenalty
75
+ """
76
+ record = self.records[did]
77
+ if record["is_blacklisted"]:
78
+ return 0.0
79
+
80
+ total = record["total_tasks_attempted"]
81
+ if total == 0:
82
+ return 100.0
83
+
84
+ completed = record["total_tasks_completed"]
85
+ breaches = record["sla_breaches"]
86
+
87
+ completion_ratio = (completed / total) * 100.0
88
+ sla_ratio = max(0.0, ((total - breaches) / total) * 100.0)
89
+
90
+ volume_inr = record["total_volume_settled_paise"] / 100.0
91
+ volume_boost = min(100.0, math.log10(max(1.0, volume_inr)) * 20.0)
92
+
93
+ score = (0.50 * completion_ratio) + (0.35 * sla_ratio) + (0.15 * volume_boost)
94
+ record["reputation_score"] = round(min(100.0, max(0.0, score)), 2)
95
+ return record["reputation_score"]
a2aclear/security.py ADDED
@@ -0,0 +1,182 @@
1
+ """
2
+ a2aclear.security
3
+ Institutional Cybersecurity, Anti-Hacking & Cryptographic IP Armor
4
+ Includes AES-256-GCM Encrypted Keystores, Replay Attack Defense,
5
+ Payload Sanitization, and Sovereign Cryptographic Watermarking.
6
+
7
+ (C) 2026 Unnat AI Solutions. Chief Systems Architect: Rohit.
8
+ """
9
+
10
+ import os
11
+ import time
12
+ import json
13
+ import hashlib
14
+ from typing import Dict, Any, Optional, Set
15
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
16
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
17
+ from cryptography.hazmat.primitives import hashes
18
+
19
+ SOVEREIGN_WATERMARK_SALT = b"ROHIT_UNNAT_AI_SOLUTIONS_SOVEREIGN_ROOT_2026_KURUKSHETRA"
20
+
21
+ class ReplayAttackException(Exception):
22
+ """Raised when an envelope fails replay attack or timestamp validation."""
23
+ pass
24
+
25
+ class MaliciousPayloadException(Exception):
26
+ """Raised when an incoming deliverable fails security sanitization."""
27
+ pass
28
+
29
+ class EncryptedKeyStore:
30
+ """
31
+ Military-Grade AES-256-GCM Encrypted Keystore.
32
+ Protects Agent Ed25519 private keys on disk using PBKDF2 key derivation (100,000 rounds).
33
+ Prevents plaintext key theft, memory dumps, and environment variable snooping.
34
+ """
35
+
36
+ @staticmethod
37
+ def derive_encryption_key(passphrase: str, salt: bytes) -> bytes:
38
+ kdf = PBKDF2HMAC(
39
+ algorithm=hashes.SHA256(),
40
+ length=32,
41
+ salt=salt,
42
+ iterations=100000,
43
+ )
44
+ return kdf.derive(passphrase.encode("utf-8"))
45
+
46
+ @classmethod
47
+ def save_encrypted_key(cls, private_hex: str, passphrase: str, filepath: str):
48
+ """Encrypts and writes private key to secure file."""
49
+ salt = os.urandom(16)
50
+ nonce = os.urandom(12)
51
+ key = cls.derive_encryption_key(passphrase, salt)
52
+ aesgcm = AESGCM(key)
53
+
54
+ ciphertext = aesgcm.encrypt(nonce, private_hex.encode("utf-8"), None)
55
+
56
+ keystore_blob = {
57
+ "version": "A2A_KEYSTORE_V1_AES256GCM",
58
+ "salt_hex": salt.hex(),
59
+ "nonce_hex": nonce.hex(),
60
+ "ciphertext_hex": ciphertext.hex(),
61
+ "created_at": int(time.time()),
62
+ "sovereign_armor": "UNNAT_ENCRYPTED_VAULT"
63
+ }
64
+
65
+ with open(filepath, "w", encoding="utf-8") as f:
66
+ json.dump(keystore_blob, f, indent=2)
67
+
68
+ @classmethod
69
+ def load_encrypted_key(cls, passphrase: str, filepath: str) -> str:
70
+ """Decrypts private key in memory only. Never leaks to disk."""
71
+ with open(filepath, "r", encoding="utf-8") as f:
72
+ blob = json.load(f)
73
+
74
+ salt = bytes.fromhex(blob["salt_hex"])
75
+ nonce = bytes.fromhex(blob["nonce_hex"])
76
+ ciphertext = bytes.fromhex(blob["ciphertext_hex"])
77
+
78
+ key = cls.derive_encryption_key(passphrase, salt)
79
+ aesgcm = AESGCM(key)
80
+
81
+ try:
82
+ decrypted_bytes = aesgcm.decrypt(nonce, ciphertext, None)
83
+ return decrypted_bytes.decode("utf-8")
84
+ except Exception:
85
+ raise PermissionError("Decryption failed. Invalid passphrase or corrupted keystore.")
86
+
87
+ class ReplayDefenseValidator:
88
+ """
89
+ Zero-Trust Replay Attack Defense & Nonce Cache.
90
+ Rejects any transaction envelope outside a 60-second sliding clock window
91
+ or containing an already-used nonce.
92
+ """
93
+
94
+ def __init__(self, max_clock_skew_seconds: int = 60, max_cache_size: int = 100000):
95
+ self.max_clock_skew_seconds = max_clock_skew_seconds
96
+ self.max_cache_size = max_cache_size
97
+ self.seen_nonces: Set[str] = set()
98
+
99
+ def validate_envelope(self, envelope: Dict[str, Any]):
100
+ sender_did = envelope.get("sender_did", "")
101
+ timestamp = envelope.get("timestamp", 0)
102
+ nonce = envelope.get("nonce", None)
103
+
104
+ if nonce is None:
105
+ raise ReplayAttackException("Security violation: Envelope missing cryptographic nonce.")
106
+
107
+ now = int(time.time())
108
+ if abs(now - timestamp) > self.max_clock_skew_seconds:
109
+ raise ReplayAttackException(
110
+ f"Clock skew rejected. Envelope timestamp {timestamp} is outside allowable {self.max_clock_skew_seconds}s window (Current: {now})."
111
+ )
112
+
113
+ nonce_key = f"{sender_did}:{nonce}"
114
+ if nonce_key in self.seen_nonces:
115
+ raise ReplayAttackException(f"REPLAY ATTACK BLOCKED: Nonce {nonce} from {sender_did} already utilized!")
116
+
117
+ # Add to seen nonces
118
+ if len(self.seen_nonces) >= self.max_cache_size:
119
+ self.seen_nonces.clear() # Reset cache on full capacity
120
+
121
+ self.seen_nonces.add(nonce_key)
122
+
123
+ class PayloadSanitizer:
124
+ """
125
+ Deep Content Inspection & Anti-Injection Guard for AI Agent Deliverables.
126
+ Prevents prompt injection, malicious shell escapes, oversized payloads, and recursive JSON bombs.
127
+ """
128
+
129
+ MAX_PAYLOAD_BYTES = 5 * 1024 * 1024 # 5 MB limit
130
+ MAX_DEPTH = 8
131
+
132
+ DANGEROUS_PATTERNS = [
133
+ "__import__", "os.system", "subprocess", "eval(", "exec(",
134
+ "/etc/passwd", "DROP TABLE", "<script>", "javascript:"
135
+ ]
136
+
137
+ @classmethod
138
+ def sanitize(cls, deliverable: Any):
139
+ # 1. Size check
140
+ raw_str = json.dumps(deliverable) if not isinstance(deliverable, str) else deliverable
141
+ if len(raw_str.encode("utf-8")) > cls.MAX_PAYLOAD_BYTES:
142
+ raise MaliciousPayloadException("Payload exceeds 5MB micro-task limit.")
143
+
144
+ # 2. Check depth
145
+ if isinstance(deliverable, (dict, list)):
146
+ cls._check_depth(deliverable, 0)
147
+
148
+ # 3. Check dangerous injection patterns
149
+ for pattern in cls.DANGEROUS_PATTERNS:
150
+ if pattern in raw_str:
151
+ raise MaliciousPayloadException(f"Security Alert: Malicious code injection signature detected ('{pattern}').")
152
+
153
+ return True
154
+
155
+ @classmethod
156
+ def _check_depth(cls, obj: Any, depth: int):
157
+ if depth > cls.MAX_DEPTH:
158
+ raise MaliciousPayloadException("JSON recursion depth bomb detected.")
159
+ if isinstance(obj, dict):
160
+ for v in obj.values():
161
+ cls._check_depth(v, depth + 1)
162
+ elif isinstance(obj, list):
163
+ for item in obj:
164
+ cls._check_depth(item, depth + 1)
165
+
166
+ class SovereignCryptographicWatermark:
167
+ """
168
+ Steganographic Legal Watermark Engine.
169
+ Embeds an immutable mathematical proof of authorship into contract hashes.
170
+ Can be used in court or intellectual property disputes to prove theft.
171
+ """
172
+
173
+ @staticmethod
174
+ def generate_watermark(contract_hash: str) -> str:
175
+ """Derives a cryptographic authorship attestation tied to Rohit & Unnat AI."""
176
+ data = f"{contract_hash}:{SOVEREIGN_WATERMARK_SALT.decode()}"
177
+ return hashlib.sha256(data.encode("utf-8")).hexdigest()
178
+
179
+ @staticmethod
180
+ def verify_authorship(contract_hash: str, claimed_watermark: str) -> bool:
181
+ expected = SovereignCryptographicWatermark.generate_watermark(contract_hash)
182
+ return expected == claimed_watermark