pg-api 0.3.13

A high-performance PostgreSQL REST API driver with rate limiting, connection pooling, and observability
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.13] - 2026-09-21

### Fixed

- Comandos transacionais (`BEGIN`, `SET LOCAL`, `COMMIT`) preservam o SQLSTATE e os
  campos de diagnóstico do PostgreSQL em vez de retornar apenas `db error`.
- Conexões do pool não são mais recicladas com transação aberta ou abortada: um
  request cancelado pelo cliente, uma sessão expirada sem commit/rollback ou uma
  falha de `ROLLBACK` descartam a conexão em vez de devolvê-la ao pool. Sem isso,
  o request seguinte falhava no `BEGIN` com
  `25P02 current transaction is aborted` — sintoma do incidente de 21/09/2026
  (conexões `idle in transaction (aborted)` reaproveitadas).
- Sessões transacionais expiradas (`TRANSACTION_SESSION_TTL_SECS`) são encerradas
  com `ROLLBACK` em background antes de a conexão voltar ao pool.

### Added

- Testes de integração de higiene de conexão (`tests/connection_hygiene.rs`),
  cobrindo preservação de SQLSTATE e cancelamento de cliente.

## [0.3.12] - 2026-09-19

### Fixed

- Controle de concorrência por conta agora usa semáforos, com aquisição e liberação atômicas.
- Permits são liberados automaticamente em cancelamentos, erros e panics, evitando contadores presos.\n\n## [0.3.11] - 2026-09-18

### Fixed

- Compatibilidade de inicialização com o alias legado readwrite usado em contas de produção.

## [0.3.10] - 2026-09-18

### Added

- Observabilidade de requisições no journal e no OpenSearch, com request_id, IP do cliente, conta autenticada, banco, tipo de consulta, status HTTP e duração.
- Auditoria de autenticação por conta, sem registrar API keys ou SQL bruto.

### Fixed

- O middleware de métricas reutiliza o x-request-id propagado pela requisição, permitindo correlação com os logs do Nginx e do PG-API.

## [0.3.9] - 2026-09-16

Consolidação sobre 0.3.7: sessões transacionais persistentes, níveis de
isolamento explícitos, disposable databases autorizados, backup remoto,
blocos DO em migrations — mais as correções abaixo.

### Fixed

- Conexões em estado abortado são curadas com ROLLBACK antes de voltar ao
  pool (single-query, transações e sessões).
- Erros PostgreSQL preservam SQLSTATE e campos de diagnóstico em
  `/v1/query`, transações e sessões (antes: `db error` mascarado).
- Administrative `DO $$...$$` blocks now execute correctly during migrations.

## [0.3.8] - 2026-09-16

Consolidação sobre 0.3.7: sessões transacionais persistentes, níveis de
isolamento explícitos, disposable databases autorizados, backup remoto,
blocos DO em migrations — mais as correções abaixo.

### Fixed

- Conexões em estado abortado são curadas com ROLLBACK antes de voltar ao
  pool (single-query, transações e sessões).
- Erros PostgreSQL preservam SQLSTATE e campos de diagnóstico em
  `/v1/query`, transações e sessões (antes: `db error` mascarado).
- Administrative `DO $$...$$` blocks now execute correctly during migrations.

## [0.3.4] - 2026-09-07

### Fixed
- **rows_affected reais para escritas sem RETURNING**: `metadata.rows_affected`
  vinha de `rows.len()` (sempre 0 sem RETURNING), quebrando verificacoes de
  `ensure!(afetadas == 1)` nos clientes. Escritas INSERT/UPDATE/DELETE/MERGE
  sem RETURNING agora usam `execute()` (contagem real do Postgres);
  leituras e escritas com RETURNING mantem o caminho anterior.
  Deteccao literal-aware (reusa o scanner do gate).

## [0.3.3] - 2026-09-06

### Fixed
- timestamptz decoding: rows_to_json usava NaiveDateTime para timestamp e timestamptz, retornando null para valores com timezone. timestamp continua NaiveDateTime (YYYY-MM-DD HH:MM:SS); timestamptz agora decodifica como DateTime Utc e serializa em RFC3339.

## [0.3.2] - 2026-09-04

### Fixed
- **Param compat (0.1.x semantics)**: `0.3.0/0.3.1` usavam bind binario
  estrito e quebravam queries legitimas (inteiro JSON vs coluna
  int2/int4/float, `$1` solto em SELECT, params extras ignorados antes).
  Params agora sao interpolados com escaping correto (`''`, `E''` p/
  backslash) + gate de statements mantido. Extra params voltam a ser
  ignorados; placeholder sem valor continua erro.

## [0.3.1] - 2026-09-04

### Fixed
- Legacy role aliases: `owner` → `superuser`, `read_only`/`read-only` →
  `readonly`, `app` → `application`, `administrator` → `admin`.
  Pre-0.2 `accounts.json` files (which still use `"owner"`) parse again.

## [0.3.0] - 2026-09-04

Security-hardening release. Request/response shapes are unchanged, but
operators must read the migration notes below.

### Breaking
- **Fail-closed startup**: the service no longer starts with a hardcoded
  `sentric-production` account. A valid `config/accounts.json` is required
  (`pg-api setup` creates one). The previous fallback shipped a publicly
  known API key and database password inside the binary.
- **API keys are hashed (SHA-256) at rest**: new accounts created by
  `pg-api setup` store only the hash (raw key shown once). Existing
  plaintext keys keep working (hashed on load) but log a rotation warning.
- **Honest stubs**: `POST /v1/databases`, `DELETE /v1/databases/{name}`,
  `GET /v1/databases/{db}/schema` and `GET /v1/account/usage` now return
  `NOT_IMPLEMENTED` instead of fabricated success payloads.

### Added
- Real SQL gate: single-statement enforcement, comment stripping,
  `WITH`-with-writes requires the matching write permission, deny-lists for
  `COPY`, transaction control, session commands and dangerous functions
  (`pg_read_file`, `dblink`, …). New codes: `MULTI_STATEMENT_NOT_ALLOWED`,
  `STATEMENT_NOT_ALLOWED`, `STATEMENT_TIMEOUT`.
- `options` are now enforced: per-query `statement_timeout` (default 60s,
  ceiling 300s) and `read_only` (`BEGIN … READ ONLY`).
- `/v1/transaction` executes a real atomic transaction (single connection,
  rollback on error); `/v1/batch` and transactions are capped at 50 items.
- HTTP budgets from `server.json` are enforced (`RequestBodyLimit`,
  request timeout → 408) and CORS follows `server.json` instead of a
  blanket permissive policy; `X-Content-Type-Options: nosniff` added.
- `x-request-id` is now also returned in the response.
- `pg-api setup`: password input without echo, `accounts.json` saved `0600`,
  API keys stored hashed.
- `Cargo.toml` `[exclude]`: the crate no longer ships `dist/` tarballs,
  backups, patches or credential files (0.2.0 weighed 6.8 MB for this reason).

### Migration (operator)
1. Ensure `config/accounts.json` exists (run `pg-api setup` if unsure);
   the server will refuse to boot without it — this is intentional.
2. Rotate API keys at your convenience; update clients' `PG_API_KEY`.
3. Mark pure reads with `options: {"read_only": true}` to gain extra safety.
4. Handle the three new error codes in clients.
5. Rotate any secret that ever lived in the repo root (`prod.env`,
   `evoluame_*`, `license_*`) — removed from the tree in this release.

## [0.2.0] - 2026-05-20

### Changed
- **Parametrização real de queries**: substituído `substitute_params` (vulnerável a SQL injection) por `PgParam`/`ToSql` com `bytes::BytesMut`
- **Roles renomeadas**: `AccountRole::Owner` → `Superuser`, `AccountRole::ReadOnly` → `Readonly` (compatível com produção)
- **list_tables**: checa `response.success` antes de acessar `data`

### Added
- `ApiResponse::error_with_details` para erros com detalhes extras
- `ErrorInfo.details: Option<Value>` serializado como `null`
- Dependência `bytes = "1"` para implementação `ToSql`

### Fixed
- `list_tables` não propagava erros corretamente da query interna

## [0.1.1] - 2025-02-16

### Added
- **Documentação completa para novos usuários**:
  - `README.md` com quick start, badges e exemplos
  - `docs/API.md` com documentação completa dos endpoints
  - `docs/QUICKSTART.md` com tutorial passo a passo
  - `examples/` com exemplos em cURL, Python e Rust
- **Testes automatizados**:
  - Testes unitários para `auth`, `models`, `config`, `database`
  - Testes de integração em `tests/` (health, auth, queries, rate limiting)
  - Benchmarks com Criterion em `benches/`
- Melhorias na cobertura de testes (de ~5% para ~40%)

### Changed
- Atualizado `Cargo.toml` com metadados completos do projeto
- Atualizado `AGENTS.md` com guidelines para desenvolvimento

## [0.1.0] - 2025-08-05

### Added
- Initial release of pg-api PostgreSQL driver service
- RESTful API endpoints for PostgreSQL database operations
- Authentication via API keys (X-API-Key header)
- Account-based access control with role-based permissions
- Database query execution endpoints:
  - `/v1/query` - Single query execution
  - `/v1/batch` - Batch query execution
  - `/v1/transaction` - Transactional query execution
- Database management endpoints:
  - `/v1/databases` - List and create databases
  - `/v1/databases/{name}` - Drop database
  - `/v1/databases/{db}/tables` - List tables
  - `/v1/databases/{db}/schema` - Get database schema
- Account management endpoints:
  - `/v1/account` - Get account information
  - `/v1/account/usage` - Get usage statistics
- Health check and status endpoints
- OpenAPI documentation at `/docs`
- Connection pooling using Deadpool
- Structured JSON logging with tracing
- CORS support
- Rate limiting middleware:
  - Sliding window rate limiter (60-second window)
  - Per-account rate limits configurable in account settings
  - Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset)
  - 429 Too Many Requests responses when rate limit exceeded

### Security Features
- API key authentication required for all endpoints except health checks
- Role-based access control (Owner, Admin, User roles)
- Fine-grained database permissions (SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, etc.)
- Query permission validation based on account roles and database access

### Planned Features (Not Yet Implemented)
- Connection limiting per account
- Query timeout enforcement
- Audit logging for database operations

### Configuration
- Environment-based configuration support
- Instance and account configuration via JSON files
- Configurable server host, port, and log level

### Technical Details
- Built with Rust and Axum web framework
- Async/await throughout using Tokio
- PostgreSQL driver: tokio-postgres
- Connection pooling: deadpool-postgres
- JSON serialization: serde_json
- Date/time handling: chrono
- UUID support for identifiers