Files
pn-new-crm/scripts/tunnel-url.sh

65 lines
2.4 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# Print the current Cloudflare quick-tunnel URL, or a clear status line
# if the launchd job isn't running.
#
# Usage:
# ./scripts/tunnel-url.sh # print URL or status
# ./scripts/tunnel-url.sh --copy # print URL and copy to clipboard
#
# Paired with the launchd plist at:
# ~/Library/LaunchAgents/solutions.letsbe.pn-crm-tunnel.plist
#
# Quick ops:
# launchctl load ~/Library/LaunchAgents/solutions.letsbe.pn-crm-tunnel.plist # start
# launchctl unload ~/Library/LaunchAgents/solutions.letsbe.pn-crm-tunnel.plist # stop
# launchctl kickstart -k gui/$(id -u)/solutions.letsbe.pn-crm-tunnel # restart (NEW URL)
set -euo pipefail
LOG_FILE="$HOME/Library/Logs/pn-crm-tunnel.err.log"
LABEL="solutions.letsbe.pn-crm-tunnel"
if ! launchctl print "gui/$(id -u)/$LABEL" >/dev/null 2>&1; then
echo "Tunnel is not loaded. Start with:"
echo " launchctl load ~/Library/LaunchAgents/$LABEL.plist"
exit 1
fi
if [[ ! -f "$LOG_FILE" ]]; then
echo "Tunnel job is loaded but hasn't produced a log yet. Try again in a few seconds."
exit 1
fi
# cloudflared prints the public URL once on startup, like:
# https://<words>.trycloudflare.com
# Take the most recent occurrence so a restart-then-rerun picks the
# current one rather than a stale earlier line.
URL=$(grep -Eo 'https://[a-z0-9-]+\.trycloudflare\.com' "$LOG_FILE" | tail -1 || true)
if [[ -z "$URL" ]]; then
echo "Tunnel is running but no URL has appeared in the log yet."
echo "Tail it: tail -f $LOG_FILE"
exit 1
fi
echo "$URL"
echo "$URL/api/webhooks/documenso ← paste this into Documenso webhook settings"
if [[ "${1:-}" == "--copy" ]]; then
printf "%s/api/webhooks/documenso" "$URL" | pbcopy
echo "(webhook URL copied to clipboard)"
fi
feat(documenso-audit-phase-1): persist documensoId early + preflight + state machine + reconciliation + tests Phase 1 of the comprehensive Documenso upload audit per the 2026-05-26 locked-decisions block in docs/superpowers/audits/active-uat.md. P1.1 — persist documensoId immediately after create Was set only at the late `status: 'sent'` commit. Any throw between documensoCreate and the late update left an orphaned Documenso envelope the CRM had no link to. Now the UPDATE runs right after documensoCreate succeeds; rollback paths can find and void the envelope. P1.2 — pre-flight validation hard-blocks Submit UploadForSigningDialog computes a submissionErrors memo over recipients + fields. Submit button disabled when errors > 0. Inline amber summary lists every issue (missing email, invalid email, missing name, field assigned to non-existent recipient, no fields placed). Service layer mirrors the same email + name checks so direct API hits reject early. No override path per locked decision. P1.3 — cancel/delete affordance audit + sweep Document-list per-row Delete + Send for Signing actions now: - Wrapped in PermissionGate (documents.delete + send_for_signing). - Surface toast on success + toastError on failure (were silently swallowing errors). - Use a broader predicate-based query invalidation so every doc list across the app refreshes, not just the local key. EOI tab Regenerate + Cancel EOI buttons + reservation/contract tab Cancel buttons wrapped in PermissionGate (documents.edit, the cancel route's auth check). P1.4 — Documenso webhook URL auto-PATCH (env-gated) scripts/update-documenso-webhook.ts written. Reads DEV_AUTO_UPDATE_DOCUMENSO_WEBHOOK env flag (when 1, runs; otherwise no-op). Lists every webhook on the Documenso instance via v2 (with v1 fallback), identifies webhooks pointing at trycloudflare.com hosts OR /api/webhooks/documenso paths, PATCHes them to the new tunnel URL. scripts/tunnel-url.sh chains the script after the URL print so a re-tunnel auto-rotates the webhook (when flag set). P1.5 — state-machine refactor with rollbackTo() helper custom-document-upload.service.ts: - Single try around create → send → place steps. - state.step tracks which step is current; state.documensoDocId records the envelope id once we have it. - rollbackTo(reason) composes the recovery: status='cancelled' on the CRM row, documensoVoidSafe on the envelope when applicable. Idempotent — calling twice is safe. - Removes three independent try/catches. P1.6 — recipient ↔ Documenso identity reconciliation After documensoSend, validates every distinct email we sent appears in sentDoc.recipients. If Documenso silently dropped one, a ConflictError fires before field placement so the rollback path triggers. Explicit message names the missing emails for the rep. P1.7 — vitest extension + per-failure audit-log entries - 5 new vitest cases (blank email, whitespace email, malformed email, blank name, duplicate-emails-OK semantic). - rollbackTo writes a structured audit_log entry with failedStep, documensoEnvelopeId, errorClass, errorMessage. Post-mortem investigation has structured data instead of just logger lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 21:09:50 +02:00
# Auto-PATCH Documenso's webhook URL when the env flag is set. Gated so
# production ports can never have their webhook rotated by a stale dev
# script. The TS script reads DOCUMENSO_API_URL + DOCUMENSO_API_KEY +
# DOCUMENSO_API_VERSION from .env and updates every webhook whose URL
# already points at our path OR at any *.trycloudflare.com host.
if [[ "${DEV_AUTO_UPDATE_DOCUMENSO_WEBHOOK:-}" == "1" ]]; then
echo ""
echo "DEV_AUTO_UPDATE_DOCUMENSO_WEBHOOK=1 — updating Documenso webhook(s)…"
cd "$(dirname "$0")/.." || exit 1
DEV_AUTO_UPDATE_DOCUMENSO_WEBHOOK=1 \
pnpm tsx scripts/update-documenso-webhook.ts "$URL"
fi