Skip to content

Commit cf4735c

Browse files
committed
Merge branch 'main' into feat/mailing-list-integration-CM-1318
2 parents 037a969 + 9f4ac47 commit cf4735c

125 files changed

Lines changed: 13492 additions & 561 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Router } from 'express'
2+
3+
import { createRateLimiter } from '@/api/apiRateLimiter'
4+
import { requireScopes } from '@/api/public/middlewares/requireScopes'
5+
import { safeWrap } from '@/middlewares/errorMiddleware'
6+
import { SCOPES } from '@/security/scopes'
7+
8+
import { getAkritesExternalAdvisoryDetail } from '../packages/getAkritesExternalAdvisoryDetail'
9+
import { getAkritesExternalAdvisoryDetailBatch } from '../packages/getAkritesExternalAdvisoryDetailBatch'
10+
import { getAkritesExternalContactDetail } from '../packages/getAkritesExternalContactDetail'
11+
import { getAkritesExternalContactDetailBatch } from '../packages/getAkritesExternalContactDetailBatch'
12+
import { getAkritesExternalPackageDetail } from '../packages/getAkritesExternalPackageDetail'
13+
import { getAkritesExternalPackageDetailBatch } from '../packages/getAkritesExternalPackageDetailBatch'
14+
15+
const rateLimiter = createRateLimiter({ max: 60, windowMs: 60 * 1000 })
16+
17+
export function akritesExternalRouter(): Router {
18+
const router = Router()
19+
20+
// TODO: swap for a dedicated cdp:packages:read scope once Akrites gets its own
21+
// Auth0 M2M scopes (per the akrites-external draft contract) — reusing the
22+
// internal CDP UI scopes for now since that's what's actually issued today.
23+
const packagesSubRouter = Router()
24+
packagesSubRouter.use(rateLimiter)
25+
packagesSubRouter.use(requireScopes([SCOPES.READ_PACKAGES, SCOPES.READ_STEWARDSHIPS], 'all'))
26+
packagesSubRouter.get('/detail', safeWrap(getAkritesExternalPackageDetail))
27+
packagesSubRouter.post(/^\/detail:batch\/?$/, safeWrap(getAkritesExternalPackageDetailBatch))
28+
router.use('/packages', packagesSubRouter)
29+
30+
// TODO: the contract gates advisories behind a dedicated read:advisories scope
31+
// (see the scope-naming note in the akrites-external OpenAPI). That scope isn't
32+
// issued by Auth0 yet, so reuse READ_PACKAGES for now — advisories are package
33+
// security data and, unlike the packages endpoints above, need no stewardship read.
34+
const advisoriesSubRouter = Router()
35+
advisoriesSubRouter.use(rateLimiter)
36+
advisoriesSubRouter.use(requireScopes([SCOPES.READ_PACKAGES]))
37+
advisoriesSubRouter.get('/detail', safeWrap(getAkritesExternalAdvisoryDetail))
38+
advisoriesSubRouter.post(/^\/detail:batch\/?$/, safeWrap(getAkritesExternalAdvisoryDetailBatch))
39+
router.use('/advisories', advisoriesSubRouter)
40+
41+
// Security contacts expose contact PII (e.g. reporter emails), so the contract gates
42+
// them behind a dedicated cdp:maintainers:read scope and explicitly forbids reaching
43+
// them via the packages scope. That scope isn't issued by Auth0 yet, so reuse the
44+
// closest issued one — READ_MAINTAINER_ROLES (maintainer data) — NOT READ_PACKAGES.
45+
// TODO: swap for cdp:maintainers:read once issued.
46+
const contactsSubRouter = Router()
47+
contactsSubRouter.use(rateLimiter)
48+
contactsSubRouter.use(requireScopes([SCOPES.READ_MAINTAINER_ROLES]))
49+
contactsSubRouter.get('/detail', safeWrap(getAkritesExternalContactDetail))
50+
contactsSubRouter.post(/^\/detail:batch\/?$/, safeWrap(getAkritesExternalContactDetailBatch))
51+
router.use('/contacts', contactsSubRouter)
52+
53+
return router
54+
}

0 commit comments

Comments
 (0)