import { createHash } from 'node:crypto'; import { createRequire } from 'node:module'; const { parseProxyConfig, proxyConnectTunnel, proxyFetch, } = createRequire(import.meta.url)('../_proxy-utils.cjs'); export const CROSS_STRAIT_ACTIVITY_KEY = 'military:cross-strait-activity:v1'; export const MND_MAX_LIST_PAGES_PER_BACKFILL_RUN = 11; export const MND_MAX_DETAIL_REQUESTS_PER_RUN = 20; export const MND_REFRESH_DETAIL_REQUESTS_PER_RUN = 3; export const MND_REQUIRED_REPORTING_DAYS = 91; export const MND_RETENTION_REPORTING_DAYS = 365; export const MND_MAX_REVISION_VINTAGES_PER_DAY = 20; export const CROSS_STRAIT_ACTIVITY_MAX_SERIALIZED_BYTES = 4 * 1024 * 1024; /** * Reasons that justify reporting a source as durably blocked rather than * failing. Both mean no configured transport path can reach the publisher, so * retained reviewed records are the best obtainable truth and health must not * be pinned on an outage that will never clear on its own. Every consumer that * branches on `blockedReason` reads this list — widening it in one place only * is how a new reason silently degrades to `error`. */ export const CROSS_STRAIT_BLOCKED_SOURCE_REASONS = Object.freeze([ 'HTTP_403', 'PROXY_TARGET_FORBIDDEN', ]); const USER_AGENT = 'WorldMonitor/2.10 (+https://worldmonitor.app)'; const MND_LIST_URL = 'https://www.mnd.gov.tw/en/news/plaactlist'; const JMOD_INDEX_URL = 'https://www.mod.go.jp/js/press/index-en.html'; const MND_MAX_RESPONSE_BYTES = 131_072; const JMOD_MAX_RESPONSE_BYTES = 524_288; const REQUEST_TIMEOUT_MS = 20_000; const REQUEST_CADENCE_MS = 200; const MND_SEED_FETCH_DEADLINE_MS = 240_000; const MND_PERSISTENCE_HEADROOM_MS = 40_000; export const MND_OUTBOUND_BUDGET_MS = MND_SEED_FETCH_DEADLINE_MS - MND_PERSISTENCE_HEADROOM_MS; const MND_REFRESH_ROTATION_INTERVAL_MS = 3 * 60 * 60 * 1_000; const DAY_MS = 86_400_000; const MAX_PERSISTED_STRING_LENGTH = 2_048; const MAX_SOURCE_URL_LENGTH = 512; const PROXY_DIAGNOSTIC_MAX_CHARS = 256; function monotonicNow() { return globalThis.performance.now(); } export const CROSS_STRAIT_SOURCE_CONTRACTS = Object.freeze({ taiwanMnd: Object.freeze({ id: 'taiwan-mnd', publisher: 'Taiwan Ministry of National Defense', publisherType: 'official_government', publisherReference: Object.freeze({ id: 'publisher:taiwan-mnd', registrySourceType: 'gov', propagandaRisk: 'high', }), launchStatus: 'launched', listUrl: MND_LIST_URL, allowedHosts: ['www.mnd.gov.tw'], redirectPolicy: 'error', maxResponseBytes: MND_MAX_RESPONSE_BYTES, maxListPagesPerBackfillRun: MND_MAX_LIST_PAGES_PER_BACKFILL_RUN, maxDetailRequestsPerRun: MND_MAX_DETAIL_REQUESTS_PER_RUN, requestCadenceMs: REQUEST_CADENCE_MS, preflight: Object.freeze({ environment: 'railway-production', checkedAt: '2026-07-25', reachable: true, redirectCount: 0, observedListStatus: 200, observedDetailStatus: 206, largestObservedBytes: 39_046, }), }), japanMod: Object.freeze({ id: 'japan-mod', publisher: 'Japan Joint Staff', publisherType: 'official_government', publisherReference: Object.freeze({ id: 'publisher:japan-joint-staff', registrySourceType: 'gov', propagandaRisk: 'high', }), launchStatus: 'launched_reviewed_only', indexUrl: JMOD_INDEX_URL, allowedHosts: ['www.mod.go.jp'], redirectPolicy: 'error', maxResponseBytes: JMOD_MAX_RESPONSE_BYTES, requestCadenceMs: REQUEST_CADENCE_MS, // Documents the fixed one-direct-then-one-proxy flow hard-coded in // fetchJapanIndexOutcome; these bounds are not read back to drive it. maxRequestsPerRun: 2, maxDirectRequestsPerRun: 1, maxProxyRequestsPerRun: 1, fallbackPolicy: 'direct_then_proxy_on_transport_failure', documentAdmission: 'manual_review_required', runtimePdfRequestsPerRun: 0, // A proxy CONNECT refusal is emitted before the tunnel reaches Japan MOD, // so on its own it cannot separate "this provider forbids this destination" // from "the proxy is down for everything". One CONNECT-only control tunnel // to a host we already contract with settles that, and is torn down without // sending a byte — so it is transport telemetry, not a source request, and // it deliberately targets a host other than the one under test. proxyControlProbeHost: 'www.mnd.gov.tw', maxProxyControlProbesPerRun: 1, preflight: Object.freeze({ environment: 'railway-production', checkedAt: '2026-07-26', reachable: false, redirectCount: 0, observedIndexStatus: 403, }), }), }); function known(value) { return { status: 'known', value }; } function unknown(reason) { return { status: 'unknown', reason }; } function notApplicable(reason) { return { status: 'not_applicable', reason }; } function publisherReference(sourceId) { const source = Object.values(CROSS_STRAIT_SOURCE_CONTRACTS) .find((candidate) => candidate.id === sourceId); if (!source) throw new Error('UNKNOWN_CROSS_STRAIT_SOURCE'); return { id: source.publisherReference.id, name: source.publisher, type: source.publisherType, registryReference: { sourceName: source.publisher, sourceType: source.publisherReference.registrySourceType, propagandaRisk: source.publisherReference.propagandaRisk, }, }; } function buildProvenance({ signalId, sourceId, sourceUrl, referenceId, reportingTime, publicationTime, retrievalTime, revision, supersession = { state: 'current' }, extractionConfidence, classificationConfidence, }) { const observationPrecision = /^\d{4}-\d{2}-\d{2}$/.test(reportingTime) ? 'day' : 'instant'; const publicationPrecision = /^\d{4}-\d{2}-\d{2}$/.test(publicationTime) ? 'day' : 'instant'; return { contractVersion: 'decision-signal-provenance/v1', signalId, familyId: 'operational_activity_record', claims: { publisher: known(publisherReference(sourceId)), source_url: known(sourceUrl), original_reference: known({ kind: 'document', id: referenceId, }), original_language: known('en'), translation: known({ state: 'not_translated' }), observation_time: known({ role: 'observation', value: reportingTime, precision: observationPrecision, }), effective_time: unknown('Publisher reports an observation window, not a separate effective time'), publication_time: known({ role: 'publication', value: publicationTime, precision: publicationPrecision, }), retrieval_time: known({ role: 'retrieval', value: retrievalTime, precision: 'instant', }), revision: known(revision), supersession: known(supersession), extraction_confidence: known(extractionConfidence), classification_confidence: known(classificationConfidence), corroboration: known({ state: 'single_source', sourceSignalIds: [signalId], }), transport_freshness: known({ state: 'fresh', assessedAt: retrievalTime, lastSuccessAt: retrievalTime, }), content_freshness: known({ state: 'current', assessedAt: retrievalTime, contentAsOf: reportingTime, }), derivation: notApplicable('Publisher activity records are not derived WorldMonitor outputs'), }, }; } function stableHash(value) { return createHash('sha256').update(JSON.stringify(value)).digest('hex'); } function sourceReferenceId(sourceUrl) { const parsed = new URL(sourceUrl); return parsed.pathname.split('/').filter(Boolean).at(-1) ?? parsed.pathname; } function buildReviewedJapanObservation({ documentId, sourceUrl, reportingDay, reportingTime, reportingPeriod, publicationTime, categories, originalTerminology, summary, }) { const id = `japan-mod:${documentId}`; const vintageId = stableHash({ sourceUrl, reportingTime, categories, originalTerminology }); const signalId = `cross-strait:${id}:v1`; const retrievalTime = '2026-07-25T08:30:00.000Z'; const revision = { vintageId, sequence: 1, state: 'original' }; return Object.freeze({ id, sourceId: 'japan-mod', observationKind: 'reviewed_regional_augmentation', reportingDay, reportingPeriod, publicationTime, retrievalTime, categories, originalTerminology, summary, sourceUrl, originalLanguage: 'en', translation: { state: 'not_translated' }, revision, contentHash: vintageId, history: [], provenance: buildProvenance({ signalId, sourceId: 'japan-mod', sourceUrl, referenceId: documentId, reportingTime, publicationTime, retrievalTime, revision, extractionConfidence: { score: 1, method: 'human-reviewed-official-document-v1' }, classificationConfidence: { score: 1, method: 'human-reviewed-activity-category-v1' }, }), }); } export const REVIEWED_JAPAN_MOD_OBSERVATIONS = Object.freeze([ buildReviewedJapanObservation({ documentId: 'p20260724_05e', sourceUrl: 'https://www.mod.go.jp/js/pdf/2026/p20260724_05e.pdf', reportingDay: '2026-07-21', reportingTime: '2026-07-20T21:00:00.000Z', reportingPeriod: { start: '2026-07-20T21:00:00.000Z', end: '2026-07-20T21:00:00.000Z', timezone: 'Asia/Tokyo', utcOffset: '+09:00', semantics: 'publisher-stated-observation-time', }, publicationTime: '2026-07-24', categories: { plaAircraft: null, planShips: 3, russianNavyShips: 1, }, originalTerminology: { planShips: 'PLAN Renhai-class DDG x 1; PLAN Luyang-III-class DDG x 1; PLAN Fuchi-class AOR x 1', russianNavyShips: 'RFN Steregushchiy-class FFG x 1', }, summary: 'JMSDF reported three PLAN vessels and one Russian Navy vessel southeast of Minami-iwo-to.', }), buildReviewedJapanObservation({ documentId: 'p20260708_01e', sourceUrl: 'https://www.mod.go.jp/js/pdf/2026/p20260708_01e.pdf', reportingDay: '2026-07-06', reportingTime: '2026-07-06', reportingPeriod: { start: '2026-07-06', end: '2026-07-06', timezone: 'Asia/Tokyo', utcOffset: '+09:00', semantics: 'publisher-stated-afternoon-observation', }, publicationTime: '2026-07-08', categories: { plaAircraft: 1, planShips: null, russianNavyShips: null, }, originalTerminology: { plaAircraft: 'Y-9 intelligence-gathering aircraft x 1', }, summary: 'JASDF reported one Chinese Y-9 intelligence-gathering aircraft over the East China Sea.', }), ]); const HTML_HIDDEN_CONTENT_ELEMENTS = new Set([ 'audio', 'canvas', 'datalist', 'iframe', 'meter', 'noembed', 'noframes', 'noscript', 'progress', 'rp', 'script', 'style', 'template', 'title', 'video', ]); const HTML_RAW_TEXT_ELEMENTS = new Set([ 'iframe', 'noembed', 'noframes', 'noscript', 'script', 'style', 'textarea', 'title', 'xmp', ]); const HTML_VOID_ELEMENTS = new Set([ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr', ]); const HTML_P_IMPLICIT_CLOSE_STARTS = new Set([ 'address', 'article', 'aside', 'blockquote', 'center', 'details', 'dialog', 'dir', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'search', 'section', 'summary', 'table', 'ul', ]); const HTML_ELEMENT_SCOPE_BOUNDARIES = new Set([ 'annotation-xml', 'applet', 'caption', 'desc', 'foreignobject', 'html', 'marquee', 'mi', 'mn', 'mo', 'ms', 'mtext', 'object', 'table', 'td', 'template', 'th', 'title', ]); const HTML_BUTTON_SCOPE_BOUNDARIES = new Set([ ...HTML_ELEMENT_SCOPE_BOUNDARIES, 'button', ]); const HTML_TAG_SPECIFIC_END_ELEMENTS = new Set([ 'address', 'article', 'aside', 'blockquote', 'button', 'center', 'details', 'dialog', 'dir', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'li', 'listing', 'main', 'menu', 'nav', 'ol', 'pre', 'search', 'section', 'summary', 'ul', ]); const HTML_SPECIAL_ELEMENTS = new Set([ ...HTML_TAG_SPECIFIC_END_ELEMENTS, ...HTML_ELEMENT_SCOPE_BOUNDARIES, 'area', 'base', 'basefont', 'bgsound', 'body', 'br', 'col', 'colgroup', 'dd', 'dt', 'embed', 'frame', 'frameset', 'head', 'hr', 'iframe', 'img', 'input', 'link', 'meta', 'noembed', 'noframes', 'noscript', 'param', 'plaintext', 'script', 'select', 'source', 'style', 'tbody', 'textarea', 'tfoot', 'thead', 'tr', 'track', 'wbr', 'xmp', ]); function startTagImplicitlyCloses(openElement, tag) { // Only recover paragraph omission here. Other optional-end-tag rules are // scope-sensitive (for example a nested
  • inside