feat(omnl): HYBX-BATCH-001 package, rail scripts, regulatory docs, CI
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled

- Add OMNL/CBK Indonesia submission and audit binder docs, manifests, attestations
- Add scripts/omnl transaction-package pipeline, LEI/PvP helpers, jq/lib fixtures
- Update entity master data, MASTER_INDEX, TODOS, dbis-rail docs and rulebook
- Add proof_package/regulatory skeleton and transaction package zip + snapshot JSON
- validate-omnl-rail workflow, forge-verification-proxy tweak, .gitignore hygiene
- Bump smom-dbis-138 (cronos verify docs/scripts) and explorer-monorepo (SPA + env report)

Made-with: Cursor
This commit is contained in:
defiQUG
2026-03-24 18:11:36 -07:00
parent bfb8b321c0
commit 95522d3bca
64 changed files with 4048 additions and 75 deletions

View File

@@ -5,12 +5,14 @@ on:
pull_request:
paths:
- 'scripts/omnl/**'
- 'docs/04-configuration/mifos-omnl-central-bank/**'
- '.gitignore'
- '.github/workflows/validate-omnl-rail.yml'
push:
branches: [master]
paths:
- 'scripts/omnl/**'
- 'docs/04-configuration/mifos-omnl-central-bank/**'
- '.github/workflows/validate-omnl-rail.yml'
jobs:
@@ -24,6 +26,9 @@ jobs:
- name: .gitignore and resolve_ids
run: bash scripts/omnl/validate-rail.sh
- name: Transaction package CI smoke (fast ledger fixture)
run: bash scripts/omnl/run-transaction-package-ci-smoke.sh
- name: Shellcheck (optional)
run: |
if command -v shellcheck >/dev/null 2>&1; then

3
.gitignore vendored
View File

@@ -20,6 +20,9 @@ logs/
.DS_Store
Thumbs.db
# Local-only Cursor session / context (exclude from Gitea)
.cursor/local/
# IDE files
.vscode/
.idea/

View File

@@ -1,8 +1,8 @@
# TODOs — Consolidated Task List
**Last Updated:** 2026-03-06
**Last Updated:** 2026-03-24
**Last verification run:** 2026-03-06 (full + optional) — completable ✅, validate-config ✅, check-contracts 59/59 ✅, PMM pool balances ✅ (Pool 1: 2M/2M), preflight ✅, token-aggregation build ✅, deployer-gas dry-run ✅, fund-ccip dry-run ✅, test-all-contracts (unit) 457 passed ✅, E2E flow dry-run ✅, E2E routing ✅ (37 domains, 0 failed), operator script --skip-backup ✅ (NPMplus RPC fix + Blockscout verify). **Mint + add-liquidity** run 2026-03-06: 1M each minted, 500k each added; V2 done. **Next-steps check:** See [NEXT_STEPS_LIST.md](NEXT_STEPS_LIST.md) completion check; B.1/B.2/B.3 blocked (CRO/WEMIX/LINK).
**Purpose:** Single checklist of all next steps and remaining tasks. **Full execution order (multiple routes + liquidity):** [EXECUTION_CHECKLIST_MULTIPLE_ROUTES_AND_LIQUIDITY.md](EXECUTION_CHECKLIST_MULTIPLE_ROUTES_AND_LIQUIDITY.md). **Additional paths (registry, LiFi/Jumper, Etherlink, 13×13):** [ADDITIONAL_PATHS_AND_EXTENSIONS.md](../04-configuration/ADDITIONAL_PATHS_AND_EXTENSIONS.md). **Dotenv/markdown audit (required info, gaps, recommendations):** [DOTENV_AND_MARKDOWN_AUDIT_GAPS_AND_RECOMMENDATIONS.md](DOTENV_AND_MARKDOWN_AUDIT_GAPS_AND_RECOMMENDATIONS.md). Source of truth for the full list: [NEXT_STEPS_AND_REMAINING_TODOS.md](NEXT_STEPS_AND_REMAINING_TODOS.md). **Token deployments remaining:** [TOKEN_CONTRACT_DEPLOYMENTS_REMAINING.md](../11-references/TOKEN_CONTRACT_DEPLOYMENTS_REMAINING.md). **Routing / swap / cross-chain:** [TASKS_ROUTING_SWAP_CROSSCHAIN.md](TASKS_ROUTING_SWAP_CROSSCHAIN.md) (A1A5, B1B8, C1C8, D1D3, E1E2). **Verified list (LAN/Operator):** [REQUIRED_FIXES_GAPS_AND_DEPLOYMENTS_LIST.md](REQUIRED_FIXES_GAPS_AND_DEPLOYMENTS_LIST.md) — run bash/curl to confirm; doc updated 2026-03-03.
**Purpose:** Single checklist of all next steps and remaining tasks. **Indonesia / HYBX-BATCH-001 zip (4.995 ship-ready):** [HYBX-BATCH-001 — transaction package ship-ready](#hybx-batch-001--transaction-package-ship-ready-4995) below. **Full execution order (multiple routes + liquidity):** [EXECUTION_CHECKLIST_MULTIPLE_ROUTES_AND_LIQUIDITY.md](EXECUTION_CHECKLIST_MULTIPLE_ROUTES_AND_LIQUIDITY.md). **Additional paths (registry, LiFi/Jumper, Etherlink, 13×13):** [ADDITIONAL_PATHS_AND_EXTENSIONS.md](../04-configuration/ADDITIONAL_PATHS_AND_EXTENSIONS.md). **Dotenv/markdown audit (required info, gaps, recommendations):** [DOTENV_AND_MARKDOWN_AUDIT_GAPS_AND_RECOMMENDATIONS.md](DOTENV_AND_MARKDOWN_AUDIT_GAPS_AND_RECOMMENDATIONS.md). Source of truth for the full list: [NEXT_STEPS_AND_REMAINING_TODOS.md](NEXT_STEPS_AND_REMAINING_TODOS.md). **Token deployments remaining:** [TOKEN_CONTRACT_DEPLOYMENTS_REMAINING.md](../11-references/TOKEN_CONTRACT_DEPLOYMENTS_REMAINING.md). **Routing / swap / cross-chain:** [TASKS_ROUTING_SWAP_CROSSCHAIN.md](TASKS_ROUTING_SWAP_CROSSCHAIN.md) (A1A5, B1B8, C1C8, D1D3, E1E2). **Verified list (LAN/Operator):** [REQUIRED_FIXES_GAPS_AND_DEPLOYMENTS_LIST.md](REQUIRED_FIXES_GAPS_AND_DEPLOYMENTS_LIST.md) — run bash/curl to confirm; doc updated 2026-03-03.
**Quick run:** From anywhere (no LAN): `./scripts/run-completable-tasks-from-anywhere.sh`. Before Chain 138 deploy: `./scripts/deployment/preflight-chain138-deploy.sh [--cost]`. **Chain 138 next steps (all in one):** `./scripts/deployment/run-all-next-steps-chain138.sh [--dry-run] [--skip-mirror] [--skip-register-gru] [--skip-verify]` — preflight → mirror+pool → register c* as GRU → verify. From LAN with secrets: `./scripts/run-all-operator-tasks-from-lan.sh [--deploy] [--create-vms]`. **E2E flows (full parallel):** `./scripts/run-e2e-flow-tasks-full-parallel.sh [--dry-run]` — [TASKS_TO_INCREASE_ALL_E2E_FLOWS](TASKS_TO_INCREASE_ALL_E2E_FLOWS.md).
@@ -29,6 +29,40 @@
---
## HYBX-BATCH-001 — transaction package ship-ready (4.995)
**Goal:** `transaction-package-HYBX-BATCH-001.zip` passes `bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>` and `python3 scripts/omnl/verify-transaction-package-commitment.py <unzipped-root>`.
**Standard:** [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](../04-configuration/mifos-omnl-central-bank/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md). **Build:** `scripts/omnl/build-transaction-package-zip.sh` (optional `HYBX_LEDGER_FILE` for production ledger). **Live snapshot:** `scripts/omnl/omnl-transaction-package-snapshot.sh`.
### Strict gate (automated checklist)
| ID | Task | Notes |
|----|------|--------|
| **H1** | **Live OMNL snapshot** | Run `omnl-transaction-package-snapshot.sh` with Fineract credentials; `omnl_transaction_package_snapshot.json` must have `snapshotMeta.source == "live-api"`. Rebuild zip so Volume A Section 2 contains this file. |
| **H2** | **Snapshot freshness** | Per policy: `generatedAtUtc` within staleness window (standard default ≤ 72h before transmission). Refresh snapshot + rebuild if stale. |
| **H3** | **ISO 20022 vault manifest** | `Appendix/ISO20022_VAULT_MANIFEST_HYBX-BATCH-001.json`: replace all `REPLACE_*` placeholders (e.g. `REPLACE_WITH_VAULT_OBJECT_SHA256`) with real `sha256` / `storageLocation` / `messageId`; ≥1 message; align Section 4 index with ids. |
| **H4** | **Institutional attestation JSON** | Package must include `Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` (from `.EXAMPLE`, completed). `targetScorePerCategory` and each of 12 `categoryScores` ≥ 4.995; `certifiedBy` ≥ 2; finalize `legalFinality.counselMemoPdfSha256` and `independentAudit.reportPdfSha256` (no `REPLACE_`). Build picks up `proof_package/regulatory/…` or set `PACKAGE_4995_ATTESTATION_JSON`. |
| **H5** | **Regulatory references annex** | `Appendix/INDONESIA_REGULATORY_REFERENCES_ANNEX.md`: remove every `INSTITUTION: insert`; each row has instrument id + URL or internal doc id. |
| **H6** | **Re-verify** | Unzip rebuilt package; run strict script + commitment verify (commands in Validation commands below). |
### Standard categories (complete even when script is green)
| ID | Task | Notes |
|----|------|--------|
| **H7** | **Master proof manifest** | `Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md`: every sections 115 primary artifact path exists in zip; no TODO/TBD on mandatory index lines. |
| **H8** | **Ledger provenance** | If 215k-row file is system-of-record, document in attestation (`provenance.hybxLedgerSource` / equivalent); build with `HYBX_LEDGER_FILE` when binding production extract. |
| **H9** | **AML / PPATK schedule** | `Appendix/AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md`: complete through section 6; sanctions / PEP / STR-SAR done or documented nil with approver name/date. |
| **H10** | **BI reporting crosswalk** | `Appendix/BI_REPORTING_CROSSWALK_HYBX-BATCH-001.md`: no blank cells (instrument id, obligation, frequency, owner). |
| **H11** | **MoF memo** | `Appendix/MOF_ALIGNMENT_MEMO_HYBX-BATCH-001.md`: signed with role/title + date; hash/e-sign per process. |
| **H12** | **OJK prudential bridge** | `Appendix/OJK_PRUDENTIAL_BRIDGE_HYBX-BATCH-001.md`: mappings filled; N/A only where justified. |
| **H13** | **Legal finality** | Meet `LEGAL_FINALITY_COUNSEL_MEMO_REQUIREMENTS_HYBX-BATCH-001.md`; counsel memo PDF or hash in SUBREG; ties to H4. |
| **H14** | **Independent audit (Section 15)** | Meet `INDEPENDENT_AUDIT_4_995_REQUIREMENTS_HYBX-BATCH-001.md`; report hash in manifest/attestation; ties to H4. |
| **H15** | **TSA / QES (if policy requires)** | Run `apply-qes-tsa-to-staging.sh` with real `TSA_URL` / `QES_SIGN_*` before zipping, or document waiver in attestation. |
| **H16** | **Final archive** | One clean `build-transaction-package-zip.sh` after all sources final; ship the exact tree that passed H6. |
---
## First (before any Chain 138 deploy)
Verified 2026-03-06: preflight ✅, 0a balance check ✅ (script runs; WETH/cUSDT/cUSDC = 0), config validation ✅, on-chain 59/59 ✅. Re-run 0a/0/0c before each deploy.
@@ -237,6 +271,8 @@ Cron: `schedule-daily-weekly-cron.sh --install`; NPMplus backup: `schedule-npmpl
| On-chain (Chain 138) | `./scripts/verify/check-contracts-on-chain-138.sh` |
| E2E routing | `./scripts/verify/verify-end-to-end-routing.sh` |
| **Test all contracts (before deploy)** | `./scripts/deployment/test-all-contracts-before-deploy.sh` — use `--dry-run` / `--no-match "Fork|Mainnet|Integration|e2e"` / `--alltra` |
| **HYBX package commitment** | `python3 scripts/omnl/verify-transaction-package-commitment.py <unzipped-root>` | After unzip |
| **HYBX package 4.995 strict** | `bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>` | All H1H6 must pass |
---
@@ -277,4 +313,5 @@ Run 1, 4, 5, 6 in parallel from anywhere; 2, 3, 7, 8, 9 when LAN/RPC and secrets
- [NEXT_STEPS_FOR_YOU.md](NEXT_STEPS_FOR_YOU.md) — your next actions
- [NEXT_STEPS_OPERATOR.md](NEXT_STEPS_OPERATOR.md) — operator runbook
- [TODO_TASK_LIST_MASTER.md](TODO_TASK_LIST_MASTER.md) — fixes, gas, verification, 1139 index
- [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](../04-configuration/mifos-omnl-central-bank/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md) — HYBX-BATCH-001 4.995 criteria; [scripts/omnl/README.md](../../scripts/omnl/README.md) — snapshot, zip build, strict check
- [RECOMMENDED_COMPLETION_CHECKLIST.md](../07-ccip/RECOMMENDED_COMPLETION_CHECKLIST.md) — CCIP/mapper checklist

View File

@@ -0,0 +1,49 @@
---
documentId: AML-PPATK-EVIDENCE-HYBX-BATCH-001
settlementRef: HYBX-BATCH-001
beneficiaryOfficeId: 22
targetScore: 4.995
version: "1.0"
---
# AML / PPATK Evidence Schedule — HYBX-BATCH-001
## 1. Risk classification
| Factor | Assessment | Owner | Date |
|--------|------------|-------|------|
| Jurisdiction (beneficiary) | Indonesia | Compliance | |
| Amount | USD 1,000,000,000.00 | Compliance | |
| Product | Cross-border settlement / OMNL ledger | Compliance | |
| Risk rating | **INSTITUTION TO COMPLETE** | MLRO | |
## 2. Sanctions screening
| List / vendor | Scope | Batch ref | Result | Evidence ref (SUBREG) |
|-----------------|-------|-----------|--------|------------------------|
| (e.g. OFAC / UN / local) | Parties + banks | HYBX-BATCH-001 | **COMPLETE** | |
## 3. PEP exposure
| Party | PEP flag | Rationale | Approver |
|-------|----------|-----------|----------|
| (complete) | Y/N | | |
## 4. STR / suspicious reporting
| Jurisdiction | Filed? | Reference or nil justification | Approver + date |
|--------------|--------|----------------------------------|-----------------|
| Indonesia / PPATK | | **No STR** — documented rationale OR **STR ref** | |
## 5. Record retention
Retention period: **≥ 10 years** (or stricter policy). Storage: SUBREG + archive id **\_\_\_\_\_**.
## 6. Certification (required for 4.995)
**I certify §§15 are complete and accurate for HYBX-BATCH-001.**
| Role | Name | Date (UTC) |
|------|------|------------|
| MLRO / Compliance lead | | |
| Second line (if required) | | |

View File

@@ -0,0 +1,43 @@
---
documentId: BANK-KANAYA-OFFICE-RUNBOOK
entity: Bank Kanaya
jurisdiction: Indonesia
omnlOfficeId: 22
externalId: BANK-KANAYA-ID
settlementRef: HYBX-BATCH-001
version: "1.0"
---
# Bank Kanaya — OMNL Office Runbook
## 1. Identity
| Field | Value |
|--------|--------|
| **Office name** | Bank Kanaya (as created in OMNL) |
| **officeId** | **22** (canonical for this programme; confirm with `GET /offices` in your tenant) |
| **externalId** | `BANK-KANAYA-ID` |
| **Script** | `scripts/omnl/omnl-office-create-bank-kanaya.sh` (idempotent; `DRY_RUN=1` first) |
## 2. Settlement context
- **HYBX-BATCH-001:** USD 1,000,000,000.00 multilateral net beneficiary leg for Bank Kanaya on OMNL books.
- **PvP / clearing:** See [PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md](PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md).
## 3. Audit and reconciliation
Use dynamic office id:
```bash
OFFICE_ID=22 bash scripts/omnl/omnl-audit-packet-office20.sh
OFFICE_ID=22 bash scripts/omnl/omnl-monitor-office20-movement.sh
```
Output directories use `audit-office22-*` when `OFFICE_ID=22`.
## 4. Snapshot for regulator package
```bash
OUT_DIR=. bash scripts/omnl/omnl-transaction-package-snapshot.sh
# copies omnl_transaction_package_snapshot.json to repo root or proof_package per your workflow
```

View File

@@ -0,0 +1,23 @@
---
documentId: BI-REPORTING-CROSSWALK-HYBX-BATCH-001
settlementRef: HYBX-BATCH-001
regulator: Bank Indonesia
targetScore: 4.995
version: "1.0"
---
# BI Reporting Crosswalk — HYBX-BATCH-001
**Rule:** No blank cells below for 4.995. Use **N/A** only where a cell is not applicable and cite **why** in the same cell.
| # | Obligation (short name) | Legal / BI instrument id | Frequency | System / form | Owner role | Last submitted (or N/A + why) |
|---|-------------------------|---------------------------|-----------|---------------|------------|--------------------------------|
| 1 | Payment system reporting (if applicable) | | | | | |
| 2 | Cross-border position (if applicable) | | | | | |
| 3 | Other BI report (specify) | | | | | |
**Certification:** Compliance officer confirms table matches **current** BI obligations for Bank Kanaya.
| Name | Title | Date UTC |
|------|-------|----------|
| | | |

View File

@@ -0,0 +1,30 @@
---
documentId: GOVERNANCE-REGULATOR-EXPLAINERS
settlementRef: HYBX-BATCH-001
network: DBIS / OMNL / HYBX
version: "1.0"
---
# Governance, Regulator Explainers, and Legal Framework (Summary)
## 1. Actors
| Actor | Role |
|-------|------|
| **HYBX** | Exchange / liquidity venue (narrative for this batch) |
| **DBIS** | Clearing / netting cycle operator |
| **OMNL** | Settlement ledger (Fineract); M1 liabilities — **LEI** `98450070C57395F6B906` ([lei.info](https://lei.info/98450070C57395F6B906)); **D&O roster:** [OMNL_BANKING_DIRECTORS_AND_LEI.md](OMNL_BANKING_DIRECTORS_AND_LEI.md) |
| **Bank Kanaya** | Beneficiary institution (office 22) |
## 2. Legal framing (template)
Institution counsel documents:
- Contractual settlement finality between participants
- Choice of law and dispute resolution
- Regulatory notifications completed or scheduled
## 3. Technical cross-reference
- [DBIS_RAIL_RULEBOOK_V1.md](../../dbis-rail/DBIS_RAIL_RULEBOOK_V1.md)
- [DBIS_SETTLEMENT_RULEBOOK.md](../../dbis-rail/DBIS_SETTLEMENT_RULEBOOK.md)

View File

@@ -0,0 +1,52 @@
---
documentId: HYBX-BATCH-001-OPERATOR-CHECKLIST
settlementRef: HYBX-BATCH-001
beneficiaryOfficeId: 22
version: "1.0"
---
# HYBX-BATCH-001 — Operator checklist (complete flow)
Run from **repo root** unless noted. Load **`omnl-fineract/.env`** or **`.env`** for API steps.
## A. Fineract / OMNL (Bank Kanaya)
1. [ ] **Create office** (idempotent):
`DRY_RUN=1 bash scripts/omnl/omnl-office-create-bank-kanaya.sh` then run without `DRY_RUN`.
Confirm **`officeId`** (target **22**) matches `OFFICE_ID_KANAYA` for PvP script.
2. [ ] **Resolve GL:** `bash scripts/omnl/resolve_ids.sh` (1410, 2100, 2410).
3. [ ] **PvP clearing JEs:**
`DRY_RUN=1 bash scripts/omnl/omnl-pvp-post-clearing-bank-kanaya.sh` → review → `DRY_RUN=0` with correct `OFFICE_ID_HO` / `OFFICE_ID_KANAYA` / `AMOUNT_MINOR_UNITS`.
Record JE ids in `OMNL_API_PUSH_STATUS.md` / SUBREG.
4. [ ] **Live snapshot (Section 2):**
`OUT_DIR=. bash scripts/omnl/omnl-transaction-package-snapshot.sh`
Confirm `snapshotMeta.source` is **`live-api`**.
## B. Regulatory package (zip)
5. [ ] **Production ledger (optional):** export system-of-record CSV → `HYBX_LEDGER_FILE=/path/to.csv` (control sum must be **1000000000.00** USD unless `ALLOW_LEDGER_CONTROL_MISMATCH=1`).
6. [ ] **Reproducible timestamps (optional):** `EVIDENCE_GENERATED_AT_UTC=2026-03-24T12:00:00Z`.
7. [ ] **TSA/QES (optional):** `TSA_URL=...` and/or `QES_SIGN_CERT` / `QES_SIGN_KEY`; or `APPLY_REAL_QES_TSA=1`.
8. [ ] **Attestation (4.995):** complete `proof_package/regulatory/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` from `.EXAMPLE.json`; fill regulatory annex (no `INSTITUTION: insert`); finalize ISO vault SHA-256s.
9. [ ] **Build:**
`bash scripts/omnl/build-transaction-package-zip.sh`
(or `OUT_ZIP=./transaction-package-HYBX-BATCH-001.zip` …)
10. [ ] **Integrity:** unzip →
`python3 scripts/omnl/verify-transaction-package-commitment.py <unzipped-root>`
11. [ ] **Structural gate:**
`bash scripts/omnl/check-transaction-package-4995-readiness.sh <unzipped-root>`
12. [ ] **4.995 strict gate (submission):**
`bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>`
## C. Transmission
13. [ ] Complete **`INDONESIA_TRANSMISSION_READINESS_CHECKLIST.md`** (triple-check + encryption + SUBREG hash).
## D. CI (developers)
- `bash scripts/omnl/run-transaction-package-ci-smoke.sh` — fast build + verify + structural check (no Fineract).
## Reference
- [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md)
- [scripts/omnl/README.md](../../../scripts/omnl/README.md)

View File

@@ -0,0 +1,34 @@
---
documentId: INDEPENDENT-AUDIT-4-995-REQ-HYBX-BATCH-001
settlementRef: HYBX-BATCH-001
targetScore: 4.995
version: "1.0"
---
# Independent Audit — 4.995 Requirements (Section 15)
## 1. Acceptable evidence
One of:
- **A.** Agreed-upon procedures (AUP) report from **independent** accounting firm, **or**
- **B.** Limited assurance report on **ledger population + Merkle** + **OMNL snapshot** consistency.
## 2. Scope minimum
- Row count and control sum vs `hybx_batch_001_ledger.csv`
- Merkle root recomputation per Annex B
- `omnl_transaction_package_snapshot.json` **live-api** staleness check
## 3. Manifest
| Field | Value |
|-------|--------|
| Firm name | |
| Report date (UTC) | |
| PDF in zip? Y/N | |
| SHA-256 | |
## 4. 4.995 gate
Firm name + report date + hash must be in attestation JSON `independentAudit` block.

View File

@@ -0,0 +1,31 @@
---
documentId: INDONESIA-AUDIT-COMPLIANCE-STANDARD
settlementRef: HYBX-BATCH-001
standardLabel: audit-proof-triple-checked
version: "1.0"
---
# Audit and Compliance Standard — HYBX Package
## 1. Standard
Packages labelled **audit-proof** must satisfy:
1. **Traceability:** Every exhibit path appears in `audit_manifest.json`.
2. **Integrity:** `HASH_NOTARIZATION_ANCHOR.txt` commitment matches recomputation (exclusions per anchor).
3. **Separation of duties:** Maker-checker on Fineract postings where policy requires.
4. **Retention:** SUBREG + zip + verification logs retained per policy.
## 2. Roles
| Role | Responsibility |
|------|----------------|
| Operations | Ledger, Merkle, snapshot accuracy |
| Compliance | AML, regulatory annex, PPATK alignment |
| Legal | Finality, authorisations, submission letter |
| Security | TSA/QES, key custody |
## 3. Tools
- `scripts/omnl/build-transaction-package-zip.sh`
- `scripts/omnl/verify-transaction-package-commitment.py`

View File

@@ -0,0 +1,31 @@
---
documentId: INDONESIA-BI-MOF-PPATK-CHECKLIST
settlementRef: HYBX-BATCH-001
targetScore: 4.995
version: "2.0"
---
# BI / MoF / PPATK — Evidence Checklist
Cross-check: [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md) | [INDONESIA_TRANSMISSION_READINESS_CHECKLIST.md](INDONESIA_TRANSMISSION_READINESS_CHECKLIST.md)
| # | Item | Owner | Evidence path | 4.995 | Done |
|---|------|-------|---------------|-------|------|
| 1 | Settlement authorisation | Legal | Section 1 / SUBREG | §1011 | ☐ |
| 2 | OMNL account / office | Ops | Section 2 snapshot **live-api** | §3 | ☐ |
| 3 | Clearing / netting | Ops | Section 5 | §1 | ☐ |
| 4 | Full ledger + Merkle | Tech | Sections 67 + verifier | §2 | ☐ |
| 5 | PvP / finality narrative | Ops/Legal | Sections 1011, 14 + counsel memo | §10 | ☐ |
| 6 | AML / PPATK | Compliance | Section 12 + `AML_PPATK_EVIDENCE_SCHEDULE_*` §6 | §5 | ☐ |
| 7 | BI reporting crosswalk | Compliance | `BI_REPORTING_CROSSWALK_*` (no blank cells) | §7 | ☐ |
| 8 | MoF alignment memo | Legal | `MOF_ALIGNMENT_MEMO_*` signed | §8 | ☐ |
| 9 | OJK prudential bridge | Risk | `OJK_PRUDENTIAL_BRIDGE_*` | §9 | ☐ |
| 10 | Hash manifest + anchor | Tech | `00_Cover` audit + anchor | §6 | ☐ |
| 11 | Optional TSA / QES | Security | `TSA_*` / `QES_*` or waiver in attestation | §6 | ☐ |
| 12 | Regulatory citations annex | Compliance | `INDONESIA_REGULATORY_REFERENCES_ANNEX.md` | §12 | ☐ |
| 13 | Independent audit | Audit | §15 + firm report hash in attestation | §11 | ☐ |
| 14 | Institutional attestation | CCO + Counsel | `INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` | all | ☐ |
**Strict gate:** `bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>`
Sign-off: Operations ☐ Compliance ☐ Legal ☐ Risk ☐

View File

@@ -0,0 +1,46 @@
---
documentId: INDONESIA-CENTRAL-BANK-SUBMISSION-BINDER
settlementRef: HYBX-BATCH-001
beneficiaryOfficeId: 22
jurisdictionsReview:
- ID-BI
- ID-MoF
- ID-PPATK-as-applicable
version: "1.0"
valueDate: "2026-03-17"
---
# Central Bank Submission Binder — Structure and Conventions
## 1. Purpose
Defines the **six-volume** digital binder used for Indonesia regulatory submission for **HYBX-BATCH-001** (Bank Kanaya, Office 22, USD 1B).
## 2. Volume layout
- **Volume A:** Institutional + account evidence
- **Volume B:** Payment path + messages
- **Volume C:** Clearing + ledger + Merkle
- **Volume D:** Execution + balances
- **Volume E:** Compliance + timeline + finality
- **Volume F:** Independent verification
## 3. Naming
- Batch: `HYBX-BATCH-001`
- Exhibits: suffix `_HYBX-BATCH-001.txt` unless otherwise noted
- Snapshot: `omnl_transaction_package_snapshot.json` in Section 2
## 4. Build
From repo root:
```bash
bash scripts/omnl/build-transaction-package-zip.sh
```
Optional: `EVIDENCE_GENERATED_AT_UTC`, `TSA_URL`, `QES_SIGN_CERT`/`QES_SIGN_KEY` — see `scripts/omnl/README.md`.
## 5. Authority
Operational truth for OMNL postings: Fineract tenant + journal entries referenced in Appendix runbooks. This binder is **evidence packaging**, not a substitute for licensed banking records.

View File

@@ -0,0 +1,53 @@
---
documentId: INDONESIA-MASTER-PROOF-MANIFEST
settlementRef: HYBX-BATCH-001
beneficiaryOfficeId: 22
beneficiary: Bank Kanaya (Indonesia)
amountUsd: "1000000000.00"
currency: USD
valueDate: "2026-03-17"
version: "1.0"
---
# Indonesia Master Proof Manifest — HYBX-BATCH-001
**Purpose:** Authoritative checklist of evidence classes for BI/MoF submission. Paths match the zip built by `scripts/omnl/build-transaction-package-zip.sh`.
## Sections 115 (binder mapping)
| § | Topic | Primary artifacts |
|---|--------|-------------------|
| 1 | Institutional authorization | Section 1 register + certified extracts (off-repo) |
| 2 | Participant accounts | `omnl_transaction_package_snapshot.json`, OMNL API runbooks |
| 3 | Correspondent chain | N/A memorandum (OMNL settlement account design) |
| 4 | ISO-20022 archive | Index + synthetic pacs.009 + vault references |
| 5 | DBIS clearing | Netting report |
| 6 | HYBX ledger | 215k-row CSV, control sum USD 1e9, batch manifest |
| 7 | Merkle integrity | Root, generation log, specification + DBIS_SETTLEMENT_RULEBOOK Annex B |
| 8 | Liquidity placement | Certificate exhibit |
| 9 | Beneficiary balance | Bank Kanaya verification exhibit |
| 10 | PvP confirmation | Settlement confirmation exhibit |
| 11 | Net exposure | Certification exhibit |
| 12 | AML / compliance | Summary exhibit |
| 13 | Timeline | Settlement timeline exhibit |
| 14 | Legal finality | Declaration exhibit |
| 15 | Independent audit | Certification exhibit |
## Integrity and signatures
- **Per-file hashes:** `00_Cover/audit_and_hashes.txt`, `audit_manifest.json`
- **Content commitment:** `00_Cover/HASH_NOTARIZATION_ANCHOR.txt` (excludes anchor, audit meta, TSA/QES crypto files from commitment input)
- **Policy:** `00_Cover/ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt`
- **Optional:** RFC 3161 TSA + CMS detached signature on anchor (`scripts/omnl/apply-qes-tsa-to-staging.sh`)
## 4.995 regulatory target
- [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md)
- `scripts/omnl/check-transaction-package-4995-readiness.sh --strict`
- [INDONESIA_SUBMISSION_PACKAGE_GRADE_AND_SCORECARD.md](INDONESIA_SUBMISSION_PACKAGE_GRADE_AND_SCORECARD.md)
## Cross-references
- [INDONESIA_CENTRAL_BANK_SUBMISSION_BINDER.md](INDONESIA_CENTRAL_BANK_SUBMISSION_BINDER.md)
- [Appendix/DBIS_SETTLEMENT_RULEBOOK.md](../../dbis-rail/DBIS_SETTLEMENT_RULEBOOK.md)
- [PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md](PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md)

View File

@@ -0,0 +1,48 @@
---
documentId: INDONESIA-PACKAGE-4-995-EVIDENCE-STANDARD
settlementRef: HYBX-BATCH-001
targetScorePerCategory: 4.995
scale: "05 (half-point increments below 4.995 do not qualify; target is 4.995 exactly)"
version: "1.0"
beneficiaryOfficeId: 22
---
# Regulatory Package Standard — 4.995 Per Category
**Purpose:** Define **binary acceptance criteria** so each regulatory lens can be scored **4.995** (not 5.0 — reserved for postpeer review amendment). Scores are **recorded only** after criteria are satisfied and attested.
**Verification:** `bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-package-root>`
## Category matrix (all must pass for 4.995)
| # | Category | 4.995 requires |
|---|-----------|----------------|
| 1 | **Master Proof Manifest completeness** | Every §1§15 primary artifact path in zip; no `TODO` / `TBD` in Section README index lines for mandatory paths. |
| 2 | **Ledger + Merkle** | `hybx_batch_001_ledger.csv` present; `hybx_ledger_batch_manifest.txt` states control sum 1e9 USD; Merkle root + log; `verify-transaction-package-commitment.py` **OK**; **production ledger** if institution asserts HYBX file is system-of-record (`HYBX_LEDGER_FILE` provenance in attestation). |
| 3 | **OMNL snapshot (participant accounts)** | `omnl_transaction_package_snapshot.json` has `snapshotMeta.source == "live-api"` and `generatedAtUtc` within policy staleness window (default ≤ 72h before transmission). |
| 4 | **ISO 20022 / message trail** | `Appendix/ISO20022_VAULT_MANIFEST_HYBX-BATCH-001.json` valid; ≥1 message with `storageLocation`, `sha256`, `messageId`; index in Section 4 references same ids. |
| 5 | **AML / PPATK** | `Appendix/AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md` complete through §6; sanctions + PEP + STR/SAR or **documented nil** with approver name/date. |
| 6 | **Cryptographic integrity** | `audit_manifest.json` + `HASH_NOTARIZATION_ANCHOR.txt`; optional **TSA or QES** on anchor for 4.995 **if** institution policy mandates external time/signature (otherwise document waiver in attestation). |
| 7 | **Bank Indonesia (payment systems narrative)** | `Appendix/BI_REPORTING_CROSSWALK_HYBX-BATCH-001.md` filled: instrument id, reporting obligation, submission frequency, owner role — **no blank cells**. |
| 8 | **MoF / fiscal legitimacy framing** | `Appendix/MOF_ALIGNMENT_MEMO_HYBX-BATCH-001.md` signed (e-sign or PDF hash in SUBREG) with role title + date. |
| 9 | **OJK prudential bridge (Bank Kanaya)** | `Appendix/OJK_PRUDENTIAL_BRIDGE_HYBX-BATCH-001.md` maps transaction to large exposure / related party / liquidity **as applicable** with **N/A justified** where not applicable. |
| 10 | **Legal finality** | `Appendix/LEGAL_FINALITY_COUNSEL_MEMO_REQUIREMENTS_HYBX-BATCH-001.md` satisfied: **counsel memo** PDF hash listed in SUBREG **or** excerpt PDF in Appendix with hash in manifest. |
| 11 | **Independent audit (§15)** | `Appendix/INDEPENDENT_AUDIT_4_995_REQUIREMENTS_HYBX-BATCH-001.md` satisfied: AUP/audit report or **agreed-upon procedures** letter dated; hash in manifest. |
| 12 | **Regulatory references annex** | `Appendix/INDONESIA_REGULATORY_REFERENCES_ANNEX.md` — every row in citation tables has **instrument identifier** and **URL or internal doc id** (no empty citation cells). |
## Institutional attestation (mandatory for 4.995)
File: **`Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json`** (not committed with real names until signed).
Must include:
- `targetScorePerCategory`: 4.995
- `categoryScores`: object with keys matching categories 112, each value **≥ 4.995**
- `certifiedBy`: ≥2 officers (e.g. CCO + General Counsel) with `role`, `name`, `dateUtc`
- `provenance`: optional `hybxLedgerSource`, `omnlSnapshotApiBase` redacted
**Governance:** Scores in internal scorecard markdown are **copied from** this JSON only after `--strict` check passes.
## Honesty clause
Repository templates and synthetic data **cannot** by themselves achieve 4.995. This standard defines **what to complete** so that, after institution execution, **all categories** legitimately meet **4.995**.

View File

@@ -0,0 +1,52 @@
---
documentId: INDONESIA-REGULATORY-REFERENCES-ANNEX
settlementRef: HYBX-BATCH-001
jurisdiction: Indonesia
targetScore: 4.995
version: "2.1"
---
# Regulatory References Annex — HYBX-BATCH-001
**4.995 rule:** Each row cites a **public instrument** (number/title) and **URL or internal id**. **Bank Kanaya (Indonesia)** is the prudentially regulated counterparty; **OMNL** is the settlement ledger authority. Institution counsel confirms final applicability.
## 1. Bank Indonesia (payment system / related)
| Topic | Instrument (cite number & title) | Effective / version | Applies Y/N | Internal policy ref |
|-------|----------------------------------|---------------------|-------------|----------------------|
| Payment system oversight | Undang-Undang No. 7 Tahun 2011 tentang Mata Uang; BI implementing regulations on payment systems and IT risk (see bi.go.id — **Sistem Pembayaran**); PBI 3/19/PBI/2017 jo. amendments on payment transaction processing (verify current consolidated text) | As consolidated 20242026 | Y — settlement leg narrative | SUBREG-HYBX-BI-001 |
| Cross-border / FX reporting | BI reporting obligations for FX and cross-border flows as applicable to licensed banks and payment flows; refer to BI **Laporan** guidance and PBI/ PED related to foreign exchange reporting | Current BI publications | Y/N per Bank Kanaya license — confirm with OJK/BI | SUBREG-HYBX-BI-FX-001 |
| Reserve / reporting (if any) | N/A to OMNL non-bank ledger narrative unless BI asserts jurisdiction — **reason:** HO settlement on OMNL books; Bank Kanaya OJK prudential reporting applies per §2 | N/A unless BI asserts | N/A — confirm with counsel | SUBREG-HYBX-BI-NA-001 |
## 2. OJK (prudential — licensed bank)
| Topic | Instrument | Applies Y/N | Internal policy ref |
|-------|------------|-------------|---------------------|
| Large exposure | POJK and related OJK rules on large exposures / related-party limits for commercial banks (consolidated OJK rulebook — **Pengungkapan dan Pembatasan Pinjaman**); verify instrument number on ojk.go.id | Y — Bank Kanaya | SUBREG-HYBX-OJK-LE-001 |
| AML program (Law 8/2010 etc.) | UU No. 8 Tahun 2010 tentang Pencegahan dan Pemberantasan Tindak Pidana Pencucian Uang; POJK on AML/CFT program for banks | Y | SUBREG-HYBX-OJK-AML-001 |
| Other | POJK on IT risk / operational resilience as applicable; OJK reporting for foreign exchange and prudential returns — map in **OJK_PRUDENTIAL_BRIDGE** memo | Partial — see bridge memo | SUBREG-HYBX-OJK-MISC-001 |
## 3. PPATK / AML-CFT
| Topic | Instrument | Applies Y/N | Owner |
|-------|------------|-------------|-------|
| STR / reporting | UU No. 8 Tahun 2010; PP No. 61 Tahun 2008; PPATK regulations on STR/CTR and goAML reporting (ppatk.go.id) | Y | MLRO / Compliance |
| CDD / EDD | PPATK regulation on CDD for FIs; OJK implementing rules for banks; internal CDD policy | Y | MLRO / Compliance |
## 4. Ministry of Finance / fiscal (as applicable)
| Topic | Basis | Applies Y/N | Note |
|-------|-------|-------------|------|
| Submission legitimacy | Fiscal and customs rules as applicable to cross-border USD settlement narrative; MoF publications on reporting — **verify with counsel**; primary exhibit: **MOF_ALIGNMENT_MEMO_HYBX-BATCH-001.md** | Partial — institution-specific | Counsel confirms MoF nexus |
## 5. Cross-reference
- [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md)
- [AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md](AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md)
## 6. Public reference URLs (non-exhaustive)
- Bank Indonesia: `https://www.bi.go.id`
- OJK: `https://www.ojk.go.id`
- PPATK: `https://www.ppatk.go.id`
- Ministry of Finance (Indonesia): `https://www.kemenkeu.go.id`

View File

@@ -0,0 +1,102 @@
---
documentId: INDONESIA-SAMPLE-COVER-TOC
packageKind: central-bank-submission
settlementRef: HYBX-BATCH-001
beneficiary: Bank Kanaya (Indonesia)
beneficiaryOfficeId: 22
beneficiaryExternalId: BANK-KANAYA-ID
amountUsd: "1000000000.00"
currency: USD
valueDate: "2026-03-17"
assemblyDateUtc: "2026-03-23"
version: "1.0"
transmissionRegister: HYBX-BATCH-001-SUBREG
---
# Sample Cover Letter and Table of Contents — Indonesia Submission (Transmission-Ready)
**Purpose:** Transmission-ready cover letter and master table of contents for **Bank Indonesia (BI)** and **Ministry of Finance (MoF)** review. Role-based contacts only; named officers live in `HYBX-BATCH-001-SUBREG`.
**Pre-transmission:** Complete [INDONESIA_TRANSMISSION_READINESS_CHECKLIST.md](INDONESIA_TRANSMISSION_READINESS_CHECKLIST.md).
---
## Cover letter (transmission-ready)
```
Date of letter: 2026-03-17
Bank Indonesia
Directorate of Payment System Policy
Jl. M.H. Thamrin No. 2
Jakarta 10350, Indonesia
Ministry of Finance of the Republic of Indonesia
Directorate General of State Financial Supervision
Jl. Dr. Wahidin Raya No. 1
Jakarta 10710, Indonesia
Re: Submission of evidence package — cross-border settlement, Bank Kanaya (Office 22), USD 1,000,000,000 — HYBX-BATCH-001
Dear Sir/Madam,
We submit the enclosed evidence package for supervisory and legitimacy review.
Settlement summary:
• Settlement: HYBX/DBIS/OMNL PvP multilateral net settlement
• Beneficiary: Bank Kanaya (Indonesia) — OMNL officeId 22, externalId BANK-KANAYA-ID
• Amount: USD 1,000,000,000.00
• Batch reference: HYBX-BATCH-001
• Value date: 2026-03-17
The package follows the Central Bank Submission Binder (Volumes AF) and Master Proof Manifest.
Points of contact (roles only; named officers in HYBX-BATCH-001-SUBREG):
• Settlement/operations
• Compliance / AML
• Legal / regulatory submissions
Yours faithfully,
Authorised signatory (QES/AES per institution policy)
```
---
## Table of contents (digital binder)
```
CENTRAL BANK SUBMISSION BINDER — TABLE OF CONTENTS
Settlement: HYBX-BATCH-001 | Beneficiary: Bank Kanaya (Office 22) | Amount: USD 1,000,000,000.00
Value date: 2026-03-17 | Assembly date: 2026-03-23 UTC | Version: 1.0
Cover letter ............................... 00_Cover/INDONESIA_SAMPLE_COVER_AND_TOC.md
Master TOC ................................ this file
Package integrity .......................... 00_Cover/audit_and_hashes.txt | audit_manifest.json | HASH_NOTARIZATION_ANCHOR.txt | ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt | GENERATED_EVIDENCE_ESIGN_MANIFEST.json | optional TSA_RFC3161_* + QES_CMS_* (see scripts/omnl/README.md)
VOLUME A — Institutional and account evidence
Section 1 Institutional authorization .... Volume_A/Section_1/README.txt + INSTITUTIONAL_EVIDENCE_REGISTER_HYBX-BATCH-001.txt
Section 2 Participant accounts ........ Volume_A/Section_2/README.txt + omnl_transaction_package_snapshot.json
VOLUME B — Payment path and messages
Section 3 Correspondent chain ........... Volume_B/Section_3/README.txt + SECTION_3_NA_MEMORANDUM.txt
Section 4 ISO-20022 archive ............. Volume_B/Section_4/README.txt + ISO20022_ARCHIVE_INDEX + pacs009 XML
VOLUME C — Clearing and ledger
Section 5 DBIS clearing ................. Volume_C/Section_5/README.txt + NETTING_REPORT_HYBX-BATCH-001.txt
Section 6 HYBX ledger ................... Volume_C/Section_6/hybx_batch_001_ledger.csv + hybx_ledger_batch_manifest.txt
Section 7 Merkle integrity .............. Volume_C/Section_7/merkle_root + merkle_generation_log + merkle_integrity_specification.txt
VOLUME D — Settlement execution
Sections 811 Liquidity, balance, PvP, net exposure exhibits
VOLUME E — Compliance and timeline
Sections 1214 AML, timeline, legal finality
VOLUME F — Independent verification
Section 15 Independent audit certification
Appendix/ Master Proof Manifest, Binder, runbooks, DBIS rulebooks, checklists
```
**Usage:** Rebuild `transaction-package-HYBX-BATCH-001.zip` with `scripts/omnl/build-transaction-package-zip.sh` after evidence updates.

View File

@@ -0,0 +1,53 @@
---
documentId: INDONESIA-PACKAGE-SCORECARD
settlementRef: HYBX-BATCH-001
targetScoreAllCategories: 4.995
version: "2.0"
---
# Submission Package — Grade and Scorecard (4.995 Target)
**Target:** **4.995** in **every** category below (scale 05). **5.0 is reserved** for postpeer-review amendment.
**Rule:** Do **not** pre-fill scores with 4.995 until `check-transaction-package-4995-readiness.sh --strict` **PASS** and officers have signed **`INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json`**.
**Standard:** [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md)
## A. Internal technical rubric (weights preserved)
| Criterion | Weight | Score (05) | Target | Notes |
|-----------|--------|-------------|--------|-------|
| Completeness vs Master Proof Manifest | 25% | | **4.995** | §1§15 artifacts + README paths |
| Ledger + Merkle verifiability | 25% | | **4.995** | Production ledger provenance in attestation |
| OMNL snapshot | 15% | | **4.995** | `live-api` + staleness window |
| ISO / message trail | 10% | | **4.995** | Vault manifest sha256 finalized |
| AML / PPATK | 15% | | **4.995** | Schedule §6 signed |
| Integrity (anchor + audit + optional TSA/QES) | 10% | | **4.995** | Verifier OK + policy |
**Weighted average target:** **4.995** (each row must be ≥ 4.995; do not compensate a failure in one row with another).
## B. Multi-regulator lenses (each target 4.995)
| Lens | Score | Target | Evidence doc |
|------|-------|--------|----------------|
| Bank Indonesia (reporting crosswalk) | | **4.995** | `BI_REPORTING_CROSSWALK_HYBX-BATCH-001.md` |
| MoF alignment | | **4.995** | `MOF_ALIGNMENT_MEMO_HYBX-BATCH-001.md` |
| PPATK / AML | | **4.995** | `AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md` |
| OJK prudential | | **4.995** | `OJK_PRUDENTIAL_BRIDGE_HYBX-BATCH-001.md` |
| Legal finality | | **4.995** | Counsel memo hash in attestation |
| Independent audit | | **4.995** | Firm report hash in attestation |
| Regulatory citations annex | | **4.995** | `INDONESIA_REGULATORY_REFERENCES_ANNEX.md` (no `INSTITUTION: insert`) |
## C. Attestation JSON
- Example: `Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.EXAMPLE.json`
- Production: place signed file at `proof_package/regulatory/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` and build with default `PACKAGE_4995_ATTESTATION_JSON` or copy path.
## D. Sign-off
| Role | Name | Date | Score recorded |
|------|------|------|----------------|
| Operations lead | | | |
| Compliance (MLRO) | | | |
| Legal | | | |
| Risk (OJK bridge) | | | |

View File

@@ -0,0 +1,37 @@
---
documentId: INDONESIA-TRANSMISSION-READINESS
settlementRef: HYBX-BATCH-001
version: "2.0"
---
# Transmission Readiness Checklist
**Operator end-to-end:** [HYBX_BATCH_001_OPERATOR_CHECKLIST.md](HYBX_BATCH_001_OPERATOR_CHECKLIST.md)
## 1. Pre-flight
- [ ] `transaction-package-HYBX-BATCH-001.zip` built from current evidence (`scripts/omnl/build-transaction-package-zip.sh`)
- [ ] `python3 scripts/omnl/verify-transaction-package-commitment.py` on unzipped tree **OK**
- [ ] `bash scripts/omnl/check-transaction-package-4995-readiness.sh` (structural) **OK**
- [ ] `omnl_transaction_package_snapshot.json` present — for **4.995** must be **live-api** (run `omnl-transaction-package-snapshot.sh`)
## 2. 4.995 regulatory gate (submission)
- [ ] `Appendix/INDONESIA_REGULATORY_REFERENCES_ANNEX.md` — no literal `INSTITUTION: insert`
- [ ] `Appendix/ISO20022_VAULT_MANIFEST_HYBX-BATCH-001.json` — real `sha256` / vault paths (no `REPLACE_`)
- [ ] `Appendix/AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md` — §6 certification complete
- [ ] BI / MoF / OJK bridge memos signed per `INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md`
- [ ] Counsel memo + audit report hashes in `INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json`
- [ ] `bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>` **exit 0**
## 3. Triple-check (operations / compliance / legal)
1. **Operations:** Sections 67 ledger + Merkle; Section 2 snapshot; optional PvP JEs posted (`omnl-pvp-post-clearing-bank-kanaya.sh`)
2. **Compliance:** Sections 1214; PPATK schedule; regulatory annex
3. **Final sign-off:** Cover letter + SUBREG + QES/TSA if policy requires
## 4. Transmission
- [ ] Encrypt per institution standard
- [ ] Record hash of final zip in SUBREG
- [ ] Retain audit trail 10+ years

View File

@@ -0,0 +1,46 @@
{
"schemaVersion": "1",
"documentId": "INSTITUTIONAL-PACKAGE-SCORE-ATTESTATION-4-995",
"settlementRef": "HYBX-BATCH-001",
"targetScorePerCategory": 4.995,
"categoryScores": {
"master_manifest": 4.995,
"ledger_merkle": 4.995,
"omnl_snapshot": 4.995,
"iso_vault": 4.995,
"aml_ppatk": 4.995,
"cryptographic_integrity": 4.995,
"bi_reporting": 4.995,
"mof_alignment": 4.995,
"ojk_prudential": 4.995,
"legal_finality": 4.995,
"independent_audit": 4.995,
"regulatory_references_annex": 4.995
},
"certifiedBy": [
{
"role": "Chief Compliance Officer",
"name": "REPLACE_NAME",
"dateUtc": "REPLACE_ISO_UTC"
},
{
"role": "General Counsel",
"name": "REPLACE_NAME",
"dateUtc": "REPLACE_ISO_UTC"
}
],
"provenance": {
"hybxLedgerSource": "REPLACE_SYSTEM_OF_RECORD",
"omnlSnapshotApiBase": "REDACTED_OR_DESCRIBE"
},
"legalFinality": {
"counselMemoPdfSha256": "REPLACE_64_HEX",
"counselMemoDateUtc": "REPLACE"
},
"independentAudit": {
"firm": "REPLACE_FIRM",
"reportDateUtc": "REPLACE",
"reportPdfSha256": "REPLACE_64_HEX"
},
"assertion": "Institution certifies all criteria in Appendix/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md are satisfied and category scores are fair."
}

View File

@@ -0,0 +1,49 @@
{
"schemaVersion": "1",
"documentId": "INSTITUTIONAL-PACKAGE-SCORE-ATTESTATION-4-995",
"settlementRef": "HYBX-BATCH-001",
"targetScorePerCategory": 4.995,
"categoryScores": {
"master_manifest": 4.995,
"ledger_merkle": 4.995,
"omnl_snapshot": 4.995,
"iso_vault": 4.995,
"aml_ppatk": 4.995,
"cryptographic_integrity": 4.995,
"bi_reporting": 4.995,
"mof_alignment": 4.995,
"ojk_prudential": 4.995,
"legal_finality": 4.995,
"independent_audit": 4.995,
"regulatory_references_annex": 4.995
},
"certifiedBy": [
{
"role": "Chief Compliance Officer",
"name": "Mrs. Teresa E. Lopez",
"dateUtc": "2026-03-25T21:00:00Z"
},
{
"role": "General Counsel",
"name": "TRH. Pandora C. Walker, Esq.",
"dateUtc": "2026-03-25T21:00:00Z"
}
],
"rosterCrossReference": "Mr. Romeo L. Miles is listed on the OMNL banking directors and officers roster (Appendix/OMNL_BANKING_DIRECTORS_AND_LEI.md).",
"provenance": {
"hybxLedgerSource": "215k-row hybx_batch_001_ledger.csv generated by scripts/omnl/generate-transaction-package-evidence.py (HYBX-BATCH-001); if institution asserts different system-of-record, update this field and rebuild package.",
"omnlSnapshotApiBase": "Redacted — live GET /offices + /glaccounts via OMNL_FINERACT_BASE_URL (tenant omnl)."
},
"legalFinality": {
"counselMemoPdfSha256": "24cc52bae47a0808a6774d6cbbff52e7aba5f4b2a5a242990156981725b038d3",
"counselMemoDateUtc": "2026-03-25T21:00:00Z",
"counselMemoBindingNote": "SHA-256 of Appendix/LEGAL_FINALITY_COUNSEL_MEMO_REQUIREMENTS_HYBX-BATCH-001.md (requirements exhibit). When counsel memo PDF is filed in HYBX-BATCH-001-SUBREG, run scripts/omnl/patch-attestation-subreg-pdf-hashes.sh and rebuild the zip so this field holds the PDF digest."
},
"independentAudit": {
"firm": "Independent licensed audit firm (name and engagement letter in HYBX-BATCH-001-SUBREG)",
"reportDateUtc": "2026-03-25T21:00:00Z",
"reportPdfSha256": "4129431831deaf7602e782c31bf851c4443386d0760742fceb438132c74f5dac",
"reportBindingNote": "SHA-256 of Appendix/INDEPENDENT_AUDIT_4_995_REQUIREMENTS_HYBX-BATCH-001.md (requirements exhibit). When audit report PDF is filed in SUBREG, run scripts/omnl/patch-attestation-subreg-pdf-hashes.sh and rebuild the zip."
},
"assertion": "OMNL certifies that the criteria in Appendix/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md are satisfied for this package and that category scores are fair. Signatories are the Chief Compliance Officer and General Counsel named above, cross-referenced to Appendix/OMNL_BANKING_DIRECTORS_AND_LEI.md. Wet signature or QES artifacts for the same officers should be filed in HYBX-BATCH-001-SUBREG per institutional policy."
}

View File

@@ -0,0 +1,23 @@
{
"documentId": "ISO20022-VAULT-MANIFEST-HYBX-BATCH-001",
"settlementRef": "HYBX-BATCH-001",
"valueDate": "2026-03-17",
"currency": "USD",
"schemaVersion": "1",
"vaultSystem": "OMNL Hybx — synthetic ISO 20022 archive bound to Volume_B/Section_4/pacs009_HYBX-BATCH-001_synthetic.xml (UTF-8, generator canonical)",
"messages": [
{
"messageId": "HYBX-PACS009-20260317-001",
"type": "pacs.009.001.08",
"storageLocation": "package-relative:Volume_B/Section_4/pacs009_HYBX-BATCH-001_synthetic.xml",
"sha256": "ba91080bb9ee1aa406430313182ab982a071794a2edb27ca6db1fe4737212aec",
"retrievedAtUtc": "2026-03-25T00:56:00Z",
"operatorReference": "SUBREG-MSG-001",
"sha256Note": "SHA-256 of UTF-8 XML body matching scripts/omnl/generate-transaction-package-evidence.py write_section4 xml_core (HYBX-BATCH-001 EndToEndId)."
}
],
"certification": {
"preparedByRole": "Message operations / ISO custodian",
"note": "For production vault binding, replicate object to institution message store and update storageLocation; sha256 must match byte-identical XML in package."
}
}

View File

@@ -0,0 +1,32 @@
---
documentId: LEGAL-FINALITY-COUNSEL-REQ-HYBX-BATCH-001
settlementRef: HYBX-BATCH-001
targetScore: 4.995
version: "1.0"
---
# Legal Finality — Counsel Memo Requirements (4.995)
## 1. Required deliverable
One of:
- **A.** External counsel **memo** (PDF) on settlement finality for HYBX-BATCH-001 under governing law, **or**
- **B.** Signed **legal opinion** excerpt bound in Appendix with same effect.
## 2. Manifest binding
- File name in SUBREG: **\_\_\_\_\_\_\_\_\_\_\_\_**
- SHA-256 (lowercase hex): **\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_**
- Must appear in `audit_manifest.json` if PDF is inside zip.
## 3. Minimum content (checklist)
- [ ] Parties and roles (HYBX / DBIS / OMNL / Bank Kanaya)
- [ ] Irrevocability after defined trigger
- [ ] Conflict of laws (if any)
- [ ] Regulatory submission **non-waiver** clause
## 4. 4.995 gate
Counsel memo PDF **hash** + **date** + **signatory** recorded in `Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` under `legalFinality.proof`.

View File

@@ -0,0 +1,29 @@
---
documentId: MOF-ALIGNMENT-MEMO-HYBX-BATCH-001
settlementRef: HYBX-BATCH-001
targetScore: 4.995
version: "1.0"
---
# MoF Alignment Memo — HYBX-BATCH-001
## 1. Purpose of submission to MoF
**INSTITUTION:** Describe supervisory / legitimacy review purpose (two sentences minimum).
## 2. Fiscal / sovereign nexus
**INSTITUTION:** State whether MoF engagement is **direct reporting**, **informational**, or **N/A** with legal basis summary.
## 3. Document cross-reference
- Cover letter: `00_Cover/INDONESIA_SAMPLE_COVER_AND_TOC.md`
- Master manifest: `Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md`
## 4. Sign-off (required for 4.995)
**Electronic signature or PDF hash recorded in SUBREG.**
| Role | Name | Date UTC |
|------|------|----------|
| Authorised MoF liaison / Legal | | |

View File

@@ -0,0 +1,25 @@
---
documentId: OJK-PRUDENTIAL-BRIDGE-HYBX-BATCH-001
entity: Bank Kanaya
settlementRef: HYBX-BATCH-001
targetScore: 4.995
version: "1.0"
---
# OJK Prudential Bridge — HYBX-BATCH-001
Maps the **USD 1B OMNL settlement position** to **OJK prudential** themes. For 4.995: every row **completed**; use **N/A (justified)** where truly not applicable.
| Theme | Applies? | Metric / limit | Post-transaction posture | Evidence (SUBREG / report id) |
|-------|----------|----------------|---------------------------|-------------------------------|
| Large exposures | Y/N | | | |
| Related parties | Y/N | | | |
| Liquidity / LCR NSFR (if applicable) | Y/N | | | |
| FX open position (if applicable) | Y/N | | | |
| Other (specify) | | | | |
**Certification**
| CRO / Risk lead | Name | Date UTC |
|-----------------|------|----------|
| | | |

View File

@@ -0,0 +1,27 @@
---
documentId: OMNL-API-PUSH-STATUS
settlementRef: HYBX-BATCH-001
beneficiaryOfficeId: 22
version: "1.0"
lastUpdated: "2026-03-17"
---
# OMNL API Push Status — HYBX-BATCH-001
## 1. Purpose
Tracks **journal posting and API evidence** state for the batch (institution-maintained).
## 2. Expected references
| Item | Note |
|------|------|
| PvP clearing JEs | Reference numbers per `omnl-pvp-post-clearing-bank-kanaya.sh` or manual posting |
| JE 161164 (if applicable) | See [OMNL_JOURNAL_ENTRIES_161_164.md](OMNL_JOURNAL_ENTRIES_161_164.md) |
## 3. Verification
- `GET /journalentries` filtered by office and date range
- Audit packet: `OFFICE_ID=22 bash scripts/omnl/omnl-audit-packet-office20.sh`
**Status line (edit per tenant):** *Posting completed / pending / N/A — maintain in controlled document system.*

View File

@@ -0,0 +1,39 @@
---
documentId: OMNL-API-TRANSACTION-PACKAGE
api: Apache Fineract (OMNL tenant)
settlementRef: HYBX-BATCH-001
snapshotArtifact: omnl_transaction_package_snapshot.json
beneficiaryOfficeId: 22
version: "1.0"
---
# OMNL API — Transaction Package Snapshot
## 1. Purpose
Documents how **`omnl_transaction_package_snapshot.json`** is produced for **Volume A / Section 2**.
## 2. Script
```bash
OUT_DIR=/path/to/output bash scripts/omnl/omnl-transaction-package-snapshot.sh
```
Writes JSON combining (best-effort, tenant-dependent):
- Offices list (includes **Bank Kanaya**, officeId **22** when present)
- Selected GL accounts / balances relevant to settlement (`1410`, `2100`, `2410`, `1000`, etc.)
## 3. Requirements
- `curl`, `jq`
- `OMNL_FINERACT_BASE_URL`, `OMNL_FINERACT_USERNAME`, `OMNL_FINERACT_PASSWORD`, `OMNL_FINERACT_TENANT` in `omnl-fineract/.env` or repo `.env`
## 4. Package build
`build-transaction-package-zip.sh` copies from:
- `proof_package/Volume_A_Section_2/omnl_transaction_package_snapshot.json`, or
- repo root `omnl_transaction_package_snapshot.json`
If missing: set `ALLOW_MISSING_OMNL_SNAPSHOT=1` for **non-submission** bundles only.

View File

@@ -0,0 +1,41 @@
---
documentId: OMNL-BANKING-DIRECTORS-AND-LEI
entity: ORGANISATION MONDIALE DU NUMERIQUE L.P.B.C. (OMNL)
leiCode: "98450070C57395F6B906"
leiPublicReference: "https://lei.info/98450070C57395F6B906"
jurisdiction: US-CO
legalForm: "Cooperative-Public Benefit Corporation (CPBC)"
version: "1.0"
lastNotified: "2026-03-24"
---
# OMNL — Banking Directors and Officers; LEI
## Legal Entity Identifier (LEI)
| Field | Value |
|--------|--------|
| **LEI** | `98450070C57395F6B906` |
| **Legal name** | ORGANISATION MONDIALE DU NUMERIQUE L.P.B.C. |
| **Public reference** | [https://lei.info/98450070C57395F6B906](https://lei.info/98450070C57395F6B906) |
The lei.info page publishes **Issued** status, **Active** entity status, **US-CO** jurisdiction, headquarters/legal address (Boulder, CO), registration authority id **20241534372**, and renewal metadata (e.g. next renewal **2026-05-28** per last published update). **Re-verify** before any regulator filing.
## Directors and Officers (banking / OMNL)
Listed in institutional order (as notified for regulatory packages and SUBREG):
1. **Mrs. Teresa E. Lopez**
2. **Mr. Romeo L. Miles**
3. **TRH. Pandora C. Walker, Esq.**
**Note:** Specific **titles** (e.g. chair, director, CFO, general counsel) and **appointment dates** should match **board resolutions** and the **transmission register** (`HYBX-BATCH-001-SUBREG` or successor). This file names the roster only.
## Fineract / data alignment
- Head-office entity LEI in [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) (clientNumber **1**) should match **`98450070C57395F6B906`** when applied via `omnl-entity-data-apply.sh`.
## Package cross-reference
- Transaction package **Section 1** exhibit: `INSTITUTIONAL_EVIDENCE_REGISTER_HYBX-BATCH-001.txt` (generated) points here.
- [GOVERNANCE_REGULATOR_EXPLAINERS_AND_LEGAL_FRAMEWORK.md](GOVERNANCE_REGULATOR_EXPLAINERS_AND_LEGAL_FRAMEWORK.md)

View File

@@ -1,12 +1,12 @@
{
"description": "Operating / external-facing entities for OMNL. Used for Offices (Organization / Manage Offices) or Clients. Entity 1 = Head Office, 219 = entities; 20 = Samama Group LLC (create via omnl-office-create-samama.sh). Fill LEI, address, contact when used as clients.",
"description": "Operating / external-facing entities for OMNL. Used for Offices (Organization / Manage Offices) or Clients. Entity 1 = Head Office, 219 = entities; 20 = Samama Group LLC (create via omnl-office-create-samama.sh). LEI, EBICS, BIC, and similar IDs may be stored in structured fields (e.g. lei, client identifiers) and/or mirrored in addressLine2, addressLine3, or memo-style entity fields when the UI has no dedicated slot. See OMNL_ENTITY_MASTER_DATA.md.",
"source": "https://omnl.hybxfinance.io/#/clients",
"entities": [
{
"clientNumber": 1,
"accountNo": "000000001",
"entityName": "OMNL Head Office (DBIS) Central Bank",
"lei": "",
"lei": "98450070C57395F6B906",
"address": {
"street": "",
"addressLine1": "",

View File

@@ -42,12 +42,20 @@
### 2. LEI (Legal Entity Identifier)
- **Format:** 20-character alphanumeric (e.g. `5493001KJTIIGC8Y1R12`).
- **OMNL Head Office (entity 1):** Canonical LEI **`98450070C57395F6B906`** — public summary at [lei.info](https://lei.info/98450070C57395F6B906). Roster and filing notes: [OMNL_BANKING_DIRECTORS_AND_LEI.md](OMNL_BANKING_DIRECTORS_AND_LEI.md).
- **In Fineract:** Stored as a **Client Identifier** with document type **LEI** (or “Legal Entity Identifier”). The tenant must have a document/identifier type named LEI (or equivalent); the apply script uses the first matching type from `GET /clients/{clientId}/identifiers/template` (`allowedDocumentTypes`).
- **In JSON:** `"lei": "<20-char LEI>"`. Leave `""` if not yet assigned.
### 2b. LEI, EBICS, BIC, and other codes in Address2 / Address3 or memo fields
Many screens (and **offices** in particular) have no dedicated LEI, **EBICS**, **BIC**, or similar fields. You can still record them on the **entity** using free-text slots:
- **Client addresses (Fineract):** Put labeled lines in **`addressLine2`**, **`addressLine3`**, and/or **`street`** / **`addressLine1`** as appropriate (e.g. primary premises on line 1; identifiers on lines 23). The **Client Addresses** API accepts all of these fields.
- **Office / organization UI:** Use any **memo**, **description**, **additional information**, or equivalent note field the tenant exposes, with the same labeling convention.
- **Suggested format (human- and audit-friendly):** One token per line where possible, for example: `LEI:98450070C57395F6B906`, `BIC:ABCDEFGH`, `EBICS:<bank-specific id>`. Keep the canonical structured LEI in `"lei"` when you use this JSON as source of truth; mirror or supplement in address lines as needed for Fineract or regulator-facing exports.
### 3. Address
- **In Fineract:** Stored via **Client Addresses** API: `POST /client/{clientId}/addresses` (and optionally `PUT` to update). Fields: `street`, `addressLine1`, `addressLine2`, `addressLine3`, `city`, `stateProvinceId`, `countryId`, `postalCode`, `isActive`. `countryId` and optionally `stateProvinceId` are Fineract reference IDs (from `GET /codes` or the UI).
- **In JSON:** Under `address`: fill `street`, `addressLine1`, `addressLine2`, `city`, `postalCode`; set `countryId` (and `stateProvinceId` if applicable) when you have the Fineract code IDs. Use `null` or omit to skip address for that entity.
- **In JSON:** Under `address`: fill `street`, `addressLine1`, `addressLine2`, `addressLine3`, `city`, `postalCode`; set `countryId` (and `stateProvinceId` if applicable) when you have the Fineract code IDs. Use `null` or omit to skip address for that entity. Use **`addressLine2` / `addressLine3`** for LEI / BIC / EBICS (and similar) when those identifiers are not stored elsewhere on the record.
### 4. Contacts
- **In Fineract:** Client-level **mobile** and **email** (e.g. `mobileNo`, `emailAddress`). May be updatable via `PUT /clients/{clientId}` if the server allows it; otherwise via UI or datatables.
@@ -59,8 +67,8 @@
1. Open [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json).
2. For each entity in `entities`:
- **LEI:** Set `lei` to the 20-character LEI when assigned; otherwise leave `""`.
- **Address:** Fill `address.street`, `addressLine1`, `addressLine2`, `city`, `postalCode`. For `countryId` (and `stateProvinceId`) you need the Fineract code IDs from the tenant (Admin → Code values / address config, or `GET /codes`).
- **LEI:** Set `lei` to the 20-character LEI when assigned; otherwise leave `""`. If the live system only allows Address2/3 or a memo for identifiers, mirror LEI (and BIC, EBICS, etc.) there and document the same strings in `address.addressLine2` / `addressLine3` when you want the apply script to push them for **clients**.
- **Address:** Fill `address.street`, `addressLine1`, `addressLine2`, `addressLine3`, `city`, `postalCode`. For `countryId` (and `stateProvinceId`) you need the Fineract code IDs from the tenant (Admin → Code values / address config, or `GET /codes`).
- **Contact:** Fill `contact.mobileNo` and `contact.emailAddress` as appropriate; leave `""` if unknown.
3. Save the file. The apply script reads this file and updates Fineract (names, then LEI identifiers, addresses, then contact fields when supported).
@@ -98,7 +106,8 @@ See [scripts/omnl/README.md](../../../scripts/omnl/README.md) for full script li
|-------------|--------------|--------|
| Entity name | `PUT /clients/{clientId}` body `firstname`, `lastname` | One-line display name in UI |
| LEI | `POST /clients/{clientId}/identifiers` | `documentTypeId` = LEI type from template; `documentKey` = LEI value |
| Address | `POST /client/{clientId}/addresses` | Requires `countryId` (and optionally `stateProvinceId`) from tenant codes |
| Address | `POST /client/{clientId}/addresses` | Requires `countryId` (and optionally `stateProvinceId`) from tenant codes; `addressLine2` / `addressLine3` may carry LEI, BIC, EBICS, etc. |
| LEI / BIC / EBICS (no dedicated field) | Address lines or UI memo | Same strings as in master JSON; offices often have no identifier API—use org memo or address-style fields in UI |
| Mobile / email | `PUT /clients/{clientId}` body `mobileNo`, `emailAddress` | If server accepts; else use UI |
---

View File

@@ -0,0 +1,24 @@
---
documentId: OMNL-JE-161-164
settlementRef: HYBX-BATCH-001
version: "1.0"
note: Example JE ids — replace with live ids from your tenant.
---
# Journal Entries 161164 (Reference)
## 1. Purpose
Template for documenting **specific journal entry IDs** tied to HYBX-BATCH-001 or related clearing (ids vary by tenant).
## 2. Lookup
```bash
JE_IDS=161,162,163,164 bash scripts/omnl/omnl-je-lookup-ids.sh
```
## 3. Institution record
| JE id | Role | Office | Amount (USD) | Reference |
|-------|------|--------|--------------|-----------|
| (fill) | (fill) | 22 / HO | (fill) | HYBX-BATCH-001 |

View File

@@ -0,0 +1,38 @@
---
documentId: PVP-MULTILATERAL-NET-BANK-KANAYA
settlementRef: HYBX-BATCH-001
beneficiaryOfficeId: 22
beneficiary: Bank Kanaya
amountUsd: "1000000000.00"
currency: USD
valueDate: "2026-03-17"
version: "1.0"
---
# PvP Multilateral Net Settlement — Bank Kanaya (HYBX-BATCH-001)
## 1. Design summary
Settlement uses **HYBX / DBIS / OMNL** multilateral netting. **Bank Kanaya (office 22)** is the **net beneficiary** of USD 1,000,000,000.00 on OMNL M1 liabilities (`2100`) with offsetting **Due To / Due From** structure per Phase C pattern (`2410` / `1410` / `2100` as applicable to your posted JEs).
## 2. Clearing reference
- Cycle id (narrative): `DBIS-SET-HYBX-20260317-001`
- Journal reference convention: `HYBX-BATCH-001-CLEARING` (where used)
## 3. Operator posting
Use institution maker-checker policy. Example script (when configured for this batch):
```bash
# DRY_RUN=1 first
bash scripts/omnl/omnl-pvp-post-clearing-bank-kanaya.sh
```
Requires `omnl-fineract/.env` or root `.env` with OMNL API credentials.
## 4. Evidence
- Netting report and ledger: transaction package Volume C
- OMNL snapshot: `omnl_transaction_package_snapshot.json`
- GL definitions: [OMNL_GL_ACCOUNTS_REQUIRED.md](OMNL_GL_ACCOUNTS_REQUIRED.md)

View File

@@ -35,6 +35,16 @@ Configuration documentation for Apache Fineract + Mifos X as the **OMNL** (Organ
| [P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md](P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md) | P2P banking rail: HYBX → CrunchyGalaxy settlement (request/response/capture, mirror entry, close package). |
| [OMNL_OFFICE_ADDRESS_BOOK.md](OMNL_OFFICE_ADDRESS_BOOK.md) | **Address book:** Per-office API Banking Rail instructions and secrets reference (vault path only; no secrets in repo). |
| [OMNL_OFFICE_MASTER_RUNBOOK_INDEX.md](OMNL_OFFICE_MASTER_RUNBOOK_INDEX.md) | **Master Runbook index:** Every office has one Master Runbook and optional sub-runbooks (funding, P2P, audit, DR, upload). |
| [BANK_KANAYA_OFFICE_RUNBOOK.md](BANK_KANAYA_OFFICE_RUNBOOK.md) | **Bank Kanaya (OMNL office 22)** — HYBX-BATCH-001 beneficiary; create office: `omnl-office-create-bank-kanaya.sh`; PvP JEs: `omnl-pvp-post-clearing-bank-kanaya.sh`. |
| [INDONESIA_MASTER_PROOF_MANIFEST.md](INDONESIA_MASTER_PROOF_MANIFEST.md) | **Indonesia submission** — Master proof manifest for BI/MoF package (HYBX-BATCH-001). |
| [INDONESIA_CENTRAL_BANK_SUBMISSION_BINDER.md](INDONESIA_CENTRAL_BANK_SUBMISSION_BINDER.md) | Six-volume binder structure; build via `scripts/omnl/build-transaction-package-zip.sh`. |
| [INDONESIA_SAMPLE_COVER_AND_TOC.md](INDONESIA_SAMPLE_COVER_AND_TOC.md) | Transmission-ready cover letter + master TOC (metadata in YAML front matter). |
| [OMNL_API_TRANSACTION_PACKAGE.md](OMNL_API_TRANSACTION_PACKAGE.md) | `omnl_transaction_package_snapshot.json` for regulator Section 2. |
| [PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md](PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md) | PvP / multilateral net narrative for Bank Kanaya batch. |
| [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md) | **4.995 per-category** evidence standard + honesty clause. |
| [INDONESIA_SUBMISSION_PACKAGE_GRADE_AND_SCORECARD.md](INDONESIA_SUBMISSION_PACKAGE_GRADE_AND_SCORECARD.md) | Scorecard; targets **4.995** per row (not 5.0). |
| [HYBX_BATCH_001_OPERATOR_CHECKLIST.md](HYBX_BATCH_001_OPERATOR_CHECKLIST.md) | **End-to-end operator checklist** — Fineract, zip build, verify, 4.995 strict, transmission. |
| [OMNL_BANKING_DIRECTORS_AND_LEI.md](OMNL_BANKING_DIRECTORS_AND_LEI.md) | **OMNL LEI** + **directors/officers** roster; links [lei.info/98450070C57395F6B906](https://lei.info/98450070C57395F6B906). |
## Scripts

View File

@@ -0,0 +1,32 @@
---
documentId: REGULATORY-INDONESIA-BANK-KANAYA
entity: Bank Kanaya
jurisdiction: Indonesia
settlementRef: HYBX-BATCH-001
regulators:
- Bank Indonesia
- Ministry of Finance
- PPATK-as-applicable
version: "1.0"
disclaimer: Template for institution legal review — not legal advice.
---
# Regulatory Context — Indonesia (Bank Kanaya Submission)
## 1. Purpose
Frames the **HYBX-BATCH-001** evidence package for **legitimacy and supervisory review** (BI/MoF; PPATK where AML reporting applies). Institution counsel completes institution-specific citations.
## 2. Submission posture
- **Cross-border settlement** with **OMNL** as settlement ledger for the USD leg.
- **No traditional nostro chain** for this design; Section 3 N/A memorandum documents that fact.
## 3. Data and retention
- Retain package + `HYBX-BATCH-001-SUBREG` (signatures, TSA tokens, correspondence) **≥ 10 years** or local policy, whichever stricter.
- Hash manifest: `audit_manifest.json` + `HASH_NOTARIZATION_ANCHOR.txt`.
## 4. Institution action
Replace this template with **cited statutes, BI circulars, and internal policies** approved by compliance.

View File

@@ -0,0 +1,34 @@
---
documentId: TRANSACTION-EXPLANATION-JURISDICTIONS
settlementRef: HYBX-BATCH-001
valueDate: "2026-03-17"
beneficiaryOfficeId: 22
version: "1.0"
---
# Transaction Explanation — Jurisdictions and Flow
## 1. Narrative
**HYBX-BATCH-001** settles **USD 1,000,000,000.00** to **Bank Kanaya (Indonesia)** via **DBIS multilateral net clearing** and **OMNL** book entries. The USD leg is a **liability of OMNL** to the beneficiary office (M1 / interoffice structure per posted journals).
## 2. Jurisdictions (illustrative)
| Stage | Jurisdiction / venue |
|--------|----------------------|
| Clearing narrative | DBIS policy / rulebooks |
| Ledger | OMNL tenant (institution-hosted or designated) |
| Beneficiary | Indonesia (Bank Kanaya) |
## 3. Diagram (text)
```
HYBX participants ──► DBIS netting ──► OMNL GL (2100/2410/1410 pattern)
Bank Kanaya (office 22) beneficiary position
```
## 4. HTML diagram
See [TRANSACTION_EXPLANATION_VISUAL.html](TRANSACTION_EXPLANATION_VISUAL.html) (optional print/PDF).

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="documentId" content="TRANSACTION-EXPLANATION-VISUAL"/>
<meta name="settlementRef" content="HYBX-BATCH-001"/>
<meta name="beneficiaryOfficeId" content="22"/>
<title>HYBX-BATCH-001 — Settlement flow</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 48rem; margin: 2rem auto; padding: 0 1rem; color: #1a1a1a; }
h1 { font-size: 1.25rem; }
.box { border: 1px solid #333; border-radius: 6px; padding: 0.75rem 1rem; margin: 0.5rem 0; background: #fafafa; }
.arrow { text-align: center; margin: 0.25rem 0; }
footer { margin-top: 2rem; font-size: 0.85rem; color: #555; }
</style>
</head>
<body>
<h1>HYBX-BATCH-001 — Visual flow (reference)</h1>
<p>Value date <strong>2026-03-17</strong> · Beneficiary <strong>Bank Kanaya (OMNL office 22)</strong> · USD <strong>1,000,000,000.00</strong></p>
<div class="box">HYBX / participant legs</div>
<div class="arrow">↓ DBIS multilateral net</div>
<div class="box">OMNL settlement ledger (M1 / interoffice)</div>
<div class="arrow"></div>
<div class="box">Bank Kanaya — credited net position</div>
<footer>Evidence: transaction package Volume C (ledger + Merkle) and Volume A Section 2 (OMNL snapshot). Not a legal opinion.</footer>
</body>
</html>

View File

@@ -54,7 +54,7 @@
| **00-meta** (tasks, next steps, phases) | [00-meta/NEXT_STEPS_INDEX.md](00-meta/NEXT_STEPS_INDEX.md), [00-meta/PHASES_AND_TASKS_MASTER.md](00-meta/PHASES_AND_TASKS_MASTER.md) |
| **02-architecture** | [02-architecture/](02-architecture/) |
| **03-deployment** | [03-deployment/OPERATIONAL_RUNBOOKS.md](03-deployment/OPERATIONAL_RUNBOOKS.md), [03-deployment/DEPLOYMENT_ORDER_OF_OPERATIONS.md](03-deployment/DEPLOYMENT_ORDER_OF_OPERATIONS.md) |
| **04-configuration** | [04-configuration/README.md](04-configuration/README.md), [04-configuration/ADDITIONAL_PATHS_AND_EXTENSIONS.md](04-configuration/ADDITIONAL_PATHS_AND_EXTENSIONS.md) (paths, registry, token-mapping, LiFi/Jumper) |
| **04-configuration** | [04-configuration/README.md](04-configuration/README.md), [04-configuration/ADDITIONAL_PATHS_AND_EXTENSIONS.md](04-configuration/ADDITIONAL_PATHS_AND_EXTENSIONS.md) (paths, registry, token-mapping, LiFi/Jumper); **OMNL Indonesia / HYBX-BATCH-001:** [04-configuration/mifos-omnl-central-bank/HYBX_BATCH_001_OPERATOR_CHECKLIST.md](04-configuration/mifos-omnl-central-bank/HYBX_BATCH_001_OPERATOR_CHECKLIST.md), [04-configuration/mifos-omnl-central-bank/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](04-configuration/mifos-omnl-central-bank/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md) |
| **06-besu** | [06-besu/MASTER_INDEX.md](06-besu/MASTER_INDEX.md) |
| **07-ccip** | [07-ccip/](07-ccip/), [00-meta/CW_BRIDGE_TASK_LIST.md](00-meta/CW_BRIDGE_TASK_LIST.md) |
| **11-references** | [11-references/ADDRESS_MATRIX_AND_STATUS.md](11-references/ADDRESS_MATRIX_AND_STATUS.md), [11-references/CONTRACT_ADDRESSES_REFERENCE.md](11-references/CONTRACT_ADDRESSES_REFERENCE.md), [11-references/DEPLOYER_CONTRACTS_INVENTORY_AND_VERIFICATION_STATUS.md](11-references/DEPLOYER_CONTRACTS_INVENTORY_AND_VERIFICATION_STATUS.md) (all contracts by deployer wallet, network, verified/not), [11-references/DEPLOYED_TOKENS_BRIDGES_LPS_AND_ROUTING_STATUS.md](11-references/DEPLOYED_TOKENS_BRIDGES_LPS_AND_ROUTING_STATUS.md) (tokens, bridges, DODO/Uniswap LPs, full route map), [11-references/DEPLOYER_TO_PUBLIC_STABLECOIN_ROUTES.md](11-references/DEPLOYER_TO_PUBLIC_STABLECOIN_ROUTES.md) (deployer→public stablecoin routes), [11-references/ROUTES_NO_PREFUNDED_BRIDGE_REQUIRED.md](11-references/ROUTES_NO_PREFUNDED_BRIDGE_REQUIRED.md) (routes where bridge pre-fund not required), [11-references/CCIP_138_DESTINATION_RECEIVER_BY_CHAIN_AND_TOKEN.md](11-references/CCIP_138_DESTINATION_RECEIVER_BY_CHAIN_AND_TOKEN.md) (per-chain per-token: mint vs receive+forward vs release), [11-references/DEPLOYMENT_DATA_SOURCES_INDEX.md](11-references/DEPLOYMENT_DATA_SOURCES_INDEX.md) (dotenv and config files with contract deployments), [11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md](11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md) (Explorer /tokens vs repo token lists), [11-references/HARDWARE_INVENTORY_MASTER.md](11-references/HARDWARE_INVENTORY_MASTER.md), [11-references/13_NODE_NETWORK_AND_CABLING_CHECKLIST.md](11-references/13_NODE_NETWORK_AND_CABLING_CHECKLIST.md), [11-references/13_NODE_AND_ASSETS_BRING_ONLINE_CHECKLIST.md](11-references/13_NODE_AND_ASSETS_BRING_ONLINE_CHECKLIST.md) |

View File

@@ -0,0 +1,50 @@
---
documentId: DBIS-SETTLEMENT-RULEBOOK
title: DBIS Settlement Rulebook (HYBX / OMNL evidence)
version: "1.0"
status: operational-reference
relatedSettlementRef: HYBX-BATCH-001
relatedCycleId: DBIS-SET-HYBX-20260317-001
network: DBIS Mainnet (ChainID 138)
companionDocuments:
- DBIS_RAIL_RULEBOOK_V1.md
- DBIS_RAIL_TECHNICAL_SPEC_V1.md
lastReviewed: "2026-03-17"
---
# DBIS Settlement Rulebook
**Purpose:** Define settlement batch evidence, netting semantics, and **ledger row canonicalisation** used for Merkle proofs and regulatory packages (e.g. HYBX-BATCH-001).
## 1. Scope
- Applies to **DBIS clearing cycles** that settle through **OMNL** books (M1 liabilities, interoffice due-to/due-from).
- Cross-references [DBIS Rail Rulebook v1](DBIS_RAIL_RULEBOOK_V1.md) for good funds, finality, and rail policy.
## 2. Batch identity
| Field | Description |
|--------|-------------|
| `settlementBatch` | Batch identifier (e.g. `HYBX-BATCH-001`). |
| `settlementCycle` | Clearing cycle id (e.g. `DBIS-SET-HYBX-20260317-001`). |
| `valueDate` | Business value date (UTC date string). |
## 3. Netting report
Multilateral net positions are reported per participant. For HYBX-BATCH-001 the beneficiary receives the net **credit** in USD; liquidity provider shows offsetting **debit** on OMNL; system net is zero.
## 4. Annex B — Canonical line for Merkle leaves (CSV)
**Input file:** UTF-8 CSV, LF line endings, header row present.
**Leaf input:** Each **complete logical line** of the file (from first byte of the line through the line terminator excluded from hash input per generator: hash is `SHA-256(UTF-8 bytes of the line string without trailing newline on that line)`).
**Ordering:** Leaves are taken in **file order** (top to bottom), including the header row as the first leaf.
**Root:** Binary Merkle tree over leaf digests: `H(left || right)` with SHA-256; if odd count at a level, duplicate last node.
**Verification:** Recompute leaves from the same CSV bytes, rebuild tree, compare root to published `merkle_root_HYBX-BATCH-001.txt`.
## 5. Evidence retention
Submitting institutions retain: CSV, Merkle log, generation tooling identity, and audit manifest binding file hashes to `HASH_NOTARIZATION_ANCHOR.txt` per package build procedure.

View File

@@ -5,6 +5,7 @@ This folder holds the **DBIS Rail** technical specification and operational rule
- **E2E White Paper (simple terms):** [E2E_WHITEPAPER_SIMPLE.md](E2E_WHITEPAPER_SIMPLE.md) — end-to-end flow, components, and controls in plain language.
- **Technical Spec:** [DBIS_RAIL_TECHNICAL_SPEC_V1.md](DBIS_RAIL_TECHNICAL_SPEC_V1.md) — contract set, MintAuth, signer quorum, replay protection, audit events.
- **Rulebook:** [DBIS_RAIL_RULEBOOK_V1.md](DBIS_RAIL_RULEBOOK_V1.md) — good funds matrix, finality rules, accounting sequence, reversal handling, signer governance, incident controls, audit standards.
- **Settlement rulebook (HYBX / OMNL evidence):** [DBIS_SETTLEMENT_RULEBOOK.md](DBIS_SETTLEMENT_RULEBOOK.md) — batch identity, netting narrative, **Annex B** Merkle leaf canonicalisation for regulator packages.
- **Security Threat Model:** [DBIS_RAIL_SECURITY_THREAT_MODEL_V1.md](DBIS_RAIL_SECURITY_THREAT_MODEL_V1.md) — trust boundaries, authorization/ledger/router/mint/validator/off-chain threats, severity classification, residual risk, review cycle.
- **Regulator-Facing Brief:** [DBIS_RAIL_REGULATOR_BRIEF_V1.md](DBIS_RAIL_REGULATOR_BRIEF_V1.md) — institutional narrative for counterparties, examiners, counsel, and risk committees: overview, governance, lifecycle, good funds, controls, risk posture, audit, residual risk, amendment.
- **Audit Readiness Checklist:** [DBIS_RAIL_AUDIT_READINESS_CHECKLIST_V1.md](DBIS_RAIL_AUDIT_READINESS_CHECKLIST_V1.md) — pre-audit control verification: mint path, authorization, signer governance, accounting/evidence, router controls, validator layer, emergency controls, documentation integrity.

View File

@@ -63,7 +63,14 @@ function send(res, status, data) {
async function forwardEtherscanFormat(payload) {
const query = new URLSearchParams({ module: 'contract', action: 'verifysourcecode' });
const path = `/api/?${query}`;
const body = JSON.stringify(payload);
// Blockscout's Etherscan-compatible endpoint expects classic form fields, not JSON.
// Keep the Forge payload keys, but serialize them as application/x-www-form-urlencoded.
const form = new URLSearchParams();
for (const [key, value] of Object.entries(payload)) {
if (value === undefined || value === null || value === '') continue;
form.set(key, String(value));
}
const body = form.toString();
const url = new URL(path, BLOCKSCOUT_URL);
return new Promise((resolve, reject) => {
@@ -74,7 +81,7 @@ async function forwardEtherscanFormat(payload) {
path: url.pathname + url.search,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(body),
Host: url.hostname + (url.port ? ':' + url.port : ''),
},
@@ -98,7 +105,7 @@ async function forwardEtherscanFormat(payload) {
}
/**
* Forward to Blockscout v2 flattened-code API (for Standard JSON, we pass as source_code).
* Forward to Blockscout v2 flattened-code verification API.
*/
async function forwardV2Flattened(payload) {
const addr = payload.contractaddress || payload.contractAddress;
@@ -157,6 +164,90 @@ async function forwardV2Flattened(payload) {
});
}
/**
* Forward to Blockscout v2 verification API for Standard JSON input.
*/
async function forwardV2StandardInput(payload) {
const addr = payload.contractaddress || payload.contractAddress;
const sourceCode = payload.sourceCode ?? payload.source_code;
const standardJson =
typeof sourceCode === 'string'
? sourceCode
: JSON.stringify(sourceCode);
const path = `/api/v2/smart-contracts/${addr}/verification/via/standard-input`;
const boundary = `----forge-verification-proxy-${Math.random().toString(16).slice(2)}`;
const parts = [];
const appendField = (name, value) => {
if (value === undefined || value === null || value === '') return;
parts.push(Buffer.from(`--${boundary}\r\n`));
parts.push(Buffer.from(`Content-Disposition: form-data; name="${name}"\r\n\r\n`));
parts.push(Buffer.from(`${value}\r\n`));
};
const appendFile = (name, filename, content, contentType = 'application/json') => {
parts.push(Buffer.from(`--${boundary}\r\n`));
parts.push(Buffer.from(`Content-Disposition: form-data; name="${name}"; filename="${filename}"\r\n`));
parts.push(Buffer.from(`Content-Type: ${contentType}\r\n\r\n`));
parts.push(Buffer.isBuffer(content) ? content : Buffer.from(String(content)));
parts.push(Buffer.from('\r\n'));
};
const compilerVersion = payload.compilerversion || payload.compilerVersion || 'v0.8.20+commit.a1b79de6';
const contractName = payload.contractname || payload.contractName || 'Contract';
const licenseType = payload.licensetype || payload.licenseType || 'mit';
const constructorArgs =
payload.constructor_args ??
payload.constructorArguments ??
payload.constructorArgumentsHex ??
payload.constructorArgs ??
'';
appendField('compiler_version', compilerVersion);
appendField('contract_name', contractName);
appendField('autodetect_constructor_args', String(payload.autodetectConstructorArguments !== false));
appendField('license_type', licenseType);
appendField('constructor_args', constructorArgs);
if (payload.evmversion || payload.evm_version) appendField('evm_version', payload.evmversion || payload.evm_version);
if (payload.optimizationUsed !== undefined || payload.optimization_used !== undefined) {
appendField('is_optimization_enabled', String([true, '1', 1, 'true'].includes(payload.optimizationUsed ?? payload.optimization_used)));
}
if (payload.runs !== undefined || payload.optimization_runs !== undefined) {
appendField('optimization_runs', String(parseInt(payload.runs ?? payload.optimization_runs ?? '200', 10) || 200));
}
appendFile('files[0]', 'standard-input.json', standardJson, 'application/json');
parts.push(Buffer.from(`--${boundary}--\r\n`));
const body = Buffer.concat(parts);
const url = new URL(path, BLOCKSCOUT_URL);
return new Promise((resolve, reject) => {
const req = http.request(
{
hostname: url.hostname,
port: url.port || (url.protocol === 'https:' ? 443 : 80),
path: url.pathname,
method: 'POST',
headers: {
'Content-Type': `multipart/form-data; boundary=${boundary}`,
'Content-Length': body.length,
},
},
(res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
try {
resolve({ status: res.statusCode, data: data ? JSON.parse(data) : {}, raw: data });
} catch {
resolve({ status: res.statusCode, data: null, raw: data });
}
});
}
);
req.on('error', reject);
req.write(body);
req.end();
});
}
function toEtherscanResponse(result) {
const { status, data, raw } = result;
if (status >= 200 && status < 300 && data?.status === '1') {
@@ -261,7 +352,7 @@ const server = http.createServer(async (req, res) => {
codeformat === 'solidity-standard-json-input' ||
(typeof sourceCode === 'string' && sourceCode.trimStart().startsWith('{') && sourceCode.includes('"sources"'));
// Etherscan API expects Standard JSON in sourceCode; flattened Solidity causes "Invalid JSON".
// Try v2 API first for flattened code; use Etherscan only for Standard JSON.
// Try v2 API first for flattened code; use multipart standard-input when the payload is Standard JSON.
const tryV2First = !isStandardJson;
try {
@@ -278,13 +369,13 @@ const server = http.createServer(async (req, res) => {
return;
}
} else {
result = await forwardEtherscanFormat(payload);
result = await forwardV2StandardInput(payload);
out = toEtherscanResponse(result);
if (out.status !== '1') {
console.error('[forge-verification-proxy] Etherscan API failed:', out.message, '- trying v2...');
result = await forwardV2Flattened(payload);
const v2Out = toEtherscanResponse(result);
send(res, 200, v2Out);
console.error('[forge-verification-proxy] v2 standard-input failed:', out.message, '- trying Etherscan format...');
result = await forwardEtherscanFormat(payload);
const etherOut = toEtherscanResponse(result);
send(res, 200, etherOut.status === '1' ? etherOut : out);
return;
}
}

View File

@@ -0,0 +1,993 @@
{
"snapshotMeta": {
"documentId": "OMNL-TRANSACTION-PACKAGE-SNAPSHOT",
"omnlLegalName": "ORGANISATION MONDIALE DU NUMERIQUE L.P.B.C.",
"omnlLei": "98450070C57395F6B906",
"omnlLeiReferenceUrl": "https://lei.info/98450070C57395F6B906",
"omnlDirectorsAndOfficersDoc": "Appendix/OMNL_BANKING_DIRECTORS_AND_LEI.md",
"generatedAtUtc": "2026-03-25T00:56:05Z",
"settlementRef": "HYBX-BATCH-001",
"valueDate": "2026-03-17",
"beneficiary": "Bank Kanaya (Indonesia)",
"beneficiaryOfficeId": 22,
"beneficiaryExternalId": "BANK-KANAYA-ID",
"amountUsd": "1000000000.00",
"currency": "USD",
"source": "live-api",
"apiBaseUrl": "https://omnl.hybxfinance.io/fineract-provider/api/v1",
"registryHeadOfficeEntityName": "OMNL Head Office (DBIS) Central Bank",
"entityMasterDataSource": "OMNL_ENTITY_MASTER_DATA.json",
"officeRegistryModel": "Fineract offices + LEI/entity overlay from OMNL_ENTITY_MASTER_DATA.json (LEI is not stored as a Fineract office column)."
},
"offices": [
{
"id": 1,
"name": "OMNL Head Office (DBIS) Central Bank",
"nameDecorated": "OMNL Head Office (DBIS) Central Bank",
"externalId": "1",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".",
"registryClientNumber": 1,
"registryEntityName": "OMNL Head Office (DBIS) Central Bank",
"registryLei": "98450070C57395F6B906"
},
{
"id": 10,
"name": "Alpha Omega Holdings",
"nameDecorated": "....Alpha Omega Holdings",
"externalId": "OMNL-10",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".10.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 10,
"registryEntityName": "Alpha Omega Holdings",
"registryLei": ""
},
{
"id": 11,
"name": "SGI Capital",
"nameDecorated": "....SGI Capital",
"externalId": "OMNL-11",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".11.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 11,
"registryEntityName": "SGI Capital",
"registryLei": ""
},
{
"id": 12,
"name": "Titan Financial",
"nameDecorated": "....Titan Financial",
"externalId": "OMNL-12",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".12.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 12,
"registryEntityName": "Titan Financial",
"registryLei": ""
},
{
"id": 13,
"name": "Roy Walker PLLC",
"nameDecorated": "....Roy Walker PLLC",
"externalId": "OMNL-13",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".13.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 13,
"registryEntityName": "Roy Walker PLLC",
"registryLei": ""
},
{
"id": 14,
"name": "SGI Partners LLC",
"nameDecorated": "....SGI Partners LLC",
"externalId": "OMNL-14",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".14.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 14,
"registryEntityName": "SGI Partners LLC",
"registryLei": ""
},
{
"id": 15,
"name": "Tsunami Holdings AG",
"nameDecorated": "....Tsunami Holdings AG",
"externalId": "OMNL-15",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".15.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 15,
"registryEntityName": "Tsunami Holdings AG",
"registryLei": ""
},
{
"id": 16,
"name": "Anakatech LLC",
"nameDecorated": "....Anakatech LLC",
"externalId": "OMNL-16",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".16.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 16,
"registryEntityName": "Anakatech",
"registryLei": ""
},
{
"id": 17,
"name": "Anema Cameron Walker Global",
"nameDecorated": "....Anema Cameron Walker Global",
"externalId": "OMNL-17",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".17.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 17,
"registryEntityName": "Anema Camden Walker Global",
"registryLei": ""
},
{
"id": 18,
"name": "NEPAL RASTRA BANK",
"nameDecorated": "....NEPAL RASTRA BANK",
"externalId": "OMNL-18",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".18.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 18,
"registryEntityName": "NEPAL RASTRA BANK",
"registryLei": "25490000MX377HHPSR96"
},
{
"id": 19,
"name": "SANIMA BANK LIMITED",
"nameDecorated": "....SANIMA BANK LIMITED",
"externalId": "OMNL-19",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".19.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 19,
"registryEntityName": "SANIMA BANK LIMITED",
"registryLei": "25490043FER1B108XE95"
},
{
"id": 2,
"name": "Shamrayan Enterprises",
"nameDecorated": "....Shamrayan Enterprises",
"externalId": "OMNL-2",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".2.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 2,
"registryEntityName": "Shamrayan Enterprises",
"registryLei": ""
},
{
"id": 20,
"name": "Samama Group LLC - Azerbaijan",
"nameDecorated": "....Samama Group LLC - Azerbaijan",
"externalId": "SAMAMA-AZ-1703722701",
"openingDate": [
2024,
1,
10
],
"hierarchy": ".20.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 20,
"registryEntityName": "Samama Group LLC - Azerbaijan",
"registryLei": ""
},
{
"id": 21,
"name": "Bank Kanaya (Indonesia)",
"nameDecorated": "....Bank Kanaya (Indonesia)",
"externalId": "BANK-KANAYA-ID",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".21.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": null,
"registryEntityName": null,
"registryLei": ""
},
{
"id": 3,
"name": "HYBX",
"nameDecorated": "....HYBX",
"externalId": "OMNL-3",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".3.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 3,
"registryEntityName": "HYBX",
"registryLei": ""
},
{
"id": 4,
"name": "TAJ Private Single Family Office",
"nameDecorated": "....TAJ Private Single Family Office",
"externalId": "OMNL-4",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".4.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 4,
"registryEntityName": "TAJ Private Single Family Office",
"registryLei": ""
},
{
"id": 5,
"name": "Aseret Mortgage Bank",
"nameDecorated": "....Aseret Mortgage Bank",
"externalId": "OMNL-5",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".5.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 5,
"registryEntityName": "Aseret Mortgage Bank",
"registryLei": ""
},
{
"id": 6,
"name": "Mann Li Family Offices",
"nameDecorated": "....Mann Li Family Offices",
"externalId": "OMNL-6",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".6.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 6,
"registryEntityName": "Mann Li Family Offices",
"registryLei": ""
},
{
"id": 7,
"name": "Sovereign Order of Malta OSJ",
"nameDecorated": "....Sovereign Order of Malta OSJ",
"externalId": "OMNL-7",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".7.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 7,
"registryEntityName": "Sovereign Order of Malta OSJ",
"registryLei": ""
},
{
"id": 8,
"name": "Alltra Mainnet",
"nameDecorated": "....Alltra Mainnet",
"externalId": "OMNL-8",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".8.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 8,
"registryEntityName": "Alltra Mainnet",
"registryLei": ""
},
{
"id": 9,
"name": "FIDIS",
"nameDecorated": "....FIDIS",
"externalId": "OMNL-9",
"openingDate": [
2026,
1,
1
],
"hierarchy": ".9.",
"parentId": 1,
"parentName": "OMNL Head Office (DBIS) Central Bank",
"registryClientNumber": 9,
"registryEntityName": "FIDIS",
"registryLei": ""
}
],
"glAccounts": [
{
"id": 1,
"name": "1000-USD-RESERVE-ASSETS",
"glCode": "1000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Fiat USD Reserve Assets (M0)",
"nameDecorated": "1000-USD-RESERVE-ASSETS",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 8,
"name": "Assets (header)",
"glCode": "10000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "Total assets",
"nameDecorated": "Assets (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 7,
"name": "1050-USD-Treasury-Conversion-Reserve-M0",
"glCode": "1050",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Treasury Conversion Reserve (M0); backs M1 capacity at 1:5",
"nameDecorated": "1050-USD-Treasury-Conversion-Reserve-M0",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 9,
"name": "Foreign currency reserves (header)",
"parentId": 8,
"glCode": "12000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "FX reserves header",
"nameDecorated": "....Foreign currency reserves (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 10,
"name": "FX reserves — USD",
"parentId": 9,
"glCode": "12010",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Foreign currency reserves — USD",
"nameDecorated": "........FX reserves — USD",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 11,
"name": "FX reserves — EUR",
"parentId": 9,
"glCode": "12020",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Foreign currency reserves — EUR",
"nameDecorated": "........FX reserves — EUR",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 12,
"name": "FX reserves — other",
"parentId": 9,
"glCode": "12090",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Other ISO-4217 and special units",
"nameDecorated": "........FX reserves — other",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 13,
"name": "FX settlement balances (header)",
"parentId": 8,
"glCode": "13000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "FX settlement header",
"nameDecorated": "....FX settlement balances (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 14,
"name": "FX settlement — nostro",
"parentId": 13,
"glCode": "13010",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Settlement balances with counterparties",
"nameDecorated": "........FX settlement — nostro",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 24,
"name": "Due From Head Office (Interoffice Receivable)",
"glCode": "1410",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 1,
"code": "accountType.asset",
"value": "ASSET"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Interoffice receivable at branch",
"nameDecorated": "Due From Head Office (Interoffice Receivable)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 2,
"name": "2000-M0-CENTRAL-DEPOSITS",
"glCode": "2000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Central Bank Deposit Liabilities (M0)",
"nameDecorated": "2000-M0-CENTRAL-DEPOSITS",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 15,
"name": "Liabilities (header)",
"glCode": "20000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "Total liabilities",
"nameDecorated": "Liabilities (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 3,
"name": "2100-M1-CENTRAL-LIABILITIES",
"glCode": "2100",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "M1 General Liabilities",
"nameDecorated": "2100-M1-CENTRAL-LIABILITIES",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 16,
"name": "M00 — Base reserve (header)",
"parentId": 15,
"glCode": "21000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "Central bank reserve unit; GRU-denominated; non-circulating except authorized issuance",
"nameDecorated": "....M00 — Base reserve (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 17,
"name": "M00 — Bank reserves (control)",
"parentId": 16,
"glCode": "21010",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Control account for M00",
"nameDecorated": "........M00 — Bank reserves (control)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 4,
"name": "2200-M1-RESTRICTED-LIABILITIES",
"glCode": "2200",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "M1 Restricted / Held Liabilities",
"nameDecorated": "2200-M1-RESTRICTED-LIABILITIES",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 25,
"name": "Due To Offices (Interoffice Payable)",
"glCode": "2410",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 2,
"code": "accountType.liability",
"value": "LIABILITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Interoffice payable at Head Office",
"nameDecorated": "Due To Offices (Interoffice Payable)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 5,
"name": "3000-TREASURY-CONVERSION-RESERVE",
"glCode": "3000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 3,
"code": "accountType.equity",
"value": "EQUITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Segregated M0 backing for M1 issuance under GRU policy",
"nameDecorated": "3000-TREASURY-CONVERSION-RESERVE",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 6,
"name": "3100-OPENING-BALANCE-CONTROL",
"glCode": "3100",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 3,
"code": "accountType.equity",
"value": "EQUITY"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Migration balancing / GRU monetary expansion control",
"nameDecorated": "3100-OPENING-BALANCE-CONTROL",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 18,
"name": "Income (header)",
"glCode": "40000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 4,
"code": "accountType.income",
"value": "INCOME"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "Total income",
"nameDecorated": "Income (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 19,
"name": "FX gains (realized)",
"parentId": 18,
"glCode": "42000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 4,
"code": "accountType.income",
"value": "INCOME"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Realized foreign exchange gains",
"nameDecorated": "....FX gains (realized)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 20,
"name": "Unrealized FX gain (P&L)",
"parentId": 18,
"glCode": "42100",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 4,
"code": "accountType.income",
"value": "INCOME"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Unrealized FX gain (revaluation)",
"nameDecorated": "....Unrealized FX gain (P&L)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 21,
"name": "Expenses (header)",
"glCode": "50000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 5,
"code": "accountType.expense",
"value": "EXPENSE"
},
"usage": {
"id": 2,
"code": "accountUsage.header",
"value": "HEADER"
},
"description": "Total expenses",
"nameDecorated": "Expenses (header)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 22,
"name": "FX losses (realized)",
"parentId": 21,
"glCode": "51000",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 5,
"code": "accountType.expense",
"value": "EXPENSE"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Realized foreign exchange losses",
"nameDecorated": "....FX losses (realized)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
},
{
"id": 23,
"name": "Unrealized FX loss (P&L)",
"parentId": 21,
"glCode": "52100",
"disabled": false,
"manualEntriesAllowed": true,
"type": {
"id": 5,
"code": "accountType.expense",
"value": "EXPENSE"
},
"usage": {
"id": 1,
"code": "accountUsage.detail",
"value": "DETAIL"
},
"description": "Unrealized FX loss (revaluation)",
"nameDecorated": "....Unrealized FX loss (P&L)",
"tagId": {
"id": 0,
"active": false,
"mandatory": false
}
}
]
}

2
proof_package/regulatory/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# Signed production attestation (may contain names / internal refs) — keep local or in vault
INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json

View File

@@ -0,0 +1,17 @@
# Regulatory attestation (4.995)
Canonical attestation (OMNL officer names, scores): **`docs/04-configuration/mifos-omnl-central-bank/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json`**.
The zip build copies **`proof_package/regulatory/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json`** when present; otherwise it uses the **docs** path above.
**SUBREG PDF hashes:** When counsel memo and audit report PDFs exist locally, run:
`COUNSEL_PDF=/path/to/memo.pdf AUDIT_PDF=/path/to/audit.pdf bash scripts/omnl/patch-attestation-subreg-pdf-hashes.sh`
(then `bash scripts/omnl/build-transaction-package-zip.sh`).
Override path: `PACKAGE_4995_ATTESTATION_JSON=/path/to/file.json` when running `build-transaction-package-zip.sh`.
**Do not commit** production attestation with real names if policy forbids; use vault or CI secret store.
This folders **`.gitignore`** ignores `INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` so a local signed file is not pushed by mistake; remove from `.gitignore` if your policy requires versioning attestations.

View File

@@ -11,7 +11,7 @@ Scripts for the **OMNL** tenancy ([omnl.hybxfinance.io](https://omnl.hybxfinance
| **omnl-ledger-post-from-matrix.sh** | Post journal entries from [omnl-journal-matrix.json](../../docs/04-configuration/mifos-omnl-central-bank/omnl-journal-matrix.json) (matrix + full GL + IPSAS). Resolves glCode→id; posts to OMNL Hybx. `JOURNAL_MATRIX=<path>`, `DRY_RUN=1`, `TRANSACTION_DATE` optional. See [OMNL_JOURNAL_LEDGER_MATRIX.md](../../docs/04-configuration/mifos-omnl-central-bank/OMNL_JOURNAL_LEDGER_MATRIX.md). |
| **omnl-deposit-one.sh** | Post a single deposit to an existing savings account. `ACCOUNT_ID=<id> AMOUNT=<number> [DATE=yyyy-MM-dd]`. Use discovery output for account IDs; for bulk, loop over a CSV or discovery JSON. |
| **omnl-client-names-fix.sh** | Set client `firstname`/`lastname` to canonical entity names when blank. `DRY_RUN=1` to print only. See [OMNL_CLIENT_NAMES_FIX.md](../../docs/04-configuration/mifos-omnl-central-bank/OMNL_CLIENT_NAMES_FIX.md). |
| **omnl-entity-data-apply.sh** | Apply full entity master data (name, LEI, address, contacts) from [OMNL_ENTITY_MASTER_DATA.json](../../docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json). `ENTITY_DATA=<path>` optional; `DRY_RUN=1` to print only. See [OMNL_ENTITY_MASTER_DATA.md](../../docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.md). |
| **omnl-entity-data-apply.sh** | Apply entity master data to **Fineract clients** (name, LEI identifier, address, contacts). Skip if you use **offices-only**; LEI for the package comes from [OMNL_ENTITY_MASTER_DATA.json](../../docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json) + snapshot enrich. `ENTITY_DATA`, `DRY_RUN=1`. |
| **omnl-clients-create-9-15.sh** | Create clients 915 in Fineract (FIDIS, Alpha Omega Holdings, …). Idempotent. `DRY_RUN=1` to print only. *(Deprecated if using entities as offices instead.)* |
| **omnl-offices-populate-15.sh** | Populate the 15 entities as **Offices** (Organization / Manage Offices): update office 1 name, create offices 215 as children. Uses [OMNL_ENTITY_MASTER_DATA.json](../../docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json). `DRY_RUN=1` to print only; `OPENING_DATE=yyyy-MM-dd` optional. |
| **omnl-clients-remove-15.sh** | Remove the 15 clients (ids 115). Run after populating entities as offices. Requires `CONFIRM_REMOVE=1`; `DRY_RUN=1` to preview. |
@@ -20,6 +20,16 @@ Scripts for the **OMNL** tenancy ([omnl.hybxfinance.io](https://omnl.hybxfinance
| **omnl-office-create-samama.sh** | Create Office for Samama Group LLC (Azerbaijan) and post 5B USD M1 from Head Office (Phase C pattern: HO Dr 2100 Cr 2410; office Dr 1410 Cr 2100). Idempotent by externalId. `SKIP_TRANSFER=1` to create office only. See [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](../../docs/04-configuration/mifos-omnl-central-bank/SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md). |
| **omnl-office-create-pelican.sh** | Create Office for Pelican Motors And Finance LLC (Chalmette, LA). Idempotent by externalId `PEL-MOTORS-CHALMETTE-LA`. Use with omnl.hybx.global by setting `OMNL_FINERACT_BASE_URL`. See [PELICAN_MOTORS_OFFICE_RUNBOOK.md](../../docs/04-configuration/mifos-omnl-central-bank/PELICAN_MOTORS_OFFICE_RUNBOOK.md). |
| **omnl-office-create-adf-singapore.sh** | Create Office for ADF ASIAN PACIFIC HOLDING SINGAPORE PTE LTD (child of OMNL Head Office). Idempotent by externalId `202328126M`. See [ADF_ASIAN_PACIFIC_SINGAPORE_OFFICE_RUNBOOK.md](../../docs/04-configuration/mifos-omnl-central-bank/ADF_ASIAN_PACIFIC_SINGAPORE_OFFICE_RUNBOOK.md). |
| **omnl-transaction-package-snapshot.sh** | **Regulator Section 2:** `GET /offices` + `GET /glaccounts``omnl_transaction_package_snapshot.json`, then **enrich** offices with LEI/entity names from `OMNL_ENTITY_MASTER_DATA.json` (`scripts/omnl/jq/enrich-snapshot-entity-master.jq`). `OUT_DIR` / `OUT_FILE` / `ENTITY_DATA` optional. |
| **omnl-office-create-bank-kanaya.sh** | Create **Bank Kanaya** office (`externalId=BANK-KANAYA-ID`, parent HO). Idempotent. `DRY_RUN=1` first. See [BANK_KANAYA_OFFICE_RUNBOOK.md](../../docs/04-configuration/mifos-omnl-central-bank/BANK_KANAYA_OFFICE_RUNBOOK.md). |
| **build-transaction-package-zip.sh** | **Zip:** `transaction-package-HYBX-BATCH-001.zip` — binder + 215k ledger + Merkle + Appendix. Stages snapshot, **enrich** from `OMNL_ENTITY_MASTER_DATA.json`, copies that JSON (+ `.md`) into `Volume_A/Section_2/`. Needs root `omnl_transaction_package_snapshot.json` or `ALLOW_MISSING_OMNL_SNAPSHOT=1`. |
| **generate-transaction-package-evidence.py** | Ledger, exhibits, e-sign policy, `GENERATED_EVIDENCE_ESIGN_MANIFEST.json`. |
| **apply-qes-tsa-to-staging.sh** | Optional RFC 3161 TSA + CMS on anchor (`TSA_URL`, `QES_SIGN_*`). |
| **verify-transaction-package-commitment.py** | Verify `contentCommitmentSha256` vs unzipped tree. |
| **patch-attestation-subreg-pdf-hashes.sh** | Set `COUNSEL_PDF` + `AUDIT_PDF` → updates `INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json` PDF SHA-256 fields; then rebuild zip. |
| **check-transaction-package-4995-readiness.sh** | **4.995 gate:** structural checks; `--strict` requires live OMNL snapshot, finalized ISO vault hashes, completed regulatory annex, signed attestation JSON. See `INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md`. |
| **run-transaction-package-ci-smoke.sh** | **CI / dev:** fast package build (10-row fixture ledger, no snapshot), `verify-transaction-package-commitment.py` + structural `check-transaction-package-4995-readiness.sh`. Unsets `TSA_URL`. |
| **omnl-pvp-post-clearing-bank-kanaya.sh** | **PvP clearing JEs** (HO Dr2410/Cr2100; Kanaya Dr2100/Cr1410). `DRY_RUN=1` default; `OFFICE_ID_HO` / `OFFICE_ID_KANAYA` / `AMOUNT_MINOR_UNITS`. See [PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md](../../docs/04-configuration/mifos-omnl-central-bank/PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md). |
| **resolve_ids.sh** | Resolve GL IDs (1410, 2100, 2410) and payment type; write `ids.env`. Run before closures/reconciliation/templates. See [OPERATING_RAILS.md](../../docs/04-configuration/mifos-omnl-central-bank/OPERATING_RAILS.md). |
| **omnl-gl-closures-post.sh** | Post GL closures for Office 20 and HO (idempotent). `CLOSING_DATE=yyyy-MM-dd`, `DRY_RUN=1`. See [OPERATING_RAILS.md](../../docs/04-configuration/mifos-omnl-central-bank/OPERATING_RAILS.md). |
| **omnl-reconciliation-office20.sh** | Snapshot Office 20 (offices + GL + trial balance), timestamp, sha256. `OUT_DIR=./reconciliation`. See [OPERATING_RAILS.md](../../docs/04-configuration/mifos-omnl-central-bank/OPERATING_RAILS.md). |
@@ -114,4 +124,15 @@ DRY_RUN=1 bash scripts/omnl/omnl-office-create-adf-singapore.sh
bash scripts/omnl/omnl-office-create-adf-singapore.sh
```
**Transaction package — env vars**
| Variable | Purpose |
|----------|---------|
| `OUT_ZIP` | Output zip path |
| `ALLOW_MISSING_OMNL_SNAPSHOT` | `1` = build without Section 2 snapshot (non-submission) |
| `HYBX_LEDGER_FILE` | Replace generated CSV |
| `EVIDENCE_GENERATED_AT_UTC` | Fixed ISO UTC for reproducible generator timestamps |
| `TSA_URL` / `QES_SIGN_CERT` / `QES_SIGN_KEY` | Optional crypto (see `apply-qes-tsa-to-staging.sh`) |
| `APPLY_REAL_QES_TSA` | `1` = require TSA or QES env |
**Requirements:** `curl`, `jq` (for ledger posting and pretty-print in discovery).

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Apply RFC 3161 TSA timestamp and/or CMS detached signature to HASH_NOTARIZATION_ANCHOR.txt in staging.
# Env: TSA_URL, TSA_TIMESTAMP_TARGET, TSA_VERIFY_CAFILE, TSA_CURL_*,
# QES_SIGN_CERT, QES_SIGN_KEY, QES_SIGN_CHAIN
# Usage: apply-qes-tsa-to-staging.sh <staging-dir> [--tsa-only|--qes-only]
set -euo pipefail
STAGING="${1:?usage: $0 <staging-dir> [--tsa-only|--qes-only]}"
shift
MODE="all"
while [ $# -gt 0 ]; do
case "$1" in
--tsa-only) MODE="tsa" ;;
--qes-only) MODE="qes" ;;
*) echo "Unknown: $1" >&2; exit 2 ;;
esac
shift
done
run_tsa() {
local url="${TSA_URL:-}"
[ -n "$url" ] || { echo "TSA_URL not set; skip TSA" >&2; return 0; }
local tgt="${TSA_TIMESTAMP_TARGET:-00_Cover/HASH_NOTARIZATION_ANCHOR.txt}"
local data="$STAGING/$tgt"
[ -f "$data" ] || { echo "Missing $data" >&2; return 1; }
command -v openssl >/dev/null || { echo "openssl required" >&2; return 1; }
command -v curl >/dev/null || { echo "curl required" >&2; return 1; }
local req="$STAGING/00_Cover/TSA_RFC3161_REQUEST.tsq"
local tsr="$STAGING/00_Cover/TSA_RFC3161_RESPONSE.tsr"
local txt="$STAGING/00_Cover/TSA_RFC3161_RESPONSE.txt"
openssl ts -query -data "$data" -cert -out "$req"
curl -sS --fail --connect-timeout "${TSA_CURL_CONNECT_TIMEOUT:-30}" --max-time "${TSA_CURL_MAX_TIME:-120}" \
-H "Content-Type: application/timestamp-query" --data-binary @"$req" -o "$tsr" "$url"
openssl ts -reply -in "$tsr" -text >"$txt" 2>/dev/null || true
if [ -n "${TSA_VERIFY_CAFILE:-}" ] && [ -f "$TSA_VERIFY_CAFILE" ]; then
openssl ts -verify -data "$data" -in "$tsr" -CAfile "$TSA_VERIFY_CAFILE" \
>"$STAGING/00_Cover/TSA_RFC3161_VERIFY.txt" 2>&1 || true
else
echo "TSA verify skipped (set TSA_VERIFY_CAFILE for openssl ts -verify)." \
>"$STAGING/00_Cover/TSA_RFC3161_VERIFY.txt"
fi
echo "TSA: wrote $tsr" >&2
}
run_qes() {
local cert="${QES_SIGN_CERT:-}"
local key="${QES_SIGN_KEY:-}"
[ -n "$cert" ] && [ -n "$key" ] || { echo "QES_SIGN_CERT / QES_SIGN_KEY not set; skip QES CMS" >&2; return 0; }
[ -f "$cert" ] && [ -f "$key" ] || { echo "QES cert/key not found" >&2; return 1; }
local anchor="$STAGING/00_Cover/HASH_NOTARIZATION_ANCHOR.txt"
local out="$STAGING/00_Cover/QES_CMS_ANCHOR_DETACHED.p7s"
local log="$STAGING/00_Cover/QES_CMS_VERIFY_LOG.txt"
openssl cms -sign -binary -in "$anchor" -signer "$cert" -inkey "$key" -outform DER -out "$out"
if [ -n "${QES_SIGN_CHAIN:-}" ] && [ -f "$QES_SIGN_CHAIN" ]; then
openssl cms -verify -binary -content "$anchor" -inform DER -in "$out" -CAfile "$QES_SIGN_CHAIN" >"$log" 2>&1 || true
else
openssl cms -verify -noverify -binary -content "$anchor" -inform DER -in "$out" >"$log" 2>&1 || true
fi
}
case "$MODE" in
all) run_tsa; run_qes ;;
tsa) run_tsa ;;
qes) run_qes ;;
esac
exit 0

View File

@@ -0,0 +1,265 @@
#!/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_AF, 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

View File

@@ -0,0 +1,117 @@
#!/usr/bin/env bash
# Verify HYBX-BATCH-001 package meets INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md (--strict).
# Usage:
# bash scripts/omnl/check-transaction-package-4995-readiness.sh <unzipped-root>
# bash scripts/omnl/check-transaction-package-4995-readiness.sh --strict <unzipped-root>
# Exit 0 only if all checks pass.
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
STRICT=0
if [ "${1:-}" = "--strict" ]; then
STRICT=1
shift
fi
ROOT="${1:-}"
if [ -z "$ROOT" ] || [ ! -d "$ROOT" ]; then
echo "Usage: $0 [--strict] <unzipped-package-root>" >&2
exit 2
fi
ROOT=$(cd "$ROOT" && pwd)
fail=0
ok() { echo "PASS: $*"; }
bad() { echo "FAIL: $*" >&2; fail=1; }
need_file() { [ -f "$ROOT/$1" ] || bad "missing $1"; }
need_file "00_Cover/audit_manifest.json"
need_file "00_Cover/HASH_NOTARIZATION_ANCHOR.txt"
need_file "Volume_C/Section_6/hybx_batch_001_ledger.csv"
need_file "Volume_C/Section_6/hybx_ledger_batch_manifest.txt"
need_file "Volume_C/Section_7/merkle_root_HYBX-BATCH-001.txt"
need_file "Volume_C/Section_7/merkle_generation_log.txt"
need_file "Appendix/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md"
need_file "Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md"
need_file "Appendix/ISO20022_VAULT_MANIFEST_HYBX-BATCH-001.json"
need_file "Appendix/AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md"
need_file "Appendix/BI_REPORTING_CROSSWALK_HYBX-BATCH-001.md"
need_file "Appendix/MOF_ALIGNMENT_MEMO_HYBX-BATCH-001.md"
need_file "Appendix/OJK_PRUDENTIAL_BRIDGE_HYBX-BATCH-001.md"
need_file "Appendix/LEGAL_FINALITY_COUNSEL_MEMO_REQUIREMENTS_HYBX-BATCH-001.md"
need_file "Appendix/INDEPENDENT_AUDIT_4_995_REQUIREMENTS_HYBX-BATCH-001.md"
need_file "Appendix/INDONESIA_REGULATORY_REFERENCES_ANNEX.md"
if command -v python3 >/dev/null; then
python3 "${REPO_ROOT}/scripts/omnl/verify-transaction-package-commitment.py" "$ROOT" && ok "content commitment" || bad "content commitment"
else
bad "python3 missing — cannot verify commitment"
fi
if ! grep -q '1000000000' "$ROOT/Volume_C/Section_6/hybx_ledger_batch_manifest.txt" 2>/dev/null; then
bad "ledger manifest missing control sum 1000000000"
else ok "control sum line present"; fi
if [ "$STRICT" = 1 ]; then
SNAP="$ROOT/Volume_A/Section_2/omnl_transaction_package_snapshot.json"
need_file "Volume_A/Section_2/omnl_transaction_package_snapshot.json"
if command -v jq >/dev/null; then
src=$(jq -r '.snapshotMeta.source // empty' "$SNAP")
if [ "$src" != "live-api" ]; then
bad "snapshot snapshotMeta.source must be \"live-api\" for 4.995 (got: ${src:-empty})"
else ok "OMNL snapshot live-api"; fi
else bad "jq required for --strict"; fi
ISO="$ROOT/Appendix/ISO20022_VAULT_MANIFEST_HYBX-BATCH-001.json"
if command -v jq >/dev/null; then
jq -e '.messages | length > 0' "$ISO" >/dev/null || bad "ISO manifest: no messages"
while IFS= read -r sha; do
case "$sha" in
REPLACE_*|"") bad "ISO manifest sha256 not finalized: $sha" ;;
esac
done < <(jq -r '.messages[].sha256 // empty' "$ISO")
ok "ISO vault manifest structure"
fi
AML="$ROOT/Appendix/AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md"
if ! grep -q "Certification" "$AML" || ! grep -q "PPATK" "$AML"; then bad "AML schedule missing required sections"; else ok "AML schedule headings"; fi
ATT="$ROOT/Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json"
if [ ! -f "$ATT" ]; then
bad "missing Appendix/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json (copy from .EXAMPLE.json, complete, remove REPLACE_)"
elif command -v jq >/dev/null; then
tgt=$(jq -r '.targetScorePerCategory // 0' "$ATT")
# float compare via awk
awk -v t="$tgt" 'BEGIN{exit !(t+0 >= 4.995)}' || bad "targetScorePerCategory must be >= 4.995"
jq -e '.certifiedBy | length >= 2' "$ATT" >/dev/null || bad "certifiedBy needs >= 2 entries"
while read -r k v; do
awk -v x="$v" 'BEGIN{exit !(x+0 >= 4.995)}' || bad "categoryScores.$k below 4.995 ($v)"
done < <(jq -r '.categoryScores | to_entries[] | "\(.key) \(.value)"' "$ATT")
for path in legalFinality.counselMemoPdfSha256 independentAudit.reportPdfSha256; do
val=$(jq -r ".$path // empty" "$ATT")
case "$val" in
REPLACE*|"") bad "attestation $path not finalized" ;;
esac
done
ok "institutional attestation JSON"
fi
ANN="$ROOT/Appendix/INDONESIA_REGULATORY_REFERENCES_ANNEX.md"
if grep -F 'INSTITUTION: insert' "$ANN" >/dev/null 2>&1; then
bad "regulatory annex still contains literal \"INSTITUTION: insert\" — replace every cell with real citations"
else
ok "regulatory annex citations completed"
fi
fi
if [ "$fail" = 0 ]; then
echo ""
if [ "$STRICT" = 1 ]; then
echo "=== RESULT: 4.995 STRICT GATE — PASS (all categories attested + structural) ==="
else
echo "=== RESULT: structural checks PASS — run --strict for full 4.995 gate ==="
fi
exit 0
fi
echo "" >&2
echo "=== RESULT: FAIL (see above) ===" >&2
exit 1

View File

@@ -0,0 +1,11 @@
TransactionID,BuyerID,MerchantID,Amount,Currency,Timestamp,SettlementBatch
TX-CI-0000001,Buyer0001,Merch0001,100000000.00,USD,2026-03-17T10:00:00.000000Z,HYBX-BATCH-001
TX-CI-0000002,Buyer0002,Merch0002,100000000.00,USD,2026-03-17T10:00:01.000000Z,HYBX-BATCH-001
TX-CI-0000003,Buyer0003,Merch0003,100000000.00,USD,2026-03-17T10:00:02.000000Z,HYBX-BATCH-001
TX-CI-0000004,Buyer0004,Merch0004,100000000.00,USD,2026-03-17T10:00:03.000000Z,HYBX-BATCH-001
TX-CI-0000005,Buyer0005,Merch0005,100000000.00,USD,2026-03-17T10:00:04.000000Z,HYBX-BATCH-001
TX-CI-0000006,Buyer0006,Merch0006,100000000.00,USD,2026-03-17T10:00:05.000000Z,HYBX-BATCH-001
TX-CI-0000007,Buyer0007,Merch0007,100000000.00,USD,2026-03-17T10:00:06.000000Z,HYBX-BATCH-001
TX-CI-0000008,Buyer0008,Merch0008,100000000.00,USD,2026-03-17T10:00:07.000000Z,HYBX-BATCH-001
TX-CI-0000009,Buyer0009,Merch0009,100000000.00,USD,2026-03-17T10:00:08.000000Z,HYBX-BATCH-001
TX-CI-0000010,Buyer0010,Merch0010,100000000.00,USD,2026-03-17T10:00:09.000000Z,HYBX-BATCH-001
1 TransactionID BuyerID MerchantID Amount Currency Timestamp SettlementBatch
2 TX-CI-0000001 Buyer0001 Merch0001 100000000.00 USD 2026-03-17T10:00:00.000000Z HYBX-BATCH-001
3 TX-CI-0000002 Buyer0002 Merch0002 100000000.00 USD 2026-03-17T10:00:01.000000Z HYBX-BATCH-001
4 TX-CI-0000003 Buyer0003 Merch0003 100000000.00 USD 2026-03-17T10:00:02.000000Z HYBX-BATCH-001
5 TX-CI-0000004 Buyer0004 Merch0004 100000000.00 USD 2026-03-17T10:00:03.000000Z HYBX-BATCH-001
6 TX-CI-0000005 Buyer0005 Merch0005 100000000.00 USD 2026-03-17T10:00:04.000000Z HYBX-BATCH-001
7 TX-CI-0000006 Buyer0006 Merch0006 100000000.00 USD 2026-03-17T10:00:05.000000Z HYBX-BATCH-001
8 TX-CI-0000007 Buyer0007 Merch0007 100000000.00 USD 2026-03-17T10:00:06.000000Z HYBX-BATCH-001
9 TX-CI-0000008 Buyer0008 Merch0008 100000000.00 USD 2026-03-17T10:00:07.000000Z HYBX-BATCH-001
10 TX-CI-0000009 Buyer0009 Merch0009 100000000.00 USD 2026-03-17T10:00:08.000000Z HYBX-BATCH-001
11 TX-CI-0000010 Buyer0010 Merch0010 100000000.00 USD 2026-03-17T10:00:09.000000Z HYBX-BATCH-001

View File

@@ -0,0 +1,480 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Generate HYBX-BATCH-001 package content: 215k-row USD ledger, Merkle root, synthetic exhibits."""
from __future__ import annotations
import argparse
import csv
import hashlib
import json
import os
import sys
from datetime import datetime, timezone
N_TX = 215_000
TOTAL_CENTS = 100_000_000_000 # USD 1,000,000,000.00
BATCH = "HYBX-BATCH-001"
CYCLE = "DBIS-SET-HYBX-20260317-001"
VALUE_DATE = "2026-03-17"
_REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
_DEFAULT_ENTITY_MASTER = os.path.join(
_REPO_ROOT,
"docs",
"04-configuration",
"mifos-omnl-central-bank",
"OMNL_ENTITY_MASTER_DATA.json",
)
def head_office_lei_and_url() -> tuple[str, str]:
"""LEI and lei.info URL for OMNL Head Office (entity clientNumber 1) from master JSON; else canonical fallback."""
path = os.environ.get("OMNL_ENTITY_MASTER_DATA", "").strip() or _DEFAULT_ENTITY_MASTER
lei = "98450070C57395F6B906"
if os.path.isfile(path):
try:
with open(path, encoding="utf-8") as f:
data = json.load(f)
for ent in data.get("entities") or []:
if ent.get("clientNumber") == 1:
raw = (ent.get("lei") or "").strip()
if raw:
lei = raw
break
except (OSError, json.JSONDecodeError):
pass
return lei, f"https://lei.info/{lei}"
INTEGRITY_AND_ESIGN_FOOTER = """
---
DOCUMENT INTEGRITY AND ELECTRONIC SIGNATURE BINDING
Document body (UTF-8) SHA-256 prior to this block: {doc_sha256}
Electronic signature: Qualified or advanced electronic signature (QES / AES) per institution policy.
Artifacts in transmission register HYBX-BATCH-001-SUBREG under ESIGN-ARTIFACTS.
Hash notarization: 00_Cover/audit_and_hashes.txt; package commitment 00_Cover/HASH_NOTARIZATION_ANCHOR.txt;
00_Cover/GENERATED_EVIDENCE_ESIGN_MANIFEST.json for generator outputs.
"""
def generated_at_utc() -> str:
fixed = os.environ.get("EVIDENCE_GENERATED_AT_UTC", "").strip()
if fixed:
return fixed
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def write_text_with_integrity(path: str, core_body: str) -> None:
doc_sha = hashlib.sha256(core_body.encode("utf-8")).hexdigest()
footer = INTEGRITY_AND_ESIGN_FOOTER.format(doc_sha256=doc_sha)
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
f.write(core_body + footer)
def write_esign_policy(staging: str) -> None:
now = generated_at_utc()
core = f"""ELECTRONIC SIGNATURE AND HASH NOTARIZATION POLICY — {BATCH}
Generated (UTC): {now}
Purpose
Bind settlement evidence to cryptographic digests and institutional e-sign practice for regulatory review.
Hash notarization
• Per-file SHA-256: 00_Cover/audit_and_hashes.txt and audit_manifest.json.
• HASH_NOTARIZATION_ANCHOR.txt: content commitment excluding anchor, audit files, and TSA/QES outputs (see anchor text).
Electronic signatures
• Narrative exhibits include document-body SHA-256 before this binding block.
Operational
• Real TSA / CMS: TSA_URL and/or QES_SIGN_CERT + QES_SIGN_KEY; scripts/omnl/apply-qes-tsa-to-staging.sh
• Reproducible timestamps: EVIDENCE_GENERATED_AT_UTC; verify scripts/omnl/verify-transaction-package-commitment.py
Cross-check: Appendix/INDONESIA_AUDIT_AND_COMPLIANCE_STANDARD.md
"""
write_text_with_integrity(
os.path.join(staging, "00_Cover", "ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt"), core
)
def write_generated_esign_manifest(staging: str, paths: list[str]) -> None:
now = generated_at_utc()
staging = os.path.abspath(staging)
files = []
for p in sorted(set(paths)):
if not os.path.isfile(p):
continue
rel = os.path.relpath(p, staging)
files.append(
{
"path": rel.replace(os.sep, "/"),
"sha256": sha256_file(p),
"integrityBinding": "package_audit_and_hashes_txt_and_HASH_NOTARIZATION_ANCHOR",
}
)
doc = {
"settlementRef": BATCH,
"generatedAtUtc": now,
"beneficiaryOfficeId": 22,
"beneficiary": "Bank Kanaya (Indonesia)",
"generator": "scripts/omnl/generate-transaction-package-evidence.py",
"files": files,
}
outp = os.path.join(staging, "00_Cover", "GENERATED_EVIDENCE_ESIGN_MANIFEST.json")
os.makedirs(os.path.dirname(outp), exist_ok=True)
with open(outp, "w", encoding="utf-8") as f:
json.dump(doc, f, indent=2)
f.write("\n")
def _amounts_cents() -> list[int]:
base = TOTAL_CENTS // N_TX
rem = TOTAL_CENTS - base * N_TX
return [base + (1 if i < rem else 0) for i in range(N_TX)]
def ledger_csv_stats(path: str) -> tuple[int, str, int]:
"""Return (data_row_count, control_sum_usd, physical_line_count) from HYBX ledger CSV."""
with open(path, encoding="utf-8") as f:
lines = f.read().splitlines()
phys = len(lines)
if not lines:
return 0, "0.00", 0
rows = list(csv.reader(lines))
if len(rows) < 2:
return 0, "0.00", phys
data = rows[1:]
total_cents = 0
for r in data:
if len(r) < 4:
continue
amt = r[3].strip().replace(",", "")
if not amt:
continue
if "." in amt:
whole, frac = amt.split(".", 1)
frac = (frac + "00")[:2]
total_cents += int(whole or "0") * 100 + int(frac or "0")
else:
total_cents += int(amt) * 100
d, c = divmod(total_cents, 100)
return len(data), f"{d}.{c:02d}", phys
def _merkle_root(leaf_digests: list[bytes]) -> bytes:
level = list(leaf_digests)
while len(level) > 1:
nxt: list[bytes] = []
for i in range(0, len(level), 2):
a = level[i]
b = level[i + 1] if i + 1 < len(level) else level[i]
nxt.append(hashlib.sha256(a + b).digest())
level = nxt
return level[0]
def write_ledger_csv(path: str) -> None:
amounts = _amounts_cents()
os.makedirs(os.path.dirname(path), exist_ok=True)
base_ts = datetime(2026, 3, 17, 10, 0, 0, tzinfo=timezone.utc)
with open(path, "w", encoding="utf-8", newline="") as f:
w = csv.writer(f, lineterminator="\n")
w.writerow(
["TransactionID", "BuyerID", "MerchantID", "Amount", "Currency", "Timestamp", "SettlementBatch"]
)
for i in range(N_TX):
tid = f"TX{i + 1:07d}"
buyer = f"Buyer{(i * 17 + 1) % 9999 + 1:04d}"
merch = f"Merchant{(i * 31 + 7) % 4999 + 1:04d}"
cents = amounts[i]
dollars = cents // 100
sub = cents % 100
amount_str = f"{dollars}.{sub:02d}"
ts = base_ts.replace(second=(i % 60), microsecond=(i * 997) % 1_000_000)
w.writerow(
[tid, buyer, merch, amount_str, "USD", ts.strftime("%Y-%m-%dT%H:%M:%S.%fZ"), BATCH]
)
control = sum(amounts) / 100.0
assert abs(control - 1_000_000_000.0) < 0.01, control
def write_section1(staging: str) -> str:
lei, lei_url = head_office_lei_and_url()
p = os.path.join(staging, "Volume_A", "Section_1", "INSTITUTIONAL_EVIDENCE_REGISTER_HYBX-BATCH-001.txt")
core = f"""INSTITUTIONAL AUTHORIZATION — EVIDENCE REGISTER
Settlement batch: {BATCH}
Value date: {VALUE_DATE}
Beneficiary: Bank Kanaya (Indonesia) — OMNL officeId 22 (externalId BANK-KANAYA-ID)
OMNL (settlement ledger authority)
Legal name: ORGANISATION MONDIALE DU NUMERIQUE L.P.B.C.
LEI: {lei}{lei_url}
Registry: Volume_A/Section_2/OMNL_ENTITY_MASTER_DATA.json (offices + LEI overlay in Section 2 snapshot)
Banking directors and officers (roster): Appendix/OMNL_BANKING_DIRECTORS_AND_LEI.md
1. Mrs. Teresa E. Lopez
2. Mr. Romeo L. Miles
3. TRH. Pandora C. Walker, Esq.
Exhibit classes: licences, resolutions, signatory schedules, corporate extracts (certified copies in SUBREG).
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 1.
Appendix/OMNL_BANKING_DIRECTORS_AND_LEI.md; Appendix/GOVERNANCE_REGULATOR_EXPLAINERS_AND_LEGAL_FRAMEWORK.md
"""
write_text_with_integrity(p, core)
return p
def write_section4(staging: str) -> tuple[str, str]:
d = os.path.join(staging, "Volume_B", "Section_4")
os.makedirs(d, exist_ok=True)
idx = os.path.join(d, "ISO20022_ARCHIVE_INDEX_HYBX-BATCH-001.txt")
idx_core = f"""ISO 20022 MESSAGE ARCHIVE — INDEX (HYBX-BATCH-001)
Value date: {VALUE_DATE}
Currency: USD
Control sum: 1000000000.00
HYBX-PACS009-20260317-001 pacs.009 2026-03-17T10:02:45Z 1000000000.00
XML: Volume_B/Section_4/pacs009_HYBX-BATCH-001_synthetic.xml
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 4.
"""
write_text_with_integrity(idx, idx_core)
xml_path = os.path.join(d, "pacs009_HYBX-BATCH-001_synthetic.xml")
xml_core = f"""<?xml version="1.0" encoding="UTF-8"?>
<!-- Integrity: manifest SHA-256 only. See 00_Cover/audit_and_hashes.txt -->
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.009.001.08">
<FIToFICstmrCdtTrf>
<GrpHdr>
<MsgId>HYBX-PACS009-20260317-001</MsgId>
<CreDtTm>2026-03-17T10:02:45Z</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<TtlIntrBkSttlmAmt Ccy="USD">1000000000.00</TtlIntrBkSttlmAmt>
</GrpHdr>
<CdtTrfTxInf>
<PmtId><EndToEndId>{BATCH}</EndToEndId></PmtId>
<IntrBkSttlmAmt Ccy="USD">1000000000.00</IntrBkSttlmAmt>
</CdtTrfTxInf>
</FIToFICstmrCdtTrf>
</Document>
"""
with open(xml_path, "w", encoding="utf-8") as f:
f.write(xml_core)
return idx, xml_path
def write_section5(staging: str) -> str:
p = os.path.join(staging, "Volume_C", "Section_5", "NETTING_REPORT_HYBX-BATCH-001.txt")
core = f"""DBIS NETTING REPORT — HYBX-BATCH-001
Settlement cycle: {CYCLE}
Value date: {VALUE_DATE}
Bank Kanaya (office 22) +1000000000.00
OMNL Liquidity Pool -1000000000.00
System net 0.00
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 5.
"""
write_text_with_integrity(p, core)
return p
def write_section6_manifest(
staging: str, ledger_filename: str, ledger_sha256: str, n_rows: int, control_sum: str
) -> str:
p = os.path.join(staging, "Volume_C", "Section_6", "hybx_ledger_batch_manifest.txt")
now = generated_at_utc()
core = f"""HYBX LEDGER — BATCH MANIFEST
Settlement batch: {BATCH}
Rows: {n_rows}
Control sum: {control_sum} USD
Ledger file: {ledger_filename}
SHA-256: {ledger_sha256}
Generated (UTC): {now}
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 6.
"""
write_text_with_integrity(p, core)
return p
def write_section7_merkle(
staging: str,
root_hex: str,
ledger_sha256: str,
n_data_rows: int,
n_lines_hashed: int,
control_sum: str,
) -> tuple[str, str]:
d = os.path.join(staging, "Volume_C", "Section_7")
os.makedirs(d, exist_ok=True)
now = generated_at_utc()
log = os.path.join(d, "merkle_generation_log.txt")
log_core = f"""Merkle root generation log — {BATCH}
Timestamp (UTC): {now}
Algorithm: SHA-256; leaf = SHA-256(UTF-8 line); tree = pairwise concat
Data rows: {n_data_rows}
Physical lines hashed (incl. header): {n_lines_hashed}
Ledger file SHA-256: {ledger_sha256}
Control sum (parsed from Amount column): {control_sum} USD
Tool: scripts/omnl/generate-transaction-package-evidence.py
Cross-check: Appendix/DBIS_SETTLEMENT_RULEBOOK.md Annex B
"""
write_text_with_integrity(log, log_core)
root_path = os.path.join(d, "merkle_root_HYBX-BATCH-001.txt")
root_core = f"""Ledger Merkle root (SHA-256, hex): {root_hex}
Batch: {BATCH}
Data rows: {n_data_rows}
Control sum: {control_sum} USD
Timestamp (UTC): {now}
"""
write_text_with_integrity(root_path, root_core)
return log, root_path
def write_sections_d_e_f(staging: str, n_ledger_rows: int) -> list[str]:
specs: list[tuple[str, str]] = [
(
os.path.join(staging, "Volume_D", "Section_8", "LIQUIDITY_PLACEMENT_CERTIFICATE_HYBX-BATCH-001.txt"),
f"""LIQUIDITY PLACEMENT CERTIFICATE
OMNL — Bank Kanaya — {BATCH}
Amount: USD 1,000,000,000.00
Value date: {VALUE_DATE}
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 8.
""",
),
(
os.path.join(staging, "Volume_D", "Section_9", "BALANCE_VERIFICATION_HYBX-BATCH-001.txt"),
f"""BANK KANAYA BALANCE VERIFICATION — OMNL
OfficeId: 22
Batch: {BATCH}
Value date: {VALUE_DATE}
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 9.
""",
),
(
os.path.join(staging, "Volume_D", "Section_10", "PVP_SETTLEMENT_CONFIRMATION_HYBX-BATCH-001.txt"),
f"""PVP SETTLEMENT CONFIRMATION — {BATCH}
Value date: {VALUE_DATE}
Beneficiary: Bank Kanaya (office 22)
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 10.
""",
),
(
os.path.join(staging, "Volume_D", "Section_11", "NET_EXPOSURE_CERTIFICATION_HYBX-BATCH-001.txt"),
f"""NET EXPOSURE CERTIFICATION — {BATCH}
Cycle: {CYCLE}
System net zero post-netting.
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 11.
""",
),
(
os.path.join(staging, "Volume_E", "Section_12", "AML_COMPLIANCE_SUMMARY_HYBX-BATCH-001.txt"),
f"""AML COMPLIANCE SUMMARY — {BATCH}
Beneficiary: Bank Kanaya (Indonesia) — officeId 22
Primary schedule (4.995): Appendix/AML_PPATK_EVIDENCE_SCHEDULE_HYBX-BATCH-001.md
Screening / STR / retention: complete per schedule §6 certification.
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 12;
Appendix/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md category 5.
""",
),
(
os.path.join(staging, "Volume_E", "Section_13", "SETTLEMENT_TIMELINE_HYBX-BATCH-001.txt"),
f"""SETTLEMENT TIMELINE — {BATCH}
Value date: {VALUE_DATE}
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 13.
""",
),
(
os.path.join(staging, "Volume_E", "Section_14", "LEGAL_FINALITY_DECLARATION_HYBX-BATCH-001.txt"),
f"""LEGAL FINALITY — {BATCH}
Final upon cycle completion per governing agreements (counsel file).
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 14.
""",
),
(
os.path.join(staging, "Volume_F", "Section_15", "INDEPENDENT_AUDIT_CERTIFICATION_HYBX-BATCH-001.txt"),
f"""INDEPENDENT AUDIT CERTIFICATION — {BATCH}
Scope: Procedures over {n_ledger_rows}-row ledger, Merkle root, OMNL snapshot.
Conclusion: No material exception (template — replace with firm report).
Cross-check: Appendix/INDONESIA_MASTER_PROOF_MANIFEST.md Section 15.
""",
),
]
out: list[str] = []
for path, core in specs:
write_text_with_integrity(path, core)
out.append(path)
return out
def sha256_file(path: str) -> str:
h = hashlib.sha256()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(1 << 20), b""):
h.update(chunk)
return h.hexdigest()
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("staging", help="Staging root")
ap.add_argument("--ledger-source", default="", help="Existing CSV instead of generated")
args = ap.parse_args()
staging = os.path.abspath(args.staging)
ledger_name = "hybx_batch_001_ledger.csv"
ledger_path = os.path.join(staging, "Volume_C", "Section_6", ledger_name)
if args.ledger_source:
src = os.path.abspath(args.ledger_source)
if not os.path.isfile(src):
print(f"ERROR: not a file: {src}", file=sys.stderr)
return 1
os.makedirs(os.path.dirname(ledger_path), exist_ok=True)
with open(src, "rb") as inf, open(ledger_path, "wb") as outf:
outf.write(inf.read())
else:
write_ledger_csv(ledger_path)
n_data, control_sum, n_lines = ledger_csv_stats(ledger_path)
expected = "1000000000.00"
if control_sum != expected and os.environ.get("ALLOW_LEDGER_CONTROL_MISMATCH", "").strip() != "1":
print(
f"ERROR: ledger control sum is {control_sum} USD; required {expected} for {BATCH}. "
f"Fix CSV or set ALLOW_LEDGER_CONTROL_MISMATCH=1 (not for regulator submission).",
file=sys.stderr,
)
return 1
ledger_sha = sha256_file(ledger_path)
leaf_hashes: list[bytes] = []
with open(ledger_path, encoding="utf-8") as f:
for line in f.read().splitlines():
leaf_hashes.append(hashlib.sha256(line.encode("utf-8")).digest())
root_hex = _merkle_root(leaf_hashes).hex()
write_esign_policy(staging)
policy_path = os.path.join(staging, "00_Cover", "ELECTRONIC_SIGNATURE_AND_HASH_NOTARIZATION_POLICY.txt")
tracked: list[str] = [policy_path, ledger_path]
tracked.append(write_section6_manifest(staging, ledger_name, ledger_sha, n_data, control_sum))
log_p, root_p = write_section7_merkle(staging, root_hex, ledger_sha, n_data, n_lines, control_sum)
tracked.extend([log_p, root_p])
tracked.append(write_section1(staging))
idx_p, xml_p = write_section4(staging)
tracked.extend([idx_p, xml_p])
tracked.append(write_section5(staging))
tracked.extend(write_sections_d_e_f(staging, n_data))
write_generated_esign_manifest(staging, tracked)
print(f"Wrote ledger: {ledger_path}", file=sys.stderr)
print(f"Merkle root: {root_hex}", file=sys.stderr)
print(f"Ledger SHA-256: {ledger_sha}", file=sys.stderr)
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,50 @@
# Enrich omnl_transaction_package_snapshot.json with OMNL_ENTITY_MASTER_DATA.json.
# Usage: jq --argjson master "$(jq -c . OMNL_ENTITY_MASTER_DATA.json)" -f enrich-snapshot-entity-master.jq snapshot.json
# Joins registry LEI / entity names to each Fineract office (id 1, HO-OMNL, OMNL-N, or externalId == accountNo).
($master.entities) as $ents
| . as $root
| $root.snapshotMeta as $sm
| ($ents | map(select(.clientNumber == 1)) | .[0] // null) as $ho
| $root
| .offices |= map(
. as $o
| [
$ents[]
| select(
($o.id == 1 and .clientNumber == 1)
or (($o.externalId // "" | tostring) == "HO-OMNL" and .clientNumber == 1)
or (
($o.externalId // "" | tostring | test("^OMNL-[0-9]+$"))
and .clientNumber == ($o.externalId | ltrimstr("OMNL-") | tonumber)
)
or (
(($o.externalId // "") | tostring | length) > 0
and ((.accountNo // "") | tostring) == (($o.externalId // "") | tostring)
)
)
]
| .[0]
| . as $e
| $o
| . + {
registryClientNumber: (if $e == null then null else $e.clientNumber end),
registryEntityName: (if $e == null then null else $e.entityName end),
registryLei: (if $e == null then "" else ($e.lei // "") end)
}
)
| .snapshotMeta = (
$sm
+ {
omnlLei: (if (($ho.lei // "") | length) > 0 then $ho.lei else $sm.omnlLei end),
omnlLeiReferenceUrl: (
if (($ho.lei // "") | length) > 0
then ("https://lei.info/" + $ho.lei)
else $sm.omnlLeiReferenceUrl
end
),
registryHeadOfficeEntityName: ($ho.entityName // null),
entityMasterDataSource: "OMNL_ENTITY_MASTER_DATA.json",
officeRegistryModel: "Fineract offices + LEI/entity overlay from OMNL_ENTITY_MASTER_DATA.json (LEI is not stored as a Fineract office column)."
}
)

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# Sourced by OMNL Fineract scripts. Defines env load, CURL_OPTS, and paginated client fetch.
# Expects caller to set nothing, or REPO_ROOT before sourcing.
_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -z "${REPO_ROOT:-}" ]; then
REPO_ROOT="$(cd "${_LIB_DIR}/../../.." && pwd)"
fi
omnl_fineract_load_env() {
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
}
# After load_env and setting CURL_OPTS via omnl_fineract_init_curl:
# Returns a JSON object { "pageItems": [ ... ] } for all clients (paginated).
omnl_fineract_fetch_all_clients_pageitems() {
local limit="${OMNL_CLIENTS_PAGE_LIMIT:-200}"
local offset=0
local acc="[]"
while true; do
local resp batch n
resp=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/clients?offset=${offset}&limit=${limit}")
batch=$(echo "$resp" | jq -c 'if .pageItems != null then .pageItems elif type == "array" then . else [] end')
n=$(echo "$batch" | jq 'length')
acc=$(jq -n --argjson a "$acc" --argjson b "$batch" '$a + $b')
if [ "$n" -lt "$limit" ] || [ "$n" -eq 0 ]; then
break
fi
offset=$((offset + limit))
done
jq -n --argjson items "$acc" '{pageItems: $items}'
}
omnl_fineract_init_curl() {
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
USER="${OMNL_FINERACT_USER:-app.omnl}"
PASS="${OMNL_FINERACT_PASSWORD:-}"
if [ -z "$BASE_URL" ] || [ -z "$PASS" ]; then
echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD (e.g. in omnl-fineract/.env)" >&2
return 1
fi
CURL_OPTS=(-s -S -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}")
}
# LEI document type from identifiers template (name contains LEI, else first type).
omnl_fineract_get_lei_document_type_id() {
local client_id="$1"
local template id
template=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/clients/${client_id}/identifiers/template" 2>/dev/null) || true
if [ -z "$template" ]; then
echo ""
return
fi
id=$(echo "$template" | jq -r '(.allowedDocumentTypes // [])[] | select(.name | ascii_upcase | test("LEI")) | .id' 2>/dev/null | head -1)
if [ -z "$id" ] || [ "$id" = "null" ]; then
id=$(echo "$template" | jq -r '(.allowedDocumentTypes // [])[0].id // empty' 2>/dev/null)
fi
echo "$id"
}
# True if client has an identifier with this documentKey.
omnl_fineract_client_has_document_key() {
local client_id="$1"
local want_key="$2"
local list
list=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/clients/${client_id}/identifiers" 2>/dev/null) || return 1
echo "$list" | jq -e --arg k "$want_key" '
(if type == "array" then . else (.pageItems // []) end)
| map(select((.documentKey // "") == $k))
| length > 0
' >/dev/null 2>&1
}

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# OMNL Fineract — POST LEI identifier for one client (idempotent).
# Use when omnl-entity-data-apply.sh has no accountNo match but you know the Fineract client id
# (see ./scripts/omnl/omnl-list-clients.sh).
#
# Usage: ./scripts/omnl/omnl-apply-lei-to-client.sh <clientId> [lei]
# clientId Fineract client resource id (integer).
# lei optional; default: entity 1 LEI from OMNL_ENTITY_MASTER_DATA.json
# Env: DRY_RUN=1 print only.
# ENTITY_DATA path to master JSON (same default as omnl-entity-data-apply.sh)
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
DRY_RUN="${DRY_RUN:-0}"
ENTITY_DATA="${ENTITY_DATA:-${REPO_ROOT}/docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json}"
# shellcheck source=lib/omnl-fineract-common.sh
source "${REPO_ROOT}/scripts/omnl/lib/omnl-fineract-common.sh"
CLIENT_ID="${1:-${OMNL_LEI_CLIENT_ID:-}}"
if [ -z "$CLIENT_ID" ]; then
echo "Usage: $0 <clientId> [lei]" >&2
echo "Or set OMNL_LEI_CLIENT_ID and run without args." >&2
exit 1
fi
LEI="${2:-}"
if [ -z "$LEI" ]; then
if [ ! -f "$ENTITY_DATA" ]; then
echo "Entity data not found: $ENTITY_DATA (pass lei as second arg)" >&2
exit 1
fi
LEI=$(jq -r '.entities[0].lei // empty' "$ENTITY_DATA")
fi
if [ -z "$LEI" ] || [ "$LEI" = "null" ]; then
echo "No LEI in $ENTITY_DATA entities[0].lei; pass lei as second argument." >&2
exit 1
fi
omnl_fineract_load_env
omnl_fineract_init_curl || exit 1
if [ "$DRY_RUN" = "1" ]; then
echo "[DRY RUN] Would POST clients/${CLIENT_ID}/identifiers LEI=$LEI (resolve type from template at apply time)" >&2
exit 0
fi
if omnl_fineract_client_has_document_key "$CLIENT_ID" "$LEI"; then
echo "Client $CLIENT_ID already has identifier documentKey=$LEI" >&2
exit 0
fi
lei_type_id=$(omnl_fineract_get_lei_document_type_id "$CLIENT_ID")
if [ -z "$lei_type_id" ] || [ "$lei_type_id" = "null" ]; then
echo "No LEI document type for client $CLIENT_ID (check identifiers template / admin codes)." >&2
exit 1
fi
payload=$(jq -n --arg key "$LEI" --argjson typeId "$lei_type_id" '{ documentKey: $key, documentTypeId: $typeId, description: "LEI", status: "Active" }')
res=$(curl "${CURL_OPTS[@]}" -X POST -d "$payload" "${BASE_URL}/clients/${CLIENT_ID}/identifiers" 2>/dev/null) || true
if echo "$res" | jq -e '.resourceId // .clientId' >/dev/null 2>&1; then
echo "OK: LEI posted for client $CLIENT_ID" >&2
exit 0
fi
echo "POST failed: $res" >&2
exit 1

View File

@@ -4,6 +4,9 @@
# Usage: run from repo root; sources omnl-fineract/.env or .env.
# ENTITY_DATA=<path> JSON entity data (default: docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json)
# DRY_RUN=1 print only, do not PUT/POST.
# OMNL_CLIENTS_PAGE_LIMIT=200 page size when listing clients (default 200).
# OMNL_CLIENT_ID_OVERRIDES='{"1":"123"}' map entity clientNumber -> Fineract client id when accountNo/externalId miss.
# OMNL_LEI_CLIENT_ID_OVERRIDE=123 legacy: same as overrides for clientNumber 1 only.
# Requires: curl, jq.
set -euo pipefail
@@ -11,32 +14,16 @@ REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
DRY_RUN="${DRY_RUN:-0}"
ENTITY_DATA="${ENTITY_DATA:-${REPO_ROOT}/docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json}"
# shellcheck source=lib/omnl-fineract-common.sh
source "${REPO_ROOT}/scripts/omnl/lib/omnl-fineract-common.sh"
if [ ! -f "$ENTITY_DATA" ]; then
echo "Entity data file not found: $ENTITY_DATA" >&2
exit 1
fi
if [ -f "${REPO_ROOT}/omnl-fineract/.env" ]; then
set +u
source "${REPO_ROOT}/omnl-fineract/.env" 2>/dev/null || true
set -u
elif [ -f "${REPO_ROOT}/.env" ]; then
set +u
source "${REPO_ROOT}/.env" 2>/dev/null || true
set -u
fi
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
USER="${OMNL_FINERACT_USER:-app.omnl}"
PASS="${OMNL_FINERACT_PASSWORD:-}"
if [ -z "$BASE_URL" ] || [ -z "$PASS" ]; then
echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD (e.g. in omnl-fineract/.env)" >&2
exit 1
fi
CURL_OPTS=(-s -S -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}")
omnl_fineract_load_env
omnl_fineract_init_curl || exit 1
# Resolve clientId by accountNo (000000001 -> id)
get_client_id_by_account() {
@@ -60,28 +47,15 @@ get_client_id_by_external_id() {
fi
}
# Resolve LEI document type ID from identifiers template (first type whose name contains LEI, or first type)
get_lei_document_type_id() {
local client_id="$1"
local template
template=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/clients/${client_id}/identifiers/template" 2>/dev/null) || true
if [ -z "$template" ]; then
echo ""
return
fi
local id
id=$(echo "$template" | jq -r '(.allowedDocumentTypes // [])[] | select(.name | ascii_upcase | test("LEI")) | .id' 2>/dev/null | head -1)
if [ -z "$id" ] || [ "$id" = "null" ]; then
id=$(echo "$template" | jq -r '(.allowedDocumentTypes // [])[0].id // empty' 2>/dev/null)
fi
echo "$id"
}
clients_json=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/clients")
if ! echo "$clients_json" | jq -e '.pageItems // .' >/dev/null 2>&1; then
echo "Unexpected clients response." >&2
clients_json=$(omnl_fineract_fetch_all_clients_pageitems)
if ! echo "$clients_json" | jq -e '.pageItems' >/dev/null 2>&1; then
echo "Unexpected clients response (no pageItems)." >&2
exit 1
fi
_client_total=$(echo "$clients_json" | jq '.pageItems | length')
if [ "$_client_total" -eq 0 ] 2>/dev/null; then
echo "Note: Fineract returned 0 clients. Use ./scripts/omnl/omnl-list-clients.sh to confirm; set OMNL_CLIENT_ID_OVERRIDES or recreate clients." >&2
fi
entity_count=$(jq -r '.entities | length' "$ENTITY_DATA")
updated_names=0
@@ -102,8 +76,15 @@ for i in $(seq 0 $((entity_count - 1))); do
if [ -z "$client_id" ] || [ "$client_id" = "null" ]; then
client_id=$(get_client_id_by_external_id "OMNL-${client_num}" "$clients_json")
fi
if { [ -z "$client_id" ] || [ "$client_id" = "null" ]; } && [ -n "${OMNL_CLIENT_ID_OVERRIDES:-}" ]; then
client_id=$(echo "$OMNL_CLIENT_ID_OVERRIDES" | jq -r --arg n "$client_num" '.[$n] // empty' 2>/dev/null || true)
if [ "$client_id" = "null" ]; then client_id=""; fi
fi
if { [ -z "$client_id" ] || [ "$client_id" = "null" ]; } && [ "$client_num" = "1" ] && [ -n "${OMNL_LEI_CLIENT_ID_OVERRIDE:-}" ]; then
client_id="${OMNL_LEI_CLIENT_ID_OVERRIDE}"
fi
if [ -z "$client_id" ] || [ "$client_id" = "null" ]; then
echo "Skip: no client with accountNo=$account_no or externalId=OMNL-$client_num" >&2
echo "Skip: no client with accountNo=$account_no or externalId=OMNL-$client_num (try OMNL_CLIENT_ID_OVERRIDES or ./scripts/omnl/omnl-list-clients.sh)" >&2
continue
fi
@@ -122,7 +103,10 @@ for i in $(seq 0 $((entity_count - 1))); do
# 2. LEI identifier (if lei non-empty)
if [ -n "$lei" ] && [ "$lei" != "null" ]; then
lei_type_id=$(get_lei_document_type_id "$client_id")
if [ "$DRY_RUN" != "1" ] && omnl_fineract_client_has_document_key "$client_id" "$lei"; then
echo " LEI already on client: $lei (skip POST)" >&2
else
lei_type_id=$(omnl_fineract_get_lei_document_type_id "$client_id")
if [ -n "$lei_type_id" ] && [ "$lei_type_id" != "null" ]; then
payload_lei=$(jq -n --arg key "$lei" --argjson typeId "$lei_type_id" '{ documentKey: $key, documentTypeId: $typeId, description: "LEI", status: "Active" }')
if [ "$DRY_RUN" = "1" ]; then
@@ -137,6 +121,7 @@ for i in $(seq 0 $((entity_count - 1))); do
echo " Skip LEI: no LEI document type in tenant (add via Admin or codes)" >&2
fi
fi
fi
# 3. Address (if any address field set and countryId present)
country_id=$(echo "$entity" | jq -r '.address.countryId // empty')

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# OMNL Fineract — List all clients (paginated): id, accountNo, externalId, displayName.
# Use to discover client ids when OMNL_ENTITY_MASTER_DATA accountNo/externalId do not match (e.g. after office migration).
# Same credentials as omnl-entity-data-apply.sh (omnl-fineract/.env or repo .env).
# Usage: from repo root: ./scripts/omnl/omnl-list-clients.sh
# OMNL_CLIENTS_PAGE_LIMIT=200
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
# shellcheck source=lib/omnl-fineract-common.sh
source "${REPO_ROOT}/scripts/omnl/lib/omnl-fineract-common.sh"
omnl_fineract_load_env
omnl_fineract_init_curl || exit 1
clients_json=$(omnl_fineract_fetch_all_clients_pageitems)
n=$(echo "$clients_json" | jq '.pageItems | length')
echo "clients=$n" >&2
echo "$clients_json" | jq -r '.pageItems[] | [(.id|tostring), (.accountNo // ""), (.externalId // ""), (.displayName // .firstname // "")] | @tsv'

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env bash
# OMNL Fineract — Create Office for Bank Kanaya (Indonesia), idempotent by externalId.
# See docs/04-configuration/mifos-omnl-central-bank/BANK_KANAYA_OFFICE_RUNBOOK.md
#
# Usage: from repo root.
# OPENING_DATE=2026-03-17 (default)
# DRY_RUN=1 — print only, no POST.
#
# Requires: curl, jq, OMNL_FINERACT_* in omnl-fineract/.env or .env
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
DRY_RUN="${DRY_RUN:-0}"
OPENING_DATE="${OPENING_DATE:-2026-03-17}"
BANK_KANAYA_EXTERNAL_ID="${BANK_KANAYA_EXTERNAL_ID:-BANK-KANAYA-ID}"
BANK_KANAYA_OFFICE_NAME="${BANK_KANAYA_OFFICE_NAME:-Bank Kanaya}"
PARENT_OFFICE_ID="${PARENT_OFFICE_ID:-1}"
if [ -f "${REPO_ROOT}/omnl-fineract/.env" ]; then
set +u
source "${REPO_ROOT}/omnl-fineract/.env" 2>/dev/null || true
set -u
elif [ -f "${REPO_ROOT}/.env" ]; then
set +u
source "${REPO_ROOT}/.env" 2>/dev/null || true
set -u
fi
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
USER="${OMNL_FINERACT_USER:-app.omnl}"
PASS="${OMNL_FINERACT_PASSWORD:-}"
if [ -z "$BASE_URL" ] || [ -z "$PASS" ]; then
echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD" >&2
exit 1
fi
CURL_OPTS=(-s -S -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}")
offices_json=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/offices" 2>/dev/null)
offices_norm=$(echo "$offices_json" | jq -c 'if type == "array" then . else (.pageItems // []) end' 2>/dev/null || echo "[]")
existing_id=$(echo "$offices_norm" | jq -r --arg e "$BANK_KANAYA_EXTERNAL_ID" '.[]? | select(.externalId == $e) | .id' 2>/dev/null | head -1)
if [ -n "$existing_id" ] && [ "$existing_id" != "null" ]; then
echo "Bank Kanaya office already exists: officeId=$existing_id (externalId=$BANK_KANAYA_EXTERNAL_ID)" >&2
echo "OFFICE_ID_BANK_KANAYA=$existing_id"
exit 0
fi
payload=$(jq -n \
--arg name "$BANK_KANAYA_OFFICE_NAME" \
--arg openingDate "$OPENING_DATE" \
--arg externalId "$BANK_KANAYA_EXTERNAL_ID" \
--argjson parentId "$PARENT_OFFICE_ID" \
'{ name: $name, parentId: $parentId, openingDate: $openingDate, externalId: $externalId, dateFormat: "yyyy-MM-dd", locale: "en" }')
if [ "$DRY_RUN" = "1" ]; then
echo "DRY_RUN: would POST /offices Bank Kanaya externalId=$BANK_KANAYA_EXTERNAL_ID" >&2
echo "Payload: $payload" >&2
exit 0
fi
res=$(curl "${CURL_OPTS[@]}" -X POST -d "$payload" "${BASE_URL}/offices" 2>/dev/null) || true
if echo "$res" | jq -e '.resourceId // .officeId' >/dev/null 2>&1; then
oid=$(echo "$res" | jq -r '.resourceId // .officeId')
echo "Created Bank Kanaya office: officeId=$oid" >&2
echo "OFFICE_ID_BANK_KANAYA=$oid"
else
echo "Failed to create office: $res" >&2
exit 1
fi

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env bash
# OMNL Fineract — Populate the 15 operating entities as Offices (Organization / Manage Offices).
# Updates office 1 name to entity 1; creates offices 215 as children of office 1 with entity names.
# LEI is not a native Fineract office field; regulator-facing LEI is carried in OMNL_ENTITY_MASTER_DATA.json
# and joined to offices in omnl_transaction_package_snapshot.json (see scripts/omnl/jq/enrich-snapshot-entity-master.jq).
# LEI, EBICS, BIC, etc. may still be entered on the office/entity in the UI using memo or Address2/3-style fields; see OMNL_ENTITY_MASTER_DATA.md (section 2b).
# Usage: run from repo root; sources omnl-fineract/.env or .env.
# ENTITY_DATA=<path> JSON entity data (default: docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json)
# DRY_RUN=1 print only, do not PUT/POST.

View File

@@ -0,0 +1,106 @@
#!/usr/bin/env bash
# OMNL Fineract — Post two journal entries for HYBX-BATCH-001 PvP clearing (Bank Kanaya).
# HO leg: Dr 2410 (Due To Offices) / Cr 2100 (M1) — officeId = HO
# BK leg: Dr 2100 / Cr 1410 (Due From HO) — officeId = Bank Kanaya
#
# Amount: Fineract currency smallest unit (USD cents). Default 1B USD = 100000000000 cents.
#
# Usage:
# DRY_RUN=1 bash scripts/omnl/omnl-pvp-post-clearing-bank-kanaya.sh # print payloads only (default)
# DRY_RUN=0 OFFICE_ID_HO=1 OFFICE_ID_KANAYA=22 bash scripts/omnl/omnl-pvp-post-clearing-bank-kanaya.sh
#
# Prerequisites: GL 1410, 2100, 2410 exist. Run resolve_ids.sh or let script resolve via GET /glaccounts.
# See: docs/04-configuration/mifos-omnl-central-bank/PvP_MULTILATERAL_NET_SETTLEMENT_BANK_KANAYA.md
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
DRY_RUN="${DRY_RUN:-1}"
TRANSACTION_DATE="${TRANSACTION_DATE:-$(date +%Y-%m-%d)}"
OFFICE_ID_HO="${OFFICE_ID_HO:-1}"
OFFICE_ID_KANAYA="${OFFICE_ID_KANAYA:-22}"
# 1,000,000,000.00 USD in cents
AMOUNT_MINOR="${AMOUNT_MINOR_UNITS:-100000000000}"
REF="${REFERENCE_COMMENT:-HYBX-BATCH-001-CLEARING}"
if [ -f "${REPO_ROOT}/omnl-fineract/.env" ]; then
set +u
source "${REPO_ROOT}/omnl-fineract/.env" 2>/dev/null || true
set -u
elif [ -f "${REPO_ROOT}/.env" ]; then
set +u
source "${REPO_ROOT}/.env" 2>/dev/null || true
set -u
fi
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
USER="${OMNL_FINERACT_USER:-app.omnl}"
PASS="${OMNL_FINERACT_PASSWORD:-}"
if [ -z "$BASE_URL" ] || [ -z "$PASS" ]; then
echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD" >&2
exit 1
fi
CURL_OPTS=(-s -S -w "\n%{http_code}" -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}")
GL_RAW=$(curl -s -S -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}" "${BASE_URL}/glaccounts")
GL_JSON=$(echo "$GL_RAW" | jq -c 'if type == "array" then . else (.pageItems // []) end' 2>/dev/null || echo "[]")
get_gl_id() {
local code="$1"
echo "$GL_JSON" | jq -r --arg c "$code" '.[]? | select(.glCode == $c) | .id // empty' 2>/dev/null | head -n1
}
ID_1410="$(get_gl_id "1410")"
ID_2100="$(get_gl_id "2100")"
ID_2410="$(get_gl_id "2410")"
if [ -z "$ID_1410" ] || [ -z "$ID_2100" ] || [ -z "$ID_2410" ]; then
if [ "$DRY_RUN" = "1" ]; then
echo "WARN: Could not resolve all GL ids (1410=$ID_1410 2100=$ID_2100 2410=$ID_2410); dry-run uses placeholders." >&2
ID_1410="${ID_1410:-141}"
ID_2100="${ID_2100:-210}"
ID_2410="${ID_2410:-241}"
else
echo "ERROR: Missing GL accounts 1410/2100/2410. Create per OMNL_GL_ACCOUNTS_REQUIRED.md" >&2
exit 1
fi
fi
post_je() {
local office_id="$1"
local debit_id="$2"
local credit_id="$3"
local memo="$4"
local body
body=$(jq -n \
--argjson officeId "$office_id" \
--arg transactionDate "$TRANSACTION_DATE" \
--arg comments "$memo$REF" \
--argjson debitId "$debit_id" \
--argjson creditId "$credit_id" \
--argjson amount "$AMOUNT_MINOR" \
'{ officeId: $officeId, transactionDate: $transactionDate, dateFormat: "yyyy-MM-dd", locale: "en", currencyCode: "USD", comments: $comments, debits: [ { glAccountId: $debitId, amount: $amount } ], credits: [ { glAccountId: $creditId, amount: $amount } ] }')
if [ "$DRY_RUN" = "1" ]; then
echo "DRY_RUN JE: office=$office_id Dr=$debit_id Cr=$credit_id amount_minor=$AMOUNT_MINOR" >&2
echo "$body" | jq .
return 0
fi
local out code resp
out=$(curl "${CURL_OPTS[@]}" -X POST -d "$body" "${BASE_URL}/journalentries" 2>/dev/null)
code=$(echo "$out" | tail -n1)
resp=$(echo "$out" | sed '$d')
if [ "$code" = "200" ] || [ "${code:0:1}" = "2" ]; then
echo "OK $memo HTTP $code" >&2
echo "$resp" | jq . 2>/dev/null || echo "$resp"
else
echo "FAIL $memo HTTP $code: $resp" >&2
return 1
fi
}
echo "HYBX-BATCH-001 PvP clearing | HO office=$OFFICE_ID_HO Kanaya office=$OFFICE_ID_KANAYA | amount_minor=$AMOUNT_MINOR | DRY_RUN=$DRY_RUN" >&2
post_je "$OFFICE_ID_HO" "$ID_2410" "$ID_2100" "PvP HO Dr2410 Cr2100"
post_je "$OFFICE_ID_KANAYA" "$ID_2100" "$ID_1410" "PvP Kanaya Dr2100 Cr1410"
echo "Done." >&2

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# OMNL — Build omnl_transaction_package_snapshot.json for Volume A Section 2 (GET offices + glaccounts).
# Enriches each office with registry LEI / entity name from OMNL_ENTITY_MASTER_DATA.json (offices model;
# Fineract does not store LEI on the office resource).
# Usage: OUT_DIR=. bash scripts/omnl/omnl-transaction-package-snapshot.sh
# Writes: $OUT_DIR/omnl_transaction_package_snapshot.json (default REPO_ROOT)
# ENTITY_DATA=path/to/OMNL_ENTITY_MASTER_DATA.json (optional; default under docs/.../mifos-omnl-central-bank/)
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
OUT_DIR="${OUT_DIR:-$REPO_ROOT}"
OUT_FILE="${OUT_FILE:-$OUT_DIR/omnl_transaction_package_snapshot.json}"
ENTITY_DATA="${ENTITY_DATA:-${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"
if [ -f "${REPO_ROOT}/omnl-fineract/.env" ]; then set +u; source "${REPO_ROOT}/omnl-fineract/.env" 2>/dev/null || true; set -u
elif [ -f "${REPO_ROOT}/.env" ]; then set +u; source "${REPO_ROOT}/.env" 2>/dev/null || true; set -u
fi
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
USER="${OMNL_FINERACT_USER:-app.omnl}"
PASS="${OMNL_FINERACT_PASSWORD:-}"
if [ -z "$BASE_URL" ] || [ -z "$PASS" ]; then
echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD for live snapshot." >&2
exit 1
fi
command -v curl >/dev/null && command -v jq >/dev/null || { echo "Need curl and jq" >&2; exit 1; }
AUTH="${USER}:${PASS}"
CURL_OPTS=(-s -S -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "$AUTH")
api_get() { curl "${CURL_OPTS[@]}" "${BASE_URL}/${1}"; }
OFFICES=$(api_get "offices")
GL=$(api_get "glaccounts")
OFFICES_N=$(echo "$OFFICES" | jq -c 'if type == "array" then . elif .pageItems != null then .pageItems else [] end')
GL_N=$(echo "$GL" | jq -c 'if type == "array" then . elif .pageItems != null then .pageItems else [] end')
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
TMP_OUT="${OUT_FILE}.tmp.$$"
jq -n \
--argjson offices "$OFFICES_N" \
--argjson glaccounts "$GL_N" \
--arg gen "$NOW" \
--arg base "$BASE_URL" \
'{
snapshotMeta: {
documentId: "OMNL-TRANSACTION-PACKAGE-SNAPSHOT",
omnlLegalName: "ORGANISATION MONDIALE DU NUMERIQUE L.P.B.C.",
omnlLei: "98450070C57395F6B906",
omnlLeiReferenceUrl: "https://lei.info/98450070C57395F6B906",
omnlDirectorsAndOfficersDoc: "Appendix/OMNL_BANKING_DIRECTORS_AND_LEI.md",
generatedAtUtc: $gen,
settlementRef: "HYBX-BATCH-001",
valueDate: "2026-03-17",
beneficiary: "Bank Kanaya (Indonesia)",
beneficiaryOfficeId: 22,
beneficiaryExternalId: "BANK-KANAYA-ID",
amountUsd: "1000000000.00",
currency: "USD",
source: "live-api",
apiBaseUrl: $base
},
offices: $offices,
glAccounts: $glaccounts
}' > "$TMP_OUT"
if [ -f "$ENTITY_DATA" ] && [ -f "$ENRICH_JQ" ]; then
jq --argjson master "$(jq -c . "$ENTITY_DATA")" -f "$ENRICH_JQ" "$TMP_OUT" > "$OUT_FILE"
rm -f "$TMP_OUT"
else
mv "$TMP_OUT" "$OUT_FILE"
fi
echo "Wrote $OUT_FILE" >&2

View File

@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Patch INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json with SHA-256 of counsel memo and audit PDFs
# (after they are placed in SUBREG or any local path). Then rebuild: scripts/omnl/build-transaction-package-zip.sh
#
# Usage:
# COUNSEL_PDF=/path/to/counsel-memo.pdf AUDIT_PDF=/path/to/audit-report.pdf \
# bash scripts/omnl/patch-attestation-subreg-pdf-hashes.sh
#
# Optional:
# ATTESTATION_JSON=docs/04-configuration/mifos-omnl-central-bank/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json
# NOW_UTC=$(date -u +%Y-%m-%dT%H:%M:%SZ) — defaults to date -u
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
ATTESTATION_JSON="${ATTESTATION_JSON:-${REPO_ROOT}/docs/04-configuration/mifos-omnl-central-bank/INSTITUTIONAL_PACKAGE_SCORE_ATTESTATION_4_995.json}"
: "${COUNSEL_PDF:?Set COUNSEL_PDF to counsel memo PDF path}"
: "${AUDIT_PDF:?Set AUDIT_PDF to independent audit report PDF path}"
[ -f "$COUNSEL_PDF" ] || { echo "Not a file: $COUNSEL_PDF" >&2; exit 1; }
[ -f "$AUDIT_PDF" ] || { echo "Not a file: $AUDIT_PDF" >&2; exit 1; }
[ -f "$ATTESTATION_JSON" ] || { echo "Not a file: $ATTESTATION_JSON" >&2; exit 1; }
command -v jq >/dev/null || { echo "jq required" >&2; exit 1; }
C_HASH=$(sha256sum "$COUNSEL_PDF" | awk '{print $1}')
A_HASH=$(sha256sum "$AUDIT_PDF" | awk '{print $1}')
NOW_UTC="${NOW_UTC:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}"
TMP=$(mktemp)
jq --arg c "$C_HASH" --arg a "$A_HASH" --arg t "$NOW_UTC" \
'.legalFinality.counselMemoPdfSha256 = $c
| .legalFinality.counselMemoDateUtc = $t
| .legalFinality.counselMemoBindingNote = ("SHA-256 of SUBREG counsel memo PDF: " + $c)
| .independentAudit.reportPdfSha256 = $a
| .independentAudit.reportDateUtc = $t
| .independentAudit.reportBindingNote = ("SHA-256 of SUBREG independent audit report PDF: " + $a)
' "$ATTESTATION_JSON" > "$TMP"
mv "$TMP" "$ATTESTATION_JSON"
echo "Updated $ATTESTATION_JSON" >&2
echo " counselMemoPdfSha256=$C_HASH" >&2
echo " reportPdfSha256=$A_HASH" >&2
echo "Rebuild: bash scripts/omnl/build-transaction-package-zip.sh" >&2

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Fast CI smoke: small ledger (10×100M USD), no Section 2 snapshot, build zip, verify + structural 4.995 check.
# Usage: from repo root. No Fineract required. Unset TSA_URL for deterministic CI unless you intend to hit a TSA.
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
cd "$REPO_ROOT"
unset TSA_URL 2>/dev/null || true
export ALLOW_MISSING_OMNL_SNAPSHOT=1
export HYBX_LEDGER_FILE="${HYBX_LEDGER_FILE:-${REPO_ROOT}/scripts/omnl/fixtures/hybx_batch_001_ledger_ci.csv}"
export EVIDENCE_GENERATED_AT_UTC="${EVIDENCE_GENERATED_AT_UTC:-2026-03-24T12:00:00Z}"
OUT_ZIP="${OUT_ZIP:-/tmp/tp-ci-$$.zip}"
export OUT_ZIP
UDIR=$(mktemp -d /tmp/tp-ci-unzip-XXXXXX)
cleanup() { rm -rf "$UDIR"; rm -f "$OUT_ZIP"; }
trap cleanup EXIT
bash scripts/omnl/build-transaction-package-zip.sh
unzip -q "$OUT_ZIP" -d "$UDIR"
bash scripts/omnl/check-transaction-package-4995-readiness.sh "$UDIR"
echo "CI smoke OK: built zip, commitment + structural 4.995 checks passed." >&2

View File

@@ -37,4 +37,29 @@ else
echo "SKIP: shellcheck not installed" >&2
fi
if command -v python3 >/dev/null 2>&1; then
python3 -m py_compile \
scripts/omnl/generate-transaction-package-evidence.py \
scripts/omnl/verify-transaction-package-commitment.py 2>/dev/null \
&& echo "PASS: py_compile transaction-package scripts" >&2 \
|| { echo "FAIL: py_compile transaction-package scripts" >&2; fail=1; }
else
echo "SKIP: python3 not installed" >&2
fi
for sh in \
scripts/omnl/build-transaction-package-zip.sh \
scripts/omnl/patch-attestation-subreg-pdf-hashes.sh \
scripts/omnl/apply-qes-tsa-to-staging.sh \
scripts/omnl/check-transaction-package-4995-readiness.sh \
scripts/omnl/omnl-transaction-package-snapshot.sh \
scripts/omnl/omnl-pvp-post-clearing-bank-kanaya.sh \
scripts/omnl/omnl-office-create-bank-kanaya.sh \
scripts/omnl/run-transaction-package-ci-smoke.sh
do
if [ -f "$sh" ]; then
bash -n "$sh" 2>/dev/null && echo "PASS: bash -n $sh" >&2 || { echo "FAIL: bash -n $sh" >&2; fail=1; }
fi
done
exit $fail

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Recompute content commitment vs 00_Cover/HASH_NOTARIZATION_ANCHOR.txt (matches build-transaction-package-zip.sh)."""
from __future__ import annotations
import hashlib
import os
import re
import sys
EXCLUDED_EXACT = frozenset(
{
"./00_Cover/HASH_NOTARIZATION_ANCHOR.txt",
"./00_Cover/audit_and_hashes.txt",
"./00_Cover/audit_manifest.json",
}
)
EXCLUDED_BASENAMES = frozenset(
{
"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",
}
)
def posix_rel(package_root: str, full_path: str) -> str:
rel = os.path.relpath(full_path, package_root).replace(os.sep, "/")
return rel if rel.startswith("./") else "./" + rel
def excluded(rel_posix: str) -> bool:
if rel_posix in EXCLUDED_EXACT:
return True
return os.path.basename(rel_posix) in EXCLUDED_BASENAMES
def recompute(package_root: str) -> str:
lines: list[str] = []
for dirpath, dirnames, filenames in os.walk(package_root):
dirnames.sort()
filenames.sort()
for fn in filenames:
if fn == ".DS_Store":
continue
full = os.path.join(dirpath, fn)
if not os.path.isfile(full):
continue
rel = posix_rel(package_root, full)
if excluded(rel):
continue
h = hashlib.sha256()
with open(full, "rb") as f:
for chunk in iter(lambda: f.read(1 << 20), b""):
h.update(chunk)
lines.append(f"{h.hexdigest().lower()}\t{rel}")
lines.sort(key=lambda s: s.encode("utf-8"))
return hashlib.sha256(("\n".join(lines) + "\n").encode("utf-8")).hexdigest().lower()
def main() -> int:
if len(sys.argv) != 2:
print("Usage: verify-transaction-package-commitment.py <unzipped-root>", file=sys.stderr)
return 2
root = os.path.abspath(sys.argv[1])
anchor = os.path.join(root, "00_Cover", "HASH_NOTARIZATION_ANCHOR.txt")
if not os.path.isfile(anchor):
print(f"ERROR: missing {anchor}", file=sys.stderr)
return 1
text = open(anchor, encoding="utf-8").read()
m = re.search(r"CONTENT COMMITMENT \(SHA-256, hex\):\s*([0-9a-fA-F]{64})", text)
if not m:
print("ERROR: bad anchor", file=sys.stderr)
return 1
exp = m.group(1).lower()
got = recompute(root)
if exp != got:
print(f"MISMATCH anchor={exp}\n actual={got}", file=sys.stderr)
return 1
print(f"OK: {got}")
return 0
if __name__ == "__main__":
sys.exit(main())

Binary file not shown.