feat(guosmm): deploy gazette notices across API, portal, and office configs
Some checks failed
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Lint and Format (push) Has been cancelled
CI/CD Pipeline / Terraform Validation (push) Has been cancelled
CI/CD Pipeline / Kubernetes Validation (push) Has been cancelled
CI/CD Pipeline / Solidity Contracts (push) Has been cancelled
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Has been cancelled
Validation / validate-genesis (push) Has been cancelled
Validation / validate-terraform (push) Has been cancelled
Validation / validate-kubernetes (push) Has been cancelled
Validation / validate-smart-contracts (push) Has been cancelled
Validation / validate-security (push) Has been cancelled
Validation / validate-documentation (push) Has been cancelled
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 45s
Verify Deployment / Verify Deployment (push) Failing after 58s

Register GUOSMM-B-2026-001 and C-2026-003/004/005 in SSOT, expose via
/api/v1/omnl/gazette/notices, hub and central-bank UI, offices 29-31,
compliance console, and production deploy sync script.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-03 02:03:38 -07:00
parent 4919328162
commit 14238dc81d
26 changed files with 3159 additions and 7 deletions

View File

@@ -15,6 +15,7 @@ import { omnlComplianceCore138, omnlReserveStore138 } from '../../services/omnl-
import { computeOmnlReconcileAnchor } from '../../services/omnl-reconcile-anchor';
import { getOmnlIntegrationStatus } from '../../services/omnl-integration-status';
import { getOmnlApiCatalog } from '../../services/omnl-api-catalog';
import { loadGuosmmNotices, getGuosmmNotice } from '../../services/omnl-gazette-notices';
import omnlOpenApi from '../../resources/omnl-openapi.json';
import {
executeErc20Transfer,
@@ -90,6 +91,28 @@ router.get('/omnl/integration-status', (_req: Request, res: Response) => {
});
});
/**
* GET /omnl/gazette/notices — GUOSMM official gazette registry (public disclosure).
*/
router.get('/omnl/gazette/notices', (_req: Request, res: Response) => {
const reg = loadGuosmmNotices();
res.json({
generatedAt: new Date().toISOString(),
gazetteBase: reg.gazetteBase,
count: reg.notices.length,
notices: reg.notices,
});
});
router.get('/omnl/gazette/notices/:documentId', (req: Request, res: Response) => {
const notice = getGuosmmNotice(req.params.documentId);
if (!notice) {
res.status(404).json({ error: 'Notice not found' });
return;
}
res.json(notice);
});
/**
* GET /omnl/reconcile-anchor — same SHA-256 as omnl-reconcile-report.mjs (IPSAS + matrix files).
*/

View File

@@ -19,6 +19,8 @@ export function getOmnlApiCatalog(): {
endpoints: [
{ method: 'GET', path: '/omnl/openapi.json', description: 'OpenAPI 3.0 JSON (Swagger-compatible)', auth: 'none' },
{ method: 'GET', path: '/omnl/catalog', description: 'This catalog (machine-readable)', auth: 'none' },
{ method: 'GET', path: '/omnl/gazette/notices', description: 'GUOSMM official gazette notice registry', auth: 'none' },
{ method: 'GET', path: '/omnl/gazette/notices/:documentId', description: 'Single GUOSMM notice by document ID', auth: 'none' },
{ method: 'GET', path: '/omnl/integration-status', description: 'Which env-backed integrations are configured', auth: 'none' },
{ method: 'GET', path: '/omnl/reconcile-anchor', description: 'SHA-256 of canonical IPSAS registry + journal matrix JSON', auth: 'OMNL_API_KEY when OMNL_REQUIRE_API_KEY=1' },
{ method: 'GET', path: '/omnl/reconcile/triple-state', description: 'Fineract + on-chain + custodian reconcile', query: ['lineId'], auth: 'OMNL_API_KEY' },

View File

@@ -6,6 +6,7 @@ import { getWeb3ComplianceSummary } from './omnl-web3-compliance';
import { getComplianceSignoffsSummary } from './omnl-ifrs-disclosures';
import { omnlReserveStore138 } from './omnl-chain138-addresses';
import { buildSafeNotaryGateTransaction } from './omnl-safe-notary-gate-tx';
import { loadGuosmmNotices } from './omnl-gazette-notices';
function projectRoot(): string {
return (
@@ -83,6 +84,11 @@ export interface ComplianceConsoleSnapshot {
externalVisibility: {
defiLlama: { chainPage: string; pr12094: string; pr19451: string; note: string };
safeDeployments: { pr1568: string; note: string };
guosmmGazette: {
base: string;
apiRegistry: string;
notices: Array<{ documentId: string; title: string; url: string }>;
};
};
explorerBase: string;
}
@@ -280,6 +286,15 @@ export async function buildComplianceConsoleSnapshot(
pr1568: 'https://github.com/safe-global/safe-deployments/pull/1568',
note: 'Safe Wallet npm registry for chain 138',
},
guosmmGazette: {
base: loadGuosmmNotices().gazetteBase,
apiRegistry: '/api/v1/omnl/gazette/notices',
notices: loadGuosmmNotices().notices.map((n) => ({
documentId: n.documentId,
title: n.title,
url: n.url,
})),
},
},
explorerBase: process.env.EXPLORER_PUBLIC_URL?.trim() || 'https://explorer.d-bis.org',
};

View File

@@ -0,0 +1,49 @@
import { readFileSync, existsSync } from 'node:fs';
import { resolve } from 'node:path';
export type GuosmmNotice = {
documentId: string;
series: string;
title: string;
documentType: string;
url: string;
publishedAt: string;
effectiveAt: string;
signingAuthority: string;
contentSha256: string;
[key: string]: unknown;
};
export type GuosmmNoticeRegistry = {
version: string;
gazetteBase: string;
updated: string;
notices: GuosmmNotice[];
};
function repoRoot(): string {
return (
process.env.OMNL_BANK_ROOT?.trim() ||
process.env.PROXMOX_ROOT?.trim() ||
resolve(process.cwd(), '../../..')
);
}
export function loadGuosmmNotices(): GuosmmNoticeRegistry {
const path = resolve(repoRoot(), 'config/guosmm-notices.v1.json');
if (!existsSync(path)) {
return { version: '0', gazetteBase: 'https://gazette.shosjj.org/notices/2026', updated: '', notices: [] };
}
return JSON.parse(readFileSync(path, 'utf8')) as GuosmmNoticeRegistry;
}
export function getGuosmmNotice(documentId: string): GuosmmNotice | null {
const reg = loadGuosmmNotices();
return reg.notices.find((n) => n.documentId === documentId) ?? null;
}
export function listGuosmmNoticesByScope(scope?: string): GuosmmNotice[] {
const reg = loadGuosmmNotices();
if (!scope) return reg.notices;
return reg.notices.filter((n) => Array.isArray(n.scope) && (n.scope as string[]).includes(scope));
}