diff --git a/backend/src/api/public/v1/ossprey/packageList.ts b/backend/src/api/public/v1/ossprey/packageList.ts index 6247a758d1..02e3228cfe 100644 --- a/backend/src/api/public/v1/ossprey/packageList.ts +++ b/backend/src/api/public/v1/ossprey/packageList.ts @@ -5,6 +5,7 @@ import { computeHealthBand, getPackageStatusCounts, listPackagesForApi, + translateActivityContent, } from '@crowd/data-access-layer' import { getPackagesQx } from '@/db/packagesDb' @@ -79,7 +80,11 @@ export async function packageListHandler(req: Request, res: Response): Promise | null lastActivityAt?: Date | null stewards?: StewardEntry[] total: string @@ -470,7 +471,7 @@ export async function listPackagesForApi( opts.includeLastActivity === true ? ` LEFT JOIN LATERAL ( - SELECT sa.activity_type, sa.content, sa.created_at + SELECT sa.activity_type, sa.content, sa.metadata, sa.created_at FROM stewardship_activity sa WHERE sa.stewardship_id = s.id ORDER BY sa.created_at DESC @@ -502,7 +503,7 @@ export async function listPackagesForApi( pm_counts.cnt AS "maintainerCount", r_sc.scorecard_score AS "scorecardScore", p.latest_release_at AS "latestReleaseAt", - ${opts.includeLastActivity === true ? `last_act.activity_type AS "lastActivityType", last_act.content AS "lastActivityContent", last_act.created_at AS "lastActivityAt",` : ''} + ${opts.includeLastActivity === true ? `last_act.activity_type AS "lastActivityType", last_act.content AS "lastActivityContent", last_act.metadata AS "lastActivityMetadata", last_act.created_at AS "lastActivityAt",` : ''} ${opts.includeStewards === true ? "COALESCE(ss_agg.stewards, '[]'::json) AS stewards," : ''} COUNT(*) OVER() AS total FROM packages p diff --git a/services/libs/data-access-layer/src/osspckgs/stewardships.ts b/services/libs/data-access-layer/src/osspckgs/stewardships.ts index 8583d73b67..6577435474 100644 --- a/services/libs/data-access-layer/src/osspckgs/stewardships.ts +++ b/services/libs/data-access-layer/src/osspckgs/stewardships.ts @@ -383,7 +383,11 @@ export async function listStewardshipActivity( actorUserId: row.actorUserId, actorType: row.actorType, activityType: row.activityType, - content: row.content, + content: translateActivityContent( + row.content, + row.activityType, + row.metadata as Record | null, + ), metadata: row.metadata as Record | null, stewardshipStatus: row.stewardshipStatus, createdAt: toIso(row.createdAt), @@ -424,7 +428,11 @@ export async function listPackageHistory( actorUserId: r.actorUserId ? String(r.actorUserId) : null, actorType: String(r.actorType), activityType: String(r.activityType), - content: r.content ? String(r.content) : null, + content: translateActivityContent( + r.content ? String(r.content) : null, + String(r.activityType), + r.metadata as Record | null, + ), metadata: r.metadata as Record | null, createdAt: toIso(r.createdAt), })) @@ -441,6 +449,32 @@ export const ESCALATION_RESOLUTION_PATHS = [ export type EscalationResolutionPath = (typeof ESCALATION_RESOLUTION_PATHS)[number] +export const ESCALATION_RESOLUTION_PATH_LABELS: Record = { + right_of_first_refusal: 'Right of First Refusal', + replace_the_dependency: 'Replace the Dependency', + find_vendor_for_lts: 'Find Vendor for LTS', + consortium_adopts_maintainership: 'Consortium Adopts Maintainership', + compensating_controls_monitor: 'Compensating Controls / Monitor', + namespace_takeover: 'Namespace Takeover', +} + +export function translateActivityContent( + content: string | null, + activityType?: string | null, + metadata?: Record | null, +): string | null { + if (!content) return content + if (activityType === 'escalation' && metadata?.resolutionPath) { + const label = + ESCALATION_RESOLUTION_PATH_LABELS[metadata.resolutionPath as EscalationResolutionPath] + if (label) return `Escalated with resolution path: ${label}` + } + return content.replace(/^(Escalated with resolution path: )(\S+)$/, (_, prefix, key) => { + const label = ESCALATION_RESOLUTION_PATH_LABELS[key as EscalationResolutionPath] + return label ? `${prefix}${label}` : content + }) +} + /** * Escalates a stewardship. Updates status to 'escalated' and logs the * chosen resolution path in stewardship_activity metadata.