Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ 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.16.0] - 2026-02-25

### Added
- Added listing endpoints with pagination (`offset`, `limit`) for secrets (`GET /v1/secrets`), transit keys (`GET /v1/transit/keys`), and tokenization keys (`GET /v1/tokenization/keys`)
- Added list DTO structures for consistent API responses across modules

## [0.15.0] - 2026-02-25

### Added
Expand Down
7 changes: 7 additions & 0 deletions GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ Configuration is managed via environment variables (see `internal/config/config.
### Testing Practices
- **Parallel Tests:** Unit tests should be able to run in parallel.
- **Integration Tests:** Located in `test/integration/`. Use `make test-with-db` to run them locally.
- **CRITICAL:** Every new repository method (e.g., `Create`, `Get`, `List`, `Delete`) MUST have corresponding tests written natively in BOTH its `mysql_..._repository_test.go` and `postgresql_..._repository_test.go` files, and must be validated to pass against the test databases via `make test-with-db`.
- **HTTP/DTO Tests:**
- **CRITICAL:** Every new HTTP handler (e.g., `ListHandler`, `CreateHandler`) MUST have corresponding unit tests in its `..._handler_test.go` file.
- **CRITICAL:** Every new mapping DTO (e.g., `MapSecretsToListResponse`) MUST have corresponding unit tests in its package (e.g., `list_secrets_response_test.go`) to ensure accurate payload mapping.
- **Usecase Tests:**
- **CRITICAL:** Every new usecase method MUST have corresponding unit tests written natively in its `..._usecase_test.go` file to ensure core business logic is tested independently.
- **Coverage:** Aim for high coverage in `usecase` and `domain` layers.

### Contribution Guidelines
Expand All @@ -63,6 +69,7 @@ Configuration is managed via environment variables (see `internal/config/config.
3. **Changelog:** Every new version MUST be added to the high-level `CHANGELOG.md` in the root directory.
4. **Main Version:** The `version` variable in `cmd/app/main.go` MUST be updated to match the new release version.
5. **Docs Linting:** The command `make docs-lint` MUST be executed and all issues resolved.
6. **OpenAPI Spec:** Any new API handler or configuration change MUST be reflected in `docs/openapi.yaml`.
- **Migrations:** New database changes must include both `up` and `down` SQL scripts for both MySQL and PostgreSQL.

### Tooling
Expand Down
2 changes: 1 addition & 1 deletion cmd/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

// Build-time version information (injected via ldflags during build).
var (
version = "v0.15.0" // Semantic version with "v" prefix (e.g., "v0.12.0")
version = "v0.16.0" // Semantic version with "v" prefix (e.g., "v0.12.0")
buildDate = "unknown" // ISO 8601 build timestamp
commitSHA = "unknown" // Git commit SHA
)
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Welcome to the full documentation for Secrets. Pick a path and dive in 🚀

OpenAPI scope note:

- `openapi.yaml` is a baseline subset for common API flows in the current release (v0.15.0, see `docs/metadata.json`)
- `openapi.yaml` is a baseline subset for common API flows in the current release (v0.16.0, see `docs/metadata.json`)
- Full endpoint behavior is documented in the endpoint pages under `docs/api/`
- Tokenization endpoints are included in `openapi.yaml` for the current release

Expand Down
32 changes: 32 additions & 0 deletions docs/api/data/secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ All endpoints require Bearer authentication.

- `POST /v1/secrets/*path` (create or update)
- `GET /v1/secrets/*path` (read latest)
- `GET /v1/secrets` (list secrets with pagination)
- `DELETE /v1/secrets/*path` (soft delete latest)

## Status Code Quick Reference
Expand All @@ -25,6 +26,7 @@ All endpoints require Bearer authentication.
| --- | --- | --- |
| `POST /v1/secrets/*path` | `201` | `401`, `403`, `422`, `429` |
| `GET /v1/secrets/*path` | `200` | `401`, `403`, `404`, `429` |
| `GET /v1/secrets` | `200` | `401`, `403`, `422`, `429` |
| `DELETE /v1/secrets/*path` | `204` | `401`, `403`, `404`, `429` |

## Create or Update Secret
Expand Down Expand Up @@ -70,6 +72,35 @@ Example response (`200 OK`):
}
```

## List Secrets

```bash
curl "http://localhost:8080/v1/secrets?offset=0&limit=50" \
-H "Authorization: Bearer <token>"
```

Pagination parameters:

- `offset`: Defaults to `0`
- `limit`: Defaults to `50` (max `100`)

Example response (`200 OK`):

```json
{
"items": [
{
"id": "0194f4a5-73fe-7a7d-a3a0-6fbe9b5ef8f3",
"path": "/app/prod/database-password",
"version": 3,
"created_at": "2026-02-14T18:22:00Z"
}
]
}
```

> **Note**: Secret values are deliberately excluded from list responses. Use `GET /v1/secrets/*path` to retrieve specific secret payloads.

## Delete Secret

```bash
Expand Down Expand Up @@ -144,6 +175,7 @@ Expected result: write returns `201 Created`; read returns `200 OK` with base64

- `POST /v1/secrets/*path` -> `encrypt`
- `GET /v1/secrets/*path` -> `decrypt`
- `GET /v1/secrets` -> `read`
- `DELETE /v1/secrets/*path` -> `delete`

Wildcard matcher semantics reference:
Expand Down
29 changes: 29 additions & 0 deletions docs/api/data/tokenization.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ All endpoints require `Authorization: Bearer <token>`.

Key management:

- `GET /v1/tokenization/keys` (list keys)
- `POST /v1/tokenization/keys` (create key)
- `POST /v1/tokenization/keys/:name/rotate` (rotate key)
- `DELETE /v1/tokenization/keys/:id` (soft delete key)
Expand All @@ -38,6 +39,7 @@ Capability mapping:

| Endpoint | Required capability |
| --- | --- |
| `GET /v1/tokenization/keys` | `read` |
| `POST /v1/tokenization/keys` | `write` |
| `POST /v1/tokenization/keys/:name/rotate` | `rotate` |
| `DELETE /v1/tokenization/keys/:id` | `delete` |
Expand All @@ -50,6 +52,7 @@ Capability mapping:

| Endpoint | Success | Common error statuses |
| --- | --- | --- |
| `GET /v1/tokenization/keys` | `200` | `401`, `403`, `422`, `429` |
| `POST /v1/tokenization/keys` | `201` | `401`, `403`, `409`, `422`, `429` |
| `POST /v1/tokenization/keys/:name/rotate` | `201` | `401`, `403`, `404`, `422`, `429` |
| `DELETE /v1/tokenization/keys/:id` | `204` | `401`, `403`, `404`, `422`, `429` |
Expand All @@ -58,6 +61,32 @@ Capability mapping:
| `POST /v1/tokenization/validate` | `200` | `401`, `403`, `422`, `429` |
| `POST /v1/tokenization/revoke` | `204` | `401`, `403`, `404`, `422`, `429` |

## List Tokenization Keys

Retrieves a paginated list of tokenization keys, showing the latest version for each.

```bash
curl "http://localhost:8080/v1/tokenization/keys?offset=0&limit=50" \
-H "Authorization: Bearer <token>"
```

Example response (`200 OK`):

```json
{
"items": [
{
"id": "0194f4a6-7ec7-78e6-9fe7-5ca35fef48db",
"name": "payment-cards",
"version": 1,
"format_type": "luhn-preserving",
"is_deterministic": true,
"created_at": "2026-02-18T10:30:00Z"
}
]
}
```

## Create Tokenization Key

Creates the initial tokenization key version (`version = 1`) for a key name.
Expand Down
28 changes: 28 additions & 0 deletions docs/api/data/transit.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ All endpoints require Bearer authentication.

## Endpoints

- `GET /v1/transit/keys` (list keys)
- `POST /v1/transit/keys` (create key)
- `POST /v1/transit/keys/:name/rotate` (rotate key)
- `DELETE /v1/transit/keys/:id` (soft delete key)
Expand All @@ -36,6 +37,7 @@ All endpoints require Bearer authentication.

Capability mapping:

- `GET /v1/transit/keys` -> `read`
- `POST /v1/transit/keys` -> `write`
- `POST /v1/transit/keys/:name/rotate` -> `rotate`
- `DELETE /v1/transit/keys/:id` -> `delete`
Expand All @@ -50,12 +52,38 @@ Wildcard matcher semantics reference:

| Endpoint | Success | Common error statuses |
| --- | --- | --- |
| `GET /v1/transit/keys` | `200` | `401`, `403`, `422`, `429` |
| `POST /v1/transit/keys` | `201` | `401`, `403`, `409`, `422`, `429` |
| `POST /v1/transit/keys/:name/rotate` | `200` | `401`, `403`, `404`, `422`, `429` |
| `POST /v1/transit/keys/:name/encrypt` | `200` | `401`, `403`, `404`, `422`, `429` |
| `POST /v1/transit/keys/:name/decrypt` | `200` | `401`, `403`, `404`, `422`, `429` |
| `DELETE /v1/transit/keys/:id` | `204` | `401`, `403`, `404`, `422`, `429` |

## List Transit Keys

```bash
curl "http://localhost:8080/v1/transit/keys?offset=0&limit=50" \
-H "Authorization: Bearer <token>"
```

Retrieves a paginated list of transit keys. Only the latest active version of each key name is returned.

Example response (`200 OK`):

```json
{
"items": [
{
"id": "0194f4a6-7ec7-78e6-9fe7-5ca35fef48db",
"name": "payment-data",
"algorithm": "aes-gcm",
"version": 2,
"created_at": "2026-02-15T10:30:00Z"
}
]
}
```

## Create Transit Key

Creates the initial transit key version (`version = 1`) for a key name.
Expand Down
2 changes: 1 addition & 1 deletion docs/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"current_release": "v0.15.0",
"current_release": "v0.16.0",
"api_version": "v1",
"last_docs_refresh": "2026-02-25"
}
97 changes: 97 additions & 0 deletions docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,39 @@ paths:
$ref: "#/components/schemas/ErrorResponse"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/secrets:
get:
tags: [secrets]
summary: List secrets
security:
- bearerAuth: []
parameters:
- name: offset
in: query
schema:
type: integer
- name: limit
in: query
schema:
type: integer
responses:
"200":
description: Secrets list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: "#/components/schemas/SecretWriteResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/secrets/{path}:
parameters:
- name: path
Expand Down Expand Up @@ -219,6 +252,38 @@ paths:
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/transit/keys:
get:
tags: [transit]
summary: List transit keys
security:
- bearerAuth: []
parameters:
- name: offset
in: query
schema:
type: integer
- name: limit
in: query
schema:
type: integer
responses:
"200":
description: Transit keys list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: "#/components/schemas/TransitKeyResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
post:
tags: [transit]
summary: Create transit key
Expand Down Expand Up @@ -360,6 +425,38 @@ paths:
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/tokenization/keys:
get:
tags: [tokenization]
summary: List tokenization keys
security:
- bearerAuth: []
parameters:
- name: offset
in: query
schema:
type: integer
- name: limit
in: query
schema:
type: integer
responses:
"200":
description: Tokenization keys list
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: "#/components/schemas/TokenizationKeyResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
post:
tags: [tokenization]
summary: Create tokenization key
Expand Down
4 changes: 2 additions & 2 deletions docs/operations/deployment/production-rollout.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ docker run -d --name secrets-api \

```bash
# Update docker-compose.yml to use previous version
sed -i.bak 's|allisson/secrets:v0.15.0|allisson/secrets:v<PREVIOUS_VERSION>|' docker-compose.yml
sed -i.bak 's|allisson/secrets:v0.16.0|allisson/secrets:v<PREVIOUS_VERSION>|' docker-compose.yml

# Restart service
docker-compose up -d secrets-api
Expand Down Expand Up @@ -239,7 +239,7 @@ docker run -d --name secrets-api \
--network secrets-net \
--env-file .env \
-p 8080:8080 \
allisson/secrets:v0.15.0 server
allisson/secrets:v0.16.0 server

# Verify health and functionality (repeat Step 3 checks)

Expand Down
14 changes: 13 additions & 1 deletion docs/releases/RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ For the compatibility matrix across versions, see [compatibility-matrix.md](comp

## 📑 Quick Navigation

**Latest Release**: [v0.15.0](#0150---2026-02-25)
**Latest Release**: [v0.16.0](#0160---2026-02-25)

**All Releases**:

- [v0.16.0 (2026-02-25)](#0160---2026-02-25) - Listing Endpoints

- [v0.15.0 (2026-02-25)](#0150---2026-02-25) - Goreleaser support

- [v0.14.1 (2026-02-25)](#0141---2026-02-25) - KEK bug fixes
Expand Down Expand Up @@ -50,6 +52,16 @@ For the compatibility matrix across versions, see [compatibility-matrix.md](comp

---

## [0.16.0] - 2026-02-25

### Added

- Added `/v1/secrets` endpoint for listing secrets with pagination (does not return secret data)
- Added `/v1/transit/keys` endpoint for listing transit keys with pagination
- Added `/v1/tokenization/keys` endpoint for listing tokenization keys with pagination

---

## [0.15.0] - 2026-02-25

### Added
Expand Down
Loading
Loading