Skip to content

Commit 0228f92

Browse files
committed
feat: classify and persist security-contact email reachability
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
1 parent 0597438 commit 0228f92

3 files changed

Lines changed: 31 additions & 2 deletions

File tree

services/apps/packages_worker/src/security-contacts/reconcile.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { classifyEmailReachability, type EmailReachabilityReason } from '@crowd/common'
2+
13
import { scoreContact } from './score'
24
import {
35
ContactChannel,
@@ -56,6 +58,15 @@ function isJunkContact(c: RawContact): boolean {
5658
return false
5759
}
5860

61+
function classifyReachability(c: RawContact): {
62+
reachable: boolean
63+
reachabilityReason: EmailReachabilityReason | null
64+
} {
65+
if (c.channel !== 'email') return { reachable: true, reachabilityReason: null }
66+
const r = classifyEmailReachability(c.value)
67+
return { reachable: r.reachable, reachabilityReason: r.reason }
68+
}
69+
5970
function normalizeValue(channel: ContactChannel, value: string): string {
6071
const v = value.trim()
6172
return channel === 'email' || channel === 'github-handle' ? v.toLowerCase() : v
@@ -130,7 +141,7 @@ export function reconcile(contacts: RawContact[], now: Date = new Date()): Score
130141

131142
const scored: ScoredContact[] = merged.map((c) => {
132143
const contact = { ...c, provenance: dedupeProvenance(c.provenance) }
133-
return { ...contact, ...scoreContact(contact, now) }
144+
return { ...contact, ...scoreContact(contact, now), ...classifyReachability(contact) }
134145
})
135146

136147
scored.sort(

services/apps/packages_worker/src/security-contacts/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { EmailReachabilityReason } from '@crowd/common'
12
import type { SecurityContactConfidence } from '@crowd/data-access-layer/src/osspckgs/api'
23

34
export type ContactChannel = 'email' | 'github-pvr' | 'url' | 'github-handle' | 'web-form'
@@ -30,6 +31,8 @@ export interface RawContact {
3031
export interface ScoredContact extends RawContact {
3132
score: number
3233
confidence: SecurityContactConfidence
34+
reachable: boolean
35+
reachabilityReason: EmailReachabilityReason | null
3336
}
3437

3538
export interface RepoPolicies {

services/apps/packages_worker/src/security-contacts/writeContacts.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,18 @@ export async function writeContacts(
3030
await tx.result(
3131
prepareBulkInsert(
3232
'security_contacts',
33-
['repo_id', 'channel', 'value', 'role', 'name', 'score', 'confidence', 'provenance'],
33+
[
34+
'repo_id',
35+
'channel',
36+
'value',
37+
'role',
38+
'name',
39+
'score',
40+
'confidence',
41+
'provenance',
42+
'reachable',
43+
'reachability_reason',
44+
],
3445
contacts.map((c) => ({
3546
repo_id: repoId,
3647
channel: c.channel,
@@ -40,13 +51,17 @@ export async function writeContacts(
4051
score: c.score,
4152
confidence: c.confidence,
4253
provenance: JSON.stringify(c.provenance),
54+
reachable: c.reachable,
55+
reachability_reason: c.reachabilityReason,
4356
})),
4457
`(repo_id, channel, value) DO UPDATE SET
4558
role = EXCLUDED.role,
4659
name = EXCLUDED.name,
4760
score = EXCLUDED.score,
4861
confidence = EXCLUDED.confidence,
4962
provenance = EXCLUDED.provenance,
63+
reachable = EXCLUDED.reachable,
64+
reachability_reason = EXCLUDED.reachability_reason,
5065
last_refreshed = NOW(),
5166
updated_at = NOW(),
5267
deleted_at = NULL`,

0 commit comments

Comments
 (0)