#!/usr/bin/env bash set -euo pipefail # === METADATA === SCRIPT_NAME="$(basename "$0")" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SKILL_ROOT="$(dirname "$SCRIPT_DIR")" # === CONFIGURATION === : "${OUTPUT_DIR:=$SKILL_ROOT/outputs}" : "${NODE_NAME:=node-a}" # === FUNCTIONS === log_info() { echo "[INFO] $(date -Iseconds) $*"; } log_error() { echo "[ERROR] $(date -Iseconds) $*" >&2; } die() { log_error "$@"; exit 1; } b3_file() { if command -v b3sum &>/dev/null; then b3sum "$1" | awk '{print $1}' else blake3 "$1" fi } b3_string() { if command -v b3sum &>/dev/null; then echo -n "$1" | b3sum | awk '{print $1}' else echo -n "$1" | blake3 fi } main() { local last_run_file="$OUTPUT_DIR/last_run_dir.txt" [[ -f "$last_run_file" ]] || die "No last run pointer. Run 11_backup_apply.sh first." local run_dir run_dir="$(cat "$last_run_file")" local manifest="$run_dir/manifest.json" [[ -f "$manifest" ]] || die "Missing manifest: $manifest" # Find encrypted archive local encrypted="" if [[ -f "$run_dir/archive.tar.gz.age" ]]; then encrypted="$run_dir/archive.tar.gz.age" else die "Missing encrypted archive. Run 21_encrypt_apply.sh first." fi log_info "Generating proof receipts..." log_info "Run directory: $run_dir" # Compute BLAKE3 hashes local manifest_b3 encrypted_b3 manifest_b3=$(b3_file "$manifest") encrypted_b3=$(b3_file "$encrypted") log_info "Manifest BLAKE3: $manifest_b3" log_info "Encrypted BLAKE3: $encrypted_b3" # Compute ROOT = BLAKE3(manifest_b3 || encrypted_b3) # Using stable text concatenation local concat root_b3 concat="${manifest_b3}${encrypted_b3}" root_b3=$(b3_string "$concat") log_info "ROOT BLAKE3: $root_b3" # Write ROOT.txt echo "$root_b3" > "$run_dir/ROOT.txt" log_info "Wrote: $run_dir/ROOT.txt" # Write PROOF.json cat > "$run_dir/PROOF.json" <