feat: add universal resource activation policy profile flow
This commit is contained in:
@@ -21,5 +21,9 @@ jobs:
|
||||
REMOTE="${GITEA_WORKFLOW_REMOTE:-gitea}"
|
||||
fi
|
||||
git fetch --depth=1 "$REMOTE" main master
|
||||
# Optional: set org/repo variable URA_STRICT_CLOSURE=1 to fail PRs while pilot placeholders
|
||||
# remain in manifest (see scripts/ura/validate-manifest-closure.mjs). Not enabled by default.
|
||||
- name: run-all-validation (no LAN, no genesis)
|
||||
env:
|
||||
URA_STRICT_CLOSURE: ${{ vars.URA_STRICT_CLOSURE }}
|
||||
run: bash scripts/verify/run-all-validation.sh --skip-genesis
|
||||
|
||||
@@ -21,5 +21,9 @@ jobs:
|
||||
REMOTE="${GITEA_WORKFLOW_REMOTE:-gitea}"
|
||||
fi
|
||||
git fetch --depth=1 "$REMOTE" main master
|
||||
# Optional: set org/repo variable URA_STRICT_CLOSURE=1 to fail PRs while pilot placeholders
|
||||
# remain in manifest (see scripts/ura/validate-manifest-closure.mjs). Not enabled by default.
|
||||
- name: run-all-validation (no LAN, no genesis)
|
||||
env:
|
||||
URA_STRICT_CLOSURE: ${{ vars.URA_STRICT_CLOSURE }}
|
||||
run: bash scripts/verify/run-all-validation.sh --skip-genesis
|
||||
|
||||
44
config/jurisdictions/catalog.v1.json
Normal file
44
config/jurisdictions/catalog.v1.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"updatedAt": "2026-04-25T18:00:00Z",
|
||||
"description": "Canonical jurisdiction catalog for multi-institution onboarding. Add rows as jurisdictions are formally in-scope. Legal review required before marking status production_ready.",
|
||||
"jurisdictions": [
|
||||
{
|
||||
"id": "ID",
|
||||
"label": "Indonesia",
|
||||
"governingLawNote": "Indonesian law; BI and sector regulators — detail in compliance matrix, not legal advice.",
|
||||
"regulatorsNote": "Bank Indonesia (BI); OJK where applicable — confirm with counsel.",
|
||||
"activitiesInScope": ["payments_omnl", "server_funds_treasury", "rtgs_sidecars", "chain138_settlement_evidence"],
|
||||
"activitiesExcluded": ["generic_securities_issuance_unless_scoped"],
|
||||
"complianceMatrixPath": "docs/04-configuration/compliance-matrices/ID-INDONESIA/banking_v1.md",
|
||||
"status": "pilot_ready",
|
||||
"policyProfileIdsReferenced": [
|
||||
"institutional_custody_skr_v1",
|
||||
"server_funds_treasury_v1",
|
||||
"infra_capacity_ops_v1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "GENERIC-COMMON-LAW-STUB",
|
||||
"label": "Generic common-law banking stub (template)",
|
||||
"governingLawNote": "Illustrative only — replace with real jurisdiction before production.",
|
||||
"regulatorsNote": "Placeholder — no regulator list.",
|
||||
"activitiesInScope": ["template_process_only"],
|
||||
"activitiesExcluded": ["all_production_until_replaced"],
|
||||
"complianceMatrixPath": "docs/04-configuration/compliance-matrices/GENERIC-COMMON-LAW-STUB/banking_v1.md",
|
||||
"status": "template_only",
|
||||
"policyProfileIdsReferenced": []
|
||||
},
|
||||
{
|
||||
"id": "US-DELAWARE-CORP-STUB",
|
||||
"label": "US Delaware corporate stub (draft second jurisdiction)",
|
||||
"governingLawNote": "Illustrative corporate/treasury stub — not legal advice; replace with real federal/state matrix.",
|
||||
"regulatorsNote": "Placeholder.",
|
||||
"activitiesInScope": ["draft_matrix_training_only"],
|
||||
"activitiesExcluded": ["all_production_until_replaced"],
|
||||
"complianceMatrixPath": "docs/04-configuration/compliance-matrices/US-DELAWARE-CORP-STUB/banking_v1.md",
|
||||
"status": "draft",
|
||||
"policyProfileIdsReferenced": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://d-bis.org/schemas/universal-resource-activation.policy-profile-registry.v1.json",
|
||||
"title": "PolicyProfileRegistry",
|
||||
"type": "object",
|
||||
"required": ["schemaVersion", "profiles"],
|
||||
"properties": {
|
||||
"schemaVersion": { "type": "string", "minLength": 1 },
|
||||
"updatedAt": { "type": "string" },
|
||||
"description": { "type": "string" },
|
||||
"profiles": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"policyProfileId",
|
||||
"version",
|
||||
"jurisdictions",
|
||||
"participantClasses",
|
||||
"resourceFamilies",
|
||||
"minimumGruGovernanceLevel"
|
||||
],
|
||||
"properties": {
|
||||
"policyProfileId": { "type": "string", "minLength": 1 },
|
||||
"version": { "type": "string", "minLength": 1 },
|
||||
"effectiveFrom": { "type": "string" },
|
||||
"effectiveTo": { "type": "string" },
|
||||
"supersedes": { "type": "string" },
|
||||
"jurisdictions": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"participantClasses": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"resourceFamilies": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"tokenizationModesAllowed": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"ledgerModel": { "type": "string" },
|
||||
"standards": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"minimumGruGovernanceLevel": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 5
|
||||
},
|
||||
"complianceMatrixPaths": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"notes": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# URA manifest — automation design
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** **Implemented in-repo:** fragment merge + strict closure gate + public Phoenix read for `policy-profiles.json` + ledger/settlement fragment CLIs + [`URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md`](../../docs/04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md). Full OMNL ETL and GRU M00 diamond remain **operator/service** work; standalone `PolicyProfileRegistry` ships under `smom-dbis-138/contracts/universal-resource/`.
|
||||
|
||||
## Implemented
|
||||
|
||||
| Piece | Location |
|
||||
|-------|----------|
|
||||
| Merge fragments → validated manifest | `scripts/ura/merge-manifest-fragments.mjs` · `pnpm ura:merge-manifest` |
|
||||
| Shared schema validation | `scripts/ura/lib/validate-ura-manifest.mjs` (used by `pnpm ura:validate` and merge) |
|
||||
| Production placeholder gate | `scripts/ura/validate-manifest-closure.mjs` · `pnpm ura:validate-closure` (warn) / `pnpm ura:validate-closure:strict` (fail) · optional `URA_STRICT_CLOSURE=1` in `validate-config-files.sh` |
|
||||
| Fragment drop zone | `manifest-fragments/README.md` |
|
||||
| Public API: policy profiles | `GET /api/v1/universal-resource-activation/policy-profiles` on phoenix-deploy-api |
|
||||
|
||||
## Goals (remaining / service-bound)
|
||||
|
||||
- Generate fragments from **approved** ops forms, ledger exports, chain receipts (outside this repo or future ETL).
|
||||
- Fail CI on **production** branches when closure rules violate (use `URA_STRICT_CLOSURE=1` on that pipeline).
|
||||
|
||||
## Pipeline (merge)
|
||||
|
||||
1. **Inputs:** JSON fragments under `manifest-fragments/*.json` (or another `--fragments-dir`).
|
||||
2. **Merge:** Deterministic sort; `policyProfileRefs` union; resources/evidence by id with shallow merge.
|
||||
3. **Validate:** Full JSON Schema + cross-checks (`validateUraManifestData`).
|
||||
4. **Optional:** `--out path` to write; then review and replace `manifest.json` if intended.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Automatic legal classification of assets (human sign-off on matrices + profiles).
|
||||
- Writing to chain or OMNL from this repo without separate deployment controls.
|
||||
|
||||
## Related
|
||||
|
||||
- [`UNIVERSAL_RESOURCE_WIRING.md`](../../docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md)
|
||||
- [`scripts/validate/validate-ura-policy-profiles.mjs`](../../scripts/validate/validate-ura-policy-profiles.mjs)
|
||||
@@ -0,0 +1,23 @@
|
||||
# Policy profiles registry — doc control
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Human-readable **change control** for rows in [`policy-profiles.json`](policy-profiles.json). Legal/risk owns interpretation; engineering owns schema conformance (`pnpm ura:validate-profiles`).
|
||||
|
||||
| `policyProfileId` | Version in registry | `effectiveFrom` | Legal / risk sign-off | Notes |
|
||||
|-------------------|---------------------|-----------------|----------------------|-------|
|
||||
| `institutional_custody_skr_v1` | 1 | 2026-04-25 | Pending — replace when signed | ID matrix: SKR / custody path |
|
||||
| `server_funds_treasury_v1` | 1 | 2026-04-25 | Pending — replace when signed | ID matrix: server funds / OMNL |
|
||||
| `infra_capacity_ops_v1` | 1 | 2026-04-25 | Pending — replace when signed | LAN internal capacity |
|
||||
|
||||
## Procedure
|
||||
|
||||
1. Add or bump `version` and `effectiveFrom` in `policy-profiles.json`; update this table with sign-off reference (ticket, memo id, or “N/A — internal only”).
|
||||
2. Ensure [`manifest.json`](manifest.json) `policyProfileRefs` lists every profile used by a resource at the correct version.
|
||||
3. Run `pnpm ura:validate && pnpm ura:validate-profiles`.
|
||||
|
||||
## Related
|
||||
|
||||
- [`UNIVERSAL_RESOURCE_POLICY_PROFILES.md`](../../docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_POLICY_PROFILES.md)
|
||||
- [`DBIS_RAIL_JURISDICTION_TRACEABILITY.md`](../../docs/dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md)
|
||||
- **Public read:** `GET /api/v1/universal-resource-activation/policy-profiles` on phoenix-deploy-api (same auth rules as manifest; override via `UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH`).
|
||||
- **On-chain anchor (optional):** `smom-dbis-138/contracts/universal-resource/PolicyProfileRegistry.sol` — publish `contentHash` from `pnpm ura:profile-hash <policyProfileId>`; see [`GRU_REGISTRY_WIRING_CHECKLIST.md`](../../docs/runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md) §6.
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"journalEntryId": "OMNL-JE-2026-00042",
|
||||
"batchRef": "FINERACT-BATCH-88",
|
||||
"postedAt": "2026-04-25T12:00:00Z",
|
||||
"currency": "USD",
|
||||
"amountMinor": "1000000",
|
||||
"notes": "Illustrative export shape — replace with real OMNL/Fineract field names from your deployment."
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"description": "Example mapping from Fineract/OMNL export fields to URA evidence package columns. Copy to omnl-ledger-mapping.v1.json when live.",
|
||||
"evidencePackages": [
|
||||
{
|
||||
"evidencePackageId": "ura:pilot:evidence-register-bootstrap",
|
||||
"accountingRefField": "journalEntryId"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://d-bis.org/schemas/omnl-ledger-mapping.v1.json",
|
||||
"title": "OMNLLedgerMapping",
|
||||
"type": "object",
|
||||
"required": ["schemaVersion", "evidencePackages"],
|
||||
"properties": {
|
||||
"schemaVersion": { "type": "string", "const": "1.0.0" },
|
||||
"description": { "type": "string" },
|
||||
"resourceUpdates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["resourceId", "quantityField"],
|
||||
"properties": {
|
||||
"resourceId": { "type": "string", "minLength": 1 },
|
||||
"quantityField": { "type": "string", "description": "Dot path in ledger snapshot for quantity string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"evidencePackages": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["evidencePackageId"],
|
||||
"properties": {
|
||||
"evidencePackageId": { "type": "string", "minLength": 1 },
|
||||
"accountingRefField": {
|
||||
"type": "string",
|
||||
"description": "Dot path into ledger snapshot JSON for accountingRef string (e.g. journalEntryId or omnl.batchRef)"
|
||||
},
|
||||
"quantityField": {
|
||||
"type": "string",
|
||||
"description": "Optional dot path for resource quantity string"
|
||||
},
|
||||
"resourceIdForQuantity": {
|
||||
"type": "string",
|
||||
"description": "If quantityField set, which resource row to patch"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# URA manifest fragments (optional)
|
||||
|
||||
**Purpose:** Drop partial JSON files here to **merge** onto the canonical [`../manifest.json`](../manifest.json) without hand-editing the full file. Used for ops overlays, environment-specific rows, or generated snippets.
|
||||
|
||||
## Fragment shape
|
||||
|
||||
Each `*.json` file (sorted by filename; skip `_prefix.json`) may contain any of:
|
||||
|
||||
| Key | Effect |
|
||||
|-----|--------|
|
||||
| `policyProfileRefs` | Union with manifest (same `id` + `version` deduped). |
|
||||
| `resources` | Add or **shallow-merge** replace by `resourceId`. |
|
||||
| `evidencePackages` | Add or **shallow-merge** replace by `evidencePackageId`. |
|
||||
|
||||
Top-level manifest fields (`schemaVersion`, `description`, …) come **only** from the `--base` file (default: `manifest.json`).
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
pnpm ura:merge-manifest
|
||||
# Validate merge and print counts (dry-run; does not write)
|
||||
|
||||
node scripts/ura/merge-manifest-fragments.mjs --out /tmp/merged.json
|
||||
# Write merged JSON; inspect and copy into manifest.json if correct
|
||||
```
|
||||
|
||||
After any manifest edit: `pnpm ura:validate && pnpm ura:validate-profiles`.
|
||||
|
||||
## Production gate
|
||||
|
||||
When pilots are closed, enforce no placeholders:
|
||||
|
||||
```bash
|
||||
pnpm ura:validate-closure:strict
|
||||
# Or: URA_STRICT_CLOSURE=1 bash scripts/validation/validate-config-files.sh
|
||||
```
|
||||
|
||||
See [`MANIFEST_AUTOMATION_DESIGN.md`](../MANIFEST_AUTOMATION_DESIGN.md) and [`URA_PILOT_CLOSURE_RUNBOOK.md`](../../../docs/04-configuration/universal-resource-activation/URA_PILOT_CLOSURE_RUNBOOK.md).
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"updatedAt": "2026-04-24T00:00:00Z",
|
||||
"description": "Canonical in-repo store for universal resource activation (SKR, server funds, infra). Replace example-* rows in production; keep valid JSON and run scripts/validate/validate-universal-resource-activation.mjs in CI.",
|
||||
"updatedAt": "2026-04-25T12:00:00Z",
|
||||
"description": "Canonical in-repo store for universal resource activation (SKR, server funds, infra). Pilot-scoped resourceIds; jurisdiction ID for financial pilots per JURISDICTION_CATALOG and ID-INDONESIA matrix. Replace ura:participant:pilot-*-assign and evidence TBDs per URA_PILOT_CLOSURE_RUNBOOK.md. Run pnpm ura:validate && pnpm ura:validate-profiles in CI.",
|
||||
"policyProfileRefs": [
|
||||
{ "id": "institutional_custody_skr_v1", "version": "1" },
|
||||
{ "id": "server_funds_treasury_v1", "version": "1" },
|
||||
@@ -9,14 +9,14 @@
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"resourceId": "ura:example:skr-pilot-placeholder",
|
||||
"resourceId": "ura:pilot-1:skr-custody-record",
|
||||
"schemaVersion": 1,
|
||||
"displayName": "Example SKR / custody position (pilot template)",
|
||||
"description": "Replace with a real safekeeping or strategic evidence-backed record. Not production.",
|
||||
"displayName": "Pilot 1 — SKR / custody record",
|
||||
"description": "PILOT-1 (Indonesia-scope): bind participant registry id, evidenceRefs, and custody evidence per URA_PILOT_CLOSURE_RUNBOOK.md and ID-INDONESIA compliance matrix.",
|
||||
"family": "SKR_SAFEKEEPING",
|
||||
"subType": "CUSTODY_STATEMENT",
|
||||
"ownerParticipantId": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"jurisdiction": "TBD",
|
||||
"ownerParticipantId": "ura:participant:pilot-1-assign",
|
||||
"jurisdiction": "ID",
|
||||
"policyProfileId": "institutional_custody_skr_v1",
|
||||
"tokenizationMode": "NONE",
|
||||
"quantity": "0",
|
||||
@@ -25,17 +25,17 @@
|
||||
"encumbranceState": "unencumbered",
|
||||
"lifecycleState": "draft",
|
||||
"deployabilityState": "informational_only",
|
||||
"evidenceRefs": []
|
||||
"evidenceRefs": ["ura:evidence:pending-pilot-1-custody-package"]
|
||||
},
|
||||
{
|
||||
"resourceId": "ura:example:server-funds-pilot",
|
||||
"resourceId": "ura:pilot-2:server-funds-treasury-pool",
|
||||
"schemaVersion": 1,
|
||||
"displayName": "Example server funds pool (pilot template)",
|
||||
"description": "Logical funding resource; bind to OMNL/Fineract and server-funds-sidecar when SoR is frozen. Not a wallet balance.",
|
||||
"displayName": "Pilot 2 — Server funds treasury pool",
|
||||
"description": "PILOT-2 (Indonesia-scope): OMNL + server-funds-sidecar SoR; replace accountingRef in evidence when ledger posts per runbook.",
|
||||
"family": "SERVER_FUNDS",
|
||||
"subType": "TREASURY_POOL",
|
||||
"ownerParticipantId": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"jurisdiction": "TBD",
|
||||
"ownerParticipantId": "ura:participant:pilot-2-assign",
|
||||
"jurisdiction": "ID",
|
||||
"policyProfileId": "server_funds_treasury_v1",
|
||||
"tokenizationMode": "NONE",
|
||||
"quantity": "0",
|
||||
@@ -44,16 +44,16 @@
|
||||
"encumbranceState": "unencumbered",
|
||||
"lifecycleState": "draft",
|
||||
"deployabilityState": "funding_eligible",
|
||||
"evidenceRefs": []
|
||||
"evidenceRefs": ["ura:evidence:pending-pilot-2-ledger-link"]
|
||||
},
|
||||
{
|
||||
"resourceId": "ura:example:infra-r630-01-capacity",
|
||||
"resourceId": "ura:pilot-3:infra-r630-01-api-small",
|
||||
"schemaVersion": 1,
|
||||
"displayName": "Example R630-01 capacity slice (pilot template)",
|
||||
"description": "Operational capacity record; not a tradable security. See reports/storage and ALL_VMIDS_ENDPOINTS for live inventory.",
|
||||
"displayName": "Pilot 3 — Infra capacity (R630-01, api_small)",
|
||||
"description": "PILOT-3: LAN ops capacity; link deploymentRef in evidence after non-prod deploy per runbook.",
|
||||
"family": "INFRA_CAPACITY",
|
||||
"subType": "BUNDLE",
|
||||
"ownerParticipantId": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"ownerParticipantId": "ura:participant:pilot-3-assign",
|
||||
"jurisdiction": "LAN",
|
||||
"policyProfileId": "infra_capacity_ops_v1",
|
||||
"tokenizationMode": "NONE",
|
||||
@@ -62,22 +62,26 @@
|
||||
"encumbranceState": "unencumbered",
|
||||
"lifecycleState": "active",
|
||||
"deployabilityState": "infra_allocatable",
|
||||
"evidenceRefs": []
|
||||
"evidenceRefs": ["ura:evidence:pending-pilot-3-capacity-verify"]
|
||||
}
|
||||
],
|
||||
"evidencePackages": [
|
||||
{
|
||||
"evidencePackageId": "ura:example:evidence-ura-bootstrap",
|
||||
"evidencePackageId": "ura:pilot:evidence-register-bootstrap",
|
||||
"resourceIds": [
|
||||
"ura:example:skr-pilot-placeholder",
|
||||
"ura:example:server-funds-pilot",
|
||||
"ura:example:infra-r630-01-capacity"
|
||||
"ura:pilot-1:skr-custody-record",
|
||||
"ura:pilot-2:server-funds-treasury-pool",
|
||||
"ura:pilot-3:infra-r630-01-api-small"
|
||||
],
|
||||
"actionType": "REGISTER",
|
||||
"initiator": "repo_bootstrap",
|
||||
"timestamp": "2026-04-24T00:00:00Z",
|
||||
"reconciliationStatus": "matched",
|
||||
"explanation": "Bootstrap example package linking the three template resources; replace with real packages per UNIVERSAL_RESOURCE_PILOT_PLAN.md"
|
||||
"initiator": "pilot_bootstrap",
|
||||
"timestamp": "2026-04-25T12:00:00Z",
|
||||
"reconciliationStatus": "open",
|
||||
"custodyOrSourceEvidence": "PILOT-1: TBD — custodian statement or attestation hash per UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md; remove when real ref linked.",
|
||||
"accountingRef": "PILOT-2: TBD — OMNL/Fineract journal or batch id when server-funds path posts (see URA_PILOT_CLOSURE_RUNBOOK.md).",
|
||||
"settlementOrChainRef": "PILOT-2/3: TBD — MintAuth messageId / tx hash / rail ref per DBIS_RAIL_TECHNICAL_SPEC_V1.md when settlement leg exists.",
|
||||
"deploymentRef": "PILOT-3: TBD — VMID, FQDN, health URL after deploy per UNIVERSAL_RESOURCE_PILOT_PLAN.md.",
|
||||
"explanation": "REGISTER package binding three pilots. Set reconciliationStatus to matched only after mandatory joins per UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md and jurisdiction matrix rows."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
53
config/universal-resource-activation/policy-profiles.json
Normal file
53
config/universal-resource-activation/policy-profiles.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"updatedAt": "2026-04-25T00:00:00Z",
|
||||
"description": "Machine-readable URA policy profile registry. Manifest policyProfileRefs must reference ids listed here. See UNIVERSAL_RESOURCE_POLICY_PROFILES.md and compliance-matrices/.",
|
||||
"profiles": [
|
||||
{
|
||||
"policyProfileId": "institutional_custody_skr_v1",
|
||||
"version": "1",
|
||||
"effectiveFrom": "2026-04-25",
|
||||
"jurisdictions": ["*", "ID"],
|
||||
"participantClasses": ["institutional", "sovereign"],
|
||||
"resourceFamilies": ["SKR_SAFEKEEPING", "STRATEGIC_RECORD"],
|
||||
"tokenizationModesAllowed": ["NONE", "CLAIM", "ENTITLEMENT"],
|
||||
"ledgerModel": "off_chain_omnl",
|
||||
"standards": ["ISO20022_LOGGING"],
|
||||
"minimumGruGovernanceLevel": 2,
|
||||
"complianceMatrixPaths": [
|
||||
"docs/04-configuration/compliance-matrices/ID-INDONESIA/banking_v1.md"
|
||||
],
|
||||
"notes": "SKR / custody evidence-backed; conservative transfer defaults per policy doc."
|
||||
},
|
||||
{
|
||||
"policyProfileId": "server_funds_treasury_v1",
|
||||
"version": "1",
|
||||
"effectiveFrom": "2026-04-25",
|
||||
"jurisdictions": ["*", "ID"],
|
||||
"participantClasses": ["institutional", "sovereign"],
|
||||
"resourceFamilies": ["SERVER_FUNDS"],
|
||||
"tokenizationModesAllowed": ["NONE"],
|
||||
"ledgerModel": "hybrid",
|
||||
"standards": ["ISO20022_LOGGING", "TRAVEL_RULE"],
|
||||
"minimumGruGovernanceLevel": 3,
|
||||
"complianceMatrixPaths": [
|
||||
"docs/04-configuration/compliance-matrices/ID-INDONESIA/banking_v1.md"
|
||||
],
|
||||
"notes": "Good-funds, GL mapping, holds/releases; Rail settlement when on-chain leg used."
|
||||
},
|
||||
{
|
||||
"policyProfileId": "infra_capacity_ops_v1",
|
||||
"version": "1",
|
||||
"effectiveFrom": "2026-04-25",
|
||||
"jurisdictions": ["*", "LAN"],
|
||||
"participantClasses": ["institutional", "internal_ops"],
|
||||
"resourceFamilies": ["INFRA_CAPACITY"],
|
||||
"tokenizationModesAllowed": ["NONE", "ENTITLEMENT"],
|
||||
"ledgerModel": "off_chain_omnl",
|
||||
"standards": ["IPSAS"],
|
||||
"minimumGruGovernanceLevel": 1,
|
||||
"complianceMatrixPaths": [],
|
||||
"notes": "Internal capacity; not a traded security by default."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -65,6 +65,7 @@
|
||||
|
||||
## Related artifacts
|
||||
|
||||
- [DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md) — workstreams and exit criteria aligned to this matrix (multi-jurisdiction master plan execution).
|
||||
- [dbis_chain_138_technical_master_plan.md](../../dbis_chain_138_technical_master_plan.md)
|
||||
- [docs/00-meta/TODO_TASK_LIST_MASTER.md](../00-meta/TODO_TASK_LIST_MASTER.md)
|
||||
- [docs/03-deployment/DBIS_PHASES_1_TO_3_PRODUCTION_GATE.md](DBIS_PHASES_1_TO_3_PRODUCTION_GATE.md)
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
# DBIS RTGS — master plan implementation tracker
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Executable tracker mapping the **multi-jurisdiction institutional onboarding master plan** to [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md) rows and slice-1 scope ([SLICE1_SCOPE_FREEZE.md](../04-configuration/jurisdictions/SLICE1_SCOPE_FREEZE.md)). **Status here is documentation of intent;** the canonical component status remains the E2E matrix until rows are updated there.
|
||||
|
||||
## How to use
|
||||
|
||||
1. Pick a **workstream** below.
|
||||
2. Execute engineering / ops tasks until **exit criteria** match the matrix row’s **Production gate** column.
|
||||
3. Update **DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md** `Current state` to `Complete` (or `Retired` with rationale).
|
||||
4. Link evidence to URA packages per [ID-INDONESIA/banking_v1.md](../04-configuration/compliance-matrices/ID-INDONESIA/banking_v1.md) where applicable.
|
||||
|
||||
---
|
||||
|
||||
## Workstream W1 — Canonical OMNL / Fineract rail
|
||||
|
||||
| Matrix rows (indicative) | OMNL / Fineract API rail; Mifos X frontend / tenant |
|
||||
|--------------------------|-----------------------------------------------------|
|
||||
| **Exit criteria** | Tenant and operator rail **frozen**; reproducible posting, office/GL mapping, reconciliation package path. |
|
||||
| **Owner** | OMNL / banking ops |
|
||||
| **URA link** | `SERVER_FUNDS` resources get real `accountingRef`; [URA_PILOT_CLOSURE_RUNBOOK.md](../04-configuration/universal-resource-activation/URA_PILOT_CLOSURE_RUNBOOK.md) pilot 2. |
|
||||
|
||||
## Workstream W2 — `server-funds-sidecar`
|
||||
|
||||
| Matrix rows | `server-funds-sidecar` (VMID 5803) |
|
||||
|-------------|-------------------------------------|
|
||||
| **Exit criteria** | Treasury SoR boundaries frozen; **draw / hold / release** validated with auth; Phoenix `SERVER_FUNDS_SIDECAR_URL` set in prod. |
|
||||
| **Owner** | HYBX integration lead |
|
||||
| **URA link** | Pilot 2; [UNIVERSAL_RESOURCE_WIRING.md](../04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) probe returns 200. |
|
||||
|
||||
## Workstream W3 — `off-ledger-2-on-ledger-sidecar`
|
||||
|
||||
| Matrix rows | Off-ledger → Chain 138 settlement |
|
||||
|-------------|-----------------------------------|
|
||||
| **Exit criteria** | Canonical event → settlement **end-to-end** with durable evidence; finality handling closed. |
|
||||
| **Owner** | HYBX + Chain 138 settlement lead |
|
||||
| **URA link** | `settlementOrChainRef` in evidence packages. |
|
||||
|
||||
## Workstream W4 — ISO 20022 + institutional 4.995 package
|
||||
|
||||
| Matrix rows | ISO evidence and vault path; Institutional 4.995 package path |
|
||||
|-------------|---------------------------------------------------------------|
|
||||
| **Exit criteria** | `--strict` or institution-agreed readiness; reproducible archive/hash path. |
|
||||
| **Owner** | Regulatory / compliance + eng |
|
||||
| **Compliance link** | [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](../04-configuration/mifos-omnl-central-bank/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md) |
|
||||
|
||||
## Workstream W5 — Indonesia BNI domestic path
|
||||
|
||||
| Matrix rows | Indonesia / BNI domestic banking path |
|
||||
|-------------|----------------------------------------|
|
||||
| **Exit criteria** | Live endpoint/auth/message contract **or** explicit deferral documented in matrix + jurisdiction matrix. |
|
||||
| **Owner** | Indonesia banking integration lead |
|
||||
| **Compliance link** | [DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md](DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md) |
|
||||
|
||||
## Workstream W6 — Global correspondent path
|
||||
|
||||
| Matrix rows | Global correspondent / liquidity bank path |
|
||||
|-------------|---------------------------------------------|
|
||||
| **Exit criteria** | Same as matrix production gate; cross-border flow validated **or** out of slice 1. |
|
||||
| **Owner** | Cross-border banking integration lead |
|
||||
|
||||
## Workstream W7 — Identity stack (Fabric / Indy / Aries)
|
||||
|
||||
| Matrix rows | Fabric, Indy, Aries, AnonCreds, etc. |
|
||||
|-------------|--------------------------------------|
|
||||
| **Exit criteria** | **Scope decision** in/out slice 1; if out, matrix shows Planned/Retired without production claims. |
|
||||
| **Owner** | Identity architecture lead |
|
||||
|
||||
## Workstream W8 — Depository / custody / securities
|
||||
|
||||
| Matrix rows | Depository, global custodian, securities-sidecar, custody flow |
|
||||
|-------------|----------------------------------------------------------------|
|
||||
| **Exit criteria** | Canonical lifecycle documented + one path validated **or** deferred with rationale. |
|
||||
| **Owner** | Custody / securities architecture leads |
|
||||
| **URA link** | Pilot 1 SKR; policy profile `institutional_custody_skr_v1`. |
|
||||
|
||||
## Workstream W9 — RTGS production gate
|
||||
|
||||
| Matrix rows | RTGS production gate row |
|
||||
|-------------|--------------------------|
|
||||
| **Exit criteria** | All **mandatory** rows for **chosen architecture** = `Complete`. |
|
||||
| **Owner** | DBIS program owner |
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md)
|
||||
- [DBIS_HYBX_SIDECAR_BOUNDARY_MATRIX.md](DBIS_HYBX_SIDECAR_BOUNDARY_MATRIX.md)
|
||||
- [INSTITUTION_ONBOARDING_CHARTER.md](../04-configuration/compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md)
|
||||
63
docs/03-deployment/URA_MANIFEST_WRITER_OPS.md
Normal file
63
docs/03-deployment/URA_MANIFEST_WRITER_OPS.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# URA manifest writer — operations
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Runbook for **ledger- and chain-driven** manifest updates: secrets, ETL, publish path, reconciliation, optional features, legal record, DR.
|
||||
|
||||
## 1. Components
|
||||
|
||||
| Piece | Role |
|
||||
|-------|------|
|
||||
| OMNL / Fineract | System of record for `accountingRef` (journal / batch ids). |
|
||||
| Server-funds sidecar | Operational draws/holds; must correlate to ledger lines. |
|
||||
| [`build-ledger-fragment.mjs`](../../scripts/ura/manifest-writer/build-ledger-fragment.mjs) | Maps export JSON → manifest fragment. |
|
||||
| [`merge-manifest-fragments.mjs`](../../scripts/ura/merge-manifest-fragments.mjs) | Merges fragments; validates. |
|
||||
| Phoenix | Serves canonical [`manifest.json`](../../config/universal-resource-activation/manifest.json) read-only. |
|
||||
|
||||
## 2. Fineract / OMNL field inventory
|
||||
|
||||
**Operator task:** Document the **exact** REST or batch export fields your deployment uses (tenant, office, product). Map them in [`omnl-ledger-mapping.v1.example.json`](../../config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json) (copy to `omnl-ledger-mapping.v1.json`).
|
||||
|
||||
Minimum: one stable string for `accountingRef` (journal id or composite `officeId:transactionId`).
|
||||
|
||||
## 3. Secrets and IAM
|
||||
|
||||
- Store Fineract credentials in vault / `.env` on the writer host (never in git).
|
||||
- Use read-only Fineract user where possible.
|
||||
- Rotate keys on the same cadence as OMNL operator policy.
|
||||
|
||||
## 4. Publish path (choose one)
|
||||
|
||||
| Mode | Pattern |
|
||||
|------|---------|
|
||||
| **Git PR** | Writer opens PR updating `manifest.json` or a fragment; CI runs `pnpm ura:validate`. |
|
||||
| **Secured sync** | Writer writes to `PHOENIX_REPO_ROOT` on deploy host; reload Phoenix. |
|
||||
| **Authenticated API** | Future: POST internal-only (not the public GET routes). |
|
||||
|
||||
## 5. Reconciliation
|
||||
|
||||
- Nightly (or per batch): compare latest Fineract journal id set to manifest `accountingRef`.
|
||||
- On mismatch: page on-call; do **not** auto-overwrite without human ack for production.
|
||||
|
||||
## 6. Optional features
|
||||
|
||||
- **Real-time:** Webhook from Fineract vs **batch** cron — feature-flag in writer.
|
||||
- **Multi-pool:** Multiple rows in `resourceUpdates` / evidence mapping file.
|
||||
- **DLQ:** Failed merges land in a queue path for replay.
|
||||
- **Audit log:** Append-only log of fragment bytes + git SHA + operator id.
|
||||
|
||||
## 7. Legal sign-off record
|
||||
|
||||
When automation goes live, archive:
|
||||
|
||||
- Compliance memo id or ticket referencing matrix rows satisfied by automated fields.
|
||||
- Version of [`policy-profiles.json`](../../config/universal-resource-activation/policy-profiles.json) and [`ID-INDONESIA/banking_v1.md`](../04-configuration/compliance-matrices/ID-INDONESIA/banking_v1.md) (or relevant matrix).
|
||||
|
||||
## 8. DR and rollback
|
||||
|
||||
- **Backup:** Git history of `manifest.json` + weekly object-store copy if using direct sync.
|
||||
- **Rollback:** Revert commit or restore file; re-run `pnpm ura:validate && pnpm ura:validate-profiles`.
|
||||
- **Incident:** Disable writer cron/systemd; serve last known-good manifest from Phoenix override path.
|
||||
|
||||
## Related
|
||||
|
||||
- [`URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md`](../04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
@@ -93,9 +93,17 @@ This directory contains setup and configuration guides.
|
||||
- **[DBIS Rail Control Mapping v1](../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md)** ⭐⭐ - Control IDs mapped to checklist, Spec, Rulebook, and Threat Model for audit and SOC 2 / ISO 27001 alignment.
|
||||
- **[DBIS Rail and Project Completion Master v1](../dbis-rail/DBIS_RAIL_AND_PROJECT_COMPLETION_MASTER_V1.md)** ⭐⭐ - Project and deployment status; full task list (required and optional) for DBIS Rail and project completion.
|
||||
|
||||
**Multi-jurisdiction institutional onboarding (master plan artifacts):**
|
||||
- **[compliance-matrices/README.md](compliance-matrices/README.md)** — Per-jurisdiction matrices, template, Indonesia + generic stub.
|
||||
- **[compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md](compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md)** — RACI and definition of Complete.
|
||||
- **[compliance-matrices/INSTITUTION_ONBOARDING_PLAYBOOK.md](compliance-matrices/INSTITUTION_ONBOARDING_PLAYBOOK.md)** — Repeatable onboarding steps.
|
||||
- **[jurisdictions/JURISDICTION_CATALOG.md](jurisdictions/JURISDICTION_CATALOG.md)**, **[jurisdictions/SLICE1_SCOPE_FREEZE.md](jurisdictions/SLICE1_SCOPE_FREEZE.md)** — Catalog + slice-1 scope; machine: [`config/jurisdictions/catalog.v1.json`](../../config/jurisdictions/catalog.v1.json).
|
||||
- **[../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md)** — Rail controls ↔ jurisdiction matrices ↔ profiles.
|
||||
|
||||
**Universal resource activation (SKR, server funds, infra capacity):**
|
||||
- **[universal-resource-activation/README.md](universal-resource-activation/README.md)** ⭐⭐ — Ontology, policy profiles, lanes, pilots, JSON Schemas, in-repo [`manifest.json`](../../config/universal-resource-activation/manifest.json), `node scripts/validate/validate-universal-resource-activation.mjs`, Phoenix `GET /api/v1/universal-resource-activation/manifest`.
|
||||
- **[universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md](universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md)** — Operator wiring: env (`UNIVERSAL_RESOURCE_MANIFEST_PATH`), CI, API resolution order.
|
||||
- **[universal-resource-activation/README.md](universal-resource-activation/README.md)** ⭐⭐ — Ontology, policy profiles, lanes, pilots, [`manifest.json`](../../config/universal-resource-activation/manifest.json), [`policy-profiles.json`](../../config/universal-resource-activation/policy-profiles.json); `pnpm ura:validate`, `pnpm ura:validate-profiles`, `pnpm ura:keccak`, `pnpm ura:smoke` (`--http` + `PHOENIX_BASE_URL`). Phoenix: `GET /api/v1/universal-resource-activation/manifest`, `GET /api/v1/universal-resource-activation/server-funds-sidecar-probe`. [MASTER_INDEX.md](../MASTER_INDEX.md) §04-configuration.
|
||||
- **[universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md](universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md)** — Operator wiring: `UNIVERSAL_RESOURCE_MANIFEST_PATH`, `SERVER_FUNDS_SIDECAR_URL`, CI, testing checklist.
|
||||
- **RTGS execution tracker:** [../03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](../03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md).
|
||||
- **[Implementation coordination (transcript 540ae663)](../dbis-rail/IMPLEMENTATION_COORDINATION_WITH_TRANSCRIPT_540AE663.md)** ⭐⭐ - Coordinate implementations with PMM/DEX, tokens, GRU, cW*, deployments; maps Completion Master tasks to done/partial/open.
|
||||
- **[DBIS Rail Ledger Attestation Add-On v1.5](../dbis-rail/DBIS_RAIL_LEDGER_ATTESTATION_ADDON_V1_5.md)** ⭐⭐ - LPA state machine, reversal matrix, signer effectiveFromBlock/revokedAtBlock mandatory.
|
||||
- **[DBIS Rail Conversion Router Spec v1.5](../dbis-rail/DBIS_RAIL_CONVERSION_ROUTER_SPEC_V1_5.md)** ⭐⭐ - SwapAuth, best execution/MEV, quote provenance, venue allowlist, sanctions/AML for swaps.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# GENERIC-COMMON-LAW-STUB — template only
|
||||
|
||||
**Status:** template_only — **not** for production institutions.
|
||||
|
||||
Use this folder to practice matrix structure before copying [_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md](../_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md) to a real jurisdiction code.
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| [banking_v1.md](banking_v1.md) | Illustrative obligation rows |
|
||||
@@ -0,0 +1,36 @@
|
||||
# Compliance matrix — GENERIC-COMMON-LAW-STUB — banking_v1 (ILLUSTRATIVE ONLY)
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** **template_only** — do **not** use for production institutions. Copy [../_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md](../_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md) and replace with a real jurisdiction.
|
||||
|
||||
**Purpose:** Train the onboarding process: obligation rows, control linkage, evidence columns.
|
||||
|
||||
---
|
||||
|
||||
## 1. Law / regulation inventory (fictional placeholders)
|
||||
|
||||
| Ref id | Short title | Scope | Notes |
|
||||
|--------|-------------|-------|-------|
|
||||
| STUB-BANK-001 | Illustrative banking supervision act | banking | Fictional — replace with real citations. |
|
||||
| STUB-AML-001 | Illustrative AML law | AML | Fictional. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Requirement and control mapping (illustrative rows)
|
||||
|
||||
| Matrix row id | Obligation summary | Participant classes | URA family | Enforcement | Control ids | Evidence expectation |
|
||||
|---------------|-------------------|---------------------|------------|-------------|-------------|----------------------|
|
||||
| STUB-001 | Illustrative: know your customer for institutional treasury | institutional | `SERVER_FUNDS` | off-chain | C7, STUB-KYB-001 | Onboarding file + audit log reference |
|
||||
| STUB-002 | Illustrative: sanctions screening before funding draw | institutional | `SERVER_FUNDS` | hybrid | C7, STUB-SAN-001 | Screening vendor ref + timestamp in evidence package |
|
||||
| STUB-003 | Illustrative: safekeeping evidence for custody record | institutional | `SKR_SAFEKEEPING` | off-chain | C9, STUB-CUST-001 | Custodian statement hash in `custodyOrSourceEvidence` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Residual risk
|
||||
|
||||
All rows are **non-binding** examples. Production matrices require **counsel-approved** law inventory and signed control mapping.
|
||||
|
||||
## Related
|
||||
|
||||
- [JURISDICTION_CATALOG.md](../../jurisdictions/JURISDICTION_CATALOG.md)
|
||||
- [ID-INDONESIA/banking_v1.md](../ID-INDONESIA/banking_v1.md) — real pilot jurisdiction example in this repo.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Indonesia (ID) — compliance matrices
|
||||
|
||||
**Status:** pilot_ready (counsel must validate legal inventory in `banking_v1.md`)
|
||||
|
||||
| File | Regime / topic |
|
||||
|------|----------------|
|
||||
| [banking_v1.md](banking_v1.md) | Banking, OMNL, sidecars, Rail, ISO / 4.995, BNI path |
|
||||
|
||||
**Catalog:** [`config/jurisdictions/catalog.v1.json`](../../../config/jurisdictions/catalog.v1.json) — `id: "ID"`
|
||||
|
||||
**Related:** [INSTITUTION_ONBOARDING_PLAYBOOK.md](../INSTITUTION_ONBOARDING_PLAYBOOK.md), [DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md](../../../03-deployment/DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md)
|
||||
@@ -0,0 +1,59 @@
|
||||
# Compliance matrix — Indonesia (ID) — banking_v1
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Jurisdiction id:** ID
|
||||
**Status:** **pilot_ready** — consolidate scattered repo guidance; **counsel must validate** all legal citations and obligation text before production claims.
|
||||
|
||||
**Machine-readable catalog:** [`config/jurisdictions/catalog.v1.json`](../../../config/jurisdictions/catalog.v1.json)
|
||||
|
||||
---
|
||||
|
||||
## 1. Law / regulation inventory (outline — verify with counsel)
|
||||
|
||||
| Ref id | Short title | Scope | Repo anchor (non-legal) |
|
||||
|--------|-------------|-------|-------------------------|
|
||||
| ID-BI-PAYMENT | BI payment system / RTGS-related rules (confirm scope) | banking, payments | [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](../../../03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md), Indonesia rows |
|
||||
| ID-OJK-SEC | OJK capital markets rules (if securities path in scope) | securities | Depository / securities sidecar rows in same matrix |
|
||||
| ID-AML-CTF | AML / CTF obligations (confirm statutes) | AML | [DBIS_RAIL_RULEBOOK_V1.md](../../../dbis-rail/DBIS_RAIL_RULEBOOK_V1.md) good-funds / compliance alignment |
|
||||
| ID-DP | Data protection (confirm PDP / sector rules) | data | Evidence vault / ISO path |
|
||||
|
||||
*Replace summaries with counsel-approved citations and effective dates.*
|
||||
|
||||
---
|
||||
|
||||
## 2. Requirement and control mapping (starter rows)
|
||||
|
||||
| Matrix row id | Obligation summary | Participant classes | URA family | Enforcement | Control ids | Evidence expectation |
|
||||
|---------------|-------------------|---------------------|------------|-------------|-------------|----------------------|
|
||||
| ID-OMNL-001 | Institutional ledger / OMNL posting path for RTGS slice | institutional | `SERVER_FUNDS` | off-chain | C8, C9, C17 | Deterministic `accountingRef`; JE / package per [OMNL_JOURNAL_LEDGER_MATRIX.md](../../mifos-omnl-central-bank/OMNL_JOURNAL_LEDGER_MATRIX.md) |
|
||||
| ID-SIDECAR-001 | Server-funds treasury orchestration aligned with good-funds policy | institutional | `SERVER_FUNDS` | hybrid | C17, C12 | Sidecar draw/hold/release + evidence package; Phoenix probe [UNIVERSAL_RESOURCE_WIRING.md](../../universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) |
|
||||
| ID-RAIL-001 | On-chain settlement evidence (MintAuth / messageId) when rail used | institutional | `SERVER_FUNDS`, `FIAT_DIGITAL` (if applicable) | on-chain | C1–C6, C10 | `settlementOrChainRef` per [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md) |
|
||||
| ID-ISO-001 | ISO 20022 / institutional evidence packaging | institutional | all lanes | off-chain | C9 | [INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md](../../mifos-omnl-central-bank/INDONESIA_PACKAGE_4_995_EVIDENCE_STANDARD.md), matrix ISO row |
|
||||
| ID-BNI-001 | Domestic bank partner connectivity (when BNI path in scope) | institutional | payments | off-chain | — | [DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md](../../../03-deployment/DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md); freeze endpoint/auth |
|
||||
| ID-SKR-001 | Custody / safekeeping evidence for SKR pilot | institutional | `SKR_SAFEKEEPING` | off-chain | C9 | `custodyOrSourceEvidence`, `evidenceRefs` on resource |
|
||||
|
||||
---
|
||||
|
||||
## 3. Deep links (implementation)
|
||||
|
||||
- HYBX operator: [HYBX_BATCH_001_OPERATOR_CHECKLIST.md](../../mifos-omnl-central-bank/HYBX_BATCH_001_OPERATOR_CHECKLIST.md)
|
||||
- RTGS checklist: [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](../../../03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md)
|
||||
- Rail controls: [DBIS_RAIL_CONTROL_MAPPING_V1.md](../../../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md)
|
||||
- Traceability: [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md)
|
||||
|
||||
---
|
||||
|
||||
## 4. Residual risk / exceptions
|
||||
|
||||
| Topic | Decision | Owner |
|
||||
|-------|----------|-------|
|
||||
| BNI live contract | Planned until live endpoint/auth evidenced — see RTGS matrix | Indonesia banking integration lead |
|
||||
| Securities / CSD | Planned unless explicitly in slice 1 | Securities architecture lead |
|
||||
|
||||
---
|
||||
|
||||
## Document control
|
||||
|
||||
| Version | Date | Change |
|
||||
|---------|------|--------|
|
||||
| 0.1 | 2026-04-25 | Initial Indonesia banking_v1 matrix from master plan |
|
||||
@@ -0,0 +1,47 @@
|
||||
# Institution onboarding charter — multi-jurisdiction compliance program
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Governance for onboarding **institutions** under explicit **jurisdictions**, aligned with the multi-jurisdiction master plan (policy profiles, per-jurisdiction compliance matrices, RTGS/Rail evidence, URA).
|
||||
|
||||
**Do not treat this document as legal advice.** Counsel owns interpretation of statutes and regulations; this charter defines **roles, artifacts, and “complete”** for program execution.
|
||||
|
||||
---
|
||||
|
||||
## Definitions
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **Institution** | Licensed or contracted participant (bank, CSD, treasury entity, program operator) using DBIS RTGS / Rail / URA artifacts. |
|
||||
| **Jurisdiction** | Legal regime under which the institution operates for a given activity (may be multiple per institution). |
|
||||
| **Policy profile** | Versioned ruleset referenced by `policyProfileId` on URA resources — see [UNIVERSAL_RESOURCE_POLICY_PROFILES.md](../universal-resource-activation/UNIVERSAL_RESOURCE_POLICY_PROFILES.md) and [policy-profiles.json](../../../config/universal-resource-activation/policy-profiles.json). |
|
||||
| **Compliance matrix** | Per-jurisdiction mapping: law / obligation → control id → evidence / system behavior — see [compliance-matrices/README.md](README.md). |
|
||||
| **Complete (institution)** | All **in-scope** matrix rows for that institution’s jurisdictions are **implemented or explicitly waived** with sign-off; URA pilots or production resources carry **non-placeholder** evidence where policy requires; RTGS matrix rows for the **chosen architecture** are `Complete` or **excluded with rationale** (see [DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](../../03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md)). |
|
||||
|
||||
---
|
||||
|
||||
## RACI (summary)
|
||||
|
||||
| Activity | Responsible | Accountable | Consulted | Informed |
|
||||
|----------|-------------|-------------|-----------|----------|
|
||||
| Jurisdiction / law inventory | Compliance | Legal | Local counsel | Program, Eng |
|
||||
| Compliance matrix draft | Compliance | Legal | Risk, Product | Eng |
|
||||
| Policy profile version & registry | Product / Arch | Legal + Risk | Compliance | Eng |
|
||||
| URA manifest & evidence packages | Ops | Compliance | Audit | Eng |
|
||||
| RTGS / sidecar / OMNL integration | Eng | Program | Banking ops | Compliance |
|
||||
| Rail / on-chain controls | Eng | Risk | Audit | Legal |
|
||||
| Production gate sign-off | Program | Executive sponsor | Legal, Risk | All |
|
||||
|
||||
---
|
||||
|
||||
## Exit criteria (program slice 1)
|
||||
|
||||
1. [JURISDICTION_CATALOG.md](../jurisdictions/JURISDICTION_CATALOG.md) and [config/jurisdictions/catalog.v1.json](../../../config/jurisdictions/catalog.v1.json) list **in-scope** jurisdictions and activities.
|
||||
2. [SLICE1_SCOPE_FREEZE.md](../jurisdictions/SLICE1_SCOPE_FREEZE.md) is agreed and references [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](../../03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md) immediate priorities.
|
||||
3. At least one **full** jurisdiction matrix exists (see [ID-INDONESIA/banking_v1.md](ID-INDONESIA/banking_v1.md)) plus [GENERIC-COMMON-LAW-STUB](GENERIC-COMMON-LAW-STUB/banking_v1.md) for process training and a **draft second jurisdiction** ([US-DELAWARE-CORP-STUB](US-DELAWARE-CORP-STUB/README.md)) for multi-matrix workflow rehearsal.
|
||||
4. Policy profiles registered and validated in CI (`pnpm ura:validate-profiles`).
|
||||
5. Traceability doc links controls to matrices — [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md).
|
||||
|
||||
## Related
|
||||
|
||||
- [INSTITUTION_ONBOARDING_PLAYBOOK.md](INSTITUTION_ONBOARDING_PLAYBOOK.md) — step-by-step onboarding.
|
||||
- [UNIVERSAL_RESOURCE_WIRING.md](../universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) — URA ops.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Institution onboarding playbook — jurisdictions and compliance matrices
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Repeatable steps to onboard an **institution** under one or more **jurisdictions**, producing signed compliance matrices, registered policy profiles, and URA/RTGS artifacts.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [INSTITUTION_ONBOARDING_CHARTER.md](INSTITUTION_ONBOARDING_CHARTER.md) acknowledged (RACI).
|
||||
- [JURISDICTION_CATALOG.md](../jurisdictions/JURISDICTION_CATALOG.md) and [`config/jurisdictions/catalog.v1.json`](../../config/jurisdictions/catalog.v1.json) updated for new jurisdictions.
|
||||
- [SLICE1_SCOPE_FREEZE.md](../jurisdictions/SLICE1_SCOPE_FREEZE.md) or successor scope doc current.
|
||||
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Legal and compliance intake
|
||||
|
||||
1. Institution name, regulator(s), licensed activities.
|
||||
2. Build **law / regulation inventory** (counsel-owned citations).
|
||||
3. Confirm **in-scope** vs **excluded** activities; align with RTGS matrix architecture choice.
|
||||
|
||||
### 2. Compliance matrix
|
||||
|
||||
1. Copy [_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md](_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md) to `docs/04-configuration/compliance-matrices/<JURISDICTION_CODE>/`.
|
||||
2. Fill obligation rows; map **Control ids** to [DBIS_RAIL_CONTROL_MAPPING_V1.md](../../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md) and add `<JUR>-*` ids as needed.
|
||||
3. Link evidence expectations to ISO / 4.995 / institution package standards where applicable.
|
||||
4. Update [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md) when new obligation ↔ control links are stable.
|
||||
|
||||
### 3. Policy profiles
|
||||
|
||||
1. Add or extend entries in [`config/universal-resource-activation/policy-profiles.json`](../../config/universal-resource-activation/policy-profiles.json) (`jurisdictions[]`, `minimumGruGovernanceLevel`, `complianceMatrixPaths`).
|
||||
2. Run `pnpm ura:validate-profiles`.
|
||||
3. Update [UNIVERSAL_RESOURCE_POLICY_PROFILES.md](../universal-resource-activation/UNIVERSAL_RESOURCE_POLICY_PROFILES.md) if new profile semantics are introduced.
|
||||
|
||||
### 4. URA resources
|
||||
|
||||
1. Add or update rows in [`config/universal-resource-activation/manifest.json`](../../config/universal-resource-activation/manifest.json) with correct `policyProfileId`, `jurisdiction`, `ownerParticipantId`.
|
||||
2. Follow [URA_PILOT_CLOSURE_RUNBOOK.md](../universal-resource-activation/URA_PILOT_CLOSURE_RUNBOOK.md) for evidence packages.
|
||||
3. Run `pnpm ura:validate`.
|
||||
|
||||
### 5. RTGS / technical closure
|
||||
|
||||
1. Use [DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](../../03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md) to assign workstreams.
|
||||
2. Update [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](../../03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md) when components reach **Complete**.
|
||||
|
||||
### 6. Automation (recommended)
|
||||
|
||||
| Action | Command / artifact |
|
||||
|--------|-------------------|
|
||||
| URA manifest + schemas | `pnpm ura:validate` |
|
||||
| Policy registry + manifest refs | `pnpm ura:validate-profiles` |
|
||||
| Merge manifest fragments (optional) | `pnpm ura:merge-manifest` · [`manifest-fragments/README.md`](../../../config/universal-resource-activation/manifest-fragments/README.md) |
|
||||
| Production closure gate (no pilot/TBD) | `pnpm ura:validate-closure:strict` · or `URA_STRICT_CLOSURE=1` with `validate-config-files.sh` |
|
||||
| Phoenix HTTP smoke (staging) | `pnpm ura:smoke -- --http` with `PHOENIX_BASE_URL` (manifest + policy-profiles + sidecar-probe) |
|
||||
| On-chain id hashes | `pnpm ura:keccak` |
|
||||
|
||||
**Service-bound next steps:** manifest/ledger writers fed by OMNL/sidecar events — out of repo until those APIs are stable; use merge + manual `manifest.json` until then.
|
||||
|
||||
### 7. Exit
|
||||
|
||||
Institution **Complete** per charter when: matrix rows implemented or waived with sign-off, mandatory RTGS rows green for chosen architecture, URA evidence **matched** where policy requires.
|
||||
|
||||
## Related
|
||||
|
||||
- [compliance-matrices/README.md](README.md)
|
||||
- [UNIVERSAL_RESOURCE_WIRING.md](../universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md)
|
||||
- [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](../universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
24
docs/04-configuration/compliance-matrices/README.md
Normal file
24
docs/04-configuration/compliance-matrices/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Per-jurisdiction compliance matrices
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** One **separate** matrix (or split by regime) per **onboarded jurisdiction**, mapping **local obligations** → **control IDs** (Rail + jurisdiction-specific) → **evidence / system behavior**.
|
||||
|
||||
## Index
|
||||
|
||||
| Jurisdiction code | Folder | Status |
|
||||
|-------------------|--------|--------|
|
||||
| _TEMPLATE | [_TEMPLATE/](_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md) | Use for new jurisdictions |
|
||||
| GENERIC-COMMON-LAW-STUB | [GENERIC-COMMON-LAW-STUB/](GENERIC-COMMON-LAW-STUB/README.md) | Template only |
|
||||
| ID (Indonesia) | [ID-INDONESIA/](ID-INDONESIA/README.md) | Pilot-ready |
|
||||
| US-DELAWARE-CORP-STUB | [US-DELAWARE-CORP-STUB/](US-DELAWARE-CORP-STUB/README.md) | Draft (second jurisdiction exercise) |
|
||||
|
||||
## Governance
|
||||
|
||||
- [INSTITUTION_ONBOARDING_CHARTER.md](INSTITUTION_ONBOARDING_CHARTER.md) — RACI and definition of **Complete**.
|
||||
- [JURISDICTION_CATALOG.md](../jurisdictions/JURISDICTION_CATALOG.md) — catalog index.
|
||||
- [INSTITUTION_ONBOARDING_PLAYBOOK.md](INSTITUTION_ONBOARDING_PLAYBOOK.md) — onboarding steps (Phase 6).
|
||||
|
||||
## Related
|
||||
|
||||
- [DBIS_RAIL_CONTROL_MAPPING_V1.md](../../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md)
|
||||
- [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md)
|
||||
@@ -0,0 +1,9 @@
|
||||
# US-DELAWARE-CORP-STUB — draft (second jurisdiction template)
|
||||
|
||||
**Status:** **draft** — placeholder for a second jurisdiction onboarding exercise. **Not** production-ready; no counsel review recorded.
|
||||
|
||||
Replace this stub with a real US state / federal matrix when an institution requires it, or delete if out of scope.
|
||||
|
||||
| File | Regime / topic |
|
||||
|------|----------------|
|
||||
| [banking_v1.md](banking_v1.md) | Draft starter rows (fictional placeholders) |
|
||||
@@ -0,0 +1,25 @@
|
||||
# Compliance matrix — US-DELAWARE-CORP-STUB — banking_v1 (DRAFT)
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** **draft** — second-jurisdiction process training only. **Do not** use for compliance claims.
|
||||
|
||||
## 1. Law / regulation inventory (placeholders — replace with counsel research)
|
||||
|
||||
| Ref id | Short title | Scope | Notes |
|
||||
|--------|-------------|-------|-------|
|
||||
| US-D-STUB-001 | Illustrative: corporate treasury governance | corporate | Fictional row for template practice. |
|
||||
| US-D-STUB-002 | Illustrative: AML program expectations | AML | Fictional. |
|
||||
|
||||
## 2. Requirement mapping (starter)
|
||||
|
||||
| Matrix row id | Obligation summary | URA family | Control ids | Evidence |
|
||||
|---------------|-------------------|------------|-------------|----------|
|
||||
| US-STUB-001 | Illustrative: treasury policy for server funds | `SERVER_FUNDS` | C8, C17 | OMNL refs + policy attestation |
|
||||
| US-STUB-002 | Illustrative: custody evidence for SKR | `SKR_SAFEKEEPING` | C9 | Custodian hash / WORM id |
|
||||
|
||||
## 3. Next steps
|
||||
|
||||
1. Rename jurisdiction folder to the agreed code (e.g. state + program).
|
||||
2. Replace inventory with **real** citations.
|
||||
3. Register profiles in [`policy-profiles.json`](../../../config/universal-resource-activation/policy-profiles.json) if new `policyProfileId`s are needed.
|
||||
4. Add row to [`config/jurisdictions/catalog.v1.json`](../../../config/jurisdictions/catalog.v1.json) with `status: pilot_ready` when reviewed.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Compliance matrix — `<JURISDICTION_CODE>` — `<REGIME_OR_TOPIC>_v1`
|
||||
|
||||
**Last updated:** YYYY-MM-DD
|
||||
**Jurisdiction id:** `<ISO or program code, e.g. ID, US-NY>`
|
||||
**Owning counsel / compliance:** `<Name or role — not legal advice in this file>`
|
||||
**Effective from / to:** `<dates or “until superseded”>`
|
||||
**Related `policyProfileId`(s):** `<list>`
|
||||
**Related URA families:** `SKR_SAFEKEEPING` | `SERVER_FUNDS` | `INFRA_CAPACITY` | …
|
||||
|
||||
---
|
||||
|
||||
## 1. Law / regulation inventory
|
||||
|
||||
| Ref id | Short title | Scope (banking, securities, AML, DP, FX, digital assets) | Notes |
|
||||
|--------|-------------|---------------------------------------------------------------|-------|
|
||||
| LAW-001 | `<Statute or reg>` | `<scope>` | `<counsel summary>` |
|
||||
|
||||
---
|
||||
|
||||
## 2. Requirement and control mapping
|
||||
|
||||
| Matrix row id | Obligation summary (non-legal) | Participant classes | URA family | Enforcement (on-chain / off-chain / hybrid) | Control ids | Evidence expectation |
|
||||
|---------------|--------------------------------|---------------------|------------|---------------------------------------------|-------------|----------------------|
|
||||
| `<JUR>-001` | `<e.g. KYC for treasury operators>` | `<institutional>` | `SERVER_FUNDS` | off-chain | `C7` [Rail mapping](../../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md), `<JUR>-AML-001` | `<ISO package / audit artifact>` |
|
||||
|
||||
**Control id conventions**
|
||||
|
||||
- **C1–C18:** [DBIS_RAIL_CONTROL_MAPPING_V1.md](../../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md) where applicable.
|
||||
- **`<JUR>-*`** jurisdiction-specific controls not covered by Rail mapping.
|
||||
|
||||
---
|
||||
|
||||
## 3. Residual risk / exceptions
|
||||
|
||||
| Topic | Decision | Owner |
|
||||
|-------|----------|-------|
|
||||
| Manual vs automated control | `<>` | `<>` |
|
||||
|
||||
---
|
||||
|
||||
## 4. Document control
|
||||
|
||||
| Version | Date | Author | Change |
|
||||
|---------|------|--------|--------|
|
||||
| 0.1 | YYYY-MM-DD | `<>` | Draft |
|
||||
22
docs/04-configuration/jurisdictions/JURISDICTION_CATALOG.md
Normal file
22
docs/04-configuration/jurisdictions/JURISDICTION_CATALOG.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Jurisdiction catalog (human index)
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Machine-readable source:** [`config/jurisdictions/catalog.v1.json`](../../config/jurisdictions/catalog.v1.json)
|
||||
|
||||
| ID | Label | Compliance matrix | Status | Notes |
|
||||
|----|-------|-------------------|--------|--------|
|
||||
| ID | Indonesia | [ID-INDONESIA/banking_v1.md](../compliance-matrices/ID-INDONESIA/banking_v1.md) | pilot_ready | Align with BNI / OMNL / 4.995 evidence paths. |
|
||||
| GENERIC-COMMON-LAW-STUB | Template stub | [GENERIC-COMMON-LAW-STUB/README.md](../compliance-matrices/GENERIC-COMMON-LAW-STUB/README.md) | template_only | Train process only; not for production. |
|
||||
| US-DELAWARE-CORP-STUB | US draft stub | [US-DELAWARE-CORP-STUB/README.md](../compliance-matrices/US-DELAWARE-CORP-STUB/README.md) | draft | Second-jurisdiction placeholder; replace or remove. |
|
||||
|
||||
## Adding a jurisdiction
|
||||
|
||||
1. Add an object to `catalog.v1.json` with `id`, `label`, paths, `status`.
|
||||
2. Create `docs/04-configuration/compliance-matrices/<id>/` using [_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md](../compliance-matrices/_TEMPLATE/COMPLIANCE_MATRIX_TEMPLATE.md).
|
||||
3. Register or extend [policy-profiles.json](../../config/universal-resource-activation/policy-profiles.json) entries with `jurisdictions[]`.
|
||||
4. Update [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md) when controls are mapped.
|
||||
|
||||
## Related
|
||||
|
||||
- [INSTITUTION_ONBOARDING_CHARTER.md](../compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md)
|
||||
- [SLICE1_SCOPE_FREEZE.md](SLICE1_SCOPE_FREEZE.md)
|
||||
36
docs/04-configuration/jurisdictions/SLICE1_SCOPE_FREEZE.md
Normal file
36
docs/04-configuration/jurisdictions/SLICE1_SCOPE_FREEZE.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Slice 1 scope freeze (RTGS + URA alignment)
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Operational **scope freeze** for production slice 1, aligned with [DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](../../03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md) **Immediate execution priority** and URA pilots.
|
||||
|
||||
## Frozen priorities (from RTGS matrix)
|
||||
|
||||
1. **Freeze the canonical banking rail** on the proven OMNL / Fineract tenant and authenticated posting path.
|
||||
2. **Freeze participant / treasury / GL model** (and dependent depository, custody, FX, liquidity layers as in-scope for slice 1).
|
||||
3. **Complete the canonical settlement path** from HYBX sidecars into Chain 138 with durable evidence.
|
||||
|
||||
## In-scope for slice 1 (default)
|
||||
|
||||
- OMNL / Fineract operator rail and office–GL mapping (as documented in matrix rows).
|
||||
- HYBX first-slice sidecars: **`mifos-fineract-sidecar`**, **`server-funds-sidecar`**, **`off-ledger-2-on-ledger-sidecar`** — business flows and evidence, not only health.
|
||||
- ISO 20022 / institutional evidence packaging toward **submission-grade** where matrix requires.
|
||||
- Indonesia domestic path **when** institution is Indonesia-facing — see [ID-INDONESIA compliance matrix](../compliance-matrices/ID-INDONESIA/banking_v1.md).
|
||||
- URA [pilot plan](../universal-resource-activation/UNIVERSAL_RESOURCE_PILOT_PLAN.md) closure per [URA_PILOT_CLOSURE_RUNBOOK.md](../universal-resource-activation/URA_PILOT_CLOSURE_RUNBOOK.md).
|
||||
|
||||
## Explicitly out of scope for slice 1 (unless program re-opens)
|
||||
|
||||
- Fabric / Indy / Aries **production** until matrix rows move from Planned/Reserved to Complete with validation.
|
||||
- Mojaloop, card networks, flash-loan XAU, etc., unless a **written scope addendum** promotes them.
|
||||
- **Template-only** jurisdiction [GENERIC-COMMON-LAW-STUB](../compliance-matrices/GENERIC-COMMON-LAW-STUB/banking_v1.md) — never production.
|
||||
|
||||
## Change control
|
||||
|
||||
Any change to this freeze requires: Program owner + Legal/Compliance acknowledgment and update to this file’s **Last updated** and a short **revision note** block (append below).
|
||||
|
||||
---
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change |
|
||||
|------|--------|
|
||||
| 2026-04-25 | Initial slice 1 freeze document created from master plan. |
|
||||
@@ -15,11 +15,17 @@
|
||||
| [UNIVERSAL_RESOURCE_INFRA_CAPACITY_LANE.md](UNIVERSAL_RESOURCE_INFRA_CAPACITY_LANE.md) | Infrastructure capacity lane: inventory, bundles, broker, metering |
|
||||
| [UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md](UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md) | Shared evidence and reconciliation package |
|
||||
| [UNIVERSAL_RESOURCE_PILOT_PLAN.md](UNIVERSAL_RESOURCE_PILOT_PLAN.md) | First three pilots (SKR, server funds, infra) |
|
||||
| [URA_PILOT_CLOSURE_RUNBOOK.md](URA_PILOT_CLOSURE_RUNBOOK.md) | Replace manifest placeholders; close pilots and evidence |
|
||||
| [policy-profiles.json (registry)](../../config/universal-resource-activation/policy-profiles.json) | Machine-readable profiles + GRU governance level |
|
||||
| [POLICY_PROFILES_REGISTRY.md](../../config/universal-resource-activation/POLICY_PROFILES_REGISTRY.md) | Doc control / sign-off table per profile version |
|
||||
| [MANIFEST_AUTOMATION_DESIGN.md](../../config/universal-resource-activation/MANIFEST_AUTOMATION_DESIGN.md) | Future manifest merge/CI design (not implemented) |
|
||||
| [Compliance matrices / onboarding](../compliance-matrices/README.md) | Per-jurisdiction matrices, charter, playbook |
|
||||
| [Jurisdiction catalog](../jurisdictions/JURISDICTION_CATALOG.md) | Catalog index + `config/jurisdictions/catalog.v1.json` |
|
||||
| [JSON Schema v1](../../../config/universal-resource-activation.resource.v1.schema.json) | Machine-readable resource body (`UniversalResource` subset) |
|
||||
| [URAWiring / ops](UNIVERSAL_RESOURCE_WIRING.md) | **Manifest, CI validation, Phoenix `GET` route, env overrides** |
|
||||
| [manifest.json (live store)](../../../config/universal-resource-activation/manifest.json) | In-repo `resources[]` and `evidencePackages[]` |
|
||||
|
||||
**Validate:** `node scripts/validate/validate-universal-resource-activation.mjs` (from repo root) · **smoke (schema ± HTTP):** `bash scripts/verify/smoke-universal-resource-activation.sh` — [wiring §2.1](UNIVERSAL_RESOURCE_WIRING.md#21-testing-checklist)
|
||||
**Validate:** `pnpm ura:validate` · `pnpm ura:validate-profiles` · **merge fragments:** `pnpm ura:merge-manifest` · **ledger mapping:** `pnpm ura:validate-ledger-mapping` · **writers:** `pnpm ura:writer:ledger` / `pnpm ura:writer:settlement` · **profile hash (on-chain anchor):** `pnpm ura:profile-hash` · **closure gate:** `pnpm ura:validate-closure` / `pnpm ura:validate-closure:strict` · **smoke:** `pnpm ura:smoke` (add `--http` for Phoenix: manifest + policy-profiles + sidecar-probe) · **on-chain id hashes:** `pnpm ura:keccak` — [wiring §2.1](UNIVERSAL_RESOURCE_WIRING.md#21-testing-checklist) · **full automation tracker:** [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
|
||||
## Upstream anchors
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# SKR / custody — automation notes for `evidenceRefs`
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Guide for **Pilot 1** automation: populating [`manifest.json`](../../../config/universal-resource-activation/manifest.json) `evidenceRefs` and evidence package `custodyOrSourceEvidence` from custodian or internal systems.
|
||||
|
||||
## 1. Typical sources
|
||||
|
||||
| Source | Pattern |
|
||||
|--------|---------|
|
||||
| **Custodian API** | Poll or webhook for statement id / secure URL; store hash in manifest. |
|
||||
| **Signed PDF / ISO package** | Landing zone (S3, SFTP); writer computes SHA-256; `evidenceRefs` = `sha256:…` or object URL + hash. |
|
||||
| **Internal attestation** | HSM-signed payload; reference id in manifest. |
|
||||
|
||||
## 2. Jurisdiction
|
||||
|
||||
Obligations live in the per-jurisdiction matrix (e.g. [ID-INDONESIA/banking_v1.md](../compliance-matrices/ID-INDONESIA/banking_v1.md)). Automation must not change **meaning** of evidence without counsel review.
|
||||
|
||||
## 3. Implementation sketch
|
||||
|
||||
1. Custody ETL outputs JSON `{ "statementId", "hash", "effectiveDate" }`.
|
||||
2. Extend [`build-ledger-fragment.mjs`](../../../scripts/ura/manifest-writer/build-ledger-fragment.mjs) pattern with a **custody fragment** script (future) or reuse merge fragments manually.
|
||||
3. Run `pnpm ura:validate` and `pnpm ura:validate-closure:strict` before production CI enables strict mode.
|
||||
|
||||
## Related
|
||||
|
||||
- [`URA_PILOT_CLOSURE_RUNBOOK.md`](URA_PILOT_CLOSURE_RUNBOOK.md) §2
|
||||
- [`URA_MANIFEST_WRITER_OPS.md`](../../03-deployment/URA_MANIFEST_WRITER_OPS.md)
|
||||
@@ -1,6 +1,6 @@
|
||||
# Shared Evidence and Reconciliation Package
|
||||
|
||||
**Last updated:** 2026-04-24
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** A single **reproducible evidence package** for every **resource activation** and cross-lane action (SKR, server funds, infra, settlement). Aligns with ISO-20022 and institutional audit patterns referenced in [DBIS Rail technical spec](../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md) and the custody operating model in [DBIS_RTGS_DEPOSITORY_AND_CUSTODY_OPERATING_MODEL.md](../../03-deployment/DBIS_RTGS_DEPOSITORY_AND_CUSTODY_OPERATING_MODEL.md).
|
||||
|
||||
## Design principles
|
||||
@@ -30,6 +30,8 @@
|
||||
| `reconciliationStatus` | `open`, `matched`, `exception` |
|
||||
| `explanation` | Human-readable for auditors |
|
||||
|
||||
Use **`reconciliationStatus = open`** when mandatory joins (e.g. a real `accountingRef` or `settlementOrChainRef` where policy requires them) are not yet present or verified; set **`matched`** only after those joins succeed in the same reconciliation window. Bootstrap packages with TBD text placeholders should stay **`open`**.
|
||||
|
||||
## Minimum object set by lane
|
||||
|
||||
| Lane | Must include |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Universal Resource Ontology
|
||||
|
||||
**Last updated:** 2026-04-24
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Define the canonical **resource** model used across financial and infrastructure lanes. This is the schema contract for registries, APIs, and (when applicable) on-chain mirrors.
|
||||
|
||||
## Design principles
|
||||
@@ -19,6 +19,8 @@
|
||||
| `createdAt` | RFC3339 / epoch | Audit. |
|
||||
| `updatedAt` | RFC3339 / epoch | Audit. |
|
||||
|
||||
**In-repo manifest (human-readable URNs):** The [URA `manifest.json`](../../config/universal-resource-activation/manifest.json) may use stable string IDs such as `ura:pilot-1:…` for reviewability. For optional EVM anchoring, derive **`keccak256(utf8(resourceId))`** (same as `node scripts/ura/keccak-resource-ids.mjs`); the manifest string remains the canonical off-chain id unless you later standardize on bytes32 at rest.
|
||||
|
||||
## Resource families
|
||||
|
||||
`family` discriminates top-level behavior and which lane adapters apply.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# First Three Pilots — Universal Resource Activation
|
||||
|
||||
**Last updated:** 2026-04-24
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Operable, low-risk **pilots** that validate the ontology, policy profiles, each lane, and the shared [evidence package](UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md) before broad rollout.
|
||||
|
||||
**Governance default:** `tokenizationMode = NONE` and conservative `deployabilityState` for all three pilots.
|
||||
|
||||
**In-repo `manifest.json` (bootstrap):** The shared [`config/universal-resource-activation/manifest.json`](../../config/universal-resource-activation/manifest.json) uses **pilot-scoped** `resourceId`s and may keep the pilot evidence package at **`reconciliationStatus: open`** while `accountingRef` / `settlementOrChainRef` (or other mandatory joins) are still TBD. The “Done when” columns below are **end states** for each pilot, not a live mirror of the JSON on every row. Update the manifest to **`matched`** when the corresponding pilot’s reconciliation is closed (see [UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md](UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md)).
|
||||
|
||||
---
|
||||
|
||||
## Pilot 1 — SKR- or statement-backed resource record (custody or strategic with evidence)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Universal Resource Policy Profiles
|
||||
|
||||
**Last updated:** 2026-04-24
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Define **modular policy profiles** that bind legal, regulatory, compliance, accounting, valuation, and transferability rules to resources without hardcoding jurisdiction logic in each adapter.
|
||||
|
||||
## Why profiles
|
||||
@@ -105,6 +105,16 @@ Map to on-chain or off-chain enforcement:
|
||||
3. `effectiveFrom` in production; keep prior versions for historical reconciliation.
|
||||
4. Emit `PolicyProfileUpdated` (off-chain) or on-chain event if a chain registry is used.
|
||||
|
||||
## Machine-readable registry (CI)
|
||||
|
||||
Production-facing profiles SHOULD be listed in [`config/universal-resource-activation/policy-profiles.json`](../../config/universal-resource-activation/policy-profiles.json) (JSON Schema: [`universal-resource-activation.policy-profile-registry.v1.schema.json`](../../config/universal-resource-activation.policy-profile-registry.v1.schema.json)). Each entry includes **`minimumGruGovernanceLevel`** (0–5) per [GRU_M00_DIAMOND_FACET_MAP.md](../GRU_M00_DIAMOND_FACET_MAP.md) §4.
|
||||
|
||||
**Doc control:** [`POLICY_PROFILES_REGISTRY.md`](../../config/universal-resource-activation/POLICY_PROFILES_REGISTRY.md) — sign-off table per profile version.
|
||||
|
||||
**Validate:** `pnpm ura:validate-profiles` — also invoked from [`scripts/validation/validate-config-files.sh`](../../../scripts/validation/validate-config-files.sh).
|
||||
|
||||
**Per-jurisdiction matrices:** [`docs/04-configuration/compliance-matrices/`](../compliance-matrices/README.md).
|
||||
|
||||
## Related
|
||||
|
||||
- [UNIVERSAL_RESOURCE_ONTOLOGY.md](UNIVERSAL_RESOURCE_ONTOLOGY.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Universal Resource Activation — Wiring and Operations
|
||||
|
||||
**Last updated:** 2026-04-24
|
||||
**Last updated:** 2026-04-25
|
||||
|
||||
This document describes how the **in-repo** universal resource system is wired: config store, JSON schemas, validation in CI, and the Phoenix Deploy API.
|
||||
|
||||
@@ -30,34 +30,45 @@ node scripts/validate/validate-universal-resource-activation.mjs
|
||||
| 1. JSON Schema (manifest, each resource, each evidence row) | `node scripts/validate/validate-universal-resource-activation.mjs` | Invalid or incomplete JSON vs schemas |
|
||||
| 2. Full config gate (includes step 1) | `bash scripts/validation/validate-config-files.sh` | Any required project config check fails |
|
||||
| 3. CI-style aggregate | `bash scripts/verify/run-all-validation.sh --skip-genesis` | Any step in the wrapper fails |
|
||||
| 4. URA smoke (schema + optional HTTP) | `bash scripts/verify/smoke-universal-resource-activation.sh` | Step 1 fails. With `--http` (or `PHOENIX_BASE_URL=…`), also fails if Phoenix does not return HTTP 200 JSON with `.schemaVersion` at `/api/v1/universal-resource-activation/manifest` |
|
||||
| 5. OpenAPI / Swagger | Open `http://<host>:<port>/api-docs` on `phoenix-deploy-api` and confirm `GET /api/v1/universal-resource-activation/manifest` is listed (see [`phoenix-deploy-api/openapi.yaml`](../../../phoenix-deploy-api/openapi.yaml)) | N/A (manual) |
|
||||
| 4. URA smoke (schema + optional HTTP) | `bash scripts/verify/smoke-universal-resource-activation.sh` | Step 1 fails. With `--http` (or `PHOENIX_BASE_URL=…`), checks `GET …/manifest` (200 + `.schemaVersion`), `GET …/policy-profiles` (200 + `.profiles` array), and `GET …/server-funds-sidecar-probe` (**200** = sidecar or probe ok JSON; **503** + `configured: false` = URL unset, OK for dev; **502** = URL set but sidecar unreachable) |
|
||||
| 4b. On-chain / GRU hash (optional) | `node scripts/ura/keccak-resource-ids.mjs` | Prints `keccak256(utf8(resourceId))` per row (requires root `ethers`); does not block CI |
|
||||
| 4c. Server-funds sidecar probe (optional) | `curl` `GET /api/v1/universal-resource-activation/server-funds-sidecar-probe` on Phoenix | `503` + `configured:false` until `SERVER_FUNDS_SIDECAR_URL` is set; `200` when a health path returns 2xx |
|
||||
| 5. OpenAPI / Swagger | Open `http://<host>:<port>/api-docs` on `phoenix-deploy-api` and confirm URA paths (see [`phoenix-deploy-api/openapi.yaml`](../../../phoenix-deploy-api/openapi.yaml)) | N/A (manual) |
|
||||
|
||||
**Operator note:** `smoke-universal-resource-activation.sh` without flags only runs steps that need Node (no live Phoenix). Use `PHOENIX_BASE_URL=http://127.0.0.1:4001 bash scripts/verify/smoke-universal-resource-activation.sh --http` when the API is up on that host.
|
||||
**Operator note:** `smoke-universal-resource-activation.sh` without flags only runs steps that need Node (no live Phoenix). With Phoenix up: `PHOENIX_BASE_URL=http://127.0.0.1:4001 bash scripts/verify/smoke-universal-resource-activation.sh --http` (default base `http://127.0.0.1:4001` if unset with `--http`).
|
||||
|
||||
## 3. Phoenix Deploy API (read-only)
|
||||
|
||||
The API exposes the manifest as **JSON** without a partner API key (same pattern as the public-sector program manifest).
|
||||
The API exposes the manifest and policy profile registry as **JSON** without a partner API key (same pattern as the public-sector program manifest).
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| **Endpoint** | `GET /api/v1/universal-resource-activation/manifest` |
|
||||
| **Override path** | Set `UNIVERSAL_RESOURCE_MANIFEST_PATH` to a full file path. |
|
||||
| **Default resolution** | `PHOENIX_REPO_ROOT` (or `PROXMOX_REPO_PATH`) + `config/universal-resource-activation/manifest.json`, or `../config/...` when running with `phoenix-deploy-api` CWD. |
|
||||
| **Manifest** | `GET /api/v1/universal-resource-activation/manifest` |
|
||||
| **Policy profiles** | `GET /api/v1/universal-resource-activation/policy-profiles` |
|
||||
| **Manifest override** | `UNIVERSAL_RESOURCE_MANIFEST_PATH` (full file path). |
|
||||
| **Policy registry override** | `UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH` (full file path). |
|
||||
| **Default resolution** | `PHOENIX_REPO_ROOT` (or `PROXMOX_REPO_PATH`) + `config/universal-resource-activation/{manifest.json,policy-profiles.json}`, or `../config/...` when running with `phoenix-deploy-api` CWD. |
|
||||
|
||||
**Implementation:** [phoenix-deploy-api/server.js](../../../phoenix-deploy-api/server.js) — `resolveUniversalResourceManifestPath`, route registered before `partnerKeyMiddleware`.
|
||||
**Implementation:** [phoenix-deploy-api/server.js](../../../phoenix-deploy-api/server.js) — `resolveUniversalResourceManifestPath`, `resolveUniversalResourcePolicyProfilesPath`, routes registered before `partnerKeyMiddleware`.
|
||||
|
||||
## 4. Gitea / Phoenix deploy
|
||||
|
||||
When Gitea deploy syncs the `d-bis/proxmox` archive, the `config/` tree (including `config/universal-resource-activation/`) is part of the synced subtree. The Phoenix host can serve the manifest as soon as the file is present under `PHOENIX_REPO_ROOT`.
|
||||
|
||||
## 5. Future wiring (out of this pass)
|
||||
## 5. Integration tools (in-repo; operator or next phase)
|
||||
|
||||
- **On-chain / GRU M00:** When `UniversalAssetRegistry` and M00 are the SoR, mirror or hash `resourceId` into on-chain registries; keep the manifest as operator/air-gapped copy until a dedicated DB is introduced.
|
||||
- **OMNL / `server-funds-sidecar`:** Add API calls to register draws/holds; store returned `accountingRef` in new evidence package rows in `manifest.json` or a database — follow [UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md](UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md).
|
||||
- **DBIS Rail:** Link `settlementOrChainRef` in evidence packages to `MintAuth` / settlement router events per [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md).
|
||||
- **Manifest fragments + merge:** Drop partial JSON under `config/universal-resource-activation/manifest-fragments/` and run `pnpm ura:merge-manifest` (validate-only) or `node scripts/ura/merge-manifest-fragments.mjs --out <file>`. See [manifest-fragments/README.md](../../../config/universal-resource-activation/manifest-fragments/README.md) and [MANIFEST_AUTOMATION_DESIGN.md](../../../config/universal-resource-activation/MANIFEST_AUTOMATION_DESIGN.md). **Task index:** [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md).
|
||||
- **Ledger / Rail fragments:** `pnpm ura:writer:ledger`, `pnpm ura:writer:settlement`, `pnpm ura:validate-ledger-mapping` — [manifest-writer/README.md](../../../scripts/ura/manifest-writer/README.md); settlement sources: [DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md](../../dbis-rail/DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md); ops: [URA_MANIFEST_WRITER_OPS.md](../../03-deployment/URA_MANIFEST_WRITER_OPS.md).
|
||||
- **On-chain policy anchor (standalone):** `PolicyProfileRegistry` in `smom-dbis-138` + `pnpm ura:profile-hash` — [GRU_REGISTRY_WIRING_CHECKLIST.md](../../runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md) §6.
|
||||
- **Production closure gate:** `pnpm ura:validate-closure` (warnings) or `pnpm ura:validate-closure:strict` (exit 1 on pilot ids, pending evidence refs, `TBD` in evidence fields, or `reconciliationStatus: open`). Optional CI: `URA_STRICT_CLOSURE=1` with `validate-config-files.sh`.
|
||||
- **On-chain / GRU M00:** Canonical manifest stays the off-chain store. To **derive** EVM keccak for optional registry anchoring: `node scripts/ura/keccak-resource-ids.mjs` (uses `ethers` v6; prints one hash per `resourceId`). On-chain contract wiring remains a separate deployment task.
|
||||
- **OMNL / `server-funds-sidecar`:** Phoenix exposes **`GET /api/v1/universal-resource-activation/server-funds-sidecar-probe`** (no API key). Set `SERVER_FUNDS_SIDECAR_URL` to the sidecar base URL; optional `SERVER_FUNDS_SIDECAR_HEALTH_PATH` for a first path. Returns **503** with a configuration hint if unset. Draw/hold APIs and writing `accountingRef` into the manifest (or a DB) remain follow-on work per [UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md](UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md).
|
||||
- **DBIS Rail / MintAuth:** Evidence packages support **`settlementOrChainRef`** in JSON Schema. Populate the manifest with live settlement or event refs when the pilot posts to the rail; see [UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md](UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md) and [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md). Automated mirroring is out of scope until services expose stable query endpoints.
|
||||
|
||||
## Related
|
||||
|
||||
- [README.md](README.md) — document map
|
||||
- [README.md](README.md) — document map
|
||||
- [technical-specs/README.md](technical-specs/README.md) — normative TS-* specs for OMNL/sidecar, settlement indexer, SKR ETL, GRU program, compliance sign-off
|
||||
- [URA_PILOT_CLOSURE_RUNBOOK.md](URA_PILOT_CLOSURE_RUNBOOK.md) — close pilots / replace placeholders
|
||||
- [../compliance-matrices/README.md](../compliance-matrices/README.md) — jurisdiction matrices and onboarding charter/playbook
|
||||
- [../README.md](../README.md) (04-configuration) — main index
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# URA manifest automation — implementation tracker
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Single checklist for **OMNL/ledger → manifest**, **chain/Rail → manifest**, **GRU/on-chain registry**, and **ops gates**. Repo artifacts are linked; rows that need live services name the owning team.
|
||||
|
||||
**Legend:** **Done (repo)** = implemented or specified in this monorepo. **Operator** = execution on your LAN/RPC/Fineract deployment.
|
||||
|
||||
**Normative technical specs (remaining implementation):** [technical-specs/README.md](technical-specs/README.md) — RFC 2119 requirements, interfaces, acceptance tests for pending workstreams.
|
||||
|
||||
| ID | Task | Status | Artifact / next step |
|
||||
|----|------|--------|----------------------|
|
||||
| ura-auto-01 | OMNL/Fineract APIs → `accountingRef` | **Done (repo)** | [`URA_MANIFEST_WRITER_OPS.md`](../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §2; mapping schema |
|
||||
| ura-auto-02 | Server-funds sidecar ↔ ledger | **Operator** | Todo `ura-auto-02`; RTGS tracker; Phoenix probe only today |
|
||||
| ura-auto-03 | Mapping table (idempotency) | **Done (repo)** | [`omnl-ledger-mapping.v1.schema.json`](../../../config/universal-resource-activation/integration/omnl-ledger-mapping.v1.schema.json) |
|
||||
| ura-auto-04 | Manifest writer job | **Done (repo)** | [`build-ledger-fragment.mjs`](../../../scripts/ura/manifest-writer/build-ledger-fragment.mjs), [`merge-manifest-fragments.mjs`](../../../scripts/ura/merge-manifest-fragments.mjs) |
|
||||
| ura-auto-05 | Publish path (git/sync/API) | **Operator** | [`URA_MANIFEST_WRITER_OPS.md`](../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §4 |
|
||||
| ura-auto-06 | Secrets & IAM | **Operator** | Same doc §3 |
|
||||
| ura-auto-07 | Reconciliation / drift | **Done (repo)** | Spec in ops doc §5; implement alerts in your APM |
|
||||
| ura-auto-08 | E2E staging | **Operator** | Todo `ura-auto-08`; run writer + `pnpm ura:validate` after real journal export |
|
||||
| ura-auto-opt-a | Real-time vs batch | **Done (repo)** | Ops doc §6 optional |
|
||||
| ura-auto-opt-b | Multi-pool / DLQ / audit log | **Done (repo)** | Ops doc §6 optional |
|
||||
| chain-01 | Rail settlement event sources | **Done (repo)** | [`DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md`](../../dbis-rail/DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md) |
|
||||
| chain-02 | Indexer → `settlementOrChainRef` | **Partial (repo)** | Fragment CLI: [`build-settlement-fragment.mjs`](../../../scripts/ura/manifest-writer/build-settlement-fragment.mjs); **Operator:** Todo `chain-02` (live listener) |
|
||||
| chain-03 | SKR custody automation | **Partial (repo)** | [`SKR_CUSTODY_AUTOMATION_NOTES.md`](SKR_CUSTODY_AUTOMATION_NOTES.md); **Operator:** custodian ETL |
|
||||
| chain-opt-a | Anchor manifest hash on-chain | **Operator** | Optional pattern in settlement doc |
|
||||
| chain-opt-b | `keccak(resourceId)` in registry | **Operator** | After GRU facet; use [`keccak-resource-ids.mjs`](../../../scripts/ura/keccak-resource-ids.mjs) |
|
||||
| gru-01 | Lock GRC → M00 strategy | **Operator** | Todo `gru-01`; [`GRU_REGISTRY_WIRING_CHECKLIST.md`](../../runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md) §1 |
|
||||
| gru-02 | GRUStorage + bitmask | **Operator** | Todo `gru-02`; checklist §2 + facet map |
|
||||
| gru-03 | Minimum ship facets | **Operator** | Todo `gru-03`; checklist §3 (Solidity) |
|
||||
| gru-04 | Asset registry / Token factory | **Operator** | Todo `gru-04`; checklist §4 |
|
||||
| gru-05 | Deploy & verify M00 | **Operator** | Todo `gru-05`; [`GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md`](../../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) |
|
||||
| gru-06 | Multisig / pause drills | **Operator** | Todo `gru-06`; checklist §5 |
|
||||
| gru-07 | On-chain policy profile registry | **Done (repo)** | `smom-dbis-138/contracts/universal-resource/PolicyProfileRegistry.sol` + [`policy-profiles-content-hash.mjs`](../../../scripts/ura/policy-profiles-content-hash.mjs) |
|
||||
| gru-08 | Doc handoff (Phoenix/URA) | **Done (repo)** | This file + [`UNIVERSAL_RESOURCE_WIRING.md`](UNIVERSAL_RESOURCE_WIRING.md) §5 |
|
||||
| gru-opt-a | Oracle / cross-chain mirror | **Operator** | Checklist §7 |
|
||||
| gru-opt-b | External audit / formal verification | **Cancelled** | Vendor scope; not automatable in-repo |
|
||||
| xc-01 | `URA_STRICT_CLOSURE` in CI | **Done (repo)** | [`.gitea/workflows/validate-on-pr.yml`](../../../.gitea/workflows/validate-on-pr.yml) (documented env); [`validate-config-files.sh`](../../../scripts/validation/validate-config-files.sh) |
|
||||
| xc-02 | Legal sign-off on automation | **Operator** | Todo `xc-02` (counsel); template in [`URA_MANIFEST_WRITER_OPS.md`](../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §7 |
|
||||
| xc-03 | DR / rollback | **Done (repo)** | Ops doc §8 |
|
||||
|
||||
## Quick commands
|
||||
|
||||
```bash
|
||||
pnpm ura:validate-ledger-mapping
|
||||
pnpm ura:writer:ledger -- --mapping config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json --ledger config/universal-resource-activation/integration/examples/ledger-snapshot.example.json
|
||||
pnpm ura:writer:settlement -- --evidence-package-id ura:pilot:evidence-register-bootstrap --message-id 0x1 --tx-hash 0x2 --chain-id 138
|
||||
pnpm ura:profile-hash institutional_custody_skr_v1
|
||||
cd smom-dbis-138 && FORGE_SCOPE=universal-resource bash scripts/forge/scope.sh test --match-contract PolicyProfileRegistryTest
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [`MANIFEST_AUTOMATION_DESIGN.md`](../../../config/universal-resource-activation/MANIFEST_AUTOMATION_DESIGN.md)
|
||||
- [`URA_PILOT_CLOSURE_RUNBOOK.md`](URA_PILOT_CLOSURE_RUNBOOK.md)
|
||||
@@ -0,0 +1,62 @@
|
||||
# URA pilot closure runbook — replace placeholders with working components
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Operator checklist to move [`config/universal-resource-activation/manifest.json`](../../config/universal-resource-activation/manifest.json) from **bootstrap** to **pilot-closed** state, aligned with [UNIVERSAL_RESOURCE_PILOT_PLAN.md](UNIVERSAL_RESOURCE_PILOT_PLAN.md) and jurisdiction matrices (e.g. [ID-INDONESIA/banking_v1.md](../compliance-matrices/ID-INDONESIA/banking_v1.md)).
|
||||
|
||||
**Before production:** run `pnpm ura:validate` and `pnpm ura:validate-profiles`; legal/compliance must sign off obligation coverage in the compliance matrix.
|
||||
|
||||
---
|
||||
|
||||
## 1. Participant and jurisdiction (all resources)
|
||||
|
||||
| Step | Action | Manifest fields |
|
||||
|------|--------|-----------------|
|
||||
| 1.1 | Register institution in your participant registry; assign stable id. | `ownerParticipantId` — replace `ura:participant:pilot-*-assign` with canonical id. |
|
||||
| 1.2 | Confirm governing jurisdiction(s) with counsel. | `jurisdiction` — use catalog code (e.g. `ID`) or agreed tag; not `TBD`. |
|
||||
| 1.3 | Align profile with registry. | `policyProfileId` must exist in [policy-profiles.json](../../config/universal-resource-activation/policy-profiles.json). |
|
||||
|
||||
---
|
||||
|
||||
## 2. Pilot 1 — SKR / custody
|
||||
|
||||
| Step | Action | Manifest / evidence |
|
||||
|------|--------|---------------------|
|
||||
| 2.1 | Attach custodian / strategic evidence. | `evidenceRefs[]` — hashes, object ids, or signed manifest refs. |
|
||||
| 2.2 | Advance lifecycle per policy. | `lifecycleState` e.g. `pending_validation` → `active` when appropriate. |
|
||||
| 2.3 | Evidence package | Add or update package with `custodyOrSourceEvidence` pointing to SKR row; keep `reconciliationStatus` **open** until validator sign-off, then **matched** if all joins satisfied. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Pilot 2 — Server funds
|
||||
|
||||
| Step | Action | Manifest / evidence |
|
||||
|------|--------|---------------------|
|
||||
| 3.1 | Ensure `SERVER_FUNDS_SIDECAR_URL` and live draw/hold/release path. | Phoenix probe 200; see [UNIVERSAL_RESOURCE_WIRING.md](UNIVERSAL_RESOURCE_WIRING.md). |
|
||||
| 3.2 | Capture ledger reference. | `accountingRef` — real OMNL / Fineract / batch id (not narrative TBD). |
|
||||
| 3.3 | Capture rail / chain ref if used. | `settlementOrChainRef` — MintAuth `messageId`, tx hash, or rail id per [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md). |
|
||||
| 3.4 | Update notional if policy tracks pool balance. | `quantity` / `unitOfMeasure` on SERVER_FUNDS resource. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Pilot 3 — Infra capacity
|
||||
|
||||
| Step | Action | Manifest / evidence |
|
||||
|------|--------|---------------------|
|
||||
| 4.1 | Verify host and bundle against inventory. | `infraHostId`, `infraBundleId`; `evidenceRefs` may link to storage / VMID reports. |
|
||||
| 4.2 | After deploy, record deployment. | Evidence package `deploymentRef` — VMID, FQDN, health URL. |
|
||||
| 4.3 | Meter and reconcile. | Additional evidence package or same package with metering refs; `reconciliationStatus` **matched** when FinOps agrees. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Bootstrap evidence package closure
|
||||
|
||||
| Step | Action |
|
||||
|------|--------|
|
||||
| 5.1 | When pilots 1–3 mandatory joins are satisfied, set `reconciliationStatus` to **`matched`**. |
|
||||
| 5.2 | Set `manifest.json` top-level `updatedAt` to RFC3339 UTC. |
|
||||
| 5.3 | Re-run `pnpm ura:validate` and deploy manifest path on Phoenix (`PHOENIX_REPO_ROOT` / `UNIVERSAL_RESOURCE_MANIFEST_PATH`). |
|
||||
|
||||
## Related
|
||||
|
||||
- [DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](../../03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md)
|
||||
- [INSTITUTION_ONBOARDING_PLAYBOOK.md](../compliance-matrices/INSTITUTION_ONBOARDING_PLAYBOOK.md)
|
||||
@@ -0,0 +1,23 @@
|
||||
# URA / RTGS / GRU — technical specifications (remaining implementation)
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Normative **implementation** specifications for work that is still **operator- or engineering-pending** after repo scaffolding (writers, mapping schema, `PolicyProfileRegistry`, docs). These specs **do not replace** authoritative architecture documents; they bind them to testable interfaces and acceptance criteria.
|
||||
|
||||
## Document control
|
||||
|
||||
| ID | Title | Covers (tracker / todo ids) | Normative references |
|
||||
|----|--------|----------------------------|----------------------|
|
||||
| [TS-OMNL-SIDECAR-MANIFEST-SYNC-V1.md](TS-OMNL-SIDECAR-MANIFEST-SYNC-V1.md) | OMNL + server-funds-sidecar → manifest | `ura-auto-02`, `ura-auto-05`, `ura-auto-06`, `ura-auto-08` | [UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md](../UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md), [DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md](../../../03-deployment/DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md) §7 |
|
||||
| [TS-SETTLEMENT-INDEXER-MANIFEST-V1.md](TS-SETTLEMENT-INDEXER-MANIFEST-V1.md) | Chain / Rail events → `settlementOrChainRef` | `chain-02`, optional anchoring | [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md), [DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md](../../../dbis-rail/DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md) |
|
||||
| [TS-SKR-CUSTODY-ETL-MANIFEST-V1.md](TS-SKR-CUSTODY-ETL-MANIFEST-V1.md) | Custody evidence → manifest | `chain-03` | [SKR_CUSTODY_AUTOMATION_NOTES.md](../SKR_CUSTODY_AUTOMATION_NOTES.md), evidence package schema |
|
||||
| [TS-GRU-M00-IMPLEMENTATION-PROGRAM-V1.md](TS-GRU-M00-IMPLEMENTATION-PROGRAM-V1.md) | GRU M00 program (strategy → deploy → ops) | `gru-01`–`gru-06`, `gru-opt-a` | [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](../../GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md), [GRU_M00_DIAMOND_FACET_MAP.md](../../GRU_M00_DIAMOND_FACET_MAP.md), [GRU_REGISTRY_WIRING_CHECKLIST.md](../../../runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md) |
|
||||
| [TS-COMPLIANCE-AUTOMATION-SIGNOFF-V1.md](TS-COMPLIANCE-AUTOMATION-SIGNOFF-V1.md) | Legal / compliance gate for automation | `xc-02` | [INSTITUTION_ONBOARDING_CHARTER.md](../../compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md), [URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) |
|
||||
|
||||
## Conventions
|
||||
|
||||
- **MUST / SHOULD / MAY** follow [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) (and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174) for clarity when BCP 14 is intended).
|
||||
- **Canonical SoR:** OMNL / Fineract owns `accountingRef`; chain owns settlement attestations only per DBIS Rail design principle ([DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md) §0).
|
||||
|
||||
## Related
|
||||
|
||||
- [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](../URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
@@ -0,0 +1,52 @@
|
||||
# TS-COMPLIANCE-AUTOMATION-SIGNOFF-V1 — Legal / compliance gate for URA automation
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** Normative for **governance process** (not legal advice).
|
||||
**Audience:** Legal, compliance, program office, engineering leads.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Ensure **automated** updates to [`manifest.json`](../../../../config/universal-resource-activation/manifest.json) and related evidence fields **remain** within **counsel-approved** obligation coverage in per-jurisdiction compliance matrices.
|
||||
|
||||
## 2. Normative references
|
||||
|
||||
| Document | Role |
|
||||
|----------|------|
|
||||
| [INSTITUTION_ONBOARDING_CHARTER.md](../../compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md) | Definition of **Complete**, RACI |
|
||||
| [INSTITUTION_ONBOARDING_PLAYBOOK.md](../../compliance-matrices/INSTITUTION_ONBOARDING_PLAYBOOK.md) | Operational steps |
|
||||
| [POLICY_PROFILES_REGISTRY.md](../../../../config/universal-resource-activation/POLICY_PROFILES_REGISTRY.md) | Profile version sign-off table |
|
||||
| [URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §7 | Memo / ticket template |
|
||||
|
||||
## 3. Triggers requiring sign-off
|
||||
|
||||
Automation **SHALL NOT** be marked **production-ready** until **all** applicable rows below are satisfied:
|
||||
|
||||
| # | Trigger | Owner |
|
||||
|---|---------|-------|
|
||||
| T-1 | First production writer for **ledger** (`accountingRef`) | Legal + Compliance |
|
||||
| T-2 | First production **settlement indexer** (`settlementOrChainRef`) | Legal + Compliance + Risk |
|
||||
| T-3 | First production **custody ETL** (`evidenceRefs` / custody fields) | Legal + Compliance |
|
||||
| T-4 | Change to **mapping file** that alters which matrix obligation is evidenced | Legal + Compliance |
|
||||
| T-5 | Change to **`policyProfileId`** or registry row affecting production resources | Legal + Risk (per registry doc) |
|
||||
|
||||
## 4. Evidence package for auditors (recommended content)
|
||||
|
||||
Each sign-off **SHOULD** archive:
|
||||
|
||||
1. **Matrix reference:** Jurisdiction code + version + row ids (e.g. `ID-OMNL-001`) satisfied by automation.
|
||||
2. **Field mapping:** Table: automation output field → matrix control id → system of record.
|
||||
3. **Residual risk:** Known gaps, manual overrides, exception path.
|
||||
4. **Test artifacts:** Staging E2E logs (see [TS-OMNL-SIDECAR-MANIFEST-SYNC-V1.md](TS-OMNL-SIDECAR-MANIFEST-SYNC-V1.md) §7, [TS-SETTLEMENT-INDEXER-MANIFEST-V1.md](TS-SETTLEMENT-INDEXER-MANIFEST-V1.md) §10).
|
||||
5. **CI posture:** Whether `URA_STRICT_CLOSURE` / `vars.URA_STRICT_CLOSURE` is enabled for the branch.
|
||||
|
||||
## 5. Engineering obligations after sign-off
|
||||
|
||||
1. **R-COMP-1:** Manifest automation **MUST** log **immutable** correlation ids (ledger, chain, custody) per technical specs.
|
||||
2. **R-COMP-2:** Rollback and DR **MUST** be documented ([URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §8).
|
||||
3. **R-COMP-3:** Production manifest **SHOULD** pass `pnpm ura:validate-closure:strict` when pilots are closed.
|
||||
|
||||
## 6. Related
|
||||
|
||||
- [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md)
|
||||
- [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](../URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
@@ -0,0 +1,92 @@
|
||||
# TS-GRU-M00-IMPLEMENTATION-PROGRAM-V1 — GRU M00 diamond implementation program
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** Normative **program** specification (execution phases). Architecture remains in [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](../../GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) and [GRU_M00_DIAMOND_FACET_MAP.md](../../GRU_M00_DIAMOND_FACET_MAP.md).
|
||||
**Audience:** Solidity leads, governance ops, institutional spec owners.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Turn the **GRU M00 institutional spec + facet map** into a **sequenced, testable delivery program** with explicit decision gates, without duplicating the full facet catalog here.
|
||||
|
||||
## 2. Strategy gate (`gru-01`) — MUST complete first
|
||||
|
||||
| Decision | Options | Output artifact |
|
||||
|----------|---------|-----------------|
|
||||
| **GRC → M00 path** | **Option A:** new diamond · **Option B:** migrate GRC-2535 in place | Signed ADR + pointer in [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../../../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) §3–4 |
|
||||
|
||||
**R-GRU-0:** No Phase 2 storage layout work **SHALL** begin until **GRC → M00** is recorded and storage collision analysis is approved (see [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](../../GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md) §4.3).
|
||||
|
||||
## 3. Storage and governance (`gru-02`)
|
||||
|
||||
### 3.1 Deliverables
|
||||
|
||||
1. **D-GRU-S-1:** Written **GRUStorage** layout (namespaces, structs, slot discipline) reviewed by Solidity lead.
|
||||
2. **D-GRU-S-2:** **Governance level** default per environment (dev/test/prod) aligned with [GRU_M00_DIAMOND_FACET_MAP.md](../../GRU_M00_DIAMOND_FACET_MAP.md).
|
||||
3. **D-GRU-S-3:** **Bitmask / gate** mapping table: which gates invoke for levels 0–5.
|
||||
|
||||
### 3.2 Acceptance
|
||||
|
||||
- Forge (or Hardhat) **storage layout** diff shows **no collision** with existing GRC namespaces if Option B.
|
||||
|
||||
## 4. Minimum ship spine (`gru-03`)
|
||||
|
||||
Per gaps doc §5.1 “minimum ship list”, the program **MUST** deliver callable facets (stubs acceptable where marked):
|
||||
|
||||
| Facet class | MUST |
|
||||
|-------------|------|
|
||||
| PolicyRouter + gates | Expose entrypoints; emit events or structured reverts for policy violations |
|
||||
| StandardsRegistryFacet | Register at least one standards module id for tests |
|
||||
| GovernanceLevelFacet | Read/write level with access control |
|
||||
| TokenFactory / AssetRegistry path | Register at least one test asset type |
|
||||
|
||||
**R-GRU-M-1:** `diamondCut` integration tests **MUST** pass on CI for the scoped tree before testnet deploy.
|
||||
|
||||
## 5. Universal asset alignment (`gru-04`)
|
||||
|
||||
1. **R-GRU-U-1:** Document **cutover** from `UniversalAssetRegistry` (smom-dbis-138) to M00 registry: mirror vs replace, per [UNIVERSAL_RESOURCE_ONTOLOGY.md](../UNIVERSAL_RESOURCE_ONTOLOGY.md) §Mapping to GRU M00.
|
||||
2. **R-GRU-U-2:** `resourceId` ↔ on-chain `assetId` mapping **SHOULD** be tabulated in `docs/11-references` or deployment annex when addresses are known.
|
||||
|
||||
## 6. Deploy and verify (`gru-05`)
|
||||
|
||||
Follow [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../../../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) §6 verification table.
|
||||
|
||||
**Additional MUST for this program:**
|
||||
|
||||
1. Record Diamond + facet addresses in [CONTRACT_ADDRESSES_REFERENCE.md](../../../11-references/CONTRACT_ADDRESSES_REFERENCE.md) (or successor inventory).
|
||||
2. Run **loupe** + **governance level** + **PolicyRouter smoke** on each target chain before “complete” sign-off.
|
||||
|
||||
## 7. Governance operations (`gru-06`)
|
||||
|
||||
| Control | MUST |
|
||||
|---------|------|
|
||||
| Upgrade authority | Multisig or Timelock documented with addresses |
|
||||
| Pause | Drill once per quarter; RTO documented |
|
||||
| Incident | Rollback cut procedure documented (runbook §4.3 Option B) |
|
||||
|
||||
## 8. Standalone policy anchor (already in repo)
|
||||
|
||||
**PolicyProfileRegistry** ([`PolicyProfileRegistry.sol`](../../../../smom-dbis-138/contracts/universal-resource/PolicyProfileRegistry.sol)) **MAY** deploy **before** full M00 spine per [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../../../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) §7.
|
||||
|
||||
**R-GRU-P-1:** Published `contentHash` **MUST** match `pnpm ura:profile-hash <policyProfileId>` for the same JSON canonicalization rule.
|
||||
|
||||
## 9. Optional phase — oracle / cross-chain (`gru-opt-a`)
|
||||
|
||||
**MAY** follow after Phase 6 stable:
|
||||
|
||||
1. Define attestation format for off-chain evidence hashes.
|
||||
2. Define mirror registry addresses per chain; document in multi-chain deployment annex.
|
||||
|
||||
## 10. Program exit criteria (all phases)
|
||||
|
||||
| Gate | Condition |
|
||||
|------|------------|
|
||||
| **G1** | ADR + storage signed off |
|
||||
| **G2** | Spine facets on testnet + verification table green |
|
||||
| **G3** | Mainnet (or Chain 138 prod) addresses recorded + ontology cutover doc updated |
|
||||
| **G4** | Pause/upgrade drill log archived |
|
||||
|
||||
## 11. Related
|
||||
|
||||
- [GRU_REGISTRY_WIRING_CHECKLIST.md](../../../runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md)
|
||||
- [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](../URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
@@ -0,0 +1,99 @@
|
||||
# TS-OMNL-SIDECAR-MANIFEST-SYNC-V1 — OMNL + server-funds-sidecar → URA manifest
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** Normative for implementation (supplements [UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md](../UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md)).
|
||||
**Audience:** HYBX integration, banking ops, platform SRE.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Define **end-to-end technical requirements** so that:
|
||||
|
||||
1. **OMNL / Fineract** remains the **system of record** for ledger postings and `accountingRef`.
|
||||
2. **`server-funds-sidecar`** exposes **stable, authenticated** APIs (or exports) that correlate treasury actions with OMNL lines.
|
||||
3. The **URA manifest** receives **non-placeholder** `accountingRef` (and optional quantity) on the correct `resourceId` / `evidencePackageId` rows, validated by `pnpm ura:validate` / `pnpm ura:validate-profiles`.
|
||||
|
||||
## 2. Scope and non-goals
|
||||
|
||||
### 2.1 In scope
|
||||
|
||||
- Correlation model: sidecar draw/hold/release ↔ OMNL journal/batch identifiers.
|
||||
- Writer / publish pipeline (batch or near-real-time) from SoR exports to manifest fragments.
|
||||
- Idempotency, observability, and security for the sync path.
|
||||
- Staging E2E acceptance criteria.
|
||||
|
||||
### 2.2 Out of scope (this TS)
|
||||
|
||||
- Replacing Fineract as SoR or defining full Fineract product configuration.
|
||||
- Full OpenAPI for every OMNL deployment variant (this TS defines **required capability classes**; concrete paths MAY be tenant-specific annexes).
|
||||
- On-chain settlement logic (see [TS-SETTLEMENT-INDEXER-MANIFEST-V1.md](TS-SETTLEMENT-INDEXER-MANIFEST-V1.md)).
|
||||
|
||||
## 3. Normative references (answers consolidated from repo)
|
||||
|
||||
| Topic | Source |
|
||||
|-------|--------|
|
||||
| Sidecar responsibilities (treasury, limits, handoff) | [DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md](../../../03-deployment/DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md) §7 `server-funds-sidecar` |
|
||||
| SoR boundary | [UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md](../UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md) §System-of-record boundary |
|
||||
| Workstream exit criteria | [DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](../../../03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md) W1, W2 |
|
||||
| Mapping file schema | [`omnl-ledger-mapping.v1.schema.json`](../../../../config/universal-resource-activation/integration/omnl-ledger-mapping.v1.schema.json) |
|
||||
| Fragment builder | [`build-ledger-fragment.mjs`](../../../../scripts/ura/manifest-writer/build-ledger-fragment.mjs) |
|
||||
| Ops (secrets, publish, DR) | [URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) |
|
||||
|
||||
## 4. Definitions
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| **Correlation id** | Stable string linking one sidecar operation to exactly one OMNL posting (or explicitly documented 1:N with parent ref). |
|
||||
| **Ledger snapshot** | JSON export row (API response or batch file) containing at least the fields referenced by `accountingRefField` in the mapping file. |
|
||||
| **Manifest fragment** | JSON object with optional `evidencePackages[]` / `resources[]` partial rows, mergeable per [merge-manifest-fragments.mjs](../../../../scripts/ura/merge-manifest-fragments.mjs). |
|
||||
|
||||
## 5. Functional requirements
|
||||
|
||||
### 5.1 Sidecar → OMNL correlation
|
||||
|
||||
The implementation **MUST** satisfy:
|
||||
|
||||
1. **R-OMNL-1:** Every **production** draw, hold, or release that affects a URA-tracked `SERVER_FUNDS` pool **MUST** emit or record a **correlation id** retrievable after the fact (log, DB row, or event).
|
||||
2. **R-OMNL-2:** For each correlation id, operators **MUST** be able to obtain the **OMNL `accountingRef`** (journal entry id, batch id, or institution-agreed composite) that the mapping file can point at.
|
||||
3. **R-OMNL-3:** If OMNL posting is **asynchronous**, the sidecar **MUST** expose **status** (pending / posted / failed) so the writer does not publish a final `accountingRef` until `posted`.
|
||||
|
||||
### 5.2 Manifest writer pipeline
|
||||
|
||||
1. **R-WR-1:** The writer **MUST** consume [`omnl-ledger-mapping.v1.json`](../../../../config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json) (or equivalent path) validated by `pnpm ura:validate-ledger-mapping`.
|
||||
2. **R-WR-2:** Before any publish, merged output **MUST** pass `pnpm ura:validate` and `pnpm ura:validate-profiles`.
|
||||
3. **R-WR-3:** Writes **SHOULD** be **idempotent**: same ledger snapshot + mapping **MUST NOT** create duplicate conflicting evidence rows (use deterministic merge; reject second publish with same `(evidencePackageId, accountingRef)` if policy forbids change).
|
||||
4. **R-WR-4:** Publish path **MUST** follow one mode documented in [URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §4 (git PR, secured sync, or future authenticated API).
|
||||
|
||||
### 5.3 Phoenix / runtime
|
||||
|
||||
1. **R-PHX-1:** Production **SHOULD** set `SERVER_FUNDS_SIDECAR_URL` so [server-funds-sidecar-probe](../../../../phoenix-deploy-api/server.js) returns **200** when the sidecar is healthy (not only 503 unset).
|
||||
2. **R-PHX-2:** After manifest update, Phoenix **MUST** serve updated JSON from `PHOENIX_REPO_ROOT` or `UNIVERSAL_RESOURCE_MANIFEST_PATH` without manual restart if your deploy model supports file watch; otherwise document reload step.
|
||||
|
||||
## 6. Non-functional requirements
|
||||
|
||||
| ID | Category | Requirement |
|
||||
|----|----------|-------------|
|
||||
| N-S-1 | Security | Fineract and sidecar credentials **MUST NOT** be stored in git; use vault / host env. |
|
||||
| N-S-2 | Security | Writer service **MUST** use mutual TLS or private network to reach sidecar/OMNL where exposed beyond localhost. |
|
||||
| N-O-1 | Observability | Emit structured logs: `correlationId`, `resourceId`, `evidencePackageId`, `accountingRef`, manifest git SHA or file version. |
|
||||
| N-O-2 | Observability | Metric: `ura_manifest_ledger_sync_success_total`, `ura_manifest_ledger_sync_fail_total`, histogram of lag vs OMNL `postedAt`. |
|
||||
| N-R-1 | Reliability | Failed merge/validate **MUST** land in DLQ or alert; **MUST NOT** partially write corrupt manifest. |
|
||||
|
||||
## 7. Staging E2E acceptance (`ura-auto-08`)
|
||||
|
||||
The following **MUST** pass in a non-production environment before production automation is enabled:
|
||||
|
||||
1. Inject or use a real OMNL posting tied to a test sidecar operation.
|
||||
2. Produce ledger snapshot JSON; run `pnpm ura:writer:ledger` → fragment.
|
||||
3. Merge with `merge-manifest-fragments.mjs --out` (or production equivalent).
|
||||
4. `pnpm ura:validate && pnpm ura:validate-profiles` exit 0.
|
||||
5. Optional: `pnpm ura:smoke --http` against staging Phoenix shows updated `accountingRef` in served manifest.
|
||||
|
||||
## 8. Optional capability annex (informative)
|
||||
|
||||
Concrete REST paths for Fineract (`/journalentries`, `/savingstransactions`, etc.) **SHOULD** be recorded in a **tenant annex** (one Markdown or OpenAPI file per OMNL deployment), linked from this TS version header.
|
||||
|
||||
## 9. Related
|
||||
|
||||
- [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](../URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
- [URA_PILOT_CLOSURE_RUNBOOK.md](../URA_PILOT_CLOSURE_RUNBOOK.md) §3
|
||||
@@ -0,0 +1,95 @@
|
||||
# TS-SETTLEMENT-INDEXER-MANIFEST-V1 — Settlement / MintAuth events → URA manifest
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** Normative for implementation (supplements [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md) for **off-chain mirror** only).
|
||||
**Audience:** Chain 138 integrators, indexer operators, platform SRE.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Specify how **on-chain (or ISO-gateway-derived) settlement identifiers** flow into [`settlementOrChainRef`](../../../../config/universal-resource-activation.evidence-package.v1.schema.json) on the correct evidence package rows, using the repo’s [`build-settlement-fragment.mjs`](../../../../scripts/ura/manifest-writer/build-settlement-fragment.mjs) as the **canonical string format** for v1.
|
||||
|
||||
## 2. Design principle (normative)
|
||||
|
||||
**Fiat finality and compliance remain off-chain** per DBIS Rail §0. This indexer **MUST NOT** infer good funds from `tx.status` alone; it **MUST** only record **authorization / settlement identifiers** already produced by the Rail / gateway.
|
||||
|
||||
## 3. Scope and non-goals
|
||||
|
||||
### 3.1 In scope
|
||||
|
||||
- Event subscription (logs, websocket, or indexer) → deterministic `settlementOrChainRef` string.
|
||||
- Reorg handling policy (minimum depth before write).
|
||||
- Optional: manifest or evidence-package hash anchoring (see §8).
|
||||
|
||||
### 3.2 Out of scope
|
||||
|
||||
- Replacing MintAuth verification inside contracts.
|
||||
- Parsing full ISO-20022 payloads on-chain.
|
||||
|
||||
## 4. Normative references
|
||||
|
||||
| Topic | Source |
|
||||
|-------|--------|
|
||||
| Event inventory | [DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md](../../../dbis-rail/DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md) |
|
||||
| Rail controls / IDs | [DBIS_RAIL_TECHNICAL_SPEC_V1.md](../../../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md) |
|
||||
| Fragment CLI | [`build-settlement-fragment.mjs`](../../../../scripts/ura/manifest-writer/build-settlement-fragment.mjs) |
|
||||
|
||||
## 5. `settlementOrChainRef` format (v1)
|
||||
|
||||
Unless a future TS supersedes this, production automation **SHOULD** emit:
|
||||
|
||||
```text
|
||||
messageId=<mintAuthOrGatewayMessageId>;tx=<0x-prefixed-tx-hash>;chain=<decimal-chain-id>
|
||||
```
|
||||
|
||||
Omitted components **MAY** be dropped if not applicable; **MUST NOT** use ambiguous comma-separated free text without `key=` prefixes.
|
||||
|
||||
## 6. Functional requirements
|
||||
|
||||
### 6.1 Indexer
|
||||
|
||||
1. **R-IX-1:** The indexer **MUST** subscribe to a **documented** contract/event set per environment (addresses in deployment annex).
|
||||
2. **R-IX-2:** Before writing the manifest, the indexer **MUST** wait **N** confirmations (N **SHOULD** default to 12 on Chain 138 unless risk review says otherwise).
|
||||
3. **R-IX-3:** On reorg deeper than N, the indexer **MUST** emit **alert** and **MUST NOT** silently delete manifest rows without human or policy-governed rollback ([URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §8).
|
||||
4. **R-IX-4:** Each processed event **MUST** carry an **idempotency key** `(chainId, blockNumber, logIndex)` or equivalent to prevent duplicate `settlementOrChainRef` appends.
|
||||
|
||||
### 6.2 Binding to evidence packages
|
||||
|
||||
1. **R-BIND-1:** Configuration **MUST** map `(settlement profile | pool id | message route)` → `evidencePackageId` (YAML or JSON in secure config, not hard-coded in indexer binary).
|
||||
2. **R-BIND-2:** If no mapping exists, the indexer **MUST** **fail closed** (alert, no manifest write).
|
||||
|
||||
### 6.3 Validation gate
|
||||
|
||||
Merged manifest **MUST** pass `pnpm ura:validate` before publish.
|
||||
|
||||
## 7. Observability and security
|
||||
|
||||
| ID | Requirement |
|
||||
|----|-------------|
|
||||
| N-IX-O-1 | Logs **MUST** include `blockNumber`, `txHash`, `evidencePackageId`, idempotency key. |
|
||||
| N-IX-S-1 | RPC URLs and API keys **MUST** use secrets management. |
|
||||
| N-IX-S-2 | Indexer write principal **SHOULD** be least-privilege (only manifest publish path, not chain admin). |
|
||||
|
||||
## 8. Optional: evidence / manifest anchoring (`chain-opt-a`)
|
||||
|
||||
If anchoring is required:
|
||||
|
||||
1. Compute `sha256` (or keccak per policy) over canonical JSON of the **evidence package row** (or full manifest).
|
||||
2. Publish hash via **PolicyProfileRegistry-style** pattern or dedicated anchor contract **MAY** be used; document address in deployment annex.
|
||||
3. Anchoring **MUST NOT** replace manifest JSON as the operational read model for Phoenix.
|
||||
|
||||
## 9. Optional: `keccak(resourceId)` (`chain-opt-b`)
|
||||
|
||||
When a GRU or Rail registry facet accepts resource id hashes, use [`keccak-resource-ids.mjs`](../../../../scripts/ura/keccak-resource-ids.mjs) and document the facet’s expected encoding (UTF-8 string vs ABI-encoded).
|
||||
|
||||
## 10. Acceptance criteria (staging)
|
||||
|
||||
1. Deployed mock or testnet settlement emits event with known `messageId` / tx.
|
||||
2. Indexer produces fragment matching §5.
|
||||
3. After merge + validate, Phoenix GET manifest shows updated `settlementOrChainRef`.
|
||||
4. Replay same event → no duplicate ref (idempotency).
|
||||
|
||||
## 11. Related
|
||||
|
||||
- [DBIS_RAIL_JURISDICTION_TRACEABILITY.md](../../../dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md)
|
||||
- [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](../URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
@@ -0,0 +1,71 @@
|
||||
# TS-SKR-CUSTODY-ETL-MANIFEST-V1 — Custody / SKR evidence → URA manifest
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Last updated:** 2026-04-25
|
||||
**Status:** Normative for implementation (supplements [SKR_CUSTODY_AUTOMATION_NOTES.md](../SKR_CUSTODY_AUTOMATION_NOTES.md)).
|
||||
**Audience:** Custody ops, compliance engineering, integration.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Define how **custodian or internal attestation outputs** become **`evidenceRefs`** and evidence-package **`custodyOrSourceEvidence`** fields without weakening jurisdiction matrix obligations ([ID-INDONESIA/banking_v1.md](../../compliance-matrices/ID-INDONESIA/banking_v1.md) or successor).
|
||||
|
||||
## 2. Scope and non-goals
|
||||
|
||||
### 2.1 In scope
|
||||
|
||||
- Data model for custody **artifact** ingestion.
|
||||
- Hashing, object storage references, and manifest field mapping.
|
||||
- PII / retention constraints at integration boundary.
|
||||
- Acceptance tests for Pilot 1 closure path.
|
||||
|
||||
### 2.2 Out of scope
|
||||
|
||||
- Legal interpretation of custody regulations (counsel-owned).
|
||||
- Replacing custodian’s own audit trail.
|
||||
|
||||
## 3. Definitions
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| **Artifact** | Statement file, API payload, or signed attestation representing a custody position. |
|
||||
| **Fingerprint** | Cryptographic digest (SHA-256 **RECOMMENDED**) over canonical bytes of artifact. |
|
||||
| **External ref** | URI or object key (e.g. `s3://…`, `https://…`) **SHOULD** be paired with fingerprint. |
|
||||
|
||||
## 4. Functional requirements
|
||||
|
||||
### 4.1 Ingestion
|
||||
|
||||
1. **R-SKR-1:** ETL **MUST** accept artifacts only over **authenticated** channels (mTLS, signed webhook, or VPN).
|
||||
2. **R-SKR-2:** Each artifact **MUST** produce `fingerprint` and **SHOULD** store `retrievedAt` (RFC 3339 UTC).
|
||||
3. **R-SKR-3:** `evidenceRefs` entries **SHOULD** use **`sha256:<hex>`** or documented URI scheme agreed with audit.
|
||||
|
||||
### 4.2 Manifest mapping
|
||||
|
||||
1. **R-SKR-4:** Pilot 1 resource (`SKR_SAFEKEEPING`) **MUST** reference the same logical artifact in `evidenceRefs` and in the evidence package row required by [URA_PILOT_CLOSURE_RUNBOOK.md](../URA_PILOT_CLOSURE_RUNBOOK.md) §2.
|
||||
2. **R-SKR-5:** Updates **MUST** be idempotent per `(resourceId, fingerprint)`.
|
||||
|
||||
### 4.3 Evidence package text field
|
||||
|
||||
`custodyOrSourceEvidence` **MAY** hold human-readable summary; **MUST** include fingerprint or stable id counsel approved for audit.
|
||||
|
||||
## 5. Privacy and retention
|
||||
|
||||
1. **N-SKR-P-1:** Personally identifiable data **MUST NOT** be copied into manifest JSON unless explicitly allowed by DPA and matrix.
|
||||
2. **N-SKR-P-2:** Retention of manifest snapshots **MUST** follow institution policy; DR per [URA_MANIFEST_WRITER_OPS.md](../../../03-deployment/URA_MANIFEST_WRITER_OPS.md) §8.
|
||||
|
||||
## 6. Validation
|
||||
|
||||
Before production:
|
||||
|
||||
1. `pnpm ura:validate` / `pnpm ura:validate-profiles` pass.
|
||||
2. `pnpm ura:validate-closure:strict` passes **after** placeholders replaced per runbook.
|
||||
3. Compliance sign-off recorded per [TS-COMPLIANCE-AUTOMATION-SIGNOFF-V1.md](TS-COMPLIANCE-AUTOMATION-SIGNOFF-V1.md).
|
||||
|
||||
## 7. Implementation note
|
||||
|
||||
A dedicated `build-custody-fragment.mjs` **MAY** be added mirroring the ledger writer; until then, fragments **MAY** be hand-crafted JSON matching merge rules in [merge-manifest-fragments.mjs](../../../../scripts/ura/merge-manifest-fragments.mjs).
|
||||
|
||||
## 8. Related
|
||||
|
||||
- [UNIVERSAL_RESOURCE_SKR_CUSTODY_LANE.md](../UNIVERSAL_RESOURCE_SKR_CUSTODY_LANE.md)
|
||||
- [UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md](../UNIVERSAL_RESOURCE_EVIDENCE_PACKAGE.md)
|
||||
@@ -102,7 +102,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/) — **client / division terminology:** [02-architecture/CLIENT_DIVISION_TERMINOLOGY.md](02-architecture/CLIENT_DIVISION_TERMINOLOGY.md); **Public sector + Phoenix catalog baseline:** [02-architecture/PUBLIC_SECTOR_TENANCY_MARKETPLACE_AND_DEPLOYMENT_BASELINE.md](02-architecture/PUBLIC_SECTOR_TENANCY_MARKETPLACE_AND_DEPLOYMENT_BASELINE.md); **non-goals (incl. catalog vs marketing §9):** [02-architecture/NON_GOALS.md](02-architecture/NON_GOALS.md); **DeFi Oracle Meta Mainnet (Chain 138):** [dbis_chain_138_technical_master_plan.md](../dbis_chain_138_technical_master_plan.md), [02-architecture/DBIS_NODE_ROLE_MATRIX.md](02-architecture/DBIS_NODE_ROLE_MATRIX.md), [02-architecture/DBIS_PHASE2_PROXMOX_SOVEREIGNIZATION_ROADMAP.md](02-architecture/DBIS_PHASE2_PROXMOX_SOVEREIGNIZATION_ROADMAP.md) |
|
||||
| **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), **Public sector live checklist:** [03-deployment/PUBLIC_SECTOR_LIVE_DEPLOYMENT_CHECKLIST.md](03-deployment/PUBLIC_SECTOR_LIVE_DEPLOYMENT_CHECKLIST.md), **Proxmox VE ops template:** [03-deployment/PROXMOX_VE_OPERATIONAL_DEPLOYMENT_TEMPLATE.md](03-deployment/PROXMOX_VE_OPERATIONAL_DEPLOYMENT_TEMPLATE.md) · [`config/proxmox-operational-template.json`](config/proxmox-operational-template.json); **DBIS Phase 1–3:** [03-deployment/PHASE1_DISCOVERY_RUNBOOK.md](03-deployment/PHASE1_DISCOVERY_RUNBOOK.md), [03-deployment/DBIS_PHASE3_E2E_PRODUCTION_SIMULATION_RUNBOOK.md](03-deployment/DBIS_PHASE3_E2E_PRODUCTION_SIMULATION_RUNBOOK.md), [03-deployment/CALIPER_CHAIN138_PERF_HOOK.md](03-deployment/CALIPER_CHAIN138_PERF_HOOK.md), [03-deployment/DBIS_HYPERLEDGER_RUNTIME_STATUS.md](03-deployment/DBIS_HYPERLEDGER_RUNTIME_STATUS.md), [03-deployment/DBIS_PHASES_1_TO_3_PRODUCTION_GATE.md](03-deployment/DBIS_PHASES_1_TO_3_PRODUCTION_GATE.md), **RTGS canonical production checklist and institutional-finance layers:** [03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md](03-deployment/DBIS_RTGS_E2E_REQUIREMENTS_MATRIX.md), [03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md](03-deployment/DBIS_RTGS_MASTER_PLAN_IMPLEMENTATION_TRACKER.md), [03-deployment/DBIS_RTGS_FX_TRANSACTION_CATALOG.md](03-deployment/DBIS_RTGS_FX_TRANSACTION_CATALOG.md), [03-deployment/DBIS_RTGS_DEPOSITORY_AND_CUSTODY_OPERATING_MODEL.md](03-deployment/DBIS_RTGS_DEPOSITORY_AND_CUSTODY_OPERATING_MODEL.md), [03-deployment/DBIS_RTGS_FX_AND_LIQUIDITY_OPERATING_MODEL.md](03-deployment/DBIS_RTGS_FX_AND_LIQUIDITY_OPERATING_MODEL.md), [03-deployment/DBIS_RTGS_CONTROL_PLANE_DEPLOYMENT_CHECKLIST.md](03-deployment/DBIS_RTGS_CONTROL_PLANE_DEPLOYMENT_CHECKLIST.md), [03-deployment/DBIS_RTGS_LATER_PHASE_SIDECARS_DEPLOYMENT_CHECKLIST.md](03-deployment/DBIS_RTGS_LATER_PHASE_SIDECARS_DEPLOYMENT_CHECKLIST.md), [03-deployment/DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md](03-deployment/DBIS_OMNL_INDONESIA_BNI_E2E_INTEGRATION_BLUEPRINT.md), [03-deployment/DBIS_RTGS_FIRST_SLICE_ARCHITECTURE.md](03-deployment/DBIS_RTGS_FIRST_SLICE_ARCHITECTURE.md), [03-deployment/DBIS_RTGS_FIRST_SLICE_DEPLOYMENT_CHECKLIST.md](03-deployment/DBIS_RTGS_FIRST_SLICE_DEPLOYMENT_CHECKLIST.md), [03-deployment/DBIS_HYBX_SIDECAR_BOUNDARY_MATRIX.md](03-deployment/DBIS_HYBX_SIDECAR_BOUNDARY_MATRIX.md), [03-deployment/DBIS_MOJALOOP_INTEGRATION_STATUS.md](03-deployment/DBIS_MOJALOOP_INTEGRATION_STATUS.md), [03-deployment/DBIS_HYPERLEDGER_IDENTITY_STACK_DECISION.md](03-deployment/DBIS_HYPERLEDGER_IDENTITY_STACK_DECISION.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); **Multi-jurisdiction compliance (matrices, charter, playbook):** [04-configuration/compliance-matrices/README.md](04-configuration/compliance-matrices/README.md), [04-configuration/jurisdictions/JURISDICTION_CATALOG.md](04-configuration/jurisdictions/JURISDICTION_CATALOG.md), [`config/jurisdictions/catalog.v1.json`](../config/jurisdictions/catalog.v1.json), [dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md](dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md); **Universal resource activation (SKR, server funds, infra):** [04-configuration/universal-resource-activation/README.md](04-configuration/universal-resource-activation/README.md), [UNIVERSAL_RESOURCE_WIRING.md](04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md), `pnpm ura:validate`, `pnpm ura:validate-profiles`, `pnpm ura:merge-manifest`, `pnpm ura:validate-closure` / `URA_STRICT_CLOSURE`, `pnpm ura:smoke`, `node scripts/ura/keccak-resource-ids.mjs`, Phoenix URA routes (manifest, policy-profiles, sidecar-probe), [`config/universal-resource-activation/manifest.json`](../config/universal-resource-activation/manifest.json), [`config/universal-resource-activation/policy-profiles.json`](../config/universal-resource-activation/policy-profiles.json), [manifest-fragments/README.md](../config/universal-resource-activation/manifest-fragments/README.md); **Chain 138 wallets:** [04-configuration/CHAIN138_WALLET_CONFIG_VALIDATION.md](04-configuration/CHAIN138_WALLET_CONFIG_VALIDATION.md); **Chain 2138 testnet wallets:** [04-configuration/CHAIN2138_WALLET_CONFIG_VALIDATION.md](04-configuration/CHAIN2138_WALLET_CONFIG_VALIDATION.md); **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) |
|
||||
| **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); **Multi-jurisdiction compliance (matrices, charter, playbook):** [04-configuration/compliance-matrices/README.md](04-configuration/compliance-matrices/README.md), [04-configuration/jurisdictions/JURISDICTION_CATALOG.md](04-configuration/jurisdictions/JURISDICTION_CATALOG.md), [`config/jurisdictions/catalog.v1.json`](../config/jurisdictions/catalog.v1.json), [dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md](dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md); **Universal resource activation (SKR, server funds, infra):** [04-configuration/universal-resource-activation/README.md](04-configuration/universal-resource-activation/README.md), [UNIVERSAL_RESOURCE_WIRING.md](04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md), [URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md](04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md), [technical-specs/README.md](04-configuration/universal-resource-activation/technical-specs/README.md) (normative TS-* for remaining implementation), [URA_MANIFEST_WRITER_OPS.md](03-deployment/URA_MANIFEST_WRITER_OPS.md), [GRU_REGISTRY_WIRING_CHECKLIST.md](runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md), `pnpm ura:*`, Phoenix URA routes, [`config/universal-resource-activation/`](../config/universal-resource-activation/); **Chain 138 wallets:** [04-configuration/CHAIN138_WALLET_CONFIG_VALIDATION.md](04-configuration/CHAIN138_WALLET_CONFIG_VALIDATION.md); **Chain 2138 testnet wallets:** [04-configuration/CHAIN2138_WALLET_CONFIG_VALIDATION.md](04-configuration/CHAIN2138_WALLET_CONFIG_VALIDATION.md); **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) |
|
||||
| **Phoenix / Sankofa deploy handoff** | [04-configuration/PHOENIX_SANKOFA_OPERATOR_HANDOFF.md](04-configuration/PHOENIX_SANKOFA_OPERATOR_HANDOFF.md) — live CTs, env locations, secret split, rotate/reload/verify commands |
|
||||
| **06-besu** | [06-besu/MASTER_INDEX.md](06-besu/MASTER_INDEX.md) |
|
||||
| **Testnet (2138)** | [testnet/DEFI_ORACLE_META_TESTNET_2138_RUNBOOK.md](testnet/DEFI_ORACLE_META_TESTNET_2138_RUNBOOK.md), [testnet/TESTNET_DEPLOYMENT.md](testnet/TESTNET_DEPLOYMENT.md) |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Network:** DBIS Mainnet (ChainID 138)
|
||||
**Document type:** Control verification checklist (pre-audit)
|
||||
**Companion documents:** [Technical Spec v1](DBIS_RAIL_TECHNICAL_SPEC_V1.md), [Rulebook v1](DBIS_RAIL_RULEBOOK_V1.md), [Security Threat Model v1](DBIS_RAIL_SECURITY_THREAT_MODEL_V1.md), [Regulator Brief v1](DBIS_RAIL_REGULATOR_BRIEF_V1.md)
|
||||
**Companion documents:** [Technical Spec v1](DBIS_RAIL_TECHNICAL_SPEC_V1.md), [Rulebook v1](DBIS_RAIL_RULEBOOK_V1.md), [Security Threat Model v1](DBIS_RAIL_SECURITY_THREAT_MODEL_V1.md), [Regulator Brief v1](DBIS_RAIL_REGULATOR_BRIEF_V1.md), [Jurisdiction traceability](DBIS_RAIL_JURISDICTION_TRACEABILITY.md) (controls ↔ per-jurisdiction compliance matrices ↔ URA policy profiles)
|
||||
|
||||
**Purpose:** Bridge documentation to operational evidence. Each item is verifiable (code, config, procedure, or test). Use this checklist before external audit or formal control mapping.
|
||||
|
||||
|
||||
@@ -35,6 +35,20 @@ Section numbers refer to the respective document sections (e.g. Spec 6.5 = DBIS_
|
||||
|
||||
---
|
||||
|
||||
## Jurisdiction matrices and policy profiles
|
||||
|
||||
Obligations in **per-jurisdiction compliance matrices** map to these control IDs where the Rail is in scope. Full obligation → control → `policyProfileId` → URA field mapping lives in **[DBIS_RAIL_JURISDICTION_TRACEABILITY.md](DBIS_RAIL_JURISDICTION_TRACEABILITY.md)**.
|
||||
|
||||
| Artifact | Role |
|
||||
|----------|------|
|
||||
| [compliance-matrices/README.md](../04-configuration/compliance-matrices/README.md) | Index of jurisdiction folders (ID, stubs, drafts). |
|
||||
| [policy-profiles.json](../../config/universal-resource-activation/policy-profiles.json) | Machine-readable `policyProfileId` registry with `minimumGruGovernanceLevel`. |
|
||||
| [POLICY_PROFILES_REGISTRY.md](../../config/universal-resource-activation/POLICY_PROFILES_REGISTRY.md) | Doc control and legal sign-off table for profile versions. |
|
||||
|
||||
When a jurisdiction adds **local** controls (prefix e.g. `J-ID-AML-001`), document them in that jurisdiction’s matrix and extend the traceability doc; they do not replace C1–C18 for on-chain Rail behavior.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **Spec:** [DBIS_RAIL_TECHNICAL_SPEC_V1.md](DBIS_RAIL_TECHNICAL_SPEC_V1.md)
|
||||
|
||||
42
docs/dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md
Normal file
42
docs/dbis-rail/DBIS_RAIL_JURISDICTION_TRACEABILITY.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# DBIS Rail — jurisdiction and compliance matrix traceability
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Cross-link [DBIS_RAIL_CONTROL_MAPPING_V1.md](DBIS_RAIL_CONTROL_MAPPING_V1.md) controls to **jurisdiction compliance matrices** and **URA policy profiles**, so auditors can navigate: **obligation (matrix row) → Rail control → profile → evidence**.
|
||||
|
||||
**Not legal advice.** Matrix obligation text must be counsel-approved per jurisdiction.
|
||||
|
||||
---
|
||||
|
||||
## Rail controls → jurisdiction artifacts (starter mapping)
|
||||
|
||||
| Control ID | Rail / ops intent | Example jurisdiction matrix rows | Policy profile(s) | Evidence / manifest fields |
|
||||
|------------|-------------------|----------------------------------|-------------------|----------------------------|
|
||||
| C1 | Mint path restricted to SettlementRouter | ID-RAIL-001 | `server_funds_treasury_v1` | `settlementOrChainRef` |
|
||||
| C2 | Owner mint revoked / GRU pattern | ID-RAIL-001 | `server_funds_treasury_v1`, `institutional_custody_skr_v1` | On-chain config + evidence package |
|
||||
| C3–C6 | EIP-712, replay, quorum, signers | ID-RAIL-001 | `server_funds_treasury_v1` | MintAuth / messageId |
|
||||
| C7 | Signer allowlist / revocation | ID-OMNL-001, ID-SIDECAR-001 | all production profiles | Ops attestations |
|
||||
| C8 | Deterministic accountingRef | ID-OMNL-001 | `server_funds_treasury_v1` | `accountingRef` |
|
||||
| C9 | Evidence bundle hashed (isoHash) | ID-ISO-001, ID-SKR-001 | all | `custodyOrSourceEvidence`, ISO package |
|
||||
| C10 | messageId / accountingRef / mint 1:1 | ID-RAIL-001 | `server_funds_treasury_v1` | Evidence package closure |
|
||||
| C11–C15 | Router safety, caps, pause, corridor, suspension | ID-RAIL-001, ID-SIDECAR-001 | `server_funds_treasury_v1` | Rail + sidecar monitoring |
|
||||
| C16 | Validator segregation | ID-RAIL-001 (infra) | `infra_capacity_ops_v1` | Ops runbooks |
|
||||
| C17 | Good funds and finality | ID-OMNL-001, ID-SIDECAR-001 | `server_funds_treasury_v1` | Rulebook alignment + ledger |
|
||||
| C18 | Documentation versioning | (program-wide) | registry in [policy-profiles.json](../../config/universal-resource-activation/policy-profiles.json) | Doc control tables |
|
||||
|
||||
**Indonesia matrix row ids** reference [ID-INDONESIA/banking_v1.md](../04-configuration/compliance-matrices/ID-INDONESIA/banking_v1.md).
|
||||
|
||||
**US-DELAWARE-CORP-STUB** is a draft second-jurisdiction exercise only ([README](../04-configuration/compliance-matrices/US-DELAWARE-CORP-STUB/README.md)); do not use its row ids in production traceability until counsel replaces the stub.
|
||||
|
||||
---
|
||||
|
||||
## Audit checklist cross-reference
|
||||
|
||||
When updating [DBIS_RAIL_AUDIT_READINESS_CHECKLIST_V1.md](DBIS_RAIL_AUDIT_READINESS_CHECKLIST_V1.md), add **jurisdiction matrix id** and **policyProfileId** to each section’s evidence appendix where a jurisdiction-specific obligation applies.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [DBIS_RAIL_CONTROL_MAPPING_V1.md](DBIS_RAIL_CONTROL_MAPPING_V1.md)
|
||||
- [INSTITUTION_ONBOARDING_CHARTER.md](../04-configuration/compliance-matrices/INSTITUTION_ONBOARDING_CHARTER.md)
|
||||
- [URA_PILOT_CLOSURE_RUNBOOK.md](../04-configuration/universal-resource-activation/URA_PILOT_CLOSURE_RUNBOOK.md)
|
||||
33
docs/dbis-rail/DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md
Normal file
33
docs/dbis-rail/DBIS_RAIL_SETTLEMENT_EVENT_SOURCES.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# DBIS Rail — settlement event sources for URA `settlementOrChainRef`
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Inventory of where **MintAuth / settlement** identifiers originate so an indexer or batch job can populate [`manifest.json`](../../config/universal-resource-activation/manifest.json) evidence fields (`settlementOrChainRef`).
|
||||
|
||||
**Not exhaustive** — align field names with [`DBIS_RAIL_TECHNICAL_SPEC_V1.md`](DBIS_RAIL_TECHNICAL_SPEC_V1.md) and your deployed contracts in `smom-dbis-138`.
|
||||
|
||||
## 1. On-chain (EVM)
|
||||
|
||||
| Source | What to capture | Notes |
|
||||
|--------|-----------------|--------|
|
||||
| **Settlement / router events** | `messageId`, optional `accountingRef` echo | Subscribe via WebSocket or `eth_getLogs` with tuned filters. |
|
||||
| **Transaction receipt** | `tx.hash`, `blockNumber`, `chainId` | Compose ref: `messageId=…;tx=…;chain=…` (see [`build-settlement-fragment.mjs`](../../scripts/ura/manifest-writer/build-settlement-fragment.mjs)). |
|
||||
| **Indexed subgraph** | Same fields | If you run Graph Node / Ponder, expose a stable query for “last settlement for resource X”. |
|
||||
|
||||
## 2. Off-chain / ISO path
|
||||
|
||||
| Source | What to capture |
|
||||
|--------|-----------------|
|
||||
| ISO-20022 gateway / `dbis_core` | Business message id, end-to-end id, or gateway correlation id stored when mint authorized. |
|
||||
|
||||
Store the chosen id in `settlementOrChainRef` and document the format in the evidence package `explanation` until a single canonical encoding is enforced.
|
||||
|
||||
## 3. Wire-up checklist
|
||||
|
||||
1. Pick authoritative source per environment (Chain 138 vs testnet).
|
||||
2. Implement listener → call writer (`build-settlement-fragment`) → merge → validate → publish.
|
||||
3. Add alert if no settlement event within SLA for an open `reconciliationStatus`.
|
||||
|
||||
## Related
|
||||
|
||||
- [`URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md`](../04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
- [`DBIS_RAIL_JURISDICTION_TRACEABILITY.md`](DBIS_RAIL_JURISDICTION_TRACEABILITY.md)
|
||||
@@ -106,7 +106,13 @@ Add Forge or Hardhat tests for facet upgrade and storage consistency when the sp
|
||||
|
||||
---
|
||||
|
||||
## 7. Related documents
|
||||
## 7. Standalone URA policy anchor (pre–full M00)
|
||||
|
||||
Before the full M00 spine is live, you can deploy **`PolicyProfileRegistry`** in `smom-dbis-138` to anchor `policyProfileId` content hashes on-chain (`pnpm ura:profile-hash` in the proxmox repo). See [GRU_REGISTRY_WIRING_CHECKLIST.md](GRU_REGISTRY_WIRING_CHECKLIST.md) §6 and `contracts/universal-resource/PolicyProfileRegistry.sol`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Related documents
|
||||
|
||||
- [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](../04-configuration/GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) — §1–§8, default governance level, event signatures appendix.
|
||||
- [GRU_M00_DIAMOND_FACET_MAP.md](../04-configuration/GRU_M00_DIAMOND_FACET_MAP.md) — Facet map, governance levels 0–5.
|
||||
@@ -114,3 +120,4 @@ Add Forge or Hardhat tests for facet upgrade and storage consistency when the sp
|
||||
- [MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT.md](MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT.md) — CREATE2 factory and salts.
|
||||
- [CONTRACT_DEPLOYMENT_RUNBOOK.md](../03-deployment/CONTRACT_DEPLOYMENT_RUNBOOK.md) — General deployment and env.
|
||||
- [gru-docs/contracts/README.md](../gru-docs/contracts/README.md) — GRC-2535 Diamond (Option B migration source).
|
||||
- [GRU_REGISTRY_WIRING_CHECKLIST.md](GRU_REGISTRY_WIRING_CHECKLIST.md) — URA + GRU wiring checklist (includes PolicyProfileRegistry).
|
||||
|
||||
57
docs/runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md
Normal file
57
docs/runbooks/GRU_REGISTRY_WIRING_CHECKLIST.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# GRU / on-chain registry wiring checklist
|
||||
|
||||
**Last updated:** 2026-04-25
|
||||
**Purpose:** Operationalize URA + GRU alignment: diamond strategy, storage, facets, deployment, governance, **standalone PolicyProfileRegistry** (in `smom-dbis-138`), and optional hardening.
|
||||
|
||||
**Specs:** [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](../04-configuration/GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) · [GRU_M00_DIAMOND_FACET_MAP.md](../04-configuration/GRU_M00_DIAMOND_FACET_MAP.md) · [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](../04-configuration/GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md) · [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md)
|
||||
|
||||
## 1. Strategy (gru-01)
|
||||
|
||||
- [ ] Decide **Option A** (new M00 diamond) vs **Option B** (migrate GRC-2535) per deployment runbook §3–4.
|
||||
- [ ] Record decision + approvers in deployment ticket.
|
||||
|
||||
## 2. Storage and governance model (gru-02)
|
||||
|
||||
- [ ] Finalize GRUStorage namespaces (no collision with GRC if migrating).
|
||||
- [ ] Document governance level defaults per env (dev 0, prod ≥2).
|
||||
|
||||
## 3. Minimum ship facets (gru-03)
|
||||
|
||||
- [ ] PolicyRouter + Compliance/Accounting gate stubs (or full implementations).
|
||||
- [ ] StandardsRegistryFacet + GovernanceLevelFacet.
|
||||
- [ ] TokenFactory / AssetRegistry path per spec.
|
||||
|
||||
## 4. Universal asset alignment (gru-04)
|
||||
|
||||
- [ ] Map `UniversalAssetRegistry` / token lists to future `assetId` — see [UNIVERSAL_RESOURCE_ONTOLOGY.md](../04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_ONTOLOGY.md) §Mapping to GRU M00.
|
||||
|
||||
## 5. Deploy, verify, ops (gru-05 / gru-06)
|
||||
|
||||
- [ ] Follow [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) §6 verification table.
|
||||
- [ ] Multisig / Timelock on `diamondCut` and policy changes.
|
||||
- [ ] Pause drill documented and executed once per quarter.
|
||||
|
||||
## 6. Policy profile on-chain anchor (gru-07) — **standalone contract (shipped)**
|
||||
|
||||
| Step | Command / action |
|
||||
|------|------------------|
|
||||
| Unit test | `cd smom-dbis-138 && FORGE_SCOPE=universal-resource bash scripts/forge/scope.sh test --match-contract PolicyProfileRegistryTest` |
|
||||
| Content hash | `pnpm ura:profile-hash <policyProfileId>` (proxmox repo root) |
|
||||
| Deploy | `forge script script/universal-resource/DeployPolicyProfileRegistry.s.sol:DeployPolicyProfileRegistry --rpc-url $RPC_URL_138 --broadcast` (set `PRIVATE_KEY`, optional `POLICY_PROFILE_REGISTRY_ADMIN`) |
|
||||
| Publish | Call `publishProfile(policyProfileId, contentHash, version, effectiveFrom)` with `PUBLISHER_ROLE` |
|
||||
|
||||
Contract: [`smom-dbis-138/contracts/universal-resource/PolicyProfileRegistry.sol`](../../smom-dbis-138/contracts/universal-resource/PolicyProfileRegistry.sol)
|
||||
|
||||
## 7. Optional (gru-opt-a)
|
||||
|
||||
- [ ] Oracle or attestation bridge for off-chain evidence hashes.
|
||||
- [ ] Cross-chain registry mirror addresses.
|
||||
|
||||
## 8. Doc handoff (gru-08)
|
||||
|
||||
- [ ] Record deployed `PolicyProfileRegistry` address in [CONTRACT_ADDRESSES_REFERENCE](../11-references/CONTRACT_ADDRESSES_REFERENCE.md) when live.
|
||||
- [ ] Link from [UNIVERSAL_RESOURCE_WIRING.md](../04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) §5.
|
||||
|
||||
## Related
|
||||
|
||||
- [`URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md`](../04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
11
package.json
11
package.json
@@ -25,6 +25,17 @@
|
||||
"test:basic": "cd mcp-proxmox && node test-basic-tools.js",
|
||||
"test:workflows": "cd mcp-proxmox && node test-workflows.js",
|
||||
"verify:ws-chain138": "node scripts/verify-ws-rpc-chain138.mjs",
|
||||
"ura:validate": "node scripts/validate/validate-universal-resource-activation.mjs",
|
||||
"ura:validate-profiles": "node scripts/validate/validate-ura-policy-profiles.mjs",
|
||||
"ura:validate-closure": "node scripts/ura/validate-manifest-closure.mjs",
|
||||
"ura:validate-closure:strict": "node scripts/ura/validate-manifest-closure.mjs --strict",
|
||||
"ura:merge-manifest": "node scripts/ura/merge-manifest-fragments.mjs",
|
||||
"ura:validate-ledger-mapping": "node scripts/validate/validate-omnl-ledger-mapping.mjs",
|
||||
"ura:writer:ledger": "node scripts/ura/manifest-writer/build-ledger-fragment.mjs",
|
||||
"ura:writer:settlement": "node scripts/ura/manifest-writer/build-settlement-fragment.mjs",
|
||||
"ura:profile-hash": "node scripts/ura/policy-profiles-content-hash.mjs",
|
||||
"ura:keccak": "node scripts/ura/keccak-resource-ids.mjs",
|
||||
"ura:smoke": "bash scripts/verify/smoke-universal-resource-activation.sh",
|
||||
"mission-control:dev": "pnpm --filter mission-control dev",
|
||||
"mission-control:build": "pnpm --filter mission-control build",
|
||||
"mission-control:start": "pnpm --filter mission-control start",
|
||||
|
||||
@@ -32,8 +32,15 @@ PHOENIX_PARTNER_KEYS=
|
||||
|
||||
# Optional: override path for GET /api/v1/public-sector/programs (else bundled copy, repo config/, or ../config/)
|
||||
PUBLIC_SECTOR_MANIFEST_PATH=
|
||||
# Optional: URA manifest for GET /api/v1/universal-resource-activation/manifest
|
||||
UNIVERSAL_RESOURCE_MANIFEST_PATH=
|
||||
# Optional: URA policy profile registry for GET /api/v1/universal-resource-activation/policy-profiles
|
||||
#UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH=
|
||||
# Optional: proxmox repo root on host (manifest = $PHOENIX_REPO_ROOT/config/public-sector-program-manifest.json)
|
||||
PHOENIX_REPO_ROOT=/home/intlc/projects/proxmox
|
||||
# Optional: server-funds-sidecar base URL for GET /api/v1/universal-resource-activation/server-funds-sidecar-probe
|
||||
#SERVER_FUNDS_SIDECAR_URL=http://192.168.x.x:8080
|
||||
#SERVER_FUNDS_SIDECAR_HEALTH_PATH=/actuator/health
|
||||
# Gitea "cloudflare-sync" deploy target: allow scripts/deployment/gitea-cloudflare-sync.sh to call Cloudflare (1/true)
|
||||
#PHOENIX_CLOUDFLARE_SYNC=0
|
||||
# Optional zone for that sync: CLOUDFLARE_GITEA_SYNC_ZONE=d-bis.org
|
||||
|
||||
@@ -19,9 +19,11 @@ Gitea webhook receiver and deploy endpoint for Gitea → Phoenix / Proxmox deplo
|
||||
| GET | /api/v1/health/summary | Aggregated health for Portal |
|
||||
| GET | /api/v1/public-sector/programs | Public-sector / eIDAS program manifest (JSON; **no API key**) |
|
||||
| GET | /api/v1/universal-resource-activation/manifest | Universal resource activation store: resources, evidence, profile refs (JSON; **no API key**) — see [docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md](../docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) |
|
||||
| GET | /api/v1/universal-resource-activation/policy-profiles | URA policy profile registry: `policy-profiles.json` (JSON; **no API key**) |
|
||||
| GET | /api/v1/universal-resource-activation/server-funds-sidecar-probe | Optional: proxy health check to `SERVER_FUNDS_SIDECAR_URL` (**no API key**; 503 if URL unset) |
|
||||
| GET | /health | Health check |
|
||||
|
||||
All `/api/v1/*` routes except **`GET /api/v1/public-sector/programs`** and **`GET /api/v1/universal-resource-activation/manifest`** accept optional partner API key when `PHOENIX_PARTNER_KEYS` is set (`X-API-Key` or `Authorization: Bearer <key>`).
|
||||
All `/api/v1/*` routes except **`GET /api/v1/public-sector/programs`**, **`GET /api/v1/universal-resource-activation/manifest`**, **`GET /api/v1/universal-resource-activation/policy-profiles`**, and **`GET /api/v1/universal-resource-activation/server-funds-sidecar-probe`** accept optional partner API key when `PHOENIX_PARTNER_KEYS` is set (`X-API-Key` or `Authorization: Bearer <key>`). The same public path list is defined as `PUBLIC_V1_NO_PARTNER_KEY_PATHS` in [`server.js`](server.js) (keep in sync when adding a new unauthenticated read).
|
||||
|
||||
## Environment
|
||||
|
||||
@@ -48,10 +50,13 @@ Copy `.env.example` to `.env` and set `GITEA_TOKEN` (and optionally `PHOENIX_DEP
|
||||
| PHOENIX_PARTNER_KEYS | | Comma-separated API keys for /api/v1/* (optional) |
|
||||
| PUBLIC_SECTOR_MANIFEST_PATH | | Override JSON path for `/api/v1/public-sector/programs` |
|
||||
| UNIVERSAL_RESOURCE_MANIFEST_PATH | | Override JSON path for `/api/v1/universal-resource-activation/manifest` (default: `config/universal-resource-activation/manifest.json` under `PHOENIX_REPO_ROOT` or `../config/…`) |
|
||||
| UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH | | Override JSON path for `/api/v1/universal-resource-activation/policy-profiles` (default: `config/universal-resource-activation/policy-profiles.json` under repo root) |
|
||||
| SERVER_FUNDS_SIDECAR_URL | | Base URL for `/api/v1/universal-resource-activation/server-funds-sidecar-probe` (e.g. `http://<host>:8080`); if unset, probe returns 503 with hint |
|
||||
| SERVER_FUNDS_SIDECAR_HEALTH_PATH | | Optional first path to try (e.g. `/actuator/health`); also tries `/actuator/health`, `/health`, `/api/health` |
|
||||
| PHOENIX_REPO_ROOT | | Proxmox repo root; loads `config/public-sector-program-manifest.json` if present |
|
||||
| DEPLOY_TARGETS_PATH | | Override deploy target file; default is `phoenix-deploy-api/deploy-targets.json` |
|
||||
|
||||
**URA smoke (proxmox repo):** `bash scripts/verify/smoke-universal-resource-activation.sh` validates the manifest with JSON Schema; add `--http` and set `PHOENIX_BASE_URL` (e.g. `http://127.0.0.1:4001`) to assert this API returns 200. See [UNIVERSAL_RESOURCE_WIRING.md](../docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) §2.1.
|
||||
**URA smoke (proxmox repo):** `bash scripts/verify/smoke-universal-resource-activation.sh` validates the manifest with JSON Schema; add `--http` and set `PHOENIX_BASE_URL` to also GET `/api/v1/universal-resource-activation/manifest`, `/api/v1/universal-resource-activation/policy-profiles`, and `/api/v1/universal-resource-activation/server-funds-sidecar-probe` (503 + `configured: false` is OK if `SERVER_FUNDS_SIDECAR_URL` is unset). See [UNIVERSAL_RESOURCE_WIRING.md](../docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md) §2.1.
|
||||
|
||||
**Program manifest:** From a full repo checkout, the file is `config/public-sector-program-manifest.json`. `scripts/install-systemd.sh` copies it next to `server.js` on `/opt/phoenix-deploy-api` so the endpoint works without a full tree.
|
||||
|
||||
|
||||
@@ -123,6 +123,50 @@ paths:
|
||||
'500': { description: Invalid JSON or read error }
|
||||
'503': { description: Manifest file not found }
|
||||
|
||||
/api/v1/universal-resource-activation/policy-profiles:
|
||||
get:
|
||||
tags: [UniversalResource]
|
||||
summary: URA policy profile registry (JSON)
|
||||
description: |
|
||||
Serves `config/universal-resource-activation/policy-profiles.json` (machine-readable profiles + GRU levels).
|
||||
Override with `UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH`. No API key required. Returns 503 if the file is missing.
|
||||
responses:
|
||||
'200':
|
||||
description: Policy profile registry JSON
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
schemaVersion: { type: string }
|
||||
updatedAt: { type: string }
|
||||
profiles: { type: array, items: { type: object } }
|
||||
'500': { description: Invalid JSON or read error }
|
||||
'503': { description: Registry file not found }
|
||||
|
||||
/api/v1/universal-resource-activation/server-funds-sidecar-probe:
|
||||
get:
|
||||
tags: [UniversalResource]
|
||||
summary: Optional health probe to server-funds-sidecar
|
||||
description: |
|
||||
If `SERVER_FUNDS_SIDECAR_URL` is set, tries `/actuator/health`, `/health`, `/api/health` (or `SERVER_FUNDS_SIDECAR_HEALTH_PATH`).
|
||||
No API key. Returns 503 with hint when the env var is unset; 200 when a path returns 2xx with JSON or body.
|
||||
responses:
|
||||
'200':
|
||||
description: Sidecar responded 2xx on a candidate path
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
configured: { type: boolean }
|
||||
baseUrl: { type: string }
|
||||
healthPath: { type: string }
|
||||
status: { type: integer }
|
||||
'500': { description: Server error when handling the probe }
|
||||
'502': { description: All candidate paths failed or non-2xx }
|
||||
'503': { description: SERVER_FUNDS_SIDECAR_URL not set }
|
||||
|
||||
/api/v1/infra/nodes:
|
||||
get:
|
||||
tags: [Infra]
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
* GET /api/v1/ve/vms/:node/:vmid/status — VM/CT status
|
||||
* GET /api/v1/public-sector/programs — Public-sector / eIDAS program manifest (JSON)
|
||||
* GET /api/v1/universal-resource-activation/manifest — Universal resource activation manifest (JSON; no secret)
|
||||
* GET /api/v1/universal-resource-activation/policy-profiles — URA policy profile registry JSON (no secret)
|
||||
* GET /api/v1/universal-resource-activation/server-funds-sidecar-probe — Optional health proxy to server-funds-sidecar (no secret; 503 if URL unset)
|
||||
* GET /health — Health check
|
||||
*
|
||||
* Env: PORT, GITEA_URL, GITEA_TOKEN, PHOENIX_DEPLOY_SECRET
|
||||
@@ -47,6 +49,18 @@ const PROXMOX_TOKEN_NAME = process.env.PROXMOX_TOKEN_NAME || '';
|
||||
const PROXMOX_TOKEN_VALUE = process.env.PROXMOX_TOKEN_VALUE || '';
|
||||
const hasProxmox = PROXMOX_HOST && PROXMOX_TOKEN_NAME && PROXMOX_TOKEN_VALUE;
|
||||
const VE_LIFECYCLE_ENABLED = process.env.PHOENIX_VE_LIFECYCLE_ENABLED === '1' || process.env.PHOENIX_VE_LIFECYCLE_ENABLED === 'true';
|
||||
const SERVER_FUNDS_SIDECAR_URL = (process.env.SERVER_FUNDS_SIDECAR_URL || '').trim();
|
||||
|
||||
/**
|
||||
* GET paths that skip partner API key — each route must be registered *before* `app.use('/api/v1', partnerKeyMiddleware)`.
|
||||
* Keep in sync with docs (AGENTS, phoenix-deploy-api README, OpenAPI) when adding a new public /api/v1 read.
|
||||
*/
|
||||
const PUBLIC_V1_NO_PARTNER_KEY_PATHS = [
|
||||
'/api/v1/public-sector/programs',
|
||||
'/api/v1/universal-resource-activation/manifest',
|
||||
'/api/v1/universal-resource-activation/policy-profiles',
|
||||
'/api/v1/universal-resource-activation/server-funds-sidecar-probe',
|
||||
];
|
||||
|
||||
const PROMETHEUS_URL = (process.env.PROMETHEUS_URL || 'http://localhost:9090').replace(/\/$/, '');
|
||||
const PHOENIX_WEBHOOK_URL = process.env.PHOENIX_WEBHOOK_URL || '';
|
||||
@@ -101,6 +115,23 @@ function resolveUniversalResourceManifestPath() {
|
||||
return path.join(__dirname, '..', 'config', 'universal-resource-activation', 'manifest.json');
|
||||
}
|
||||
|
||||
/**
|
||||
* URA policy profile registry (policy-profiles.json).
|
||||
* 1) UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH
|
||||
* 2) PHOENIX_REPO_ROOT / PROXMOX_REPO_PATH + config/universal-resource-activation/policy-profiles.json
|
||||
* 3) ../config/...
|
||||
*/
|
||||
function resolveUniversalResourcePolicyProfilesPath() {
|
||||
const override = (process.env.UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH || '').trim();
|
||||
if (override && existsSync(override)) return override;
|
||||
const repoRoot = (process.env.PHOENIX_REPO_ROOT || process.env.PROXMOX_REPO_PATH || '').trim().replace(/\/$/, '');
|
||||
if (repoRoot) {
|
||||
const fromRepo = path.join(repoRoot, 'config', 'universal-resource-activation', 'policy-profiles.json');
|
||||
if (existsSync(fromRepo)) return fromRepo;
|
||||
}
|
||||
return path.join(__dirname, '..', 'config', 'universal-resource-activation', 'policy-profiles.json');
|
||||
}
|
||||
|
||||
function resolveDeployTargetsPath() {
|
||||
const override = (process.env.DEPLOY_TARGETS_PATH || '').trim();
|
||||
if (override && existsSync(override)) return override;
|
||||
@@ -711,6 +742,89 @@ app.get('/api/v1/universal-resource-activation/manifest', (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/v1/universal-resource-activation/policy-profiles — URA policy profile registry (JSON; no secret).
|
||||
*/
|
||||
app.get('/api/v1/universal-resource-activation/policy-profiles', (req, res) => {
|
||||
const registryPath = resolveUniversalResourcePolicyProfilesPath();
|
||||
try {
|
||||
if (!existsSync(registryPath)) {
|
||||
return res.status(503).json({
|
||||
error: 'Policy profile registry not found',
|
||||
path: registryPath,
|
||||
hint: 'Set UNIVERSAL_RESOURCE_POLICY_PROFILES_PATH or deploy with config/universal-resource-activation/policy-profiles.json under PHOENIX_REPO_ROOT',
|
||||
});
|
||||
}
|
||||
const raw = readFileSync(registryPath, 'utf8');
|
||||
const data = JSON.parse(raw);
|
||||
res.type('application/json').json(data);
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message, path: registryPath });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/v1/universal-resource-activation/server-funds-sidecar-probe — forward probe to server-funds-sidecar when SERVER_FUNDS_SIDECAR_URL is set.
|
||||
* No API key. Returns 503 with hint when unset (operator LAN / VM path per pilot plan).
|
||||
*/
|
||||
app.get('/api/v1/universal-resource-activation/server-funds-sidecar-probe', async (req, res) => {
|
||||
if (!SERVER_FUNDS_SIDECAR_URL) {
|
||||
return res.status(503).json({
|
||||
configured: false,
|
||||
error: 'SERVER_FUNDS_SIDECAR_URL not set',
|
||||
hint: 'Set to base URL (e.g. http://<rtgs-funds-host>:8080) to probe /actuator/health or /health. See UNIVERSAL_RESOURCE_WIRING.md and UNIVERSAL_RESOURCE_SERVER_FUNDS_LANE.md.',
|
||||
});
|
||||
}
|
||||
const base = SERVER_FUNDS_SIDECAR_URL.replace(/\/$/, '');
|
||||
const extra = (process.env.SERVER_FUNDS_SIDECAR_HEALTH_PATH || '').trim();
|
||||
const candidates = [];
|
||||
if (extra) candidates.push(extra.startsWith('/') ? extra : `/${extra}`);
|
||||
for (const p of ['/actuator/health', '/health', '/api/health']) {
|
||||
if (!candidates.includes(p)) candidates.push(p);
|
||||
}
|
||||
const attempts = [];
|
||||
for (const p of candidates) {
|
||||
if (!p.startsWith('/')) continue;
|
||||
const url = `${base}${p}`;
|
||||
const controller = new AbortController();
|
||||
const t = setTimeout(() => controller.abort(), 8000);
|
||||
try {
|
||||
const r = await fetch(url, {
|
||||
signal: controller.signal,
|
||||
headers: { Accept: 'application/json, text/plain, */*' },
|
||||
});
|
||||
const text = await r.text();
|
||||
let body;
|
||||
try {
|
||||
body = JSON.parse(text);
|
||||
} catch {
|
||||
body = { raw: text.length > 4000 ? `${text.slice(0, 4000)}…` : text };
|
||||
}
|
||||
if (r.ok) {
|
||||
clearTimeout(t);
|
||||
return res.json({
|
||||
configured: true,
|
||||
baseUrl: base,
|
||||
healthPath: p,
|
||||
status: r.status,
|
||||
body,
|
||||
});
|
||||
}
|
||||
attempts.push({ path: p, status: r.status });
|
||||
} catch (err) {
|
||||
attempts.push({ path: p, error: err.message || String(err) });
|
||||
} finally {
|
||||
clearTimeout(t);
|
||||
}
|
||||
}
|
||||
return res.status(502).json({
|
||||
configured: true,
|
||||
baseUrl: base,
|
||||
error: 'All server-funds-sidecar health paths failed or returned non-2xx',
|
||||
attempts,
|
||||
});
|
||||
});
|
||||
|
||||
app.use('/api/v1', partnerKeyMiddleware);
|
||||
|
||||
/**
|
||||
@@ -937,12 +1051,17 @@ app.listen(PORT, () => {
|
||||
if (PHOENIX_WEBHOOK_URL) console.log('Outbound webhook enabled:', PHOENIX_WEBHOOK_URL);
|
||||
if (WEBHOOK_DEPLOY_ENABLED) console.log('Inbound webhook deploy execution enabled');
|
||||
if (PARTNER_KEYS.length > 0) {
|
||||
console.log('Partner API key auth enabled for /api/v1/* (except GET /api/v1/public-sector/programs and GET /api/v1/universal-resource-activation/manifest)');
|
||||
console.log('Partner API key auth: /api/v1/* except', PUBLIC_V1_NO_PARTNER_KEY_PATHS.join(', '));
|
||||
}
|
||||
const mpath = resolvePublicSectorManifestPath();
|
||||
const urapath = resolveUniversalResourceManifestPath();
|
||||
const uraprof = resolveUniversalResourcePolicyProfilesPath();
|
||||
const dpath = resolveDeployTargetsPath();
|
||||
console.log(`Public-sector manifest: ${mpath} (${existsSync(mpath) ? 'ok' : 'missing'})`);
|
||||
console.log(`URA manifest: ${urapath} (${existsSync(urapath) ? 'ok' : 'missing'})`);
|
||||
console.log(`URA policy-profiles: ${uraprof} (${existsSync(uraprof) ? 'ok' : 'missing'})`);
|
||||
if (SERVER_FUNDS_SIDECAR_URL) {
|
||||
console.log('Server-funds sidecar probe target:', SERVER_FUNDS_SIDECAR_URL);
|
||||
}
|
||||
console.log(`Deploy targets: ${dpath} (${existsSync(dpath) ? 'ok' : 'missing'})`);
|
||||
});
|
||||
|
||||
@@ -204,7 +204,7 @@ CT 2301 (besu-rpc-private-1) may fail to start with `lxc.hook.pre-start` due to
|
||||
|
||||
- **Daily/weekly checks:** `./scripts/maintenance/daily-weekly-checks.sh [daily|weekly|all]` — explorer sync (135), RPC health (136), config API (137). **Cron:** `./scripts/maintenance/schedule-daily-weekly-cron.sh [--install|--show]` (daily 08:00, weekly Sun 09:00). See [OPERATIONAL_RUNBOOKS.md](../docs/03-deployment/OPERATIONAL_RUNBOOKS.md) § Maintenance.
|
||||
- **Start firefly-ali-1 (6201):** `./scripts/maintenance/start-firefly-6201.sh [--dry-run] [--host HOST]` — start CT 6201 on r630-02 when needed (optional ongoing).
|
||||
- **Config validation (pre-deploy):** `./scripts/validation/validate-config-files.sh` — set `VALIDATE_REQUIRED_FILES` for required paths. **CI / all validation:** `./scripts/verify/run-all-validation.sh [--skip-genesis] [--json-out reports/status/run-all-validation-latest.json]` — dependencies, config files, **cW\* mesh matrix** (merge of `cross-chain-pmm-lps/config/deployment-status.json` and `reports/extraction/promod-uniswap-v2-live-pair-discovery-latest.json` when that file exists; no RPC), optional genesis (no LAN/SSH). **Matrix only:** `./scripts/verify/build-cw-mesh-deployment-matrix.sh` — stdout markdown; `--json-out reports/status/cw-mesh-deployment-matrix-latest.json` for machine-readable rows. **URA (universal resource activation) smoke:** `./scripts/verify/smoke-universal-resource-activation.sh` (JSON Schema only) or the same with `--http` and optional `PHOENIX_BASE_URL` to assert Phoenix `GET /api/v1/universal-resource-activation/manifest`; see `docs/04-configuration/universal-resource-activation/UNIVERSAL_RESOURCE_WIRING.md` §2.1.
|
||||
- **Config validation (pre-deploy):** `./scripts/validation/validate-config-files.sh` — set `VALIDATE_REQUIRED_FILES` for required paths. **CI / all validation:** `./scripts/verify/run-all-validation.sh [--skip-genesis] [--json-out reports/status/run-all-validation-latest.json]` — dependencies, config files, **cW\* mesh matrix** (merge of `cross-chain-pmm-lps/config/deployment-status.json` and `reports/extraction/promod-uniswap-v2-live-pair-discovery-latest.json` when that file exists; no RPC), optional genesis (no LAN/SSH). **Matrix only:** `./scripts/verify/build-cw-mesh-deployment-matrix.sh` — stdout markdown; `--json-out reports/status/cw-mesh-deployment-matrix-latest.json` for machine-readable rows. **URA (universal resource activation):** **`pnpm ura:validate`**, **`pnpm ura:validate-profiles`**, **`pnpm ura:merge-manifest`**, **`pnpm ura:validate-ledger-mapping`**, **`pnpm ura:writer:ledger`**, **`pnpm ura:writer:settlement`**, **`pnpm ura:profile-hash`**, **`pnpm ura:validate-closure`** / **`pnpm ura:validate-closure:strict`**, **`pnpm ura:keccak`**, **`pnpm ura:smoke`**. Optional **`URA_STRICT_CLOSURE=1`**. Tracker: `docs/04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md`. See `UNIVERSAL_RESOURCE_WIRING.md` §2.1 and §5; multi-jurisdiction: `docs/04-configuration/compliance-matrices/README.md`.
|
||||
- **Wrapper summaries:** `./scripts/run-completable-tasks-from-anywhere.sh --json-out reports/status/run-completable-tasks-latest.json`, `./scripts/run-e2e-flow-tasks-full-parallel.sh --json-out reports/status/run-e2e-flow-tasks-latest.json`, `./scripts/deployment/run-all-next-steps-chain138.sh --json-out reports/status/run-all-next-steps-chain138-latest.json`, and `./scripts/run-all-operator-tasks-from-lan.sh --json-out reports/status/run-all-operator-tasks-latest.json` produce machine-readable step summaries that match the terminal progress output.
|
||||
|
||||
### 13. Phase 2, 3 & 4 Deployment Scripts
|
||||
|
||||
38
scripts/ura/keccak-resource-ids.mjs
Executable file
38
scripts/ura/keccak-resource-ids.mjs
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Emit keccak256(utf8(resourceId)) for each row in the URA manifest.
|
||||
* Use when anchoring resourceId in on-chain / GRU registries (operator step; not automatic mirroring).
|
||||
*
|
||||
* Usage: from repo root — node scripts/ura/keccak-resource-ids.mjs
|
||||
* Requires: root devDependency `ethers` (v6).
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { keccak256, toUtf8Bytes } from 'ethers';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.join(__dirname, '../..');
|
||||
const manifestPath = path.join(projectRoot, 'config', 'universal-resource-activation', 'manifest.json');
|
||||
|
||||
if (!existsSync(manifestPath)) {
|
||||
console.error(`[keccak-ura] Missing ${manifestPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const m = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
||||
const resources = m.resources || [];
|
||||
|
||||
console.log(
|
||||
'# keccak256(utf8(resourceId)) for universal-resource-activation resources\n# Use for optional on-chain / GRU registry rows; keep manifest as canonical off-chain store.\n',
|
||||
);
|
||||
|
||||
for (const r of resources) {
|
||||
const id = r.resourceId;
|
||||
if (typeof id !== 'string' || !id) continue;
|
||||
const h = keccak256(toUtf8Bytes(id));
|
||||
console.log(id);
|
||||
console.log(` ${h}`);
|
||||
console.log('');
|
||||
}
|
||||
console.log(`[keccak-ura] ${resources.length} resource(s)`);
|
||||
134
scripts/ura/lib/validate-ura-manifest.mjs
Normal file
134
scripts/ura/lib/validate-ura-manifest.mjs
Normal file
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Shared URA manifest validation (schemas + cross-checks).
|
||||
* Used by validate-universal-resource-activation.mjs and merge-manifest-fragments.mjs.
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Ajv from 'ajv';
|
||||
import addFormats from 'ajv-formats';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export function getProjectRoot() {
|
||||
return path.resolve(path.join(__dirname, '..', '..', '..'));
|
||||
}
|
||||
|
||||
export function getDefaultManifestPath(projectRoot = getProjectRoot()) {
|
||||
return path.join(projectRoot, 'config', 'universal-resource-activation', 'manifest.json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {{ validateManifest: import('ajv').ValidateFunction, validateResource: import('ajv').ValidateFunction, validateEvidence: import('ajv').ValidateFunction, ajv: import('ajv').default }}
|
||||
*/
|
||||
export function loadUraManifestValidators(projectRoot = getProjectRoot()) {
|
||||
const manifestSchemaPath = path.join(projectRoot, 'config', 'universal-resource-activation.manifest.v1.schema.json');
|
||||
const resourceSchemaPath = path.join(projectRoot, 'config', 'universal-resource-activation.resource.v1.schema.json');
|
||||
const evidenceSchemaPath = path.join(projectRoot, 'config', 'universal-resource-activation.evidence-package.v1.schema.json');
|
||||
|
||||
const ajv = new Ajv({
|
||||
allErrors: true,
|
||||
strict: false,
|
||||
validateSchema: false,
|
||||
});
|
||||
addFormats(ajv);
|
||||
|
||||
const manifestSchema = JSON.parse(readFileSync(manifestSchemaPath, 'utf8'));
|
||||
const resourceSchema = JSON.parse(readFileSync(resourceSchemaPath, 'utf8'));
|
||||
const evidenceSchema = JSON.parse(readFileSync(evidenceSchemaPath, 'utf8'));
|
||||
|
||||
return {
|
||||
validateManifest: ajv.compile(manifestSchema),
|
||||
validateResource: ajv.compile(resourceSchema),
|
||||
validateEvidence: ajv.compile(evidenceSchema),
|
||||
ajv,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {unknown} data
|
||||
* @param {{ validateManifest: import('ajv').ValidateFunction, validateResource: import('ajv').ValidateFunction, validateEvidence: import('ajv').ValidateFunction }} validators
|
||||
* @returns {string[]} empty if valid
|
||||
*/
|
||||
export function validateUraManifestData(data, validators) {
|
||||
const errors = [];
|
||||
const { validateManifest, validateResource, validateEvidence, ajv } = validators;
|
||||
|
||||
if (!validateManifest(data)) {
|
||||
return [`Manifest failed manifest schema: ${ajv.errorsText(validateManifest.errors, { separator: '\n' })}`];
|
||||
}
|
||||
|
||||
if (!Array.isArray(data.resources)) {
|
||||
return ['resources must be an array'];
|
||||
}
|
||||
if (!Array.isArray(data.evidencePackages)) {
|
||||
return ['evidencePackages must be an array'];
|
||||
}
|
||||
|
||||
data.resources.forEach((r, i) => {
|
||||
if (!validateResource(r)) {
|
||||
errors.push(
|
||||
`resources[${i}] (resourceId=${r?.resourceId}): ${ajv.errorsText(validateResource.errors, { separator: '\n' })}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
data.evidencePackages.forEach((p, i) => {
|
||||
if (!validateEvidence(p)) {
|
||||
errors.push(
|
||||
`evidencePackages[${i}] (id=${p?.evidencePackageId}): ${ajv.errorsText(validateEvidence.errors, { separator: '\n' })}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length) return errors;
|
||||
|
||||
const ids = new Set(data.resources.map((r) => r.resourceId).filter(Boolean));
|
||||
data.evidencePackages.forEach((p, pi) => {
|
||||
(p.resourceIds || []).forEach((rid) => {
|
||||
if (!ids.has(rid)) {
|
||||
errors.push(`evidencePackages[${pi}] references unknown resourceId: ${rid}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* CLI-style: read file, validate, log, exit 0 or 1.
|
||||
* @param {string} [manifestPath]
|
||||
*/
|
||||
export function validateUraManifestFileCli(manifestPath) {
|
||||
const projectRoot = getProjectRoot();
|
||||
const pathToUse = manifestPath || getDefaultManifestPath(projectRoot);
|
||||
|
||||
function fail(msg) {
|
||||
console.error(`[validate-ura] ${msg}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!existsSync(pathToUse)) {
|
||||
fail(`Missing ${pathToUse}`);
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(readFileSync(pathToUse, 'utf8'));
|
||||
} catch (e) {
|
||||
fail(`Invalid JSON: ${e.message}`);
|
||||
}
|
||||
|
||||
const validators = loadUraManifestValidators(projectRoot);
|
||||
const errs = validateUraManifestData(data, validators);
|
||||
if (errs.length) {
|
||||
errs.forEach((e) => console.error(`[validate-ura] ${e}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[validate-ura] OK: ${data.resources.length} resource(s), ${data.evidencePackages.length} evidence package(s)`
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
36
scripts/ura/manifest-writer/README.md
Normal file
36
scripts/ura/manifest-writer/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# URA manifest writer (ledger + settlement fragments)
|
||||
|
||||
**Purpose:** Build **partial manifest fragments** from machine-readable inputs so ops or a batch job can merge them (`pnpm ura:merge-manifest` or manual paste) after validation.
|
||||
|
||||
## Ledger → `accountingRef`
|
||||
|
||||
1. Define mapping: [`omnl-ledger-mapping.v1.example.json`](../../../config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json) → copy to `omnl-ledger-mapping.v1.json` (gitignored or secured).
|
||||
2. Export ledger snapshot JSON (Fineract/OMNL/sidecar ETL).
|
||||
3. Run:
|
||||
|
||||
```bash
|
||||
pnpm ura:writer:ledger -- \
|
||||
--mapping config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json \
|
||||
--ledger config/universal-resource-activation/integration/examples/ledger-snapshot.example.json
|
||||
```
|
||||
|
||||
4. Pipe output into a file under `manifest-fragments/` or merge with `merge-manifest-fragments.mjs --out`.
|
||||
|
||||
Validate mapping: `pnpm ura:validate-ledger-mapping -- config/.../omnl-ledger-mapping.v1.example.json`
|
||||
|
||||
## Rail / chain → `settlementOrChainRef`
|
||||
|
||||
```bash
|
||||
pnpm ura:writer:settlement -- \
|
||||
--evidence-package-id ura:pilot:evidence-register-bootstrap \
|
||||
--message-id 0xabc \
|
||||
--tx-hash 0xdef \
|
||||
--chain-id 138
|
||||
```
|
||||
|
||||
Emits a fragment with a single `evidencePackages[]` row (shallow merge by id).
|
||||
|
||||
## Related
|
||||
|
||||
- [`URA_MANIFEST_WRITER_OPS.md`](../../../docs/03-deployment/URA_MANIFEST_WRITER_OPS.md)
|
||||
- [`URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md`](../../../docs/04-configuration/universal-resource-activation/URA_MANIFEST_AUTOMATION_IMPLEMENTATION_TRACKER.md)
|
||||
71
scripts/ura/manifest-writer/build-ledger-fragment.mjs
Normal file
71
scripts/ura/manifest-writer/build-ledger-fragment.mjs
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Build a manifest fragment from a ledger snapshot JSON + omnl-ledger-mapping.v1.json
|
||||
* See scripts/ura/manifest-writer/README.md
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { getByPath, asString } from './lib/get-by-path.mjs';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.join(__dirname, '..', '..', '..');
|
||||
|
||||
function parseArgs() {
|
||||
const a = process.argv.slice(2);
|
||||
const o = {};
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] === '--mapping') o.mapping = a[++i];
|
||||
else if (a[i] === '--ledger') o.ledger = a[++i];
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
const args = parseArgs();
|
||||
const mappingPath = path.resolve(projectRoot, args.mapping || 'config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json');
|
||||
const ledgerPath = path.resolve(
|
||||
projectRoot,
|
||||
args.ledger || 'config/universal-resource-activation/integration/examples/ledger-snapshot.example.json'
|
||||
);
|
||||
|
||||
for (const p of [mappingPath, ledgerPath]) {
|
||||
if (!existsSync(p)) {
|
||||
console.error(`[writer-ledger] Missing file: ${p}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
let mapping;
|
||||
let ledger;
|
||||
try {
|
||||
mapping = JSON.parse(readFileSync(mappingPath, 'utf8'));
|
||||
ledger = JSON.parse(readFileSync(ledgerPath, 'utf8'));
|
||||
} catch (e) {
|
||||
console.error(`[writer-ledger] JSON error: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const evidencePackages = [];
|
||||
for (const row of mapping.evidencePackages || []) {
|
||||
const pkg = { evidencePackageId: row.evidencePackageId };
|
||||
if (row.accountingRefField) {
|
||||
const v = getByPath(ledger, row.accountingRefField);
|
||||
pkg.accountingRef = asString(v);
|
||||
}
|
||||
evidencePackages.push(pkg);
|
||||
}
|
||||
|
||||
const resources = [];
|
||||
for (const ru of mapping.resourceUpdates || []) {
|
||||
const v = getByPath(ledger, ru.quantityField);
|
||||
resources.push({
|
||||
resourceId: ru.resourceId,
|
||||
quantity: asString(v),
|
||||
});
|
||||
}
|
||||
|
||||
const fragment = {};
|
||||
if (evidencePackages.length) fragment.evidencePackages = evidencePackages;
|
||||
if (resources.length) fragment.resources = resources;
|
||||
|
||||
process.stdout.write(`${JSON.stringify(fragment, null, 2)}\n`);
|
||||
38
scripts/ura/manifest-writer/build-settlement-fragment.mjs
Normal file
38
scripts/ura/manifest-writer/build-settlement-fragment.mjs
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Build a manifest fragment with settlementOrChainRef on an evidence package.
|
||||
*/
|
||||
function parseArgs() {
|
||||
const a = process.argv.slice(2);
|
||||
const o = {};
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] === '--evidence-package-id') o.evidencePackageId = a[++i];
|
||||
else if (a[i] === '--message-id') o.messageId = a[++i];
|
||||
else if (a[i] === '--tx-hash') o.txHash = a[++i];
|
||||
else if (a[i] === '--chain-id') o.chainId = a[++i];
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
const args = parseArgs();
|
||||
if (!args.evidencePackageId) {
|
||||
console.error('[writer-settlement] Required: --evidence-package-id');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
if (args.messageId) parts.push(`messageId=${args.messageId}`);
|
||||
if (args.txHash) parts.push(`tx=${args.txHash}`);
|
||||
if (args.chainId) parts.push(`chain=${args.chainId}`);
|
||||
const settlementOrChainRef = parts.length ? parts.join(';') : '';
|
||||
|
||||
const fragment = {
|
||||
evidencePackages: [
|
||||
{
|
||||
evidencePackageId: args.evidencePackageId,
|
||||
settlementOrChainRef,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
process.stdout.write(`${JSON.stringify(fragment, null, 2)}\n`);
|
||||
25
scripts/ura/manifest-writer/lib/get-by-path.mjs
Normal file
25
scripts/ura/manifest-writer/lib/get-by-path.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @param {Record<string, unknown>} obj
|
||||
* @param {string} dotPath e.g. "a.b.c"
|
||||
* @returns {unknown}
|
||||
*/
|
||||
export function getByPath(obj, dotPath) {
|
||||
if (!dotPath || typeof dotPath !== 'string') return undefined;
|
||||
const parts = dotPath.split('.').filter(Boolean);
|
||||
let cur = obj;
|
||||
for (const p of parts) {
|
||||
if (cur == null || typeof cur !== 'object') return undefined;
|
||||
cur = /** @type {Record<string, unknown>} */ (cur)[p];
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {unknown} v
|
||||
* @returns {string}
|
||||
*/
|
||||
export function asString(v) {
|
||||
if (v == null) return '';
|
||||
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);
|
||||
return JSON.stringify(v);
|
||||
}
|
||||
162
scripts/ura/merge-manifest-fragments.mjs
Normal file
162
scripts/ura/merge-manifest-fragments.mjs
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Merge optional JSON fragments into the URA manifest and validate (dry-run or --out).
|
||||
*
|
||||
* Fragments: partial objects with optional keys resources[], evidencePackages[], policyProfileRefs[].
|
||||
* Later files in sort order override same resourceId / evidencePackageId.
|
||||
*
|
||||
* Usage (repo root):
|
||||
* node scripts/ura/merge-manifest-fragments.mjs
|
||||
* node scripts/ura/merge-manifest-fragments.mjs --out /tmp/merged-manifest.json
|
||||
* node scripts/ura/merge-manifest-fragments.mjs --base config/universal-resource-activation/manifest.json --fragments-dir config/universal-resource-activation/manifest-fragments
|
||||
*/
|
||||
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
getProjectRoot,
|
||||
getDefaultManifestPath,
|
||||
loadUraManifestValidators,
|
||||
validateUraManifestData,
|
||||
} from './lib/validate-ura-manifest.mjs';
|
||||
|
||||
function parseArgs() {
|
||||
const argv = process.argv.slice(2);
|
||||
const out = {};
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
const a = argv[i];
|
||||
if (a === '--out') out.out = argv[++i];
|
||||
else if (a === '--base') out.base = argv[++i];
|
||||
else if (a === '--fragments-dir') out.fragmentsDir = argv[++i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function deepClone(o) {
|
||||
return JSON.parse(JSON.stringify(o));
|
||||
}
|
||||
|
||||
function profileKey(ref) {
|
||||
if (!ref || typeof ref.id !== 'string') return null;
|
||||
const v = ref.version != null ? String(ref.version) : '';
|
||||
return `${ref.id}@${v}`;
|
||||
}
|
||||
|
||||
function mergeFragment(base, frag, fragmentLabel) {
|
||||
const issues = [];
|
||||
|
||||
if (frag.policyProfileRefs && Array.isArray(frag.policyProfileRefs)) {
|
||||
const map = new Map();
|
||||
(base.policyProfileRefs || []).forEach((r) => {
|
||||
const k = profileKey(r);
|
||||
if (k) map.set(k, r);
|
||||
});
|
||||
frag.policyProfileRefs.forEach((r) => {
|
||||
const k = profileKey(r);
|
||||
if (k) map.set(k, r);
|
||||
});
|
||||
base.policyProfileRefs = [...map.values()].sort((a, b) => {
|
||||
const ka = profileKey(a);
|
||||
const kb = profileKey(b);
|
||||
return ka.localeCompare(kb);
|
||||
});
|
||||
}
|
||||
|
||||
if (frag.resources && Array.isArray(frag.resources)) {
|
||||
const byId = new Map((base.resources || []).map((r) => [r.resourceId, r]));
|
||||
frag.resources.forEach((r) => {
|
||||
if (!r || typeof r.resourceId !== 'string') {
|
||||
issues.push(`${fragmentLabel}: skip resource without resourceId`);
|
||||
return;
|
||||
}
|
||||
issues.push(
|
||||
`${fragmentLabel}: ${byId.has(r.resourceId) ? 'replace' : 'add'} resource ${r.resourceId}`
|
||||
);
|
||||
byId.set(r.resourceId, { ...(byId.get(r.resourceId) || {}), ...r });
|
||||
});
|
||||
base.resources = [...byId.values()].sort((a, b) => String(a.resourceId).localeCompare(String(b.resourceId)));
|
||||
}
|
||||
|
||||
if (frag.evidencePackages && Array.isArray(frag.evidencePackages)) {
|
||||
const byId = new Map((base.evidencePackages || []).map((p) => [p.evidencePackageId, p]));
|
||||
frag.evidencePackages.forEach((p) => {
|
||||
if (!p || typeof p.evidencePackageId !== 'string') {
|
||||
issues.push(`${fragmentLabel}: skip evidence package without evidencePackageId`);
|
||||
return;
|
||||
}
|
||||
issues.push(
|
||||
`${fragmentLabel}: ${byId.has(p.evidencePackageId) ? 'replace' : 'add'} evidencePackage ${p.evidencePackageId}`
|
||||
);
|
||||
const prev = byId.get(p.evidencePackageId) || {};
|
||||
byId.set(p.evidencePackageId, { ...prev, ...p });
|
||||
});
|
||||
base.evidencePackages = [...byId.values()].sort((a, b) =>
|
||||
String(a.evidencePackageId).localeCompare(String(b.evidencePackageId))
|
||||
);
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = parseArgs();
|
||||
const projectRoot = getProjectRoot();
|
||||
const basePath = path.resolve(projectRoot, args.base || getDefaultManifestPath(projectRoot));
|
||||
const fragmentsDir = path.resolve(
|
||||
projectRoot,
|
||||
args.fragmentsDir || path.join('config', 'universal-resource-activation', 'manifest-fragments')
|
||||
);
|
||||
|
||||
if (!existsSync(basePath)) {
|
||||
console.error(`[merge-ura-manifest] Missing base: ${basePath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let merged;
|
||||
try {
|
||||
merged = JSON.parse(readFileSync(basePath, 'utf8'));
|
||||
} catch (e) {
|
||||
console.error(`[merge-ura-manifest] Invalid base JSON: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const mergeNotes = [];
|
||||
if (existsSync(fragmentsDir)) {
|
||||
const files = readdirSync(fragmentsDir)
|
||||
.filter((f) => f.endsWith('.json') && !f.startsWith('_'))
|
||||
.sort();
|
||||
for (const f of files) {
|
||||
const fp = path.join(fragmentsDir, f);
|
||||
let frag;
|
||||
try {
|
||||
frag = JSON.parse(readFileSync(fp, 'utf8'));
|
||||
} catch (e) {
|
||||
console.error(`[merge-ura-manifest] Invalid JSON in ${fp}: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
mergeNotes.push(...mergeFragment(merged, frag, f));
|
||||
}
|
||||
}
|
||||
|
||||
const validators = loadUraManifestValidators(projectRoot);
|
||||
const errs = validateUraManifestData(merged, validators);
|
||||
if (errs.length) {
|
||||
errs.forEach((e) => console.error(`[merge-ura-manifest] ${e}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
mergeNotes.forEach((n) => console.log(`[merge-ura-manifest] ${n}`));
|
||||
console.log(
|
||||
`[merge-ura-manifest] OK: ${merged.resources.length} resource(s), ${merged.evidencePackages.length} evidence package(s)`
|
||||
);
|
||||
|
||||
if (args.out) {
|
||||
writeFileSync(path.resolve(args.out), `${JSON.stringify(merged, null, 2)}\n`, 'utf8');
|
||||
console.log(`[merge-ura-manifest] Wrote ${path.resolve(args.out)}`);
|
||||
} else {
|
||||
console.log('[merge-ura-manifest] Dry-run (pass --out <file> to write merged JSON)');
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
main();
|
||||
46
scripts/ura/policy-profiles-content-hash.mjs
Normal file
46
scripts/ura/policy-profiles-content-hash.mjs
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Compute a content hash for one policy profile row (for PolicyProfileRegistry.publishProfile on-chain).
|
||||
* Uses keccak256(utf8(canonicalJson)) where canonicalJson is stable key-sorted JSON of the profile object.
|
||||
*
|
||||
* Usage: node scripts/ura/policy-profiles-content-hash.mjs <policyProfileId>
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { keccak256, toUtf8Bytes } from 'ethers';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.join(__dirname, '..', '..');
|
||||
const registryPath = path.join(projectRoot, 'config/universal-resource-activation/policy-profiles.json');
|
||||
|
||||
const id = process.argv[2];
|
||||
if (!id) {
|
||||
console.error('Usage: node scripts/ura/policy-profiles-content-hash.mjs <policyProfileId>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!existsSync(registryPath)) {
|
||||
console.error(`Missing ${registryPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const data = JSON.parse(readFileSync(registryPath, 'utf8'));
|
||||
const profile = (data.profiles || []).find((p) => p.policyProfileId === id);
|
||||
if (!profile) {
|
||||
console.error(`Unknown policyProfileId: ${id}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function sortKeys(obj) {
|
||||
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) return obj;
|
||||
const out = {};
|
||||
for (const k of Object.keys(obj).sort()) {
|
||||
out[k] = sortKeys(obj[k]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const canonical = JSON.stringify(sortKeys(profile));
|
||||
const hash = keccak256(toUtf8Bytes(canonical));
|
||||
console.log(JSON.stringify({ policyProfileId: id, contentHash: hash, canonicalBytes: canonical.length }, null, 2));
|
||||
81
scripts/ura/validate-manifest-closure.mjs
Normal file
81
scripts/ura/validate-manifest-closure.mjs
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Optional production gate: fail if manifest still contains pilot placeholders or open reconciliation.
|
||||
*
|
||||
* Usage (repo root):
|
||||
* node scripts/ura/validate-manifest-closure.mjs # warnings only, exit 0
|
||||
* node scripts/ura/validate-manifest-closure.mjs --strict # exit 1 on violations
|
||||
*
|
||||
* CI: set URA_STRICT_CLOSURE=1 and run validate-config-files.sh (see script header there).
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import { getProjectRoot, getDefaultManifestPath } from './lib/validate-ura-manifest.mjs';
|
||||
|
||||
const PILOT_PARTICIPANT = /ura:participant:pilot-/i;
|
||||
const PENDING_EVIDENCE = /^ura:evidence:pending-/i;
|
||||
const TBD_RE = /\bTBD\b/i;
|
||||
|
||||
const strict = process.argv.includes('--strict');
|
||||
const projectRoot = getProjectRoot();
|
||||
const manifestPath = getDefaultManifestPath(projectRoot);
|
||||
|
||||
function main() {
|
||||
const log = (m) => console.log(`[validate-ura-closure] ${m}`);
|
||||
const warn = (m) => console.warn(`[validate-ura-closure] WARN: ${m}`);
|
||||
const err = (m) => console.error(`[validate-ura-closure] ${strict ? 'FAIL' : 'WARN'}: ${m}`);
|
||||
|
||||
if (!existsSync(manifestPath)) {
|
||||
console.error(`[validate-ura-closure] Missing ${manifestPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
||||
} catch (e) {
|
||||
console.error(`[validate-ura-closure] Invalid JSON: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const violations = [];
|
||||
|
||||
(data.resources || []).forEach((r, i) => {
|
||||
const pid = r.ownerParticipantId;
|
||||
if (typeof pid === 'string' && PILOT_PARTICIPANT.test(pid)) {
|
||||
violations.push(`resources[${i}] ownerParticipantId is pilot placeholder: ${pid}`);
|
||||
}
|
||||
(r.evidenceRefs || []).forEach((ref, j) => {
|
||||
if (typeof ref === 'string' && PENDING_EVIDENCE.test(ref)) {
|
||||
violations.push(`resources[${i}] evidenceRefs[${j}] pending: ${ref}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
(data.evidencePackages || []).forEach((p, i) => {
|
||||
if (p.reconciliationStatus === 'open') {
|
||||
violations.push(`evidencePackages[${i}] (${p.evidencePackageId}) reconciliationStatus is open`);
|
||||
}
|
||||
const checkFields = ['custodyOrSourceEvidence', 'accountingRef', 'settlementOrChainRef', 'deploymentRef', 'explanation'];
|
||||
for (const f of checkFields) {
|
||||
const v = p[f];
|
||||
if (typeof v === 'string' && TBD_RE.test(v)) {
|
||||
violations.push(`evidencePackages[${i}] (${p.evidencePackageId}).${f} contains TBD`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (violations.length === 0) {
|
||||
log('OK: no pilot/TBD/open-reconciliation patterns detected');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
violations.forEach((v) => (strict ? err : warn)(v));
|
||||
if (strict) {
|
||||
err(`${violations.length} violation(s) — close pilots per URA_PILOT_CLOSURE_RUNBOOK.md`);
|
||||
process.exit(1);
|
||||
}
|
||||
log(`${violations.length} notice(s) (use --strict to fail CI)`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
main();
|
||||
51
scripts/validate/validate-omnl-ledger-mapping.mjs
Normal file
51
scripts/validate/validate-omnl-ledger-mapping.mjs
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate omnl-ledger-mapping.v1.json against omnl-ledger-mapping.v1.schema.json
|
||||
* Usage: node scripts/validate/validate-omnl-ledger-mapping.mjs [path]
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Ajv from 'ajv';
|
||||
import addFormats from 'ajv-formats';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.join(__dirname, '../..');
|
||||
const defaultPath = path.join(
|
||||
projectRoot,
|
||||
'config/universal-resource-activation/integration/omnl-ledger-mapping.v1.example.json'
|
||||
);
|
||||
const schemaPath = path.join(
|
||||
projectRoot,
|
||||
'config/universal-resource-activation/integration/omnl-ledger-mapping.v1.schema.json'
|
||||
);
|
||||
|
||||
const file = path.resolve(projectRoot, process.argv[2] || defaultPath);
|
||||
|
||||
if (!existsSync(file)) {
|
||||
console.error(`[validate-ledger-mapping] Missing ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!existsSync(schemaPath)) {
|
||||
console.error(`[validate-ledger-mapping] Missing schema ${schemaPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const ajv = new Ajv({ allErrors: true, strict: false, validateSchema: false });
|
||||
addFormats(ajv);
|
||||
const validate = ajv.compile(JSON.parse(readFileSync(schemaPath, 'utf8')));
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(readFileSync(file, 'utf8'));
|
||||
} catch (e) {
|
||||
console.error(`[validate-ledger-mapping] Invalid JSON: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!validate(data)) {
|
||||
console.error(`[validate-ledger-mapping] FAIL: ${ajv.errorsText(validate.errors, { separator: '\n' })}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`[validate-ledger-mapping] OK: ${file}`);
|
||||
process.exit(0);
|
||||
@@ -1,100 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate config/universal-resource-activation/manifest.json against
|
||||
* - universal-resource-activation.manifest.v1.schema.json
|
||||
* - universal-resource-activation.resource.v1.schema.json (per item in resources[])
|
||||
* - universal-resource-activation.evidence-package.v1.schema.json (per item in evidencePackages[])
|
||||
* Validate config/universal-resource-activation/manifest.json against URA JSON Schemas.
|
||||
*
|
||||
* Usage: from repo root: node scripts/validate/validate-universal-resource-activation.mjs
|
||||
* Exit 0 on success, 1 on error.
|
||||
* Usage: from repo root: node scripts/validate/validate-universal-resource-activation.mjs [path/to/manifest.json]
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Ajv from 'ajv';
|
||||
import addFormats from 'ajv-formats';
|
||||
import { validateUraManifestFileCli } from '../ura/lib/validate-ura-manifest.mjs';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.join(__dirname, '../..');
|
||||
const configDir = path.join(projectRoot, 'config', 'universal-resource-activation');
|
||||
|
||||
const manifestPath = path.join(configDir, 'manifest.json');
|
||||
const manifestSchemaPath = path.join(projectRoot, 'config', 'universal-resource-activation.manifest.v1.schema.json');
|
||||
const resourceSchemaPath = path.join(projectRoot, 'config', 'universal-resource-activation.resource.v1.schema.json');
|
||||
const evidenceSchemaPath = path.join(projectRoot, 'config', 'universal-resource-activation.evidence-package.v1.schema.json');
|
||||
|
||||
function fail(msg) {
|
||||
console.error(`[validate-ura] ${msg}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!existsSync(manifestPath)) {
|
||||
fail(`Missing ${manifestPath}`);
|
||||
}
|
||||
|
||||
const ajv = new Ajv({
|
||||
allErrors: true,
|
||||
strict: false,
|
||||
validateSchema: false,
|
||||
});
|
||||
addFormats(ajv);
|
||||
|
||||
const manifestSchema = JSON.parse(readFileSync(manifestSchemaPath, 'utf8'));
|
||||
const resourceSchema = JSON.parse(readFileSync(resourceSchemaPath, 'utf8'));
|
||||
const evidenceSchema = JSON.parse(readFileSync(evidenceSchemaPath, 'utf8'));
|
||||
|
||||
const validateManifest = ajv.compile(manifestSchema);
|
||||
const validateResource = ajv.compile(resourceSchema);
|
||||
const validateEvidence = ajv.compile(evidenceSchema);
|
||||
|
||||
const raw = readFileSync(manifestPath, 'utf8');
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(raw);
|
||||
} catch (e) {
|
||||
fail(`Invalid JSON: ${e.message}`);
|
||||
}
|
||||
|
||||
if (!validateManifest(data)) {
|
||||
fail(`Manifest failed manifest schema: ${ajv.errorsText(validateManifest.errors, { separator: '\n' })}`);
|
||||
}
|
||||
|
||||
if (!Array.isArray(data.resources)) {
|
||||
fail('resources must be an array');
|
||||
}
|
||||
if (!Array.isArray(data.evidencePackages)) {
|
||||
fail('evidencePackages must be an array');
|
||||
}
|
||||
|
||||
data.resources.forEach((r, i) => {
|
||||
if (!validateResource(r)) {
|
||||
fail(
|
||||
`resources[${i}] (resourceId=${r?.resourceId}): ${ajv.errorsText(validateResource.errors, { separator: '\n' })}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
data.evidencePackages.forEach((p, i) => {
|
||||
if (!validateEvidence(p)) {
|
||||
fail(
|
||||
`evidencePackages[${i}] (id=${p?.evidencePackageId}): ${ajv.errorsText(validateEvidence.errors, { separator: '\n' })}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Cross-check: all resourceIds referenced in evidence exist
|
||||
const ids = new Set(data.resources.map((r) => r.resourceId).filter(Boolean));
|
||||
data.evidencePackages.forEach((p, pi) => {
|
||||
(p.resourceIds || []).forEach((rid) => {
|
||||
if (!ids.has(rid)) {
|
||||
fail(
|
||||
`evidencePackages[${pi}] references unknown resourceId: ${rid}`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(
|
||||
`[validate-ura] OK: ${data.resources.length} resource(s), ${data.evidencePackages.length} evidence package(s)`
|
||||
);
|
||||
process.exit(0);
|
||||
const arg = process.argv[2];
|
||||
validateUraManifestFileCli(arg || undefined);
|
||||
|
||||
65
scripts/validate/validate-ura-policy-profiles.mjs
Normal file
65
scripts/validate/validate-ura-policy-profiles.mjs
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate config/universal-resource-activation/policy-profiles.json against
|
||||
* universal-resource-activation.policy-profile-registry.v1.schema.json
|
||||
* and ensure manifest policyProfileRefs[] ids exist in the registry.
|
||||
*
|
||||
* Usage: from repo root — node scripts/validate/validate-ura-policy-profiles.mjs
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Ajv from 'ajv';
|
||||
import addFormats from 'ajv-formats';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.join(__dirname, '../..');
|
||||
|
||||
const registryPath = path.join(projectRoot, 'config', 'universal-resource-activation', 'policy-profiles.json');
|
||||
const registrySchemaPath = path.join(
|
||||
projectRoot,
|
||||
'config',
|
||||
'universal-resource-activation.policy-profile-registry.v1.schema.json',
|
||||
);
|
||||
const manifestPath = path.join(projectRoot, 'config', 'universal-resource-activation', 'manifest.json');
|
||||
|
||||
function fail(msg) {
|
||||
console.error(`[validate-ura-profiles] ${msg}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!existsSync(registryPath)) fail(`Missing ${registryPath}`);
|
||||
if (!existsSync(registrySchemaPath)) fail(`Missing ${registrySchemaPath}`);
|
||||
|
||||
const ajv = new Ajv({ allErrors: true, strict: false, validateSchema: false });
|
||||
addFormats(ajv);
|
||||
|
||||
const registrySchema = JSON.parse(readFileSync(registrySchemaPath, 'utf8'));
|
||||
const validateRegistry = ajv.compile(registrySchema);
|
||||
const registry = JSON.parse(readFileSync(registryPath, 'utf8'));
|
||||
|
||||
if (!validateRegistry(registry)) {
|
||||
console.error('[validate-ura-profiles] policy-profiles.json failed schema:', validateRegistry.errors);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const ids = new Set(registry.profiles.map((p) => p.policyProfileId));
|
||||
console.log(`[validate-ura-profiles] OK: ${ids.size} profile(s) in registry`);
|
||||
|
||||
if (existsSync(manifestPath)) {
|
||||
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
||||
const refs = manifest.policyProfileRefs || [];
|
||||
for (const r of refs) {
|
||||
const pid = r.id;
|
||||
if (!pid || !ids.has(pid)) {
|
||||
fail(`manifest policyProfileRefs contains unknown or missing id: "${pid}"`);
|
||||
}
|
||||
}
|
||||
for (const res of manifest.resources || []) {
|
||||
const pid = res.policyProfileId;
|
||||
if (pid && !ids.has(pid)) {
|
||||
fail(`resource ${res.resourceId} references unknown policyProfileId: "${pid}"`);
|
||||
}
|
||||
}
|
||||
console.log('[validate-ura-profiles] OK: manifest refs match registry');
|
||||
}
|
||||
@@ -188,6 +188,15 @@ else
|
||||
log_warn "Optional config/universal-resource-activation/policy-profiles.json missing; skipping"
|
||||
fi
|
||||
# Optional production gate: URA_STRICT_CLOSURE=1 fails if pilots/TBD/open reconciliation remain
|
||||
if [[ -f "$PROJECT_ROOT/config/universal-resource-activation/integration/omnl-ledger-mapping.v1.json" ]] && command -v node &>/dev/null && [[ -f "$PROJECT_ROOT/scripts/validate/validate-omnl-ledger-mapping.mjs" ]]; then
|
||||
log_ok "Found: config/universal-resource-activation/integration/omnl-ledger-mapping.v1.json"
|
||||
if node "$PROJECT_ROOT/scripts/validate/validate-omnl-ledger-mapping.mjs" "$PROJECT_ROOT/config/universal-resource-activation/integration/omnl-ledger-mapping.v1.json"; then
|
||||
log_ok "omnl-ledger-mapping.v1.json: JSON Schema OK"
|
||||
else
|
||||
log_err "omnl-ledger-mapping.v1.json: validation failed"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
if [[ "${URA_STRICT_CLOSURE:-}" == "1" ]] && [[ -f "$PROJECT_ROOT/scripts/ura/validate-manifest-closure.mjs" ]]; then
|
||||
log_info "URA_STRICT_CLOSURE=1: running URA manifest closure gate…"
|
||||
if node "$PROJECT_ROOT/scripts/ura/validate-manifest-closure.mjs" --strict; then
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Universal resource activation — local smoke: JSON Schema validation (always) +
|
||||
# optional HTTP GET to Phoenix (when --http or PHOENIX_BASE_URL is set).
|
||||
# optional HTTP GETs to Phoenix (when --http or PHOENIX_BASE_URL is set):
|
||||
# 1) GET /api/v1/universal-resource-activation/manifest (expect 200 + .schemaVersion)
|
||||
# 2) GET /api/v1/universal-resource-activation/policy-profiles (expect 200 + .profiles array)
|
||||
# 3) GET /api/v1/universal-resource-activation/server-funds-sidecar-probe
|
||||
# — expect 200 (sidecar ok or probe JSON) or 503 with .configured == false (URL unset)
|
||||
# — 502 = fail (URL set but sidecar paths not healthy)
|
||||
#
|
||||
# Usage (repo root):
|
||||
# bash scripts/verify/smoke-universal-resource-activation.sh
|
||||
@@ -61,7 +66,9 @@ fi
|
||||
|
||||
log "GET $URL (expect 200, JSON with .schemaVersion)…"
|
||||
body_file="$(mktemp)"
|
||||
trap 'rm -f "$body_file"' EXIT
|
||||
probe_file="$(mktemp)"
|
||||
profiles_file="$(mktemp)"
|
||||
trap 'rm -f "$body_file" "$probe_file" "$profiles_file"' EXIT
|
||||
code=$(curl -sS -o "$body_file" -w '%{http_code}' --connect-timeout 5 --max-time 15 "$URL" || true)
|
||||
|
||||
if [[ "$code" != "200" ]]; then
|
||||
@@ -78,4 +85,42 @@ if ! jq -e '.schemaVersion | type == "string"' "$body_file" &>/dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
log "HTTP OK (.schemaVersion present; HTTP $code)"
|
||||
|
||||
PROFILES_URL="${BASE}/api/v1/universal-resource-activation/policy-profiles"
|
||||
log "GET $PROFILES_URL (expect 200, JSON with .profiles array)…"
|
||||
prcode=$(curl -sS -o "$profiles_file" -w '%{http_code}' --connect-timeout 5 --max-time 15 "$PROFILES_URL" || true)
|
||||
if [[ "$prcode" != "200" ]]; then
|
||||
log_err "policy-profiles HTTP $prcode (expected 200). BASE=$BASE"
|
||||
exit 1
|
||||
fi
|
||||
if ! jq -e '(.profiles | type == "array")' "$profiles_file" &>/dev/null; then
|
||||
log_err "policy-profiles response missing .profiles array"
|
||||
cat "$profiles_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
log "policy-profiles HTTP OK"
|
||||
|
||||
PROBE_URL="${BASE}/api/v1/universal-resource-activation/server-funds-sidecar-probe"
|
||||
log "GET $PROBE_URL (expect 200 OK response or 503 with configured not true when URL unset)…"
|
||||
pcode=$(curl -sS -o "$probe_file" -w '%{http_code}' --connect-timeout 5 --max-time 20 "$PROBE_URL" || true)
|
||||
|
||||
if [[ "$pcode" == "200" ]]; then
|
||||
if ! jq -e 'type == "object"' "$probe_file" &>/dev/null; then
|
||||
log_err "Probe response is not a JSON object"
|
||||
exit 1
|
||||
fi
|
||||
log "sidecar-probe HTTP 200 (JSON object returned)"
|
||||
elif [[ "$pcode" == "503" ]]; then
|
||||
if ! jq -e '.configured == false' "$probe_file" &>/dev/null; then
|
||||
log_err "Probe expected 503 with .configured==false when SERVER_FUNDS_SIDECAR_URL unset; got: $(head -c 400 "$probe_file")"
|
||||
exit 1
|
||||
fi
|
||||
log "sidecar-probe HTTP 503 (SERVER_FUNDS_SIDECAR_URL not set — expected in dev)"
|
||||
elif [[ "$pcode" == "502" ]]; then
|
||||
log_err "sidecar-probe HTTP 502 — SERVER_FUNDS_SIDECAR_URL is set but sidecar health paths failed. Fix env or sidecar. Body: $(head -c 400 "$probe_file")"
|
||||
exit 1
|
||||
else
|
||||
log_err "sidecar-probe HTTP $pcode (expected 200, 503, or 502). Body: $(head -c 400 "$probe_file")"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
|
||||
Submodule smom-dbis-138 updated: f3d2961b97...4540ec4480
Reference in New Issue
Block a user