From 6fb46cbbc214061aeea4374c98ad52955f80a9eb Mon Sep 17 00:00:00 2001 From: Rodrigo Patote <47055922+patote85@users.noreply.github.com> Date: Thu, 24 Sep 2026 07:27:22 -0300 Subject: [PATCH 1/2] agent-friendly #5: ban datetime.utcnow (ruff DTZ) - Enable ruff flake8-datetimez (DTZ) in pyproject - Replace utcnow with datetime.now(timezone.utc) in lambda/ - README: hard constraints note (DTZ + no CORS *) --- lambda/domain_dynamo.py | 4 ++-- pyproject.toml | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lambda/domain_dynamo.py b/lambda/domain_dynamo.py index 9d881a6..3eea64c 100644 --- a/lambda/domain_dynamo.py +++ b/lambda/domain_dynamo.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from datetime import datetime +from datetime import datetime, timezone from decimal import Decimal import boto3 @@ -64,7 +64,7 @@ def put_solicitacao_with_latest( def confirm_payment(cliente_id: str, request_id: str) -> None: """Mark history + LATEST as PAID when pointer matches request_id.""" - ts = datetime.utcnow().isoformat() + ts = datetime.now(timezone.utc).isoformat() table.update_item( Key={"cliente_id": cliente_id, "request_id": request_id}, UpdateExpression="SET #status = :paid, updated_at = :ts", diff --git a/pyproject.toml b/pyproject.toml index 716f504..edd6a26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,9 +9,12 @@ line-length = 100 src = ["lambda", "tests", "cdk"] [tool.ruff.lint] -# Hard constraints (Lauren/pstack): errors + unused. Import-sort (I) deferred — +# Hard constraints (Lauren/pstack): errors + unused + timezone-aware datetimes. +# DTZ bans naive utcnow/utcfromtimestamp (DTZ003 etc.). Import-sort (I) deferred — # CDK multi-alias imports fight isort without value; enable in a later PR. -select = ["E", "F", "W"] +# CORS AllowOrigins "*" is already avoided in cdk/app.py (localhost only) — +# do not reintroduce wildcard origins in CDK. +select = ["E", "F", "W", "DTZ"] ignore = ["E501"] [tool.ruff.lint.per-file-ignores] From 8407065ce14a0d813edf14e9f42835c6a11a802f Mon Sep 17 00:00:00 2001 From: Rodrigo Patote <47055922+patote85@users.noreply.github.com> Date: Thu, 24 Sep 2026 07:27:42 -0300 Subject: [PATCH 2/2] agent-friendly #5: fix app.py utcnow + README hard constraints --- README.md | 5 +++++ lambda/app.py | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c63db36..9e189fa 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,11 @@ Usa **moto** (sem AWS real). O pacote `lambda/` importa via `importlib` (nome re CI (GitHub Actions): em todo PR/`push` na `main` — jobs **`lint`** (ruff + mypy), **`test`** (pytest/moto) e **`synth`** (`npx aws-cdk@2 synth`, sem AWS / sem deploy). +### Agent-friendly / hard constraints + +- **Timezone-aware datetimes:** ruff `DTZ` (incl. DTZ003) — use `datetime.now(timezone.utc)`, never `datetime.utcnow()`. +- **CORS:** CDK lab origins are localhost only (no `AllowOrigins: "*"`). Do not reintroduce wildcards in `cdk/`. + --- ## CDK / Deploy diff --git a/lambda/app.py b/lambda/app.py index 3b63bd2..ad91650 100644 --- a/lambda/app.py +++ b/lambda/app.py @@ -4,7 +4,7 @@ import json import uuid -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from aws_lambda_powertools import Logger, Metrics, Tracer from aws_lambda_powertools.event_handler import APIGatewayHttpResolver @@ -59,8 +59,8 @@ def solicitar_exclusao(event: APIGatewayProxyEvent): } request_id = str(uuid.uuid4()) - timestamp = datetime.utcnow().isoformat() - expires_at = (datetime.utcnow() + timedelta(days=7)).isoformat() + timestamp = datetime.now(timezone.utc).isoformat() + expires_at = (datetime.now(timezone.utc) + timedelta(days=7)).isoformat() qr_code_data = domain.generate_pix_qr_code(cliente_id, domain.PIX_FEE, request_id) domain.put_solicitacao_with_latest(