@@ -234,9 +234,9 @@ READ_MAINTAINERS: 'read:maintainers',
234234Reads ` req.auth.payload.azp ` . Throws ` UnauthorizedError ` if the value is
235235missing or not in the allowlist passed at wire-up. Fails closed.
236236
237- ** ` backend/src/api/public/v1/index.ts ` ** — insert a ** new ** route
238- registration after the existing ` /akrites ` mount ( line 44) and before the
239- 404 catch-all at line 46 :
237+ ** ` backend/src/api/public/v1/index.ts ` ** — update the existing
238+ ` /akrites-external ` mount at line 46 to add the ` azp ` allowlist and the
239+ mount-level scope check on top of the existing ` oauth2Middleware ` :
240240``` ts
241241router .use (
242242 ' /akrites-external' ,
@@ -250,10 +250,16 @@ router.use(
250250)
251251```
252252
253- ` akritesExternalRouter() ` is a ** new module** at
254- ` backend/src/api/public/v1/akrites-external/index.ts ` — separate from the
255- existing ` akritesRouter ` and free of its inner scope guards, so the
256- mount-level ` requireScopes ` above is authoritative for this route.
253+ ` akritesExternalRouter() ` at
254+ ` backend/src/api/public/v1/akrites-external/index.ts ` already exists (a
255+ recent main merge brought it in) and currently carries per-subrouter
256+ ` requireScopes ` guards inherited from the pre-decision scaffold —
257+ ` [READ_PACKAGES, READ_STEWARDSHIPS] ` on packages, ` [READ_PACKAGES] ` on
258+ advisories/blast-radius, ` [READ_MAINTAINER_ROLES] ` on contacts. Refactor
259+ the module to strip all inner read-scope guards, so the mount-level
260+ ` requireScopes ` above is the authoritative check for this route. Leave
261+ any write-scope guards on write routes (there are none today, but the
262+ convention holds).
257263
258264` /akrites ` (Self Serve) is untouched.
259265
@@ -268,27 +274,25 @@ Implement the token exchange described in the Auth Flow diagram:
268274 allow ` secretsmanager:GetSecretValue ` on the full LF secret ARN. If
269275 LF confirms the secret is encrypted with a customer-managed KMS key
270276 (see the Context KMS note), also allow ` kms:Decrypt ` on that KMS key
271- ARN. Choose one of the delivery patterns Eric outlined; each has a
272- different rotation behavior:
273- - ** ECS ` ValueFrom ` ** on the task definition, referencing the LF
274- secret ARN. The secret is injected as an environment variable at
275- task start only — ECS does not refresh ` ValueFrom ` values while the
276- task is running. Rotation therefore requires task replacement; the
277- step-5 retry-once flow means restarting the task, not an in-process
278- re-read.
279- - ** EKS External Secrets Operator + IRSA** , with the operator
280- configured to re-sync the secret on a short refresh interval so
281- pods pick up the rotated value shortly after LF rotates. In-process
282- retry is still possible if the operator has already refreshed.
283- - ** Direct SDK read** using the workload role — process reads the
284- secret via ` GetSecretValue ` at boot and again on demand for the
285- step-5 retry. Simplest match for the retry-once flow without
286- touching the task/pod lifecycle.
277+ ARN. Common delivery patterns — Akrites picks one, and the specific
278+ role ARN(s) LF grants in the item policy follow that choice
279+ (task execution role for ECS ` ValueFrom ` , operator SA role for EKS
280+ External Secrets Operator, workload role for a direct SDK read):
281+ - ** ECS ` ValueFrom ` ** — secret injected at task start only, so
282+ rotation means task replacement, not an in-process re-read.
283+ - ** EKS External Secrets Operator + IRSA** — pods pick up rotated
284+ values on the operator's refresh interval.
285+ - ** Direct SDK read** — process reads the secret at boot and again
286+ on demand for the step-5 retry; simplest match for the
287+ retry-once flow.
287288
288289 Dev: 1Password via the LF-provided vault item.
2892902 . Build and sign a ` client_assertion ` JWT with ` alg: RS256 ` and header
290291 ` kid ` set to the current key's ID. Claims: ` iss ` = ` sub ` =
291- Akrites client ID, ` aud ` = LFX Auth0 tenant token endpoint URL, short
292+ Akrites client ID, ` aud ` = ** LFX Auth0 tenant base URL, with the
293+ trailing slash** (e.g. ` https://linuxfoundation.auth0.com/ ` , or the
294+ custom-domain equivalent) — Auth0's ` private_key_jwt ` verifier
295+ expects the issuer URL, not the ` /oauth/token ` endpoint. Short
292296 ` exp ` (≤ 5 min), unique ` jti ` .
2932973 . POST to Auth0 ` /oauth/token ` as ` application/x-www-form-urlencoded `
294298 with:
0 commit comments