kyd-shared-badge 0.2.10 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyd-shared-badge",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "private": false,
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -239,12 +239,24 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
239
239
  <div className="space-y-8">
240
240
  <div>
241
241
  <h4 className={'text-xl font-bold mb-4'} style={{ color: 'var(--text-main)' }}>Sanctions & Watchlists</h4>
242
- <AppendixTables
243
- type="sanctions"
244
- sources={[...(screening_sources.ofac_lists || []), ...(screening_sources.additional_watchlists || [])]}
245
- searchedAt={updatedAt}
246
- developerName={developerName || 'this developer'}
247
- />
242
+ {(() => {
243
+ const ofacProvided = screening_sources.ofac_screen?.sources || [];
244
+ const lists = [...(screening_sources.ofac_lists || []), ...ofacProvided];
245
+ const seen: { [k: string]: boolean } = {};
246
+ const dedup: string[] = [];
247
+ for (let i = 0; i < lists.length; i++) {
248
+ const val = lists[i];
249
+ if (!seen[val]) { seen[val] = true; dedup.push(val); }
250
+ }
251
+ return (
252
+ <AppendixTables
253
+ type="sanctions"
254
+ sources={dedup}
255
+ searchedAt={updatedAt}
256
+ developerName={developerName || 'this developer'}
257
+ />
258
+ );
259
+ })()}
248
260
  </div>
249
261
  <div>
250
262
  <h4 className={'text-xl font-bold mb-4'} style={{ color: 'var(--text-main)' }}>Country-specific Entity Affiliations</h4>
@@ -6,6 +6,7 @@ import { DomainCSVRow } from '../types';
6
6
  interface SanctionSource {
7
7
  issuingEntity: string;
8
8
  listName: string;
9
+ matched?: boolean;
9
10
  }
10
11
 
11
12
  interface DomainSource {
@@ -25,7 +26,7 @@ interface AppendixTableProps {
25
26
  }
26
27
 
27
28
  const SanctionsRow = ({ source, searchedAt, developerName }: { source: SanctionSource, searchedAt: string, developerName: string }) => (
28
- <tr className={'transition-colors hover:bg-black/5'}>
29
+ <tr className={'transition-colors hover:bg-black/5'} style={source.matched ? { backgroundColor: 'rgba(236,102,98,0.08)' } : undefined}>
29
30
  <td className={'px-4 py-4 whitespace-nowrap text-sm font-medium'} style={{ color: 'var(--text-main)' }}>
30
31
  {source.issuingEntity}
31
32
  </td>
@@ -36,12 +37,20 @@ const SanctionsRow = ({ source, searchedAt, developerName }: { source: SanctionS
36
37
  {searchedAt}
37
38
  </td>
38
39
  <td className={'px-4 py-4 whitespace-nowrap text-sm'} style={{ color: 'var(--text-secondary)' }}>
39
- <span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' }}>
40
- Not Found
41
- </span>
40
+ {source.matched ? (
41
+ <span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'rgba(236,102,98,0.2)', color: 'var(--text-main)' }}>
42
+ Match
43
+ </span>
44
+ ) : (
45
+ <span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' }}>
46
+ Not Found
47
+ </span>
48
+ )}
42
49
  </td>
43
50
  <td className={'px-4 py-4 text-sm whitespace-normal'} style={{ color: 'var(--text-secondary)' }}>
44
- No exact match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> (based on name and email) was found on this list.
51
+ {source.matched
52
+ ? (<span>Exact or strong match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)
53
+ : (<span>No exact match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)}
45
54
  </td>
46
55
  </tr>
47
56
  );
@@ -77,9 +86,12 @@ const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedA
77
86
  : ["Country", "Entity Type", "Entity/Domain", "Searched On", "Value", "Findings"];
78
87
 
79
88
  const parsedSources = type === 'sanctions'
80
- ? (sources as string[]).map(sourceString => {
81
- const parts = sourceString.split(':');
82
- return { issuingEntity: parts[0].trim(), listName: parts.slice(1).join(':').trim() };
89
+ ? (sources as any[]).map((src: any) => {
90
+ if (typeof src === 'string') {
91
+ const parts = src.split(':');
92
+ return { issuingEntity: parts[0].trim(), listName: parts.slice(1).join(':').trim(), matched: false } as SanctionSource;
93
+ }
94
+ return src as SanctionSource;
83
95
  })
84
96
  : (sources as DomainCSVRow[]).map(s => ({
85
97
  country: s.Country,
@@ -88,7 +100,11 @@ const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedA
88
100
  url: s.URL,
89
101
  }));
90
102
 
91
- const visibleParsedSources = parsedSources.slice(0, visibleCount);
103
+ const sortedParsedSources = (type === 'sanctions')
104
+ ? (parsedSources as SanctionSource[]).slice().sort((a, b) => (b.matched === true ? 1 : 0) - (a.matched === true ? 1 : 0))
105
+ : parsedSources;
106
+
107
+ const visibleParsedSources = sortedParsedSources.slice(0, visibleCount);
92
108
 
93
109
  const handleLoadMore = () => {
94
110
  setVisibleCount(currentCount => currentCount + PAGE_SIZE);
package/src/types.ts CHANGED
@@ -156,6 +156,12 @@ export interface AssessmentResult {
156
156
  risk_profile_domains: DomainCSVRow[];
157
157
  additional_watchlists?: string[];
158
158
  ip_risk_analysis?: IpRiskAnalysis;
159
+ ofac_screen?: {
160
+ checked?: boolean;
161
+ sources?: string[];
162
+ matches?: any[];
163
+ };
164
+ sanctions_sources_detailed?: { issuingEntity: string; listName: string; matched?: boolean }[];
159
165
  };
160
166
  optOutScreening?: boolean;
161
167
  clientMetadata?: ClientMetadata;