openapi: 3.0.3 info: title: CDP → Akrites External Advisories Dashboard 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: Dashboard description: KPI bar metrics and activity feed. paths: /akrites/metrics: get: operationId: getAkritesMetrics summary: Get KPI bar metrics description: 'Returns aggregate counts that power the global KPI bar on the OSSPREY dashboard (total packages, coverage %, active stewards, unassigned critical, needs-attention, escalated). ' tags: - Dashboard responses: '200': description: Metrics snapshot. content: application/json: schema: $ref: '#/components/schemas/OsspreyMetrics' '401': description: Missing or invalid bearer token. content: application/json: schema: $ref: '#/components/schemas/Error' /akrites/activity: get: operationId: getAkritesActivity summary: Get stewardship activity feed description: 'Returns a paginated, reverse-chronological list of stewardship activity events across all packages (status changes, assignments, escalations, etc.). ' tags: - Dashboard 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 responses: '200': description: Paginated activity feed. content: application/json: schema: allOf: - $ref: '#/components/schemas/PaginationMeta' - type: object required: - rows properties: rows: type: array items: $ref: '#/components/schemas/ActivityEntry' '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' /ossprey/metrics: get: operationId: getOsspreyMetrics summary: Global KPI bar metrics description: 'Returns the seven aggregate metrics shown in the sticky KPI bar across all four dashboard tabs. Fetch once on page load; refresh after any write action. ' tags: - Dashboard security: - BearerAuth: [] responses: '200': description: KPI metrics. content: application/json: schema: type: object required: - totalPackages - criticalPackages - coveragePercent - activeStewards - unassignedCritical - needsAttention - escalated properties: totalPackages: type: integer description: Total critical packages (is_critical = true). example: 1842 criticalPackages: type: integer description: Critical packages with at least one critical-severity advisory. example: 312 coveragePercent: type: number format: float description: 'Percentage of critical packages with status in (assessing, active, needs_attention). One decimal place. ' example: 33.2 coverageTrend: type: - number - 'null' description: 'Percentage-point change vs. previous month. Null until snapshot mechanism is implemented. ' example: null activeStewards: type: integer description: 'COUNT(DISTINCT user_id) from stewardship_stewards where deleted_at IS NULL and stewardship status != inactive. ' example: 42 unassignedCritical: type: integer description: Critical packages with no stewardship row or status = unassigned. example: 1230 needsAttention: type: integer description: Critical packages with status = needs_attention. example: 47 escalated: type: integer description: Critical packages with status = escalated. example: 8 example: totalPackages: 1842 criticalPackages: 312 coveragePercent: 33.2 coverageTrend: null activeStewards: 42 unassignedCritical: 1230 needsAttention: 47 escalated: 8 '401': description: Missing or invalid bearer token. content: application/json: schema: $ref: '#/components/schemas/Error' /ossprey/activity: get: operationId: listStewardshipActivity summary: Paginated stewardship activity feed description: 'Returns recent stewardship events across all packages, ordered by most recent first. Used to populate the activity feed on the Overview tab. The frontend groups items by day using `createdAt`. ' tags: - Dashboard security: - BearerAuth: [] 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 responses: '200': description: Paginated activity feed. content: application/json: schema: type: object required: - rows - total - page - pageSize properties: rows: type: array items: $ref: '#/components/schemas/ActivityFeedItem' total: type: integer example: 142 page: type: integer example: 1 pageSize: type: integer example: 25 example: rows: - id: '9182736' stewardshipId: '4501' packagePurl: pkg:maven/org.slf4j/slf4j-api packageName: slf4j-api packageEcosystem: maven actorUserId: auth0|mock-user-alice actorType: user activityType: state_changed content: Assessment complete, moving to active metadata: from: assessing to: active stewardshipStatus: active createdAt: '2026-06-14T10:23:00Z' total: 11 page: 1 pageSize: 25 '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' components: schemas: PaginationMeta: type: object required: - total - page - pageSize properties: total: type: integer page: type: integer pageSize: type: integer ActivityFeedItem: type: object required: - id - stewardshipId - packagePurl - packageName - packageEcosystem - actorType - activityType - stewardshipStatus - createdAt properties: id: type: string example: '9182736' stewardshipId: type: string example: '4501' packagePurl: type: string example: pkg:npm/minimist@1.2.6 packageName: type: string example: minimist packageEcosystem: type: string example: npm actorUserId: type: - string - 'null' description: Auth0 sub. Null for system events. example: auth0|abc123 actorName: type: - string - 'null' description: 'Display name of the actor. Currently returns actorUserId as a placeholder — will be resolved to a display name once the cross-DB users join is implemented. ' example: auth0|abc123 actorType: type: string enum: - user - system activityType: type: string enum: - state_changed - steward_added - steward_removed - escalation - escalation_resolved - assessment_started - assessment_completed - assessment_flagged - spot_check - note_added example: escalation content: type: - string - 'null' example: 'Escalated with resolution path: right_of_first_refusal' metadata: type: - object - 'null' additionalProperties: true stewardshipStatus: $ref: '#/components/schemas/StewardshipStatus' createdAt: type: string format: date-time OsspreyMetrics: type: object required: - criticalPackages - coveragePercent - coverageTrend - activeStewards - unassignedCritical - needsAttention - escalated properties: criticalPackages: type: integer description: Total number of packages marked as critical (is_critical = true). coveragePercent: type: number format: float description: Percentage of critical packages with an active stewardship (assessing, active, or needs_attention). coverageTrend: type: number format: float nullable: true description: Coverage delta vs. previous period. Currently always null (requires snapshot mechanism). activeStewards: type: integer description: Distinct stewards assigned to a non-inactive stewardship. unassignedCritical: type: integer description: Critical packages with no stewardship or status = unassigned. needsAttention: type: integer description: Critical packages whose stewardship status is needs_attention. escalated: type: integer description: Critical packages whose stewardship status is escalated. 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. ActivityEntry: type: object required: - id - stewardshipId - packagePurl - packageName - packageEcosystem - actorUserId - actorName - actorType - activityType - stewardshipStatus - createdAt properties: id: type: string stewardshipId: type: string packagePurl: type: string packageName: type: string packageEcosystem: type: string actorUserId: type: string nullable: true actorName: type: string nullable: true description: Display name (currently same as actorUserId; resolution from members table is pending). actorType: type: string example: user activityType: type: string example: status_change content: type: string nullable: true metadata: type: object nullable: true additionalProperties: true stewardshipStatus: $ref: '#/components/schemas/StewardshipStatus' createdAt: type: string format: date-time 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 `; 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)