Fix compliance violations: Lambda defaults, CI node-version, dead code

oss-index-creator Lambda was missing functionName, arm64 architecture,
and explicit log retention — all required by the engineering handbook.
CI workflow was not passing node-version to reusable workflows, risking
drift. Removed unused _api_request helper from all four main Lambdas.
Added missing suggestions log group to foundation stack.
This commit is contained in:
Adam Moussa 2026-05-18 18:28:26 -04:00
parent 69c989847f
commit fdaaf5ed4a
8 changed files with 8 additions and 103 deletions

View file

@ -21,6 +21,7 @@ jobs:
with: with:
working-directory: web working-directory: web
cache-dependency-path: web/package-lock.json cache-dependency-path: web/package-lock.json
node-version: "24"
run-cdk-synth: false run-cdk-synth: false
run-conventions-check: false run-conventions-check: false
@ -38,6 +39,7 @@ jobs:
with: with:
working-directory: mobile working-directory: mobile
cache-dependency-path: mobile/package-lock.json cache-dependency-path: mobile/package-lock.json
node-version: "24"
run-cdk-synth: false run-cdk-synth: false
run-conventions-check: false run-conventions-check: false
@ -47,6 +49,7 @@ jobs:
with: with:
working-directory: infra working-directory: infra
cache-dependency-path: infra/package-lock.json cache-dependency-path: infra/package-lock.json
node-version: "24"
dotnet-version: "8.0.x" dotnet-version: "8.0.x"
dotnet-publish-project: api/src/ProposalSystem.Api/ProposalSystem.Api.csproj dotnet-publish-project: api/src/ProposalSystem.Api/ProposalSystem.Api.csproj
run-typecheck: false run-typecheck: false

View file

@ -93,7 +93,9 @@ export class ComputeStack extends cdk.Stack {
// Lambda to pre-create the vector index (retries until AOSS access policy propagates) // Lambda to pre-create the vector index (retries until AOSS access policy propagates)
const indexCreatorFn = new lambda.Function(this, 'OssIndexCreator', { const indexCreatorFn = new lambda.Function(this, 'OssIndexCreator', {
functionName: 'proposal-system-oss-index-creator',
runtime: lambda.Runtime.PYTHON_3_12, runtime: lambda.Runtime.PYTHON_3_12,
architecture: lambda.Architecture.ARM_64,
handler: 'app.handler', handler: 'app.handler',
code: lambda.Code.fromAsset('../lambdas/oss-index-creator', { code: lambda.Code.fromAsset('../lambdas/oss-index-creator', {
bundling: { bundling: {
@ -105,6 +107,7 @@ export class ComputeStack extends cdk.Stack {
}, },
}), }),
timeout: cdk.Duration.minutes(6), timeout: cdk.Duration.minutes(6),
logRetention: logs.RetentionDays.TWO_MONTHS,
}); });
indexCreatorFn.addToRolePolicy(new iam.PolicyStatement({ indexCreatorFn.addToRolePolicy(new iam.PolicyStatement({

View file

@ -259,6 +259,7 @@ export class FoundationStack extends cdk.Stack {
'proposal-system-pdf-extract', 'proposal-system-pdf-extract',
'proposal-system-pdf-generate', 'proposal-system-pdf-generate',
'proposal-system-library-ingest', 'proposal-system-library-ingest',
'proposal-system-suggestions',
]; ];
for (const name of logGroupNames) { for (const name of logGroupNames) {

View file

@ -8,7 +8,6 @@ then triggers a KB sync.
import json import json
import logging import logging
import os import os
import time
from datetime import datetime from datetime import datetime
import boto3 import boto3
@ -199,27 +198,3 @@ def _api_headers() -> dict:
if api_key: if api_key:
headers["X-Internal-Api-Key"] = api_key headers["X-Internal-Api-Key"] = api_key
return headers return headers
def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response:
kwargs.setdefault("headers", _api_headers())
kwargs.setdefault("timeout", 10)
for attempt in range(retries):
try:
resp = httpx.request(method, url, **kwargs)
if resp.status_code < 500:
return resp
logger.warning(
"API returned %s on attempt %d for %s",
resp.status_code,
attempt + 1,
url,
)
except httpx.TransportError as e:
logger.warning(
"Transport error on attempt %d for %s: %s", attempt + 1, url, e
)
if attempt == retries - 1:
raise
time.sleep(min(2**attempt, 4))
return resp # type: ignore[possibly-undefined]

View file

@ -37,9 +37,7 @@ def handler(event, context):
) )
index_body = { index_body = {
"settings": { "settings": {"index": {"knn": True, "knn.algo_param.ef_search": 512}},
"index": {"knn": True, "knn.algo_param.ef_search": 512}
},
"mappings": { "mappings": {
"properties": { "properties": {
vector_field: { vector_field: {

View file

@ -9,7 +9,6 @@ import json
import logging import logging
import os import os
import tempfile import tempfile
import time
import boto3 import boto3
import httpx import httpx
@ -339,27 +338,3 @@ def _api_headers() -> dict:
if api_key: if api_key:
headers["X-Internal-Api-Key"] = api_key headers["X-Internal-Api-Key"] = api_key
return headers return headers
def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response:
kwargs.setdefault("headers", _api_headers())
kwargs.setdefault("timeout", 10)
for attempt in range(retries):
try:
resp = httpx.request(method, url, **kwargs)
if resp.status_code < 500:
return resp
logger.warning(
"API returned %s on attempt %d for %s",
resp.status_code,
attempt + 1,
url,
)
except httpx.TransportError as e:
logger.warning(
"Transport error on attempt %d for %s: %s", attempt + 1, url, e
)
if attempt == retries - 1:
raise
time.sleep(min(2**attempt, 4))
return resp # type: ignore[possibly-undefined]

View file

@ -7,7 +7,6 @@ Triggered via SQS when an admin requests PDF generation.
import json import json
import logging import logging
import os import os
import time
from datetime import datetime from datetime import datetime
from io import BytesIO from io import BytesIO
@ -543,27 +542,3 @@ def _api_headers() -> dict:
if api_key: if api_key:
headers["X-Internal-Api-Key"] = api_key headers["X-Internal-Api-Key"] = api_key
return headers return headers
def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response:
kwargs.setdefault("headers", _api_headers())
kwargs.setdefault("timeout", 10)
for attempt in range(retries):
try:
resp = httpx.request(method, url, **kwargs)
if resp.status_code < 500:
return resp
logger.warning(
"API returned %s on attempt %d for %s",
resp.status_code,
attempt + 1,
url,
)
except httpx.TransportError as e:
logger.warning(
"Transport error on attempt %d for %s: %s", attempt + 1, url, e
)
if attempt == retries - 1:
raise
time.sleep(min(2**attempt, 4))
return resp # type: ignore[possibly-undefined]

View file

@ -7,7 +7,6 @@ to generate line item suggestions for new proposals.
import json import json
import logging import logging
import os import os
import time
import boto3 import boto3
import httpx import httpx
@ -320,27 +319,3 @@ def _api_headers() -> dict:
if api_key: if api_key:
headers["X-Internal-Api-Key"] = api_key headers["X-Internal-Api-Key"] = api_key
return headers return headers
def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response:
kwargs.setdefault("headers", _api_headers())
kwargs.setdefault("timeout", 10)
for attempt in range(retries):
try:
resp = httpx.request(method, url, **kwargs)
if resp.status_code < 500:
return resp
logger.warning(
"API returned %s on attempt %d for %s",
resp.status_code,
attempt + 1,
url,
)
except httpx.TransportError as e:
logger.warning(
"Transport error on attempt %d for %s: %s", attempt + 1, url, e
)
if attempt == retries - 1:
raise
time.sleep(min(2**attempt, 4))
return resp # type: ignore[possibly-undefined]