Crowd.dev Packages API
Package detail — requires read:packages and read:stewardships (see TODO above).
Package detail — requires read:packages and read:stewardships (see TODO above).
openapi: 3.0.3
info:
title: CDP → Akrites External Advisories Packages API
version: 0.1.0
description: 'Read-only external API exposing CDP package security data to the Akrites service. Authenticated via Auth0 M2M client-credentials — CDP only verifies the resulting access token; the assertion exchange happens entirely between Akrites and Auth0.
Packages, Advisories and Contacts endpoints are implemented. Blast Radius is specced separately and not yet built.
TODO: scopes below (read:packages, read:stewardships) are the existing internal CDP UI scopes, reused here for now. Swap for a dedicated cdp:packages:read scope once Akrites gets its own Auth0 M2M scopes per the akrites-external draft contract.
'
servers:
- url: https://cm.lfx.dev/api/v1
description: Production
security:
- M2MBearer:
- read:packages
- read:stewardships
tags:
- name: Packages
description: Package detail — requires read:packages and read:stewardships (see TODO above).
paths:
/akrites-external/packages/detail:
get:
operationId: getPackageDetail
summary: Get package detail by PURL
tags:
- Packages
security:
- M2MBearer:
- read:packages
- read:stewardships
parameters:
- name: purl
in: query
required: true
schema:
type: string
example: pkg:npm/%40angular/core
responses:
'200':
description: Package detail.
content:
application/json:
schema:
$ref: '#/components/schemas/PackageDetail'
'400':
description: Malformed purl.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Token missing read:packages or read:stewardships scope.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Package not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites-external/packages/detail:batch:
post:
operationId: getPackageDetailBatch
summary: Bulk package detail lookup
tags:
- Packages
security:
- M2MBearer:
- read:packages
- read:stewardships
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- purls
properties:
purls:
type: array
minItems: 1
maxItems: 100
items:
type: string
page:
type: integer
minimum: 1
default: 1
pageSize:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: One page of results, in request order.
content:
application/json:
schema:
type: object
required:
- page
- pageSize
- total
- results
properties:
page:
type: integer
pageSize:
type: integer
total:
type: integer
description: Total number of requested purls, across all pages.
results:
type: array
items:
$ref: '#/components/schemas/PackageDetailBulkEntry'
'400':
description: Validation error (empty array, >100 items, malformed purl).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Token missing read:packages or read:stewardships scope.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites/packages:
get:
operationId: listAkritesPackages
summary: List packages with stewardship data
description: 'Paginated list of critical packages enriched with stewardship status, vulnerability counts, health band, and the latest stewardship activity. Supports rich filtering and sorting.
'
tags:
- Packages
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: pageSize
in: query
schema:
type: integer
minimum: 1
maximum: 250
default: 25
- name: ecosystem
in: query
schema:
type: string
- name: lifecycle
in: query
schema:
type: string
enum:
- active
- stable
- declining
- abandoned
- name: name
in: query
description: Substring match on package name.
schema:
type: string
- name: status
in: query
schema:
$ref: '#/components/schemas/StewardshipStatus'
- name: healthBand
in: query
schema:
$ref: '#/components/schemas/HealthBand_2'
- name: vulnSeverity
in: query
description: 'Filter by highest open vulnerability severity present on the package. `none` returns packages with zero vulnerabilities; `any` disables the filter.
'
schema:
type: string
enum:
- any
- high
- critical
- none
- name: staleOnly
in: query
schema:
type: boolean
default: false
- name: unstewardedOnly
in: query
schema:
type: boolean
default: false
- name: busFactor1Only
in: query
description: Return only packages whose maintainer count is 1.
schema:
type: boolean
default: false
- name: sortBy
in: query
schema:
type: string
enum:
- name
- risk
- impact
- openVulns
- health
default: risk
- name: sortDir
in: query
schema:
type: string
enum:
- asc
- desc
default: desc
responses:
'200':
description: Paginated package list.
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PaginationMeta'
- type: object
required:
- rows
- statusCounts
properties:
rows:
type: array
items:
$ref: '#/components/schemas/PackageListRow'
statusCounts:
$ref: '#/components/schemas/StatusCounts'
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/akrites/packages/scatter:
get:
operationId: getAkritesPackagesScatter
summary: Get risk matrix scatter data
description: 'Returns all critical packages as scatter-plot points with impact score (x-axis) and health score (y-axis). No pagination — the full dataset is returned.
'
tags:
- Packages
responses:
'200':
description: Scatter plot dataset.
content:
application/json:
schema:
type: object
required:
- points
- total
properties:
points:
type: array
items:
$ref: '#/components/schemas/ScatterPoint'
total:
type: integer
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/akrites/packages/metrics:
get:
operationId: getAkritesPackagesMetrics
summary: Get package count metrics
description: 'Returns total and critical package counts. Lighter alternative to `/akrites/metrics` when only package-level counts are needed.
'
tags:
- Packages
responses:
'200':
description: Package count metrics.
content:
application/json:
schema:
$ref: '#/components/schemas/PackageMetrics'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/akrites/packages/detail:
get:
operationId: getAkritesPackageDetail
summary: Get package detail
description: 'Returns the full detail view for a single package identified by its PURL, including risk signals, security advisories, repository provenance, and current stewardship state.
'
tags:
- Packages
parameters:
- name: purl
in: query
required: true
description: 'Package URL (PURL) — must start with `pkg:`. Version qualifiers are normalised server-side.
'
schema:
type: string
example: pkg:npm/%40angular/core@17.0.0
responses:
'200':
description: Package detail.
content:
application/json:
schema:
$ref: '#/components/schemas/PackageDetail_2'
'400':
description: Validation error (malformed purl).
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'404':
description: Package not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/akrites/packages/advisories:
get:
operationId: getAkritesPackageAdvisories
summary: Get advisories for a package
description: 'Returns a paginated list of security advisories for a single package identified by PURL. Intended for lazy-loading the Security tab in the package detail drawer.
'
tags:
- Packages
parameters:
- name: purl
in: query
required: true
description: Package URL (PURL) — must start with `pkg:`.
schema:
type: string
example: pkg:npm/%40angular/core@17.0.0
- name: page
in: query
required: false
description: Page number (1-based).
schema:
type: integer
minimum: 1
default: 1
- name: pageSize
in: query
required: false
description: Number of advisories per page (max 100).
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: severity
in: query
required: false
description: Filter by severity. Accepts comma-separated values or multiple params.
schema:
type: array
items:
type: string
enum:
- critical
- high
- moderate
- low
- name: resolution
in: query
required: false
description: Filter by resolution status. Accepts comma-separated values or multiple params.
schema:
type: array
items:
type: string
enum:
- open
- patched
- name: critical
in: query
required: false
description: Filter by criticality flag (CVSS >= 7.0).
schema:
type: boolean
responses:
'200':
description: Paginated advisory list.
content:
application/json:
schema:
type: object
required:
- page
- pageSize
- total
- advisories
properties:
page:
type: integer
pageSize:
type: integer
total:
type: integer
advisories:
type: array
items:
$ref: '#/components/schemas/Advisory'
'400':
description: Validation error (malformed purl).
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'404':
description: Package not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/akrites/packages/history:
get:
operationId: getAkritesPackageHistory
summary: Get stewardship history for a package
description: 'Returns the full activity log for the stewardship associated with the given PURL, ordered newest-first. Returns an empty list if no stewardship exists. Intended for lazy-loading the History tab in the package detail drawer.
'
tags:
- Packages
parameters:
- name: purl
in: query
required: true
description: Package URL (PURL) — must start with `pkg:`.
schema:
type: string
example: pkg:npm/%40angular/core@17.0.0
responses:
'200':
description: Stewardship activity history.
content:
application/json:
schema:
type: object
required:
- events
- total
properties:
events:
type: array
items:
$ref: '#/components/schemas/PackageHistoryEvent'
total:
type: integer
'400':
description: Validation error (malformed purl).
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'404':
description: Package not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/akrites/packages:batch-stewardship:
post:
operationId: batchGetStewardship
summary: Batch stewardship lookup by PURL
description: 'Given up to 100 PURLs, returns a map of `purl → stewardship summary` for each. Missing packages are returned as `null`. Useful for enriching external package listings with CDP stewardship state.
'
tags:
- Packages
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- purls
properties:
purls:
type: array
minItems: 1
maxItems: 100
items:
type: string
description: Must start with `pkg:`.
example: pkg:npm/%40angular/core@17.0.0
responses:
'200':
description: Per-purl stewardship map.
content:
application/json:
schema:
type: object
required:
- packages
properties:
packages:
type: object
description: 'Keys are the original PURLs from the request. Values are null when the package is not found in CDP.
'
additionalProperties:
oneOf:
- $ref: '#/components/schemas/PackageStewardshipSummary'
- type: 'null'
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_2'
/ossprey/packages:
get:
operationId: listOsspreyPackages
summary: Filtered paginated package list
description: "Returns a paginated, filtered, sorted list of critical packages with their stewardship state and risk signals.\n\nUsed by three tabs:\n- **Queue tab** — full table with all filters\n- **Triage Board** — one request per status column, fired in parallel\n (`?status=X&pageSize=50`)\n\n- **Summary panel** — click-through navigates to Queue with pre-filled filter\n\nThe response always includes `statusCounts` — per-status counts computed without the active `status` filter, used to drive the tab bar badge numbers.\n"
tags:
- Packages
security:
- BearerAuth: []
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: pageSize
in: query
schema:
type: integer
minimum: 1
maximum: 250
default: 25
- name: name
in: query
description: Case-insensitive substring search on package name.
schema:
type: string
- name: ecosystem
in: query
description: Filter by package ecosystem. Not validated server-side — any ecosystem stored in the DB is accepted.
schema:
type: string
- name: lifecycle
in: query
schema:
type: string
enum:
- active
- stable
- declining
- abandoned
- archived
- name: status
in: query
description: 'Filter by stewardship status. `unassigned` includes packages with no stewardship row (s.id IS NULL).
'
schema:
$ref: '#/components/schemas/StewardshipStatus'
- name: healthBand
in: query
schema:
$ref: '#/components/schemas/HealthBand_3'
- name: vulnSeverity
in: query
description: '`any` = at least one open advisory · `high` = worst rank ≥ HIGH · `critical` = worst rank = CRITICAL · `none` = zero advisories.
'
schema:
type: string
enum:
- any
- high
- critical
- none
- name: staleOnly
in: query
description: Return only packages with no release in ≥ 18 months.
schema:
type: boolean
default: false
- name: unstewardedOnly
in: query
description: Return only packages with status = unassigned or no stewardship row.
schema:
type: boolean
default: false
- name: busFactor1Only
in: query
description: Return only packages with exactly one maintainer.
schema:
type: boolean
default: false
- name: sortBy
in: query
schema:
type: string
enum:
- risk
- name
- impact
- openVulns
- health
default: risk
- name: sortDir
in: query
schema:
type: string
enum:
- asc
- desc
default: desc
responses:
'200':
description: Paginated package list.
content:
application/json:
schema:
type: object
required:
- rows
- total
- page
- pageSize
- statusCounts
properties:
rows:
type: array
items:
$ref: '#/components/schemas/PackageRow'
total:
type: integer
example: 1842
page:
type: integer
example: 1
pageSize:
type: integer
example: 25
statusCounts:
$ref: '#/components/schemas/StatusCounts_2'
example:
rows:
- purl: pkg:maven/org.slf4j/slf4j-api
name: slf4j-api
ecosystem: maven
criticalityScore: 0.998
impact: 100
stewardshipId: '101'
stewardshipStatus: active
openVulns: 0
maxVulnSeverity: null
maintainerCount: 2
scorecardScore: 7.5
health:
score: 75
label: healthy
lifecycle: active
latestReleaseAt: '2026-04-10T00:00:00Z'
lastActivity:
type: state_changed
content: Assessment complete, moving to active
at: '2026-06-01T10:00:00Z'
stewards:
- userId: auth0|mock-user-alice
role: lead
assignedAt: '2026-01-15T09:00:00Z'
total: 9
page: 1
pageSize: 25
statusCounts:
all: 9
unassigned: 1
open: 1
assessing: 1
active: 2
needs_attention: 1
escalated: 1
blocked: 1
inactive: 1
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_3'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_3'
/ossprey/packages/scatter:
get:
operationId: getOsspreyPackagesScatter
summary: Scatter plot data for the Risk Matrix tab
description: 'Returns all packages where `is_critical = true AND has_critical_vulnerability = true` as lightweight data points for the health-vs-impact scatter plot. No pagination — this filter set is expected to stay around 2 000 packages. Ordered by `impact DESC`.
Dot color is determined by `stewardshipStatus`. Legend checkboxes toggle visibility client-side — no additional API calls needed.
'
tags:
- Packages
security:
- BearerAuth: []
responses:
'200':
description: Scatter plot data points.
content:
application/json:
schema:
type: object
required:
- points
- total
properties:
points:
type: array
items:
$ref: '#/components/schemas/ScatterPoint_2'
total:
type: integer
description: 'Count of packages matching the filter (is_critical = true AND has_critical_vulnerability = true). Equals points.length — no separate count query.
'
example: 2000
example:
points:
- purl: pkg:maven/org.slf4j/slf4j-api
name: slf4j-api
criticalityScore: 100
healthScore: 75
healthBand: healthy
stewardshipStatus: active
stewardshipId: '101'
openVulns: 0
advisoryCount: 0
- purl: pkg:maven/com.fasterxml.jackson.core/jackson-databind
name: jackson-databind
criticalityScore: 99
healthScore: 0
healthBand: critical
stewardshipStatus: needs_attention
stewardshipId: '102'
openVulns: 2
advisoryCount: 2
total: 2000
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_3'
/packages:
get:
operationId: listPackages
summary: List packages
tags:
- Packages
security:
- M2MBearer:
- read:packages
- read:stewardships
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: pageSize
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: ecosystem
in: query
schema:
type: string
- name: lifecycle
in: query
schema:
type: string
enum:
- active
- stable
- declining
- abandoned
- archived
- name: busFactor1Only
in: query
schema:
type: boolean
default: false
description: Return only packages with bus factor = 1.
- name: staleOnly
in: query
schema:
type: boolean
default: false
description: Return only packages with no release in >= 18 months.
- name: unstewardedOnly
in: query
schema:
type: boolean
default: false
description: Return only packages with stewardship = unassigned.
- name: sortBy
in: query
schema:
type: string
enum:
- name
- health
- impact
- openVulns
default: name
- name: sortDir
in: query
schema:
type: string
enum:
- asc
- desc
default: asc
responses:
'200':
description: Paginated list of packages.
content:
application/json:
schema:
type: object
required:
- page
- pageSize
- total
- filters
- sort
- packages
properties:
page:
type: integer
pageSize:
type: integer
total:
type: integer
filters:
type: object
properties:
ecosystem:
type:
- string
- 'null'
lifecycle:
type:
- string
- 'null'
busFactor1Only:
type: boolean
staleOnly:
type: boolean
unstewardedOnly:
type: boolean
sort:
type: object
properties:
by:
type: string
dir:
type: string
packages:
type: array
items:
$ref: '#/components/schemas/PackageListItem'
'400':
description: Validation error (e.g. invalid query parameters).
content:
application/json:
schema:
$ref: '#/components/schemas/Error_4'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_4'
'403':
description: Insufficient scopes.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_4'
/packages/metrics:
get:
operationId: getPackagesMetrics
summary: Overview metrics for the list page header
tags:
- Packages
security:
- M2MBearer:
- read:packages
- read:stewardships
responses:
'200':
description: Aggregate package metrics.
content:
application/json:
schema:
$ref: '#/components/schemas/PackagesMetrics'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_4'
'403':
description: Insufficient scopes.
content:
application/json:
schema:
$ref: '#/components/schemas/Error_4'
/packages/detail:
get:
operationId: getPackage
summary: Get full package detail
description: 'Returns data for the drawer''s Overview, Security, and Provenance tabs. Pass the canonical purl as a query parameter — no URL-encoding needed. Example: `?purl=pkg:npm/lodash@4.17.21`.
'
tags:
- Packages
security:
- M2MBearer:
- read:packages
- read:stewardships
parameters:
- name: purl
in: query
required: true
schema:
type: string
example: pkg:npm/lodash@4.17.21
responses:
'200':
description: Package found.
content:
application/json:
schema:
$ref: '#/components/schemas/PackageDetail_3'
example:
purl: pkg:npm/lodash
name: lodash
ecosystem: npm
general:
healthScore: 18
healthScoreDetails:
total: 18
label: critical
maintainerHealth: 4
securitySupplyChain: 8
developmentActivity: 6
healthBand: critical
impact:
impactScore: 71
downloadsLastMonth: 52142891
dependentPackages: 142312
dependentRepos: 39104
transitiveReach: Top 0.4%
riskSignals:
lifecycle: declining
maintainerBusFactor: 1
lastRelease: '2021-02-20T00:00:00Z'
hasSecurityFile: null
openSSFScorecard: 5.2
assessment: {}
security:
securityContacts: null
advisories:
- osvId: CVE-2021-44906
severity: high
resolution: null
cvd:
isPvrEnabled: null
# --- truncated at 32 KB (75 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/crowddev/refs/heads/main/openapi/crowddev-packages-api-openapi.yml