#!/usr/bin/env bash
# quote-render-gate — PreToolUse gate on browser-pdf-save.
#
# A customer only ever receives the two client-facing quote documents from the
# customer documents scope (memory/users/<phone>/documents/). This gate refuses
# to print one to PDF unless the deterministic quote-render tool actually
# produced it — proven by the render receipt quote-render writes on success
# (quoting/jobs/<jobId>/render-receipt.json). No receipt for the job means the
# quote was hand-authored off the deterministic path, so the fixed-layout
# guarantee and the reconcile/margin/link gates never ran; the PDF is refused and
# the bypass is surfaced as [quote-render] op=bypass, not delivered.
#
# Scope: only a .pdf under memory/users/<phone>/documents/ named
# quote-<jobId>.pdf or quote-<jobId>-breakdown.pdf is gated. Every other PDF —
# brochures, invoices, the admin-scope internal view — passes untouched.
#
# Exit codes: 0 = allow, 2 = block (stderr shown to the agent). Fail OPEN on an
# uninspectable call (browser-pdf-save is a general-purpose tool; the bypass we
# guard is an agent skipping quote-render, and the agent never controls this
# hook's stdin, so failing open here opens no bypass). No task numbers or
# internal refs in any operator-visible string.

set -uo pipefail

# No envelope (tty or empty stdin) → allow: cannot inspect, must not brick PDFs.
if [ -t 0 ]; then exit 0; fi
INPUT=$(cat)
[ -z "$INPUT" ] && exit 0

# Print the jobId of a gated client-quote artefact, or nothing for any other
# call. The customer documents scope is a path convention, so match on it
# structurally rather than resolving symlinks.
JOBID=$(INPUT="$INPUT" python3 - <<'PY' 2>/dev/null || true
import os, json, re, sys
try:
    d = json.loads(os.environ["INPUT"])
except Exception:
    sys.exit(0)
tool = d.get("tool_name", "") or ""
if not tool.endswith("browser-pdf-save"):
    sys.exit(0)
path = (d.get("tool_input", {}) or {}).get("path", "") or ""
if not path:
    sys.exit(0)
norm = os.path.normpath(path)
m = re.search(r'(?:^|/)memory/users/[^/]+/documents/quote-(.+?)(?:-breakdown)?\.pdf$', norm)
if not m:
    sys.exit(0)
print(m.group(1))
PY
)

# Not a gated client-quote artefact → allow.
[ -z "$JOBID" ] && exit 0

# A jobId is a single path segment. A separator or traversal in it never keys a
# legitimate receipt, so treat it as a bypass rather than resolving a stray file.
case "$JOBID" in
  */*|*..*)
    echo "[quote-render] op=bypass jobId=$JOBID reason=bad-jobid" >&2
    echo "Blocked: this looks like a client quote PDF but its name does not resolve to a job. Produce the quote with the quote-render tool, which files the document and its render receipt, then print the path it returns." >&2
    exit 2
    ;;
esac

# The receipt lives beside the job's figures, written by quote-render only after
# every gate passed. Its presence is the proof the deterministic path ran.
if [ -f "$PWD/quoting/jobs/$JOBID/render-receipt.json" ]; then
  exit 0
fi

echo "[quote-render] op=bypass jobId=$JOBID detail=client quote PDF has no render receipt" >&2
echo "Blocked: this client quote was not produced by the quote-render tool, so its fixed layout and the reconcile, margin-leak and link-liveness gates never ran. Run quote-render for this job (it files the document and its receipt), then print the client HTML path it returns to PDF." >&2
exit 2
