// OFAC — US Treasury Office of Foreign Assets Control Sanctions // No auth required. Monitors the Specially Designated Nationals (SDN) list // and consolidated sanctions list for changes. const EXPORTS_BASE = 'https://sanctionslistservice.ofac.treas.gov/api/PublicationPreview/exports'; // SDN list endpoints const SDN_XML_URL = `${EXPORTS_BASE}/SDN.XML`; const SDN_ADVANCED_URL = `${EXPORTS_BASE}/SDN_ADVANCED.XML`; const CONS_ADVANCED_URL = `${EXPORTS_BASE}/CONS_ADVANCED.XML`; // Parse basic info from SDN XML (publish date, entry count) function parseSDNMetadata(xml) { if (!xml || xml.error) return { error: xml?.error || 'No data returned' }; const raw = xml.rawText || ''; // Extract publish date const publishDate = raw.match(/(.*?)<\/Publish_Date>/)?.[1] || raw.match(/(.*?)<\/publish_date>/i)?.[1] || null; // Count SDN entries const entryMatches = raw.match(//gi); const entryCount = entryMatches ? entryMatches.length : null; // Extract record count if present const recordCount = raw.match(/(.*?)<\/Record_Count>/)?.[1] || raw.match(/(.*?)<\/records_count>/i)?.[1] || null; return { publishDate, entryCount, recordCount: recordCount ? parseInt(recordCount, 10) : null, hasData: raw.length > 0, dataSize: raw.length, }; } // Fetch SDN list metadata (smaller initial chunk via timeout) export async function getSDNMetadata() { const data = await fetchXmlSnippet(SDN_XML_URL); return parseSDNMetadata(data); } // Fetch advanced SDN data (includes more structured info) export async function getSDNAdvanced() { const data = await fetchXmlSnippet(SDN_ADVANCED_URL); return parseSDNMetadata(data); } // Fetch consolidated list metadata export async function getConsolidatedMetadata() { const data = await fetchXmlSnippet(CONS_ADVANCED_URL); return parseSDNMetadata(data); } // Parse recent SDN entries from XML snippet function parseRecentEntries(xml) { if (!xml || xml.error) return []; const raw = xml.rawText || ''; const entries = []; const entryRegex = /([\s\S]*?)<\/sdnEntry>/gi; let match; let count = 0; while ((match = entryRegex.exec(raw)) !== null && count < 20) { const content = match[1]; const uid = content.match(/(.*?)<\/uid>/i)?.[1]; const lastName = content.match(/(.*?)<\/lastName>/i)?.[1]; const firstName = content.match(/(.*?)<\/firstName>/i)?.[1]; const sdnType = content.match(/(.*?)<\/sdnType>/i)?.[1]; // Extract programs const programs = []; const progRegex = /(.*?)<\/program>/gi; let progMatch; while ((progMatch = progRegex.exec(content)) !== null) { programs.push(progMatch[1]); } if (uid || lastName) { entries.push({ uid, name: [firstName, lastName].filter(Boolean).join(' '), type: sdnType, programs, }); count++; } } return entries; } // Briefing — report on sanctions list status and metadata export async function briefing() { const [sdnMeta, advancedMeta, advancedSnippet] = await Promise.all([ getSDNMetadata(), getSDNAdvanced(), fetchXmlSnippet(SDN_ADVANCED_URL, { maxBytes: 256_000 }), ]); const sampleEntries = parseRecentEntries(advancedSnippet); return { source: 'OFAC Sanctions', timestamp: new Date().toISOString(), lastUpdated: sdnMeta.publishDate || advancedMeta.publishDate || 'unknown', sdnList: { publishDate: sdnMeta.publishDate, entryCount: sdnMeta.entryCount, recordCount: sdnMeta.recordCount, dataAvailable: sdnMeta.hasData, }, advancedList: { publishDate: advancedMeta.publishDate, entryCount: advancedMeta.entryCount, recordCount: advancedMeta.recordCount, dataAvailable: advancedMeta.hasData, }, sampleEntries: sampleEntries.slice(0, 10), endpoints: { sdnXml: SDN_XML_URL, sdnAdvanced: SDN_ADVANCED_URL, consolidatedAdvanced: CONS_ADVANCED_URL, }, }; } async function fetchXmlSnippet(url, opts = {}) { const timeout = opts.timeout || 9000; const maxBytes = opts.maxBytes || 128_000; const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeout); try { const res = await fetch(url, { headers: { 'User-Agent': 'Crucix/2.0', 'Range': `bytes=0-${maxBytes - 1}`, }, signal: controller.signal, }); if (!res.ok && res.status !== 206) { const body = await res.text().catch(() => ''); return { error: `HTTP ${res.status}: ${body.slice(0, 160)}` }; } if (!res.body?.getReader) { const text = await res.text(); return { rawText: text.slice(0, maxBytes) }; } const reader = res.body.getReader(); const chunks = []; let bytes = 0; while (bytes < maxBytes) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); bytes += value.byteLength; } await reader.cancel().catch(() => {}); const buffer = Buffer.concat(chunks.map(chunk => Buffer.from(chunk)), bytes); return { rawText: buffer.toString('utf8', 0, Math.min(bytes, maxBytes)) }; } catch (error) { return { error: error.name === 'AbortError' ? `OFAC snippet request timed out after ${timeout}ms` : error.message }; } finally { clearTimeout(timer); } } // Run standalone if (process.argv[1]?.endsWith('ofac.mjs')) { const data = await briefing(); console.log(JSON.stringify(data, null, 2)); }