Skip to content

feat(crypto): cfg.kms + key-manager factory + AWS KMS provider (Step 6.7b) - #156

Merged
officialCodeWork merged 1 commit into
mainfrom
build/phase-6/step-6.7b-cloud-kms
Jun 8, 2026
Merged

feat(crypto): cfg.kms + key-manager factory + AWS KMS provider (Step 6.7b)#156
officialCodeWork merged 1 commit into
mainfrom
build/phase-6/step-6.7b-cloud-kms

Conversation

@officialCodeWork

Copy link
Copy Markdown
Owner

Summary

Second slice of Step 6.7 — BYOK: makes the 6.7a encryption library configurable + provider-selectable, and adds the first cloud provider (AWS KMS).

  • Config: cfg.kms (enabled / providernoop/local/aws / default_key_id / region / local_key) + tenants[].kms_key_id — the per-tenant key reference (a KMS ARN for aws, a hex 32-byte KEK for local).
  • Factory: build_key_manager_from_config(cfg) (in the gateway, lazy rag-backends imports so rag-backends stays config-free) selects the provider. build_app(key_manager=…) exposes app.state.key_manager + app.state.kms_enabled (passthrough NoopKeyManager when disabled).
  • AwsKmsKeyManager (rag-backends/kms/aws.py) subclasses EnvelopeKeyManager and wraps/unwraps the DEK via AWS KMS Encrypt/Decrypt for the tenant's customer-managed key — over the already-present aioboto3 (no new dependency). Per-tenant CMK from the key-id map (+ default_key_id); any KMS failure (revoked / denied / unreachable) or a missing key id → KeyUnavailableError (sealing). An injectable client seam makes it fully unit-testable with a fake KMS — no AWS creds / network.

Scope / deferred: AWS provider + config + factory + the app.state.key_manager seam. 6.7c — GCP KMS / Azure Key Vault / HashiCorp Vault providers (same EnvelopeKeyManager pattern, behind [kms-*] extras) + zero-downtime key rotation. Wiring EncryptingStorage into the ingest path is deferred (chunk content is inline today; it lands with tiered storage, ADR-0007).

Tests & gates

  • ~14 new tests: AWS provider over a fake KMS (tests/kms/test_aws.py — round-trip, KMS-key-bound cross-tenant block, sealing on missing key, default-key fallback, KMS-error → KeyUnavailableError); config defaults; factory (noop/local/aws); gateway wiring (app.state.key_manager + kms_enabled + a local round-trip).
  • Full tests/ packages/ 2353 passed, 1 skipped; gateway 289 passed (+8, no regression). Green: ruff, mypy --strict (306 files), RAG001, policy-coverage, log-schema; only the intended dist/rag.schema.* regen (no core-schema / openapi drift).

Documentation

Test plan

  • uv run pytest tests/ packages/ -m "not integration" — 2353 passed, 1 skipped
  • uv run pytest apps/gateway/tests — 289 passed
  • ruff + mypy --strict (306) + RAG001 + policy-coverage + log-schema; config schema-drift regenerated
  • AWS provider sealing / cross-tenant binding / KMS-error mapping verified via a fake KMS client

🤖 Generated with Claude Code

…6.7b)

Make BYOK configurable + provider-selectable. New cfg.kms (enabled / provider ∈
noop|local|aws / default_key_id / region / local_key) + tenants[].kms_key_id (a
KMS ARN for aws, a hex 32-byte KEK for local). build_key_manager_from_config
factory (in the gateway, lazy rag-backends imports so rag-backends stays
config-free) selects the provider; build_app(key_manager=) exposes
app.state.key_manager + app.state.kms_enabled (passthrough NoopKeyManager when
disabled).

AwsKmsKeyManager subclasses EnvelopeKeyManager and wraps/unwraps the DEK via AWS
KMS Encrypt/Decrypt for the tenant's customer-managed key (over the already-present
aioboto3 — no new dep). Per-tenant CMK from the key-id map (+ default_key_id); any
KMS failure or missing key id maps to KeyUnavailableError (sealing). An injectable
client seam makes it fully unit-testable with a fake KMS — no AWS creds/network.

Scope: AWS provider + config + factory + the app.state.key_manager seam. Deferred:
GCP/Azure/Vault providers + key rotation (6.7c); wiring EncryptingStorage into the
ingest path (blocked on tiered-storage plumbing — chunk content is inline today).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@officialCodeWork
officialCodeWork merged commit f53583a into main Jun 8, 2026
12 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant