From 1cb3a83500e172638f4b887d349ef897aa6b03a9 Mon Sep 17 00:00:00 2001 From: UttyWotty <105616324+UttyWotty@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:02:20 +0900 Subject: [PATCH 1/2] feat(site): watchlist monitoring and integrity checks [v0.29.0] The site described what we collect, not what we built for the buyers: the watchlist subscription and the procurement integrity checks. Methods only; no firm named. Co-Authored-By: Claude Opus 5.5 (1M context) --- CHANGELOG.md | 20 ++++++++++++++++++++ VERSION | 2 +- src/components/Fraud.astro | 17 +++++++++++++++++ src/components/Procurement.astro | 17 +++++++++++++++++ src/i18n/fraud.ts | 27 ++++++++++++++++++++++++++- src/i18n/home.ts | 8 ++++---- src/i18n/procurement.ts | 25 +++++++++++++++++++++++++ 7 files changed, 110 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1ec99e..4317310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Routine `stats.json` refreshes take a PATCH version bump but are grouped rather than listed individually. +## [0.29.0] - 2026-09-25 + +### Added + +- **Fraud page: *Watchlist monitoring*** (EN, KO) — identifiers the buyer + hands over, checked nightly against the whole collection; baseline versus + new; a count-only mail with the detail behind the buyer's own sign-in; a + monthly one-page summary; and what "not seen" does not mean. Turkish + carries no section: that market is not sold. +- **Procurement page: *Integrity checks*** (EN, KO) — related bidders who + meet in tenders, closed companies still bidding (국세청 status), priced + bids and awards only (anonymised entrants left out), 법인 only. Methods + only; no firm is named. +- Home cards for fraud and procurement mention the two. + +### Note + +- The Korean copy was written by the agent and needs a native read before + it is merged. + ## [0.28.2] - 2026-09-22 ### Changed diff --git a/VERSION b/VERSION index 987e7c6..ae6dd4e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.28.9 \ No newline at end of file +0.29.0 diff --git a/src/components/Fraud.astro b/src/components/Fraud.astro index f10ceea..8763ff7 100644 --- a/src/components/Fraud.astro +++ b/src/components/Fraud.astro @@ -30,6 +30,23 @@ const n = copy.numbers; +{copy.watch && ( +
+
{copy.watch.heading}
+

{copy.watch.lead}

+
+ {copy.watch.blocks.map((b) => ( +
+
+

{b.title}

+

{b.body}

+
+ ))} +
+

{copy.watch.note}

+
+)} +
{copy.coverage.heading}

{copy.coverage.lead}

diff --git a/src/components/Procurement.astro b/src/components/Procurement.astro index d1ea01e..e59bc59 100644 --- a/src/components/Procurement.astro +++ b/src/components/Procurement.astro @@ -61,6 +61,23 @@ const { copy, locale } = Astro.props;
+{copy.integrity && ( +
+
{copy.integrity.heading}
+

{copy.integrity.lead}

+
+ {copy.integrity.blocks.map((b) => ( +
+
+

{b.title}

+

{b.body}

+
+ ))} +
+

{copy.integrity.note}

+
+)} +
{copy.how.heading}

{copy.how.body}

diff --git a/src/i18n/fraud.ts b/src/i18n/fraud.ts index 2368d81..73a0521 100644 --- a/src/i18n/fraud.ts +++ b/src/i18n/fraud.ts @@ -18,6 +18,9 @@ export interface FraudCopy { description: string; hero: { eyebrow: string; title: string; lead: string; live: string; primary: string }; what: { heading: string; lead: string; blocks: Block[] }; + // Optional: the watchlist subscription (2026-09-25). Rendered only where a + // locale carries it; Turkish does not, because the TR market is not sold. + watch?: { heading: string; lead: string; blocks: Block[]; note: string }; coverage: { heading: string; lead: string; blocks: Block[] }; numbers: { heading: string; lead: string; entities: string; bank: string; phone: string; crypto: string; clusters: string }; delivery: { heading: string; body: string }; @@ -48,6 +51,17 @@ export const fraud: Record = { { title: 'Deliver', body: 'Machine-readable watchlists (CSV, MISP IOC), bank-specific alert feeds, STIX bundles, an authenticated REST API and webhooks for SIEM/SOAR, and evidence-grade reports with confidence scoring, audit trails and legal reference mappings for every finding.' }, ], }, + watch: { + heading: 'Watchlist monitoring', + lead: 'Hand over the identifiers you care about — accounts, phone numbers, wallets, channels. Every night they are checked against everything the platform collects, and you are told when something new appears.', + blocks: [ + { title: 'Your list, checked nightly', body: 'Paste a list once. Each identifier is read the way it was written — a number that could be a phone or a bank account is watched as both — and checked against the whole collection every night.' }, + { title: 'Baseline, then news', body: 'What the platform already knew when you added an identifier is shown as the baseline. Only what arrives afterwards counts as new, so an alert means something changed.' }, + { title: 'Counts by mail, detail behind your sign-in', body: 'The nightly mail says how many new records appeared — never which identifier. The detail, with the record behind every link, is on the console behind your own sign-in.' }, + { title: 'One page a month', body: 'A monthly one-page summary per list: what was watched, what the platform knows, what changed and of what kind — ready to print or file.' }, + ], + note: '"Not seen" means the platform has not observed an identifier in what it collects. It does not mean the identifier is clean.', + }, coverage: { heading: 'Coverage', lead: 'Active collection across the markets below; Turkish-language ecosystems are monitored and can be scoped into a subscription.', @@ -71,7 +85,7 @@ export const fraud: Record = { }, delivery: { heading: 'How it arrives', - body: 'Nightly. A subscription is scoped to your market and your watchlist and arrives by email or webhook: new entities, escalations and networks that have gone quiet — scored, deduplicated, evidence attached. Curated feeds, bank risk briefs and the managed intelligence package are scoped per buyer. Pricing on request.', + body: 'Nightly. A subscription is scoped to your market and your watchlist and arrives by email or webhook: new entities, escalations and networks that have gone quiet — scored, deduplicated, evidence attached. A watchlist subscription adds your own identifiers to the nightly check. Curated feeds, bank risk briefs and the managed intelligence package are scoped per buyer. Pricing on request.', }, contact: { heading: 'Get in touch', @@ -103,6 +117,17 @@ export const fraud: Record = { { title: '전달', body: '기계 판독 가능한 감시 목록(CSV, MISP IOC), 은행별 알림 피드, STIX 번들, 인증된 REST API와 SIEM/SOAR용 웹훅, 그리고 모든 발견 사항에 신뢰도 점수·감사 추적·법적 참조를 담은 증거 수준 보고서.' }, ], }, + watch: { + heading: '워치리스트 모니터링', + lead: '관심 있는 계좌, 전화번호, 지갑 주소, 채널을 알려주시면 매일 밤 플랫폼이 수집한 전체 데이터와 대조하고, 새로운 기록이 생기면 알려드립니다.', + blocks: [ + { title: '매일 밤 확인하는 목록', body: '목록은 한 번만 등록하면 됩니다. 각 식별자는 입력된 형태 그대로 읽으며, 전화번호와 계좌번호 둘 다로 해석될 수 있는 번호는 두 가지 모두로 감시하고, 매일 밤 전체 수집 데이터와 대조합니다.' }, + { title: '기준선, 그리고 새 기록', body: '등록 시점에 플랫폼이 이미 알고 있던 내용은 기준선으로 표시하고, 그 이후에 들어온 것만 새 기록으로 셉니다. 알림이 왔다면 실제로 무언가 바뀌었다는 뜻입니다.' }, + { title: '메일은 건수만, 상세는 로그인 후', body: '매일 밤 메일에는 새 기록의 건수만 담기며, 어떤 식별자인지는 적지 않습니다. 각 연결의 근거 기록을 포함한 상세 내용은 본인 로그인 후 콘솔에서 확인합니다.' }, + { title: '월 1페이지 요약', body: '목록별 월간 1페이지 요약: 감시 대상, 플랫폼이 파악한 대상, 변화의 건수와 종류를 정리해 출력하거나 보관할 수 있습니다.' }, + ], + note: '"미확인"은 플랫폼이 수집 범위에서 해당 식별자를 관측하지 못했다는 뜻이며, 문제가 없다는 뜻은 아닙니다.', + }, coverage: { heading: '커버리지', lead: '아래 시장에서 적극적으로 수집합니다. 터키어 생태계는 모니터링 중이며 구독 범위에 포함할 수 있습니다.', diff --git a/src/i18n/home.ts b/src/i18n/home.ts index b3822c4..4dcfdfd 100644 --- a/src/i18n/home.ts +++ b/src/i18n/home.ts @@ -54,14 +54,14 @@ export const home: Record = { fraud: { badge: 'Fraud', title: 'Fraud Intelligence', - body: 'Telegram and OSINT monitoring of criminal and grey-market ecosystems — financial crime, illegal betting, drug trafficking and laundering — delivered as feeds, alerts and evidence-grade reports.', + body: 'Telegram and OSINT monitoring of criminal and grey-market ecosystems — financial crime, illegal betting, drug trafficking and laundering — delivered as feeds, alerts, evidence-grade reports and a nightly watchlist of your own identifiers.', action: 'Request a sample report →', href: '/fraud', }, procurement: { badge: 'Procurement', title: 'Procurement Intelligence', - body: 'Every Korean public tender, bidder and winning price — against the published estimate. Collected nightly, nationwide, not sampled.', + body: 'Every Korean public tender, bidder and winning price — against the published estimate. Collected nightly, nationwide, not sampled — and read for integrity: related bidders, and closed companies still bidding.', action: 'See what we collect →', href: '/procurement', }, @@ -132,14 +132,14 @@ export const home: Record = { fraud: { badge: '사기', title: '사기 인텔리전스', - body: '텔레그램과 OSINT로 범죄·회색시장 생태계를 모니터링합니다 — 금융범죄, 불법도박, 마약, 자금세탁 — 피드, 알림, 증거 수준 보고서로 전달합니다.', + body: '텔레그램과 OSINT로 범죄·회색시장 생태계를 모니터링합니다 — 금융범죄, 불법도박, 마약, 자금세탁 — 피드, 알림, 증거 수준 보고서, 그리고 고객이 지정한 식별자를 매일 밤 확인하는 워치리스트로 전달합니다.', action: '샘플 보고서 요청 →', href: '/ko/fraud', }, procurement: { badge: '공공조달', title: '공공조달 인텔리전스', - body: '한국 공공입찰의 모든 공고, 입찰자, 낙찰가를 기초금액과 비교합니다. 매일 밤 전국 단위로 수집하며, 표본이 아닙니다.', + body: '한국 공공입찰의 모든 공고, 입찰자, 낙찰가를 기초금액과 비교합니다. 매일 밤 전국 단위로 수집하며, 표본이 아닙니다. 관계 업체의 반복 동반 투찰, 폐업 후 입찰 같은 청렴성 점검도 함께 실행합니다.', action: '수집 항목 보기 →', href: '/ko/procurement', }, diff --git a/src/i18n/procurement.ts b/src/i18n/procurement.ts index 274338b..6ff84ce 100644 --- a/src/i18n/procurement.ts +++ b/src/i18n/procurement.ts @@ -20,6 +20,9 @@ export interface ProcurementCopy { problem: { heading: string; body: string }; collect: { heading: string; lead: string; liveBadge: string; blocks: Block[] }; coverage: { heading: string; blocks: Block[] }; + // Optional: the integrity checks (2026-09-25) -- methods only, no firm is + // ever named on the site. + integrity?: { heading: string; lead: string; blocks: Block[]; note: string }; how: { heading: string; body: string; platform: string }; figures: { heading: string; lead: string; more: string; moreLink: string; rateTitle: string; rateNote: string; dailyTitle: string; noticesLabel: string; awardsLabel: string; tableLabel: string; awardsCol: string; medianCol: string; rangeCol: string; dateCol: string }; calculator: { @@ -88,6 +91,17 @@ export const procurement: Record = { tableLabel: 'Show as a table', awardsCol: 'Awards', medianCol: 'Median', rangeCol: 'p25–p75', dateCol: 'Date', }, + integrity: { + heading: 'Integrity checks', + lead: 'The same record, read for the questions an auditor asks. Each check runs nightly across every corporate bidder and winner, and every result shows the public records it rests on.', + blocks: [ + { title: 'Related bidders who meet in tenders', body: 'Two firms the corporate registry links — the same 대표이사 or the same registered address — that keep bidding on the same notices. A competition question for the buying agency, not a finding of wrongdoing; whether a shared name is one person is settled only by 법인등기.' }, + { title: 'Closed companies still bidding', body: 'A firm the National Tax Service (국세청) holds as closed that bid on, or won, a tender after its closing date — or a dormant firm still bidding. A status fact from the state set beside the tender record, not an inference.' }, + { title: 'Only what is published by name', body: 'A check counts priced bids and awards — the entries an agency publishes by name. Where an agency lists unplaced entrants anonymously, as in design competitions, they are left out, even when the open data carries them.' }, + { title: 'Companies only', body: 'Checks run on corporate (법인) records. Sole proprietors (개인사업자) are withheld: their records identify a person.' }, + ], + note: 'Every result is a question for the agency that holds the documents. None is an accusation.', + }, how: { heading: 'How it is built', body: 'A deterministic pipeline: collect the public procurement record nightly, normalize it, key it per lot and per company, flag implausible figures, and report — every output traceable to the published record it came from. Built on public and free-tier sources.', @@ -188,6 +202,17 @@ export const procurement: Record = { tableLabel: '표로 보기', awardsCol: '낙찰', medianCol: '중앙값', rangeCol: 'p25–p75', dateCol: '날짜', }, + integrity: { + heading: '청렴성 점검', + lead: '같은 기록을 감사의 관점에서 읽습니다. 모든 점검은 매일 밤 전체 법인 입찰·낙찰 업체를 대상으로 실행되며, 각 결과에는 근거가 된 공개 기록이 함께 표시됩니다.', + blocks: [ + { title: '같은 공고에서 반복해 만나는 관계 업체', body: '공시(DART) 정보상 대표이사 또는 등록 주소가 같은 두 업체가 같은 공고에 반복해서 투찰하는 경우입니다. 발주기관이 확인할 경쟁성의 문제이며 위법 판단이 아닙니다. 같은 이름이 동일인인지는 법인등기부로만 확정됩니다.' }, + { title: '폐업 후에도 입찰하는 업체', body: '국세청이 폐업으로 관리하는 업체가 폐업일 이후 입찰에 참여하거나 낙찰받은 경우, 또는 휴업 중인 업체가 입찰한 경우입니다. 추정이 아니라 국세청 상태 정보와 입찰 기록을 나란히 놓은 사실입니다.' }, + { title: '이름이 공개된 참여만', body: '가격을 제출한 투찰과 낙찰만 셉니다. 설계공모처럼 발주기관이 미입상 참가자를 익명으로 공개하는 경우에는, 공개 데이터에 이름이 남아 있더라도 제외합니다.' }, + { title: '법인만', body: '점검은 법인 기록에만 적용합니다. 개인사업자 정보는 개인을 식별할 수 있어 제외합니다.' }, + ], + note: '모든 결과는 관련 문서를 보유한 발주기관이 확인할 질문이며, 어떤 결과도 고발이 아닙니다.', + }, how: { heading: '어떻게 만드는가', body: '결정론적 파이프라인: 매일 밤 공공조달 기록을 수집하고, 정규화하고, 건별·업체별로 키를 부여하고, 비정상 수치를 표시하고, 보고합니다 — 모든 출력은 그것이 나온 공개 기록으로 추적됩니다. 공개 및 무료 데이터 소스로 구축했습니다.', From 66f2e428aa6b4f81d3c66eb091b4916e1785122a Mon Sep 17 00:00:00 2001 From: UttyWotty <105616324+UttyWotty@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:06:06 +0900 Subject: [PATCH 2/2] style(site): space the section notes from the cards [v0.29.1] Co-Authored-By: Claude Opus 5.5 (1M context) --- CHANGELOG.md | 7 +++++++ VERSION | 2 +- src/components/Fraud.astro | 2 +- src/components/Procurement.astro | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4317310..164b2e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Routine `stats.json` refreshes take a PATCH version bump but are grouped rather than listed individually. +## [0.29.1] - 2026-09-25 + +### Fixed + +- The closing note under *Watchlist monitoring* and *Integrity checks* sat + flush against the last card; it now has the section's spacing. + ## [0.29.0] - 2026-09-25 ### Added diff --git a/VERSION b/VERSION index ae6dd4e..25939d3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.29.0 +0.29.1 diff --git a/src/components/Fraud.astro b/src/components/Fraud.astro index 8763ff7..ac841fd 100644 --- a/src/components/Fraud.astro +++ b/src/components/Fraud.astro @@ -43,7 +43,7 @@ const n = copy.numbers; ))} -

{copy.watch.note}

+

{copy.watch.note}

)} diff --git a/src/components/Procurement.astro b/src/components/Procurement.astro index e59bc59..da45094 100644 --- a/src/components/Procurement.astro +++ b/src/components/Procurement.astro @@ -74,7 +74,7 @@ const { copy, locale } = Astro.props; ))} -

{copy.integrity.note}

+

{copy.integrity.note}

)}