Source Audit
Why this page exists
This page records the repo-vs-docs audit points that are easy to miss when reading only the README or landing page. It is source-backed against the current Go handlers, SQL functions, compose files, and GitHub Actions workflows.
Confirmed implementation facts
| Area | Source-backed behavior | Source |
|---|---|---|
| HTTP routes | The API exposes GET /healthz, GET /clientes/{id}/extrato, and POST /clientes/{id}/transacoes. |
src/WebApi/main.go |
| Server timeouts | The HTTP server uses a 5-second read timeout, 10-second write timeout, and 5-second DB context timeout per handler call. | src/WebApi/main.go |
| Client limits | Clients 1–5 are defined in both Go and SQL with limits 100000, 80000, 1000000, 10000000, and 500000. |
main.go, rinha.dump.sql |
| Statement rows | PostgreSQL stores RealizadoEm and selects it in the statement function, but the Go TransacaoDto currently serializes only valor, tipo, and descricao. |
rinha.dump.sql, main.go |
| Binary startup | Running the Go binary outside compose requires DATABASE_URL; compose injects the service connection string. |
main.go, compose files |
| 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 |
Current API contract
GET /healthz
Used by Docker Compose and CI as a readiness smoke check.
HTTP/1.1 200 OK
Healthy
POST /clientes/{id}/transacoes
Request body accepted by the Go handler:
{
"valor": 1000,
"tipo": "c",
"descricao": "deposito"
}
Successful response shape:
{
"id": 1,
"limite": 100000,
"saldo": 1000
}
Validation and error behavior currently implemented:
| Case | Status | Source-backed note |
|---|---|---|
Non-integer {id} |
400 |
strconv.Atoi failure in postTransacaoHandler. |
| Unknown client ID | 404 |
Client not found in the in-memory clientes map. |
| Invalid JSON | 400 |
JSON decode failure. |
Invalid tipo, empty/long descricao, or non-positive valor |
422 |
isTransacaoValid failure. |
| Over-limit debit | 200 |
InsertTransacao refuses the mutation and returns the existing balance; the handler serializes that value. |
| Database/query failure | 500 |
Handler returns the database error as an internal server error. |
GET /clientes/{id}/extrato
Successful response shape currently emitted by Go:
{
"saldo": {
"total": 1000,
"limite": 100000,
"data_extrato": "2026-05-29T22:00:00Z"
},
"ultimas_transacoes": [
{
"valor": 1000,
"tipo": "c",
"descricao": "deposito"
}
]
}
Statement error behavior currently implemented:
| Case | Status | Source-backed note |
|---|---|---|
Non-integer {id} |
400 |
strconv.Atoi failure in getExtratoHandler. |
| Unknown client ID | 404 |
Client not found in the in-memory clientes map. |
| Database row missing | 404 |
Defensive sql.ErrNoRows branch after the stored-function call. |
| Database/query failure | 500 |
Handler returns the database error as an internal server error. |
| Transaction JSON unmarshal failure | 200 |
Handler logs the failure and emits an empty ultimas_transacoes array. |
Behaviors that differ from the original challenge shape
Over-limit debits
The Go handler validates JSON shape, tipo, descricao, and positive valor before calling PostgreSQL. The stored procedure refuses to apply a debit that would exceed the negative credit limit, but it returns the current balance instead of raising an error. The handler then serializes that balance with HTTP 200 unless the database call itself fails.
That means the current implementation behavior is:
- malformed client IDs:
400 - unknown client IDs:
404 - invalid transaction fields:
422 - over-limit debit: no balance mutation; current balance returned by the stored procedure with
200
If strict challenge compatibility requires a 422 for over-limit debits, that is an implementation follow-up rather than a docs-only change.
Statement transaction timestamp
The SQL function includes RealizadoEm in the JSON row source, but the Go response DTO has no timestamp field. The public statement response currently documents the stable fields emitted by Go: valor, tipo, and descricao inside ultimas_transacoes.
If the project wants full challenge response parity, add a timestamp field to TransacaoDto with the expected JSON name and then update the docs.
Runtime stacks
Development/root compose
The root compose file is the local/dev stack:
- builds the Go image from
src/WebApi/Dockerfile - exposes NGINX at
localhost:9999 - exposes direct API containers on
4200and4201 - runs two API containers behind NGINX
least_conn - includes PostgreSQL, Grafana, Prometheus, InfluxDB, postgres-exporter, and k6
- runs k6 with
MODE=dev
Production/release compose
The prod/ compose file is the CI/release stack:
- consumes the GHCR image instead of building from local source
- maps API containers to
8081and8082 - uses config from
prod/conf/ - runs k6 with
MODE=prod - writes the HTML stress report uploaded by
main-release.yml
CI/CD boundaries
Pull-request checks are intentionally path-filtered:
build-check.ymlwatchessrc/**, root Go/Docker/Compose inputs, and its workflow file.- CodeQL watches
src/**, root Go module files, and its workflow file. - Docs-only changes usually skip Docker runtime jobs.
prod/**changes are not part of the PR runtime health filter today; they are exercised bymain-release.ymlafter merge tomain.
Main-branch flows remain the deployment and release path:
deploy.ymlpublishes the Astro static site to GitHub Pages.main-release.ymlbuilds/pushes the GHCR image, runs prod compose health checks, runs k6, and uploads the stress-test report artifact.
Implementation decisions still open
These are now documented, not hidden, but they are implementation choices the project may still want to change later:
- Whether over-limit debits should keep returning unchanged balance with
200or be changed to strict422behavior. - Whether
ultimas_transacoesshould expose the storedRealizadoEmtimestamp for full challenge response parity. - Whether PR path filters should include
prod/**andprod/conf/**so release-stack config changes run the runtime health gate before merge.