feat: add governed local content encryption provider

This commit is contained in:
2026-08-02 03:40:50 +02:00
parent 858c41d5ad
commit 42f35f8d00
11 changed files with 2318 additions and 26 deletions
@@ -9,6 +9,7 @@ from sqlalchemy import (
Index,
Integer,
JSON,
LargeBinary,
String,
Text,
UniqueConstraint,
@@ -150,6 +151,142 @@ class EncryptionKeyOperation(Base, TimestampMixin):
)
class EncryptionLocalKeyMaterial(Base, TimestampMixin):
"""Provider-owned wrapped data-encryption key material.
The configured deployment master key never enters this table. The raw data
key exists only inside the provider while a cryptographic operation runs.
"""
__tablename__ = "encryption_local_key_material"
__table_args__ = (
UniqueConstraint(
"provider_key_ref",
name="uq_encryption_local_provider_key_ref",
),
UniqueConstraint(
"tenant_id",
"vault_id",
"key_version",
name="uq_encryption_local_vault_key_version",
),
UniqueConstraint(
"tenant_id",
"provision_idempotency_key",
name="uq_encryption_local_provision_idempotency",
),
Index(
"ix_encryption_local_key_state",
"tenant_id",
"state",
"updated_at",
),
)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
vault_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
key_version: Mapped[int] = mapped_column(Integer, nullable=False)
provider_key_ref: Mapped[str] = mapped_column(
String(255), nullable=False, index=True
)
algorithm_suite: Mapped[str] = mapped_column(String(120), nullable=False)
purpose: Mapped[str] = mapped_column(String(255), nullable=False)
state: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
wrapped_key: Mapped[bytes | None] = mapped_column(LargeBinary, nullable=True)
wrap_nonce: Mapped[bytes | None] = mapped_column(LargeBinary, nullable=True)
wrap_context_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
provision_idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False)
provision_request_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
revoked_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
destruction_scheduled_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
destroyed_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
class EncryptionLocalWrappedContentKey(Base, TimestampMixin):
__tablename__ = "encryption_local_wrapped_content_keys"
__table_args__ = (
UniqueConstraint(
"wrapped_key_ref",
name="uq_encryption_local_wrapped_key_ref",
),
UniqueConstraint(
"tenant_id",
"idempotency_key",
name="uq_encryption_local_content_idempotency",
),
Index(
"ix_encryption_local_content_state",
"tenant_id",
"state",
"updated_at",
),
)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
wrapped_key_ref: Mapped[str] = mapped_column(
String(255), nullable=False, index=True
)
provider_key_ref: Mapped[str] = mapped_column(
String(255), nullable=False, index=True
)
algorithm_suite: Mapped[str] = mapped_column(String(120), nullable=False)
state: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
wrapped_content_key: Mapped[bytes | None] = mapped_column(
LargeBinary, nullable=True
)
wrap_nonce: Mapped[bytes | None] = mapped_column(LargeBinary, nullable=True)
content_nonce: Mapped[bytes | None] = mapped_column(LargeBinary, nullable=True)
authenticated_context_sha256: Mapped[str] = mapped_column(
String(64), nullable=False
)
plaintext_commitment: Mapped[str] = mapped_column(String(64), nullable=False)
idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False)
request_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
source_wrapped_key_ref: Mapped[str | None] = mapped_column(
String(255), nullable=True
)
destroyed_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
class EncryptionLocalProviderOperation(Base, TimestampMixin):
__tablename__ = "encryption_local_provider_operations"
__table_args__ = (
UniqueConstraint(
"tenant_id",
"idempotency_key",
name="uq_encryption_local_provider_operation_idem",
),
Index(
"ix_encryption_local_provider_operation_state",
"tenant_id",
"state",
"updated_at",
),
)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
operation: Mapped[str] = mapped_column(String(50), nullable=False, index=True)
target_ref: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
outcome_ref: Mapped[str | None] = mapped_column(String(255), nullable=True)
idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False)
request_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
state: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
completed_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
class ContentProtectionRecord(Base, TimestampMixin):
__tablename__ = "encryption_content_protections"
__table_args__ = (
@@ -305,6 +442,9 @@ __all__ = [
"ContentProtectionRecord",
"EncryptionKeyOperation",
"EncryptionKeyVersion",
"EncryptionLocalKeyMaterial",
"EncryptionLocalProviderOperation",
"EncryptionLocalWrappedContentKey",
"EncryptionVault",
"ProtectionMigration",
"RecoveryApproval",