Close completed date evidence custody without replaying operations
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
This commit is contained in:
tegwick 2026-10-31 12:45:42 +01:00
parent fa5177d89e
commit 803203a332
5 changed files with 384 additions and 13 deletions

View file

@ -248,7 +248,7 @@ class Node:
return point
def prepare_root(self, root):
root.mkdir(mode=0o700, parents=True, exist_ok=True)
root.mkdir(mode=0o700, exist_ok=True)
info = root.lstat()
if (not stat.S_ISDIR(info.st_mode) or info.st_uid != os.geteuid() or info.st_mode & 0o077
or any(p.is_symlink() for p in root.parents)):
@ -285,6 +285,68 @@ class Node:
sync_directory(path)
sync_directory(path.parent)
@contextmanager
def helper_evidence_files(self, path):
"""Open only the closed helper's known evidence; preserve crash recovery."""
with ExitStack() as stack:
def opened(name, flags, parent=None):
fd = os.open(name, flags | os.O_NOFOLLOW, dir_fd=parent)
stack.callback(os.close, fd)
return fd
directory = opened("/", os.O_RDONLY | os.O_DIRECTORY)
for component in path.parts[1:]:
directory = opened(component, os.O_RDONLY | os.O_DIRECTORY, directory)
info = os.fstat(directory)
if (info.st_uid not in {os.geteuid(), 10001}
or info.st_gid not in {os.getegid(), 10001}
or stat.S_IMODE(info.st_mode) != 0o700):
raise Refused("private_helper_evidence_required")
names = sorted(os.listdir(directory))
if set(names) - {"execute.lock", "journal.json", "result.json"}:
raise Refused("unexpected_helper_evidence")
files, evidence = {}, {}
for name in names:
fd = opened(name, os.O_RDONLY | os.O_NONBLOCK, directory)
info = os.fstat(fd)
if (not stat.S_ISREG(info.st_mode) or info.st_nlink != 1
or info.st_uid not in {os.geteuid(), 10001}
or info.st_gid not in {os.getegid(), 10001}
or stat.S_IMODE(info.st_mode) != 0o600):
raise Refused("private_helper_evidence_required")
if name == "execute.lock":
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
digest = hashlib.sha256()
while chunk := os.read(fd, 1024 * 1024):
digest.update(chunk)
after = os.fstat(fd)
if any(getattr(info, key) != getattr(after, key) for key in (
"st_dev", "st_ino", "st_mode", "st_uid", "st_gid", "st_nlink",
"st_size", "st_mtime_ns", "st_ctime_ns")):
raise Refused("helper_evidence_changed")
files[name] = fd
evidence[name] = {"sha256": digest.hexdigest(), "bytes": info.st_size,
"device": info.st_dev, "inode": info.st_ino,
"mtime_ns": info.st_mtime_ns}
yield directory, files, evidence
def helper_evidence(self, path):
with self.helper_evidence_files(path) as (_, _, evidence):
return evidence
def seal_helper_evidence(self, path, expected):
# Mixed helper/root custody is allowed only to resume this recorded step.
with self.helper_evidence_files(path) as (directory, files, evidence):
if evidence != expected:
raise Refused("helper_evidence_changed")
for fd in [*files.values(), directory]:
os.fchown(fd, os.geteuid(), os.getegid())
os.fsync(fd)
info = os.fstat(fd)
if (info.st_uid, info.st_gid) != (os.geteuid(), os.getegid()):
raise Refused("helper_evidence_custody_unconfirmed")
sync_directory(path.parent)
def read_state(self, path):
return json.loads(private_file(path))
@ -492,7 +554,27 @@ class Supervisor:
self.node.command(["kubectl", "rollout", "status", f"deployment/{NS}", "-n", NS,
"--timeout=180s"])
self.deployment(1)
self.record("completed", application_resumed=True)
return self.complete()
def complete(self, **changes):
"""Seal evidence only after resume, when helper recovery is no longer needed."""
self.deployment(1)
path = self.directory / "private"
for pod in self.node.doc("get", "pods", "-A")["items"]:
if pod["metadata"]["name"] == self.helper:
raise Refused("helper_still_present_at_closeout")
for volume in pod["spec"].get("volumes", []):
if "hostPath" in volume:
mount = Path(volume["hostPath"]["path"])
if mount == path or mount in path.parents or path in mount.parents:
raise Refused("helper_evidence_still_mounted")
evidence = self.state.get("helper_evidence")
if evidence is None:
evidence = self.node.helper_evidence(path)
self.record("custody_closeout_started", application_resumed=True,
helper_evidence=evidence, **changes)
self.node.seal_helper_evidence(path, evidence)
self.record("completed", helper_evidence_root_custody_verified=True)
return self.state
def execute(self):
@ -559,19 +641,23 @@ class Supervisor:
if (self.state.get("schema") != "coulomb.supervised-date-attempt.v1"
or self.state["proposal_digest"] != self.capsule.digest):
raise Refused("original_attempt_required")
if self.state["phase"] == "completed":
raise Refused("completed_attempt_must_not_be_replayed")
self.identity()
dep = self.node.doc("get", "deployment", NS, "-n", NS)
if dep["spec"]["replicas"] == 1:
# A lost response after scale-up must never undo later writes.
if (self.state.get("failed_phase", self.state["phase"]) != "resume_started"
phase = (self.state["failed_phase"] if self.state["phase"] == "requires_review"
else self.state["phase"])
if (phase not in {
"resume_started", "custody_closeout_started"}
or "expected_final" not in self.state):
raise Refused("running_application_requires_owner_review")
self.deployment(1)
self.node.command(["kubectl", "rollout", "status", f"deployment/{NS}",
"-n", NS, "--timeout=180s"])
self.record("completed", application_resumed=True,
resumed_reply_reconciled=True, post_resume_writes_preserved=True)
return self.state
return self.complete(resumed_reply_reconciled=True,
post_resume_writes_preserved=True)
self.deployment(0)
writers = self.writers()
if not writers: