Crowd.dev Stewardships API
Open, assign, escalate, and update stewardship status.
Open, assign, escalate, and update stewardship status.
openapi: 3.0.3
info:
title: CDP → Akrites External Advisories Stewardships 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: Stewardships
description: Open, assign, escalate, and update stewardship status.
paths:
/akrites/stewardships/me/packages:
get:
operationId: getMyPackages
summary: List packages stewarded by the authenticated user
description: 'Returns a paginated list of packages where the authenticated user (`req.actor.id`) is an active steward (`lead` or `co_steward`). Includes package metadata, health, open vulnerabilities, last activity, and the user''s role and stewardship status. The `meta.statusCounts` object always reflects counts across **all** of the user''s stewardships, regardless of the active `status` filter, so the tab bar can render all buckets at once.
'
tags:
- 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: 25
- name: status
in: query
description: Filter by stewardship status.
schema:
type: string
enum:
- assessing
- active
- needs_attention
- escalated
- blocked
- name: search
in: query
description: Case-insensitive substring match on package name or PURL.
schema:
type: string
- name: ecosystem
in: query
schema:
type: string
enum:
- npm
- maven
- pypi
- go
- cargo
- name: healthBand
in: query
schema:
type: string
enum:
- healthy
- fair
- concerning
- critical
- name: vulnSeverity
in: query
description: Filter to packages with at least one vulnerability of this severity or worse.
schema:
type: string
enum:
- high
- critical
- name: sortBy
in: query
schema:
type: string
enum:
- risk
- health
- vulns
- name
- last_activity
default: risk
- name: sortDir
in: query
schema:
type: string
enum:
- asc
- desc
default: desc
responses:
'200':
description: Paginated list of the user's stewarded packages.
content:
application/json:
schema:
type: object
required:
- data
- meta
properties:
data:
type: array
items:
type: object
required:
- purl
- name
- ecosystem
- openVulns
- stewardshipId
- stewardshipStatus
- myRole
properties:
purl:
type: string
example: pkg:npm/minimist
name:
type: string
example: minimist
ecosystem:
type: string
example: npm
lifecycle:
type: string
nullable: true
example: abandoned
healthScore:
type: integer
minimum: 0
maximum: 100
nullable: true
description: Scorecard score scaled to 0–100.
healthBand:
type: string
enum:
- healthy
- fair
- concerning
- critical
openVulns:
type: integer
example: 2
vulnSeverity:
type: string
enum:
- critical
- high
- medium
- low
nullable: true
description: Worst open vulnerability severity.
lastActivityDescription:
type: string
nullable: true
example: Escalated for intervention
lastActivityAt:
type: string
format: date-time
nullable: true
stewardshipId:
type: string
example: '42'
stewardshipStatus:
type: string
enum:
- assessing
- active
- needs_attention
- escalated
- blocked
myRole:
type: string
enum:
- lead
- co_steward
meta:
type: object
required:
- total
- page
- pageSize
- statusCounts
properties:
total:
type: integer
page:
type: integer
pageSize:
type: integer
statusCounts:
type: object
required:
- assessing
- active
- needs_attention
- escalated
- blocked
properties:
assessing:
type: integer
active:
type: integer
needs_attention:
type: integer
escalated:
type: integer
blocked:
type: integer
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites/stewardships/me/activity:
get:
operationId: getMyActivity
summary: Latest activity feed for the authenticated user's stewardships
description: 'Returns the most recent stewardship activity events scoped to packages where the authenticated user is an active steward. Results are **deduplicated by stewardship** — only the single most recent event per package is returned — and sorted newest-first. Designed to power the "Latest activity" strip on the My Stewardships page. Default `pageSize` is 3 (one card per attention-needed status); increase for a "load more" experience.
'
tags:
- 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: 3
- name: status
in: query
description: 'Comma-separated list of stewardship statuses to filter. Example: `needs_attention,blocked,escalated,assessing`
'
schema:
type: string
responses:
'200':
description: Deduplicated activity feed for the user's stewardships.
content:
application/json:
schema:
type: object
required:
- data
- meta
properties:
data:
type: array
items:
type: object
required:
- stewardshipId
- packageName
- purl
- packageEcosystem
- stewardshipStatus
- activityType
- createdAt
properties:
stewardshipId:
type: string
example: '42'
packageName:
type: string
example: jackson-databind
purl:
type: string
example: pkg:maven/com.fasterxml.jackson.core/jackson-databind
packageEcosystem:
type: string
example: maven
stewardshipStatus:
type: string
enum:
- assessing
- active
- needs_attention
- escalated
- blocked
- unassigned
- open
- inactive
activityType:
type: string
example: advisory_detected
description:
type: string
nullable: true
example: New security advisory detected
createdAt:
type: string
format: date-time
suggestedAction:
type: string
nullable: true
description: Label for the primary CTA button on the activity card.
example: Review & respond
meta:
type: object
required:
- total
- page
- pageSize
properties:
total:
type: integer
page:
type: integer
pageSize:
type: integer
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites/stewardships/open:
post:
operationId: openStewardship
summary: Open a stewardship for a package
description: 'Creates a new stewardship record for the package identified by the given PURL, setting its status to `open`. The authenticated user is recorded as the actor who opened it.
'
tags:
- Stewardships
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- purl
properties:
purl:
type: string
description: Must start with `pkg:`.
example: pkg:npm/%40angular/core@17.0.0
responses:
'200':
description: Stewardship opened.
content:
application/json:
schema:
type: object
required:
- stewardship
properties:
stewardship:
$ref: '#/components/schemas/StewardshipRecord'
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Package not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites/stewardships/{id}/assign:
post:
operationId: assignSteward
summary: Assign a steward to a stewardship
description: 'Assigns a user as a steward (lead or co-steward) for the given stewardship. Optionally transitions the stewardship status to `assessing` in the same operation.
'
tags:
- Stewardships
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- userId
- role
properties:
userId:
type: string
description: Auth0 sub of the user to assign.
example: auth0|abc123
role:
type: string
enum:
- lead
- co_steward
note:
type: string
minLength: 1
description: Optional note stored in the steward_added activity metadata.
moveToAssessing:
type: boolean
default: false
description: 'When true, automatically transitions stewardship status to `assessing` after assignment.
'
responses:
'200':
description: Steward assigned.
content:
application/json:
schema:
type: object
required:
- stewardship
- stewards
properties:
stewardship:
$ref: '#/components/schemas/StewardshipRecord'
stewards:
type: array
items:
$ref: '#/components/schemas/StewardEntry'
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Stewardship not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites/stewardships/{id}/escalate:
post:
operationId: escalateStewardship
summary: Escalate a stewardship
description: 'Transitions the stewardship to `escalated` status and records the chosen resolution path. Optionally attaches a free-text note.
'
tags:
- Stewardships
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- resolutionPath
properties:
resolutionPath:
$ref: '#/components/schemas/EscalationResolutionPath'
notes:
type: string
minLength: 1
responses:
'200':
description: Stewardship escalated.
content:
application/json:
schema:
type: object
required:
- stewardship
properties:
stewardship:
$ref: '#/components/schemas/StewardshipRecord'
'400':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Stewardship not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/akrites/stewardships/{id}/status:
patch:
operationId: updateStewardshipStatus
summary: Update stewardship status
description: 'Updates the stewardship status. Valid target statuses are: `assessing`, `active`, `needs_attention`, `blocked`, `inactive`. When setting `inactive`, `inactiveReason` is required.
'
tags:
- Stewardships
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- status
properties:
status:
type: string
enum:
- assessing
- active
- needs_attention
- blocked
- inactive
inactiveReason:
$ref: '#/components/schemas/InactiveReason'
description: Required when status is `inactive`.
notes:
type: string
minLength: 1
responses:
'200':
description: Stewardship status updated.
content:
application/json:
schema:
type: object
required:
- stewardship
properties:
stewardship:
$ref: '#/components/schemas/StewardshipRecord'
'400':
description: 'Validation error. Also returned when `status` is `inactive` but `inactiveReason` is missing.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Stewardship not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
InactiveReason:
type: string
enum:
- quarterly_cadence_missed
- stepped_down
- no_longer_critical
EscalationResolutionPath:
type: string
enum:
- right_of_first_refusal
- replace_the_dependency
- find_vendor_for_lts
- consortium_adopts_maintainership
- compensating_controls_monitor
- namespace_takeover
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
example: VALIDATION_ERROR
message:
type: string
example: Invalid query parameter.
StewardshipRecord:
type: object
required:
- id
- packageId
- status
- origin
- version
- createdAt
- updatedAt
properties:
id:
type: string
packageId:
type: string
status:
$ref: '#/components/schemas/StewardshipStatus'
origin:
type: string
version:
type: integer
openedAt:
type: string
format: date-time
nullable: true
lastStatusAt:
type: string
format: date-time
nullable: true
inactiveReason:
$ref: '#/components/schemas/InactiveReason'
nullable: true
resolutionPath:
$ref: '#/components/schemas/EscalationResolutionPath'
nullable: true
statusNote:
type: string
nullable: true
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
StewardEntry:
type: object
required:
- id
- stewardshipId
- userId
- role
- assignedAt
properties:
id:
type: string
stewardshipId:
type: string
userId:
type: string
name:
type: string
nullable: true
role:
type: string
enum:
- lead
- co_steward
assignedAt:
type: string
format: date-time
assignedBy:
type: string
nullable: true
StewardshipStatus:
type: string
enum:
- unassigned
- open
- assessing
- active
- needs_attention
- escalated
- blocked
- inactive
securitySchemes:
M2MBearer:
type: oauth2
description: 'Auth0 machine-to-machine client-credentials flow. Akrites exchanges its client ID/secret with Auth0 for a JWT and sends it as `Authorization: Bearer <token>`; CDP only verifies the resulting token.
'
flows:
clientCredentials:
tokenUrl: https://linuxfoundation.auth0.com/oauth/token
scopes:
read:packages: Read package detail
read:stewardships: Read package stewardship data
read:maintainer-roles: Read security contacts (interim scope for Contacts; see the Contacts tag)