Skip to content

Commit d854296

Browse files
authored
docs: add transit create vs rotate guidance (#47)
- Clarifies transit key create behavior (returns 409 when key name already exists at version=1) and documents that rotate is required for subsequent versions. - Adds comprehensive endpoint error matrices, failure playbooks for 401/403/409 incidents, API versioning policy page, glossary, and ADRs for envelope encryption and transit ciphertext contract. - Introduces executable example shape checks (make docs-check-examples) with CI integration to validate JSON payloads used in documentation. - Updates all API reference pages with status code quick-reference tables and cross-links. - Enhances example pages (curl/python/javascript/go) with environment bootstrap sections and common mistakes guidance. - Transit create usecase now returns ErrTransitKeyAlreadyExists (409) when attempting to create duplicate key names, preventing silent failures in automation workflows.
1 parent 706f8f3 commit d854296

29 files changed

Lines changed: 695 additions & 19 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ jobs:
6262
docs/**/*.md
6363
.github/pull_request_template.md
6464
65+
- name: Example shape checks
66+
run: python3 docs/tools/check_example_shapes.py
67+
6568
- name: Markdown link check (offline)
6669
uses: lycheeverse/lychee-action@v2
6770
with:

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: help build run test lint clean migrate-up migrate-down docker-build docker-run mocks docs-lint
1+
.PHONY: help build run test lint clean migrate-up migrate-down docker-build docker-run mocks docs-lint docs-check-examples
22

33
APP_NAME := app
44
BINARY_DIR := bin
@@ -70,9 +70,14 @@ mocks: ## Regenerate mock implementations
7070
@mockery
7171
@echo "Mocks regenerated"
7272

73+
docs-check-examples: ## Validate JSON shapes used by docs examples
74+
@echo "Running docs example shape checks..."
75+
@python3 docs/tools/check_example_shapes.py
76+
7377
docs-lint: ## Run markdown lint and offline link checks
7478
@echo "Running markdownlint-cli2..."
7579
@docker run --rm -v "$(PWD):/workdir" -w /workdir davidanson/markdownlint-cli2:v0.18.1 README.md "docs/**/*.md" ".github/pull_request_template.md"
80+
@$(MAKE) docs-check-examples
7681
@echo "Running lychee offline link checks..."
7782
@docker run --rm -v "$(PWD):/input" lycheeverse/lychee:latest --offline --include-fragments --no-progress "/input/README.md" "/input/docs/**/*.md" "/input/.github/pull_request_template.md"
7883

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ Then follow the Docker setup guide in [docs/getting-started/docker.md](docs/gett
3838
- ⚙️ **Environment variables**: [docs/configuration/environment-variables.md](docs/configuration/environment-variables.md)
3939
- 🏗️ **Architecture concepts**: [docs/concepts/architecture.md](docs/concepts/architecture.md)
4040
- 🔒 **Security model**: [docs/concepts/security-model.md](docs/concepts/security-model.md)
41+
- 📘 **Glossary**: [docs/concepts/glossary.md](docs/concepts/glossary.md)
4142
- 🔑 **Key management operations**: [docs/operations/key-management.md](docs/operations/key-management.md)
43+
- 🚑 **Failure playbooks**: [docs/operations/failure-playbooks.md](docs/operations/failure-playbooks.md)
4244
- 🏭 **Production deployment**: [docs/operations/production.md](docs/operations/production.md)
4345
- 🛠️ **Development and testing**: [docs/development/testing.md](docs/development/testing.md)
4446
- 🤝 **Docs contributing**: [docs/contributing.md](docs/contributing.md)
@@ -51,6 +53,7 @@ Then follow the Docker setup guide in [docs/getting-started/docker.md](docs/gett
5153
- 📦 **Secrets API**: [docs/api/secrets.md](docs/api/secrets.md)
5254
- 🚄 **Transit API**: [docs/api/transit.md](docs/api/transit.md)
5355
- 📜 **Audit logs API**: [docs/api/audit-logs.md](docs/api/audit-logs.md)
56+
- 🧩 **API versioning policy**: [docs/api/versioning-policy.md](docs/api/versioning-policy.md)
5457

5558
- **Examples**
5659
- 🧪 **Curl examples**: [docs/examples/curl.md](docs/examples/curl.md)
@@ -63,7 +66,7 @@ All detailed guides include practical use cases and copy/paste-ready examples.
6366
## ✨ What You Get
6467

6568
- 🔐 Envelope encryption (`Master Key -> KEK -> DEK -> Secret Data`)
66-
- 🚄 Transit encryption (`/v1/transit/keys/*`) for encrypt/decrypt as a service (decrypt input uses `<version>:<base64-ciphertext>`; see [Transit API docs](docs/api/transit.md))
69+
- 🚄 Transit encryption (`/v1/transit/keys/*`) for encrypt/decrypt as a service (decrypt input uses `<version>:<base64-ciphertext>`; see [Transit API docs](docs/api/transit.md), [create vs rotate](docs/api/transit.md#create-vs-rotate), and [error matrix](docs/api/transit.md#endpoint-error-matrix))
6770
- 👤 Token-based authentication and policy-based authorization
6871
- 📦 Versioned secrets by path (`/v1/secrets/*path`)
6972
- 📜 Audit logs with request correlation (`request_id`) and filtering
@@ -75,7 +78,7 @@ All detailed guides include practical use cases and copy/paste-ready examples.
7578
- Token issuance: `POST /v1/token`
7679
- Clients: `GET/POST /v1/clients`, `GET/PUT/DELETE /v1/clients/:id`
7780
- Secrets: `POST/GET/DELETE /v1/secrets/*path`
78-
- Transit: `POST /v1/transit/keys`, `POST /v1/transit/keys/:name/rotate`, `POST /v1/transit/keys/:name/encrypt`, `POST /v1/transit/keys/:name/decrypt`, `DELETE /v1/transit/keys/:id`
81+
- Transit: `POST /v1/transit/keys`, `POST /v1/transit/keys/:name/rotate`, `POST /v1/transit/keys/:name/encrypt`, `POST /v1/transit/keys/:name/decrypt`, `DELETE /v1/transit/keys/:id` ([create vs rotate](docs/api/transit.md#create-vs-rotate), [error matrix](docs/api/transit.md#endpoint-error-matrix))
7982
- Audit logs: `GET /v1/audit-logs`
8083

8184
## 📄 License

docs/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@
2929
- Added transit decrypt input contract examples (valid/invalid) and representative `422` payloads
3030
- Added OpenAPI decrypt request examples and explicit `401`/`403`/`404` responses
3131
- Added 422 troubleshooting matrix and transit round-trip verification/decode notes in examples
32+
- Clarified transit key create behavior: duplicate key names now documented as `409 Conflict` and rotate is required for new versions
33+
- Added transit create-vs-rotate guidance, idempotency notes, endpoint error matrix, and representative `409` conflict payload examples
34+
- Added transit automation runbook note for handling create `409` by rotating keys
35+
- Added API status code quick-reference tables to clients, secrets, transit, and audit docs
36+
- Added glossary page and cross-links from API/reference documentation
37+
- Added example-page common mistakes sections (curl, python, javascript, go)
38+
- Added docs contribution policy for breaking vs non-breaking documentation updates
39+
- Added docs freshness SLA table in docs index
40+
- Added failure playbooks for 401/403/409 incident triage
41+
- Added API compatibility/versioning policy page for breaking/non-breaking expectations
42+
- Added ADRs for envelope encryption model and transit versioned ciphertext contract
43+
- Added executable example shape checks (`make docs-check-examples`) and CI integration
44+
- Added environment bootstrap sections to all examples pages
3245

3346
## See also
3447

docs/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,24 @@ Welcome to the full documentation for Secrets. Pick a path and dive in 🚀
2222
- ⚙️ [configuration/environment-variables.md](configuration/environment-variables.md)
2323
- 🏗️ [concepts/architecture.md](concepts/architecture.md)
2424
- 🔒 [concepts/security-model.md](concepts/security-model.md)
25+
- 📘 [concepts/glossary.md](concepts/glossary.md)
2526
- 🔑 [operations/key-management.md](operations/key-management.md)
2627
- 🏭 [operations/production.md](operations/production.md)
28+
- 🚑 [operations/failure-playbooks.md](operations/failure-playbooks.md)
2729
- 🛠️ [development/testing.md](development/testing.md)
2830
- 🤝 [contributing.md](contributing.md)
2931
- 🗒️ [CHANGELOG.md](CHANGELOG.md)
3032

33+
## 🧭 Docs Freshness SLA
34+
35+
| Area | Primary owner | Review cadence |
36+
| --- | --- | --- |
37+
| Getting started | Maintainers | Monthly |
38+
| API reference | Maintainers + feature PR author | Every behavior change + monthly |
39+
| Operations runbooks | Maintainers + on-call | Monthly and after incidents |
40+
| Examples | Maintainers | Monthly and when API contract changes |
41+
| Concepts/architecture | Maintainers | Quarterly |
42+
3143
## 🌐 API Reference
3244

3345
- 🔐 [api/authentication.md](api/authentication.md)
@@ -37,8 +49,14 @@ Welcome to the full documentation for Secrets. Pick a path and dive in 🚀
3749
- 🚄 [api/transit.md](api/transit.md)
3850
- 📜 [api/audit-logs.md](api/audit-logs.md)
3951
- 🧱 [api/response-shapes.md](api/response-shapes.md)
52+
- 🧩 [api/versioning-policy.md](api/versioning-policy.md)
4053
- 📄 [openapi.yaml](openapi.yaml)
4154

55+
## 🧠 ADRs
56+
57+
- 🧾 [adr/0001-envelope-encryption-model.md](adr/0001-envelope-encryption-model.md)
58+
- 🧾 [adr/0002-transit-versioned-ciphertext-contract.md](adr/0002-transit-versioned-ciphertext-contract.md)
59+
4260
## 🖥️ Supported Platforms
4361

4462
- ✅ Linux and macOS environments for local development and operations
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# ADR 0001: Envelope Encryption Model
2+
3+
> Status: accepted
4+
> Date: 2026-02-14
5+
6+
## Context
7+
8+
The system must protect stored secret payloads while supporting key rotation without re-encrypting all historical data at once.
9+
10+
## Decision
11+
12+
Use envelope encryption hierarchy:
13+
14+
`Master Key -> KEK -> DEK -> Secret Data`
15+
16+
- master keys protect KEKs
17+
- KEKs protect DEKs
18+
- DEKs encrypt secret payloads
19+
20+
## Consequences
21+
22+
- key rotation can happen incrementally
23+
- historical versions remain decryptable with prior key material
24+
- clear separation between root trust, key-wrapping, and data encryption roles
25+
26+
## See also
27+
28+
- [Architecture](../concepts/architecture.md)
29+
- [Security model](../concepts/security-model.md)
30+
- [Key management operations](../operations/key-management.md)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# ADR 0002: Transit Versioned Ciphertext Contract
2+
3+
> Status: accepted
4+
> Date: 2026-02-14
5+
6+
## Context
7+
8+
Transit decryption must reliably select the correct transit key version and reject malformed ciphertext early.
9+
10+
## Decision
11+
12+
Adopt transit ciphertext contract:
13+
14+
`<version>:<base64-ciphertext>`
15+
16+
- decrypt requires version prefix and base64 payload
17+
- malformed input returns validation errors (`422`)
18+
- callers must pass ciphertext exactly as returned by encrypt
19+
20+
## Consequences
21+
22+
- deterministic key version selection for decrypt
23+
- stronger input validation with predictable errors
24+
- simpler client behavior by treating encrypt output as opaque
25+
26+
## See also
27+
28+
- [Transit API](../api/transit.md)
29+
- [Response shapes](../api/response-shapes.md)
30+
- [Troubleshooting](../getting-started/troubleshooting.md)

docs/api/audit-logs.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ Authorization: `read` capability for `/v1/audit-logs`.
1818

1919
- `GET /v1/audit-logs`
2020

21+
## Status Code Quick Reference
22+
23+
| Endpoint | Success | Common error statuses |
24+
| --- | --- | --- |
25+
| `GET /v1/audit-logs` | `200` | `401`, `403`, `422` |
26+
2127
Query parameters:
2228

2329
- `offset` (default `0`)
@@ -153,3 +159,5 @@ curl -s "http://localhost:8080/v1/audit-logs?limit=100" \
153159
- [Clients API](clients.md)
154160
- [Policies cookbook](policies.md)
155161
- [Response shapes](response-shapes.md)
162+
- [API compatibility policy](versioning-policy.md)
163+
- [Glossary](../concepts/glossary.md)

docs/api/clients.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ Capability mapping:
2929
- `PUT /v1/clients/:id` -> `write`
3030
- `DELETE /v1/clients/:id` -> `delete`
3131

32+
## Status Code Quick Reference
33+
34+
| Endpoint | Success | Common error statuses |
35+
| --- | --- | --- |
36+
| `POST /v1/clients` | `201` | `401`, `403`, `409`, `422` |
37+
| `GET /v1/clients` | `200` | `401`, `403`, `422` |
38+
| `GET /v1/clients/:id` | `200` | `401`, `403`, `404`, `422` |
39+
| `PUT /v1/clients/:id` | `200` | `401`, `403`, `404`, `409`, `422` |
40+
| `DELETE /v1/clients/:id` | `204` | `401`, `403`, `404`, `422` |
41+
3242
## Create Client
3343

3444
```bash
@@ -138,3 +148,5 @@ Expected result: create returns `201 Created` with one-time `secret`; list retur
138148
- [Policies cookbook](policies.md)
139149
- [Audit logs API](audit-logs.md)
140150
- [Response shapes](response-shapes.md)
151+
- [API compatibility policy](versioning-policy.md)
152+
- [Glossary](../concepts/glossary.md)

docs/api/response-shapes.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,20 @@ Common error categories:
109109
- `not_found`
110110
- `conflict`
111111

112+
Representative conflict payload (for example duplicate transit key create):
113+
114+
```json
115+
{
116+
"error": "conflict",
117+
"message": "transit key already exists"
118+
}
119+
```
120+
112121
## See also
113122

114123
- [Authentication API](authentication.md)
115124
- [Clients API](clients.md)
116125
- [Secrets API](secrets.md)
117126
- [Transit API](transit.md)
127+
- [API compatibility policy](versioning-policy.md)
128+
- [Glossary](../concepts/glossary.md)

0 commit comments

Comments
 (0)