#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$ROOT_DIR"

SANDBOX="$ROOT_DIR/sandbox/rho-result-release"
REPO="$SANDBOX/repo"
OWNER_HOME="$SANDBOX/owner-rho-home"
COLLAB_HOME="$SANDBOX/collab-rho-home"
OWNER_ID="rho://id/github/rho-owner"
COLLAB_ID="rho://id/github/rho-collab"
REQUEST_ID="req-release"
EXPLICIT_SENDER_REQUEST_ID="req-explicit-sender"
RUN_ID="run-run-real-release"
BAD_REQUEST_ID="req-release-missing-input"
BAD_RUN_ID="run-run-real-missing-input"
ACTION_ID="act-run-real-release"
RESULT_DIR="rho/messages/inbox/id/github/rho-collab/$REQUEST_ID"
RESULT_ATTACHMENT="$RESULT_DIR/attachments/stdout.txt"
RECEIPT_DIR="rho/run-receipts/$REQUEST_ID"
APPROVAL_DIR="rho/approval-grants/$REQUEST_ID"

rm -rf "$SANDBOX"
mkdir -p "$REPO"

git -C "$REPO" init >/dev/null
git -C "$REPO" config user.name "Rho Result Release Test"
git -C "$REPO" config user.email "result-release@example.test"
git -C "$REPO" config commit.gpgsign false
git -C "$REPO" switch -c main >/dev/null

RHO_HOME="$OWNER_HOME" ./rho id init \
  --github rho-owner \
  --display-name "Rho Owner" \
  --generate-ssh-key >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id init \
  --github rho-collab \
  --display-name "Rho Collaborator" \
  --generate-ssh-key >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id init \
  --github rho-extra \
  --display-name "Rho Extra Local Identity" \
  --generate-ssh-key >/dev/null
RHO_HOME="$OWNER_HOME" ./rho id export \
  --identity "$OWNER_ID" \
  --out "$SANDBOX/rho-owner-public.yaml" >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id export \
  --identity "$COLLAB_ID" \
  --out "$SANDBOX/rho-collab-public.yaml" >/dev/null
RHO_HOME="$OWNER_HOME" ./rho id import "$SANDBOX/rho-collab-public.yaml" >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id import "$SANDBOX/rho-owner-public.yaml" >/dev/null

./rho repo init \
  --root "$REPO" \
  --repo-id rho://repo/local/result-release \
  --owner "$OWNER_ID" >/dev/null
RHO_HOME="$OWNER_HOME" ./rho id export \
  --identity "$OWNER_ID" \
  --out "$REPO/rho/participants/rho-owner.yaml" >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id export \
  --identity "$COLLAB_ID" \
  --out "$REPO/rho/participants/rho-collab.yaml" >/dev/null
cat > "$REPO/rho/membership.yaml" <<EOF
version: 1
members:
  - identity: $OWNER_ID
    role: owner
  - identity: $COLLAB_ID
    role: collaborator
EOF
RHO_HOME="$OWNER_HOME" ./rho repo protect-path \
  "rho/messages/inbox/id/github/rho-collab/**" \
  --root "$REPO" \
  --rho-bin "$ROOT_DIR/rho" \
  --recipient "$COLLAB_ID" >/dev/null

mkdir -p \
  "$REPO/rho/messages/inbox/id/github/rho-owner/$REQUEST_ID" \
  "$REPO/.rho/action-grants" \
  "$REPO/.rho/control/outbox" \
  "$REPO/.rho/runs/$RUN_ID" \
  "$REPO/$APPROVAL_DIR" \
  "$SANDBOX/private"
cat > "$REPO/rho/messages/inbox/id/github/rho-owner/$REQUEST_ID/request.yaml" <<EOF
version: 1
request:
  id: $REQUEST_ID
  from: $COLLAB_ID
  to: $OWNER_ID
  type: private-analysis
EOF
printf "1113.03\n" > "$REPO/.rho/runs/$RUN_ID/stdout.txt"
printf "date,symbol,price\n2026-06-15,RHO,1113.03\n" > "$SANDBOX/private/prices-real.csv"
INPUT_SHA256="$(shasum -a 256 "$SANDBOX/private/prices-real.csv" | awk '{print $1}')"
OUTPUT_SHA256="$(shasum -a 256 "$REPO/.rho/runs/$RUN_ID/stdout.txt" | awk '{print $1}')"
cat > "$REPO/.rho/control/outbox/$ACTION_ID.json" <<EOF
{"action_id":"$ACTION_ID","request_id":"$REQUEST_ID","tool_id":"run_real"}
EOF
ACTION_SHA256="$(shasum -a 256 "$REPO/.rho/control/outbox/$ACTION_ID.json" | awk '{print $1}')"
cat > "$REPO/.rho/action-grants/$ACTION_ID.yaml" <<EOF
version: 1
action_grant:
  action_id: $ACTION_ID
  request_id: $REQUEST_ID
  tool_id: run_real
  action_type: private_analysis
  decision: approved
  granted_by: $OWNER_ID
  created_at: "2026-06-15T00:00:00Z"
  action:
    path: .rho/control/outbox/$ACTION_ID.json
    sha256: $ACTION_SHA256
  repo:
    git_commit:
  inputs:
    - kind: code
      path: workspace/sum_prices.py
      sha256: abcdef0123456789
    - kind: dataset
      path: $SANDBOX/private/prices-real.csv
      sha256: $INPUT_SHA256
EOF
LOCAL_GRANT_SHA256="$(shasum -a 256 "$REPO/.rho/action-grants/$ACTION_ID.yaml" | awk '{print $1}')"
cat > "$REPO/$APPROVAL_DIR/$ACTION_ID.yaml" <<EOF
version: 1
approval_grant:
  action_id: $ACTION_ID
  request_id: $REQUEST_ID
  tool_id: run_real
  action_type: private_analysis
  decision: approved
  granted_by: $OWNER_ID
  created_at: "2026-06-15T00:00:00Z"
  action:
    path: .rho/control/outbox/$ACTION_ID.json
    sha256: $ACTION_SHA256
  local_grant:
    path: .rho/action-grants/$ACTION_ID.yaml
    sha256: $LOCAL_GRANT_SHA256
  repo:
    git_commit:
  code:
    kind: code
    path: workspace/sum_prices.py
    sha256: abcdef0123456789
  private_input:
    dataset_uuid: prices-real
    tier: real
    sha256: $INPUT_SHA256
EOF
RHO_HOME="$OWNER_HOME" ./rho crypto sign \
  "$REPO/$APPROVAL_DIR/$ACTION_ID.yaml" \
  --identity "$OWNER_ID" \
  --out "$REPO/$APPROVAL_DIR/$ACTION_ID.rhosig.yaml" \
  --repo-id rho://repo/local/result-release \
  --request-id "$REQUEST_ID" \
  --recipient "$COLLAB_ID" \
  --purpose rho.approval_grant >/dev/null
cat > "$REPO/.rho/runs/$RUN_ID.yaml" <<EOF
version: 1
run:
  id: $RUN_ID
  request_id: $REQUEST_ID
  status: completed
  tier: real
  runner: gondolin
  dataset_csv: $SANDBOX/private/prices-real.csv
  code_path: $REPO/workspace/sum_prices.py
  code_sha256: abcdef0123456789
  command:
    - python3
    - sum_prices.py
    - DATASET_CSV
  exit_code: 0
  stdout_path: $REPO/.rho/runs/$RUN_ID/stdout.txt
  stderr_path: $REPO/.rho/runs/$RUN_ID/stderr.txt
  created_at: "2026-06-15T00:00:00Z"
EOF

cat > "$REPO/.rho/runs/$BAD_RUN_ID.yaml" <<EOF
version: 1
run:
  id: $BAD_RUN_ID
  request_id: $BAD_REQUEST_ID
  status: completed
  tier: real
  runner: gondolin
  code_path: $REPO/workspace/sum_prices.py
  code_sha256: abcdef0123456789
  command:
    - python3
    - sum_prices.py
    - DATASET_CSV
  exit_code: 0
  stdout_path: $REPO/.rho/runs/$BAD_RUN_ID/stdout.txt
  stderr_path: $REPO/.rho/runs/$BAD_RUN_ID/stderr.txt
  created_at: "2026-06-15T00:00:00Z"
EOF
if RHO_HOME="$OWNER_HOME" ./rho result release "$BAD_REQUEST_ID" \
  --root "$REPO" \
  --from "$OWNER_ID" \
  --to "$COLLAB_ID" \
  --run-id "$BAD_RUN_ID" \
  --runner gondolin \
  --value "0" \
  --allow-missing-request \
  --no-branch \
  --no-stage \
  >"$SANDBOX/release-missing-input-stdout.txt" \
  2>"$SANDBOX/release-missing-input-stderr.txt"; then
  echo "result release allowed missing real input commitment" >&2
  exit 1
fi
grep -q "real run receipt requires dataset_csv" "$SANDBOX/release-missing-input-stderr.txt"
test ! -e "$REPO/rho/messages/inbox/id/github/rho-collab/$BAD_REQUEST_ID/result.yaml"
test ! -e "$REPO/rho/messages/inbox/id/github/rho-collab/$BAD_REQUEST_ID/result.rhosig.yaml"

mkdir -p "$REPO/$RECEIPT_DIR"
cat > "$REPO/$RECEIPT_DIR/$RUN_ID.yaml" <<EOF
version: 1
run_receipt:
  request_id: $REQUEST_ID
  run_id: $RUN_ID
  runner: gondolin
  status: completed
  tier: real
  code_path: workspace/sum_prices.py
  code_sha256: abcdef0123456789
  input_sha256: $INPUT_SHA256
  output_sha256: $OUTPUT_SHA256
  result_path: $RESULT_DIR/result.yaml
  created_at: "2026-06-15T00:00:00Z"
EOF
RHO_HOME="$OWNER_HOME" ./rho crypto sign \
  "$REPO/$RECEIPT_DIR/$RUN_ID.yaml" \
  --identity "$OWNER_ID" \
  --out "$REPO/$RECEIPT_DIR/$RUN_ID.rhosig.yaml" \
  --repo-id rho://repo/local/result-release \
  --request-id "$REQUEST_ID" \
  --recipient "$COLLAB_ID" \
  --purpose rho.run_receipt >/dev/null
RHO_HOME="$OWNER_HOME" ./rho repo sign-governance --root "$REPO" > "$SANDBOX/sign-governance.txt"
RHO_HOME="$COLLAB_HOME" ./rho repo doctor --root "$REPO" --flow > "$SANDBOX/doctor-flow-before-result.txt"
grep -q "flow: passed" "$SANDBOX/doctor-flow-before-result.txt"
grep -q "governance: passed" "$SANDBOX/doctor-flow-before-result.txt"
grep -q "flow next: rho result release $REQUEST_ID --run-id $RUN_ID --to $COLLAB_ID" "$SANDBOX/doctor-flow-before-result.txt"

RHO_HOME="$OWNER_HOME" ./rho result release "$REQUEST_ID" \
  --root "$REPO" \
  --from "$OWNER_ID" \
  --to "$COLLAB_ID" \
  --run-id "$RUN_ID" \
  --runner gondolin \
  > "$SANDBOX/release-output.txt"
test "$(git -C "$REPO" branch --show-current)" = "rho-owner/result-$REQUEST_ID"
grep -q "staged encrypted result files" "$SANDBOX/release-output.txt"
grep -q "staged signed run receipt" "$SANDBOX/release-output.txt"
grep -q "result branch: rho-owner/result-$REQUEST_ID" "$SANDBOX/release-output.txt"
grep -q "next: rho repo create-pr .*Release encrypted result for $REQUEST_ID" "$SANDBOX/release-output.txt"
grep -q "$RESULT_ATTACHMENT" "$SANDBOX/release-output.txt"
grep -q "attachments:" "$REPO/$RESULT_DIR/result.yaml"
grep -q "attachments/stdout.txt" "$REPO/$RESULT_DIR/result.yaml"
grep -q "$OUTPUT_SHA256" "$REPO/$RESULT_DIR/result.yaml"
grep -q "1113.03" "$REPO/$RESULT_ATTACHMENT"
if grep -q "1113.03" "$REPO/$RESULT_DIR/result.yaml"; then
  echo "result metadata embedded file-backed output" >&2
  exit 1
fi
grep -q "$INPUT_SHA256" "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"
grep -q "$OUTPUT_SHA256" "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"
grep -q "$RESULT_DIR/result.yaml" "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"
grep -q 'created_at: "2026-06-15T00:00:00Z"' "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"
if grep -q "input_path:" "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"; then
  echo "run receipt leaked input_path" >&2
  exit 1
fi
if grep -q "$SANDBOX/private" "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"; then
  echo "run receipt leaked local private input path" >&2
  exit 1
fi
grep -q "$INPUT_SHA256" "$REPO/$APPROVAL_DIR/$ACTION_ID.yaml"
RHO_HOME="$OWNER_HOME" ./rho crypto verify \
  "$REPO/$RESULT_DIR/result.yaml" \
  --signature "$REPO/$RESULT_DIR/result.rhosig.yaml" \
  --identity "$OWNER_ID" \
  --repo-id rho://repo/local/result-release \
  --request-id "$REQUEST_ID" \
  --recipient "$COLLAB_ID" \
  --purpose rho.result >/dev/null
RHO_HOME="$OWNER_HOME" ./rho crypto verify \
  "$REPO/$RECEIPT_DIR/$RUN_ID.yaml" \
  --signature "$REPO/$RECEIPT_DIR/$RUN_ID.rhosig.yaml" \
  --identity "$OWNER_ID" \
  --repo-id rho://repo/local/result-release \
  --request-id "$REQUEST_ID" \
  --recipient "$COLLAB_ID" \
  --purpose rho.run_receipt >/dev/null
grep -q "purpose: rho.result" "$REPO/$RESULT_DIR/result.rhosig.yaml"
grep -q "purpose: rho.run_receipt" "$REPO/$RECEIPT_DIR/$RUN_ID.rhosig.yaml"
RHO_HOME="$COLLAB_HOME" ./rho repo doctor --root "$REPO" --flow > "$SANDBOX/doctor-flow-pass.txt"
grep -q "flow: passed" "$SANDBOX/doctor-flow-pass.txt"
RHO_HOME="$COLLAB_HOME" ./rho result verify "$REQUEST_ID" \
  --root "$REPO" \
  --to "$COLLAB_ID" \
  > "$SANDBOX/result-verify-pass.txt"
grep -q "result: verified $RESULT_DIR/result.yaml" "$SANDBOX/result-verify-pass.txt"
grep -q "run receipt: verified $RECEIPT_DIR/$RUN_ID.yaml" "$SANDBOX/result-verify-pass.txt"
grep -q "approval grant: verified $APPROVAL_DIR/$ACTION_ID.yaml" "$SANDBOX/result-verify-pass.txt"
grep -q "output_sha256: $OUTPUT_SHA256" "$SANDBOX/result-verify-pass.txt"
grep -q "input_sha256: $INPUT_SHA256" "$SANDBOX/result-verify-pass.txt"

cp "$REPO/$RESULT_DIR/result.yaml" "$SANDBOX/result-plain.yaml"
cp "$REPO/$RESULT_DIR/result.rhosig.yaml" "$SANDBOX/result-signature-plain.yaml"
git -C "$REPO" show ":$RESULT_DIR/result.yaml" > "$SANDBOX/result-index.yaml"
git -C "$REPO" show ":$RESULT_DIR/result.rhosig.yaml" > "$SANDBOX/result-signature-index.yaml"
git -C "$REPO" show ":$RESULT_DIR/result.yaml" > "$REPO/$RESULT_DIR/result.yaml"
git -C "$REPO" show ":$RESULT_DIR/result.rhosig.yaml" > "$REPO/$RESULT_DIR/result.rhosig.yaml"
grep -q "kind: rho_recipient_envelope" "$REPO/$RESULT_DIR/result.yaml"
grep -q "kind: rho_recipient_envelope" "$REPO/$RESULT_DIR/result.rhosig.yaml"
RHO_HOME="$COLLAB_HOME" RHO_IDENTITY="$COLLAB_ID" ./rho result verify "$REQUEST_ID" \
  --root "$REPO" \
  --to "$COLLAB_ID" \
  > "$SANDBOX/result-verify-encrypted-worktree-pass.txt"
grep -q "refreshed protected file: $RESULT_DIR/result.yaml" "$SANDBOX/result-verify-encrypted-worktree-pass.txt"
grep -q "refreshed protected file: $RESULT_DIR/result.rhosig.yaml" "$SANDBOX/result-verify-encrypted-worktree-pass.txt"
grep -q "result: verified $RESULT_DIR/result.yaml" "$SANDBOX/result-verify-encrypted-worktree-pass.txt"

awk '
  /^[[:space:]]+ciphertext_base64:/ && !done {
    prefix = substr($0, 1, index($0, "ciphertext_base64:") - 1)
    value = $2
    first = substr(value, 1, 1)
    replacement = first == "A" ? "B" : "A"
    print prefix "ciphertext_base64: " replacement substr(value, 2)
    done = 1
    next
  }
  { print }
' "$SANDBOX/result-index.yaml" > "$REPO/$RESULT_DIR/result.yaml"
git -C "$REPO" show ":$RESULT_DIR/result.rhosig.yaml" > "$REPO/$RESULT_DIR/result.rhosig.yaml"
if RHO_HOME="$COLLAB_HOME" RHO_IDENTITY="$COLLAB_ID" ./rho result verify "$REQUEST_ID" \
  --root "$REPO" \
  --to "$COLLAB_ID" \
  > "$SANDBOX/result-verify-tampered-result-stdout.txt" \
  2> "$SANDBOX/result-verify-tampered-result-stderr.txt"; then
  echo "result verify accepted tampered encrypted result ciphertext" >&2
  exit 1
fi
grep -q "rho crypto smudge failed for $RESULT_DIR/result.yaml" "$SANDBOX/result-verify-tampered-result-stderr.txt"
grep -q "recipient envelope decrypt failed for $COLLAB_ID" "$SANDBOX/result-verify-tampered-result-stderr.txt"
grep -q "AEAD decryption failed" "$SANDBOX/result-verify-tampered-result-stderr.txt"
cp "$SANDBOX/result-plain.yaml" "$REPO/$RESULT_DIR/result.yaml"
cp "$SANDBOX/result-signature-plain.yaml" "$REPO/$RESULT_DIR/result.rhosig.yaml"

mv "$REPO/$APPROVAL_DIR/$ACTION_ID.rhosig.yaml" "$REPO/$APPROVAL_DIR/$ACTION_ID.rhosig.yaml.missing"
if RHO_HOME="$COLLAB_HOME" ./rho repo doctor --root "$REPO" --flow >"$SANDBOX/doctor-flow-missing-grant-stdout.txt" 2>"$SANDBOX/doctor-flow-missing-grant-stderr.txt"; then
  echo "doctor --flow allowed an unsigned approval grant" >&2
  exit 1
fi
grep -q "approval grant signature missing" "$SANDBOX/doctor-flow-missing-grant-stderr.txt"
if RHO_HOME="$COLLAB_HOME" ./rho result verify "$REQUEST_ID" \
  --root "$REPO" \
  --to "$COLLAB_ID" \
  >"$SANDBOX/result-verify-missing-grant-stdout.txt" \
  2>"$SANDBOX/result-verify-missing-grant-stderr.txt"; then
  echo "result verify allowed an unsigned approval grant" >&2
  exit 1
fi
grep -q "signature missing" "$SANDBOX/result-verify-missing-grant-stderr.txt"
mv "$REPO/$APPROVAL_DIR/$ACTION_ID.rhosig.yaml.missing" "$REPO/$APPROVAL_DIR/$ACTION_ID.rhosig.yaml"

git -C "$REPO" show ":$RESULT_DIR/result.yaml" > "$SANDBOX/result-index.yaml"
git -C "$REPO" show ":$RESULT_DIR/result.rhosig.yaml" > "$SANDBOX/result-signature-index.yaml"
git -C "$REPO" show ":$RESULT_ATTACHMENT" > "$SANDBOX/result-attachment-index.yaml"
git -C "$REPO" show ":$RECEIPT_DIR/$RUN_ID.yaml" > "$SANDBOX/receipt-index.yaml"
grep -q "kind: rho_recipient_envelope" "$SANDBOX/result-index.yaml"
grep -q "kind: rho_recipient_envelope" "$SANDBOX/result-signature-index.yaml"
grep -q "kind: rho_recipient_envelope" "$SANDBOX/result-attachment-index.yaml"
grep -q "$OUTPUT_SHA256" "$SANDBOX/receipt-index.yaml"
if grep -q "1113.03" "$SANDBOX/result-index.yaml"; then
  echo "staged result leaked plaintext" >&2
  exit 1
fi
if grep -q "1113.03" "$SANDBOX/result-attachment-index.yaml"; then
  echo "staged result attachment leaked plaintext" >&2
  exit 1
fi

EXPLICIT_RESULT_DIR="rho/messages/inbox/id/github/rho-owner/$EXPLICIT_SENDER_REQUEST_ID"
RHO_HOME="$OWNER_HOME" ./rho repo protect-path \
  "rho/messages/inbox/id/github/rho-owner/**" \
  --root "$REPO" \
  --rho-bin "$ROOT_DIR/rho" \
  --recipient "$OWNER_ID" >/dev/null
RHO_HOME="$OWNER_HOME" ./rho repo sign-governance --root "$REPO" > "$SANDBOX/sign-governance-owner-inbox.txt"
RHO_HOME="$COLLAB_HOME" ./rho result release "$EXPLICIT_SENDER_REQUEST_ID" \
  --root "$REPO" \
  --from "$COLLAB_ID" \
  --to "$OWNER_ID" \
  --run-id run-explicit-sender \
  --value "sender self check" \
  --allow-missing-request \
  --no-branch \
  > "$SANDBOX/release-explicit-sender-output.txt"
grep -q "staged encrypted result files" "$SANDBOX/release-explicit-sender-output.txt"
git -C "$REPO" show ":$EXPLICIT_RESULT_DIR/result.yaml" > "$SANDBOX/explicit-sender-result-index.yaml"
grep -q "kind: rho_recipient_envelope" "$SANDBOX/explicit-sender-result-index.yaml"
grep -q "$OWNER_ID" "$SANDBOX/explicit-sender-result-index.yaml"
grep -q "$COLLAB_ID" "$SANDBOX/explicit-sender-result-index.yaml"
if grep -q "sender self check" "$SANDBOX/explicit-sender-result-index.yaml"; then
  echo "explicit sender result leaked plaintext" >&2
  exit 1
fi
RHO_HOME="$COLLAB_HOME" ./rho crypto smudge \
  --repo-root "$REPO" \
  --path "$EXPLICIT_RESULT_DIR/result.yaml" \
  < "$SANDBOX/explicit-sender-result-index.yaml" \
  > "$SANDBOX/explicit-sender-collab-smudged.yaml"
grep -q "sender self check" "$SANDBOX/explicit-sender-collab-smudged.yaml"

printf "\n# tamper receipt\n" >> "$REPO/$RECEIPT_DIR/$RUN_ID.yaml"
if RHO_HOME="$COLLAB_HOME" ./rho repo doctor --root "$REPO" --flow >"$SANDBOX/doctor-flow-fail-stdout.txt" 2>"$SANDBOX/doctor-flow-fail-stderr.txt"; then
  echo "doctor --flow allowed tampered run receipt" >&2
  exit 1
fi
grep -q "signature verification failed" "$SANDBOX/doctor-flow-fail-stderr.txt"

echo "inspect sandbox: $SANDBOX"
find "$SANDBOX" \
  -path "*/.git" -prune -o \
  -maxdepth 7 -type f -print | sort
echo "rho result release e2e passed"
