Crowd.dev Packages API

Package detail — requires read:packages and read:stewardships (see TODO above).

OpenAPI Specification

crowddev-packages-api-openapi.yml Raw ↑
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