Publish Chimera GFX source
phase0-ci / build-and-audit (push) Successful in 2m14s

This commit is contained in:
Chimera GFX release export
2026-09-03 03:27:14 +02:00
commit a6037502d7
828 changed files with 100454 additions and 0 deletions
+390
View File
@@ -0,0 +1,390 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Generate deterministic Phase-0.7 static ELF evidence without execution."""
from __future__ import annotations
import argparse
import hashlib
import json
import re
import subprocess
from pathlib import Path
from typing import Any
EXPECTED_COMMITS = {
"lifecycle": "fe08300339a13f899fb78ea404ada381a5cba87c",
"loader": "197623058f509eddde18868dafcb92fdcac66464",
"manager": "e23d94ff91233aa770e2342800c1467875bdef44",
}
EXPECTED_HASHES = {
"lifecycle": "bfb4a5cc768e162fe4c2fddf41c3978e152722918a39085277fd172cb95a7182",
"loader": "63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561",
"manager": "8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1",
}
EXPECTED_SIZES = {"lifecycle": 112680, "loader": 397000, "manager": 99560}
LIFECYCLE_IMPORTS = {"_exit", "sceKernelSendNotificationRequest"}
LIFECYCLE_NEEDED = {"libSceLibcInternal.sprx", "libkernel_web.sprx"}
LIFECYCLE_FORBIDDEN = re.compile(
r"(sceGnm|VideoOut|SDL_|sceNet|socket|connect|dlopen|dlsym|"
r"kernel_copyin|kernel_copyout|kernel_set_ucred|__patch_init)"
)
SENSITIVE_CATEGORIES = {
"dynamic_loading": re.compile(
r"(^|_)(dlopen|dlsym)$|^__(dlopen|dlsym)$|dynlib|"
r"LoadStartModule|StopUnloadModule"
),
"graphics_or_display": re.compile(
r"sceGnm|[Vv]ideoOut|SDL_|[Gg]pu|[Mm][Mm][Ii][Oo]"
),
"kernel_runtime_write": re.compile(
r"__patch_init|kernel_copy(in|out)|kernel_set_ucred|"
r"kernel_overlap_sockets|syscall.*(patch|set)|"
r"(patch|set).*syscall"
),
"network": re.compile(r"(^|_)(socket|connect|listen|accept)$|sceNet"),
"ptrace_or_jit": re.compile(r"ptrace|PT_[A-Z]|[Jj][Ii][Tt]"),
}
def sha256_bytes(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def sha256_file(path: Path) -> str:
return sha256_bytes(path.read_bytes())
def run(command: list[str]) -> str:
result = subprocess.run(
command,
check=True,
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
)
return result.stdout.replace("\r\n", "\n")
def git_head(path: Path, expected: str, lifecycle_source: bool = False) -> str:
git = [
"git",
"-c",
"core.autocrlf=true",
"-c",
"core.fileMode=false",
"-C",
str(path),
]
head = run([*git, "rev-parse", "HEAD"]).strip()
if lifecycle_source:
subprocess.run(
[*git, "merge-base", "--is-ancestor", expected, head],
check=True,
)
changed = subprocess.run(
[
*git,
"diff",
"--quiet",
expected,
"--",
"samples/lifecycle_probe/main.c",
],
check=False,
)
if changed.returncode != 0:
raise ValueError(f"{path}: lifecycle source differs from {expected}")
return expected
if head != expected:
raise ValueError(f"{path}: expected {expected}, got {head}")
if run([*git, "status", "--porcelain"]):
raise ValueError(f"{path}: source tree is dirty")
return head
def parse_undefined(symbols: str) -> list[str]:
imports: set[str] = set()
for line in symbols.splitlines():
match = re.search(r"\bU\s+(\S+)\s*$", line)
if match:
imports.add(match.group(1))
return sorted(imports)
def parse_needed(dynamic: str) -> list[str]:
return sorted(set(re.findall(r"Shared library: \[([^\]]+)\]", dynamic)))
def parse_callgraph(disassembly: str) -> list[dict[str, Any]]:
current = "<outside-symbol>"
edges: list[dict[str, Any]] = []
for line in disassembly.splitlines():
function = re.match(r"^[0-9a-fA-F]+\s+<([^>]+)>:$", line)
if function:
current = function.group(1)
continue
call = re.match(
r"^\s*([0-9a-fA-F]+):.*\bcallq?\b\s+(.+?)\s*$", line
)
if not call:
continue
operand = call.group(2).strip()
target_match = re.search(r"<([^>]+)>", operand)
edges.append(
{
"address": f"0x{call.group(1).lower()}",
"from": current,
"indirect": "*" in operand or target_match is None,
"target": target_match.group(1) if target_match else operand,
}
)
return edges
def function_name(name: str) -> str:
return re.sub(r"\+0x[0-9a-fA-F]+$", "", name)
def defined_functions(disassembly: str) -> set[str]:
return {
match.group(1)
for match in re.finditer(
r"^[0-9a-fA-F]+\s+<([^>]+)>:$", disassembly, re.MULTILINE
)
}
def map_symbols(linker_map: str) -> set[str]:
symbols = set()
pattern = re.compile(
r"^\s*[0-9a-fA-F]+\s+[0-9a-fA-F]+\s+[0-9a-fA-F]+"
r"\s+\d+\s+([A-Za-z_][A-Za-z0-9_.$@]*)\s*$"
)
for line in linker_map.splitlines():
match = pattern.match(line)
if match:
symbols.add(match.group(1))
return symbols
def direct_reachable(
callgraph: list[dict[str, Any]], entrypoint: str
) -> set[str]:
adjacency: dict[str, set[str]] = {}
for edge in callgraph:
if edge["indirect"]:
continue
source = function_name(edge["from"])
target = function_name(edge["target"])
adjacency.setdefault(source, set()).add(target)
reachable = {entrypoint}
pending = [entrypoint]
while pending:
source = pending.pop()
for target in adjacency.get(source, set()):
if target not in reachable:
reachable.add(target)
pending.append(target)
return reachable
def sensitive_inventory(
disassembly: str,
linker_map: str,
callgraph: list[dict[str, Any]],
entrypoint: str,
) -> dict[str, Any]:
defined = defined_functions(disassembly)
mapped = map_symbols(linker_map)
reachable = direct_reachable(callgraph, entrypoint)
categories = {}
for category, pattern in SENSITIVE_CATEGORIES.items():
disassembly_linked = sorted(
name for name in defined if pattern.search(name)
)
map_linked = sorted(name for name in mapped if pattern.search(name))
categories[category] = {
"directly_reachable_from_entrypoint": sorted(
name for name in disassembly_linked if name in reachable
),
"linked": sorted(set(disassembly_linked) | set(map_linked)),
"linked_in_disassembly": disassembly_linked,
"linked_in_linker_map": map_linked,
}
return {
"categories": categories,
"direct_call_reachability_available": entrypoint in defined,
"direct_call_reachability_only": True,
"entrypoint": entrypoint,
"indirect_call_edges_retained_but_not_resolved": sum(
1 for edge in callgraph if edge["indirect"]
),
}
def normalize_map(data: str) -> str:
return re.sub(
r"/tmp/([A-Za-z0-9_]+)-[0-9a-f]{6}\.o",
r"/tmp/\1-<deterministic-temp>.o",
data.replace("\r\n", "\n"),
)
def analyze(
*,
name: str,
first: Path,
second: Path,
map_path: Path,
nm: Path,
readelf: Path,
objdump: Path,
output: Path,
) -> dict[str, Any]:
first_bytes = first.read_bytes()
second_bytes = second.read_bytes()
if first_bytes != second_bytes:
raise ValueError(f"{name}: the two clean builds are not byte-identical")
digest = sha256_bytes(first_bytes)
if digest != EXPECTED_HASHES[name] or len(first_bytes) != EXPECTED_SIZES[name]:
raise ValueError(f"{name}: identity differs from the reviewed profile")
dynamic = run([str(readelf), "-d", str(first)])
symbols = run([str(nm), "-u", str(first)])
headers = run([str(readelf), "-h", "-l", "-S", str(first)])
relocations = run([str(readelf), "-r", str(first)])
all_symbols = run([str(readelf), "-Ws", str(first)])
disassembly = run([str(objdump), "-d", str(first)])
callgraph = parse_callgraph(disassembly)
normalized_map = normalize_map(map_path.read_text(encoding="utf-8"))
sensitive = sensitive_inventory(
disassembly, normalized_map, callgraph, "_start"
)
reports = {
"callgraph": json.dumps(callgraph, indent=2, sort_keys=True) + "\n",
"disassembly": disassembly,
"dynamic": dynamic,
"headers_sections": headers,
"linker_map_normalized": normalized_map,
"relocations": relocations,
"symbols": all_symbols,
"undefined": symbols,
}
report_hashes: dict[str, str] = {}
for report_name, content in reports.items():
report_path = output / f"{name}.{report_name}.txt"
report_path.write_text(content, encoding="utf-8", newline="\n")
report_hashes[report_name] = sha256_file(report_path)
imports = parse_undefined(symbols)
needed = parse_needed(dynamic)
if name == "lifecycle":
if set(imports) != LIFECYCLE_IMPORTS:
raise ValueError(f"lifecycle: unexpected imports {imports}")
if set(needed) != LIFECYCLE_NEEDED:
raise ValueError(f"lifecycle: unexpected DT_NEEDED {needed}")
forbidden_matches = sorted(set(LIFECYCLE_FORBIDDEN.findall(symbols)))
if forbidden_matches:
raise ValueError(f"lifecycle: forbidden import {forbidden_matches}")
if b"phase07-fw960-v1" not in first_bytes or b"9.60" not in first_bytes:
raise ValueError("lifecycle: firmware/build gates are absent")
return {
"byte_identical_clean_builds": True,
"call_edges": callgraph,
"dt_needed": needed,
"filename": first.name,
"imports": imports,
"report_sha256": report_hashes,
"sensitive_static_inventory": sensitive,
"sha256": digest,
"size": len(first_bytes),
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--loader-source", type=Path, required=True)
parser.add_argument("--manager-source", type=Path, required=True)
parser.add_argument("--artifact-dir", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--manifest-output", type=Path, required=True)
parser.add_argument("--nm", type=Path, required=True)
parser.add_argument("--readelf", type=Path, required=True)
parser.add_argument("--objdump", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
sources = {
"lifecycle": root,
"loader": args.loader_source.resolve(),
"manager": args.manager_source.resolve(),
}
source_commits = {
name: git_head(
path, EXPECTED_COMMITS[name], lifecycle_source=name == "lifecycle"
)
for name, path in sources.items()
}
artifact_dir = args.artifact_dir.resolve()
output = args.output.resolve()
output.mkdir(parents=True, exist_ok=True)
artifacts: dict[str, Any] = {}
for name, stem in {
"lifecycle": "chimera-gfx-lifecycle-probe-phase07",
"loader": "chimera-elfldr-phase07",
"manager": "chimera-pldmgr-phase07",
}.items():
artifacts[name] = analyze(
name=name,
first=artifact_dir / f"{stem}-a.elf",
second=artifact_dir / f"{stem}-b.elf",
map_path=artifact_dir / f"{stem}-b.map",
nm=args.nm.resolve(strict=True),
readelf=args.readelf.resolve(strict=True),
objdump=args.objdump.resolve(strict=True),
output=output,
)
document = {
"schema_version": 1,
"decision": "READY_FOR_HARDENED_RUNTIME_DEPLOYMENT",
"firmware": "9.60",
"offline_only": True,
"ps5_actions": {
"connected": False,
"installed": False,
"transferred": False,
"executed": False,
},
"source_commits": source_commits,
"artifacts": artifacts,
"forbidden_lifecycle_imports": [],
"permanent_denylist_sha256": (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
),
}
machine_output = output / "phase-0.7-offline-audit.json"
content = json.dumps(document, indent=2, sort_keys=True) + "\n"
machine_output.write_text(content, encoding="utf-8", newline="\n")
args.manifest_output.resolve().write_text(
content, encoding="utf-8", newline="\n"
)
print(
"Phase-0.7 audit passed: three byte-identical ELF pairs, exact "
"firmware 9.60 lifecycle imports, and no PS5 action"
)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (OSError, subprocess.CalledProcessError, ValueError) as error:
print(f"Phase-0.7 artifact audit failed: {error}")
raise SystemExit(1) from error
+135
View File
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Conservative source/build audit for the Phase-0 non-rendering boundary."""
from __future__ import annotations
import argparse
import json
import re
from pathlib import Path
FORBIDDEN_CALLS = (
r"\bsceGnm[A-Za-z0-9_]*\s*\(",
r"\bsceVideoOutSubmitFlip\s*\(",
r"\b(mmap|mprotect|ioctl)\s*\(",
)
FORBIDDEN_TERMS = (
"MMIO",
"SCE_PROSPERO_SDK_DIR", # should exist only in the external SDK, not project code
"smu_",
"fan_control",
"clock_boost",
)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
errors: list[str] = []
phase0_sources = (
sorted((root / "src").rglob("*.c"))
+ sorted((root / "adapters").rglob("*.c"))
+ sorted((root / "samples/capability_probe").rglob("*.c"))
)
all_sources = phase0_sources + sorted(
(root / "samples/phase1_videoout_clear").rglob("*.c")
)
combined = "\n".join(path.read_text(encoding="utf-8") for path in all_sources)
for pattern in FORBIDDEN_CALLS:
if re.search(pattern, combined):
errors.append(f"forbidden Phase-0 call expression matched: {pattern}")
for term in FORBIDDEN_TERMS:
if term.lower() in combined.lower():
errors.append(f"forbidden Phase-0 implementation term: {term}")
platform = (root / "src/backends/ps5/probe_platform.c").read_text(encoding="utf-8")
if platform.count("dlsym(") != 1:
errors.append("PS5 loader must contain exactly one dlsym call site")
if "address = dlsym(" not in platform or "address = NULL;" not in platform:
errors.append("resolved address must be local and explicitly discarded")
if re.search(r"\([^\n;]*\(\s*\*[^)]*\)\s*\)\s*dlsym", platform):
errors.append("dlsym result is cast to a callable function pointer")
if "fprintf" in platform or "%p" in combined:
errors.append("platform shim must not log addresses or loader details")
cmake = (root / "CMakeLists.txt").read_text(encoding="utf-8")
for term in ("prospero-deploy", "PS5_HOST", "PS5_PORT", "add_custom_target(deploy",
"add_custom_target(upload", "add_custom_target(run"):
if term.lower() in cmake.lower():
errors.append(f"deployment behavior in build graph: {term}")
if 'set(CHIMERA_GFX_PS5_ALLOWED_FIRMWARE "NONE"' not in cmake:
errors.append("default firmware gate is not NONE")
if 'option(CHIMERA_GFX_BUILD_PHASE1_VIDEOOUT_CLEAR' not in cmake:
errors.append("Phase-1 candidate does not have an explicit build gate")
if 'option(CHIMERA_GFX_BUILD_PS5_MINIMAL_STARTUP' not in cmake:
errors.append("Phase-0.5 minimal startup lacks an explicit build gate")
if "no minimal PS5 ELF may be built" not in cmake:
errors.append("Phase-0.5 minimal startup is not explicitly blocked")
phase1 = (root / "samples/phase1_videoout_clear/main.c").read_text(
encoding="utf-8"
)
gate_position = phase1.find("if (!chimera_gfx_firmware_gate_allows(")
init_position = phase1.find("SDL_Init(SDL_INIT_VIDEO)")
present_position = phase1.find("SDL_UpdateWindowSurface(window)")
if min(gate_position, init_position, present_position) < 0:
errors.append("Phase-1 source is missing its reviewed gate/init/present sequence")
elif not gate_position < init_position < present_position:
errors.append("Phase-1 firmware gate must precede SDL init and present")
if "SDL2main" in cmake:
errors.append("Phase-1 target must not link the pre-gate SDL2main wrapper")
if any((root / "samples/clear_screen").rglob("*.c")):
errors.append("legacy clear-screen placeholder unexpectedly contains source")
compatibility = (root / "FIRMWARE_COMPATIBILITY.md").read_text(encoding="utf-8")
if "| _none_ |" not in compatibility or "| `9.60` |" not in compatibility:
errors.append("firmware compatibility table lacks NONE or exact 9.60 rows")
if '"firmware_allowlist": ["9.60"]' not in (
root / "manifests/ps5_gnm_symbols.json"
).read_text(encoding="utf-8"):
errors.append("discovery-only firmware allowlist is not exactly 9.60")
denylist = json.loads(
(root / "manifests/artifact-denylist.json").read_text(encoding="utf-8")
)
blocked_hash = (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
)
entries = denylist.get("entries", [])
if len(entries) != 1 or entries[0].get("sha256") != blocked_hash:
errors.append("permanent firmware-9.60 artifact denial is absent")
elif (
entries[0].get("permanent") is not True
or entries[0].get("execution_eligible") is not False
):
errors.append("firmware-9.60 artifact denial is not permanent and ineligible")
artifact_manifest = json.loads(
(
root
/ "manifests/artifacts/chimera-gfx-capability-probe-0.1.0-fw-9.60.json"
).read_text(encoding="utf-8")
)
if artifact_manifest["execution"].get("execution_eligible") is not False:
errors.append("firmware-9.60 artifact manifest is not execution-ineligible")
if errors:
for error in errors:
print(f"safety audit failed: {error}")
return 1
print(
f"Phase-0/disabled-Phase-1 safety audit passed across "
f"{len(all_sources)} C source files"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+225
View File
@@ -0,0 +1,225 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Statically audit the fail-closed PS5 ELFs without executing them."""
from __future__ import annotations
import argparse
import json
import re
import subprocess
from pathlib import Path
EXPECTED_PHASE1_SCE_IMPORTS = {
"sceKernelAllocateMainDirectMemory",
"sceKernelCreateEqueue",
"sceKernelDeleteEqueue",
"sceKernelMapDirectMemory",
"sceKernelReleaseDirectMemory",
"sceKernelWaitEqueue",
"sceSystemServiceHideSplashScreen",
"sceVideoOutAddFlipEvent",
"sceVideoOutClose",
"sceVideoOutDeleteFlipEvent",
"sceVideoOutOpen",
"sceVideoOutRegisterBuffers2",
"sceVideoOutSetBufferAttribute2",
"sceVideoOutSetFlipRate",
"sceVideoOutSubmitFlip",
}
EXPECTED_PROBE_UNDEFINED_IMPORTS = {
"__stderrp",
"__stdoutp",
"fprintf",
"fwrite",
"snprintf",
"strcmp",
}
EXPECTED_PROBE_NEEDED = {
"libkernel_web.sprx",
"libSceLibcInternal.sprx",
"libSceNet.sprx",
}
def run_nm(nm: Path, artifact: Path, undefined_only: bool) -> str:
command = [str(nm)]
command.append("-u" if undefined_only else "-a")
command.append(str(artifact))
result = subprocess.run(command, check=True, capture_output=True, text=True)
return result.stdout
def run_readelf(readelf: Path, artifact: Path) -> str:
result = subprocess.run(
[str(readelf), "--dynamic-table", str(artifact)],
check=True,
capture_output=True,
text=True,
)
return result.stdout
def extract_sce_imports(undefined_symbols: str) -> set[str]:
imports: set[str] = set()
for line in undefined_symbols.splitlines():
match = re.search(r"\bU\s+(sce[A-Za-z0-9_]+)\s*$", line)
if match is not None:
imports.add(match.group(1))
return imports
def extract_undefined_imports(undefined_symbols: str) -> set[str]:
imports: set[str] = set()
for line in undefined_symbols.splitlines():
match = re.search(r"\bU\s+(\S+)\s*$", line)
if match is not None:
imports.add(match.group(1))
return imports
def extract_needed(dynamic_table: str) -> set[str]:
return set(re.findall(r"Shared library: \[([^\]]+)\]", dynamic_table))
def require_symbols(symbols: str, names: set[str], artifact: Path) -> None:
missing = sorted(name for name in names if name not in symbols)
if missing:
raise ValueError(f"{artifact.name}: missing retained symbols: {', '.join(missing)}")
def require_bytes(artifact: Path, values: set[bytes]) -> None:
content = artifact.read_bytes()
missing = sorted(value.decode("ascii") for value in values if value not in content)
if missing:
raise ValueError(f"{artifact.name}: missing gate strings: {', '.join(missing)}")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--nm", type=Path, required=True)
parser.add_argument("--readelf", type=Path, required=True)
parser.add_argument("--probe", type=Path, required=True)
parser.add_argument("--symbol-manifest", type=Path, required=True)
parser.add_argument("--phase1", type=Path)
parser.add_argument("--firmware", default="NONE")
args = parser.parse_args()
nm = args.nm.resolve(strict=True)
readelf = args.readelf.resolve(strict=True)
probe = args.probe.resolve(strict=True)
symbol_manifest = json.loads(
args.symbol_manifest.read_text(encoding="utf-8")
)
probe_undefined = run_nm(nm, probe, undefined_only=True)
probe_all_imports = extract_undefined_imports(probe_undefined)
probe_imports = extract_sce_imports(probe_undefined)
if probe_imports:
raise ValueError(
f"{probe.name}: unexpected direct Sce imports: "
f"{', '.join(sorted(probe_imports))}"
)
if probe_all_imports != EXPECTED_PROBE_UNDEFINED_IMPORTS:
missing = sorted(EXPECTED_PROBE_UNDEFINED_IMPORTS - probe_all_imports)
unexpected = sorted(probe_all_imports - EXPECTED_PROBE_UNDEFINED_IMPORTS)
raise ValueError(
f"{probe.name}: undefined import inventory changed; "
f"missing={missing}, unexpected={unexpected}"
)
dynamic_table = run_readelf(readelf, probe)
needed = extract_needed(dynamic_table)
if needed != EXPECTED_PROBE_NEEDED:
missing = sorted(EXPECTED_PROBE_NEEDED - needed)
unexpected = sorted(needed - EXPECTED_PROBE_NEEDED)
raise ValueError(
f"{probe.name}: DT_NEEDED inventory changed; "
f"missing={missing}, unexpected={unexpected}"
)
for array in ("INIT_ARRAYSZ", "FINI_ARRAYSZ"):
if not re.search(
rf"(?:\({array}\)|{array})\s+0 \(bytes\)", dynamic_table
):
raise ValueError(f"{probe.name}: {array} is not empty")
require_symbols(
run_nm(nm, probe, undefined_only=False),
{
"chimera_gfx_firmware_gate_allows",
"chimera_gfx_ps5_make_loader_ops",
"chimera_gfx_ps5_probe_symbols",
"dlclose",
"dlopen",
"dlsym",
},
probe,
)
require_bytes(
probe,
{
args.firmware.encode("ascii"),
b"--acknowledge-read-only-probe",
b"firmware is not allowlisted",
b"libSceGnmDriver.sprx",
}
| {
entry["name"].encode("ascii")
for entry in symbol_manifest["symbols"]
},
)
if args.phase1 is not None:
phase1 = args.phase1.resolve(strict=True)
phase1_undefined = run_nm(nm, phase1, undefined_only=True)
phase1_imports = extract_sce_imports(phase1_undefined)
if phase1_imports != EXPECTED_PHASE1_SCE_IMPORTS:
missing = sorted(EXPECTED_PHASE1_SCE_IMPORTS - phase1_imports)
unexpected = sorted(phase1_imports - EXPECTED_PHASE1_SCE_IMPORTS)
raise ValueError(
f"{phase1.name}: Sce import inventory changed; "
f"missing={missing}, unexpected={unexpected}"
)
if any(name.startswith("sceGnm") for name in phase1_imports):
raise ValueError(f"{phase1.name}: direct GNM import detected")
require_symbols(
run_nm(nm, phase1, undefined_only=False),
{
"chimera_gfx_firmware_gate_allows",
"SDL_Init",
"SDL_UpdateWindowSurface",
},
phase1,
)
require_bytes(
phase1,
{
args.firmware.encode("ascii"),
b"--acknowledge-phase1-videoout-clear",
b"firmware is not allowlisted",
},
)
print(
"PS5 artifact audit passed: probe has exactly 6 reviewed undefined "
"imports, 3 reviewed DT_NEEDED modules, empty init/fini arrays, and "
f"0 direct Sce imports; Phase-1 has {len(phase1_imports)} reviewed "
"Sce imports and 0 GNM imports"
)
else:
print(
"PS5 artifact audit passed: probe has exactly 6 reviewed undefined "
"imports, 3 reviewed DT_NEEDED modules, empty init/fini arrays, all "
"manifest names, and 0 direct Sce/GNM imports"
)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (OSError, subprocess.CalledProcessError, ValueError, json.JSONDecodeError,
KeyError, TypeError) as error:
print(f"PS5 artifact audit failed: {error}")
raise SystemExit(1) from error
+573
View File
@@ -0,0 +1,573 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Generate the exact Phase-0.6 PS5 loader/runtime audit without execution."""
from __future__ import annotations
import argparse
import hashlib
import json
import re
import subprocess
from pathlib import Path
from typing import Any
ELFLDR_COMMIT = "699e8bcff03e91e8d6ca6eba281af25c5a58d8c2"
ELFLDR_SHA256 = "092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8"
ELFLDR_SIZE = 397000
PLDMGR_COMMIT = "cfbc70f30f419b09bf2b52283f7409e2d3117ee1"
PLDMGR_SHA256 = "518740adbacccb9094fadb07dd424c53ee290f38306449ccc9d6957fdf813c0b"
SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37"
def digest_bytes(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def digest_file(path: Path) -> str:
return digest_bytes(path.read_bytes())
def run(command: list[str]) -> str:
result = subprocess.run(
command,
check=True,
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
)
return result.stdout.replace("\r\n", "\n")
def git_identity(path: Path, expected: str) -> dict[str, Any]:
git = ["git", "-c", "core.autocrlf=true", "-C", str(path)]
commit = run([*git, "rev-parse", "HEAD"]).strip()
if commit != expected:
raise ValueError(f"{path}: expected commit {expected}, got {commit}")
status = run([*git, "status", "--porcelain"])
if status:
raise ValueError(f"{path}: source checkout is dirty")
return {"commit": commit, "dirty": False}
def source_record(root: Path, path: Path) -> dict[str, Any]:
data = path.read_bytes().replace(b"\r\n", b"\n")
return {
"normalization": "lf",
"path": path.relative_to(root).as_posix(),
"sha256": digest_bytes(data),
"size": len(data),
}
def require_tokens(path: Path, tokens: list[str]) -> None:
text = path.read_text(encoding="utf-8")
missing = [token for token in tokens if token not in text]
if missing:
raise ValueError(f"{path}: required evidence missing: {missing}")
def parse_binary(readelf_output: str, disassembly: str) -> dict[str, Any]:
entry_match = re.search(r"Entry point address:\s+(0x[0-9a-f]+)", readelf_output)
relocation_match = re.search(
r"Relocation section '\.rela\.dyn'.*contains (\d+) entries",
readelf_output,
)
relative_match = re.search(r"\(RELACOUNT\)\s+(\d+)", readelf_output)
if entry_match is None or relocation_match is None or relative_match is None:
raise ValueError("readelf output lacks required header/relocation evidence")
needed = sorted(re.findall(r"\(NEEDED\).*\[([^\]]+)\]", readelf_output))
dynsym_match = re.search(
r"Symbol table '\.dynsym'.*?\n(?P<body>.*?)(?:\nSymbol table|\Z)",
readelf_output,
flags=re.DOTALL,
)
if dynsym_match is None:
raise ValueError("readelf output lacks .dynsym")
undefined: list[str] = []
for line in dynsym_match.group("body").splitlines():
match = re.search(r"\bUND\s+(\S+)\s*$", line)
if match and match.group(1):
undefined.append(match.group(1))
array_sizes: dict[str, int] = {}
for name in ("PREINIT_ARRAY", "INIT_ARRAY", "FINI_ARRAY"):
match = re.search(rf"\({name}SZ\)\s+(\d+)", readelf_output)
if match is None:
raise ValueError(f"readelf output lacks {name}SZ")
array_sizes[name.lower()] = int(match.group(1))
load_segments = []
for line in readelf_output.splitlines():
match = re.match(
r"\s*LOAD\s+\S+\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+([RWE ]+)\s+\S+",
line,
)
if match:
load_segments.append(
{
"file_size": int(match.group(1), 16),
"memory_size": int(match.group(2), 16),
"permissions": match.group(3).replace(" ", ""),
}
)
return {
"disassembly_sha256": digest_bytes(disassembly.encode("utf-8")),
"dt_needed": needed,
"entry_point": entry_match.group(1),
"init_fini_array_sizes": array_sizes,
"load_segments": load_segments,
"readelf_report_sha256": digest_bytes(readelf_output.encode("utf-8")),
"relocations": {
"relative": int(relative_match.group(1)),
"total": int(relocation_match.group(1)),
},
"tls_present": bool(
re.search(r"^\s*TLS\s", readelf_output, flags=re.MULTILINE)
or re.search(r"\.(?:tdata|tbss)\b", readelf_output)
),
"undefined_dynamic_symbols": sorted(undefined),
}
def effect(
effect_id: str,
classification: str,
scope: str,
evidence: list[str],
blocker: bool,
) -> dict[str, Any]:
return {
"blocker": blocker,
"classification": classification,
"evidence": evidence,
"id": effect_id,
"scope": scope,
}
def build_audit(args: argparse.Namespace) -> dict[str, Any]:
root = args.root.resolve()
loader_source = args.loader_source.resolve()
manager_source = args.payload_manager_source.resolve()
sdk_source = args.sdk_source.resolve()
asset = args.loader_asset.resolve()
loader_git = git_identity(loader_source, ELFLDR_COMMIT)
manager_git = git_identity(manager_source, PLDMGR_COMMIT)
sdk_git = git_identity(sdk_source, SDK_COMMIT)
if asset.stat().st_size != ELFLDR_SIZE or digest_file(asset) != ELFLDR_SHA256:
raise ValueError("elfldr release asset identity mismatch")
loader_files = [
loader_source / name
for name in ("main.c", "elfldr.c", "elfldr.h", "pt.c", "pt.h", "socksrv.c", "Makefile")
]
manager_files = [
manager_source / name
for name in (
"src/ps5_launcher.c",
"src/http_server.c",
"src/autoload.c",
"src/main.c",
"src/payload_mgr.c",
"include/pldmgr.h",
"Makefile",
)
]
sdk_files = [
sdk_source / name
for name in (
"crt/crt.c",
"crt/patch.c",
"crt/kernel.c",
"include/ps5/payload.h",
"crt/Makefile",
)
]
require_tokens(
loader_source / "elfldr.c",
[
"rfork_thread(RFPROC | RFCFDG | RFMEM",
"execve(SceSpZeroConf, argv, 0)",
"pt_setlong(pid, r.r_rsp-8, r.r_rip)",
"r.r_rip = entry",
"r.r_rdi = args",
"kernel_overlap_sockets",
"kernel_set_ucred_uid(pid, 0)",
"pt_detach(pid, 0)",
],
)
require_tokens(
loader_source / "pt.c",
[
"kernel_set_ucred_authid(mypid, 0x4800000000010003l)",
"kernel_set_ucred_authid(mypid, authid)",
"while(jmp_reg.r_rsp <= bak_reg.r_rsp)",
],
)
require_tokens(
loader_source / "main.c",
["kernel_set_qaflags(qa_flags)", "elfldr_raise_privileges(mypid)"],
)
require_tokens(
loader_source / "socksrv.c",
["signal(SIGCHLD, SIG_IGN)", "while(1)", "serve_elfldr(port)"],
)
require_tokens(
manager_source / "src/ps5_launcher.c",
['server_addr.sin_addr.s_addr = inet_addr("127.0.0.1")', "send(sock"],
)
require_tokens(
manager_source / "src/http_server.c",
[
"ps5_launch_elf(final_path)",
"fopen(path, \"wb\")",
"payload_mgr_import_to_storage",
],
)
require_tokens(
sdk_source / "crt/crt.c",
["__patch_init()", "payload_terminate(void)", "_start(payload_args_t *args)"],
)
readelf_output = run(
[
str(args.readelf),
"-h",
"-l",
"-S",
"-d",
"-r",
"-s",
"-W",
str(asset),
]
)
disassembly = run(
[str(args.objdump), "-d", "--no-show-raw-insn", str(asset)]
)
binary = parse_binary(readelf_output, disassembly)
effects = [
effect(
"elfldr_first_stage_qaflags_enable",
"EXPECTED_VOLATILE_RUNTIME_EFFECT",
"existing_loader_bootstrap",
["elfldr/main.c:48-59"],
False,
),
effect(
"elfldr_first_stage_privilege_restore",
"UNBOUNDED_OR_UNKNOWN",
"existing_exploit_host_process",
[
"elfldr/main.c:61-105 restores jail/root/caps/authid",
"UID is changed by elfldr_raise_privileges but is not backed up or restored",
],
True,
),
effect(
"payload_process_creation",
"PAYLOAD_PROCESS_LOCAL",
"new_SceSpZeroConf_child",
["elfldr/elfldr.c:570-710"],
False,
),
effect(
"ptrace_authid_restore_success_path",
"RESTORED_BY_LOADER",
"elfldr_service_process",
["elfldr/pt.c:35-54"],
False,
),
effect(
"ptrace_authid_restore_failure_path",
"UNBOUNDED_OR_UNKNOWN",
"elfldr_service_process",
[
"elfldr/pt.c:50-51 returns after failed restoration",
"no second restoration or process shutdown is present",
],
True,
),
effect(
"ptrace_single_step_completion",
"UNBOUNDED_OR_UNKNOWN",
"loader_control_path",
["elfldr/pt.c:238-246", "elfldr/pt.c:291-299"],
True,
),
effect(
"breakpoint_byte",
"RESTORED_BY_LOADER",
"payload_child",
["elfldr/elfldr.c:675-700"],
False,
),
effect(
"breakpoint_page_permissions",
"PAYLOAD_PROCESS_LOCAL",
"payload_child",
[
"elfldr/elfldr.c:669 changes page to RWX",
"no source edge restores the original protection",
],
False,
),
effect(
"payload_credentials",
"UNBOUNDED_OR_UNKNOWN",
"payload_child",
[
"elfldr/elfldr.c:447-513 restores jail/root/caps/authid",
"UID is set to zero and is not restored",
],
True,
),
effect(
"payload_mapping_args_sockets_pipes",
"UNBOUNDED_OR_UNKNOWN",
"payload_child",
[
"elfldr/elfldr.c:143-343",
"successful detach has no explicit unmap/close cleanup",
"cleanup depends on an unproven child termination path",
],
True,
),
effect(
"sdk_patch_init",
"PAYLOAD_PROCESS_LOCAL",
"payload_child",
["sdk/crt/crt.c", "sdk/crt/patch.c"],
False,
),
effect(
"sdk_termination_branch",
"UNBOUNDED_OR_UNKNOWN",
"payload_child",
[
"sdk/crt/crt.c payload_terminate may return, call exit, or trap",
"the exact branch for the injected SceSpZeroConf child is not proven",
],
True,
),
effect(
"payload_runtime_limit",
"UNBOUNDED_OR_UNKNOWN",
"detached_payload_child",
[
"elfldr/elfldr.c:703-710 detaches and returns the PID",
"no 2000 ms watchdog, wait, kill, or retry budget is present",
],
True,
),
effect(
"child_reaping",
"UNBOUNDED_OR_UNKNOWN",
"elfldr_service_process",
[
"elfldr/socksrv.c:400 ignores SIGCHLD",
"post-detach exit/resource cleanup semantics are not documented",
],
True,
),
effect(
"payload_manager_launch_hash_binding",
"UNBOUNDED_OR_UNKNOWN",
"payload_manager_to_elfldr",
[
"pldmgr/http_server.c resolves a path then calls ps5_launch_elf",
"pldmgr/ps5_launcher.c streams bytes without calculating or checking SHA-256",
],
True,
),
effect(
"payload_manager_upload",
"PERSISTENT_WRITE",
"payload_manager_storage",
[
"pldmgr/http_server.c writes /data/pldmgr/payloads/<name>.tmp",
"the upload is committed into payload storage",
],
True,
),
]
source_files = {
"elfldr": [source_record(root, path) for path in loader_files],
"payload_manager": [source_record(root, path) for path in manager_files],
"sdk": [source_record(root, path) for path in sdk_files],
}
hard_blockers = [
item["id"]
for item in effects
if item["classification"] in ("PERSISTENT_WRITE", "UNBOUNDED_OR_UNKNOWN")
and item["blocker"]
]
hard_blockers.extend(
[
"exact_exploit_and_autoloader_identity_unproven",
"firmware_9_60_not_independently_device_attested",
"return_continuation_after_payload_start_unproven",
]
)
return {
"artifact": {
"built": False,
"execution_eligible": False,
"filename": None,
"sha256": None,
"size": None,
},
"binary_evidence": binary,
"callgraph": {
"entry": "Payload Manager /loadpayload:<path>",
"edges": [
["Payload Manager /loadpayload:<path>", "ps5_launch_elf"],
["ps5_launch_elf", "connect 127.0.0.1:9021"],
["ps5_launch_elf", "send ELF bytes"],
["serve_elfldr", "elfldr_spawn"],
["elfldr_spawn", "rfork_thread"],
["rfork_thread child", "elfldr_rfork_entry"],
["elfldr_rfork_entry", "ptrace PT_TRACE_ME"],
["elfldr_rfork_entry", "execve SceSpZeroConf"],
["elfldr_spawn parent", "pt_syscall 599"],
["elfldr_spawn parent", "install then restore INT3 byte"],
["elfldr_spawn parent", "elfldr_exec"],
["elfldr_exec", "elfldr_raise_privileges"],
["elfldr_exec", "elfldr_prepare_exec"],
["elfldr_prepare_exec", "elfldr_load"],
["elfldr_prepare_exec", "elfldr_payload_args"],
["elfldr_prepare_exec", "push observed RIP at RSP-8"],
["elfldr_prepare_exec", "set RIP=payload entry"],
["elfldr_prepare_exec", "set RDI=payload_args"],
["elfldr_exec", "restore subset of credentials"],
["elfldr_exec", "ptrace PT_DETACH"],
["payload _start", "SDK __patch_init"],
["payload _start", "payload main"],
["payload _start", "payload_terminate"],
["payload_terminate", "return or exit or trap"],
],
"extraction": "reviewed source edges with required-token assertions",
},
"decision": "BLOCKED_VERSION_OR_UNBOUNDED_EFFECT",
"effects": effects,
"firmware": {
"device_attested": False,
"exact": "9.60",
"evidence": "user_provided_only",
},
"hard_blockers": sorted(hard_blockers),
"identity": {
"elfldr": {
**loader_git,
"installed_asset_hash_match": True,
"observed_inventory_path": (
"/data/pldmgr/payloads/elfldr/elfldr_v0.23.elf"
),
"observed_inventory_sha256": ELFLDR_SHA256,
"observed_inventory_version": "v0.23",
"release": "v0.23",
"release_asset_sha256": ELFLDR_SHA256,
"release_asset_size": ELFLDR_SIZE,
"repository": "https://github.com/ps5-payload-dev/elfldr.git",
},
"exact_exploit_autoloader": {
"identified": False,
"local_candidate": {
"filename": "Y2JB-Autoloader-403-1240.zip",
"sha256": (
"805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291"
),
"size": 504159435,
"status": "local_backup_candidate_not_installed_identity_proof",
},
"status": "UNPROVEN",
},
"payload_manager": {
**manager_git,
"installed_asset_hash_match": True,
"observed_inventory_path": (
"/data/pldmgr/payloads/pldmgr/pldmgr_v0.3.1.elf"
),
"observed_inventory_sha256": PLDMGR_SHA256,
"observed_inventory_version": "v0.3.1",
"observed_version_endpoint": "0.3.1",
"release": "v0.3.1",
"release_asset_sha256": PLDMGR_SHA256,
"repository": "https://github.com/itsPLK/ps5-payload-manager.git",
},
"sdk": {
**sdk_git,
"release": "v0.41",
"repository": "https://github.com/ps5-payload-dev/sdk.git",
},
},
"no_console_actions": {
"elf_executed": False,
"elf_transferred": False,
"gnm": False,
"raw_port_9021_contacted": False,
"rendering": False,
"videoout": False,
},
"observation_scope": {
"date": "2026-07-17",
"payload_manager_routes": [
"/autoload_status",
"/get_config",
"/list_payloads",
"/log",
"/sources_list",
"/version",
],
"payload_manager_routes_read_only": True,
"strict_status_port_744_result": "ECONNREFUSED",
},
"phase": "0.6",
"schema_version": 1,
"source_evidence": source_files,
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--loader-source", type=Path, required=True)
parser.add_argument("--loader-asset", type=Path, required=True)
parser.add_argument("--payload-manager-source", type=Path, required=True)
parser.add_argument("--sdk-source", type=Path, required=True)
parser.add_argument("--readelf", type=Path, required=True)
parser.add_argument("--objdump", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
try:
document = build_audit(args)
output = args.output.resolve()
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(
json.dumps(document, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
newline="\n",
)
print(
"Phase-0.6 loader audit: BLOCKED_VERSION_OR_UNBOUNDED_EFFECT; "
f"{len(document['hard_blockers'])} hard blockers"
)
return 0
except (OSError, subprocess.CalledProcessError, ValueError) as error:
print(f"Phase-0.6 loader audit failed: {error}")
return 1
if __name__ == "__main__":
raise SystemExit(main())
+193
View File
@@ -0,0 +1,193 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Audit the pinned SDK startup/loader chain without executing a PS5 ELF."""
from __future__ import annotations
import argparse
import json
import subprocess
from pathlib import Path
EXPECTED_SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37"
def require_in_order(text: str, snippets: tuple[str, ...], source: Path) -> None:
position = -1
for snippet in snippets:
position = text.find(snippet, position + 1)
if position < 0:
raise ValueError(f"{source}: missing or reordered evidence: {snippet}")
def read(source: Path, relative: str) -> str:
path = source / relative
return path.read_text(encoding="utf-8")
def git_head(source: Path) -> str:
result = subprocess.run(
["git", "-C", str(source), "rev-parse", "HEAD"],
check=True,
capture_output=True,
text=True,
)
return result.stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--sdk-source", type=Path, required=True)
parser.add_argument("--project-root", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
sdk = args.sdk_source.resolve(strict=True)
project = args.project_root.resolve(strict=True)
if git_head(sdk) != EXPECTED_SDK_COMMIT:
raise ValueError("SDK source checkout differs from the pinned v0.41 commit")
crt = read(sdk, "crt/crt.c")
patch = read(sdk, "crt/patch.c")
rtld = read(sdk, "crt/rtld.c")
dlfcn = read(sdk, "crt/rtld_dlfcn.c")
sprx = read(sdk, "crt/rtld_sprx.c")
kernel = read(sdk, "crt/kernel.c")
probe_main = read(project, "samples/capability_probe/main.c")
probe_platform = read(project, "src/backends/ps5/probe_platform.c")
require_in_order(
crt,
(
"__crt_syscall_init(args)",
"__kernel_init(args)",
"__klog_init()",
"__patch_init()",
"__rtld_init()",
"*payload_args->payloadout = main(argc, argv, environ)",
),
sdk / "crt/crt.c",
)
require_in_order(
patch,
(
"patch_kernel_ucred()",
"patch_syscall_permissions()",
),
sdk / "crt/patch.c",
)
for snippet in (
"kernel_set_ucred_caps(pid, caps)",
"kernel_set_ucred_attrs(pid, attrs)",
"kernel_copyin(&uaddr, kaddr + 0xf0, sizeof(uaddr))",
"kernel_copyin(&uaddr, kaddr + 0xf8, sizeof(uaddr))",
):
if snippet not in patch:
raise ValueError(f"crt/patch.c: missing expected write: {snippet}")
require_in_order(
rtld,
("__rtld_sprx_init()", "__rtld_dlfcn_init()"),
sdk / "crt/rtld.c",
)
for snippet in (
"sceKernelLoadStartModule(\"/system/common/lib/libSceSysmodule.sprx\"",
"sceKernelLoadStartModule(path, 0, 0, 0, 0, 0)",
"sceKernelStopUnloadModule(lib->handle, 0, 0, 0, 0, 0)",
):
if snippet not in sprx:
raise ValueError(f"crt/rtld_sprx.c: missing loader evidence: {snippet}")
require_in_order(
dlfcn,
("__rtld_lib_open(lib)", "__rtld_lib_init(lib, getargc(), getargv(), environ)"),
sdk / "crt/rtld_dlfcn.c",
)
require_in_order(
dlfcn,
("__rtld_lib_fini(lib)", "__rtld_lib_close(lib)", "__rtld_lib_destroy(lib)"),
sdk / "crt/rtld_dlfcn.c",
)
for snippet in ("int\nkernel_copyin", "int\nkernel_copyout"):
if snippet not in kernel:
raise ValueError(f"crt/kernel.c: missing kernel I/O primitive: {snippet}")
require_in_order(
probe_main,
(
"chimera_gfx_firmware_gate_allows",
"chimera_gfx_ps5_make_loader_ops",
"chimera_gfx_ps5_probe_symbols",
),
project / "samples/capability_probe/main.c",
)
for snippet in (
"dlopen(module_name, RTLD_LAZY | RTLD_LOCAL)",
"address = dlsym(loader->module, symbol_name)",
"address = NULL;",
"dlclose(loader->module)",
):
if snippet not in probe_platform:
raise ValueError(f"probe_platform.c: missing loader boundary: {snippet}")
document = {
"schema_version": 1,
"sdk": {
"release": "v0.41",
"commit": EXPECTED_SDK_COMMIT,
},
"execution_eligible_under_project_policy": False,
"blocking_side_effects_before_main": [
"__patch_init calls patch_kernel_ucred",
"patch_kernel_ucred writes process capability and attribute fields",
"__patch_init calls patch_syscall_permissions",
"patch_syscall_permissions writes the process syscall-address bounds",
],
"startup_calls_before_main": [
"__crt_syscall_init",
"__kernel_init",
"__klog_init",
"__patch_init",
"__rtld_init",
"__rtld_sprx_init",
"__rtld_dlfcn_init",
"payload constructors",
],
"project_requested_calls_after_firmware_gate": [
"fprintf",
"chimera_gfx_ps5_make_loader_ops",
"dlopen",
"dlerror",
"dlsym (21 bounded lookups; returned addresses discarded)",
"snprintf",
"dlclose",
],
"loader_side_effects": [
"SDK rtld startup may load and start libSceSysmodule.sprx",
"probe dlopen may load and start libSceGnmDriver.sprx",
"module open allocates user memory and copies symbol/string tables",
],
"cleanup_side_effects": [
"dlclose invokes rtld fini, close, and destroy paths",
"a newly loaded SPRX is stopped/unloaded with sceKernelStopUnloadModule",
"SDK sprx_init and sprx_fini are empty at the pinned commit",
"cleanup is not guaranteed after a hang, crash, or loader failure",
],
"conclusion": (
"Project code requests no GNM call, rendering, or GPU mutation, but the "
"linked SDK payload CRT performs prohibited kernel writes before main. "
"The resulting ELF must not be transferred or executed."
),
}
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(
json.dumps(document, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
print("SDK runtime audit completed: execution blocked by pre-main kernel writes")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (OSError, subprocess.CalledProcessError, ValueError) as error:
print(f"SDK runtime audit failed: {error}")
raise SystemExit(1) from error
+612
View File
@@ -0,0 +1,612 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Audit SDK v0.41 startup and decide whether a minimal ELF may be built."""
from __future__ import annotations
import argparse
import hashlib
import json
import re
import subprocess
import tempfile
from collections import deque
from pathlib import Path
from typing import Any
EXPECTED_SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37"
CRT_OBJECTS = {
"crt.o": "crt/crt.c",
"syscall.o": "crt/syscall.c",
"klog.o": "crt/klog.c",
"nid.o": "crt/nid.c",
"kernel.o": "crt/kernel.c",
"rtld.o": "crt/rtld.c",
"rtld_so.o": "crt/rtld_so.c",
"rtld_sprx.o": "crt/rtld_sprx.c",
"rtld_payload.o": "crt/rtld_payload.c",
"rtld_dlfcn.o": "crt/rtld_dlfcn.c",
"mdbg.o": "crt/mdbg.c",
"patch.o": "crt/patch.c",
}
EMPTY_CRT_ARCHIVES = (
"crti.o",
"crtn.o",
"crtbegin.o",
"crtend.o",
"crtbeginS.o",
"crtendS.o",
)
DANGEROUS_REACHABLE = {
"__patch_init",
"kernel_copyin",
"kernel_copyout",
"kernel_set_ucred_attrs",
"kernel_set_ucred_caps",
}
LINKED_PROHIBITED = DANGEROUS_REACHABLE | {
"__dlopen",
"__dlsym",
"kernel_mprotect",
"kernel_overlap_sockets",
"kernel_set_vmem_protection",
}
def run(command: list[str], allowed: tuple[int, ...] = (0,)) -> str:
result = subprocess.run(command, check=False, capture_output=True, text=True)
if result.returncode not in allowed:
raise ValueError(
f"command failed ({result.returncode}): {' '.join(command)}\n"
f"{result.stdout}{result.stderr}"
)
return result.stdout + result.stderr
def sha256_bytes(content: bytes) -> str:
return hashlib.sha256(content).hexdigest()
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def require(text: str, snippets: tuple[str, ...], source: str) -> None:
for snippet in snippets:
if snippet not in text:
raise ValueError(f"{source}: missing pinned evidence: {snippet}")
def normalize_target(symbol: str) -> str:
symbol = re.sub(r"[-+]0x[0-9a-f]+$", "", symbol)
symbol = re.sub(r"[-+][0-9a-f]+$", "", symbol)
return symbol
def parse_symbols(nm_output: str) -> tuple[set[str], set[str]]:
functions: set[str] = set()
undefined: set[str] = set()
for line in nm_output.splitlines():
parts = line.split()
if len(parts) < 2:
continue
name, kind = parts[0], parts[1]
if kind in {"T", "t"}:
functions.add(name)
elif kind.lower() == "u" or kind == "w":
undefined.add(name)
return functions, undefined
def parse_callgraph(disassembly: str) -> list[dict[str, str]]:
label = re.compile(r"^[0-9a-f]+ <([^>]+)>:$")
instruction = re.compile(
r"^\s*([0-9a-f]+):\s+([a-z][a-z0-9.]*)\s*(.*?)\s*$"
)
relocation = re.compile(r"^\s*[0-9a-f]+:\s+R_X86_64_\S+\s+(\S+)")
current: str | None = None
pending: dict[str, str] | None = None
edges: list[dict[str, str]] = []
def flush() -> None:
nonlocal pending
if pending is None:
return
operand = pending.pop("operand")
direct = re.search(r"<([^>]+)>", operand)
if "target" not in pending:
if direct is not None and "+0x" not in direct.group(1):
pending["target"] = direct.group(1)
else:
pending["target"] = f"INDIRECT:{operand}"
edges.append(pending)
pending = None
for raw_line in disassembly.splitlines():
line = raw_line.rstrip()
match = label.match(line)
if match is not None:
flush()
current = match.group(1)
continue
match = relocation.match(line)
if match is not None and pending is not None:
pending["target"] = normalize_target(match.group(1))
flush()
continue
match = instruction.match(line)
if match is None:
continue
flush()
if current is None:
continue
address, mnemonic, operand = match.groups()
if mnemonic in {"call", "callq"}:
pending = {
"address": address,
"caller": current,
"kind": "call",
"operand": operand,
}
elif mnemonic in {"jmp", "jmpq"} and (
operand.startswith("*") or ("<" in operand and "+0x" not in operand)
):
pending = {
"address": address,
"caller": current,
"kind": "tail_call",
"operand": operand,
}
flush()
return edges
def reachable_callgraph(
edges: list[dict[str, str]], functions: set[str]
) -> tuple[list[str], list[dict[str, str]]]:
by_caller: dict[str, list[dict[str, str]]] = {}
for edge in edges:
by_caller.setdefault(edge["caller"], []).append(edge)
visited: set[str] = set()
selected: list[dict[str, str]] = []
queue: deque[str] = deque(["_start"])
while queue:
caller = queue.popleft()
if caller in visited:
continue
visited.add(caller)
for edge in by_caller.get(caller, []):
selected.append(edge)
target = edge["target"]
if target in functions and target not in visited:
queue.append(target)
return sorted(visited), sorted(
selected, key=lambda item: (item["caller"], item["address"], item["target"])
)
def driver_trace(compiler: Path, source: Path, freestanding: bool) -> str:
command = [str(compiler), "-###", "-Qunused-arguments", "-Werror"]
if freestanding:
command.extend(["-nostartfiles", "-nodefaultlibs"])
command.extend([str(source), "-o", str(source.with_suffix(".never.elf"))])
trace = run(command)
if source.with_suffix(".never.elf").exists():
raise ValueError("compiler -### unexpectedly produced an ELF")
trace = trace.replace(str(source.parent), "<TEMP>")
return re.sub(r"trace-[0-9a-f]+\.o", "trace-<ID>.o", trace)
def git_grep_loader_contract(checkout: Path) -> list[str]:
if not (checkout / ".git").exists():
return []
output = run(
[
"git",
"-C",
str(checkout),
"grep",
"-n",
"-e",
"payload_args_t",
"-e",
"payloadout",
"--",
],
allowed=(0, 1),
)
return sorted(line for line in output.splitlines() if line.strip())
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--sdk-source", type=Path, required=True)
parser.add_argument("--sdk-install", type=Path, required=True)
parser.add_argument("--objdump", type=Path, required=True)
parser.add_argument("--readelf", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve(strict=True)
sdk_source = args.sdk_source.resolve(strict=True)
sdk_install = args.sdk_install.resolve(strict=True)
sdk_head = run(["git", "-C", str(sdk_source), "rev-parse", "HEAD"]).strip()
if sdk_head != EXPECTED_SDK_COMMIT:
raise ValueError("SDK source does not match the pinned v0.41 commit")
source_files = set(CRT_OBJECTS.values()) | {
"Makefile.inc",
"crt/Makefile",
"crt/payload.h",
"include/ps5/payload.h",
"host/bin/prospero-clang",
"host/bin/prospero-lld",
"host/elf_x86_64.x",
"host/Makefile",
"host/toolchain/prospero.cmake",
"host/toolchain/prospero.mk",
"host/toolchain/prospero.sh",
}
source_files.update(
str(path.relative_to(sdk_source)).replace("\\", "/")
for path in (sdk_source / "crt").glob("*.h")
)
source_hashes = {
relative: sha256_file(sdk_source / relative)
for relative in sorted(source_files)
}
makefile = (sdk_source / "crt/Makefile").read_text(encoding="utf-8")
object_text_match = re.search(r"OBJ := (.+?)\n\n", makefile, re.DOTALL)
if object_text_match is None:
raise ValueError("could not parse CRT object inventory")
makefile_objects = object_text_match.group(1).replace("\\\n", " ").split()
if makefile_objects != list(CRT_OBJECTS):
raise ValueError(f"CRT object inventory changed: {makefile_objects}")
require(
makefile,
(
"-ffreestanding -fno-builtin -nostdlib -fPIC",
"-target x86_64-sie-ps5",
"crt1.o: $(OBJ)",
"$(LD) -m elf_x86_64 -r -o $@ $^",
),
"crt/Makefile",
)
crt = (sdk_source / "crt/crt.c").read_text(encoding="utf-8")
patch = (sdk_source / "crt/patch.c").read_text(encoding="utf-8")
payload_header = (sdk_source / "include/ps5/payload.h").read_text(
encoding="utf-8"
)
linker_script = (sdk_source / "host/elf_x86_64.x").read_text(encoding="utf-8")
compiler_wrapper = (sdk_source / "host/bin/prospero-clang").read_text(
encoding="utf-8"
)
require(
crt,
(
"_start(payload_args_t *args)",
"for(unsigned char* bss=__bss_start; bss<__bss_end; bss++)",
"__crt_syscall_init(args)",
"__kernel_init(args)",
"__klog_init()",
"__patch_init()",
"__rtld_init()",
"return payload_terminate()",
),
"crt/crt.c",
)
require(
patch,
(
"kernel_set_ucred_caps(pid, caps)",
"kernel_set_ucred_attrs(pid, attrs)",
"caps[15] |= 0x40",
"attrs[3] |= 0x80",
"kernel_copyin(&uaddr, kaddr + 0xf0, sizeof(uaddr))",
"kernel_copyin(&uaddr, kaddr + 0xf8, sizeof(uaddr))",
),
"crt/patch.c",
)
require(
payload_header,
(
"int (*sys_dynlib_dlsym)(int, const char*, void*)",
"int* rwpipe",
"int* rwpair",
"intptr_t kpipe_addr",
"intptr_t kdata_base_addr",
"int* payloadout",
),
"include/ps5/payload.h",
)
require(
linker_script,
(
"OUTPUT_ARCH(i386:x86-64)",
"PROVIDE_HIDDEN (__bss_start = .)",
"PROVIDE_HIDDEN (__bss_end = .)",
".init_array",
".fini_array",
"PT_DYNAMIC",
),
"host/elf_x86_64.x",
)
require(
compiler_wrapper,
(
'LIBS_CRT="${PS5_PAYLOAD_SDK}/target/lib/crt1.o"',
'if [[ "$ARG" == "-nostdlibc" ||',
'"$ARG" == "-nodefaultlibs"',
'if [[ "$ARG" == "-nostartfiles" ||',
"-target x86_64-sie-ps5",
),
"host/bin/prospero-clang",
)
crt1 = sdk_install / "target/lib/crt1.o"
nm = sdk_install / "bin/llvm-nm"
ar = sdk_install / "bin/llvm-ar"
compiler = sdk_install / "bin/prospero-clang"
linker = sdk_install / "bin/prospero-lld"
for path in (crt1, nm, ar, compiler, linker, args.objdump, args.readelf):
path.resolve(strict=True)
nm_output = run([str(nm), "--format=posix", str(crt1)])
functions, undefined = parse_symbols(nm_output)
expected_undefined = {
"_DYNAMIC",
"__bss_end",
"__bss_start",
"__fini_array_end",
"__fini_array_start",
"__image_end",
"__image_start",
"__init_array_end",
"__init_array_start",
"main",
}
if undefined != expected_undefined:
raise ValueError(f"crt1.o undefined symbol inventory changed: {undefined}")
if not DANGEROUS_REACHABLE.issubset(functions):
raise ValueError("crt1.o no longer contains the reviewed dangerous functions")
if not LINKED_PROHIBITED.issubset(functions):
raise ValueError("crt1.o linked prohibited-function inventory changed")
empty_archives: dict[str, list[str]] = {}
for filename in EMPTY_CRT_ARCHIVES:
members = run([str(ar), "t", str(sdk_install / "target/lib" / filename)])
empty_archives[filename] = members.splitlines()
if empty_archives[filename]:
raise ValueError(f"{filename} unexpectedly contains members")
disassembly = run(
[str(args.objdump), "-dr", "--no-show-raw-insn", str(crt1)]
)
all_edges = parse_callgraph(disassembly)
reachable_functions, reachable_edges = reachable_callgraph(all_edges, functions)
reachable_set = set(reachable_functions)
if not DANGEROUS_REACHABLE.issubset(reachable_set):
missing = sorted(DANGEROUS_REACHABLE - reachable_set)
raise ValueError(f"disassembly call graph lost expected reachable writes: {missing}")
section_table = run([str(args.readelf), "-SW", str(crt1)])
relocation_table = run([str(args.readelf), "-Wr", str(crt1)])
elf_header = run([str(args.readelf), "-h", str(crt1)])
if ".text._start" not in section_table or ".rela.text._start" not in section_table:
raise ValueError("crt1.o lacks the audited _start sections")
if "__patch_init" not in relocation_table or "kernel_copyin" not in relocation_table:
raise ValueError("crt1.o relocation evidence no longer exposes the write path")
tls_sections = sorted(
match.group(1)
for line in section_table.splitlines()
if (match := re.search(r"\]\s+(\.\S+)\s+\S+.*\sT\s", line)) is not None
)
with tempfile.TemporaryDirectory() as directory:
trace_source = Path(directory) / "trace.c"
trace_source.write_text("int main(void) { return 0; }\n", encoding="utf-8")
default_trace = driver_trace(compiler, trace_source, freestanding=False)
free_trace = driver_trace(compiler, trace_source, freestanding=True)
for expected in ("crt1.o", '"-lc"', '"-lkernel_web"', '"-lSceLibcInternal"', '"-lSceNet"'):
if expected not in default_trace:
raise ValueError(f"default driver trace lacks {expected}")
for forbidden in ("crt1.o", '"-lc"', '"-lkernel_web"', '"-lSceLibcInternal"', '"-lSceNet"'):
if forbidden in free_trace:
raise ValueError(f"freestanding driver trace retains {forbidden}")
upstream = root / "work/upstream"
loader_search: dict[str, list[str]] = {}
for name in ("SDL", "RetroArch", "pacbrew-repo", "ps5-linux-loader"):
loader_search[name] = git_grep_loader_contract(upstream / name)
if any(loader_search.values()):
raise ValueError("an unreviewed local loader caller appeared in the evidence set")
document: dict[str, Any] = {
"schema_version": 1,
"audit_date": "2026-07-17",
"decision": "BLOCKED",
"scope": "phase-0.5-kernelwrite-free-startup-offline-only",
"artifact": {
"built": False,
"execution_eligible": False,
"reason": "safe loader return and cleanup are not proven",
"sha256": None,
},
"sdk": {
"release": "v0.41",
"commit": EXPECTED_SDK_COMMIT,
"target": "x86_64-sie-ps5",
"source_hashes": source_hashes,
},
"tool_versions": {
"prospero_clang": run([str(compiler), "--version"]).splitlines()[0],
"prospero_lld": run([str(linker), "--version"]).splitlines()[0],
"objdump": run([str(args.objdump), "--version"]).splitlines()[0],
"readelf": run([str(args.readelf), "--version"]).splitlines()[0],
},
"startup_linkage": {
"default_driver_additions": [
"target/lib/crt1.o",
"libc",
"libkernel_web",
"libSceLibcInternal",
"libSceNet",
],
"default_driver_trace_sha256": sha256_bytes(default_trace.encode()),
"freestanding_flags": ["-nostartfiles", "-nodefaultlibs"],
"freestanding_driver_additions": [],
"freestanding_driver_trace_sha256": sha256_bytes(free_trace.encode()),
"crt1_sha256": sha256_file(crt1),
"installed_linker_script_sha256": sha256_file(
sdk_install / "ldscripts/elf_x86_64.x"
),
"installed_main_script_sha256": sha256_file(
sdk_install / "target/lib/main.script"
),
"installed_prx_script_sha256": sha256_file(
sdk_install / "target/lib/prx.script"
),
"crt1_composition": [
{"object": obj, "source": source}
for obj, source in CRT_OBJECTS.items()
],
"empty_startup_archives": empty_archives,
"crt1_undefined_symbols": sorted(undefined),
},
"crt1_static_evidence": {
"disassembly_sha256": sha256_bytes(disassembly.encode()),
"elf_header_sha256": sha256_bytes(elf_header.encode()),
"section_table_sha256": sha256_bytes(section_table.encode()),
"relocation_table_sha256": sha256_bytes(relocation_table.encode()),
"relocation_count": len(re.findall(r"R_X86_64_", relocation_table)),
"tls_sections": tls_sections,
"reachable_functions": reachable_functions,
"reachable_callgraph": reachable_edges,
"reachable_prohibited_functions": sorted(
DANGEROUS_REACHABLE & reachable_set
),
"linked_prohibited_functions": sorted(LINKED_PROHIBITED & functions),
"linked_but_not_startup_reachable": sorted(
LINKED_PROHIBITED - reachable_set
),
"source_token_inventory": {
"GNM": any(
"sceGnm" in (sdk_source / source).read_text(encoding="utf-8")
for source in CRT_OBJECTS.values()
),
"SDL": any(
"SDL_" in (sdk_source / source).read_text(encoding="utf-8")
for source in CRT_OBJECTS.values()
),
"VideoOut": any(
"sceVideoOut" in (sdk_source / source).read_text(encoding="utf-8")
for source in CRT_OBJECTS.values()
),
"module_loading": True,
"network_socket_helper": True,
},
},
"loader_evidence": {
"sdk_readme_loader_candidates": [
"ps5-payload-dev/elfldr",
"cryonumb/elfloader via ps5-jar-loader",
"shahrilnet/remote_lua_loader",
],
"local_non_sdk_contract_hits": loader_search,
"exact_loader_used_for_firmware_9_60_identified": False,
"caller_source_present": False,
"entry_argument_layout": "SAFE_SOURCE_FACT",
"callee_first_argument_register_rdi": "SAFE_DISASSEMBLY_FACT",
"caller_stack_alignment": "UNPROVEN",
"payloadout_lifetime_and_writability": "UNPROVEN",
"return_address_and_return_consumption": "UNPROVEN",
"post_return_cleanup": "UNPROVEN",
"crash_cleanup": "UNPROVEN",
"pre_entry_loader_process_changes": "UNPROVEN",
},
"review": [
{
"component": "payload_args_t field order and 48-byte x86_64 layout",
"status": "SAFE",
"basis": "public SDK header plus _start payloadout access at offset 0x28",
},
{
"component": "SDK v0.41 default crt1.o",
"status": "UNSAFE",
"basis": "source, relocation, and reachable disassembly prove kernel-write paths",
},
{
"component": "-nostartfiles -nodefaultlibs removes SDK CRT/default libs",
"status": "SAFE",
"basis": "compiler -### trace only; no output ELF was produced",
},
{
"component": "custom BSS zeroing implementation",
"status": "SAFE",
"basis": "linker symbols and byte-zero loop can be freestanding",
},
{
"component": "loader entry stack and ABI preconditions",
"status": "UNPROVEN",
"basis": "callee disassembly does not prove caller behavior",
},
{
"component": "return, exit, crash, and cleanup behavior",
"status": "UNPROVEN",
"basis": "no exact pinned public loader caller source is locally available",
},
{
"component": "loader changes before _start",
"status": "UNPROVEN",
"basis": "payload args expose pre-existing kernel access but not how it was established",
},
],
"custom_artifact_verification": {
"linker_map": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"disassembly": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"undefined_symbols": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"dt_needed": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"relocations": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"init_fini_arrays": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"tls": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"double_clean_build": "NOT_PERFORMED_BLOCKED_BEFORE_BUILD",
"artifact_sha256": None,
},
"minimal_missing_evidence": [
"the exact loader and pinned source commit used on firmware 9.60",
"the caller instruction sequence that establishes RDI, RSP alignment, and return address",
"payload_args_t allocation, payloadout lifetime, writability, and ownership",
"the caller path after _start returns, including restoration and cleanup",
"crash/fault behavior before and during _start",
"all process, credential, syscall, module, and memory changes made before entry",
],
"safe_alternatives": [
"continue libchimera-gfx through mock and software backends",
"develop a separately scoped Linux-on-PS5 backend as a long-term track",
],
}
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(
json.dumps(document, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
print(
"Phase-0.5 startup audit: BLOCKED; loader return contract is unproven; "
"no PS5 ELF built"
)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (KeyError, OSError, TypeError, ValueError) as error:
print(f"startup feasibility audit failed: {error}")
raise SystemExit(1) from error
+52
View File
@@ -0,0 +1,52 @@
# SPDX-License-Identifier: GPL-3.0-or-later
[CmdletBinding()]
param(
[string]$Destination = ""
)
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($Destination)) {
$Destination = Join-Path $root "work/toolchains/ps5-payload-sdk-v0.41"
}
$cache = Join-Path $root "work/cache"
$archive = Join-Path $cache "ps5-payload-sdk-v0.41.zip"
$url = "https://github.com/ps5-payload-dev/sdk/releases/download/v0.41/ps5-payload-sdk.zip"
$expectedHash = "ebfb0acb5260511951a80e17db41650c62d20a8caf8659a230b928dc85005984"
$expectedSize = 8810966
New-Item -ItemType Directory -Force -Path $cache | Out-Null
if (-not (Test-Path -LiteralPath $archive)) {
& curl.exe -fL --retry 3 --output $archive $url
if ($LASTEXITCODE -ne 0) {
throw "SDK download failed"
}
}
$file = Get-Item -LiteralPath $archive
if ($file.Length -ne $expectedSize) {
throw "SDK size mismatch: expected $expectedSize, got $($file.Length)"
}
$actualHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $archive).Hash.ToLowerInvariant()
if ($actualHash -ne $expectedHash) {
throw "SDK SHA-256 mismatch"
}
if (-not (Test-Path -LiteralPath $Destination)) {
$temporary = Join-Path $root "work/toolchains/sdk-extract"
$resolvedRoot = [System.IO.Path]::GetFullPath($root).TrimEnd('\') + '\'
$resolvedTemporary = [System.IO.Path]::GetFullPath($temporary)
if (-not $resolvedTemporary.StartsWith($resolvedRoot,
[System.StringComparison]::OrdinalIgnoreCase)) {
throw "Refusing temporary cleanup outside the workspace"
}
New-Item -ItemType Directory -Force -Path $temporary | Out-Null
Expand-Archive -LiteralPath $archive -DestinationPath $temporary -Force
$extracted = Join-Path $temporary "ps5-payload-sdk"
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $Destination) | Out-Null
Move-Item -LiteralPath $extracted -Destination $Destination
Remove-Item -LiteralPath $temporary -Recurse -Force
}
Write-Output "Verified PS5 Payload SDK v0.41 at $Destination"
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-or-later
set -euo pipefail
readonly allowed_firmware="9.60"
readonly expected_sdk_commit="d2e2e585740362976a39fdd5ccf390f199a7bc37"
readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly root="$(cd "${script_dir}/.." && pwd)"
readonly sdk="${PS5_PAYLOAD_SDK:-${root}/work/toolchains/ps5-payload-sdk-v0.41}"
readonly sdk_source="${CHIMERA_GFX_SDK_SOURCE:-${root}/work/upstream/sdk}"
readonly build="${root}/build/probe-9.60"
readonly outputs="${root}/outputs"
readonly artifact_name="chimera-gfx-capability-probe-0.1.0-fw-9.60-offline-audit-only.elf"
readonly manifest_name="chimera-gfx-capability-probe-0.1.0-fw-9.60.json"
if [[ "${1:-}" != "${allowed_firmware}" || $# -ne 1 ]]; then
echo "usage: $0 9.60" >&2
exit 64
fi
if [[ ! -f "${sdk}/toolchain/prospero.cmake" ||
! -x "${sdk}/bin/prospero-nm" ]]; then
echo "missing verified PS5 Payload SDK v0.41 toolchain" >&2
exit 2
fi
if ! command -v llvm-readelf-18 >/dev/null 2>&1; then
echo "missing llvm-readelf-18 for the strict dynamic-table audit" >&2
exit 2
fi
if [[ ! -d "${sdk_source}/.git" ||
"$(git -C "${sdk_source}" rev-parse HEAD)" != "${expected_sdk_commit}" ]]; then
echo "SDK source checkout is not at the locked v0.41 commit" >&2
exit 2
fi
if ! git -C "${root}" diff --quiet ||
! git -C "${root}" diff --cached --quiet; then
echo "refusing provenance build from a dirty project tree" >&2
exit 2
fi
mkdir -p "${build}" "${outputs}"
python3 "${root}/tools/audit_ps5_sdk_runtime.py" \
--sdk-source "${sdk_source}" \
--project-root "${root}" \
--output "${build}/sdk-runtime-audit.json"
export LLVM_CONFIG="${LLVM_CONFIG:-/usr/bin/llvm-config-18}"
cmake -S "${root}" -B "${build}" -G Ninja \
-DCMAKE_TOOLCHAIN_FILE="${sdk}/toolchain/prospero.cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DCHIMERA_GFX_BUILD_PS5_PROBE=ON \
-DCHIMERA_GFX_BUILD_PHASE1_VIDEOOUT_CLEAR=OFF \
-DCHIMERA_GFX_PS5_ALLOWED_FIRMWARE="${allowed_firmware}"
cmake --build "${build}" --clean-first \
--target chimera-gfx-capability-probe
cmake -E copy_if_different \
"${build}/chimera-gfx-capability-probe.elf" \
"${outputs}/${artifact_name}"
cmake -E copy_if_different \
"${build}/sdk-runtime-audit.json" \
"${outputs}/sdk-runtime-audit-v0.41.json"
python3 "${root}/tools/audit_ps5_artifacts.py" \
--nm "${sdk}/bin/prospero-nm" \
--readelf "$(command -v llvm-readelf-18)" \
--probe "${outputs}/${artifact_name}" \
--symbol-manifest "${root}/manifests/ps5_gnm_symbols.json" \
--firmware "${allowed_firmware}"
readonly source_commit="$(git -C "${root}" rev-parse HEAD)"
python3 "${root}/tools/generate_artifact_manifest.py" \
--artifact "${outputs}/${artifact_name}" \
--output "${outputs}/${manifest_name}" \
--id "chimera-gfx-capability-probe-fw-9.60" \
--version "0.1.0" \
--source-repository \
"https://gitea.itworx.tech/Jens/chimera-gfx.git" \
--source-commit "${source_commit}" \
--target "ps5-x86_64" \
--firmware "${allowed_firmware}" \
--profile "symbol-discovery-only-offline-audit" \
--note "Transfer and execution are not authorized." \
--note "Project code calls no resolved GNM symbol and requests no rendering or GPU mutation." \
--note "SDK v0.41 CRT performs kernel credential and syscall-permission writes before main; execution is blocked by project policy."
python3 "${root}/tools/verify_artifact_manifest.py" \
--manifest "${outputs}/${manifest_name}" \
--artifact "${outputs}/${artifact_name}"
echo "Built and audited offline only: ${outputs}/${artifact_name}"
echo "Execution eligibility: false; do not transfer or execute this ELF."
+40
View File
@@ -0,0 +1,40 @@
# SPDX-License-Identifier: GPL-3.0-or-later
[CmdletBinding()]
param(
[ValidateSet("Debug", "Release")]
[string]$Configuration = "Debug"
)
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $PSScriptRoot
$cmake = "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe"
$ctest = "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\ctest.exe"
if (-not (Test-Path -LiteralPath $cmake)) {
$cmakeCommand = Get-Command cmake -ErrorAction Stop
$cmake = $cmakeCommand.Source
$ctestCommand = Get-Command ctest -ErrorAction Stop
$ctest = $ctestCommand.Source
}
$rootBytes = [System.Text.Encoding]::UTF8.GetBytes(
[System.IO.Path]::GetFullPath($root).ToLowerInvariant())
$sha256 = [System.Security.Cryptography.SHA256]::Create()
try {
$rootHashBytes = $sha256.ComputeHash($rootBytes)
}
finally {
$sha256.Dispose()
}
$rootHash = (
[System.BitConverter]::ToString($rootHashBytes) -replace "-", ""
).Substring(0, 12).ToLowerInvariant()
$buildName = "build/windows-{0}-{1}" -f $Configuration.ToLowerInvariant(), $rootHash
$build = Join-Path $root $buildName
& $cmake -S $root -B $build -G "Visual Studio 17 2022" -A x64 `
-DBUILD_TESTING=ON -DCHIMERA_GFX_REGISTER_EXTERNAL_EVIDENCE_VALIDATORS=OFF
if ($LASTEXITCODE -ne 0) { throw "Host configure failed" }
& $cmake --build $build --config $Configuration
if ($LASTEXITCODE -ne 0) { throw "Host build failed" }
& $ctest --test-dir $build -C $Configuration --output-on-failure
if ($LASTEXITCODE -ne 0) { throw "Host tests failed" }
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-or-later
set -euo pipefail
readonly expected_sdl_commit="0baf4ac49382b537ba449901b5b6d0d189bb1fbb"
readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly root="$(cd "${script_dir}/.." && pwd)"
readonly sdk="${PS5_PAYLOAD_SDK:-${root}/work/toolchains/ps5-payload-sdk-v0.41}"
readonly sdl_source="${CHIMERA_GFX_SDL_SOURCE:-${root}/work/upstream/SDL}"
readonly sdl_stage="${root}/work/generated/SDL-phase1-video-only"
readonly sdl_build="${root}/build/phase1-sdl"
readonly project_build="${root}/build/phase1-videoout"
readonly sdl_patch="${root}/packaging/patches/sdl2-phase1-video-only.patch"
if [[ ! -f "${sdk}/toolchain/prospero.cmake" ]]; then
echo "missing verified PS5 Payload SDK v0.41" >&2
exit 2
fi
if ! command -v llvm-readelf-18 >/dev/null 2>&1; then
echo "missing llvm-readelf-18 for the strict dynamic-table audit" >&2
exit 2
fi
if [[ ! -d "${sdl_source}/.git" ]]; then
echo "missing pinned PS5 SDL source checkout" >&2
exit 2
fi
if [[ "$(git -C "${sdl_source}" rev-parse HEAD)" != "${expected_sdl_commit}" ]]; then
echo "PS5 SDL checkout is not at the locked commit" >&2
exit 2
fi
if [[ ! -e "${sdl_stage}/.git" ]]; then
mkdir -p "$(dirname "${sdl_stage}")"
git -C "${sdl_source}" -c core.autocrlf=false -c core.eol=lf \
worktree add --detach "${sdl_stage}" "${expected_sdl_commit}"
fi
if [[ "$(git -C "${sdl_stage}" rev-parse HEAD)" != "${expected_sdl_commit}" ]]; then
echo "staged PS5 SDL checkout is not at the locked commit" >&2
exit 2
fi
if git -C "${sdl_stage}" apply --check "${sdl_patch}" 2>/dev/null; then
git -C "${sdl_stage}" apply "${sdl_patch}"
elif ! git -C "${sdl_stage}" apply --reverse --check "${sdl_patch}" \
2>/dev/null; then
echo "staged PS5 SDL checkout differs from the reviewed overlay" >&2
exit 2
fi
if [[ "$(git -C "${sdl_stage}" diff --name-only)" != \
"src/video/ps5/SDL_ps5video.c" ]]; then
echo "staged PS5 SDL checkout has changes outside the reviewed overlay" >&2
exit 2
fi
export LLVM_CONFIG="${LLVM_CONFIG:-/usr/bin/llvm-config-18}"
cmake -S "${sdl_stage}" -B "${sdl_build}" -G Ninja \
-DCMAKE_TOOLCHAIN_FILE="${sdk}/toolchain/prospero.cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DSDL_SHARED=OFF \
-DSDL_STATIC=ON \
-DSDL_TEST=OFF \
-DSDL2_DISABLE_SDL2MAIN=ON \
-DSDL_AUDIO=OFF \
-DSDL_JOYSTICK=OFF \
-DSDL_HAPTIC=OFF \
-DSDL_SENSOR=OFF \
-DSDL_POWER=OFF \
-DSDL_FILE=OFF \
-DSDL_FILESYSTEM=OFF \
-DSDL_LOCALE=OFF \
-DSDL_MISC=OFF \
-DSDL_OPENGL=OFF \
-DSDL_LOADSO=OFF \
-DSDL_RENDER=OFF \
-DSDL_VULKAN=OFF \
-DSDL_DUMMYVIDEO=OFF \
-DSDL_OFFSCREEN=OFF \
-DSDL_HIDAPI=OFF
cmake --build "${sdl_build}" --target SDL2-static
cmake -S "${root}" -B "${project_build}" -G Ninja \
-DCMAKE_TOOLCHAIN_FILE="${sdk}/toolchain/prospero.cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DCHIMERA_GFX_BUILD_PS5_PROBE=ON \
-DCHIMERA_GFX_BUILD_PHASE1_VIDEOOUT_CLEAR=ON \
-DCHIMERA_GFX_PHASE1_SDL_BUILD="${sdl_build}" \
-DCHIMERA_GFX_PS5_ALLOWED_FIRMWARE=NONE
cmake --build "${project_build}" --clean-first
python3 "${root}/tools/audit_ps5_artifacts.py" \
--nm "${sdk}/bin/prospero-nm" \
--readelf "$(command -v llvm-readelf-18)" \
--probe "${project_build}/chimera-gfx-capability-probe.elf" \
--symbol-manifest "${root}/manifests/ps5_gnm_symbols.json" \
--phase1 "${project_build}/chimera-gfx-phase1-videoout-clear.elf"
echo "Built offline only; do not transfer or execute either ELF."
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Derive the W^X linker script and build the offline Phase-1.0DM ELF."""
from __future__ import annotations
import argparse,hashlib,subprocess
from pathlib import Path
SDK_SCRIPT_SHA256="3bacf56a21602a1298752023a4c5b0c305954ddf6cdbce1464476fc9da9d9093"
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);a=p.parse_args();root=a.root.resolve();sdk=root/"work/toolchains/ps5-payload-sdk-v0.41";source=sdk/"target/lib/main.script";raw=source.read_bytes()
if hashlib.sha256(raw).hexdigest()!=SDK_SCRIPT_SHA256:raise SystemExit("SDK linker script identity mismatch")
text=raw.decode();needle="ph_text PT_LOAD FLAGS (0x7);"
if text.count(needle)!=1:raise SystemExit("SDK text PHDR differs")
derived=text.replace(needle,"ph_text PT_LOAD FLAGS (0x5);")
out=root/"build/phase10dm";out.mkdir(parents=True,exist_ok=True);script=out/"observer-wx.script";script.write_text(derived,newline="\n")
source=root.parent/"chimera-retroarch/pkg/ps5/chimera_ps5_title_snapshot_observer.c";artifact=out/"chimera_title_snapshot_observer.elf";linkmap=out/"chimera_title_snapshot_observer.map"
if not source.is_file():raise SystemExit("target source missing")
def wsl(path):return "/mnt/c/"+path.as_posix().split(":/",1)[1]
command=f"set -euo pipefail; '{wsl(sdk)}/bin/prospero-clang' -std=c11 -Wall -Wextra -Werror -O2 -fno-common -Wl,-T,'{wsl(script)}' -Wl,-Map,'{wsl(linkmap)}' -o '{wsl(artifact)}' '{wsl(source)}'"
subprocess.run(["wsl.exe","bash","-lc",command],check=True)
return 0
if __name__=="__main__":raise SystemExit(main())
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Derive the W^X linker script and build the offline Phase-1.0DQ ELF."""
from __future__ import annotations
import argparse,hashlib,subprocess
from pathlib import Path
SDK_SCRIPT_SHA256="3bacf56a21602a1298752023a4c5b0c305954ddf6cdbce1464476fc9da9d9093"
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);a=p.parse_args();root=a.root.resolve();sdk=root/"work/toolchains/ps5-payload-sdk-v0.41";source_script=sdk/"target/lib/main.script";raw=source_script.read_bytes()
if hashlib.sha256(raw).hexdigest()!=SDK_SCRIPT_SHA256:raise SystemExit("SDK linker script identity mismatch")
text=raw.decode();needle="ph_text PT_LOAD FLAGS (0x7);"
if text.count(needle)!=1:raise SystemExit("SDK text PHDR differs")
out=root/"build/phase10dq";out.mkdir(parents=True,exist_ok=True);script=out/"observer-wx.script";script.write_text(text.replace(needle,"ph_text PT_LOAD FLAGS (0x5);"),newline="\n")
source=root.parent/"chimera-retroarch/pkg/ps5/chimera_ps5_fake00000_inventory_observer.c";artifact=out/"chimera_fake00000_inventory_observer.elf";linkmap=out/"chimera_fake00000_inventory_observer.map"
if not source.is_file():raise SystemExit("target source missing")
def wsl(path):return "/mnt/c/"+path.as_posix().split(":/",1)[1]
command=f"set -euo pipefail; '{wsl(sdk)}/bin/prospero-clang' -std=c11 -Wall -Wextra -Werror -O2 -fno-common -Wl,-T,'{wsl(script)}' -Wl,-Map,'{wsl(linkmap)}' -o '{wsl(artifact)}' '{wsl(source)}'"
subprocess.run(["wsl.exe","bash","-lc",command],check=True)
return 0
if __name__=="__main__":raise SystemExit(main())
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import argparse,hashlib,subprocess
from pathlib import Path
SDK_SCRIPT_SHA256="3bacf56a21602a1298752023a4c5b0c305954ddf6cdbce1464476fc9da9d9093"
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);root=p.parse_args().root.resolve();sdk=root/"work/toolchains/ps5-payload-sdk-v0.41";raw=(sdk/"target/lib/main.script").read_bytes()
if hashlib.sha256(raw).hexdigest()!=SDK_SCRIPT_SHA256:raise SystemExit("SDK linker script identity mismatch")
text=raw.decode();needle="ph_text PT_LOAD FLAGS (0x7);"
if text.count(needle)!=1:raise SystemExit("SDK text PHDR differs")
out=root/"build/phase10ds";out.mkdir(parents=True,exist_ok=True);script=out/"observer-wx.script";script.write_text(text.replace(needle,"ph_text PT_LOAD FLAGS (0x5);"),newline="\n")
source=root.parent/"chimera-retroarch/pkg/ps5/chimera_ps5_fake00000_metadata_observer.c";artifact=out/"chimera_fake00000_metadata_observer.elf";linkmap=out/"chimera_fake00000_metadata_observer.map"
def wsl(path):return "/mnt/c/"+path.as_posix().split(":/",1)[1]
subprocess.run(["wsl.exe","bash","-lc",f"set -euo pipefail; '{wsl(sdk)}/bin/prospero-clang' -std=c11 -Wall -Wextra -Werror -O2 -fno-common -Wl,-T,'{wsl(script)}' -Wl,-Map,'{wsl(linkmap)}' -o '{wsl(artifact)}' '{wsl(source)}'"],check=True)
if __name__=="__main__":main()
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
import argparse,hashlib,subprocess
from pathlib import Path
H="3bacf56a21602a1298752023a4c5b0c305954ddf6cdbce1464476fc9da9d9093"
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);r=p.parse_args().root.resolve();sdk=r/"work/toolchains/ps5-payload-sdk-v0.41";raw=(sdk/"target/lib/main.script").read_bytes()
if hashlib.sha256(raw).hexdigest()!=H:raise SystemExit("SDK identity")
out=r/"build/phase10du";out.mkdir(parents=True,exist_ok=True);script=out/"wx.script";script.write_text(raw.decode().replace("ph_text PT_LOAD FLAGS (0x7);","ph_text PT_LOAD FLAGS (0x5);"),newline="\n");src=r.parent/"chimera-retroarch/pkg/ps5/chimera_ps5_fake00000_package_stat.c";elf=out/"chimera_fake00000_package_stat.elf"
def w(p):return "/mnt/c/"+p.as_posix().split(":/",1)[1]
subprocess.run(["wsl.exe","bash","-lc",f"set -e; '{w(sdk)}/bin/prospero-clang' -std=c11 -Wall -Wextra -Werror -O2 -Wl,-T,'{w(script)}' -o '{w(elf)}' '{w(src)}'"],check=True)
if __name__=="__main__":main()
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
import argparse,hashlib,subprocess
from pathlib import Path
H="3bacf56a21602a1298752023a4c5b0c305954ddf6cdbce1464476fc9da9d9093"
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);r=p.parse_args().root.resolve();sdk=r/"work/toolchains/ps5-payload-sdk-v0.41";raw=(sdk/"target/lib/main.script").read_bytes()
if hashlib.sha256(raw).hexdigest()!=H:raise SystemExit("SDK identity")
out=r/"build/phase10dw";out.mkdir(parents=True,exist_ok=True);script=out/"wx.script";script.write_text(raw.decode().replace("ph_text PT_LOAD FLAGS (0x7);","ph_text PT_LOAD FLAGS (0x5);"),newline="\n");src=r.parent/"chimera-retroarch/pkg/ps5/chimera_ps5_fake00000_package_readback.c";elf=out/"chimera_fake00000_package_readback.elf"
def w(p):return "/mnt/c/"+p.as_posix().split(":/",1)[1]
subprocess.run(["wsl.exe","bash","-lc",f"set -e; '{w(sdk)}/bin/prospero-clang' -std=c11 -Wall -Wextra -Werror -O2 -Wl,-T,'{w(script)}' -o '{w(elf)}' '{w(src)}'"],check=True)
if __name__=="__main__":main()
+341
View File
@@ -0,0 +1,341 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Fail-closed static eligibility gate for artifact execution tooling."""
from __future__ import annotations
import argparse
import hashlib
import json
import re
from pathlib import Path
from typing import Any
SHA256_PATTERN = re.compile(r"[0-9a-f]{64}")
COMMIT_PATTERN = re.compile(r"[0-9a-f]{40}")
READY_DECISION = "READY_FOR_HARDENED_RUNTIME_DEPLOYMENT"
HARD_EFFECTS = {"PERSISTENT_WRITE", "UNBOUNDED_OR_UNKNOWN"}
ALLOWED_EFFECTS = {
"ALLOWED_APPLICATION_WRITE",
"BOUNDED_WATCHDOG",
"EXPLICIT_PROCESS_EXIT",
"EXPECTED_VOLATILE_RUNTIME_EFFECT",
"FAIL_CLOSED_TERMINATION",
"HASH_BOUND_SAME_FD",
"OS_RECLAIMED_ON_EXIT",
"RESTORED_BY_LOADER",
"PAYLOAD_PROCESS_LOCAL",
*HARD_EFFECTS,
}
EXPECTED_PAYLOAD_MANAGER = {
"base_commit": "cfbc70f30f419b09bf2b52283f7409e2d3117ee1",
"hardened_commit": "e23d94ff91233aa770e2342800c1467875bdef44",
"installed": False,
"release": "v0.3.1-chimera-controlled-phase07",
"reproducible": True,
"sha256": "8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1",
"size": 99560,
}
EXPECTED_LOADER = {
"base_commit": "699e8bcff03e91e8d6ca6eba281af25c5a58d8c2",
"hardened_commit": "197623058f509eddde18868dafcb92fdcac66464",
"installed": False,
"release": "v0.23-chimera-phase07",
"reproducible": True,
"sha256": "63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561",
"size": 397000,
}
EXPECTED_SDK = {
"commit": "d2e2e585740362976a39fdd5ccf390f199a7bc37",
"release": "v0.41",
}
def hash_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def deny(reason_codes: list[str], artifact_sha256: str | None = None) -> int:
result: dict[str, Any] = {
"decision": "DENY",
"execution_authorized": False,
"reason_codes": sorted(set(reason_codes)),
"schema_version": 1,
}
if artifact_sha256 is not None:
result["artifact_sha256"] = artifact_sha256
print(json.dumps(result, sort_keys=True))
return 2
def load_json(path: Path) -> dict[str, Any]:
document = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(document, dict):
raise ValueError(f"{path}: root must be an object")
return document
def validate_runtime_profile(
profile: dict[str, Any],
manifest: dict[str, Any],
firmware: str | None,
) -> list[str]:
if profile.get("schema_version") != 1:
raise ValueError("unsupported controlled runtime profile schema")
if profile.get("profile") != "controlled-ps5-runtime":
raise ValueError("unexpected controlled runtime profile")
reasons: list[str] = []
artifact = profile["artifact"]
execution = profile["execution"]
profile_firmware = profile["firmware"]
payload_manager = profile["payload_manager"]
loader = profile["loader"]
sdk = profile["sdk"]
budgets = profile["budgets"]
deployment = profile["deployment"]
effects = profile["effects"]
expected_volatile_effects = profile["expected_volatile_effects"]
blockers = profile["hard_blockers"]
if not all(
isinstance(item, dict)
for item in (
artifact,
execution,
profile_firmware,
payload_manager,
loader,
sdk,
budgets,
deployment,
)
):
raise ValueError("controlled runtime profile contains a malformed object")
if (
not isinstance(effects, list)
or not isinstance(expected_volatile_effects, list)
or not isinstance(blockers, list)
):
raise ValueError("controlled runtime profile arrays are malformed")
if profile.get("decision") != READY_DECISION:
reasons.append("RUNTIME_PROFILE_BLOCKED")
if (
profile.get("execution_authorized") is not False
or execution.get("authorized") is not False
or execution.get("transferred") is not False
or execution.get("executed") is not False
):
reasons.append("RUNTIME_PROFILE_EXECUTION_STATE_INVALID")
if execution.get("execution_eligible") is not True:
reasons.append("RUNTIME_PROFILE_EXECUTION_INELIGIBLE")
if artifact.get("built") is not True:
reasons.append("RUNTIME_PROFILE_ARTIFACT_NOT_BUILT")
if blockers:
reasons.append("RUNTIME_PROFILE_HARD_BLOCKERS_PRESENT")
manifest_artifact = manifest["artifact"]
manifest_source = manifest.get("source")
if not isinstance(manifest_source, dict):
raise ValueError("artifact manifest source record is required")
for key in ("id", "filename", "sha256", "size"):
if artifact.get(key) != manifest_artifact.get(key):
reasons.append("RUNTIME_PROFILE_ARTIFACT_MISMATCH")
source_commit = artifact.get("source_commit")
if (
not isinstance(source_commit, str)
or COMMIT_PATTERN.fullmatch(source_commit) is None
or source_commit != manifest_source.get("commit")
or manifest_source.get("dirty") is not False
):
reasons.append("RUNTIME_PROFILE_SOURCE_COMMIT_MISMATCH")
if firmware is None:
reasons.append("EXACT_FIRMWARE_REQUIRED")
if profile_firmware.get("exact") != "9.60" or firmware != "9.60":
reasons.append("FIRMWARE_MISMATCH")
if profile_firmware.get("evidence") != "jens_explicitly_confirmed_exact_9.60":
reasons.append("FIRMWARE_EVIDENCE_MISMATCH")
for key, value in EXPECTED_PAYLOAD_MANAGER.items():
if payload_manager.get(key) != value:
reasons.append("PAYLOAD_MANAGER_IDENTITY_MISMATCH")
for key, value in EXPECTED_LOADER.items():
if loader.get(key) != value:
reasons.append("LOADER_IDENTITY_MISMATCH")
for key, value in EXPECTED_SDK.items():
if sdk.get(key) != value:
reasons.append("SDK_IDENTITY_MISMATCH")
expected_budgets = {
"automatic_retry": False,
"filesystem_write_budget": "controlled_artifact_directory_only",
"payload_network_access": "none",
"persistent_write_budget": "controlled_artifact_removable",
}
for key, value in expected_budgets.items():
if budgets.get(key) != value:
reasons.append("RUNTIME_BUDGET_MISMATCH")
runtime = budgets.get("maximum_runtime_ms")
if (
not isinstance(runtime, int)
or isinstance(runtime, bool)
or not (1 <= runtime <= 2000)
):
reasons.append("RUNTIME_BUDGET_MISMATCH")
if deployment != {
"installed": False,
"ready_for_installation": True,
"rollback_prepared": True,
}:
reasons.append("DEPLOYMENT_STATE_MISMATCH")
classified_volatile_effects: list[str] = []
effect_ids: set[str] = set()
for item in effects:
if not isinstance(item, dict):
raise ValueError("controlled runtime effect must be an object")
effect_id = item.get("id")
if not isinstance(effect_id, str) or not effect_id or effect_id in effect_ids:
raise ValueError("controlled runtime effect IDs must be unique strings")
effect_ids.add(effect_id)
if item.get("classification") not in ALLOWED_EFFECTS:
raise ValueError("controlled runtime effect classification is invalid")
if item.get("classification") == "EXPECTED_VOLATILE_RUNTIME_EFFECT":
classified_volatile_effects.append(effect_id)
if item.get("classification") in HARD_EFFECTS:
reasons.append("RUNTIME_PROFILE_HARD_EFFECT")
if (
not all(
isinstance(item, str) and item for item in expected_volatile_effects
)
or len(set(expected_volatile_effects)) != len(expected_volatile_effects)
or sorted(expected_volatile_effects) != sorted(classified_volatile_effects)
):
reasons.append("RUNTIME_PROFILE_VOLATILE_EFFECTS_MISMATCH")
return reasons
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--manifest", type=Path, required=True)
parser.add_argument("--denylist", type=Path, required=True)
parser.add_argument("--artifact", type=Path)
parser.add_argument("--runtime-profile", type=Path)
parser.add_argument("--firmware")
args = parser.parse_args()
try:
manifest = load_json(args.manifest)
denylist = load_json(args.denylist)
if manifest.get("schema_version") != 1:
raise ValueError("unsupported artifact manifest schema")
if denylist.get("schema_version") != 1:
raise ValueError("unsupported denylist schema")
if denylist.get("hash_algorithm") != "sha256":
raise ValueError("denylist hash algorithm must be sha256")
if denylist.get("fail_closed") is not True:
raise ValueError("denylist must be fail-closed")
artifact_record = manifest["artifact"]
execution = manifest["execution"]
if not isinstance(artifact_record, dict) or not isinstance(execution, dict):
raise ValueError("manifest artifact and execution records must be objects")
digest = artifact_record["sha256"]
if not isinstance(digest, str) or SHA256_PATTERN.fullmatch(digest) is None:
raise ValueError("manifest artifact SHA-256 is invalid")
if not isinstance(execution.get("execution_eligible"), bool):
raise ValueError("execution_eligible must be an explicit boolean")
if any(
execution.get(key) is not False
for key in ("authorized", "transferred", "executed")
):
reasons = ["MANIFEST_EXECUTION_STATE_INVALID"]
else:
reasons = []
if not isinstance(artifact_record.get("filename"), str):
raise ValueError("artifact filename must be a string")
if (
not isinstance(artifact_record.get("size"), int)
or artifact_record["size"] < 1
):
raise ValueError("artifact size must be a positive integer")
blocked_hashes: set[str] = set()
entries = denylist["entries"]
if not isinstance(entries, list) or not entries:
raise ValueError("denylist entries must be a non-empty array")
for entry in entries:
entry_digest = entry["sha256"]
if not isinstance(entry_digest, str) or SHA256_PATTERN.fullmatch(
entry_digest
) is None:
raise ValueError("denylist contains an invalid SHA-256")
if (
entry.get("status") != "BLOCKED"
or entry.get("permanent") is not True
or entry.get("execution_eligible") is not False
):
raise ValueError("denylist entry is not permanently blocked")
if entry_digest in blocked_hashes:
raise ValueError("denylist contains a duplicate SHA-256")
blocked_hashes.add(entry_digest)
if execution["execution_eligible"] is not True:
reasons.append("MANIFEST_EXECUTION_INELIGIBLE")
if digest in blocked_hashes:
reasons.append("ARTIFACT_PERMANENTLY_DENYLISTED")
if execution["execution_eligible"] is True:
if args.runtime_profile is None:
reasons.append("CONTROLLED_RUNTIME_PROFILE_REQUIRED")
else:
profile = load_json(args.runtime_profile)
reasons.extend(
validate_runtime_profile(profile, manifest, args.firmware)
)
elif args.runtime_profile is not None:
profile = load_json(args.runtime_profile)
reasons.extend(validate_runtime_profile(profile, manifest, args.firmware))
if args.artifact is not None:
artifact = args.artifact.resolve(strict=True)
if not artifact.is_file():
raise ValueError("artifact is not a regular file")
if artifact.name != artifact_record["filename"]:
reasons.append("ARTIFACT_FILENAME_MISMATCH")
if artifact.stat().st_size != artifact_record["size"]:
reasons.append("ARTIFACT_SIZE_MISMATCH")
if hash_file(artifact) != digest:
reasons.append("ARTIFACT_DIGEST_MISMATCH")
else:
reasons.append("ARTIFACT_BYTES_NOT_SUPPLIED")
if reasons:
return deny(reasons, digest)
print(
json.dumps(
{
"artifact_sha256": digest,
"decision": "PASS_STATIC_DEPLOYMENT_ELIGIBILITY_GATE",
"execution_authorized": False,
"reason_codes": [],
"schema_version": 1,
},
sort_keys=True,
)
)
return 0
except (KeyError, OSError, TypeError, ValueError, json.JSONDecodeError):
return deny(["INVALID_OR_INCOMPLETE_POLICY_INPUT"])
if __name__ == "__main__":
raise SystemExit(main())
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Check project-owned C and header files with clang-format."""
from __future__ import annotations
import argparse
import subprocess
from pathlib import Path
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--clang-format", required=True)
args = parser.parse_args()
root = args.root.resolve()
files: list[Path] = []
for directory in ("include", "src", "adapters", "samples", "tests"):
files.extend(sorted((root / directory).rglob("*.c")))
files.extend(sorted((root / directory).rglob("*.h")))
result = subprocess.run(
[args.clang_format, "--dry-run", "--Werror", *map(str, files)],
cwd=root,
check=False,
)
if result.returncode != 0:
return result.returncode
print(f"format check passed across {len(files)} C/header files")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-or-later
set -euo pipefail
if [ "$#" -ne 1 ]; then
echo "Usage: $0 OUTPUT_DIRECTORY" >&2
exit 2
fi
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUTPUT_DIR="$1"
if [ -e "$OUTPUT_DIR" ]; then
echo "Output path already exists: $OUTPUT_DIR" >&2
exit 1
fi
if ! git -C "$ROOT_DIR" -c core.fileMode=false diff --ignore-space-at-eol --quiet \
|| ! git -C "$ROOT_DIR" -c core.fileMode=false diff --cached --quiet; then
echo "Commit or stash repository changes before creating a public export." >&2
exit 1
fi
mkdir -p "$OUTPUT_DIR"
git -C "$ROOT_DIR" archive --format=tar HEAD | tar -xf - -C "$OUTPUT_DIR"
# Agent instructions contain private research-session context and are not part
# of the distributable library or its safety evidence.
find "$OUTPUT_DIR" -type f -name AGENTS.md -delete
for forbidden in \
'.env' '*.pem' '*.key' '*.p12' '*.pfx' '*.db' '*.sqlite' '*.sqlite3' \
'*.elf' '*.self' '*.bin' '*.dmp' '*.core' '*.zip' \
'secret.key' 'id_rsa' 'id_ed25519'; do
if find "$OUTPUT_DIR" -type f -name "$forbidden" -print -quit | grep -q .; then
echo "Forbidden file found in public export: $forbidden" >&2
exit 1
fi
done
if grep -RIlE --exclude='export-public-source.sh' \
'192\.168\.10\.150|NuklearRabbit|C:\\Users\\Jens' "$OUTPUT_DIR" >/dev/null; then
echo "Private operator marker found in public export." >&2
exit 1
fi
if find "$OUTPUT_DIR" -type f -size +10M -print -quit | grep -q .; then
echo "Unexpected file larger than 10 MiB found in public export." >&2
exit 1
fi
git -C "$OUTPUT_DIR" init -q
# The export is created in a fresh repository, so source paths that happen to
# match a diagnostic ignore rule (for example src/core/) must still be added.
git -C "$OUTPUT_DIR" add --force .
git -C "$OUTPUT_DIR" -c user.name='Chimera GFX release export' \
-c user.email='release-export@invalid.example' \
commit -q -m "Publish Chimera GFX source"
EXPECTED_FILES="$(mktemp)"
ACTUAL_FILES="$(mktemp)"
trap 'rm -f "$EXPECTED_FILES" "$ACTUAL_FILES"' EXIT
git -C "$ROOT_DIR" ls-tree -r --name-only HEAD \
| grep -Ev '(^|/)AGENTS\.md$' \
| LC_ALL=C sort > "$EXPECTED_FILES"
git -C "$OUTPUT_DIR" ls-files | LC_ALL=C sort > "$ACTUAL_FILES"
if ! diff -u "$EXPECTED_FILES" "$ACTUAL_FILES"; then
echo "Public export does not contain the complete tracked source tree." >&2
exit 1
fi
(
cd "$OUTPUT_DIR"
git ls-files -z | sort -z | xargs -0 sha256sum > PUBLIC-SOURCE-MANIFEST.sha256
)
git -C "$OUTPUT_DIR" add PUBLIC-SOURCE-MANIFEST.sha256
git -C "$OUTPUT_DIR" -c user.name='Chimera GFX release export' \
-c user.email='release-export@invalid.example' \
commit -q --amend --no-edit
git -C "$OUTPUT_DIR" tag public-release-baseline
echo "Public source export created at $OUTPUT_DIR"
echo "Commit: $(git -C "$OUTPUT_DIR" rev-parse HEAD)"
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Generate a deterministic manifest for a locally built, unexecuted artifact."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37"
SDL_COMMIT = "0baf4ac49382b537ba449901b5b6d0d189bb1fbb"
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--artifact", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--id", required=True)
parser.add_argument("--version", required=True)
parser.add_argument("--source-repository", required=True)
parser.add_argument("--source-commit", required=True)
parser.add_argument("--target", required=True)
parser.add_argument("--firmware", default="NONE")
parser.add_argument("--profile", required=True)
parser.add_argument("--execution-eligible", action="store_true")
parser.add_argument("--with-sdl", action="store_true")
parser.add_argument("--note", action="append", default=[])
args = parser.parse_args()
artifact = args.artifact.resolve(strict=True)
if not artifact.is_file() or artifact.stat().st_size == 0:
raise SystemExit("artifact must be a non-empty regular file")
if len(args.source_commit) != 40 or any(
character not in "0123456789abcdef" for character in args.source_commit
):
raise SystemExit("source commit must be a lowercase 40-character SHA-1")
toolchain = {
"ps5_payload_sdk_release": "v0.41",
"ps5_payload_sdk_commit": SDK_COMMIT,
}
if args.with_sdl:
toolchain["sdl_commit"] = SDL_COMMIT
document = {
"schema_version": 1,
"artifact": {
"id": args.id,
"version": args.version,
"filename": artifact.name,
"size": artifact.stat().st_size,
"sha256": sha256(artifact),
"target": args.target,
},
"source": {
"repository": args.source_repository,
"commit": args.source_commit,
"dirty": False,
},
"toolchain": toolchain,
"firmware_gate": {
"embedded_identifier": args.firmware,
"allowlisted": args.firmware != "NONE",
},
"execution": {
"execution_eligible": args.execution_eligible,
"authorized": False,
"transferred": False,
"executed": False,
},
"safety": {
"profile": args.profile,
"direct_gnm_imports": 0,
"notes": args.note,
},
}
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(
json.dumps(document, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Generate the C X-macro list from the read-only JSON manifest."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
def render(manifest_path: Path) -> str:
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
symbols = manifest["symbols"]
lines = ["/* Generated from manifests/ps5_gnm_symbols.json. Do not edit. */"]
lines.extend(f'CHIMERA_GNM_SYMBOL("{entry["name"]}")' for entry in symbols)
return "\n".join(lines) + "\n"
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--manifest", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--check", action="store_true")
args = parser.parse_args()
expected = render(args.manifest)
if args.check:
if not args.output.exists() or args.output.read_text(encoding="utf-8") != expected:
print(f"stale generated file: {args.output}")
return 1
print(f"generated file is current: {args.output}")
return 0
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(expected, encoding="utf-8", newline="\n")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+509
View File
@@ -0,0 +1,509 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Read-only, host-only parser for bounded PS5 SIECAF structural metadata.
This module never decrypts, extracts content, invokes ps5-bar-tool, opens a
network connection, or writes an output file. The byte layout is based on:
* https://www.psdevwiki.com/ps5/Archive.dat
* c0w-ar/ps5-bar-tool include/bar_file.h at
36d014672bc87577a6e0d750c2cccadc3fae0854
"""
from __future__ import annotations
import argparse
from contextlib import contextmanager
import hashlib
import json
from pathlib import Path
import struct
from typing import Any, BinaryIO, Iterator
import zipfile
MAGIC = b"SIECAF\x00\x00"
HEADER = struct.Struct("<8sQiIiI16s12sIQQQ")
SEGMENT_META = struct.Struct("<iHHQQQQ12sIQ")
SECTION_HASH = struct.Struct("<ii16s24s")
ALIGNMENT = 0x10000
UINT64_MAX = (1 << 64) - 1
SUPPORTED_VERSIONS = frozenset({3, 6})
class SiecafError(ValueError):
"""A fail-closed SIECAF structural error."""
def _sha256(value: bytes) -> str:
return hashlib.sha256(value).hexdigest()
def _checked_add(left: int, right: int, label: str) -> int:
result = left + right
if left < 0 or right < 0 or result > UINT64_MAX:
raise SiecafError(f"{label}: uint64 addition overflow")
return result
def _checked_mul(left: int, right: int, label: str) -> int:
result = left * right
if left < 0 or right < 0 or result > UINT64_MAX:
raise SiecafError(f"{label}: uint64 multiplication overflow")
return result
def _read_exact(stream: BinaryIO, size: int, label: str) -> bytes:
value = stream.read(size)
if len(value) != size:
raise SiecafError(f"{label}: truncated input")
return value
def _canonical_hash(records: list[dict[str, Any]]) -> str:
encoded = json.dumps(
records, sort_keys=True, separators=(",", ":"), ensure_ascii=True
).encode("ascii")
return _sha256(encoded)
def inspect_siecaf(
stream: BinaryIO, source_size: int, *, source_label: str = "<stream>"
) -> dict[str, Any]:
"""Parse structural metadata from an already-open, read-only stream."""
if source_size < HEADER.size:
return {
"source": source_label,
"source_size": source_size,
"classification": "SIECAF_MALFORMED",
"errors": ["header: truncated input"],
"warnings": [],
}
stream.seek(0)
header_raw = _read_exact(stream, HEADER.size, "header")
(
magic,
unknown_u64,
mode,
pad1,
version,
pad2,
key,
iv12,
pad3,
segment_count,
file_offset,
file_size,
) = HEADER.unpack(header_raw)
header = {
"magic_hex": magic.hex(),
"magic_ascii": magic.rstrip(b"\x00").decode("ascii", errors="replace"),
"unknown_u64": unknown_u64,
"mode_i32": mode,
"padding_1_u32": pad1,
"version_i32": version,
"padding_2_u32": pad2,
"key_or_unknown_16_redacted": True,
"key_or_unknown_16_sha256": _sha256(key),
"iv_12_hex": iv12.hex(),
"padding_3_u32": pad3,
"segment_count": segment_count,
"file_offset": file_offset,
"file_size": file_size,
"raw_sha256": _sha256(header_raw),
}
if magic != MAGIC:
return {
"source": source_label,
"source_size": source_size,
"classification": "SIECAF_MALFORMED",
"header": header,
"errors": ["magic: expected SIECAF\\0\\0"],
"warnings": [],
}
if version not in SUPPORTED_VERSIONS:
return {
"source": source_label,
"source_size": source_size,
"classification": "SIECAF_UNSUPPORTED_VERSION",
"header": header,
"errors": [f"unsupported SIECAF header version: {version}"],
"warnings": [],
}
errors: list[str] = []
warnings: list[str] = []
if segment_count == 0:
errors.append("segment_count: zero")
try:
metadata_bytes = _checked_mul(
segment_count, SEGMENT_META.size, "segment metadata table"
)
hash_bytes = _checked_mul(
segment_count, SECTION_HASH.size, "section hash table"
)
metadata_end = _checked_add(HEADER.size, metadata_bytes, "metadata end")
tables_end = _checked_add(metadata_end, hash_bytes, "tables end")
declared_end = _checked_add(file_offset, file_size, "declared file end")
except SiecafError as error:
return {
"source": source_label,
"source_size": source_size,
"classification": "SIECAF_MALFORMED",
"header": header,
"errors": [str(error)],
"warnings": [],
}
if tables_end > source_size:
errors.append("tables: outside source file")
if tables_end > file_offset:
errors.append("tables: overlap declared data region")
if file_offset % ALIGNMENT != 0:
errors.append(f"file_offset: not aligned to {ALIGNMENT}")
if declared_end > source_size:
errors.append("declared file range: outside source file")
elif declared_end < source_size:
warnings.append(
f"trailing data after declared file range: {source_size - declared_end}"
)
if errors:
return {
"source": source_label,
"source_size": source_size,
"classification": "SIECAF_MALFORMED",
"header": header,
"tables_end": tables_end,
"errors": errors,
"warnings": warnings,
}
metadata: list[dict[str, Any]] = []
for index in range(segment_count):
raw = _read_exact(stream, SEGMENT_META.size, f"segment metadata {index}")
(
section_id,
padding_1,
part_number,
data_offset,
aligned_length,
hash_key_id,
encryption_key_id,
segment_iv12,
segment_iv_padding,
unaligned_length,
) = SEGMENT_META.unpack(raw)
iv16 = segment_iv12 + struct.pack("<I", segment_iv_padding)
metadata.append(
{
"table_index": index,
"section_id": section_id,
"padding_1_u16": padding_1,
"part_number": part_number,
"data_offset": data_offset,
"aligned_length": aligned_length,
"unaligned_length": unaligned_length,
"hash_key_id_or_algorithm_type": hash_key_id,
"encryption_key_id_or_algorithm_version": encryption_key_id,
"iv_hex": iv16.hex(),
"raw_sha256": _sha256(raw),
}
)
hashes: list[dict[str, Any]] = []
for index in range(segment_count):
raw = _read_exact(stream, SECTION_HASH.size, f"section hash {index}")
section_id, section_type, section_hash, padding = SECTION_HASH.unpack(raw)
hashes.append(
{
"table_index": index,
"section_id": section_id,
"section_type": section_type,
"section_hash_128_hex": section_hash.hex(),
"padding_hex": padding.hex(),
"raw_sha256": _sha256(raw),
}
)
metadata_keys = [(item["section_id"], item["part_number"]) for item in metadata]
metadata_ids = [item["section_id"] for item in metadata]
hash_ids = [item["section_id"] for item in hashes]
duplicate_metadata_ids = sorted(
{
section_id
for section_id, part_number in metadata_keys
if metadata_keys.count((section_id, part_number)) > 1
}
)
duplicate_metadata_keys = sorted(
{
(section_id, part_number)
for section_id, part_number in metadata_keys
if metadata_keys.count((section_id, part_number)) > 1
}
)
repeated_metadata_ids = sorted(
{item for item in metadata_ids if metadata_ids.count(item) > 1}
)
duplicate_hash_ids = sorted({item for item in hash_ids if hash_ids.count(item) > 1})
if duplicate_metadata_ids:
errors.append(
f"duplicate metadata section ID/part keys: {duplicate_metadata_keys}"
)
if duplicate_hash_ids:
errors.append(f"duplicate hash section IDs: {duplicate_hash_ids}")
if set(hash_ids) != set(range(segment_count)):
errors.append("hash section IDs do not cover metadata table indexes")
hash_by_id = {
item["section_id"]: item
for item in hashes
if item["section_id"] not in duplicate_hash_ids
}
ranges: list[tuple[int, int, int]] = []
for item in metadata:
section_id = item["section_id"]
start = item["data_offset"]
length = item["aligned_length"]
unaligned = item["unaligned_length"]
try:
end = _checked_add(start, length, f"section {section_id} end")
except SiecafError as error:
errors.append(str(error))
continue
if section_id < 0:
errors.append(f"section {section_id}: negative ID")
if start % ALIGNMENT != 0:
errors.append(f"section {section_id}: unaligned data offset")
if length == 0 and unaligned != 0:
errors.append(f"section {section_id}: incoherent unaligned length")
if length > 0 and length % ALIGNMENT != 0:
errors.append(f"section {section_id}: incoherent aligned length")
if length > 0 and (unaligned > length or length - unaligned >= ALIGNMENT):
errors.append(f"section {section_id}: incoherent unaligned length")
if start < file_offset or end > declared_end or end > source_size:
errors.append(f"section {section_id}: range outside declared file data")
if length > 0:
ranges.append((start, end, section_id))
hash_record = hash_by_id.get(item["table_index"])
item["section_type"] = (
hash_record["section_type"] if hash_record is not None else None
)
item["section_hash_128_hex"] = (
hash_record["section_hash_128_hex"] if hash_record is not None else None
)
ranges.sort()
overlaps: list[dict[str, int]] = []
gaps: list[dict[str, int]] = []
previous_end = file_offset
previous_id = -1
for start, end, section_id in ranges:
if start < previous_end:
overlaps.append(
{
"left_section_id": previous_id,
"right_section_id": section_id,
"overlap_bytes": previous_end - start,
}
)
elif start > previous_end:
gaps.append(
{
"after_section_id": previous_id,
"before_section_id": section_id,
"gap_bytes": start - previous_end,
}
)
if end > previous_end:
previous_end = end
previous_id = section_id
if overlaps:
errors.append(f"overlapping section ranges: {len(overlaps)}")
if gaps:
warnings.append(f"gaps between section ranges: {len(gaps)}")
trailing_data = max(0, source_size - previous_end)
if trailing_data:
warnings.append(f"trailing data after final section: {trailing_data}")
if previous_end < declared_end:
warnings.append(
f"uncovered bytes inside declared data range: {declared_end - previous_end}"
)
normalized_segments = [
{
key: item[key]
for key in (
"section_id",
"part_number",
"data_offset",
"aligned_length",
"unaligned_length",
"hash_key_id_or_algorithm_type",
"encryption_key_id_or_algorithm_version",
"iv_hex",
)
}
for item in sorted(
metadata,
key=lambda value: (
value["section_id"],
value["part_number"],
value["data_offset"],
),
)
]
normalized_hashes = [
{
key: item[key]
for key in ("section_id", "section_type", "section_hash_128_hex")
}
for item in sorted(
hashes, key=lambda value: (value["section_id"], value["section_type"])
)
]
normalized_layout = [
{
key: item[key]
for key in (
"section_id",
"part_number",
"data_offset",
"aligned_length",
"unaligned_length",
"hash_key_id_or_algorithm_type",
"encryption_key_id_or_algorithm_version",
)
}
for item in normalized_segments
]
normalized_segment_table_sha256 = _canonical_hash(normalized_segments)
normalized_hash_blocks_sha256 = _canonical_hash(normalized_hashes)
normalized_layout_sha256 = _canonical_hash(
[
{
"unknown_u64": unknown_u64,
"version_i32": version,
"segment_count": segment_count,
"file_offset": file_offset,
"file_size": file_size,
},
*normalized_layout,
]
)
structural_fingerprint_sha256 = _canonical_hash(
[
{
"header_raw_sha256": header["raw_sha256"],
"normalized_segment_table_sha256": (normalized_segment_table_sha256),
"normalized_hash_blocks_sha256": normalized_hash_blocks_sha256,
}
]
)
return {
"source": source_label,
"source_size": source_size,
"classification": ("SIECAF_MALFORMED" if errors else "SIECAF_VALID_STRUCTURE"),
"header": header,
"tables_end": tables_end,
"table_padding_bytes": file_offset - tables_end,
"segments": sorted(metadata, key=lambda item: item["table_index"]),
"section_hashes": sorted(hashes, key=lambda item: item["table_index"]),
"normalized_segment_table_sha256": normalized_segment_table_sha256,
"normalized_hash_blocks_sha256": normalized_hash_blocks_sha256,
"normalized_layout_sha256": normalized_layout_sha256,
"structural_fingerprint_sha256": structural_fingerprint_sha256,
"duplicate_metadata_section_ids": duplicate_metadata_ids,
"duplicate_metadata_section_keys": [
{"section_id": section_id, "part_number": part_number}
for section_id, part_number in duplicate_metadata_keys
],
"repeated_metadata_section_ids": repeated_metadata_ids,
"duplicate_hash_section_ids": duplicate_hash_ids,
"overlaps": overlaps,
"gaps": gaps,
"trailing_data_bytes": trailing_data,
"errors": errors,
"warnings": warnings,
}
def compare_structures(left: dict[str, Any], right: dict[str, Any]) -> dict[str, Any]:
"""Classify two already-parsed structural fingerprints."""
if (
left.get("classification") == "SIECAF_UNSUPPORTED_VERSION"
or right.get("classification") == "SIECAF_UNSUPPORTED_VERSION"
):
classification = "SIECAF_UNSUPPORTED_VERSION"
elif (
left.get("classification") != "SIECAF_VALID_STRUCTURE"
or right.get("classification") != "SIECAF_VALID_STRUCTURE"
):
classification = "SIECAF_MALFORMED"
elif left.get("structural_fingerprint_sha256") == right.get(
"structural_fingerprint_sha256"
):
classification = "SIECAF_STRUCTURAL_EXACT"
elif left.get("normalized_layout_sha256") == right.get("normalized_layout_sha256"):
classification = "SIECAF_LAYOUT_MATCH_HASHES_DIFFER"
else:
classification = "SIECAF_LAYOUT_DIFFERENT"
return {
"classification": classification,
"left_structural_fingerprint_sha256": left.get("structural_fingerprint_sha256"),
"right_structural_fingerprint_sha256": right.get(
"structural_fingerprint_sha256"
),
"left_layout_sha256": left.get("normalized_layout_sha256"),
"right_layout_sha256": right.get("normalized_layout_sha256"),
"left_hash_blocks_sha256": left.get("normalized_hash_blocks_sha256"),
"right_hash_blocks_sha256": right.get("normalized_hash_blocks_sha256"),
}
@contextmanager
def open_source(
path: Path, zip_entry: str | None
) -> Iterator[tuple[BinaryIO, int, str]]:
if zip_entry is None:
with path.open("rb") as stream:
yield stream, path.stat().st_size, str(path)
return
with zipfile.ZipFile(path) as archive:
info = archive.getinfo(zip_entry)
with archive.open(info) as stream:
yield stream, info.file_size, f"{path}::{zip_entry}"
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("path", type=Path)
parser.add_argument("--zip-entry")
parser.add_argument("--label")
parser.add_argument("--pretty", action="store_true")
args = parser.parse_args()
try:
with open_source(args.path.resolve(), args.zip_entry) as (
stream,
size,
default_label,
):
result = inspect_siecaf(
stream, size, source_label=args.label or default_label
)
except (OSError, KeyError, zipfile.BadZipFile, SiecafError) as error:
result = {
"source": args.label or str(args.path),
"classification": "SIECAF_MALFORMED",
"errors": [str(error)],
"warnings": [],
}
print(
json.dumps(
result,
sort_keys=True,
indent=2 if args.pretty else None,
)
)
return 0 if result["classification"] == "SIECAF_VALID_STRUCTURE" else 2
if __name__ == "__main__":
raise SystemExit(main())
+253
View File
@@ -0,0 +1,253 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Create deterministic, offline-only Phase-0.7 review archives."""
from __future__ import annotations
import argparse
import hashlib
import json
import shutil
import subprocess
import zipfile
from pathlib import Path
ARCHIVE_TIMESTAMP = (2026, 7, 17, 0, 0, 0)
ARTIFACTS = {
"chimera-elfldr-phase07.elf": {
"source": "outputs/phase07/artifacts/chimera-elfldr-phase07-a.elf",
"sha256": "63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561",
"size": 397000,
},
"chimera-gfx-lifecycle-probe.elf": {
"source": "outputs/phase07/artifacts/chimera-gfx-lifecycle-probe.elf",
"sha256": "bfb4a5cc768e162fe4c2fddf41c3978e152722918a39085277fd172cb95a7182",
"size": 112680,
},
"chimera-payload-manager-phase07.elf": {
"source": "outputs/phase07/artifacts/chimera-pldmgr-phase07-a.elf",
"sha256": "8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1",
"size": 99560,
},
}
STOCK_ELFLDR = {
"source": "work/upstream/release-assets/elfldr-ps5-v0.23.elf",
"sha256": "092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8",
"size": 397000,
}
BLOCKED_SHA256 = (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
)
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def verify(path: Path, expected: dict[str, object]) -> None:
if not path.is_file():
raise RuntimeError(f"missing package input: {path}")
if path.stat().st_size != expected["size"]:
raise RuntimeError(f"unexpected size: {path}")
if sha256(path) != expected["sha256"]:
raise RuntimeError(f"unexpected SHA-256: {path}")
def copy(root: Path, relative_source: str, destination: Path) -> None:
source = root / relative_source
if not source.is_file():
raise RuntimeError(f"missing package input: {source}")
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(source, destination)
def write_json(path: Path, document: object) -> None:
path.write_text(
json.dumps(document, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
newline="\n",
)
def write_sums(directory: Path) -> None:
entries = []
for path in sorted(directory.rglob("*")):
if path.is_file() and path.name != "SHA256SUMS.txt":
relative = path.relative_to(directory).as_posix()
entries.append(f"{sha256(path)} {relative}")
(directory / "SHA256SUMS.txt").write_text(
"\n".join(entries) + "\n", encoding="utf-8", newline="\n"
)
def deterministic_zip(source: Path, destination: Path) -> None:
with zipfile.ZipFile(
destination, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9
) as archive:
for path in sorted(source.rglob("*")):
if not path.is_file():
continue
relative = (Path(source.name) / path.relative_to(source)).as_posix()
info = zipfile.ZipInfo(relative, ARCHIVE_TIMESTAMP)
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = 0o100644 << 16
archive.writestr(info, path.read_bytes(), compresslevel=9)
def clean_destination(root: Path, destination: Path) -> None:
resolved_root = root.resolve()
resolved = destination.resolve()
if resolved_root not in resolved.parents:
raise RuntimeError(f"refusing destination outside repository: {resolved}")
if destination.exists():
shutil.rmtree(destination)
def git_head(root: Path) -> str:
status = subprocess.run(
["git", "status", "--porcelain", "--untracked-files=no"],
cwd=root,
check=True,
capture_output=True,
text=True,
)
if status.stdout.strip():
raise RuntimeError("tracked worktree must be clean before packaging")
result = subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=root,
check=True,
capture_output=True,
text=True,
)
return result.stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
head = git_head(root)
packages = root / "outputs" / "phase07" / "packages"
installation = packages / "phase07-installation-review"
rollback = packages / "phase07-rollback-review"
clean_destination(root, installation)
clean_destination(root, rollback)
packages.mkdir(parents=True, exist_ok=True)
for filename, expected in ARTIFACTS.items():
source = root / str(expected["source"])
verify(source, expected)
copy(root, str(expected["source"]), installation / "artifacts" / filename)
review_files = [
"docs/approvals/phase07-hardened-installation-request.md",
"docs/approvals/phase07-lifecycle-transfer-execution-request.md",
"docs/runtime/phase-0.7-hardening.md",
"docs/runtime/controlled-runtime-policy.md",
"manifests/artifact-denylist.json",
"manifests/artifacts/chimera-elfldr-phase07-fw-9.60.json",
"manifests/artifacts/chimera-gfx-lifecycle-probe-phase07-fw-9.60.json",
"manifests/artifacts/chimera-payload-manager-phase07-fw-9.60.json",
"manifests/runtime/controlled-ps5-runtime-profile.json",
"manifests/runtime/phase-0.7-kernelwrite-proof-matrix.json",
"manifests/runtime/phase-0.7-offline-audit.json",
"packaging/phase07/README-installation-review.md",
]
for relative in review_files:
copy(root, relative, installation / relative)
audit_directory = root / "outputs" / "phase07" / "audit"
if not audit_directory.is_dir():
raise RuntimeError("full Phase-0.7 audit reports are absent")
(installation / "audit").mkdir(parents=True, exist_ok=True)
for report in sorted(audit_directory.glob("*")):
if report.is_file():
shutil.copyfile(report, installation / "audit" / report.name)
install_manifest = {
"artifacts": {
name: {
"sha256": item["sha256"],
"size": item["size"],
}
for name, item in ARTIFACTS.items()
},
"blocked_sha256": BLOCKED_SHA256,
"decision": "READY_FOR_HARDENED_RUNTIME_DEPLOYMENT",
"execution_authorized": False,
"firmware": "9.60",
"installation_authorized": False,
"repository_head": head,
"schema_version": 1,
}
write_json(installation / "PACKAGE-MANIFEST.json", install_manifest)
write_sums(installation)
stock_source = root / str(STOCK_ELFLDR["source"])
verify(stock_source, STOCK_ELFLDR)
copy(
root,
str(STOCK_ELFLDR["source"]),
rollback / "stock" / "elfldr-ps5-v0.23.elf",
)
copy(
root,
"packaging/phase07/README-rollback.md",
rollback / "README-rollback.md",
)
rollback_manifest = {
"existing_payload_manager_backup": {
"available_offline": False,
"required_before_installation": True,
"sha256": "518740adbacccb9094fadb07dd424c53ee290f38306449ccc9d6957fdf813c0b",
"size": 2050320,
},
"installation_authorized": False,
"repository_head": head,
"rollback_authorized": False,
"schema_version": 1,
"stock_elfldr": {
"available_offline": True,
"sha256": STOCK_ELFLDR["sha256"],
"size": STOCK_ELFLDR["size"],
},
}
write_json(rollback / "ROLLBACK-MANIFEST.json", rollback_manifest)
write_sums(rollback)
installation_zip = packages / "phase07-installation-review.zip"
rollback_zip = packages / "phase07-rollback-review.zip"
for archive in (installation_zip, rollback_zip):
if archive.exists():
archive.unlink()
deterministic_zip(installation, installation_zip)
deterministic_zip(rollback, rollback_zip)
package_index = {
"archives": {
installation_zip.name: {
"sha256": sha256(installation_zip),
"size": installation_zip.stat().st_size,
},
rollback_zip.name: {
"sha256": sha256(rollback_zip),
"size": rollback_zip.stat().st_size,
},
},
"execution_authorized": False,
"installation_authorized": False,
"repository_head": head,
"schema_version": 1,
}
write_json(packages / "package-index.json", package_index)
print(json.dumps(package_index, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
+287
View File
@@ -0,0 +1,287 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline Phase-1.0AA integration for the passive batch contract.
Only the exact built-in fake adapter and synthetic clock are accepted. This
module has no live adapter protocol, network import, address, CLI or real clock.
"""
from __future__ import annotations
from dataclasses import dataclass
import hashlib
import math
from typing import Any
from phase10w_shsrv_client_policy import SessionPlan
from phase10x_inactive_transport import (
EvidenceFailure,
EvidenceRecord,
ExclusiveEvidenceStore,
)
from phase10z_passive_batch_contract import (
PassiveBatch,
PassiveContractError,
PassiveResultAccumulator,
build_passive_batch,
)
PHASE10Z_CONTRACT_SHA256 = \
"0728c2be7f368e0a7f4b68efe86f6e0c5c2f50704a41d0e1992b0bfec19dde06"
MAX_FAKE_EVENTS = 257
MAX_FAKE_ADVANCE_SECONDS = 60.0
EVENT_DATA = "DATA"
EVENT_HARD_DEADLINE = "HARD_DEADLINE"
EVENT_REMOTE_EOF = "REMOTE_EOF"
EVENT_BLOCKED = "BLOCKED"
EVENT_KINDS = {
EVENT_DATA, EVENT_HARD_DEADLINE, EVENT_REMOTE_EOF, EVENT_BLOCKED,
}
class OfflineIntegrationError(RuntimeError):
"""Normalized offline failure without supplied data, target or path."""
class FakeAdapterError(RuntimeError):
"""Built-in fake-adapter state failure."""
@dataclass(frozen=True)
class FakeReceiveEvent:
"""One caller-supplied synthetic event; never a live receive result."""
kind: str
data: bytes = b""
advance_seconds: float = 0.0
def __post_init__(self) -> None:
if self.kind not in EVENT_KINDS:
raise FakeAdapterError("fake event kind is invalid")
if not isinstance(self.data, bytes):
raise FakeAdapterError("fake event data must be bytes")
if self.kind == EVENT_DATA and not self.data:
raise FakeAdapterError("fake data event is empty")
if self.kind != EVENT_DATA and self.data:
raise FakeAdapterError("fake control event contains data")
value = self.advance_seconds
if not isinstance(value, (int, float)) or isinstance(value, bool) or \
not math.isfinite(value) or not 0.0 <= value <= \
MAX_FAKE_ADVANCE_SECONDS:
raise FakeAdapterError("fake time advance is invalid")
class OfflineFakeClock:
"""Explicit synthetic monotonic value; never acquires host time."""
def __init__(self, initial: float = 0.0) -> None:
if not isinstance(initial, (int, float)) or isinstance(initial, bool) or \
not math.isfinite(initial):
raise FakeAdapterError("fake clock initial value is invalid")
self._value = float(initial)
def monotonic(self) -> float:
return self._value
def advance(self, seconds: float) -> None:
if not isinstance(seconds, (int, float)) or isinstance(seconds, bool) or \
not math.isfinite(seconds) or not 0.0 <= seconds <= \
MAX_FAKE_ADVANCE_SECONDS:
raise FakeAdapterError("fake clock advance is invalid")
self._value += float(seconds)
class OfflineFakeBatchAdapter:
"""Closed fake only: one open, one exact batch and scripted events."""
def __init__(
self, clock: OfflineFakeClock, events: tuple[FakeReceiveEvent, ...],
) -> None:
if type(clock) is not OfflineFakeClock:
raise FakeAdapterError("only the exact fake clock is accepted")
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_FAKE_EVENTS:
raise FakeAdapterError("fake event sequence is invalid")
if any(type(event) is not FakeReceiveEvent for event in events):
raise FakeAdapterError("fake event type is invalid")
self.clock = clock
self._events = list(events)
self.state = "NEW"
self.open_count = 0
self.send_count = 0
self.close_count = 0
self.sent_sha256: str | None = None
self.trace: list[str] = []
self.logical_event_buffer_discarded = False
def open_once(self) -> None:
if self.state != "NEW":
raise FakeAdapterError("fake adapter cannot open")
self.open_count += 1
self.trace.append("FAKE_OPEN")
self.state = "OPEN"
def send_one_batch(self, batch: PassiveBatch) -> None:
if self.state != "OPEN" or type(batch) is not PassiveBatch:
raise FakeAdapterError("fake adapter cannot accept a batch")
self.send_count += 1
if self.send_count != 1:
raise FakeAdapterError("second fake send is forbidden")
self.sent_sha256 = hashlib.sha256(batch.payload).hexdigest()
self.trace.append("FAKE_SEND_ONE_BATCH")
self.state = "SENT"
def next_event(self) -> FakeReceiveEvent:
if self.state not in {"SENT", "RECEIVING"} or not self._events:
raise FakeAdapterError("fake adapter has no next event")
event = self._events.pop(0)
self.clock.advance(event.advance_seconds)
self.trace.append(f"FAKE_EVENT_{event.kind}")
self.state = "RECEIVING"
return event
def close_once(self) -> None:
if self.state not in {"OPEN", "SENT", "RECEIVING"}:
raise FakeAdapterError("fake adapter cannot close")
self.close_count += 1
if self.close_count != 1:
raise FakeAdapterError("second fake close is forbidden")
self._events.clear()
self.logical_event_buffer_discarded = True
self.trace.append("FAKE_CLOSE")
self.state = "CLOSED"
class OfflineFakeEvidenceStore(ExclusiveEvidenceStore):
"""Phase-specific exclusive local evidence; no raw transcript."""
def create_fake_consumed_receipt(
self, plan: SessionPlan, batch: PassiveBatch, start: float,
) -> EvidenceRecord:
return self._create(f"{plan.run_id}.aa-consumed.json", {
"schema_version": 1,
"status": "OFFLINE_FAKE_ATTEMPT_CONSUMED_BEFORE_OPEN",
"run_id": plan.run_id,
"phase10z_contract_sha256": PHASE10Z_CONTRACT_SHA256,
"window": batch.window,
"batch_sha256": hashlib.sha256(batch.payload).hexdigest(),
"batch_size": len(batch.payload),
"deadline_seconds": batch.deadline_seconds,
"created_fake_monotonic": start,
"target_retained": False,
"raw_transcript_persisted": False,
"retry_allowed": False,
"reconnect_allowed": False,
"resume_allowed": False,
"device_behavior_proven": False,
})
@dataclass(frozen=True)
class OfflineFakeOutcome:
receipt: EvidenceRecord
output: EvidenceRecord
classification: str
exact_identity: bool
batch_sha256: str
trace: tuple[str, ...]
fake_only: bool = True
device_behavior_proven: bool = False
def run_offline_fake_batch(
plan: SessionPlan,
adapter: OfflineFakeBatchAdapter,
clock: OfflineFakeClock,
evidence: OfflineFakeEvidenceStore,
) -> OfflineFakeOutcome:
"""Exercise Z end-to-end with exact built-in fakes and local evidence."""
if type(adapter) is not OfflineFakeBatchAdapter or \
type(clock) is not OfflineFakeClock or \
type(evidence) is not OfflineFakeEvidenceStore or \
adapter.clock is not clock:
raise OfflineIntegrationError("offline fake boundary type is invalid")
try:
batch = build_passive_batch(plan)
except PassiveContractError as error:
raise OfflineIntegrationError("passive batch preparation failed") from error
start = clock.monotonic()
deadline = start + batch.deadline_seconds
try:
receipt = evidence.create_fake_consumed_receipt(plan, batch, start)
except EvidenceFailure as error:
raise OfflineIntegrationError("offline receipt creation failed") from error
trace = ["RECEIPT_CREATED"]
accumulator = PassiveResultAccumulator(batch)
sanitized: dict[str, Any] | None = None
opened = False
failure: OfflineIntegrationError | None = None
try:
opened = True
adapter.open_once()
trace.extend(adapter.trace[-1:])
if clock.monotonic() >= deadline:
raise OfflineIntegrationError("deadline reached before fake send")
adapter.send_one_batch(batch)
trace.extend(adapter.trace[-1:])
for _index in range(MAX_FAKE_EVENTS):
event = adapter.next_event()
trace.extend(adapter.trace[-1:])
now = clock.monotonic()
if event.kind == EVENT_DATA:
if now >= deadline:
raise OfflineIntegrationError("fake data reached deadline")
accumulator.feed_supplied_chunk(event.data)
continue
if event.kind == EVENT_HARD_DEADLINE:
if now < deadline:
raise OfflineIntegrationError("fake deadline arrived early")
sanitized = accumulator.seal_at_hard_deadline(True)
break
if event.kind == EVENT_REMOTE_EOF:
raise OfflineIntegrationError("remote EOF is not completion")
if event.kind == EVENT_BLOCKED:
raise OfflineIntegrationError("blocked fake receive is invalid")
if sanitized is None:
raise OfflineIntegrationError("hard deadline result is missing")
except Exception as error: # noqa: BLE001 - exact fake boundary normalization
failure = OfflineIntegrationError("offline fake integration failed")
failure.__cause__ = error
finally:
if opened:
try:
adapter.close_once()
trace.extend(adapter.trace[-1:])
except FakeAdapterError as error:
if failure is None:
failure = OfflineIntegrationError("offline fake close failed")
failure.__cause__ = error
if failure is not None:
raise failure
if sanitized is None or adapter.sent_sha256 is None:
raise OfflineIntegrationError("offline fake result is incomplete")
sanitized["phase10aa_fake_integration"] = {
"offline_fake_only": True,
"exact_builtin_adapter_required": True,
"exact_builtin_clock_required": True,
"receipt_created_before_fake_open": True,
"one_fake_open": adapter.open_count == 1,
"one_fake_batch_send": adapter.send_count == 1,
"one_fake_close": adapter.close_count == 1,
"logical_event_buffer_discarded": adapter.logical_event_buffer_discarded,
"physical_memory_erasure_proven": False,
"network_transport_present": False,
"device_behavior_proven": False,
}
try:
output = evidence.create_sanitized_output(plan, receipt, sanitized)
except EvidenceFailure as error:
raise OfflineIntegrationError("offline sanitized output failed") from error
return OfflineFakeOutcome(
receipt=receipt,
output=output,
classification=str(sanitized["classification"]),
exact_identity=bool(sanitized["exact_identity"]),
batch_sha256=adapter.sent_sha256,
trace=tuple(trace),
)
+218
View File
@@ -0,0 +1,218 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Pure offline trace model for a future nonblocking host adapter.
No socket, selector, address, DNS, OS call, real clock, CLI or file output is
present. The model only validates caller-supplied synthetic operation traces.
"""
from __future__ import annotations
from dataclasses import dataclass
import math
MAX_TRACE_EVENTS = 512
MAX_BATCH_BYTES = 1035
MAX_RECEIVE_BYTES = 65_536
MAX_DEADLINE_SECONDS = 10.0
RECEIPT_CREATED = "RECEIPT_CREATED"
SOCKET_CREATED = "SOCKET_CREATED"
SET_NONBLOCKING = "SET_NONBLOCKING"
CONNECT_IMMEDIATE = "CONNECT_IMMEDIATE"
CONNECT_PENDING = "CONNECT_PENDING"
READY_WRITE = "READY_WRITE"
SO_ERROR_ZERO = "SO_ERROR_ZERO"
SEND_BYTES = "SEND_BYTES"
READY_READ = "READY_READ"
RECV_BYTES = "RECV_BYTES"
RECV_EOF = "RECV_EOF"
WAIT_INTERRUPTED = "WAIT_INTERRUPTED"
WAIT_TIMEOUT = "WAIT_TIMEOUT"
DEADLINE_REACHED = "DEADLINE_REACHED"
SANITIZER_ACCEPTED = "SANITIZER_ACCEPTED"
LOCAL_CLOSE = "LOCAL_CLOSE"
OUTPUT_CREATED = "OUTPUT_CREATED"
OPERATIONS = {
RECEIPT_CREATED, SOCKET_CREATED, SET_NONBLOCKING, CONNECT_IMMEDIATE,
CONNECT_PENDING, READY_WRITE, SO_ERROR_ZERO, SEND_BYTES, READY_READ,
RECV_BYTES, RECV_EOF, WAIT_INTERRUPTED, WAIT_TIMEOUT, DEADLINE_REACHED,
SANITIZER_ACCEPTED, LOCAL_CLOSE, OUTPUT_CREATED,
}
class TraceModelError(RuntimeError):
"""Fail-closed synthetic trace error."""
@dataclass(frozen=True)
class TraceEvent:
operation: str
at_seconds: float
value: int = 0
def __post_init__(self) -> None:
if self.operation not in OPERATIONS:
raise TraceModelError("trace operation is invalid")
if not isinstance(self.at_seconds, (int, float)) or isinstance(
self.at_seconds, bool) or not math.isfinite(self.at_seconds) or \
self.at_seconds < 0:
raise TraceModelError("trace time is invalid")
if not isinstance(self.value, int) or isinstance(self.value, bool) or \
self.value < 0:
raise TraceModelError("trace value is invalid")
if self.operation not in {SEND_BYTES, RECV_BYTES} and self.value != 0:
raise TraceModelError("valueless trace operation has a value")
if self.operation in {SEND_BYTES, RECV_BYTES} and self.value == 0:
raise TraceModelError("byte operation has no progress")
@dataclass(frozen=True)
class TraceAssessment:
classification: str
batch_bytes_sent: int
receive_bytes: int
receipt_before_create: bool
nonblocking_before_connect: bool
complete_send_loop: bool
deadline_only_completion: bool
local_close_observed: bool
exact_identity_proven: bool = False
device_behavior_proven: bool = False
live_transport_present: bool = False
def assess_nonblocking_trace(
batch_size: int, deadline_seconds: float, events: tuple[TraceEvent, ...],
) -> TraceAssessment:
"""Validate one exact synthetic lifecycle; raise on every ambiguity."""
if not isinstance(batch_size, int) or isinstance(batch_size, bool) or \
not 1 <= batch_size <= MAX_BATCH_BYTES:
raise TraceModelError("batch size is invalid")
if not isinstance(deadline_seconds, (int, float)) or isinstance(
deadline_seconds, bool) or not math.isfinite(deadline_seconds) or \
not 0 < deadline_seconds <= MAX_DEADLINE_SECONDS:
raise TraceModelError("deadline is invalid")
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_TRACE_EVENTS or \
any(type(event) is not TraceEvent for event in events):
raise TraceModelError("trace shape is invalid")
state = "START"
last_time = -1.0
sent = 0
received = 0
write_ready = False
read_ready = False
connected = False
deadline_seen = False
sanitizer_seen = False
close_seen = False
for event in events:
if event.at_seconds < last_time:
raise TraceModelError("trace time moved backward")
last_time = float(event.at_seconds)
operation = event.operation
if deadline_seen and operation not in {
SANITIZER_ACCEPTED, LOCAL_CLOSE, OUTPUT_CREATED}:
raise TraceModelError("I/O occurred after deadline")
if not deadline_seen and event.at_seconds >= deadline_seconds and \
operation != DEADLINE_REACHED:
raise TraceModelError("nondeadline operation reached deadline")
if operation == RECEIPT_CREATED:
if state != "START":
raise TraceModelError("receipt ordering is invalid")
state = "RECEIPT"
elif operation == SOCKET_CREATED:
if state != "RECEIPT":
raise TraceModelError("socket creation precedes receipt")
state = "CREATED"
elif operation == SET_NONBLOCKING:
if state != "CREATED":
raise TraceModelError("nonblocking setup ordering is invalid")
state = "NONBLOCKING"
elif operation == CONNECT_IMMEDIATE:
if state != "NONBLOCKING":
raise TraceModelError("immediate connect ordering is invalid")
connected = True
state = "CONNECTED"
elif operation == CONNECT_PENDING:
if state != "NONBLOCKING":
raise TraceModelError("pending connect ordering is invalid")
state = "CONNECT_PENDING"
elif operation == READY_WRITE:
if state == "CONNECT_PENDING":
state = "CONNECT_READY"
elif connected and not deadline_seen:
write_ready = True
else:
raise TraceModelError("write readiness is unexpected")
elif operation == SO_ERROR_ZERO:
if state != "CONNECT_READY":
raise TraceModelError("SO_ERROR ordering is invalid")
connected = True
state = "CONNECTED"
elif operation == SEND_BYTES:
if not connected or not write_ready or sent >= batch_size:
raise TraceModelError("send ordering is invalid")
if event.value > batch_size - sent:
raise TraceModelError("send exceeded exact batch")
sent += event.value
write_ready = False
elif operation == READY_READ:
if not connected or sent != batch_size or deadline_seen:
raise TraceModelError("read readiness is unexpected")
read_ready = True
elif operation == RECV_BYTES:
if not read_ready:
raise TraceModelError("receive occurred without readiness")
if received + event.value > MAX_RECEIVE_BYTES:
raise TraceModelError("receive bound exceeded")
received += event.value
read_ready = False
elif operation == RECV_EOF:
raise TraceModelError("EOF is not a completion event")
elif operation in {WAIT_INTERRUPTED, WAIT_TIMEOUT}:
if not connected or deadline_seen:
raise TraceModelError("wait event ordering is invalid")
write_ready = False
read_ready = False
elif operation == DEADLINE_REACHED:
if event.at_seconds < deadline_seconds or not connected or \
sent != batch_size or received == 0:
raise TraceModelError("deadline preconditions are incomplete")
deadline_seen = True
write_ready = False
read_ready = False
elif operation == SANITIZER_ACCEPTED:
if not deadline_seen or sanitizer_seen:
raise TraceModelError("sanitizer ordering is invalid")
sanitizer_seen = True
elif operation == LOCAL_CLOSE:
if not deadline_seen or not sanitizer_seen or close_seen:
raise TraceModelError("local close ordering is invalid")
close_seen = True
elif operation == OUTPUT_CREATED:
if not close_seen or state == "COMPLETE":
raise TraceModelError("output ordering is invalid")
state = "COMPLETE"
else:
raise TraceModelError("unhandled trace operation")
if state != "COMPLETE" or not deadline_seen or not sanitizer_seen or \
not close_seen or sent != batch_size:
raise TraceModelError("trace is incomplete")
return TraceAssessment(
classification="OFFLINE_NONBLOCKING_SEQUENCE_FEASIBLE",
batch_bytes_sent=sent,
receive_bytes=received,
receipt_before_create=True,
nonblocking_before_connect=True,
complete_send_loop=True,
deadline_only_completion=True,
local_close_observed=True,
)
+348
View File
@@ -0,0 +1,348 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Dormant Phase-1.0AC adapter driven only by exact built-in fake syscalls.
The module has no socket, selector, address, DNS, CLI, real clock or file
output. It exercises one nonblocking lifecycle with synthetic outcomes and
the existing passive batch/result contract.
"""
from __future__ import annotations
from dataclasses import dataclass
import math
from phase10z_passive_batch_contract import (
PassiveBatch,
PassiveContractError,
PassiveResultAccumulator,
)
MAX_FAKE_STEPS = 1024
MAX_STEP_ADVANCE_SECONDS = 60.0
MAX_RECEIVE_BYTES = 65536
CREATE_STREAM = "CREATE_STREAM"
SET_NONBLOCKING = "SET_NONBLOCKING"
START_CONNECT = "START_CONNECT"
WAIT_WRITE = "WAIT_WRITE"
GET_SO_ERROR = "GET_SO_ERROR"
WRITE_BYTES = "WRITE_BYTES"
WAIT_READ = "WAIT_READ"
READ_BYTES = "READ_BYTES"
OK = "OK"
IMMEDIATE = "IMMEDIATE"
PENDING = "PENDING"
READY = "READY"
INTERRUPTED = "INTERRUPTED"
TIMEOUT = "TIMEOUT"
ZERO = "ZERO"
NONZERO = "NONZERO"
PROGRESS = "PROGRESS"
EOF = "EOF"
ERROR = "ERROR"
ALLOWED_RESULTS = {
CREATE_STREAM: {OK, ERROR},
SET_NONBLOCKING: {OK, ERROR},
START_CONNECT: {IMMEDIATE, PENDING, ERROR},
WAIT_WRITE: {READY, INTERRUPTED, TIMEOUT, ERROR},
GET_SO_ERROR: {ZERO, NONZERO, ERROR},
WRITE_BYTES: {PROGRESS, ZERO, ERROR},
WAIT_READ: {READY, INTERRUPTED, TIMEOUT, ERROR},
READ_BYTES: {PROGRESS, EOF, ERROR},
}
class DormantAdapterError(RuntimeError):
"""Normalized synthetic adapter failure without supplied bytes."""
class FakeSyscallError(RuntimeError):
"""Exact fake-facade state or script failure."""
@dataclass(frozen=True)
class FakeSyscallStep:
"""One synthetic syscall outcome; never an operating-system call."""
operation: str
result: str
value: int = 0
data: bytes = b""
advance_seconds: float = 0.0
def __post_init__(self) -> None:
if self.operation not in ALLOWED_RESULTS or \
self.result not in ALLOWED_RESULTS[self.operation]:
raise FakeSyscallError("fake syscall operation/result is invalid")
if not isinstance(self.value, int) or isinstance(self.value, bool) or \
self.value < 0:
raise FakeSyscallError("fake syscall value is invalid")
if not isinstance(self.data, bytes):
raise FakeSyscallError("fake syscall data is invalid")
advance = self.advance_seconds
if not isinstance(advance, (int, float)) or isinstance(advance, bool) or \
not math.isfinite(advance) or not 0.0 <= advance <= \
MAX_STEP_ADVANCE_SECONDS:
raise FakeSyscallError("fake syscall time advance is invalid")
if self.operation == WRITE_BYTES and self.result == PROGRESS:
if self.value <= 0 or self.data:
raise FakeSyscallError("fake write progress is invalid")
elif self.operation == READ_BYTES and self.result == PROGRESS:
if not self.data or self.value != len(self.data):
raise FakeSyscallError("fake read progress is invalid")
elif self.value != 0 or self.data:
raise FakeSyscallError("fake syscall carries unexpected data")
class OfflineFakeClock:
"""Explicit synthetic monotonic value; never reads the host clock."""
def __init__(self, initial: float = 0.0) -> None:
if not isinstance(initial, (int, float)) or isinstance(initial, bool) or \
not math.isfinite(initial):
raise FakeSyscallError("fake clock initial value is invalid")
self._value = float(initial)
def monotonic(self) -> float:
return self._value
def advance(self, seconds: float) -> None:
if not isinstance(seconds, (int, float)) or isinstance(seconds, bool) or \
not math.isfinite(seconds) or not 0.0 <= seconds <= \
MAX_STEP_ADVANCE_SECONDS:
raise FakeSyscallError("fake clock advance is invalid")
self._value += float(seconds)
class OfflineFakeSyscallFacade:
"""Closed fake facade; it cannot retain a target or create a capability."""
def __init__(
self, clock: OfflineFakeClock, steps: tuple[FakeSyscallStep, ...],
close_result: str = OK,
) -> None:
if type(clock) is not OfflineFakeClock:
raise FakeSyscallError("only the exact fake clock is accepted")
if not isinstance(steps, tuple) or not 1 <= len(steps) <= MAX_FAKE_STEPS \
or any(type(step) is not FakeSyscallStep for step in steps):
raise FakeSyscallError("fake syscall script is invalid")
if close_result not in {OK, ERROR}:
raise FakeSyscallError("fake close result is invalid")
self.clock = clock
self._steps = list(steps)
self._close_result = close_result
self.state = "NEW"
self.invoke_count = 0
self.close_count = 0
self.discarded_steps = 0
self.trace: list[str] = []
def invoke(self, operation: str) -> FakeSyscallStep:
if self.state == "CLOSED" or not self._steps:
raise FakeSyscallError("fake syscall script is exhausted")
step = self._steps.pop(0)
if step.operation != operation:
raise FakeSyscallError("fake syscall ordering is invalid")
self.clock.advance(step.advance_seconds)
self.invoke_count += 1
self.trace.append(f"{operation}:{step.result}")
self.state = "ACTIVE"
return step
def close_once(self) -> None:
if self.state == "CLOSED" or self.close_count != 0:
raise FakeSyscallError("fake facade cannot close")
self.close_count = 1
self.discarded_steps = len(self._steps)
self._steps.clear()
self.trace.append(f"LOCAL_CLOSE:{self._close_result}")
self.state = "CLOSED"
if self._close_result != OK:
raise FakeSyscallError("synthetic local close failed")
@dataclass(frozen=True)
class DormantAdapterOutcome:
classification: str
result_classification: str
exact_identity: bool
batch_bytes_sent: int
received_bytes: int
write_calls: int
read_calls: int
interrupted_waits: int
timed_out_waits: int
discarded_steps_after_close: int
trace: tuple[str, ...]
target_retained: bool = False
live_transport_present: bool = False
device_behavior_proven: bool = False
def _before_deadline(clock: OfflineFakeClock, deadline: float) -> None:
if clock.monotonic() >= deadline:
raise DormantAdapterError("synthetic deadline reached")
def _wait_until_ready(
facade: OfflineFakeSyscallFacade,
clock: OfflineFakeClock,
deadline: float,
operation: str,
) -> tuple[bool, int, int]:
interrupted = 0
timed_out = 0
while True:
_before_deadline(clock, deadline)
step = facade.invoke(operation)
if clock.monotonic() >= deadline:
if step.result == READY:
raise DormantAdapterError(
"synthetic deadline won readiness race")
if step.result == INTERRUPTED:
return False, interrupted + 1, timed_out
if step.result == TIMEOUT:
return False, interrupted, timed_out + 1
raise DormantAdapterError("synthetic wait failed at deadline")
if step.result == READY:
return True, interrupted, timed_out
if step.result == INTERRUPTED:
interrupted += 1
continue
if step.result == TIMEOUT:
timed_out += 1
continue
raise DormantAdapterError("synthetic readiness failed")
def run_dormant_adapter(
batch: PassiveBatch,
facade: OfflineFakeSyscallFacade,
clock: OfflineFakeClock,
receipt_precommitted: bool,
) -> DormantAdapterOutcome:
"""Run one target-free fake-syscall lifecycle and normalize all failure."""
if type(batch) is not PassiveBatch or \
type(facade) is not OfflineFakeSyscallFacade or \
type(clock) is not OfflineFakeClock or facade.clock is not clock or \
receipt_precommitted is not True:
raise DormantAdapterError("dormant adapter boundary is invalid")
start = clock.monotonic()
deadline = start + batch.deadline_seconds
accumulator: PassiveResultAccumulator
try:
accumulator = PassiveResultAccumulator(batch)
except PassiveContractError as error:
raise DormantAdapterError("passive batch is invalid") from error
sent = 0
received = 0
write_calls = 0
read_calls = 0
interrupted_waits = 0
timed_out_waits = 0
opened = False
sanitized = None
primary_failure: DormantAdapterError | None = None
try:
_before_deadline(clock, deadline)
if facade.invoke(CREATE_STREAM).result != OK:
raise DormantAdapterError("synthetic stream creation failed")
opened = True
_before_deadline(clock, deadline)
if facade.invoke(SET_NONBLOCKING).result != OK:
raise DormantAdapterError("synthetic nonblocking setup failed")
_before_deadline(clock, deadline)
connect_result = facade.invoke(START_CONNECT).result
if connect_result == PENDING:
ready, interrupted, timed_out = _wait_until_ready(
facade, clock, deadline, WAIT_WRITE)
interrupted_waits += interrupted
timed_out_waits += timed_out
if not ready:
raise DormantAdapterError(
"synthetic connect reached deadline")
if facade.invoke(GET_SO_ERROR).result != ZERO:
raise DormantAdapterError("synthetic pending connect failed")
_before_deadline(clock, deadline)
elif connect_result != IMMEDIATE:
raise DormantAdapterError("synthetic immediate connect failed")
while sent < len(batch.payload):
ready, interrupted, timed_out = _wait_until_ready(
facade, clock, deadline, WAIT_WRITE)
interrupted_waits += interrupted
timed_out_waits += timed_out
if not ready:
raise DormantAdapterError("synthetic write reached deadline")
step = facade.invoke(WRITE_BYTES)
write_calls += 1
if step.result != PROGRESS or step.value > len(batch.payload) - sent:
raise DormantAdapterError("synthetic write made invalid progress")
sent += step.value
_before_deadline(clock, deadline)
while clock.monotonic() < deadline:
ready, interrupted, timed_out = _wait_until_ready(
facade, clock, deadline, WAIT_READ)
interrupted_waits += interrupted
timed_out_waits += timed_out
if not ready:
break
step = facade.invoke(READ_BYTES)
read_calls += 1
if step.result == EOF:
raise DormantAdapterError("synthetic EOF is not completion")
if step.result != PROGRESS or received + len(step.data) > \
MAX_RECEIVE_BYTES:
raise DormantAdapterError("synthetic read is invalid")
if clock.monotonic() >= deadline:
raise DormantAdapterError("synthetic data reached deadline")
try:
accumulator.feed_supplied_chunk(step.data)
except PassiveContractError as error:
raise DormantAdapterError("passive result rejected input") from error
received += len(step.data)
if clock.monotonic() < deadline or received == 0:
raise DormantAdapterError("synthetic deadline result is incomplete")
try:
sanitized = accumulator.seal_at_hard_deadline(True)
except PassiveContractError as error:
raise DormantAdapterError("passive deadline result is invalid") from error
except Exception as error: # noqa: BLE001 - exact fake boundary normalization
primary_failure = DormantAdapterError("dormant fake-syscall run failed")
primary_failure.__cause__ = error
finally:
if opened:
try:
facade.close_once()
except FakeSyscallError as error:
if primary_failure is None:
primary_failure = DormantAdapterError(
"dormant fake-syscall cleanup failed")
primary_failure.__cause__ = error
if primary_failure is not None:
raise primary_failure
if sanitized is None or facade.close_count != 1:
raise DormantAdapterError("dormant fake-syscall result is incomplete")
return DormantAdapterOutcome(
classification="OFFLINE_DORMANT_FAKE_SYSCALL_ADAPTER_COMPLETE",
result_classification=str(sanitized["classification"]),
exact_identity=bool(sanitized["exact_identity"]),
batch_bytes_sent=sent,
received_bytes=received,
write_calls=write_calls,
read_calls=read_calls,
interrupted_waits=interrupted_waits,
timed_out_waits=timed_out_waits,
discarded_steps_after_close=facade.discarded_steps,
trace=("CONSUMED_RECEIPT_PREEXISTS", *facade.trace),
)
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline Phase-1.0AD activation-record contract.
This module validates data only. It has no socket, DNS, clock, CLI, file
output, transport or device capability.
"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
import ipaddress
import re
PHASE = "PHASE_1_0AD_INACTIVE_NUMERIC_TARGET_CONTRACT"
PORT = 2323
MAX_WINDOW_SECONDS = 300
RUN_ID = re.compile(r"^[A-Z0-9][A-Z0-9_-]{7,63}$")
SHA256 = re.compile(r"^[0-9a-f]{64}$")
class ActivationContractError(ValueError):
"""An activation record is incomplete, ambiguous or unsafe."""
def _utc(value: str) -> datetime:
if not isinstance(value, str) or not value.endswith("Z"):
raise ActivationContractError("timestamp must be UTC with Z suffix")
try:
parsed = datetime.fromisoformat(value[:-1] + "+00:00")
except ValueError as error:
raise ActivationContractError("timestamp is invalid") from error
if parsed.tzinfo != timezone.utc:
raise ActivationContractError("timestamp is not UTC")
return parsed
def validate_numeric_target(value: str) -> str:
"""Return canonical private IPv4 text without resolving a name."""
if not isinstance(value, str) or not value or value != value.strip():
raise ActivationContractError("target must be exact numeric text")
if ":" in value or any(character.isalpha() for character in value):
raise ActivationContractError("only numeric IPv4 targets are allowed")
try:
address = ipaddress.IPv4Address(value)
except ipaddress.AddressValueError as error:
raise ActivationContractError("target is not canonical IPv4") from error
if str(address) != value or not address.is_private or address.is_loopback \
or address.is_link_local or address.is_multicast \
or address.is_unspecified:
raise ActivationContractError("target is not canonical private IPv4")
return value
@dataclass(frozen=True)
class ActivationRecord:
phase: str
active: bool
target_address: str | None
target_port: int | None
run_id: str | None
not_before: str | None
expires_at: str | None
launcher_sha256: str | None
payload_sha256: str | None
approval_sha256: str | None
one_shot: bool
automatic_retry: bool
reconnect: bool
resume: bool
device_write_authorized: bool
app_termination_authorized: bool
system_remount_authorized: bool
def validate_inactive(record: ActivationRecord) -> None:
"""Validate the only tracked Phase-1.0AD state: entirely inactive."""
if type(record) is not ActivationRecord or record.phase != PHASE:
raise ActivationContractError("activation phase is invalid")
if record.active is not False:
raise ActivationContractError("tracked activation must be inactive")
optional = (
record.target_address, record.target_port, record.run_id,
record.not_before, record.expires_at, record.launcher_sha256,
record.payload_sha256, record.approval_sha256,
)
if any(value is not None for value in optional):
raise ActivationContractError("inactive activation must be target-free")
if record.one_shot is not True or record.automatic_retry is not False \
or record.reconnect is not False or record.resume is not False:
raise ActivationContractError("inactive one-shot policy is invalid")
if record.device_write_authorized or record.app_termination_authorized \
or record.system_remount_authorized:
raise ActivationContractError("inactive device effects must be false")
def validate_candidate(record: ActivationRecord) -> None:
"""Validate hypothetical activation data without activating anything."""
if type(record) is not ActivationRecord or record.phase != PHASE \
or record.active is not True:
raise ActivationContractError("candidate is not explicitly active")
validate_numeric_target(record.target_address) # type: ignore[arg-type]
if record.target_port != PORT:
raise ActivationContractError("candidate port is not source-bound")
if not isinstance(record.run_id, str) or not RUN_ID.fullmatch(record.run_id):
raise ActivationContractError("candidate run id is invalid")
if not isinstance(record.launcher_sha256, str) \
or not SHA256.fullmatch(record.launcher_sha256):
raise ActivationContractError("launcher identity is invalid")
if not isinstance(record.payload_sha256, str) \
or not SHA256.fullmatch(record.payload_sha256):
raise ActivationContractError("payload identity is invalid")
if not isinstance(record.approval_sha256, str) \
or not SHA256.fullmatch(record.approval_sha256):
raise ActivationContractError("approval identity is invalid")
start = _utc(record.not_before) # type: ignore[arg-type]
end = _utc(record.expires_at) # type: ignore[arg-type]
duration = (end - start).total_seconds()
if not 0 < duration <= MAX_WINDOW_SECONDS:
raise ActivationContractError("candidate window is invalid")
if record.one_shot is not True or record.automatic_retry is not False \
or record.reconnect is not False or record.resume is not False:
raise ActivationContractError("candidate one-shot policy is invalid")
if record.device_write_authorized or record.app_termination_authorized \
or record.system_remount_authorized:
raise ActivationContractError("candidate requests forbidden effects")
+213
View File
@@ -0,0 +1,213 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Closed host-only model of one bounded BigApp launcher lifecycle.
The model accepts only exact built-in fake operations. It imports no target
headers, socket, process, syscall, clock, CLI or filesystem interface.
"""
from __future__ import annotations
from dataclasses import dataclass
FIXED_TITLE = "PPSA01659"
MAX_MAIN_TICKS = 64
MAX_FAKE_EVENTS = 64
MAX_CLEANUP_EVENTS = 3
CHECK_NO_BIGAPP = "CHECK_NO_BIGAPP"
ATTACH_PARENT = "ATTACH_PARENT"
ARM_FORK = "ARM_FORK"
CONTINUE_PARENT = "CONTINUE_PARENT"
LAUNCH_FIXED_TITLE = "LAUNCH_FIXED_TITLE"
AWAIT_UNIQUE_CHILD = "AWAIT_UNIQUE_CHILD"
DETACH_PARENT = "DETACH_PARENT"
ARM_EXEC = "ARM_EXEC"
CONTINUE_CHILD = "CONTINUE_CHILD"
AWAIT_EXEC = "AWAIT_EXEC"
REPLACE_EXACT_PAYLOAD = "REPLACE_EXACT_PAYLOAD"
RESTORE_MUTATIONS = "RESTORE_MUTATIONS"
DETACH_CHILD = "DETACH_CHILD"
TERMINATE_CHILD = "TERMINATE_CHILD"
EMIT_RESULT = "EMIT_RESULT"
OK = "OK"
NONE = "NONE"
EXISTS = "EXISTS"
CHILD = "CHILD"
TIMEOUT = "TIMEOUT"
ERROR = "ERROR"
ALLOWED = {
CHECK_NO_BIGAPP: {NONE, EXISTS, ERROR},
ATTACH_PARENT: {OK, ERROR}, ARM_FORK: {OK, ERROR},
CONTINUE_PARENT: {OK, ERROR}, LAUNCH_FIXED_TITLE: {OK, ERROR},
AWAIT_UNIQUE_CHILD: {CHILD, TIMEOUT, ERROR},
DETACH_PARENT: {OK, ERROR}, ARM_EXEC: {OK, ERROR},
CONTINUE_CHILD: {OK, ERROR}, AWAIT_EXEC: {OK, TIMEOUT, ERROR},
REPLACE_EXACT_PAYLOAD: {OK, ERROR}, RESTORE_MUTATIONS: {OK, ERROR},
DETACH_CHILD: {OK, ERROR}, TERMINATE_CHILD: {OK, ERROR},
EMIT_RESULT: {OK, ERROR},
}
class LifecycleModelError(RuntimeError):
"""The synthetic lifecycle or its cleanup is invalid."""
@dataclass(frozen=True)
class FakeEvent:
operation: str
result: str
ticks: int = 1
child_id: int = 0
def __post_init__(self) -> None:
if self.operation not in ALLOWED or self.result not in ALLOWED[self.operation]:
raise LifecycleModelError("fake operation/result is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_MAIN_TICKS:
raise LifecycleModelError("fake ticks are invalid")
if self.operation == AWAIT_UNIQUE_CHILD and self.result == CHILD:
if not isinstance(self.child_id, int) or isinstance(self.child_id, bool) \
or self.child_id <= 1:
raise LifecycleModelError("fake child identity is invalid")
elif self.child_id != 0:
raise LifecycleModelError("unexpected fake child identity")
class FakeLifecycleFacade:
"""Exact closed script; it cannot execute an operation itself."""
def __init__(self, events: tuple[FakeEvent, ...]) -> None:
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_FAKE_EVENTS \
or any(type(event) is not FakeEvent for event in events):
raise LifecycleModelError("fake lifecycle script is invalid")
self._events = list(events)
self.trace: list[str] = []
self.ticks = 0
def invoke(self, operation: str, cleanup: bool = False) -> FakeEvent:
if not self._events:
raise LifecycleModelError("fake lifecycle script is exhausted")
event = self._events.pop(0)
if event.operation != operation:
raise LifecycleModelError("fake lifecycle ordering is invalid")
self.ticks += event.ticks
self.trace.append(f"{operation}:{event.result}")
if not cleanup and self.ticks > MAX_MAIN_TICKS:
raise LifecycleModelError("bounded main lifecycle expired")
return event
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class LifecycleOutcome:
classification: str
success: bool
child_id: int
parent_detached: bool
child_detached: bool
child_terminated: bool
mutations_restored: bool
existing_bigapp_killed: bool
fixed_title: str
trace: tuple[str, ...]
target_code_present: bool = False
device_behavior_proven: bool = False
def _require_ok(facade: FakeLifecycleFacade, operation: str) -> None:
if facade.invoke(operation).result != OK:
raise LifecycleModelError(f"{operation} failed")
def run_lifecycle(facade: FakeLifecycleFacade) -> LifecycleOutcome:
"""Model one attempt and exhaustively unwind every acquired state."""
if type(facade) is not FakeLifecycleFacade:
raise LifecycleModelError("only the exact fake facade is accepted")
parent_attached = False
parent_detached = False
child_id = 0
child_detached = False
child_terminated = False
mutations_started = False
mutations_restored = False
success = False
primary_error: Exception | None = None
cleanup_events = 0
try:
if facade.invoke(CHECK_NO_BIGAPP).result != NONE:
raise LifecycleModelError("pre-existing BigApp blocks launch")
_require_ok(facade, ATTACH_PARENT)
parent_attached = True
_require_ok(facade, ARM_FORK)
_require_ok(facade, CONTINUE_PARENT)
_require_ok(facade, LAUNCH_FIXED_TITLE)
child = facade.invoke(AWAIT_UNIQUE_CHILD)
if child.result != CHILD:
raise LifecycleModelError("unique child was not observed")
child_id = child.child_id
_require_ok(facade, DETACH_PARENT)
parent_attached = False
parent_detached = True
_require_ok(facade, ARM_EXEC)
_require_ok(facade, CONTINUE_CHILD)
_require_ok(facade, AWAIT_EXEC)
replace = facade.invoke(REPLACE_EXACT_PAYLOAD)
mutations_started = True
if replace.result != OK:
raise LifecycleModelError("exact payload replacement failed")
_require_ok(facade, RESTORE_MUTATIONS)
mutations_started = False
mutations_restored = True
_require_ok(facade, DETACH_CHILD)
child_detached = True
_require_ok(facade, EMIT_RESULT)
success = True
except Exception as error: # exact fake boundary normalization
primary_error = error
finally:
try:
if parent_attached:
cleanup_events += 1
if facade.invoke(DETACH_PARENT, cleanup=True).result != OK:
raise LifecycleModelError("parent cleanup failed")
parent_attached = False
parent_detached = True
if mutations_started:
cleanup_events += 1
if facade.invoke(RESTORE_MUTATIONS, cleanup=True).result != OK:
raise LifecycleModelError("mutation restoration failed")
mutations_started = False
mutations_restored = True
if child_id and not child_detached:
cleanup_events += 1
if facade.invoke(TERMINATE_CHILD, cleanup=True).result != OK:
raise LifecycleModelError("new child cleanup failed")
child_terminated = True
if cleanup_events > MAX_CLEANUP_EVENTS:
raise LifecycleModelError("cleanup operation bound exceeded")
except Exception as cleanup_error:
raise LifecycleModelError("lifecycle cleanup is incomplete") from cleanup_error
if facade.remaining:
raise LifecycleModelError("fake lifecycle has unused operations")
if primary_error is not None:
return LifecycleOutcome(
"OFFLINE_BIGAPP_LIFECYCLE_FAILED_CLEANLY", False, child_id,
parent_detached, child_detached, child_terminated,
mutations_restored, False, FIXED_TITLE, tuple(facade.trace))
if not success or not parent_detached or not child_detached \
or not mutations_restored or child_terminated:
raise LifecycleModelError("successful lifecycle invariants failed")
return LifecycleOutcome(
"OFFLINE_BIGAPP_LIFECYCLE_MODEL_COMPLETE", True, child_id,
parent_detached, child_detached, child_terminated,
mutations_restored, False, FIXED_TITLE, tuple(facade.trace))
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Bytes-only bounded ELF64 admission contract for a future launcher.
No path, file, process, target, network or execution interface is present.
"""
from __future__ import annotations
from dataclasses import dataclass
import hashlib
import re
import struct
MAX_FILE_SIZE = 2 * 1024 * 1024
MAX_PROGRAM_HEADERS = 32
MAX_SECTION_HEADERS = 256
MAX_LOAD_SEGMENTS = 8
MAX_TOTAL_LOAD_MEMORY = 64 * 1024 * 1024
MAX_LOAD_SPAN = 128 * 1024 * 1024
MAX_ALIGNMENT = 2 * 1024 * 1024
ELF_HEADER = struct.Struct("<16sHHIQQQIHHHHHH")
PROGRAM_HEADER = struct.Struct("<IIQQQQQQ")
SECTION_HEADER_SIZE = 64
PT_LOAD = 1
PT_INTERP = 3
ET_DYN = 3
EM_X86_64 = 62
PF_X = 1
PF_W = 2
PF_R = 4
SHA256 = re.compile(r"^[0-9a-f]{64}$")
class ElfContractError(ValueError):
"""The supplied bytes are not an admitted bounded payload."""
@dataclass(frozen=True)
class LoadSegment:
flags: int
offset: int
virtual_address: int
file_size: int
memory_size: int
alignment: int
@dataclass(frozen=True)
class ElfAssessment:
size: int
sha256: str
entry: int
program_header_count: int
load_segments: tuple[LoadSegment, ...]
total_load_memory: int
load_span: int
pie: bool = True
machine_x86_64: bool = True
writable_executable_segment: bool = False
interpreter_present: bool = False
execution_performed: bool = False
def _bounded_range(offset: int, size: int, limit: int, label: str) -> None:
if offset < 0 or size < 0 or offset > limit or size > limit - offset:
raise ElfContractError(f"{label} range is outside supplied bytes")
def _power_of_two(value: int) -> bool:
return value > 0 and value & (value - 1) == 0
def assess_elf(payload: bytes, expected_sha256: str) -> ElfAssessment:
"""Validate exact supplied bytes without opening or executing anything."""
if not isinstance(payload, bytes) or not ELF_HEADER.size <= len(payload) <= MAX_FILE_SIZE:
raise ElfContractError("payload size is outside the admission bound")
if not isinstance(expected_sha256, str) or not SHA256.fullmatch(expected_sha256):
raise ElfContractError("expected SHA-256 is invalid")
digest = hashlib.sha256(payload).hexdigest()
if digest != expected_sha256:
raise ElfContractError("payload SHA-256 does not match")
(ident, elf_type, machine, version, entry, phoff, shoff, flags,
ehsize, phentsize, phnum, shentsize, shnum, shstrndx) = ELF_HEADER.unpack_from(payload)
del flags, shstrndx
if ident[:4] != b"\x7fELF" or ident[4] != 2 or ident[5] != 1 \
or ident[6] != 1 or ident[7] not in {0, 9}:
raise ElfContractError("ELF identity is unsupported")
if elf_type != ET_DYN or machine != EM_X86_64 or version != 1:
raise ElfContractError("ELF type, machine or version is unsupported")
if ehsize != ELF_HEADER.size or phentsize != PROGRAM_HEADER.size \
or not 1 <= phnum <= MAX_PROGRAM_HEADERS:
raise ElfContractError("ELF header sizing is invalid")
if phoff < ELF_HEADER.size:
raise ElfContractError("program header table overlaps ELF header")
_bounded_range(phoff, phnum * phentsize, len(payload), "program header table")
if shnum == 0:
if shoff != 0 or shentsize not in {0, SECTION_HEADER_SIZE}:
raise ElfContractError("absent section table is inconsistent")
else:
if not 1 <= shnum <= MAX_SECTION_HEADERS or shentsize != SECTION_HEADER_SIZE:
raise ElfContractError("section header sizing is invalid")
_bounded_range(shoff, shnum * shentsize, len(payload), "section header table")
loads: list[LoadSegment] = []
interpreter = False
for index in range(phnum):
values = PROGRAM_HEADER.unpack_from(payload, phoff + index * phentsize)
p_type, p_flags, p_offset, p_vaddr, _p_paddr, p_filesz, p_memsz, p_align = values
if p_type == PT_INTERP:
interpreter = True
if p_type != PT_LOAD:
continue
if len(loads) >= MAX_LOAD_SEGMENTS or p_memsz == 0 or p_filesz > p_memsz:
raise ElfContractError("load segment count or sizing is invalid")
_bounded_range(p_offset, p_filesz, len(payload), "load segment file")
if p_vaddr > (1 << 64) - 1 - p_memsz:
raise ElfContractError("load segment address overflows")
if p_flags & ~(PF_R | PF_W | PF_X) or p_flags & PF_W and p_flags & PF_X:
raise ElfContractError("load segment permissions are invalid")
if not _power_of_two(p_align) or p_align > MAX_ALIGNMENT \
or p_offset % p_align != p_vaddr % p_align:
raise ElfContractError("load segment alignment is invalid")
loads.append(LoadSegment(p_flags, p_offset, p_vaddr, p_filesz,
p_memsz, p_align))
if interpreter:
raise ElfContractError("interpreter segment is forbidden")
if not loads:
raise ElfContractError("ELF has no load segments")
ordered = sorted(loads, key=lambda item: item.virtual_address)
for previous, current in zip(ordered, ordered[1:]):
if previous.virtual_address + previous.memory_size > current.virtual_address:
raise ElfContractError("load segment virtual ranges overlap")
total_memory = sum(item.memory_size for item in ordered)
span = ordered[-1].virtual_address + ordered[-1].memory_size - ordered[0].virtual_address
if total_memory > MAX_TOTAL_LOAD_MEMORY or span > MAX_LOAD_SPAN:
raise ElfContractError("load memory budget is exceeded")
executable = [item for item in ordered if item.flags & PF_X]
if not executable or not any(item.virtual_address <= entry <
item.virtual_address + item.memory_size
for item in executable):
raise ElfContractError("entry is not in an executable load segment")
return ElfAssessment(len(payload), digest, entry, phnum, tuple(ordered),
total_memory, span)
+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Bytes-only dynamic/relocation contract layered on Phase 1.0AG."""
from __future__ import annotations
from dataclasses import dataclass
import struct
from phase10ag_bounded_elf import (
ELF_HEADER, ElfContractError, PF_W, assess_elf,
)
SECTION_HEADER = struct.Struct("<IIQQQQIIQQ")
DYNAMIC_ENTRY = struct.Struct("<qQ")
RELA_ENTRY = struct.Struct("<QQq")
SHT_STRTAB = 3
SHT_RELA = 4
SHT_DYNAMIC = 6
DT_NULL = 0
DT_NEEDED = 1
R_X86_64_GLOB_DAT = 6
R_X86_64_RELATIVE = 8
MAX_DYNAMIC_ENTRIES = 256
MAX_RELOCATION_SECTIONS = 4
MAX_RELOCATIONS = 4096
MAX_NEEDED = 16
MAX_NEEDED_NAME = 128
ALLOWED_MODULES = frozenset({
"libSceAudioOut.sprx", "libSceLibcInternal.sprx", "libScePad.sprx",
"libSceSystemService.sprx", "libSceUserService.sprx",
"libSceVideoOut.sprx", "libkernel_web.sprx",
})
class DynamicContractError(ValueError):
"""Dynamic metadata exceeds or violates the admitted subset."""
@dataclass(frozen=True)
class DynamicAssessment:
needed: tuple[str, ...]
relative_count: int
glob_dat_count: int
total_relocations: int
relocation_sections: int
loader_applied_types: tuple[int, ...] = (R_X86_64_RELATIVE,)
crt_applied_types: tuple[int, ...] = (R_X86_64_GLOB_DAT,)
unknown_relocation_types: tuple[int, ...] = ()
target_mapping_performed: bool = False
runtime_module_loading_performed: bool = False
def _range(offset: int, size: int, limit: int, label: str) -> None:
if offset < 0 or size < 0 or offset > limit or size > limit - offset:
raise DynamicContractError(f"{label} is outside supplied bytes")
def _sections(payload: bytes) -> list[tuple[int, ...]]:
header = ELF_HEADER.unpack_from(payload)
shoff, shentsize, shnum = header[6], header[11], header[12]
if shnum == 0 or shentsize != SECTION_HEADER.size:
raise DynamicContractError("section table is required")
_range(shoff, shnum * shentsize, len(payload), "section table")
return [SECTION_HEADER.unpack_from(payload, shoff + index * shentsize)
for index in range(shnum)]
def _needed(payload: bytes, sections: list[tuple[int, ...]]) -> tuple[str, ...]:
dynamic_sections = [section for section in sections if section[1] == SHT_DYNAMIC]
if len(dynamic_sections) != 1:
raise DynamicContractError("exactly one dynamic section is required")
section = dynamic_sections[0]
offset, size, link, entsize = section[4], section[5], section[6], section[9]
if entsize != DYNAMIC_ENTRY.size or size % entsize or size // entsize > MAX_DYNAMIC_ENTRIES:
raise DynamicContractError("dynamic table sizing is invalid")
_range(offset, size, len(payload), "dynamic table")
if link >= len(sections) or sections[link][1] != SHT_STRTAB:
raise DynamicContractError("dynamic string table link is invalid")
strings = sections[link]
string_offset, string_size = strings[4], strings[5]
_range(string_offset, string_size, len(payload), "dynamic string table")
string_data = payload[string_offset:string_offset + string_size]
names: list[str] = []
terminated = False
for position in range(offset, offset + size, entsize):
tag, value = DYNAMIC_ENTRY.unpack_from(payload, position)
if terminated:
if tag != DT_NULL or value != 0:
raise DynamicContractError("nonzero dynamic data follows DT_NULL")
continue
if tag == DT_NULL:
terminated = True
continue
if tag != DT_NEEDED:
continue
if len(names) >= MAX_NEEDED or value >= len(string_data):
raise DynamicContractError("DT_NEEDED count or offset is invalid")
end = string_data.find(b"\0", value, min(len(string_data), value + MAX_NEEDED_NAME + 1))
if end < 0:
raise DynamicContractError("DT_NEEDED name is unterminated or too long")
try:
name = string_data[value:end].decode("ascii")
except UnicodeDecodeError as error:
raise DynamicContractError("DT_NEEDED name is not ASCII") from error
if name not in ALLOWED_MODULES or name in names:
raise DynamicContractError("DT_NEEDED module is unknown or duplicated")
names.append(name)
if not terminated:
raise DynamicContractError("dynamic table has no DT_NULL terminator")
return tuple(names)
def assess_dynamic(payload: bytes, expected_sha256: str,
expected_needed: tuple[str, ...]) -> DynamicAssessment:
"""Validate exact dynamic dependencies and the bounded relocation split."""
try:
elf = assess_elf(payload, expected_sha256)
except ElfContractError as error:
raise DynamicContractError("base ELF admission failed") from error
if not isinstance(expected_needed, tuple) or not 1 <= len(expected_needed) <= MAX_NEEDED \
or any(not isinstance(item, str) for item in expected_needed) \
or len(set(expected_needed)) != len(expected_needed) \
or any(item not in ALLOWED_MODULES for item in expected_needed):
raise DynamicContractError("expected module inventory is invalid")
sections = _sections(payload)
needed = _needed(payload, sections)
if needed != expected_needed:
raise DynamicContractError("DT_NEEDED inventory or order differs")
writable = [(item.virtual_address, item.virtual_address + item.memory_size)
for item in elf.load_segments if item.flags & PF_W]
image = [(item.virtual_address, item.virtual_address + item.memory_size)
for item in elf.load_segments]
relative = 0
glob_dat = 0
total = 0
relocation_sections = 0
for section in sections:
if section[1] != SHT_RELA:
continue
relocation_sections += 1
if relocation_sections > MAX_RELOCATION_SECTIONS:
raise DynamicContractError("too many relocation sections")
offset, size, entsize = section[4], section[5], section[9]
if entsize != RELA_ENTRY.size or size % entsize:
raise DynamicContractError("relocation table sizing is invalid")
_range(offset, size, len(payload), "relocation table")
for position in range(offset, offset + size, entsize):
total += 1
if total > MAX_RELOCATIONS:
raise DynamicContractError("relocation count is exceeded")
target, info, addend = RELA_ENTRY.unpack_from(payload, position)
relocation_type = info & 0xffffffff
symbol = info >> 32
if target % 8 or not any(start <= target and target + 8 <= end
for start, end in writable):
raise DynamicContractError("relocation target is not aligned RW memory")
if relocation_type == R_X86_64_RELATIVE:
if symbol != 0 or addend < 0 or not any(start <= addend < end
for start, end in image):
raise DynamicContractError("relative relocation is invalid")
relative += 1
elif relocation_type == R_X86_64_GLOB_DAT:
if symbol == 0 or addend != 0:
raise DynamicContractError("GLOB_DAT relocation is invalid")
glob_dat += 1
else:
raise DynamicContractError("relocation type is outside the contract")
if relocation_sections == 0 or relative == 0:
raise DynamicContractError("relative relocation closure is absent")
return DynamicAssessment(needed, relative, glob_dat, total,
relocation_sections)
+239
View File
@@ -0,0 +1,239 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only transactional mapping/protection model for admitted ELF loads."""
from __future__ import annotations
from dataclasses import dataclass
from phase10ag_bounded_elf import LoadSegment, PF_R, PF_W, PF_X
PAGE_SIZE = 16 * 1024
MAX_SEGMENTS = 8
MAX_RELATIVE_RELOCATIONS = 4096
MAX_EVENTS = 64
MAX_MAIN_TICKS = 128
MAX_REGION_SIZE = 128 * 1024 * 1024
RESERVE_CHILD = "RESERVE_CHILD"
CREATE_MIRROR = "CREATE_MIRROR"
COPY_FILE_BYTES = "COPY_FILE_BYTES"
ZERO_BSS = "ZERO_BSS"
APPLY_RELATIVE = "APPLY_RELATIVE"
COPY_MIRROR_TO_CHILD = "COPY_MIRROR_TO_CHILD"
SET_FINAL_PROTECTION = "SET_FINAL_PROTECTION"
SYNC_IMAGE = "SYNC_IMAGE"
RELEASE_MIRROR = "RELEASE_MIRROR"
UNMAP_CHILD = "UNMAP_CHILD"
OK = "OK"
ERROR = "ERROR"
OPERATIONS = {
RESERVE_CHILD, CREATE_MIRROR, COPY_FILE_BYTES, ZERO_BSS,
APPLY_RELATIVE, COPY_MIRROR_TO_CHILD, SET_FINAL_PROTECTION,
SYNC_IMAGE, RELEASE_MIRROR, UNMAP_CHILD,
}
class MappingModelError(RuntimeError):
"""The mapping transaction or its rollback is incomplete."""
def _round_down(value: int) -> int:
return value & ~(PAGE_SIZE - 1)
def _round_up(value: int) -> int:
if value > (1 << 64) - PAGE_SIZE:
raise MappingModelError("mapping address cannot be rounded")
return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)
@dataclass(frozen=True)
class MappingPlan:
segments: tuple[LoadSegment, ...]
relative_relocations: int
def __post_init__(self) -> None:
if not isinstance(self.segments, tuple) or not 1 <= len(self.segments) <= MAX_SEGMENTS \
or any(type(item) is not LoadSegment for item in self.segments):
raise MappingModelError("mapping segments are invalid")
if tuple(sorted(self.segments, key=lambda item: item.virtual_address)) != self.segments:
raise MappingModelError("mapping segments are not ordered")
if not isinstance(self.relative_relocations, int) \
or isinstance(self.relative_relocations, bool) \
or not 1 <= self.relative_relocations <= MAX_RELATIVE_RELOCATIONS:
raise MappingModelError("relative relocation count is invalid")
protected: list[tuple[int, int]] = []
for segment in self.segments:
if segment.memory_size <= 0 or segment.file_size < 0 \
or segment.file_size > segment.memory_size \
or segment.flags & ~(PF_R | PF_W | PF_X) \
or segment.flags & PF_W and segment.flags & PF_X:
raise MappingModelError("mapping segment is unsafe")
start = _round_down(segment.virtual_address)
end = _round_up(segment.virtual_address + segment.memory_size)
if protected and protected[-1][1] > start:
raise MappingModelError("page-rounded protections overlap")
protected.append((start, end))
if self.region_size > MAX_REGION_SIZE:
raise MappingModelError("mapping region exceeds budget")
@property
def region_start(self) -> int:
return _round_down(self.segments[0].virtual_address)
@property
def region_size(self) -> int:
end = _round_up(self.segments[-1].virtual_address +
self.segments[-1].memory_size)
return end - self.region_start
@dataclass(frozen=True)
class FakeMappingEvent:
operation: str
result: str
segment_index: int = -1
value: int = 0
ticks: int = 1
def __post_init__(self) -> None:
if self.operation not in OPERATIONS or self.result not in {OK, ERROR}:
raise MappingModelError("fake mapping operation/result is invalid")
if not isinstance(self.segment_index, int) or isinstance(self.segment_index, bool) \
or self.segment_index < -1:
raise MappingModelError("fake segment index is invalid")
if not isinstance(self.value, int) or isinstance(self.value, bool) or self.value < 0:
raise MappingModelError("fake mapping value is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_MAIN_TICKS:
raise MappingModelError("fake mapping ticks are invalid")
indexed = self.operation in {COPY_FILE_BYTES, ZERO_BSS, SET_FINAL_PROTECTION}
if indexed != (self.segment_index >= 0):
raise MappingModelError("fake mapping segment binding is invalid")
class FakeMappingFacade:
"""Exact scripted facade with no memory or process capability."""
def __init__(self, events: tuple[FakeMappingEvent, ...]) -> None:
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_EVENTS \
or any(type(event) is not FakeMappingEvent for event in events):
raise MappingModelError("fake mapping script is invalid")
self._events = list(events)
self.trace: list[str] = []
self.ticks = 0
def invoke(self, operation: str, segment_index: int = -1,
value: int = 0, cleanup: bool = False) -> FakeMappingEvent:
if not self._events:
raise MappingModelError("fake mapping script is exhausted")
event = self._events.pop(0)
if event.operation != operation or event.segment_index != segment_index \
or event.value != value:
raise MappingModelError("fake mapping ordering or binding differs")
if not cleanup and self.ticks + event.ticks > MAX_MAIN_TICKS:
self.trace.append(f"DEADLINE_BEFORE:{operation}")
raise MappingModelError("mapping main tick budget expired before operation")
self.ticks += event.ticks
self.trace.append(f"{operation}:{segment_index}:{value}:{event.result}")
return event
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class MappingOutcome:
classification: str
success: bool
region_size: int
copied_file_bytes: int
zeroed_bss_bytes: int
relative_relocations: int
final_protections: tuple[int, ...]
mirror_released: bool
child_region_retained: bool
child_region_unmapped: bool
target_mapping_performed: bool = False
device_behavior_proven: bool = False
def _ok(facade: FakeMappingFacade, operation: str, segment_index: int = -1,
value: int = 0) -> None:
if facade.invoke(operation, segment_index, value).result != OK:
raise MappingModelError(f"{operation} failed")
def run_mapping(plan: MappingPlan, facade: FakeMappingFacade) -> MappingOutcome:
"""Run one synthetic mapping transaction with full-region rollback."""
if type(plan) is not MappingPlan or type(facade) is not FakeMappingFacade:
raise MappingModelError("mapping model boundary is invalid")
child_reserved = False
mirror_active = False
mirror_released = False
child_unmapped = False
committed = False
copied = 0
zeroed = 0
protections: list[int] = []
primary_error: Exception | None = None
try:
_ok(facade, RESERVE_CHILD, value=plan.region_size)
child_reserved = True
_ok(facade, CREATE_MIRROR, value=plan.region_size)
mirror_active = True
for index, segment in enumerate(plan.segments):
if segment.file_size:
_ok(facade, COPY_FILE_BYTES, index, segment.file_size)
copied += segment.file_size
bss = segment.memory_size - segment.file_size
if bss:
_ok(facade, ZERO_BSS, index, bss)
zeroed += bss
_ok(facade, APPLY_RELATIVE, value=plan.relative_relocations)
_ok(facade, COPY_MIRROR_TO_CHILD, value=plan.region_size)
for index, segment in enumerate(plan.segments):
_ok(facade, SET_FINAL_PROTECTION, index, segment.flags)
protections.append(segment.flags)
_ok(facade, SYNC_IMAGE, value=plan.region_size)
_ok(facade, RELEASE_MIRROR)
mirror_active = False
mirror_released = True
committed = True
except Exception as error:
primary_error = error
finally:
try:
if mirror_active:
if facade.invoke(RELEASE_MIRROR, cleanup=True).result != OK:
raise MappingModelError("mirror cleanup failed")
mirror_active = False
mirror_released = True
if child_reserved and not committed:
if facade.invoke(UNMAP_CHILD, value=plan.region_size,
cleanup=True).result != OK:
raise MappingModelError("child mapping rollback failed")
child_unmapped = True
child_reserved = False
except Exception as cleanup_error:
raise MappingModelError("mapping rollback is incomplete") from cleanup_error
if facade.remaining:
raise MappingModelError("fake mapping script has unused operations")
if primary_error is not None:
return MappingOutcome(
"OFFLINE_MAPPING_TRANSACTION_ROLLED_BACK", False, plan.region_size,
copied, zeroed, plan.relative_relocations, tuple(protections),
mirror_released, False, child_unmapped)
if not committed or not mirror_released or child_unmapped \
or tuple(protections) != tuple(item.flags for item in plan.segments):
raise MappingModelError("successful mapping invariants failed")
return MappingOutcome(
"OFFLINE_MAPPING_TRANSACTION_MODEL_COMPLETE", True, plan.region_size,
copied, zeroed, plan.relative_relocations, tuple(protections), True,
True, False)
+214
View File
@@ -0,0 +1,214 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only ownership model for hybrid BigApp/JIT mapping composition."""
from __future__ import annotations
from dataclasses import dataclass
MAX_EXECUTABLE_SEGMENTS = 8
MAX_EVENTS = 256
MAX_TICKS = 256
CREATE_CHILD = "CREATE_CHILD"
RESERVE_REGION = "RESERVE_REGION"
CREATE_MIRROR = "CREATE_MIRROR"
CREATE_JIT_MASTER = "CREATE_JIT_MASTER"
MAP_EXECUTABLE = "MAP_EXECUTABLE"
CREATE_JIT_ALIAS = "CREATE_JIT_ALIAS"
MAP_HOST_ALIAS = "MAP_HOST_ALIAS"
MAP_REMOTE_ALIAS = "MAP_REMOTE_ALIAS"
COPY_ALIAS = "COPY_ALIAS"
UNMAP_REMOTE_ALIAS = "UNMAP_REMOTE_ALIAS"
UNMAP_HOST_ALIAS = "UNMAP_HOST_ALIAS"
CLOSE_JIT_ALIAS = "CLOSE_JIT_ALIAS"
CLOSE_JIT_MASTER = "CLOSE_JIT_MASTER"
FINALIZE_IMAGE = "FINALIZE_IMAGE"
RELEASE_MIRROR = "RELEASE_MIRROR"
UNMAP_REGION = "UNMAP_REGION"
KILL_AND_REAP_CHILD = "KILL_AND_REAP_CHILD"
OK = "OK"
ERROR = "ERROR"
INDEXED = {
CREATE_JIT_MASTER, MAP_EXECUTABLE, CREATE_JIT_ALIAS, MAP_HOST_ALIAS,
MAP_REMOTE_ALIAS, COPY_ALIAS, UNMAP_REMOTE_ALIAS, UNMAP_HOST_ALIAS,
CLOSE_JIT_ALIAS, CLOSE_JIT_MASTER,
}
OPERATIONS = INDEXED | {
CREATE_CHILD, RESERVE_REGION, CREATE_MIRROR, FINALIZE_IMAGE,
RELEASE_MIRROR, UNMAP_REGION, KILL_AND_REAP_CHILD,
}
class CompositionError(RuntimeError):
"""The synthetic ownership transaction cannot close safely."""
@dataclass(frozen=True)
class CompositionPlan:
executable_segments: int
def __post_init__(self) -> None:
if not isinstance(self.executable_segments, int) \
or isinstance(self.executable_segments, bool) \
or not 1 <= self.executable_segments <= MAX_EXECUTABLE_SEGMENTS:
raise CompositionError("executable segment count is invalid")
@dataclass(frozen=True)
class FakeEvent:
operation: str
result: str
segment: int = -1
ticks: int = 1
def __post_init__(self) -> None:
if self.operation not in OPERATIONS or self.result not in {OK, ERROR}:
raise CompositionError("event operation/result is invalid")
if (self.operation in INDEXED) != (self.segment >= 0):
raise CompositionError("event segment binding is invalid")
if not isinstance(self.segment, int) or isinstance(self.segment, bool):
raise CompositionError("event segment is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise CompositionError("event ticks are invalid")
class FakeFacade:
"""Exact fake script with no process, mapping, clock or device access."""
def __init__(self, events: tuple[FakeEvent, ...]) -> None:
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_EVENTS \
or any(type(event) is not FakeEvent for event in events):
raise CompositionError("fake composition script is invalid")
self._events = list(events)
self.ticks = 0
def invoke(self, operation: str, segment: int = -1,
cleanup: bool = False) -> str:
if not self._events:
raise CompositionError("fake composition script is exhausted")
event = self._events.pop(0)
if event.operation != operation or event.segment != segment:
raise CompositionError("fake composition ordering differs")
if not cleanup and self.ticks + event.ticks > MAX_TICKS:
raise CompositionError("composition deadline precedes operation")
self.ticks += event.ticks
return event.result
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class CompositionOutcome:
classification: str
success: bool
child_alive: bool
image_retained: bool
resources_open: int
fail_closed_termination: bool
target_action_performed: bool = False
firmware_behavior_proven: bool = False
def _require(facade: FakeFacade, operation: str, segment: int = -1) -> None:
if facade.invoke(operation, segment) != OK:
raise CompositionError(f"{operation} failed")
def run_composition(plan: CompositionPlan, facade: FakeFacade) -> CompositionOutcome:
"""Compose synthetic resources; cleanup failure requires child termination."""
if type(plan) is not CompositionPlan or type(facade) is not FakeFacade:
raise CompositionError("composition boundary is invalid")
child = region = mirror = committed = False
masters: set[int] = set()
aliases: set[int] = set()
host_aliases: set[int] = set()
remote_aliases: set[int] = set()
primary_failed = cleanup_failed = terminated = False
try:
_require(facade, CREATE_CHILD)
child = True
_require(facade, RESERVE_REGION)
region = True
_require(facade, CREATE_MIRROR)
mirror = True
for segment in range(plan.executable_segments):
_require(facade, CREATE_JIT_MASTER, segment)
masters.add(segment)
_require(facade, MAP_EXECUTABLE, segment)
_require(facade, CREATE_JIT_ALIAS, segment)
aliases.add(segment)
_require(facade, MAP_HOST_ALIAS, segment)
host_aliases.add(segment)
_require(facade, MAP_REMOTE_ALIAS, segment)
remote_aliases.add(segment)
_require(facade, COPY_ALIAS, segment)
_require(facade, UNMAP_REMOTE_ALIAS, segment)
remote_aliases.remove(segment)
_require(facade, UNMAP_HOST_ALIAS, segment)
host_aliases.remove(segment)
_require(facade, CLOSE_JIT_ALIAS, segment)
aliases.remove(segment)
_require(facade, CLOSE_JIT_MASTER, segment)
masters.remove(segment)
_require(facade, FINALIZE_IMAGE)
_require(facade, RELEASE_MIRROR)
mirror = False
committed = True
except Exception:
primary_failed = True
if primary_failed:
for resources, operation in (
(remote_aliases, UNMAP_REMOTE_ALIAS),
(host_aliases, UNMAP_HOST_ALIAS),
(aliases, CLOSE_JIT_ALIAS),
(masters, CLOSE_JIT_MASTER),
):
for segment in sorted(resources, reverse=True):
if facade.invoke(operation, segment, cleanup=True) != OK:
cleanup_failed = True
else:
resources.remove(segment)
if mirror:
if facade.invoke(RELEASE_MIRROR, cleanup=True) != OK:
cleanup_failed = True
else:
mirror = False
if region:
if facade.invoke(UNMAP_REGION, cleanup=True) != OK:
cleanup_failed = True
else:
region = False
if child:
if facade.invoke(KILL_AND_REAP_CHILD, cleanup=True) != OK:
raise CompositionError("fail-closed child termination failed")
child = False
terminated = True
masters.clear()
aliases.clear()
host_aliases.clear()
remote_aliases.clear()
mirror = region = False
if facade.remaining:
raise CompositionError("fake composition script has unused operations")
open_count = (int(mirror) + int(region) + len(masters) + len(aliases) +
len(host_aliases) + len(remote_aliases))
if primary_failed:
if child or open_count:
raise CompositionError("failed composition retained ownership")
classification = ("OFFLINE_FAIL_CLOSED_AFTER_CLEANUP_FAILURE" if cleanup_failed
else "OFFLINE_COMPOSITION_ROLLED_BACK")
return CompositionOutcome(classification, False, False, False, 0,
terminated)
if not committed or not child or not region or mirror or open_count != 1:
raise CompositionError("successful composition invariants failed")
return CompositionOutcome("OFFLINE_HYBRID_COMPOSITION_COMPLETE", True,
True, True, 0, False)
+197
View File
@@ -0,0 +1,197 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Capability-free exact-progress copy and credential restoration model."""
from __future__ import annotations
from dataclasses import dataclass
MAX_COPY_SIZE = 128 * 1024 * 1024
MAX_CHUNKS = 4096
MAX_EVENTS = MAX_CHUNKS + 16
MAX_TICKS = 8192
MAX_U64 = (1 << 64) - 1
BACKUP_AUTHID = "BACKUP_AUTHID"
BACKUP_CAPS = "BACKUP_CAPS"
SET_PRIV_AUTHID = "SET_PRIV_AUTHID"
SET_PRIV_CAPS = "SET_PRIV_CAPS"
COPY_CHUNK = "COPY_CHUNK"
RESTORE_CAPS = "RESTORE_CAPS"
RESTORE_AUTHID = "RESTORE_AUTHID"
KILL_AND_REAP_CHILD = "KILL_AND_REAP_CHILD"
TERMINATE_SERVICE = "TERMINATE_SERVICE"
OK = "OK"
ERROR = "ERROR"
MORE = "MORE"
COMPLETE = "COMPLETE"
OPERATIONS = {
BACKUP_AUTHID, BACKUP_CAPS, SET_PRIV_AUTHID, SET_PRIV_CAPS, COPY_CHUNK,
RESTORE_CAPS, RESTORE_AUTHID, KILL_AND_REAP_CHILD, TERMINATE_SERVICE,
}
class CopyModelError(RuntimeError):
"""The synthetic copy contract cannot reach a bounded safe state."""
@dataclass(frozen=True)
class CopyPlan:
source: int
destination: int
length: int
def __post_init__(self) -> None:
for value in (self.source, self.destination, self.length):
if not isinstance(value, int) or isinstance(value, bool) or value < 0:
raise CopyModelError("copy plan value is invalid")
if not 1 <= self.length <= MAX_COPY_SIZE:
raise CopyModelError("copy length is invalid")
if self.source > MAX_U64 - self.length \
or self.destination > MAX_U64 - self.length:
raise CopyModelError("copy range overflows")
@dataclass(frozen=True)
class FakeCopyEvent:
operation: str
result: str
progress: int = 0
remote_status: str = ""
ticks: int = 1
def __post_init__(self) -> None:
if self.operation not in OPERATIONS or self.result not in {OK, ERROR}:
raise CopyModelError("copy event operation/result is invalid")
if not isinstance(self.progress, int) or isinstance(self.progress, bool) \
or self.progress < 0:
raise CopyModelError("copy progress is invalid")
if self.operation == COPY_CHUNK:
if self.remote_status not in {MORE, COMPLETE}:
raise CopyModelError("copy status is invalid")
elif self.progress or self.remote_status:
raise CopyModelError("non-copy event carries copy result")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise CopyModelError("copy event ticks are invalid")
class FakeCopyFacade:
"""Exact fake script with no credential, process, clock or memory access."""
def __init__(self, events: tuple[FakeCopyEvent, ...]) -> None:
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_EVENTS \
or any(type(item) is not FakeCopyEvent for item in events):
raise CopyModelError("copy event script is invalid")
self._events = list(events)
self.ticks = 0
def invoke(self, operation: str, cleanup: bool = False) -> FakeCopyEvent:
if not self._events:
raise CopyModelError("copy event script is exhausted")
event = self._events.pop(0)
if event.operation != operation:
raise CopyModelError("copy event ordering differs")
if not cleanup and self.ticks + event.ticks > MAX_TICKS:
raise CopyModelError("copy deadline precedes operation")
self.ticks += event.ticks
return event
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class CopyOutcome:
classification: str
success: bool
copied: int
restore_failure_bits: int
child_alive: bool
service_available: bool
target_copy_performed: bool = False
firmware_behavior_proven: bool = False
def run_copy(plan: CopyPlan, facade: FakeCopyFacade) -> CopyOutcome:
"""Run one bounded synthetic copy and attempt every required restore."""
if type(plan) is not CopyPlan or type(facade) is not FakeCopyFacade:
raise CopyModelError("copy model boundary is invalid")
auth_changed = caps_changed = False
copied = chunks = restore_failures = 0
failed = False
try:
if facade.invoke(BACKUP_AUTHID).result != OK:
failed = True
elif facade.invoke(BACKUP_CAPS).result != OK:
failed = True
elif facade.invoke(SET_PRIV_AUTHID).result != OK:
failed = True
else:
auth_changed = True
if facade.invoke(SET_PRIV_CAPS).result != OK:
failed = True
else:
caps_changed = True
while copied < plan.length:
if chunks >= MAX_CHUNKS:
failed = True
break
event = facade.invoke(COPY_CHUNK)
chunks += 1
remaining = plan.length - copied
if event.result != OK or event.progress == 0 \
or event.progress > remaining:
failed = True
break
copied += event.progress
if event.remote_status == COMPLETE:
if copied != plan.length:
failed = True
break
if copied == plan.length:
failed = True
break
if copied != plan.length:
failed = True
except CopyModelError:
failed = True
if caps_changed:
if facade.invoke(RESTORE_CAPS, cleanup=True).result != OK:
restore_failures |= 1
caps_changed = False
if auth_changed:
if facade.invoke(RESTORE_AUTHID, cleanup=True).result != OK:
restore_failures |= 2
auth_changed = False
child_alive = True
service_available = True
if (failed and copied) or restore_failures:
if facade.invoke(KILL_AND_REAP_CHILD, cleanup=True).result != OK:
raise CopyModelError("child termination failed")
child_alive = False
if restore_failures:
if facade.invoke(TERMINATE_SERVICE, cleanup=True).result != OK:
raise CopyModelError("compromised service termination failed")
service_available = False
if facade.remaining:
raise CopyModelError("copy event script has unused operations")
success = not failed and copied == plan.length and restore_failures == 0
if success:
return CopyOutcome("OFFLINE_EXACT_COPY_COMPLETE", True, copied, 0,
True, True)
if restore_failures:
classification = "OFFLINE_RESTORE_FAILURE_CONTAINED"
elif copied:
classification = "OFFLINE_PARTIAL_COPY_CONTAINED"
else:
classification = "OFFLINE_COPY_REJECTED_BEFORE_MUTATION"
return CopyOutcome(classification, False, copied, restore_failures,
child_alive, service_available)
+188
View File
@@ -0,0 +1,188 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only supervisor/worker preemption architecture model."""
from __future__ import annotations
from dataclasses import dataclass
MAX_COPY_SIZE = 128 * 1024 * 1024
MAX_TICKS = 256
MAX_EVENTS = 16
CREATE_WORKER = "CREATE_WORKER"
VERIFY_WORKER = "VERIFY_WORKER"
START_COPY = "START_COPY"
RECEIVE_RESULT = "RECEIVE_RESULT"
DEADLINE = "DEADLINE"
TERMINATE_WORKER = "TERMINATE_WORKER"
REAP_WORKER = "REAP_WORKER"
TERMINATE_CHILD = "TERMINATE_CHILD"
REAP_CHILD = "REAP_CHILD"
OK = "OK"
ERROR = "ERROR"
SUCCESS = "SUCCESS"
COPY_ERROR = "COPY_ERROR"
RESTORE_ERROR = "RESTORE_ERROR"
OPERATIONS = {
CREATE_WORKER, VERIFY_WORKER, START_COPY, RECEIVE_RESULT, DEADLINE,
TERMINATE_WORKER, REAP_WORKER, TERMINATE_CHILD, REAP_CHILD,
}
class SupervisorError(RuntimeError):
"""The synthetic supervisor cannot prove containment."""
@dataclass(frozen=True)
class WorkerPlan:
worker_id: int
child_id: int
copy_length: int
def __post_init__(self) -> None:
for value in (self.worker_id, self.child_id, self.copy_length):
if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
raise SupervisorError("worker plan value is invalid")
if self.worker_id == self.child_id or self.copy_length > MAX_COPY_SIZE:
raise SupervisorError("worker plan identity or size is invalid")
@dataclass(frozen=True)
class WorkerResult:
worker_id: int
status: str
copied: int
restore_failure_bits: int
def __post_init__(self) -> None:
if not isinstance(self.worker_id, int) or isinstance(self.worker_id, bool) \
or self.worker_id <= 0 or self.status not in {
SUCCESS, COPY_ERROR, RESTORE_ERROR}:
raise SupervisorError("worker result identity/status is invalid")
if not isinstance(self.copied, int) or isinstance(self.copied, bool) \
or self.copied < 0 or not isinstance(self.restore_failure_bits, int) \
or isinstance(self.restore_failure_bits, bool) \
or not 0 <= self.restore_failure_bits <= 3:
raise SupervisorError("worker result fields are invalid")
@dataclass(frozen=True)
class FakeSupervisorEvent:
operation: str
result: str
worker_result: WorkerResult | None = None
ticks: int = 1
def __post_init__(self) -> None:
if self.operation not in OPERATIONS or self.result not in {OK, ERROR}:
raise SupervisorError("supervisor event is invalid")
if (self.operation == RECEIVE_RESULT) != (self.worker_result is not None):
raise SupervisorError("worker result binding is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise SupervisorError("supervisor event ticks are invalid")
class FakeSupervisorFacade:
"""Exact fake operations with no process, signal, clock or IPC access."""
def __init__(self, events: tuple[FakeSupervisorEvent, ...]) -> None:
if not isinstance(events, tuple) or not 1 <= len(events) <= MAX_EVENTS \
or any(type(item) is not FakeSupervisorEvent for item in events):
raise SupervisorError("supervisor script is invalid")
self._events = list(events)
self.ticks = 0
def invoke(self, operation: str, terminal: bool = False) -> FakeSupervisorEvent:
if not self._events:
raise SupervisorError("supervisor script is exhausted")
event = self._events.pop(0)
if event.operation != operation:
raise SupervisorError("supervisor event ordering differs")
if not terminal and self.ticks + event.ticks > MAX_TICKS:
raise SupervisorError("supervisor deadline precedes operation")
self.ticks += event.ticks
return event
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class SupervisorOutcome:
classification: str
success: bool
service_alive: bool
worker_alive: bool
child_alive: bool
copied: int
automatic_restart: bool = False
target_action_performed: bool = False
firmware_behavior_proven: bool = False
def _terminal(facade: FakeSupervisorFacade, operation: str) -> None:
if facade.invoke(operation, terminal=True).result != OK:
raise SupervisorError(f"terminal operation failed: {operation}")
def run_supervisor(plan: WorkerPlan, facade: FakeSupervisorFacade,
deadline_first: bool = False) -> SupervisorOutcome:
"""Run one synthetic, non-restarting worker attempt."""
if type(plan) is not WorkerPlan or type(facade) is not FakeSupervisorFacade \
or type(deadline_first) is not bool:
raise SupervisorError("supervisor model boundary is invalid")
worker = started = False
copied = 0
failed = deadline = False
if facade.invoke(CREATE_WORKER).result != OK:
failed = True
else:
worker = True
if facade.invoke(VERIFY_WORKER).result != OK:
failed = True
elif facade.invoke(START_COPY).result != OK:
started = True
failed = True
else:
started = True
if deadline_first:
if facade.invoke(DEADLINE).result != OK:
raise SupervisorError("deadline event failed")
deadline = failed = True
else:
event = facade.invoke(RECEIVE_RESULT)
result = event.worker_result
if event.result != OK or result is None:
failed = True
else:
copied = result.copied
valid = (result.worker_id == plan.worker_id and
result.status == SUCCESS and
result.copied == plan.copy_length and
result.restore_failure_bits == 0)
failed = not valid
if worker:
if failed:
_terminal(facade, TERMINATE_WORKER)
_terminal(facade, REAP_WORKER)
worker = False
if failed and started:
_terminal(facade, TERMINATE_CHILD)
_terminal(facade, REAP_CHILD)
if facade.remaining:
raise SupervisorError("supervisor script has unused operations")
if not failed:
return SupervisorOutcome("OFFLINE_WORKER_RESULT_ACCEPTED", True, True,
False, True, copied)
classification = ("OFFLINE_DEADLINE_CONTAINED" if deadline else
"OFFLINE_WORKER_FAILURE_CONTAINED")
return SupervisorOutcome(classification, False, True, False,
not started, copied)
+127
View File
@@ -0,0 +1,127 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Bytes-only fixed worker result record and generation identity contract."""
from __future__ import annotations
from dataclasses import dataclass
import hashlib
import struct
MAGIC = b"CHW10AQ1"
VERSION = 1
RECORD_SIZE = 128
HASHED_SIZE = 96
MAX_COPY_SIZE = 128 * 1024 * 1024
STATUS_SUCCESS = 0
STATUS_COPY_ERROR = 1
STATUS_RESTORE_ERROR = 2
STATUS_DEADLINE = 3
VALID_STATUSES = {STATUS_SUCCESS, STATUS_COPY_ERROR,
STATUS_RESTORE_ERROR, STATUS_DEADLINE}
PREFIX = struct.Struct("<8sHHIIIQQQII16s16s8s")
class WorkerRecordError(ValueError):
"""The fixed worker record is malformed or not precommitted."""
def _token(value: bytes, name: str) -> bytes:
if type(value) is not bytes or len(value) != 16 or not any(value):
raise WorkerRecordError(f"{name} must be a nonzero 16-byte token")
return value
@dataclass(frozen=True)
class WorkerPrecommit:
attempt_id: bytes
nonce: bytes
worker_pid: int
child_pid: int
generation: int
requested: int
def __post_init__(self) -> None:
_token(self.attempt_id, "attempt ID")
_token(self.nonce, "worker nonce")
for value in (self.worker_pid, self.child_pid, self.generation,
self.requested):
if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
raise WorkerRecordError("precommit integer is invalid")
if self.worker_pid == self.child_pid or self.worker_pid > 0xffffffff \
or self.child_pid > 0xffffffff or self.generation > 0xffffffffffffffff \
or self.requested > MAX_COPY_SIZE:
raise WorkerRecordError("precommit identity or size is invalid")
@dataclass(frozen=True)
class WorkerRecord:
status: int
worker_pid: int
child_pid: int
generation: int
requested: int
copied: int
restore_failure_bits: int
flags: int
attempt_id: bytes
nonce: bytes
@property
def successful(self) -> bool:
return (self.status == STATUS_SUCCESS and self.copied == self.requested
and self.restore_failure_bits == 0 and self.flags == 0)
def encode_record(precommit: WorkerPrecommit, status: int, copied: int,
restore_failure_bits: int = 0, flags: int = 0) -> bytes:
"""Encode synthetic bytes; this function has no transport capability."""
if type(precommit) is not WorkerPrecommit or status not in VALID_STATUSES:
raise WorkerRecordError("record input is invalid")
for value in (copied, restore_failure_bits, flags):
if not isinstance(value, int) or isinstance(value, bool) or value < 0:
raise WorkerRecordError("record numeric field is invalid")
if copied > precommit.requested or restore_failure_bits > 3 \
or flags > 0xffffffff:
raise WorkerRecordError("record progress, restore bits or flags are invalid")
if status == STATUS_SUCCESS and (copied != precommit.requested
or restore_failure_bits or flags):
raise WorkerRecordError("success record is not exact")
prefix = PREFIX.pack(MAGIC, VERSION, RECORD_SIZE, status,
precommit.worker_pid, precommit.child_pid,
precommit.generation, precommit.requested, copied,
restore_failure_bits, flags, precommit.attempt_id,
precommit.nonce, bytes(8))
if len(prefix) != HASHED_SIZE:
raise WorkerRecordError("internal record layout differs")
return prefix + hashlib.sha256(prefix).digest()
def parse_record(raw: bytes, expected: WorkerPrecommit) -> WorkerRecord:
"""Parse exactly one complete record and enforce the full precommit."""
if type(raw) is not bytes or len(raw) != RECORD_SIZE \
or type(expected) is not WorkerPrecommit:
raise WorkerRecordError("record boundary is invalid")
prefix, digest = raw[:HASHED_SIZE], raw[HASHED_SIZE:]
if not hashlib.sha256(prefix).digest() == digest:
raise WorkerRecordError("record digest differs")
(magic, version, size, status, worker_pid, child_pid, generation,
requested, copied, restore_bits, flags, attempt_id, nonce,
reserved) = PREFIX.unpack(prefix)
if magic != MAGIC or version != VERSION or size != RECORD_SIZE \
or status not in VALID_STATUSES or any(reserved):
raise WorkerRecordError("record header is invalid")
if (worker_pid, child_pid, generation, requested, attempt_id, nonce) != (
expected.worker_pid, expected.child_pid, expected.generation,
expected.requested, expected.attempt_id, expected.nonce):
raise WorkerRecordError("record identity differs from precommit")
if copied > requested or restore_bits > 3 or flags != 0:
raise WorkerRecordError("record result fields are invalid")
record = WorkerRecord(status, worker_pid, child_pid, generation, requested,
copied, restore_bits, flags, attempt_id, nonce)
if status == STATUS_SUCCESS and not record.successful:
raise WorkerRecordError("success record is incomplete")
if status == STATUS_RESTORE_ERROR and restore_bits == 0:
raise WorkerRecordError("restore error has no failure bits")
return record
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Transport-free partial-read/deadline model for one worker result record."""
from __future__ import annotations
from dataclasses import dataclass
from phase10aq_worker_result_record import (
RECORD_SIZE, WorkerPrecommit, WorkerRecord, WorkerRecordError, parse_record,
)
MAX_CHUNKS = 128
MAX_TICKS = 256
DATA = "DATA"
EOF = "EOF"
DEADLINE = "DEADLINE"
EVENTS = {DATA, EOF, DEADLINE}
class ChannelModelError(RuntimeError):
"""The synthetic channel script or boundary is invalid."""
@dataclass(frozen=True)
class FakeReadEvent:
kind: str
data: bytes = b""
ticks: int = 1
def __post_init__(self) -> None:
if self.kind not in EVENTS or type(self.data) is not bytes:
raise ChannelModelError("read event is invalid")
if (self.kind == DATA) != bool(self.data) or len(self.data) > RECORD_SIZE:
raise ChannelModelError("read event payload is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise ChannelModelError("read event ticks are invalid")
@dataclass(frozen=True)
class ChannelPlan:
precommit: WorkerPrecommit
writer_pid: int
writer_generation: int
writer_nonce: bytes
exclusive_writer: bool = True
def __post_init__(self) -> None:
if type(self.precommit) is not WorkerPrecommit \
or self.writer_pid != self.precommit.worker_pid \
or self.writer_generation != self.precommit.generation \
or self.writer_nonce != self.precommit.nonce \
or self.exclusive_writer is not True:
raise ChannelModelError("exclusive writer precommit differs")
@dataclass(frozen=True)
class ChannelOutcome:
classification: str
accepted: bool
buffered: int
record: WorkerRecord | None
containment_required: bool
eof_is_success: bool = False
live_transport_present: bool = False
def receive_record(plan: ChannelPlan,
events: tuple[FakeReadEvent, ...]) -> ChannelOutcome:
"""Assemble one exact record from supplied bytes; no I/O is performed."""
if type(plan) is not ChannelPlan or not isinstance(events, tuple) \
or not 1 <= len(events) <= MAX_CHUNKS \
or any(type(item) is not FakeReadEvent for item in events):
raise ChannelModelError("channel model boundary is invalid")
buffer = bytearray()
ticks = 0
for index, event in enumerate(events):
if ticks + event.ticks > MAX_TICKS:
return ChannelOutcome("OFFLINE_CHANNEL_DEADLINE", False,
len(buffer), None, True)
ticks += event.ticks
if event.kind == DEADLINE:
return ChannelOutcome("OFFLINE_CHANNEL_DEADLINE", False,
len(buffer), None, True)
if event.kind == EOF:
return ChannelOutcome("OFFLINE_EOF_BEFORE_COMPLETE_RECORD", False,
len(buffer), None, True)
if len(buffer) + len(event.data) > RECORD_SIZE:
return ChannelOutcome("OFFLINE_CHANNEL_OVERFLOW", False,
len(buffer), None, True)
buffer.extend(event.data)
if len(buffer) == RECORD_SIZE:
if index != len(events) - 1:
raise ChannelModelError("events remain after record boundary")
try:
record = parse_record(bytes(buffer), plan.precommit)
except WorkerRecordError:
return ChannelOutcome("OFFLINE_RECORD_REJECTED", False,
RECORD_SIZE, None, True)
return ChannelOutcome("OFFLINE_EXACT_RECORD_ACCEPTED", True,
RECORD_SIZE, record, False)
return ChannelOutcome("OFFLINE_INCOMPLETE_WITHOUT_DEADLINE", False,
len(buffer), None, True)
+205
View File
@@ -0,0 +1,205 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only RFFDG descriptor ownership and absolute deadline model."""
from __future__ import annotations
from dataclasses import dataclass
from phase10aq_worker_result_record import (
RECORD_SIZE, WorkerPrecommit, WorkerRecordError, parse_record,
)
MAX_TICKS = 256
MAX_READ_EVENTS = 256
CREATE_PIPE = "CREATE_PIPE"
SET_PARENT_READ_NONBLOCK = "SET_PARENT_READ_NONBLOCK"
SPAWN_RFFDG = "SPAWN_RFFDG"
PARENT_CLOSE_WRITE = "PARENT_CLOSE_WRITE"
CHILD_CLOSE_READ = "CHILD_CLOSE_READ"
CHILD_CLOSE_WRITE = "CHILD_CLOSE_WRITE"
PARENT_CLOSE_READ = "PARENT_CLOSE_READ"
TERMINATE_CHILD = "TERMINATE_CHILD"
REAP_CHILD = "REAP_CHILD"
OK = "OK"
ERROR = "ERROR"
DATA = "DATA"
EINTR = "EINTR"
WOULD_BLOCK = "WOULD_BLOCK"
EOF = "EOF"
OPERATIONS = {
CREATE_PIPE, SET_PARENT_READ_NONBLOCK, SPAWN_RFFDG,
PARENT_CLOSE_WRITE, CHILD_CLOSE_READ, CHILD_CLOSE_WRITE,
PARENT_CLOSE_READ, TERMINATE_CHILD, REAP_CHILD,
}
READ_KINDS = {DATA, EINTR, WOULD_BLOCK, EOF}
class FdModelError(RuntimeError):
"""The synthetic descriptor transaction cannot close safely."""
@dataclass(frozen=True)
class FakeFdEvent:
operation: str
result: str
ticks: int = 1
def __post_init__(self) -> None:
if self.operation not in OPERATIONS or self.result not in {OK, ERROR}:
raise FdModelError("FD event is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise FdModelError("FD event ticks are invalid")
@dataclass(frozen=True)
class FakeRead:
kind: str
data: bytes = b""
ticks: int = 1
def __post_init__(self) -> None:
if self.kind not in READ_KINDS or type(self.data) is not bytes:
raise FdModelError("read event is invalid")
if (self.kind == DATA) != bool(self.data) or len(self.data) > RECORD_SIZE:
raise FdModelError("read payload is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise FdModelError("read ticks are invalid")
class FakeFdFacade:
"""Exact scripted FD facade with no OS, process, clock or I/O imports."""
def __init__(self, events: tuple[FakeFdEvent, ...]) -> None:
if not isinstance(events, tuple) or not events \
or any(type(item) is not FakeFdEvent for item in events):
raise FdModelError("FD script is invalid")
self._events = list(events)
self.ticks = 0
def invoke(self, operation: str, cleanup: bool = False) -> str:
if not self._events:
raise FdModelError("FD script is exhausted")
event = self._events.pop(0)
if event.operation != operation:
raise FdModelError("FD operation ordering differs")
if not cleanup and self.ticks + event.ticks > MAX_TICKS:
raise FdModelError("absolute deadline precedes FD operation")
self.ticks += event.ticks
return event.result
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class FdOutcome:
classification: str
success: bool
buffered: int
eintr_count: int
parent_fds_open: int
child_fds_open: int
worker_alive: bool
containment_required: bool
rffdg_used: bool = True
live_fd_present: bool = False
def _close(facade: FakeFdFacade, operation: str) -> None:
if facade.invoke(operation, cleanup=True) != OK:
raise FdModelError(f"terminal cleanup failed: {operation}")
def run_fd_transaction(precommit: WorkerPrecommit, facade: FakeFdFacade,
reads: tuple[FakeRead, ...]) -> FdOutcome:
"""Model exact descriptor ownership and one absolute deadline."""
if type(precommit) is not WorkerPrecommit or type(facade) is not FakeFdFacade \
or not isinstance(reads, tuple) or not 1 <= len(reads) <= MAX_READ_EVENTS \
or any(type(item) is not FakeRead for item in reads):
raise FdModelError("FD model boundary is invalid")
parent_read = parent_write = child_read = child_write = worker = False
failed = False
buffer = bytearray()
eintr_count = 0
try:
if facade.invoke(CREATE_PIPE) != OK:
failed = True
else:
parent_read = parent_write = True
if facade.invoke(SET_PARENT_READ_NONBLOCK) != OK:
failed = True
elif facade.invoke(SPAWN_RFFDG) != OK:
failed = True
else:
worker = child_read = child_write = True
if facade.invoke(PARENT_CLOSE_WRITE) != OK:
failed = True
else:
parent_write = False
if facade.invoke(CHILD_CLOSE_READ) != OK:
failed = True
else:
child_read = False
for index, read in enumerate(reads):
if facade.ticks + read.ticks > MAX_TICKS:
failed = True
break
facade.ticks += read.ticks
if read.kind == EINTR:
eintr_count += 1
continue
if read.kind == WOULD_BLOCK:
continue
if read.kind == EOF:
failed = True
break
if len(buffer) + len(read.data) > RECORD_SIZE:
failed = True
break
buffer.extend(read.data)
if len(buffer) == RECORD_SIZE:
if index != len(reads) - 1:
failed = True
break
try:
parse_record(bytes(buffer), precommit)
except WorkerRecordError:
failed = True
break
if len(buffer) != RECORD_SIZE:
failed = True
except FdModelError:
failed = True
if worker:
if failed:
_close(facade, TERMINATE_CHILD)
if child_read:
_close(facade, CHILD_CLOSE_READ)
child_read = False
if child_write:
_close(facade, CHILD_CLOSE_WRITE)
child_write = False
_close(facade, REAP_CHILD)
worker = False
if parent_write:
_close(facade, PARENT_CLOSE_WRITE)
parent_write = False
if parent_read:
_close(facade, PARENT_CLOSE_READ)
parent_read = False
if facade.remaining:
raise FdModelError("FD script has unused operations")
if failed:
return FdOutcome("OFFLINE_FD_TRANSACTION_CONTAINED", False,
len(buffer), eintr_count, 0, 0, False, True)
return FdOutcome("OFFLINE_FD_TRANSACTION_COMPLETE", True,
RECORD_SIZE, eintr_count, 0, 0, False, False)
+179
View File
@@ -0,0 +1,179 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Target-free launch-context A/B canary contract.
This module validates immutable synthetic data only. It has no target source,
artifact, socket, process, clock, filesystem output or device capability.
"""
from __future__ import annotations
from dataclasses import dataclass
import re
PHASE = "PHASE_1_0AV_TARGET_FREE_LAUNCH_CONTEXT_CANARY"
FIRMWARE = "9.60"
PROTOCOL_MAGIC = "CHD10AV1"
RAW_ELFLDR = "RAW_ELFLDR"
BIGAPP_CANDIDATE = "BIGAPP_CANDIDATE"
ARM_KINDS = (RAW_ELFLDR, BIGAPP_CANDIDATE)
SHA256 = re.compile(r"^[0-9a-f]{64}$")
RUN_ID = re.compile(r"^CHIMERA_AV_[A-Z0-9_-]{8,48}$")
RETURN_MIN = -(1 << 31)
RETURN_MAX = (1 << 31) - 1
class CanaryContractError(ValueError):
"""The offline canary contract is incomplete, ambiguous or unsafe."""
def _exact_hash(value: str) -> bool:
return isinstance(value, str) and SHA256.fullmatch(value) is not None
@dataclass(frozen=True)
class CanaryArm:
kind: str
launcher_sha256: str
run_id: str
approval_sha256: str
@dataclass(frozen=True)
class CanaryPairPlan:
phase: str
firmware: str
protocol_magic: str
payload_sha256: str
arms: tuple[CanaryArm, CanaryArm]
one_shot_each: bool
automatic_retry: bool
reconnect: bool
resume: bool
installation: bool
autoload: bool
device_write_authorized: bool
app_termination_authorized: bool
result_reception_authorized: bool
activation_authorized: bool
@dataclass(frozen=True)
class CanaryObservation:
kind: str
launcher_sha256: str
payload_sha256: str
run_id: str
protocol_magic: str
d04_seen: bool
d04_result: int
d04_sequence: int
submit_seen: bool
submit_result: int
submit_errno: int
submit_sequence: int
terminal_seen: bool
terminal_sequence: int
cleanup_complete: bool
visible_output_observed: bool
retry_count: int
persistent_write_count: int
@dataclass(frozen=True)
class CanaryClassification:
status: str
pair_comparable: bool
submit_return_differs: bool
launch_context_candidate: bool
root_cause_proven: bool = False
visible_output_proven: bool = False
firmware_behavior_proven: bool = False
device_action_authorized: bool = False
def validate_plan(plan: CanaryPairPlan) -> None:
"""Validate a hypothetical pair without activating either arm."""
if type(plan) is not CanaryPairPlan or plan.phase != PHASE \
or plan.firmware != FIRMWARE or plan.protocol_magic != PROTOCOL_MAGIC:
raise CanaryContractError("pair identity is invalid")
if not _exact_hash(plan.payload_sha256) or type(plan.arms) is not tuple \
or len(plan.arms) != 2 \
or any(type(arm) is not CanaryArm for arm in plan.arms):
raise CanaryContractError("pair binding is invalid")
if tuple(arm.kind for arm in plan.arms) != ARM_KINDS:
raise CanaryContractError("arm order or kind is invalid")
for arm in plan.arms:
if not _exact_hash(arm.launcher_sha256) \
or not _exact_hash(arm.approval_sha256) \
or not isinstance(arm.run_id, str) \
or RUN_ID.fullmatch(arm.run_id) is None:
raise CanaryContractError("arm identity is invalid")
if plan.arms[0].launcher_sha256 == plan.arms[1].launcher_sha256 \
or plan.arms[0].run_id == plan.arms[1].run_id \
or plan.arms[0].approval_sha256 == plan.arms[1].approval_sha256:
raise CanaryContractError("arms are not independently authorized")
if plan.one_shot_each is not True or plan.automatic_retry is not False \
or plan.reconnect is not False or plan.resume is not False \
or plan.installation is not False or plan.autoload is not False:
raise CanaryContractError("pair one-shot policy is invalid")
if plan.device_write_authorized or plan.app_termination_authorized \
or plan.result_reception_authorized or plan.activation_authorized:
raise CanaryContractError("offline plan grants device authority")
def _validate_observation(plan: CanaryPairPlan, arm: CanaryArm,
observation: CanaryObservation) -> bool:
if type(observation) is not CanaryObservation \
or observation.kind != arm.kind \
or observation.launcher_sha256 != arm.launcher_sha256 \
or observation.payload_sha256 != plan.payload_sha256 \
or observation.run_id != arm.run_id \
or observation.protocol_magic != PROTOCOL_MAGIC:
raise CanaryContractError("observation identity differs")
booleans = (observation.d04_seen, observation.submit_seen,
observation.terminal_seen, observation.cleanup_complete,
observation.visible_output_observed)
if any(type(value) is not bool for value in booleans):
raise CanaryContractError("observation boolean field is invalid")
numeric = (observation.d04_result, observation.submit_result,
observation.submit_errno)
if any(type(value) is not int or not RETURN_MIN <= value <= RETURN_MAX
for value in numeric):
raise CanaryContractError("observation numeric field is invalid")
counts = (observation.submit_sequence, observation.d04_sequence,
observation.terminal_sequence,
observation.retry_count, observation.persistent_write_count)
if any(type(value) is not int or value < 0 for value in counts):
raise CanaryContractError("observation count is invalid")
if observation.retry_count != 0 or observation.persistent_write_count != 0:
raise CanaryContractError("observation reports forbidden effects")
if observation.visible_output_observed:
raise CanaryContractError("unscoped visible-output claim is forbidden")
complete = observation.d04_seen and observation.submit_seen \
and observation.terminal_seen and observation.cleanup_complete \
and observation.submit_sequence < observation.d04_sequence \
and observation.d04_sequence < observation.terminal_sequence
return complete
def classify_pair(plan: CanaryPairPlan,
observations: tuple[CanaryObservation, CanaryObservation]
) -> CanaryClassification:
"""Classify supplied synthetic results without interpreting VideoOut ABI."""
validate_plan(plan)
if type(observations) is not tuple or len(observations) != 2:
raise CanaryContractError("observation pair is invalid")
complete = tuple(_validate_observation(plan, arm, observation)
for arm, observation in zip(plan.arms, observations))
if not all(complete):
return CanaryClassification("INCOMPLETE_NO_CAUSAL_COMPARISON",
False, False, False)
differs = observations[0].submit_result != observations[1].submit_result
if not differs:
return CanaryClassification("NO_SUBMIT_RETURN_DIFFERENCE",
True, False, False)
return CanaryClassification(
"LAUNCH_CONTEXT_SUBMIT_RETURN_DIFFERENCE_CANDIDATE_ONLY",
True, True, True)
+189
View File
@@ -0,0 +1,189 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only CHD10AV1 frame and cleanup-terminal reference model."""
from __future__ import annotations
from dataclasses import dataclass
import struct
import zlib
MAGIC = b"CHD10AV1"
VERSION = 1
FRAME_SIZE = 64
D04 = 4
D07 = 7
D12 = 12
D14 = 30
KIND_RAW = 1
KIND_PAIR = 2
RAW0_VALID = 1 << 0
RAW1_VALID = 1 << 1
TERMINAL = 1 << 2
ALLOWED_FLAGS = RAW0_VALID | RAW1_VALID | TERMINAL
S15_COMPLETE = 15
UINT32_MAX = (1 << 32) - 1
INT32_MIN = -(1 << 31)
INT32_MAX = (1 << 31) - 1
class CanaryProtocolError(ValueError):
"""A synthetic AV frame or cleanup state is invalid."""
@dataclass(frozen=True)
class Frame:
sequence: int
stage: int
kind: int
flags: int
raw0: int
raw1: int
result: int
aux0: int
aux1: int
@dataclass(frozen=True)
class CleanupSnapshot:
rarch_main_returned: bool
d04_emitted: bool
phase: int
initialized_mask: int
cleaned_mask: int
cleanup_order_errors: int
cleanup_failure_count: int
rarch_main_result: int
@dataclass(frozen=True)
class TraceResult:
complete: bool
submit_result: int
sdl_result: int
rarch_main_result: int
cleaned_mask: int
visible_output_proven: bool = False
firmware_behavior_proven: bool = False
device_action_authorized: bool = False
def _u32(value: int, label: str) -> int:
if type(value) is not int or not 0 <= value <= UINT32_MAX:
raise CanaryProtocolError(f"{label} is not uint32")
return value
def _i32(value: int, label: str) -> int:
if type(value) is not int or not INT32_MIN <= value <= INT32_MAX:
raise CanaryProtocolError(f"{label} is not int32")
return value
def encode_frame(frame: Frame) -> bytes:
"""Encode one exact frame; AV has exactly one possible terminal stage."""
if type(frame) is not Frame:
raise CanaryProtocolError("frame type is invalid")
_u32(frame.sequence, "sequence")
if frame.sequence == 0 or type(frame.stage) is not int \
or not 0 <= frame.stage <= D14 or frame.kind not in {KIND_RAW, KIND_PAIR}:
raise CanaryProtocolError("frame identity is invalid")
if type(frame.flags) is not int or frame.flags & ~ALLOWED_FLAGS:
raise CanaryProtocolError("frame flags are invalid")
if frame.stage == D14:
if frame.kind != KIND_PAIR or frame.flags != (RAW0_VALID | RAW1_VALID | TERMINAL):
raise CanaryProtocolError("D14 is not the exact terminal frame")
elif frame.flags & TERMINAL:
raise CanaryProtocolError("only D14 may be terminal")
for value, label in ((frame.raw0, "raw0"), (frame.raw1, "raw1"),
(frame.result, "result")):
_i32(value, label)
_u32(frame.aux0, "aux0")
_u32(frame.aux1, "aux1")
output = bytearray(FRAME_SIZE)
output[:8] = MAGIC
struct.pack_into(">HHIBBHiiiII", output, 8, VERSION, FRAME_SIZE,
frame.sequence, frame.stage, frame.kind, frame.flags,
frame.raw0, frame.raw1, frame.result,
frame.aux0, frame.aux1)
struct.pack_into(">I", output, 60, zlib.crc32(output[:60]) & UINT32_MAX)
return bytes(output)
def parse_frame(raw: bytes) -> Frame:
if type(raw) is not bytes or len(raw) != FRAME_SIZE or raw[:8] != MAGIC:
raise CanaryProtocolError("frame envelope is invalid")
if any(raw[40:60]):
raise CanaryProtocolError("reserved frame bytes are nonzero")
expected = zlib.crc32(raw[:60]) & UINT32_MAX
if struct.unpack_from(">I", raw, 60)[0] != expected:
raise CanaryProtocolError("frame CRC differs")
version, size, sequence, stage, kind, flags, raw0, raw1, result, aux0, aux1 = \
struct.unpack_from(">HHIBBHiiiII", raw, 8)
if version != VERSION or size != FRAME_SIZE:
raise CanaryProtocolError("frame version or size differs")
frame = Frame(sequence, stage, kind, flags, raw0, raw1, result, aux0, aux1)
if encode_frame(frame) != raw:
raise CanaryProtocolError("frame is not canonical")
return frame
def build_cleanup_terminal(sequence: int, snapshot: CleanupSnapshot) -> bytes | None:
"""Return D14 only when the modeled lifecycle is completely closed."""
if type(snapshot) is not CleanupSnapshot:
raise CanaryProtocolError("cleanup snapshot type is invalid")
booleans = (snapshot.rarch_main_returned, snapshot.d04_emitted)
if any(type(value) is not bool for value in booleans):
raise CanaryProtocolError("cleanup booleans are invalid")
for value, label in ((snapshot.phase, "phase"),
(snapshot.initialized_mask, "initialized mask"),
(snapshot.cleaned_mask, "cleaned mask"),
(snapshot.cleanup_order_errors, "cleanup order errors"),
(snapshot.cleanup_failure_count, "cleanup failure count")):
_u32(value, label)
_i32(snapshot.rarch_main_result, "rarch_main result")
complete = snapshot.rarch_main_returned and snapshot.d04_emitted \
and snapshot.phase == S15_COMPLETE and snapshot.initialized_mask == 0 \
and snapshot.cleanup_order_errors == 0 \
and snapshot.cleanup_failure_count == 0
if not complete:
return None
return encode_frame(Frame(sequence, D14, KIND_PAIR,
RAW0_VALID | RAW1_VALID | TERMINAL,
snapshot.initialized_mask, snapshot.cleaned_mask,
snapshot.rarch_main_result,
snapshot.cleanup_order_errors,
snapshot.cleanup_failure_count))
def validate_trace(raw_frames: tuple[bytes, ...]) -> TraceResult:
"""Require one ordered D07/D04/D14 path and no bytes after terminal."""
if type(raw_frames) is not tuple or not raw_frames:
raise CanaryProtocolError("trace is empty or not immutable")
frames = tuple(parse_frame(raw) for raw in raw_frames)
if any(right.sequence <= left.sequence for left, right in zip(frames, frames[1:])):
raise CanaryProtocolError("frame sequence is not strictly increasing")
terminal_indexes = [index for index, frame in enumerate(frames)
if frame.flags & TERMINAL]
if terminal_indexes != [len(frames) - 1]:
raise CanaryProtocolError("terminal is absent, duplicated or not final")
for stage in (D07, D04, D14):
if sum(frame.stage == stage for frame in frames) != 1:
raise CanaryProtocolError("required stage is absent or duplicated")
if sum(frame.stage == D12 for frame in frames) > 1:
raise CanaryProtocolError("D12 is duplicated")
positions = {frame.stage: index for index, frame in enumerate(frames)
if frame.stage in {D07, D04, D14}}
if not positions[D07] < positions[D04] < positions[D14]:
raise CanaryProtocolError("submit/D04/D14 order differs")
terminal = frames[-1]
if terminal.raw0 != 0 or terminal.aux0 != 0 or terminal.aux1 != 0:
raise CanaryProtocolError("D14 cleanup predicate differs")
submit = frames[positions[D07]]
sdl = frames[positions[D04]]
if any(frame.kind != KIND_RAW or frame.flags != RAW0_VALID
for frame in (submit, sdl)):
raise CanaryProtocolError("D07 or D04 semantics differ")
return TraceResult(True, submit.raw0, sdl.raw0, terminal.result,
terminal.raw1)
+138
View File
@@ -0,0 +1,138 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Pure, inactive Phase-1.0DC BigApp comparison-gate contract."""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
import re
PHASE = "PHASE_1_0DC_INACTIVE_BIGAPP_COMPARISON_GATE"
FIRMWARE = "9.60"
TITLE_ID = "PPSA01659"
PAYLOAD_NAME = "retroarch_ps5_launch_canary.elf"
PAYLOAD_SIZE = 1845240
PAYLOAD_SHA256 = "8dadce9d9faaef21ea129a3d216c768eea9a3ca9bf8ecb8d852e376b58a9bf95"
PROTOCOL_MAGIC = "CHD10AV1"
PROTOCOL_TERMINAL = "D14"
MAX_WINDOW_SECONDS = 300
SHA256 = re.compile(r"^[0-9a-f]{64}$")
RUN_ID = re.compile(r"^[A-Z0-9][A-Z0-9_-]{7,63}$")
class BigAppGateError(ValueError):
"""Candidate data is incomplete, ambiguous, or unsafe."""
@dataclass(frozen=True)
class BigAppGateRecord:
phase: str
active: bool
firmware: str | None
title_id: str | None
run_id: str | None
not_before: str | None
expires_at: str | None
launcher_name: str | None
launcher_size: int | None
launcher_sha256: str | None
payload_name: str | None
payload_size: int | None
payload_sha256: str | None
approval_sha256: str | None
result_magic: str | None
result_terminal: str | None
no_running_bigapp_attested: bool
kernel_ptrace_effects_accepted: bool
app_termination_authorized: bool
persistent_write_authorized: bool
system_remount_authorized: bool
installation_authorized: bool
autoload_authorized: bool
automatic_retry: bool
reconnect: bool
fallback_title: bool
bounded_parent_detach_proven: bool
bounded_child_cleanup_proven: bool
bounded_result_channel_proven: bool
def _utc(value: str | None) -> datetime:
if not isinstance(value, str) or not value.endswith("Z"):
raise BigAppGateError("timestamp must be exact UTC")
try:
result = datetime.fromisoformat(value[:-1] + "+00:00")
except ValueError as error:
raise BigAppGateError("timestamp is invalid") from error
if result.tzinfo != timezone.utc:
raise BigAppGateError("timestamp is not UTC")
return result
def validate_inactive(record: BigAppGateRecord) -> None:
"""Require the tracked record to contain no live identity or authority."""
if type(record) is not BigAppGateRecord or record.phase != PHASE or record.active:
raise BigAppGateError("tracked gate is not inert")
identities = (
record.firmware, record.title_id, record.run_id, record.not_before,
record.expires_at, record.launcher_name, record.launcher_size,
record.launcher_sha256, record.payload_name, record.payload_size,
record.payload_sha256, record.approval_sha256, record.result_magic,
record.result_terminal,
)
if any(value is not None for value in identities):
raise BigAppGateError("inactive gate contains an identity")
if any((record.no_running_bigapp_attested,
record.kernel_ptrace_effects_accepted,
record.app_termination_authorized,
record.persistent_write_authorized,
record.system_remount_authorized,
record.installation_authorized, record.autoload_authorized,
record.automatic_retry, record.reconnect, record.fallback_title,
record.bounded_parent_detach_proven,
record.bounded_child_cleanup_proven,
record.bounded_result_channel_proven)):
raise BigAppGateError("inactive gate contains authority or proof")
def validate_candidate(record: BigAppGateRecord) -> None:
"""Validate hypothetical data; this function grants no authorization."""
if type(record) is not BigAppGateRecord or record.phase != PHASE or not record.active:
raise BigAppGateError("candidate is not explicitly active")
if record.firmware != FIRMWARE or record.title_id != TITLE_ID:
raise BigAppGateError("firmware or fixed title mismatch")
if not isinstance(record.run_id, str) or not RUN_ID.fullmatch(record.run_id):
raise BigAppGateError("run identity is invalid")
start, end = _utc(record.not_before), _utc(record.expires_at)
if not 0 < (end - start).total_seconds() <= MAX_WINDOW_SECONDS:
raise BigAppGateError("activation window is invalid")
if record.launcher_name != "chimera_bigapp_canary_launcher.elf" or \
not isinstance(record.launcher_size, int) or isinstance(record.launcher_size, bool) or \
not 1 <= record.launcher_size <= 1048576 or \
not isinstance(record.launcher_sha256, str) or not SHA256.fullmatch(record.launcher_sha256):
raise BigAppGateError("launcher identity is invalid")
if (record.payload_name, record.payload_size, record.payload_sha256) != \
(PAYLOAD_NAME, PAYLOAD_SIZE, PAYLOAD_SHA256):
raise BigAppGateError("payload identity is not the unchanged CZ artifact")
if not isinstance(record.approval_sha256, str) or not SHA256.fullmatch(record.approval_sha256):
raise BigAppGateError("separate approval identity is invalid")
if (record.result_magic, record.result_terminal) != \
(PROTOCOL_MAGIC, PROTOCOL_TERMINAL):
raise BigAppGateError("result protocol is invalid")
required = (record.no_running_bigapp_attested,
record.kernel_ptrace_effects_accepted,
record.bounded_parent_detach_proven,
record.bounded_child_cleanup_proven,
record.bounded_result_channel_proven)
if any(value is not True for value in required):
raise BigAppGateError("required attestation or bounded proof is absent")
forbidden = (record.app_termination_authorized,
record.persistent_write_authorized,
record.system_remount_authorized,
record.installation_authorized, record.autoload_authorized,
record.automatic_retry, record.reconnect,
record.fallback_title)
if any(value is not False for value in forbidden):
raise BigAppGateError("candidate permits a forbidden effect")
+136
View File
@@ -0,0 +1,136 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Pure, inactive title-presence observer contract for Phase 1.0DF."""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
import re
PHASE = "PHASE_1_0DF_INACTIVE_TITLE_PRESENCE_OBSERVER"
FIRMWARE = "9.60"
TITLE_ID = "PPSA01659"
MAX_RESULT_BYTES = 4096
SHA256 = re.compile(r"^[0-9a-f]{64}$")
class ObserverError(ValueError):
"""An observer plan or result is ambiguous or unsafe."""
class Outcome(Enum):
PRESENT = "PRESENT"
ABSENT = "ABSENT"
UNKNOWN = "UNKNOWN"
@dataclass(frozen=True)
class ObserverPlan:
phase: str
active: bool
firmware: str | None
title_id: str | None
method: str | None
query_contract_sha256: str | None
exact_literal_path: str | None
path_provenance_sha256: str | None
request_bytes_sha256: str | None
maximum_result_bytes: int | None
one_request: bool
read_only: bool
shell_present: bool
directory_enumeration: bool
title_launch: bool
app_termination: bool
device_write: bool
retry: bool
reconnect: bool
@dataclass(frozen=True)
class SyntheticResult:
firmware: str
title_id: str
method: str
request_bytes_sha256: str
complete: bool
result_bytes: int
explicit_present: bool
explicit_absent: bool
error_code: int | None
def validate_inactive(plan: ObserverPlan) -> None:
"""Require the tracked plan to be empty and incapable of a request."""
if type(plan) is not ObserverPlan or plan.phase != PHASE or plan.active:
raise ObserverError("tracked observer is not inactive")
optional = (plan.firmware, plan.title_id, plan.method,
plan.query_contract_sha256, plan.exact_literal_path,
plan.path_provenance_sha256, plan.request_bytes_sha256,
plan.maximum_result_bytes)
if any(value is not None for value in optional):
raise ObserverError("inactive observer contains request data")
if any((plan.one_request, plan.read_only, plan.shell_present,
plan.directory_enumeration, plan.title_launch,
plan.app_termination, plan.device_write, plan.retry,
plan.reconnect)):
raise ObserverError("inactive observer contains capability")
def validate_candidate(plan: ObserverPlan) -> None:
"""Validate hypothetical data without creating or authorizing a request."""
if type(plan) is not ObserverPlan or plan.phase != PHASE or not plan.active:
raise ObserverError("candidate is not active data")
if plan.firmware != FIRMWARE or plan.title_id != TITLE_ID:
raise ObserverError("firmware or title mismatch")
if plan.method not in {"SOURCE_BOUND_QUERY", "EXACT_PATH_METADATA"}:
raise ObserverError("observer method is not allowlisted")
if not isinstance(plan.query_contract_sha256, str) or \
not SHA256.fullmatch(plan.query_contract_sha256):
raise ObserverError("query contract identity is absent")
if not isinstance(plan.request_bytes_sha256, str) or \
not SHA256.fullmatch(plan.request_bytes_sha256):
raise ObserverError("request bytes are not bound")
if plan.maximum_result_bytes != MAX_RESULT_BYTES:
raise ObserverError("result bound is not exact")
if plan.method == "SOURCE_BOUND_QUERY":
if plan.exact_literal_path is not None or \
plan.path_provenance_sha256 is not None:
raise ObserverError("query method must not carry a path")
else:
if not isinstance(plan.exact_literal_path, str) or \
not plan.exact_literal_path.startswith("/") or \
".." in plan.exact_literal_path or \
not isinstance(plan.path_provenance_sha256, str) or \
not SHA256.fullmatch(plan.path_provenance_sha256):
raise ObserverError("exact path provenance is absent")
if plan.one_request is not True or plan.read_only is not True:
raise ObserverError("one read-only request is not exact")
if any((plan.shell_present, plan.directory_enumeration,
plan.title_launch, plan.app_termination, plan.device_write,
plan.retry, plan.reconnect)):
raise ObserverError("candidate contains a forbidden capability")
def classify_synthetic(plan: ObserverPlan, result: SyntheticResult) -> Outcome:
"""Classify supplied bytes; errors and incomplete data remain UNKNOWN."""
validate_candidate(plan)
if type(result) is not SyntheticResult or \
(result.firmware, result.title_id, result.method,
result.request_bytes_sha256) != \
(plan.firmware, plan.title_id, plan.method,
plan.request_bytes_sha256):
raise ObserverError("result binding mismatch")
if result.result_bytes < 0 or result.result_bytes > MAX_RESULT_BYTES:
raise ObserverError("result bound exceeded")
if result.explicit_present and result.explicit_absent:
raise ObserverError("contradictory result")
if not result.complete or result.error_code is not None:
return Outcome.UNKNOWN
if result.explicit_present:
return Outcome.PRESENT
if result.explicit_absent:
return Outcome.ABSENT
return Outcome.UNKNOWN
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Hash-bound, offline-only appinfo snapshot query for Phase 1.0DH."""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
import hashlib
from pathlib import Path
import re
import sqlite3
from urllib.parse import quote
PHASE = "PHASE_1_0DH_HASH_BOUND_SNAPSHOT_QUERY"
TITLE_ID = "PPSA01659"
MAX_SNAPSHOT_BYTES = 64 * 1024 * 1024
SHA256 = re.compile(r"^[0-9a-f]{64}$")
class SnapshotError(ValueError):
"""The supplied snapshot or query contract is invalid."""
class Outcome(Enum):
PRESENT = "PRESENT"
ABSENT = "ABSENT"
UNKNOWN = "UNKNOWN"
@dataclass(frozen=True)
class SnapshotBinding:
phase: str
title_id: str
size: int
sha256: str
def _digest(path: Path) -> tuple[int, str]:
total = 0
digest = hashlib.sha256()
with path.open("rb") as stream:
while block := stream.read(64 * 1024):
total += len(block)
if total > MAX_SNAPSHOT_BYTES:
raise SnapshotError("snapshot exceeds size ceiling")
digest.update(block)
return total, digest.hexdigest()
def validate_binding(binding: SnapshotBinding) -> None:
if type(binding) is not SnapshotBinding or binding.phase != PHASE:
raise SnapshotError("phase binding mismatch")
if binding.title_id != TITLE_ID:
raise SnapshotError("title binding mismatch")
if not isinstance(binding.size, int) or isinstance(binding.size, bool) or \
binding.size <= 0 or binding.size > MAX_SNAPSHOT_BYTES:
raise SnapshotError("snapshot size is invalid")
if not isinstance(binding.sha256, str) or not SHA256.fullmatch(binding.sha256):
raise SnapshotError("snapshot hash is invalid")
def query_snapshot(path: Path, binding: SnapshotBinding) -> Outcome:
"""Query a byte-exact local snapshot without creating SQLite sidecars."""
validate_binding(binding)
path = path.resolve(strict=True)
if not path.is_file() or _digest(path) != (binding.size, binding.sha256):
raise SnapshotError("snapshot identity mismatch")
if path.read_bytes()[:16] != b"SQLite format 3\x00":
raise SnapshotError("snapshot is not SQLite 3")
uri = f"file:{quote(path.as_posix(), safe='/:')}?mode=ro&immutable=1"
try:
connection = sqlite3.connect(uri, uri=True)
try:
connection.execute("PRAGMA query_only = ON")
columns = {
row[1] for row in connection.execute(
"PRAGMA table_info(tbl_appinfo)")
}
if "titleId" not in columns:
return Outcome.UNKNOWN
rows = connection.execute(
"SELECT 1 FROM tbl_appinfo WHERE titleId = ? LIMIT 2",
(TITLE_ID,),
).fetchall()
if len(rows) == 1:
return Outcome.PRESENT
if len(rows) == 0:
return Outcome.ABSENT
return Outcome.UNKNOWN
finally:
connection.close()
except sqlite3.Error:
return Outcome.UNKNOWN
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline parser for the bounded Phase-1.0DM snapshot stream."""
from __future__ import annotations
from dataclasses import dataclass
import hashlib,struct
MAGIC=b"CHS10DM1";FRAME=struct.Struct("<8sIIiiQQQQq");MAX_BYTES=64*1024*1024
BEGIN=1;END=2;ERROR=3
class ProtocolError(ValueError):pass
@dataclass(frozen=True)
class SnapshotResult:
data:bytes
sha256:str
size:int
device:int
inode:int
mtime:int
def _frame(data:bytes):
if len(data)!=64:raise ProtocolError("frame size")
values=FRAME.unpack(data)
if values[0]!=MAGIC or values[1]!=1:raise ProtocolError("frame identity")
return values
def parse_stream(raw:bytes)->SnapshotResult:
if not isinstance(raw,bytes) or len(raw)<128:raise ProtocolError("stream truncated")
begin=_frame(raw[:64]);kind,status,saved,size,sent,dev,ino,mtime=begin[2:]
if kind==ERROR:raise ProtocolError(f"target error {status}")
if kind!=BEGIN or status!=0 or saved!=0 or sent!=0 or not 0<size<=MAX_BYTES:raise ProtocolError("begin invalid")
if len(raw)!=64+size+64:raise ProtocolError("stream length")
payload=raw[64:64+size];end=_frame(raw[64+size:]);ekind,estatus,esaved,esize,esent,edev,eino,emtime=end[2:]
if ekind!=END or estatus!=0 or esaved!=0 or esize!=size or esent!=size or (edev,eino,emtime)!=(dev,ino,mtime):raise ProtocolError("terminal invalid")
if payload[:16]!=b"SQLite format 3\x00":raise ProtocolError("not sqlite")
return SnapshotResult(payload,hashlib.sha256(payload).hexdigest(),size,dev,ino,mtime)
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Network-free streaming receiver for one Phase-1.0DM result."""
from __future__ import annotations
from dataclasses import dataclass
import hashlib,os
from pathlib import Path
from phase10dm_snapshot_protocol import BEGIN,END,FRAME,MAGIC,MAX_BYTES,ProtocolError,_frame
@dataclass(frozen=True)
class ReceivedSnapshot:
path:Path;size:int;sha256:str;device:int;inode:int;mtime:int
class SnapshotReceiver:
def __init__(self,path:Path):
if not isinstance(path,Path) or path.exists():raise ProtocolError("exclusive output required")
self.path=path;self.stream=path.open("xb");self.buffer=bytearray();self.state="HEADER";self.expected=None;self.written=0;self.digest=hashlib.sha256();self.begin=None
def feed(self,chunk:bytes):
if self.state not in {"HEADER","PAYLOAD","TERMINAL"} or not isinstance(chunk,bytes):raise ProtocolError("receiver state")
self.buffer.extend(chunk)
if self.state=="HEADER" and len(self.buffer)>=64:
self.begin=_frame(bytes(self.buffer[:64]));del self.buffer[:64];kind,status,saved,size,sent,*_=self.begin[2:]
if kind!=BEGIN or status or saved or sent or not 0<size<=MAX_BYTES:self.abort();raise ProtocolError("begin invalid")
self.expected=size;self.state="PAYLOAD"
if self.state=="PAYLOAD":
take=min(len(self.buffer),self.expected-self.written)
if take:
data=bytes(self.buffer[:take]);del self.buffer[:take];self.stream.write(data);self.digest.update(data);self.written+=take
if self.written==self.expected:self.state="TERMINAL"
if self.state=="TERMINAL" and len(self.buffer)>64:self.abort();raise ProtocolError("trailing bytes")
def finish(self)->ReceivedSnapshot:
if self.state!="TERMINAL" or len(self.buffer)!=64 or self.begin is None:self.abort();raise ProtocolError("stream incomplete")
end=_frame(bytes(self.buffer));kind,status,saved,size,sent,dev,ino,mtime=end[2:];_,_,_,bsize,_,bdev,bino,bmtime=self.begin[2:]
if kind!=END or status or saved or size!=bsize or sent!=bsize or (dev,ino,mtime)!=(bdev,bino,bmtime):self.abort();raise ProtocolError("terminal invalid")
self.stream.flush();os.fsync(self.stream.fileno());self.stream.close();self.state="SEALED"
with self.path.open("rb") as check:
if check.read(16)!=b"SQLite format 3\x00":raise ProtocolError("not sqlite")
return ReceivedSnapshot(self.path,self.written,self.digest.hexdigest(),dev,ino,mtime)
def abort(self):
if not self.stream.closed:self.stream.flush();self.stream.close()
self.state="ABORTED"
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Manifest-gated one-shot raw-elfldr snapshot runner."""
from __future__ import annotations
import hashlib, ipaddress, json, os, socket, time
from pathlib import Path
from phase10dn_snapshot_receiver import SnapshotReceiver
ARTIFACT_SIZE=109896
ARTIFACT_SHA256="147b5bede0f0b5b7d2be903bc72ff0d0541a2cdc28eae7d86b6bf95e1978ebdf"
PORT=9021
CONNECT_TIMEOUT=3.0
TOTAL_TIMEOUT=30.0
MAX_WIRE=67108992
FIELDS={"active","run_id","target","port","artifact_size","artifact_sha256","snapshot_path","receipt_path","not_before","not_after","one_connection","one_transfer","one_execution","result_receive","target_file_read","device_write","installation","autoload","retry","reconnect"}
class RunnerError(RuntimeError):
pass
def _load(path: Path) -> dict:
value=json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value,dict): raise RunnerError("record is not an object")
return value
def validate_records(activation: dict,approval: dict,now: float)->dict:
if set(activation)!=FIELDS or set(approval)!=FIELDS: raise RunnerError("record fields differ")
if activation!=approval: raise RunnerError("activation and approval differ")
if activation["active"] is not True: raise RunnerError("activation is inactive")
if not activation["not_before"]<=now<=activation["not_after"]: raise RunnerError("approval window inactive")
if activation["port"]!=PORT or activation["artifact_size"]!=ARTIFACT_SIZE or activation["artifact_sha256"]!=ARTIFACT_SHA256: raise RunnerError("artifact route mismatch")
if any(activation[k] is not True for k in ("one_connection","one_transfer","one_execution","result_receive","target_file_read")): raise RunnerError("required authority absent")
if any(activation[k] is not False for k in ("device_write","installation","autoload","retry","reconnect")): raise RunnerError("forbidden authority present")
ipaddress.IPv4Address(activation["target"])
for key in ("snapshot_path","receipt_path"):
path=Path(activation[key])
if not path.is_absolute() or path.exists(): raise RunnerError("exclusive absolute evidence path required")
return activation
def _consume(plan: dict)->None:
path=Path(plan["receipt_path"])
with path.open("x",encoding="utf-8",newline="\n") as out:
json.dump({"run_id":plan["run_id"],"artifact_sha256":ARTIFACT_SHA256,"consumed_before_socket":True},out,sort_keys=True)
out.write("\n");out.flush();os.fsync(out.fileno())
def run(artifact:Path,activation_path:Path,approval_path:Path,socket_factory=socket.socket,clock=time.monotonic,wall_clock=time.time):
plan=validate_records(_load(activation_path),_load(approval_path),wall_clock())
raw=artifact.read_bytes()
if len(raw)!=ARTIFACT_SIZE or hashlib.sha256(raw).hexdigest()!=ARTIFACT_SHA256: raise RunnerError("artifact identity mismatch")
_consume(plan)
receiver=SnapshotReceiver(Path(plan["snapshot_path"]));sock=None;received=0;deadline=clock()+TOTAL_TIMEOUT
try:
sock=socket_factory(socket.AF_INET,socket.SOCK_STREAM);sock.settimeout(CONNECT_TIMEOUT);sock.connect((plan["target"],PORT));sock.sendall(raw);sock.shutdown(socket.SHUT_WR)
while True:
remain=deadline-clock()
if remain<=0: raise RunnerError("result deadline")
sock.settimeout(remain);chunk=sock.recv(min(65536,MAX_WIRE-received))
if not chunk: break
received+=len(chunk)
if received>MAX_WIRE: raise RunnerError("wire bound")
receiver.feed(chunk)
return receiver.finish()
except Exception:
receiver.abort();raise
finally:
if sock is not None: sock.close()
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Strict parser for the bounded Phase-1.0DQ inventory stream."""
from __future__ import annotations
from dataclasses import dataclass
import struct
MAGIC=b"CHI10DQ1";FRAME=struct.Struct("<8sIIiiIIQ24s");ENTRY=struct.Struct("<256sIIIIQQq24s")
HEADER=1;TERMINAL=2;ERROR=3;MAX_ENTRIES=256;MAX_WIRE=64+MAX_ENTRIES*320+64
class ProtocolError(ValueError):pass
@dataclass(frozen=True)
class InventoryEntry:name:str;file_type:int;mode:int;size:int;inode:int;mtime:int
def _frame(raw:bytes):
if len(raw)!=FRAME.size:raise ProtocolError("frame size")
value=FRAME.unpack(raw)
if value[0]!=MAGIC or value[1]!=1 or value[8]!=bytes(24):raise ProtocolError("frame identity")
return value
def parse_stream(raw:bytes)->tuple[InventoryEntry,...]:
if not isinstance(raw,bytes) or not 128<=len(raw)<=MAX_WIRE or (len(raw)-128)%ENTRY.size:raise ProtocolError("stream length")
first=_frame(raw[:64]);kind,status,saved,count,reserved,transferred=first[2:8]
if kind==ERROR:raise ProtocolError(f"target error {status}:{saved}")
if kind!=HEADER or status or saved or count or reserved or transferred:raise ProtocolError("header invalid")
entries=[]
for offset in range(64,len(raw)-64,ENTRY.size):
name_raw,name_length,file_type,mode,reserved,size,inode,mtime,padding=ENTRY.unpack(raw[offset:offset+ENTRY.size])
if not 0<name_length<256 or reserved or padding!=bytes(24) or any(name_raw[name_length:]):raise ProtocolError("entry encoding")
try:name=name_raw[:name_length].decode("utf-8")
except UnicodeDecodeError as exc:raise ProtocolError("entry utf8") from exc
if name in {".",".."} or "/" in name or "\\" in name or "\x00" in name:raise ProtocolError("entry name")
entries.append(InventoryEntry(name,file_type,mode,size,inode,mtime))
terminal=_frame(raw[-64:]);kind,status,saved,count,reserved,transferred=terminal[2:8]
if kind!=TERMINAL or status or saved or reserved or count!=len(entries) or transferred!=len(entries)*ENTRY.size:raise ProtocolError("terminal invalid")
return tuple(entries)
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Inactive manifest-gated one-shot runner for Phase-1.0DQ."""
from __future__ import annotations
import hashlib,ipaddress,json,os,socket,time
from dataclasses import asdict
from pathlib import Path
from phase10dq_inventory_protocol import MAX_WIRE,parse_stream
ARTIFACT_SIZE=110032;ARTIFACT_SHA256="914fce06a490ad048fdd0a85ae117858e8904b47c72054bf12fbfebc213a6db8";PORT=9021
FIELDS={"active","run_id","target","port","artifact_size","artifact_sha256","output_path","receipt_path","not_before","not_after","one_connection","one_transfer","one_execution","result_receive","directory_inventory","possible_atime_effect_acknowledged","device_file_content_read","persistent_device_write","installation","autoload","retry","reconnect"}
class RunnerError(RuntimeError):pass
def _load(path:Path):
value=json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value,dict):raise RunnerError("record object required")
return value
def validate_records(activation:dict,approval:dict,now:float):
if set(activation)!=FIELDS or set(approval)!=FIELDS or activation!=approval:raise RunnerError("record mismatch")
if activation["active"] is not True or not activation["not_before"]<=now<=activation["not_after"]:raise RunnerError("inactive window")
if activation["port"]!=PORT or activation["artifact_size"]!=ARTIFACT_SIZE or activation["artifact_sha256"]!=ARTIFACT_SHA256:raise RunnerError("route mismatch")
if any(activation[k] is not True for k in ("one_connection","one_transfer","one_execution","result_receive","directory_inventory","possible_atime_effect_acknowledged")):raise RunnerError("authority absent")
if any(activation[k] is not False for k in ("device_file_content_read","persistent_device_write","installation","autoload","retry","reconnect")):raise RunnerError("forbidden authority")
ipaddress.IPv4Address(activation["target"])
for key in ("output_path","receipt_path"):
p=Path(activation[key])
if not p.is_absolute() or p.exists():raise RunnerError("exclusive path required")
return activation
def _exclusive_json(path:Path,value:dict):
with path.open("x",encoding="utf-8",newline="\n") as out:json.dump(value,out,sort_keys=True);out.write("\n");out.flush();os.fsync(out.fileno())
def run(artifact:Path,activation_path:Path,approval_path:Path,socket_factory=socket.socket,clock=time.monotonic,wall_clock=time.time):
plan=validate_records(_load(activation_path),_load(approval_path),wall_clock());raw=artifact.read_bytes()
if len(raw)!=ARTIFACT_SIZE or hashlib.sha256(raw).hexdigest()!=ARTIFACT_SHA256:raise RunnerError("artifact identity")
_exclusive_json(Path(plan["receipt_path"]),{"artifact_sha256":ARTIFACT_SHA256,"consumed_before_socket":True,"run_id":plan["run_id"]})
sock=None;wire=bytearray();deadline=clock()+20.0
try:
sock=socket_factory(socket.AF_INET,socket.SOCK_STREAM);sock.settimeout(3.0);sock.connect((plan["target"],PORT));sock.sendall(raw);sock.shutdown(socket.SHUT_WR)
while True:
remaining=deadline-clock()
if remaining<=0:raise RunnerError("result deadline")
sock.settimeout(remaining);chunk=sock.recv(min(4096,MAX_WIRE-len(wire)))
if not chunk:break
wire.extend(chunk)
if len(wire)==MAX_WIRE:break
entries=parse_stream(bytes(wire));_exclusive_json(Path(plan["output_path"]),{"entries":[asdict(item) for item in entries],"entry_count":len(entries),"path":"/user/app/FAKE00000","run_id":plan["run_id"]});return entries
finally:
for index in range(len(wire)):wire[index]=0
if sock is not None:sock.close()
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import struct
MAGIC=b"CHM10DS1";FRAME=struct.Struct("<8sIIiiIIQ24s");NAMES=("app.pbm","app.json","app.xml","app.crc");MAX_FILE=4096;MAX_WIRE=16768
class ProtocolError(ValueError):pass
def frame(raw):
if len(raw)!=64:raise ProtocolError("frame size")
v=FRAME.unpack(raw)
if v[0]!=MAGIC or v[1]!=1 or v[8]!=bytes(24):raise ProtocolError("frame identity")
return v
def parse_stream(raw:bytes)->dict[str,bytes]:
if not isinstance(raw,bytes) or not 128<=len(raw)<=MAX_WIRE:raise ProtocolError("stream length")
first=frame(raw[:64]);kind,status,saved,index,length,total=first[2:8]
if kind==4:raise ProtocolError(f"target error {status}:{saved}")
if (kind,status,saved,index,length,total)!=(1,0,0,4,0,0):raise ProtocolError("header invalid")
offset=64;files={};transferred=0
for expected,name in enumerate(NAMES):
if offset+64>len(raw):raise ProtocolError("file frame truncated")
value=frame(raw[offset:offset+64]);offset+=64;kind,status,saved,index,length,total=value[2:8]
if kind==4:raise ProtocolError(f"target error {status}:{saved}")
if kind!=2 or status or saved or index!=expected or length>MAX_FILE or total!=transferred:raise ProtocolError("file frame invalid")
if offset+length>len(raw):raise ProtocolError("file truncated")
files[name]=raw[offset:offset+length];offset+=length;transferred+=length
if offset+64!=len(raw):raise ProtocolError("terminal position")
value=frame(raw[offset:]);kind,status,saved,index,length,total=value[2:8]
if (kind,status,saved,index,length,total)!=(3,0,0,4,0,transferred):raise ProtocolError("terminal invalid")
return files
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import base64,hashlib,ipaddress,json,os,socket,time
from pathlib import Path
from phase10ds_metadata_protocol import MAX_WIRE,parse_stream
ARTIFACT_SIZE=109928;ARTIFACT_SHA256="077307b98e44f566fa1db82b08cd5e71bd56bd9792826fc7254965fa768c0dc7";PORT=9021
FIELDS={"active","run_id","target","port","artifact_size","artifact_sha256","output_path","receipt_path","not_before","not_after","one_connection","one_transfer","one_execution","result_receive","four_exact_metadata_reads","possible_atime_effect_acknowledged","app_pkg_read","backup_read","persistent_device_write","installation","autoload","retry","reconnect"}
class RunnerError(RuntimeError):pass
def load(path):
v=json.loads(path.read_text(encoding="utf-8"))
if not isinstance(v,dict):raise RunnerError("record object")
return v
def validate(a,b,now):
if set(a)!=FIELDS or set(b)!=FIELDS or a!=b:raise RunnerError("record mismatch")
if a["active"] is not True or not a["not_before"]<=now<=a["not_after"]:raise RunnerError("inactive")
if a["port"]!=PORT or a["artifact_size"]!=ARTIFACT_SIZE or a["artifact_sha256"]!=ARTIFACT_SHA256:raise RunnerError("identity")
if any(a[k] is not True for k in ("one_connection","one_transfer","one_execution","result_receive","four_exact_metadata_reads","possible_atime_effect_acknowledged")):raise RunnerError("authority")
if any(a[k] is not False for k in ("app_pkg_read","backup_read","persistent_device_write","installation","autoload","retry","reconnect")):raise RunnerError("forbidden")
ipaddress.IPv4Address(a["target"])
for key in ("output_path","receipt_path"):
p=Path(a[key])
if not p.is_absolute() or p.exists():raise RunnerError("exclusive path")
return a
def exclusive(path,value):
with path.open("x",encoding="utf-8",newline="\n") as f:json.dump(value,f,sort_keys=True);f.write("\n");f.flush();os.fsync(f.fileno())
def run(artifact,activation,approval,socket_factory=socket.socket,clock=time.monotonic,wall=time.time):
p=validate(load(activation),load(approval),wall());raw=artifact.read_bytes()
if len(raw)!=ARTIFACT_SIZE or hashlib.sha256(raw).hexdigest()!=ARTIFACT_SHA256:raise RunnerError("artifact")
exclusive(Path(p["receipt_path"]),{"artifact_sha256":ARTIFACT_SHA256,"consumed_before_socket":True,"run_id":p["run_id"]});wire=bytearray();s=None;deadline=clock()+20
try:
s=socket_factory(socket.AF_INET,socket.SOCK_STREAM);s.settimeout(3);s.connect((p["target"],PORT));s.sendall(raw);s.shutdown(socket.SHUT_WR)
while True:
left=deadline-clock()
if left<=0:raise RunnerError("deadline")
s.settimeout(left);chunk=s.recv(min(4096,MAX_WIRE-len(wire)))
if not chunk:break
wire.extend(chunk)
if len(wire)==MAX_WIRE:break
files=parse_stream(bytes(wire));exclusive(Path(p["output_path"]),{"files":{k:{"base64":base64.b64encode(v).decode(),"sha256":hashlib.sha256(v).hexdigest(),"size":len(v)} for k,v in files.items()},"run_id":p["run_id"]});return files
finally:
for i in range(len(wire)):wire[i]=0
if s is not None:s.close()
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
import hashlib,ipaddress,json,os,socket,struct,time
from pathlib import Path
SIZE=109688;SHA="25b972ac202050ab5a9c1c89651b27e841cdf788d19c93bf75f051c9c8acd403";REC=struct.Struct("<8sIIiiIIQQQqq");PORT=9021
FIELDS={"active","run_id","target","port","artifact_size","artifact_sha256","output_path","receipt_path","not_before","not_after","one_connection","one_transfer","one_execution","result_receive","two_exact_lstat","file_content_read","device_write","retry","reconnect"}
class Error(RuntimeError):pass
def load(p):return json.loads(p.read_text())
def validate(a,b,now):
if set(a)!=FIELDS or set(b)!=FIELDS or a!=b or a["active"] is not True:raise Error("inactive/mismatch")
if not a["not_before"]<=now<=a["not_after"] or a["port"]!=PORT or a["artifact_size"]!=SIZE or a["artifact_sha256"]!=SHA:raise Error("window/identity")
if any(a[k] is not True for k in ("one_connection","one_transfer","one_execution","result_receive","two_exact_lstat")) or any(a[k] is not False for k in ("file_content_read","device_write","retry","reconnect")):raise Error("authority")
ipaddress.IPv4Address(a["target"])
for k in ("output_path","receipt_path"):
p=Path(a[k]);
if not p.is_absolute() or p.exists():raise Error("exclusive path")
return a
def put(p,v):
with p.open("x",encoding="utf-8",newline="\n") as f:json.dump(v,f,sort_keys=True);f.write("\n");f.flush();os.fsync(f.fileno())
def run(elf,activation,approval,factory=socket.socket,wall=time.time):
p=validate(load(activation),load(approval),wall());raw=elf.read_bytes()
if len(raw)!=SIZE or hashlib.sha256(raw).hexdigest()!=SHA:raise Error("artifact")
put(Path(p["receipt_path"]),{"consumed_before_socket":True,"run_id":p["run_id"],"artifact_sha256":SHA});s=None;wire=bytearray()
try:
s=factory(socket.AF_INET,socket.SOCK_STREAM);s.settimeout(3);s.connect((p["target"],PORT));s.sendall(raw);s.shutdown(socket.SHUT_WR);s.settimeout(10)
while len(wire)<144:
c=s.recv(144-len(wire))
if not c:break
wire.extend(c)
if len(wire)!=144 or s.recv(1):raise Error("result length")
result=[]
for i in range(2):
v=REC.unpack(wire[i*72:(i+1)*72])
if v[0]!=b"CHP10DU1" or v[1]!=1 or v[2]!=i or v[6]!=0:raise Error("record")
result.append({"index":i,"exists":bool(v[3]),"errno":v[4],"mode":v[5],"size":v[7],"device":v[8],"inode":v[9],"mtime":v[10],"ctime":v[11]})
put(Path(p["output_path"]),{"paths":["/user/app/FAKE00000/app.pkg","/mnt/usb0/IV9999-FAKE00000_00-HOMEBREWLOADER01.pkg"],"records":result,"run_id":p["run_id"]});return result
finally:
if s is not None:s.close()
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
import hashlib,ipaddress,json,os,socket,struct,time
from pathlib import Path
ELF_SIZE=109904;ELF_SHA="b41763f9261b838be2f83b0ee1c7b9bb5e07ced856e5638e3357de37e4405394";PACKAGE_SIZE=18153472;PACKAGE_SHA="dbcdd4dbc6303fc7a94aa0e8bb3e2c7de1d8b5770c6a30cf1ce50bc6e373aa7e";FRAME=struct.Struct("<8sIIiiQQQQq");PORT=9021;MAX_WIRE=PACKAGE_SIZE+128
FIELDS={"active","run_id","target","port","artifact_size","artifact_sha256","output_path","receipt_path","not_before","not_after","one_connection","one_transfer","one_execution","result_receive","exact_package_read","possible_atime_effect_acknowledged","device_write","usb_read","backup_read","installation","autoload","retry","reconnect"}
class Error(RuntimeError):pass
def load(p):return json.loads(p.read_text())
def validate(a,b,now):
if set(a)!=FIELDS or set(b)!=FIELDS or a!=b or a["active"] is not True:raise Error("inactive/mismatch")
if not a["not_before"]<=now<=a["not_after"] or a["port"]!=PORT or a["artifact_size"]!=ELF_SIZE or a["artifact_sha256"]!=ELF_SHA:raise Error("window/identity")
if any(a[k] is not True for k in ("one_connection","one_transfer","one_execution","result_receive","exact_package_read","possible_atime_effect_acknowledged")) or any(a[k] is not False for k in ("device_write","usb_read","backup_read","installation","autoload","retry","reconnect")):raise Error("authority")
ipaddress.IPv4Address(a["target"])
for k in ("output_path","receipt_path"):
p=Path(a[k]);
if not p.is_absolute() or p.exists():raise Error("exclusive path")
return a
def put(p,v):
with p.open("x",encoding="utf-8",newline="\n") as f:json.dump(v,f,sort_keys=True);f.write("\n");f.flush();os.fsync(f.fileno())
def parse_frame(raw):
v=FRAME.unpack(raw)
if v[0]!=b"CHP10DW1" or v[1]!=1:raise Error("frame identity")
return v
def run(elf,activation,approval,factory=socket.socket,clock=time.monotonic,wall=time.time):
p=validate(load(activation),load(approval),wall());raw=elf.read_bytes()
if len(raw)!=ELF_SIZE or hashlib.sha256(raw).hexdigest()!=ELF_SHA:raise Error("artifact")
put(Path(p["receipt_path"]),{"consumed_before_socket":True,"run_id":p["run_id"],"artifact_sha256":ELF_SHA});s=None;out=None;header=bytearray();terminal=bytearray();written=0;digest=hashlib.sha256();deadline=clock()+45
try:
out=Path(p["output_path"]).open("xb");s=factory(socket.AF_INET,socket.SOCK_STREAM);s.settimeout(3);s.connect((p["target"],PORT));s.sendall(raw);s.shutdown(socket.SHUT_WR)
while len(header)<64:
s.settimeout(max(.001,deadline-clock()));c=s.recv(64-len(header))
if not c:raise Error("header eof")
header.extend(c)
h=parse_frame(bytes(header));
if h[2]!=1 or h[3] or h[4] or h[5]!=PACKAGE_SIZE or h[6]:raise Error("header")
while written<PACKAGE_SIZE:
if clock()>=deadline:raise Error("deadline")
s.settimeout(max(.001,deadline-clock()));c=s.recv(min(65536,PACKAGE_SIZE-written))
if not c:raise Error("payload eof")
out.write(c);digest.update(c);written+=len(c)
while len(terminal)<64:
s.settimeout(max(.001,deadline-clock()));c=s.recv(64-len(terminal))
if not c:raise Error("terminal eof")
terminal.extend(c)
if s.recv(1):raise Error("trailing data")
t=parse_frame(bytes(terminal));
if t[2]!=2 or t[3] or t[4] or t[5]!=PACKAGE_SIZE or t[6]!=PACKAGE_SIZE or t[7:10]!=h[7:10]:raise Error("terminal")
out.flush();os.fsync(out.fileno());out.close();out=None
if digest.hexdigest()!=PACKAGE_SHA:raise Error("package digest mismatch")
return {"size":written,"sha256":digest.hexdigest()}
finally:
if out is not None:out.close()
if s is not None:s.close()
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Sanitize and classify an already-supplied shsrv transcript offline.
This tool has no networking and never preserves serial or telemetry values.
It cannot establish an exact deployed binary identity.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import re
import sys
from typing import Any
CURRENT_COMMAND_HASH = (
"f41168292e205590bda1d243cdf727044e0af280a89fb0c070f4c5d6c92f2fd7")
V07_COMMAND_HASH = (
"40313637116b532f3c7f9bebe2c23c0018fe7d4093840cf463a22ba0314ca021")
def command_hash(commands: list[str]) -> str:
normalized = "\n".join(sorted(set(commands)))
return hashlib.sha256(normalized.encode("utf-8")).hexdigest()
def parse_transcript(
transcript: str, expected_paths: set[str] | None = None,
) -> dict[str, Any]:
"""Return a sanitized, deliberately non-exact identity record."""
allowed_paths = expected_paths or set()
lines = transcript.splitlines()
compile_date = None
compile_time = None
firmware = None
commands: list[str] = []
observations: dict[str, dict[str, Any]] = {}
serial_discarded = False
telemetry_discarded = False
greeting_seen = False
in_help = False
current_observation_path = None
greeting_pattern = re.compile(
r"Welcome to shsrv\.elf running on pid \d+, "
r"compiled (.+?) at ([0-9:]+)")
command_pattern = re.compile(r"^\s{2}([A-Za-z0-9_]+)(?:\s+-.*)?$")
weak_sum_pattern = re.compile(r"^([0-9]{5})\s+(.+)$")
for line in lines:
greeting = greeting_pattern.search(line)
if greeting:
greeting_seen = True
compile_date = greeting.group(1).strip()
compile_time = greeting.group(2).strip()
continue
stripped = line.strip()
if stripped.startswith("S/N:"):
serial_discarded = True
continue
if stripped.startswith(("SoC temp:", "CPU temp:", "CPU freq:")):
telemetry_discarded = True
continue
if stripped.startswith("Model:"):
continue
if stripped.startswith("S/W:"):
firmware = stripped.split(":", 1)[1].strip()
continue
if stripped == "Builtin commands:":
in_help = True
continue
if in_help:
command = command_pattern.match(line)
if command:
commands.append(command.group(1))
continue
if stripped == "":
in_help = False
if stripped.startswith("filename:"):
path = stripped.split(":", 1)[1].strip()
if path in allowed_paths:
observations.setdefault(path, {})["metadata_seen"] = True
current_observation_path = path
else:
current_observation_path = None
continue
if ":" in stripped and current_observation_path is not None:
key, value = (part.strip() for part in stripped.split(":", 1))
if key in {"size", "mtime", "ctime"} and value.isdigit():
observations[current_observation_path][key] = int(value)
continue
weak_sum = weak_sum_pattern.match(stripped)
if weak_sum and weak_sum.group(2) in allowed_paths:
path = weak_sum.group(2)
observation = observations.setdefault(path, {})
observation["weak_checksum"] = weak_sum.group(1)
observation["weak_checksum_algorithm"] = "BSD_ROTATE_16"
observation["cryptographic_checksum"] = False
normalized_commands = sorted(set(commands))
fingerprint = command_hash(normalized_commands) if normalized_commands else None
family = "UNRESOLVED"
if fingerprint == CURRENT_COMMAND_HASH:
family = "OFFICIAL_V019_SOURCE_FAMILY_CANDIDATE"
elif fingerprint == V07_COMMAND_HASH:
family = "OFFICIAL_V07_SOURCE_FAMILY_CANDIDATE"
classification = "INVALID_OR_INCOMPLETE"
if greeting_seen:
classification = "COMPILE_METADATA_ONLY"
if greeting_seen and normalized_commands:
classification = "SOURCE_FAMILY_FINGERPRINT_ONLY"
if greeting_seen and observations:
classification = "WEAK_FILE_CORRELATION_ONLY"
return {
"schema_version": 1,
"classification": classification,
"exact_identity": False,
"compile_metadata": {
"date": compile_date,
"time": compile_time,
"firmware": firmware,
},
"sensitive_input": {
"serial_line_seen": serial_discarded,
"serial_value_retained": False,
"telemetry_line_seen": telemetry_discarded,
"telemetry_values_retained": False,
},
"command_fingerprint": {
"count": len(normalized_commands),
"sha256": fingerprint,
"source_family_match": family,
"commands": normalized_commands,
"proves_exact_binary": False,
},
"file_observations": [
{"path": path, **value, "proves_exact_binary": False}
for path, value in sorted(observations.items())
],
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--expected-path", action="append", default=[],
help="Literal pre-approved path whose metadata may be retained")
args = parser.parse_args()
result = parse_transcript(sys.stdin.read(), set(args.expected_path))
print(json.dumps(result, indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
+207
View File
@@ -0,0 +1,207 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline-only, one-shot shsrv transcript collection model.
This module has no network transport. It accepts bounded bytes from stdin or
tests, removes Telnet control traffic, and delegates sanitized classification
to the Phase-1.0T parser. It does not prove memory erasure or device behavior.
"""
from __future__ import annotations
import argparse
import json
import posixpath
import re
import sys
from typing import Any
from phase10t_shsrv_transcript import parse_transcript
MAX_RAW_BYTES = 65_536
MAX_SANITIZED_BYTES = 65_536
MAX_CHUNKS = 256
EXPECTED_FIRMWARE = "9.60"
IAC = 0xFF
SE = 0xF0
SB = 0xFA
WILL = 0xFB
WONT = 0xFC
DO = 0xFD
DONT = 0xFE
class CollectorError(RuntimeError):
"""Fail-closed model error that never embeds input bytes."""
class TelnetFilter:
"""Incrementally remove Telnet negotiations and subnegotiations."""
def __init__(self) -> None:
self.state = "DATA"
def feed(self, chunk: bytes) -> bytes:
output = bytearray()
for value in chunk:
if self.state == "DATA":
if value == IAC:
self.state = "IAC"
else:
output.append(value)
elif self.state == "IAC":
if value == IAC:
output.append(IAC)
self.state = "DATA"
elif value in {WILL, WONT, DO, DONT}:
self.state = "NEGOTIATION_OPTION"
elif value == SB:
self.state = "SUBNEGOTIATION"
else:
self.state = "DATA"
elif self.state == "NEGOTIATION_OPTION":
self.state = "DATA"
elif self.state == "SUBNEGOTIATION":
if value == IAC:
self.state = "SUBNEGOTIATION_IAC"
elif self.state == "SUBNEGOTIATION_IAC":
if value == SE:
self.state = "DATA"
elif value == IAC:
self.state = "SUBNEGOTIATION"
else:
self.state = "SUBNEGOTIATION"
return bytes(output)
def is_complete(self) -> bool:
return self.state == "DATA"
class OfflineCollector:
"""Bounded one-shot state model with no connection capability."""
def __init__(self) -> None:
self.state = "READY"
self.raw_bytes_received = 0
self.chunk_count = 0
self._filter = TelnetFilter()
self._sanitized = bytearray()
def _discard_buffer(self) -> None:
for index in range(len(self._sanitized)):
self._sanitized[index] = 0
self._sanitized.clear()
def _invalidate(self, message: str) -> None:
self._discard_buffer()
self.state = "INVALID"
raise CollectorError(message)
def feed(self, chunk: bytes) -> None:
if self.state not in {"READY", "RECEIVING"}:
raise CollectorError("collector is not accepting input")
if not isinstance(chunk, bytes):
self._invalidate("input must be bytes")
if not chunk:
return
self.chunk_count += 1
self.raw_bytes_received += len(chunk)
if self.chunk_count > MAX_CHUNKS:
self._invalidate("chunk limit exceeded")
if self.raw_bytes_received > MAX_RAW_BYTES:
self._invalidate("byte limit exceeded")
filtered = self._filter.feed(chunk)
if len(self._sanitized) + len(filtered) > MAX_SANITIZED_BYTES:
self._invalidate("sanitized byte limit exceeded")
self._sanitized.extend(filtered)
self.state = "RECEIVING"
def abort(self) -> None:
if self.state in {"SEALED", "INVALID"}:
raise CollectorError("collector can no longer abort")
self._discard_buffer()
self.state = "ABORTED"
@staticmethod
def _validate_expected_paths(expected_paths: set[str]) -> None:
path_pattern = re.compile(r"^/[A-Za-z0-9._/-]{1,511}$")
for path in expected_paths:
if not isinstance(path, str) or not path_pattern.fullmatch(path):
raise CollectorError("expected path is not a safe absolute path")
if posixpath.normpath(path) != path or "//" in path:
raise CollectorError("expected path is not normalized")
@staticmethod
def _validate_metadata(result: dict[str, Any]) -> None:
metadata = result["compile_metadata"]
date = metadata["date"]
time = metadata["time"]
firmware = metadata["firmware"]
if date is not None and not re.fullmatch(
r"[A-Z][a-z]{2} [ 0-3][0-9] [0-9]{4}", date):
raise CollectorError("compile date format is invalid")
if time is not None and not re.fullmatch(
r"(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]", time):
raise CollectorError("compile time format is invalid")
if firmware is not None and firmware != EXPECTED_FIRMWARE:
raise CollectorError("firmware metadata does not match the gate")
def finalize(self, expected_paths: set[str] | None = None) -> dict[str, Any]:
if self.state not in {"READY", "RECEIVING"}:
raise CollectorError("collector cannot be finalized")
if not self._filter.is_complete():
self._invalidate("incomplete Telnet control sequence")
try:
transcript = bytes(self._sanitized).decode("utf-8", errors="strict")
except UnicodeDecodeError:
self._invalidate("transcript is not valid UTF-8")
allowed_paths = expected_paths or set()
try:
self._validate_expected_paths(allowed_paths)
result = parse_transcript(transcript, allowed_paths)
self._validate_metadata(result)
except (ValueError, OverflowError, CollectorError):
self._invalidate("transcript validation failed")
self._discard_buffer()
self.state = "SEALED"
result["collector_model"] = {
"offline_only": True,
"one_shot": True,
"network_transport_present": False,
"raw_bytes_received": self.raw_bytes_received,
"chunk_count": self.chunk_count,
"raw_transcript_persisted": False,
"logical_buffer_discard_performed": True,
"physical_memory_erasure_proven": False,
"device_behavior_proven": False,
}
return result
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--offline-transcript", action="store_true", required=True,
help="Confirm that stdin is an already-supplied offline transcript")
parser.add_argument(
"--expected-path", action="append", default=[],
help="Literal pre-approved path whose metadata may be retained")
args = parser.parse_args()
collector = OfflineCollector()
try:
while True:
chunk = sys.stdin.buffer.read(4096)
if not chunk:
break
collector.feed(chunk)
result = collector.finalize(set(args.expected_path))
except CollectorError as error:
print(f"ERROR: {error}", file=sys.stderr)
return 1
print(json.dumps(result, indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
+180
View File
@@ -0,0 +1,180 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline policy model for a future one-shot shsrv client.
There is intentionally no transport, CLI, socket, DNS lookup, file output or
clock acquisition. Tests supply synthetic records and an explicit host time.
"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timedelta
import re
from typing import Any
from phase10v_shsrv_collector_model import (
CollectorError as CollectorModelError,
OfflineCollector,
)
COLLECTOR_SHA256 = \
"f8a306dafee5d135919bec5afda789dd741e57f39803b7683fb8747c186db25c"
SOURCE_BOUND_PORT = 2323
MAX_DEADLINE_SECONDS = 10
MAX_APPROVAL_LIFETIME = timedelta(minutes=15)
WINDOW_COMMANDS = {
"T2_GREETING_AND_HELP": ("help",),
"T3_ONE_EXACT_PATH": ("stat", "sum"),
}
ACTIVATION_FIELDS = {
"active", "policy_sha256", "collector_sha256", "run_id",
"target_address", "target_port", "window", "exact_literal_path",
"commands", "deadline_seconds", "expires_at",
}
REQUIRED_TRUE_FIELDS = {
"ps5_connection_authorized", "device_request_authorized",
"result_receive_authorized", "spawned_shell_effects_accepted",
"automatic_serial_query_accepted", "automatic_telemetry_query_accepted",
"sanitized_output_only_accepted",
"physical_memory_erasure_unproven_accepted",
}
REQUIRED_FALSE_FIELDS = {
"target_build_authorized", "device_transfer_authorized",
"device_execution_authorized", "installation_authorized",
"autoload_authorized", "device_write_authorized", "automatic_retry",
"reconnect_authorized", "resume_authorized", "fallback_authorized",
}
APPROVAL_FIELDS = ACTIVATION_FIELDS | REQUIRED_TRUE_FIELDS | \
REQUIRED_FALSE_FIELDS | {"attested", "listener_already_running_attested"}
class PolicyError(RuntimeError):
"""Fail-closed policy error without record values."""
@dataclass(frozen=True)
class SessionPlan:
"""Immutable plan only; it has no method capable of network I/O."""
run_id: str
target_address: str
target_port: int
window: str
exact_literal_path: str | None
commands: tuple[str, ...]
deadline_seconds: int
expires_at: datetime
def inactive_record_is_inert(record: dict[str, Any]) -> bool:
return record == {
"active": False,
"policy_sha256": None,
"collector_sha256": None,
"run_id": None,
"target_address": None,
"target_port": None,
"window": None,
"exact_literal_path": None,
"commands": [],
"deadline_seconds": None,
"expires_at": None,
}
def _parse_expiry(value: Any, now: datetime) -> datetime:
if not isinstance(value, str):
raise PolicyError("expiry is missing")
try:
expiry = datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError as error:
raise PolicyError("expiry format is invalid") from error
if now.tzinfo is None or expiry.tzinfo is None:
raise PolicyError("expiry must be timezone aware")
if not now < expiry <= now + MAX_APPROVAL_LIFETIME:
raise PolicyError("approval is expired or too long")
return expiry
def _validate_target(value: Any) -> str:
if not isinstance(value, str) or not re.fullmatch(
r"[A-Za-z0-9](?:[A-Za-z0-9.-]{0,251}[A-Za-z0-9])?", value):
raise PolicyError("target syntax is invalid")
if ".." in value:
raise PolicyError("target syntax is invalid")
return value
def _validate_authority(record: dict[str, Any]) -> None:
if not all(record.get(field) is True for field in REQUIRED_TRUE_FIELDS):
raise PolicyError("required authority or effect acceptance is missing")
if not all(record.get(field) is False for field in REQUIRED_FALSE_FIELDS):
raise PolicyError("forbidden authority is active")
def build_session_plan(
activation: dict[str, Any], approval: dict[str, Any], now: datetime,
) -> SessionPlan:
"""Validate dual synthetic records and return an immutable offline plan."""
if set(activation) != ACTIVATION_FIELDS or set(approval) != APPROVAL_FIELDS:
raise PolicyError("record shape is not exact")
if activation.get("active") is not True or approval.get("active") is not True:
raise PolicyError("activation is inactive")
if approval.get("attested") is not True:
raise PolicyError("operator attestation is missing")
if approval.get("listener_already_running_attested") is not True:
raise PolicyError("listener attestation is missing")
_validate_authority(approval)
matching_fields = (
"policy_sha256", "collector_sha256", "run_id", "target_address", "target_port",
"window", "exact_literal_path", "commands", "deadline_seconds",
"expires_at",
)
if any(activation.get(field) != approval.get(field)
for field in matching_fields):
raise PolicyError("activation and approval do not match")
if activation.get("collector_sha256") != COLLECTOR_SHA256:
raise PolicyError("collector identity mismatch")
if not isinstance(activation.get("policy_sha256"), str) or \
not re.fullmatch(r"[0-9a-f]{64}", activation["policy_sha256"]):
raise PolicyError("policy identity syntax is invalid")
run_id = activation.get("run_id")
if not isinstance(run_id, str) or not re.fullmatch(
r"[A-Za-z0-9_-]{8,64}", run_id):
raise PolicyError("run identifier is invalid")
target = _validate_target(activation.get("target_address"))
if activation.get("target_port") != SOURCE_BOUND_PORT:
raise PolicyError("target port mismatch")
window = activation.get("window")
if window not in WINDOW_COMMANDS:
raise PolicyError("window is not allowlisted")
commands = activation.get("commands")
if commands != list(WINDOW_COMMANDS[window]):
raise PolicyError("command sequence mismatch")
path = activation.get("exact_literal_path")
if window == "T2_GREETING_AND_HELP" and path is not None:
raise PolicyError("help window cannot include a path")
if window == "T3_ONE_EXACT_PATH":
if not isinstance(path, str):
raise PolicyError("exact path is missing")
try:
OfflineCollector._validate_expected_paths({path})
except CollectorModelError as error:
raise PolicyError("exact path is invalid") from error
deadline = activation.get("deadline_seconds")
if not isinstance(deadline, int) or isinstance(deadline, bool) or \
not 1 <= deadline <= MAX_DEADLINE_SECONDS:
raise PolicyError("deadline is invalid")
expiry = _parse_expiry(activation.get("expires_at"), now)
return SessionPlan(
run_id=run_id,
target_address=target,
target_port=SOURCE_BOUND_PORT,
window=window,
exact_literal_path=path,
commands=WINDOW_COMMANDS[window],
deadline_seconds=deadline,
expires_at=expiry,
)
+229
View File
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Inactive Phase-1.0X transport orchestration with injected adapters only.
This module has no socket, DNS, CLI, target address, byte-command formatter or
live prompt detector. It implements local exclusive evidence and orchestrates
synthetic adapter boundaries under an injected monotonic clock.
"""
from __future__ import annotations
from dataclasses import dataclass
import hashlib
import json
import os
from pathlib import Path
from typing import Any, Protocol
from phase10v_shsrv_collector_model import CollectorError, OfflineCollector
from phase10w_shsrv_client_policy import (
COLLECTOR_SHA256,
SessionPlan,
)
POLICY_SHA256 = \
"747d23c88f2722e8e8846599c3ac1dae3826eb3fca881caaad36b251f30f3592"
MAX_BOUNDARY_CHUNKS = 64
class SessionFailure(RuntimeError):
"""Generic failure that never embeds adapter data or target values."""
class EvidenceFailure(RuntimeError):
"""Generic exclusive-evidence failure."""
class MonotonicClock(Protocol):
def monotonic(self) -> float: ...
class InjectedSessionAdapter(Protocol):
def open_once(self, plan: SessionPlan, remaining_seconds: float) -> None: ...
def receive_boundary(
self, boundary: str, remaining_seconds: float,
) -> list[bytes]: ...
def send_command_token(
self, command: str, exact_path: str | None, remaining_seconds: float,
) -> None: ...
def close_once(self) -> None: ...
@dataclass(frozen=True)
class EvidenceRecord:
path: Path
size: int
sha256: str
@dataclass(frozen=True)
class SessionOutcome:
receipt: EvidenceRecord
output: EvidenceRecord
classification: str
exact_identity: bool
class ExclusiveEvidenceStore:
"""Write local JSON once with O_EXCL; never overwrite or clean up."""
def __init__(self, root: Path) -> None:
self.root = root
@staticmethod
def _encode(record: dict[str, Any]) -> bytes:
return (json.dumps(
record, sort_keys=True, separators=(",", ":"), ensure_ascii=True,
) + "\n").encode("ascii")
def _create(self, filename: str, record: dict[str, Any]) -> EvidenceRecord:
try:
self.root.mkdir(parents=True, exist_ok=True)
path = self.root / filename
payload = self._encode(record)
except (OSError, TypeError, ValueError) as error:
raise EvidenceFailure("exclusive evidence preparation failed") from error
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
if hasattr(os, "O_BINARY"):
flags |= os.O_BINARY
descriptor = -1
close_failure: OSError | None = None
try:
descriptor = os.open(path, flags, 0o600)
offset = 0
while offset < len(payload):
written = os.write(descriptor, payload[offset:])
if written <= 0:
raise OSError("short local evidence write")
offset += written
os.fsync(descriptor)
except OSError as error:
raise EvidenceFailure("exclusive evidence creation failed") from error
finally:
if descriptor >= 0:
try:
os.close(descriptor)
except OSError as error:
close_failure = error
if close_failure is not None:
raise EvidenceFailure("exclusive evidence close failed") from close_failure
try:
reopened = path.read_bytes()
except OSError as error:
raise EvidenceFailure("exclusive evidence reopen failed") from error
if reopened != payload:
raise EvidenceFailure("exclusive evidence reopen mismatch")
return EvidenceRecord(
path=path,
size=len(reopened),
sha256=hashlib.sha256(reopened).hexdigest(),
)
def create_consumed_receipt(
self, plan: SessionPlan, monotonic_value: float,
) -> EvidenceRecord:
return self._create(f"{plan.run_id}.consumed.json", {
"schema_version": 1,
"status": "CONSUMED_BEFORE_ADAPTER_OPEN",
"run_id": plan.run_id,
"policy_sha256": POLICY_SHA256,
"collector_sha256": COLLECTOR_SHA256,
"window": plan.window,
"deadline_seconds": plan.deadline_seconds,
"created_monotonic": monotonic_value,
"target_retained": False,
"retry_allowed": False,
})
def create_sanitized_output(
self, plan: SessionPlan, receipt: EvidenceRecord,
sanitized: dict[str, Any],
) -> EvidenceRecord:
return self._create(f"{plan.run_id}.sanitized.json", {
"schema_version": 1,
"status": "SANITIZED_OUTPUT_COMPLETE",
"run_id": plan.run_id,
"receipt_sha256": receipt.sha256,
"raw_transcript_persisted": False,
"result": sanitized,
})
def _remaining(clock: MonotonicClock, deadline: float) -> float:
remaining = deadline - clock.monotonic()
if remaining <= 0:
raise SessionFailure("session deadline reached")
return remaining
def _feed_boundary(
collector: OfflineCollector, chunks: list[bytes],
) -> None:
if not isinstance(chunks, list) or len(chunks) > MAX_BOUNDARY_CHUNKS:
raise SessionFailure("adapter boundary is invalid")
try:
for chunk in chunks:
collector.feed(chunk)
except CollectorError as error:
raise SessionFailure("collector rejected adapter input") from error
def run_injected_session(
plan: SessionPlan,
adapter: InjectedSessionAdapter,
clock: MonotonicClock,
evidence: ExclusiveEvidenceStore,
) -> SessionOutcome:
"""Run one injected session; never retries and never performs live I/O."""
start = clock.monotonic()
deadline = start + plan.deadline_seconds
receipt = evidence.create_consumed_receipt(plan, start)
collector = OfflineCollector()
open_attempted = False
sanitized: dict[str, Any] | None = None
primary_failure: SessionFailure | None = None
try:
open_attempted = True
adapter.open_once(plan, _remaining(clock, deadline))
chunks = adapter.receive_boundary(
"INITIAL_PROMPT", _remaining(clock, deadline))
_feed_boundary(collector, chunks)
for command in plan.commands:
adapter.send_command_token(
command, plan.exact_literal_path, _remaining(clock, deadline))
chunks = adapter.receive_boundary(
f"AFTER_{command.upper()}", _remaining(clock, deadline))
_feed_boundary(collector, chunks)
_remaining(clock, deadline)
expected_paths = (
{plan.exact_literal_path}
if plan.exact_literal_path is not None else set()
)
sanitized = collector.finalize(expected_paths)
except Exception: # noqa: BLE001 - injected adapter boundary
# Adapter exceptions are deliberately normalized; raw messages never
# become evidence or user output.
primary_failure = SessionFailure("injected session failed")
finally:
if open_attempted:
try:
adapter.close_once()
except Exception: # noqa: BLE001 - injected adapter
if primary_failure is None:
primary_failure = SessionFailure("injected session close failed")
if primary_failure is not None:
raise primary_failure from None
if sanitized is None:
raise SessionFailure("sanitized result is missing")
try:
output = evidence.create_sanitized_output(plan, receipt, sanitized)
except EvidenceFailure as error:
raise SessionFailure("sanitized output creation failed") from error
return SessionOutcome(
receipt=receipt,
output=output,
classification=str(sanitized["classification"]),
exact_identity=bool(sanitized["exact_identity"]),
)
+204
View File
@@ -0,0 +1,204 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline source-family model for shsrv framing; never opens a transport."""
from __future__ import annotations
from dataclasses import dataclass
LEGACY_RAW = "LEGACY_RAW_V07_V08"
LIBTELNET_NVT = "LIBTELNET_NVT_V09_V019"
SOURCE_FAMILIES = {LEGACY_RAW, LIBTELNET_NVT}
MAX_MODEL_BYTES = 65_536
MAX_MODEL_CHUNKS = 256
IAC = 0xFF
SE = 0xF0
SB = 0xFA
WILL = 0xFB
WONT = 0xFC
DO = 0xFD
DONT = 0xFE
class FramingError(RuntimeError):
"""Fail-closed model error without input bytes."""
@dataclass(frozen=True)
class DecodedFraming:
application: bytes
negotiation_replies: tuple[bytes, ...]
iac_commands: tuple[int, ...]
source_family: str
source_model_only: bool = True
device_behavior_proven: bool = False
@dataclass(frozen=True)
class PromptAssessment:
candidate_offsets: tuple[int, ...]
ends_with_candidate: bool
classification: str
exact_completion_proven: bool = False
def initial_server_bytes(family: str) -> bytes:
"""Both audited families emit no proactive Telnet negotiation."""
_require_family(family)
return b""
def encode_server_text(family: str, application: bytes) -> bytes:
"""Model the source-family transformation from stdout to peer bytes."""
_require_family(family)
if not isinstance(application, bytes):
raise FramingError("application text must be bytes")
if len(application) > MAX_MODEL_BYTES:
raise FramingError("application text exceeds model limit")
if family == LEGACY_RAW:
return application
output = bytearray()
for value in application:
if value == IAC:
output.extend((IAC, IAC))
elif value == 0x0D:
output.extend((0x0D, 0x00))
elif value == 0x0A:
output.extend((0x0D, 0x0A))
else:
output.append(value)
return bytes(output)
class ClientWireDecoder:
"""Bounded incremental model of bytes received by the shell."""
def __init__(self, family: str) -> None:
_require_family(family)
self.family = family
self.state = "DATA"
self.negotiation_command: int | None = None
self.raw_bytes = 0
self.chunks = 0
self._application = bytearray()
self._replies: list[bytes] = []
self._iac_commands: list[int] = []
self._sealed = False
def _append(self, value: int) -> None:
self._application.append(value)
if len(self._application) > MAX_MODEL_BYTES:
raise FramingError("decoded application exceeds model limit")
def feed(self, chunk: bytes) -> None:
if self._sealed:
raise FramingError("model is sealed")
if not isinstance(chunk, bytes):
raise FramingError("wire chunk must be bytes")
if not chunk:
return
self.chunks += 1
self.raw_bytes += len(chunk)
if self.chunks > MAX_MODEL_CHUNKS:
raise FramingError("wire chunk limit exceeded")
if self.raw_bytes > MAX_MODEL_BYTES:
raise FramingError("wire byte limit exceeded")
if self.family == LEGACY_RAW:
self._application.extend(chunk)
return
for value in chunk:
self._feed_libtelnet(value)
def _feed_libtelnet(self, value: int) -> None:
if self.state == "DATA":
if value == IAC:
self.state = "IAC"
elif value == 0x0D:
self.state = "EOL"
else:
self._append(value)
elif self.state == "EOL":
if value == 0x0A:
self._append(0x0A)
else:
self._append(0x0D)
if value != 0x00:
self._append(value)
self.state = "DATA"
elif self.state == "IAC":
if value == IAC:
self._append(IAC)
self.state = "DATA"
elif value in {WILL, WONT, DO, DONT}:
self.negotiation_command = value
self.state = "NEGOTIATION"
elif value == SB:
self.state = "SUBNEGOTIATION_OPTION"
else:
self._iac_commands.append(value)
self.state = "DATA"
elif self.state == "NEGOTIATION":
command = self.negotiation_command
if command == WILL:
self._replies.append(bytes((IAC, DONT, value)))
elif command == DO:
self._replies.append(bytes((IAC, WONT, value)))
self.negotiation_command = None
self.state = "DATA"
elif self.state == "SUBNEGOTIATION_OPTION":
self.state = "SUBNEGOTIATION"
elif self.state == "SUBNEGOTIATION":
if value == IAC:
self.state = "SUBNEGOTIATION_IAC"
elif self.state == "SUBNEGOTIATION_IAC":
if value == SE:
self.state = "DATA"
elif value == IAC:
self.state = "SUBNEGOTIATION"
else:
self.state = "IAC"
self._feed_libtelnet(value)
else:
raise FramingError("unknown model state")
def finalize(self) -> DecodedFraming:
if self._sealed:
raise FramingError("model is sealed")
self._sealed = True
if self.family == LIBTELNET_NVT and self.state != "DATA":
raise FramingError("incomplete Telnet or NVT sequence")
return DecodedFraming(
application=bytes(self._application),
negotiation_replies=tuple(self._replies),
iac_commands=tuple(self._iac_commands),
source_family=self.family,
)
def assess_prompt_candidates(application: bytes) -> PromptAssessment:
"""Find source-shaped prompt suffixes without promoting them to proof."""
if not isinstance(application, bytes):
raise FramingError("application text must be bytes")
candidates: list[int] = []
start = 0
while True:
offset = application.find(b"$ ", start)
if offset < 0:
break
candidates.append(offset)
start = offset + 2
ends = application.endswith(b"$ ")
if not ends:
classification = "NO_TERMINAL_PROMPT_CANDIDATE"
elif len(candidates) == 1:
classification = "SOURCE_SHAPE_CANDIDATE_ONLY"
else:
classification = "AMBIGUOUS_PROMPT_CANDIDATES"
return PromptAssessment(tuple(candidates), ends, classification)
def _require_family(family: str) -> None:
if family not in SOURCE_FAMILIES:
raise FramingError("unknown source family")
+240
View File
@@ -0,0 +1,240 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Offline-only passive LF-batch contract for synthetic shsrv inputs.
The module has no transport, CLI, address, clock, file output or prompt
detector. It formats one bounded batch from an already validated Phase-1.0W
plan and seals supplied bytes only when the caller supplies a synthetic hard
deadline event.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from phase10v_shsrv_collector_model import CollectorError, OfflineCollector
from phase10w_shsrv_client_policy import SessionPlan, WINDOW_COMMANDS
IAC = 0xFF
MAX_LITERAL_PATH_BYTES = 512
MAX_BATCH_BYTES = 1035
KNOWN_HELP_FAMILIES = {
"OFFICIAL_V07_SOURCE_FAMILY_CANDIDATE",
"OFFICIAL_V019_SOURCE_FAMILY_CANDIDATE",
}
class PassiveContractError(RuntimeError):
"""Fail-closed contract error that never embeds supplied bytes or paths."""
@dataclass(frozen=True)
class PassiveBatch:
"""Target-free immutable outbound bytes for one synthetic session."""
window: str
payload: bytes
expected_paths: tuple[str, ...]
command_count: int
deadline_seconds: int
outbound_batches: int = 1
lf_only: bool = True
telnet_negotiation: bool = False
retry_allowed: bool = False
reconnect_allowed: bool = False
resume_allowed: bool = False
def _validate_payload(payload: bytes) -> None:
if not payload or len(payload) > MAX_BATCH_BYTES:
raise PassiveContractError("batch length is invalid")
if any(value in payload for value in (0x00, 0x0D, IAC)):
raise PassiveContractError("batch contains a forbidden byte")
if any(value > 0x7F for value in payload):
raise PassiveContractError("batch is not ASCII")
if not payload.endswith(b"\n"):
raise PassiveContractError("batch is not LF terminated")
def _validate_batch(batch: PassiveBatch) -> None:
_validate_payload(batch.payload)
if batch.outbound_batches != 1 or batch.lf_only is not True or \
batch.telnet_negotiation is not False or \
batch.retry_allowed is not False or \
batch.reconnect_allowed is not False or batch.resume_allowed is not False:
raise PassiveContractError("batch safety fields are invalid")
if not isinstance(batch.deadline_seconds, int) or isinstance(
batch.deadline_seconds, bool) or not 1 <= batch.deadline_seconds <= 10:
raise PassiveContractError("batch deadline is invalid")
if batch.window == "T2_GREETING_AND_HELP":
if batch.payload != b"help\n" or batch.expected_paths != () or \
batch.command_count != 1:
raise PassiveContractError("help batch contract is invalid")
return
if batch.window == "T3_ONE_EXACT_PATH" and \
len(batch.expected_paths) == 1 and batch.command_count == 2:
path = batch.expected_paths[0]
try:
OfflineCollector._validate_expected_paths({path})
encoded = path.encode("ascii", errors="strict")
except (CollectorError, UnicodeEncodeError) as error:
raise PassiveContractError("path batch contract is invalid") from error
expected = b"stat " + encoded + b"\nsum " + encoded + b"\n"
if len(encoded) <= MAX_LITERAL_PATH_BYTES and batch.payload == expected:
return
raise PassiveContractError("path batch contract is invalid")
def build_passive_batch(plan: SessionPlan) -> PassiveBatch:
"""Build one target-free LF batch from an exact Phase-1.0W plan."""
if not isinstance(plan, SessionPlan):
raise PassiveContractError("session plan type is invalid")
expected_commands = WINDOW_COMMANDS.get(plan.window)
if expected_commands is None or plan.commands != expected_commands:
raise PassiveContractError("window command sequence is invalid")
if not isinstance(plan.deadline_seconds, int) or isinstance(
plan.deadline_seconds, bool) or not 1 <= plan.deadline_seconds <= 10:
raise PassiveContractError("deadline is invalid")
expected_paths: tuple[str, ...]
if plan.window == "T2_GREETING_AND_HELP":
if plan.exact_literal_path is not None:
raise PassiveContractError("help window contains a path")
payload = b"help\n"
expected_paths = ()
elif plan.window == "T3_ONE_EXACT_PATH":
path = plan.exact_literal_path
if not isinstance(path, str):
raise PassiveContractError("exact path is missing")
try:
OfflineCollector._validate_expected_paths({path})
encoded = path.encode("ascii", errors="strict")
except (CollectorError, UnicodeEncodeError) as error:
raise PassiveContractError("exact path is invalid") from error
if len(encoded) > MAX_LITERAL_PATH_BYTES:
raise PassiveContractError("exact path is too long")
payload = b"stat " + encoded + b"\nsum " + encoded + b"\n"
expected_paths = (path,)
else:
raise PassiveContractError("window is not allowlisted")
batch = PassiveBatch(
window=plan.window,
payload=payload,
expected_paths=expected_paths,
command_count=len(plan.commands),
deadline_seconds=plan.deadline_seconds,
)
_validate_batch(batch)
return batch
class PassiveResultAccumulator:
"""Consume supplied chunks once; never observes prompts or remote EOF."""
def __init__(self, batch: PassiveBatch) -> None:
if not isinstance(batch, PassiveBatch):
raise PassiveContractError("batch type is invalid")
_validate_batch(batch)
self.batch = batch
self._collector = OfflineCollector()
self.state = "READY"
def _invalidate(self, message: str) -> None:
if self._collector.state not in {"SEALED", "INVALID", "ABORTED"}:
try:
self._collector.abort()
except CollectorError:
pass
self.state = "INVALID"
raise PassiveContractError(message)
def feed_supplied_chunk(self, chunk: bytes) -> None:
if self.state not in {"READY", "RECEIVING"}:
raise PassiveContractError("accumulator is not accepting input")
if not isinstance(chunk, bytes):
self._invalidate("input must be bytes")
if IAC in chunk:
self._invalidate("unexpected Telnet control byte")
try:
self._collector.feed(chunk)
except CollectorError as error:
self._invalidate("collector rejected supplied input")
raise AssertionError("unreachable") from error
if chunk:
self.state = "RECEIVING"
def abort(self) -> None:
if self.state not in {"READY", "RECEIVING"}:
raise PassiveContractError("accumulator can no longer abort")
try:
self._collector.abort()
except CollectorError as error:
raise PassiveContractError("collector abort failed") from error
self.state = "ABORTED"
def _validate_complete_result(self, result: dict[str, Any]) -> None:
if self.batch.window == "T2_GREETING_AND_HELP":
fingerprint = result.get("command_fingerprint", {})
if fingerprint.get("source_family_match") not in KNOWN_HELP_FAMILIES:
raise PassiveContractError("help response is incomplete or unknown")
if result.get("classification") != "SOURCE_FAMILY_FINGERPRINT_ONLY":
raise PassiveContractError("help response classification is invalid")
elif self.batch.window == "T3_ONE_EXACT_PATH":
observations = result.get("file_observations")
if not isinstance(observations, list) or len(observations) != 1:
raise PassiveContractError("file response is incomplete")
observation = observations[0]
required = {
"path", "metadata_seen", "size", "weak_checksum",
"weak_checksum_algorithm", "cryptographic_checksum",
"proves_exact_binary",
}
if not required.issubset(observation) or observation.get("path") != \
self.batch.expected_paths[0]:
raise PassiveContractError("file response fields are incomplete")
if observation.get("metadata_seen") is not True or not isinstance(
observation.get("size"), int) or isinstance(
observation.get("size"), bool) or observation["size"] < 0:
raise PassiveContractError("stat response is incomplete")
if observation.get("weak_checksum_algorithm") != "BSD_ROTATE_16" or \
observation.get("cryptographic_checksum") is not False:
raise PassiveContractError("sum response is incomplete")
if result.get("classification") != "WEAK_FILE_CORRELATION_ONLY":
raise PassiveContractError("file response classification is invalid")
else:
raise PassiveContractError("batch window is invalid")
def seal_at_hard_deadline(
self, hard_deadline_reached: bool,
) -> dict[str, Any]:
"""Seal once only after an externally supplied synthetic deadline."""
if hard_deadline_reached is not True:
self._invalidate("hard deadline event is absent")
if self.state not in {"READY", "RECEIVING"}:
raise PassiveContractError("accumulator cannot be sealed")
try:
result = self._collector.finalize(set(self.batch.expected_paths))
self._validate_complete_result(result)
except (CollectorError, PassiveContractError) as error:
self.state = "INVALID"
raise PassiveContractError("deadline result is invalid") from error
self.state = "SEALED"
result["passive_batch_contract"] = {
"offline_only": True,
"one_outbound_batch": True,
"plain_lf_only": True,
"telnet_negotiation_emitted": False,
"telnet_control_received": False,
"prompt_completion_used": False,
"remote_eof_completion_used": False,
"sealed_by_synthetic_hard_deadline": True,
"source_family_selected": False,
"retry_allowed": False,
"reconnect_allowed": False,
"device_behavior_proven": False,
"exact_identity_proven": False,
}
return result
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Reject common credential material before it reaches Git history."""
from __future__ import annotations
import argparse
import os
import re
from pathlib import Path
PATTERNS = {
"private key": re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----"),
"GitHub-style token": re.compile(r"\bgh[pousr]_[A-Za-z0-9]{30,}\b"),
"OpenAI-style key": re.compile(r"\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b"),
"AWS access key": re.compile(r"\bAKIA[0-9A-Z]{16}\b"),
"credential in URL": re.compile(r"https?://[^\s/:@]+:[^\s/@]+@"),
}
SKIP_PARTS = {".git", "work", "build", ".vs", ".idea", ".vscode"}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
errors: list[str] = []
scanned = 0
for directory, subdirectories, filenames in os.walk(root):
subdirectories[:] = sorted(
name
for name in subdirectories
if name not in SKIP_PARTS and not name.startswith("build-")
)
for filename in sorted(filenames):
path = Path(directory, filename)
relative = path.relative_to(root)
if path.stat().st_size > 2_000_000:
continue
try:
text = path.read_text(encoding="utf-8")
except UnicodeDecodeError:
continue
scanned += 1
for label, pattern in PATTERNS.items():
if pattern.search(text):
errors.append(f"{relative}: possible {label}")
if errors:
for error in errors:
print(f"secret scan failed: {error}")
return 1
print(f"secret scan passed across {scanned} text files")
return 0
if __name__ == "__main__":
raise SystemExit(main())
File diff suppressed because it is too large Load Diff
+618
View File
@@ -0,0 +1,618 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the offline, fail-closed Phase-0.8R evidence contract."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
from typing import Any
STATUS = "READ_ONLY_PREFLIGHT_BLOCKED"
SOURCE_COMMIT = "2c944d6d65a08f7e1c02f518721cde061b999329"
PAYLOAD_MANAGER_COMMIT = "cfbc70f30f419b09bf2b52283f7409e2d3117ee1"
DENYLIST_SHA256 = (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
)
STOCK_ELFLDR_SHA256 = (
"092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8"
)
STOCK_PAYLOAD_MANAGER_SHA256 = (
"518740adbacccb9094fadb07dd424c53ee290f38306449ccc9d6957fdf813c0b"
)
IMMUTABLE_EVIDENCE = {
"docs/runtime/phase-0.8-read-only-preflight.md": {
"role": "historical_human_readable_preflight_record",
"sha256": "3fbe086175a6048176075f447ec1482074928e3b5282db97ea2169395fe1d508",
},
"manifests/runtime/phase-0.8-read-only-preflight.json": {
"role": "historical_machine_readable_preflight_record",
"sha256": "47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322",
},
"tests/test_phase08_preflight.py": {
"role": "historical_fail_closed_regression_test",
"sha256": "8a4ad7c70de28ffe3148fd3fd1f68c36a872c53c691c9068e1ff163970863c48",
},
}
AUTHORIZATION_FIELDS = (
"authorized",
"installation_authorized",
"lifecycle_authorized",
"execution_authorized",
"transfer_authorized",
"automatic_retry",
)
ACTIVITY_FIELDS = (
"hardware_observed",
"ps5_connected",
"files_transferred",
"target_execution_performed",
"target_mutation_performed",
"target_artifact_created",
"collector_implemented",
"target_build_performed",
)
REQUIRED_BLOCKERS = {
"exact_permission_quote_absent": "STOP-RO",
"collector_identity_absent": "STOP-RO",
"collector_side_effect_contract_absent": "STOP-RO",
"two_current_firmware_sources_absent": "STOP-GATE",
"live_object_identities_absent": "STOP-GATE",
"listeners_absent": "STOP-GATE",
"autoload_status_absent": "STOP-GATE",
"rollback_backups_absent": "STOP-GATE",
"payload_manager_backup_not_byte_exact_on_device": "HARD_STOP-GATE",
"unknown_result_is_stop": "STOP",
"timeout_is_stop": "STOP",
"deviation_is_stop": "STOP",
"automatic_retry_forbidden": "STOP",
}
REQUIRED_FINDINGS = {
"options_any_endpoint",
"get_version",
"get_log",
"get_autoload_status",
"get_config",
"get_list_payloads",
"get_processes_list",
"get_sources_list",
"get_ip",
}
REQUIRED_OBSERVATIONS = {
"firmware",
"live_paths",
"object_identities",
"file_sizes",
"sha256",
"processes_services",
"listeners",
"autoload",
"rollback_files",
"storage_precondition",
}
REQUIRED_PROHIBITED_ACTIONS = {
"connect_to_ps5",
"probe_ip_port_or_device_interface",
"use_usb_or_removable_media",
"transfer_ps5_file",
"package_for_ps5_deployment",
"install_or_replace_target_component",
"execute_elf_or_payload",
"build_target_elf",
"start_cross_compiler",
"implement_or_build_collector",
"modify_payload_manager_production_code",
"modify_elfldr_production_code",
"modify_lifecycle_code",
"activate_or_modify_autoload",
"activate_retry",
"change_target_configuration",
"start_stop_or_signal_target_service_or_process",
"implement_gnm_videoout_sdl_audio_input_shaders_cores_or_retroarch",
"download_or_install_packages",
"contact_internet_gitea_or_other_remote",
"commit_or_push",
}
TEMPLATE_REQUIRED_FIELDS = {
"exact_user_statement",
"authorization_date",
"expiration_time",
"device_identity",
"exact_purpose",
"exact_observations",
"method_or_collector_id",
"source_commit",
"collector_file_size",
"collector_sha256",
"firmware_gate",
"maximum_runtime_ms",
"maximum_execution_count",
"maximum_transfer_count",
"network_behavior",
"output_channel",
"allowed_volatile_effects",
"prohibited_persistent_effects",
"stop_criteria",
"cleanup_requirements",
"reporting_requirements",
"explicit_installation_exclusion",
"explicit_lifecycle_probe_exclusion",
"explicit_autoload_and_retry_exclusion",
"explicit_graphics_and_retroarch_exclusion",
"revocation_method",
"manual_confirmation_template_does_not_authorize",
}
TARGET_SUFFIXES = {
".elf",
".self",
".sprx",
".pkg",
".bin",
".payload",
".zip",
".tar",
".tgz",
".7z",
}
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def load_json(path: Path) -> dict[str, Any]:
document = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(document, dict):
raise ValueError(f"{path}: expected a JSON object")
return document
def extract_json_contract(path: Path, name: str) -> dict[str, Any]:
text = path.read_text(encoding="utf-8")
begin = f"<!-- BEGIN {name} -->"
end = f"<!-- END {name} -->"
if text.count(begin) != 1 or text.count(end) != 1:
raise ValueError(f"{path}: expected exactly one {name} contract")
block = text.split(begin, 1)[1].split(end, 1)[0].strip()
if not block.startswith("```json\n") or not block.endswith("\n```"):
raise ValueError(f"{path}: {name} must be one fenced JSON object")
document = json.loads(block[len("```json\n") : -len("\n```")])
if not isinstance(document, dict):
raise ValueError(f"{path}: {name} must be a JSON object")
return document
def positive_status_values(value: Any) -> list[str]:
errors: list[str] = []
positive = {
"READY",
"COMPLETE",
"COMPLETED",
"AUTHORIZED",
"PASS",
"PASSED",
"READ_ONLY_PREFLIGHT_DATA_COMPLETE",
"READY_FOR_HARDENED_RUNTIME_DEPLOYMENT",
}
if isinstance(value, dict):
for key, child in value.items():
if key == "historical_validation_report":
continue
errors.extend(positive_status_values(child))
elif isinstance(value, list):
for child in value:
errors.extend(positive_status_values(child))
elif isinstance(value, str) and value.upper() in positive:
errors.append(value)
return errors
def validate_manifest(
manifest: dict[str, Any], denylist: dict[str, Any]
) -> list[str]:
errors: list[str] = []
if manifest.get("schema_version") != 1:
errors.append("unsupported remediation schema version")
schema_contract = manifest.get("schema_contract", {})
if schema_contract.get("id") != "chimera-gfx-phase-0.8-remediation-v1":
errors.append("remediation schema-contract ID changed")
if schema_contract.get("shared_schema_available") is not False:
errors.append("remediation incorrectly claims a shared schema")
if schema_contract.get("validator") != "tools/validate_phase08_remediation.py":
errors.append("remediation validator binding changed")
if manifest.get("phase_id") != "0.8R":
errors.append("remediation phase ID changed")
if manifest.get("phase") != "offline_remediation":
errors.append("remediation phase widened beyond offline")
if manifest.get("status") != STATUS:
errors.append("Phase-0.8 status is not fail-closed")
if positive_status_values(manifest):
errors.append("manifest contains an overriding positive status")
historical = manifest.get("historical_identity", {})
if historical.get("source_commit") != SOURCE_COMMIT:
errors.append("historical source commit changed")
if historical.get("status") != STATUS:
errors.append("historical Phase-0.8 status changed")
historical_report = historical.get("historical_validation_report", {})
if (
historical_report.get("classification")
!= "historical_report_not_current_hardware_evidence"
):
errors.append("historical tests were promoted to hardware evidence")
immutable = {
item.get("path"): {
"role": item.get("role"),
"sha256": item.get("sha256"),
}
for item in manifest.get("immutable_evidence", [])
}
if immutable != IMMUTABLE_EVIDENCE:
errors.append("immutable Phase-0.8 evidence binding changed")
authorization = manifest.get("authorization", {})
if any(authorization.get(field) is not False for field in AUTHORIZATION_FIELDS):
errors.append("an authorization or retry field is not false")
activity = manifest.get("activity", {})
if any(activity.get(field) is not False for field in ACTIVITY_FIELDS):
errors.append("manifest claims a prohibited target activity")
if manifest.get("firmware_runtime_behavior") != "UNPROVEN":
errors.append("firmware runtime behavior was promoted")
claim_boundaries = manifest.get("claim_boundaries", {})
required_false_claims = {
"hardware_safety_proven",
"firmware_behavior_proven",
"absence_of_volatile_effects_proven",
"no_persistent_write_found_equals_side_effect_free",
"host_tests_are_hardware_evidence",
"missing_observation_means_safe_absence",
}
if any(claim_boundaries.get(field) is not False for field in required_false_claims):
errors.append("a prohibited safety or evidence claim was enabled")
stock = manifest.get("stock_identities", {})
if (
stock.get("classification") != "reference_only"
or stock.get("current_device_observed") is not False
):
errors.append("stock identities were promoted from reference-only")
elfldr = stock.get("elfldr", {})
if (
elfldr.get("size") != 397000
or elfldr.get("sha256") != STOCK_ELFLDR_SHA256
or elfldr.get("current_device_match") != "UNPROVEN"
):
errors.append("stock elfldr reference changed or was promoted")
manager = stock.get("payload_manager", {})
if (
manager.get("size") != 2050320
or manager.get("sha256") != STOCK_PAYLOAD_MANAGER_SHA256
or manager.get("current_device_match") != "UNPROVEN"
):
errors.append("stock Payload Manager reference changed or was promoted")
backup = manifest.get("payload_manager_backup", {})
if backup != {
"classification": "hard_blocker",
"on_device_proven": False,
"byte_exact_proven": False,
"creation_allowed_in_strict_read_only_phase": False,
"result": "HARD_STOP-GATE",
}:
errors.append("Payload Manager backup hard blocker changed")
entries = denylist.get("entries", [])
if (
denylist.get("fail_closed") is not True
or len(entries) != 1
or entries[0].get("sha256") != DENYLIST_SHA256
or entries[0].get("status") != "BLOCKED"
or entries[0].get("permanent") is not True
or entries[0].get("execution_eligible") is not False
):
errors.append("permanent denylist binding changed")
blockers = {
item.get("id"): item.get("severity") for item in manifest.get("blockers", [])
}
if blockers != REQUIRED_BLOCKERS:
errors.append("remediation blocker set changed")
findings = {
item.get("id"): item for item in manifest.get("side_effect_findings", [])
}
if set(findings) != REQUIRED_FINDINGS:
errors.append("Payload Manager side-effect finding set changed")
for finding_id, finding in findings.items():
if finding.get("strict_read_only_preflight_suitable") is not False:
errors.append(f"{finding_id}: incorrectly marked strict-read-only suitable")
references = finding.get("source_references")
if not isinstance(references, list) or not references:
errors.append(f"{finding_id}: source references are absent")
if finding_id != "options_any_endpoint":
if finding.get("http_method") == "OPTIONS":
errors.append(f"{finding_id}: non-OPTIONS finding mislabeled")
if finding.get("writes_server_active_flag") is not True:
errors.append(f"{finding_id}: server_active_flag mutation hidden")
options = findings.get("options_any_endpoint", {})
if (
options.get("http_method") != "OPTIONS"
or options.get("writes_server_active_flag") is not False
or options.get("strict_read_only_preflight_suitable") is not False
):
errors.append("OPTIONS route classification changed")
autoload = findings.get("get_autoload_status", {})
if (
autoload.get("endpoint") != "/autoload_status"
or autoload.get("writes_autoload_triggered") is not True
or autoload.get("reads_filesystem_or_configuration") is not True
):
errors.append("/autoload_status mutations or reads were hidden")
source = manifest.get("payload_manager_source", {})
if (
source.get("commit") != PAYLOAD_MANAGER_COMMIT
or source.get("release") != "v0.3.1"
):
errors.append("Payload Manager source identity changed")
source_files = source.get("files")
if not isinstance(source_files, list) or len(source_files) < 3:
errors.append("Payload Manager source-file evidence is incomplete")
observations = {
item.get("id"): item for item in manifest.get("evidence_contract", [])
}
if set(observations) != REQUIRED_OBSERVATIONS:
errors.append("future evidence-contract observation set changed")
for observation_id, observation in observations.items():
if observation.get("confidence") != "UNPROVEN":
errors.append(f"{observation_id}: confidence was promoted")
if observation.get("timeout_ms") is not None:
errors.append(f"{observation_id}: timeout invented before tool review")
if observation.get("fail_closed_result") != "STOP":
errors.append(f"{observation_id}: fail-closed result changed")
identity = observation.get("required_collector_identity")
output = observation.get("reviewer_output")
if not isinstance(identity, list) or not identity:
errors.append(f"{observation_id}: collector identity contract absent")
if not isinstance(output, list) or not output:
errors.append(f"{observation_id}: reviewer output contract absent")
prohibited = set(manifest.get("prohibited_actions", []))
if prohibited != REQUIRED_PROHIBITED_ACTIONS:
errors.append("prohibited-action set changed")
future = manifest.get("future_activity", {})
if (
future.get("mode") != "design_only"
or future.get("bounded_observation_implemented") is not False
or future.get("collector_selected") is not False
or future.get("transfer_method_selected") is not False
or future.get("execution_method_selected") is not False
or future.get("new_explicit_authorization_required") is not True
):
errors.append("future bounded observation was promoted beyond design")
retroarch = manifest.get("retroarch", {})
if retroarch != {
"goal": "long_term_goal",
"active_phase": False,
"work_started": False,
"dependency_chain_only": True,
}:
errors.append("RetroArch was promoted into the active phase")
return errors
def validate_template(template: dict[str, Any]) -> list[str]:
errors: list[str] = []
if template.get("template_only") is not True:
errors.append("bounded-observation template is not template-only")
for field in (
"authorized",
"execution_authorized",
"transfer_authorized",
"installation_authorized",
"lifecycle_authorized",
"automatic_retry",
):
if template.get(field) is not False:
errors.append(f"template field {field} is not false")
required = template.get("required_fields", {})
if set(required) != TEMPLATE_REQUIRED_FIELDS:
errors.append("bounded-observation required-field set changed")
elif any(value is not None for value in required.values()):
errors.append("bounded-observation template contains prefilled request data")
exclusions = template.get("fixed_exclusions", {})
expected_exclusions = {
"installation",
"lifecycle_probe",
"autoload",
"automatic_retry",
"gnm",
"videoout",
"sdl",
"retroarch",
}
if set(exclusions) != expected_exclusions or any(
value is not True for value in exclusions.values()
):
errors.append("bounded-observation fixed exclusions changed")
return errors
def validate_doc_contract(
contract: dict[str, Any], manifest: dict[str, Any]
) -> list[str]:
errors: list[str] = []
if contract.get("status") != manifest.get("status"):
errors.append("documentation/manifest status mismatch")
if contract.get("authorization") != manifest.get("authorization"):
errors.append("documentation/manifest authorization mismatch")
blocker_ids = [item.get("id") for item in manifest.get("blockers", [])]
if contract.get("blockers") != blocker_ids:
errors.append("documentation/manifest blocker mismatch")
if contract.get("firmware_runtime_behavior") != "UNPROVEN":
errors.append("documentation promoted firmware behavior")
if contract.get("stock_identity_classification") != "reference_only":
errors.append("documentation promoted stock identities")
if contract.get("payload_manager_backup_classification") != "hard_blocker":
errors.append("documentation weakened the manager backup blocker")
if contract.get("retroarch_active_phase") is not False:
errors.append("documentation promoted RetroArch into the active phase")
return errors
def validate_immutable_evidence(root: Path) -> list[str]:
errors: list[str] = []
for relative, expected in IMMUTABLE_EVIDENCE.items():
path = root / relative
if not path.is_file():
errors.append(f"immutable evidence missing: {relative}")
elif sha256(path) != expected["sha256"]:
errors.append(f"immutable evidence hash mismatch: {relative}")
return errors
def changed_paths(root: Path) -> list[Path]:
result = subprocess.run(
["git", "status", "--porcelain=v1", "--untracked-files=all"],
cwd=root,
check=True,
capture_output=True,
text=True,
)
paths: list[Path] = []
for line in result.stdout.splitlines():
value = line[3:]
for candidate in value.split(" -> "):
candidate = candidate.strip('"')
paths.append(Path(candidate))
return paths
def validate_changed_files(root: Path) -> list[str]:
errors: list[str] = []
for path in changed_paths(root):
if path.suffix.lower() in TARGET_SUFFIXES:
errors.append(f"target artifact appears in change set: {path}")
normalized = path.as_posix()
if normalized.startswith(
("src/", "include/", "samples/", "adapters/", "work/upstream/")
):
errors.append(f"production/runtime source changed in remediation: {path}")
return errors
def validate_local_payload_manager_source(
root: Path, manifest: dict[str, Any]
) -> list[str]:
errors: list[str] = []
source_root = root / "work/upstream/pldmgr-v0.3.1"
if not source_root.is_dir():
return ["required local Payload Manager source checkout is absent"]
head = subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=source_root,
check=True,
capture_output=True,
text=True,
).stdout.strip()
if head != PAYLOAD_MANAGER_COMMIT:
errors.append("local Payload Manager source commit changed")
status = subprocess.run(
["git", "status", "--porcelain"],
cwd=source_root,
check=True,
capture_output=True,
text=True,
).stdout.strip()
if status:
errors.append("local Payload Manager source checkout is dirty")
for item in manifest["payload_manager_source"]["files"]:
path = source_root / item["path"]
if not path.is_file():
errors.append(f"Payload Manager source file missing: {item['path']}")
elif sha256(path) != item["sha256"]:
errors.append(f"Payload Manager source hash mismatch: {item['path']}")
return errors
def collect_errors(root: Path, require_local_source: bool = False) -> list[str]:
manifest = load_json(root / "manifests/runtime/phase-0.8-remediation.json")
denylist = load_json(root / "manifests/artifact-denylist.json")
doc_contract = extract_json_contract(
root / "docs/runtime/phase-0.8-remediation.md", "PHASE08R_CONTRACT"
)
template = extract_json_contract(
root / "docs/approvals/phase-0.8-bounded-observation-template.md",
"PHASE08_BOUNDED_OBSERVATION_TEMPLATE",
)
errors = validate_immutable_evidence(root)
errors.extend(validate_manifest(manifest, denylist))
errors.extend(validate_doc_contract(doc_contract, manifest))
errors.extend(validate_template(template))
errors.extend(validate_changed_files(root))
if require_local_source:
errors.extend(validate_local_payload_manager_source(root, manifest))
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument(
"--require-local-source",
action="store_true",
help="also require and rehash the ignored pinned Payload Manager checkout",
)
args = parser.parse_args()
root = args.root.resolve()
errors = collect_errors(root, args.require_local_source)
if errors:
for error in errors:
print(f"Phase-0.8R validation failed: {error}")
return 1
print(
"Phase-0.8R remediation validation passed: "
f"{len(IMMUTABLE_EVIDENCE)} immutable files, "
f"{len(REQUIRED_FINDINGS)} side-effect findings, "
f"{len(REQUIRED_OBSERVATIONS)} observation contracts, "
f"{len(REQUIRED_BLOCKERS)} blockers; hardware evidence not claimed"
)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (
KeyError,
OSError,
subprocess.CalledProcessError,
TypeError,
ValueError,
json.JSONDecodeError,
) as error:
print(f"Phase-0.8R validation failed: {error}")
raise SystemExit(1) from error
+464
View File
@@ -0,0 +1,464 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the blocked, offline-only Phase-0.9B observer audit."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess
import sys
from typing import Any
EXPECTED_DECISION = {
"OBSERVER_STARTUP_OR_EXIT_ABI_UNPROVEN",
"NO_PROVEN_NON_PERSISTENT_OUTPUT_CHANNEL",
}
AUTHORIZATION_FIELDS = (
"authorized",
"transfer_authorized",
"execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"backup_creation_authorized",
"automatic_retry",
)
SOURCE_COMMITS = {
"hardened_elfldr": ("../chimera-elfldr", "197623058f509eddde18868dafcb92fdcac66464"),
"controlled_payload_manager": (
"../chimera-ps5-payload-manager",
"e23d94ff91233aa770e2342800c1467875bdef44",
),
"elfldr_public_base": (
"work/upstream/elfldr-v0.23",
"699e8bcff03e91e8d6ca6eba281af25c5a58d8c2",
),
"payload_manager_public_base": (
"work/upstream/pldmgr-v0.3.1",
"cfbc70f30f419b09bf2b52283f7409e2d3117ee1",
),
"ps5_payload_sdk_v0_41": (
"work/upstream/sdk",
"d2e2e585740362976a39fdd5ccf390f199a7bc37",
),
}
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as handle:
value = json.load(handle)
if not isinstance(value, dict):
raise ValueError(f"{path} must contain a JSON object")
return value
def extract_json_contract(path: Path, marker: str) -> dict[str, Any]:
text = path.read_text(encoding="utf-8")
pattern = (
rf"<!-- BEGIN {re.escape(marker)} -->\s*```json\s*(.*?)\s*```\s*"
rf"<!-- END {re.escape(marker)} -->"
)
match = re.search(pattern, text, flags=re.DOTALL)
if not match:
raise ValueError(f"{path} is missing {marker}")
value = json.loads(match.group(1))
if not isinstance(value, dict):
raise ValueError(f"{marker} must be a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def git_output(root: Path, *args: str) -> str:
return subprocess.check_output(
["git", *args], cwd=root, text=True, encoding="utf-8"
).strip()
def validate_authorizations(value: dict[str, Any], prefix: str) -> list[str]:
errors: list[str] = []
for field in AUTHORIZATION_FIELDS:
if value.get(field) is not False:
errors.append(f"{prefix}.{field} must be false")
return errors
def validate_schema(schema: dict[str, Any], manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
properties = schema.get("properties", {})
for field in AUTHORIZATION_FIELDS:
if properties.get(field, {}).get("const") is not False:
errors.append(f"schema {field} must be const false")
if properties.get("device_address", {}).get("const", "missing") is not None:
errors.append("schema device_address must be const null")
if properties.get("maximum_execution_count", {}).get("const") != 0:
errors.append("schema maximum_execution_count must be const zero")
default = schema.get("x-chimera-default-plan")
if default != manifest.get("default_observation_plan"):
errors.append("schema default plan must equal manifest default plan")
if not isinstance(default, dict):
return errors
errors.extend(validate_authorizations(default, "default_plan"))
if default.get("device_address") is not None:
errors.append("default plan contains a device address")
if default.get("device_identity") is not None:
errors.append("default plan contains a device identity")
if default.get("read_paths") != []:
errors.append("default plan contains read paths")
if default.get("allowed_observations") != []:
errors.append("default plan contains observations")
if default.get("output_channel") is not None:
errors.append("default plan contains an output channel")
if default.get("maximum_execution_count") != 0:
errors.append("default plan permits an execution")
return errors
def validate_manifest(root: Path, manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
if manifest.get("status") != "BLOCKED":
errors.append("Phase-0.9B status must be BLOCKED")
if set(manifest.get("decision", [])) != EXPECTED_DECISION:
errors.append("Phase-0.9B hard-gate decision changed")
errors.extend(
validate_authorizations(manifest.get("authorization", {}), "authorization")
)
canonical = manifest.get("canonical_state_preserved", {})
expected_canonical = {
"historical_phase08_status": "READ_ONLY_PREFLIGHT_BLOCKED",
"phase09a_status": "DESIGN_ONLY",
"firmware_runtime_behavior": "UNPROVEN",
"stock_hashes": "reference_only",
"payload_manager_backup": "HARD_BLOCKER",
"device_contact_performed": False,
"device_transfer_performed": False,
"device_execution_performed": False,
}
for field, expected in expected_canonical.items():
if canonical.get(field) != expected:
errors.append(f"canonical state {field} must be {expected!r}")
deny_binding = manifest.get("permanent_denylist_binding", {})
if deny_binding != {
"sha256": "4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63",
"status": "BLOCKED",
"permanent": True,
"execution_eligible": False,
}:
errors.append("permanent denylist binding changed")
commits = manifest.get("source_commits", {})
tree_status = manifest.get("source_tree_status", {})
for key, (relative, expected_commit) in SOURCE_COMMITS.items():
if commits.get(key) != expected_commit:
errors.append(f"manifest source commit mismatch: {key}")
path = (root / relative).resolve()
if not path.exists():
errors.append(f"source tree missing: {relative}")
continue
try:
actual_commit = git_output(path, "rev-parse", "HEAD")
dirty = git_output(path, "status", "--porcelain")
except (OSError, subprocess.CalledProcessError) as exc:
errors.append(f"source tree unreadable: {relative}: {exc}")
continue
if actual_commit != expected_commit:
errors.append(f"source tree commit mismatch: {relative}")
if dirty:
errors.append(f"source tree is dirty: {relative}")
if tree_status.get(key) != "clean":
errors.append(f"manifest does not classify {key} as clean")
for evidence in manifest.get("source_evidence", []):
relative = evidence.get("path")
expected_digest = evidence.get("sha256")
if not isinstance(relative, str) or not isinstance(expected_digest, str):
errors.append("source evidence entry lacks path or SHA-256")
continue
path = (root / relative).resolve()
if not path.is_file():
errors.append(f"source evidence file missing: {relative}")
continue
if sha256_file(path) != expected_digest:
errors.append(f"source evidence digest mismatch: {relative}")
if "size" in evidence and path.stat().st_size != evidence["size"]:
errors.append(f"source evidence size mismatch: {relative}")
matrix = manifest.get("capability_matrix", [])
expected_facts = {
"firmware_source_1",
"firmware_source_2",
"file_metadata",
"object_identity",
"sha256",
"mount_information",
"processes_services",
"listeners",
"autoload_configuration",
"output_channel",
"monotonic_time_deadline",
"process_exit",
}
if {entry.get("needed_fact") for entry in matrix} != expected_facts:
errors.append("capability matrix is incomplete or changed")
if any(entry.get("implement") is not False for entry in matrix):
errors.append("a blocked capability is marked for implementation")
gate = manifest.get("build_gate", {})
for field in (
"startup_and_exit_abi_proven",
"non_persistent_output_channel_proven",
"normal_sdk_crt_kernelwrite_free",
"custom_freestanding_cleanup_proven",
"observer_source_created",
"observer_target_declared",
"target_build_performed",
"double_clean_build_performed",
):
if gate.get(field) is not False:
errors.append(f"build gate {field} must be false")
if gate.get("reason") != "BLOCKED_BEFORE_SOURCE_AND_BUILD":
errors.append("build gate reason changed")
implementation = manifest.get("implementation", {})
if implementation.get("observer_logic_implemented") is not False:
errors.append("observer logic must remain unimplemented")
if implementation.get("observations_implemented") != []:
errors.append("target observations must remain unimplemented")
artifact = manifest.get("artifact", {})
if artifact.get("present") is not False:
errors.append("observer artifact must be absent")
for field in ("path", "sha256", "size"):
if artifact.get(field) is not None:
errors.append(f"artifact {field} must be null")
for field in (
"imports",
"undefined_symbols",
"dynamic_dependencies",
"network_functions",
"filesystem_reads",
):
if artifact.get(field) != []:
errors.append(f"artifact {field} must be empty")
for field in (
"installation_eligible",
"lifecycle_eligible",
"autoload_eligible",
"execution_authorized",
"execution_eligible",
):
if artifact.get(field) is not False:
errors.append(f"artifact {field} must be false")
if (
manifest.get("static_artifact_audit", {}).get("status")
!= "NOT_PERFORMED_BLOCKED_BEFORE_BUILD"
):
errors.append("artifact audit must be recorded as not performed")
reproducibility = manifest.get("reproducibility", {})
if reproducibility.get("status") != "NOT_PERFORMED_BLOCKED_BEFORE_BUILD":
errors.append("reproducibility must be recorded as not performed")
for field in ("build_1_sha256", "build_2_sha256", "byte_identical"):
if reproducibility.get(field) is not None:
errors.append(f"reproducibility {field} must be null")
return errors
def validate_denylist(root: Path) -> list[str]:
denylist = load_json(root / "manifests/artifact-denylist.json")
for entry in denylist.get("entries", []):
if (
entry.get("sha256")
== "4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
and entry.get("status") == "BLOCKED"
and entry.get("permanent") is True
and entry.get("execution_eligible") is False
):
return []
return ["permanent blocked artifact is missing from the denylist"]
def validate_repository_boundary(root: Path) -> list[str]:
errors: list[str] = []
cmake = (root / "CMakeLists.txt").read_text(encoding="utf-8")
forbidden_cmake = (
"CHIMERA_GFX_BUILD_PS5_OBSERVER",
"chimera-gfx-bounded-observer",
"phase09b-observer.elf",
)
for value in forbidden_cmake:
if value in cmake:
errors.append(f"blocked observer target found in CMake: {value}")
forbidden_paths = (
root / "samples/phase09b_observer",
root / "samples/bounded_observer",
root / "src/observer",
root / "packaging/phase09b/observer.elf",
)
for path in forbidden_paths:
if path.exists():
errors.append(f"blocked observer source/artifact path exists: {path}")
for base in (root / "samples", root / "src", root / "packaging"):
for path in base.rglob("*"):
if not path.is_file():
continue
lowered = path.as_posix().lower()
if path.suffix.lower() in {".c", ".cc", ".cpp", ".s", ".asm"} and (
"phase09b" in lowered or "bounded_observer" in lowered
):
errors.append(f"blocked observer target source exists: {path}")
if path.suffix.lower() in {".elf", ".self", ".sprx", ".pkg", ".map"} and (
"phase09b" in lowered or "observer" in lowered
):
errors.append(f"blocked observer target artifact exists: {path}")
try:
tracked = git_output(root, "ls-files").splitlines()
except (OSError, subprocess.CalledProcessError) as exc:
return [f"could not inspect tracked files: {exc}"]
for relative in tracked:
lowered = relative.lower()
if "phase09b" in lowered or "phase-0.9b" in lowered:
if lowered.endswith((".elf", ".self", ".sprx", ".pkg", ".map")):
errors.append(f"tracked Phase-0.9B target artifact exists: {relative}")
if "phase09b" in lowered and (
"install" in lowered or "lifecycle-package" in lowered
):
errors.append(f"Phase-0.9B install/lifecycle package exists: {relative}")
return errors
def validate_review_checksums(root: Path) -> list[str]:
errors: list[str] = []
expected_paths = {
"docs/approvals/phase-0.9b-observer-execution-template.md",
"docs/runtime/phase-0.9b-bounded-observer-design.md",
"docs/runtime/phase-0.9b-observer-limitations.md",
"docs/runtime/phase-0.9b-observer-result-contract.md",
"docs/runtime/phase-0.9b-observer-static-audit.md",
"manifests/runtime/phase-0.9b-observation-plan.schema.json",
"manifests/runtime/phase-0.9b-observer.json",
"tests/phase09b_observer_model.py",
"tests/test_phase09b_observer_audit.py",
"tools/validate_phase09b_observer_audit.py",
}
checksum_path = root / "packaging/phase09b/SHA256SUMS.txt"
observed: set[str] = set()
for line_number, line in enumerate(
checksum_path.read_text(encoding="utf-8").splitlines(), start=1
):
match = re.fullmatch(r"([0-9a-f]{64}) ([^\r\n]+)", line)
if not match:
errors.append(f"invalid checksum line {line_number}")
continue
expected_digest, relative = match.groups()
if relative in observed:
errors.append(f"duplicate checksum path: {relative}")
continue
observed.add(relative)
path = root / relative
if not path.is_file():
errors.append(f"checksummed file missing: {relative}")
elif sha256_file(path) != expected_digest:
errors.append(f"review checksum mismatch: {relative}")
if observed != expected_paths:
errors.append("Phase-0.9B review checksum inventory is incomplete or expanded")
return errors
def collect_errors(root: Path, require_source_trees: bool = True) -> list[str]:
errors: list[str] = []
manifest_path = root / "manifests/runtime/phase-0.9b-observer.json"
schema_path = root / "manifests/runtime/phase-0.9b-observation-plan.schema.json"
required = [
manifest_path,
schema_path,
root / "docs/runtime/phase-0.9b-bounded-observer-design.md",
root / "docs/runtime/phase-0.9b-observer-static-audit.md",
root / "docs/runtime/phase-0.9b-observer-result-contract.md",
root / "docs/runtime/phase-0.9b-observer-limitations.md",
root / "docs/approvals/phase-0.9b-observer-execution-template.md",
root / "tests/phase09b_observer_model.py",
root / "tests/test_phase09b_observer_audit.py",
root / "packaging/phase09b/SHA256SUMS.txt",
]
for path in required:
if not path.is_file():
errors.append(f"required Phase-0.9B file missing: {path}")
if errors:
return errors
manifest = load_json(manifest_path)
schema = load_json(schema_path)
errors.extend(validate_manifest(root, manifest))
if not require_source_trees:
errors = [
error
for error in errors
if not error.startswith(("source tree missing:", "source tree unreadable:"))
]
errors.extend(validate_schema(schema, manifest))
errors.extend(validate_denylist(root))
errors.extend(validate_repository_boundary(root))
errors.extend(validate_review_checksums(root))
template = extract_json_contract(
root / "docs/approvals/phase-0.9b-observer-execution-template.md",
"PHASE09B_OBSERVER_EXECUTION_TEMPLATE",
)
errors.extend(validate_authorizations(template, "execution_template"))
if template.get("status") != "BLOCKED":
errors.append("execution template must remain BLOCKED")
required_fields = template.get("required_fields", {})
if any(value is not None for value in required_fields.values()):
errors.append("execution template contains prefilled request-specific values")
for relative in (
"docs/runtime/phase-0.9b-bounded-observer-design.md",
"docs/runtime/phase-0.9b-observer-limitations.md",
):
text = (root / relative).read_text(encoding="utf-8")
normalized_text = re.sub(r"[^A-Z0-9]+", " ", text.upper()).strip()
for decision in EXPECTED_DECISION:
if decision.replace("_", " ") not in normalized_text:
errors.append(f"{relative} does not state blocker {decision}")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument(
"--no-source-tree-check",
action="store_true",
help="Skip only missing external source-tree errors for packaged review.",
)
args = parser.parse_args()
root = args.root.resolve()
errors = collect_errors(root, require_source_trees=not args.no_source_tree_check)
if errors:
for error in errors:
print(f"ERROR: {error}", file=sys.stderr)
return 1
print("Phase-0.9B blocked observer audit: PASS")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+687
View File
@@ -0,0 +1,687 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the blocked, host-only Phase-0.9C feasibility closure."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess
from typing import Any
EXPECTED_CLASSIFICATION = "BLOCKED_MULTIPLE_FOUNDATIONAL_CONTRACTS"
EXPECTED_BASELINE = "3ddc213ea67bb286256ae42e52c65e00488608ca"
EXPECTED_BRANCH = "codex/chimera-gfx-phase09c-execution-feasibility"
BLOCKED_HASH = (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
)
AUTHORIZATION_FIELDS = (
"authorized",
"transfer_authorized",
"execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"backup_creation_authorized",
"observer_build_authorized",
"automatic_retry",
)
SOURCE_COMMITS = {
"hardened_elfldr": (
"../chimera-elfldr",
"197623058f509eddde18868dafcb92fdcac66464",
),
"controlled_payload_manager": (
"../chimera-ps5-payload-manager",
"e23d94ff91233aa770e2342800c1467875bdef44",
),
"elfldr_public_base": (
"work/upstream/elfldr-v0.23",
"699e8bcff03e91e8d6ca6eba281af25c5a58d8c2",
),
"payload_manager_public_base": (
"work/upstream/pldmgr-v0.3.1",
"cfbc70f30f419b09bf2b52283f7409e2d3117ee1",
),
"ps5_payload_sdk_v0_41": (
"work/upstream/sdk",
"d2e2e585740362976a39fdd5ccf390f199a7bc37",
),
}
SOURCE_HASHES = {
"../chimera-elfldr/elfldr.c": (
"9949f8e4037984d10f1f5aa498e4665593d1fac8a33614d7f2141349839bb803"
),
"../chimera-elfldr/socksrv.c": (
"d642ced3e9b4a296dd15e355050ebe956f53a6dfdaa6ac10109cd067a3bba3d7"
),
"../chimera-elfldr/controlled_runtime.c": (
"10145f3bbb3b54e3d715b1667e45c6f12d3c7f52a04342ab104ec8dd49e384c9"
),
"../chimera-elfldr/ps5_controlled.c": (
"68717ef1cc31c483743c5af325c59e73a90f66e93b880b989e349a4ddc748772"
),
"../chimera-ps5-payload-manager/src/verified_launcher.c": (
"066100ca4917c7acc560e2e85666ca136cd7ccfd9094417377048f41106dd56e"
),
"../chimera-ps5-payload-manager/src/ps5_launcher.c": (
"29c1a5fd01784a59e88b3698940f120cb03020071bc2b7d74a1da1a51524ef59"
),
"work/upstream/sdk/crt/crt.c": (
"3875f4739ec40b33f1f4967a1acbb585a527d2c281a360153e1f69c8b945932a"
),
"work/upstream/sdk/crt/patch.c": (
"4f76a677bba54f4641e1cf2755768c29afb7464a35b2f21e85db2aa2785eceac"
),
"work/upstream/sdk/crt/Makefile": (
"6a62f777f32ab05cbe7bff81c00cfd6639ba8bf440aba611a40ff0b62732568b"
),
"work/upstream/sdk/host/bin/prospero-clang": (
"0cf49ae43d6110a7606c0ee4d702fc4b5d5e1c3ae9a722945a48b80294e295ba"
),
"work/upstream/sdk/host/elf_x86_64.x": (
"169b80d01da601ef96bbc584986608dec1d9c01397eae81eccd4e1a66b0a6c6a"
),
"work/upstream/sdk/crt/kernel.c": (
"ac1c375aae8d3cb1be5fb8bad2f4e6492b6ec1f1450977b534202f46b5b70321"
),
"work/upstream/sdk/sce_stubs/libkernel_web.c": (
"dca70757a0680ede52502fe7db10060fe30506f7ed0adfc43ce00700145ab4ff"
),
"samples/lifecycle_probe/main.c": (
"1ae7df1fe921ccab2a252f77975d3d441ef7725e34535b024580c0d4a242d766"
),
}
IMMUTABLE_HASHES = {
"docs/runtime/phase-0.8-read-only-preflight.md": (
"3fbe086175a6048176075f447ec1482074928e3b5282db97ea2169395fe1d508"
),
"manifests/runtime/phase-0.8-read-only-preflight.json": (
"47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322"
),
"tests/test_phase08_preflight.py": (
"8a4ad7c70de28ffe3148fd3fd1f68c36a872c53c691c9068e1ff163970863c48"
),
"manifests/runtime/phase-0.9-anti-brick-design.json": (
"39fd7c70cae998d9d74e7caf1ff3c19f9f76f7de2e5a50bc09baede4ba53e9e9"
),
"manifests/runtime/phase-0.9b-observer.json": (
"104c4a667ad17f9827fc7276852c6faeef96effb8e3561a5ebc19a62c7d51634"
),
"manifests/runtime/phase-0.9b-observation-plan.schema.json": (
"efcea3b0001ef5b2da65c372ceb93ee2fec09c9331b2e4cbb6008212504c0918"
),
}
CHECKSUM_FILES = (
"docs/runtime/phase-0.9c-capability-closure.md",
"docs/runtime/phase-0.9c-output-channel-feasibility.md",
"docs/runtime/phase-0.9c-side-effect-model.md",
"docs/runtime/phase-0.9c-startup-exit-feasibility.md",
"docs/runtime/phase-0.9c-static-audit.md",
"manifests/runtime/phase-0.9c-feasibility.json",
"manifests/runtime/phase-0.9c-feasibility.schema.json",
"tests/phase09c_feasibility_model.py",
"tests/test_phase09c_feasibility.py",
"tests/test_phase09c_protocol.py",
"tools/validate_phase09c_feasibility.py",
)
CAPABILITIES = {
"runtime_self_identity",
"firmware_source_1",
"firmware_source_2",
"mount_query",
"metadata",
"object_id",
"size",
"sha256",
"processes",
"services",
"listeners",
"autoload",
"rollback_objects",
"monotonic_time",
"startup",
"output",
"normal_exit",
"error_exit",
"timeout",
"cleanup",
"recovery_independence",
}
OUTPUT_ARCHITECTURES = (
(
"D1_CALLER_OWNED_BOUNDED_BUFFER",
"CONCEPT_FEASIBLE_REQUIRES_LOADER_CHANGE_AND_EXIT_PROOF",
),
("D2_EXISTING_REQUEST_RESPONSE", "REJECTED_SEND_ONLY_NO_RESULT_RECEIVE"),
(
"D3_LOADER_OWNED_STATUS_RECORD",
"UNPROVEN_REQUIRES_LOADER_STATE_AND_PROPAGATION_CHANGE",
),
(
"D4_PROCESS_EXIT_STATUS",
"REJECTED_WAIT_STATUS_DISCARDED_AND_AMBIGUOUS",
),
)
FORBIDDEN_PHASE09C_SUFFIXES = {
".c",
".cc",
".cpp",
".cxx",
".s",
".asm",
".o",
".obj",
".elf",
".self",
".sprx",
".map",
".pkg",
".zip",
".tar",
".gz",
}
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as handle:
value = json.load(handle)
if not isinstance(value, dict):
raise ValueError(f"{path} must contain a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def git_output(root: Path, *args: str) -> str:
return subprocess.check_output(
["git", *args], cwd=root, text=True, encoding="utf-8"
).strip()
def _json_type_matches(expected: str, value: Any) -> bool:
if expected == "object":
return isinstance(value, dict)
if expected == "array":
return isinstance(value, list)
if expected == "string":
return isinstance(value, str)
if expected == "integer":
return isinstance(value, int) and not isinstance(value, bool)
if expected == "boolean":
return isinstance(value, bool)
if expected == "null":
return value is None
return True
def validate_schema_instance(
schema: dict[str, Any], value: Any, path: str = "$"
) -> list[str]:
"""Validate the JSON-Schema features used by the Phase-0.9C schema."""
errors: list[str] = []
if "const" in schema and value != schema["const"]:
errors.append(f"{path} differs from schema const")
return errors
expected_type = schema.get("type")
if isinstance(expected_type, str) and not _json_type_matches(expected_type, value):
errors.append(f"{path} is not {expected_type}")
return errors
if isinstance(value, dict):
required = schema.get("required", [])
for key in required:
if key not in value:
errors.append(f"{path}.{key} is required")
properties = schema.get("properties", {})
if schema.get("additionalProperties") is False:
for key in value:
if key not in properties:
errors.append(f"{path}.{key} is not allowed")
for key, child_schema in properties.items():
if key in value:
errors.extend(
validate_schema_instance(child_schema, value[key], f"{path}.{key}")
)
if isinstance(value, list):
minimum = schema.get("minItems")
maximum = schema.get("maxItems")
if isinstance(minimum, int) and len(value) < minimum:
errors.append(f"{path} has fewer than {minimum} items")
if isinstance(maximum, int) and len(value) > maximum:
errors.append(f"{path} has more than {maximum} items")
if schema.get("uniqueItems") is True:
normalized = [json.dumps(item, sort_keys=True) for item in value]
if len(normalized) != len(set(normalized)):
errors.append(f"{path} contains duplicate items")
item_schema = schema.get("items")
if isinstance(item_schema, dict):
for index, item in enumerate(value):
errors.extend(
validate_schema_instance(item_schema, item, f"{path}[{index}]")
)
return errors
def validate_authorizations(value: dict[str, Any]) -> list[str]:
errors: list[str] = []
for field in AUTHORIZATION_FIELDS:
if value.get(field) is not False:
errors.append(f"authorization.{field} must be false")
return errors
def validate_manifest(manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
if manifest.get("schema_version") != 1 or manifest.get("phase") != "0.9C":
errors.append("Phase-0.9C manifest identity changed")
if manifest.get("status") != "BLOCKED":
errors.append("Phase-0.9C status must remain BLOCKED")
if manifest.get("classification") != EXPECTED_CLASSIFICATION:
errors.append("Phase-0.9C classification changed")
if manifest.get("baseline_commit") != EXPECTED_BASELINE:
errors.append("Phase-0.9C baseline changed")
if manifest.get("branch") != EXPECTED_BRANCH:
errors.append("Phase-0.9C branch changed")
errors.extend(validate_authorizations(manifest.get("authorization", {})))
canonical = manifest.get("canonical_state_preserved", {})
expected_canonical = {
"historical_phase08_status": "READ_ONLY_PREFLIGHT_BLOCKED",
"phase09a_status": "DESIGN_ONLY",
"phase09b_status": "BLOCKED",
"firmware_runtime_behavior": "UNPROVEN",
"stock_hashes": "reference_only",
"payload_manager_backup": "HARD_BLOCKER",
"device_contact_performed": False,
"device_transfer_performed": False,
"device_execution_performed": False,
"target_build_performed": False,
}
if canonical != expected_canonical:
errors.append("canonical Phase-0.8/0.9 state changed")
deny = manifest.get("permanent_denylist_binding", {})
if deny != {
"sha256": BLOCKED_HASH,
"status": "BLOCKED",
"permanent": True,
"execution_eligible": False,
}:
errors.append("permanent artifact denial changed")
source_commits = manifest.get("source_commits", {})
for key, (_, expected_commit) in SOURCE_COMMITS.items():
if source_commits.get(key) != expected_commit:
errors.append(f"source commit changed: {key}")
if source_commits.get("lifecycle_probe_source") != (
"fe08300339a13f899fb78ea404ada381a5cba87c"
):
errors.append("lifecycle source commit changed")
if manifest.get("source_tree_status") != {
key: "clean" for key in SOURCE_COMMITS
}:
errors.append("source tree status record changed")
evidence = {
item.get("path"): item.get("sha256")
for item in manifest.get("source_evidence", [])
if isinstance(item, dict)
}
if evidence != SOURCE_HASHES:
errors.append("source evidence path/hash inventory changed")
immutable = manifest.get("immutable_evidence", {})
if immutable.get("phase08", {}).get("files") != {
key: IMMUTABLE_HASHES[key]
for key in (
"docs/runtime/phase-0.8-read-only-preflight.md",
"manifests/runtime/phase-0.8-read-only-preflight.json",
"tests/test_phase08_preflight.py",
)
}:
errors.append("Phase-0.8 immutable manifest bindings changed")
if immutable.get("phase09a_manifest_sha256") != IMMUTABLE_HASHES[
"manifests/runtime/phase-0.9-anti-brick-design.json"
]:
errors.append("Phase-0.9A manifest binding changed")
if immutable.get("phase09b_manifest_sha256") != IMMUTABLE_HASHES[
"manifests/runtime/phase-0.9b-observer.json"
]:
errors.append("Phase-0.9B manifest binding changed")
if immutable.get("phase09b_schema_sha256") != IMMUTABLE_HASHES[
"manifests/runtime/phase-0.9b-observation-plan.schema.json"
]:
errors.append("Phase-0.9B schema binding changed")
startup = manifest.get("startup_exit", {})
false_startup_fields = (
"normal_sdk_kernelwrite_free",
"freestanding_dependency_closure_proven",
"stack_alignment_proven",
"complete_relocation_and_bss_tls_contract_proven",
"callable_read_and_time_abi_proven",
"safe_return_proven",
"safe_process_exit_proven",
"error_exit_proven",
"timeout_safe_exit_proven",
"complete_cleanup_proven",
)
for field in false_startup_fields:
if startup.get(field) is not False:
errors.append(f"startup_exit.{field} must be false")
if startup.get("normal_sdk_status") != "PROVEN_SIDE_EFFECTING":
errors.append("normal SDK startup side effects were hidden")
if not startup.get("blockers"):
errors.append("startup/exit blockers are absent")
architectures = manifest.get("output_architectures", [])
observed_architectures = tuple(
(item.get("id"), item.get("status"))
for item in architectures
if isinstance(item, dict)
)
if observed_architectures != OUTPUT_ARCHITECTURES:
errors.append("output architecture decisions changed or reordered")
if any(item.get("current_implementation") is not False for item in architectures):
errors.append("an output architecture claims current implementation")
protocol = manifest.get("host_protocol", {})
expected_protocol = {
"model": "tests/phase09c_feasibility_model.py",
"host_only": True,
"target_implemented": False,
"magic": "CHG09C01",
"version": 1,
"header_size": 256,
"maximum_output_size": 4096,
"maximum_body_size": 3840,
"integer_encoding": "unsigned_big_endian",
"execution_nonce_bytes": 16,
"request_id_bytes": 16,
"firmware_field_bytes": 8,
"artifact_hash_algorithm": "sha256",
"body_checksum_algorithm": "sha256",
"result_checksum_algorithm": "sha256",
"completion_marker": "COMPLETE",
"pointers_present": False,
"dynamic_growth": False,
}
for field, expected in expected_protocol.items():
if protocol.get(field) != expected:
errors.append(f"host protocol field changed: {field}")
if len(protocol.get("required_fields", [])) < 16:
errors.append("host protocol required fields are incomplete")
if len(protocol.get("fail_closed_conditions", [])) < 10:
errors.append("host protocol fail-closed cases are incomplete")
firmware = manifest.get("firmware", {})
source_two = firmware.get("source_two", {})
if firmware.get("expected") != "9.60":
errors.append("exact firmware gate changed")
if source_two != {
"identity": None,
"status": "ABSENT",
"export_name_candidate_accepted": False,
"nonce_bound_runtime_result_present": False,
}:
errors.append("firmware source two was fabricated or promoted")
if firmware.get("agreement_proven") is not False:
errors.append("firmware agreement was claimed")
if firmware.get("gate") != "BLOCKED_FIRMWARE_SOURCE_INCOMPLETE":
errors.append("firmware gate was promoted")
side_effects = manifest.get("side_effect_model", {})
for field in (
"no_persistent_content_write_is_side_effect_free",
"read_only_flag_is_side_effect_free",
"all_planned_observations_proven_side_effect_free",
):
if side_effects.get(field) is not False:
errors.append(f"side-effect claim must remain false: {field}")
if side_effects.get("gate") != "BLOCKED_OBSERVATION_SIDE_EFFECTS_UNBOUNDED":
errors.append("side-effect gate changed")
required_dimensions = {
"content",
"metadata",
"atime",
"audit",
"cache",
"counters",
"service_state",
"security_monitoring",
"open_bookkeeping",
"process_accounting",
"object_lifetime",
"races",
}
if set(side_effects.get("dimensions", [])) != required_dimensions:
errors.append("side-effect dimensions are incomplete")
capabilities = manifest.get("capability_closure", [])
if {item.get("id") for item in capabilities if isinstance(item, dict)} != CAPABILITIES:
errors.append("capability closure inventory changed")
for item in capabilities:
if not isinstance(item, dict):
errors.append("capability entry is not an object")
continue
if item.get("implementation_allowed") is not False:
errors.append(f"capability implementation enabled: {item.get('id')}")
if item.get("execution_allowed") is not False:
errors.append(f"capability execution enabled: {item.get('id')}")
if item.get("target_evidence") in (None, "", "PROVEN"):
errors.append(f"capability target evidence invalid: {item.get('id')}")
if not item.get("blocker"):
errors.append(f"capability blocker absent: {item.get('id')}")
implementation = manifest.get("implementation", {})
if not implementation or any(value is not False for value in implementation.values()):
errors.append("target/runtime implementation state must be entirely false")
if manifest.get("artifact") != {
"present": False,
"path": None,
"sha256": None,
"size": None,
"execution_eligible": False,
"execution_authorized": False,
}:
errors.append("Phase-0.9C artifact must not exist")
static = manifest.get("static_audit", {})
if static.get("status") != "NOT_APPLICABLE_NO_TARGET_SOURCE_OR_ARTIFACT":
errors.append("static target audit was falsely promoted")
if static.get("host_model_only") is not True:
errors.append("static audit is not explicitly host-only")
decision = manifest.get("final_decision", {})
if decision.get("positive_classification_allowed") is not False:
errors.append("positive classification was enabled")
if decision.get("classification") != EXPECTED_CLASSIFICATION:
errors.append("final decision differs from top-level classification")
expected_blockers = {
"BLOCKED_STARTUP_ABI_UNPROVEN",
"BLOCKED_EXIT_CLEANUP_UNPROVEN",
"BLOCKED_NO_BOUNDED_OUTPUT_CHANNEL",
"BLOCKED_FIRMWARE_SOURCE_INCOMPLETE",
"BLOCKED_OBSERVATION_SIDE_EFFECTS_UNBOUNDED",
}
if set(decision.get("foundational_blockers", [])) != expected_blockers:
errors.append("foundational blocker set changed")
if decision.get("next_phase_automatic") is not False:
errors.append("automatic next phase was enabled")
return errors
def validate_source_trees(root: Path) -> list[str]:
errors: list[str] = []
for key, (relative, expected_commit) in SOURCE_COMMITS.items():
source_root = (root / relative).resolve()
if not source_root.is_dir():
errors.append(f"source tree missing: {key}")
continue
try:
commit = git_output(source_root, "rev-parse", "HEAD")
status = git_output(source_root, "status", "--short")
except subprocess.CalledProcessError:
errors.append(f"source tree is not readable Git: {key}")
continue
if commit != expected_commit:
errors.append(f"source tree commit mismatch: {key}")
if status:
errors.append(f"source tree is dirty: {key}")
for relative, expected_hash in SOURCE_HASHES.items():
path = (root / relative).resolve()
if not path.is_file():
errors.append(f"source evidence missing: {relative}")
elif sha256_file(path) != expected_hash:
errors.append(f"source evidence hash mismatch: {relative}")
return errors
def validate_immutable_evidence(root: Path) -> list[str]:
errors: list[str] = []
for relative, expected_hash in IMMUTABLE_HASHES.items():
path = root / relative
if not path.is_file():
errors.append(f"immutable evidence missing: {relative}")
elif sha256_file(path) != expected_hash:
errors.append(f"immutable evidence changed: {relative}")
return errors
def forbidden_repository_path(relative: str) -> bool:
normalized = relative.replace("\\", "/").lower()
path = Path(normalized)
phase_marker = "phase09c" in normalized or "phase-0.9c" in normalized
if phase_marker and path.suffix in FORBIDDEN_PHASE09C_SUFFIXES:
return True
if normalized.startswith(
(
"samples/phase09c",
"samples/phase-0.9c",
"src/backends/ps5/phase09c",
"src/backends/ps5/observer",
)
):
return True
if normalized.startswith("packaging/phase09c/"):
return normalized != "packaging/phase09c/sha256sums.txt"
return False
def validate_repository_boundary(root: Path) -> list[str]:
errors: list[str] = []
listed = git_output(
root, "ls-files", "--cached", "--others", "--exclude-standard"
).splitlines()
for relative in listed:
if forbidden_repository_path(relative):
errors.append(f"forbidden Phase-0.9C target/package path: {relative}")
cmake = (root / "CMakeLists.txt").read_text(encoding="utf-8")
if re.search(
r"add_(?:executable|library)\s*\([^)]*phase[-_]?0?9c",
cmake,
flags=re.IGNORECASE | re.DOTALL,
):
errors.append("CMake declares a Phase-0.9C target")
forbidden_directories = (
root / "samples/phase09c_observer",
root / "samples/phase-0.9c-observer",
root / "packaging/phase09c/lifecycle",
root / "packaging/phase09c/install",
root / "packaging/phase09c/autoload",
)
for path in forbidden_directories:
if path.exists():
errors.append(f"forbidden Phase-0.9C path exists: {path.relative_to(root)}")
return errors
def validate_checksums(root: Path) -> list[str]:
errors: list[str] = []
checksum_path = root / "packaging/phase09c/SHA256SUMS.txt"
if not checksum_path.is_file():
return ["Phase-0.9C checksum file is missing"]
observed: dict[str, str] = {}
for line in checksum_path.read_text(encoding="utf-8").splitlines():
parts = line.split(" ", 1)
if len(parts) != 2 or not re.fullmatch(r"[0-9a-f]{64}", parts[0]):
errors.append("malformed Phase-0.9C checksum line")
continue
observed[parts[1]] = parts[0]
if tuple(observed) != CHECKSUM_FILES:
errors.append("Phase-0.9C checksum inventory or order changed")
for relative in CHECKSUM_FILES:
path = root / relative
if not path.is_file():
errors.append(f"Phase-0.9C checksummed file missing: {relative}")
elif observed.get(relative) != sha256_file(path):
errors.append(f"Phase-0.9C checksum mismatch: {relative}")
return errors
def collect_errors(root: Path) -> list[str]:
manifest_path = root / "manifests/runtime/phase-0.9c-feasibility.json"
schema_path = root / "manifests/runtime/phase-0.9c-feasibility.schema.json"
manifest = load_json(manifest_path)
schema = load_json(schema_path)
errors = validate_manifest(manifest)
errors.extend(validate_schema_instance(schema, manifest))
errors.extend(validate_source_trees(root))
errors.extend(validate_immutable_evidence(root))
errors.extend(validate_repository_boundary(root))
errors.extend(validate_checksums(root))
denylist = load_json(root / "manifests/artifact-denylist.json")
entries = denylist.get("entries", [])
if (
len(entries) != 1
or entries[0].get("sha256") != BLOCKED_HASH
or entries[0].get("status") != "BLOCKED"
or entries[0].get("permanent") is not True
or entries[0].get("execution_eligible") is not False
):
errors.append("permanent denylist no longer blocks the legacy artifact")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
errors = collect_errors(root)
if errors:
for error in errors:
print(f"Phase-0.9C validation failed: {error}")
return 1
print(
"Phase-0.9C feasibility manifest, schema, sources, immutable evidence, "
"denylist, checksums, and no-target boundary: PASS"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+759
View File
@@ -0,0 +1,759 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the offline-only Phase-0.9D readback and recovery audit."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
from typing import Any
EXPECTED_BASELINE = "e0e68829ab76977c845e7106ef93e6c01fbc966e"
EXPECTED_BRANCH = "codex/chimera-gfx-phase09d-existing-stack-readback"
EXPECTED_PHASE = "PHASE_0_9D_EXISTING_STACK_READBACK"
EXPECTED_STATUS = "DESIGN_ONLY"
BLOCKED_HASH = (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
)
DENYLIST_HASH = (
"e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
)
AUTHORIZATION_FIELDS = (
"installation_authorized",
"execution_authorized",
"lifecycle_authorized",
"automatic_retry",
"autoload_authorized",
"device_write_authorized",
"transfer_authorized",
"observer_build_authorized",
"backup_creation_authorized",
)
ACTION_FIELDS = (
"ps5_connected",
"device_request_performed",
"files_transferred",
"device_write_performed",
"target_execution_performed",
"target_artifact_created",
"target_build_performed",
"observer_created",
"device_client_created",
"backup_created",
"staging_performed",
)
SOURCE_COMMITS = {
"hardened_elfldr": (
"../chimera-elfldr",
"197623058f509eddde18868dafcb92fdcac66464",
),
"controlled_payload_manager": (
"../chimera-ps5-payload-manager",
"e23d94ff91233aa770e2342800c1467875bdef44",
),
"elfldr_public_base": (
"work/upstream/elfldr-v0.23",
"699e8bcff03e91e8d6ca6eba281af25c5a58d8c2",
),
"payload_manager_public_base": (
"work/upstream/pldmgr-v0.3.1",
"cfbc70f30f419b09bf2b52283f7409e2d3117ee1",
),
"ps5_payload_sdk_v0_41": (
"work/upstream/sdk",
"d2e2e585740362976a39fdd5ccf390f199a7bc37",
),
}
SOURCE_HASHES = {
"../chimera-elfldr/README.md": (
"372aeb28dc971b2bd98093a47fdaf77c32f75bbdc3b3d7e8678900744b91eadb"
),
"../chimera-elfldr/main.c": (
"876389a26999073994e63ca29926982280d9594a1ee941244205b54f57e2b4d1"
),
"../chimera-elfldr/bootstrap.c": (
"5a8072ec0d6db919cb3a81a7028dc91fd8e2c3a0d69b0fa7e84836fa93b45381"
),
"../chimera-elfldr/socksrv.c": (
"d642ced3e9b4a296dd15e355050ebe956f53a6dfdaa6ac10109cd067a3bba3d7"
),
"../chimera-ps5-payload-manager/README.md": (
"a00277252da46c701326ef66e5ca0d13cadffd50b3c8adf6da89cd1948c97718"
),
"../chimera-ps5-payload-manager/DEVELOPMENT.md": (
"0c17bed71b07c9aadf31c47625bbe1ccb42e670e594fb64a1e07aa782d5eec31"
),
"../chimera-ps5-payload-manager/deploy.sh": (
"2facdc1ca70db57ba258265c07a8ae1d30d3d2fb429d6718d5d5088300788e52"
),
"../chimera-ps5-payload-manager/include/pldmgr.h": (
"8603b8338364cea60ffaf94f985f112fb2ddfda2f44b1ccc9a2bd7a15d1b229a"
),
"../chimera-ps5-payload-manager/src/http_server.c": (
"2c8ff2a4bc1028d71e3cc342839584d425b6e7502e55e18e2762cdbf62c59d40"
),
"../chimera-ps5-payload-manager/src/log_server.c": (
"659095f43df1bbe8eb24acb165f027edc277af1e60aabb26ba9e3920b233d6f1"
),
"../chimera-ps5-payload-manager/src/autoload.c": (
"7051cab3ee1a3e0b9f6498000565eb9e160b9c63efa1771f250e98ec3aa4ae67"
),
"../chimera-ps5-payload-manager/src/main.c": (
"b2374e8fb101587b15c8261c58cb4f0573d88c490214365051eb9facd60f6eed"
),
"../chimera-ps5-payload-manager/src/controlled_manager.c": (
"042b55b2cece32effed636529249fd18061a2fe3c5e70c7f755f2817cfb84b99"
),
"../chimera-ps5-payload-manager/src/verified_launcher.c": (
"066100ca4917c7acc560e2e85666ca136cd7ccfd9094417377048f41106dd56e"
),
"../chimera-ps5-payload-manager/src/ps5_launcher.c": (
"29c1a5fd01784a59e88b3698940f120cb03020071bc2b7d74a1da1a51524ef59"
),
"../chimera-ps5-payload-manager/src/payload_mgr.c": (
"d67e9ba33edc8ca3a45aae07923d4c4790348b5f8570307e581e16780abafcba"
),
"../chimera-ps5-payload-manager/src/repository.c": (
"8ba694ae6d4813573752acd82ce2dbfb715b51d4ec6155f783904d76dd115adb"
),
"../chimera-ps5-payload-manager/src/sources.c": (
"a7a4a5cafccfba74902d6ed21ba001e6a9f62d4dff840ac38882d04827162c96"
),
"work/upstream/elfldr-v0.23/socksrv.c": (
"500d3c7df7ed5eac1adc925c89344d75c469651b71143716fdb77bfb2209a40c"
),
"work/upstream/pldmgr-v0.3.1/include/pldmgr.h": (
"01c693a3248dce7a663dd4ed9c73ce5f3a4443b5f2bd210746d94993dee27b91"
),
"work/upstream/pldmgr-v0.3.1/src/http_server.c": (
"35cf5d8f0dd44cf64ceab5e4b0ecc09413c82d7e9946ba9de2ca4b1898631fdd"
),
"samples/lifecycle_probe/main.c": (
"1ae7df1fe921ccab2a252f77975d3d441ef7725e34535b024580c0d4a242d766"
),
}
IMMUTABLE_HASHES = {
"manifests/runtime/phase-0.8-read-only-preflight.json": (
"47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322"
),
"manifests/runtime/phase-0.8-remediation.json": (
"a9dafed8c83722c43709dcf90ea117c21d6f996ff8fe233810ed08aa20cbe071"
),
"manifests/runtime/phase-0.9-anti-brick-design.json": (
"39fd7c70cae998d9d74e7caf1ff3c19f9f76f7de2e5a50bc09baede4ba53e9e9"
),
"manifests/runtime/phase-0.9b-observer.json": (
"104c4a667ad17f9827fc7276852c6faeef96effb8e3561a5ebc19a62c7d51634"
),
"manifests/runtime/phase-0.9c-feasibility.json": (
"84eb737ff3486d0c5d8b5ecf06809f93bc573497da4919595b4c1817fd34247c"
),
}
DELIVERABLES = (
"docs/runtime/phase-0.9d-bootstrap-recovery-chain.md",
"docs/runtime/phase-0.9d-existing-stack-endpoint-matrix.md",
"docs/runtime/phase-0.9d-readback-feasibility.md",
"docs/runtime/phase-0.9d-off-device-backup-contract.md",
"docs/runtime/phase-0.9d-independent-recovery-analysis.md",
"docs/runtime/phase-0.9d-operational-windows.md",
"manifests/runtime/phase-0.9d-existing-stack-readback.json",
"manifests/runtime/phase-0.9d-existing-stack-readback.schema.json",
"tools/validate_phase09d_readback.py",
"tests/test_phase09d_readback.py",
)
EXPECTED_DECISIONS = {
"new_observer_feasibility": "BLOCKED",
"existing_stack_manual_fact_collection": "PARTIAL",
"existing_stack_single_readback": "BLOCKED_NO_READBACK_PATH",
"existing_stack_repeat_readback": "BLOCKED",
"elfldr_independent_recovery": "PARTIAL",
"payload_manager_independent_recovery": "PARTIAL",
"side_by_side_feasibility": "BLOCKED",
"device_write": "NOT_AUTHORIZED",
"target_execution": "NOT_AUTHORIZED",
"installation": "NOT_AUTHORIZED",
}
REQUIRED_EFFECTIVE_ROUTE_FIELDS = (
"method",
"endpoint",
"handler",
"source",
"lines",
"parameters",
"authentication",
"response",
"open_flags",
"reads_bytes",
"writes_bytes",
"creates_file",
"removes_file",
"renames_file",
"reads_directory",
"reads_metadata",
"calculates_hash",
"modifies_configuration",
"writes_server_active_flag",
"writes_autoload_triggered",
"writes_log_ring",
"launches_payload",
"process_or_service_action",
"network_behavior",
"timeout_behavior",
"retry_behavior",
"maximum_size",
"short_read_behavior",
"error_behavior",
"effect_class",
"readback_candidate",
"observation_candidate",
"binary_safe_file_response",
"exact_returned_byte_count",
"partial_result_rejected",
"forbidden_reason",
)
BACKUP_STATES = (
"TRANSFER_NOT_STARTED",
"TRANSFER_INCOMPLETE",
"HOST_COPY_RECEIVED",
"HOST_COPY_REOPENED",
"HOST_COPY_HASHED",
"SECOND_COPY_CREATED",
"SECOND_COPY_REOPENED",
"SECOND_COPY_HASHED",
"COPIES_MATCH",
"SOURCE_MAPPING_PARTIAL",
"SOURCE_MAPPING_VERIFIED",
"INVALID",
)
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as stream:
value = json.load(stream)
if not isinstance(value, dict):
raise ValueError(f"{path} does not contain an object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
check=False,
capture_output=True,
text=True,
)
if result.returncode != 0:
raise RuntimeError(result.stderr.strip() or "git command failed")
return result.stdout.strip()
def effective_route(
route: dict[str, Any], defaults: dict[str, Any]
) -> dict[str, Any]:
merged = dict(defaults)
merged.update(route)
return merged
def route_readback_errors(
route: dict[str, Any], defaults: dict[str, Any] | None = None
) -> list[str]:
merged = effective_route(route, defaults or {})
errors: list[str] = []
flags = {str(flag).lower() for flag in merged.get("open_flags", [])}
mutating_open = any(
token in flag
for flag in flags
for token in ("o_wronly", "o_rdwr", "o_creat", "o_append", "wb", "(w)")
)
mutating = any(
bool(merged.get(field))
for field in (
"writes_bytes",
"creates_file",
"removes_file",
"renames_file",
"modifies_configuration",
)
) or mutating_open
if merged.get("readback_candidate"):
if mutating:
errors.append("readback candidate mutates a device file or configuration")
if merged.get("launches_payload"):
errors.append("readback candidate launches a payload")
if merged.get("process_or_service_action"):
errors.append("readback candidate performs a process/service action")
if merged.get("writes_autoload_triggered"):
errors.append("readback candidate writes autoload_triggered")
if not merged.get("binary_safe_file_response"):
errors.append("readback candidate lacks binary-safe framing")
if not merged.get("exact_returned_byte_count"):
errors.append("readback candidate lacks an exact byte count")
if not merged.get("partial_result_rejected"):
errors.append("readback candidate does not reject partial output")
if str(merged.get("short_read_behavior", "")).upper() in {
"",
"ABSENT",
"UNPROVEN",
"NO_HOST_FILE_READBACK_CONTRACT",
"NO_FILE_RESPONSE",
}:
errors.append("readback candidate lacks short-read detection")
if merged.get("automatic_retry") is True:
errors.append("readback candidate enables automatic retry")
if merged.get("automatic_resume") is True:
errors.append("readback candidate enables automatic resume")
return errors
def backup_record_errors(record: dict[str, Any]) -> list[str]:
errors: list[str] = []
status = record.get("status")
if status not in BACKUP_STATES:
errors.append("unknown backup status")
if record.get("automatic_resume"):
errors.append("automatic resume is forbidden")
if record.get("automatic_retry"):
errors.append("automatic retry is forbidden")
if status in {"HOST_COPY_HASHED", "SECOND_COPY_HASHED", "COPIES_MATCH"}:
if not isinstance(record.get("exact_byte_count"), int):
errors.append("a hash requires an exact byte count")
if not record.get("closed_and_reopened"):
errors.append("hash requires close and reopen")
if not record.get("sha256"):
errors.append("hashed state requires SHA-256")
if status == "COPIES_MATCH":
if not all(
record.get(field)
for field in ("sizes_match", "hashes_match", "bytes_match")
):
errors.append("COPIES_MATCH requires size, hash, and byte equality")
if record.get("transfer_complete") is False and status != "INVALID":
errors.append("partial transfer must be INVALID")
if record.get("recovery_proven"):
errors.append("host backup cannot prove recovery")
return errors
def server_active_observation_status(semantics: dict[str, Any]) -> str:
if (
not semantics.get("fully_documented")
or semantics.get("reset_path") in {None, "UNPROVEN"}
):
return "BLOCKED"
if semantics.get("reset_path") == "NONE_IN_PROCESS":
return "PARTIAL"
return "READY_FOR_REVIEW"
def recovery_dependency_classification(
component: str, recovery_executor: str
) -> str:
if component == recovery_executor:
return "SELF_DEPENDENT"
if recovery_executor in {"ABSENT", "UNPROVEN", ""}:
return recovery_executor
return "CROSS_DEPENDENT"
def _type_matches(value: Any, expected: str) -> bool:
return {
"object": isinstance(value, dict),
"array": isinstance(value, list),
"string": isinstance(value, str),
"boolean": isinstance(value, bool),
"integer": isinstance(value, int) and not isinstance(value, bool),
"number": isinstance(value, (int, float)) and not isinstance(value, bool),
"null": value is None,
}.get(expected, True)
def validate_schema_instance(
schema: dict[str, Any], instance: Any, path: str = "$"
) -> list[str]:
"""Small offline validator for the schema features used by this record."""
errors: list[str] = []
expected_type = schema.get("type")
if expected_type and not _type_matches(instance, expected_type):
return [f"{path}: expected {expected_type}"]
if "const" in schema and instance != schema["const"]:
errors.append(f"{path}: expected constant {schema['const']!r}")
if "enum" in schema and instance not in schema["enum"]:
errors.append(f"{path}: value is outside enum")
if isinstance(instance, dict):
required = schema.get("required", [])
for key in required:
if key not in instance:
errors.append(f"{path}: missing {key}")
if len(instance) < schema.get("minProperties", 0):
errors.append(f"{path}: too few properties")
properties = schema.get("properties", {})
for key, value in instance.items():
if key in properties:
errors.extend(
validate_schema_instance(properties[key], value, f"{path}.{key}")
)
elif schema.get("additionalProperties") is False:
errors.append(f"{path}: unexpected property {key}")
elif isinstance(schema.get("additionalProperties"), dict):
errors.extend(
validate_schema_instance(
schema["additionalProperties"], value, f"{path}.{key}"
)
)
if isinstance(instance, list):
if len(instance) < schema.get("minItems", 0):
errors.append(f"{path}: too few items")
if "maxItems" in schema and len(instance) > schema["maxItems"]:
errors.append(f"{path}: too many items")
item_schema = schema.get("items")
if isinstance(item_schema, dict):
for index, item in enumerate(instance):
errors.extend(
validate_schema_instance(item_schema, item, f"{path}[{index}]")
)
return errors
def validate_manifest(manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
if manifest.get("phase") != EXPECTED_PHASE:
errors.append("wrong phase")
if manifest.get("status") != EXPECTED_STATUS:
errors.append("status must remain DESIGN_ONLY")
if manifest.get("baseline_commit") != EXPECTED_BASELINE:
errors.append("wrong baseline")
if manifest.get("branch") != EXPECTED_BRANCH:
errors.append("wrong branch")
for field in AUTHORIZATION_FIELDS:
if manifest.get("authorization", {}).get(field) is not False:
errors.append(f"authorization.{field} must be false")
for field in ACTION_FIELDS:
if manifest.get("actions", {}).get(field) is not False:
errors.append(f"actions.{field} must be false")
canonical = manifest.get("canonical_state", {})
expected_canonical = {
"phase08_status": "READ_ONLY_PREFLIGHT_BLOCKED",
"phase09a_status": "DESIGN_ONLY",
"phase09b_status": "BLOCKED",
"phase09c_classification": "BLOCKED_MULTIPLE_FOUNDATIONAL_CONTRACTS",
"firmware_runtime_behavior": "UNPROVEN",
"stock_identities": "reference_only",
"payload_manager_backup": "HARD_BLOCKER_FOR_INSTALLATION",
"independent_recovery": "UNPROVEN",
"permanent_denylist_sha256": DENYLIST_HASH,
"permanently_blocked_artifact_sha256": BLOCKED_HASH,
}
for field, expected in expected_canonical.items():
if canonical.get(field) != expected:
errors.append(f"canonical_state.{field} changed")
if manifest.get("decisions") != EXPECTED_DECISIONS:
errors.append("decision matrix changed")
if manifest.get("source_commits", {}).get("lifecycle_source") != (
"fe08300339a13f899fb78ea404ada381a5cba87c"
):
errors.append("lifecycle source binding changed")
for name, (_, expected) in SOURCE_COMMITS.items():
if manifest.get("source_commits", {}).get(name) != expected:
errors.append(f"source commit changed: {name}")
if manifest.get("source_tree_status", {}).get(name) != "clean":
errors.append(f"source tree is not recorded clean: {name}")
routes = manifest.get("endpoint_matrix", [])
if len(routes) != 40:
errors.append("endpoint matrix must contain all 40 audited route records")
defaults = manifest.get("endpoint_defaults", {})
identities: set[tuple[str, str]] = set()
for route in routes:
effective = effective_route(route, defaults)
identity = (str(route.get("profile")), str(route.get("endpoint")))
if identity in identities:
errors.append(f"duplicate route identity: {identity}")
identities.add(identity)
for field in REQUIRED_EFFECTIVE_ROUTE_FIELDS:
if field not in effective:
errors.append(f"{identity}: missing effective field {field}")
errors.extend(
f"{identity}: {error}"
for error in route_readback_errors(route, defaults)
)
if effective.get("readback_candidate") is not False:
errors.append(f"{identity}: no audited route may be a readback candidate")
autoload = next(
(
effective_route(route, defaults)
for route in routes
if route.get("profile") == "full"
and route.get("endpoint") == "/autoload_status"
),
None,
)
if not autoload or not autoload.get("writes_autoload_triggered"):
errors.append("/autoload_status mutation is not recorded")
flags = manifest.get("flag_semantics", {})
server_active = flags.get("server_active_flag", {})
if server_active.get("classification") == "ANTI_BRICK_CRITICAL":
errors.append("server_active_flag is incorrectly anti-brick critical")
if (
not server_active.get("fully_documented")
or server_active.get("reset_path") != "NONE_IN_PROCESS"
or server_active.get("lifetime") != "PROCESS_LOCAL"
):
errors.append("server_active_flag semantics are incomplete")
autoload_flag = flags.get("autoload_triggered", {})
if autoload_flag.get("excluded_windows") != [1, 2]:
errors.append("autoload_triggered must be excluded from Windows 1 and 2")
if len(manifest.get("readback_routes", [])) != 7:
errors.append("readback route search is incomplete")
for route in manifest.get("readback_routes", []):
if route.get("usable_once") or route.get("usable_twice"):
errors.append("a rejected readback route is marked usable")
if manifest.get("path_classification") != "PATH_CONFLICT":
errors.append("path conflict was removed")
if manifest.get("runtime_observed_live_paths") != []:
errors.append("offline package/config paths cannot become live paths")
contract = manifest.get("host_backup_contract", {})
if contract.get("statuses") != list(BACKUP_STATES):
errors.append("backup status vocabulary changed")
required_true = (
"one_component_per_session",
"new_exclusive_local_output",
"binary_mode",
"exact_received_byte_count_required",
"close_reopen_before_hash",
"sha256_required",
"size_required",
"second_independent_connection",
"second_new_output",
"compare_size",
"compare_sha256",
"compare_every_byte",
"capture_raw_protocol_metadata",
"capture_literal_source_path",
"capture_device_and_session",
"capture_client_commit",
"off_device_backup_valid_requires_copies_match",
)
for field in required_true:
if contract.get(field) is not True:
errors.append(f"host_backup_contract.{field} must be true")
required_false = (
"overwrite_existing_output",
"automatic_resume",
"automatic_retry",
"contains_device_write_command",
"recovery_proven_allowed",
)
for field in required_false:
if contract.get(field) is not False:
errors.append(f"host_backup_contract.{field} must be false")
if contract.get("partial_transfer_status") != "INVALID":
errors.append("partial host transfer must be INVALID")
recovery = manifest.get("recovery_dependencies", {})
if recovery.get("elfldr", {}).get("classification") != "PARTIAL":
errors.append("elfldr recovery must remain PARTIAL")
manager = recovery.get("payload_manager", {})
if manager.get("classification") != "PARTIAL":
errors.append("Payload Manager recovery must remain PARTIAL")
if "CROSS_DEPENDENT" not in manager.get("detailed", []):
errors.append("Payload Manager cross-dependence is missing")
if manifest.get("side_by_side", {}).get("classification") != "BLOCKED":
errors.append("side-by-side must remain blocked")
if manifest.get("side_by_side", {}).get(
"grants_installation_authorization"
):
errors.append("side-by-side cannot authorize installation")
windows = manifest.get("operational_windows", [])
if [window.get("window") for window in windows] != list(range(1, 8)):
errors.append("operational windows are incomplete or reordered")
for window in windows:
if window.get("device_write") is not False:
errors.append(f"Window {window.get('window')} permits device write")
if window.get("payload_launch") is not False:
errors.append(f"Window {window.get('window')} permits payload launch")
if window.get("autoload_status_route") is not False:
errors.append(f"Window {window.get('window')} permits /autoload_status")
if window.get("automatic_retry") is not False:
errors.append(f"Window {window.get('window')} permits retry")
if windows and windows[0].get("file_transfer") is not False:
errors.append("Window 1 contains file transfer")
if len(windows) >= 3 and windows[2].get("automatic_third_attempt") is not False:
errors.append("Window 3 permits an automatic third attempt")
if len(windows) >= 4 and windows[3].get("component_session_separate") is not True:
errors.append("components do not have separate windows")
final = manifest.get("final_decision", {})
if (
final.get("classification") != "BLOCKED"
or final.get("hardware_evidence_claimed") is not False
or final.get("device_action_authorized") is not False
):
errors.append("final decision must remain an offline-only block")
return errors
def _phase09d_paths(root: Path) -> list[str]:
paths: set[str] = set()
for candidate in git(root, "ls-files").splitlines():
normalized = candidate.replace("\\", "/")
lowered = normalized.lower()
if "phase-0.9d" in lowered or "phase09d" in lowered:
paths.add(normalized)
output = git(root, "status", "--porcelain=v1", "--untracked-files=all")
for line in output.splitlines():
if len(line) < 4:
continue
candidate = line[3:].replace("\\", "/")
if " -> " in candidate:
candidate = candidate.rsplit(" -> ", 1)[1]
lowered = candidate.lower()
if "phase-0.9d" in lowered or "phase09d" in lowered:
paths.add(candidate)
return sorted(paths)
def collect_errors(root: Path) -> list[str]:
errors: list[str] = []
manifest_path = (
root / "manifests/runtime/phase-0.9d-existing-stack-readback.json"
)
schema_path = (
root
/ "manifests/runtime/phase-0.9d-existing-stack-readback.schema.json"
)
try:
manifest = load_json(manifest_path)
schema = load_json(schema_path)
except (OSError, ValueError, json.JSONDecodeError) as error:
return [str(error)]
errors.extend(validate_manifest(manifest))
errors.extend(validate_schema_instance(schema, manifest))
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
for relative, expected in SOURCE_HASHES.items():
path = (root / relative).resolve()
if not path.is_file():
errors.append(f"missing source evidence: {relative}")
elif sha256_file(path) != expected:
errors.append(f"source evidence changed: {relative}")
if manifest.get("source_evidence", {}).get(relative) != expected:
errors.append(f"manifest source hash mismatch: {relative}")
for relative, expected in IMMUTABLE_HASHES.items():
path = root / relative
if not path.is_file() or sha256_file(path) != expected:
errors.append(f"immutable evidence changed: {relative}")
if manifest.get("immutable_evidence", {}).get(relative) != expected:
errors.append(f"manifest immutable hash mismatch: {relative}")
denylist = root / "manifests/artifact-denylist.json"
if not denylist.is_file() or sha256_file(denylist) != DENYLIST_HASH:
errors.append("permanent denylist changed")
else:
denylist_data = load_json(denylist)
entries = json.dumps(denylist_data, sort_keys=True)
if BLOCKED_HASH not in entries:
errors.append("permanently blocked artifact is absent from denylist")
for name, (relative, expected) in SOURCE_COMMITS.items():
source_root = (root / relative).resolve()
try:
if git(source_root, "rev-parse", "HEAD") != expected:
errors.append(f"source HEAD changed: {name}")
if git(source_root, "status", "--porcelain=v1"):
errors.append(f"source tree is dirty: {name}")
except RuntimeError as error:
errors.append(f"{name}: {error}")
try:
if git(root, "branch", "--show-current") != EXPECTED_BRANCH:
errors.append("current branch is not the Phase-0.9D branch")
except RuntimeError as error:
errors.append(str(error))
allowed_suffixes = {".md", ".json", ".py"}
forbidden_roots = ("samples/", "src/", "include/", "packaging/", "adapters/")
for relative in _phase09d_paths(root):
lowered = relative.lower()
if Path(relative).suffix.lower() not in allowed_suffixes:
errors.append(f"forbidden Phase-0.9D artifact/source suffix: {relative}")
if lowered.startswith(forbidden_roots):
errors.append(f"forbidden Phase-0.9D target/product path: {relative}")
if lowered.endswith((".elf", ".o", ".a", ".so", ".map", ".s", ".asm", ".ld")):
errors.append(f"forbidden Phase-0.9D target artifact: {relative}")
docs = "\n".join(
(root / relative).read_text(encoding="utf-8")
for relative in DELIVERABLES
if relative.endswith(".md") and (root / relative).is_file()
)
for marker in (
"BLOCKED_NO_READBACK_PATH",
"PATH_CONFLICT",
"server_active_flag",
"autoload_triggered",
"OFF_DEVICE_BACKUP_VALID",
"RECOVERY_PROVEN",
"No PS5 was contacted",
):
if marker not in docs:
errors.append(f"documentation marker missing: {marker}")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
errors = collect_errors(args.root.resolve())
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print("Phase-0.9D existing-stack readback audit: PASS")
print("Decision: BLOCKED_NO_READBACK_PATH")
print("Device contact/write/execution/artifact creation: false")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+798
View File
@@ -0,0 +1,798 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the offline-only Phase-0.9E bootstrap provenance audit."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess
from typing import Any
import zipfile
EXPECTED_BASELINE = "e5304e394efb0790e1939bef87404f19b58caa43"
EXPECTED_BRANCH = "codex/chimera-gfx-phase09e-bootstrap-rescue-provenance"
EXPECTED_PHASE = "PHASE_0_9E_BOOTSTRAP_RESCUE_PROVENANCE"
EXPECTED_STATUS = "DESIGN_ONLY"
EXPECTED_CLASSIFICATION = "BOOTSTRAP_IMPLEMENTATION_MISSING"
BLOCKED_HASH = (
"4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63"
)
DENYLIST_HASH = (
"e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
)
OUTER_NAME = "Y2JB-Autoloader-403-1240.zip"
OUTER_SIZE = 504159435
OUTER_SHA256 = (
"805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291"
)
INNER_NAME = "PS5/EXPORT/BACKUP/202606102126_00/archive.dat"
INNER_SIZE = 504365056
INNER_SHA256 = (
"6439834e8856d45b6d6fe699b74c35ca6985a199ea8ecf3e398c018d37be2d55"
)
ZIP_ENTRIES = (
"PS5/",
"PS5/EXPORT/",
"PS5/EXPORT/BACKUP/",
"PS5/EXPORT/BACKUP/202606102126_00/",
INNER_NAME,
)
AUTHORIZATION_FIELDS = (
"device_action_authorized",
"execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"device_write_authorized",
"transfer_authorized",
"automatic_retry",
"target_build_authorized",
"rescue_payload_design_authorized",
)
ACTION_FIELDS = (
"internet_used",
"fetch_performed",
"clone_performed",
"package_installed",
"ps5_connected",
"device_request_performed",
"files_transferred",
"device_write_performed",
"target_execution_performed",
"target_build_performed",
"target_artifact_created",
"rescue_payload_created",
"readback_payload_created",
"device_client_created",
"backup_created",
"staging_performed",
)
PROVENANCE_FIELDS = (
"logical_name",
"artifact_role",
"local_relative_path",
"size",
"sha256",
"file_type",
"source_repository",
"source_commit",
"build_identity",
"version",
"obtained_from",
"evidence_that_it_is_deployed_or_used",
"confidence",
"immutable",
"executable",
"persistent_on_device",
"transferred_per_session",
"required_for_bootstrap",
"required_for_recovery",
)
SOURCE_COMMITS = {
"hardened_elfldr": (
"../chimera-elfldr",
"197623058f509eddde18868dafcb92fdcac66464",
),
"controlled_payload_manager": (
"../chimera-ps5-payload-manager",
"e23d94ff91233aa770e2342800c1467875bdef44",
),
"elfldr_public_base": (
"work/upstream/elfldr-v0.23",
"699e8bcff03e91e8d6ca6eba281af25c5a58d8c2",
),
"payload_manager_public_base": (
"work/upstream/pldmgr-v0.3.1",
"cfbc70f30f419b09bf2b52283f7409e2d3117ee1",
),
"ps5_payload_sdk_v0_41": (
"work/upstream/sdk",
"d2e2e585740362976a39fdd5ccf390f199a7bc37",
),
}
SOURCE_HASHES = {
"../chimera-elfldr/elfldr-ps5.elf": (
397000,
"63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561",
),
"../chimera-elfldr/elfldr-ps5.elf.map": (
142905,
"2ea5ff73299db6e61d5fd998c358ee910bc4e8fa1e6e7c73dbaa842bc813124f",
),
"../chimera-elfldr/bootstrap.elf.map": (
143081,
"ec4ae17abeb8270948d8a7d4196593ba94cbdb69376b8b9f7f009b25ab5b3323",
),
"../chimera-elfldr/socksrv.elf.map": (
145072,
"bf74db6ee68a60652426936e7037bb5a143078f44cc7774fa04c9bc4bc5447c1",
),
"../chimera-elfldr/Makefile": (
1902,
"3df93b48fc61ec67907b136e44ea2085baacf08347864d32befc072a7a783384",
),
"../chimera-elfldr/README.md": (
2821,
"372aeb28dc971b2bd98093a47fdaf77c32f75bbdc3b3d7e8678900744b91eadb",
),
"../chimera-elfldr/main.c": (
2473,
"876389a26999073994e63ca29926982280d9594a1ee941244205b54f57e2b4d1",
),
"../chimera-elfldr/bootstrap.c": (
2081,
"5a8072ec0d6db919cb3a81a7028dc91fd8e2c3a0d69b0fa7e84836fa93b45381",
),
"../chimera-elfldr/socksrv.c": (
11556,
"d642ced3e9b4a296dd15e355050ebe956f53a6dfdaa6ac10109cd067a3bba3d7",
),
"work/upstream/release-assets/elfldr-ps5-v0.23.elf": (
397000,
"092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8",
),
"../chimera-ps5-payload-manager/pldmgr-controlled.elf": (
99560,
"8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1",
),
}
IMMUTABLE_HASHES = {
"manifests/runtime/phase-0.8-read-only-preflight.json": (
"47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322"
),
"manifests/runtime/phase-0.8-remediation.json": (
"a9dafed8c83722c43709dcf90ea117c21d6f996ff8fe233810ed08aa20cbe071"
),
"manifests/runtime/phase-0.9-anti-brick-design.json": (
"39fd7c70cae998d9d74e7caf1ff3c19f9f76f7de2e5a50bc09baede4ba53e9e9"
),
"manifests/runtime/phase-0.9b-observer.json": (
"104c4a667ad17f9827fc7276852c6faeef96effb8e3561a5ebc19a62c7d51634"
),
"manifests/runtime/phase-0.9c-feasibility.json": (
"84eb737ff3486d0c5d8b5ecf06809f93bc573497da4919595b4c1817fd34247c"
),
"manifests/runtime/phase-0.9d-existing-stack-readback.json": (
"86e5aaf034685dbe058b71ffeec645b682f0a8cc7d249e8ac0397155233991de"
),
}
DELIVERABLES = (
"docs/runtime/phase-0.9e-bootstrap-provenance.md",
"docs/runtime/phase-0.9e-independent-rescue-chain.md",
"docs/runtime/phase-0.9e-loader-9020-protocol.md",
"docs/runtime/phase-0.9e-reboot-and-crash-model.md",
"docs/runtime/phase-0.9e-future-rescue-payload-contract.md",
"docs/runtime/phase-0.9e-output-architecture-options.md",
"manifests/runtime/phase-0.9e-bootstrap-provenance.json",
"manifests/runtime/phase-0.9e-bootstrap-provenance.schema.json",
"manifests/runtime/phase-0.9e-loader-protocol.json",
"manifests/runtime/phase-0.9e-loader-protocol.schema.json",
"tools/validate_phase09e_bootstrap.py",
"tests/test_phase09e_bootstrap.py",
"packaging/phase09e/SHA256SUMS.txt",
)
FORBIDDEN_NEW_SUFFIXES = {
".c",
".cc",
".cpp",
".s",
".asm",
".ld",
".elf",
".self",
".sprx",
".pkg",
".bin",
}
FORBIDDEN_PRODUCTION_PREFIXES = (
"include/",
"src/",
"adapters/",
"samples/",
)
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as stream:
value = json.load(stream)
if not isinstance(value, dict):
raise ValueError(f"{path} does not contain an object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def candidate_archive_path(root: Path) -> Path:
"""Resolve the same Windows user Downloads path from Windows or WSL."""
windows_home_candidate = Path.home() / "Downloads" / OUTER_NAME
if windows_home_candidate.is_file():
return windows_home_candidate
for ancestor in (root, *root.parents):
if ancestor.parent.name.lower() == "users":
return ancestor / "Downloads" / OUTER_NAME
return windows_home_candidate
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
check=False,
capture_output=True,
text=True,
)
if result.returncode != 0:
raise RuntimeError(result.stderr.strip() or "git command failed")
return result.stdout.strip()
def provenance_errors(artifact: dict[str, Any]) -> list[str]:
errors: list[str] = []
for field in PROVENANCE_FIELDS:
if field not in artifact:
errors.append(f"missing provenance field {field}")
confidence = artifact.get("confidence")
if confidence not in {
"EXACT_USED",
"STRONG_MATCH",
"POSSIBLE",
"REFERENCE_ONLY",
"UNKNOWN",
}:
errors.append("invalid confidence")
obtained = str(artifact.get("obtained_from", "")).lower()
repository = str(artifact.get("source_repository") or "").lower()
if (
"public" in obtained or "upstream" in obtained or "upstream" in repository
) and confidence == "EXACT_USED":
errors.append("public upstream cannot be exact-used without provenance")
if (
artifact.get("source_repository") is None
and artifact.get("build_identity") is None
and artifact.get("source_commit") is not None
):
errors.append("opaque binary cannot carry an invented source commit")
if not re.fullmatch(r"[0-9a-f]{64}", str(artifact.get("sha256", ""))):
errors.append("invalid SHA-256")
if not isinstance(artifact.get("size"), int) or artifact.get("size", -1) < 0:
errors.append("invalid artifact size")
return errors
def rescue_classification(
*,
actual_package_available: bool,
requires_elfldr: bool = False,
requires_payload_manager: bool = False,
replaces_live_component: bool = False,
all_required_properties_proven: bool = False,
) -> str:
if not actual_package_available:
return "BOOTSTRAP_IMPLEMENTATION_MISSING"
if requires_elfldr or requires_payload_manager:
return "SELF_OR_CROSS_DEPENDENT"
if replaces_live_component:
return "NO_INDEPENDENT_RESCUE_PATH"
if all_required_properties_proven:
return "INDEPENDENT_RESCUE_EXECUTOR_CANDIDATE"
return "PARTIAL_RESCUE_EXECUTOR"
def host_to_memory_classification(
*,
receive_code: bool,
mapping_code: bool,
entrypoint_code: bool,
device_file_only: bool = False,
) -> str:
if device_file_only:
return "DEVICE_FILE_ONLY"
if receive_code and mapping_code and entrypoint_code:
return "PROVEN_FROM_SOURCE"
if receive_code or mapping_code or entrypoint_code:
return "PARTIAL"
return "UNKNOWN"
def protocol_model_complete(protocol: dict[str, Any]) -> bool:
required = (
"maximum_payload_size",
"headers",
"length_fields",
"short_read_detection",
"short_write_detection",
"bounds_checks",
)
return all(protocol.get(field) not in {None, "", "UNKNOWN"} for field in required)
def risk_classification(
*,
temporary_socket: bool = False,
live_filesystem_write: bool = False,
autoload_activation: bool = False,
) -> str:
if live_filesystem_write or autoload_activation:
return "BRICK_RELEVANT"
if temporary_socket:
return "LOW_TECHNICAL"
return "UNKNOWN"
def reboot_classification(
*,
exact_package: bool,
source_design_restartable: bool,
hardware_observed: bool,
) -> str:
if exact_package and source_design_restartable and hardware_observed:
return "REBOOT_RECOVERY_SUPPORTED_BY_DESIGN"
if exact_package and source_design_restartable:
return "REBOOT_RECOVERY_PLAUSIBLE"
return "REBOOT_RECOVERY_UNPROVEN"
def phase09f_design_allowed(
*,
actual_package_available: bool,
independent_from_elfldr: bool,
independent_from_payload_manager: bool,
no_live_replacement: bool,
) -> bool:
return all(
(
actual_package_available,
independent_from_elfldr,
independent_from_payload_manager,
no_live_replacement,
)
)
def _type_matches(value: Any, expected: str) -> bool:
return {
"object": isinstance(value, dict),
"array": isinstance(value, list),
"string": isinstance(value, str),
"boolean": isinstance(value, bool),
"integer": isinstance(value, int) and not isinstance(value, bool),
"number": isinstance(value, (int, float)) and not isinstance(value, bool),
"null": value is None,
}.get(expected, True)
def validate_schema_instance(
schema: dict[str, Any], instance: Any, path: str = "$"
) -> list[str]:
"""Small offline validator for the schema features used by this phase."""
errors: list[str] = []
expected_type = schema.get("type")
if expected_type and not _type_matches(instance, expected_type):
return [f"{path}: expected {expected_type}"]
if "const" in schema and instance != schema["const"]:
errors.append(f"{path}: expected constant {schema['const']!r}")
if "enum" in schema and instance not in schema["enum"]:
errors.append(f"{path}: value is outside enum")
pattern = schema.get("pattern")
if pattern and isinstance(instance, str) and not re.fullmatch(pattern, instance):
errors.append(f"{path}: pattern mismatch")
if isinstance(instance, dict):
for key in schema.get("required", []):
if key not in instance:
errors.append(f"{path}: missing {key}")
properties = schema.get("properties", {})
for key, value in instance.items():
if key in properties:
errors.extend(
validate_schema_instance(properties[key], value, f"{path}.{key}")
)
elif schema.get("additionalProperties") is False:
errors.append(f"{path}: unexpected property {key}")
elif isinstance(schema.get("additionalProperties"), dict):
errors.extend(
validate_schema_instance(
schema["additionalProperties"], value, f"{path}.{key}"
)
)
if isinstance(instance, list):
if "maxItems" in schema and len(instance) > schema["maxItems"]:
errors.append(f"{path}: too many items")
item_schema = schema.get("items")
if isinstance(item_schema, dict):
for index, item in enumerate(instance):
errors.extend(
validate_schema_instance(item_schema, item, f"{path}[{index}]")
)
return errors
def validate_manifest(manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
expected_top = {
"phase": EXPECTED_PHASE,
"status": EXPECTED_STATUS,
"baseline_commit": EXPECTED_BASELINE,
"branch": EXPECTED_BRANCH,
}
for field, expected in expected_top.items():
if manifest.get(field) != expected:
errors.append(f"{field} changed")
for field in AUTHORIZATION_FIELDS:
if manifest.get("authorization", {}).get(field) is not False:
errors.append(f"authorization.{field} must be false")
for field in ACTION_FIELDS:
if manifest.get("actions", {}).get(field) is not False:
errors.append(f"actions.{field} must be false")
canonical = manifest.get("canonical_state", {})
expected_canonical = {
"phase09d_decision": "BLOCKED_NO_READBACK_PATH",
"phase09c_new_observer": "BLOCKED_MULTIPLE_FOUNDATIONAL_CONTRACTS",
"payload_manager_backup": "HARD_BLOCKER_FOR_INSTALLATION",
"independent_recovery": "UNPROVEN",
"firmware_runtime_behavior": "UNPROVEN",
"permanent_denylist_sha256": DENYLIST_HASH,
"permanently_blocked_artifact_sha256": BLOCKED_HASH,
}
for field, expected in expected_canonical.items():
if canonical.get(field) != expected:
errors.append(f"canonical_state.{field} changed")
decisions = manifest.get("decisions", {})
expected_decisions = {
"actual_bootstrap_package_available": False,
"actual_bootstrap_identity": None,
"bootstrap_provenance": "POSSIBLE",
"independent_from_elfldr": "unproven",
"independent_from_payload_manager": "unproven",
"restartable_after_reboot": "unproven",
"host_to_memory": "UNKNOWN",
"output_channel_for_future_rescue": "UNKNOWN",
"independent_rescue_classification": EXPECTED_CLASSIFICATION,
"phase09f_rescue_payload_design_allowed": False,
"device_action_authorized": False,
"execution_authorized": False,
"installation_authorized": False,
"automatic_retry": False,
}
if decisions != expected_decisions:
errors.append("decision matrix changed")
if rescue_classification(actual_package_available=False) != (
EXPECTED_CLASSIFICATION
):
errors.append("missing implementation is misclassified")
for name, (_, expected) in SOURCE_COMMITS.items():
if manifest.get("source_commits", {}).get(name) != expected:
errors.append(f"source commit changed: {name}")
if manifest.get("source_tree_status", {}).get(name) != "clean":
errors.append(f"source tree not recorded clean: {name}")
audit = manifest.get("candidate_archive_audit", {})
expected_audit = {
"outer_size": OUTER_SIZE,
"outer_sha256": OUTER_SHA256,
"zip_entry_count": len(ZIP_ENTRIES),
"inner_path": INNER_NAME,
"inner_size": INNER_SIZE,
"inner_sha256": INNER_SHA256,
"inner_magic_ascii": "SIECAF",
"acceptable_local_parser_present": False,
"decryption_attempted": False,
"source_identity_proven": False,
"deployed_use_proven": False,
"classification": "POSSIBLE",
}
for field, expected in expected_audit.items():
if audit.get(field) != expected:
errors.append(f"candidate_archive_audit.{field} changed")
artifacts = manifest.get("artifacts", [])
if len(artifacts) != 13:
errors.append("artifact inventory must contain 13 records")
seen: set[str] = set()
for artifact in artifacts:
name = str(artifact.get("logical_name"))
if name in seen:
errors.append(f"duplicate artifact: {name}")
seen.add(name)
errors.extend(f"{name}: {error}" for error in provenance_errors(artifact))
if artifact.get("confidence") == "EXACT_USED":
errors.append(f"{name}: no exact-used artifact is proven")
if manifest.get("exact_used_artifacts") != []:
errors.append("exact_used_artifacts must remain empty")
host_memory = manifest.get("host_to_memory_analysis", {})
if (
host_memory.get("classification") != "UNKNOWN"
or host_memory.get("receive_code") != "MISSING"
or host_memory.get("mapping_code") != "MISSING"
or host_memory.get("entrypoint_selection") != "UNKNOWN"
):
errors.append("host-to-memory is overclaimed")
reboot = manifest.get("reboot_and_crash", {})
if (
reboot.get("classification") != "REBOOT_RECOVERY_UNPROVEN"
or reboot.get("automatic_retry") is not False
):
errors.append("reboot recovery is overclaimed or retry enabled")
finding_classes = {
item.get("id"): item.get("classification")
for item in manifest.get("security_findings", [])
}
if finding_classes.get("unknown_live_filesystem_effect") != "BRICK_RELEVANT":
errors.append("unknown live filesystem effect is not brick relevant")
if finding_classes.get("unknown_autoload_effect") != "BRICK_RELEVANT":
errors.append("unknown autoload effect is not brick relevant")
if finding_classes.get(
"temporary_socket_not_automatically_brick_relevant"
) == "BRICK_RELEVANT":
errors.append("temporary socket is automatically overclassified")
contract = manifest.get("future_rescue_contract", {})
if (
contract.get("requirements_total") != 20
or contract.get("bootstrap_supported_now") != []
or contract.get("target_source_allowed") is not False
):
errors.append("future rescue contract is not fully blocked")
if len(manifest.get("output_options", [])) != 5:
errors.append("output architecture options are incomplete")
if len(manifest.get("missing_actual_files", [])) < 5:
errors.append("missing actual bootstrap inputs are incomplete")
final = manifest.get("final_decision", {})
if final.get("classification") != EXPECTED_CLASSIFICATION:
errors.append("final decision changed")
return errors
def validate_protocol(protocol_manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
expected = {
"phase": "PHASE_0_9E_LOADER_9020_PROTOCOL",
"status": "UNPROVEN_IMPLEMENTATION_MISSING",
"exact_server_source_present": False,
"exact_server_binary_present": False,
"exact_host_client_present": False,
"protocol_identity": None,
"classification": "CONCEPTUAL_9020_DESCRIPTION_IS_NOT_PROTOCOL_PROOF",
}
for field, value in expected.items():
if protocol_manifest.get(field) != value:
errors.append(f"protocol {field} changed")
protocol = protocol_manifest.get("protocol", {})
if protocol.get("port") != 9020:
errors.append("protocol port changed")
if protocol_model_complete(protocol):
errors.append("missing implementation cannot yield a complete protocol")
for field in (
"handshake",
"length_fields",
"maximum_payload_size",
"timeout",
"retry",
"response_direction",
"parser",
"mappings",
"entrypoint_validation",
"filesystem_staging",
"cleanup",
):
if protocol.get(field) not in {"UNKNOWN", "MISSING"}:
errors.append(f"protocol.{field} is overclaimed")
host_model = protocol_manifest.get("host_model", {})
for field in (
"allowed",
"created",
"network_port_opened",
"device_connection_performed",
"payload_sent",
"binary_executed",
):
if host_model.get(field) is not False:
errors.append(f"host_model.{field} must be false")
return errors
def _changed_paths(root: Path) -> set[str]:
paths = {
path
for path in git(root, "diff", "--name-only", EXPECTED_BASELINE).splitlines()
if path
}
status = git(root, "status", "--porcelain=v1", "--untracked-files=all")
for line in status.splitlines():
if not line:
continue
path = line[3:]
if " -> " in path:
path = path.split(" -> ", 1)[1]
paths.add(path.replace("\\", "/"))
return paths
def phase09e_path_errors(paths: set[str]) -> list[str]:
errors: list[str] = []
for path in paths:
normalized = path.replace("\\", "/")
suffix = Path(normalized).suffix.lower()
if normalized.startswith(FORBIDDEN_PRODUCTION_PREFIXES):
errors.append(f"production/target path changed: {normalized}")
if suffix in FORBIDDEN_NEW_SUFFIXES:
errors.append(f"forbidden target artifact/source added: {normalized}")
lowered = normalized.lower()
if any(
token in lowered
for token in ("rescue.elf", "readback.elf", "executionpackage", "installpackage")
):
errors.append(f"forbidden Phase-0.9E output added: {normalized}")
if "tests/host/phase09e_protocol_model.py" in paths:
errors.append("protocol model created without exact protocol source")
return errors
def _validate_checksum_file(root: Path) -> list[str]:
path = root / "packaging/phase09e/SHA256SUMS.txt"
if not path.is_file():
return ["missing packaging/phase09e/SHA256SUMS.txt"]
errors: list[str] = []
for line in path.read_text(encoding="utf-8").splitlines():
if not line or line.startswith("#"):
continue
parts = line.split(" ", 1)
if len(parts) != 2 or not re.fullmatch(r"[0-9a-f]{64}", parts[0]):
errors.append(f"invalid checksum line: {line}")
continue
expected, label = parts
if label == f"~/Downloads/{OUTER_NAME}":
actual = sha256_file(candidate_archive_path(root))
elif label == f"~/Downloads/{OUTER_NAME}::{INNER_NAME}":
with zipfile.ZipFile(candidate_archive_path(root)) as archive:
digest = hashlib.sha256()
with archive.open(INNER_NAME) as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
actual = digest.hexdigest()
else:
candidate = root / label
if not candidate.is_file():
errors.append(f"checksum target missing: {label}")
continue
actual = sha256_file(candidate)
if actual != expected:
errors.append(f"checksum mismatch: {label}")
return errors
def collect_errors(root: Path) -> list[str]:
errors: list[str] = []
manifest_path = (
root / "manifests/runtime/phase-0.9e-bootstrap-provenance.json"
)
protocol_path = root / "manifests/runtime/phase-0.9e-loader-protocol.json"
schema_path = (
root / "manifests/runtime/phase-0.9e-bootstrap-provenance.schema.json"
)
protocol_schema_path = (
root / "manifests/runtime/phase-0.9e-loader-protocol.schema.json"
)
try:
manifest = load_json(manifest_path)
protocol_manifest = load_json(protocol_path)
schema = load_json(schema_path)
protocol_schema = load_json(protocol_schema_path)
except (OSError, ValueError, json.JSONDecodeError) as error:
return [str(error)]
errors.extend(validate_schema_instance(schema, manifest))
errors.extend(validate_schema_instance(protocol_schema, protocol_manifest))
errors.extend(validate_manifest(manifest))
errors.extend(validate_protocol(protocol_manifest))
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
if git(root, "rev-parse", "--abbrev-ref", "HEAD") != EXPECTED_BRANCH:
errors.append("current branch is not the Phase-0.9E branch")
if git(root, "merge-base", EXPECTED_BASELINE, "HEAD") != EXPECTED_BASELINE:
errors.append("Phase-0.9E branch no longer descends from baseline")
if sha256_file(root / "manifests/artifact-denylist.json") != DENYLIST_HASH:
errors.append("permanent denylist changed")
for relative, expected in IMMUTABLE_HASHES.items():
path = root / relative
if not path.is_file() or sha256_file(path) != expected:
errors.append(f"immutable evidence changed: {relative}")
for name, (relative, expected) in SOURCE_COMMITS.items():
source_root = (root / relative).resolve()
if git(source_root, "rev-parse", "HEAD") != expected:
errors.append(f"source HEAD changed: {name}")
if git(source_root, "status", "--porcelain"):
errors.append(f"source tree dirty: {name}")
for relative, (expected_size, expected_hash) in SOURCE_HASHES.items():
path = (root / relative).resolve()
if not path.is_file():
errors.append(f"source artifact missing: {relative}")
continue
if path.stat().st_size != expected_size or sha256_file(path) != expected_hash:
errors.append(f"source artifact identity changed: {relative}")
outer = candidate_archive_path(root)
if not outer.is_file():
errors.append(f"candidate archive missing: {outer}")
else:
if outer.stat().st_size != OUTER_SIZE or sha256_file(outer) != OUTER_SHA256:
errors.append("candidate outer archive identity changed")
try:
with zipfile.ZipFile(outer) as archive:
if tuple(item.filename for item in archive.infolist()) != ZIP_ENTRIES:
errors.append("candidate ZIP inventory changed")
info = archive.getinfo(INNER_NAME)
if info.file_size != INNER_SIZE:
errors.append("candidate inner size changed")
digest = hashlib.sha256()
magic = b""
with archive.open(INNER_NAME) as stream:
while True:
chunk = stream.read(1024 * 1024)
if not chunk:
break
if not magic:
magic = chunk[:6]
digest.update(chunk)
if magic != b"SIECAF" or digest.hexdigest() != INNER_SHA256:
errors.append("candidate inner identity changed")
except (OSError, KeyError, zipfile.BadZipFile) as error:
errors.append(f"candidate ZIP audit failed: {error}")
errors.extend(phase09e_path_errors(_changed_paths(root)))
errors.extend(_validate_checksum_file(root))
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
errors = collect_errors(args.root.resolve())
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print("Phase-0.9E bootstrap provenance validation: PASS")
print(f"Decision: {EXPECTED_CLASSIFICATION}")
print("Device actions: NONE")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+658
View File
@@ -0,0 +1,658 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the host-only Phase-0.9E-R2 inner-backup correlation."""
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
from pathlib import Path
import re
import subprocess
import sys
from types import ModuleType
from typing import Any
import zipfile
BASELINE = "48714bb542f3ea5b9893d0461ba4c9d938cd6d8d"
BRANCH = "codex/chimera-gfx-phase09e-r2-inner-correlation"
PHASE = "PHASE_0_9E_R2_INNER_BACKUP_CORRELATION"
OUTER_NAME = "Y2JB-Autoloader-403-1240.zip"
OUTER_SIZE = 504159435
OUTER_SHA256 = "805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291"
INNER_NAME = "PS5/EXPORT/BACKUP/202606102126_00/archive.dat"
INNER_SIZE = 504365056
INNER_SHA256 = "6439834e8856d45b6d6fe699b74c35ca6985a199ea8ecf3e398c018d37be2d55"
DENYLIST_SHA256 = "e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
PRIMARY_CLASSIFICATION = "LOCAL_BACKUP_UNCORRELATED"
AUTHORIZATION_FIELDS = (
"device_action_authorized",
"target_build_authorized",
"transfer_authorized",
"execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"device_write_authorized",
"rescue_payload_design_authorized",
"automatic_retry",
)
IMMUTABLE_HASHES = {
"manifests/runtime/phase-0.8-read-only-preflight.json": "47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322",
"manifests/runtime/phase-0.8-remediation.json": "a9dafed8c83722c43709dcf90ea117c21d6f996ff8fe233810ed08aa20cbe071",
"manifests/runtime/phase-0.9-anti-brick-design.json": "39fd7c70cae998d9d74e7caf1ff3c19f9f76f7de2e5a50bc09baede4ba53e9e9",
"manifests/runtime/phase-0.9b-observer.json": "104c4a667ad17f9827fc7276852c6faeef96effb8e3561a5ebc19a62c7d51634",
"manifests/runtime/phase-0.9c-feasibility.json": "84eb737ff3486d0c5d8b5ecf06809f93bc573497da4919595b4c1817fd34247c",
"manifests/runtime/phase-0.9d-existing-stack-readback.json": "86e5aaf034685dbe058b71ffeec645b682f0a8cc7d249e8ac0397155233991de",
"manifests/runtime/phase-0.9e-bootstrap-provenance.json": "5dfa9bfe2ae751b2f0ea0e03c60c1a4471a35452389cf471456e6c54eb4601cf",
"manifests/runtime/phase-0.9e-loader-protocol.json": "a7ca8b4e8072cb60ad4cd4869f6c508e8014059c8d81ad3b94a8d9e8cd0db4cb",
"manifests/runtime/phase-0.9e-r-release-correlation.json": "09f916b20def51fd519690b6d940de5f93818a4d9bd5eebef462fe2a828b88be",
"manifests/runtime/phase-0.9e-r-port9020-audit.json": "ea84f1885ad4286670a401cbf73e9a371cdcd03a1f247908b90ea27553ee820e",
}
DELIVERABLES = (
"docs/runtime/phase-0.9e-r2-local-download-provenance.md",
"docs/runtime/phase-0.9e-r2-inner-archive-correlation.md",
"docs/runtime/phase-0.9e-r2-siecaf-structural-analysis.md",
"docs/runtime/phase-0.9e-r2-community-backup-correlation.md",
"docs/runtime/phase-0.9e-r2-final-provenance-decision.md",
"manifests/runtime/phase-0.9e-r2-inner-correlation.json",
"manifests/runtime/phase-0.9e-r2-siecaf-fingerprints.json",
"tools/inspect_siecaf_header.py",
"tools/validate_phase09er2_correlation.py",
"tests/test_phase09er2_correlation.py",
"tests/test_siecaf_header_parser.py",
"packaging/phase09er2/SHA256SUMS.txt",
)
FORBIDDEN_SUFFIXES = {
".c",
".cc",
".cpp",
".s",
".asm",
".ld",
".elf",
".self",
".sprx",
".pkg",
".bin",
".wasm",
".sqlite",
".download",
}
FORBIDDEN_PREFIXES = ("include/", "src/", "adapters/", "samples/")
MAX_TRACKED_FILE_SIZE = 10 * 1024 * 1024
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as stream:
value = json.load(stream)
if not isinstance(value, dict):
raise ValueError(f"{path} is not a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def sha256_zip_entry(path: Path, entry: str) -> tuple[int, str]:
digest = hashlib.sha256()
with zipfile.ZipFile(path) as archive:
info = archive.getinfo(entry)
with archive.open(info) as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return info.file_size, digest.hexdigest()
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
check=False,
capture_output=True,
text=True,
)
if result.returncode != 0:
raise RuntimeError(result.stderr.strip() or "git command failed")
return result.stdout.strip()
def load_module(name: str, path: Path) -> ModuleType:
spec = importlib.util.spec_from_file_location(name, path)
if spec is None or spec.loader is None:
raise RuntimeError(f"could not import {path}")
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
def candidate_archive_path(root: Path) -> Path:
direct = Path.home() / "Downloads" / OUTER_NAME
if direct.is_file():
return direct
for ancestor in (root, *root.parents):
if ancestor.parent.name.lower() == "users":
return ancestor / "Downloads" / OUTER_NAME
return direct
def inner_byte_match(
*,
left_size: int,
right_size: int,
left_sha256: str,
right_sha256: str,
full_byte_equal: bool,
) -> bool:
"""Require count, digest, and complete comparison for an inner match."""
return left_size == right_size and left_sha256 == right_sha256 and full_byte_equal
def classify_inner_comparison(
*,
download_valid: bool,
inner_present: bool,
left_size: int,
right_size: int,
left_sha256: str,
right_sha256: str,
full_byte_equal: bool,
) -> str:
if not download_valid:
return "OFFICIAL_ASSET_DOWNLOAD_INVALID"
if not inner_present:
return "EXPECTED_INNER_ARCHIVE_ABSENT"
if inner_byte_match(
left_size=left_size,
right_size=right_size,
left_sha256=left_sha256,
right_sha256=right_sha256,
full_byte_equal=full_byte_equal,
):
return "INNER_ARCHIVE_BYTE_MATCH"
if left_size == right_size:
return "INNER_ARCHIVE_SIZE_ONLY_MATCH"
return "INNER_ARCHIVE_HASH_MISMATCH"
def phase09f_reconsideration_allowed(
*,
inner_source_bound: bool,
mediafire_maker_source_bound: bool,
auditable_bootstrap_closure: bool,
) -> bool:
return auditable_bootstrap_closure and (
inner_source_bound or mediafire_maker_source_bound
)
def _canonical_hash(records: list[dict[str, Any]]) -> str:
encoded = json.dumps(
records, sort_keys=True, separators=(",", ":"), ensure_ascii=True
).encode("ascii")
return hashlib.sha256(encoded).hexdigest()
def _normalized_records(
archive: dict[str, Any],
) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[dict[str, Any]]]:
segment_fields = (
"section_id",
"part_number",
"data_offset",
"aligned_length",
"unaligned_length",
"hash_key_id_or_algorithm_type",
"encryption_key_id_or_algorithm_version",
"iv_hex",
)
layout_fields = segment_fields[:-1]
hash_fields = ("section_id", "section_type", "section_hash_128_hex")
segments = [
{field: item[field] for field in segment_fields}
for item in sorted(
archive["segments"],
key=lambda value: (
value["section_id"],
value["part_number"],
value["data_offset"],
),
)
]
hashes = [
{field: item[field] for field in hash_fields}
for item in sorted(
archive["section_hashes"],
key=lambda value: (value["section_id"], value["section_type"]),
)
]
layout = [{field: item[field] for field in layout_fields} for item in segments]
return segments, hashes, layout
def validate_fingerprint_archive(name: str, archive: dict[str, Any]) -> list[str]:
errors: list[str] = []
if archive.get("classification") != "SIECAF_VALID_STRUCTURE":
errors.append(f"{name}: structure is not valid")
return errors
header = archive.get("header", {})
if (
"key_or_unknown_16_hex" in header
or "raw_hex" in header
or header.get("key_or_unknown_16_redacted") is not True
or len(header.get("key_or_unknown_16_sha256", "")) != 64
):
errors.append(f"{name}: cryptographic header material is not redacted")
count = header.get("segment_count")
if len(archive.get("segments", [])) != count:
errors.append(f"{name}: segment count mismatch")
if len(archive.get("section_hashes", [])) != count:
errors.append(f"{name}: hash count mismatch")
segments, hashes, layout = _normalized_records(archive)
if _canonical_hash(segments) != archive.get("normalized_segment_table_sha256"):
errors.append(f"{name}: normalized segment hash mismatch")
if _canonical_hash(hashes) != archive.get("normalized_hash_blocks_sha256"):
errors.append(f"{name}: normalized hash-block hash mismatch")
layout_value = [
{
"unknown_u64": header.get("unknown_u64"),
"version_i32": header.get("version_i32"),
"segment_count": count,
"file_offset": header.get("file_offset"),
"file_size": header.get("file_size"),
},
*layout,
]
if _canonical_hash(layout_value) != archive.get("normalized_layout_sha256"):
errors.append(f"{name}: normalized layout hash mismatch")
structural = _canonical_hash(
[
{
"header_raw_sha256": header.get("raw_sha256"),
"normalized_segment_table_sha256": archive.get(
"normalized_segment_table_sha256"
),
"normalized_hash_blocks_sha256": archive.get(
"normalized_hash_blocks_sha256"
),
}
]
)
if structural != archive.get("structural_fingerprint_sha256"):
errors.append(f"{name}: structural fingerprint mismatch")
for field in (
"duplicate_metadata_section_keys",
"duplicate_hash_section_ids",
"overlaps",
"gaps",
"errors",
"warnings",
):
if archive.get(field):
errors.append(f"{name}: unexpected {field}")
if archive.get("trailing_data_bytes") != 0:
errors.append(f"{name}: trailing data is not zero")
return errors
def validate_fingerprints(
root: Path,
value: dict[str, Any],
inspector: ModuleType,
local_path: Path,
) -> list[str]:
errors: list[str] = []
if value.get("phase") != PHASE or value.get("status") != "HOST_ONLY_EVIDENCE":
errors.append("fingerprint manifest phase/status mismatch")
evidence = value.get("parser_evidence", {})
if (
evidence.get("source_commit") != "36d014672bc87577a6e0d750c2cccadc3fae0854"
or evidence.get("header_blob") != "fdbc368353a7797464873ada306f0297257eb95e"
):
errors.append("public SIECAF source binding changed")
for field in (
"decryption_attempted",
"content_extraction_attempted",
"ps5_bar_tool_executed",
):
if evidence.get(field) is not False:
errors.append(f"fingerprint manifest permits {field}")
archives = value.get("archives", {})
expected_names = {
"local",
"official_y2jb_1_6_4_03",
"community_owendswang_v1_4_autoloader_7_61",
}
if set(archives) != expected_names:
errors.append("fingerprint archive set mismatch")
return errors
for name, archive in archives.items():
errors.extend(validate_fingerprint_archive(name, archive))
with zipfile.ZipFile(local_path) as local:
info = local.getinfo(INNER_NAME)
with local.open(info) as stream:
observed = inspector.inspect_siecaf(
stream, info.file_size, source_label="local-mediafire-inner"
)
if observed != archives["local"]:
errors.append("local SIECAF evidence does not reproduce")
pairs = {
"local_vs_official_y2jb_1_6_4_03": (
archives["local"],
archives["official_y2jb_1_6_4_03"],
),
"local_vs_community_owendswang_v1_4_autoloader_7_61": (
archives["local"],
archives["community_owendswang_v1_4_autoloader_7_61"],
),
"official_vs_community": (
archives["official_y2jb_1_6_4_03"],
archives["community_owendswang_v1_4_autoloader_7_61"],
),
}
comparisons = value.get("comparisons", {})
for name, (left, right) in pairs.items():
expected = inspector.compare_structures(left, right)
if comparisons.get(name) != expected:
errors.append(f"{name}: comparison does not reproduce")
if expected["classification"] != "SIECAF_LAYOUT_DIFFERENT":
errors.append(f"{name}: expected fail-closed layout difference")
authorization = value.get("authorization", {})
for field in AUTHORIZATION_FIELDS:
if authorization.get(field) is not False:
errors.append(f"fingerprints authorize {field}")
return errors
def validate_manifest(value: dict[str, Any]) -> list[str]:
errors: list[str] = []
if value.get("phase") != PHASE or value.get("status") != "HOST_ONLY_COMPLETE":
errors.append("main manifest phase/status mismatch")
if value.get("baseline_commit") != BASELINE:
errors.append("baseline commit mismatch")
if value.get("prior_phase_classification") != "LOCAL_BACKUP_NOT_CORRELATED":
errors.append("prior classification was not preserved")
if value.get("primary_provenance_classification") != PRIMARY_CLASSIFICATION:
errors.append("primary provenance classification mismatch")
for field in (
"outer_zip_official",
"runtime_deployment_verified",
"current_device_contents_verified",
"phase09f_offline_design_reconsideration_allowed",
):
if value.get(field) is not False:
errors.append(f"{field} must remain false")
if value.get("runtime_firmware_9_60") != "UNPROVEN":
errors.append("runtime firmware state was overclaimed")
outer = value.get("local_candidate", {}).get("outer", {})
inner = value.get("local_candidate", {}).get("inner", {})
if (
outer.get("name"),
outer.get("size"),
outer.get("sha256"),
) != (OUTER_NAME, OUTER_SIZE, OUTER_SHA256):
errors.append("local outer identity mismatch")
if (
inner.get("entry"),
inner.get("size"),
inner.get("sha256"),
) != (INNER_NAME, INNER_SIZE, INNER_SHA256):
errors.append("local inner identity mismatch")
provenance = value.get("local_download_provenance", {})
zone = provenance.get("zone_identifier", {})
if provenance.get("classification") != "MEDIAFIRE_URL_EXACT":
errors.append("local URL provenance classification mismatch")
if zone.get("mediafire_file_key") != "jq3fcutuwbb1mrb":
errors.append("MediaFire key mismatch")
if "<redacted-signed-segment>" not in zone.get("host_url", {}).get(
"path_redacted", ""
):
errors.append("signed MediaFire path is not redacted")
browser = provenance.get("browser_history", {})
if (
browser.get("matching_records") != 0
or browser.get("full_history_exported") is not False
or browser.get("original_databases_modified") is not False
):
errors.append("browser-history boundary mismatch")
mediafire = value.get("mediafire_object", {})
if mediafire.get("classification") != "MEDIAFIRE_OBJECT_METADATA_BOUND":
errors.append("MediaFire object classification mismatch")
if mediafire.get("redownload_performed") is not False:
errors.append("MediaFire duplicate download was recorded")
official = value.get("official_candidate", {})
if (
official.get("asset_id") != 442358421
or official.get("official_size") != 504395044
or official.get("official_sha256")
!= "b01b4f442327f9eca90ffc4506dfa58249e4ac70cb9d7488c856c9e8dfaf37b4"
or official.get("download_attempts") != 1
or official.get("resume") is not False
or official.get("automatic_retry") is not False
or official.get("download_valid") is not True
):
errors.append("official download evidence mismatch")
comparison = official.get("inner_comparison", {})
observed_class = classify_inner_comparison(
download_valid=official.get("download_valid") is True,
inner_present=True,
left_size=comparison.get("official_inner_size", -1),
right_size=comparison.get("local_inner_size", -1),
left_sha256=comparison.get("official_inner_sha256", ""),
right_sha256=comparison.get("local_inner_sha256", ""),
full_byte_equal=comparison.get("full_byte_equal") is True,
)
if comparison.get("classification") != observed_class:
errors.append("official inner classification does not reproduce")
families = value.get("community_families", [])
if len(families) != 3:
errors.append("community family count mismatch")
downloaded = [item for item in families if item.get("large_backup_downloaded")]
if len(downloaded) != 1:
errors.append("community large-download count mismatch")
elif (
downloaded[0].get("downloaded_asset", {}).get("inner_comparison")
!= "INNER_ARCHIVE_HASH_MISMATCH"
):
errors.append("community inner mismatch is not preserved")
siecaf = value.get("siecaf", {})
for field in (
"local_vs_official",
"local_vs_community",
"official_vs_community",
):
if siecaf.get(field) != "SIECAF_LAYOUT_DIFFERENT":
errors.append(f"{field}: structural result overclaimed")
for field in (
"decryption_attempted",
"content_extraction_attempted",
"ps5_bar_tool_executed",
):
if siecaf.get(field) is not False:
errors.append(f"main manifest permits {field}")
authorization = value.get("authorization", {})
for field in AUTHORIZATION_FIELDS:
if authorization.get(field) is not False:
errors.append(f"main manifest authorizes {field}")
actions = value.get("actions", {})
prohibited_true = (
"download_resume_used",
"automatic_retry_used",
"downloaded_file_executed",
"downloaded_file_restored",
"ps5_bar_tool_executed",
"ps5_connected",
"ps5_ip_used",
"device_request_performed",
"files_transferred_to_or_from_ps5",
"target_build_performed",
"target_code_created",
"target_artifact_created",
"payload_created",
"device_client_created",
)
for field in prohibited_true:
if actions.get(field) is not False:
errors.append(f"prohibited action recorded: {field}")
storage = value.get("temporary_research_storage", {})
if (
storage.get("cleaned") is not True
or storage.get("cleanup_verified") is not True
or storage.get("large_files_tracked") is not False
or storage.get("browser_database_copies_tracked") is not False
):
errors.append("temporary-storage final state mismatch")
if value.get("blocking_state", {}).get("payload_manager_backup") != (
"HARD_BLOCKER_FOR_INSTALLATION"
):
errors.append("Payload Manager installation blocker changed")
if phase09f_reconsideration_allowed(
inner_source_bound=False,
mediafire_maker_source_bound=False,
auditable_bootstrap_closure=False,
):
errors.append("Phase 0.9F fail-closed decision failed")
return errors
def validate_checksums(root: Path) -> list[str]:
errors: list[str] = []
path = root / "packaging/phase09er2/SHA256SUMS.txt"
if not path.is_file():
return ["Phase-0.9E-R2 checksum inventory is missing"]
entries = 0
for line in path.read_text(encoding="utf-8").splitlines():
if not line or line.startswith("#"):
continue
match = re.fullmatch(r"([0-9a-f]{64}) (.+)", line)
if not match:
errors.append(f"malformed checksum line: {line}")
continue
expected, relative = match.groups()
target = root / relative
if not target.is_file():
errors.append(f"checksum target missing: {relative}")
elif sha256_file(target) != expected:
errors.append(f"checksum mismatch: {relative}")
entries += 1
if entries < 12:
errors.append("checksum inventory is unexpectedly small")
return errors
def validate_repository(root: Path) -> list[str]:
errors: list[str] = []
if git(root, "branch", "--show-current") != BRANCH:
errors.append("current branch mismatch")
ancestors = git(root, "merge-base", "--is-ancestor", BASELINE, "HEAD")
if ancestors:
errors.append("unexpected merge-base output")
for relative, expected in IMMUTABLE_HASHES.items():
path = root / relative
if not path.is_file() or sha256_file(path) != expected:
errors.append(f"immutable evidence changed: {relative}")
denylist = root / "manifests/artifact-denylist.json"
if sha256_file(denylist) != DENYLIST_SHA256:
errors.append("permanent artifact denylist changed")
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"deliverable missing: {relative}")
tracked = git(root, "ls-files").splitlines()
for relative in tracked:
path = root / relative
if path.is_file() and path.stat().st_size > MAX_TRACKED_FILE_SIZE:
errors.append(f"large tracked file: {relative}")
suffix = Path(relative).suffix.lower()
if relative.startswith("packaging/phase09er2/") and suffix in {
".zip",
".rar",
".7z",
".dat",
}:
errors.append(f"backup material tracked: {relative}")
changed = git(
root, "diff", "--name-only", "--diff-filter=ACMR", f"{BASELINE}...HEAD"
).splitlines()
changed.extend(git(root, "diff", "--name-only", "--diff-filter=ACMR").splitlines())
untracked = git(root, "ls-files", "--others", "--exclude-standard").splitlines()
changed.extend(untracked)
for relative in sorted(set(filter(None, changed))):
normalized = relative.replace("\\", "/")
suffix = Path(normalized).suffix.lower()
if normalized.startswith(FORBIDDEN_PREFIXES) or suffix in FORBIDDEN_SUFFIXES:
errors.append(f"target/binary source forbidden in phase: {normalized}")
path = root / relative
if path.is_file() and path.stat().st_size <= 2 * 1024 * 1024:
try:
text = path.read_text(encoding="utf-8")
except UnicodeDecodeError:
errors.append(f"unexpected binary tracked or staged: {normalized}")
continue
if re.search(r"download2434\.mediafire\.com/[^<\s]+", text):
errors.append(f"unredacted signed MediaFire URL: {normalized}")
return errors
def validate_local_candidate(root: Path) -> tuple[Path, list[str]]:
errors: list[str] = []
path = candidate_archive_path(root)
if not path.is_file():
return path, [f"local candidate missing: {path}"]
if path.stat().st_size != OUTER_SIZE or sha256_file(path) != OUTER_SHA256:
errors.append("local outer candidate identity changed")
return path, errors
try:
size, digest = sha256_zip_entry(path, INNER_NAME)
except (KeyError, OSError, zipfile.BadZipFile) as error:
errors.append(f"local inner candidate cannot be read: {error}")
else:
if size != INNER_SIZE or digest != INNER_SHA256:
errors.append("local inner candidate identity changed")
return path, errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
errors: list[str] = []
local_path, candidate_errors = validate_local_candidate(root)
errors.extend(candidate_errors)
errors.extend(validate_repository(root))
main_manifest = load_json(
root / "manifests/runtime/phase-0.9e-r2-inner-correlation.json"
)
fingerprints = load_json(
root / "manifests/runtime/phase-0.9e-r2-siecaf-fingerprints.json"
)
errors.extend(validate_manifest(main_manifest))
if local_path.is_file():
inspector = load_module(
"phase09er2_siecaf_inspector",
root / "tools/inspect_siecaf_header.py",
)
errors.extend(validate_fingerprints(root, fingerprints, inspector, local_path))
errors.extend(validate_checksums(root))
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print(
"Phase-0.9E-R2 validation PASS: "
"LOCAL_BACKUP_UNCORRELATED; no device action authorized"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+621
View File
@@ -0,0 +1,621 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the host-only Phase-0.9E-R official Y2JB correlation."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess
from typing import Any
import zipfile
BASELINE = "3d3151bd12ff0f786c1e1b9af75d7174408e3d2f"
BRANCH = "codex/chimera-gfx-phase09e-r-y2jb-correlation"
PHASE = "PHASE_0_9E_R_OFFICIAL_Y2JB_CORRELATION"
OUTER_NAME = "Y2JB-Autoloader-403-1240.zip"
OUTER_SIZE = 504159435
OUTER_SHA256 = "805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291"
INNER_NAME = "PS5/EXPORT/BACKUP/202606102126_00/archive.dat"
INNER_SIZE = 504365056
INNER_SHA256 = "6439834e8856d45b6d6fe699b74c35ca6985a199ea8ecf3e398c018d37be2d55"
DENYLIST_SHA256 = "e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
UPSTREAM_COMMIT = "0dbbf4e7e0203af7e5d101a3256c634edf4e3ba2"
UPSTREAM_TREE = "c4344f43af7c268337437e6419548dba6f6bc211"
UPSTREAM_REMOTE = "https://github.com/Gezine/Y2JB.git"
PORT_9020_CLASSIFICATION = "PORT_9020_REFERENCE_ONLY"
FINAL_CLASSIFICATION = "LOCAL_BACKUP_NOT_CORRELATED"
PROVENANCE_FIELDS = (
"logical_name",
"artifact_role",
"local_relative_path",
"size",
"sha256",
"file_type",
"source_repository",
"source_commit",
"build_identity",
"version",
"obtained_from",
"evidence_that_it_is_deployed_or_used",
"confidence",
"immutable",
"executable",
"persistent_on_device",
"transferred_per_session",
"required_for_bootstrap",
"required_for_recovery",
)
AUTHORIZATION_FIELDS = (
"device_action_authorized",
"target_build_authorized",
"transfer_authorized",
"execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"device_write_authorized",
"automatic_retry",
)
IMMUTABLE_HASHES = {
"manifests/runtime/phase-0.8-read-only-preflight.json":
"47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322",
"manifests/runtime/phase-0.8-remediation.json":
"a9dafed8c83722c43709dcf90ea117c21d6f996ff8fe233810ed08aa20cbe071",
"manifests/runtime/phase-0.9-anti-brick-design.json":
"39fd7c70cae998d9d74e7caf1ff3c19f9f76f7de2e5a50bc09baede4ba53e9e9",
"manifests/runtime/phase-0.9b-observer.json":
"104c4a667ad17f9827fc7276852c6faeef96effb8e3561a5ebc19a62c7d51634",
"manifests/runtime/phase-0.9c-feasibility.json":
"84eb737ff3486d0c5d8b5ecf06809f93bc573497da4919595b4c1817fd34247c",
"manifests/runtime/phase-0.9d-existing-stack-readback.json":
"86e5aaf034685dbe058b71ffeec645b682f0a8cc7d249e8ac0397155233991de",
"manifests/runtime/phase-0.9e-bootstrap-provenance.json":
"5dfa9bfe2ae751b2f0ea0e03c60c1a4471a35452389cf471456e6c54eb4601cf",
"manifests/runtime/phase-0.9e-loader-protocol.json":
"a7ca8b4e8072cb60ad4cd4869f6c508e8014059c8d81ad3b94a8d9e8cd0db4cb",
}
UPSTREAM_FILE_HASHES = {
"README.md": (7500, "16bfdaa624b8b04f4a6a4a7d512ca8473ad2db73e80df39a974267403e34f751"),
"payload_sender.py": (1064, "8c87920c41dbdbd66b9f36ca9509f0d6bef9170f351dd97ff831cfb98e642ec6"),
"log_server.py": (929, "463114fd46479a7286706de13beb3f52221f36f3cbe37dc5a27bdb6104787a98"),
"appinfo_editor.py": (2008, "c1bcb453660f597cbc9026dba76519a4929fc3e967c183deec8a1ca56912e2e8"),
"download0/cache/splash_screen/aHR0cHM6Ly93d3cueW91dHViZS5jb20vdHY=/remotejsloader.js":
(7132, "30cc6d1535549b2a49b47a9e0c85a3444cf84177be54398691694b7c6505f38e"),
"download0/cache/splash_screen/aHR0cHM6Ly93d3cueW91dHViZS5jb20vdHY=/elfldr-ps5-1340.elf":
(397000, "30478bcadb6439e1247451c4ac706b6e1385044dd0f12d6486b6d7057929453b"),
}
DELIVERABLES = (
"docs/runtime/phase-0.9e-r-official-release-correlation.md",
"docs/runtime/phase-0.9e-r-release-source-binding.md",
"docs/runtime/phase-0.9e-r-port9020-source-audit.md",
"docs/runtime/phase-0.9e-r-official-hostsender-audit.md",
"docs/runtime/phase-0.9e-r-provenance-gaps.md",
"docs/approvals/phase-0.9e-r-y2jb-deployed-use-attestation.md",
"manifests/runtime/phase-0.9e-r-release-correlation.json",
"manifests/runtime/phase-0.9e-r-release-correlation.schema.json",
"manifests/runtime/phase-0.9e-r-port9020-audit.json",
"manifests/runtime/phase-0.9e-r-port9020-audit.schema.json",
"tools/validate_phase09er_provenance.py",
"tests/test_phase09er_provenance.py",
"packaging/phase09er/SHA256SUMS.txt",
)
FORBIDDEN_SUFFIXES = {
".c", ".cc", ".cpp", ".s", ".asm", ".ld", ".elf", ".self", ".sprx",
".pkg", ".bin", ".wasm",
}
FORBIDDEN_PREFIXES = ("include/", "src/", "adapters/", "samples/")
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as stream:
value = json.load(stream)
if not isinstance(value, dict):
raise ValueError(f"{path} does not contain a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
check=False,
capture_output=True,
text=True,
)
if result.returncode != 0:
raise RuntimeError(result.stderr.strip() or "git command failed")
return result.stdout.strip()
def candidate_archive_path(root: Path) -> Path:
direct = Path.home() / "Downloads" / OUTER_NAME
if direct.is_file():
return direct
for ancestor in (root, *root.parents):
if ancestor.parent.name.lower() == "users":
return ancestor / "Downloads" / OUTER_NAME
return direct
def official_byte_match(
*,
official_source: bool,
local_name: str,
local_size: int,
local_sha256: str,
asset_name: str,
asset_size: int,
asset_sha256: str,
) -> bool:
"""Only exact official name, byte count, and hash establish a match."""
return (
official_source
and local_name == asset_name
and local_size == asset_size
and local_sha256 == asset_sha256
)
def source_binding(
*, release_associated: bool, inner_bytes_matched: bool, inner_opaque: bool
) -> str:
if inner_bytes_matched:
return "REPRODUCIBLE_CONTENT_BINDING"
if release_associated and inner_opaque:
return "SOURCE_ONLY_ASSOCIATION"
if release_associated:
return "OFFICIAL_RELEASE_ASSOCIATION"
return "NO_LOCAL_RELEASE_ASSOCIATION"
def port_implementation_sufficient(classification: str) -> bool:
return classification in {
"PORT_9020_IMPLEMENTATION_FOUND",
"PORT_9020_IMPLEMENTATION_PARTIAL",
}
def phase09f_design_allowed(
*,
correlation: str,
release_commit_known: bool,
upstream_clean: bool,
port_classification: str,
sender_identified: bool,
attestation_available: bool,
all_authorizations_false: bool,
) -> bool:
return all(
(
correlation == "OFFICIAL_RELEASE_BYTE_MATCH",
release_commit_known,
upstream_clean,
port_implementation_sufficient(port_classification),
sender_identified,
attestation_available,
all_authorizations_false,
)
)
def sender_duplex(*, sends: bool, receives: bool) -> bool:
return sends and receives
def sender_short_send_deficiency(*, uses_sendall: bool, explicit_send_loop: bool) -> bool:
return not (uses_sendall or explicit_send_loop)
def attestation_is_runtime_proof(*, attested: bool, hardware_observed: bool) -> bool:
return attested and hardware_observed
def _type_matches(value: Any, expected: str | list[str]) -> bool:
if isinstance(expected, list):
return any(_type_matches(value, item) for item in expected)
checks = {
"object": isinstance(value, dict),
"array": isinstance(value, list),
"string": isinstance(value, str),
"boolean": isinstance(value, bool),
"integer": isinstance(value, int) and not isinstance(value, bool),
"null": value is None,
}
return checks.get(expected, True)
def validate_schema_instance(
schema: dict[str, Any], instance: Any, path: str = "$"
) -> list[str]:
errors: list[str] = []
expected_type = schema.get("type")
if expected_type is not None and not _type_matches(instance, expected_type):
return [f"{path}: type mismatch"]
if "const" in schema and instance != schema["const"]:
errors.append(f"{path}: const mismatch")
if "enum" in schema and instance not in schema["enum"]:
errors.append(f"{path}: outside enum")
if isinstance(instance, dict):
for required in schema.get("required", []):
if required not in instance:
errors.append(f"{path}: missing {required}")
properties = schema.get("properties", {})
for key, value in instance.items():
if key in properties:
errors.extend(
validate_schema_instance(properties[key], value, f"{path}.{key}")
)
elif isinstance(schema.get("additionalProperties"), dict):
errors.extend(
validate_schema_instance(
schema["additionalProperties"], value, f"{path}.{key}"
)
)
if isinstance(instance, list) and len(instance) < schema.get("minItems", 0):
errors.append(f"{path}: too few items")
return errors
def validate_release_manifest(manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
expected = {
"phase": PHASE,
"status": "DESIGN_ONLY",
"baseline_commit": BASELINE,
"release_correlation": "OFFICIAL_RELEASE_NO_MATCH",
"final_classification": FINAL_CLASSIFICATION,
"identified_release": None,
"identified_release_asset": None,
"inner_content_binding": "SIECAF_OPAQUE_UNBOUND",
"phase09f_offline_design_allowed": False,
}
for field, value in expected.items():
if manifest.get(field) != value:
errors.append(f"{field} changed")
for field in AUTHORIZATION_FIELDS:
if manifest.get("authorization", {}).get(field) is not False:
errors.append(f"authorization.{field} must be false")
local = manifest.get("local_candidate", {})
if (
local.get("file_name") != OUTER_NAME
or local.get("size") != OUTER_SIZE
or local.get("sha256") != OUTER_SHA256
):
errors.append("local candidate identity changed")
inner = manifest.get("inner_archive", {})
if (
inner.get("size") != INNER_SIZE
or inner.get("sha256") != INNER_SHA256
or inner.get("classification") != "OPAQUE_UNBOUND"
or inner.get("further_reverse_engineering_performed") is not False
):
errors.append("inner SIECAF boundary changed")
assets = manifest.get("assets", [])
if len(assets) != 7:
errors.append("official asset inventory must contain seven assets")
for asset in assets:
if not re.fullmatch(r"[0-9a-f]{64}", str(asset.get("sha256", ""))):
errors.append(f"official asset digest malformed: {asset.get('name')}")
if asset.get("classification") != "NO_MATCH" or asset.get("downloaded"):
errors.append(f"asset was not metadata-excluded: {asset.get('name')}")
if official_byte_match(
official_source=True,
local_name=OUTER_NAME,
local_size=OUTER_SIZE,
local_sha256=OUTER_SHA256,
asset_name=str(asset.get("name")),
asset_size=int(asset.get("size", -1)),
asset_sha256=str(asset.get("sha256")),
):
errors.append(f"unrecorded official byte match: {asset.get('name')}")
tags = manifest.get("tags", [])
if len(tags) != 5:
errors.append("official tag inventory must contain five tags")
for tag in tags:
if not re.fullmatch(r"[0-9a-f]{40}", str(tag.get("commit", ""))):
errors.append(f"tag commit is not exact: {tag.get('tag')}")
if not re.fullmatch(r"[0-9a-f]{64}", str(tag.get("source_archive_sha256", ""))):
errors.append(f"source archive hash missing: {tag.get('tag')}")
if len(manifest.get("release_inventory", [])) != 6:
errors.append("release inventory must cover versions 1.2 through 1.6")
provenance = manifest.get("artifact_provenance", [])
if len(provenance) < 6:
errors.append("artifact provenance inventory is incomplete")
for artifact in provenance:
missing = [field for field in PROVENANCE_FIELDS if field not in artifact]
if missing:
errors.append(
f"{artifact.get('logical_name')}: missing provenance fields {missing}"
)
if artifact.get("confidence") == "EXACT_USED":
errors.append(
f"{artifact.get('logical_name')}: deployed-use provenance overclaimed"
)
if artifact.get("logical_name") == "official_embedded_elfldr_1_6":
if artifact.get("source_commit") is not None:
errors.append("embedded elfldr received an invented source commit")
worktree = manifest.get("upstream_worktree", {})
if (
worktree.get("commit") != UPSTREAM_COMMIT
or worktree.get("tree") != UPSTREAM_TREE
or worktree.get("clean") is not True
or worktree.get("submodules") != 0
or worktree.get("git_lfs_pointers") != 0
):
errors.append("official upstream worktree record changed")
sender = manifest.get("official_host_sender", {})
if (
sender.get("response_read") is not False
or sender.get("duplex") is not False
or sender.get("deployed_use_attested") is not False
):
errors.append("official sender was overclaimed")
if manifest.get("operator_attestation", {}).get("attested") is not False:
errors.append("operator attestation must remain empty")
actions = manifest.get("actions", {})
expected_false_actions = (
"downloaded_code_executed",
"dependency_installed",
"ps5_connected",
"ps5_ip_used",
"device_request_performed",
"files_transferred_to_or_from_ps5",
"target_build_performed",
"target_code_created",
"target_artifact_created",
"payload_created",
"device_client_created",
)
for field in expected_false_actions:
if actions.get(field) is not False:
errors.append(f"actions.{field} must be false")
if (
actions.get("large_release_assets_downloaded") != 0
or actions.get("large_release_asset_bytes_downloaded") != 0
):
errors.append("large release asset download was recorded")
if manifest.get("blocking_state", {}).get("payload_manager_backup") != (
"HARD_BLOCKER_FOR_INSTALLATION"
):
errors.append("Payload Manager installation blocker changed")
if phase09f_design_allowed(
correlation=str(manifest.get("release_correlation")),
release_commit_known=False,
upstream_clean=True,
port_classification=PORT_9020_CLASSIFICATION,
sender_identified=True,
attestation_available=True,
all_authorizations_false=True,
):
errors.append("Phase 0.9F incorrectly passed")
return errors
def validate_port_manifest(manifest: dict[str, Any]) -> list[str]:
errors: list[str] = []
if manifest.get("phase") != PHASE or manifest.get("status") != "DESIGN_ONLY":
errors.append("port manifest phase/status changed")
if manifest.get("release_commit") != UPSTREAM_COMMIT:
errors.append("port manifest release commit changed")
if manifest.get("port_9020_classification") != PORT_9020_CLASSIFICATION:
errors.append("port-9020 implementation was overclaimed")
if (
manifest.get("port_9020_listener_found") is not False
or manifest.get("port_9020_parser_found") is not False
or manifest.get("port_9020_mapping_found") is not False
):
errors.append("port-9020 source was invented")
loader = manifest.get("official_remote_js_loader", {})
if (
loader.get("desired_dynamic_port") != 50000
or loader.get("maximum_receive_bytes") != 512000
or loader.get("framing") != "CONNECTION_EOF_OR_BUFFER_LIMIT"
or loader.get("declared_length") is not False
or loader.get("timeout") is not False
or loader.get("native_elf_mapping") is not False
):
errors.append("Remote JS Loader contract changed")
if loader.get("automatic_retry_authorized") is not False:
errors.append("automatic retry was authorized")
relation = manifest.get("port_9021_relation", {})
if relation.get("listener_source_in_y2jb") is not False:
errors.append("embedded 9021 listener source was invented")
if relation.get("source_commit") is not None:
errors.append("embedded elfldr received an invented source commit")
sender = manifest.get("official_sender", {})
if sender.get("response_read") is not False or sender.get("duplex") is not False:
errors.append("one-way sender was classified duplex")
for field in AUTHORIZATION_FIELDS:
if manifest.get("authorization", {}).get(field) is not False:
errors.append(f"port authorization.{field} must be false")
if manifest.get("phase09f_offline_design_allowed") is not False:
errors.append("Phase 0.9F was authorized")
return errors
def changed_paths(root: Path) -> set[str]:
paths = set(git(root, "diff", "--name-only", BASELINE).splitlines())
for line in git(root, "status", "--porcelain=v1", "--untracked-files=all").splitlines():
path = line[3:]
if " -> " in path:
path = path.split(" -> ", 1)[1]
paths.add(path.replace("\\", "/"))
return {path for path in paths if path}
def phase09er_path_errors(paths: set[str]) -> list[str]:
errors: list[str] = []
for path in paths:
normalized = path.replace("\\", "/")
lowered = normalized.lower()
if normalized.startswith(FORBIDDEN_PREFIXES):
errors.append(f"target/production path changed: {normalized}")
if Path(normalized).suffix.lower() in FORBIDDEN_SUFFIXES:
errors.append(f"target artifact/source added: {normalized}")
if any(
token in lowered
for token in (
"rescue.elf", "observer.elf", "readback.elf", "executionpackage",
"installpackage", "transferpackage",
)
):
errors.append(f"forbidden Phase-0.9E-R output: {normalized}")
return errors
def validate_checksum_file(root: Path) -> list[str]:
checksum_path = root / "packaging/phase09er/SHA256SUMS.txt"
if not checksum_path.is_file():
return ["missing packaging/phase09er/SHA256SUMS.txt"]
errors: list[str] = []
for line in checksum_path.read_text(encoding="utf-8").splitlines():
if not line or line.startswith("#"):
continue
parts = line.split(" ", 1)
if len(parts) != 2 or not re.fullmatch(r"[0-9a-f]{64}", parts[0]):
errors.append(f"invalid checksum line: {line}")
continue
expected, relative = parts
path = root / relative
if not path.is_file() or sha256_file(path) != expected:
errors.append(f"checksum mismatch or missing: {relative}")
return errors
def collect_errors(root: Path) -> list[str]:
errors: list[str] = []
release_path = root / "manifests/runtime/phase-0.9e-r-release-correlation.json"
port_path = root / "manifests/runtime/phase-0.9e-r-port9020-audit.json"
release_schema_path = (
root / "manifests/runtime/phase-0.9e-r-release-correlation.schema.json"
)
port_schema_path = (
root / "manifests/runtime/phase-0.9e-r-port9020-audit.schema.json"
)
try:
release = load_json(release_path)
port = load_json(port_path)
release_schema = load_json(release_schema_path)
port_schema = load_json(port_schema_path)
except (OSError, ValueError, json.JSONDecodeError) as error:
return [str(error)]
errors.extend(validate_schema_instance(release_schema, release))
errors.extend(validate_schema_instance(port_schema, port))
errors.extend(validate_release_manifest(release))
errors.extend(validate_port_manifest(port))
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
if git(root, "rev-parse", "--abbrev-ref", "HEAD") != BRANCH:
errors.append("current branch is not the Phase-0.9E-R branch")
if git(root, "merge-base", BASELINE, "HEAD") != BASELINE:
errors.append("branch no longer descends from the canonical baseline")
if sha256_file(root / "manifests/artifact-denylist.json") != DENYLIST_SHA256:
errors.append("permanent artifact denylist changed")
for relative, expected in IMMUTABLE_HASHES.items():
path = root / relative
if not path.is_file() or sha256_file(path) != expected:
errors.append(f"immutable evidence changed: {relative}")
outer = candidate_archive_path(root)
if not outer.is_file():
errors.append(f"local Y2JB candidate missing: {outer}")
elif outer.stat().st_size != OUTER_SIZE or sha256_file(outer) != OUTER_SHA256:
errors.append("local Y2JB outer identity changed")
else:
try:
with zipfile.ZipFile(outer) as archive:
info = archive.getinfo(INNER_NAME)
if (
len(archive.infolist()) != 5
or archive.comment != b""
or info.file_size != INNER_SIZE
or info.compress_size != 504158629
or info.CRC != int("522808c8", 16)
):
errors.append("local ZIP metadata changed")
digest = hashlib.sha256()
magic = b""
with archive.open(info) as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
if not magic:
magic = chunk[:6]
digest.update(chunk)
if magic != b"SIECAF" or digest.hexdigest() != INNER_SHA256:
errors.append("inner SIECAF identity changed")
except (OSError, KeyError, zipfile.BadZipFile) as error:
errors.append(f"local ZIP validation failed: {error}")
upstream = root / "work/upstream/Y2JB-official"
if not upstream.is_dir():
errors.append("official immutable upstream worktree missing")
else:
if git(upstream, "rev-parse", "HEAD") != UPSTREAM_COMMIT:
errors.append("official upstream HEAD changed")
if git(upstream, "rev-parse", "HEAD^{tree}") != UPSTREAM_TREE:
errors.append("official upstream tree changed")
if git(upstream, "status", "--porcelain=v1"):
errors.append("official upstream worktree is dirty")
remotes = git(upstream, "remote", "-v")
if UPSTREAM_REMOTE not in remotes:
errors.append("official upstream remote changed")
if git(upstream, "submodule", "status"):
errors.append("unexpected official upstream submodule")
if len(git(upstream, "ls-files").splitlines()) != 19:
errors.append("official upstream tracked file inventory changed")
for relative, (expected_size, expected_hash) in UPSTREAM_FILE_HASHES.items():
path = upstream / relative
if (
not path.is_file()
or path.stat().st_size != expected_size
or sha256_file(path) != expected_hash
):
errors.append(f"official upstream file identity changed: {relative}")
errors.extend(phase09er_path_errors(changed_paths(root)))
for path in root.rglob("*"):
if (
path.is_file()
and ".git" not in path.parts
and "work" not in path.parts
and path.stat().st_size > 50 * 1024 * 1024
):
errors.append(f"large release-like object present in repository: {path}")
errors.extend(validate_checksum_file(root))
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
errors = collect_errors(args.root.resolve())
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print("Phase-0.9E-R official Y2JB provenance validation: PASS")
print(f"Release correlation: OFFICIAL_RELEASE_NO_MATCH")
print(f"Port 9020: {PORT_9020_CLASSIFICATION}")
print(f"Decision: {FINAL_CLASSIFICATION}")
print("Device actions: NONE")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+326
View File
@@ -0,0 +1,326 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the offline Phase-1.0A RetroArch PS5 port evidence."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess
import sys
from typing import Any
PHASE = "PHASE_1_0A_RETROARCH_PS5_PORT_BOOTSTRAP"
STATUS = "RETROARCH_PS5_SOFTWARE_PORT_BUILT"
BASELINE = "4c086f84ab2e7c53e6750b66b3b3e1f591ff6a06"
BRANCH = "codex/chimera-gfx-phase10a-retroarch-port-bootstrap"
RETROARCH_BRANCH = "codex/ps5-port-bootstrap"
RETROARCH_TAG = "v1.22.2"
RETROARCH_COMMIT = "69a4f0ea1e8aaf442ae4858f2e7f2b31a1776576"
RETROARCH_TREE = "33babf9eb7699b5d571a3063ea21c3e488c159fe"
RETROARCH_ARCHIVE_SHA256 = (
"245ef18c8fa8fbd9fbb5eb25cf43e17c6aace2f95c1ed99873cbd794012bb232"
)
SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37"
SDL_COMMIT = "0baf4ac49382b537ba449901b5b6d0d189bb1fbb"
PACBREW_COMMIT = "c2abcfcb60f569128abd0e8e70ad03a67bee5ea7"
DENYLIST_SHA256 = "e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
OFFLINE_AUTHORIZATION_FIELDS = (
"offline_source_acquisition_authorized",
"offline_source_modification_authorized",
"offline_target_build_authorized",
"offline_artifact_analysis_authorized",
"private_gitea_push_authorized",
)
DEVICE_AUTHORIZATION_FIELDS = (
"ps5_connection_authorized",
"device_transfer_authorized",
"device_execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"device_write_authorized",
"automatic_retry",
)
DELIVERABLES = (
"docs/retroarch/phase-1.0a-port-plan.md",
"docs/retroarch/phase-1.0a-upstream-analysis.md",
"docs/retroarch/phase-1.0a-ps4-reference-delta.md",
"docs/retroarch/phase-1.0a-pacbrew-sdl-analysis.md",
"docs/retroarch/phase-1.0a-build-results.md",
"docs/retroarch/phase-1.0a-driver-status.md",
"docs/retroarch/phase-1.0a-next-device-smoke-test.md",
"manifests/retroarch/upstreams.json",
"manifests/retroarch/phase-1.0a-build.json",
"manifests/retroarch/phase-1.0a-artifacts.json",
"tests/test_retroarch_phase10a.py",
"tools/validate_retroarch_phase10a.py",
"packaging/retroarch/phase10a/SHA256SUMS.txt",
)
REQUIRED_REAL_SYMBOLS = {
"rarch_main",
"retroarch_main_init",
"runloop_iterate",
"retro_init",
"retro_deinit",
"retro_run",
"frontend_ctx_ps5",
}
DISABLED_FEATURES = {
"networking",
"online_updater",
"dynamic_cores",
"autoload",
"installation",
"gnm",
"opengl",
"vulkan",
}
FORBIDDEN_MARKERS = (
"chimera_lifecycle_probe",
"prospero-deploy",
"payload_sender",
"sceSystemServiceLoadExec",
)
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as stream:
value = json.load(stream)
if not isinstance(value, dict):
raise ValueError(f"{path} is not a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def artifact_execution_allowed(record: dict[str, Any]) -> bool:
return bool(record.get("execution_eligible", False))
def route_is_forbidden(text: str) -> bool:
lowered = text.lower()
return any(marker.lower() in lowered for marker in FORBIDDEN_MARKERS)
def profile_is_closed(profile: dict[str, Any]) -> bool:
disabled = set(profile.get("disabled_features", []))
return (
DISABLED_FEATURES.issubset(disabled)
and profile.get("automatic_retry") is False
and profile.get("filesystem_writes_on_default_path") is False
)
def is_real_retroarch_artifact(record: dict[str, Any]) -> bool:
return REQUIRED_REAL_SYMBOLS.issubset(set(record.get("required_symbols", [])))
def has_personal_path(strings: list[str]) -> bool:
patterns = (
re.compile(r"[A-Za-z]:\\Users\\", re.IGNORECASE),
re.compile(r"/(?:mnt/[a-z]/)?Users/[^/]+/", re.IGNORECASE),
re.compile(r"/home/[^/]+/", re.IGNORECASE),
)
return any(pattern.search(value) for value in strings for pattern in patterns)
def has_ip_address(strings: list[str]) -> bool:
pattern = re.compile(r"(?<!\d)(?:\d{1,3}\.){3}\d{1,3}(?!\d)")
return any(pattern.search(value) for value in strings)
def validate_artifact(record: dict[str, Any]) -> list[str]:
errors: list[str] = []
name = record.get("name", "<unnamed>")
if artifact_execution_allowed(record):
errors.append(f"{name}: execution_eligible must be false")
if record.get("target_execution_performed") is not False:
errors.append(f"{name}: target execution state is not false")
if record.get("reproducibility") != "BYTE_IDENTICAL_TWO_CLEAN_BUILDS":
errors.append(f"{name}: reproducibility is not byte exact")
if not is_real_retroarch_artifact(record):
errors.append(f"{name}: real RetroArch symbols are incomplete")
if len(record.get("sha256", "")) != 64 or record.get("size", 0) <= 0:
errors.append(f"{name}: invalid size/hash identity")
if not record.get("linker_map_sha256"):
errors.append(f"{name}: linker map identity is missing")
if not isinstance(record.get("undefined_symbols"), list):
errors.append(f"{name}: undefined-symbol inventory is missing")
if record.get("embedded_personal_paths") is not False:
errors.append(f"{name}: personal path audit did not pass")
if not isinstance(record.get("embedded_ip_addresses"), list):
errors.append(f"{name}: IP-address inventory is missing")
if record.get("embedded_device_ip_addresses") is not False:
errors.append(f"{name}: a device/private address is embedded")
if record.get("forbidden_markers_found"):
errors.append(f"{name}: forbidden marker found")
return errors
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
capture_output=True,
text=True,
check=False,
)
if result.returncode:
raise RuntimeError(result.stderr.strip() or "git command failed")
return result.stdout.strip()
def validate(root: Path, retroarch_root: Path | None = None) -> list[str]:
errors: list[str] = []
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
try:
build = load_json(root / "manifests/retroarch/phase-1.0a-build.json")
artifacts_doc = load_json(
root / "manifests/retroarch/phase-1.0a-artifacts.json"
)
upstreams = load_json(root / "manifests/retroarch/upstreams.json")
except (OSError, ValueError, json.JSONDecodeError) as error:
return errors + [str(error)]
if build.get("phase") != PHASE or build.get("status") != STATUS:
errors.append("phase/status mismatch")
if build.get("baseline_commit") != BASELINE:
errors.append("baseline mismatch")
if build.get("branch") != BRANCH:
errors.append("branch mismatch")
for field in OFFLINE_AUTHORIZATION_FIELDS:
if build.get(field) is not True:
errors.append(f"{field} must record the explicit offline grant")
for field in DEVICE_AUTHORIZATION_FIELDS:
if build.get(field) is not False:
errors.append(f"{field} must remain false")
for field in (
"ps5_connected",
"device_request_performed",
"files_transferred",
"device_write_performed",
"target_execution_performed",
"install_package_created",
"execution_package_created",
):
if build.get(field) is not False:
errors.append(f"{field} must remain false")
fork = build.get("chimera_retroarch", {})
if fork.get("branch") != RETROARCH_BRANCH or len(fork.get("commit", "")) != 40:
errors.append("private fork identity is incomplete")
if fork.get("working_tree_clean") is not True:
errors.append("private fork was not clean at final build")
profiles = build.get("profiles", {})
for name in (
"ps5-headless-smokecore",
"ps5-software-rgui-smokecore",
"host-smokecore-integration",
):
if name not in profiles or not profile_is_closed(profiles[name]):
errors.append(f"profile is not closed: {name}")
host = build.get("host_tests", {})
if (
host.get("frames") != 600
or host.get("video_fnv1a64") != "43f920496eb5f435"
or host.get("audio_fnv1a64") != "a48f47dc08c56625"
or host.get("asan_ubsan") != "PASS"
or host.get("input_mapping") != "PASS"
or host.get("clean_shutdown") != "PASS"
):
errors.append("host smoke-core evidence mismatch")
expected_upstreams = {
"retroarch": RETROARCH_COMMIT,
"ps5_payload_sdk": SDK_COMMIT,
"ps5_sdl": SDL_COMMIT,
"pacbrew": PACBREW_COMMIT,
}
for name, commit in expected_upstreams.items():
if upstreams.get("sources", {}).get(name, {}).get("commit") != commit:
errors.append(f"upstream mismatch: {name}")
retroarch = upstreams.get("sources", {}).get("retroarch", {})
if (
retroarch.get("tag") != RETROARCH_TAG
or retroarch.get("tree") != RETROARCH_TREE
or retroarch.get("source_archive_sha256") != RETROARCH_ARCHIVE_SHA256
):
errors.append("RetroArch release provenance mismatch")
records = artifacts_doc.get("artifacts", [])
if {item.get("name") for item in records} != {
"retroarch_ps5_headless.elf",
"retroarch_ps5_software.elf",
}:
errors.append("artifact set mismatch")
for record in records:
errors.extend(validate_artifact(record))
denylist = root / "manifests/artifact-denylist.json"
if not denylist.is_file() or sha256_file(denylist) != DENYLIST_SHA256:
errors.append("permanent denylist changed")
tracked = git(root, "ls-files").splitlines()
forbidden_suffixes = (".elf", ".self", ".sprx", ".pkg")
for relative in tracked:
if relative.lower().endswith(forbidden_suffixes):
errors.append(f"tracked target artifact: {relative}")
new_text = "\n".join(
(root / relative).read_text(encoding="utf-8", errors="replace")
for relative in DELIVERABLES
if (root / relative).is_file()
)
unfinished_template = "{" * 2
unfinished_label = "".join(("T", "B", "D"))
if unfinished_template in new_text or unfinished_label in new_text:
errors.append("unfinished placeholder in deliverables")
if retroarch_root is not None:
for record in records:
path = retroarch_root / record["local_relative_path"]
if not path.is_file():
errors.append(f"local artifact missing: {path}")
continue
if path.stat().st_size != record["size"] or sha256_file(path) != record[
"sha256"
]:
errors.append(f"local artifact identity mismatch: {path.name}")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path)
args = parser.parse_args()
errors = validate(
args.root.resolve(),
args.retroarch_root.resolve() if args.retroarch_root else None,
)
if errors:
for error in errors:
print(error, file=sys.stderr)
return 1
print("Phase 1.0A RetroArch evidence validated")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+204
View File
@@ -0,0 +1,204 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AA offline fake-adapter integration evidence."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
from typing import Any
PHASE = "PHASE_1_0AA_OFFLINE_FAKE_ADAPTER_INTEGRATION"
STATUS = "OFFLINE_FAKE_BATCH_INTEGRATION_COMPLETE_LIVE_ADAPTER_BLOCKED"
START_COMMIT = "57ff9a1c5937575b00df05f2cd9897118eab1f2a"
SOURCE_BINDINGS = {
"phase10x_transport_size": 8040,
"phase10x_transport_sha256": "568d7578482ecf2fcd9e29085b2eb9d8705fc699611508acdf22afd30f2ddd23",
"phase10z_contract_size": 10487,
"phase10z_contract_sha256": "0728c2be7f368e0a7f4b68efe86f6e0c5c2f50704a41d0e1992b0bfec19dde06",
"phase10aa_integration_size": 11200,
"phase10aa_integration_sha256": "8e1cac255f85d2cd14baf8fbc27d631c9b607fc7d19fc57c65462089f0574055",
"phase10aa_integration_tests_size": 10667,
"phase10aa_integration_tests_sha256": "18a5470a651fcbe4b23f2a68cba499dd19d3da15a229623c054be0b598025699",
}
SOURCE_FILES = {
"phase10x_transport": "tools/phase10x_inactive_transport.py",
"phase10z_contract": "tools/phase10z_passive_batch_contract.py",
"phase10aa_integration": "tools/phase10aa_offline_fake_batch.py",
"phase10aa_integration_tests": "tests/test_phase10aa_offline_fake_batch.py",
}
AUTHORIZATION_FIELDS = {
"target_build_authorized", "ps5_connection_authorized",
"device_request_authorized", "result_receive_authorized",
"device_transfer_authorized", "device_execution_authorized",
"installation_authorized", "autoload_authorized",
"device_write_authorized", "automatic_retry", "reconnect_authorized",
"resume_authorized",
}
NETWORK_MODULES = {
"socket", "asyncio", "selectors", "urllib", "http", "ftplib",
"requests", "telnetlib", "paramiko",
}
def load_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise ValueError("Phase-1.0AA manifest is not an object")
return value
def exact_file(path: Path, size: int, digest: str) -> bool:
try: payload = path.read_bytes()
except OSError: return False
return len(payload) == size and hashlib.sha256(payload).hexdigest() == digest
def _imports(tree: ast.AST) -> set[str]:
values: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
values.update(alias.name.split(".")[0] for alias in node.names)
elif isinstance(node, ast.ImportFrom) and node.module:
values.add(node.module.split(".")[0])
return values
def validate_record(record: dict[str, Any], root: Path | None = None) -> list[str]:
errors: list[str] = []
if record.get("phase") != PHASE or record.get("status") != STATUS:
errors.append("phase/status mismatch")
if record.get("start_commit") != START_COMMIT:
errors.append("start commit mismatch")
if record.get("activation") != {
"active": False, "integration_sha256": None, "run_id": None,
"target_address": None, "target_port": None, "window": None,
"deadline_seconds": None,
}:
errors.append("activation is not inert")
if record.get("source_bindings") != SOURCE_BINDINGS:
errors.append("source bindings mismatch")
if record.get("fake_boundary") != {
"exact_builtin_adapter_required": True,
"adapter_subclasses_allowed": False,
"exact_builtin_clock_required": True,
"clock_subclasses_allowed": False,
"exact_fake_evidence_store_required": True,
"live_adapter_protocol_present": False,
"network_import_present": False,
"real_clock_present": False,
"target_present": False,
"cli_present": False,
"maximum_fake_events": 257,
"event_kinds": ["DATA", "HARD_DEADLINE", "REMOTE_EOF", "BLOCKED"],
}:
errors.append("fake boundary mismatch")
if record.get("ordering_contract") != {
"receipt_before_fake_open": True, "fake_open_count": 1,
"complete_batch_send_count": 1, "fake_close_count": 1,
"completion_event": "SYNTHETIC_HARD_DEADLINE_ONLY",
"early_deadline": "INVALID", "remote_eof": "INVALID",
"blocked_receive": "INVALID", "missing_deadline": "INVALID",
"data_at_or_after_deadline": "INVALID", "partial_result": "INVALID",
"incoming_iac": "INVALID", "retry_allowed": False,
"reconnect_allowed": False, "resume_allowed": False,
}:
errors.append("ordering contract mismatch")
evidence = record.get("evidence_contract", {})
if evidence != {
"exclusive_create": True, "consumed_receipt_retained_on_failure": True,
"failure_output_created": False, "sanitized_output_receipt_bound": True,
"batch_sha256_recorded": True, "batch_size_recorded": True,
"target_retained": False, "raw_transcript_persisted": False,
"logical_event_buffer_discarded": True,
"physical_memory_erasure_proven": False,
"directory_entry_durability_proven": False,
"device_behavior_proven": False, "exact_identity_proven": False,
}:
errors.append("evidence contract mismatch")
authority = record.get("authorizations", {})
if set(authority) != AUTHORIZATION_FIELDS or any(
authority.get(field) is not False for field in AUTHORIZATION_FIELDS):
errors.append("authorization fields are not exactly false")
if record.get("decision") != {
"offline_fake_batch_integration_complete": True,
"live_adapter_created": False, "live_adapter_allowed": False,
"live_collection_allowed": False, "device_action_allowed": False,
"phase10ab_offline_live_adapter_feasibility_review_allowed": True,
"next_step": "OFFLINE_LIVE_ADAPTER_TIMEOUT_AND_CLEANUP_FEASIBILITY_REVIEW",
}:
errors.append("decision mismatch")
performed = record.get("performed_actions", {})
if not performed or any(value is not False for value in performed.values()):
errors.append("performed actions are missing or true")
if record.get("tests") != {
"chimera_gfx_ctest": "89_OF_89_PASS", "phase10aa_guardrails": 20,
"phase10aa_integration_tests": 25, "safety_audit": "PASS",
"secret_scan": "PASS", "network_required_by_tests": False,
"hardware_claim_from_host_test": False,
}:
errors.append("test evidence mismatch")
if root is not None:
for prefix, relative in SOURCE_FILES.items():
if not exact_file(root / relative, SOURCE_BINDINGS[f"{prefix}_size"],
SOURCE_BINDINGS[f"{prefix}_sha256"]):
errors.append(f"source identity mismatch: {relative}")
source_path = root / SOURCE_FILES["phase10aa_integration"]
try:
source = source_path.read_text(encoding="utf-8")
tree = ast.parse(source)
except (OSError, SyntaxError, UnicodeError):
errors.append("integration source cannot be parsed")
else:
if _imports(tree) & NETWORK_MODULES or "time" in _imports(tree):
errors.append("integration imports network or real-clock support")
names = {node.name for node in ast.walk(tree)
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))}
if {"main", "connect", "recv", "open_socket"} & names:
errors.append("integration exposes a live API or CLI")
if "target_address" in source or "target_port" in source:
errors.append("integration contains target fields")
required_shapes = (
"type(adapter) is not OfflineFakeBatchAdapter",
"type(clock) is not OfflineFakeClock",
"type(evidence) is not OfflineFakeEvidenceStore",
"receipt = evidence.create_fake_consumed_receipt",
"adapter.send_one_batch(batch)",
"accumulator.seal_at_hard_deadline(True)",
)
if any(shape not in source for shape in required_shapes):
errors.append("exact fake ordering source shape is missing")
approval = (root / "docs/approvals/phase-1.0aa-offline-fake-adapter.md").read_text(encoding="utf-8")
if "active=false" not in approval or "attested=false" not in approval or \
"ps5_connection_authorized=false" not in approval:
errors.append("approval template is not inert")
for base in (root / "tools", root / "tests", root / "docs", root / "manifests"):
if any(path.is_file() and path.suffix.lower() in {".elf", ".self", ".sprx", ".pkg"} for path in base.rglob("*")):
errors.append("target artifact exists in a Phase-1.0AA output area")
break
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args(); root = args.root.resolve()
try:
record = load_json(root / "manifests/retroarch/phase-1.0aa-offline-fake-adapter.json")
errors = validate_record(record, root)
except (OSError, ValueError, json.JSONDecodeError) as error:
errors = [f"validation input failed: {error}"]
if errors:
for error in errors: print(f"ERROR: {error}")
return 1
print("Phase-1.0AA offline fake-adapter validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+146
View File
@@ -0,0 +1,146 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AB offline live-adapter feasibility evidence."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
from typing import Any
PHASE = "PHASE_1_0AB_OFFLINE_LIVE_ADAPTER_FEASIBILITY"
STATUS = "PARTIAL_FEASIBILITY_LIVE_IMPLEMENTATION_BLOCKED"
START_COMMIT = "06d2fe831959b71562401722ae36821faa197636"
MODEL_SIZE = 8738
MODEL_SHA256 = "7d1aa32d49b91b1e5cf3a085dda033767bdf17ab34389ff044f7403f86287959"
MODEL_TEST_SIZE = 7558
MODEL_TEST_SHA256 = "39597e991b15bcfa9aa28cb2f68c87ed048c38482c6dbf81a28c56ccfceb0a48"
NETWORK_MODULES = {"socket", "selectors", "select", "asyncio", "urllib", "http", "requests", "telnetlib"}
AUTHORIZATION_FIELDS = {
"target_build_authorized", "ps5_connection_authorized",
"device_request_authorized", "result_receive_authorized",
"device_transfer_authorized", "device_execution_authorized",
"installation_authorized", "autoload_authorized",
"device_write_authorized", "automatic_retry", "reconnect_authorized",
"resume_authorized",
}
def load_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict): raise ValueError("Phase-1.0AB manifest is not an object")
return value
def exact_file(path: Path, size: int, digest: str) -> bool:
try: payload = path.read_bytes()
except OSError: return False
return len(payload) == size and hashlib.sha256(payload).hexdigest() == digest
def _imports(tree: ast.AST) -> set[str]:
values=set()
for node in ast.walk(tree):
if isinstance(node, ast.Import): values.update(alias.name.split(".")[0] for alias in node.names)
elif isinstance(node, ast.ImportFrom) and node.module: values.add(node.module.split(".")[0])
return values
def validate_record(record: dict[str, Any], root: Path | None = None,
python_root: Path | None = None) -> list[str]:
errors=[]
if record.get("phase") != PHASE or record.get("status") != STATUS: errors.append("phase/status mismatch")
if record.get("start_commit") != START_COMMIT: errors.append("start commit mismatch")
if record.get("activation") != {"active": False, "trace_model_sha256": None, "target_address": None, "target_port": None, "run_id": None}: errors.append("activation is not inert")
runtime=record.get("local_runtime", {})
if runtime != {
"python_version": "3.13.2", "compiler": "MSC_V_1942_64_BIT_AMD64",
"platform": "WINDOWS", "default_selector": "SelectSelector",
"monotonic_implementation": "QueryPerformanceCounter()", "monotonic": True,
"monotonic_adjustable": False, "reported_resolution_seconds": 1e-7,
"socket_py_size": 38741, "socket_py_sha256": "523695ac3383799547b421b4fe18004de1e80181e97181b6d7a10533b47f4c49",
"selectors_py_size": 20060, "selectors_py_sha256": "b3d6cebd4a3a03b4a614f12f171622ce4e4ba3295b9e8b89e2bde051003106eb",
"socket_pyd_size": 84984, "socket_pyd_sha256": "8daefaff53e6956f5aea5279a7c71f17d8c63e2b0d54031c3b9e82fcb0fb84db",
"select_pyd_size": 32248, "select_pyd_sha256": "baee284995b22d495fd12fa8378077e470978db1522c61bfb9af37fb827f33d1",
}: errors.append("local runtime record mismatch")
if record.get("source_bindings") != {
"phase10aa_integration_sha256": "8e1cac255f85d2cd14baf8fbc27d631c9b607fc7d19fc57c65462089f0574055",
"phase10ab_trace_model_size": MODEL_SIZE, "phase10ab_trace_model_sha256": MODEL_SHA256,
"phase10ab_trace_tests_size": MODEL_TEST_SIZE, "phase10ab_trace_tests_sha256": MODEL_TEST_SHA256,
}: errors.append("source bindings mismatch")
if record.get("feasibility") != {
"receipt_before_socket": "FEASIBLE_FROM_EXISTING_HOST_MODEL",
"numeric_address_only": "DESIGN_REQUIRED",
"nonblocking_before_connect": "FEASIBLE_FROM_LOCAL_RUNTIME",
"pending_connect": "PARTIAL", "complete_send_loop": "FEASIBLE_FROM_LOCAL_RUNTIME",
"bounded_receive_memory": "FEASIBLE_FROM_EXISTING_MODEL",
"hard_wall_clock_deadline": "PARTIAL",
"prompt_independent_completion": "FEASIBLE_FROM_Z",
"remote_eof": "FEASIBLE_FAIL_CLOSED",
"local_descriptor_cleanup": "FEASIBLE_BY_DESIGN",
"remote_shell_cleanup": "UNPROVEN", "retry_reconnect_resume": "EXCLUDED",
}: errors.append("feasibility matrix mismatch")
if record.get("trace_model") != {
"synthetic_input_only": True, "maximum_events": 512,
"maximum_batch_bytes": 1035, "maximum_receive_bytes": 65536,
"maximum_deadline_seconds": 10, "network_import_present": False,
"selector_import_present": False, "real_clock_present": False,
"address_present": False, "cli_present": False, "file_output_present": False,
"exact_identity_proven": False, "device_behavior_proven": False,
}: errors.append("trace model record mismatch")
stops=record.get("hard_stops", {})
if set(stops) != {"live_adapter_implementation","socket_creation","dns","target_retention","connection","request","retry","device_action"} or any(value is not True for value in stops.values()): errors.append("hard stops mismatch")
auth=record.get("authorizations", {})
if set(auth) != AUTHORIZATION_FIELDS or any(auth.get(field) is not False for field in AUTHORIZATION_FIELDS): errors.append("authorization fields are not exactly false")
if record.get("decision") != {
"overall": STATUS, "live_adapter_created": False, "live_adapter_allowed": False,
"device_action_allowed": False, "phase10ac_offline_dormant_syscall_facade_allowed": True,
"next_step": "OFFLINE_DORMANT_TARGET_FREE_ADAPTER_WITH_FAKE_SYSCALLS",
}: errors.append("decision mismatch")
performed=record.get("performed_actions", {})
if not performed or any(value is not False for value in performed.values()): errors.append("performed actions are missing or true")
if record.get("tests") != {
"chimera_gfx_ctest": "92_OF_92_PASS", "phase10ab_guardrails": 20,
"phase10ab_trace_tests": 25, "safety_audit": "PASS", "secret_scan": "PASS",
"network_required_by_tests": False, "hardware_claim_from_host_test": False,
}: errors.append("test evidence mismatch")
if root is not None:
model=root / "tools/phase10ab_nonblocking_trace_model.py"; tests=root / "tests/test_phase10ab_nonblocking_trace_model.py"
if not exact_file(model, MODEL_SIZE, MODEL_SHA256): errors.append("trace model identity mismatch")
if not exact_file(tests, MODEL_TEST_SIZE, MODEL_TEST_SHA256): errors.append("trace tests identity mismatch")
try: source=model.read_text(encoding="utf-8"); tree=ast.parse(source)
except (OSError,SyntaxError,UnicodeError): errors.append("trace model cannot be parsed")
else:
if _imports(tree) & NETWORK_MODULES or "time" in _imports(tree): errors.append("trace model imports live capability")
names={node.name for node in ast.walk(tree) if isinstance(node,(ast.FunctionDef,ast.AsyncFunctionDef))}
if {"main","connect","send","recv"} & names: errors.append("trace model exposes live API")
if "target_address" in source or "target_port" in source: errors.append("trace model contains target fields")
approval=(root / "docs/approvals/phase-1.0ab-live-adapter-feasibility.md").read_text(encoding="utf-8")
if "active=false" not in approval or "ps5_connection_authorized=false" not in approval: errors.append("approval is not inert")
if python_root is not None:
paths={
"socket_py": python_root / "Lib/socket.py", "selectors_py": python_root / "Lib/selectors.py",
"socket_pyd": python_root / "DLLs/_socket.pyd", "select_pyd": python_root / "DLLs/select.pyd",
}
for prefix,path in paths.items():
if not exact_file(path, runtime[f"{prefix}_size"], runtime[f"{prefix}_sha256"]): errors.append(f"local runtime identity mismatch: {prefix}")
return errors
def main() -> int:
parser=argparse.ArgumentParser();parser.add_argument("--root",type=Path,required=True);parser.add_argument("--python-root",type=Path)
args=parser.parse_args();root=args.root.resolve()
try: record=load_json(root / "manifests/retroarch/phase-1.0ab-live-adapter-feasibility.json");errors=validate_record(record,root,args.python_root)
except (OSError,ValueError,json.JSONDecodeError) as error: errors=[f"validation input failed: {error}"]
if errors:
for error in errors: print(f"ERROR: {error}")
return 1
print("Phase-1.0AB offline live-adapter feasibility validation passed");return 0
if __name__ == "__main__": raise SystemExit(main())
+198
View File
@@ -0,0 +1,198 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the inactive Phase-1.0AC dormant-adapter evidence."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
import re
from typing import Any
PHASE = "PHASE_1_0AC_OFFLINE_DORMANT_ADAPTER"
STATUS = "OFFLINE_DORMANT_FAKE_SYSCALL_ADAPTER_COMPLETE_LIVE_ADAPTER_BLOCKED"
START_COMMIT = "3bc8ac09615dda3c4ee3ad02f19440ca9f4f8f96"
ADAPTER_SIZE = 13282
ADAPTER_SHA256 = "6f28926b59fd9afa6de1ff36d4fa9b013d7e027c9adc0bffd9445d7c89acf939"
ADAPTER_TEST_SIZE = 11681
ADAPTER_TEST_SHA256 = "9c8c611dbab5e43df71d523169d9a1bf7579ed1918943df7531bf75ef4b9abfc"
NETWORK_MODULES = {
"socket", "selectors", "select", "asyncio", "urllib", "http",
"requests", "ftplib", "telnetlib", "subprocess",
}
AUTHORIZATION_FIELDS = {
"target_build_authorized", "ps5_connection_authorized",
"device_request_authorized", "result_receive_authorized",
"device_transfer_authorized", "device_execution_authorized",
"installation_authorized", "autoload_authorized",
"device_write_authorized", "automatic_retry", "reconnect_authorized",
"resume_authorized",
}
def load_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise ValueError("Phase-1.0AC manifest is not an object")
return value
def exact_file(path: Path, size: int, digest: str) -> bool:
try:
payload = path.read_bytes()
except OSError:
return False
return len(payload) == size and hashlib.sha256(payload).hexdigest() == digest
def _imports(tree: ast.AST) -> set[str]:
values: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
values.update(alias.name.split(".")[0] for alias in node.names)
elif isinstance(node, ast.ImportFrom) and node.module:
values.add(node.module.split(".")[0])
return values
def validate_record(record: dict[str, Any], root: Path | None = None) -> list[str]:
errors: list[str] = []
if record.get("phase") != PHASE or record.get("status") != STATUS:
errors.append("phase/status mismatch")
if record.get("start_commit") != START_COMMIT:
errors.append("start commit mismatch")
if record.get("activation") != {
"active": False, "adapter_sha256": None, "target_address": None,
"target_port": None, "run_id": None,
}:
errors.append("activation is not inert")
if record.get("source_bindings") != {
"phase10ab_trace_model_sha256": "7d1aa32d49b91b1e5cf3a085dda033767bdf17ab34389ff044f7403f86287959",
"phase10ac_adapter_size": ADAPTER_SIZE,
"phase10ac_adapter_sha256": ADAPTER_SHA256,
"phase10ac_tests_size": ADAPTER_TEST_SIZE,
"phase10ac_tests_sha256": ADAPTER_TEST_SHA256,
}:
errors.append("source bindings mismatch")
if record.get("adapter") != {
"exact_builtin_fake_facade_required": True,
"exact_builtin_fake_clock_required": True,
"precommitted_receipt_required": True,
"maximum_fake_steps": 1024, "maximum_receive_bytes": 65536,
"maximum_batch_bytes": 1035, "maximum_deadline_seconds": 10,
"network_import_present": False, "selector_import_present": False,
"dns_present": False, "real_clock_present": False,
"address_present": False, "cli_present": False,
"file_output_present": False,
"live_adapter_protocol_present": False, "target_retained": False,
"device_behavior_proven": False,
}:
errors.append("adapter boundary mismatch")
if record.get("lifecycle") != {
"create_count": 1, "nonblocking_before_connect": True,
"pending_connect_requires_write_ready": True,
"pending_connect_requires_zero_so_error": True,
"partial_write_loop": True, "zero_write_rejected": True,
"remote_eof_rejected": True,
"deadline_wins_readiness_race": True,
"deadline_only_completion": True,
"local_close_on_success": True, "local_close_on_failure": True,
"remote_cleanup_proven": False, "automatic_retry": False,
"reconnect": False, "resume": False,
}:
errors.append("lifecycle contract mismatch")
stops = record.get("hard_stops", {})
if set(stops) != {
"live_adapter_implementation", "socket_creation", "dns",
"target_retention", "connection", "device_request", "retry",
"device_action",
} or any(value is not True for value in stops.values()):
errors.append("hard stops mismatch")
authorizations = record.get("authorizations", {})
if set(authorizations) != AUTHORIZATION_FIELDS or any(
authorizations.get(field) is not False
for field in AUTHORIZATION_FIELDS):
errors.append("authorization fields are not exactly false")
performed = record.get("performed_actions", {})
if not performed or any(value is not False for value in performed.values()):
errors.append("performed actions are missing or true")
if record.get("decision") != {
"overall": STATUS, "dormant_fake_adapter_created": True,
"live_adapter_created": False, "live_adapter_allowed": False,
"device_action_allowed": False,
"phase10ad_offline_inactive_activation_design_allowed": True,
"next_step": "OFFLINE_NUMERIC_TARGET_AND_INACTIVE_ACTIVATION_CONTRACT",
}:
errors.append("decision mismatch")
if record.get("tests") != {
"chimera_gfx_ctest": "95_OF_95_PASS", "phase10ac_guardrails": 20,
"phase10ac_adapter_tests": 32, "safety_audit": "PASS",
"secret_scan": "PASS", "network_required_by_tests": False,
"hardware_claim_from_host_test": False,
}:
errors.append("test evidence mismatch")
if root is not None:
adapter = root / "tools/phase10ac_dormant_adapter.py"
tests = root / "tests/test_phase10ac_dormant_adapter.py"
if not exact_file(adapter, ADAPTER_SIZE, ADAPTER_SHA256):
errors.append("dormant adapter identity mismatch")
if not exact_file(tests, ADAPTER_TEST_SIZE, ADAPTER_TEST_SHA256):
errors.append("dormant adapter tests identity mismatch")
try:
source = adapter.read_text(encoding="utf-8")
tree = ast.parse(source)
except (OSError, SyntaxError, UnicodeError):
errors.append("dormant adapter cannot be parsed")
else:
imports = _imports(tree)
if imports & NETWORK_MODULES or "time" in imports:
errors.append("dormant adapter imports a live capability")
names = {
node.name for node in ast.walk(tree)
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
}
if {"connect", "send", "recv", "main"} & names:
errors.append("dormant adapter exposes a live API")
if re.search(r"(?<!\d)(?:\d{1,3}\.){3}\d{1,3}(?!\d)", source):
errors.append("dormant adapter embeds an address")
if "target_address" in source or "target_port" in source:
errors.append("dormant adapter contains target fields")
approval = (root / "docs/approvals/phase-1.0ac-dormant-adapter.md").read_text(
encoding="utf-8")
if "active=false" not in approval or \
"ps5_connection_authorized=false" not in approval or \
"automatic_retry=false" not in approval:
errors.append("approval record is not inert")
forbidden = list(root.glob("**/*phase10ac*.elf")) + \
list(root.glob("**/*phase-1.0ac*.elf"))
if forbidden:
errors.append("Phase-1.0AC target artifact exists")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
try:
record = load_json(
root / "manifests/retroarch/phase-1.0ac-dormant-adapter.json")
errors = validate_record(record, root)
except (OSError, ValueError, json.JSONDecodeError) as error:
errors = [f"validation input failed: {error}"]
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print("Phase-1.0AC dormant-adapter validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the inactive Phase-1.0AD record and byte bindings."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root.resolve()
manifest = json.loads((root / "manifests/retroarch/phase-1.0ad-inactive-activation.json").read_text(encoding="utf-8"))
activation = manifest["activation"]
authorization = manifest["authorizations"]
assert manifest["phase"] == "PHASE_1_0AD_INACTIVE_NUMERIC_TARGET_CONTRACT"
assert activation["active"] is False
assert all(activation[name] is None for name in (
"target_address", "target_port", "run_id", "not_before",
"expires_at", "launcher_sha256", "payload_sha256", "approval_sha256"))
assert activation["one_shot"] is True
assert activation["automatic_retry"] is False
assert activation["reconnect"] is False
assert activation["resume"] is False
assert not any(authorization.values())
assert manifest["decision"]["device_action_allowed"] is False
assert manifest["decision"]["bigapp_launcher_implementation_allowed"] is False
bindings = manifest["source_bindings"]
files = {
"contract": root / "tools/phase10ad_activation_contract.py",
"tests": root / "tests/test_phase10ad_activation_contract.py",
"documentation": root / "docs/retroarch/phase-1.0ad-inactive-activation-contract.md",
}
for name, path in files.items():
size, sha256 = digest(path)
assert bindings[f"{name}_size"] == size
assert bindings[f"{name}_sha256"] == sha256
tree = ast.parse(files["contract"].read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"socket", "selectors", "subprocess", "urllib", "http", "requests"})
calls = {node.func.id for node in ast.walk(tree) if isinstance(node, ast.Call)
and isinstance(node.func, ast.Name)}
assert not calls.intersection({"open", "exec", "eval", "compile", "input"})
print("Phase-1.0AD inactive activation contract validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AE against exact official shsrv worktrees."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def git(root: Path, value: str) -> str:
return subprocess.run(["git", "-C", str(root), "rev-parse", value],
check=True, capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--shsrv-root", type=Path, required=True)
parser.add_argument("--shsrv-v07-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0ae-launcher-architecture.json").read_text(encoding="utf-8"))
sources = data["official_sources"]
for label, root in (("v019", args.shsrv_root), ("v07", args.shsrv_v07_root)):
assert git(root, "HEAD") == sources[f"{label}_commit"]
assert git(root, "HEAD^{tree}") == sources[f"{label}_tree"]
assert sha256(args.shsrv_root / "bundles/hbldr/hbldr.c") == sources["v019_hbldr_sha256"]
assert sha256(args.shsrv_root / "elfldr.c") == sources["v019_elfldr_sha256"]
assert sha256(args.shsrv_root / "pt.c") == sources["v019_pt_sha256"]
assert sha256(args.shsrv_v07_root / "bundles/hbldr/main.c") == sources["v07_hbldr_sha256"]
assert sha256(args.shsrv_v07_root / "elfldr.c") == sources["v07_elfldr_sha256"]
assert sha256(args.shsrv_v07_root / "pt.c") == sources["v07_pt_sha256"]
v019 = (args.shsrv_root / "bundles/hbldr/hbldr.c").read_text(encoding="utf-8")
v07 = (args.shsrv_v07_root / "bundles/hbldr/main.c").read_text(encoding="utf-8")
assert "FAKE00000" in v019 and "remount_system_ex" in v019
assert "PPSA01659" in v07 and "FAKE00000" not in v07 and "nmount" not in v07
assert data["lineage_decision"]["selected_reference"] == "OFFICIAL_SHSRV_V0_7"
assert data["mandatory_policy"]["kill_existing_bigapp"] is False
assert data["decision"]["target_implementation_allowed"] is False
assert data["decision"]["device_action_allowed"] is False
assert not any(data["authorizations"].values())
print("Phase-1.0AE launcher architecture validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AF identities and offline-only boundary."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def identity(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0af-bigapp-lifecycle-model.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0ae-launcher-architecture.json").read_bytes()).hexdigest() == bindings["phase10ae_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10af_bigapp_lifecycle_model.py"),
("tests", "tests/test_phase10af_bigapp_lifecycle_model.py")):
size, digest = identity(root / relative)
assert bindings[f"{prefix}_size"] == size
assert bindings[f"{prefix}_sha256"] == digest
source = (root / "tools/phase10af_bigapp_lifecycle_model.py").read_text(encoding="utf-8")
tree = ast.parse(source)
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"socket", "subprocess", "os", "sys", "ctypes", "time", "pathlib"})
assert "PPSA01659" in source and "FAKE00000" not in source
assert not any(data["authorizations"].values())
assert data["decision"]["target_implementation_allowed"] is False
assert data["decision"]["device_action_allowed"] is False
print("Phase-1.0AF offline lifecycle validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AG byte identities and closed parser boundary."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def identity(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0ag-bounded-elf-contract.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0af-bigapp-lifecycle-model.json").read_bytes()).hexdigest() == bindings["phase10af_manifest_sha256"]
for prefix, relative in (("validator", "tools/phase10ag_bounded_elf.py"),
("tests", "tests/test_phase10ag_bounded_elf.py")):
size, digest = identity(root / relative)
assert size == bindings[f"{prefix}_size"]
assert digest == bindings[f"{prefix}_sha256"]
source = (root / "tools/phase10ag_bounded_elf.py").read_text(encoding="utf-8")
tree = ast.parse(source)
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"pathlib", "os", "sys", "subprocess", "socket", "ctypes", "mmap"})
assert data["historical_reference"]["validated_by_phase10ag"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["target_implementation_allowed"] is False
assert data["decision"]["device_action_allowed"] is False
print("Phase-1.0AG bounded ELF contract validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AH identities and official source bindings."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
import subprocess
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def git(root: Path) -> str:
return subprocess.run(["git", "-C", str(root), "rev-parse", "HEAD"],
check=True, capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--shsrv-v07-root", type=Path, required=True)
parser.add_argument("--sdk-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0ah-dynamic-contract.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((args.root / "manifests/retroarch/phase-1.0ag-bounded-elf-contract.json").read_bytes()).hexdigest() == bindings["phase10ag_manifest_sha256"]
for prefix, relative in (("contract", "tools/phase10ah_dynamic_contract.py"),
("tests", "tests/test_phase10ah_dynamic_contract.py")):
size, sha256 = digest(args.root / relative)
assert size == bindings[f"{prefix}_size"] and sha256 == bindings[f"{prefix}_sha256"]
assert git(args.shsrv_v07_root) == bindings["official_shsrv_v07_commit"]
assert digest(args.shsrv_v07_root / "elfldr.c")[1] == bindings["official_shsrv_v07_elfldr_sha256"]
assert git(args.sdk_root) == bindings["official_sdk_v041_commit"]
assert digest(args.sdk_root / "crt/rtld_payload.c")[1] == bindings["official_sdk_v041_rtld_payload_sha256"]
tree = ast.parse((args.root / "tools/phase10ah_dynamic_contract.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"pathlib", "os", "sys", "subprocess", "socket", "ctypes", "mmap"})
assert not any(data["authorizations"].values())
assert data["historical_phase10m_reference"]["validated_by_phase10ah"] is False
assert data["decision"]["target_mapping_allowed"] is False
assert data["decision"]["device_action_allowed"] is False
print("Phase-1.0AH dynamic contract validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AI byte bindings and closed model boundary."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0ai-mapping-model.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0ah-dynamic-contract.json").read_bytes()).hexdigest() == bindings["phase10ah_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10ai_mapping_model.py"),
("tests", "tests/test_phase10ai_mapping_model.py")):
size, sha256 = digest(root / relative)
assert size == bindings[f"{prefix}_size"] and sha256 == bindings[f"{prefix}_sha256"]
tree = ast.parse((root / "tools/phase10ai_mapping_model.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"os", "sys", "pathlib", "subprocess", "socket", "ctypes", "mmap"})
transaction = data["transaction"]
assert transaction["partial_mapping_retained_on_failure"] is False
assert transaction["deadline_preempts_operation_atomically"] is True
assert not any(data["authorizations"].values())
assert data["decision"]["target_mapping_allowed"] is False
assert data["decision"]["device_action_allowed"] is False
print("Phase-1.0AI mapping transaction validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AJ external source bindings and closed boundary."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def commit(root: Path) -> str:
return subprocess.run(
["git", "rev-parse", "HEAD"], cwd=root, check=True,
capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--shsrv-v07-root", type=Path, required=True)
parser.add_argument("--hardened-elfldr-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0aj-primitive-audit.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert sha256(args.root / "manifests/retroarch/phase-1.0ai-mapping-model.json") == bindings["phase10ai_manifest_sha256"]
assert commit(args.shsrv_v07_root) == bindings["shsrv_v07_commit"]
assert sha256(args.shsrv_v07_root / "elfldr.c") == bindings["shsrv_v07_elfldr_sha256"]
assert sha256(args.shsrv_v07_root / "pt.c") == bindings["shsrv_v07_pt_sha256"]
assert commit(args.hardened_elfldr_root) == bindings["hardened_elfldr_commit"]
for key, relative in (
("controlled_runtime_c_sha256", "controlled_runtime.c"),
("controlled_runtime_h_sha256", "controlled_runtime.h"),
("hardened_pt_sha256", "pt.c"),
("ps5_controlled_sha256", "ps5_controlled.c"),
):
assert sha256(args.hardened_elfldr_root / relative) == bindings[key]
assert not any(data["authorizations"].values())
assert data["decision"]["target_implementation_allowed"] is False
assert data["decision"]["device_action_allowed"] is False
print("Phase-1.0AJ primitive source audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AK byte bindings and capability-free model."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0ak-hybrid-composition.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0aj-primitive-audit.json").read_bytes()).hexdigest() == bindings["phase10aj_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10ak_hybrid_composition.py"),
("tests", "tests/test_phase10ak_hybrid_composition.py")):
size, sha256 = digest(root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
tree = ast.parse((root / "tools/phase10ak_hybrid_composition.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"os", "sys", "pathlib", "subprocess", "socket", "ctypes", "mmap", "time"})
ownership = data["ownership"]
assert ownership["cleanup_failure_requires_child_termination"] is True
assert ownership["failed_child_termination_is_hard_error"] is True
assert ownership["partial_success_allowed"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["target_implementation_allowed"] is False
print("Phase-1.0AK hybrid composition validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AL against the exact pinned SDK source."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--sdk-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0al-mdbg-copy-audit.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((args.root / "manifests/retroarch/phase-1.0ak-hybrid-composition.json").read_bytes()).hexdigest() == bindings["phase10ak_manifest_sha256"]
sdk_commit = subprocess.run(["git", "rev-parse", "HEAD"], cwd=args.sdk_root,
check=True, capture_output=True, text=True).stdout.strip()
assert sdk_commit == bindings["sdk_commit"]
for prefix, relative in (("mdbg_c", "crt/mdbg.c"),
("public_header", "include/ps5/mdbg.h")):
size, sha256 = digest(args.sdk_root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
findings = data["findings"]
assert findings["target_may_be_partially_mutated_on_error"] is True
assert findings["return_zero_proves_complete_copy"] is False
assert findings["monotonic_deadline_present"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["direct_sdk_mdbg_copy_reuse_allowed"] is False
print("Phase-1.0AL mdbg copy audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AM bindings and capability-free boundary."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0am-bounded-copy-model.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0al-mdbg-copy-audit.json").read_bytes()).hexdigest() == bindings["phase10al_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10am_bounded_copy_model.py"),
("tests", "tests/test_phase10am_bounded_copy_model.py")):
size, sha256 = digest(root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
tree = ast.parse((root / "tools/phase10am_bounded_copy_model.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"os", "sys", "pathlib", "subprocess", "socket", "ctypes", "mmap", "time"})
contract = data["contract"]
assert contract["partial_copy_kills_and_reaps_child"] is True
assert contract["restore_failure_kills_child_and_terminates_service"] is True
assert contract["terminal_cleanup_failure_is_hard_error"] is True
assert not any(data["authorizations"].values())
assert data["decision"]["target_implementation_allowed"] is False
print("Phase-1.0AM bounded copy/restore validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AN against the hardened elfldr source."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--hardened-elfldr-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0an-service-lifecycle-audit.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((args.root / "manifests/retroarch/phase-1.0am-bounded-copy-model.json").read_bytes()).hexdigest() == bindings["phase10am_manifest_sha256"]
commit = subprocess.run(["git", "rev-parse", "HEAD"],
cwd=args.hardened_elfldr_root, check=True,
capture_output=True, text=True).stdout.strip()
assert commit == bindings["hardened_elfldr_commit"]
for prefix, relative in (("socksrv", "socksrv.c"), ("pt", "pt.c"),
("main", "main.c"), ("elfldr", "elfldr.c")):
size, sha256 = digest(args.hardened_elfldr_root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
assert data["service_lifecycle"]["request_handler_process_exits_125"] is True
assert data["service_lifecycle"]["service_restart_owner_present"] is False
assert data["copy_path"]["hard_deadline_or_preemption_present"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["hardened_pt_copyin_reuse_allowed"] is False
print("Phase-1.0AN service lifecycle audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AO bindings and capability-free boundary."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0ao-worker-supervisor-model.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0an-service-lifecycle-audit.json").read_bytes()).hexdigest() == bindings["phase10an_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10ao_worker_supervisor_model.py"),
("tests", "tests/test_phase10ao_worker_supervisor_model.py")):
size, sha256 = digest(root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
tree = ast.parse((root / "tools/phase10ao_worker_supervisor_model.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"os", "sys", "pathlib", "subprocess", "socket", "ctypes", "signal", "time"})
architecture = data["architecture"]
assert architecture["automatic_restart"] is False
assert architecture["retry"] is False
assert architecture["terminal_cleanup_failure_is_hard_error"] is True
assert not any(data["authorizations"].values())
assert data["decision"]["target_architecture_feasible"] is False
print("Phase-1.0AO worker supervisor validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AP against current official Git objects."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def check_blob(repo: Path, commit: str, path: str,
expected_blob: str, expected_size: int) -> None:
spec = f"{commit}:{path}"
assert git(repo, "rev-parse", spec) == expected_blob
assert int(git(repo, "cat-file", "-s", spec)) == expected_size
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--sdk-root", type=Path, required=True)
parser.add_argument("--shsrv-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0ap-worker-feasibility-audit.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((args.root / "manifests/retroarch/phase-1.0ao-worker-supervisor-model.json").read_bytes()).hexdigest() == bindings["phase10ao_manifest_sha256"]
check_blob(args.sdk_root, bindings["sdk_commit"], "include/freebsd/unistd.h",
bindings["sdk_unistd_blob"], bindings["sdk_unistd_size"])
check_blob(args.sdk_root, bindings["sdk_commit"], "crt/syscall.h",
bindings["sdk_syscall_blob"], bindings["sdk_syscall_size"])
for prefix, path in (("shsrv_builtin", "builtin.c"),
("shsrv_elfldr", "elfldr.c"),
("shsrv_shell", "sh.c"), ("shsrv_pt", "pt.c")):
check_blob(args.shsrv_root, bindings["shsrv_commit"], path,
bindings[f"{prefix}_blob"], bindings[f"{prefix}_size"])
assert data["worker_creation"]["classification"] == "STRONG_SOURCE_CANDIDATE_NOT_RUNTIME_PROOF"
assert data["preemption"]["waitpid_calls_are_bounded"] is False
assert data["result_channel"]["fixed_size_worker_result_record_present"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["target_worker_architecture_feasible"] is False
print("Phase-1.0AP worker feasibility audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AQ byte bindings and transport-free boundary."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0aq-worker-result-record.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0ap-worker-feasibility-audit.json").read_bytes()).hexdigest() == bindings["phase10ap_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10aq_worker_result_record.py"),
("tests", "tests/test_phase10aq_worker_result_record.py")):
size, sha256 = digest(root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
tree = ast.parse((root / "tools/phase10aq_worker_result_record.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"os", "sys", "pathlib", "subprocess", "socket", "ctypes", "secrets", "random", "time"})
assert data["record"]["size"] == 128
assert data["identity"]["pid_alone_is_identity"] is False
assert data["result"]["digest_is_authentication"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["transport_implementation_allowed"] is False
print("Phase-1.0AQ worker result record validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AR bindings and absence of live channel capability."""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> tuple[int, str]:
data = path.read_bytes()
return len(data), hashlib.sha256(data).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
root = parser.parse_args().root
data = json.loads((root / "manifests/retroarch/phase-1.0ar-result-channel-model.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert hashlib.sha256((root / "manifests/retroarch/phase-1.0aq-worker-result-record.json").read_bytes()).hexdigest() == bindings["phase10aq_manifest_sha256"]
for prefix, relative in (("model", "tools/phase10ar_result_channel_model.py"),
("tests", "tests/test_phase10ar_result_channel_model.py")):
size, sha256 = digest(root / relative)
assert size == bindings[f"{prefix}_size"]
assert sha256 == bindings[f"{prefix}_sha256"]
tree = ast.parse((root / "tools/phase10ar_result_channel_model.py").read_text(encoding="utf-8"))
imports = {alias.name.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.Import) for alias in node.names}
imports.update(node.module.split(".")[0] for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom) and node.module)
assert not imports.intersection({"os", "sys", "pathlib", "subprocess", "socket", "selectors", "select", "ctypes", "time"})
channel = data["channel"]
assert channel["eof_is_success"] is False
assert channel["record_completion_is_success_boundary"] is True
assert channel["live_pipe_present"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["live_channel_implementation_allowed"] is False
print("Phase-1.0AR result channel validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AS against exact current upstream Git objects."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def check(repo: Path, commit: str, path: str, blob: str, size: int) -> None:
spec = f"{commit}:{path}"
assert git(repo, "rev-parse", spec) == blob
assert int(git(repo, "cat-file", "-s", spec)) == size
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--sdk-root", type=Path, required=True)
parser.add_argument("--shsrv-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0as-channel-primitive-audit.json").read_text(encoding="utf-8"))
b = data["source_bindings"]
assert hashlib.sha256((args.root / "manifests/retroarch/phase-1.0ar-result-channel-model.json").read_bytes()).hexdigest() == b["phase10ar_manifest_sha256"]
for prefix, path in (("sdk_sys_unistd", "include/freebsd/sys/unistd.h"),
("sdk_unistd", "include/freebsd/unistd.h"),
("sdk_poll", "include/freebsd/sys/poll.h"),
("sdk_time", "include/freebsd/sys/time.h")):
check(args.sdk_root, b["sdk_commit"], path,
b[f"{prefix}_blob"], b[f"{prefix}_size"])
for prefix, path in (("shsrv_shell", "sh.c"),
("shsrv_builtin", "builtin.c")):
check(args.shsrv_root, b["shsrv_commit"], path,
b[f"{prefix}_blob"], b[f"{prefix}_size"])
assert data["fd_ownership"]["official_shsrv_worker_uses_rfcfdg"] is True
assert data["fd_ownership"]["result_fd_inherited_by_worker"] is False
assert data["deadline_and_cleanup"]["absolute_monotonic_deadline_present"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["live_channel_architecture_feasible"] is False
print("Phase-1.0AS channel primitive audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate exact Phase-1.0AT offline model bindings."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root
data = json.loads((root / "manifests/retroarch/phase-1.0at-fd-deadline-model.json").read_text(encoding="utf-8"))
bindings = data["source_bindings"]
assert digest(root / "manifests/retroarch/phase-1.0as-channel-primitive-audit.json") == bindings["phase10as_manifest_sha256"]
assert digest(root / "tools/phase10at_fd_deadline_model.py") == bindings["model_sha256"]
assert digest(root / "tests/test_phase10at_fd_deadline_model.py") == bindings["failure_tests_sha256"]
assert data["model_boundary"]["fake_facade_only"] is True
assert data["ownership_contract"]["all_acquired_ends_closed_on_failure"] is True
assert data["deadline_contract"]["trailing_read_event_fails"] is True
assert not any(data["authorizations"].values())
assert data["decision"]["live_channel_architecture_feasible"] is False
print("Phase-1.0AT FD/deadline model validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AU against exact official Git objects."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def check(repo: Path, commit: str, path: str, blob: str, size: int) -> None:
spec = f"{commit}:{path}"
assert git(repo, "rev-parse", spec) == blob
assert int(git(repo, "cat-file", "-s", spec)) == size
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--sdk-root", type=Path, required=True)
parser.add_argument("--shsrv-root", type=Path, required=True)
args = parser.parse_args()
path = args.root / "manifests/retroarch/phase-1.0au-live-channel-feasibility.json"
data = json.loads(path.read_text(encoding="utf-8"))
binding = data["source_bindings"]
at_path = args.root / "manifests/retroarch/phase-1.0at-fd-deadline-model.json"
assert hashlib.sha256(at_path.read_bytes()).hexdigest() == binding["phase10at_manifest_sha256"]
sdk_paths = {
"sdk_sys_unistd": "include/freebsd/sys/unistd.h",
"sdk_unistd": "include/freebsd/unistd.h",
"sdk_sys_fcntl": "include/freebsd/sys/fcntl.h",
"sdk_time": "include/freebsd/time.h",
"sdk_wait": "include/freebsd/sys/wait.h",
"sdk_signal": "include/freebsd/signal.h",
}
for prefix, source in sdk_paths.items():
check(args.sdk_root, binding["sdk_commit"], source,
binding[f"{prefix}_blob"], binding[f"{prefix}_size"])
shsrv_paths = {"shsrv_builtin": "builtin.c", "shsrv_shell": "sh.c",
"shsrv_service": "shsrv.c"}
for prefix, source in shsrv_paths.items():
check(args.shsrv_root, binding["shsrv_commit"], source,
binding[f"{prefix}_blob"], binding[f"{prefix}_size"])
assert data["public_source_contracts"]["source_level_design_inputs_complete"] is True
assert data["official_composition_audit"]["worker_uses_rffdg"] is False
assert data["official_composition_audit"]["worker_uses_rfcfdg_close_all"] is True
assert not any(data["authorizations"].values())
assert data["decision"]["live_result_channel_implementation_allowed"] is False
print("Phase-1.0AU live-channel feasibility validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate exact Phase-1.0AV offline canary bindings."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root
path = root / "manifests/retroarch/phase-1.0av-launch-context-canary-contract.json"
data = json.loads(path.read_text(encoding="utf-8"))
binding = data["source_bindings"]
assert digest(root / "manifests/retroarch/phase-1.0au-live-channel-feasibility.json") == binding["phase10au_manifest_sha256"]
assert digest(root / "tools/phase10av_launch_context_canary.py") == binding["contract_sha256"]
assert digest(root / "tests/test_phase10av_launch_context_canary.py") == binding["tests_sha256"]
assert data["pair_contract"]["same_payload_sha256_required"] is True
assert data["result_contract"]["distinct_terminal_after_d04_required"] is True
assert data["interpretation_limits"]["submit_zero_means_visible_flip"] is False
assert not any(data["authorizations"].values())
assert not any(value is not None for key, value in data["tracked_state"].items()
if key.endswith("sha256") or key in {"raw_run_id", "bigapp_run_id",
"target_address", "target_port"})
assert data["decision"]["causal_hardware_comparison_ready"] is False
print("Phase-1.0AV launch-context canary validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0AW against exact RetroArch and shsrv Git objects."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def check(repo: Path, commit: str, path: str, blob: str, size: int) -> None:
spec = f"{commit}:{path}"
assert git(repo, "rev-parse", spec) == blob
assert int(git(repo, "cat-file", "-s", spec)) == size
def show(repo: Path, commit: str, path: str) -> str:
return git(repo, "show", f"{commit}:{path}")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path, required=True)
parser.add_argument("--shsrv-root", type=Path, required=True)
args = parser.parse_args()
root = args.root
path = root / "manifests/retroarch/phase-1.0aw-canary-source-delta-audit.json"
data = json.loads(path.read_text(encoding="utf-8"))
b = data["source_bindings"]
av = root / "manifests/retroarch/phase-1.0av-launch-context-canary-contract.json"
assert hashlib.sha256(av.read_bytes()).hexdigest() == b["phase10av_manifest_sha256"]
retroarch_paths = {
"retroarch_c": "retroarch.c", "sdl2_gfx": "gfx/drivers/sdl2_gfx.c",
"platform_smoke_c": "frontend/drivers/platform_ps5_smoke.c",
"platform_smoke_h": "frontend/drivers/platform_ps5_smoke.h",
"diag_c": "pkg/ps5/chimera_ps5_diag.c",
"diag_h": "pkg/ps5/chimera_ps5_diag.h",
"stream_c": "pkg/ps5/chimera_ps5_diag_stream.c",
"stream_h": "pkg/ps5/chimera_ps5_diag_stream.h",
"makefile": "Makefile.ps5",
"sdl_hardening_patch": "pkg/ps5/sdl2-ps5-smoke-hardening.patch",
}
for prefix, source in retroarch_paths.items():
check(args.retroarch_root, b["retroarch_commit"], source,
b[f"{prefix}_blob"], b[f"{prefix}_size"])
shsrv_paths = {"v07_hbldr": "bundles/hbldr/main.c",
"v07_elfldr": "elfldr.c", "v07_shell": "sh.c",
"v07_service": "shsrv.c"}
for prefix, source in shsrv_paths.items():
check(args.shsrv_root, b["shsrv_v07_commit"], source,
b[f"{prefix}_blob"], b[f"{prefix}_size"])
retroarch_c = show(args.retroarch_root, b["retroarch_commit"], "retroarch.c")
diag_c = show(args.retroarch_root, b["retroarch_commit"], "pkg/ps5/chimera_ps5_diag.c")
hbldr = show(args.shsrv_root, b["shsrv_v07_commit"], "bundles/hbldr/main.c")
elfldr = show(args.shsrv_root, b["shsrv_v07_commit"], "elfldr.c")
assert "main_exit(data);" in retroarch_c and "_Exit(result);" in retroarch_c
assert "CHIMERA_PS5_DIAG_D12" in diag_c and "CHIMERA_PS5_DIAG_FRAME_TERMINAL" in diag_c
assert "elfldr_exec(STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO" in hbldr
assert "stdout_fd = pt_rdup(pid, getpid(), stdout_fd);" in elfldr
assert "while(1)" in hbldr and "sceSystemServiceKillApp" in hbldr
assert data["historical_payload"]["reusable_as_av_canary"] is False
assert data["required_payload_source_delta"]["new_cleanup_failure_counter_required"] is True
assert data["bigapp_result_path"]["live_result_path_proven"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["target_artifact_build_allowed"] is False
print("Phase-1.0AW canary source-delta audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate exact Phase-1.0AX host reference bindings."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
def digest(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root
path = root / "manifests/retroarch/phase-1.0ax-canary-protocol-model.json"
data = json.loads(path.read_text(encoding="utf-8"))
binding = data["source_bindings"]
assert digest(root / "manifests/retroarch/phase-1.0aw-canary-source-delta-audit.json") == binding["phase10aw_manifest_sha256"]
assert digest(root / "tools/phase10ax_canary_protocol_model.py") == binding["model_sha256"]
assert digest(root / "tests/test_phase10ax_canary_protocol_model.py") == binding["tests_sha256"]
assert data["frame_contract"]["only_d14_terminal"] is True
assert data["frame_contract"]["d12_terminal_forbidden"] is True
assert data["cleanup_terminal_contract"]["cleanup_failure_count_zero_required"] is True
assert data["trace_contract"]["host_trace_means_firmware_behavior"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["target_source_matches_model"] is False
print("Phase-1.0AX canary protocol model validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the exact Phase-1.0AY private source base selection."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path, required=True)
args = parser.parse_args()
root = args.root
path = root / "manifests/retroarch/phase-1.0ay-target-source-base.json"
data = json.loads(path.read_text(encoding="utf-8"))
b = data["source_bindings"]
ax = root / "manifests/retroarch/phase-1.0ax-canary-protocol-model.json"
assert hashlib.sha256(ax.read_bytes()).hexdigest() == b["phase10ax_manifest_sha256"]
assert git(args.retroarch_root, "rev-parse", b["selected_remote_ref"]) == b["selected_retroarch_commit"]
assert git(args.retroarch_root, "merge-base", b["phase10m_source_commit"],
b["selected_retroarch_commit"]) == b["phase10m_source_commit"]
paths = {
"retroarch_c": "retroarch.c", "sdl2_gfx": "gfx/drivers/sdl2_gfx.c",
"platform_smoke_c": "frontend/drivers/platform_ps5_smoke.c",
"platform_smoke_h": "frontend/drivers/platform_ps5_smoke.h",
"diag_c": "pkg/ps5/chimera_ps5_diag.c",
"diag_h": "pkg/ps5/chimera_ps5_diag.h",
"stream_c": "pkg/ps5/chimera_ps5_diag_stream.c",
"stream_h": "pkg/ps5/chimera_ps5_diag_stream.h",
"makefile": "Makefile.ps5",
}
for prefix, source in paths.items():
assert git(args.retroarch_root, "rev-parse",
f'{b["selected_retroarch_commit"]}:{source}') == b[f"{prefix}_blob"]
assert data["base_selection"]["existing_runner_must_remain_inactive"] is True
assert data["permitted_patch_scope"]["target_profile"] is False
assert not any(data["authorizations"].values())
assert data["decision"]["target_artifact_build_allowed"] is False
print("Phase-1.0AY target-source base validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the local, host-only Phase-1.0AZ RetroArch source commit."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path, required=True)
args = parser.parse_args()
path = args.root / "manifests/retroarch/phase-1.0az-host-av-source.json"
data = json.loads(path.read_text(encoding="utf-8"))
binding = data["source_bindings"]
ay = args.root / "manifests/retroarch/phase-1.0ay-target-source-base.json"
assert hashlib.sha256(ay.read_bytes()).hexdigest() == binding["phase10ay_manifest_sha256"]
commit = binding["retroarch_local_commit"]
assert git(args.retroarch_root, "rev-parse", "HEAD") == commit
assert git(args.retroarch_root, "rev-parse", binding["verified_remote_ref"]) == commit
assert git(args.retroarch_root, "rev-parse", f"{commit}^") == binding["retroarch_base_commit"]
expected = {
"Makefile.ps5", "docs/ps5-phase10az-host-av-source.md",
"frontend/drivers/platform_ps5_smoke.c",
"frontend/drivers/platform_ps5_smoke.h", "pkg/ps5/chimera_ps5_diag.c",
"pkg/ps5/chimera_ps5_diag.h", "pkg/ps5/chimera_ps5_diag_stream.c",
"tests/chimera_ps5_av_diag_test.c",
}
assert set(git(args.retroarch_root, "show", "--format=", "--name-only", commit).splitlines()) == expected
blobs = {
"makefile": "Makefile.ps5",
"platform_smoke_c": "frontend/drivers/platform_ps5_smoke.c",
"platform_smoke_h": "frontend/drivers/platform_ps5_smoke.h",
"diag_c": "pkg/ps5/chimera_ps5_diag.c",
"diag_h": "pkg/ps5/chimera_ps5_diag.h",
"stream_c": "pkg/ps5/chimera_ps5_diag_stream.c",
"host_test": "tests/chimera_ps5_av_diag_test.c",
"source_doc": "docs/ps5-phase10az-host-av-source.md",
}
for key, source in blobs.items():
assert git(args.retroarch_root, "rev-parse", f"{commit}:{source}") == binding[f"{key}_blob"]
makefile = git(args.retroarch_root, "show", f"{commit}:Makefile.ps5")
assert makefile.count("-DCHIMERA_PS5_AV_DIAG=1") == 1
assert "PS5_PROFILE=av" not in makefile and "retroarch_ps5_av" not in makefile
assert git(args.retroarch_root, "diff", "--quiet", f'{binding["retroarch_base_commit"]}', commit, "--", "retroarch.c") == ""
assert binding["remote_push_verified"] is True
assert not any(data["authorizations"].values())
assert data["decision"]["target_profile_reassessment_allowed"] is True
assert data["decision"]["target_artifact_build_allowed"] is False
print("Phase-1.0AZ host-only source validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+558
View File
@@ -0,0 +1,558 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0B bounded RetroArch smoke evidence."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import struct
import subprocess
import sys
from typing import Any
PHASE = "PHASE_1_0B_FIRST_DEVICE_SMOKE_CANDIDATE_HARDENING"
STATUS = "RETROARCH_PS5_DEVICE_SMOKE_CANDIDATE_BUILT_WITH_DECLARED_RISKS"
GFX_BRANCH = "codex/chimera-gfx-phase10b-device-smoke-hardening"
RETROARCH_BRANCH = "codex/ps5-device-smoke-hardening"
RETROARCH_BASE = "ca1b45680577befc743e1c92fa40687e1b1745e7"
RETROARCH_RELEASE = "69a4f0ea1e8aaf442ae4858f2e7f2b31a1776576"
RETROARCH_TREE = "33babf9eb7699b5d571a3063ea21c3e488c159fe"
SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37"
PACBREW_COMMIT = "c2abcfcb60f569128abd0e8e70ad03a67bee5ea7"
SDL_COMMIT = "0baf4ac49382b537ba449901b5b6d0d189bb1fbb"
DENYLIST_SHA256 = "e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
DEVICE_AUTHORIZATION_FIELDS = (
"ps5_connection_authorized",
"device_transfer_authorized",
"device_execution_authorized",
"installation_authorized",
"lifecycle_authorized",
"autoload_authorized",
"device_write_authorized",
"automatic_retry",
)
DEVICE_ACTION_FIELDS = (
"ps5_connected",
"device_request_performed",
"files_transferred",
"device_write_performed",
"target_execution_performed",
"transfer_package_created",
"execution_package_created",
"installation_package_created",
)
DISABLED_FEATURES = {
"networking",
"online_updater",
"dynamic_cores",
"content_browser_data",
"playlists",
"history",
"screenshots",
"recording",
"achievements",
"shaders",
"databases",
"compressed_content",
"sram",
"savestates",
"config_save",
"remap_save",
"autoconfig_save",
"log_file",
"temporary_files",
"keyboard_ime",
"haptics",
"rumble",
"lightbar",
"gnm",
"retroarch_dynamic_core_loading",
"installation",
"payload_launch",
"autoload",
}
FORBIDDEN_IMPORT_MARKERS = (
"scenet",
"scehttp",
"scessl",
"scegnm",
"scekernelloadstartmodule",
"scepadsetvibration",
"scepadsetlightbar",
"sceime",
"scekeyboard",
"dlopen",
"dlsym",
"socket",
"connect",
"listen",
"accept",
"send",
"recv",
)
REQUIRED_SYMBOLS = {
"rarch_main",
"retroarch_main_init",
"runloop_iterate",
"retro_init",
"retro_deinit",
"retro_run",
"frontend_ctx_ps5",
"chimera_ps5_smoke_tick",
"chimera_ps5_smoke_block_write",
"__wrap_open",
"__wrap_fopen",
"__wrap_fwrite",
}
DELIVERABLES = (
"docs/retroarch/phase-1.0b-smoke-candidate-design.md",
"docs/retroarch/phase-1.0b-runtime-and-exit-contract.md",
"docs/retroarch/phase-1.0b-persistent-write-audit.md",
"docs/retroarch/phase-1.0b-linker-and-wx-analysis.md",
"docs/retroarch/phase-1.0b-device-risk-assessment.md",
"docs/retroarch/phase-1.0b-proposed-one-shot-test.md",
"docs/approvals/phase-1.0b-device-smoke-template.md",
"manifests/retroarch/phase-1.0b-build.json",
"manifests/retroarch/phase-1.0b-artifact.json",
"manifests/retroarch/phase-1.0b-runtime-contract.json",
"tests/test_retroarch_phase10b.py",
"tools/validate_retroarch_phase10b.py",
"packaging/retroarch/phase10b/SHA256SUMS.txt",
)
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as stream:
value = json.load(stream)
if not isinstance(value, dict):
raise ValueError(f"{path} is not a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def profile_is_closed(profile: dict[str, Any]) -> bool:
return (
DISABLED_FEATURES.issubset(set(profile.get("disabled_features", [])))
and profile.get("persistent_writes_allowed") is False
and profile.get("content_required") is False
and profile.get("config_required") is False
and profile.get("networking") is False
and profile.get("autoload") is False
and profile.get("automatic_retry") is False
)
def route_is_read_only(route: dict[str, Any]) -> bool:
return (
route.get("write") is False
and route.get("create") is False
and route.get("append") is False
and route.get("truncate") is False
and route.get("rename") is False
and route.get("unlink") is False
and route.get("mkdir") is False
and route.get("retry") is False
)
def program_headers_are_wx_closed(headers: list[dict[str, Any]]) -> bool:
loads = [header for header in headers if header.get("type") == "LOAD"]
return (
len(loads) >= 3
and any("E" in str(item.get("flags", "")) for item in loads)
and all(
not (
"W" in str(item.get("flags", ""))
and "E" in str(item.get("flags", ""))
)
for item in loads
)
)
def imports_are_closed(imports: list[str]) -> bool:
lowered = [item.lower() for item in imports]
return not any(
marker in item for marker in FORBIDDEN_IMPORT_MARKERS for item in lowered
)
def parse_elf_program_headers(path: Path) -> list[dict[str, Any]]:
with path.open("rb") as stream:
header = stream.read(64)
if len(header) != 64 or header[:5] != b"\x7fELF\x02":
raise ValueError(f"{path} is not ELF64")
byte_order = "<" if header[5] == 1 else ">"
phoff = struct.unpack_from(f"{byte_order}Q", header, 32)[0]
phentsize = struct.unpack_from(f"{byte_order}H", header, 54)[0]
phnum = struct.unpack_from(f"{byte_order}H", header, 56)[0]
if phentsize < 56 or phnum > 64:
raise ValueError("invalid ELF program-header table")
result: list[dict[str, Any]] = []
stream.seek(phoff)
for _ in range(phnum):
raw = stream.read(phentsize)
if len(raw) != phentsize:
raise ValueError("truncated ELF program-header table")
kind, flags = struct.unpack_from(f"{byte_order}II", raw)
names = {1: "LOAD", 2: "DYNAMIC"}
text = (
("R" if flags & 4 else "")
+ ("W" if flags & 2 else "")
+ ("E" if flags & 1 else "")
)
result.append(
{
"type": names.get(kind, f"0x{kind:x}"),
"flags": text,
"offset": struct.unpack_from(f"{byte_order}Q", raw, 8)[0],
"virtual_address": struct.unpack_from(
f"{byte_order}Q", raw, 16
)[0],
"file_size": struct.unpack_from(f"{byte_order}Q", raw, 32)[0],
"memory_size": struct.unpack_from(
f"{byte_order}Q", raw, 40
)[0],
"alignment": struct.unpack_from(f"{byte_order}Q", raw, 48)[0],
}
)
return result
def parse_elf_sections(path: Path) -> tuple[bytes, list[tuple[int, ...]]]:
data = path.read_bytes()
if len(data) < 64 or data[:6] != b"\x7fELF\x02\x01":
raise ValueError(f"{path} is not little-endian ELF64")
section_offset = struct.unpack_from("<Q", data, 40)[0]
section_size, section_count = struct.unpack_from("<HH", data, 58)
if section_size < 64 or section_count > 4096:
raise ValueError("invalid ELF section-header table")
sections: list[tuple[int, ...]] = []
for index in range(section_count):
offset = section_offset + index * section_size
if offset + 64 > len(data):
raise ValueError("truncated ELF section-header table")
sections.append(struct.unpack_from("<IIQQQQIIQQ", data, offset))
return data, sections
def parse_elf_dynamic_symbols(path: Path) -> list[str]:
data, sections = parse_elf_sections(path)
undefined: set[str] = set()
for section in sections:
if section[1] != 11: # SHT_DYNSYM
continue
symbol_offset, symbol_size = section[4], section[5]
string_index, symbol_entry_size = section[6], section[9]
if string_index >= len(sections) or symbol_entry_size < 24:
raise ValueError("invalid ELF dynamic-symbol table")
strings_section = sections[string_index]
strings = data[
strings_section[4] : strings_section[4] + strings_section[5]
]
for offset in range(
symbol_offset, symbol_offset + symbol_size, symbol_entry_size
):
if offset + 24 > len(data):
raise ValueError("truncated ELF dynamic-symbol table")
name_offset, _, _, section_index, _, _ = struct.unpack_from(
"<IBBHQQ", data, offset
)
if section_index != 0 or name_offset >= len(strings):
continue
name_end = strings.find(b"\0", name_offset)
if name_end < 0:
raise ValueError("unterminated ELF dynamic-symbol name")
name = strings[name_offset:name_end].decode("utf-8")
if name:
undefined.add(name)
return sorted(undefined)
def parse_elf_needed(path: Path) -> list[str]:
data, sections = parse_elf_sections(path)
needed: list[str] = []
for section in sections:
if section[1] != 6: # SHT_DYNAMIC
continue
dynamic_offset, dynamic_size = section[4], section[5]
string_index, dynamic_entry_size = section[6], section[9]
if string_index >= len(sections) or dynamic_entry_size < 16:
raise ValueError("invalid ELF dynamic table")
strings_section = sections[string_index]
strings = data[
strings_section[4] : strings_section[4] + strings_section[5]
]
for offset in range(
dynamic_offset, dynamic_offset + dynamic_size, dynamic_entry_size
):
if offset + 16 > len(data):
raise ValueError("truncated ELF dynamic table")
tag, value = struct.unpack_from("<QQ", data, offset)
if tag != 1: # DT_NEEDED
continue
if value >= len(strings):
raise ValueError("invalid ELF DT_NEEDED string offset")
name_end = strings.find(b"\0", value)
if name_end < 0:
raise ValueError("unterminated ELF DT_NEEDED name")
needed.append(strings[value:name_end].decode("utf-8"))
return needed
def parse_elf_relocations(path: Path) -> dict[str, Any]:
data, sections = parse_elf_sections(path)
writable_ranges = [
(
header["virtual_address"],
header["virtual_address"] + header["memory_size"],
)
for header in parse_elf_program_headers(path)
if header["type"] == "LOAD" and "W" in header["flags"]
]
total = 0
relative = 0
outside = 0
relative_outside = 0
by_type: dict[str, int] = {}
for section in sections:
if section[1] != 4: # SHT_RELA
continue
relocation_offset, relocation_size = section[4], section[5]
relocation_entry_size = section[9]
if relocation_entry_size < 24:
raise ValueError("invalid ELF relocation table")
for offset in range(
relocation_offset,
relocation_offset + relocation_size,
relocation_entry_size,
):
if offset + 24 > len(data):
raise ValueError("truncated ELF relocation table")
target, info, _ = struct.unpack_from("<QQq", data, offset)
relocation_type = info & 0xFFFFFFFF
key = str(relocation_type)
by_type[key] = by_type.get(key, 0) + 1
total += 1
in_writable_load = any(
start <= target and target + 8 <= end
for start, end in writable_ranges
)
if not in_writable_load:
outside += 1
if relocation_type == 8: # R_X86_64_RELATIVE
relative += 1
if not in_writable_load:
relative_outside += 1
return {
"total": total,
"relative": relative,
"by_type": by_type,
"outside_rw_load": outside,
"relative_outside_rw_load": relative_outside,
}
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
capture_output=True,
text=True,
check=False,
)
if result.returncode:
raise RuntimeError(result.stderr.strip() or "git command failed")
return result.stdout.strip()
def validate(root: Path, retroarch_root: Path | None = None) -> list[str]:
errors: list[str] = []
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
try:
build = load_json(root / "manifests/retroarch/phase-1.0b-build.json")
artifact = load_json(root / "manifests/retroarch/phase-1.0b-artifact.json")
runtime = load_json(
root / "manifests/retroarch/phase-1.0b-runtime-contract.json"
)
except (OSError, ValueError, json.JSONDecodeError) as error:
return errors + [str(error)]
if build.get("phase") != PHASE or build.get("status") != STATUS:
errors.append("phase/status mismatch")
if build.get("branch") != GFX_BRANCH:
errors.append("GFX branch mismatch")
for field in DEVICE_AUTHORIZATION_FIELDS:
if build.get(field) is not False:
errors.append(f"{field} must remain false")
for field in DEVICE_ACTION_FIELDS:
if build.get(field) is not False:
errors.append(f"{field} must remain false")
source = build.get("sources", {})
expected_sources = {
"retroarch_release_commit": RETROARCH_RELEASE,
"retroarch_release_tree": RETROARCH_TREE,
"retroarch_fork_base_commit": RETROARCH_BASE,
"ps5_payload_sdk_commit": SDK_COMMIT,
"pacbrew_commit": PACBREW_COMMIT,
"sdl_commit": SDL_COMMIT,
}
for field, expected in expected_sources.items():
if source.get(field) != expected:
errors.append(f"source mismatch: {field}")
if (
build.get("chimera_retroarch", {}).get("branch") != RETROARCH_BRANCH
or len(build.get("chimera_retroarch", {}).get("source_commit", "")) != 40
):
errors.append("RetroArch fork identity is incomplete")
if not profile_is_closed(build.get("profile", {})):
errors.append("smoke profile is not closed")
record = artifact.get("artifact", {})
if record.get("name") != "retroarch_ps5_software_smoke.elf":
errors.append("artifact label mismatch")
if record.get("size", 0) <= 0 or len(record.get("sha256", "")) != 64:
errors.append("artifact identity is incomplete")
if len(record.get("linker_map_sha256", "")) != 64:
errors.append("linker-map identity is incomplete")
hashes = record.get("clean_build_sha256", [])
if len(hashes) != 2 or len(set(hashes)) != 1 or hashes[0] != record.get("sha256"):
errors.append("two clean builds are not byte-identical")
if record.get("selected_exit_method") != "PROCESS__EXIT_AFTER_TEARDOWN":
errors.append("exit method mismatch")
if record.get("entrypoint") is None:
errors.append("entrypoint missing")
if not program_headers_are_wx_closed(record.get("program_headers", [])):
errors.append("program headers are not W^X-closed")
if not imports_are_closed(record.get("imports", [])):
errors.append("forbidden import present")
if not REQUIRED_SYMBOLS.issubset(set(record.get("defined_symbols", []))):
errors.append("required real/smoke symbols are incomplete")
if record.get("relative_relocations_outside_rw_load") != 0:
errors.append("relative relocation target outside RW load")
for field in (
"persistent_writes_allowed",
"content_required",
"config_required",
"networking",
"autoload",
"automatic_retry",
"installation_eligible",
"device_write_eligible",
"transfer_eligible",
"execution_eligible",
"execution_authorized",
):
if record.get(field) is not False:
errors.append(f"artifact {field} must be false")
if runtime.get("runtime_limit_ms") != 60000:
errors.append("runtime limit mismatch")
if runtime.get("frame_limit") != 3600:
errors.append("frame limit mismatch")
if runtime.get("shutdown_hold_ms") != 2000:
errors.append("shutdown hold mismatch")
if runtime.get("shutdown_request_max") != 1:
errors.append("shutdown request is not single-shot")
if runtime.get("exit_reachable_call_count") != 1:
errors.append("exit is not exactly once reachable")
if runtime.get("audio_submit_bounded") is not False:
errors.append("blocking AudioOut risk was hidden")
if not all(route_is_read_only(route) for route in runtime.get("write_routes", [])):
errors.append("write route is not fail-closed")
denylist = root / "manifests/artifact-denylist.json"
if not denylist.is_file() or sha256_file(denylist) != DENYLIST_SHA256:
errors.append("permanent denylist changed")
for relative in git(root, "ls-files").splitlines():
if relative.lower().endswith((".elf", ".self", ".sprx", ".pkg")):
errors.append(f"tracked target artifact: {relative}")
approval = (root / "docs/approvals/phase-1.0b-device-smoke-template.md").read_text(
encoding="utf-8"
)
for value in (
"authorized: false",
"transfer_authorized: false",
"execution_authorized: false",
"installation_authorized: false",
"automatic_retry: false",
"autoload_authorized: false",
):
if value not in approval:
errors.append(f"approval template missing {value}")
if retroarch_root is not None:
path = retroarch_root / record.get("local_relative_path", "")
map_path = retroarch_root / record.get("linker_map_relative_path", "")
if not path.is_file():
errors.append("local smoke ELF missing")
elif path.stat().st_size != record.get("size") or sha256_file(path) != record.get(
"sha256"
):
errors.append("local smoke ELF identity mismatch")
else:
try:
actual_headers = parse_elf_program_headers(path)
if not program_headers_are_wx_closed(actual_headers):
errors.append("local smoke ELF has a W+X load segment")
if actual_headers != record.get("program_headers"):
errors.append("local program headers differ from manifest")
actual_needed = parse_elf_needed(path)
if actual_needed != record.get("dt_needed"):
errors.append("local DT_NEEDED differs from manifest")
actual_undefined = parse_elf_dynamic_symbols(path)
if actual_undefined != record.get("undefined_symbols"):
errors.append("local undefined symbols differ from manifest")
if not imports_are_closed(actual_undefined):
errors.append("local smoke ELF has a forbidden import")
actual_relocations = parse_elf_relocations(path)
if actual_relocations != record.get("relocation_audit"):
errors.append("local relocation audit differs from manifest")
except (OSError, ValueError, struct.error) as error:
errors.append(str(error))
if not map_path.is_file():
errors.append("local linker map missing")
elif sha256_file(map_path) != record.get("linker_map_sha256"):
errors.append("local linker-map identity mismatch")
if git(retroarch_root, "rev-parse", "HEAD") != build.get(
"chimera_retroarch", {}
).get("source_commit"):
errors.append("RetroArch HEAD does not match manifest source")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path)
args = parser.parse_args()
errors = validate(
args.root.resolve(),
args.retroarch_root.resolve() if args.retroarch_root else None,
)
if errors:
for error in errors:
print(error, file=sys.stderr)
return 1
print("Phase 1.0B bounded RetroArch smoke evidence validated")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the Phase-1.0BA callsite and profile-delta audit."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path, required=True)
args = parser.parse_args()
path = args.root / "manifests/retroarch/phase-1.0ba-target-profile-callsite-audit.json"
data = json.loads(path.read_text(encoding="utf-8"))
bind = data["source_bindings"]
az = args.root / "manifests/retroarch/phase-1.0az-host-av-source.json"
assert hashlib.sha256(az.read_bytes()).hexdigest() == bind["phase10az_manifest_sha256"]
commit = bind["retroarch_commit"]
paths = {"retroarch_c": "retroarch.c",
"platform_ps5_c": "frontend/drivers/platform_ps5.c",
"makefile": "Makefile.ps5"}
for key, source in paths.items():
assert git(args.retroarch_root, "rev-parse", f"{commit}:{source}") == bind[f"{key}_blob"]
source = git(args.retroarch_root, "show", f"{commit}:retroarch.c")
sequence = "int result = rarch_main(argc, argv, NULL);"
sequence += "\n#if defined(CHIMERA_PS5_SMOKE_MODE)"
sequence += "\n chimera_ps5_smoke_set_phase(CHIMERA_SMOKE_S15_COMPLETE);\n _Exit(result);"
assert sequence in source
assert "main_exit(data);\n#endif\n\n return 0;" in source
assert not data["authorizations"]["target_build_authorized"]
assert data["decision"]["source_patch_allowed"]
assert not data["decision"]["cross_build_allowed"]
print("Phase-1.0BA callsite/profile audit validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the remote-bound Phase-1.0BB source profile."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(repo: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=repo, check=True,
capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0bb-source-only-launch-canary-profile.json").read_text(encoding="utf-8"))
bind = data["source_bindings"]
ba = args.root / "manifests/retroarch/phase-1.0ba-target-profile-callsite-audit.json"
assert hashlib.sha256(ba.read_bytes()).hexdigest() == bind["phase10ba_manifest_sha256"]
commit = bind["retroarch_commit"]
assert git(args.retroarch_root, "rev-parse", "HEAD") == commit
assert git(args.retroarch_root, "rev-parse", bind["remote_ref"]) == commit
assert git(args.retroarch_root, "rev-parse", f"{commit}^") == bind["retroarch_parent_commit"]
paths = {"makefile": "Makefile.ps5", "retroarch_c": "retroarch.c",
"validator": "tools/validate_ps5_phase10bb.py",
"tests": "tests/test_ps5_phase10bb.py",
"source_doc": "docs/ps5-phase10bb-launch-canary-profile.md"}
for key, source in paths.items():
assert git(args.retroarch_root, "rev-parse", f"{commit}:{source}") == bind[f"{key}_blob"]
assert data["verification"]["launch_canary_artifact_absent"]
assert data["authorizations"]["build_prerequisite_audit_authorized"]
assert not data["authorizations"]["target_build_authorized"]
assert not data["decision"]["cross_build_allowed"]
print("Phase-1.0BB source-profile binding validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the remote-bound Phase-1.0BD policy commit."""
import argparse
import hashlib
import json
import subprocess
from pathlib import Path
def git(root: Path, *args: str) -> str:
return subprocess.run(["git", *args], cwd=root, check=True,
capture_output=True, text=True).stdout.strip()
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path, required=True)
args = parser.parse_args()
data = json.loads((args.root / "manifests/retroarch/phase-1.0bd-dormant-sdl-materializer-policy.json").read_text(encoding="utf-8"))
bind = data["source_bindings"]
parent = args.root / "manifests/retroarch/phase-1.0bc-cross-build-prerequisite-audit.json"
assert hashlib.sha256(parent.read_bytes()).hexdigest() == bind["phase10bc_manifest_sha256"]
commit = bind["retroarch_commit"]
assert git(args.retroarch_root, "rev-parse", "HEAD") == commit
assert git(args.retroarch_root, "rev-parse", bind["remote_ref"]) == commit
assert git(args.retroarch_root, "rev-parse", f"{commit}^") == bind["retroarch_parent_commit"]
paths = {"makefile": "Makefile.ps5",
"policy": "tools/phase10bd_sdl_materializer_policy.py",
"validator": "tools/validate_ps5_phase10bd.py",
"tests": "tests/test_ps5_phase10bd_materializer_policy.py",
"source_doc": "docs/ps5-phase10bd-sdl-materializer-policy.md"}
for key, source in paths.items():
assert git(args.retroarch_root, "rev-parse", f"{commit}:{source}") == bind[f"{key}_blob"]
assert data["authorizations"]["injected_adapter_source_authorized"]
assert not data["authorizations"]["live_adapter_authorized"]
assert not data["decision"]["materialization_allowed"]
print("Phase-1.0BD dormant policy binding validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+326
View File
@@ -0,0 +1,326 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the offline Phase-1.0D diagnostic ladder evidence."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import sys
from typing import Any
PHASE = "PHASE_1_0D_LOADER_TO_ENTRY_DIAGNOSIS"
STATUS = "RETROARCH_PS5_ENTRY_DIAGNOSTIC_LADDER_BUILT_OFFLINE"
RETROARCH_BRANCH = "codex/ps5-loader-entry-diagnosis"
RETROARCH_COMMIT = "69b65858ffaee826d70f5c0df61013cd1b0e2048"
DENYLIST_SHA256 = "e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
CANARY_IMPORTS = {
"_Exit",
"memset",
"nanosleep",
"sceKernelSendNotificationRequest",
}
CANARY_NEEDED = {"libSceLibcInternal.sprx", "libkernel_web.sprx"}
REAL_MODEL_ARTIFACTS = {
"retroarch_ps5_software_smoke.elf",
"chimera_ps5_crt_entry_canary.elf",
"retroarch_ps5_early_diag.elf",
"chimera-gfx-lifecycle-probe.elf",
}
AUTHORIZATION_FIELDS = (
"ps5_connection_authorized",
"device_transfer_authorized",
"device_execution_authorized",
"installation_authorized",
"autoload_authorized",
"device_write_authorized",
"automatic_retry",
)
ACTION_FIELDS = (
"ps5_connected",
"device_request_performed",
"files_transferred",
"device_write_performed",
"target_execution_performed",
)
DELIVERABLES = (
"docs/retroarch/phase-1.0d-loader-to-entry-analysis.md",
"docs/retroarch/phase-1.0d-crt-entry-canary.md",
"docs/retroarch/phase-1.0d-early-diagnostic-design.md",
"docs/retroarch/phase-1.0d-startup-import-closure.md",
"docs/retroarch/phase-1.0d-loader-static-model.md",
"docs/retroarch/phase-1.0d-next-device-test-ladder.md",
"manifests/retroarch/phase-1.0d-canary-artifact.json",
"manifests/retroarch/phase-1.0d-early-diag-artifact.json",
"manifests/retroarch/phase-1.0d-loader-model-results.json",
"tools/validate_retroarch_phase10d.py",
"tests/test_retroarch_phase10d.py",
"packaging/retroarch/phase10d/SHA256SUMS.txt",
)
def load_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise ValueError(f"{path} is not a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def all_false(record: dict[str, Any], fields: tuple[str, ...]) -> bool:
return all(record.get(field) is False for field in fields)
def reproducible_artifact(record: dict[str, Any]) -> bool:
artifact = record.get("artifact", {})
elf_hashes = artifact.get("clean_build_sha256", [])
map_hashes = artifact.get("clean_map_sha256", [])
return (
artifact.get("size", 0) > 0
and len(artifact.get("sha256", "")) == 64
and len(elf_hashes) == 2
and len(set(elf_hashes)) == 1
and elf_hashes[0] == artifact.get("sha256")
and len(map_hashes) == 2
and len(set(map_hashes)) == 1
and map_hashes[0] == artifact.get("linker_map_sha256")
)
def wx_closed(headers: list[dict[str, Any]]) -> bool:
loads = [item for item in headers if item.get("type") == "LOAD"]
return (
len(loads) == 3
and any("E" in str(item.get("flags", "")) for item in loads)
and all(
not (
"W" in str(item.get("flags", ""))
and "E" in str(item.get("flags", ""))
)
for item in loads
)
)
def canary_is_minimal(record: dict[str, Any]) -> bool:
behavior = record.get("behavior", {})
elf = record.get("elf", {})
return (
set(elf.get("undefined_symbols", [])) == CANARY_IMPORTS
and set(elf.get("dt_needed", [])) == CANARY_NEEDED
and record.get("notification_abi", {}).get("maximum_attempts") == 1
and record.get("notification_abi", {}).get("retry") is False
and behavior.get("sleep_attempts") == 1
and behavior.get("interrupted_sleep_retry") is False
and all(
behavior.get(field) is False
for field in (
"retroarch", "sdl", "videoout", "pad", "audioout",
"filesystem", "networking", "threads", "autoload", "installation",
)
)
)
def early_ladder_is_closed(record: dict[str, Any]) -> bool:
diagnostic = record.get("diagnostic", {})
frame = record.get("first_frame", {})
policy = record.get("profile_policy", {})
return (
diagnostic.get("stages") == [f"D{index:02d}" for index in range(13)]
and diagnostic.get("notification_maximum_attempts_per_stage") == 1
and diagnostic.get("notification_retry") is False
and diagnostic.get("notification_failure_blocks_primary_path") is False
and frame.get("background") == "MAGENTA"
and frame.get("fixed_rectangle") == "WHITE"
and frame.get("embedded_pattern") == "BLACK"
and frame.get("submit_attempts") == 1
and frame.get("retry") is False
and frame.get("second_buffer_initialization") is False
and policy.get("write_firewall") is True
and all(
policy.get(field) is False
for field in (
"filesystem_writes_allowed", "networking", "dynamic_cores",
"gnm", "autoload", "installation", "payload_launch",
"automatic_retry",
)
)
)
def model_result_set_is_complete(record: dict[str, Any]) -> bool:
artifacts = record.get("real_artifacts", [])
names = {item.get("name") for item in artifacts}
return (
names == REAL_MODEL_ARTIFACTS
and all(
item.get("classification")
in {
"ACCEPTED_BY_STATIC_MODEL",
"REJECTED_BY_STATIC_MODEL",
"MODEL_INCOMPLETE",
}
for item in artifacts
)
and all(len(item.get("sha256", "")) == 64 for item in artifacts)
and record.get("model", {}).get("hardware_evidence") is False
)
def sender_trace_is_bounded(trace: dict[str, Any]) -> bool:
return (
trace.get("connections") == 1
and trace.get("sendall_calls") == 1
and trace.get("hash_before_connect") is True
and trace.get("shutdown_called") is False
and trace.get("response_read") is False
and trace.get("retry") is False
and trace.get("reconnect") is False
and trace.get("probe") is False
and "REMOTE_EXECUTION" in trace.get("cannot_prove", [])
)
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args],
cwd=root,
capture_output=True,
text=True,
check=False,
)
if result.returncode:
raise RuntimeError(result.stderr.strip() or "git failed")
return result.stdout.strip()
def validate(root: Path, retroarch_root: Path | None = None) -> list[str]:
errors: list[str] = []
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
try:
canary = load_json(
root / "manifests/retroarch/phase-1.0d-canary-artifact.json"
)
early = load_json(
root / "manifests/retroarch/phase-1.0d-early-diag-artifact.json"
)
model = load_json(
root / "manifests/retroarch/phase-1.0d-loader-model-results.json"
)
except (OSError, ValueError, json.JSONDecodeError) as error:
return errors + [str(error)]
for label, record in (("canary", canary), ("early", early), ("model", model)):
if record.get("phase") != PHASE or record.get("status") != STATUS:
errors.append(f"{label} phase/status mismatch")
if not all_false(record.get("authorizations", {}), AUTHORIZATION_FIELDS):
errors.append(f"{label} authorization must remain false")
if not all_false(record.get("actions", {}), ACTION_FIELDS):
errors.append(f"{label} device action must remain false")
for label, record in (("canary", canary), ("early", early)):
artifact = record.get("artifact", {})
elf = record.get("elf", {})
if not reproducible_artifact(record):
errors.append(f"{label} is not reproducible")
if artifact.get("execution_eligible") is not False:
errors.append(f"{label} execution eligibility must be false")
if elf.get("rwx_load_segment_count") != 0:
errors.append(f"{label} RWX count is not zero")
if not wx_closed(elf.get("program_headers", [])):
errors.append(f"{label} headers are not W^X closed")
if elf.get("init_array_size") != 0 or elf.get("fini_array_size") != 0:
errors.append(f"{label} constructor arrays are not empty")
if elf.get("tls") is not False:
errors.append(f"{label} TLS must be absent")
if not canary_is_minimal(canary):
errors.append("canary closure is not minimal")
if not early_ladder_is_closed(early):
errors.append("early diagnostic ladder is not closed")
if not model_result_set_is_complete(model):
errors.append("loader model real-artifact set is incomplete")
if not sender_trace_is_bounded(model.get("sender_trace_contract", {})):
errors.append("sender trace contract is not bounded")
negative = model.get("negative_host_cases", [])
if len(negative) != 5 or {
item.get("classification") for item in negative
} != {
"ACCEPTED_BY_STATIC_MODEL",
"REJECTED_BY_STATIC_MODEL",
"MODEL_INCOMPLETE",
}:
errors.append("negative loader cases are incomplete")
denylist = root / "manifests/artifact-denylist.json"
if not denylist.is_file() or sha256_file(denylist) != DENYLIST_SHA256:
errors.append("permanent denylist changed")
tracked = git(root, "ls-files").splitlines()
for relative in tracked:
if relative.lower().endswith((".elf", ".self", ".sprx", ".pkg")):
errors.append(f"tracked target artifact: {relative}")
forbidden_address = "192.168.10." + "105"
for relative in tracked:
path = root / relative
try:
text = path.read_text(encoding="utf-8")
except (OSError, UnicodeDecodeError):
continue
if forbidden_address in text:
errors.append(f"tracked device address in {relative}")
if retroarch_root is not None:
if git(retroarch_root, "rev-parse", "HEAD") != RETROARCH_COMMIT:
errors.append("chimera-retroarch HEAD mismatch")
if git(retroarch_root, "branch", "--show-current") != RETROARCH_BRANCH:
errors.append("chimera-retroarch branch mismatch")
for label, record in (("canary", canary), ("early", early)):
artifact = record["artifact"]
elf_path = retroarch_root / artifact["local_relative_path"]
map_path = retroarch_root / artifact["linker_map_relative_path"]
if not elf_path.is_file():
errors.append(f"{label} local ELF missing")
elif (
elf_path.stat().st_size != artifact["size"]
or sha256_file(elf_path) != artifact["sha256"]
):
errors.append(f"{label} local ELF identity mismatch")
if not map_path.is_file():
errors.append(f"{label} local map missing")
elif sha256_file(map_path) != artifact["linker_map_sha256"]:
errors.append(f"{label} local map identity mismatch")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path)
args = parser.parse_args()
errors = validate(
args.root.resolve(),
args.retroarch_root.resolve() if args.retroarch_root else None,
)
if errors:
print("\n".join(errors), file=sys.stderr)
return 1
print("Phase 1.0D offline diagnostic ladder evidence validated")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate Phase-1.0DC identities and inactive policy."""
from __future__ import annotations
import argparse,ast,hashlib,json
from pathlib import Path
SOURCE=(6096,"b8e965f343a0c3df5cf7026b68f547a81dad08d4b2e0934e4f9721de8b99010f")
TESTS=(2630,"ecef8f126e2245d707a776b4fd02aad13553e6e79515287e1002d2855a8db2d2")
NETWORK={"socket","select","selectors","subprocess","urllib","http","requests"}
def exact(path,identity):
data=path.read_bytes();return (len(data),hashlib.sha256(data).hexdigest())==identity
def errors(record,root=None):
out=[];activation=record.get("activation",{})
if record.get("status")!="INACTIVE_DUAL_ARTIFACT_BIGAPP_GATE_COMPLETE_TARGET_IMPLEMENTATION_BLOCKED":out.append("status")
if activation.get("active") is not False or any(value is not None for key,value in activation.items() if key!="active"):out.append("activation")
if any(record.get("authorizations",{}).values()):out.append("authorization")
if any(record.get("implementation_boundary",{}).values()):out.append("implementation")
c=record.get("candidate_contract",{})
if c.get("exact_payload_sha256")!="8dadce9d9faaef21ea129a3d216c768eea9a3ca9bf8ecb8d852e376b58a9bf95" or c.get("fixed_existing_title")!="PPSA01659" or c.get("sole_cleanup_terminal")!="D14":out.append("candidate")
if not all(record.get("forbidden_effects",{}).values()):out.append("forbidden")
if record.get("decision")!={"host_gate_contract_complete":True,"candidate_can_currently_pass":False,"target_implementation_allowed":False,"device_action_allowed":False,"next_step":"OFFLINE_MINIMAL_LAUNCHER_SOURCE_PREREQUISITE_CLOSURE"}:out.append("decision")
if root:
source=root/"tools/phase10dc_bigapp_gate_contract.py";tests=root/"tests/test_phase10dc_bigapp_gate_contract.py"
if not exact(source,SOURCE):out.append("source identity")
if not exact(tests,TESTS):out.append("test identity")
tree=ast.parse(source.read_text());imports={a.name.split('.')[0] for n in ast.walk(tree) if isinstance(n,ast.Import) for a in n.names}|{(n.module or '').split('.')[0] for n in ast.walk(tree) if isinstance(n,ast.ImportFrom)}
if imports&NETWORK:out.append("network import")
return out
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);root=p.parse_args().root.resolve();record=json.loads((root/"manifests/retroarch/phase-1.0dc-inactive-bigapp-comparison-gate.json").read_text());found=errors(record,root)
for item in found:print("ERROR:",item)
if found:return 1
print("Phase-1.0DC inactive BigApp gate validation passed");return 0
if __name__=="__main__":raise SystemExit(main())
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import argparse,ast,hashlib,json
from pathlib import Path
SOURCE=(5298,"2679f03617241abf37ca547141a2a51e3f89b75fec957a1da4f13b904d931f2d");TESTS=(2496,"3760fa60e66857b24bf507f196060ec9e4d8b96ebce3843ab02fc185c0f8c0b8");NETWORK={"socket","select","selectors","subprocess","urllib","http","requests"}
def exact(path,identity):data=path.read_bytes();return (len(data),hashlib.sha256(data).hexdigest())==identity
def errors(record,root=None):
out=[];a=record.get("activation",{})
if record.get("status")!="HOST_OBSERVER_CONTRACT_COMPLETE_LIVE_REQUEST_UNFORMABLE":out.append("status")
if a.get("active") is not False or any(v is not None for k,v in a.items() if k!="active"):out.append("activation")
if any(record.get("authorizations",{}).values()) or any(record.get("implementation_boundary",{}).values()):out.append("capability")
evidence=record.get("current_evidence",{})
if any(evidence.values()):out.append("evidence promoted")
contract=record.get("observer_contract",{})
if contract.get("allowlisted_methods") != ["SOURCE_BOUND_QUERY","EXACT_PATH_METADATA"] or contract.get("error_is_absence") is not False or contract.get("maximum_result_bytes")!=4096:out.append("contract")
if not all(contract.get(k) is True for k in ("shell_forbidden","directory_enumeration_forbidden","title_launch_forbidden","app_termination_forbidden","device_write_forbidden","retry_forbidden","reconnect_forbidden")):out.append("forbidden")
if record.get("decision")!={"host_observer_contract_complete":True,"live_observer_implementation_allowed":False,"live_observation_allowed":False,"device_action_allowed":False,"next_step":"OFFLINE_SOURCE_AUDIT_FOR_ONE_NONMUTATING_TITLE_PRESENCE_PRIMITIVE"}:out.append("decision")
if root:
source=root/"tools/phase10df_title_observer_contract.py";tests=root/"tests/test_phase10df_title_observer_contract.py"
if not exact(source,SOURCE):out.append("source identity")
if not exact(tests,TESTS):out.append("test identity")
tree=ast.parse(source.read_text());imports={x.name.split('.')[0] for n in ast.walk(tree) if isinstance(n,ast.Import) for x in n.names}|{(n.module or '').split('.')[0] for n in ast.walk(tree) if isinstance(n,ast.ImportFrom)}
if imports&NETWORK:out.append("network import")
return out
def main():
p=argparse.ArgumentParser();p.add_argument("--root",type=Path,required=True);root=p.parse_args().root.resolve();record=json.loads((root/"manifests/retroarch/phase-1.0df-inactive-title-presence-observer.json").read_text());found=errors(record,root)
for item in found:print("ERROR:",item)
if found:return 1
print("Phase-1.0DF inactive title observer validation passed");return 0
if __name__=="__main__":raise SystemExit(main())
+382
View File
@@ -0,0 +1,382 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Validate the consumed Phase-1.0E inherited result-channel evidence."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import sys
from typing import Any
PHASE = "PHASE_1_0E_INHERITED_RESULT_CHANNEL"
STATUS = "ONE_SHOT_DEVICE_TEST_COMPLETED_INCOMPLETE_BEFORE_D03"
RETROARCH_BRANCH = "codex/ps5-inherited-result-channel"
RETROARCH_COMMIT = "aed1a6e014d56ed25456b8b095955c7d41f7025d"
OFFLINE_FOLLOWUP_COMMIT = "f1391c3e6717ff4e2b869007fb9627c9edde52e4"
ARTIFACT_SOURCE_COMMIT = "b9fc037304a14199f35f8229edac26fa5c840509"
LOADER_COMMIT = "197623058f509eddde18868dafcb92fdcac66464"
DENYLIST_SHA256 = "e9603b0e3792781ad5b511afb22ef61e3d4fd4c5a16bf928f8609193bcd97783"
ARTIFACT_SHA256 = "1049c78099a60b472a3fb0e2999e3393b6ad76337a28532a7e53872e7772dedf"
ARTIFACT_SIZE = 1844880
MAP_SHA256 = "ae9739f6f578953bc8dc562bb55967ba587912d161b2d6787438450addec3b44"
TRACE_SHA256 = "4ff27a0eac48283cdc4c7ff964226def2689e808e3adea6594d0e77674a676f0"
TRACE_SIZE = 1795
FORBIDDEN_TARGET_IMPORTS = {"socket", "connect", "bind", "listen", "accept", "recv"}
AUTHORIZATION_FIELDS = (
"ps5_connection_authorized",
"device_transfer_authorized",
"device_execution_authorized",
"result_receive_authorized",
"installation_authorized",
"autoload_authorized",
"device_write_authorized",
"automatic_retry",
)
PERFORMED_ACTION_FIELDS = (
"ps5_connected",
"device_request_performed",
"files_transferred",
"target_execution_performed",
"result_received_from_device",
)
FORBIDDEN_ACTION_FIELDS = (
"device_write_performed",
"installation_performed",
"autoload_performed",
)
DELIVERABLES = (
"docs/retroarch/phase-1.0e-device-observations.md",
"docs/retroarch/phase-1.0e-inherited-result-channel.md",
"docs/retroarch/phase-1.0e-next-device-test.md",
"docs/approvals/phase-1.0e-one-shot-result-test.md",
"manifests/retroarch/phase-1.0e-result-channel.json",
"tools/validate_retroarch_phase10e.py",
"tests/test_retroarch_phase10e.py",
"packaging/retroarch/phase10e/SHA256SUMS.txt",
)
def load_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise ValueError(f"{path} is not a JSON object")
return value
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def git(root: Path, *args: str) -> str:
result = subprocess.run(
["git", *args], cwd=root, capture_output=True, text=True, check=False
)
if result.returncode:
raise RuntimeError(result.stderr.strip() or "git failed")
return result.stdout.strip()
def all_false(record: dict[str, Any], fields: tuple[str, ...]) -> bool:
return all(record.get(field) is False for field in fields)
def reproducible_artifact(record: dict[str, Any]) -> bool:
hashes = record.get("clean_build_sha256", [])
map_hashes = record.get("clean_map_sha256", [])
return (
record.get("size") == ARTIFACT_SIZE
and record.get("sha256") == ARTIFACT_SHA256
and hashes == [ARTIFACT_SHA256, ARTIFACT_SHA256]
and record.get("linker_map_sha256") == MAP_SHA256
and map_hashes == [MAP_SHA256, MAP_SHA256]
and record.get("execution_eligible") is False
and record.get("transfer_eligible") is False
and record.get("installation_eligible") is False
and record.get("device_action_performed") is True
)
def wx_closed(headers: list[dict[str, Any]]) -> bool:
loads = [item for item in headers if item.get("type") == "LOAD"]
return len(loads) == 3 and all(
not ({"W", "E"} <= set(str(item.get("flags", "")))) for item in loads
)
def transport_is_bounded(record: dict[str, Any]) -> bool:
loader = record.get("loader_transport", {})
protocol = record.get("result_protocol", {})
host = record.get("host_contract", {})
return (
loader.get("raw_elf_exact_length_read") is True
and loader.get("payload_stdout_inherits_connection") is True
and loader.get("controlled_route_supported") is False
and loader.get("new_loader_change") is False
and loader.get("new_target_socket") is False
and loader.get("new_target_connection") is False
and protocol.get("frame_size") == 64
and protocol.get("target_write_attempts_per_stage") == 1
and protocol.get("target_write_retry") is False
and protocol.get("short_write_retry") is False
and protocol.get("target_import_added") == "send"
and set(protocol.get("target_forbidden_imports_absent", []))
== FORBIDDEN_TARGET_IMPORTS
and host.get("hash_before_socket_creation") is True
and host.get("exact_size_before_socket_creation") is True
and host.get("connection_count") == 1
and host.get("sendall_count") == 1
and host.get("shutdown_write_count") == 1
and host.get("receive_limit_bytes") == 65536
and host.get("retry") is False
and host.get("reconnect") is False
and host.get("resume") is False
and host.get("trace_overwrite") is False
and host.get("partial_result_is_success") is False
)
def observations_are_bounded(record: dict[str, Any]) -> bool:
prior = record.get("prior_device_observations", {})
run_a = prior.get("run_a", {})
run_b = prior.get("run_b", {})
return (
prior.get("evidence_class") == "OPERATOR_OBSERVED_ARTIFACT_BOUND"
and run_a.get("authorization_consumed") is True
and run_a.get("classification")
== "CRT_MAIN_AND_NOTIFICATION_PROVEN_ON_FW_9_60"
and run_b.get("authorization_consumed") is True
and run_b.get("classification")
== "PAYLOAD_NOTIFICATION_CODE_EXECUTED_STAGE_UNCLASSIFIED"
and run_b.get("console_remained_responsive") is True
)
def device_run_is_exact(record: dict[str, Any]) -> bool:
run = record.get("device_run", {})
frames = run.get("validated_frames", [])
return (
run.get("run_id") == "RUN_C"
and run.get("authorization_consumed") is True
and run.get("firmware") == "9.60"
and run.get("trace_tracked") is False
and run.get("trace_size") == TRACE_SIZE
and run.get("trace_sha256") == TRACE_SHA256
and run.get("connection_count") == 1
and run.get("sendall_count") == 1
and run.get("shutdown_write_count") == 1
and run.get("retry_count") == 0
and run.get("reconnect_count") == 0
and run.get("close_called") is True
and run.get("remote_eof_observed") is True
and run.get("timeout_observed") is False
and run.get("parser_errors") == []
and [frame.get("stage") for frame in frames] == ["D00", "D01", "D02"]
and [frame.get("sequence") for frame in frames] == [1, 2, 3]
and frames[2].get("raw0") == 0
and all(frame.get("notification_result") == 0 for frame in frames)
and all(frame.get("terminal") is False for frame in frames)
and run.get("terminal_stage") is None
and run.get("last_proven_stage") == "D02"
and run.get("classification")
== "REMOTE_PAYLOAD_OUTPUT_PROVEN_INCOMPLETE_BEFORE_D03"
and "D03_SDL_INIT_BEGIN" in run.get("does_not_prove", [])
and "SAFE_EXIT_OR_LOADER_CLEANUP" in run.get("does_not_prove", [])
)
def offline_followup_is_bounded(record: dict[str, Any]) -> bool:
followup = record.get("offline_followup", {})
return (
followup.get("repository") == "chimera-retroarch"
and followup.get("branch") == RETROARCH_BRANCH
and followup.get("commit") == OFFLINE_FOLLOWUP_COMMIT
and followup.get("classification")
== "D02_TO_D03_SOURCE_INTERVAL_BOUNDED_CAUSE_UNPROVEN"
and followup.get("bounded_raw_stream_retention") is True
and followup.get("bounded_ordinary_stdout_retention") is True
and followup.get("encoding") == "base64"
and followup.get("sha256_recorded") is True
and followup.get("maximum_pre_encoding_bytes") == 65536
and followup.get("exclusive_trace_creation") is True
and followup.get("consumed_manifest_rejected") is True
and followup.get("retry") is False
and followup.get("reconnect") is False
and followup.get("device_action_performed") is False
and followup.get("target_code_changed") is False
and followup.get("target_artifact_created") is False
and followup.get("authorization_changed") is False
)
def validate(
root: Path,
retroarch_root: Path | None = None,
loader_root: Path | None = None,
) -> list[str]:
errors: list[str] = []
for relative in DELIVERABLES:
if not (root / relative).is_file():
errors.append(f"missing deliverable: {relative}")
try:
record = load_json(
root / "manifests/retroarch/phase-1.0e-result-channel.json"
)
except (OSError, ValueError, json.JSONDecodeError) as error:
return errors + [str(error)]
if record.get("phase") != PHASE or record.get("status") != STATUS:
errors.append("phase/status mismatch")
if record.get("source_commit") != ARTIFACT_SOURCE_COMMIT:
errors.append("source commit mismatch")
if record.get("host_client_commit") != RETROARCH_COMMIT:
errors.append("host client commit mismatch")
authorizations = record.get("authorizations", {})
if not all_false(authorizations, AUTHORIZATION_FIELDS):
errors.append("consumed Phase-1.0E authorization must be fully false")
actions = record.get("phase_actions", {})
if not all(actions.get(field) is True for field in PERFORMED_ACTION_FIELDS):
errors.append("performed one-shot actions are missing")
if not all_false(actions, FORBIDDEN_ACTION_FIELDS):
errors.append("a forbidden device action was recorded")
if not observations_are_bounded(record):
errors.append("prior device observations are overclaimed or incomplete")
active = record.get("active_one_shot", {})
if not (
active.get("artifact_sha256") == ARTIFACT_SHA256
and active.get("artifact_size") == ARTIFACT_SIZE
and active.get("firmware") == "9.60"
and active.get("connection_count") == 1
and active.get("transfer_count") == 1
and active.get("execution_count") == 1
and active.get("result_receive_count") == 1
and active.get("timeout_seconds") == 75
and active.get("automatic_retry") is False
and active.get("reconnect") is False
and active.get("installation") is False
and active.get("autoload") is False
and active.get("device_write") is False
and active.get("consumed") is True
):
errors.append("one-shot contract is not exact or not consumed")
if not reproducible_artifact(record.get("artifact", {})):
errors.append("artifact is not exact, reproducible and post-run ineligible")
if not device_run_is_exact(record):
errors.append("RUN C result is missing, malformed or overclaimed")
if not offline_followup_is_bounded(record):
errors.append("offline D02-to-D03 follow-up is missing or unsafe")
elf = record.get("elf", {})
imports = set(elf.get("undefined_symbols", []))
if elf.get("rwx_load_segment_count") != 0 or not wx_closed(
elf.get("program_headers", [])
):
errors.append("ELF load layout is not W^X closed")
if elf.get("init_array_size") != 0 or elf.get("fini_array_size") != 0:
errors.append("constructor arrays are not empty")
if elf.get("tls") is not False:
errors.append("TLS must be absent")
if "send" not in imports or imports & FORBIDDEN_TARGET_IMPORTS:
errors.append("target import closure is not inherited-output-only")
if elf.get("undefined_symbol_delta_from_phase10d") != ["send"]:
errors.append("Phase-1.0D import delta must be exactly send")
if not transport_is_bounded(record):
errors.append("transport or host contract is not bounded")
effects = record.get("startup_effects", {})
if not (
effects.get("normal_sdk_crt") is True
and effects.get("patch_init_reachable_from_start") is True
and effects.get("kernel_copy_helpers_statically_linked") is True
and effects.get("side_effect_free") is False
):
errors.append("SDK startup effects are hidden or misclassified")
denylist = root / "manifests/artifact-denylist.json"
if not denylist.is_file() or sha256_file(denylist) != DENYLIST_SHA256:
errors.append("permanent denylist changed")
tracked = git(root, "ls-files").splitlines()
for relative in tracked:
if relative.lower().endswith((".elf", ".self", ".sprx", ".pkg")):
errors.append(f"tracked target artifact: {relative}")
path = root / relative
try:
text = path.read_text(encoding="utf-8")
except (OSError, UnicodeDecodeError):
continue
if "192.168.10." + "105" in text:
errors.append(f"tracked device address in {relative}")
if retroarch_root is not None:
ancestor = subprocess.run(
["git", "merge-base", "--is-ancestor", RETROARCH_COMMIT, "HEAD"],
cwd=retroarch_root,
capture_output=True,
check=False,
)
if ancestor.returncode:
errors.append("tested chimera-retroarch host client commit is not an ancestor")
followup_ancestor = subprocess.run(
["git", "merge-base", "--is-ancestor", OFFLINE_FOLLOWUP_COMMIT, "HEAD"],
cwd=retroarch_root,
capture_output=True,
check=False,
)
if followup_ancestor.returncode:
errors.append("offline stdout-capture commit is not an ancestor")
if git(retroarch_root, "branch", "--show-current") != RETROARCH_BRANCH:
errors.append("chimera-retroarch branch mismatch")
artifact = record["artifact"]
elf_path = retroarch_root / artifact["local_relative_path"]
map_path = retroarch_root / artifact["linker_map_relative_path"]
if not elf_path.is_file() or (
elf_path.stat().st_size != ARTIFACT_SIZE
or sha256_file(elf_path) != ARTIFACT_SHA256
):
errors.append("local result ELF missing or changed")
if not map_path.is_file() or sha256_file(map_path) != MAP_SHA256:
errors.append("local result linker map missing or changed")
run = record["device_run"]
trace_path = retroarch_root / run["trace_relative_path"]
if not trace_path.is_file() or (
trace_path.stat().st_size != TRACE_SIZE
or sha256_file(trace_path) != TRACE_SHA256
):
errors.append("local ignored RUN C trace missing or changed")
if loader_root is not None:
if git(loader_root, "rev-parse", "HEAD") != LOADER_COMMIT:
errors.append("hardened elfldr HEAD mismatch")
if git(loader_root, "status", "--porcelain"):
errors.append("hardened elfldr tree is dirty")
return errors
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--retroarch-root", type=Path)
parser.add_argument("--loader-root", type=Path)
args = parser.parse_args()
errors = validate(
args.root.resolve(),
args.retroarch_root.resolve() if args.retroarch_root else None,
args.loader_root.resolve() if args.loader_root else None,
)
if errors:
for error in errors:
print(f"ERROR: {error}", file=sys.stderr)
return 1
print("Phase-1.0E inherited result-channel validation passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())

Some files were not shown because too many files have changed in this diff Show More