docs: add ura operational readiness and production gates
This commit is contained in:
@@ -20,7 +20,8 @@ const schemaPath = path.join(
|
||||
'config/universal-resource-activation/integration/omnl-ledger-mapping.v1.schema.json'
|
||||
);
|
||||
|
||||
const file = path.resolve(projectRoot, process.argv[2] || defaultPath);
|
||||
const fileArg = process.argv.slice(2).filter((a) => a !== '--')[0];
|
||||
const file = path.resolve(projectRoot, fileArg || defaultPath);
|
||||
|
||||
if (!existsSync(file)) {
|
||||
console.error(`[validate-ledger-mapping] Missing ${file}`);
|
||||
|
||||
63
scripts/verify/ura-ops-readiness.sh
Executable file
63
scripts/verify/ura-ops-readiness.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# URA — repo-level readiness: manifest, profiles, mapping schema, merge, non-strict closure, optional forge test.
|
||||
# Does not substitute staging/prod E2E or live Fineract/sidecar (see URA_OPERATIONAL_READINESS_CHECKLIST.md).
|
||||
#
|
||||
# Usage (repo root):
|
||||
# bash scripts/verify/ura-ops-readiness.sh
|
||||
# URA_READINESS_MAP=config/universal-resource-activation/integration/omnl-ledger-mapping.v1.json \
|
||||
# bash scripts/verify/ura-ops-readiness.sh
|
||||
# URA_READINESS_FORGE=1 bash scripts/verify/ura-ops-readiness.sh # also runs PolicyProfileRegistry unit test in smom-dbis-138
|
||||
# URA_READINESS_CONFIG=1 bash scripts/verify/ura-ops-readiness.sh # also runs validate-config-files.sh
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
log() { echo "[ura-ops-readiness] $*"; }
|
||||
log_err() { echo "[ura-ops-readiness] ERROR: $*" >&2; }
|
||||
|
||||
if ! command -v pnpm &>/dev/null; then
|
||||
log_err "pnpm not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "1/7 pnpm ura:validate"
|
||||
pnpm ura:validate
|
||||
log "2/7 pnpm ura:validate-profiles"
|
||||
pnpm ura:validate-profiles
|
||||
MAP_FILE="${URA_READINESS_MAP:-$ROOT/config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json}"
|
||||
if [[ -f "$MAP_FILE" ]]; then
|
||||
log "3/7 validate-omnl-ledger-mapping.mjs $MAP_FILE"
|
||||
node "$ROOT/scripts/validate/validate-omnl-ledger-mapping.mjs" "$MAP_FILE"
|
||||
else
|
||||
log "3/7 skip (mapping file not found: $MAP_FILE)"
|
||||
fi
|
||||
log "4/7 pnpm ura:validate-closure (warn mode)"
|
||||
pnpm ura:validate-closure || true
|
||||
log "5/7 pnpm ura:merge-manifest"
|
||||
pnpm ura:merge-manifest
|
||||
|
||||
if [[ "${URA_READINESS_FORGE:-}" == "1" ]]; then
|
||||
if [[ -d "$ROOT/smom-dbis-138" && -f "$ROOT/smom-dbis-138/scripts/forge/scope.sh" ]]; then
|
||||
log "6/7 FORGE_SCOPE=universal-resource forge test (PolicyProfileRegistry)"
|
||||
(cd "$ROOT/smom-dbis-138" && FORGE_SCOPE=universal-resource bash scripts/forge/scope.sh test --match-contract PolicyProfileRegistryTest) || {
|
||||
log_err "Forge test failed"
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
log "6/7 skip (smom-dbis-138 or scope.sh not present)"
|
||||
fi
|
||||
else
|
||||
log "6/7 skip forge (set URA_READINESS_FORGE=1 to run PolicyProfileRegistryTest)"
|
||||
fi
|
||||
|
||||
if [[ "${URA_READINESS_CONFIG:-}" == "1" ]]; then
|
||||
log "7/7 validate-config-files.sh"
|
||||
bash "$ROOT/scripts/validation/validate-config-files.sh"
|
||||
else
|
||||
log "7/7 skip validate-config-files (set URA_READINESS_CONFIG=1 for full project config gate)"
|
||||
fi
|
||||
|
||||
log "OK: repo URA gates passed (see docs/.../URA_OPERATIONAL_READINESS_CHECKLIST.md for runtime steps)."
|
||||
exit 0
|
||||
148
scripts/verify/ura-production-readiness.sh
Executable file
148
scripts/verify/ura-production-readiness.sh
Executable file
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env bash
|
||||
# URA production readiness verifier.
|
||||
# Enforces strict manifest closure and live endpoint checks.
|
||||
#
|
||||
# Modes (URA_PRODUCTION_MODE):
|
||||
# strict — default: repo gates + strict closure + HTTP smoke + sidecar 200. Use after URA_PILOT_CLOSURE_RUNBOOK.
|
||||
# connectivity — repo gates + HTTP + sidecar 200; skips strict closure (staging / pilot manifest still open).
|
||||
#
|
||||
# Optional env file:
|
||||
# URA_PRODUCTION_ENV_FILE — path to a file with export KEY=value lines; sourced before checks.
|
||||
#
|
||||
# Required:
|
||||
# - pnpm, curl, jq
|
||||
# - PHOENIX_BASE_URL
|
||||
# - SERVER_FUNDS_SIDECAR_URL
|
||||
# - POLICY_PROFILE_REGISTRY_ADDRESS
|
||||
#
|
||||
# Optional:
|
||||
# - GRU_REQUIRED=1 + GRU_M00_DIAMOND_ADDRESS (if GRU M00 is in scope)
|
||||
# - REQUIRE_CUSTODY=1 + CUSTODY_E2E_EVIDENCE_FILE (if custody lane is in scope)
|
||||
# - LEDGER_E2E_EVIDENCE_FILE / SETTLEMENT_E2E_EVIDENCE_FILE / COUNSEL_SIGNOFF_FILE
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
if [[ -n "${URA_PRODUCTION_ENV_FILE:-}" && -f "${URA_PRODUCTION_ENV_FILE}" ]]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "${URA_PRODUCTION_ENV_FILE}"
|
||||
set +a
|
||||
fi
|
||||
|
||||
log() { echo "[ura-prod-ready] $*"; }
|
||||
log_err() { echo "[ura-prod-ready] ERROR: $*" >&2; }
|
||||
|
||||
require_cmd() {
|
||||
if ! command -v "$1" &>/dev/null; then
|
||||
log_err "Missing command: $1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local key="$1"
|
||||
if [[ -z "${!key:-}" ]]; then
|
||||
log_err "Missing required env var: $key"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_file() {
|
||||
local p="$1"
|
||||
if [[ -z "$p" || ! -f "$p" ]]; then
|
||||
log_err "Missing required evidence file: $p"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_address() {
|
||||
local label="$1"
|
||||
local value="$2"
|
||||
if [[ ! "$value" =~ ^0x[a-fA-F0-9]{40}$ ]]; then
|
||||
log_err "$label must be a 20-byte hex EVM address, got: $value"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_cmd pnpm
|
||||
require_cmd curl
|
||||
require_cmd jq
|
||||
|
||||
require_env PHOENIX_BASE_URL
|
||||
require_env SERVER_FUNDS_SIDECAR_URL
|
||||
require_env POLICY_PROFILE_REGISTRY_ADDRESS
|
||||
validate_address "POLICY_PROFILE_REGISTRY_ADDRESS" "$POLICY_PROFILE_REGISTRY_ADDRESS"
|
||||
|
||||
if [[ "${GRU_REQUIRED:-0}" == "1" ]]; then
|
||||
require_env GRU_M00_DIAMOND_ADDRESS
|
||||
validate_address "GRU_M00_DIAMOND_ADDRESS" "$GRU_M00_DIAMOND_ADDRESS"
|
||||
fi
|
||||
|
||||
if [[ -n "${LEDGER_E2E_EVIDENCE_FILE:-}" ]]; then
|
||||
require_file "$LEDGER_E2E_EVIDENCE_FILE"
|
||||
fi
|
||||
if [[ -n "${SETTLEMENT_E2E_EVIDENCE_FILE:-}" ]]; then
|
||||
require_file "$SETTLEMENT_E2E_EVIDENCE_FILE"
|
||||
fi
|
||||
if [[ "${REQUIRE_CUSTODY:-0}" == "1" ]]; then
|
||||
require_env CUSTODY_E2E_EVIDENCE_FILE
|
||||
require_file "$CUSTODY_E2E_EVIDENCE_FILE"
|
||||
fi
|
||||
if [[ -n "${COUNSEL_SIGNOFF_FILE:-}" ]]; then
|
||||
require_file "$COUNSEL_SIGNOFF_FILE"
|
||||
fi
|
||||
|
||||
BASE="${PHOENIX_BASE_URL%/}"
|
||||
MODE="${URA_PRODUCTION_MODE:-strict}"
|
||||
if [[ "$MODE" != "strict" && "$MODE" != "connectivity" ]]; then
|
||||
log_err "URA_PRODUCTION_MODE must be 'strict' or 'connectivity', got: $MODE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$MODE" == "connectivity" ]]; then
|
||||
log "Mode: connectivity (strict manifest closure is skipped — not a full production sign-off)"
|
||||
else
|
||||
log "Mode: strict (manifest must pass ura:validate-closure:strict; close pilots per URA_PILOT_CLOSURE_RUNBOOK first)"
|
||||
fi
|
||||
|
||||
log "1/? Running full repo gates"
|
||||
pnpm ura:ops-readiness:full
|
||||
|
||||
if [[ "$MODE" == "strict" ]]; then
|
||||
log "2/? Enforcing strict closure (no placeholders/TBD/open reconciliation)"
|
||||
pnpm ura:validate-closure:strict
|
||||
else
|
||||
log "2/? Skipping strict closure (use URA_PRODUCTION_MODE=strict for production go-live)"
|
||||
pnpm ura:validate-closure || true
|
||||
fi
|
||||
|
||||
log "3/? Phoenix smoke over HTTP (PHOENIX_BASE_URL=$BASE)"
|
||||
PHOENIX_BASE_URL="$BASE" pnpm ura:smoke --http
|
||||
|
||||
log "4/? Requiring sidecar probe HTTP 200"
|
||||
probe_url="${BASE}/api/v1/universal-resource-activation/server-funds-sidecar-probe"
|
||||
probe_body="$(mktemp)"
|
||||
trap 'rm -f "$probe_body"' EXIT
|
||||
probe_code="$(curl -sS -o "$probe_body" -w '%{http_code}' --connect-timeout 5 --max-time 20 "$probe_url" || true)"
|
||||
if [[ "$probe_code" != "200" ]]; then
|
||||
log_err "Expected sidecar probe HTTP 200 at $probe_url, got $probe_code"
|
||||
if [[ -s "$probe_body" ]]; then
|
||||
log_err "Probe body: $(head -c 500 "$probe_body")"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
if ! jq -e 'type == "object"' "$probe_body" &>/dev/null; then
|
||||
log_err "Probe response is not a JSON object"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "5/? URA $MODE gate PASSED"
|
||||
log "Registry: $POLICY_PROFILE_REGISTRY_ADDRESS"
|
||||
if [[ -n "${GRU_M00_DIAMOND_ADDRESS:-}" ]]; then
|
||||
log "GRU diamond: $GRU_M00_DIAMOND_ADDRESS"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user