Update sovereign_core.py
Browse files- sovereign_core.py +52 -35
sovereign_core.py
CHANGED
|
@@ -135,6 +135,7 @@ def verify_attestation(att: dict) -> bool:
|
|
| 135 |
# ---------------------------------------------------------------------
|
| 136 |
|
| 137 |
|
|
|
|
| 138 |
def build_lineage_record(
|
| 139 |
engine: str,
|
| 140 |
fingerprint: str,
|
|
@@ -142,25 +143,20 @@ def build_lineage_record(
|
|
| 142 |
model_version: str = "1.0",
|
| 143 |
data_tags: Optional[List[str]] = None,
|
| 144 |
notes: Optional[str] = None,
|
| 145 |
-
provider: Optional[str] = None,
|
| 146 |
-
model_family: Optional[str] = None,
|
| 147 |
) -> Dict[str, Any]:
|
| 148 |
"""
|
| 149 |
-
Create a
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
- version
|
| 154 |
-
- provider (multi-model support)
|
| 155 |
-
- optional parent model
|
| 156 |
-
- optional dataset / domain tags
|
| 157 |
-
into a single signed lineage_id.
|
| 158 |
"""
|
|
|
|
| 159 |
created_at = int(time.time())
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
)
|
| 164 |
lineage_hash = hashlib.sha256(payload.encode()).hexdigest()
|
| 165 |
|
| 166 |
return {
|
|
@@ -178,6 +174,9 @@ def build_lineage_record(
|
|
| 178 |
}
|
| 179 |
|
| 180 |
|
|
|
|
|
|
|
|
|
|
| 181 |
# ---------------------------------------------------------------------
|
| 182 |
# Simple risk profile (env + data tags)
|
| 183 |
# ---------------------------------------------------------------------
|
|
@@ -598,37 +597,55 @@ def log_model_execution(
|
|
| 598 |
|
| 599 |
def verify_certificate(cert: dict) -> bool:
|
| 600 |
"""
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
|
|
|
|
|
|
|
| 605 |
"""
|
| 606 |
try:
|
| 607 |
-
# 1)
|
| 608 |
-
att = cert.get("attestation"
|
| 609 |
if not verify_attestation(att):
|
| 610 |
return False
|
| 611 |
|
| 612 |
-
# 2)
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
f"{lineage.get('engine','')}"
|
| 616 |
-
f"{lineage.get('fingerprint','')}"
|
| 617 |
-
f"{lineage.get('model_version','')}"
|
| 618 |
-
f"{lineage.get('parent_model','')}"
|
| 619 |
-
f"{lineage.get('created_at','')}"
|
| 620 |
-
)
|
| 621 |
|
| 622 |
-
|
| 623 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 624 |
return False
|
| 625 |
|
| 626 |
-
# 3)
|
| 627 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 628 |
return False
|
| 629 |
|
|
|
|
| 630 |
return True
|
| 631 |
|
| 632 |
except Exception:
|
| 633 |
return False
|
| 634 |
-
|
|
|
|
| 135 |
# ---------------------------------------------------------------------
|
| 136 |
|
| 137 |
|
| 138 |
+
|
| 139 |
def build_lineage_record(
|
| 140 |
engine: str,
|
| 141 |
fingerprint: str,
|
|
|
|
| 143 |
model_version: str = "1.0",
|
| 144 |
data_tags: Optional[List[str]] = None,
|
| 145 |
notes: Optional[str] = None,
|
| 146 |
+
provider: Optional[str] = None,
|
| 147 |
+
model_family: Optional[str] = None,
|
| 148 |
) -> Dict[str, Any]:
|
| 149 |
"""
|
| 150 |
+
Create a cryptographically-bound lineage record for a model.
|
| 151 |
+
|
| 152 |
+
Hash formula (ثابت و قابل بازتولید):
|
| 153 |
+
payload = f"{engine}|{fingerprint}|{model_version}|{parent_model or ''}|{created_at}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
"""
|
| 155 |
+
|
| 156 |
created_at = int(time.time())
|
| 157 |
+
|
| 158 |
+
core_parent = parent_model or ""
|
| 159 |
+
payload = f"{engine}|{fingerprint}|{model_version}|{core_parent}|{created_at}"
|
|
|
|
| 160 |
lineage_hash = hashlib.sha256(payload.encode()).hexdigest()
|
| 161 |
|
| 162 |
return {
|
|
|
|
| 174 |
}
|
| 175 |
|
| 176 |
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
|
| 180 |
# ---------------------------------------------------------------------
|
| 181 |
# Simple risk profile (env + data tags)
|
| 182 |
# ---------------------------------------------------------------------
|
|
|
|
| 597 |
|
| 598 |
def verify_certificate(cert: dict) -> bool:
|
| 599 |
"""
|
| 600 |
+
Verification wrapper so that app.py can import it.
|
| 601 |
+
|
| 602 |
+
A valid certificate requires:
|
| 603 |
+
- attestation to verify successfully
|
| 604 |
+
- fingerprint / engine to be consistent across cert + lineage + attestation
|
| 605 |
+
- lineage_hash to match a recomputed hash from core fields
|
| 606 |
"""
|
| 607 |
try:
|
| 608 |
+
# 1) Attestation must be valid
|
| 609 |
+
att = cert.get("attestation") or {}
|
| 610 |
if not verify_attestation(att):
|
| 611 |
return False
|
| 612 |
|
| 613 |
+
# 2) Basic consistency checks
|
| 614 |
+
cert_fp = cert.get("fingerprint")
|
| 615 |
+
cert_engine = cert.get("engine")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 616 |
|
| 617 |
+
lineage = cert.get("lineage") or {}
|
| 618 |
+
line_fp = lineage.get("fingerprint")
|
| 619 |
+
line_engine = lineage.get("engine")
|
| 620 |
+
|
| 621 |
+
if not cert_fp:
|
| 622 |
+
return False
|
| 623 |
+
|
| 624 |
+
# fingerprint باید همهجا یکی باشد
|
| 625 |
+
if cert_fp != att.get("fingerprint"):
|
| 626 |
+
return False
|
| 627 |
+
if cert_fp != line_fp:
|
| 628 |
+
return False
|
| 629 |
+
|
| 630 |
+
# engine اگر در هر دو جا هست باید یکی باشد
|
| 631 |
+
if cert_engine and line_engine and cert_engine != line_engine:
|
| 632 |
return False
|
| 633 |
|
| 634 |
+
# 3) Recompute lineage_hash exactly like build_lineage_record
|
| 635 |
+
engine_val = line_engine or ""
|
| 636 |
+
fp_val = line_fp or ""
|
| 637 |
+
model_ver = (lineage.get("model_version") or "")
|
| 638 |
+
parent_val = (lineage.get("parent_model") or "")
|
| 639 |
+
created_val = lineage.get("created_at") or ""
|
| 640 |
+
|
| 641 |
+
payload = f"{engine_val}|{fp_val}|{model_ver}|{parent_val}|{created_val}"
|
| 642 |
+
expected_hash = hashlib.sha256(payload.encode()).hexdigest()
|
| 643 |
+
|
| 644 |
+
if lineage.get("lineage_hash") != expected_hash:
|
| 645 |
return False
|
| 646 |
|
| 647 |
+
# اگر به اینجا برسیم، همه چیز ok است
|
| 648 |
return True
|
| 649 |
|
| 650 |
except Exception:
|
| 651 |
return False
|
|
|