# HML Manual Deploy Runbook - AWS ECR/ECS ARM64

This is the canonical deploy path for Monetarie HML in the AWS greenfield account.

## Fixed Targets

| Item | Value |
|------|-------|
| AWS account | `990933657879` |
| AWS profile | `vulcimonetarie` |
| AWS region | `sa-east-1` |
| ECS cluster | `monetarie-greenfield-homolog` |
| Docker platform | `linux/arm64` |
| ECR registry | `990933657879.dkr.ecr.sa-east-1.amazonaws.com` |

Do not use `default`, `monetarie`, or any Mac-local AWS profile. Do not publish `linux/amd64` images to HML.

Use this AWS command prefix to avoid inherited shell credentials:

```bash
env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws <service> <operation>
```

Validate identity before deploy:

```bash
env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws sts get-caller-identity
```

Expected account: `990933657879`.

## Services

| Service | ECR repository | ECS family | ECS service | Container |
|---------|----------------|------------|-------------|-----------|
| Core API | `monetarie/core-api` | `monetarie-core-api-homolog` | `core-api` | `core-api` |
| IB UI | `monetarie/core-banking-ui` | `monetarie-core-banking-ui-homolog` | `core-banking-ui` | `core-banking-ui` |
| PIX API | `monetarie/pix-api` | `monetarie-pix-api-homolog` | `pix-api` | `pix-api` |
| PIX Admin UI | `monetarie/pix-admin-ui` | `monetarie-pix-admin-ui-homolog` | `pix-admin-ui` | `pix-admin-ui` |

## Build And Push

Set a tag:

```bash
export TAG="homolog-$(git rev-parse --short=8 HEAD)-$(date +%Y%m%d)"
export REGISTRY="990933657879.dkr.ecr.sa-east-1.amazonaws.com"
```

Login to ECR:

```bash
env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws ecr get-login-password \
| docker login --username AWS --password-stdin "$REGISTRY"
```

Build and push ARM64 images:

```bash
docker buildx build --platform linux/arm64 \
  -t "$REGISTRY/monetarie/core-api:$TAG" \
  --push core/backend

docker buildx build --platform linux/arm64 \
  -f core/apps/banking/Dockerfile \
  -t "$REGISTRY/monetarie/core-banking-ui:$TAG" \
  --push core

docker buildx build --platform linux/arm64 \
  -t "$REGISTRY/monetarie/pix-api:$TAG" \
  --push pix/backend

docker buildx build --platform linux/arm64 \
  -t "$REGISTRY/monetarie/pix-admin-ui:$TAG" \
  --push pix/frontend/admin
```

## Register Task Definition

Use the latest active task definition as base, replace only the target container image, and remove AWS-managed fields before registering.

Example for Core API:

```bash
FAMILY="monetarie-core-api-homolog"
CONTAINER="core-api"
IMAGE="$REGISTRY/monetarie/core-api:$TAG"

env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws ecs describe-task-definition --task-definition "$FAMILY" \
| jq --arg container "$CONTAINER" --arg image "$IMAGE" '
  .taskDefinition
  | .containerDefinitions |= map(if .name == $container then .image = $image else . end)
  | del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities,
        .registeredAt, .registeredBy, .deregisteredAt)
' > /tmp/task-definition.json

env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws ecs register-task-definition --cli-input-json file:///tmp/task-definition.json
```

Repeat with the service table values.

## Update ECS Service

```bash
env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws ecs update-service \
  --cluster monetarie-greenfield-homolog \
  --service <ecs-service> \
  --task-definition <ecs-family>:<revision>

env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN \
  AWS_PROFILE=vulcimonetarie AWS_REGION=sa-east-1 AWS_EC2_METADATA_DISABLED=true \
  aws ecs wait services-stable \
  --cluster monetarie-greenfield-homolog \
  --services core-api core-banking-ui pix-api pix-admin-ui
```

## Health Checks

```bash
curl -fsS http://core-api-h.monetarie.internal/health
curl -fsS -o /tmp/ib.html -w '%{http_code}\n' http://ib-h.monetarie.internal/
curl -fsS http://pix-api-h.monetarie.internal/health
curl -fsS -o /tmp/pixadmin.html -w '%{http_code}\n' http://pixadmin-h.monetarie.internal/
```

## PIX Validation Gate

A PIX out is final in IB only when the Core receipt has SPI settlement proof from PIX/BACEN metadata. An outbound request accepted by Core, an HTTP ACK, or a SPI `ACSP`/`ACCC` intermediary state is not liquidation.

Minimum post-deploy validation:

1. IB DICT lookup returns recipient participant data for the target key.
2. IB send creates a protocol/in-flight receipt while settlement proof is absent.
3. PIX Admin shows pacs.008 sent and pacs.002 received.
4. PIX transaction history reaches `ACSC` from BACEN/SPI, not only local/system status.
5. Core receipt for that transaction exposes final status and authentication code only after the settlement proof exists.
6. Any ADMI.002/RJCT keeps IB receipt as in-flight/rejected and never as settled.
