Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m27s
CI/CD Pipeline / Security Scanning (push) Successful in 2m37s
CI/CD Pipeline / Lint and Format (push) Failing after 53s
CI/CD Pipeline / Terraform Validation (push) Failing after 31s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 29s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 37s
Validation / validate-genesis (push) Successful in 34s
Validation / validate-terraform (push) Failing after 33s
Validation / validate-kubernetes (push) Failing after 13s
Validation / validate-smart-contracts (push) Failing after 11s
Validation / validate-security (push) Failing after 1m26s
Validation / validate-documentation (push) Failing after 19s
Refreshes ho-liquidity-snapshot every 30 minutes with aggregate supplyNostroMatch and reserve alerts; embeds nostro/reserve KPIs in the OMNL compliance console; includes payout journal routes needed for token-aggregation build. Co-authored-by: Cursor <cursoragent@cursor.com>
245 lines
8.7 KiB
JavaScript
245 lines
8.7 KiB
JavaScript
(function () {
|
||
const params = new URLSearchParams(window.location.search);
|
||
const accessToken = params.get('access_token') || '';
|
||
const apiBase =
|
||
document.querySelector('meta[name="omnl-api-base"]')?.getAttribute('content')?.trim() || '/api/v1';
|
||
|
||
const els = {
|
||
status: document.getElementById('load-status'),
|
||
grid: document.getElementById('posture-grid'),
|
||
actions: document.getElementById('pending-actions'),
|
||
evidence: document.getElementById('evidence-kv'),
|
||
safe: document.getElementById('safe-kv'),
|
||
external: document.getElementById('external-kv'),
|
||
triple: document.getElementById('triple-summary'),
|
||
hoLiquidity: document.getElementById('ho-liquidity-kv'),
|
||
signoffs: document.getElementById('signoffs-summary'),
|
||
raw: document.getElementById('raw-json'),
|
||
refreshed: document.getElementById('refreshed-at'),
|
||
};
|
||
|
||
function apiHeaders() {
|
||
const h = { Accept: 'application/json' };
|
||
if (accessToken) h.Authorization = 'Bearer ' + accessToken;
|
||
return h;
|
||
}
|
||
|
||
function apiUrl(path) {
|
||
const base = apiBase.replace(/\/$/, '');
|
||
const rel = path.startsWith('/') ? path : '/' + path;
|
||
const u = new URL(base + rel, window.location.origin);
|
||
if (accessToken) u.searchParams.set('access_token', accessToken);
|
||
return u.toString();
|
||
}
|
||
|
||
function badge(ok, okLabel, badLabel) {
|
||
if (ok === true) return '<span class="badge ok">' + okLabel + '</span>';
|
||
if (ok === false) return '<span class="badge bad">' + badLabel + '</span>';
|
||
return '<span class="badge neutral">Unknown</span>';
|
||
}
|
||
|
||
function sevBadge(sev) {
|
||
const map = { critical: 'bad', high: 'bad', medium: 'warn', low: 'neutral' };
|
||
return '<span class="badge ' + (map[sev] || 'neutral') + '">' + sev + '</span>';
|
||
}
|
||
|
||
function renderPosture(data) {
|
||
const p = data.posture || {};
|
||
els.grid.innerHTML = [
|
||
card('Reporting', badge(p.reportingCompliant, 'Compliant', 'Not compliant'), ''),
|
||
card('Attestation', badge(!p.attestationStale, 'Fresh', 'Stale'), ''),
|
||
card('Triple reconcile', badge(p.tripleAligned, 'Aligned', 'Breaks'), ''),
|
||
card('Notary gate', badge(p.requireNotarizedEvidence, 'Enforced', 'Not enforced'), 'requireNotarizedEvidence'),
|
||
card('Threshold', '<div class="metric">' + (p.complianceThreshold || '—') + '</div>', 'IPSAS / IFRS / US GAAP'),
|
||
card('Policy v', '<div class="metric">' + (p.jurisdictionPolicyVersion ?? '—') + '</div>', 'ID jurisdiction'),
|
||
].join('');
|
||
}
|
||
|
||
function card(title, body, sub) {
|
||
return (
|
||
'<div class="card"><h2>' +
|
||
title +
|
||
'</h2>' +
|
||
body +
|
||
(sub ? '<small style="color:var(--muted);font-size:0.78rem">' + sub + '</small>' : '') +
|
||
'</div>'
|
||
);
|
||
}
|
||
|
||
function renderActions(actions) {
|
||
if (!actions || !actions.length) {
|
||
els.actions.innerHTML = '<p style="color:var(--muted)">No pending actions.</p>';
|
||
return;
|
||
}
|
||
els.actions.innerHTML =
|
||
'<ul class="actions-list">' +
|
||
actions
|
||
.map(function (a) {
|
||
const links = (a.links || [])
|
||
.map(function (l) {
|
||
const href = l.href.startsWith('http') ? l.href : apiUrl(l.href);
|
||
const dl = l.href.indexOf('safe-notary-gate-tx') >= 0 ? ' download="omnl-safe-notary-gate-tx.json"' : '';
|
||
return '<a href="' + href + '"' + dl + '>' + l.label + '</a>';
|
||
})
|
||
.join('');
|
||
return (
|
||
'<li><h3>' +
|
||
sevBadge(a.severity) +
|
||
' ' +
|
||
esc(a.title) +
|
||
'</h3><p>' +
|
||
esc(a.detail) +
|
||
'</p><div class="link-row">' +
|
||
links +
|
||
'</div></li>'
|
||
);
|
||
})
|
||
.join('') +
|
||
'</ul>';
|
||
}
|
||
|
||
function kv(rows) {
|
||
return (
|
||
'<dl class="kv">' +
|
||
rows
|
||
.map(function (r) {
|
||
return '<dt>' + esc(r[0]) + '</dt><dd>' + esc(String(r[1] ?? '—')) + '</dd>';
|
||
})
|
||
.join('') +
|
||
'</dl>'
|
||
);
|
||
}
|
||
|
||
function renderEvidence(data) {
|
||
const pr = data.proofReport;
|
||
const gate = data.onChainGate || {};
|
||
const triple = data.tripleReconcile;
|
||
els.evidence.innerHTML = kv([
|
||
['Evidence hash', pr && pr.evidenceHash],
|
||
['Merkle root', pr && pr.merkleRoot],
|
||
['Package 3-of-3', pr && pr.packageNotarized3of3],
|
||
['Reserve 3-of-3', pr && pr.reserveAttested3of3],
|
||
['Reserve store', gate.reserveStore],
|
||
['Notary registry', gate.notaryRegistry],
|
||
['Attestation threshold', gate.attestationThreshold],
|
||
['On-chain R', triple && triple.onChain && triple.onChain.r],
|
||
]);
|
||
}
|
||
|
||
function renderSafe(data) {
|
||
const pr = data.proofReport;
|
||
const g = (pr && pr.gnosisSafe) || {};
|
||
const sw = data.safeWallet || {};
|
||
els.safe.innerHTML = kv([
|
||
['Admin Safe', g.address || data.web3.deployed.GnosisSafeAdmin],
|
||
['Threshold', g.threshold ? g.threshold + '-of-' + g.owners : '—'],
|
||
['Safe Wallet registry', sw.npmRegistryHas138 ? 'chain 138 listed' : 'pending PR #1568'],
|
||
['Registry status', sw.status],
|
||
]);
|
||
}
|
||
|
||
function renderExternal(data) {
|
||
const ev = data.externalVisibility || {};
|
||
els.external.innerHTML = kv([
|
||
['DefiLlama chain', ev.defiLlama && ev.defiLlama.chainPage],
|
||
['Pricing PR', ev.defiLlama && ev.defiLlama.pr12094],
|
||
['Bridge TVL PR', ev.defiLlama && ev.defiLlama.pr19451],
|
||
['Safe deployments PR', ev.safeDeployments && ev.safeDeployments.pr1568],
|
||
]);
|
||
}
|
||
|
||
function renderHoLiquidity(snap) {
|
||
if (!els.hoLiquidity) return;
|
||
if (!snap) {
|
||
els.hoLiquidity.textContent = 'HO liquidity snapshot unavailable.';
|
||
return;
|
||
}
|
||
const cash = snap.cashInBank || {};
|
||
const cov = snap.reserveCoverage || {};
|
||
els.hoLiquidity.innerHTML = kv([
|
||
['Generated', snap.generatedAt],
|
||
['Nostro cash (GL 13010)', cash.cashInBankUsd != null ? '$' + Number(cash.cashInBankUsd).toLocaleString() : '—'],
|
||
['Reserve coverage', cov.coverageRatio != null ? cov.coverageRatio.toFixed(2) + '×' : '—'],
|
||
['Reserve assets', cov.reserveAssetsUsd != null ? '$' + Number(cov.reserveAssetsUsd).toLocaleString() : '—'],
|
||
['Issued c* USD', cov.issuedCStarUsd != null ? '$' + Number(cov.issuedCStarUsd).toLocaleString() : '—'],
|
||
['Public API', '/token-aggregation/api/v1/omnl/ho-liquidity-snapshot'],
|
||
]);
|
||
}
|
||
|
||
function renderTriple(data) {
|
||
const t = data.tripleReconcile;
|
||
if (!t) {
|
||
els.triple.textContent = 'Triple-state reconcile unavailable.';
|
||
return;
|
||
}
|
||
const breaks = (t.breaks || []).length;
|
||
els.triple.innerHTML =
|
||
badge(t.aligned, 'Aligned', breaks + ' break(s)') +
|
||
' <span style="color:var(--muted);margin-left:0.5rem;font-size:0.88rem">line ' +
|
||
esc(t.lineId).slice(0, 18) +
|
||
'…</span>';
|
||
}
|
||
|
||
function renderSignoffs(data) {
|
||
const s = data.signoffs || {};
|
||
els.signoffs.innerHTML = '<pre class="raw" style="max-height:10rem">' + esc(JSON.stringify(s, null, 2)) + '</pre>';
|
||
}
|
||
|
||
function esc(s) {
|
||
return String(s)
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"');
|
||
}
|
||
|
||
function setStatus(kind, msg) {
|
||
els.status.className = 'status-bar ' + kind;
|
||
els.status.textContent = msg;
|
||
}
|
||
|
||
async function load() {
|
||
setStatus('loading', 'Loading compliance console…');
|
||
try {
|
||
const res = await fetch(apiUrl('/omnl/compliance/console'), { headers: apiHeaders() });
|
||
const text = await res.text();
|
||
let data;
|
||
try {
|
||
data = JSON.parse(text);
|
||
} catch {
|
||
throw new Error(res.status + ' — non-JSON response');
|
||
}
|
||
if (!res.ok) throw new Error(data.error || res.statusText);
|
||
|
||
renderPosture(data);
|
||
renderActions(data.pendingActions);
|
||
renderEvidence(data);
|
||
renderSafe(data);
|
||
renderExternal(data);
|
||
renderTriple(data);
|
||
try {
|
||
const hoRes = await fetch(apiUrl('/omnl/ho-liquidity-snapshot'), { headers: apiHeaders() });
|
||
if (hoRes.ok) renderHoLiquidity(await hoRes.json());
|
||
} catch (_) {
|
||
renderHoLiquidity(null);
|
||
}
|
||
renderSignoffs(data);
|
||
els.raw.textContent = JSON.stringify(data, null, 2);
|
||
els.refreshed.textContent = 'Updated ' + new Date(data.generatedAt).toLocaleString();
|
||
setStatus('ok', 'Live — ' + data.pendingActions.length + ' pending action(s)');
|
||
} catch (e) {
|
||
setStatus('error', 'Failed to load: ' + (e && e.message ? e.message : e));
|
||
}
|
||
}
|
||
|
||
document.getElementById('btn-refresh').addEventListener('click', load);
|
||
document.getElementById('btn-download-safe').addEventListener('click', function () {
|
||
window.location.href = apiUrl('/omnl/compliance/safe-notary-gate-tx');
|
||
});
|
||
document.getElementById('btn-toggle-raw').addEventListener('click', function () {
|
||
document.getElementById('raw-section').classList.toggle('hidden');
|
||
});
|
||
|
||
load();
|
||
})();
|