Skip to content

Commit 0d90a96

Browse files
ulemonsclaude
andauthored
feat: adding stewardship tables and small fixis (CM-1218) (#4191)
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ac895e0 commit 0d90a96

6 files changed

Lines changed: 224 additions & 37 deletions

File tree

backend/src/api/public/v1/packages/batchGetStewardship.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ok } from '@/utils/api'
55
import { validateOrThrow } from '@/utils/validation'
66

77
import { MOCK_DETAILS } from './mockData'
8+
import type { OpenVulns, StewardshipSummary } from './types'
89

910
const MAX_PURLS = 100
1011

@@ -15,19 +16,6 @@ const bodySchema = z.object({
1516
.max(MAX_PURLS, `Maximum ${MAX_PURLS} purls per request`),
1617
})
1718

18-
interface StewardshipSummary {
19-
name: string
20-
ecosystem: string
21-
lifecycle: string
22-
health: number
23-
impact: number
24-
openVulns: { low: number; medium: number; high: number; critical: number }
25-
stewardship: string
26-
stewards: null
27-
lastActivityAt: null
28-
lastActivityDescription: null
29-
}
30-
3119
// TODO: replace with real DB queries once stewardship tables land
3220
export async function batchGetStewardship(req: Request, res: Response): Promise<void> {
3321
const { purls } = validateOrThrow(bodySchema, req.body)
@@ -38,11 +26,9 @@ export async function batchGetStewardship(req: Request, res: Response): Promise<
3826
if (!detail) {
3927
packages[purl] = null
4028
} else {
41-
const openVulns = { low: 0, medium: 0, high: 0, critical: 0 }
29+
const openVulns: OpenVulns = { low: 0, medium: 0, high: 0, critical: 0 }
4230
for (const advisory of detail.security.advisories) {
43-
if (advisory.severity in openVulns) {
44-
openVulns[advisory.severity] += 1
45-
}
31+
openVulns[advisory.severity] += 1
4632
}
4733
packages[purl] = {
4834
name: detail.name,
@@ -51,8 +37,8 @@ export async function batchGetStewardship(req: Request, res: Response): Promise<
5137
health: detail.general.healthScore.total,
5238
impact: detail.general.impact.impactScore,
5339
openVulns,
54-
stewardship: 'unassigned',
55-
stewards: null,
40+
stewardship: detail.stewardship.status,
41+
stewards: detail.stewardship.stewards,
5642
lastActivityAt: null,
5743
lastActivityDescription: null,
5844
}

backend/src/api/public/v1/packages/listPackages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export async function listPackages(req: Request, res: Response): Promise<void> {
4747
if (ecosystem && p.ecosystem !== ecosystem) return false
4848
if (lifecycle && p.lifecycle !== lifecycle) return false
4949
if (busFactor1Only && p.maintainerBusFactor !== 1) return false
50-
if (unstewardedOnly && p.stewardship !== 'unassigned') return false
50+
if (unstewardedOnly && p.stewardship !== null && p.stewardship !== 'unassigned') return false
5151
if (staleOnly) {
5252
const lastRelease = MOCK_DETAILS[p.purl]?.general.riskSignals.lastRelease
5353
if (!lastRelease || new Date(lastRelease) >= staleThreshold) return false

backend/src/api/public/v1/packages/mockData.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
import type { Lifecycle, OpenVulns, SeverityLevel, Steward, StewardshipStatus } from './types'
2+
13
export interface MockPackageListItem {
24
purl: string
35
name: string
46
ecosystem: string
57
health: number
68
impact: number
7-
lifecycle: 'active' | 'stable' | 'declining' | 'abandoned'
9+
lifecycle: Lifecycle
810
maintainerBusFactor: number
9-
openVulns: { low: number; medium: number; high: number; critical: number }
10-
stewardship: string
11-
steward: null
11+
openVulns: OpenVulns
12+
stewardship: StewardshipStatus | null
13+
stewards: Steward[] | null
1214
}
1315

1416
export interface MockPackageDetail {
@@ -30,19 +32,19 @@ export interface MockPackageDetail {
3032
transitiveReach: string
3133
}
3234
riskSignals: {
33-
lifecycle: string
35+
lifecycle: Lifecycle
3436
maintainerBusFactor: number
3537
lastRelease: string
3638
hasSecurityFile: null
3739
openSSFScorecard: number
3840
}
3941
}
40-
assessment: Record<string, never>
42+
assessment: Record<string, unknown>
4143
security: {
4244
securityContacts: null
4345
advisories: Array<{
4446
osvId: string
45-
severity: 'critical' | 'high' | 'medium' | 'low'
47+
severity: SeverityLevel
4648
resolution: null
4749
}>
4850
cvd: {
@@ -56,7 +58,12 @@ export interface MockPackageDetail {
5658
repositoryMapping: { declaredRepo: string; mappingConfidence: number; lastCommitAt: string }
5759
supplyChainIntegrity: { buildProvenance: null; signedReleases: null }
5860
}
59-
history: Record<string, never>
61+
stewardship: {
62+
status: StewardshipStatus
63+
stewards: Steward[] | null
64+
lastActivityAt: string | null
65+
}
66+
history: Record<string, unknown>
6067
}
6168

6269
export const MOCK_PACKAGES: MockPackageListItem[] = [
@@ -70,7 +77,7 @@ export const MOCK_PACKAGES: MockPackageListItem[] = [
7077
maintainerBusFactor: 1,
7178
openVulns: { low: 0, medium: 0, high: 1, critical: 0 },
7279
stewardship: 'unassigned',
73-
steward: null,
80+
stewards: null,
7481
},
7582
{
7683
purl: 'pkg:maven/org.apache.commons/commons-lang3@3.12.0',
@@ -82,7 +89,7 @@ export const MOCK_PACKAGES: MockPackageListItem[] = [
8289
maintainerBusFactor: 3,
8390
openVulns: { low: 0, medium: 0, high: 0, critical: 0 },
8491
stewardship: 'unassigned',
85-
steward: null,
92+
stewards: null,
8693
},
8794
{
8895
purl: 'pkg:npm/minimist@1.2.6',
@@ -94,7 +101,7 @@ export const MOCK_PACKAGES: MockPackageListItem[] = [
94101
maintainerBusFactor: 1,
95102
openVulns: { low: 0, medium: 1, high: 0, critical: 1 },
96103
stewardship: 'unassigned',
97-
steward: null,
104+
stewards: null,
98105
},
99106
]
100107

@@ -144,6 +151,7 @@ export const MOCK_DETAILS: Record<string, MockPackageDetail> = {
144151
},
145152
supplyChainIntegrity: { buildProvenance: null, signedReleases: null },
146153
},
154+
stewardship: { status: 'unassigned', stewards: null, lastActivityAt: null },
147155
history: {},
148156
},
149157
'pkg:maven/org.apache.commons/commons-lang3@3.12.0': {
@@ -191,6 +199,7 @@ export const MOCK_DETAILS: Record<string, MockPackageDetail> = {
191199
},
192200
supplyChainIntegrity: { buildProvenance: null, signedReleases: null },
193201
},
202+
stewardship: { status: 'unassigned', stewards: null, lastActivityAt: null },
194203
history: {},
195204
},
196205
'pkg:npm/minimist@1.2.6': {
@@ -241,6 +250,7 @@ export const MOCK_DETAILS: Record<string, MockPackageDetail> = {
241250
},
242251
supplyChainIntegrity: { buildProvenance: null, signedReleases: null },
243252
},
253+
stewardship: { status: 'unassigned', stewards: null, lastActivityAt: null },
244254
history: {},
245255
},
246256
}

backend/src/api/public/v1/packages/openapi.yaml

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ components:
105105
StewardshipSummary:
106106
type: object
107107
description: Null if the purl is not found in CDP.
108-
required: [name, ecosystem, stewardship, stewards, lastActivityAt, lastActivityDescription]
108+
required:
109+
[name, ecosystem, stewardship, stewards, openVulns, lastActivityAt, lastActivityDescription]
109110
properties:
110111
name:
111112
type: string
@@ -135,9 +136,11 @@ components:
135136
stewardship:
136137
$ref: '#/components/schemas/StewardshipStatus'
137138
stewards:
138-
description: Single steward or null. Empty in v1.
139+
description: Assigned stewards or null. Empty in v1.
139140
oneOf:
140-
- $ref: '#/components/schemas/Steward'
141+
- type: array
142+
items:
143+
$ref: '#/components/schemas/Steward'
141144
- type: 'null'
142145
lastActivityAt:
143146
type:
@@ -193,10 +196,12 @@ components:
193196
- type: 'null'
194197
stewardship:
195198
$ref: '#/components/schemas/StewardshipStatus'
196-
steward:
197-
description: Single assigned steward or null.
199+
stewards:
200+
description: Assigned stewards or null.
198201
oneOf:
199-
- $ref: '#/components/schemas/Steward'
202+
- type: array
203+
items:
204+
$ref: '#/components/schemas/Steward'
200205
- type: 'null'
201206

202207
# ── Package detail ───────────────────────────────────────────────────────────
@@ -411,6 +416,25 @@ components:
411416
type:
412417
- string
413418
- 'null'
419+
stewardship:
420+
type: object
421+
description: Stewardship state. In v1 always unassigned with no stewards or activity.
422+
properties:
423+
status:
424+
$ref: '#/components/schemas/StewardshipStatus'
425+
stewards:
426+
description: Assigned stewards or null. Null in v1.
427+
oneOf:
428+
- type: array
429+
items:
430+
$ref: '#/components/schemas/Steward'
431+
- type: 'null'
432+
lastActivityAt:
433+
type:
434+
- string
435+
- 'null'
436+
format: date-time
437+
description: Null in v1.
414438
history:
415439
type: object
416440
description: Package history data. Empty in v1.
@@ -657,6 +681,10 @@ paths:
657681
supplyChainIntegrity:
658682
buildProvenance: null
659683
signedReleases: null
684+
stewardship:
685+
status: unassigned
686+
stewards: null
687+
lastActivityAt: null
660688
history: {}
661689
'404':
662690
description: Package not found.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
export type StewardshipStatus =
2+
| 'unassigned'
3+
| 'open'
4+
| 'assessing'
5+
| 'active'
6+
| 'needs_attention'
7+
| 'escalated'
8+
| 'blocked'
9+
| 'inactive'
10+
11+
export type Lifecycle = 'active' | 'stable' | 'declining' | 'abandoned'
12+
13+
export type SeverityLevel = 'critical' | 'high' | 'medium' | 'low'
14+
15+
export interface OpenVulns {
16+
low: number
17+
medium: number
18+
high: number
19+
critical: number
20+
}
21+
22+
export interface Steward {
23+
userId: string
24+
name: string
25+
role: 'lead' | 'co_steward'
26+
assignedAt: string
27+
}
28+
29+
export interface StewardshipSummary {
30+
name: string
31+
ecosystem: string
32+
lifecycle: Lifecycle | null
33+
health: number | null
34+
impact: number | null
35+
openVulns: OpenVulns | null
36+
stewardship: StewardshipStatus | null
37+
stewards: Steward[] | null
38+
lastActivityAt: string | null
39+
lastActivityDescription: string | null
40+
}

0 commit comments

Comments
 (0)