test(hololake): validate batch01 bootstrap trust input
This commit is contained in:
parent
df9a26a363
commit
d9600a9e9e
3 changed files with 33 additions and 5 deletions
|
|
@ -4,9 +4,9 @@
|
||||||
"state":"ARCHITECTURE_TOOL_TESTED_NOT_AN_EXIT_OR_ENTRY_RECEIPT",
|
"state":"ARCHITECTURE_TOOL_TESTED_NOT_AN_EXIT_OR_ENTRY_RECEIPT",
|
||||||
"outcome":"PASS",
|
"outcome":"PASS",
|
||||||
"test_count":32,
|
"test_count":32,
|
||||||
"positive":["ARCHITECTURE_EXIT_SHAPE","CONSTRUCTION_ENTRY_SHAPE","CONSTRUCTION_EXIT_SHAPE"],
|
"positive":["ARCHITECTURE_EXIT_SHAPE","CONSTRUCTION_ENTRY_SHAPE","CONSTRUCTION_EXIT_SHAPE","BATCH_02_TO_05_ENTRY_CHAIN","BATCH_01_BOOTSTRAP_PUBLIC_TRUST_POLICY"],
|
||||||
"negative":["MISSING_FIELD","UNKNOWN_FIELD","BAD_SHA256","WELL_FORMED_BUT_WRONG_RECEIPT_SHA256","NAIVE_TIMESTAMP","FUTURE_TIMESTAMP","ARCHITECTURE_PASS_WITH_OPEN_DEFECT","ARCHITECTURE_PASS_WITH_EMPTY_DRAWING_OR_SITE_EVIDENCE","NONEMPTY_BUT_FAKE_ARCHITECTURE_EVIDENCE","UNKNOWN_OR_SELF_INSPECTOR","INSPECTOR_OUTCOME_OR_SOURCE_SET_MISMATCH","RESOLVED_JZAO_PATH_ESCAPE","ARCHITECTURE_REWORK_OPENS_NEXT_BATCH","CONSTRUCTION_REWORK_WITHOUT_ORDER_OR_CLOSED_NEXT_BATCH","REWORK_ORDER_DOES_NOT_MATCH_EXACT_DEFECTS","UNKNOWN_BATCH","EMPTY_ENTRY_EVIDENCE_OR_ASSIGNMENT","ENTRY_ARTIFACT_HASH_MISMATCH","PHASE2_SCOPE_IN_PHASE1_ENTRY","CROSS_BATCH_SCOPE","WRONG_PREVIOUS_EXIT_HASH_OR_DRAWING","TRUNCATED_PREVIOUS_EXIT","CONSTRUCTION_EXIT_ENTRY_CHAIN_TAMPER","WRONG_CREW_FOR_BATCH","UNTRUSTED_ISSUER_ROLE","ENTRY_NOT_OPEN","SELF_GRANTED_AUTHORITY"],
|
"negative":["MISSING_FIELD","UNKNOWN_FIELD","BAD_SHA256","WELL_FORMED_BUT_WRONG_RECEIPT_SHA256","NAIVE_TIMESTAMP","FUTURE_TIMESTAMP","ARCHITECTURE_PASS_WITH_OPEN_DEFECT","ARCHITECTURE_PASS_WITH_EMPTY_DRAWING_OR_SITE_EVIDENCE","NONEMPTY_BUT_FAKE_ARCHITECTURE_EVIDENCE","UNKNOWN_OR_SELF_INSPECTOR","INSPECTOR_OUTCOME_OR_SOURCE_SET_MISMATCH","RESOLVED_JZAO_PATH_ESCAPE","ARCHITECTURE_REWORK_OPENS_NEXT_BATCH","CONSTRUCTION_REWORK_WITHOUT_ORDER_OR_CLOSED_NEXT_BATCH","REWORK_ORDER_DOES_NOT_MATCH_EXACT_DEFECTS","UNKNOWN_BATCH","EMPTY_ENTRY_EVIDENCE_OR_ASSIGNMENT","ENTRY_ARTIFACT_HASH_MISMATCH","PHASE2_SCOPE_IN_PHASE1_ENTRY","CROSS_BATCH_SCOPE","WRONG_PREVIOUS_EXIT_HASH_OR_DRAWING","TRUNCATED_PREVIOUS_EXIT","CONSTRUCTION_EXIT_ENTRY_CHAIN_TAMPER","CONSTRUCTION_EXIT_BATCH_MISMATCH","CONSTRUCTION_INSPECTOR_SOURCE_MISMATCH","BUILDER_ROLE_NOT_RELEASED","WRONG_CREW_FOR_BATCH","EMPTY_CREW_SCOPE","WRONG_FORBIDDEN_ACTIONS","MISSING_BOOTSTRAP_INPUT","UNTRUSTED_ISSUER_ROLE","ENTRY_NOT_OPEN","SELF_GRANTED_AUTHORITY"],
|
||||||
"hashes":{"validator":"537e9507553e9a8549219a066a1654f1cea98398fc0639412a6d3b9f7f70f152","tests":"7cdce696350d3e1bb9ac9e277420758f5babdda9af54b10c87f5a27e502053af","handoff_contract":"91c673c34cb7d9e3bba57949de6246f689a83a8987e0d1cc6b7b9a6bbd39ed0b","foundation_schema":"da16191aeed285379a8e0ad7705b36412d66fc2a965c49442241af0e8b759279"},
|
"hashes":{"validator":"525b12e00ac8a1261a21d437cd79f8f61f87b6e78e30a3619a836e6e37f6ef9e","tests":"64c8243cff43685a60a9e666583e176e9b1a1a7232dd628f30cceeb57e515a5b","handoff_contract":"91c673c34cb7d9e3bba57949de6246f689a83a8987e0d1cc6b7b9a6bbd39ed0b","foundation_schema":"da16191aeed285379a8e0ad7705b36412d66fc2a965c49442241af0e8b759279"},
|
||||||
"receipt_written_by_validator":false,
|
"receipt_written_by_validator":false,
|
||||||
"batch_00_exit_issued":false,
|
"batch_00_exit_issued":false,
|
||||||
"batch_01_entry_issued":false,
|
"batch_01_entry_issued":false,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import argparse
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
@ -37,6 +38,7 @@ ARCHITECTURE_CHARTER = HERE.parents[5] / "runtime/fifth-domain-language-system/l
|
||||||
HANDOFF_TEST_RECEIPT = STAGE1 / "BATCH-00-HANDOFF-VALIDATOR-TEST-RECEIPT.json"
|
HANDOFF_TEST_RECEIPT = STAGE1 / "BATCH-00-HANDOFF-VALIDATOR-TEST-RECEIPT.json"
|
||||||
SELF_SCHEMA_REVIEW_RECEIPT = STAGE1 / "BATCH-00-SELF-OBSERVATION-SCHEMA-REVIEW-RECEIPT.json"
|
SELF_SCHEMA_REVIEW_RECEIPT = STAGE1 / "BATCH-00-SELF-OBSERVATION-SCHEMA-REVIEW-RECEIPT.json"
|
||||||
MOD013_SITE_PROBE_RECEIPT = Path("/Volumes/JZAO/铸渊-ICE-GL-ZY001/CODEX-DEV-20260909/hololake-phase1-persona-container/site-probe/TEST-RECEIPT-001.json")
|
MOD013_SITE_PROBE_RECEIPT = Path("/Volumes/JZAO/铸渊-ICE-GL-ZY001/CODEX-DEV-20260909/hololake-phase1-persona-container/site-probe/TEST-RECEIPT-001.json")
|
||||||
|
BOOTSTRAP_POLICY = Path("/Volumes/JZAO/铸渊-ICE-GL-ZY001/CODEX-DEV-20260909/hololake-phase1-persona-container/batch01-entry/HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001.json")
|
||||||
JZAO_ROOT = Path("/Volumes/JZAO").resolve()
|
JZAO_ROOT = Path("/Volumes/JZAO").resolve()
|
||||||
CONSTRUCTION = STAGE1 / "CONSTRUCTION-SEQUENCE.json"
|
CONSTRUCTION = STAGE1 / "CONSTRUCTION-SEQUENCE.json"
|
||||||
ALLOWED_ISSUER_ROLES = {"ENGINEERING_LEAD"}
|
ALLOWED_ISSUER_ROLES = {"ENGINEERING_LEAD"}
|
||||||
|
|
@ -126,6 +128,30 @@ def verify_previous_exit(item: Any, batch_id: str, expected_sha256: Any) -> list
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def verify_bootstrap_policy(item: Any) -> list[str]:
|
||||||
|
if not isinstance(item, dict): return ["BOOTSTRAP_POLICY_EVIDENCE_MISSING"]
|
||||||
|
try: policy = load(Path(item["path"]))
|
||||||
|
except (OSError, ValueError, json.JSONDecodeError): return ["BOOTSTRAP_POLICY_UNREADABLE"]
|
||||||
|
required = {"schema", "policy_id", "state", "public_source", "signature", "trusted_test_signers", "revocation", "private_key_packaged", "private_payload_bytes", "real_public_policy_required_before_batch01_exit", "policy_sha256", "authority_granted"}
|
||||||
|
errors=[]
|
||||||
|
if set(policy) != required or policy.get("schema") != "hololake.bootstrap-public-trust-policy/v1" or policy.get("policy_id") != "HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001": errors.append("BOOTSTRAP_POLICY_SHAPE_OR_ID_INVALID")
|
||||||
|
candidate=dict(policy); declared=candidate.pop("policy_sha256", None)
|
||||||
|
if declared != hashlib.sha256(json.dumps(candidate,ensure_ascii=False,sort_keys=True,separators=(",",":")).encode()).hexdigest(): errors.append("BOOTSTRAP_POLICY_HASH_MISMATCH")
|
||||||
|
if policy.get("private_key_packaged") is not False or policy.get("private_payload_bytes") != 0 or policy.get("authority_granted") is not False or policy.get("real_public_policy_required_before_batch01_exit") is not True: errors.append("BOOTSTRAP_POLICY_BOUNDARY_INVALID")
|
||||||
|
signers=policy.get("trusted_test_signers")
|
||||||
|
if not isinstance(signers,list) or len({row.get("signer_id") for row in signers if isinstance(row,dict)}) < 2: errors.append("BOOTSTRAP_POLICY_DISTINCT_SIGNERS_MISSING")
|
||||||
|
else:
|
||||||
|
for row in signers:
|
||||||
|
path=Path(str(row.get("public_key_path","")))
|
||||||
|
if not path.is_file() or file_sha256(path)!=row.get("public_key_sha256") or ".private." in path.name: errors.append("BOOTSTRAP_PUBLIC_KEY_INVALID")
|
||||||
|
source=policy.get("public_source",{}); repo=Path(str(source.get("path",""))); commit=str(source.get("git_commit","")); seed=repo/"SEED.json"
|
||||||
|
if not inside(repo,JZAO_ROOT) or not seed.is_file() or file_sha256(seed)!=source.get("seed_sha256") or source.get("real_remote_fetch") is not False: errors.append("BOOTSTRAP_TEST_MIRROR_INVALID")
|
||||||
|
else:
|
||||||
|
check=subprocess.run(["git","-C",str(repo),"cat-file","-e",commit+"^{commit}"],capture_output=True,text=True,timeout=10)
|
||||||
|
if check.returncode: errors.append("BOOTSTRAP_TEST_MIRROR_COMMIT_MISSING")
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
def type_ok(value: Any, expected: Any) -> bool:
|
def type_ok(value: Any, expected: Any) -> bool:
|
||||||
values = expected if isinstance(expected, list) else [expected]
|
values = expected if isinstance(expected, list) else [expected]
|
||||||
mapping = {"object": dict, "array": list, "string": str, "boolean": bool, "null": type(None), "number": (int, float), "integer": int}
|
mapping = {"object": dict, "array": list, "string": str, "boolean": bool, "null": type(None), "number": (int, float), "integer": int}
|
||||||
|
|
@ -254,6 +280,9 @@ def validate(kind: str, receipt: dict[str, Any], now: datetime | None = None) ->
|
||||||
if actual_scopes != planned_scopes: errors.append("CREW_MODULE_SCOPES_DO_NOT_MATCH_PLAN")
|
if actual_scopes != planned_scopes: errors.append("CREW_MODULE_SCOPES_DO_NOT_MATCH_PLAN")
|
||||||
accepted_ids = {item.get("id") for item in receipt.get("accepted_input_artifacts", []) if isinstance(item, dict)}
|
accepted_ids = {item.get("id") for item in receipt.get("accepted_input_artifacts", []) if isinstance(item, dict)}
|
||||||
if accepted_ids != set(batch.get("required_input_ids", [])): errors.append("REQUIRED_BATCH_INPUT_SET_MISMATCH")
|
if accepted_ids != set(batch.get("required_input_ids", [])): errors.append("REQUIRED_BATCH_INPUT_SET_MISMATCH")
|
||||||
|
if receipt.get("batch_id") == "HLP-BATCH-01":
|
||||||
|
bootstrap = next((item for item in receipt.get("accepted_input_artifacts", []) if isinstance(item,dict) and item.get("id") == "HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001"), None)
|
||||||
|
errors.extend(verify_bootstrap_policy(bootstrap))
|
||||||
if set(receipt.get("forbidden_actions", [])) != set(batch.get("mandatory_forbidden_actions", [])): errors.append("MANDATORY_FORBIDDEN_ACTIONS_MISMATCH")
|
if set(receipt.get("forbidden_actions", [])) != set(batch.get("mandatory_forbidden_actions", [])): errors.append("MANDATORY_FORBIDDEN_ACTIONS_MISMATCH")
|
||||||
if receipt.get("batch_id") == "HLP-BATCH-01":
|
if receipt.get("batch_id") == "HLP-BATCH-01":
|
||||||
drawing = ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"]
|
drawing = ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"]
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,7 @@ def entry():
|
||||||
previous_path=EVIDENCE_ROOT/"previous-architecture-exit.json"
|
previous_path=EVIDENCE_ROOT/"previous-architecture-exit.json"
|
||||||
previous=architecture(); previous_path.write_text(json.dumps(previous,sort_keys=True,separators=(",",":")))
|
previous=architecture(); previous_path.write_text(json.dumps(previous,sort_keys=True,separators=(",",":")))
|
||||||
previous_evidence=evidence("HLP-BATCH-00-EXIT",previous_path,"PASS")
|
previous_evidence=evidence("HLP-BATCH-00-EXIT",previous_path,"PASS")
|
||||||
policy_path=EVIDENCE_ROOT/"bootstrap-policy.json"; policy_path.write_text('{"policy_id":"HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001","state":"TEST_ONLY"}')
|
accepted=[previous_evidence,evidence("HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001",MODULE.BOOTSTRAP_POLICY),evidence("HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001",MODULE.SITE_SURVEY),evidence("HLP-BATCH-00-FOUNDATION-DRAWINGS-001",MODULE.ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"])]
|
||||||
accepted=[previous_evidence,evidence("HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001",policy_path),evidence("HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001",MODULE.SITE_SURVEY),evidence("HLP-BATCH-00-FOUNDATION-DRAWINGS-001",MODULE.ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"])]
|
|
||||||
forbidden=["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"]
|
forbidden=["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"]
|
||||||
return seal({"schema":"hololake.construction-batch-entry/v1","receipt_id":"R-ENTRY-001","batch_id":"HLP-BATCH-01","previous_batch_exit_receipt_sha256":previous_evidence["sha256"],"previous_batch_exit_receipt":previous_evidence,"construction_drawing_id":"HLP-BATCH-00-FOUNDATION-DRAWINGS-001","construction_drawing_sha256":MODULE.file_sha256(MODULE.ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"]),"accepted_input_artifacts":accepted,"crew_admissions":[{"development_id":"HLP-TDEV-CODEX-0001","role":"BUILDER","scope":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"]},{"development_id":"HLP-TDEV-ZCODE-0001","role":"BUILDER","scope":["HLP-NATIVE-MOD-002"]}],"inspector_assignment":{"inspector_id":"CODEX-CHILD-BATCH01","mode":"READ_ONLY_NO_PRODUCTION_WRITE"},"scope":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-002","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"],"forbidden_actions":forbidden,"issued_by_role":"ENGINEERING_LEAD","issued_at":AT,"state":"ENTRY_OPEN","authority_granted":False})
|
return seal({"schema":"hololake.construction-batch-entry/v1","receipt_id":"R-ENTRY-001","batch_id":"HLP-BATCH-01","previous_batch_exit_receipt_sha256":previous_evidence["sha256"],"previous_batch_exit_receipt":previous_evidence,"construction_drawing_id":"HLP-BATCH-00-FOUNDATION-DRAWINGS-001","construction_drawing_sha256":MODULE.file_sha256(MODULE.ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"]),"accepted_input_artifacts":accepted,"crew_admissions":[{"development_id":"HLP-TDEV-CODEX-0001","role":"BUILDER","scope":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"]},{"development_id":"HLP-TDEV-ZCODE-0001","role":"BUILDER","scope":["HLP-NATIVE-MOD-002"]}],"inspector_assignment":{"inspector_id":"CODEX-CHILD-BATCH01","mode":"READ_ONLY_NO_PRODUCTION_WRITE"},"scope":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-002","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"],"forbidden_actions":forbidden,"issued_by_role":"ENGINEERING_LEAD","issued_at":AT,"state":"ENTRY_OPEN","authority_granted":False})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue