#!/usr/bin/env bash # GATED prod-write wrapper — the ONLY path in this skill that writes PRODUCTION. # # Used solely by promote-apply.sh --target prod, at promotion time. Two deliberate # frictions make accidental or autonomous prod writes impossible (ADR-0003): # 1. The prod write key is read from the ENVIRONMENT (DOLIBARR_PROD_WRITE_KEY), # never from a stored .env — a human must supply it per invocation. # 2. Any write method (POST/PUT/DELETE/PATCH) is REFUSED unless ARCO_PROMOTE_CONFIRM # equals exactly "I-UNDERSTAND-THIS-WRITES-PROD". # GET is allowed (id read-back) but still needs the key. # # DOLIBARR_PROD_WRITE_KEY=… ARCO_PROMOTE_CONFIRM=I-UNDERSTAND-THIS-WRITES-PROD \ # dol-prod-write.sh POST /thirdparties '{...}' set -euo pipefail PROD_URL="${DOLIBARR_PROD_URL:-https://erp.arcodange.lab}" : "${DOLIBARR_PROD_WRITE_KEY:?dol-prod-write.sh: DOLIBARR_PROD_WRITE_KEY must be supplied in the environment (never stored)}" if [[ $# -lt 2 ]]; then echo "usage: dol-prod-write.sh [body]" >&2; exit 2; fi METHOD="$1"; API_PATH="$2"; BODY="${3-}" case "${METHOD}" in GET) ;; POST|PUT|DELETE|PATCH) if [[ "${ARCO_PROMOTE_CONFIRM:-}" != "I-UNDERSTAND-THIS-WRITES-PROD" ]]; then echo "dol-prod-write.sh: REFUSING ${METHOD} ${API_PATH} on PRODUCTION (${PROD_URL})." >&2 echo " Set ARCO_PROMOTE_CONFIRM=I-UNDERSTAND-THIS-WRITES-PROD to authorize prod writes." >&2 exit 3 fi ;; *) echo "dol-prod-write.sh: unsupported method '${METHOD}'" >&2; exit 2 ;; esac CURL_ARGS=( -sS -X "${METHOD}" -H "DOLAPIKEY: ${DOLIBARR_PROD_WRITE_KEY}" -H "Accept: application/json" --max-time 30 ) [[ -n "${BODY}" ]] && CURL_ARGS+=( -H "Content-Type: application/json" --data "${BODY}" ) BODY_FILE="$(mktemp -t dolprod.XXXXXX)"; trap 'rm -f "${BODY_FILE}"' EXIT HTTP_CODE=$(curl "${CURL_ARGS[@]}" -o "${BODY_FILE}" -w "%{http_code}" "${PROD_URL}/api/index.php${API_PATH}") cat "${BODY_FILE}" if [[ "${HTTP_CODE}" -ge 400 ]]; then echo "" >&2; echo "dol-prod-write.sh: HTTP ${HTTP_CODE} on ${METHOD} ${API_PATH}" >&2; exit 1 fi