- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON - Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path) - Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README - Meta docs, integration gaps, live verification log, architecture updates - CI validate-config workflow updates Operator/LAN items, submodule working trees, and public token-aggregation edge routes remain follow-up (see TODOS_CONSOLIDATED P1). Made-with: Cursor
611 lines
31 KiB
Bash
Executable File
611 lines
31 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Build complete E2E archive: Audit Proof + Settlement + Closure cluster (OMNL Fineract + Chain 138).
|
||
#
|
||
# Stages:
|
||
# - Canonical settlement events (output/settlement-events/*.json)
|
||
# - settlement-event schema + min example (validation target)
|
||
# - OMNL runbooks and RTGS cross-link doc
|
||
# - Scripts: M1 clearing, 102B chunked, chain attestation
|
||
# - AUDIT_PROOF.json, SETTLEMENT_CLOSURE.json, README_E2E_ARCHIVE.txt
|
||
# - Optional live Fineract evidence (offices 1, 21, 22) and cast receipt for attestation tx
|
||
#
|
||
# Env:
|
||
# FETCH_LIVE_EVIDENCE=1 — pull /journalentries + /offices + /glaccounts (needs omnl-fineract/.env)
|
||
# CHAIN_ATTESTATION_TX_HASH — default 102B closure attestation on Chain 138 (override if different)
|
||
# CHAIN_ATTESTATION_TX_HASH_MAINNET — optional Ethereum mainnet 0-value attestation tx (dual-anchor)
|
||
# ETHEREUM_MAINNET_RPC / RPC_URL_MAINNET — for mainnet cast receipt; if unset, mainnet receipt skipped
|
||
# Auto: if output/jvmtm-evidence/latest-dual-attestation.json exists (from omnl-chain138-attestation-tx.sh),
|
||
# CHAIN_ATTESTATION_TX_HASH_MAINNET is read from chainId 1 when env not set.
|
||
# RPC_URL_138 — for cast receipt (default LAN Core RPC)
|
||
# KEEP_STAGE=1 — keep staging dir after zip
|
||
# JVMTM_CLOSURE_DIR — optional dir with live regulatory closure JSON/txt (see config/jvmtm-regulatory-closure/README.md).
|
||
# If unset, stages repo examples (placeholders) into reconciliation/, liquidity/, acknowledgements/, etc.
|
||
# If JVMTM_CLOSURE_DIR/transactions/*.json exists, stages live transaction execution envelopes into transactions/.
|
||
# Stages config/reserve-provenance-package/ (3FR reserve attestation JSON) when present.
|
||
#
|
||
# Output: output/omnl-e2e-settlement-audit-<UTC>.zip
|
||
#
|
||
# Usage:
|
||
# bash scripts/omnl/build-omnl-e2e-settlement-audit-archive.sh
|
||
# FETCH_LIVE_EVIDENCE=1 bash scripts/omnl/build-omnl-e2e-settlement-audit-archive.sh
|
||
#
|
||
set -euo pipefail
|
||
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
||
OUT_BASE="${OUT_BASE:-${REPO_ROOT}/output}"
|
||
FETCH_LIVE_EVIDENCE="${FETCH_LIVE_EVIDENCE:-0}"
|
||
JVMTM_CLOSURE_DIR="${JVMTM_CLOSURE_DIR:-}"
|
||
STAMP_UTC="${STAMP_UTC:-$(date -u +%Y%m%dT%H%M%SZ)}"
|
||
ARCHIVE_BASENAME="omnl-e2e-settlement-audit-${STAMP_UTC}"
|
||
STAGE="${OUT_BASE}/${ARCHIVE_BASENAME}"
|
||
ZIP_PATH="${OUT_BASE}/${ARCHIVE_BASENAME}.zip"
|
||
CHAIN_ATTESTATION_TX_HASH="${CHAIN_ATTESTATION_TX_HASH:-0xb90f2da51d9c506f552d276d9aa57f4ae485528f2ee6025f435f188d09d405f4}"
|
||
RPC_URL_138="${RPC_URL_138:-http://192.168.11.211:8545}"
|
||
|
||
if [ -f "${REPO_ROOT}/smom-dbis-138/.env" ]; then
|
||
set +u
|
||
set -a
|
||
# shellcheck disable=SC1090
|
||
source "${REPO_ROOT}/smom-dbis-138/.env" 2>/dev/null || true
|
||
set +a
|
||
set -u
|
||
fi
|
||
if [ -f "${REPO_ROOT}/.env" ]; then
|
||
set +u
|
||
set -a
|
||
# shellcheck disable=SC1090
|
||
source "${REPO_ROOT}/.env" 2>/dev/null || true
|
||
set +a
|
||
set -u
|
||
fi
|
||
ETHEREUM_MAINNET_RPC="${ETHEREUM_MAINNET_RPC:-${RPC_URL_MAINNET:-}}"
|
||
CHAIN_ATTESTATION_TX_HASH_MAINNET="${CHAIN_ATTESTATION_TX_HASH_MAINNET:-}"
|
||
DUAL_ATTEST_JSON="${REPO_ROOT}/output/jvmtm-evidence/latest-dual-attestation.json"
|
||
if [ -z "$CHAIN_ATTESTATION_TX_HASH_MAINNET" ] && [ -f "$DUAL_ATTEST_JSON" ] && command -v jq &>/dev/null; then
|
||
CHAIN_ATTESTATION_TX_HASH_MAINNET="$(jq -r '[.attestations[]? | select(.chainId == 1)] | first | .transactionHash // empty' "$DUAL_ATTEST_JSON")"
|
||
fi
|
||
|
||
mkdir -p "$STAGE"/{settlement-events,schemas,schemas/jvmtm,examples,docs,scripts,evidence,audit-proof,reconciliation,liquidity,acknowledgements,exceptions,validation,bcp,disaster-recovery,monitoring,transactions,config/jvmtm-regulatory-closure,config/jvmtm-regulatory-closure/examples}
|
||
|
||
copy_if_exists() {
|
||
local dest_dir="$1"
|
||
local src="$2"
|
||
local full="${REPO_ROOT}/${src}"
|
||
if [ -f "$full" ]; then
|
||
cp -a "$full" "${STAGE}/${dest_dir}/"
|
||
else
|
||
echo "WARN: missing (skip): $src" >&2
|
||
fi
|
||
}
|
||
|
||
# JVMTM / regulatory closure: live dir overrides repo examples (basename match).
|
||
jvmtm_stage() {
|
||
local basename="$1"
|
||
local dest_subdir="$2"
|
||
local example_path="$3"
|
||
local dest="${STAGE}/${dest_subdir}/${basename}"
|
||
if [ -n "$JVMTM_CLOSURE_DIR" ] && [ -f "${JVMTM_CLOSURE_DIR}/${basename}" ]; then
|
||
cp -a "${JVMTM_CLOSURE_DIR}/${basename}" "$dest"
|
||
echo "JVMTM: staged live ${basename} -> ${dest_subdir}/" >&2
|
||
else
|
||
cp -a "${REPO_ROOT}/${example_path}" "$dest"
|
||
echo "JVMTM: staged template ${basename} -> ${dest_subdir}/ (set JVMTM_CLOSURE_DIR for live)" >&2
|
||
fi
|
||
}
|
||
|
||
# Settlement artefacts (repo-generated)
|
||
for f in omnl-102b-ledger-and-chain-20260331.json omnl-102b-notional-status-20260331.json omnl-m1-kanaya-cakra-20260331.json; do
|
||
copy_if_exists "settlement-events" "output/settlement-events/$f"
|
||
done
|
||
|
||
copy_if_exists "schemas" "config/dbis-institutional/schemas/settlement-event.schema.json"
|
||
copy_if_exists "examples" "config/dbis-institutional/examples/settlement-event.example.json"
|
||
copy_if_exists "examples" "config/dbis-institutional/examples/settlement-event.chain138-primary.example.json"
|
||
copy_if_exists "examples" "config/dbis-institutional/examples/settlement-event.min.json"
|
||
|
||
# JVMTM regulatory closure artefacts (Tables B/C/D style evidence)
|
||
jvmtm_stage "daily-3way-reconciliation-report.json" "reconciliation" "config/jvmtm-regulatory-closure/examples/daily-3way-reconciliation-report.example.json"
|
||
jvmtm_stage "prefunding-proof.json" "liquidity" "config/jvmtm-regulatory-closure/examples/prefunding-proof.example.json"
|
||
jvmtm_stage "pre-settlement-ack.json" "acknowledgements" "config/jvmtm-regulatory-closure/examples/pre-settlement-ack.example.json"
|
||
jvmtm_stage "sample-exception-event.json" "exceptions" "config/jvmtm-regulatory-closure/examples/sample-exception-event.example.json"
|
||
jvmtm_stage "kyt-screening-result.json" "validation" "config/jvmtm-regulatory-closure/examples/kyt-screening-result.example.json"
|
||
jvmtm_stage "recovery-time-report.json" "bcp" "config/jvmtm-regulatory-closure/examples/recovery-time-report.example.json"
|
||
jvmtm_stage "failover-test-log.txt" "bcp" "config/jvmtm-regulatory-closure/examples/failover-test-log.example.txt"
|
||
jvmtm_stage "DR-simulation-report.json" "disaster-recovery" "config/jvmtm-regulatory-closure/examples/dr-simulation-report.example.json"
|
||
jvmtm_stage "real-time-balance-snapshot.json" "monitoring" "config/jvmtm-regulatory-closure/examples/real-time-balance-snapshot.example.json"
|
||
|
||
if [ -n "$JVMTM_CLOSURE_DIR" ] && [ -d "${JVMTM_CLOSURE_DIR}/transactions" ]; then
|
||
shopt -s nullglob
|
||
tx_files=("${JVMTM_CLOSURE_DIR}/transactions/"*.json)
|
||
if [ "${#tx_files[@]}" -gt 0 ]; then
|
||
cp -a "${tx_files[@]}" "${STAGE}/transactions/"
|
||
echo "JVMTM: staged ${#tx_files[@]} live transaction envelope(s) -> transactions/" >&2
|
||
fi
|
||
shopt -u nullglob
|
||
fi
|
||
|
||
if [ -n "$JVMTM_CLOSURE_DIR" ] && [ -f "${JVMTM_CLOSURE_DIR}/exception-policy.md" ]; then
|
||
cp -a "${JVMTM_CLOSURE_DIR}/exception-policy.md" "${STAGE}/exceptions/exception-policy.md"
|
||
else
|
||
cp -a "${REPO_ROOT}/config/jvmtm-regulatory-closure/policies/exception-policy.md" "${STAGE}/exceptions/exception-policy.md"
|
||
fi
|
||
if [ -n "$JVMTM_CLOSURE_DIR" ] && [ -f "${JVMTM_CLOSURE_DIR}/retry-log.txt" ]; then
|
||
cp -a "${JVMTM_CLOSURE_DIR}/retry-log.txt" "${STAGE}/exceptions/retry-log.txt"
|
||
else
|
||
printf '%s\n' "retry-log (template) — append exception_id, timestamp, action per resolution; JVMTM closure" > "${STAGE}/exceptions/retry-log.txt"
|
||
fi
|
||
|
||
for js in "$REPO_ROOT"/config/jvmtm-regulatory-closure/schemas/*.schema.json; do
|
||
[ -f "$js" ] || continue
|
||
cp -a "$js" "${STAGE}/schemas/jvmtm/"
|
||
done
|
||
for pack_file in \
|
||
README.md \
|
||
OPERATIONAL_EVIDENCE_VS_TEMPLATES.md \
|
||
INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md \
|
||
JVMTM_TRANSACTION_GRADE_COMPLIANCE_MATRIX.md \
|
||
transaction-compliance-matrix.json \
|
||
transaction-compliance-matrix.csv
|
||
do
|
||
if [ -f "${REPO_ROOT}/config/jvmtm-regulatory-closure/${pack_file}" ]; then
|
||
cp -a "${REPO_ROOT}/config/jvmtm-regulatory-closure/${pack_file}" "${STAGE}/config/jvmtm-regulatory-closure/"
|
||
fi
|
||
done
|
||
if [ -f "${REPO_ROOT}/config/jvmtm-regulatory-closure/INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md" ]; then
|
||
echo "Included config/jvmtm-regulatory-closure/INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md (Tables B/C/D closure mapping)" >&2
|
||
fi
|
||
for pack_example in \
|
||
transaction-compliance-execution.example.json \
|
||
transaction-compliance-execution.blocked.example.json
|
||
do
|
||
if [ -f "${REPO_ROOT}/config/jvmtm-regulatory-closure/examples/${pack_example}" ]; then
|
||
cp -a "${REPO_ROOT}/config/jvmtm-regulatory-closure/examples/${pack_example}" "${STAGE}/config/jvmtm-regulatory-closure/examples/"
|
||
fi
|
||
done
|
||
|
||
# Machine-generated 3-way result (run generate-3way-reconciliation-evidence.sh before archiving)
|
||
if [ -f "${REPO_ROOT}/output/jvmtm-evidence/latest-3way-result.json" ]; then
|
||
cp -a "${REPO_ROOT}/output/jvmtm-evidence/latest-3way-result.json" "${STAGE}/reconciliation/3way-result.json"
|
||
echo "Included reconciliation/3way-result.json from output/jvmtm-evidence/latest-3way-result.json" >&2
|
||
fi
|
||
|
||
# Reserve provenance + funding attestation (3FR narrative; staged bank/KYT pending)
|
||
if [ -d "${REPO_ROOT}/config/reserve-provenance-package" ]; then
|
||
cp -a "${REPO_ROOT}/config/reserve-provenance-package" "${STAGE}/"
|
||
echo "Included reserve-provenance-package/ (legal, settlement, provenance, bank, kyt, reconciliation, reserve, governance)" >&2
|
||
fi
|
||
|
||
declare -a DOCS=(
|
||
"docs/04-configuration/mifos-omnl-central-bank/OMNL_M1_INTEROFFICE_OFFICE_TO_OFFICE_CLEARING_RUNBOOK.md"
|
||
"docs/04-configuration/mifos-omnl-central-bank/OMNL_IPSAS_IFRS_INTEROFFICE_COMPLIANCE.md"
|
||
"docs/04-configuration/mifos-omnl-central-bank/OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md"
|
||
"docs/03-deployment/OMNL_DBIS_CORE_CHAIN138_SMART_VAULT_RTGS_RUNBOOK.md"
|
||
"docs/03-deployment/OJK_BI_AUDIT_JVMTM_REMEDIATION_AND_UETR_POLICY.md"
|
||
"config/dbis-institutional/README.md"
|
||
)
|
||
|
||
for d in "${DOCS[@]}"; do
|
||
if [ -f "${REPO_ROOT}/$d" ]; then
|
||
mkdir -p "${STAGE}/$(dirname "$d")"
|
||
cp -a "${REPO_ROOT}/$d" "${STAGE}/$d"
|
||
fi
|
||
done
|
||
|
||
declare -a SCRIPTS=(
|
||
"scripts/omnl/omnl-m1-clearing-transfer-between-offices.sh"
|
||
"scripts/omnl/omnl-m1-clearing-102b-chunked.sh"
|
||
"scripts/omnl/omnl-chain138-attestation-tx.sh"
|
||
"scripts/omnl/build-omnl-e2e-settlement-audit-archive.sh"
|
||
"scripts/validation/validate-dbis-institutional-schemas.sh"
|
||
"scripts/validation/validate-jvmtm-regulatory-closure-schemas.sh"
|
||
"scripts/validation/validate-jvmtm-transaction-compliance-pack.py"
|
||
"scripts/jvmtm/export-transaction-compliance-matrix-csv.py"
|
||
"scripts/omnl/generate-3way-reconciliation-evidence.sh"
|
||
"scripts/omnl/verify-ack-before-credit.sh"
|
||
"scripts/omnl/fetch-kyt-vendor-report.sh"
|
||
"scripts/omnl/bcp-rpc-failover-smoke.sh"
|
||
"scripts/validation/validate-reserve-provenance-package.sh"
|
||
)
|
||
|
||
for s in "${SCRIPTS[@]}"; do
|
||
if [ -f "${REPO_ROOT}/$s" ]; then
|
||
mkdir -p "${STAGE}/$(dirname "$s")"
|
||
cp -a "${REPO_ROOT}/$s" "${STAGE}/$s"
|
||
chmod a+x "${STAGE}/$s" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# Chain receipts (best-effort): Chain 138 + optional Ethereum mainnet
|
||
if command -v cast &>/dev/null && [ -n "$CHAIN_ATTESTATION_TX_HASH" ]; then
|
||
if cast receipt "$CHAIN_ATTESTATION_TX_HASH" --rpc-url "$RPC_URL_138" &>"${STAGE}/evidence/chain138-attestation-receipt.txt"; then
|
||
echo "Wrote evidence/chain138-attestation-receipt.txt" >&2
|
||
else
|
||
echo "WARN: cast receipt failed; wrote empty or partial file" >&2
|
||
fi
|
||
else
|
||
echo "cast not found or hash empty; skip Chain 138 on-chain receipt" >&2
|
||
echo "CHAIN_ATTESTATION_TX_HASH=${CHAIN_ATTESTATION_TX_HASH:-}" > "${STAGE}/evidence/chain138-attestation-placeholder.txt"
|
||
fi
|
||
|
||
if command -v cast &>/dev/null && [ -n "${CHAIN_ATTESTATION_TX_HASH_MAINNET:-}" ] && [ -n "$ETHEREUM_MAINNET_RPC" ]; then
|
||
if cast receipt "$CHAIN_ATTESTATION_TX_HASH_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" &>"${STAGE}/evidence/mainnet-attestation-receipt.txt"; then
|
||
echo "Wrote evidence/mainnet-attestation-receipt.txt" >&2
|
||
else
|
||
echo "WARN: mainnet cast receipt failed; check ETHEREUM_MAINNET_RPC and CHAIN_ATTESTATION_TX_HASH_MAINNET" >&2
|
||
fi
|
||
elif [ -n "${CHAIN_ATTESTATION_TX_HASH_MAINNET:-}" ] && [ -z "$ETHEREUM_MAINNET_RPC" ]; then
|
||
echo "CHAIN_ATTESTATION_TX_HASH_MAINNET=${CHAIN_ATTESTATION_TX_HASH_MAINNET}" > "${STAGE}/evidence/mainnet-attestation-placeholder.txt"
|
||
echo "WARN: mainnet tx hash set but ETHEREUM_MAINNET_RPC unset; wrote mainnet-attestation-placeholder.txt" >&2
|
||
fi
|
||
|
||
# Live Fineract pulls
|
||
if [ "$FETCH_LIVE_EVIDENCE" = "1" ]; then
|
||
if [ -f "${REPO_ROOT}/omnl-fineract/.env" ]; then
|
||
set +u
|
||
# shellcheck disable=SC1090
|
||
source "${REPO_ROOT}/omnl-fineract/.env" 2>/dev/null || true
|
||
set +u
|
||
elif [ -f "${REPO_ROOT}/.env" ]; then
|
||
set +u
|
||
# shellcheck disable=SC1090
|
||
source "${REPO_ROOT}/.env" 2>/dev/null || true
|
||
set +u
|
||
fi
|
||
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
|
||
if [ -n "$BASE_URL" ] && [ -n "${OMNL_FINERACT_PASSWORD:-}" ]; then
|
||
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
|
||
CURL=(curl -sS -H "Fineract-Platform-TenantId: ${TENANT}" -u "${OMNL_FINERACT_USER:-app.omnl}:${OMNL_FINERACT_PASSWORD}")
|
||
for oid in 1 21 22; do
|
||
offset=0
|
||
limit=500
|
||
merge="${STAGE}/evidence/._je_batches_${oid}.ndjson"
|
||
: > "$merge"
|
||
while true; do
|
||
resp=$("${CURL[@]}" "${BASE_URL}/journalentries?officeId=${oid}&offset=${offset}&limit=${limit}")
|
||
echo "$resp" | jq -c '.pageItems // []' >> "$merge"
|
||
n=$(echo "$resp" | jq '.pageItems | length')
|
||
total=$(echo "$resp" | jq -r '.totalFilteredRecords // 0')
|
||
offset=$((offset + n))
|
||
if [ "$n" -lt "$limit" ] || [ "$offset" -ge "$total" ]; then
|
||
break
|
||
fi
|
||
done
|
||
jq -s 'map(.[]) | { officeId: '"$oid"', totalLines: length, pageItems: . }' "$merge" > "${STAGE}/evidence/journalentries-office${oid}-all.json"
|
||
rm -f "$merge"
|
||
done
|
||
"${CURL[@]}" "${BASE_URL}/offices" > "${STAGE}/evidence/offices.json" || true
|
||
"${CURL[@]}" "${BASE_URL}/glaccounts" > "${STAGE}/evidence/glaccounts.json" || true
|
||
echo "Live Fineract evidence written." >&2
|
||
else
|
||
echo "WARN: FETCH_LIVE_EVIDENCE=1 but OMNL credentials missing." >&2
|
||
fi
|
||
fi
|
||
|
||
GIT_COMMIT=$(git -C "$REPO_ROOT" rev-parse HEAD 2>/dev/null || echo "n/a")
|
||
GENERATED="$(date -u -Iseconds)"
|
||
TRANSACTION_ENVELOPE_COUNT="$(find "${STAGE}/transactions" -maxdepth 1 -type f -name '*.json' | wc -l | tr -d ' ')"
|
||
TRANSACTION_ENVELOPES_JSON="$(cd "$STAGE" && find ./transactions -maxdepth 1 -type f -name '*.json' | sort | jq -R -s 'split("\n") | map(select(length > 0)) | map(sub("^\\./"; ""))')"
|
||
|
||
# Validate settlement JSONs in archive (best-effort)
|
||
VALIDATION_NOTE="Install check-jsonschema (see config/dbis-institutional/README.md), then: check-jsonschema --schemafile schemas/settlement-event.schema.json settlement-events/*.json"
|
||
TRANSACTION_ENVELOPE_VALIDATION_NOTE="No staged transaction execution envelopes."
|
||
if command -v check-jsonschema &>/dev/null; then
|
||
FAILS=()
|
||
for sf in "${STAGE}"/settlement-events/*.json; do
|
||
[ -f "$sf" ] || continue
|
||
check-jsonschema --schemafile "${STAGE}/schemas/settlement-event.schema.json" "$sf" &>/dev/null || FAILS+=("$(basename "$sf")")
|
||
done
|
||
if [ "${#FAILS[@]}" -eq 0 ]; then
|
||
VALIDATION_NOTE="All settlement-events/*.json passed check-jsonschema against bundled schema."
|
||
else
|
||
VALIDATION_NOTE="Schema validation FAIL: ${FAILS[*]}"
|
||
fi
|
||
|
||
TX_FAILS=()
|
||
for tf in "${STAGE}"/transactions/*.json; do
|
||
[ -f "$tf" ] || continue
|
||
check-jsonschema --schemafile "${STAGE}/schemas/jvmtm/transaction-compliance-execution.schema.json" "$tf" &>/dev/null || TX_FAILS+=("$(basename "$tf")")
|
||
done
|
||
if [ "$TRANSACTION_ENVELOPE_COUNT" -gt 0 ]; then
|
||
if [ "${#TX_FAILS[@]}" -eq 0 ]; then
|
||
TRANSACTION_ENVELOPE_VALIDATION_NOTE="All transactions/*.json passed check-jsonschema against bundled transaction-compliance-execution.schema.json."
|
||
else
|
||
echo "ERROR: transaction execution envelope schema validation failed: ${TX_FAILS[*]}" >&2
|
||
exit 1
|
||
fi
|
||
fi
|
||
elif [ "$TRANSACTION_ENVELOPE_COUNT" -gt 0 ]; then
|
||
TRANSACTION_ENVELOPE_VALIDATION_NOTE="Transaction execution envelopes staged, but schema validation skipped because check-jsonschema is not installed."
|
||
fi
|
||
|
||
cat > "${STAGE}/README_E2E_ARCHIVE.txt" <<EOF
|
||
OMNL + Chain 138 — E2E Settlement, Audit Proof, Closure Cluster
|
||
================================================================
|
||
Generated (UTC): ${STAMP_UTC}
|
||
Repository HEAD: ${GIT_COMMIT}
|
||
|
||
Contents
|
||
--------
|
||
settlement-events/ Canonical JSON (schema: settlement-event.schema.json)
|
||
schemas/ settlement-event.schema.json; schemas/jvmtm/*.schema.json (JVMTM closure)
|
||
examples/ settlement-event.example.json, settlement-event.chain138-primary.example.json, settlement-event.min.json
|
||
reconciliation/ daily-3way-reconciliation-report.json (template or JVMTM_CLOSURE_DIR); 3way-result.json when present (from generate-3way-reconciliation-evidence.sh)
|
||
liquidity/ prefunding-proof.json
|
||
acknowledgements/ pre-settlement-ack.json
|
||
exceptions/ exception-policy.md, sample-exception-event.json, retry-log.txt
|
||
validation/ kyt-screening-result.json (optional evidence)
|
||
bcp/ recovery-time-report.json, failover-test-log.txt
|
||
disaster-recovery/ DR-simulation-report.json
|
||
monitoring/ real-time-balance-snapshot.json
|
||
transactions/ optional live transaction-compliance-execution envelopes from JVMTM_CLOSURE_DIR/transactions/*.json
|
||
config/jvmtm-regulatory-closure/ README, OPERATIONAL_EVIDENCE_VS_TEMPLATES.md, INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md (018215821582/INAAUDJVMTM/2025)
|
||
transaction-grade matrix (.md + .json + .csv) and example execution envelopes
|
||
docs/ M1 clearing runbook, IPSAS memo, Phase C, RTGS+Smart Vault runbook, OJK/BI identifier policy, dbis-institutional README
|
||
scripts/ M1 clearing, 102B chunked, chain attestation, this builder, dbis + JVMTM validators, matrix CSV exporter
|
||
evidence/ chain138-attestation-receipt.txt; mainnet-attestation-receipt.txt when dual-anchor hash + ETHEREUM_MAINNET_RPC set; optional Fineract journal pulls
|
||
audit-proof/ AUDIT_PROOF.json, SETTLEMENT_CLOSURE.json
|
||
reserve-provenance-package/ 3FR funding origin attestation layer (see README.md inside; bank/KYT truthfully pending)
|
||
|
||
Closure summary (102B USD path)
|
||
-------------------------------
|
||
- Ledger: 102 × USD 1,000,000,000.00 per Fineract journal line (office 21 → 22), refs OMNL-102B-CH{1..102}-OF21-TO22-20260331
|
||
- Chain 138: attestation tx ${CHAIN_ATTESTATION_TX_HASH} (Chain ID 138), deployer 0x4A666F96fC8764181194447A7dFdb7d471b301C8
|
||
- Ethereum mainnet (optional): ${CHAIN_ATTESTATION_TX_HASH_MAINNET:-not recorded in this build} when dual-anchor — see AUDIT_PROOF.json chainAttestationMainnet
|
||
- Correlation ID (closure): 1a62dd79-dca7-4bbf-b7f7-3d73e1f5912d
|
||
|
||
Verify integrity
|
||
----------------
|
||
cd ${ARCHIVE_BASENAME}
|
||
sha256sum -c MANIFEST.sha256
|
||
|
||
Schema validation (optional)
|
||
-----------------------------
|
||
${VALIDATION_NOTE}
|
||
|
||
JVMTM / regulatory closure JSON (optional)
|
||
------------------------------------------
|
||
check-jsonschema --schemafile schemas/jvmtm/daily-3way-reconciliation-report.schema.json reconciliation/daily-3way-reconciliation-report.json
|
||
(and similarly for liquidity/, acknowledgements/, exceptions/sample-exception-event.json, validation/, bcp/*.json, disaster-recovery/, monitoring/)
|
||
Or: bash scripts/validation/validate-jvmtm-regulatory-closure-schemas.sh (validates repo examples; re-run against archive paths after edits)
|
||
|
||
Transaction execution envelopes
|
||
-------------------------------
|
||
${TRANSACTION_ENVELOPE_VALIDATION_NOTE}
|
||
|
||
Reserve provenance package (3FR)
|
||
---------------------------------
|
||
bash scripts/validation/validate-reserve-provenance-package.sh
|
||
(validates reserve-provenance-package/*.json against reserve-provenance-package.schema.json)
|
||
EOF
|
||
|
||
jq -n \
|
||
--arg archiveId "$ARCHIVE_BASENAME" \
|
||
--arg gen "$GENERATED" \
|
||
--arg git "$GIT_COMMIT" \
|
||
--arg attTx "$CHAIN_ATTESTATION_TX_HASH" \
|
||
--arg rpc "$RPC_URL_138" \
|
||
--arg mTx "${CHAIN_ATTESTATION_TX_HASH_MAINNET:-}" \
|
||
--arg mRpc "${ETHEREUM_MAINNET_RPC:-}" \
|
||
--arg corr "1a62dd79-dca7-4bbf-b7f7-3d73e1f5912d" \
|
||
--argjson txCount "${TRANSACTION_ENVELOPE_COUNT}" \
|
||
--argjson txEnvelopes "${TRANSACTION_ENVELOPES_JSON}" \
|
||
--argjson offices '[1,21,22]' \
|
||
'{
|
||
archiveType: "OMNL_E2E_SETTLEMENT_AUDIT_CLOSURE",
|
||
archiveId: $archiveId,
|
||
archiveAttestationPolicy: "Dual-anchor: Chain 138 (mandatory path in this bundle) + Ethereum mainnet when CHAIN_ATTESTATION_TX_HASH_MAINNET and ETHEREUM_MAINNET_RPC are set or latest-dual-attestation.json present",
|
||
generatedAtUtc: $gen,
|
||
repositoryHeadCommit: $git,
|
||
auditProof: {
|
||
settlementSchema: "config/dbis-institutional/schemas/settlement-event.schema.json",
|
||
schemaDraft: "2020-12",
|
||
finercatEvidenceOffices: $offices,
|
||
validationTool: "check-jsonschema",
|
||
narrative: "Double-entry M1 interoffice (1410/2100); HO static for m1-clearing script; IPSAS/IFRS per OMNL_IPSAS_IFRS_INTEROFFICE_COMPLIANCE.md"
|
||
},
|
||
settlement: {
|
||
notionalUsdMajor: "102000000000.00",
|
||
chunking: "102 x USD 1000000000.00 per Fineract line (minor units 100000000000 cents each)",
|
||
script: "scripts/omnl/omnl-m1-clearing-102b-chunked.sh",
|
||
fromOfficeId: 21,
|
||
toOfficeId: 22,
|
||
referencePrefix: "OMNL-102B-CH",
|
||
complianceRef: "OMNL-102B-CHUNKED-20260331"
|
||
},
|
||
chainAttestation: {
|
||
chainId: 138,
|
||
rpcUrlUsed: $rpc,
|
||
transactionHash: $attTx,
|
||
description: "0-value self-send attestation; SettlementRouter not deployed per DBIS Rail status",
|
||
deployerAddress: "0x4A666F96fC8764181194447A7dFdb7d471b301C8"
|
||
},
|
||
chainAttestationMainnet: (if ($mTx | length) > 0 then {
|
||
chainId: 1,
|
||
rpcUrlUsed: $mRpc,
|
||
transactionHash: $mTx,
|
||
description: "0-value self-send attestation on Ethereum mainnet (dual-anchor with Chain 138)",
|
||
deployerAddress: "0x4A666F96fC8764181194447A7dFdb7d471b301C8"
|
||
} else null end),
|
||
closureCluster: {
|
||
correlationId: $corr,
|
||
canonicalSettlementEventFile: "settlement-events/omnl-102b-ledger-and-chain-20260331.json",
|
||
eventType: "CHAIN_SETTLEMENT",
|
||
statusExtension: "FINALIZED"
|
||
},
|
||
jvmtmRegulatoryClosure: {
|
||
description: "JVMTM-style audit commentary evidence (Tables B/C/D); templates unless JVMTM_CLOSURE_DIR set",
|
||
auditEngagementReference: "018215821582/INAAUDJVMTM/2025",
|
||
tablesBCDClosureMatrix: "config/jvmtm-regulatory-closure/INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md",
|
||
mandatoryPaths: [
|
||
"reconciliation/daily-3way-reconciliation-report.json",
|
||
"liquidity/prefunding-proof.json",
|
||
"acknowledgements/pre-settlement-ack.json",
|
||
"exceptions/exception-policy.md",
|
||
"exceptions/sample-exception-event.json"
|
||
],
|
||
supplementaryPaths: [
|
||
"config/jvmtm-regulatory-closure/INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md",
|
||
"reconciliation/3way-result.json",
|
||
"config/jvmtm-regulatory-closure/OPERATIONAL_EVIDENCE_VS_TEMPLATES.md",
|
||
"validation/kyt-screening-result.json",
|
||
"bcp/recovery-time-report.json",
|
||
"bcp/failover-test-log.txt",
|
||
"disaster-recovery/DR-simulation-report.json",
|
||
"monitoring/real-time-balance-snapshot.json",
|
||
"exceptions/retry-log.txt"
|
||
],
|
||
transactionGradePackPaths: [
|
||
"config/jvmtm-regulatory-closure/JVMTM_TRANSACTION_GRADE_COMPLIANCE_MATRIX.md",
|
||
"config/jvmtm-regulatory-closure/transaction-compliance-matrix.json",
|
||
"config/jvmtm-regulatory-closure/transaction-compliance-matrix.csv"
|
||
],
|
||
exampleExecutionEnvelopes: [
|
||
"config/jvmtm-regulatory-closure/examples/transaction-compliance-execution.example.json",
|
||
"config/jvmtm-regulatory-closure/examples/transaction-compliance-execution.blocked.example.json"
|
||
],
|
||
executionEnvelopeSchema: "schemas/jvmtm/transaction-compliance-execution.schema.json",
|
||
stagedTransactionEnvelopeCount: $txCount,
|
||
stagedTransactionEnvelopes: $txEnvelopes,
|
||
transactionEnvelopeArchiveDir: "transactions/",
|
||
schemaDir: "schemas/jvmtm",
|
||
operatorReadme: "config/jvmtm-regulatory-closure/README.md",
|
||
operationalEvidenceNote: "Templates structure controls; generated/vendor/execution artifacts prove operation — see OPERATIONAL_EVIDENCE_VS_TEMPLATES.md"
|
||
},
|
||
reserveProvenancePackage: {
|
||
description: "Staged reserve / funding origin attestation (3FR); HYBX-OMNL-DBIS regulatory stack + reserve hosting map; counsel review; MT940-camt.053-API keystone still required for bank leg",
|
||
root: "reserve-provenance-package/",
|
||
readme: "reserve-provenance-package/README.md",
|
||
schema: "reserve-provenance-package/schemas/reserve-provenance-package.schema.json",
|
||
artifacts: [
|
||
"reserve-provenance-package/legal/ATTORNEY_RECEIPT_ATTESTATION_3FR.json",
|
||
"reserve-provenance-package/settlement/SETTLEMENT_FINALITY_DECLARATION.json",
|
||
"reserve-provenance-package/provenance/FUNDING_ORIGIN_CHAIN_3FR.json",
|
||
"reserve-provenance-package/bank/JVMTM_BANK_BALANCE_JSON.json",
|
||
"reserve-provenance-package/bank/MT940_STATEMENT_3FR_TITAN_RECEIVING_ACCOUNT.txt",
|
||
"reserve-provenance-package/bank/MT940_STATEMENT_3FR_TITAN_RESERVE_LINKED.txt",
|
||
"reserve-provenance-package/bank/README_BANK_REQUEST_MT940_CAMT053.md",
|
||
"reserve-provenance-package/bank/JVMTM_BANK_BALANCE_PARSED_EXAMPLE_AFTER_MT940.example.json",
|
||
"reserve-provenance-package/kyt/KYT_EXECUTION_RECORD.json",
|
||
"reserve-provenance-package/reconciliation/3WAY_RECONCILIATION_TRIGGER.json",
|
||
"reserve-provenance-package/reserve/RESERVE_RECOGNITION_DECLARATION.json",
|
||
"reserve-provenance-package/reserve/RESERVE_MONETARY_LINKAGE_DECLARATION.json",
|
||
"reserve-provenance-package/reserve/RESERVE_HOSTING_AND_JURISDICTION_MAP.json",
|
||
"reserve-provenance-package/governance/REGULATORY_STACK_DECLARATION.json",
|
||
"reserve-provenance-package/governance/REGULATORY_STACK_NARRATIVE.txt"
|
||
]
|
||
}
|
||
}' > "${STAGE}/audit-proof/AUDIT_PROOF.json"
|
||
|
||
jq -n \
|
||
--arg gen "$GENERATED" \
|
||
--arg corr "1a62dd79-dca7-4bbf-b7f7-3d73e1f5912d" \
|
||
--arg tx "$CHAIN_ATTESTATION_TX_HASH" \
|
||
--arg mtx "${CHAIN_ATTESTATION_TX_HASH_MAINNET:-}" \
|
||
--argjson txEnvelopes "${TRANSACTION_ENVELOPES_JSON}" \
|
||
'{
|
||
closureRecord: "SETTLEMENT_CLOSURE",
|
||
generatedAtUtc: $gen,
|
||
layers: {
|
||
layer1_interofficeLedger: "102 chunked M1 posts office 21 to 22; refs OMNL-102B-CH*-20260331",
|
||
layer2_invariant: "Operator to confirm net M1 across 21+22 per SOP; HO unchanged for m1-clearing-only legs",
|
||
layer3_identifiers: {
|
||
correlationId: $corr,
|
||
chainTxHash: $tx,
|
||
chainId: 138,
|
||
ethereumMainnetChainTxHash: (if ($mtx | length) > 0 then $mtx else null end),
|
||
ethereumMainnetChainId: (if ($mtx | length) > 0 then 1 else null end)
|
||
},
|
||
layer4_schema: "settlement-events/*.json validate against settlement-event.schema.json",
|
||
layer5_transactionExecutionEnvelopes: $txEnvelopes
|
||
},
|
||
artefacts: ([
|
||
"audit-proof/AUDIT_PROOF.json",
|
||
"audit-proof/SETTLEMENT_CLOSURE.json",
|
||
"config/jvmtm-regulatory-closure/INAAUDJVMTM_2025_AUDIT_CLOSURE_MATRIX.md",
|
||
"config/jvmtm-regulatory-closure/JVMTM_TRANSACTION_GRADE_COMPLIANCE_MATRIX.md",
|
||
"config/jvmtm-regulatory-closure/transaction-compliance-matrix.json",
|
||
"config/jvmtm-regulatory-closure/transaction-compliance-matrix.csv",
|
||
"config/jvmtm-regulatory-closure/examples/transaction-compliance-execution.example.json",
|
||
"config/jvmtm-regulatory-closure/examples/transaction-compliance-execution.blocked.example.json",
|
||
"schemas/jvmtm/transaction-compliance-execution.schema.json",
|
||
"settlement-events/omnl-102b-ledger-and-chain-20260331.json",
|
||
"evidence/chain138-attestation-receipt.txt",
|
||
"evidence/mainnet-attestation-receipt.txt",
|
||
"reconciliation/daily-3way-reconciliation-report.json",
|
||
"liquidity/prefunding-proof.json",
|
||
"acknowledgements/pre-settlement-ack.json",
|
||
"exceptions/exception-policy.md",
|
||
"exceptions/sample-exception-event.json",
|
||
"exceptions/retry-log.txt",
|
||
"validation/kyt-screening-result.json",
|
||
"bcp/recovery-time-report.json",
|
||
"bcp/failover-test-log.txt",
|
||
"disaster-recovery/DR-simulation-report.json",
|
||
"monitoring/real-time-balance-snapshot.json",
|
||
"reserve-provenance-package/README.md",
|
||
"reserve-provenance-package/legal/ATTORNEY_RECEIPT_ATTESTATION_3FR.json",
|
||
"reserve-provenance-package/settlement/SETTLEMENT_FINALITY_DECLARATION.json",
|
||
"reserve-provenance-package/provenance/FUNDING_ORIGIN_CHAIN_3FR.json",
|
||
"reserve-provenance-package/bank/JVMTM_BANK_BALANCE_JSON.json",
|
||
"reserve-provenance-package/bank/MT940_STATEMENT_3FR_TITAN_RECEIVING_ACCOUNT.txt",
|
||
"reserve-provenance-package/bank/MT940_STATEMENT_3FR_TITAN_RESERVE_LINKED.txt",
|
||
"reserve-provenance-package/bank/README_BANK_REQUEST_MT940_CAMT053.md",
|
||
"reserve-provenance-package/bank/JVMTM_BANK_BALANCE_PARSED_EXAMPLE_AFTER_MT940.example.json",
|
||
"reserve-provenance-package/kyt/KYT_EXECUTION_RECORD.json",
|
||
"reserve-provenance-package/reconciliation/3WAY_RECONCILIATION_TRIGGER.json",
|
||
"reserve-provenance-package/reserve/RESERVE_RECOGNITION_DECLARATION.json",
|
||
"reserve-provenance-package/reserve/RESERVE_MONETARY_LINKAGE_DECLARATION.json",
|
||
"reserve-provenance-package/reserve/RESERVE_HOSTING_AND_JURISDICTION_MAP.json",
|
||
"reserve-provenance-package/governance/REGULATORY_STACK_DECLARATION.json",
|
||
"reserve-provenance-package/governance/REGULATORY_STACK_NARRATIVE.txt",
|
||
"reserve-provenance-package/schemas/reserve-provenance-package.schema.json",
|
||
"MANIFEST.json",
|
||
"MANIFEST.sha256"
|
||
] + $txEnvelopes)
|
||
}' > "${STAGE}/audit-proof/SETTLEMENT_CLOSURE.json"
|
||
|
||
# Manifest + sha256
|
||
NDJSON="${STAGE}/._manifest_items.ndjson"
|
||
: > "$NDJSON"
|
||
cd "$STAGE"
|
||
while IFS= read -r f; do
|
||
p="${f#./}"
|
||
[ -z "$p" ] && continue
|
||
case "$p" in MANIFEST.json|MANIFEST.sha256|._*) continue ;; esac
|
||
sz=$(wc -c < "$f" | tr -d ' ')
|
||
h=$(sha256sum "$f" | awk '{print $1}')
|
||
jq -n --arg path "$p" --arg sha "$h" --argjson size "$sz" \
|
||
'{path: $path, sha256: $sha, sizeBytes: $size}' >> "$NDJSON"
|
||
done < <(find . -type f | sort)
|
||
|
||
ITEMS=$(jq -s '.' "$NDJSON")
|
||
jq -n \
|
||
--arg id "$ARCHIVE_BASENAME" \
|
||
--arg gen "$GENERATED" \
|
||
--arg git "$GIT_COMMIT" \
|
||
--argjson files "$ITEMS" \
|
||
'{
|
||
archiveId: $id,
|
||
generatedAtUtc: $gen,
|
||
repositoryHeadCommit: $git,
|
||
description: "E2E OMNL settlement + audit proof + closure cluster (Fineract + Chain 138 attestation; optional Ethereum mainnet dual-anchor)",
|
||
files: $files
|
||
}' > "${STAGE}/MANIFEST.json"
|
||
|
||
find . -type f ! -name '._*' ! -name 'MANIFEST.sha256' | sort | while IFS= read -r f; do
|
||
p="${f#./}"
|
||
sha256sum "$f" | awk -v p="$p" '{print $1 " " p}'
|
||
done > "${STAGE}/MANIFEST.sha256"
|
||
|
||
rm -f "$NDJSON"
|
||
cd "$REPO_ROOT"
|
||
rm -f "$ZIP_PATH"
|
||
(
|
||
cd "$OUT_BASE"
|
||
zip -r -q "$ZIP_PATH" "$ARCHIVE_BASENAME"
|
||
)
|
||
echo "Wrote $ZIP_PATH" >&2
|
||
ls -la "$ZIP_PATH" >&2
|
||
if [ "${KEEP_STAGE:-0}" != "1" ]; then
|
||
rm -rf "$STAGE"
|
||
fi
|