Skip to content

Commit b00fe1b

Browse files
hermes-agentjonathanperis
authored andcommitted
docs: expand API audit coverage
1 parent a93f24a commit b00fe1b

3 files changed

Lines changed: 185 additions & 11 deletions

File tree

docs/wiki/audit.md

Lines changed: 118 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,83 @@ This page records the repo-vs-docs audit points that are easy to miss when readi
1515
| Binary startup | Running the Go binary outside compose requires `DATABASE_URL`; compose injects the service connection string. | `main.go`, compose files |
1616
| 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` |
1717

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
1995

2096
### Over-limit debits
2197

@@ -26,7 +102,7 @@ That means the current implementation behavior is:
26102
- malformed client IDs: `400`
27103
- unknown client IDs: `404`
28104
- 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`
30106

31107
If strict challenge compatibility requires a `422` for over-limit debits, that is an implementation follow-up rather than a docs-only change.
32108

@@ -36,15 +112,47 @@ The SQL function includes `RealizadoEm` in the JSON row source, but the Go respo
36112

37113
If the project wants full challenge response parity, add a timestamp field to `TransacaoDto` with the expected JSON name and then update the docs.
38114

39-
### Dev stack versus prod stack
115+
## Runtime stacks
40116

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
42118

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:
44120

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`
46127

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.

docs/wiki/challenge.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,43 @@ Rinha de Backend is a Brazilian backend programming challenge. The 2024/Q1 editi
99
| Endpoint | Method | Expected behavior | Current implementation note |
1010
|----------|--------|-------------------|-----------------------------|
1111
| `/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. |
1313

1414
The repository also exposes `GET /healthz` for compose/CI health checks; it is not part of the original banking contract.
1515

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.
48+
1649
## Seeded clients
1750

1851
| Client | Limit |

docs/wiki/getting-started.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,39 @@ curl -i -X POST http://localhost:9999/clientes/1/transacoes -H "Content-Type:
6060
| `/clientes/{id}/transacoes` | `POST` | JSON body with `valor`, `tipo`, and `descricao`. Returns `id`, `limite`, and updated `saldo`. |
6161
| `/clientes/{id}/extrato` | `GET` | Returns `saldo` metadata and up to 10 recent `ultimas_transacoes`; the current Go DTO serializes transaction `valor`, `tipo`, and `descricao`. |
6262

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/).
95+
6396
## Local Go build
6497

6598
```bash

0 commit comments

Comments
 (0)