Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CDK
cdk.out/
.cdk.staging/
*.js
!jest.config.js
*.d.ts

# Python
__pycache__/
*.py[cod]
.venv/
venv/
.env
.pytest_cache/
.mypy_cache/
.ruff_cache/

# IDE / OS
.idea/
.vscode/
.DS_Store
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,24 @@ PYTHONPATH=. pytest tests/test_exclusao.py -v
Usa **moto** (sem AWS real). O pacote `lambda/` importa via `importlib` (nome reservado).

CI (GitHub Actions): mesmo comando em Python 3.12 em todo PR/`push` na `main` — sem credenciais AWS no runner.

---

## CDK / Deploy

Stack único em `cdk/app.py` (ADR-001 PR2): **DynamoDB + Lambda + HTTP API** no mesmo stack — sem `from_function_name`, sem Cognito (PR3).

- Tabela: PK `cliente_id` / SK `request_id`, on-demand; `grant_read_write_data` na Lambda.
- Env: `TABLE_NAME` (nome da tabela), `PIX_FEE` (default `50.00`).
- Handler: `app.lambda_handler` (código em `lambda/`).
- Throttle HTTP API: **100 rps / burst 200** (espelha `aws-api-gateway-cdk`).
- Rotas: `POST /solicitar-exclusao-cliente`, `GET /status-exclusao/{cliente_id}`, `POST /confirmar-pagamento`, `GET /health`.

```bash
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 lab
```

**Nota:** o asset Lambda é o source em `lambda/` — empacotar Powertools (layer ou bundle) fica em follow-up; este PR só faz o wiring IaC.
18 changes: 18 additions & 0 deletions cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"app": "python3 cdk/app.py",
"watch": {
"include": ["**"],
"exclude": [
"README.md",
"cdk*.json",
"requirements*.txt",
"source.bat",
"**/__pycache__",
"tests"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true
}
}
111 changes: 110 additions & 1 deletion cdk/app.py
Original file line number Diff line number Diff line change
@@ -1 +1,110 @@
# CDK stack example - complete in next step
#!/usr/bin/env python3
"""CDK app — exclusão Pix (ADR-001 PR2).

Single stack: DynamoDB table + Lambda + HTTP API.
No Cognito (PR3). No from_function_name.
"""
from aws_cdk import (
App,
CfnOutput,
Duration,
RemovalPolicy,
Stack,
aws_apigatewayv2 as apigwv2,
aws_apigatewayv2_integrations as apigwv2_integrations,
aws_dynamodb as dynamodb,
aws_lambda as _lambda,
)
from constructs import Construct


class ExclusaoClienteStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)

table = dynamodb.Table(
self,
"ExclusaoClientesTable",
partition_key=dynamodb.Attribute(
name="cliente_id", type=dynamodb.AttributeType.STRING
),
sort_key=dynamodb.Attribute(
name="request_id", type=dynamodb.AttributeType.STRING
),
billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
removal_policy=RemovalPolicy.DESTROY,
)

# Handler: lambda/app.py → lambda_handler (CI uses Python 3.12)
# Powertools packaging/layer left for follow-up (asset is source only).
fn = _lambda.Function(
self,
"ExclusaoClienteLambda",
runtime=_lambda.Runtime.PYTHON_3_12,
handler="app.lambda_handler",
code=_lambda.Code.from_asset("lambda"),
timeout=Duration.seconds(30),
memory_size=256,
environment={
"TABLE_NAME": table.table_name,
"PIX_FEE": "50.00",
},
)

table.grant_read_write_data(fn)

http_api = apigwv2.HttpApi(
self,
"ExclusaoClienteHttpApi",
description="API Gateway para Exclusão de Cliente com Pix",
cors_preflight=apigwv2.CorsPreflightOptions(
allow_origins=["*"],
allow_methods=[apigwv2.CorsHttpMethod.ANY],
),
create_default_stage=False,
)

# Mirror aws-api-gateway-cdk: rate 100 / burst 200
apigwv2.HttpStage(
self,
"DefaultStage",
http_api=http_api,
stage_name="$default",
auto_deploy=True,
throttle=apigwv2.ThrottleSettings(rate_limit=100, burst_limit=200),
)

integration = apigwv2_integrations.HttpLambdaIntegration(
"LambdaIntegration", fn
)

http_api.add_routes(
path="/solicitar-exclusao-cliente",
methods=[apigwv2.HttpMethod.POST],
integration=integration,
)
http_api.add_routes(
path="/status-exclusao/{cliente_id}",
methods=[apigwv2.HttpMethod.GET],
integration=integration,
)
http_api.add_routes(
path="/confirmar-pagamento",
methods=[apigwv2.HttpMethod.POST],
integration=integration,
)
http_api.add_routes(
path="/health",
methods=[apigwv2.HttpMethod.GET],
integration=integration,
)

CfnOutput(self, "ApiUrl", value=http_api.url or "")
CfnOutput(self, "ApiId", value=http_api.api_id)
CfnOutput(self, "DynamoTableName", value=table.table_name)
CfnOutput(self, "LambdaName", value=fn.function_name)


app = App()
ExclusaoClienteStack(app, "ExclusaoClienteStack")
app.synth()
2 changes: 2 additions & 0 deletions cdk/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
aws-cdk-lib>=2.170.0,<3
constructs>=10.0.0,<11
Loading