feat: add institutional governance and recovery contracts
This commit is contained in:
@@ -18,6 +18,8 @@ from sqlalchemy import create_engine, inspect, text
|
||||
|
||||
from govoplan_core.core.migrations import MigrationMetadataPlan, migration_metadata_plan
|
||||
from govoplan_core.core import change_sequence as core_change_sequence_models # noqa: F401 - populate core metadata
|
||||
from govoplan_core.core import recovery as core_recovery_models # noqa: F401 - populate core metadata
|
||||
from govoplan_core.core import runtime_coordination as core_runtime_models # noqa: F401 - populate core metadata
|
||||
from govoplan_core.security import credential_envelopes as core_credential_models # noqa: F401 - populate core metadata
|
||||
from govoplan_core.core.change_sequence import ChangeSequenceEntry, ChangeSequenceRetentionFloor
|
||||
from govoplan_core.core.module_management import load_startup_enabled_modules, startup_candidate_module_ids
|
||||
@@ -590,6 +592,51 @@ def database_revision(database_url: str | None = None) -> str | None:
|
||||
engine.dispose()
|
||||
|
||||
|
||||
def database_migration_heads(
|
||||
database_url: str | None = None,
|
||||
) -> tuple[str, ...]:
|
||||
url = database_url or settings.database_url
|
||||
engine = create_engine(url)
|
||||
try:
|
||||
with engine.connect() as connection:
|
||||
return tuple(
|
||||
sorted(MigrationContext.configure(connection).get_current_heads())
|
||||
)
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
|
||||
def configured_migration_heads(
|
||||
database_url: str | None = None,
|
||||
*,
|
||||
enabled_modules: tuple[str, ...] | list[str] | None = None,
|
||||
manifest_factories: tuple[ManifestFactory, ...] = (),
|
||||
migration_track: str | None = None,
|
||||
) -> tuple[str, ...]:
|
||||
config = alembic_config(
|
||||
database_url=database_url,
|
||||
enabled_modules=enabled_modules,
|
||||
manifest_factories=manifest_factories,
|
||||
migration_track=migration_track,
|
||||
)
|
||||
return tuple(sorted(ScriptDirectory.from_config(config).get_heads()))
|
||||
|
||||
|
||||
def database_is_at_configured_heads(
|
||||
database_url: str | None = None,
|
||||
*,
|
||||
enabled_modules: tuple[str, ...] | list[str] | None = None,
|
||||
manifest_factories: tuple[ManifestFactory, ...] = (),
|
||||
migration_track: str | None = None,
|
||||
) -> bool:
|
||||
return database_migration_heads(database_url) == configured_migration_heads(
|
||||
database_url,
|
||||
enabled_modules=enabled_modules,
|
||||
manifest_factories=manifest_factories,
|
||||
migration_track=migration_track,
|
||||
)
|
||||
|
||||
|
||||
def _has_columns(inspector, table_name: str, required: set[str]) -> bool:
|
||||
try:
|
||||
actual = {column["name"] for column in inspector.get_columns(table_name)}
|
||||
|
||||
Reference in New Issue
Block a user