Initial public ModelForge release
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""Enforce the two fixed Node Agent credential scopes.
|
||||
|
||||
Revision ID: 20260830_0023
|
||||
Revises: 20260828_0022
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision: str = "20260830_0023"
|
||||
down_revision: str | None = "20260828_0022"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
_SCOPE_CONSTRAINTS = (
|
||||
("node_enrollments", "node.enroll", "ck_node_enrollment_scope"),
|
||||
("node_credentials", "node.publish", "ck_node_credential_scope"),
|
||||
)
|
||||
|
||||
|
||||
def _validate_existing_scopes() -> None:
|
||||
connection = op.get_bind()
|
||||
for table_name, expected_scope, _constraint_name in _SCOPE_CONSTRAINTS:
|
||||
table = sa.table(table_name, sa.column("scope", sa.String(64)))
|
||||
invalid_rows = connection.scalar(
|
||||
sa.select(sa.func.count())
|
||||
.select_from(table)
|
||||
.where(sa.or_(table.c.scope.is_(None), table.c.scope != expected_scope))
|
||||
)
|
||||
if invalid_rows:
|
||||
raise RuntimeError(
|
||||
f"refusing node-scope migration: {table_name} contains "
|
||||
f"{invalid_rows} row(s) outside {expected_scope!r}"
|
||||
)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Validate every table before changing either one. A malformed production row therefore aborts
|
||||
# the migration without leaving a partially hardened schema.
|
||||
_validate_existing_scopes()
|
||||
for table_name, expected_scope, constraint_name in _SCOPE_CONSTRAINTS:
|
||||
with op.batch_alter_table(table_name) as batch_op:
|
||||
batch_op.create_check_constraint(
|
||||
constraint_name,
|
||||
f"scope = '{expected_scope}'",
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
for table_name, _expected_scope, constraint_name in reversed(_SCOPE_CONSTRAINTS):
|
||||
with op.batch_alter_table(table_name) as batch_op:
|
||||
batch_op.drop_constraint(constraint_name, type_="check")
|
||||
Reference in New Issue
Block a user