Follow-ups: DNS dry-run/zone-only, Order NPM IDs, E2E Location assert, the-order block_exploits
- update-all-dns-to-public-ip.sh: --dry-run (no CF API), --zone-only=ZONE, help before .env, env CLOUDFLARE_DNS_DRY_RUN/DNS_ZONE_ONLY - update-sankofa-npmplus-proxy-hosts.sh: the-order + www.the-order by ID (env SANKOFA_NPM_ID_THE_ORDER, SANKOFA_NPM_ID_WWW_THE_ORDER, THE_ORDER_UPSTREAM_*) - update-npmplus-proxy-hosts-api.sh: the-order.sankofa.nexus uses block_exploits false like sankofa portal - verify-end-to-end-routing.sh: E2E_WWW_CANONICAL_BASE + Location validation (fail on wrong apex); keep local redirect vars - docs: ALL_VMIDS www 301 lines, E2E_ENDPOINTS_LIST verifier/DNS notes; AGENTS.md Cloudflare script pointer Made-with: Cursor
This commit is contained in:
@@ -24,6 +24,7 @@ Orchestration for Proxmox VE, Chain 138 (`smom-dbis-138/`), explorers, NPMplus,
|
||||
| Portal login + Keycloak systemd + `.env` (prints password once) | `./scripts/deployment/enable-sankofa-portal-login-7801.sh` (`--dry-run` first) |
|
||||
| Completable (no LAN) | `./scripts/run-completable-tasks-from-anywhere.sh` |
|
||||
| Operator (LAN + secrets) | `./scripts/run-all-operator-tasks-from-lan.sh` (use `--skip-backup` if `NPM_PASSWORD` unset) |
|
||||
| Cloudflare bulk DNS → `PUBLIC_IP` | `./scripts/update-all-dns-to-public-ip.sh` — use **`--dry-run`** and **`--zone-only=sankofa.nexus`** (or `d-bis.org` / `mim4u.org` / `defi-oracle.io`) to limit scope; see script header |
|
||||
|
||||
## Rules of engagement
|
||||
|
||||
|
||||
@@ -249,9 +249,9 @@ The following VMIDs have been permanently removed:
|
||||
|
||||
**Public Domains** (NPMplus routing):
|
||||
- `sankofa.nexus` → Routes to `http://192.168.11.51:3000` (Sankofa Portal/VMID 7801) ✅
|
||||
- `www.sankofa.nexus` → Routes to `http://192.168.11.51:3000` (Sankofa Portal/VMID 7801) ✅
|
||||
- `www.sankofa.nexus` → Same upstream as apex; NPM **`advanced_config`** issues **301** to **`https://sankofa.nexus`** (preserve path/query via `$request_uri`). ✅
|
||||
- `phoenix.sankofa.nexus` → Routes to `http://192.168.11.50:4000` (Phoenix API/VMID 7800) ✅
|
||||
- `www.phoenix.sankofa.nexus` → Routes to `http://192.168.11.50:4000` (Phoenix API/VMID 7800) ✅
|
||||
- `www.phoenix.sankofa.nexus` → Same upstream; **301** to **`https://phoenix.sankofa.nexus`**. ✅
|
||||
- `the-order.sankofa.nexus` / `www.the-order.sankofa.nexus` → OSJ management portal (secure auth). App source: **the_order** at `~/projects/the_order`. NPMplus **target** order-haproxy `http://192.168.11.39:80` (VMID **10210**) when that stack is serving. Until then, `update-npmplus-proxy-hosts-api.sh` defaults upstream to Sankofa portal `http://192.168.11.51:3000` (7801); override with `THE_ORDER_UPSTREAM_IP` / `THE_ORDER_UPSTREAM_PORT` when switching to HAProxy. **`www.the-order.sankofa.nexus`** is configured for **301** to **`https://the-order.sankofa.nexus`** (same pattern as `www.sankofa` / `www.phoenix`).
|
||||
- `studio.sankofa.nexus` → Routes to `http://192.168.11.72:8000` (Sankofa Studio / VMID 7805)
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
| secure.mim4u.org | web | https://secure.mim4u.org | MIM4U secure portal. |
|
||||
| training.mim4u.org | web | https://training.mim4u.org | MIM4U training site. |
|
||||
| sankofa.nexus | web | https://sankofa.nexus | Sankofa Nexus root / web. |
|
||||
| www.sankofa.nexus | web | https://www.sankofa.nexus | Sankofa Nexus www. |
|
||||
| phoenix.sankofa.nexus | web | https://phoenix.sankofa.nexus | Phoenix (Sankofa) web app. |
|
||||
| www.phoenix.sankofa.nexus | web | https://www.phoenix.sankofa.nexus | Phoenix www. |
|
||||
| www.sankofa.nexus | web | https://www.sankofa.nexus | **301** to `https://sankofa.nexus` (canonical apex; NPM `advanced_config`). |
|
||||
| phoenix.sankofa.nexus | web | https://phoenix.sankofa.nexus | Phoenix API (7800); E2E uses `/health` for HTTPS check. |
|
||||
| www.phoenix.sankofa.nexus | web | https://www.phoenix.sankofa.nexus | **301** to `https://phoenix.sankofa.nexus` (canonical apex; NPM `advanced_config`). |
|
||||
| the-order.sankofa.nexus | web | https://the-order.sankofa.nexus | OSJ (Sovereign Military Order of Malta) management portal behind secure auth; app source repo **the_order** at `~/projects/the_order` (NPM upstream: order-haproxy 10210 when live, else interim portal 7801 per `update-npmplus-proxy-hosts-api.sh`). |
|
||||
| www.the-order.sankofa.nexus | web | https://www.the-order.sankofa.nexus | **301** to `https://the-order.sankofa.nexus` (canonical apex; NPM `advanced_config`). |
|
||||
| studio.sankofa.nexus | web | https://studio.sankofa.nexus | Sankofa Studio (FusionAI Creator) at VMID 7805. |
|
||||
@@ -168,6 +168,10 @@ When running from outside LAN or when backends are down, the following endpoints
|
||||
|
||||
**Verifier behavior (2026-03):** `openssl s_client` is wrapped with `timeout` (`E2E_OPENSSL_TIMEOUT` default 15s, `E2E_OPENSSL_X509_TIMEOUT` default 5s) so `--profile=private` / `--profile=all` cannot hang. **`--profile=all`** merges private and public `E2E_OPTIONAL_WHEN_FAIL` lists for temporary regressions. Install **`wscat`** (`npm install -g wscat`) for full WSS JSON-RPC checks; the script uses `wscat -n` to match `curl -k`, and now treats a clean `wscat` exit as a successful full WebSocket check even when the tool prints no JSON output.
|
||||
|
||||
**Canonical www redirects (2026-03):** For `www.sankofa.nexus`, `www.phoenix.sankofa.nexus`, and `www.the-order.sankofa.nexus`, HTTP **301**/**308** must include a **`Location`** whose host matches the expected apex (`E2E_WWW_CANONICAL_BASE` in `verify-end-to-end-routing.sh`). Wrong apex → HTTPS **fail**. Missing `Location` → **warn**.
|
||||
|
||||
**Cloudflare bulk DNS:** `scripts/update-all-dns-to-public-ip.sh` supports **`--dry-run`** (no API calls) and **`--zone-only=sankofa.nexus`** (or `d-bis.org` | `mim4u.org` | `defi-oracle.io`) to limit blast radius. Env: `CLOUDFLARE_DNS_DRY_RUN=1`, `DNS_ZONE_ONLY=…`.
|
||||
|
||||
**WebSocket test-format warnings:** Older runs may show "connection established but RPC test failed" when `wscat` is used: the upgrade succeeded but the verifier expected printable `"result"` output. The script now accepts either explicit JSON output or a clean `wscat` exit, so current runs treat those WS checks as pass when the connection completes successfully. The script also accepts Chain 138 chainId `0x8a` in output.
|
||||
|
||||
### Remediation (when you want these to pass from public)
|
||||
|
||||
@@ -361,7 +361,8 @@ update_proxy_host "keycloak.sankofa.nexus" "http://${IP_KEYCLOAK}:8080" false fa
|
||||
IP_ORDER_HAPROXY="${IP_ORDER_HAPROXY:-192.168.11.39}"
|
||||
THE_ORDER_UPSTREAM_IP="${THE_ORDER_UPSTREAM_IP:-${IP_SANKOFA_PORTAL}}"
|
||||
THE_ORDER_UPSTREAM_PORT="${THE_ORDER_UPSTREAM_PORT:-${SANKOFA_PORTAL_PORT}}"
|
||||
update_proxy_host "the-order.sankofa.nexus" "http://${THE_ORDER_UPSTREAM_IP}:${THE_ORDER_UPSTREAM_PORT}" false && updated_count=$((updated_count + 1)) || { add_proxy_host "the-order.sankofa.nexus" "${THE_ORDER_UPSTREAM_IP}" "${THE_ORDER_UPSTREAM_PORT}" false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
||||
# block_exploits false — same policy as sankofa.nexus portal (Next/API-friendly; avoid 405 on some POST paths)
|
||||
update_proxy_host "the-order.sankofa.nexus" "http://${THE_ORDER_UPSTREAM_IP}:${THE_ORDER_UPSTREAM_PORT}" false false && updated_count=$((updated_count + 1)) || { add_proxy_host "the-order.sankofa.nexus" "${THE_ORDER_UPSTREAM_IP}" "${THE_ORDER_UPSTREAM_PORT}" false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
||||
update_proxy_host "www.the-order.sankofa.nexus" "http://${THE_ORDER_UPSTREAM_IP}:${THE_ORDER_UPSTREAM_PORT}" false false "https://the-order.sankofa.nexus" && updated_count=$((updated_count + 1)) || { add_proxy_host "www.the-order.sankofa.nexus" "${THE_ORDER_UPSTREAM_IP}" "${THE_ORDER_UPSTREAM_PORT}" false false "https://the-order.sankofa.nexus" && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
||||
# Sankofa Studio (FusionAI) — VMID 7805; UI at /studio/ on same origin (port 8000). Prefer IP_SANKOFA_STUDIO from ip-addresses.conf / .env
|
||||
IP_SANKOFA_STUDIO="${IP_SANKOFA_STUDIO:-192.168.11.72}"
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
# Sets all records to DNS only mode (gray cloud) for direct NAT routing
|
||||
# Supports multiple zones: sankofa.nexus, d-bis.org, mim4u.org, defi-oracle.io
|
||||
# UDM Pro port forwarding: 76.53.10.36:80/443 → ${IP_NPMPLUS:-${IP_NPMPLUS:-192.168.11.167}}:80/443 (NPMplus)
|
||||
#
|
||||
# WARNING: For each hostname, existing CNAME records are deleted before an A record is created.
|
||||
# By default all configured zones are processed. Use --zone-only to limit scope.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/update-all-dns-to-public-ip.sh
|
||||
# ./scripts/update-all-dns-to-public-ip.sh --dry-run
|
||||
# ./scripts/update-all-dns-to-public-ip.sh --zone-only=sankofa.nexus
|
||||
# ./scripts/update-all-dns-to-public-ip.sh --dry-run --zone-only=d-bis.org
|
||||
# Env (optional): CLOUDFLARE_DNS_DRY_RUN=1, DNS_ZONE_ONLY=sankofa.nexus (same as flags)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -11,6 +21,22 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
||||
|
||||
# --help before .env (so operators can read usage without credentials)
|
||||
for _arg in "$@"; do
|
||||
if [[ "$_arg" == "--help" || "$_arg" == "-h" ]]; then
|
||||
cat <<'EOF'
|
||||
Cloudflare DNS → PUBLIC_IP (A records, DNS-only / gray cloud).
|
||||
|
||||
Options:
|
||||
--dry-run Log intended changes only; no Cloudflare API calls.
|
||||
--zone-only=ZONE ZONE one of: sankofa.nexus | d-bis.org | mim4u.org | defi-oracle.io
|
||||
-h, --help This message.
|
||||
|
||||
Requires repo .env with Cloudflare auth and zone IDs (see script header).
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
@@ -63,6 +89,23 @@ ZONE_D_BIS_ORG="${CLOUDFLARE_ZONE_ID_D_BIS_ORG:-${CLOUDFLARE_ZONE_ID:-}}"
|
||||
ZONE_MIM4U_ORG="${CLOUDFLARE_ZONE_ID_MIM4U_ORG:-}"
|
||||
ZONE_DEFI_ORACLE_IO="${CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO:-}"
|
||||
|
||||
# CLI / env: dry-run and single-zone scope
|
||||
CLOUDFLARE_DNS_DRY_RUN="${CLOUDFLARE_DNS_DRY_RUN:-0}"
|
||||
DNS_ZONE_ONLY="${DNS_ZONE_ONLY:-}"
|
||||
parse_dns_update_cli_args() {
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) CLOUDFLARE_DNS_DRY_RUN=1 ;;
|
||||
--zone-only=*) DNS_ZONE_ONLY="${arg#*=}" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
parse_dns_update_cli_args "$@"
|
||||
|
||||
if [ "$CLOUDFLARE_DNS_DRY_RUN" = "1" ]; then
|
||||
log_warn "DRY-RUN: no Cloudflare list/create/update/delete API calls will be made."
|
||||
fi
|
||||
|
||||
# Function to make Cloudflare API request
|
||||
cf_api_request() {
|
||||
local method="$1"
|
||||
@@ -152,6 +195,11 @@ create_or_update_dns_record() {
|
||||
fi
|
||||
|
||||
log_info "Processing: $full_name → $ip (proxied: $proxied)"
|
||||
|
||||
if [ "$CLOUDFLARE_DNS_DRY_RUN" = "1" ]; then
|
||||
log_success "[dry-run] Would remove CNAME(s) on $full_name if any, then upsert A → $ip (proxied=$proxied)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for existing CNAME records (must delete before creating A record)
|
||||
local all_records=$(get_all_dns_records "$zone_id" "$full_name")
|
||||
@@ -256,12 +304,29 @@ main() {
|
||||
echo ""
|
||||
log_info "Public IP: $PUBLIC_IP"
|
||||
log_info "Proxy Mode: DNS Only (gray cloud)"
|
||||
if [ -n "$DNS_ZONE_ONLY" ]; then
|
||||
log_info "Zone filter: only $DNS_ZONE_ONLY"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
local total_failures=0
|
||||
local run_sankofa=1 run_dbis=1 run_mim4u=1 run_defi=1
|
||||
if [ -n "$DNS_ZONE_ONLY" ]; then
|
||||
run_sankofa=0 run_dbis=0 run_mim4u=0 run_defi=0
|
||||
case "$DNS_ZONE_ONLY" in
|
||||
sankofa.nexus) run_sankofa=1 ;;
|
||||
d-bis.org) run_dbis=1 ;;
|
||||
mim4u.org) run_mim4u=1 ;;
|
||||
defi-oracle.io) run_defi=1 ;;
|
||||
*)
|
||||
log_error "Unknown --zone-only=$DNS_ZONE_ONLY (expected: sankofa.nexus | d-bis.org | mim4u.org | defi-oracle.io)"
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# sankofa.nexus domain records
|
||||
if [ -n "$ZONE_SANKOFA_NEXUS" ]; then
|
||||
if [ "$run_sankofa" = 1 ] && [ -n "$ZONE_SANKOFA_NEXUS" ]; then
|
||||
SANKOFA_RECORDS=(
|
||||
"@" # sankofa.nexus
|
||||
"www" # www.sankofa.nexus
|
||||
@@ -273,12 +338,12 @@ main() {
|
||||
if ! process_zone "$ZONE_SANKOFA_NEXUS" "sankofa.nexus" "${SANKOFA_RECORDS[@]}"; then
|
||||
((total_failures++))
|
||||
fi
|
||||
else
|
||||
elif [ "$run_sankofa" = 1 ]; then
|
||||
log_warn "Skipping sankofa.nexus (no zone ID configured)"
|
||||
fi
|
||||
|
||||
# d-bis.org domain records
|
||||
if [ -n "$ZONE_D_BIS_ORG" ]; then
|
||||
if [ "$run_dbis" = 1 ] && [ -n "$ZONE_D_BIS_ORG" ]; then
|
||||
DBIS_RECORDS=(
|
||||
"rpc-http-pub" # rpc-http-pub.d-bis.org
|
||||
"rpc-ws-pub" # rpc-ws-pub.d-bis.org
|
||||
@@ -297,12 +362,12 @@ main() {
|
||||
if ! process_zone "$ZONE_D_BIS_ORG" "d-bis.org" "${DBIS_RECORDS[@]}"; then
|
||||
((total_failures++))
|
||||
fi
|
||||
else
|
||||
elif [ "$run_dbis" = 1 ]; then
|
||||
log_warn "Skipping d-bis.org (no zone ID configured)"
|
||||
fi
|
||||
|
||||
# mim4u.org domain records
|
||||
if [ -n "$ZONE_MIM4U_ORG" ]; then
|
||||
if [ "$run_mim4u" = 1 ] && [ -n "$ZONE_MIM4U_ORG" ]; then
|
||||
MIM4U_RECORDS=(
|
||||
"@" # mim4u.org
|
||||
"www" # www.mim4u.org
|
||||
@@ -312,12 +377,12 @@ main() {
|
||||
if ! process_zone "$ZONE_MIM4U_ORG" "mim4u.org" "${MIM4U_RECORDS[@]}"; then
|
||||
((total_failures++))
|
||||
fi
|
||||
else
|
||||
elif [ "$run_mim4u" = 1 ]; then
|
||||
log_warn "Skipping mim4u.org (no zone ID configured)"
|
||||
fi
|
||||
|
||||
# defi-oracle.io domain records
|
||||
if [ -n "$ZONE_DEFI_ORACLE_IO" ]; then
|
||||
if [ "$run_defi" = 1 ] && [ -n "$ZONE_DEFI_ORACLE_IO" ]; then
|
||||
DEFI_ORACLE_RECORDS=(
|
||||
"explorer" # explorer.defi-oracle.io (Blockscout - same as explorer.d-bis.org)
|
||||
"rpc.public-0138" # rpc.public-0138.defi-oracle.io
|
||||
@@ -327,7 +392,7 @@ main() {
|
||||
if ! process_zone "$ZONE_DEFI_ORACLE_IO" "defi-oracle.io" "${DEFI_ORACLE_RECORDS[@]}"; then
|
||||
((total_failures++))
|
||||
fi
|
||||
else
|
||||
elif [ "$run_defi" = 1 ]; then
|
||||
log_warn "Skipping defi-oracle.io (no zone ID configured)"
|
||||
fi
|
||||
|
||||
@@ -354,5 +419,5 @@ main() {
|
||||
return $total_failures
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
# Run (CLI already parsed above)
|
||||
main
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Update Sankofa NPMplus proxy hosts (portal + Phoenix API) via API.
|
||||
# Prefer: scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh (domain-based, runs with operator waves).
|
||||
# NPM proxy host IDs below match backup backup-20260325_183932 (3–6); if your DB differs, use the main script instead.
|
||||
# Update Sankofa NPMplus proxy hosts (portal + Phoenix API + the-order) via API by numeric host ID.
|
||||
# Prefer for production: scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh (domain-based, full fleet).
|
||||
# NPM proxy host IDs below match backup backup-20260325_183932 (3–6, 7, 59); override with SANKOFA_NPM_ID_* if your DB differs.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
@@ -27,12 +27,16 @@ IP_SANKOFA_PORTAL="${IP_SANKOFA_PORTAL:-${IP_SERVICE_51:-192.168.11.51}}"
|
||||
IP_SANKOFA_PHOENIX_API="${IP_SANKOFA_PHOENIX_API:-${IP_SERVICE_50:-192.168.11.50}}"
|
||||
SANKOFA_PORTAL_PORT="${SANKOFA_PORTAL_PORT:-3000}"
|
||||
SANKOFA_PHOENIX_API_PORT="${SANKOFA_PHOENIX_API_PORT:-4000}"
|
||||
THE_ORDER_UPSTREAM_IP="${THE_ORDER_UPSTREAM_IP:-${IP_SANKOFA_PORTAL}}"
|
||||
THE_ORDER_UPSTREAM_PORT="${THE_ORDER_UPSTREAM_PORT:-${SANKOFA_PORTAL_PORT}}"
|
||||
|
||||
# NPM proxy host IDs: sankofa=3, www.sankofa=4, phoenix=5, www.phoenix=6 (typical fresh install order)
|
||||
# NPM proxy host IDs: sankofa=3, www.sankofa=4, phoenix=5, www.phoenix=6; the-order=7, www.the-order=59 (typical; verify in NPM UI)
|
||||
SANKOFA_NPM_ID_ROOT="${SANKOFA_NPM_ID_ROOT:-3}"
|
||||
SANKOFA_NPM_ID_WWW="${SANKOFA_NPM_ID_WWW:-4}"
|
||||
SANKOFA_NPM_ID_PHOENIX="${SANKOFA_NPM_ID_PHOENIX:-5}"
|
||||
SANKOFA_NPM_ID_WWW_PHOENIX="${SANKOFA_NPM_ID_WWW_PHOENIX:-6}"
|
||||
SANKOFA_NPM_ID_THE_ORDER="${SANKOFA_NPM_ID_THE_ORDER:-7}"
|
||||
SANKOFA_NPM_ID_WWW_THE_ORDER="${SANKOFA_NPM_ID_WWW_THE_ORDER:-59}"
|
||||
|
||||
# Optional 4th field: canonical HTTPS apex — NPM advanced_config 301 (www → apex). Matches update-npmplus-proxy-hosts-api.sh.
|
||||
declare -A PROXY_HOSTS=(
|
||||
@@ -40,6 +44,8 @@ declare -A PROXY_HOSTS=(
|
||||
["$SANKOFA_NPM_ID_WWW"]="www.sankofa.nexus|${IP_SANKOFA_PORTAL}|${SANKOFA_PORTAL_PORT}|https://sankofa.nexus"
|
||||
["$SANKOFA_NPM_ID_PHOENIX"]="phoenix.sankofa.nexus|${IP_SANKOFA_PHOENIX_API}|${SANKOFA_PHOENIX_API_PORT}|"
|
||||
["$SANKOFA_NPM_ID_WWW_PHOENIX"]="www.phoenix.sankofa.nexus|${IP_SANKOFA_PHOENIX_API}|${SANKOFA_PHOENIX_API_PORT}|https://phoenix.sankofa.nexus"
|
||||
["$SANKOFA_NPM_ID_THE_ORDER"]="the-order.sankofa.nexus|${THE_ORDER_UPSTREAM_IP}|${THE_ORDER_UPSTREAM_PORT}|"
|
||||
["$SANKOFA_NPM_ID_WWW_THE_ORDER"]="www.the-order.sankofa.nexus|${THE_ORDER_UPSTREAM_IP}|${THE_ORDER_UPSTREAM_PORT}|https://the-order.sankofa.nexus"
|
||||
)
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
@@ -193,6 +193,30 @@ declare -A E2E_HTTPS_PATH=(
|
||||
["studio.sankofa.nexus"]="/studio/"
|
||||
)
|
||||
|
||||
# Expected apex URL for NPM www → canonical 301/308 (Location must use this host; path from E2E_HTTPS_PATH must appear when set)
|
||||
declare -A E2E_WWW_CANONICAL_BASE=(
|
||||
["www.sankofa.nexus"]="https://sankofa.nexus"
|
||||
["www.phoenix.sankofa.nexus"]="https://phoenix.sankofa.nexus"
|
||||
["www.the-order.sankofa.nexus"]="https://the-order.sankofa.nexus"
|
||||
)
|
||||
|
||||
# Returns 0 if Location URL matches expected canonical apex (and HTTPS path suffix when non-empty).
|
||||
e2e_www_redirect_location_ok() {
|
||||
local loc_val="$1" base="$2" path="${3:-}"
|
||||
local loc_lc base_lc
|
||||
loc_lc=$(printf '%s' "$loc_val" | tr '[:upper:]' '[:lower:]')
|
||||
base_lc=$(printf '%s' "$base" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "$loc_lc" != "$base_lc" && "$loc_lc" != "$base_lc/"* ]]; then
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$path" ] && [ "$path" != "/" ]; then
|
||||
local p_lc
|
||||
p_lc=$(printf '%s' "$path" | tr '[:upper:]' '[:lower:]')
|
||||
[[ "$loc_lc" == *"$p_lc"* ]] || return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# --list-endpoints: print selected profile endpoints and exit (no tests)
|
||||
if [[ "$LIST_ENDPOINTS" == "1" ]]; then
|
||||
echo ""
|
||||
@@ -332,7 +356,8 @@ test_domain() {
|
||||
|
||||
if [ -n "$http_code" ]; then
|
||||
# NPM canonical www → apex (advanced_config return 301/308)
|
||||
_e2e_canonical_www_redirect=""
|
||||
local _e2e_canonical_www_redirect=""
|
||||
local location_hdr=""
|
||||
case "$domain" in
|
||||
www.sankofa.nexus|www.phoenix.sankofa.nexus|www.the-order.sankofa.nexus)
|
||||
if [ "$http_code" = "301" ] || [ "$http_code" = "308" ]; then
|
||||
@@ -342,9 +367,25 @@ test_domain() {
|
||||
esac
|
||||
if [ -n "$_e2e_canonical_www_redirect" ]; then
|
||||
location_hdr=$(echo "$headers" | grep -iE '^[Ll]ocation:' | head -1 | tr -d '\r' || echo "")
|
||||
log_success "HTTPS: $domain returned HTTP $http_code (canonical redirect)${https_path:+ at ${https_url}}"
|
||||
result=$(echo "$result" | jq --arg code "$http_code" --arg time "$time_total" --arg loc "$location_hdr" \
|
||||
'.tests.https = {"status": "pass", "http_code": ($code | tonumber), "response_time_seconds": ($time | tonumber), "canonical_redirect": true, "location_header": $loc}')
|
||||
loc_val=$(printf '%s' "$location_hdr" | sed -E 's/^[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:[[:space:]]*//' | sed 's/[[:space:]]*$//')
|
||||
expected_base="${E2E_WWW_CANONICAL_BASE[$domain]:-}"
|
||||
if [ -z "$loc_val" ]; then
|
||||
log_warn "HTTPS: $domain returned HTTP $http_code but no Location header${https_path:+ (${https_url})}"
|
||||
result=$(echo "$result" | jq --arg code "$http_code" --arg time "$time_total" \
|
||||
'.tests.https = {"status": "warn", "http_code": ($code | tonumber), "response_time_seconds": ($time | tonumber), "note": "missing Location on redirect"}')
|
||||
elif [ -z "$expected_base" ]; then
|
||||
log_warn "HTTPS: $domain redirect pass (no E2E_WWW_CANONICAL_BASE entry)"
|
||||
result=$(echo "$result" | jq --arg code "$http_code" --arg time "$time_total" --arg loc "$location_hdr" \
|
||||
'.tests.https = {"status": "pass", "http_code": ($code | tonumber), "response_time_seconds": ($time | tonumber), "canonical_redirect": true, "location_header": $loc}')
|
||||
elif ! e2e_www_redirect_location_ok "$loc_val" "$expected_base" "$https_path"; then
|
||||
log_error "HTTPS: $domain Location mismatch (got \"$loc_val\", expected prefix \"$expected_base\" with path \"${https_path:-/}\")"
|
||||
result=$(echo "$result" | jq --arg code "$http_code" --arg time "$time_total" --arg loc "$loc_val" --arg exp "$expected_base" --arg pth "${https_path:-}" \
|
||||
'.tests.https = {"status": "fail", "http_code": ($code | tonumber), "response_time_seconds": ($time | tonumber), "reason": "location_mismatch", "location": $loc, "expected_prefix": $exp, "expected_path_suffix": $pth}')
|
||||
else
|
||||
log_success "HTTPS: $domain returned HTTP $http_code (canonical redirect → $loc_val)${https_path:+ at ${https_url}}"
|
||||
result=$(echo "$result" | jq --arg code "$http_code" --arg time "$time_total" --arg loc "$location_hdr" \
|
||||
'.tests.https = {"status": "pass", "http_code": ($code | tonumber), "response_time_seconds": ($time | tonumber), "canonical_redirect": true, "location_header": $loc}')
|
||||
fi
|
||||
elif [ "$http_code" -ge 200 ] && [ "$http_code" -lt 400 ]; then
|
||||
log_success "HTTPS: $domain returned HTTP $http_code (Time: ${time_total}s)${https_path:+ at ${https_path}}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user