API serverless para solicitação de exclusão de cliente com geração de QR Code Pix para pagamento de tarifa.
- Tabela DynamoDB criada via CDK
- Configuração via env vars
- Health Check endpoint
- Throttling no API Gateway
- ADR-001 — Unificar exclusão Pix (CDK + Lambda) — Accepted (CAB 2026-09-20). Este repo é o canônico;
aws-api-gateway-cdkserá arquivado após migrar o stack. Access pattern Dynamo: pointerLATEST. Auth (PR3): Cognito JWT.
Feature map (agents): docs/feature-map.md — rotas, auth Cognito JWT, env vars, pré-reqs make verify / make check.
Tabela: PK cliente_id, SK request_id.
Cada solicitação grava dois itens (histórico depois ponteiro):
| SK | Papel |
|---|---|
| UUID da solicitação | Histórico daquele pedido |
LATEST |
Ponteiro do estado atual (active_request_id, status, …) |
- Dedup / status leem só
LATEST(antes o código gravava UUID e lia SK=LATEST— nunca achava). - Confirmar pagamento atualiza histórico e depois
LATEST(condition emactive_request_id). - Writes ordenados (
put/update) de propósito neste PR — TransactWrite fica pra um follow-up se precisar atomicidade forte.
pip install -r requirements.txt
pip install -r requirements-dev.txt # ruff + mypy
pip install -r cdk/requirements.txt # só se for rodar synth
# prove-it-works (HTTP contracts via lambda_handler, incl. GET /health):
make verify
# full gate (lint + types + all pytest + cdk synth, sem deploy):
make checkUsa moto (sem AWS real). O pacote lambda/ importa via importlib (nome reservado).
make verify=tests/test_http_contract.py(agent-trusted HTTP status/body contracts).make check= lint + typecheck +pytest tests/+ cdk synth.
CI (GitHub Actions): em todo PR/push na main — jobs lint, test, verify (make verify), e synth (sem AWS / sem deploy).
- Timezone-aware datetimes: ruff
DTZ(incl. DTZ003) — usedatetime.now(timezone.utc), neverdatetime.utcnow(). - CORS: CDK lab origins are localhost only (no
AllowOrigins: "*"). Do not reintroduce wildcards incdk/.
Stack único em cdk/app.py (ADR-001): Cognito + DynamoDB + Lambda + HTTP API no mesmo stack — sem from_function_name.
- Tabela: PK
cliente_id/ SKrequest_id, on-demand;grant_read_write_datana Lambda. - Env:
TABLE_NAME(nome da tabela),PIX_FEE(default50.00). - Handler:
app.lambda_handler(código emlambda/). - Throttle HTTP API: 100 rps / burst 200.
- Auth: Cognito JWT nas rotas mutáveis/status;
GET /healthpúblico. - CORS lab:
http://localhost:3000ehttp://127.0.0.1:3000(sem*). Override via CDK contextcorsOrigins(lista de origins). - Rotas:
POST /solicitar-exclusao-cliente,GET /status-exclusao/{cliente_id},POST /confirmar-pagamento,GET /health.
python3 -m venv .venv && source .venv/bin/activate
pip install -r cdk/requirements.txt
npx aws-cdk@2 synth # requer Node + AWS CDK CLI
# npx aws-cdk@2 deploy # só com CAB / conta labOutputs úteis após deploy: ApiUrl, UserPoolId, UserPoolClientId, JwtIssuer.
Nota: o asset Lambda é o source em lambda/ — empacotar Powertools (layer ou bundle) fica em follow-up; este PR só faz o wiring IaC.
Após cdk deploy (com CAB), anote UserPoolId, UserPoolClientId e ApiUrl.
aws cognito-idp sign-up \
--client-id "$CLIENT_ID" \
--username "lab@example.com" \
--password 'LabPass123' \
--user-attributes Name=email,Value=lab@example.com
# Confirmar (lab — admin; self-sign-up exige confirmação de e-mail ou admin-confirm)
aws cognito-idp admin-confirm-sign-up \
--user-pool-id "$USER_POOL_ID" \
--username "lab@example.com"aws cognito-idp initiate-auth \
--client-id "$CLIENT_ID" \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters USERNAME=lab@example.com,PASSWORD='LabPass123'Use o campo AuthenticationResult.IdToken (não o AccessToken) no header.
# Público
curl -s "$API_URL/health"
# Protegido
PAYLOAD='{"cliente_id":"c1","motivo":"lab"}'
curl -s -X POST "$API_URL/solicitar-exclusao-cliente" \
-H "Authorization: Bearer $ID_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"
curl -s "$API_URL/status-exclusao/c1" \
-H "Authorization: Bearer $ID_TOKEN"Sem Bearer nas rotas protegidas → API Gateway responde 401 antes da Lambda.