You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -15,7 +15,83 @@ This page records the repo-vs-docs audit points that are easy to miss when readi
15
15
| Binary startup | Running the Go binary outside compose requires `DATABASE_URL`; compose injects the service connection string. |`main.go`, compose files |
16
16
| PR filters | Pull-request runtime checks are path-filtered. Docs-only changes usually skip Docker runtime checks; `prod/**` changes are not part of the PR health filter today, while main-branch workflows still deploy Pages and run release checks. |`.github/workflows/*.yml`|
17
17
18
-
## Behaviors to document carefully
18
+
## Current API contract
19
+
20
+
### `GET /healthz`
21
+
22
+
Used by Docker Compose and CI as a readiness smoke check.
23
+
24
+
```http
25
+
HTTP/1.1 200 OK
26
+
27
+
Healthy
28
+
```
29
+
30
+
### `POST /clientes/{id}/transacoes`
31
+
32
+
Request body accepted by the Go handler:
33
+
34
+
```json
35
+
{
36
+
"valor": 1000,
37
+
"tipo": "c",
38
+
"descricao": "deposito"
39
+
}
40
+
```
41
+
42
+
Successful response shape:
43
+
44
+
```json
45
+
{
46
+
"id": 1,
47
+
"limite": 100000,
48
+
"saldo": 1000
49
+
}
50
+
```
51
+
52
+
Validation and error behavior currently implemented:
53
+
54
+
| Case | Status | Source-backed note |
55
+
|---|---:|---|
56
+
| Non-integer `{id}`|`400`|`strconv.Atoi` failure in `postTransacaoHandler`. |
57
+
| Unknown client ID |`404`| Client not found in the in-memory `clientes` map. |
58
+
| Invalid JSON |`400`| JSON decode failure. |
59
+
| Invalid `tipo`, empty/long `descricao`, or non-positive `valor`|`422`|`isTransacaoValid` failure. |
60
+
| Over-limit debit |`200`|`InsertTransacao` refuses the mutation and returns the existing balance; the handler serializes that value. |
61
+
| Database/query failure |`500`| Handler returns the database error as an internal server error. |
62
+
63
+
### `GET /clientes/{id}/extrato`
64
+
65
+
Successful response shape currently emitted by Go:
66
+
67
+
```json
68
+
{
69
+
"saldo": {
70
+
"total": 1000,
71
+
"limite": 100000,
72
+
"data_extrato": "2026-05-29T22:00:00Z"
73
+
},
74
+
"ultimas_transacoes": [
75
+
{
76
+
"valor": 1000,
77
+
"tipo": "c",
78
+
"descricao": "deposito"
79
+
}
80
+
]
81
+
}
82
+
```
83
+
84
+
Statement error behavior currently implemented:
85
+
86
+
| Case | Status | Source-backed note |
87
+
|---|---:|---|
88
+
| Non-integer `{id}`|`400`|`strconv.Atoi` failure in `getExtratoHandler`. |
89
+
| Unknown client ID |`404`| Client not found in the in-memory `clientes` map. |
90
+
| Database row missing |`404`| Defensive `sql.ErrNoRows` branch after the stored-function call. |
91
+
| Database/query failure |`500`| Handler returns the database error as an internal server error. |
92
+
| Transaction JSON unmarshal failure |`200`| Handler logs the failure and emits an empty `ultimas_transacoes` array. |
93
+
94
+
## Behaviors that differ from the original challenge shape
19
95
20
96
### Over-limit debits
21
97
@@ -26,7 +102,7 @@ That means the current implementation behavior is:
26
102
- malformed client IDs: `400`
27
103
- unknown client IDs: `404`
28
104
- invalid transaction fields: `422`
29
-
- over-limit debit: no balance mutation; current balance returned by the stored procedure
105
+
- over-limit debit: no balance mutation; current balance returned by the stored procedure with `200`
30
106
31
107
If strict challenge compatibility requires a `422` for over-limit debits, that is an implementation follow-up rather than a docs-only change.
32
108
@@ -36,15 +112,47 @@ The SQL function includes `RealizadoEm` in the JSON row source, but the Go respo
36
112
37
113
If the project wants full challenge response parity, add a timestamp field to `TransacaoDto` with the expected JSON name and then update the docs.
38
114
39
-
### Dev stack versus prod stack
115
+
##Runtime stacks
40
116
41
-
The root compose file is the local/dev stack: it builds the Go image from source, exposes direct API ports `4200` and `4201`, and includes Grafana, Prometheus, InfluxDB, postgres-exporter, and the k6 service in `MODE=dev`.
117
+
### Development/root compose
42
118
43
-
The `prod/` compose file is the CI/release stack: it consumes the GHCR image, maps API containers to `8081` and `8082`, uses config from `prod/conf/`, and runs k6 in `MODE=prod` with an HTML report artifact.
119
+
The root compose file is the local/dev stack:
44
120
45
-
## Documentation follow-ups worth considering
121
+
- builds the Go image from `src/WebApi/Dockerfile`
122
+
- exposes NGINX at `localhost:9999`
123
+
- exposes direct API containers on `4200` and `4201`
124
+
- runs two API containers behind NGINX `least_conn`
125
+
- includes PostgreSQL, Grafana, Prometheus, InfluxDB, postgres-exporter, and k6
126
+
- runs k6 with `MODE=dev`
46
127
47
-
- Add exact example response bodies once the API shape is considered stable.
48
-
- Decide whether over-limit debit should remain a documented current behavior or be changed to return `422`.
49
-
- Decide whether statement transactions should expose the stored `RealizadoEm` timestamp.
50
-
- Consider extending PR path filters if prod compose/config changes should run the same runtime health gate before merge.
128
+
### Production/release compose
129
+
130
+
The `prod/` compose file is the CI/release stack:
131
+
132
+
- consumes the GHCR image instead of building from local source
133
+
- maps API containers to `8081` and `8082`
134
+
- uses config from `prod/conf/`
135
+
- runs k6 with `MODE=prod`
136
+
- writes the HTML stress report uploaded by `main-release.yml`
137
+
138
+
## CI/CD boundaries
139
+
140
+
Pull-request checks are intentionally path-filtered:
141
+
142
+
-`build-check.yml` watches `src/**`, root Go/Docker/Compose inputs, and its workflow file.
143
+
- CodeQL watches `src/**`, root Go module files, and its workflow file.
144
+
- Docs-only changes usually skip Docker runtime jobs.
145
+
-`prod/**` changes are not part of the PR runtime health filter today; they are exercised by `main-release.yml` after merge to `main`.
146
+
147
+
Main-branch flows remain the deployment and release path:
148
+
149
+
-`deploy.yml` publishes the Astro static site to GitHub Pages.
150
+
-`main-release.yml` builds/pushes the GHCR image, runs prod compose health checks, runs k6, and uploads the stress-test report artifact.
151
+
152
+
## Implementation decisions still open
153
+
154
+
These are now documented, not hidden, but they are implementation choices the project may still want to change later:
155
+
156
+
- Whether over-limit debits should keep returning unchanged balance with `200` or be changed to strict `422` behavior.
157
+
- Whether `ultimas_transacoes` should expose the stored `RealizadoEm` timestamp for full challenge response parity.
158
+
- Whether PR path filters should include `prod/**` and `prod/conf/**` so release-stack config changes run the runtime health gate before merge.
|`/clientes/{id}/transacoes`|`POST`| Submit a debit (`d`) or credit (`c`) transaction for clients 1 through 5. | Implemented in `postTransacaoHandler`; returns `id`, `limite`, and updated `saldo`. |
12
-
|`/clientes/{id}/extrato`|`GET`| Return current balance, credit limit, statement timestamp, and recent transactions. | Implemented in `getExtratoHandler`; returns `saldo` and up to 10 `ultimas_transacoes`. |
12
+
|`/clientes/{id}/extrato`|`GET`| Return current balance, credit limit, statement timestamp, and recent transactions. | Implemented in `getExtratoHandler`; returns `saldo` and up to 10 `ultimas_transacoes`. Current transaction rows serialize `valor`, `tipo`, and `descricao`; `RealizadoEm` is stored/selected in SQL but not exposed by the Go DTO. |
13
13
14
14
The repository also exposes `GET /healthz` for compose/CI health checks; it is not part of the original banking contract.
15
15
16
+
### Current response shapes
17
+
18
+
`POST /clientes/{id}/transacoes` returns:
19
+
20
+
```json
21
+
{
22
+
"id": 1,
23
+
"limite": 100000,
24
+
"saldo": 1000
25
+
}
26
+
```
27
+
28
+
`GET /clientes/{id}/extrato` returns:
29
+
30
+
```json
31
+
{
32
+
"saldo": {
33
+
"total": 1000,
34
+
"limite": 100000,
35
+
"data_extrato": "2026-05-29T22:00:00Z"
36
+
},
37
+
"ultimas_transacoes": [
38
+
{
39
+
"valor": 1000,
40
+
"tipo": "c",
41
+
"descricao": "deposito"
42
+
}
43
+
]
44
+
}
45
+
```
46
+
47
+
See [Source Audit](../audit/) for the complete status-code matrix and edge cases.
|`/clientes/{id}/transacoes`|`POST`| JSON body with `valor`, `tipo`, and `descricao`. Returns `id`, `limite`, and updated `saldo`. |
61
61
|`/clientes/{id}/extrato`|`GET`| Returns `saldo` metadata and up to 10 recent `ultimas_transacoes`; the current Go DTO serializes transaction `valor`, `tipo`, and `descricao`. |
62
62
63
+
## Current response examples
64
+
65
+
Transaction response:
66
+
67
+
```json
68
+
{
69
+
"id": 1,
70
+
"limite": 100000,
71
+
"saldo": 1000
72
+
}
73
+
```
74
+
75
+
Statement response:
76
+
77
+
```json
78
+
{
79
+
"saldo": {
80
+
"total": 1000,
81
+
"limite": 100000,
82
+
"data_extrato": "2026-05-29T22:00:00Z"
83
+
},
84
+
"ultimas_transacoes": [
85
+
{
86
+
"valor": 1000,
87
+
"tipo": "c",
88
+
"descricao": "deposito"
89
+
}
90
+
]
91
+
}
92
+
```
93
+
94
+
For the full status-code matrix and source-backed edge cases, see [Source Audit](../audit/).
0 commit comments