@@ -595,6 +595,16 @@ export async function listPackagesForApi(
595595 return { rows, total }
596596}
597597
598+ export type SecurityContactConfidence = 'PRIMARY' | 'SECONDARY' | 'FALLBACK' | 'NONE'
599+
600+ export interface SecurityContactRow {
601+ channel : string
602+ value : string
603+ role : string
604+ confidence : SecurityContactConfidence
605+ score : number
606+ }
607+
598608export interface PackageDetailRow {
599609 id : string
600610 purl : string
@@ -625,6 +635,12 @@ export interface PackageDetailRow {
625635 hasSecurityFile : boolean | null
626636 hasSecurityPolicy : boolean | null
627637 branchProtectionEnabled : boolean | null
638+ pvrEnabled : boolean | null
639+ securityPolicyUrl : string | null
640+ vulnerabilityReportingUrl : string | null
641+ bugBountyUrl : string | null
642+ contactsLastRefreshed : Date | null
643+ securityContacts : SecurityContactRow [ ] | null
628644 // from downloads_last_30d
629645 downloadsLast30d : string | null
630646 maintainerCount : number
@@ -639,6 +655,13 @@ export interface PackageDetailRow {
639655 signalCoverageHealth : Record < string , unknown > | null
640656}
641657
658+ export function securityContactConfidenceBand ( score : number ) : SecurityContactConfidence {
659+ if ( score >= 0.8 ) return 'PRIMARY'
660+ if ( score >= 0.55 ) return 'SECONDARY'
661+ if ( score >= 0.3 ) return 'FALLBACK'
662+ return 'NONE'
663+ }
664+
642665export interface AdvisoryRow {
643666 osvId : string
644667 severity : string
@@ -682,6 +705,21 @@ export async function getPackageDetailByPurl(
682705 r.security_file_enabled AS "hasSecurityFile",
683706 r.security_policy_enabled AS "hasSecurityPolicy",
684707 r.branch_protection_enabled AS "branchProtectionEnabled",
708+ r.pvr_enabled AS "pvrEnabled",
709+ r.security_policy_url AS "securityPolicyUrl",
710+ r.vulnerability_reporting_url AS "vulnerabilityReportingUrl",
711+ r.bug_bounty_url AS "bugBountyUrl",
712+ r.contacts_last_refreshed AS "contactsLastRefreshed",
713+ (
714+ SELECT json_agg(sc ORDER BY sc.score DESC)
715+ FROM (
716+ SELECT channel, value, role, confidence, score
717+ FROM security_contacts
718+ WHERE repo_id = pr.repo_id AND deleted_at IS NULL
719+ ORDER BY score DESC
720+ LIMIT 5
721+ ) sc
722+ ) AS "securityContacts",
685723 -- latest 30-day download count
686724 (
687725 SELECT d.count::text
0 commit comments