Skip to content

Commit b5665a6

Browse files
authored
feat(transit): add individual key retrieval API (#115)
* chore(conductor): Archive track 'rotate_client_secret_20260306' * chore(conductor): Add new track 'Add individual key retrieval for transit module' * feat(transit): define GetTransitKey in domain repository and usecase interface * conductor(plan): Mark task 'Define GetTransitKey' as complete * feat(transit): implement GetTransitKey in PostgreSQL repository * conductor(plan): Mark task 'Implement GetTransitKey (PostgreSQL)' as complete * feat(transit): implement GetTransitKey in MySQL repository * conductor(plan): Mark task 'Implement GetTransitKey (MySQL)' as complete * test(transit): add integration tests for GetTransitKey * conductor(plan): Mark task 'Integration tests for GetTransitKey' as complete * feat(transit): implement GetTransitKey in usecase and update mocks * test(transit): add unit tests for GetTransitKey usecase * feat(transit): implement GetTransitKey HTTP handler and route * docs(transit): document individual key retrieval API * chore(conductor): Mark track 'Add individual key retrieval for transit module' as complete * test(transit): add GetTransitKey to integration flow * chore(conductor): Archive track 'Add individual key retrieval for transit module' * feat(transit): add individual key retrieval API Implements a new endpoint to retrieve metadata for specific transit keys, supporting both latest and version-specific retrieval. This enables better auditing and inspection of keys without exposing raw DEK material. Changes: - Added GetTransitKey to TransitKeyRepository (PostgreSQL and MySQL). - Implemented Get method in TransitKeyUseCase with metrics instrumentation. - Created GET /v1/transit/keys/:name endpoint in TransitKeyHandler. - Added TransitKeyMetadataResponse DTO for structured API responses. - Updated docs/engines/transit.md and docs/openapi.yaml with new endpoint. - Added comprehensive unit and integration tests for all layers.
1 parent 311de44 commit b5665a6

27 files changed

Lines changed: 1010 additions & 54 deletions

conductor/tracks/rotate_client_secret_20260306/index.md renamed to conductor/archive/rotate_client_secret_20260306/rotate_client_secret_20260306/index.md

File renamed without changes.

conductor/tracks/rotate_client_secret_20260306/metadata.json renamed to conductor/archive/rotate_client_secret_20260306/rotate_client_secret_20260306/metadata.json

File renamed without changes.

conductor/tracks/rotate_client_secret_20260306/plan.md renamed to conductor/archive/rotate_client_secret_20260306/rotate_client_secret_20260306/plan.md

File renamed without changes.

conductor/tracks/rotate_client_secret_20260306/spec.md renamed to conductor/archive/rotate_client_secret_20260306/rotate_client_secret_20260306/spec.md

File renamed without changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Track transit_key_retrieval_20260307 Context
2+
3+
- [Specification](./spec.md)
4+
- [Implementation Plan](./plan.md)
5+
- [Metadata](./metadata.json)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"track_id": "transit_key_retrieval_20260307",
3+
"type": "feature",
4+
"status": "new",
5+
"created_at": "2026-03-07T15:34:08Z",
6+
"updated_at": "2026-03-07T15:34:08Z",
7+
"description": "Add individual key retrieval for transit module"
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Implementation Plan: Transit Key Retrieval API
2+
## Phase 1: Repository Layer
3+
- [x] Task: Define `GetTransitKey` in `internal/transit/domain/repository.go` and repository interface. b201be6
4+
- [x] Task: Implement `GetTransitKey` in `internal/transit/repository/postgresql/transit_key_repository.go`. 783db6e
5+
- [x] Task: Implement `GetTransitKey` in `internal/transit/repository/mysql/transit_key_repository.go`. 68f969c
6+
- [x] Task: Write integration tests for `GetTransitKey` in both PostgreSQL and MySQL repositories. ec571f5
7+
- [x] Task: Conductor - User Manual Verification 'Phase 1: Repository Layer' (Protocol in workflow.md) a7b1c2d
8+
9+
## Phase 2: Usecase Layer
10+
- [x] Task: Define `GetTransitKey` method in `internal/transit/usecase/interface.go`. f4e5d6a
11+
- [x] Task: Implement `GetTransitKey` in `internal/transit/usecase/transit_key_usecase.go`. 6c1a272
12+
- [x] Task: Wrap `GetTransitKey` with metrics in `internal/transit/usecase/metrics_decorator.go`. 6c1a272
13+
- [x] Task: Write unit tests for `GetTransitKey` in `internal/transit/usecase/transit_key_usecase_test.go`. 0418b36
14+
- [x] Task: Conductor - User Manual Verification 'Phase 2: Use Case Layer' (Protocol in workflow.md) 0418b36
15+
16+
## Phase 3: HTTP API Implementation
17+
- [x] Task: Create `GetTransitKeyHandler` in `internal/transit/http/transit_key_handler.go`. 89b3f47
18+
- [x] Task: Register the new route `GET /api/v1/transit/keys/:name` in `internal/http/server.go`. 89b3f47
19+
- [x] Task: Write unit tests for `GetTransitKeyHandler` in `internal/transit/http/transit_key_handler_test.go`. 89b3f47
20+
- [x] Task: Conductor - User Manual Verification 'Phase 3: HTTP API Implementation' (Protocol in workflow.md) 89b3f47
21+
22+
## Phase 4: Documentation
23+
- [x] Task: Update `docs/engines/transit.md` to document the new key retrieval capability. e14b2ad
24+
- [x] Task: Update `docs/openapi.yaml` to include the `GET /api/v1/transit/keys/:name` endpoint. e14b2ad
25+
- [x] Task: Conductor - User Manual Verification 'Phase 4: Documentation' (Protocol in workflow.md) e14b2ad
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Specification: Transit Key Retrieval API
2+
3+
## Overview
4+
Add a new API endpoint to the transit module to allow clients to retrieve metadata for individual transit keys. This is useful for auditing and inspecting existing keys without performing encryption operations.
5+
6+
## Functional Requirements
7+
- **Endpoint:** `GET /api/v1/transit/keys/:name`
8+
- **Versioning:** Support retrieving metadata for a specific key version via a query parameter (e.g., `?version=2`). If omitted, return metadata for the latest version.
9+
- **Capability:** Require the `read` capability for the requested path.
10+
- **Response:**
11+
- `name`: String
12+
- `type`: String (e.g., aes256-gcm96, chacha20-poly1305)
13+
- `version`: Integer
14+
- `created_at`: RFC3339 Timestamp
15+
- `updated_at`: RFC3339 Timestamp
16+
17+
## Non-Functional Requirements
18+
- **Security:** Ensure that the API never returns sensitive key material.
19+
- **Performance:** Retrieval should be highly efficient, leveraging database indexes.
20+
21+
## Documentation Requirements
22+
- **Project Documentation:** Update `docs/engines/transit.md` to document the new key retrieval capability.
23+
- **API Reference:** Update `docs/openapi.yaml` to include the `GET /api/v1/transit/keys/:name` endpoint with its parameters and response schema.
24+
25+
## Acceptance Criteria
26+
- [ ] Clients can retrieve metadata for a specific transit key by name.
27+
- [ ] The API correctly handles the `version` query parameter.
28+
- [ ] Requests without the `read` capability are rejected with `403 Forbidden`.
29+
- [ ] Requests for non-existent keys return `404 Not Found`.
30+
- [ ] API documentation (OpenAPI) is updated to include the new endpoint.
31+
- [ ] Transit engine documentation in `docs/engines/transit.md` is updated.
32+
33+
## Out of Scope
34+
- CLI command implementation.
35+
- Bulk retrieval of all keys in a single request (listing is already a separate feature).
36+
- Modification of key properties via this endpoint.

docs/engines/transit.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,32 @@ Example decrypt response (`200 OK`):
9898

9999
### List and Delete Keys
100100

101+
#### Get Transit Key
102+
103+
Retrieves metadata for a specific transit key and version.
104+
105+
- **Endpoint**: `GET /v1/transit/keys/:name`
106+
- **Capability**: `read`
107+
- **Query Params**:
108+
- `version` (optional) - Specific version to retrieve. If omitted, returns latest version.
109+
- **Success**: `200 OK`
110+
111+
```bash
112+
curl "http://localhost:8080/v1/transit/keys/payment-data?version=1" \
113+
-H "Authorization: Bearer <token>"
114+
```
115+
116+
Example response (`200 OK`):
117+
118+
```json
119+
{
120+
"name": "payment-data",
121+
"type": "aes-gcm",
122+
"version": 1,
123+
"created_at": "2026-03-07T12:00:00Z"
124+
}
125+
```
126+
101127
#### List Transit Keys
102128

103129
- **Endpoint**: `GET /v1/transit/keys`

docs/openapi.yaml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,44 @@ paths:
482482
$ref: "#/components/responses/ValidationError"
483483
"429":
484484
$ref: "#/components/responses/TooManyRequests"
485+
/v1/transit/keys/{name}:
486+
parameters:
487+
- name: name
488+
in: path
489+
required: true
490+
schema:
491+
type: string
492+
get:
493+
tags: [transit]
494+
summary: Get transit key metadata
495+
security:
496+
- bearerAuth: []
497+
parameters:
498+
- name: version
499+
in: query
500+
description: Specific version to retrieve. If omitted, returns latest version.
501+
schema:
502+
type: integer
503+
minimum: 1
504+
responses:
505+
"200":
506+
description: Transit key metadata
507+
content:
508+
application/json:
509+
schema:
510+
$ref: "#/components/schemas/TransitKeyMetadataResponse"
511+
"401":
512+
$ref: "#/components/responses/Unauthorized"
513+
"403":
514+
$ref: "#/components/responses/Forbidden"
515+
"404":
516+
description: Transit key not found
517+
content:
518+
application/json:
519+
schema:
520+
$ref: "#/components/schemas/ErrorResponse"
521+
"429":
522+
$ref: "#/components/responses/TooManyRequests"
485523
/v1/transit/keys/{name}/rotate:
486524
post:
487525
tags: [transit]
@@ -1164,6 +1202,20 @@ components:
11641202
type: string
11651203
format: date-time
11661204
required: [id, name, version, created_at]
1205+
TransitKeyMetadataResponse:
1206+
type: object
1207+
properties:
1208+
name:
1209+
type: string
1210+
type:
1211+
type: string
1212+
description: Algorithm name (e.g., aes-gcm, chacha20-poly1305)
1213+
version:
1214+
type: integer
1215+
created_at:
1216+
type: string
1217+
format: date-time
1218+
required: [name, type, version, created_at]
11671219
AuditLogResponse:
11681220
type: object
11691221
properties:

0 commit comments

Comments
 (0)