Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Guard the six-script R2 Fractal resync with immutable revisions, exact blobs and executable modes; expire the exception on the next oracle repin (#115).

## [0.6.0] - 2026-11-10

### Added
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
# Inspect every Git-source entry, including names cleanSource excludes.
src = self;
MERGEMASTER_PYTHON_ORACLE = "${python-oracle}";
MERGEMASTER_FRACTAL_FIXTURE = "${fractal-fixture}";
} ''
python3 -B "$src/tests/test-oracle-scripts.py"
python3 -B "$src/tests/oracle_scripts.py"
Expand Down
11 changes: 11 additions & 0 deletions scripts/PROVENANCE
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Source: compoundingtech/fractal
# Commit: e83871ec919f95b3b3e2a9a1cd211c2ac37babda
# Scripts copied as-is except the documented upstream patches below; Git blob SHA-1 hashes (not file SHA-1 hashes).
# R2 resync exception; exit: https://github.com/compoundingtech/mergemaster/issues/115
# The original extraction Commit above is historical; this resync starts at the current fixture revision.
# Pending requires oracle bytes; the target fixture activates exact upstream bytes and modes.
# resync-original e2721e52463428b4ff655addee129cecd2839763
# resync-rev 787e8ed592dff34d2bdc2a2b0b584482da567e7f
# resync-blob scripts/evidence-sign ea0ab64b5efc631c624cc974208bf05234839433
# resync-blob scripts/evidence-sign-hardening-test 7da656fdc8f2b4b499fa099c93efa34884434004
# resync-blob scripts/evidence-verify-test 6b9d6c5f403fae4fcb1a516562e06f8d5cfc0cc7
# resync-blob scripts/evidence-wrap-test 711847812a5d703fa9f2056468970f89a0f57c53
# resync-blob scripts/lane-definition-closure 5a844628e821bb51e6ab3fc2b38088a37c3c47c4
# resync-blob scripts/st-test feb0d16374a2dfb78af20357166f56225df46774
# scripts/fractal-test-test: apply the fixture maintenance-isolation patch from
# https://github.com/compoundingtech/fractal/pull/4398 (5f995f26e5).
# The source_blob column remains the original import; mergemaster_blob includes applied patches.
Expand Down
55 changes: 51 additions & 4 deletions tests/oracle_scripts.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
"""Require copied scripts to match the immutable Python oracle, in both directions."""
"""Byte/mode oracle guard with the bounded PROVENANCE resync exception."""
import hashlib
import json
import os
from pathlib import Path
import re

EXEMPT = {"PROVENANCE", "test-scripts"}
ORIGINAL = "e2721e52463428b4ff655addee129cecd2839763"
TARGET = "787e8ed592dff34d2bdc2a2b0b584482da567e7f"


def blob(data):
return hashlib.sha1(b"blob " + str(len(data)).encode() + b"\0" + data).hexdigest()


def table(text):
revisions, original, rows = [], [], {}
for line in text.splitlines():
if line.startswith("# resync-original "):
original.append(line.removeprefix("# resync-original "))
elif line.startswith("# resync-rev "):
revisions.append(line.removeprefix("# resync-rev "))
elif line.startswith("# resync-blob "):
path, oid = line.removeprefix("# resync-blob ").split()
if not re.fullmatch(r"scripts/[A-Za-z0-9._-]+", path) or path in rows:
raise ValueError("invalid/duplicate resync path")
if not re.fullmatch(r"[0-9a-f]{40}", oid) or path[8:] in EXEMPT:
raise ValueError("invalid resync blob")
rows[path] = oid
if len(revisions) != 1 or len(original) != 1 or not rows:
raise ValueError("resync requires one target, one original revision and paths")
if ORIGINAL == TARGET or original[0] != ORIGINAL or revisions[0] != TARGET:
raise ValueError("resync revision differs from approved constants")
return rows


def snapshot(path):
Expand All @@ -11,12 +41,25 @@ def snapshot(path):
return path.read_bytes(), path.stat().st_mode & 0o111


def check(src, oracle):
def check(src, oracle, fixture=None, fixture_rev=ORIGINAL):
rows = table((src / "scripts/PROVENANCE").read_text())
if fixture_rev not in (ORIGINAL, TARGET):
raise ValueError("fixture revision differs from approved constants")
for path, oid in rows.items():
local, old = snapshot(src / path), snapshot(oracle / path)
if blob(old[0]) == oid:
raise ValueError(f"{path}: expired resync exception; remove it (#115)")
if fixture_rev == TARGET:
upstream = snapshot(fixture / path)
if blob(upstream[0]) != oid or local != upstream or local[0] == old[0]:
raise ValueError(f"{path}: resync bytes/mode/blob mismatch")
elif local != old:
raise ValueError(f"{path}: pending resync must still equal oracle")
for path in sorted((src / "scripts").rglob("*")):
if path.is_dir() and not path.is_symlink():
continue
relative = path.relative_to(src).as_posix()
if relative[8:] in EXEMPT:
if relative[8:] in EXEMPT or relative in rows:
continue
if snapshot(path) != snapshot(oracle / relative):
raise ValueError(f"{relative}: differs from pinned oracle")
Expand All @@ -29,4 +72,8 @@ def check(src, oracle):


if __name__ == "__main__":
check(Path(os.environ["src"]), Path(os.environ["MERGEMASTER_PYTHON_ORACLE"]))
src = Path(os.environ["src"])
lock = json.loads((src / "flake.lock").read_text())
node = lock["nodes"][lock["nodes"]["root"]["inputs"]["fractal-fixture"]]
check(src, Path(os.environ["MERGEMASTER_PYTHON_ORACLE"]),
Path(os.environ["MERGEMASTER_FRACTAL_FIXTURE"]), node["locked"]["rev"])
107 changes: 80 additions & 27 deletions tests/test-oracle-scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,68 @@
from pathlib import Path
import unittest

from oracle_scripts import EXEMPT, check
from oracle_scripts import EXEMPT, ORIGINAL, TARGET, blob, check


class OracleGuard(unittest.TestCase):
class ResyncGuard(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.src, self.oracle = [Path(self.temp.name) / p for p in ("src", "oracle")]
for root in (self.src, self.oracle):
self.src, self.oracle, self.fixture = [Path(self.temp.name) / p for p in ("src", "oracle", "fixture")]
for root in (self.src, self.oracle, self.fixture):
(root / "scripts").mkdir(parents=True)
self.write(root, "one", b"old")
self.old, self.target = ORIGINAL, TARGET
self.oid = blob(b"new")
self.write(self.src, "one", b"new")
self.write(self.oracle, "one", b"old")
self.write(self.fixture, "one", b"new")
self.manifest()

def write(self, root, name, data, mode=0o755):
path = root / "scripts" / name
path.write_bytes(data)
path.chmod(mode)

def run_check(self):
check(self.src, self.oracle)
def manifest(self):
(self.src / "scripts/PROVENANCE").write_text(
f"# resync-original {self.old}\n# resync-rev {self.target}\n# resync-blob scripts/one {self.oid}\n")

def run_check(self, rev=None):
check(self.src, self.oracle, self.fixture, rev or self.target)

def test_match(self):
self.run_check()

def test_repository_owned_exemptions(self):
for name in EXEMPT:
self.write(self.src, name, b"local")
self.write(self.oracle, name, b"oracle")
self.run_check()
def test_pending_is_oracle_only(self):
with self.assertRaises(ValueError):
self.run_check(self.old)
self.write(self.src, "one", b"old")
self.run_check(self.old)
with self.assertRaises(ValueError):
self.run_check("c" * 40)

def test_local_mismatch(self):
for data in (b"edited", b"new"):
def test_local_mismatch_and_oracle_copy(self):
for data in (b"edited", b"old"):
self.write(self.src, "one", data)
with self.assertRaises(ValueError):
self.run_check()

def test_executable_modes(self):
self.write(self.src, "one", b"old", 0o644)
def test_fixture_and_table_must_agree(self):
self.write(self.fixture, "one", b"edited")
with self.assertRaises(ValueError):
self.run_check()
self.write(self.fixture, "one", b"new")
self.oid = blob(b"edited")
self.manifest()
with self.assertRaises(ValueError):
self.run_check()

def test_oracle_script_deletion_is_refused(self):
def test_modes_and_missing_paths(self):
self.write(self.src, "one", b"new", 0o644)
with self.assertRaises(ValueError):
self.run_check()
(self.src / "scripts/one").unlink()
with self.assertRaisesRegex(ValueError, "missing oracle script"):
with self.assertRaises(ValueError):
self.run_check()

def test_unlisted_stays_oracle(self):
Expand All @@ -55,21 +74,55 @@ def test_unlisted_stays_oracle(self):
with self.assertRaises(ValueError):
self.run_check()

def test_unlisted_addition_is_refused(self):
for name in ("not-in-oracle", "parity-drift", "parity-drift-test"):
with self.subTest(name=name):
self.write(self.src, name, b"new")
with self.assertRaisesRegex(ValueError, "not a regular script"):
self.run_check()
(self.src / "scripts" / name).unlink()
def test_expiry_is_byte_identical_even_if_modes_differ(self):
self.write(self.oracle, "one", b"new", 0o644)
with self.assertRaisesRegex(ValueError, "expired"):
self.run_check()

def test_manifest_cannot_retarget_approved_revisions(self):
for original, target in [("c" * 40, "c" * 40), (ORIGINAL, "c" * 40),
(TARGET, TARGET), (ORIGINAL, ORIGINAL)]:
self.old, self.target = original, target
self.manifest()
with self.assertRaisesRegex(ValueError, "approved constants"):
self.run_check(target)

def test_symlink_is_not_a_script(self):
def test_duplicate_or_malformed_rows(self):
path = self.src / "scripts/PROVENANCE"
original = path.read_text()
for row in [f"# resync-blob scripts/one {self.oid}",
"# resync-blob scripts/../escape " + self.oid,
"# resync-blob scripts/two invalid",
"# resync-blob scripts/two"]:
path.write_text(original + row + "\n")
with self.assertRaises(ValueError):
self.run_check()

def test_listed_symlink_is_not_a_script(self):
path = self.src / "scripts/one"
path.unlink()
path.symlink_to(self.oracle / "scripts/one")
path.symlink_to(self.fixture / "scripts/one")
with self.assertRaisesRegex(ValueError, "not a regular script"):
self.run_check()


def test_repository_owned_exemptions(self):
for name in EXEMPT - {"PROVENANCE"}:
self.write(self.src, name, b"local")
self.write(self.oracle, name, b"oracle")
self.run_check()

def test_oracle_script_deletion_is_refused(self):
self.write(self.oracle, "two", b"old")
with self.assertRaisesRegex(ValueError, "missing oracle script"):
self.run_check()

def test_unlisted_addition_is_refused(self):
for name in ("not-in-oracle", "parity-drift", "parity-drift-test"):
self.write(self.src, name, b"new")
with self.assertRaisesRegex(ValueError, "not a regular script"):
self.run_check()
(self.src / "scripts" / name).unlink()

if __name__ == "__main__":
unittest.main()