feat: The Other Dude v9.0.1 — full-featured email system
ci: add GitHub Pages deployment workflow for docs site Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
90
backend/alembic/versions/017_openbao_envelope_encryption.py
Normal file
90
backend/alembic/versions/017_openbao_envelope_encryption.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""OpenBao envelope encryption columns and key_access_log extensions.
|
||||
|
||||
Revision ID: 017
|
||||
Revises: 016
|
||||
Create Date: 2026-03-03
|
||||
|
||||
Adds Transit ciphertext columns (TEXT) alongside existing BYTEA columns
|
||||
for dual-write migration strategy. Extends key_access_log with device_id,
|
||||
justification, and correlation_id for Phase 29 audit trail.
|
||||
"""
|
||||
|
||||
revision = "017"
|
||||
down_revision = "016"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# --- Transit ciphertext columns (TEXT, alongside existing BYTEA) ---
|
||||
|
||||
# devices: store OpenBao Transit ciphertext for credentials
|
||||
op.add_column(
|
||||
"devices",
|
||||
sa.Column("encrypted_credentials_transit", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# certificate_authorities: Transit-encrypted CA private keys
|
||||
op.add_column(
|
||||
"certificate_authorities",
|
||||
sa.Column("encrypted_private_key_transit", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# device_certificates: Transit-encrypted device cert private keys
|
||||
op.add_column(
|
||||
"device_certificates",
|
||||
sa.Column("encrypted_private_key_transit", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# notification_channels: Transit-encrypted SMTP password
|
||||
op.add_column(
|
||||
"notification_channels",
|
||||
sa.Column("smtp_password_transit", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# --- Tenant OpenBao key tracking ---
|
||||
op.add_column(
|
||||
"tenants",
|
||||
sa.Column("openbao_key_name", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# --- Extend key_access_log for Phase 29 ---
|
||||
op.add_column(
|
||||
"key_access_log",
|
||||
sa.Column("device_id", UUID(as_uuid=True), nullable=True),
|
||||
)
|
||||
op.add_column(
|
||||
"key_access_log",
|
||||
sa.Column("justification", sa.Text(), nullable=True),
|
||||
)
|
||||
op.add_column(
|
||||
"key_access_log",
|
||||
sa.Column("correlation_id", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# Add FK constraint for device_id -> devices(id) (nullable, so no cascade needed)
|
||||
op.create_foreign_key(
|
||||
"fk_key_access_log_device_id",
|
||||
"key_access_log",
|
||||
"devices",
|
||||
["device_id"],
|
||||
["id"],
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint(
|
||||
"fk_key_access_log_device_id", "key_access_log", type_="foreignkey"
|
||||
)
|
||||
op.drop_column("key_access_log", "correlation_id")
|
||||
op.drop_column("key_access_log", "justification")
|
||||
op.drop_column("key_access_log", "device_id")
|
||||
op.drop_column("tenants", "openbao_key_name")
|
||||
op.drop_column("notification_channels", "smtp_password_transit")
|
||||
op.drop_column("device_certificates", "encrypted_private_key_transit")
|
||||
op.drop_column("certificate_authorities", "encrypted_private_key_transit")
|
||||
op.drop_column("devices", "encrypted_credentials_transit")
|
||||
Reference in New Issue
Block a user