Skip to content

feat: add security contacts api (CM-1336)#4354

Merged
ulemons merged 2 commits into
mainfrom
feat/security-contacts-api-akrites
Jul 16, 2026
Merged

feat: add security contacts api (CM-1336)#4354
ulemons merged 2 commits into
mainfrom
feat/security-contacts-api-akrites

Conversation

@ulemons

@ulemons ulemons commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds two new read-only Akrites-external endpoints — GET /akrites-external/contacts/detail and POST /akrites-external/contacts/detail:batch — exposing per-package security-contact info (reporting channels, confidence, repo security-policy/PVR/bug-bounty URLs) so external Akrites consumers can look up how to report a vulnerability for a given package.

Changes

  • New route group contacts in akrites-external/index.ts, gated behind READ_MAINTAINER_ROLES (interim stand-in for the not-yet-issued cdp:maintainers:read Auth0 scope — flagged with a TODO to swap once available). Deliberately not reachable via the existing packages scope, since these rows carry contact PII (e.g. reporter emails).
  • New DAL query getContactDetailsByPurls (services/libs/data-access-layer/src/osspckgs/api.ts) joining packages → best-linked repos → aggregated security_contacts.
  • New AkritesExternalContactDetailRow type composed via Pick<PackageDbRow, ...> & Pick<RepoDbRow, ...> (ADR-0006: DB schema row types as source of truth, no hand-declared shapes).
  • New schema-aligned row types in @crowd/types/src/db/: RepoDbRow (full repos table, including all ALTER TABLE columns added by later migrations) and SecurityContactDbRow/SecurityContactConfidence (moved out of the DAL, where they previously lived ad hoc).
  • New backend mapper toAkritesExternalContactDetail translating internal shapes to the public contract:
    • Per-contact confidence band reuses the internal PRIMARY/SECONDARY/FALLBACK/NONE scale verbatim.
    • Aggregate overallConfidenceBand uses a different contract-mandated scale (HIGH/MEDIUM/LOW/NONE); the crosswalk between the two is a straightforward 4→4 rename but is flagged UNCONFIRMED pending sign-off from Akrites/product (see akrites-api-questions-for-joana.md).
    • Several contract fields (targetOrganizationName, bugBountyProgramFlag, reportingMethods, reportingGuidelines, integrationHints) are reserved but not yet backed by stored data — typed as null so a future non-null shape requires an explicit, reviewed change.
  • GET .../detail and POST .../detail:batch handlers following the same shape as the existing packages/advisories endpoints (Zod-validated purl(s), 404 on no match for the single-detail route, found/not-found entries for the batch route).
  • OpenAPI spec updated for both endpoints.
  • Integration tests for getContactDetailsByPurls (new) seeded via raw SQL against a real packages-db, describe.skipIf'd when CROWD_PACKAGES_DB_* env vars aren't set — matching the existing sibling suites' convention. Minor fixture additions to the neighboring getPackageDetailsByPurls integration test (repos.url-only insert simplified) with no behavior change.
  • Unit tests for the mapper (akritesExternalContactDetail.test.ts).

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Performance improvement
  • Chore / dependency update
  • Documentation

JIRA ticket

CM-1336

Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
@ulemons ulemons self-assigned this Jul 16, 2026
Copilot AI review requested due to automatic review settings July 16, 2026 09:39
@ulemons ulemons added the Feature Created by Linear-GitHub Sync label Jul 16, 2026
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

PR Summary

High Risk
New external API exposes security contact PII behind a broader interim scope (read:maintainer-roles); contract fields and aggregate confidence crosswalk are still provisional.

Overview
Adds read-only Akrites-external security contact lookup by package PURL: GET /akrites-external/contacts/detail and POST /akrites-external/contacts/detail:batch, wired in a new /contacts router group with the same rate limiting and handler patterns as packages/advisories.

Auth & exposure: Endpoints require read:maintainer-roles as an interim stand-in for the contract’s cdp:maintainers:read scope, and are not reachable via read:packages, because responses can include contact PII (e.g. emails).

Data & mapping: New DAL getContactDetailsByPurls joins packages → best repo → top security contacts (shared SECURITY_CONTACTS_SUBQUERY extracted from inline SQL). toAkritesExternalContactDetail maps internal rows to the public contract (field renames, aggregate overallConfidenceBand via an unconfirmed PRIMARY→HIGH crosswalk, several contract fields always null until upstream data exists). RepoDbRow / SecurityContactDbRow types move into @crowd/types per ADR-0006.

OpenAPI documents the Contacts tag, schemas, and both paths. Unit tests cover the mapper; integration tests cover the DAL query (DB env–gated).

Reviewed by Cursor Bugbot for commit e4d63f0. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds authenticated Akrites endpoints for retrieving package security-contact details.

Changes:

  • Adds single and batch contact-detail endpoints with scope checks and validation.
  • Adds DAL queries, schema-aligned types, and response mapping.
  • Adds OpenAPI documentation and automated tests.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
services/libs/types/src/db/security-contacts.ts Defines security-contact row types.
services/libs/types/src/db/repos.ts Defines repository row type.
services/libs/types/src/db/index.ts Exports new row types.
services/libs/data-access-layer/src/osspckgs/sqlFragments.ts Extracts contact aggregation SQL.
services/libs/data-access-layer/src/osspckgs/getPackageDetailsByPurls.integration.test.ts Updates package fixtures.
services/libs/data-access-layer/src/osspckgs/getContactDetailsByPurls.integration.test.ts Tests contact lookup queries.
services/libs/data-access-layer/src/osspckgs/api.ts Adds contact-detail DAL query and types.
backend/src/api/public/v1/packages/getAkritesExternalContactDetailBatch.ts Implements batch endpoint.
backend/src/api/public/v1/packages/getAkritesExternalContactDetail.ts Implements single endpoint.
backend/src/api/public/v1/packages/akritesExternalContactDetail.ts Maps DAL rows to API responses.
backend/src/api/public/v1/packages/akritesExternalContactDetail.test.ts Tests response mapping.
backend/src/api/public/v1/akrites-external/openapi.yaml Documents contact APIs.
backend/src/api/public/v1/akrites-external/index.ts Registers scoped routes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread services/libs/types/src/db/repos.ts
Comment thread services/libs/data-access-layer/src/osspckgs/sqlFragments.ts
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 16, 2026 09:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread backend/src/api/public/v1/akrites-external/index.ts
@ulemons
ulemons merged commit aab51a3 into main Jul 16, 2026
14 checks passed
@ulemons
ulemons deleted the feat/security-contacts-api-akrites branch July 16, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature Created by Linear-GitHub Sync

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants