"""Collect/verify notices for the independent application graph, never legacy Cosmos.
Uses restored packages and existing pinned source/tool notices. Existing output
must remain byte-identical. No downloads, package edits, or binary copies occur.
"""
import argparse
import hashlib
import json
from pathlib import Path
import re
import xml.etree.ElementTree as ET
ROOT = Path(__file__).resolve().parents[2]
OUTPUT = ROOT / "Tools/IndependentKernel/Licenses"
OLD = ROOT / "Tools/CSharpBoot/Licenses/Collected"
APP_LOCK = ROOT / "Source/XFESystem.NativeRuntime/Application/packages.lock.json"
RUNTIME_LOCK = ROOT / "Tools/IndependentKernel/Runtime/NativeToolchain.json"
TLS_IDENTITY = ROOT / "Source/XFESystem.Tls/DependencyManifest.json"
TLS_LOCK = ROOT / "Source/XFESystem.Tls/Packages.lock.json"
SECURITY_ROOT = ROOT / "Source/XFESystem.NativeRuntime/Application/Security"
UPSTREAM = {"Acornima": "Acornima", "AngleSharp": "AngleSharp", "AngleSharp.Css": "AngleSharpCss",
"HtmlSanitizer": "HtmlSanitizer", "Jint": "Jint", "Markdig": "Markdig", "Mono.Cecil": "MonoCecil"}
def digest(data):
return hashlib.sha256(data).hexdigest()
def read_json(path):
return json.loads(path.read_text(encoding="utf-8-sig"))
def save(relative, data):
target = (OUTPUT / relative).resolve()
if not target.is_relative_to(OUTPUT.resolve()):
raise ValueError("Notice escaped the independent directory")
target.parent.mkdir(parents=True, exist_ok=True)
if target.exists():
assert target.read_bytes() == data, f"Existing notice changed: {relative}"
else:
target.write_bytes(data)
return {"Path": relative, "Sha256": digest(data), "Bytes": len(data)}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--NuGetCache", type=Path, default=Path.home() / ".nuget/packages")
parser.add_argument("--ToolRoot", type=Path, default=ROOT / ".tools")
args = parser.parse_args()
files, packages, components = [], [], []
source_manifest = read_json(OUTPUT / "LicenseSources.json")
package_licenses = {item["Id"]: item for item in source_manifest.get("PackageLicenseFiles", [])}
upstream_notices = {item["Id"]: item for item in source_manifest.get("ExternalPackageNotices", [])}
tls_identity = read_json(TLS_IDENTITY)
source_specs = read_json(ROOT / "Tools/CSharpBoot/LicenseSources.json")["OfficialSources"]
official = {item["Name"]: item for item in source_specs}
def copy(relative, source, scope, url=None, expected=None):
data = source.read_bytes()
if expected:
assert digest(data) == expected, f"Source differs: {source}"
record = save(relative, data)
record.update(Scope=scope)
try:
record["SourcePath"] = str(source.relative_to(ROOT)).replace("\\", "/")
except ValueError:
record["SourcePath"] = "Restored NuGet cache/" + source.name
if url:
record["SourceUrl"] = url
if not any(item["Path"] == relative for item in files):
files.append(record)
return relative
def collect_package(identifier, specification, scope):
version = specification["resolved"]
directory = args.NuGetCache / identifier.lower() / version
metadata = read_json(directory / ".nupkg.metadata")
assert metadata["contentHash"] == specification["contentHash"], identifier + " differs from lock"
bundle = directory / (identifier.lower() + "." + version + ".nupkg")
nuspec = directory / (identifier.lower() + ".nuspec")
document = ET.fromstring(nuspec.read_bytes())
ns = {"n": document.tag[1:].split("}")[0]}
declaration = document.find("n:metadata/n:license", ns)
repository = document.find("n:metadata/n:repository", ns)
prefix = "Packages/" + identifier + "-" + version
record = {"Id": identifier, "Version": version, "Scope": scope,
"Classification": "SameAuthorSeparateProject" if identifier.startswith("XFEExtension") else "External",
"LockedContentHash": specification["contentHash"], "NuGetContentHash": metadata["contentHash"],
"NupkgSha256": digest(bundle.read_bytes()),
"Repository": dict(repository.attrib) if repository is not None else {},
"LicenseDeclaration": {"Type": declaration.attrib.get("type"), "Value": declaration.text} if declaration is not None else {},
"LicenseFiles": []}
copy(prefix + "/Metadata.nuspec", nuspec, scope)
if identifier in package_licenses:
spec = package_licenses[identifier]
assert version == spec["Version"], "Pinned license package version differs"
assert identifier == tls_identity["Package"] and version == tls_identity["Version"], "TLS dependency version differs"
assert specification["contentHash"] == tls_identity["NuGetContentSha512"], "TLS content lock differs"
assert record["NupkgSha256"] == tls_identity["PackageSha256"], "TLS package archive differs"
assert record["Repository"].get("commit") == tls_identity["SourceCommitFromNuGetMetadata"], "TLS repository commit differs"
assert record["LicenseDeclaration"] == {"Type": "expression", "Value": tls_identity["License"]}, "TLS license declaration differs"
assert read_json(TLS_LOCK)["dependencies"]["net10.0"][identifier]["contentHash"] == specification["contentHash"], "TLS project lock differs"
record["LicenseFiles"].append(copy(prefix + "/" + spec["File"], directory / spec["File"], scope,
tls_identity["PackageUrl"], spec["Sha256"]))
record["DependencyManifestSha256"] = digest(TLS_IDENTITY.read_bytes())
elif identifier in upstream_notices:
spec=upstream_notices[identifier]
assert version==spec['Version'] and record['Repository'].get('commit')==spec['RepositoryCommit'], 'Storage package identity differs'
assert record['LicenseDeclaration']=={'Type':'expression','Value':spec['License']}, 'Storage package license differs'
for item in spec['Notices']:
record['LicenseFiles'].append(copy(item['Path'],OUTPUT/item['Path'],scope,item['SourceUrl'],item['Sha256']))
if spec.get('NoticeProvenance'):record['NoticeProvenance']=spec['NoticeProvenance']
elif declaration is not None and declaration.attrib.get("type") == "file":
record["LicenseFiles"].append(copy(prefix + "/" + declaration.text, directory / declaration.text, scope))
elif identifier in UPSTREAM:
key = UPSTREAM[identifier]
spec = official[key]
record["LicenseFiles"].append(copy("Upstream/" + key + "/License.txt", OLD / "Upstream" / key / "License.txt",
scope, spec["Url"], spec["Sha256"]))
else:
raise ValueError("No complete license for " + identifier)
packages.append(record)
app = read_json(APP_LOCK)
assert list(app["dependencies"]) == ["net10.0"], "Unexpected application target"
for identifier, specification in app["dependencies"]["net10.0"].items():
if specification["type"] == "Project":
continue
assert not identifier.lower().startswith("cosmos"), "Cosmos entered the independent app"
collect_package(identifier, specification, "IndependentApplicationGraph")
patch_lock = ROOT / "Tools/JintCleanupPatch/Packages.lock.json"
cecil = read_json(patch_lock)["dependencies"]["net10.0"]["Mono.Cecil"]
entropy_patch_lock = ROOT / "Tools/TlsEntropyPatch/Packages.lock.json"
entropy_cecil = read_json(entropy_patch_lock)["dependencies"]["net10.0"]["Mono.Cecil"]
assert entropy_cecil == cecil, "Private patch tools must share the pinned Mono.Cecil identity"
collect_package("Mono.Cecil", cecil, "HostJintAndTlsEntropyPrivateOutputPatchTools")
runtime = read_json(RUNTIME_LOCK)
for identifier, identity in runtime["Packages"].items():
directory = args.NuGetCache / identifier / runtime["Version"]
bundle = directory / (identifier + "." + runtime["Version"] + ".nupkg")
assert digest(bundle.read_bytes()) == identity["NupkgSha256"], identifier + " archive differs"
prefix = "Packages/" + identifier + "-" + runtime["Version"]
scope = "GuestNativeAotRuntimeAndBcl" if "nativeaot" in identifier else "HostOfficialNativeAotCompiler"
notices = []
for name in ("LICENSE.TXT", "THIRD-PARTY-NOTICES.TXT", identifier + ".nuspec"):
if (directory / name).exists():
expected = identity["FilesSha256"].get(name)
assert expected, name + " not bound to runtime lock"
notices.append(copy(prefix + "/" + name, directory / name, scope, expected=expected))
assert any(item.endswith("THIRD-PARTY-NOTICES.TXT") for item in notices)
if not any(item.endswith("LICENSE.TXT") for item in notices):
# The official compiler package declares MIT by expression and has
# no license file; provide the original official runtime MIT text.
notices.append(copy(prefix + "/LICENSE.TXT", args.NuGetCache / "microsoft.netcore.app.runtime.nativeaot.linux-x64" /
runtime["Version"] / "LICENSE.TXT", scope,
expected=runtime["Packages"]["microsoft.netcore.app.runtime.nativeaot.linux-x64"]["FilesSha256"]["LICENSE.TXT"]))
packages.append({"Id": identifier, "Version": runtime["Version"], "Scope": scope,
"Classification": "External", "NupkgSha256": identity["NupkgSha256"],
"LicenseFiles": notices})
roots_manifest_path = SECURITY_ROOT / "Manifest.json"
roots = read_json(roots_manifest_path)
root_bytes = (SECURITY_ROOT / "MozillaRoots.pem").read_bytes()
assert roots["Kind"] == "ExplicitMozillaRootSnapshot" and roots["License"] == "MPL-2.0", "Unexpected root source/license"
assert roots["Sha256"] == digest(root_bytes) and roots["Bytes"] == len(root_bytes), "Trusted root snapshot differs"
assert root_bytes.count(b"-----BEGIN CERTIFICATE-----") == roots["RootCount"] == root_bytes.count(b"-----END CERTIFICATE-----"), "Trusted root certificate count differs"
assert roots["HostCertificateStoreUsed"] is False, "Host roots entered the guest snapshot"
entries = source_manifest["Files"]
for item in entries:
source = (args.ToolRoot / item["ToolPath"]) if "ToolPath" in item else ROOT / item["SourcePath"]
path = copy(item["Destination"], source, item["Scope"], item.get("SourceUrl"), item.get("Sha256"))
components.append({"Name": item["Name"], "Version": item.get("Version"), "Scope": item["Scope"],
"Classification": item.get("Classification", "External"), "LicenseFile": path,
"SourceIdentity": item.get("SourceIdentity")})
# Preserve the complete protocol notice from the actual Limine binary's
# third-party notice, without reconstructing or abbreviating license text.
limine = (args.ToolRoot / "limine/3RDPARTY.md").read_text(encoding="utf-8")
protocol = re.search(r"### Limine Boot Protocol\s+.*?```\s*\n(.*?)\n```", limine, re.S)
assert protocol, "Actual Limine archive lacks its protocol license"
protocol_file = "Boot/LimineProtocol-0BSD.txt"
files.append(save(protocol_file, (protocol.group(1) + "\n").encode("utf-8")))
files[-1].update(Scope="GuestBootProtocolDeclarations", SourcePath=".tools/limine/3RDPARTY.md", Extraction="Exact full Limine Boot Protocol license block")
components.append({"Name": "Limine Boot Protocol", "Version": "base revision 6", "Scope": "GuestBootProtocolDeclarations", "Classification": "External", "LicenseFile": protocol_file})
manifest = {"Schema": "XFESystem.IndependentLicenses.V1", "ApplicationLockSha256": digest(APP_LOCK.read_bytes()),
"RuntimeToolchainLockSha256": digest(RUNTIME_LOCK.read_bytes()),
"JintPatchToolLockSha256": digest(patch_lock.read_bytes()),
"TlsEntropyPatchToolLockSha256": digest(entropy_patch_lock.read_bytes()),
"TlsDependencyManifestSha256": digest(TLS_IDENTITY.read_bytes()),
"TlsProjectLockSha256": digest(TLS_LOCK.read_bytes()),
"TrustedRootManifestSha256": digest(roots_manifest_path.read_bytes()),
"TrustedRootSnapshotSha256": digest(root_bytes), "TrustedRootCount": roots["RootCount"],
"SourcesSha256": digest((OUTPUT / "LicenseSources.json").read_bytes()),
"Scope": "Independent NativeApplication graph, native runtime, actual boot image components and explicitly separated host tools",
"ContainsCosmos": False, "ExcludesLegacyCollectedGraph": True, "GuestAcceptancePassed": False,
"NativeTlsAcceptancePassed": False, "FullReleaseQualified": False,
"GuestAcceptanceNote": "License completeness and hash checks do not prove guest execution; use an image-bound acceptance receipt.",
"PackageCount": len(packages), "Packages": packages, "Components": components, "Files": sorted(files, key=lambda item: item["Path"])}
content = (json.dumps(manifest, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
target = OUTPUT / "Manifest.json"
# This generated inventory may update as the lock graph changes. License
# bodies themselves can only be added or verified byte for byte.
target.write_bytes(content)
print(json.dumps({"PackageCount": len(packages), "NoticeFiles": len(files), "ContainsCosmos": False,
"Manifest": str(target), "Passed": True}))
if __name__ == "__main__":
main()
"""Collect/verify notices for the independent application graph, never legacy Cosmos.
Uses restored packages and existing pinned source/tool notices. Existing output
must remain byte-identical. No downloads, package edits, or binary copies occur.
"""
import argparse
import hashlib
import json
from pathlib import Path
import re
import xml.etree.ElementTree as ET
ROOT = Path(__file__).resolve().parents[2]
OUTPUT = ROOT / "Tools/IndependentKernel/Licenses"
OLD = ROOT / "Tools/CSharpBoot/Licenses/Collected"
APP_LOCK = ROOT / "Source/XFESystem.NativeRuntime/Application/packages.lock.json"
RUNTIME_LOCK = ROOT / "Tools/IndependentKernel/Runtime/NativeToolchain.json"
TLS_IDENTITY = ROOT / "Source/XFESystem.Tls/DependencyManifest.json"
TLS_LOCK = ROOT / "Source/XFESystem.Tls/Packages.lock.json"
SECURITY_ROOT = ROOT / "Source/XFESystem.NativeRuntime/Application/Security"
UPSTREAM = {"Acornima": "Acornima", "AngleSharp": "AngleSharp", "AngleSharp.Css": "AngleSharpCss",
"HtmlSanitizer": "HtmlSanitizer", "Jint": "Jint", "Markdig": "Markdig", "Mono.Cecil": "MonoCecil"}
def digest(data):
return hashlib.sha256(data).hexdigest()
def read_json(path):
return json.loads(path.read_text(encoding="utf-8-sig"))
def save(relative, data):
target = (OUTPUT / relative).resolve()
if not target.is_relative_to(OUTPUT.resolve()):
raise ValueError("Notice escaped the independent directory")
target.parent.mkdir(parents=True, exist_ok=True)
if target.exists():
assert target.read_bytes() == data, f"Existing notice changed: {relative}"
else:
target.write_bytes(data)
return {"Path": relative, "Sha256": digest(data), "Bytes": len(data)}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--NuGetCache", type=Path, default=Path.home() / ".nuget/packages")
parser.add_argument("--ToolRoot", type=Path, default=ROOT / ".tools")
args = parser.parse_args()
files, packages, components = [], [], []
source_manifest = read_json(OUTPUT / "LicenseSources.json")
package_licenses = {item["Id"]: item for item in source_manifest.get("PackageLicenseFiles", [])}
upstream_notices = {item["Id"]: item for item in source_manifest.get("ExternalPackageNotices", [])}
tls_identity = read_json(TLS_IDENTITY)
source_specs = read_json(ROOT / "Tools/CSharpBoot/LicenseSources.json")["OfficialSources"]
official = {item["Name"]: item for item in source_specs}
def copy(relative, source, scope, url=None, expected=None):
data = source.read_bytes()
if expected:
assert digest(data) == expected, f"Source differs: {source}"
record = save(relative, data)
record.update(Scope=scope)
try:
record["SourcePath"] = str(source.relative_to(ROOT)).replace("\\", "/")
except ValueError:
record["SourcePath"] = "Restored NuGet cache/" + source.name
if url:
record["SourceUrl"] = url
if not any(item["Path"] == relative for item in files):
files.append(record)
return relative
def collect_package(identifier, specification, scope):
version = specification["resolved"]
directory = args.NuGetCache / identifier.lower() / version
metadata = read_json(directory / ".nupkg.metadata")
assert metadata["contentHash"] == specification["contentHash"], identifier + " differs from lock"
bundle = directory / (identifier.lower() + "." + version + ".nupkg")
nuspec = directory / (identifier.lower() + ".nuspec")
document = ET.fromstring(nuspec.read_bytes())
ns = {"n": document.tag[1:].split("}")[0]}
declaration = document.find("n:metadata/n:license", ns)
repository = document.find("n:metadata/n:repository", ns)
prefix = "Packages/" + identifier + "-" + version
record = {"Id": identifier, "Version": version, "Scope": scope,
"Classification": "SameAuthorSeparateProject" if identifier.startswith("XFEExtension") else "External",
"LockedContentHash": specification["contentHash"], "NuGetContentHash": metadata["contentHash"],
"NupkgSha256": digest(bundle.read_bytes()),
"Repository": dict(repository.attrib) if repository is not None else {},
"LicenseDeclaration": {"Type": declaration.attrib.get("type"), "Value": declaration.text} if declaration is not None else {},
"LicenseFiles": []}
copy(prefix + "/Metadata.nuspec", nuspec, scope)
if identifier in package_licenses:
spec = package_licenses[identifier]
assert version == spec["Version"], "Pinned license package version differs"
assert identifier == tls_identity["Package"] and version == tls_identity["Version"], "TLS dependency version differs"
assert specification["contentHash"] == tls_identity["NuGetContentSha512"], "TLS content lock differs"
assert record["NupkgSha256"] == tls_identity["PackageSha256"], "TLS package archive differs"
assert record["Repository"].get("commit") == tls_identity["SourceCommitFromNuGetMetadata"], "TLS repository commit differs"
assert record["LicenseDeclaration"] == {"Type": "expression", "Value": tls_identity["License"]}, "TLS license declaration differs"
assert read_json(TLS_LOCK)["dependencies"]["net10.0"][identifier]["contentHash"] == specification["contentHash"], "TLS project lock differs"
record["LicenseFiles"].append(copy(prefix + "/" + spec["File"], directory / spec["File"], scope,
tls_identity["PackageUrl"], spec["Sha256"]))
record["DependencyManifestSha256"] = digest(TLS_IDENTITY.read_bytes())
elif identifier in upstream_notices:
spec=upstream_notices[identifier]
assert version==spec['Version'] and record['Repository'].get('commit')==spec['RepositoryCommit'], 'Storage package identity differs'
assert record['LicenseDeclaration']=={'Type':'expression','Value':spec['License']}, 'Storage package license differs'
for item in spec['Notices']:
record['LicenseFiles'].append(copy(item['Path'],OUTPUT/item['Path'],scope,item['SourceUrl'],item['Sha256']))
if spec.get('NoticeProvenance'):record['NoticeProvenance']=spec['NoticeProvenance']
elif declaration is not None and declaration.attrib.get("type") == "file":
record["LicenseFiles"].append(copy(prefix + "/" + declaration.text, directory / declaration.text, scope))
elif identifier in UPSTREAM:
key = UPSTREAM[identifier]
spec = official[key]
record["LicenseFiles"].append(copy("Upstream/" + key + "/License.txt", OLD / "Upstream" / key / "License.txt",
scope, spec["Url"], spec["Sha256"]))
else:
raise ValueError("No complete license for " + identifier)
packages.append(record)
app = read_json(APP_LOCK)
assert list(app["dependencies"]) == ["net10.0"], "Unexpected application target"
for identifier, specification in app["dependencies"]["net10.0"].items():
if specification["type"] == "Project":
continue
assert not identifier.lower().startswith("cosmos"), "Cosmos entered the independent app"
collect_package(identifier, specification, "IndependentApplicationGraph")
patch_lock = ROOT / "Tools/JintCleanupPatch/Packages.lock.json"
cecil = read_json(patch_lock)["dependencies"]["net10.0"]["Mono.Cecil"]
entropy_patch_lock = ROOT / "Tools/TlsEntropyPatch/Packages.lock.json"
entropy_cecil = read_json(entropy_patch_lock)["dependencies"]["net10.0"]["Mono.Cecil"]
assert entropy_cecil == cecil, "Private patch tools must share the pinned Mono.Cecil identity"
collect_package("Mono.Cecil", cecil, "HostJintAndTlsEntropyPrivateOutputPatchTools")
runtime = read_json(RUNTIME_LOCK)
for identifier, identity in runtime["Packages"].items():
directory = args.NuGetCache / identifier / runtime["Version"]
bundle = directory / (identifier + "." + runtime["Version"] + ".nupkg")
assert digest(bundle.read_bytes()) == identity["NupkgSha256"], identifier + " archive differs"
prefix = "Packages/" + identifier + "-" + runtime["Version"]
scope = "GuestNativeAotRuntimeAndBcl" if "nativeaot" in identifier else "HostOfficialNativeAotCompiler"
notices = []
for name in ("LICENSE.TXT", "THIRD-PARTY-NOTICES.TXT", identifier + ".nuspec"):
if (directory / name).exists():
expected = identity["FilesSha256"].get(name)
assert expected, name + " not bound to runtime lock"
notices.append(copy(prefix + "/" + name, directory / name, scope, expected=expected))
assert any(item.endswith("THIRD-PARTY-NOTICES.TXT") for item in notices)
if not any(item.endswith("LICENSE.TXT") for item in notices):
# The official compiler package declares MIT by expression and has
# no license file; provide the original official runtime MIT text.
notices.append(copy(prefix + "/LICENSE.TXT", args.NuGetCache / "microsoft.netcore.app.runtime.nativeaot.linux-x64" /
runtime["Version"] / "LICENSE.TXT", scope,
expected=runtime["Packages"]["microsoft.netcore.app.runtime.nativeaot.linux-x64"]["FilesSha256"]["LICENSE.TXT"]))
packages.append({"Id": identifier, "Version": runtime["Version"], "Scope": scope,
"Classification": "External", "NupkgSha256": identity["NupkgSha256"],
"LicenseFiles": notices})
roots_manifest_path = SECURITY_ROOT / "Manifest.json"
roots = read_json(roots_manifest_path)
root_bytes = (SECURITY_ROOT / "MozillaRoots.pem").read_bytes()
assert roots["Kind"] == "ExplicitMozillaRootSnapshot" and roots["License"] == "MPL-2.0", "Unexpected root source/license"
assert roots["Sha256"] == digest(root_bytes) and roots["Bytes"] == len(root_bytes), "Trusted root snapshot differs"
assert root_bytes.count(b"-----BEGIN CERTIFICATE-----") == roots["RootCount"] == root_bytes.count(b"-----END CERTIFICATE-----"), "Trusted root certificate count differs"
assert roots["HostCertificateStoreUsed"] is False, "Host roots entered the guest snapshot"
entries = source_manifest["Files"]
for item in entries:
source = (args.ToolRoot / item["ToolPath"]) if "ToolPath" in item else ROOT / item["SourcePath"]
path = copy(item["Destination"], source, item["Scope"], item.get("SourceUrl"), item.get("Sha256"))
components.append({"Name": item["Name"], "Version": item.get("Version"), "Scope": item["Scope"],
"Classification": item.get("Classification", "External"), "LicenseFile": path,
"SourceIdentity": item.get("SourceIdentity")})
# Preserve the complete protocol notice from the actual Limine binary's
# third-party notice, without reconstructing or abbreviating license text.
limine = (args.ToolRoot / "limine/3RDPARTY.md").read_text(encoding="utf-8")
protocol = re.search(r"### Limine Boot Protocol\s+.*?```\s*\n(.*?)\n```", limine, re.S)
assert protocol, "Actual Limine archive lacks its protocol license"
protocol_file = "Boot/LimineProtocol-0BSD.txt"
files.append(save(protocol_file, (protocol.group(1) + "\n").encode("utf-8")))
files[-1].update(Scope="GuestBootProtocolDeclarations", SourcePath=".tools/limine/3RDPARTY.md", Extraction="Exact full Limine Boot Protocol license block")
components.append({"Name": "Limine Boot Protocol", "Version": "base revision 6", "Scope": "GuestBootProtocolDeclarations", "Classification": "External", "LicenseFile": protocol_file})
manifest = {"Schema": "XFESystem.IndependentLicenses.V1", "ApplicationLockSha256": digest(APP_LOCK.read_bytes()),
"RuntimeToolchainLockSha256": digest(RUNTIME_LOCK.read_bytes()),
"JintPatchToolLockSha256": digest(patch_lock.read_bytes()),
"TlsEntropyPatchToolLockSha256": digest(entropy_patch_lock.read_bytes()),
"TlsDependencyManifestSha256": digest(TLS_IDENTITY.read_bytes()),
"TlsProjectLockSha256": digest(TLS_LOCK.read_bytes()),
"TrustedRootManifestSha256": digest(roots_manifest_path.read_bytes()),
"TrustedRootSnapshotSha256": digest(root_bytes), "TrustedRootCount": roots["RootCount"],
"SourcesSha256": digest((OUTPUT / "LicenseSources.json").read_bytes()),
"Scope": "Independent NativeApplication graph, native runtime, actual boot image components and explicitly separated host tools",
"ContainsCosmos": False, "ExcludesLegacyCollectedGraph": True, "GuestAcceptancePassed": False,
"NativeTlsAcceptancePassed": False, "FullReleaseQualified": False,
"GuestAcceptanceNote": "License completeness and hash checks do not prove guest execution; use an image-bound acceptance receipt.",
"PackageCount": len(packages), "Packages": packages, "Components": components, "Files": sorted(files, key=lambda item: item["Path"])}
content = (json.dumps(manifest, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
target = OUTPUT / "Manifest.json"
# This generated inventory may update as the lock graph changes. License
# bodies themselves can only be added or verified byte for byte.
target.write_bytes(content)
print(json.dumps({"PackageCount": len(packages), "NoticeFiles": len(files), "ContainsCosmos": False,
"Manifest": str(target), "Passed": True}))
if __name__ == "__main__":
main()