[object Object]

← back to Cncp Domains

initial snapshot — gitify all builds (CLAUDE.md rule 2026-05-06)

161ada1e465b800406fe133e7ffb19b7a3dcc354 · 2026-05-06 10:20:41 -0700 · Steve

Files touched

Diff

commit 161ada1e465b800406fe133e7ffb19b7a3dcc354
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed May 6 10:20:41 2026 -0700

    initial snapshot — gitify all builds (CLAUDE.md rule 2026-05-06)
---
 .gitignore                  |  25 ++++++
 logs/expiring-2026-05-05.md |  39 ++++++++++
 logs/expiring-2026-05-06.md |  38 +++++++++
 logs/last-george.err        |   0
 logs/last-george.json       |   1 +
 scripts/expiring-soon.sh    | 182 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 285 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9ae81e0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+node_modules/
+.env
+.env.*
+!.env.example
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+.cache/
+.parcel-cache/
+coverage/
+__pycache__/
+*.pyc
+*.pyo
+.venv/
+venv/
+.pytest_cache/
+.ruff_cache/
+.idea/
+.vscode/
+*.swp
+.qodo/
+out/
diff --git a/logs/expiring-2026-05-05.md b/logs/expiring-2026-05-05.md
new file mode 100644
index 0000000..447e756
--- /dev/null
+++ b/logs/expiring-2026-05-05.md
@@ -0,0 +1,39 @@
+# CNCP domains expiring within 14 days
+
+_As of 2026-05-05 — 33 expiring (7 Keep, 25 Toss, 30 under 7d)_
+
+| Days Left | Domain | Registrar | Auto-Renew | Suggestion | Expires |
+|---:|---|---|---|---|---|
+| 0 | wallpapernashville.com | GoDaddy | OFF | Toss | 2026-05-05 |
+| 1 | commercialdesignreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 1 | commercialsalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 1 | designtradesalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 1 | filthyrichliving.com | GoDaddy | OFF | Toss | 2026-05-06 |
+| 1 | flufears.org | GoDaddy | OFF | Toss | 2026-05-06 |
+| 1 | hospitalitydesignreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 1 | hospitalitysalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 1 | interiordesignreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 1 | localsalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 1 | showroomreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 1 | showroomsalesreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 1 | telesalesrep.com | GoDaddy | ON | Toss | 2026-05-06 |
+| ⚠ 3 | steveabramsdesigns.com | GoDaddy | OFF | Keep | 2026-05-08 |
+| 4 | blankstocklining.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| ⚠ 4 | flockedwallpaper.com | GoDaddy | OFF | Keep | 2026-05-09 |
+| 4 | goldleafwallpaper.com | GoDaddy | unknown | - | 2026-05-09 |
+| 4 | hotelwallcoverings.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 4 | linenwallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 4 | madagascarwallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 4 | naturaltextilewallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 4 | raffiawallcoverings.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 4 | silkwallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 5 | 1970swallpaper.com | GoDaddy | OFF | Toss | 2026-05-10 |
+| 5 | wallpapercanada.com | GoDaddy | OFF | Toss | 2026-05-10 |
+| 6 | 1920swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 6 | 1930swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 6 | 1940swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 6 | 1960swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 6 | 1980swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 7 | customdigitalwallcoverings.com | GoDaddy | OFF | Toss | 2026-05-12 |
+| 9 | sheltermagazines.com | GoDaddy | OFF | Toss | 2026-05-14 |
+| 12 | designerrepresentatives.com | GoDaddy | ON | Toss | 2026-05-17 |
diff --git a/logs/expiring-2026-05-06.md b/logs/expiring-2026-05-06.md
new file mode 100644
index 0000000..e946aa8
--- /dev/null
+++ b/logs/expiring-2026-05-06.md
@@ -0,0 +1,38 @@
+# CNCP domains expiring within 14 days
+
+_As of 2026-05-06 — 32 expiring (7 Keep, 24 Toss, 30 under 7d)_
+
+| Days Left | Domain | Registrar | Auto-Renew | Suggestion | Expires |
+|---:|---|---|---|---|---|
+| 0 | commercialdesignreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 0 | commercialsalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 0 | designtradesalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 0 | filthyrichliving.com | GoDaddy | OFF | Toss | 2026-05-06 |
+| 0 | flufears.org | GoDaddy | OFF | Toss | 2026-05-06 |
+| 0 | hospitalitydesignreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 0 | hospitalitysalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 0 | interiordesignreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 0 | localsalesreps.com | GoDaddy | ON | Keep | 2026-05-06 |
+| 0 | showroomreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 0 | showroomsalesreps.com | GoDaddy | ON | Toss | 2026-05-06 |
+| 0 | telesalesrep.com | GoDaddy | ON | Toss | 2026-05-06 |
+| ⚠ 2 | steveabramsdesigns.com | GoDaddy | OFF | Keep | 2026-05-08 |
+| 3 | blankstocklining.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| ⚠ 3 | flockedwallpaper.com | GoDaddy | OFF | Keep | 2026-05-09 |
+| 3 | goldleafwallpaper.com | GoDaddy | unknown | - | 2026-05-09 |
+| 3 | hotelwallcoverings.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 3 | linenwallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 3 | madagascarwallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 3 | naturaltextilewallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 3 | raffiawallcoverings.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 3 | silkwallpaper.com | GoDaddy | OFF | Toss | 2026-05-09 |
+| 4 | 1970swallpaper.com | GoDaddy | OFF | Toss | 2026-05-10 |
+| 4 | wallpapercanada.com | GoDaddy | OFF | Toss | 2026-05-10 |
+| 5 | 1920swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 5 | 1930swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 5 | 1940swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 5 | 1960swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 5 | 1980swallpaper.com | GoDaddy | OFF | Toss | 2026-05-11 |
+| 6 | customdigitalwallcoverings.com | GoDaddy | OFF | Toss | 2026-05-12 |
+| 8 | sheltermagazines.com | GoDaddy | OFF | Toss | 2026-05-14 |
+| 11 | designerrepresentatives.com | GoDaddy | ON | Toss | 2026-05-17 |
diff --git a/logs/last-george.err b/logs/last-george.err
new file mode 100644
index 0000000..e69de29
diff --git a/logs/last-george.json b/logs/last-george.json
new file mode 100644
index 0000000..126e748
--- /dev/null
+++ b/logs/last-george.json
@@ -0,0 +1 @@
+{"success":true,"messageId":"19dfe199e68e1abd","threadId":"19dfe199e68e1abd","account":"steve-office","source":"curl/8.7.1","inThread":false}
\ No newline at end of file
diff --git a/scripts/expiring-soon.sh b/scripts/expiring-soon.sh
new file mode 100755
index 0000000..ce6bc56
--- /dev/null
+++ b/scripts/expiring-soon.sh
@@ -0,0 +1,182 @@
+#!/usr/bin/env bash
+# expiring-soon.sh — alert Steve about CNCP domains expiring within 14 days.
+#   - reads ~/cncp-starter/cncp-config.json
+#   - filters domains with `expires` in the next 14 days from today
+#   - posts an HTML email via George Gmail bridge (localhost:9850)
+#   - on George failure, writes a markdown report to logs/ and exits 1
+#   - silent exit 0 when nothing is expiring
+
+set -uo pipefail
+
+CONFIG="${HOME}/cncp-starter/cncp-config.json"
+PROJECT_DIR="${HOME}/Projects/cncp-domains"
+LOG_DIR="${PROJECT_DIR}/logs"
+GEORGE_URL="http://localhost:9850/api/send"
+GEORGE_AUTH="admin:DWSecure2024!"
+RECIPIENT="steveabramsdesigns@gmail.com"
+WINDOW_DAYS=14
+URGENT_DAYS=7
+DRY_RUN="${DRY_RUN:-0}"
+
+mkdir -p "${LOG_DIR}"
+
+if [[ ! -f "${CONFIG}" ]]; then
+  echo "[expiring-soon] config not found: ${CONFIG}" >&2
+  exit 1
+fi
+
+if ! command -v jq >/dev/null 2>&1; then
+  echo "[expiring-soon] jq is required" >&2
+  exit 1
+fi
+
+TODAY="$(date -I)"
+TODAY_EPOCH="$(date -j -f '%Y-%m-%d' "${TODAY}" +%s 2>/dev/null || date -d "${TODAY}" +%s)"
+
+# Build a JSON array of expiring domains, each with a `daysLeft` field.
+EXPIRING_JSON="$(
+  jq --arg today "${TODAY}" --argjson window "${WINDOW_DAYS}" '
+    def dayDiff(d):
+      ((d | strptime("%Y-%m-%d") | mktime) - ($today | strptime("%Y-%m-%d") | mktime)) / 86400 | floor;
+    [
+      .domains[]
+      | select(.expires != null and .expires != "")
+      | . + {daysLeft: dayDiff(.expires)}
+      | select(.daysLeft >= 0 and .daysLeft <= $window)
+    ]
+    | sort_by(.daysLeft)
+  ' "${CONFIG}"
+)"
+
+COUNT="$(echo "${EXPIRING_JSON}" | jq 'length')"
+
+if [[ "${COUNT}" -eq 0 ]]; then
+  # Nothing to alert about — silent exit per spec.
+  exit 0
+fi
+
+# ---------- build HTML body ----------
+HTML_TABLE="$(
+  echo "${EXPIRING_JSON}" | jq -r --argjson urgent "${URGENT_DAYS}" '
+    def autorenew(n):
+      if n == null then "unknown"
+      elif (n | test("(?i)Auto-renew:\\s*ON")) then "ON"
+      elif (n | test("(?i)Auto-renew:\\s*OFF")) then "OFF"
+      else "unknown"
+      end;
+    def keepish(s): (s // "" | ascii_downcase) | startswith("keep");
+    def warnRow(d):
+      d.daysLeft < $urgent
+      and autorenew(d.note) == "OFF"
+      and keepish(d.suggestion);
+    map(
+      "<tr style=\"background:" +
+      (if warnRow(.) then "#fee2e2" else (if (.daysLeft|tonumber) < 7 then "#fef3c7" else "#ffffff" end) end) +
+      ";\">" +
+      "<td style=\"padding:6px 10px;border:1px solid #e5e7eb;text-align:right;\">" +
+        (if warnRow(.) then "&#9888; " else "" end) + (.daysLeft|tostring) +
+      "</td>" +
+      "<td style=\"padding:6px 10px;border:1px solid #e5e7eb;\"><b>" + (.name // "?") + "</b></td>" +
+      "<td style=\"padding:6px 10px;border:1px solid #e5e7eb;\">" + (.reg // "?") + "</td>" +
+      "<td style=\"padding:6px 10px;border:1px solid #e5e7eb;\">" + autorenew(.note) + "</td>" +
+      "<td style=\"padding:6px 10px;border:1px solid #e5e7eb;\">" + (.suggestion // "-") + "</td>" +
+      "<td style=\"padding:6px 10px;border:1px solid #e5e7eb;color:#555;\">" + (.expires // "") + "</td>" +
+      "</tr>"
+    ) | join("\n")
+  '
+)"
+
+KEEP_COUNT="$(echo "${EXPIRING_JSON}" | jq '[.[] | select((.suggestion // "" | ascii_downcase) | startswith("keep"))] | length')"
+TOSS_COUNT="$(echo "${EXPIRING_JSON}" | jq '[.[] | select((.suggestion // "" | ascii_downcase) | startswith("toss"))] | length')"
+URGENT_COUNT="$(echo "${EXPIRING_JSON}" | jq --argjson u "${URGENT_DAYS}" '[.[] | select(.daysLeft < $u)] | length')"
+
+REGISTRAR_BREAKDOWN="$(
+  echo "${EXPIRING_JSON}" | jq -r '
+    group_by(.reg // "Unknown")
+    | map("<li><b>" + (.[0].reg // "Unknown") + ":</b> " + (length|tostring) + "</li>")
+    | join("")
+  '
+)"
+
+HTML_BODY="$(cat <<HTMLEOF
+<html><body style="font-family:-apple-system,Segoe UI,Roboto,sans-serif;color:#111;">
+<h2 style="margin:0 0 8px;">CNCP domains expiring in the next ${WINDOW_DAYS} days</h2>
+<p style="margin:0 0 12px;color:#555;">As of ${TODAY} &middot; <b>${COUNT}</b> expiring &middot; <b>${KEEP_COUNT}</b> Keep &middot; <b>${TOSS_COUNT}</b> Toss &middot; <b>${URGENT_COUNT}</b> under ${URGENT_DAYS} days</p>
+<h3 style="margin:14px 0 6px;">By registrar</h3>
+<ul style="margin:0 0 12px 18px;">${REGISTRAR_BREAKDOWN}</ul>
+<table style="border-collapse:collapse;border:1px solid #e5e7eb;font-size:13px;min-width:640px;">
+<thead><tr style="background:#f3f4f6;">
+<th style="padding:6px 10px;border:1px solid #e5e7eb;text-align:right;">Days Left</th>
+<th style="padding:6px 10px;border:1px solid #e5e7eb;text-align:left;">Domain</th>
+<th style="padding:6px 10px;border:1px solid #e5e7eb;text-align:left;">Registrar</th>
+<th style="padding:6px 10px;border:1px solid #e5e7eb;text-align:left;">Auto-Renew</th>
+<th style="padding:6px 10px;border:1px solid #e5e7eb;text-align:left;">Suggestion</th>
+<th style="padding:6px 10px;border:1px solid #e5e7eb;text-align:left;">Expires</th>
+</tr></thead>
+<tbody>
+${HTML_TABLE}
+</tbody></table>
+<p style="margin:14px 0 0;color:#888;font-size:12px;">Red rows = under ${URGENT_DAYS} days, auto-renew OFF, suggestion = Keep. Yellow rows = under 7 days but lower urgency.</p>
+<p style="margin:6px 0 0;color:#888;font-size:12px;">Source: ~/cncp-starter/cncp-config.json &middot; alert script: ~/Projects/cncp-domains/scripts/expiring-soon.sh</p>
+</body></html>
+HTMLEOF
+)"
+
+SUBJECT="CNCP domains expiring this week (${COUNT} in ${WINDOW_DAYS}d, ${URGENT_COUNT} urgent)"
+
+# ---------- markdown fallback (always written for audit) ----------
+LOG_FILE="${LOG_DIR}/expiring-${TODAY}.md"
+{
+  echo "# CNCP domains expiring within ${WINDOW_DAYS} days"
+  echo ""
+  echo "_As of ${TODAY} — ${COUNT} expiring (${KEEP_COUNT} Keep, ${TOSS_COUNT} Toss, ${URGENT_COUNT} under ${URGENT_DAYS}d)_"
+  echo ""
+  echo "| Days Left | Domain | Registrar | Auto-Renew | Suggestion | Expires |"
+  echo "|---:|---|---|---|---|---|"
+  echo "${EXPIRING_JSON}" | jq -r --argjson u "${URGENT_DAYS}" '
+    def autorenew(n):
+      if n == null then "unknown"
+      elif (n | test("(?i)Auto-renew:\\s*ON")) then "ON"
+      elif (n | test("(?i)Auto-renew:\\s*OFF")) then "OFF"
+      else "unknown"
+      end;
+    def keepish(s): (s // "" | ascii_downcase) | startswith("keep");
+    .[] | (
+      (if (.daysLeft < $u and autorenew(.note) == "OFF" and keepish(.suggestion)) then "⚠ " else "" end)
+      + (.daysLeft|tostring)
+    ) as $d
+    | "| " + $d + " | " + (.name // "?") + " | " + (.reg // "?") + " | " + autorenew(.note) + " | " + (.suggestion // "-") + " | " + (.expires // "") + " |"
+  '
+} > "${LOG_FILE}"
+
+# ---------- DRY RUN: never actually email ----------
+if [[ "${DRY_RUN}" == "1" ]]; then
+  echo "[expiring-soon] DRY RUN — would email ${RECIPIENT}"
+  echo "[expiring-soon] subject: ${SUBJECT}"
+  echo "[expiring-soon] markdown report: ${LOG_FILE}"
+  echo "[expiring-soon] expiring count: ${COUNT}"
+  echo "----- markdown table -----"
+  cat "${LOG_FILE}"
+  exit 0
+fi
+
+# ---------- POST to George ----------
+PAYLOAD="$(jq -nc \
+  --arg to "${RECIPIENT}" \
+  --arg subject "${SUBJECT}" \
+  --arg body "${HTML_BODY}" \
+  '{to:$to, subject:$subject, body:$body}')"
+
+HTTP_OUT="$(curl -sS -o "${LOG_DIR}/last-george.json" -w '%{http_code}' \
+  -X POST "${GEORGE_URL}" \
+  -u "${GEORGE_AUTH}" \
+  -H 'content-type: application/json' \
+  --data-binary "${PAYLOAD}" 2>>"${LOG_DIR}/last-george.err" || echo "000")"
+
+if [[ "${HTTP_OUT}" =~ ^2 ]]; then
+  echo "[expiring-soon] sent ${COUNT} expiring domains to ${RECIPIENT} (HTTP ${HTTP_OUT})"
+  exit 0
+fi
+
+echo "[expiring-soon] George send FAILED (HTTP ${HTTP_OUT}); markdown report kept at ${LOG_FILE}" >&2
+exit 1

(oldest)  ·  back to Cncp Domains  ·  snapshot: 8 file(s) changed, +6 new, ~2 modified 9d4555c →