266 lines
12 KiB
Bash
266 lines
12 KiB
Bash
|
|
#!/usr/bin/env bash
|
|||
|
|
# Build transaction-package-HYBX-BATCH-001.zip (Indonesia / Bank Kanaya submission binder).
|
|||
|
|
# See docs/04-configuration/mifos-omnl-central-bank/INDONESIA_CENTRAL_BANK_SUBMISSION_BINDER.md
|
|||
|
|
|
|||
|
|
set -euo pipefail
|
|||
|
|
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|||
|
|
DOCS="${REPO_ROOT}/docs/04-configuration/mifos-omnl-central-bank"
|
|||
|
|
DBIS_DOCS="${REPO_ROOT}/docs/dbis-rail"
|
|||
|
|
STAGING="${REPO_ROOT}/.transaction-package-staging"
|
|||
|
|
OUT_ZIP="${OUT_ZIP:-${REPO_ROOT}/transaction-package-HYBX-BATCH-001.zip}"
|
|||
|
|
|
|||
|
|
rm -rf "$STAGING"
|
|||
|
|
mkdir -p "$STAGING"/{00_Cover,Volume_A/Section_1,Volume_A/Section_2,Volume_B/Section_3,Volume_B/Section_4,Volume_C/Section_5,Volume_C/Section_6,Volume_C/Section_7,Volume_D/Section_8,Volume_D/Section_9,Volume_D/Section_10,Volume_D/Section_11,Volume_E/Section_12,Volume_E/Section_13,Volume_E/Section_14,Volume_F/Section_15,Appendix}
|
|||
|
|
|
|||
|
|
SNAPSHOT_SRC=""
|
|||
|
|
if [ -f "${REPO_ROOT}/proof_package/Volume_A_Section_2/omnl_transaction_package_snapshot.json" ]; then
|
|||
|
|
SNAPSHOT_SRC="${REPO_ROOT}/proof_package/Volume_A_Section_2/omnl_transaction_package_snapshot.json"
|
|||
|
|
elif [ -f "${REPO_ROOT}/omnl_transaction_package_snapshot.json" ]; then
|
|||
|
|
SNAPSHOT_SRC="${REPO_ROOT}/omnl_transaction_package_snapshot.json"
|
|||
|
|
fi
|
|||
|
|
if [ -n "$SNAPSHOT_SRC" ]; then
|
|||
|
|
cp "$SNAPSHOT_SRC" "$STAGING/Volume_A/Section_2/omnl_transaction_package_snapshot.json"
|
|||
|
|
elif [ "${ALLOW_MISSING_OMNL_SNAPSHOT:-0}" != "1" ]; then
|
|||
|
|
echo "ERROR: omnl_transaction_package_snapshot.json missing. Run omnl-transaction-package-snapshot.sh or ALLOW_MISSING_OMNL_SNAPSHOT=1" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
ENTITY_MASTER="${REPO_ROOT}/docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json"
|
|||
|
|
ENRICH_JQ="${REPO_ROOT}/scripts/omnl/jq/enrich-snapshot-entity-master.jq"
|
|||
|
|
SNAP_STAGED="$STAGING/Volume_A/Section_2/omnl_transaction_package_snapshot.json"
|
|||
|
|
if [ -f "$SNAP_STAGED" ] && [ -f "$ENTITY_MASTER" ] && [ -f "$ENRICH_JQ" ]; then
|
|||
|
|
jq --argjson master "$(jq -c . "$ENTITY_MASTER")" -f "$ENRICH_JQ" "$SNAP_STAGED" > "${SNAP_STAGED}.e.$$" && mv "${SNAP_STAGED}.e.$$" "$SNAP_STAGED"
|
|||
|
|
fi
|
|||
|
|
if [ -f "$ENTITY_MASTER" ]; then
|
|||
|
|
cp "$ENTITY_MASTER" "$STAGING/Volume_A/Section_2/OMNL_ENTITY_MASTER_DATA.json"
|
|||
|
|
fi
|
|||
|
|
[ -f "$DOCS/OMNL_ENTITY_MASTER_DATA.md" ] && cp "$DOCS/OMNL_ENTITY_MASTER_DATA.md" "$STAGING/Volume_A/Section_2/"
|
|||
|
|
|
|||
|
|
cp "$DOCS/INDONESIA_SAMPLE_COVER_AND_TOC.md" "$STAGING/00_Cover/"
|
|||
|
|
cat > "$STAGING/00_Cover/README.txt" << 'COVERREADME'
|
|||
|
|
HYBX-BATCH-001 | Bank Kanaya (OMNL office 22) | USD 1,000,000,000.00
|
|||
|
|
Cover/TOC: INDONESIA_SAMPLE_COVER_AND_TOC.md
|
|||
|
|
Integrity: ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt; GENERATED_EVIDENCE_ESIGN_MANIFEST.json;
|
|||
|
|
HASH_NOTARIZATION_ANCHOR.txt; audit_and_hashes.txt; audit_manifest.json (contentCommitmentSha256).
|
|||
|
|
Optional TSA/QES: TSA_RFC3161_* QES_CMS_* (excluded from commitment; see anchor).
|
|||
|
|
Verify: python3 scripts/omnl/verify-transaction-package-commitment.py <unzipped-root>
|
|||
|
|
4.995 gate: bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>
|
|||
|
|
See: 00_Cover/REGULATORY_TARGET_4_995.json | Appendix/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md
|
|||
|
|
COVERREADME
|
|||
|
|
|
|||
|
|
for f in \
|
|||
|
|
INDONESIA_MASTER_PROOF_MANIFEST.md \
|
|||
|
|
INDONESIA_CENTRAL_BANK_SUBMISSION_BINDER.md \
|
|||
|
|
INDONESIA_SAMPLE_COVER_AND_TOC.md \
|
|||
|
|
INDONESIA_REGULATORY_REFERENCES_ANNEX.md \
|
|||
|
|
INDONESIA_BI_MOF_PPATK_CHECKLIST.md \
|
|||
|
|
INDONESIA_TRANSMISSION_READINESS_CHECKLIST.md \
|
|||
|
|
INDONESIA_SUBMISSION_PACKAGE_GRADE_AND_SCORECARD.md \
|
|||
|
|
OMNL_API_TRANSACTION_PACKAGE.md \
|
|||
|
|
PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md \
|
|||
|
|
BANK_KANAYA_OFFICE_RUNBOOK.md \
|
|||
|
|
REGULATORY_INDONESIA_BANK_KANAYA.md \
|
|||
|
|
OMNL_GL_ACCOUNTS_REQUIRED.md \
|
|||
|
|
INDONESIA_AUDIT_AND_COMPLIANCE_STANDARD.md \
|
|||
|
|
OMNL_API_PUSH_STATUS.md \
|
|||
|
|
TRANSACTION_EXPLANATION_JURISDICTIONS_AND_DIAGRAMS.md \
|
|||
|
|
TRANSACTION_EXPLANATION_VISUAL.html \
|
|||
|
|
OMNL_JOURNAL_ENTRIES_161_164.md \
|
|||
|
|
OPERATING_RAILS.md \
|
|||
|
|
LEDGER_ALLOCATION_POSTING_RUNBOOK.md \
|
|||
|
|
OMNL_JOURNAL_LEDGER_MATRIX.md \
|
|||
|
|
GOVERNANCE_REGULATOR_EXPLAINERS_AND_LEGAL_FRAMEWORK.md \
|
|||
|
|
INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md \
|
|||
|
|
ISO20022_VAULT_MANIFEST_HYBX-BATCH-001.json \
|
|||
|
|
AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md \
|
|||
|
|
BI_REPORTING_CROSSWALK_HYBX-BATCH-001.md \
|
|||
|
|
MOF_ALIGNMENT_MEMO_HYBX-BATCH-001.md \
|
|||
|
|
OJK_PRUDENTIAL_BRIDGE_HYBX-BATCH-001.md \
|
|||
|
|
LEGAL_FINALITY_COUNSEL_MEMO_REQUIREMENTS_HYBX-BATCH-001.md \
|
|||
|
|
INDEPENDENT_AUDIT_4_995_REQUIREMENTS_HYBX-BATCH-001.md \
|
|||
|
|
INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.EXAMPLE.json \
|
|||
|
|
HYBX_BATCH_001_OPERATOR_CHECKLIST.md \
|
|||
|
|
OMNL_BANKING_DIRECTORS_AND_LEI.md
|
|||
|
|
do
|
|||
|
|
[ -f "$DOCS/$f" ] && cp "$DOCS/$f" "$STAGING/Appendix/" || { echo "ERROR: missing $DOCS/$f" >&2; exit 1; }
|
|||
|
|
done
|
|||
|
|
cp "$DBIS_DOCS/DBIS_SETTLEMENT_RULEBOOK.md" "$STAGING/Appendix/"
|
|||
|
|
cp "$DBIS_DOCS/DBIS_RAIL_RULEBOOK_V1.md" "$STAGING/Appendix/"
|
|||
|
|
|
|||
|
|
ATT_SRC="${PACKAGE_4995_ATTESTATION_JSON:-}"
|
|||
|
|
if [ -z "$ATT_SRC" ]; then
|
|||
|
|
if [ -f "${REPO_ROOT}/proof_package/regulatory/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json" ]; then
|
|||
|
|
ATT_SRC="${REPO_ROOT}/proof_package/regulatory/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json"
|
|||
|
|
else
|
|||
|
|
ATT_SRC="${DOCS}/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
if [ -f "$ATT_SRC" ]; then
|
|||
|
|
cp "$ATT_SRC" "$STAGING/Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
cat > "$STAGING/00_Cover/REGULATORY_TARGET_4_995.json" << 'REGJSON'
|
|||
|
|
{
|
|||
|
|
"documentId": "REGULATORY-TARGET-4-995",
|
|||
|
|
"targetScorePerCategory": 4.995,
|
|||
|
|
"scale": "0-5",
|
|||
|
|
"standard": "Appendix/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md",
|
|||
|
|
"checkScript": "scripts/omnl/check-transaction-package-4995-readiness.sh --strict",
|
|||
|
|
"attestationFile": "Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json",
|
|||
|
|
"attestationExample": "Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.EXAMPLE.json",
|
|||
|
|
"note": "4.995 is attained only when --strict check passes; scores are not implied by templates."
|
|||
|
|
}
|
|||
|
|
REGJSON
|
|||
|
|
|
|||
|
|
GEN_PY="${REPO_ROOT}/scripts/omnl/generate-transaction-package-evidence.py"
|
|||
|
|
[ -f "$GEN_PY" ] || { echo "ERROR: missing $GEN_PY" >&2; exit 1; }
|
|||
|
|
command -v python3 >/dev/null || { echo "ERROR: python3 required" >&2; exit 1; }
|
|||
|
|
if [ -n "${HYBX_LEDGER_FILE:-}" ] && [ -f "$HYBX_LEDGER_FILE" ]; then
|
|||
|
|
python3 "$GEN_PY" --ledger-source "$HYBX_LEDGER_FILE" "$STAGING"
|
|||
|
|
else
|
|||
|
|
python3 "$GEN_PY" "$STAGING"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
cat > "$STAGING/Volume_B/Section_3/SECTION_3_NA_MEMORANDUM.txt" << 'EOF'
|
|||
|
|
SECTION 3 — CORRESPONDENT BANKING — NOT APPLICABLE (HYBX-BATCH-001)
|
|||
|
|
Settlement via OMNL central-bank-ledger design; USD leg on OMNL books. Bank Kanaya office 22.
|
|||
|
|
No multi-hop nostro/vostro chain applies. See Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md.
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
cat > "$STAGING/Volume_C/Section_7/merkle_integrity_specification.txt" << 'EOF'
|
|||
|
|
MERKLE SPECIFICATION — HYBX-BATCH-001
|
|||
|
|
Algorithm: SHA-256. Leaf: UTF-8 line hash per Appendix/DBIS_SETTLEMENT_RULEBOOK.md Annex B.
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
append_prebind_integrity_footer() {
|
|||
|
|
local file="$1"
|
|||
|
|
[ -f "$file" ] || return 0
|
|||
|
|
local pre
|
|||
|
|
pre=$(sha256sum "$file" | awk '{print $1}')
|
|||
|
|
cat >> "$file" <<FTR
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
PRE-BINDING DOCUMENT SHA-256 (UTF-8 bytes above this line): ${pre}
|
|||
|
|
E-sign / notarization: 00_Cover/ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt
|
|||
|
|
FTR
|
|||
|
|
}
|
|||
|
|
append_prebind_integrity_footer "$STAGING/Volume_B/Section_3/SECTION_3_NA_MEMORANDUM.txt"
|
|||
|
|
append_prebind_integrity_footer "$STAGING/Volume_C/Section_7/merkle_integrity_specification.txt"
|
|||
|
|
|
|||
|
|
section_readme() {
|
|||
|
|
local id="$1"
|
|||
|
|
local out="$2"
|
|||
|
|
{
|
|||
|
|
echo "HYBX-BATCH-001 — Section index ($id)"
|
|||
|
|
echo "Settlement ref: HYBX-BATCH-001 | Value date: 2026-03-17 | Beneficiary: Bank Kanaya (office 22)"
|
|||
|
|
echo "See Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md for required exhibits."
|
|||
|
|
} >"$out"
|
|||
|
|
}
|
|||
|
|
section_readme "Volume A §1" "$STAGING/Volume_A/Section_1/README.txt"
|
|||
|
|
section_readme "Volume A §2" "$STAGING/Volume_A/Section_2/README.txt"
|
|||
|
|
section_readme "Volume B §3" "$STAGING/Volume_B/Section_3/README.txt"
|
|||
|
|
section_readme "Volume B §4" "$STAGING/Volume_B/Section_4/README.txt"
|
|||
|
|
section_readme "Volume C §5" "$STAGING/Volume_C/Section_5/README.txt"
|
|||
|
|
section_readme "Volume C §6" "$STAGING/Volume_C/Section_6/README.txt"
|
|||
|
|
section_readme "Volume C §7" "$STAGING/Volume_C/Section_7/README.txt"
|
|||
|
|
section_readme "Volume D §8" "$STAGING/Volume_D/Section_8/README.txt"
|
|||
|
|
section_readme "Volume D §9" "$STAGING/Volume_D/Section_9/README.txt"
|
|||
|
|
section_readme "Volume D §10" "$STAGING/Volume_D/Section_10/README.txt"
|
|||
|
|
section_readme "Volume D §11" "$STAGING/Volume_D/Section_11/README.txt"
|
|||
|
|
section_readme "Volume E §12" "$STAGING/Volume_E/Section_12/README.txt"
|
|||
|
|
section_readme "Volume E §13" "$STAGING/Volume_E/Section_13/README.txt"
|
|||
|
|
section_readme "Volume E §14" "$STAGING/Volume_E/Section_14/README.txt"
|
|||
|
|
section_readme "Volume F §15" "$STAGING/Volume_F/Section_15/README.txt"
|
|||
|
|
|
|||
|
|
cat > "$STAGING/README.txt" << 'ZIPREADME'
|
|||
|
|
TRANSACTION PACKAGE — HYBX-BATCH-001
|
|||
|
|
Beneficiary: Bank Kanaya (Indonesia) — OMNL officeId 22 | USD 1,000,000,000.00
|
|||
|
|
Structure: 00_Cover, Volume_A–F, Appendix. Generator: scripts/omnl/generate-transaction-package-evidence.py
|
|||
|
|
Override ledger: HYBX_LEDGER_FILE=/path/to.csv. Integrity: 00_Cover/HASH_NOTARIZATION_ANCHOR.txt + audit_manifest.json
|
|||
|
|
ZIPREADME
|
|||
|
|
|
|||
|
|
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|||
|
|
AUDIT_FILE="$STAGING/00_Cover/audit_and_hashes.txt"
|
|||
|
|
AUDIT_JSON="$STAGING/00_Cover/audit_manifest.json"
|
|||
|
|
ANCHOR_FILE="$STAGING/00_Cover/HASH_NOTARIZATION_ANCHOR.txt"
|
|||
|
|
HASH_TSV=$(mktemp)
|
|||
|
|
trap 'rm -f "$HASH_TSV"' EXIT
|
|||
|
|
|
|||
|
|
excluded_from_content_commitment() {
|
|||
|
|
local rel="$1"
|
|||
|
|
case "$rel" in
|
|||
|
|
./00_Cover/HASH_NOTARIZATION_ANCHOR.txt | ./00_Cover/audit_and_hashes.txt | ./00_Cover/audit_manifest.json) return 0 ;;
|
|||
|
|
esac
|
|||
|
|
case "$(basename -- "$rel")" in
|
|||
|
|
TSA_RFC3161_REQUEST.tsq | TSA_RFC3161_RESPONSE.tsr | TSA_RFC3161_RESPONSE.txt | TSA_RFC3161_VERIFY.txt | QES_CMS_ANCHOR_DETACHED.p7s | QES_CMS_VERIFY_LOG.txt) return 0 ;;
|
|||
|
|
esac
|
|||
|
|
return 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
while IFS= read -r rel; do
|
|||
|
|
path="${STAGING}/${rel#./}"
|
|||
|
|
[ -f "$path" ] || continue
|
|||
|
|
excluded_from_content_commitment "$rel" && continue
|
|||
|
|
hash=$(sha256sum "$path" | awk '{print $1}')
|
|||
|
|
printf '%s\t%s\n' "$hash" "$rel" >> "$HASH_TSV"
|
|||
|
|
done < <((cd "$STAGING" && find . -type f ! -name '.DS_Store' | sort))
|
|||
|
|
|
|||
|
|
CONTENT_COMMITMENT=$(LC_ALL=C sort "$HASH_TSV" | sha256sum | awk '{print $1}')
|
|||
|
|
|
|||
|
|
cat > "$ANCHOR_FILE" <<ANCHOR
|
|||
|
|
HASH NOTARIZATION ANCHOR — HYBX-BATCH-001
|
|||
|
|
Build date (UTC): $BUILD_DATE
|
|||
|
|
Beneficiary: Bank Kanaya — OMNL officeId 22
|
|||
|
|
CONTENT COMMITMENT (SHA-256, hex): $CONTENT_COMMITMENT
|
|||
|
|
|
|||
|
|
Excluded from commitment input: this file; audit_and_hashes.txt; audit_manifest.json;
|
|||
|
|
TSA_RFC3161_* and QES_CMS_* outputs from apply-qes-tsa-to-staging.sh.
|
|||
|
|
|
|||
|
|
Verification: hash each other file as sha256, emit lowercase-hex<TAB>./relative/path,
|
|||
|
|
sort LC_ALL=C, UTF-8 join with newlines, final newline, SHA-256 that byte string.
|
|||
|
|
|
|||
|
|
Electronic signatures: HYBX-BATCH-001-SUBREG / ESIGN-ARTIFACTS.
|
|||
|
|
See 00_Cover/ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt
|
|||
|
|
ANCHOR
|
|||
|
|
|
|||
|
|
APPLY_SCRIPT="${REPO_ROOT}/scripts/omnl/apply-qes-tsa-to-staging.sh"
|
|||
|
|
if [ "${APPLY_REAL_QES_TSA:-0}" = "1" ]; then
|
|||
|
|
if [ -z "${TSA_URL:-}" ] && { [ -z "${QES_SIGN_CERT:-}" ] || [ -z "${QES_SIGN_KEY:-}" ]; }; then
|
|||
|
|
echo "ERROR: APPLY_REAL_QES_TSA=1 needs TSA_URL and/or QES_SIGN_CERT+QES_SIGN_KEY" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
bash "$APPLY_SCRIPT" "$STAGING"
|
|||
|
|
elif [ -n "${TSA_URL:-}" ] || { [ -n "${QES_SIGN_CERT:-}" ] && [ -n "${QES_SIGN_KEY:-}" ]; }; then
|
|||
|
|
bash "$APPLY_SCRIPT" "$STAGING"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
echo "Transaction package audit — HYBX-BATCH-001 | Bank Kanaya | office 22"
|
|||
|
|
echo "Build date (UTC): $BUILD_DATE"
|
|||
|
|
echo "Generator: scripts/omnl/build-transaction-package-zip.sh"
|
|||
|
|
echo ""
|
|||
|
|
echo "File hashes (SHA-256):"
|
|||
|
|
echo "---"
|
|||
|
|
(cd "$STAGING" && find . -type f ! -name '.DS_Store' | sort) | while read -r rel; do
|
|||
|
|
p="${STAGING}/${rel#./}"
|
|||
|
|
[ -f "$p" ] || continue
|
|||
|
|
printf " %s %s\n" "$(sha256sum "$p" | awk '{print $1}')" "$rel"
|
|||
|
|
done
|
|||
|
|
} > "$AUDIT_FILE"
|
|||
|
|
|
|||
|
|
echo "{\"buildDate\":\"$BUILD_DATE\",\"generator\":\"scripts/omnl/build-transaction-package-zip.sh\",\"settlementRef\":\"HYBX-BATCH-001\",\"beneficiaryOfficeId\":22,\"beneficiary\":\"Bank Kanaya (Indonesia)\",\"contentCommitmentSha256\":\"$CONTENT_COMMITMENT\",\"files\":[" > "$AUDIT_JSON"
|
|||
|
|
first=1
|
|||
|
|
(cd "$STAGING" && find . -type f ! -name '.DS_Store' | sort) | while read -r rel; do
|
|||
|
|
p="${STAGING}/${rel#./}"
|
|||
|
|
[ -f "$p" ] || continue
|
|||
|
|
h=$(sha256sum "$p" | awk '{print $1}')
|
|||
|
|
[ "$first" = 1 ] && first=0 || echo -n "," >> "$AUDIT_JSON"
|
|||
|
|
printf '{"path":"%s","sha256":"%s"}' "$rel" "$h" >> "$AUDIT_JSON"
|
|||
|
|
done
|
|||
|
|
echo "]}" >> "$AUDIT_JSON"
|
|||
|
|
|
|||
|
|
(cd "$STAGING" && zip -r "$OUT_ZIP" . -x "*.DS_Store")
|
|||
|
|
rm -rf "$STAGING"
|
|||
|
|
echo "Created: $OUT_ZIP" >&2
|
|||
|
|
ls -la "$OUT_ZIP" >&2
|